diff --git a/README.md b/README.md index bbdd5dda..9d1b3b73 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.3-runnable.jar +java -jar coda-calibration/calibration-standalone/target/calibration-standalone-1.0.4-runnable.jar ``` #### **GUI alone** ```shell -java -jar coda-calibration/calibration-gui/target/calibration-gui-1.0.3-runnable.jar +java -jar coda-calibration/calibration-gui/target/calibration-gui-1.0.4-runnable.jar ``` #### **Calibration REST service alone** ```shell -java -jar coda-calibration/calibration-service/application/target/application-1.0.3-runnable.jar +java -jar coda-calibration/calibration-service/application/target/application-1.0.4-runnable.jar ``` #### A note about HTTPS diff --git a/calibration-gui/.gitignore b/calibration-gui/.gitignore deleted file mode 100644 index 2af7cefb..00000000 --- a/calibration-gui/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -target/ -!.mvn/wrapper/maven-wrapper.jar - -### STS ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans - -### IntelliJ IDEA ### -.idea -*.iws -*.iml -*.ipr - -### NetBeans ### -nbproject/private/ -build/ -nbbuild/ -dist/ -nbdist/ -.nb-gradle/ \ No newline at end of file diff --git a/calibration-gui/pom.xml b/calibration-gui/pom.xml index 32d5f2fb..ad3105e0 100644 --- a/calibration-gui/pom.xml +++ b/calibration-gui/pom.xml @@ -1,13 +1,17 @@ - 4.0.0 - gov.llnl.gnem.apps.coda.calibration + + gov.llnl.gnem.apps.coda.calibration + coda-calibration + 1.0.4-SNAPSHOT + + calibration-gui - 1.0.3 jar - calibration-gui http://www.llnl.gov @@ -17,11 +21,7 @@ - UTF-8 - 1.8 - 1.8 gov.llnl.gnem.apps.coda.calibration.gui.GuiApplication - 3.0.0 @@ -41,36 +41,22 @@ - - - - - io.projectreactor - reactor-bom - Bismuth-RELEASE - pom - import - - - org.springframework.boot - spring-boot-starter-parent - 2.0.2.RELEASE - pom - import - - - - gov.llnl.gnem.apps.coda.calibration externals - 1.0.3 + + + gov.llnl.gnem.apps.coda.common + common-gui + + + gov.llnl.gnem.apps.coda.common + mapping gov.llnl.gnem.apps.coda.calibration - model - 1.0.3 + calibration-model org.eclipse.persistence @@ -130,8 +116,18 @@ test - junit - junit + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-params + test + + + org.junit.jupiter + junit-jupiter-engine test @@ -160,17 +156,14 @@ org.glassfish.tyrus.bundles tyrus-standalone-client - 1.13.1 org.apache.commons commons-compress - 1.14 org.apache.commons commons-math3 - 3.6.1 org.apache.commons @@ -179,30 +172,66 @@ com.google.guava guava - 23.0 net.jodah failsafe - 1.0.4 + + + org.mockito + mockito-core + test + + + org.mockito + mockito-junit-jupiter + test + + org.apache.maven.plugins + maven-dependency-plugin + + + + unpack + + + + + gov.llnl.gnem.apps.coda.common + common-gui + ${project.version} + ** + gov/** + + + gov.llnl.gnem.apps.coda.common + mapping + ${project.version} + ** + gov/** + + + ${project.build.directory}/classes/ + + + + org.apache.maven.plugins maven-compiler-plugin - 3.6.1 - 1.8 - 1.8 + ${maven.compile.source} + ${maven.compile.target} org.springframework.boot spring-boot-maven-plugin - 2.0.2.RELEASE true ${start-class} @@ -220,7 +249,6 @@ org.apache.maven.plugins maven-jar-plugin - 3.0.2 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 19e9d6f4..c70ff08d 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -14,10 +14,19 @@ */ package gov.llnl.gnem.apps.coda.calibration.gui; +import java.util.ArrayList; +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 { @@ -25,6 +34,7 @@ public class AppProperties { private Integer height = 800; private Integer width = 600; private Boolean debugEnabled = false; + private List wmsLayers = new ArrayList<>(); public Boolean getDebugEnabled() { return debugEnabled; @@ -57,4 +67,17 @@ public Integer getWidth() { public void setWidth(Integer width) { this.width = width; } + + public List getWmsLayers() { + return wmsLayers; + } + + 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 fcc79e30..ba21c712 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -14,7 +14,10 @@ */ package gov.llnl.gnem.apps.coda.calibration.gui; +import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -34,17 +37,33 @@ import com.google.common.eventbus.Subscribe; import gov.llnl.gnem.apps.coda.calibration.gui.controllers.CodaParamLoadingController; -import gov.llnl.gnem.apps.coda.calibration.gui.controllers.ProgressGui; +import gov.llnl.gnem.apps.coda.calibration.gui.controllers.DataController; +import gov.llnl.gnem.apps.coda.calibration.gui.controllers.EnvelopeLoadingController; +import gov.llnl.gnem.apps.coda.calibration.gui.controllers.PathController; import gov.llnl.gnem.apps.coda.calibration.gui.controllers.ReferenceEventLoadingController; -import gov.llnl.gnem.apps.coda.calibration.gui.controllers.WaveformLoadingController; +import gov.llnl.gnem.apps.coda.calibration.gui.controllers.ShapeController; +import gov.llnl.gnem.apps.coda.calibration.gui.controllers.SiteController; +import gov.llnl.gnem.apps.coda.calibration.gui.controllers.parameters.ParametersController; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.CalibrationClient; -import gov.llnl.gnem.apps.coda.calibration.gui.events.ShowFailureReportEvent; +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.util.CalibrationProgressListener; -import gov.llnl.gnem.apps.coda.calibration.gui.util.ProgressMonitor; -import gov.llnl.gnem.apps.coda.calibration.model.domain.messaging.CalibrationStatusEvent; -import gov.llnl.gnem.apps.coda.calibration.model.domain.messaging.CalibrationStatusEvent.Status; +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.events.ShowFailureReportEvent; +import gov.llnl.gnem.apps.coda.common.gui.util.ProgressMonitor; +import gov.llnl.gnem.apps.coda.common.mapping.LeafletMapController; +import javafx.application.Platform; +import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.Node; +import javafx.scene.control.Alert; +import javafx.scene.control.Alert.AlertType; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.Tab; import javafx.scene.input.TransferMode; import javafx.stage.DirectoryChooser; import javafx.stage.FileChooser; @@ -53,12 +72,52 @@ @Component public class CodaGuiController { - private final Logger log = LoggerFactory.getLogger(this.getClass()); + private static final Logger log = LoggerFactory.getLogger(CodaGuiController.class); @FXML private Node rootElement; - private WaveformLoadingController waveformLoadingController; + private DataController data; + private ParametersController param; + private ShapeController shape; + private PathController path; + private SiteController site; + + @FXML + private Tab dataTab; + + @FXML + private Tab paramTab; + + @FXML + private Tab shapeTab; + + @FXML + private Tab pathTab; + + @FXML + private Tab siteTab; + + private Runnable dataRefresh = () -> data.update(); + private Runnable paramRefresh = () -> param.update(); + private Runnable shapeRefresh = () -> shape.update(); + private Runnable pathRefresh = () -> path.update(); + private Runnable siteRefresh = () -> site.update(); + private Runnable activeTabRefresh = dataRefresh; + + @FXML + private Button showMapButton; + + @FXML + private Button refreshButton; + + private Label activeMapIcon; + + private Label showMapIcon; + + private LeafletMapController mapController; + + private EnvelopeLoadingController envelopeLoadingController; private CodaParamLoadingController codaParamLoadingController; @@ -68,13 +127,19 @@ public class CodaGuiController { private DirectoryChooser sacDirFileChooser = new DirectoryChooser(); private FileChooser sacFileChooser = new FileChooser(); - private FileChooser referenceEventFileChooser = new FileChooser(); private FileChooser codaParamsFileChooser = new FileChooser(); + private FileChooser codaJsonParamsFileChooser = new FileChooser(); + private FileChooser referenceEventFileChooser = new FileChooser(); private FileChooser psModelFileChooser = new FileChooser(); private FileChooser fiModelFileChooser = new FileChooser(); + private final ExtensionFilter allFilesFilter = new ExtensionFilter("All Files", "*.*"); + + private ParamExporter paramExporter; private EventBus bus; + private boolean initialized = false; + private ProgressGui loadingGui; private Map monitors = new HashMap<>(); @@ -86,33 +151,56 @@ public class CodaGuiController { }); @Autowired - public CodaGuiController(WaveformLoadingController waveformLoadingController, CodaParamLoadingController codaParamLoadingController, ReferenceEventLoadingController refEventLoadingController, - CalibrationClient calibrationClient, EventBus bus) throws IOException { + 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 { super(); - this.waveformLoadingController = waveformLoadingController; + this.mapController = mapController; + this.envelopeLoadingController = waveformLoadingController; this.codaParamLoadingController = codaParamLoadingController; this.refEventLoadingController = refEventLoadingController; this.calibrationClient = calibrationClient; + this.paramExporter = paramExporter; + this.data = data; + this.param = param; + this.shape = shape; + this.path = path; + this.site = site; this.bus = bus; + bus.register(this); + sacDirFileChooser.setTitle("Coda STACK File Directory"); sacFileChooser.getExtensionFilters().add(new ExtensionFilter("Coda STACK Files (.sac,.env)", "*.sac", "*.env")); - sacFileChooser.getExtensionFilters().add(new ExtensionFilter("All Files", "*")); - referenceEventFileChooser.getExtensionFilters().add(new ExtensionFilter("Reference Event Files (.txt,.dat)", "*.txt", "*.dat")); - referenceEventFileChooser.getExtensionFilters().add(new ExtensionFilter("All Files", "*")); + sacFileChooser.getExtensionFilters().add(allFilesFilter); + + codaJsonParamsFileChooser.getExtensionFilters().add(new ExtensionFilter("Coda Parameters File (.json)", "*.json")); + codaJsonParamsFileChooser.getExtensionFilters().add(allFilesFilter); codaParamsFileChooser.getExtensionFilters().add(new ExtensionFilter("Coda Parameters File (.param)", "*.param")); - codaParamsFileChooser.getExtensionFilters().add(new ExtensionFilter("All Files", "*")); + codaParamsFileChooser.getExtensionFilters().add(allFilesFilter); psModelFileChooser.getExtensionFilters().add(new ExtensionFilter("MDAC Ps Model File (.txt,.dat)", "*ps*.txt", "*ps*.dat")); - psModelFileChooser.getExtensionFilters().add(new ExtensionFilter("All Files", "*")); + psModelFileChooser.getExtensionFilters().add(allFilesFilter); fiModelFileChooser.getExtensionFilters().add(new ExtensionFilter("MDAC Ps Model File (.txt,.dat)", "*ps*.txt", "*ps*.dat")); - fiModelFileChooser.getExtensionFilters().add(new ExtensionFilter("All Files", "*")); + fiModelFileChooser.getExtensionFilters().add(allFilesFilter); + + referenceEventFileChooser.getExtensionFilters().add(new ExtensionFilter("Reference Event Files (.txt,.dat)", "*.txt", "*.dat")); + referenceEventFileChooser.getExtensionFilters().add(allFilesFilter); } @FXML private void openWaveformLoadingWindow() { - Optional.ofNullable(sacFileChooser.showOpenMultipleDialog(rootElement.getScene().getWindow())).ifPresent(waveformLoadingController::loadFiles); + Optional.ofNullable(sacFileChooser.showOpenMultipleDialog(rootElement.getScene().getWindow())).ifPresent(envelopeLoadingController::loadFiles); + } + + @FXML + private void showMapWindow() { + Platform.runLater(() -> { + if (mapController != null) { + mapController.show(); + } + }); } @FXML @@ -120,14 +208,54 @@ private void openFailureReportDisplay() { bus.post(new ShowFailureReportEvent()); } + @FXML + private void openCalibrationDataSavingWindow(ActionEvent e) { + //Save all parameters to an archive file and prompt the user about where to save it. + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Open Resource File"); + fileChooser.getExtensionFilters().addAll(new ExtensionFilter("Archive File", "*.zip")); + fileChooser.setInitialFileName("Calibration_Data.zip"); + File selectedFile = fileChooser.showSaveDialog(rootElement.getScene().getWindow()); + + if (selectedFile != null) { + + File exportArchive; + try { + if (!selectedFile.exists()) { + selectedFile.createNewFile(); + } else if (!selectedFile.canWrite()) { + Platform.runLater(() -> { + Alert alert = new Alert(AlertType.ERROR); + alert.setTitle("File Permissions Error"); + alert.setHeaderText("Unable to write to file or directory."); + alert.setContentText("Unable to write file, do you have write permissions on the selected directory?"); + alert.show(); + }); + } + exportArchive = paramExporter.createExportArchive(); + if (exportArchive != null) { + Files.move(exportArchive.toPath(), selectedFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + } + } catch (IOException e1) { + Platform.runLater(() -> { + Alert alert = new Alert(AlertType.ERROR); + alert.setTitle("File IO Error"); + alert.setHeaderText("Unable to export results"); + alert.setContentText(e1.getMessage()); + alert.show(); + }); + } + } + } + @FXML private void openWaveformDirectorySavingWindow() { - Optional.ofNullable(sacDirFileChooser.showDialog(rootElement.getScene().getWindow())).ifPresent(waveformLoadingController::saveToDirectory); + Optional.ofNullable(sacDirFileChooser.showDialog(rootElement.getScene().getWindow())).ifPresent(envelopeLoadingController::saveToDirectory); } @FXML private void openWaveformDirectoryLoadingWindow() { - Optional.ofNullable(sacDirFileChooser.showDialog(rootElement.getScene().getWindow())).map(Collections::singletonList).ifPresent(waveformLoadingController::loadFiles); + Optional.ofNullable(sacDirFileChooser.showDialog(rootElement.getScene().getWindow())).map(Collections::singletonList).ifPresent(envelopeLoadingController::loadFiles); } @FXML @@ -135,6 +263,11 @@ private void openReferenceEventLoadingWindow() { Optional.ofNullable(referenceEventFileChooser.showOpenMultipleDialog(rootElement.getScene().getWindow())).ifPresent(refEventLoadingController::loadFiles); } + @FXML + private void openCodaJsonParamWindow() { + Optional.ofNullable(codaJsonParamsFileChooser.showOpenDialog(rootElement.getScene().getWindow())).map(Collections::singletonList).ifPresent(codaParamLoadingController::loadFiles); + } + @FXML private void openCodaParamWindow() { Optional.ofNullable(codaParamsFileChooser.showOpenDialog(rootElement.getScene().getWindow())).map(Collections::singletonList).ifPresent(codaParamLoadingController::loadFiles); @@ -167,6 +300,56 @@ private void runAutoPickingCalibration() { @FXML public void initialize() { + activeMapIcon = makeMapLabel(); + showMapIcon = makeMapLabel(); + + dataTab.setOnSelectionChanged(e -> { + if (dataTab.isSelected()) { + data.refreshView(); + dataTab.setGraphic(activeMapIcon); + activeTabRefresh = dataRefresh; + } else { + dataTab.setGraphic(null); + } + }); + + paramTab.setOnSelectionChanged(e -> { + if (paramTab.isSelected()) { + mapController.clearIcons(); + activeTabRefresh = paramRefresh; + } + }); + + shapeTab.setOnSelectionChanged(e -> { + if (shapeTab.isSelected()) { + shape.refreshView(); + shapeTab.setGraphic(activeMapIcon); + activeTabRefresh = shapeRefresh; + } else { + shapeTab.setGraphic(null); + } + }); + + pathTab.setOnSelectionChanged(e -> { + if (pathTab.isSelected()) { + path.refreshView(); + pathTab.setGraphic(activeMapIcon); + activeTabRefresh = pathRefresh; + } else { + pathTab.setGraphic(null); + } + }); + + siteTab.setOnSelectionChanged(e -> { + if (siteTab.isSelected()) { + site.refreshView(); + siteTab.setGraphic(activeMapIcon); + activeTabRefresh = siteRefresh; + } else { + siteTab.setGraphic(null); + } + }); + rootElement.setOnDragOver(event -> { if (event.getGestureSource() != rootElement && event.getDragboard().hasFiles()) { event.acceptTransferModes(TransferMode.COPY); @@ -177,7 +360,7 @@ public void initialize() { rootElement.setOnDragDropped(event -> { boolean success = false; if (event.getGestureSource() != rootElement && event.getDragboard().hasFiles()) { - waveformLoadingController.loadFiles(event.getDragboard().getFiles()); + envelopeLoadingController.loadFiles(event.getDragboard().getFiles()); codaParamLoadingController.loadFiles(event.getDragboard().getFiles()); success = true; } @@ -190,13 +373,32 @@ public void initialize() { } catch (IllegalStateException e) { log.error("Unable to instantiate loading display {}", e.getMessage(), e); } - bus.register(this); + } + + @FXML + private void refreshTab(ActionEvent e) { + activeTabRefresh.run(); + } + + private Label makeMapLabel() { + Label mapLabel = new Label("\uE55B"); + mapLabel.getStyleClass().add("material-icons-medium"); + mapLabel.setMaxHeight(16); + mapLabel.setMinWidth(16); + return mapLabel; + } + + private Label makeRefreshLabel() { + Label label = new Label("\uE5D5"); + label.getStyleClass().add("material-icons-medium"); + label.setMaxHeight(16); + label.setMinWidth(16); + return label; } //TODO: Move this to a controller @Subscribe private void listener(CalibrationStatusEvent event) { - if (!monitors.containsKey(event.getId()) && event.getStatus() == Status.STARTING) { CalibrationProgressListener eventMonitor = new CalibrationProgressListener(bus, event); ProgressMonitor monitor = new ProgressMonitor("Calibration Progress " + event.getId(), eventMonitor); @@ -210,6 +412,29 @@ private void listener(CalibrationStatusEvent event) { } } + @Subscribe + private void listener(EnvelopeLoadCompleteEvent evt) { + if (dataTab.isSelected()) { + data.update(); + } + } + + @Subscribe + private void listener(CalibrationStageShownEvent evt) { + if (!initialized) { + Platform.runLater(() -> { + dataTab.setGraphic(activeMapIcon); + if (showMapButton.getGraphic() == null) { + showMapButton.setGraphic(showMapIcon); + } + if (refreshButton.getGraphic() == null) { + refreshButton.setGraphic(makeRefreshLabel()); + } + initialized = true; + }); + } + } + @PreDestroy private void cleanUp() { service.shutdownNow(); 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 ae6ad2f6..b5312c1e 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -14,9 +14,7 @@ */ package gov.llnl.gnem.apps.coda.calibration.gui; -import java.awt.Toolkit; import java.io.IOException; -import java.lang.reflect.Method; import java.net.URL; import java.util.TimeZone; import java.util.concurrent.CompletableFuture; @@ -25,7 +23,6 @@ import java.util.jar.Manifest; import javax.annotation.PostConstruct; -import javax.swing.SwingUtilities; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,7 +31,13 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.ComponentScan; +import com.google.common.eventbus.EventBus; + +import gov.llnl.gnem.apps.coda.calibration.gui.events.CalibrationStageShownEvent; +import gov.llnl.gnem.apps.coda.common.gui.SimpleGuiPreloader; +import gov.llnl.gnem.apps.coda.common.gui.util.CommonGuiUtils; import javafx.application.Application; import javafx.application.Platform; import javafx.fxml.FXMLLoader; @@ -46,14 +49,19 @@ import reactor.core.publisher.Hooks; @SpringBootApplication +@ComponentScan("gov.llnl.gnem.apps.coda.common.mapping") +@ComponentScan("gov.llnl.gnem.apps.coda.common.gui") +@ComponentScan("gov.llnl.gnem.apps.coda.calibration.gui") public class GuiApplication extends Application { - private final Logger log = LoggerFactory.getLogger(this.getClass()); + private static final Logger log = LoggerFactory.getLogger(GuiApplication.class); private ConfigurableApplicationContext springContext; private Stage primaryStage; + private EventBus bus; + @PostConstruct void started() { TimeZone.setDefault(TimeZone.getTimeZone("UTC")); @@ -62,35 +70,26 @@ void started() { public GuiApplication() { } - public GuiApplication(ConfigurableApplicationContext springContext) { + public GuiApplication(ConfigurableApplicationContext springContext, EventBus bus) { this.springContext = springContext; + this.bus = bus; } public static void main(String[] args) { String preloaderName = System.getProperty("javafx.preloader"); if (preloaderName == null) { - System.setProperty("javafx.preloader", CodaGuiPreloader.class.getName()); + System.setProperty("javafx.preloader", SimpleGuiPreloader.class.getName()); } launch(GuiApplication.class, args); } @Override public void init() throws Exception { - SwingUtilities.invokeLater(() -> { - try { - Class util = Class.forName("com.apple.eawt.Application"); - Method getApplication = util.getMethod("getApplication", new Class[0]); - Object application = getApplication.invoke(util); - Class params[] = new Class[1]; - params[0] = java.awt.Image.class; - Method setDockIconImage = util.getMethod("setDockIconImage", params); - URL url = this.getClass().getResource("/coda_256x256.png"); - java.awt.Image image = Toolkit.getDefaultToolkit().getImage(url); - setDockIconImage.invoke(application, image); - } catch (Exception e) { - } - }); + CommonGuiUtils.setIcon(this.getClass(), "/coda_256x256.png"); springContext = new SpringApplicationBuilder(GuiApplication.class).bannerMode(Mode.OFF).web(WebApplicationType.NONE).headless(false).run(); + if (bus == null) { + bus = springContext.getBean(EventBus.class); + } } @Override @@ -101,6 +100,7 @@ public void start(Stage primaryStage) throws Exception { primaryStage.getIcons().add(new Image(this.getClass().getResourceAsStream("/coda_128x128.png"))); primaryStage.getIcons().add(new Image(this.getClass().getResourceAsStream("/coda_256x256.png"))); primaryStage.setOnCloseRequest((evt) -> Platform.exit()); + primaryStage.setOnShown((evt) -> bus.post(new CalibrationStageShownEvent())); AppProperties props = springContext.getBean(AppProperties.class); @@ -119,12 +119,13 @@ public void start(Stage primaryStage) throws Exception { Manifest mf = new Manifest(new URL(manifestPath).openStream()); Attributes atts = mf.getMainAttributes(); // Put this info in the log to help with analysis - log.info("Version:{} Commit:{} Branch:{} By:{} at {}", - atts.getValue("Implementation-Version"), - atts.getValue("Implementation-Build"), - atts.getValue("Build-Branch"), - atts.getValue("Built-By"), - atts.getValue("Build-Timestamp")); + log.info( + "Version:{} Commit:{} Branch:{} By:{} at {}", + atts.getValue("Implementation-Version"), + atts.getValue("Implementation-Build"), + atts.getValue("Build-Branch"), + atts.getValue("Built-By"), + atts.getValue("Build-Timestamp")); // Update the title bar baseTitle += " Built at " + atts.getValue("Build-Timestamp"); } else { 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 2da1b4f9..47791487 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -16,6 +16,7 @@ import java.io.File; import java.nio.file.Path; +import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -28,72 +29,123 @@ import org.springframework.stereotype.Component; import com.fasterxml.jackson.core.JsonProcessingException; +import com.google.common.eventbus.EventBus; import gov.llnl.gnem.apps.coda.calibration.gui.converters.api.FileToParameterConverter; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ParameterClient; +import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ReferenceEventClient; +import gov.llnl.gnem.apps.coda.calibration.gui.events.ParametersLoadedEvent; import gov.llnl.gnem.apps.coda.calibration.model.domain.MdacParametersFI; import gov.llnl.gnem.apps.coda.calibration.model.domain.MdacParametersPS; -import gov.llnl.gnem.apps.coda.calibration.model.domain.SharedFrequencyBandParameters; +import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; +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 final Logger log = LoggerFactory.getLogger(this.getClass()); + private static final Logger log = LoggerFactory.getLogger(CodaParamLoadingController.class); - private ParameterClient client; + private ParameterClient paramsClient; + + private ReferenceEventClient refMwClient; private int maxBatching = 100; private List> fileConverters; + private EventBus bus; + @Autowired - public CodaParamLoadingController(List> fileConverters, ParameterClient client) { + public CodaParamLoadingController(List> fileConverters, ParameterClient paramsClient, ReferenceEventClient refMwClient, EventBus bus) { super(); this.fileConverters = fileConverters; - this.client = client; + this.paramsClient = paramsClient; + this.refMwClient = refMwClient; + this.bus = bus; + if (paramsClient == null) { + throw new IllegalStateException("Unable to find implementation of Coda Param loding client"); + } + + if (refMwClient == null) { + throw new IllegalStateException("Unable to find implementation of Reference Event loding client"); + } } public void loadFiles(List files) { - CompletableFuture.runAsync(() -> { - List validFiles = files.stream().filter(f -> validPath(f.toPath())).collect(Collectors.toList()); - 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 { - client.postSharedFrequencyBandParameters(sfb).retry(3).subscribe(); - } catch (JsonProcessingException ex) { - log.trace(ex.getMessage(), ex); + if (fileConverters != null && !fileConverters.isEmpty()) { + List validFiles = files.stream().filter(f -> validPath(f.toPath())).collect(Collectors.toList()); + convertFiles(validFiles); + bus.post(new ParametersLoadedEvent()); + } + }); + } + + 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); } - } else if (res.get() instanceof MdacParametersPS) { - MdacParametersPS entry = (MdacParametersPS) res.get(); - try { - client.postPsParameters(entry).retry(3).subscribe(); - } catch (JsonProcessingException ex) { - log.trace(ex.getMessage(), ex); + } 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); } - } else if (res.get() instanceof MdacParametersFI) { - MdacParametersFI entry = (MdacParametersFI) res.get(); - try { - client.postFiParameters(entry).retry(3).subscribe(); - } catch (JsonProcessingException ex) { - log.trace(ex.getMessage(), ex); + } 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); } } } - })); - }); + } + })); } private boolean validPath(Path p) { - Optional> match = fileConverters.stream().filter(fc -> fc.getMatchingPattern().matches(p)).findAny(); + Optional> match = Optional.ofNullable(fileConverters).orElse(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 31cac78f..d120cc43 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -22,16 +22,18 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.WaveformClient; -import gov.llnl.gnem.apps.coda.calibration.gui.mapping.api.Icon.IconTypes; -import gov.llnl.gnem.apps.coda.calibration.gui.mapping.api.IconFactory; -import gov.llnl.gnem.apps.coda.calibration.gui.mapping.api.Location; -import gov.llnl.gnem.apps.coda.calibration.gui.mapping.api.Map; -import gov.llnl.gnem.apps.coda.calibration.gui.util.MaybeNumericStringComparator; -import gov.llnl.gnem.apps.coda.calibration.model.domain.Event; -import gov.llnl.gnem.apps.coda.calibration.model.domain.Station; -import gov.llnl.gnem.apps.coda.calibration.model.domain.Stream; -import gov.llnl.gnem.apps.coda.calibration.model.domain.Waveform; +import com.google.common.eventbus.EventBus; + +import gov.llnl.gnem.apps.coda.common.gui.data.client.api.WaveformClient; +import gov.llnl.gnem.apps.coda.common.gui.util.MaybeNumericStringComparator; +import gov.llnl.gnem.apps.coda.common.mapping.api.GeoMap; +import gov.llnl.gnem.apps.coda.common.mapping.api.Icon.IconTypes; +import gov.llnl.gnem.apps.coda.common.mapping.api.IconFactory; +import gov.llnl.gnem.apps.coda.common.mapping.api.Location; +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 javafx.beans.binding.Bindings; import javafx.collections.FXCollections; import javafx.collections.ObservableList; @@ -45,12 +47,11 @@ import javafx.scene.control.TableView; import javafx.scene.control.cell.CheckBoxTableCell; import javafx.scene.control.cell.PropertyValueFactory; -import javafx.scene.layout.StackPane; @Component public class DataController { - private final Logger log = LoggerFactory.getLogger(this.getClass()); + private static final Logger log = LoggerFactory.getLogger(DataController.class); @FXML private MenuItem importWaveforms; @@ -59,34 +60,35 @@ public class DataController { private TableView tableView; @FXML - TableColumn selectionCol; + private TableColumn selectionCol; @FXML - CheckBox selectAllCheckbox; + private CheckBox selectAllCheckbox; @FXML - TableColumn stationCol; + private TableColumn stationCol; @FXML - TableColumn eventCol; - - @FXML - StackPane mapParent; + private TableColumn eventCol; private ObservableList listData = FXCollections.synchronizedObservableList(FXCollections.observableArrayList()); - private Map mapImpl; + private GeoMap mapImpl; private IconFactory iconFactory; private WaveformClient client; + private EventBus bus; + @Autowired - public DataController(WaveformClient client, Map mapImpl, IconFactory iconFactory) { + public DataController(WaveformClient client, GeoMap mapImpl, IconFactory iconFactory, EventBus bus) { super(); this.client = client; this.mapImpl = mapImpl; this.iconFactory = iconFactory; + this.bus = bus; + bus.register(this); } @FXML @@ -103,36 +105,52 @@ public void initialize() { selectionCol.setCellValueFactory(new PropertyValueFactory("checkBoxValue")); selectionCol.setCellFactory(CheckBoxTableCell.forTableColumn(selectionCol)); - eventCol.setCellValueFactory(x -> Bindings.createStringBinding(() -> Optional.ofNullable(x) - .map(CellDataFeatures::getValue) - .map(Waveform::getEvent) - .map(Event::getEventId) - .orElseGet(String::new))); + 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()); - stationCol.setCellValueFactory(x -> Bindings.createStringBinding(() -> Optional.ofNullable(x) - .map(CellDataFeatures::getValue) - .map(Waveform::getStream) - .map(Stream::getStation) - .map(Station::getStationName) - .orElseGet(String::new))); + stationCol.setCellValueFactory( + x -> Bindings.createStringBinding( + () -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(Waveform::getStream).map(Stream::getStation).map(Station::getStationName).orElseGet(String::new))); tableView.setItems(listData); + } - mapImpl.attach(mapParent); + public void refreshView() { + if (listData.isEmpty()) { + requestData(); + } else { + mapImpl.clearIcons(); + listData.forEach(waveform -> genIconsFromData(waveform)); + } + } + + public void update() { + requestData(); } private void requestData() { listData.clear(); mapImpl.clearIcons(); - client.getUniqueEventStationStacks().filter(Objects::nonNull).subscribe(waveform -> { + client.getUniqueEventStationMetadataForStacks().filter(Objects::nonNull).doOnComplete(() -> tableView.sort()).subscribe(waveform -> { listData.add(waveform); - mapImpl.addIcon(iconFactory.newIcon(IconTypes.TRIANGLE_UP, - new Location(waveform.getStream().getStation().getLatitude(), waveform.getStream().getStation().getLongitude()), - waveform.getStream().getStation().getStationName())); - mapImpl.addIcon(iconFactory.newIcon(new Location(waveform.getEvent().getLatitude(), waveform.getEvent().getLongitude()), waveform.getEvent().getEventId())); + genIconsFromData(waveform); }, err -> log.trace(err.getMessage(), err)); } + protected void genIconsFromData(Waveform waveform) { + mapImpl.addIcon( + iconFactory.newIcon( + IconTypes.TRIANGLE_UP, + new Location(waveform.getStream().getStation().getLatitude(), waveform.getStream().getStation().getLongitude()), + waveform.getStream().getStation().getStationName())); + mapImpl.addIcon( + iconFactory.newIcon( + waveform.getEvent().getEventId(), + IconTypes.CIRCLE, + new Location(waveform.getEvent().getLatitude(), waveform.getEvent().getLongitude()), + waveform.getEvent().getEventId())); + } + } 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 new file mode 100644 index 00000000..1db90fe5 --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/EnvelopeLoadingController.java @@ -0,0 +1,44 @@ +/* +* 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.controllers; + +import java.util.List; + +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; + +import gov.llnl.gnem.apps.coda.common.gui.controllers.AbstractSeismogramSaveLoadController; +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; + +@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)); + this.setCompletionCallback(() -> bus.post(new EnvelopeLoadCompleteEvent())); + } +} 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 cf6fcf15..452a6c5b 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -32,28 +32,30 @@ import javax.swing.SwingUtilities; import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics; -import org.apache.commons.math3.util.Pair; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.SpectraClient; -import gov.llnl.gnem.apps.coda.calibration.gui.mapping.api.Icon.IconTypes; -import gov.llnl.gnem.apps.coda.calibration.gui.mapping.api.IconFactory; -import gov.llnl.gnem.apps.coda.calibration.gui.mapping.api.Location; -import gov.llnl.gnem.apps.coda.calibration.gui.util.NumberFormatFactory; -import gov.llnl.gnem.apps.coda.calibration.model.domain.FrequencyBand; import gov.llnl.gnem.apps.coda.calibration.model.domain.SpectraMeasurement; -import gov.llnl.gnem.apps.coda.calibration.model.domain.Station; +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.mapping.api.Icon.IconStyles; +import gov.llnl.gnem.apps.coda.common.mapping.api.Icon.IconTypes; +import gov.llnl.gnem.apps.coda.common.mapping.api.IconFactory; +import gov.llnl.gnem.apps.coda.common.mapping.api.Location; +import gov.llnl.gnem.apps.coda.common.model.domain.Event; +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.Station; import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableSet; import javafx.embed.swing.SwingNode; -import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.ComboBox; import javafx.scene.control.ListCell; import javafx.scene.control.Tooltip; -import javafx.scene.layout.StackPane; import llnl.gnem.core.gui.plotting.MouseOverPlotObject; import llnl.gnem.core.gui.plotting.PaintMode; import llnl.gnem.core.gui.plotting.PenStyle; @@ -66,7 +68,6 @@ import llnl.gnem.core.gui.plotting.plotobject.Symbol; import llnl.gnem.core.gui.plotting.plotobject.TriangleDn; import llnl.gnem.core.gui.plotting.plotobject.TriangleUp; -import llnl.gnem.core.util.SeriesMath; import llnl.gnem.core.util.Geometry.EModel; @Component @@ -88,9 +89,6 @@ public class PathController { @FXML private ComboBox station2ComboBox; - @FXML - StackPane mapParent; - @FXML SwingNode stationPlotSwingNode; @@ -99,7 +97,7 @@ public class PathController { private SpectraClient spectraMeasurementClient; - private gov.llnl.gnem.apps.coda.calibration.gui.mapping.api.Map mapImpl; + private GeoMap mapImpl; private IconFactory iconFactory; @@ -108,7 +106,7 @@ public class PathController { private Tooltip stationPlotTooltip; @Autowired - public PathController(SpectraClient spectraMeasurementClient, gov.llnl.gnem.apps.coda.calibration.gui.mapping.api.Map mapImpl, IconFactory iconFactory) { + public PathController(SpectraClient spectraMeasurementClient, GeoMap mapImpl, IconFactory iconFactory) { super(); this.spectraMeasurementClient = spectraMeasurementClient; this.mapImpl = mapImpl; @@ -178,9 +176,7 @@ public void update(Observable observable, Object obj) { frequencyBandComboBox.setCellFactory(fb -> getFBCell()); frequencyBandComboBox.setButtonCell(getFBCell()); frequencyBandComboBox.valueProperty().addListener(e -> { - plotPaths(); - plotBeforeAfter(); - plotSd(); + refreshView(); }); station1ComboBox.setCellFactory(station -> getStationCell()); @@ -189,10 +185,8 @@ public void update(Observable observable, Object obj) { station2ComboBox.setCellFactory(station -> getStationCell()); station2ComboBox.setButtonCell(getStationCell()); - station1ComboBox.valueProperty().addListener(e -> plotBeforeAfter()); - station2ComboBox.valueProperty().addListener(e -> plotBeforeAfter()); - - mapImpl.attach(mapParent); + station1ComboBox.valueProperty().addListener(e -> refreshView()); + station2ComboBox.valueProperty().addListener(e -> refreshView()); } private ListCell getStationCell() { @@ -219,25 +213,19 @@ protected void updateItem(FrequencyBand item, boolean empty) { }; } - @FXML - private void reloadData(ActionEvent e) { - reloadData(); - } - private void reloadData() { - mapImpl.clearIcons(); measurementsFreqBandMap.clear(); stations.clear(); station1ComboBox.getItems().clear(); station2ComboBox.getItems().clear(); frequencyBandComboBox.getItems().clear(); - measurementsFreqBandMap.putAll(spectraMeasurementClient.getMeasuredSpectra() - .filter(Objects::nonNull) - .filter(spectra -> spectra.getWaveform() != null) - .toStream() - .collect(Collectors.groupingBy(spectra -> new FrequencyBand(spectra.getWaveform().getLowFrequency(), - spectra.getWaveform().getHighFrequency())))); + measurementsFreqBandMap.putAll( + spectraMeasurementClient.getMeasuredSpectra() + .filter(Objects::nonNull) + .filter(spectra -> spectra.getWaveform() != null) + .toStream() + .collect(Collectors.groupingBy(spectra -> new FrequencyBand(spectra.getWaveform().getLowFrequency(), spectra.getWaveform().getHighFrequency())))); stations.addAll(measurementsFreqBandMap.values().parallelStream().flatMap(List::parallelStream).map(spectra -> spectra.getWaveform().getStream().getStation()).collect(Collectors.toList())); @@ -250,35 +238,67 @@ private void reloadData() { station2ComboBox.getItems().addAll(stations); station2ComboBox.getSelectionModel().selectFirst(); + refreshView(); + } + + public void refreshView() { plotPaths(); plotBeforeAfter(); plotSd(); } private void plotPaths() { + mapImpl.clearIcons(); if (measurementsFreqBandMap != null && !measurementsFreqBandMap.isEmpty()) { - mapImpl.clearIcons(); SwingUtilities.invokeLater(() -> { List measurements = measurementsFreqBandMap.get(frequencyBandComboBox.getSelectionModel().getSelectedItem()); if (measurements != null) { - mapImpl.addIcons(measurements.parallelStream() - .filter(meas -> meas.getWaveform() != null && meas.getWaveform().getStream() != null) - .map(meas -> meas.getWaveform().getStream().getStation()) - .filter(Objects::nonNull) - .distinct() - .map(station -> iconFactory.newIcon(IconTypes.TRIANGLE_UP, new Location(station.getLatitude(), station.getLongitude()), station.getStationName())) - .collect(Collectors.toSet())); - - mapImpl.addIcons(measurements.parallelStream() - .filter(meas -> meas.getWaveform() != null) - .map(meas -> meas.getWaveform().getEvent()) - .filter(Objects::nonNull) - .map(event -> iconFactory.newIcon(new Location(event.getLatitude(), event.getLongitude()), event.getEventId())) - .collect(Collectors.toSet())); - + Map> stationToEvents = measurements.parallelStream() + .filter(meas -> meas.getWaveform() != null && meas.getWaveform().getStream() != null) + .map(meas -> meas.getWaveform()) + .filter(Objects::nonNull) + .distinct() + .collect( + Collectors.groupingBy( + w -> w.getStream().getStation(), + HashMap::new, + Collectors.mapping(w -> w.getEvent(), Collectors.toList()))); + + mapImpl.addIcons(stationToEvents.keySet().stream().distinct().map(station -> { + Icon icon; + if (station.equals(station1ComboBox.getSelectionModel().getSelectedItem()) || station.equals(station2ComboBox.getSelectionModel().getSelectedItem())) { + icon = iconFactory.newIcon(IconTypes.TRIANGLE_UP, new Location(station.getLatitude(), station.getLongitude()), station.getStationName(), IconStyles.FOCUSED); + } else { + icon = iconFactory.newIcon(IconTypes.TRIANGLE_UP, new Location(station.getLatitude(), station.getLongitude()), station.getStationName(), IconStyles.BACKGROUND); + } + return icon; + }).collect(Collectors.toSet())); + + mapImpl.addIcons( + stationToEvents.values() + .stream() + .flatMap( + events -> events.stream() + .map( + event -> iconFactory.newIcon( + event.getEventId(), + IconTypes.CIRCLE, + new Location(event.getLatitude(), event.getLongitude()), + event.getEventId()))) + .distinct() + .collect(Collectors.toSet())); + + //TODO: Map API updates for drawing Geometry and clearable geometry need to happen for this part. + // mapImpl.addIcons(stationToEvents.entrySet().stream().flatMap(entry -> { + // Station station = entry.getKey(); + // return entry.getValue() + // .stream() + // .map(event -> (Icon) iconFactory.newIcon(IconTypes.LINE, + // new Location(station.getLatitude(), station.getLongitude()), + // new Location(event.getLatitude(), event.getLongitude()))); + // }).collect(Collectors.toList())); } }); - } } @@ -316,11 +336,9 @@ private void plotSd() { if (!beforeStatsStaPair.containsKey(staPair)) { beforeStatsStaPair.put(staPair, beforeStats); afterStatsStaPair.put(staPair, afterStats); - distanceStaPair.put(staPair, - EModel.getDistanceWGS84(firstStation.getLatitude(), - firstStation.getLongitude(), - secondStation.getLatitude(), - secondStation.getLongitude())); + distanceStaPair.put( + staPair, + EModel.getDistanceWGS84(firstStation.getLatitude(), firstStation.getLongitude(), secondStation.getLatitude(), secondStation.getLongitude())); } else { beforeStats = beforeStatsStaPair.get(staPair); afterStats = afterStatsStaPair.get(staPair); @@ -345,29 +363,13 @@ private void plotSd() { if (Double.isNaN(staPairEntry.getValue().getStandardDeviation()) || staPairEntry.getValue().getStandardDeviation() == 0.0) { continue; } - String staPairDisplayName = staPair.getFirst().getStationName() + " " + staPair.getSecond().getStationName(); - Square plotObj = new Square(distanceStaPair.get(staPair), - staPairEntry.getValue().getStandardDeviation(), - 4.0, - Color.RED, - Color.RED, - Color.RED, - staPairDisplayName, - true, - false, - 0); + String staPairDisplayName = staPair.getLeft().getStationName() + " " + staPair.getRight().getStationName(); + Square plotObj = new Square(distanceStaPair.get( + staPair), staPairEntry.getValue().getStandardDeviation(), 4.0, Color.RED, Color.RED, Color.RED, staPairDisplayName, true, false, 0); plotObj.setText(staPairDisplayName + " " + staPairEntry.getValue().getN()); - Circle plotObj2 = new Circle(distanceStaPair.get(staPair), - afterStatsStaPair.get(staPair).getStandardDeviation(), - 4.0, - Color.BLUE, - Color.BLUE, - Color.BLUE, - staPairDisplayName, - true, - false, - 0); + Circle plotObj2 = new Circle(distanceStaPair.get( + staPair), afterStatsStaPair.get(staPair).getStandardDeviation(), 4.0, Color.BLUE, Color.BLUE, Color.BLUE, staPairDisplayName, true, false, 0); plotObj2.setText(staPairDisplayName + " " + afterStatsStaPair.get(staPair).getN()); if (xmax == null) { @@ -406,10 +408,9 @@ private void plotSd() { } String labelText; if (xmax != null) { - plot.SetAxisLimits(xmin - (xmin * .1) - .1, xmax + (xmax * .1) + .1, ymin - (ymin * .1) - .1, ymax + (ymax * .1) + .1); + plot.setAxisLimits(xmin - (xmin * .1) - .1, xmax + (xmax * .1) + .1, ymin - (ymin * .1) - .1, ymax + (ymax * .1) + .1); labelText = "StdDev(Before) = " + dfmt2.format(overallBeforeStats.getStandardDeviation()) + " StdDev(After) = " + dfmt2.format(overallAfterStats.getStandardDeviation()); - } - else { + } else { labelText = ""; } sdPlot.getXaxis().setVisible(false); @@ -524,7 +525,7 @@ private void plotBeforeAfter() { double paddedXmin = xmin - (xmin * .1); double paddedXmax = xmax + (xmax * .1); if (xmax != null) { - plot.SetAxisLimits(paddedXmin, paddedXmax, paddedXmin, paddedXmax); + plot.setAxisLimits(paddedXmin, paddedXmax, paddedXmin, paddedXmax); } int points = 50; double dx = (plot.getXaxis().getMax()) / (points - 1); @@ -535,12 +536,17 @@ private void plotBeforeAfter() { Line line = new Line(xy, xy, Color.black, PaintMode.COPY, PenStyle.DASH, 2); plot.AddPlotObject(line, 1); - + if (stationDistance == null) { stationDistance = 0.0; } - String labelText = "StdDev(Before) = " + dfmt2.format(beforeStats.getStandardDeviation()) + " StdDev(After) = " + dfmt2.format(afterStats.getStandardDeviation()) - + " Station Distance " + dfmt2.format(stationDistance) + " (km)"; + String labelText = "StdDev(Before) = " + + dfmt2.format(beforeStats.getStandardDeviation()) + + " StdDev(After) = " + + dfmt2.format(afterStats.getStandardDeviation()) + + " Station Distance " + + dfmt2.format(stationDistance) + + " (km)"; stationPlot.getXaxis().setVisible(false); stationPlot.getXaxis().setLabelText(labelText); stationPlot.getXaxis().setVisible(true); @@ -548,4 +554,8 @@ private void plotBeforeAfter() { }); } } + + public void update() { + reloadData(); + } } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/ReferenceEventLoadingController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/ReferenceEventLoadingController.java index 02cc616e..6f6d74f9 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/ReferenceEventLoadingController.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/ReferenceEventLoadingController.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -31,13 +31,13 @@ import gov.llnl.gnem.apps.coda.calibration.gui.converters.api.FileToReferenceEventConverter; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ReferenceEventClient; -import gov.llnl.gnem.apps.coda.calibration.model.domain.messaging.Result; +import gov.llnl.gnem.apps.coda.common.model.messaging.Result; //TODO: This class needs a GUI to display a list of files it's attempting to load and process + pass/fail indicators @Component public class ReferenceEventLoadingController { - private final Logger log = LoggerFactory.getLogger(this.getClass()); + private static final Logger log = LoggerFactory.getLogger(ReferenceEventLoadingController.class); private ReferenceEventClient client; 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 66611e51..bc5f825c 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -16,6 +16,7 @@ import java.text.NumberFormat; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -34,16 +35,21 @@ import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ParameterClient; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.PeakVelocityClient; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ShapeMeasurementClient; -import gov.llnl.gnem.apps.coda.calibration.gui.events.WaveformSelectionEvent; -import gov.llnl.gnem.apps.coda.calibration.gui.util.NumberFormatFactory; -import gov.llnl.gnem.apps.coda.calibration.model.domain.FrequencyBand; 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.calibration.model.domain.SharedFrequencyBandParameters; -import gov.llnl.gnem.apps.coda.calibration.model.domain.Waveform; +import gov.llnl.gnem.apps.coda.common.gui.events.WaveformSelectionEvent; +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.mapping.api.Icon.IconTypes; +import gov.llnl.gnem.apps.coda.common.mapping.api.IconFactory; +import gov.llnl.gnem.apps.coda.common.mapping.api.Location; +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 gov.llnl.gnem.apps.coda.common.model.domain.Waveform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import javafx.event.ActionEvent; import javafx.event.Event; import javafx.event.EventHandler; import javafx.fxml.FXML; @@ -107,13 +113,17 @@ private enum SHAPE_DATA_TYPE { private Series pointSeries = new Series<>(pointData); private ObservableList> series = FXCollections.observableArrayList(); private EventBus bus; + private GeoMap mapImpl; + private IconFactory iconFactory; @Autowired - private ShapeController(ParameterClient paramClient, PeakVelocityClient velocityClient, ShapeMeasurementClient shapeClient, EventBus bus) { + private ShapeController(ParameterClient paramClient, PeakVelocityClient velocityClient, ShapeMeasurementClient shapeClient, GeoMap map, IconFactory iconFactory, EventBus bus) { this.paramClient = paramClient; this.velocityClient = velocityClient; this.shapeClient = shapeClient; this.bus = bus; + this.mapImpl = map; + this.iconFactory = iconFactory; } @FXML @@ -124,14 +134,14 @@ public void initialize() { yAxis.setAutoRanging(false); xAxis.setAutoRanging(true); pointSeries.setName("Measurements"); - modelCurveSeries.setName("Model"); + modelCurveSeries.setName("Model"); dataTypeCombo.getItems().addAll(SHAPE_DATA_TYPE.values()); dataTypeCombo.valueProperty().addListener((observable, oldValue, newValue) -> { if (oldValue != newValue) { adjustAxis(newValue); - plotData(); + refreshView(); } }); @@ -141,7 +151,7 @@ public void initialize() { frequencyBandCombo.setButtonCell(getFBCell()); frequencyBandCombo.valueProperty().addListener((observable, oldValue, newValue) -> { if (newValue != null && !newValue.equals(oldValue)) { - plotData(); + refreshView(); } }); @@ -210,60 +220,72 @@ private void plotData() { } private void plotGamma(final FrequencyBand selectedFrequency) { - Function> curvePointProducer = null; + if (selectedFrequency != null) { + Function> curvePointProducer = null; - if (modelCurveMap != null && selectedFrequency != null && modelCurveMap.containsKey(selectedFrequency)) { - SharedFrequencyBandParameters model = modelCurveMap.get(selectedFrequency); - curvePointProducer = i -> new Data<>(i, model.getGamma0() - (model.getGamma1() / (model.getGamma2() + ((double) i)))); - } + if (modelCurveMap != null && selectedFrequency != null && modelCurveMap.containsKey(selectedFrequency)) { + SharedFrequencyBandParameters model = modelCurveMap.get(selectedFrequency); + curvePointProducer = i -> new Data<>(i, model.getGamma0() - (model.getGamma1() / (model.getGamma2() + ((double) i)))); + } - Function> valueSupplier; + Function> valueSupplier; - if (velocityDistancePairsFreqMap != null) { - valueSupplier = freq -> shapeDistancePairsFreqMap.get(freq); - } else { - valueSupplier = freq -> new ArrayList<>(0); - } + if (velocityDistancePairsFreqMap != null) { + valueSupplier = freq -> Optional.ofNullable(shapeDistancePairsFreqMap.get(freq)).orElse(new ArrayList<>(0)); + } else { + valueSupplier = freq -> new ArrayList<>(0); + } - plot(selectedFrequency, valueSupplier, val -> new Data<>(val.getDistance(), val.getMeasuredGamma()), val -> showWaveformPopup(val.getWaveform()), curvePointProducer); + Optional.ofNullable(mapMeasurements(valueSupplier.apply(selectedFrequency).stream().map(v -> v.getWaveform()).filter(Objects::nonNull).collect(Collectors.toList()))) + .ifPresent(mapImpl::addIcons); + plot(selectedFrequency, valueSupplier, val -> new Data<>(val.getDistance(), val.getMeasuredGamma()), val -> showWaveformPopup(val.getWaveform()), curvePointProducer); + } } private void plotBeta(final FrequencyBand selectedFrequency) { - Function> curvePointProducer = null; + if (selectedFrequency != null) { + Function> curvePointProducer = null; - if (modelCurveMap != null && selectedFrequency != null && modelCurveMap.containsKey(selectedFrequency)) { - SharedFrequencyBandParameters model = modelCurveMap.get(selectedFrequency); - curvePointProducer = i -> new Data<>(i, model.getBeta0() - (model.getBeta1() / (model.getBeta2() + ((double) i)))); - } + if (modelCurveMap != null && selectedFrequency != null && modelCurveMap.containsKey(selectedFrequency)) { + SharedFrequencyBandParameters model = modelCurveMap.get(selectedFrequency); + curvePointProducer = i -> new Data<>(i, model.getBeta0() - (model.getBeta1() / (model.getBeta2() + ((double) i)))); + } - Function> valueSupplier; + Function> valueSupplier; - if (velocityDistancePairsFreqMap != null) { - valueSupplier = freq -> shapeDistancePairsFreqMap.get(freq); - } else { - valueSupplier = freq -> new ArrayList<>(0); - } + if (velocityDistancePairsFreqMap != null) { + valueSupplier = freq -> Optional.ofNullable(shapeDistancePairsFreqMap.get(freq)).orElse(new ArrayList<>(0)); + } else { + valueSupplier = freq -> new ArrayList<>(0); + } - plot(selectedFrequency, valueSupplier, val -> new Data<>(val.getDistance(), val.getMeasuredBeta()), val -> showWaveformPopup(val.getWaveform()), curvePointProducer); + Optional.ofNullable(mapMeasurements(valueSupplier.apply(selectedFrequency).stream().map(v -> v.getWaveform()).filter(Objects::nonNull).collect(Collectors.toList()))) + .ifPresent(mapImpl::addIcons); + plot(selectedFrequency, valueSupplier, val -> new Data<>(val.getDistance(), val.getMeasuredBeta()), val -> showWaveformPopup(val.getWaveform()), curvePointProducer); + } } private void plotVelocity(final FrequencyBand selectedFrequency) { - Function> curvePointProducer = null; + if (selectedFrequency != null) { + Function> curvePointProducer = null; - if (modelCurveMap != null && selectedFrequency != null && modelCurveMap.containsKey(selectedFrequency)) { - SharedFrequencyBandParameters model = modelCurveMap.get(selectedFrequency); - curvePointProducer = i -> new Data<>(i, model.getVelocity0() - (model.getVelocity1() / (model.getVelocity2() + ((double) i)))); - } + if (modelCurveMap != null && selectedFrequency != null && modelCurveMap.containsKey(selectedFrequency)) { + SharedFrequencyBandParameters model = modelCurveMap.get(selectedFrequency); + curvePointProducer = i -> new Data<>(i, model.getVelocity0() - (model.getVelocity1() / (model.getVelocity2() + ((double) i)))); + } - Function> valueSupplier; + Function> valueSupplier; - if (velocityDistancePairsFreqMap != null) { - valueSupplier = freq -> velocityDistancePairsFreqMap.get(freq); - } else { - valueSupplier = freq -> new ArrayList<>(0); - } + if (velocityDistancePairsFreqMap != null) { + valueSupplier = freq -> Optional.ofNullable(velocityDistancePairsFreqMap.get(freq)).orElse(new ArrayList<>(0)); + } else { + valueSupplier = freq -> new ArrayList<>(0); + } - plot(selectedFrequency, valueSupplier, val -> new Data<>(val.getDistance(), val.getVelocity()), val -> showWaveformPopup(val.getWaveform()), curvePointProducer); + Optional.ofNullable(mapMeasurements(valueSupplier.apply(selectedFrequency).stream().map(v -> v.getWaveform()).filter(Objects::nonNull).collect(Collectors.toList()))) + .ifPresent(mapImpl::addIcons); + plot(selectedFrequency, valueSupplier, val -> new Data<>(val.getDistance(), val.getVelocity()), val -> showWaveformPopup(val.getWaveform()), curvePointProducer); + } } private void plot(final FrequencyBand selectedFrequency, Function> valueSupplier, Function> dataPointSupplier, @@ -301,17 +323,26 @@ private void plot(final FrequencyBand selectedFrequency, Function mapMeasurements(List waveforms) { + return waveforms.stream().flatMap(w -> { + List icons = new ArrayList<>(); + if (w.getStream() != null && w.getStream().getStation() != null) { + Station station = w.getStream().getStation(); + icons.add(iconFactory.newIcon(IconTypes.TRIANGLE_UP, new Location(station.getLatitude(), station.getLongitude()), station.getStationName())); + } + if (w.getEvent() != null) { + icons.add(iconFactory.newIcon(w.getEvent().getEventId(), IconTypes.CIRCLE, new Location(w.getEvent().getLatitude(), w.getEvent().getLongitude()), w.getEvent().getEventId())); + } + return icons.stream(); + }).collect(Collectors.toList()); + } + private EventHandler showWaveformPopup(Waveform waveform) { return event -> { bus.post(new WaveformSelectionEvent(waveform.getId())); }; } - @FXML - private void reloadData(ActionEvent e) { - reloadData(); - } - private void reloadData() { velocityDistancePairsFreqMap.clear(); shapeDistancePairsFreqMap.clear(); @@ -320,21 +351,32 @@ private void reloadData() { frequencyBandCombo.getItems().clear(); paramClient.getSharedFrequencyBandParameters().subscribe(sfb -> modelCurveMap.put(new FrequencyBand(sfb.getLowFrequency(), sfb.getHighFrequency()), sfb)); - velocityDistancePairsFreqMap.putAll(velocityClient.getMeasuredPeakVelocities() - .toStream() - .filter(Objects::nonNull) - .filter(pvm -> pvm.getWaveform() != null) - .collect(Collectors.groupingBy(pvm -> new FrequencyBand(pvm.getWaveform().getLowFrequency(), pvm.getWaveform().getHighFrequency())))); - - shapeDistancePairsFreqMap.putAll(shapeClient.getMeasuredShapes() - .toStream() - .filter(Objects::nonNull) - .filter(shape -> shape.getWaveform() != null) - .collect(Collectors.groupingBy(shape -> new FrequencyBand(shape.getWaveform().getLowFrequency(), shape.getWaveform().getHighFrequency())))); + velocityDistancePairsFreqMap.putAll( + velocityClient.getMeasuredPeakVelocities() + .toStream() + .filter(Objects::nonNull) + .filter(pvm -> pvm.getWaveform() != null) + .collect(Collectors.groupingBy(pvm -> new FrequencyBand(pvm.getWaveform().getLowFrequency(), pvm.getWaveform().getHighFrequency())))); + + shapeDistancePairsFreqMap.putAll( + shapeClient.getMeasuredShapes() + .toStream() + .filter(Objects::nonNull) + .filter(shape -> shape.getWaveform() != null) + .collect(Collectors.groupingBy(shape -> new FrequencyBand(shape.getWaveform().getLowFrequency(), shape.getWaveform().getHighFrequency())))); frequencyBandCombo.getItems().addAll(modelCurveMap.keySet()); frequencyBandCombo.getSelectionModel().selectFirst(); + refreshView(); + } + + public void refreshView() { + mapImpl.clearIcons(); plotData(); } + + public void update() { + reloadData(); + } } 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 cb03a4c2..b2d3eb6b 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) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -18,6 +18,7 @@ import java.awt.geom.Point2D; import java.time.Duration; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -38,23 +39,28 @@ import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ReferenceEventClient; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.SpectraClient; -import gov.llnl.gnem.apps.coda.calibration.gui.events.WaveformSelectionEvent; -import gov.llnl.gnem.apps.coda.calibration.gui.plotting.LabeledPlotPoint; -import gov.llnl.gnem.apps.coda.calibration.gui.plotting.PlotPoint; import gov.llnl.gnem.apps.coda.calibration.gui.plotting.SpectralPlot; -import gov.llnl.gnem.apps.coda.calibration.gui.plotting.SymbolStyleMapFactory; -import gov.llnl.gnem.apps.coda.calibration.gui.util.MaybeNumericStringComparator; 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.Spectra; import gov.llnl.gnem.apps.coda.calibration.model.domain.SpectraMeasurement; -import gov.llnl.gnem.apps.coda.calibration.model.domain.Waveform; +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.MaybeNumericStringComparator; +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.mapping.api.Icon.IconTypes; +import gov.llnl.gnem.apps.coda.common.mapping.api.IconFactory; +import gov.llnl.gnem.apps.coda.common.mapping.api.Location; +import gov.llnl.gnem.apps.coda.common.model.domain.Station; +import gov.llnl.gnem.apps.coda.common.model.domain.Waveform; import javafx.beans.binding.Bindings; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.embed.swing.SwingFXUtils; import javafx.embed.swing.SwingNode; -import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.ComboBox; import javafx.scene.control.TableColumn; @@ -139,12 +145,18 @@ public class SiteController { private Map symbolStyleMap; + private GeoMap mapImpl; + + private IconFactory iconFactory; + @Autowired - private SiteController(SpectraClient spectraClient, ReferenceEventClient referenceEventClient, EventBus bus, SymbolStyleMapFactory styleFactory) { + private SiteController(SpectraClient spectraClient, ReferenceEventClient referenceEventClient, SymbolStyleMapFactory styleFactory, GeoMap map, IconFactory iconFactory, EventBus bus) { this.spectraClient = spectraClient; this.referenceEventClient = referenceEventClient; - this.bus = bus; this.symbolStyleMapFactory = styleFactory; + this.mapImpl = map; + this.bus = bus; + this.iconFactory = iconFactory; } @FXML @@ -157,9 +169,9 @@ public void initialize() { @Override public void update(Observable observable, Object obj) { - if (obj instanceof PlotObjectClicked && ((PlotObjectClicked) obj).me.getID() == MouseEvent.MOUSE_RELEASED) { + if (obj instanceof PlotObjectClicked && ((PlotObjectClicked) obj).getMouseEvent().getID() == MouseEvent.MOUSE_RELEASED) { PlotObjectClicked poc = (PlotObjectClicked) obj; - PlotObject po = poc.po; + PlotObject po = poc.getPlotObject(); if (po != null && po instanceof Symbol) { SpectraMeasurement spectra = rawSymbolMap.get(new Point2D.Double(((Symbol) po).getXcenter(), ((Symbol) po).getYcenter())); if (spectra != null) { @@ -176,9 +188,9 @@ public void update(Observable observable, Object obj) { @Override public void update(Observable observable, Object obj) { - if (obj instanceof PlotObjectClicked && ((PlotObjectClicked) obj).me.getID() == MouseEvent.MOUSE_RELEASED) { + if (obj instanceof PlotObjectClicked && ((PlotObjectClicked) obj).getMouseEvent().getID() == MouseEvent.MOUSE_RELEASED) { PlotObjectClicked poc = (PlotObjectClicked) obj; - PlotObject po = poc.po; + PlotObject po = poc.getPlotObject(); if (po != null && po instanceof Symbol) { SpectraMeasurement spectra = pathSymbolMap.get(new Point2D.Double(((Symbol) po).getXcenter(), ((Symbol) po).getYcenter())); if (spectra != null) { @@ -196,9 +208,9 @@ public void update(Observable observable, Object obj) { @Override public void update(Observable observable, Object obj) { - if (obj instanceof PlotObjectClicked && ((PlotObjectClicked) obj).me.getID() == MouseEvent.MOUSE_RELEASED) { + if (obj instanceof PlotObjectClicked && ((PlotObjectClicked) obj).getMouseEvent().getID() == MouseEvent.MOUSE_RELEASED) { PlotObjectClicked poc = (PlotObjectClicked) obj; - PlotObject po = poc.po; + PlotObject po = poc.getPlotObject(); if (po != null && po instanceof Symbol) { SpectraMeasurement spectra = siteSymbolMap.get(new Point2D.Double(((Symbol) po).getXcenter(), ((Symbol) po).getYcenter())); if (spectra != null) { @@ -228,7 +240,7 @@ public void update(Observable observable, Object obj) { evidCombo.valueProperty().addListener((observable, oldValue, newValue) -> { if (newValue != null && !newValue.equals(oldValue)) { - plotSpectra(); + refreshView(); } }); @@ -237,31 +249,23 @@ public void update(Observable observable, Object obj) { 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()); + stressDropCol.setCellValueFactory( + x -> Bindings.createDoubleBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(ReferenceMwParameters::getStressDropInMpa).orElseGet(() -> 0.0)).asObject()); - measuredEvidCol.setCellValueFactory(x -> Bindings.createStringBinding(() -> Optional.ofNullable(x) - .map(CellDataFeatures::getValue) - .map(MeasuredMwParameters::getEventId) - .orElseGet(String::new))); + 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()); + 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()); + measuredStressDropCol.setCellValueFactory( + x -> Bindings.createDoubleBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(MeasuredMwParameters::getStressDropInMpa).orElseGet(() -> 0.0)).asObject()); iconCol.setCellValueFactory(x -> Bindings.createObjectBinding(() -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(pp -> { - ImageView imView = new ImageView(SwingFXUtils.toFXImage(SymbolFactory.createSymbol(pp.getStyle(), 0, 0, 2, pp.getColor(), pp.getColor(), pp.getColor(), "", true, false, 10.0) - .getBufferedImage(256), - null)); + ImageView imView = new ImageView(SwingFXUtils.toFXImage( + SymbolFactory.createSymbol(pp.getStyle(), 0, 0, 2, pp.getColor(), pp.getColor(), pp.getColor(), "", true, false, 10.0).getBufferedImage(256), + null)); imView.setFitHeight(12); imView.setFitWidth(12); return imView; @@ -272,7 +276,7 @@ public void update(Observable observable, Object obj) { refEventTable.setItems(referenceMwParameters); measuredEventTable.setItems(measuredMwParameters); iconTable.setItems(stationSymbols); - + iconCol.prefWidthProperty().bind(iconTable.widthProperty().multiply(0.3)); stationCol.prefWidthProperty().bind(iconTable.widthProperty().multiply(0.7)); } @@ -298,13 +302,29 @@ private void plotSpectra() { rawPlot.plotXYdata(toPlotPoints(filteredMeasurements, SpectraMeasurement::getRawAtMeasurementTime), Boolean.TRUE); pathPlot.plotXYdata(toPlotPoints(filteredMeasurements, SpectraMeasurement::getPathCorrected), Boolean.TRUE); sitePlot.plotXYdata(toPlotPoints(filteredMeasurements, SpectraMeasurement::getPathAndSiteCorrected), Boolean.TRUE, referenceSpectra, theoreticalSpectra); + mapImpl.addIcons(mapMeasurements(filteredMeasurements)); } else { rawPlot.plotXYdata(toPlotPoints(spectralMeasurements, SpectraMeasurement::getRawAtMeasurementTime), Boolean.FALSE); pathPlot.plotXYdata(toPlotPoints(spectralMeasurements, SpectraMeasurement::getPathCorrected), Boolean.FALSE); sitePlot.plotXYdata(toPlotPoints(spectralMeasurements, SpectraMeasurement::getPathAndSiteCorrected), Boolean.FALSE); + mapImpl.addIcons(mapMeasurements(spectralMeasurements)); } } + private Collection mapMeasurements(List filteredMeasurements) { + return filteredMeasurements.stream().map(meas -> meas.getWaveform()).filter(Objects::nonNull).flatMap(w -> { + List icons = new ArrayList<>(); + if (w.getStream() != null && w.getStream().getStation() != null) { + Station station = w.getStream().getStation(); + icons.add(iconFactory.newIcon(IconTypes.TRIANGLE_UP, new Location(station.getLatitude(), station.getLongitude()), station.getStationName())); + } + if (w.getEvent() != null) { + icons.add(iconFactory.newIcon(w.getEvent().getEventId(), IconTypes.CIRCLE, new Location(w.getEvent().getLatitude(), w.getEvent().getLongitude()), w.getEvent().getEventId())); + } + return icons.stream(); + }).collect(Collectors.toList()); + } + private void clearSpectraPlots() { rawPlot.clearPlot(); pathPlot.clearPlot(); @@ -318,11 +338,13 @@ private List filterToEvent(String selectedItem, List mapSpectraToPoint(List spectralMeasurements, Function func) { return spectralMeasurements.stream() .filter(spectra -> !func.apply(spectra).equals(0.0)) - .collect(Collectors.toMap(spectra -> new Point2D.Double(Math.log10(centerFreq(spectra.getWaveform().getLowFrequency(), spectra.getWaveform().getHighFrequency())), - func.apply(spectra)), - Function.identity(), - (a, b) -> b, - HashMap::new)); + .collect( + Collectors.toMap( + spectra -> new Point2D.Double(Math.log10(centerFreq(spectra.getWaveform().getLowFrequency(), spectra.getWaveform().getHighFrequency())), + func.apply(spectra)), + Function.identity(), + (a, b) -> b, + HashMap::new)); } private List toPlotPoints(List spectralMeasurements, Function func) { @@ -337,12 +359,7 @@ private double centerFreq(Double lowFrequency, Double highFrequency) { return lowFrequency + (highFrequency - lowFrequency) / 2.; } - @FXML - private void reloadData(ActionEvent e) { - requestData(); - } - - private void requestData() { + private void reloadData() { clearSpectraPlots(); referenceMwParameters.clear(); @@ -356,11 +373,12 @@ private void requestData() { evids.clear(); evids.add("All"); - spectralMeasurements.addAll(spectraClient.getMeasuredSpectra() - .filter(Objects::nonNull) - .filter(spectra -> spectra.getWaveform() != null && spectra.getWaveform().getEvent() != null && spectra.getWaveform().getStream() != null) - .toStream() - .collect(Collectors.toList())); + spectralMeasurements.addAll( + spectraClient.getMeasuredSpectra() + .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 @@ -372,4 +390,13 @@ public String apply(SpectraMeasurement t) { evids.addAll(spectralMeasurements.stream().map(spec -> spec.getWaveform().getEvent().getEventId()).distinct().sorted(new MaybeNumericStringComparator()).collect(Collectors.toList())); } + + public void refreshView() { + mapImpl.clearIcons(); + plotSpectra(); + } + + public void update() { + reloadData(); + } } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/ModelController.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/ModelController.java index 6ab2b001..9efa9ad2 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/ModelController.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/controllers/parameters/ModelController.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -15,6 +15,7 @@ package gov.llnl.gnem.apps.coda.calibration.gui.controllers.parameters; import java.util.Objects; +import java.util.Optional; import javax.annotation.PostConstruct; @@ -24,14 +25,18 @@ import org.springframework.stereotype.Component; import com.fasterxml.jackson.core.JsonProcessingException; +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ParameterClient; -import gov.llnl.gnem.apps.coda.calibration.gui.util.CellBindingUtils; +import gov.llnl.gnem.apps.coda.calibration.gui.util.TimeLatchedGetSet; 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.messaging.MdacDataChangeEvent; +import gov.llnl.gnem.apps.coda.common.gui.util.CellBindingUtils; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import javafx.event.Event; import javafx.fxml.FXML; import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn.CellEditEvent; @@ -40,7 +45,7 @@ @Component public class ModelController { - private final Logger log = LoggerFactory.getLogger(this.getClass()); + private static final Logger log = LoggerFactory.getLogger(ModelController.class); @FXML private TableView fiTableView; @@ -125,14 +130,32 @@ public class ModelController { private ParameterClient client; + private EventBus bus; + + private TimeLatchedGetSet scheduler; + @Autowired - public ModelController(ParameterClient client) { + public ModelController(ParameterClient client, EventBus bus) { this.client = client; - } - - @FXML - private void reloadTable(Event e) { - requestData(); + this.bus = bus; + this.bus.register(this); + + this.scheduler = new TimeLatchedGetSet(() -> requestData(), () -> { + fiData.forEach(p -> { + try { + client.setFiParameter(p).subscribe(); + } catch (JsonProcessingException e1) { + log.error(e1.getMessage(), e1); + } + }); + psData.forEach(p -> { + try { + client.setPsParameter(p).subscribe(); + } catch (JsonProcessingException e1) { + log.error(e1.getMessage(), e1); + } + }); + }); } @PostConstruct @@ -141,33 +164,35 @@ private void onSpringStartupFinished() { } @FXML - private void postUpdate(CellEditEvent e) { - fiData.forEach(p -> { - try { - client.postFiParameters(p); - } catch (JsonProcessingException e1) { - log.error(e1.getMessage(), e1); - } - }); + private void postUpdate(CellEditEvent event) { + scheduler.set(); + } - psData.forEach(p -> { - try { - client.postPsParameters(p); - } catch (JsonProcessingException e1) { - log.error(e1.getMessage(), e1); - } - }); - fiData.clear(); - psData.clear(); - requestData(); + @Subscribe + private void updateNotification(MdacDataChangeEvent event) { + scheduler.get(); } protected void requestData() { fiData.clear(); psData.clear(); - client.getFiParameters().filter(Objects::nonNull).filter(value -> null != value.getId()).subscribe(value -> fiData.add(value), err -> log.trace(err.getMessage(), err)); - client.getPsParameters().filter(Objects::nonNull).filter(value -> null != value.getId()).subscribe(value -> psData.add(value), err -> log.trace(err.getMessage(), err)); + client.getFiParameters() + .filter(Objects::nonNull) + .filter(value -> null != value.getId()) + .doOnComplete(() -> fiTableView.sort()) + .subscribe(value -> fiData.add(value), err -> log.trace(err.getMessage(), err)); + + client.getPsParameters() + .filter(Objects::nonNull) + .filter(value -> null != value.getId()) + .doOnComplete(() -> psTableView.sort()) + .subscribe(value -> psData.add(value), err -> log.trace(err.getMessage(), err)); + + Platform.runLater(() -> { + Optional.ofNullable(fiTableView).ifPresent(v -> v.refresh()); + Optional.ofNullable(psTableView).ifPresent(v -> v.refresh()); + }); } @FXML 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 9390b9d3..ec352baf 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -14,23 +14,16 @@ */ package gov.llnl.gnem.apps.coda.calibration.gui.controllers.parameters; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import gov.llnl.gnem.apps.coda.calibration.gui.data.exporters.SwftStyleParamExporter; -import javafx.application.Platform; +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; + +import gov.llnl.gnem.apps.coda.calibration.gui.events.ParametersLoadedEvent; import javafx.event.ActionEvent; import javafx.fxml.FXML; -import javafx.scene.control.Alert; -import javafx.scene.control.Alert.AlertType; import javafx.scene.layout.StackPane; -import javafx.stage.FileChooser; -import javafx.stage.FileChooser.ExtensionFilter; @Component public class ParametersController { @@ -47,55 +40,31 @@ public class ParametersController { @FXML private SiteBandController siteBandController; - private SwftStyleParamExporter paramExporter; + private EventBus bus; @Autowired - public ParametersController(SwftStyleParamExporter paramExporter) { - this.paramExporter = paramExporter; + public ParametersController(EventBus bus) { + this.bus = bus; + bus.register(this); + } + + @Subscribe + private void listener(ParametersLoadedEvent event) { + reloadData(); } @FXML private void reloadData(ActionEvent e) { + reloadData(); + } + + private void reloadData() { sharedBandController.requestData(); modelController.requestData(); siteBandController.requestData(); } - @FXML - private void exportData(ActionEvent e) { - //Save all parameters to an archive file and prompt the user about where to save it. - FileChooser fileChooser = new FileChooser(); - fileChooser.setTitle("Open Resource File"); - fileChooser.getExtensionFilters().addAll(new ExtensionFilter("Archive File", "*.zip")); - fileChooser.setInitialFileName("Calibration_Parameters.zip"); - File selectedFile = fileChooser.showSaveDialog(parameters.getScene().getWindow()); - - if (selectedFile != null) { - - File exportArchive; - try { - if (!selectedFile.exists()) { - selectedFile.createNewFile(); - } else if (!selectedFile.canWrite()) { - Platform.runLater(() -> { - Alert alert = new Alert(AlertType.ERROR); - alert.setTitle("File Permissions Error"); - alert.setHeaderText("Unable to write to file or directory."); - alert.setContentText("Unable to write file, do you have write permissions on the selected directory?"); - alert.show(); - }); - } - exportArchive = paramExporter.createExportArchive(); - Files.move(exportArchive.toPath(), selectedFile.toPath(), StandardCopyOption.REPLACE_EXISTING); - } catch (IOException e1) { - Platform.runLater(() -> { - Alert alert = new Alert(AlertType.ERROR); - alert.setTitle("File IO Error"); - alert.setHeaderText("Unable to export results"); - alert.setContentText(e1.getMessage()); - alert.show(); - }); - } - } + public void update() { + reloadData(); } } \ No newline at end of file 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 a0e3de2d..8c2ac03f 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -15,7 +15,10 @@ package gov.llnl.gnem.apps.coda.calibration.gui.controllers.parameters; import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; +import java.util.Optional; import javax.annotation.PostConstruct; @@ -25,16 +28,21 @@ import org.springframework.stereotype.Component; import com.fasterxml.jackson.core.JsonProcessingException; +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ParameterClient; -import gov.llnl.gnem.apps.coda.calibration.gui.util.CellBindingUtils; -import gov.llnl.gnem.apps.coda.calibration.gui.util.MaybeNumericStringComparator; -import gov.llnl.gnem.apps.coda.calibration.gui.util.NumberFormatFactory; -import gov.llnl.gnem.apps.coda.calibration.model.domain.SharedFrequencyBandParameters; +import gov.llnl.gnem.apps.coda.calibration.gui.util.TimeLatchedGetSet; +import gov.llnl.gnem.apps.coda.calibration.model.messaging.BandParametersDataChangeEvent; +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.SharedFrequencyBandParameters; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import javafx.event.Event; import javafx.fxml.FXML; +import javafx.scene.control.ContextMenu; +import javafx.scene.control.SelectionMode; import javafx.scene.control.TableColumn; import javafx.scene.control.TableColumn.CellEditEvent; import javafx.scene.control.TableView; @@ -42,7 +50,7 @@ @Component public class SharedBandController { - private final Logger log = LoggerFactory.getLogger(this.getClass()); + private static final Logger log = LoggerFactory.getLogger(SharedBandController.class); private final NumberFormat dfmt4 = NumberFormatFactory.fourDecimalOneLeadingZero(); @@ -50,94 +58,99 @@ public class SharedBandController { private TableView codaSharedTableView; @FXML - TableColumn lowFreqCol; + private ContextMenu paramTableContextMenu; @FXML - TableColumn highFreqCol; + private TableColumn lowFreqCol; @FXML - TableColumn v0Col; + private TableColumn highFreqCol; + + @FXML + private TableColumn v0Col; @FXML - TableColumn v1Col; + private TableColumn v1Col; @FXML - TableColumn v2Col; + private TableColumn v2Col; @FXML - TableColumn b0Col; + private TableColumn b0Col; @FXML - TableColumn b1Col; + private TableColumn b1Col; @FXML - TableColumn b2Col; + private TableColumn b2Col; @FXML - TableColumn g0Col; + private TableColumn g0Col; @FXML - TableColumn g1Col; + private TableColumn g1Col; @FXML - TableColumn g2Col; + private TableColumn g2Col; @FXML - TableColumn minSnrCol; + private TableColumn minSnrCol; @FXML - TableColumn s1Col; + private TableColumn s1Col; @FXML - TableColumn s2Col; + private TableColumn s2Col; @FXML - TableColumn xcCol; + private TableColumn xcCol; @FXML - TableColumn xtCol; + private TableColumn xtCol; @FXML - TableColumn qCol; + private TableColumn qCol; @FXML - TableColumn minLengthCol; + private TableColumn minLengthCol; @FXML - TableColumn maxLengthCol; + private TableColumn maxLengthCol; @FXML - TableColumn measureTimeCol; + private TableColumn measureTimeCol; private ObservableList sharedFbData = FXCollections.observableArrayList(); private ParameterClient client; + private EventBus bus; + + private TimeLatchedGetSet scheduler; + @Autowired - public SharedBandController(ParameterClient client) { + public SharedBandController(ParameterClient client, EventBus bus) { this.client = client; + this.bus = bus; + this.bus.register(this); + this.scheduler = new TimeLatchedGetSet(() -> requestData(), () -> sharedFbData.forEach(sfb -> { + try { + client.setSharedFrequencyBandParameter(sfb).subscribe(); + } catch (JsonProcessingException e1) { + log.error(e1.getMessage(), e1); + } + })); } @FXML - private void reloadTable(Event e) { - requestData(); + private void postUpdate(CellEditEvent event) { + scheduler.set(); } - @FXML - private void postUpdate(CellEditEvent e) { - sharedFbData.forEach(fb -> { - try { - client.postSharedFrequencyBandParameters(fb); - } catch (JsonProcessingException e1) { - log.error(e1.getMessage(), e1); - } - }); - sharedFbData.clear(); - requestData(); + @Subscribe + private void updateNotification(BandParametersDataChangeEvent event) { + scheduler.get(); } @FXML public void initialize() { CellBindingUtils.attachEditableTextCellFactories(lowFreqCol, SharedFrequencyBandParameters::getLowFrequency, SharedFrequencyBandParameters::setLowFrequency); - lowFreqCol.comparatorProperty().set(new MaybeNumericStringComparator()); - CellBindingUtils.attachEditableTextCellFactories(highFreqCol, SharedFrequencyBandParameters::getHighFrequency, SharedFrequencyBandParameters::setHighFrequency); - highFreqCol.comparatorProperty().set(new MaybeNumericStringComparator()); CellBindingUtils.attachTextCellFactories(v0Col, SharedFrequencyBandParameters::getVelocity0, dfmt4); CellBindingUtils.attachTextCellFactories(v1Col, SharedFrequencyBandParameters::getVelocity1, dfmt4); @@ -162,6 +175,23 @@ public void initialize() { CellBindingUtils.attachEditableTextCellFactories(measureTimeCol, SharedFrequencyBandParameters::getMeasurementTime, SharedFrequencyBandParameters::setMeasurementTime); codaSharedTableView.setItems(sharedFbData); + codaSharedTableView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); + } + + @FXML + private void clearTable() { + sharedFbData.forEach(x -> client.removeSharedFrequencyBandParameter(x).subscribe()); + requestData(); + } + + @FXML + private void removeBands() { + List sfb = new ArrayList<>(); + codaSharedTableView.getSelectionModel().getSelectedIndices().forEach(i -> sfb.add(sharedFbData.get(i))); + if (!sfb.isEmpty()) { + sfb.forEach(x -> client.removeSharedFrequencyBandParameter(x).subscribe()); + requestData(); + } } @PostConstruct @@ -171,6 +201,14 @@ private void onSpringStartupFinished() { protected void requestData() { sharedFbData.clear(); - client.getSharedFrequencyBandParameters().filter(Objects::nonNull).filter(value -> null != value.getId()).subscribe(value -> sharedFbData.add(value), err -> log.trace(err.getMessage(), err)); + client.getSharedFrequencyBandParameters() + .filter(Objects::nonNull) + .filter(value -> null != value.getId()) + .doOnComplete(() -> codaSharedTableView.sort()) + .subscribe(value -> sharedFbData.add(value), err -> log.trace(err.getMessage(), err)); + + Platform.runLater(() -> { + Optional.ofNullable(codaSharedTableView).ifPresent(v -> v.refresh()); + }); } } 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 458867aa..e04d02c0 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -18,18 +18,16 @@ import java.util.Objects; import java.util.Optional; -import javax.annotation.PostConstruct; - 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.gui.util.MaybeNumericStringComparator; -import gov.llnl.gnem.apps.coda.calibration.gui.util.NumberFormatFactory; import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; -import gov.llnl.gnem.apps.coda.calibration.model.domain.Station; +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.model.domain.Station; import javafx.beans.binding.Bindings; import javafx.collections.FXCollections; import javafx.collections.ObservableList; @@ -42,7 +40,7 @@ @Component public class SiteBandController { - private final Logger log = LoggerFactory.getLogger(this.getClass()); + private static final Logger log = LoggerFactory.getLogger(SiteBandController.class); private final NumberFormat dfmt2 = NumberFormatFactory.twoDecimalOneLeadingZero(); @@ -78,49 +76,49 @@ private void reloadData(ActionEvent e) { @FXML public void initialize() { - stationCol.setCellValueFactory(x -> Bindings.createStringBinding(() -> Optional.ofNullable(x) - .map(CellDataFeatures::getValue) - .map(SiteFrequencyBandParameters::getStation) - .filter(Objects::nonNull) - .map(Station::getStationName) - .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))); + stationCol.setCellValueFactory( + x -> Bindings.createStringBinding( + () -> Optional.ofNullable(x) + .map(CellDataFeatures::getValue) + .map(SiteFrequencyBandParameters::getStation) + .filter(Objects::nonNull) + .map(Station::getStationName) + .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.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))); + siteCorrectionCol.setCellValueFactory( + x -> Bindings.createStringBinding( + () -> Optional.ofNullable(x).map(CellDataFeatures::getValue).map(SiteFrequencyBandParameters::getSiteTerm).filter(Objects::nonNull).map(dfmt2::format).orElseGet(String::new))); codaSiteTableView.setItems(siteFbData); } - @PostConstruct - private void onSpringStartupFinished() { - requestData(); - } - protected void requestData() { siteFbData.clear(); - client.getSiteSpecificFrequencyBandParameters().filter(Objects::nonNull).filter(value -> null != value.getId()).subscribe(value -> siteFbData.add(value), - err -> log.trace(err.getMessage(), err)); + client.getSiteSpecificFrequencyBandParameters() + .filter(Objects::nonNull) + .filter(value -> null != value.getId()) + .doOnComplete(() -> codaSiteTableView.sort()) + .subscribe(value -> siteFbData.add(value), err -> log.trace(err.getMessage(), err)); } } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/StackInfo.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/StackInfo.java new file mode 100644 index 00000000..5f78a142 --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/StackInfo.java @@ -0,0 +1,40 @@ +/* +* 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.converters; + +public class StackInfo { + + private Double lowFreq; + private Double highFreq; + private String dataType; + + public StackInfo(Double lowFreq, Double highFreq, String dataType) { + this.lowFreq = lowFreq; + this.highFreq = highFreq; + this.dataType = dataType; + } + + public Double getLowFrequency() { + return lowFreq; + } + + public Double getHighFrequency() { + return highFreq; + } + + public String getDataType() { + return dataType; + } +} diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/api/CodaFilenameParser.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/api/CodaFilenameParser.java index 817481f2..ba339144 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/api/CodaFilenameParser.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/api/CodaFilenameParser.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -14,15 +14,10 @@ */ package gov.llnl.gnem.apps.coda.calibration.gui.converters.api; -import java.util.Map; +import gov.llnl.gnem.apps.coda.calibration.gui.converters.StackInfo; +import gov.llnl.gnem.apps.coda.common.model.messaging.Result; public interface CodaFilenameParser { - public Map parse(String name); - - public Double getLowFrequency(); - - public Double getHighFrequency(); - - public String getDataType(); + public Result parse(String name); } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/api/FileToParameterConverter.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/api/FileToParameterConverter.java index 0f233ac2..20618bbb 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/api/FileToParameterConverter.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/api/FileToParameterConverter.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -18,7 +18,7 @@ import java.nio.file.PathMatcher; import java.util.List; -import gov.llnl.gnem.apps.coda.calibration.model.domain.messaging.Result; +import gov.llnl.gnem.apps.coda.common.model.messaging.Result; import reactor.core.publisher.Flux; public interface FileToParameterConverter { diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/api/FileToReferenceEventConverter.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/api/FileToReferenceEventConverter.java index 4eeed039..3375ec2e 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/api/FileToReferenceEventConverter.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/api/FileToReferenceEventConverter.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -19,7 +19,7 @@ import java.util.List; import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; -import gov.llnl.gnem.apps.coda.calibration.model.domain.messaging.Result; +import gov.llnl.gnem.apps.coda.common.model.messaging.Result; import reactor.core.publisher.Flux; public interface FileToReferenceEventConverter { 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 new file mode 100644 index 00000000..29b85f50 --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/CodaJsonParamLoader.java @@ -0,0 +1,179 @@ +/* +* 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.converters.param; + +import static gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.CalibrationJsonConstants.BAND_FIELD; +import static gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.CalibrationJsonConstants.MDAC_FI_FIELD; +import static gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.CalibrationJsonConstants.MDAC_PS_FIELD; +import static gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.CalibrationJsonConstants.REFERENCE_EVENTS_FIELD; +import static gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.CalibrationJsonConstants.SCHEMA_FIELD; +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 java.io.File; +import java.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.PathMatcher; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; + +import org.springframework.stereotype.Service; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectReader; + +import gov.llnl.gnem.apps.coda.calibration.gui.converters.api.FileToParameterConverter; +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.mixins.SharedFrequencyBandParametersFileMixin; +import gov.llnl.gnem.apps.coda.common.model.domain.SharedFrequencyBandParameters; +import gov.llnl.gnem.apps.coda.common.model.messaging.Result; +import gov.llnl.gnem.apps.coda.common.model.util.LightweightIllegalStateException; +import reactor.core.publisher.Flux; + +@Service +public class CodaJsonParamLoader implements FileToParameterConverter { + + private final PathMatcher filter = FileSystems.getDefault().getPathMatcher("regex:(?i).*\\.json"); + + private final ObjectMapper mapper; + + public CodaJsonParamLoader() { + mapper = new ObjectMapper(); + mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + mapper.addMixIn(SharedFrequencyBandParameters.class, SharedFrequencyBandParametersFileMixin.class); + } + + @Override + public Flux> convertFile(File file) { + if (file != null && file.exists() && file.isFile() && filter.matches(file.toPath())) { + return Flux.fromIterable(convertJsonParamFile(file)); + } + return Flux.empty(); + } + + @Override + public Flux> convertFiles(List files) { + return Flux.fromIterable(files).flatMap(this::convertFile); + } + + public List> convertJsonParamFile(File file) { + if (file == null) { + return Collections.singletonList( + exceptionalResult(new LightweightIllegalStateException(String.format("Error parsing (%s): file does not exist or is unreadable. %s", "NULL", "File reference is null")))); + } + + List> results = new ArrayList<>(); + + try { + JsonNode node = mapper.readTree(file); + + if (node.has(SCHEMA_FIELD) && node.get(SCHEMA_FIELD).asText().equalsIgnoreCase(SCHEMA_VALUE) && node.has(TYPE_FIELD) && node.get(TYPE_FIELD).asText().equalsIgnoreCase(TYPE_VALUE)) { + results.addAll(convertJsonFields(node, BAND_FIELD, x -> sharedFrequenyBandFromJsonNode(x))); + results.addAll(convertJsonFields(node, 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))); + } + } catch (IOException e) { + return Collections.singletonList(exceptionalResult(new LightweightIllegalStateException(String.format("Error parsing (%s): %s", file.getName(), e.getMessage()), e))); + } + + return results; + } + + protected List> convertJsonFields(JsonNode node, String field, Function> func) { + List> results = new ArrayList<>(); + List nodes = node.findValues(field); + for (JsonNode found : nodes) { + if (found.isArray()) { + for (JsonNode entry : found) { + results.add(func.apply(entry)); + } + } else { + results.add(func.apply(found)); + } + } + return results; + } + + protected Result refEventsFromJsonNode(JsonNode node) { + ObjectReader reader = mapper.readerFor(ReferenceMwParameters.class); + try { + //TODO: Validate all fields + ReferenceMwParameters ref = reader.readValue(node); + return new Result(true, ref); + } catch (IOException e) { + return exceptionalResult(e); + } + } + + protected Result mdacPsFromJsonNode(JsonNode node) { + ObjectReader reader = mapper.readerFor(MdacParametersPS.class); + try { + //TODO: Validate all fields + MdacParametersPS ps = reader.readValue(node); + return new Result(true, ps); + } catch (IOException e) { + return exceptionalResult(e); + } + } + + protected Result mdacFiFromJsonNode(JsonNode node) { + ObjectReader reader = mapper.readerFor(MdacParametersFI.class); + try { + //TODO: Validate all fields + MdacParametersFI fi = reader.readValue(node); + return new Result(true, fi); + } catch (IOException e) { + return exceptionalResult(e); + } + } + + 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.")); + } else { + try { + ObjectReader reader = mapper.readerFor(SharedFrequencyBandParameters.class); + sfb = reader.readValue(band); + } catch (IOException e) { + return new Result(false, null).setErrors(Collections.singletonList(e)); + } + return new Result(true, sfb); + } + } + + private Result exceptionalResult(Exception error) { + List exceptions = new ArrayList<>(); + exceptions.add(error); + return exceptionalResult(exceptions); + } + + private Result exceptionalResult(List errors) { + return new Result<>(false, errors, null); + } + + @Override + public PathMatcher getMatchingPattern() { + return filter; + } +} diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/CodaParamFileLoader.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/CodaParamFileLoader.java index d5cf151f..a99fe33c 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/CodaParamFileLoader.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/CodaParamFileLoader.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -30,9 +30,9 @@ import org.springframework.stereotype.Service; import gov.llnl.gnem.apps.coda.calibration.gui.converters.api.FileToParameterConverter; -import gov.llnl.gnem.apps.coda.calibration.gui.util.LightweightIllegalStateException; -import gov.llnl.gnem.apps.coda.calibration.model.domain.SharedFrequencyBandParameters; -import gov.llnl.gnem.apps.coda.calibration.model.domain.messaging.Result; +import gov.llnl.gnem.apps.coda.common.model.domain.SharedFrequencyBandParameters; +import gov.llnl.gnem.apps.coda.common.model.messaging.Result; +import gov.llnl.gnem.apps.coda.common.model.util.LightweightIllegalStateException; import reactor.core.publisher.Flux; @Service diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/MdacFiFileLoader.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/MdacFiFileLoader.java index 3c13fa01..e6a9ee50 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/MdacFiFileLoader.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/MdacFiFileLoader.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -30,9 +30,9 @@ import org.springframework.stereotype.Service; import gov.llnl.gnem.apps.coda.calibration.gui.converters.api.FileToParameterConverter; -import gov.llnl.gnem.apps.coda.calibration.gui.util.LightweightIllegalStateException; import gov.llnl.gnem.apps.coda.calibration.model.domain.MdacParametersFI; -import gov.llnl.gnem.apps.coda.calibration.model.domain.messaging.Result; +import gov.llnl.gnem.apps.coda.common.model.messaging.Result; +import gov.llnl.gnem.apps.coda.common.model.util.LightweightIllegalStateException; import reactor.core.publisher.Flux; @Service diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/MdacPsFileLoader.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/MdacPsFileLoader.java index 08a453e4..61e98526 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/MdacPsFileLoader.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/param/MdacPsFileLoader.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -30,9 +30,9 @@ import org.springframework.stereotype.Service; import gov.llnl.gnem.apps.coda.calibration.gui.converters.api.FileToParameterConverter; -import gov.llnl.gnem.apps.coda.calibration.gui.util.LightweightIllegalStateException; import gov.llnl.gnem.apps.coda.calibration.model.domain.MdacParametersPS; -import gov.llnl.gnem.apps.coda.calibration.model.domain.messaging.Result; +import gov.llnl.gnem.apps.coda.common.model.messaging.Result; +import gov.llnl.gnem.apps.coda.common.model.util.LightweightIllegalStateException; import reactor.core.publisher.Flux; @Service 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 3f944063..ac796362 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; import java.util.Optional; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -30,9 +31,9 @@ import org.springframework.stereotype.Component; import gov.llnl.gnem.apps.coda.calibration.gui.converters.api.FileToReferenceEventConverter; -import gov.llnl.gnem.apps.coda.calibration.gui.util.LightweightIllegalStateException; import gov.llnl.gnem.apps.coda.calibration.model.domain.ReferenceMwParameters; -import gov.llnl.gnem.apps.coda.calibration.model.domain.messaging.Result; +import gov.llnl.gnem.apps.coda.common.model.messaging.Result; +import gov.llnl.gnem.apps.coda.common.model.util.LightweightIllegalStateException; import reactor.core.publisher.Flux; @Component @@ -57,7 +58,7 @@ public List> convertFileToReferenceMwParameters(Fi 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().endsWith(".TXT") && !file.getName().toUpperCase().endsWith(".DAT")) { + 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()))); } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/sac/CodaFilenameParserImpl.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/sac/CodaFilenameParserImpl.java index a7ea5458..5fc09026 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/sac/CodaFilenameParserImpl.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/sac/CodaFilenameParserImpl.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -14,59 +14,29 @@ */ package gov.llnl.gnem.apps.coda.calibration.gui.converters.sac; -import java.util.HashMap; -import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.springframework.stereotype.Component; +import gov.llnl.gnem.apps.coda.calibration.gui.converters.StackInfo; import gov.llnl.gnem.apps.coda.calibration.gui.converters.api.CodaFilenameParser; +import gov.llnl.gnem.apps.coda.common.model.messaging.Result; @Component public class CodaFilenameParserImpl implements CodaFilenameParser { - private final static Pattern codaFilePattern = Pattern.compile("[A-Za-z0-9]*_[A-Za-z0-9]*_[A-Za-z0-9]*_([A-Za-z0-9.]*)_([A-Za-z0-9.]*)_([A-Za-z0-9]*)_.*\\.ENV"); - - private static final String TYPE = "Type"; - - private static final String LOW_FREQUENCY = "LowFrequency"; - private static final String HIGH_FREQUENCY = "HighFrequency"; - - private Double lowFreq; - private Double highFreq; - private String dataType; + private final static Pattern codaFilePattern = Pattern.compile("[^_]*_[^_]*_[^_]*_([^_]*)_([^_]*)_([^_]*)_.*\\.ENV"); @Override - public Map parse(String fileName) { - Map fileInfo = new HashMap<>(); + public Result parse(String fileName) { Matcher fileNameMatcher = codaFilePattern.matcher(fileName); if (fileNameMatcher.matches()) { - lowFreq = Double.valueOf(fileNameMatcher.group(1)); - fileInfo.put(LOW_FREQUENCY, lowFreq); - - highFreq = Double.valueOf(fileNameMatcher.group(2)); - fileInfo.put(HIGH_FREQUENCY, highFreq); - - dataType = fileNameMatcher.group(3); - fileInfo.put(TYPE, dataType); + Double lowFreq = Double.valueOf(fileNameMatcher.group(1)); + Double highFreq = Double.valueOf(fileNameMatcher.group(2)); + String dataType = fileNameMatcher.group(3); + return new Result(true, new StackInfo(lowFreq, highFreq, dataType)); } - return fileInfo; - } - - @Override - public Double getLowFrequency() { - return lowFreq; + return new Result(false, null); } - - @Override - public Double getHighFrequency() { - return highFreq; - } - - @Override - public String getDataType() { - return dataType; - } - } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/sac/CodaStackedSacFileLoader.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/sac/CodaStackedSacFileLoader.java index 8fb0da73..383bdd4e 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/sac/CodaStackedSacFileLoader.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/sac/CodaStackedSacFileLoader.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -18,19 +18,22 @@ import java.nio.file.FileSystems; import java.nio.file.PathMatcher; import java.util.List; +import java.util.Locale; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import gov.llnl.gnem.apps.coda.calibration.gui.converters.StackInfo; import gov.llnl.gnem.apps.coda.calibration.gui.converters.api.CodaFilenameParser; -import gov.llnl.gnem.apps.coda.calibration.gui.converters.api.FileToWaveformConverter; -import gov.llnl.gnem.apps.coda.calibration.model.domain.Waveform; -import gov.llnl.gnem.apps.coda.calibration.model.domain.messaging.Result; +import gov.llnl.gnem.apps.coda.common.gui.converters.api.FileToEnvelopeConverter; +import gov.llnl.gnem.apps.coda.common.gui.converters.sac.SacLoader; +import gov.llnl.gnem.apps.coda.common.model.domain.Waveform; +import gov.llnl.gnem.apps.coda.common.model.messaging.Result; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @Component -public class CodaStackedSacFileLoader implements FileToWaveformConverter { +public class CodaStackedSacFileLoader implements FileToEnvelopeConverter { private static final String DEFAULT_VEL_UNITS = "nm/s"; private SacLoader sacLoader; @@ -50,12 +53,17 @@ public Mono> convertFile(File file) { return Mono.fromSupplier(() -> sacLoader.convertSacFileToWaveform(file)).map(result -> { if (result.getResultPayload().isPresent()) { Waveform waveform = result.getResultPayload().get(); - filenameParser.parse(file.getName().toUpperCase()); - waveform.getStream().setChannelName("STACK"); - waveform.setSegmentType(filenameParser.getDataType()); - waveform.setSegmentUnits(DEFAULT_VEL_UNITS); - waveform.setLowFrequency(filenameParser.getLowFrequency()); - waveform.setHighFrequency(filenameParser.getHighFrequency()); + Result res = filenameParser.parse(file.getName().toUpperCase(Locale.ENGLISH)); + if (res.isSuccess()) { + waveform.getStream().setChannelName("STACK"); + waveform.setSegmentType(res.getResultPayload().get().getDataType()); + waveform.setSegmentUnits(DEFAULT_VEL_UNITS); + waveform.setLowFrequency(res.getResultPayload().get().getLowFrequency()); + waveform.setHighFrequency(res.getResultPayload().get().getHighFrequency()); + } else { + result.getErrors().addAll(res.getErrors()); + result.setSuccess(false); + } } return result; }); diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/sac/SacExporter.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/sac/SacExporter.java deleted file mode 100644 index f73dc0b7..00000000 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/converters/sac/SacExporter.java +++ /dev/null @@ -1,98 +0,0 @@ -/* -* Copyright (c) 2017, 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.converters.sac; - -import java.io.DataOutputStream; -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.text.NumberFormat; - -import org.apache.commons.lang3.ArrayUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; - -import gov.llnl.gnem.apps.coda.calibration.gui.util.NumberFormatFactory; -import gov.llnl.gnem.apps.coda.calibration.model.domain.Waveform; -import gov.llnl.gnem.apps.coda.calibration.model.domain.WaveformPick; -import gov.llnl.gnem.apps.coda.calibration.model.domain.util.PICK_TYPES; -import llnl.gnem.core.io.SAC.SACHeader; -import llnl.gnem.core.signalprocessing.Sequence; -import llnl.gnem.core.util.TimeT; - -@Service -public class SacExporter { - private static final String SEP = "_"; - private final NumberFormat dfmt1 = NumberFormatFactory.oneDecimalOneLeadingZero(); - - private final Logger log = LoggerFactory.getLogger(this.getClass()); - - public void writeWaveformToDirectory(File exportDirectory, Waveform w) { - try (DataOutputStream os = new DataOutputStream(Files.newOutputStream(exportDirectory.toPath().resolve(getFileName(w))))) { - SACHeader header = new SACHeader(); - header.setTime(new TimeT(w.getEvent().getOriginTime())); - header.setBeginTime(new TimeT(w.getBeginTime())); - header.setOriginTime(new TimeT(w.getEvent().getOriginTime())); - - header.nevid = Integer.valueOf(w.getEvent().getEventId()); - if (w.getAssociatedPicks() != null) { - for (int i = 0; i < w.getAssociatedPicks().size() && i <= 10; i++) { - try { - WaveformPick pick = w.getAssociatedPicks().get(i); - if (pick.getPickType().equalsIgnoreCase(PICK_TYPES.F.getPhase())) { - header.f = pick.getPickTimeSecFromOrigin(); - } else if (pick.getPickType().equalsIgnoreCase(PICK_TYPES.A.getPhase())) { - header.a = pick.getPickTimeSecFromOrigin(); - } else if (pick.getPickType().equalsIgnoreCase(PICK_TYPES.B.getPhase())) { - header.b = pick.getPickTimeSecFromOrigin(); - } else if (pick.getPickType().equalsIgnoreCase(PICK_TYPES.O.getPhase())) { - header.o = pick.getPickTimeSecFromOrigin(); - } else { - header.setTimePick(i, pick.getPickTimeSecFromOrigin(), pick.getPickName()); - } - } catch (RuntimeException e) { - log.error(e.getMessage(), e); - } - } - } - - header.delta = (float) (1.0 / w.getSampleRate()); - header.kstnm = w.getStream().getStation().getStationName(); - header.kcmpnm = w.getStream().getChannelName(); - header.stla = (float) w.getStream().getStation().getLatitude(); - header.stlo = (float) w.getStream().getStation().getLongitude(); - header.knetwk = w.getStream().getStation().getNetworkName(); - header.kevnm = w.getEvent().getEventId(); - header.evla = (float) w.getEvent().getLatitude(); - header.evlo = (float) w.getEvent().getLongitude(); - float[] sequence = new Sequence(ArrayUtils.toPrimitive(w.getSegment())).getArray(); - header.npts = sequence.length; - header.write(os); - for (int i = 0; i < sequence.length; i++) { - os.writeFloat(sequence[i]); - } - os.flush(); - } catch (IOException e) { - log.error(e.getMessage(), e); - } - } - - private String getFileName(Waveform w) { - String name = w.getStream().getStation().getStationName() + SEP + w.getStream().getChannelName() + SEP + w.getEvent().getEventId() + SEP + dfmt1.format(w.getLowFrequency()) + SEP - + dfmt1.format(w.getHighFrequency()) + SEP + w.getSegmentType() + SEP + ".env"; - return name.toUpperCase(); - } -} diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/CalibrationWebClient.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/CalibrationWebClient.java index c1c15a8f..96851944 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/CalibrationWebClient.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/CalibrationWebClient.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -34,11 +34,11 @@ public CalibrationWebClient(WebClient client) { @Override public Mono runCalibration(Boolean autoPickingEnabled) { - return client.get().uri("/calibration/start/" + autoPickingEnabled).accept(MediaType.APPLICATION_JSON).exchange().map(resp -> resp.toString()); + return client.get().uri("/calibration/start/" + autoPickingEnabled).accept(MediaType.APPLICATION_JSON).exchange().flatMap(resp -> resp.bodyToMono(String.class)); } @Override public Mono clearData() { - return client.get().uri("/calibration/clear-data").accept(MediaType.APPLICATION_JSON).exchange().map(resp -> resp.toString()); + return client.get().uri("/calibration/clear-data").accept(MediaType.APPLICATION_JSON).exchange().flatMap(resp -> resp.bodyToMono(String.class)); } } 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 7034a9b0..90b3f5ad 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -24,11 +24,11 @@ import com.fasterxml.jackson.core.JsonProcessingException; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ParameterClient; -import gov.llnl.gnem.apps.coda.calibration.model.domain.FrequencyBand; 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.SharedFrequencyBandParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; +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; import reactor.core.publisher.Mono; @@ -36,7 +36,7 @@ public class ParameterWebClient implements ParameterClient { private WebClient client; - private final Logger log = LoggerFactory.getLogger(this.getClass()); + private static final Logger log = LoggerFactory.getLogger(ParameterWebClient.class); @Autowired public ParameterWebClient(WebClient client) { @@ -44,14 +44,25 @@ public ParameterWebClient(WebClient client) { } @Override - public Mono postSharedFrequencyBandParameters(SharedFrequencyBandParameters parameters) throws JsonProcessingException { + public Mono setSharedFrequencyBandParameter(SharedFrequencyBandParameters parameters) throws JsonProcessingException { return client.post() .uri("/params/shared-fb-parameters/update") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .syncBody(parameters) .exchange() - .map(resp -> resp.toString()); + .flatMap(resp -> resp.bodyToMono(String.class)); + } + + @Override + public Mono removeSharedFrequencyBandParameter(SharedFrequencyBandParameters parameters) { + return client.post() + .uri("/params/shared-fb-parameters/delete") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .syncBody(parameters) + .exchange() + .flatMap(resp -> resp.bodyToMono(String.class)); } @Override @@ -65,14 +76,14 @@ public Flux getSharedFrequencyBandParameters() { } @Override - public Mono postSiteSpecificFrequencyBandParameters(SiteFrequencyBandParameters parameters) throws JsonProcessingException { + public Mono setSiteSpecificFrequencyBandParameter(SiteFrequencyBandParameters parameters) throws JsonProcessingException { return client.post() .uri("/params/site-fb-parameters/update") .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .syncBody(parameters) .exchange() - .map(resp -> resp.toString()); + .flatMap(resp -> resp.bodyToMono(String.class)); } @Override @@ -86,8 +97,25 @@ public Flux getSiteSpecificFrequencyBandParameters( } @Override - public Mono postPsParameters(MdacParametersPS parameters) throws JsonProcessingException { - return client.post().uri("/params/ps/update").contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).syncBody(parameters).exchange().map(resp -> resp.toString()); + public Mono setPsParameter(MdacParametersPS parameters) throws JsonProcessingException { + return client.post() + .uri("/params/ps/update") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .syncBody(parameters) + .exchange() + .flatMap(resp -> resp.bodyToMono(String.class)); + } + + @Override + public Mono removePsParameter(MdacParametersPS parameters) { + return client.post() + .uri("/params/ps/delete") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .syncBody(parameters) + .exchange() + .flatMap(resp -> resp.bodyToMono(String.class)); } @Override @@ -96,8 +124,25 @@ public Flux getPsParameters() { } @Override - public Mono postFiParameters(MdacParametersFI parameters) throws JsonProcessingException { - return client.post().uri("/params/fi/update").contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).syncBody(parameters).exchange().map(resp -> resp.toString()); + public Mono setFiParameter(MdacParametersFI parameters) throws JsonProcessingException { + return client.post() + .uri("/params/fi/update") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .syncBody(parameters) + .exchange() + .flatMap(resp -> resp.bodyToMono(String.class)); + } + + @Override + public Mono removeFiParameter(MdacParametersFI parameters) { + return client.post() + .uri("/params/fi/delete") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .syncBody(parameters) + .exchange() + .flatMap(resp -> resp.bodyToMono(String.class)); } @Override 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 b5a47594..ea2b0e37 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -14,6 +14,8 @@ */ 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; @@ -22,10 +24,13 @@ import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.PeakVelocityClient; import gov.llnl.gnem.apps.coda.calibration.model.domain.PeakVelocityMeasurement; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; @Component public class PeakVelocityWebClient implements PeakVelocityClient { + private static final Logger log = LoggerFactory.getLogger(PeakVelocityWebClient.class); + private WebClient client; @Autowired @@ -42,4 +47,24 @@ public Flux getMeasuredPeakVelocities() { .flatMapMany(response -> response.bodyToFlux(PeakVelocityMeasurement.class)) .onErrorReturn(new PeakVelocityMeasurement()); } + + @Override + public Flux getMeasuredPeakVelocitiesMetadata() { + return client.get() + .uri("/peak-velocity-measurements/metadata") + .accept(MediaType.APPLICATION_JSON) + .exchange() + .flatMapMany(response -> response.bodyToFlux(PeakVelocityMeasurement.class)) + .onErrorReturn(new PeakVelocityMeasurement()); + } + + @Override + public Mono getNoiseForWaveform(Long id) { + return client.get() + .uri("/peak-velocity-measurements/metadata-by-id/" + id) + .accept(MediaType.APPLICATION_JSON) + .exchange() + .flatMap(response -> response.bodyToMono(PeakVelocityMeasurement.class)) + .onErrorReturn(new PeakVelocityMeasurement()); + } } 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 a873cba9..1c5d5db6 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -26,6 +26,7 @@ import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ReferenceEventClient; 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; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -51,7 +52,13 @@ public Flux getReferenceEvents() { @Override public Mono postReferenceEvents(List refEvents) throws JsonProcessingException { - return client.post().uri("/reference-events/batch").contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).syncBody(refEvents).exchange().map(resp -> resp.toString()); + return client.post() + .uri("/reference-events/batch") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .syncBody(refEvents) + .exchange() + .flatMap(resp -> resp.bodyToMono(String.class)); } @Override @@ -64,4 +71,9 @@ public Flux getMeasuredEvents() { .onErrorReturn(new MeasuredMwParameters()); } + @Override + 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()); + } + } 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 6aaa1fcd..f14a9c6a 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. 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 3468843a..86b6ec47 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/CalibrationClient.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/CalibrationClient.java index 2d962153..52527129 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/CalibrationClient.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/CalibrationClient.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. 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 new file mode 100644 index 00000000..efd762fe --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/CalibrationJsonConstants.java @@ -0,0 +1,27 @@ +/* +* 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.client.api; + +public class CalibrationJsonConstants { + public static final String TYPE_FIELD = "type"; + public static final String TYPE_VALUE = "llnl/coda-calibration-tool"; + public static final String SCHEMA_FIELD = "schemaVersion"; + public static final String SCHEMA_VALUE = "1"; + public static final String BAND_FIELD = "bands"; + public static final String MDAC_PS_FIELD = "mdac-ps"; + public static final String MDAC_FI_FIELD = "mdac-fi"; + public static final String REFERENCE_EVENTS_FIELD = "reference-events"; + public static final String MEASURED_EVENTS_FIELD = "measured-events"; +} 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 5d0ee1fc..71cfa2cb 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -16,32 +16,38 @@ import com.fasterxml.jackson.core.JsonProcessingException; -import gov.llnl.gnem.apps.coda.calibration.model.domain.FrequencyBand; 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.SharedFrequencyBandParameters; import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; +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; import reactor.core.publisher.Mono; public interface ParameterClient { - public Mono postSharedFrequencyBandParameters(SharedFrequencyBandParameters parameters) throws JsonProcessingException; + public Mono setSharedFrequencyBandParameter(SharedFrequencyBandParameters parameters) throws JsonProcessingException; public Flux getSharedFrequencyBandParameters(); - public Mono postSiteSpecificFrequencyBandParameters(SiteFrequencyBandParameters parameters) throws JsonProcessingException; + public Mono getSharedFrequencyBandParametersForFrequency(FrequencyBand frequencyBand); + + public Mono removeSharedFrequencyBandParameter(SharedFrequencyBandParameters parameters); + + public Mono setSiteSpecificFrequencyBandParameter(SiteFrequencyBandParameters parameters) throws JsonProcessingException; public Flux getSiteSpecificFrequencyBandParameters(); - public Mono postPsParameters(MdacParametersPS parameters) throws JsonProcessingException; + public Mono setPsParameter(MdacParametersPS parameters) throws JsonProcessingException; public Flux getPsParameters(); - public Mono postFiParameters(MdacParametersFI parameters) throws JsonProcessingException; + public Mono removePsParameter(MdacParametersPS parameters); + + public Mono setFiParameter(MdacParametersFI parameters) throws JsonProcessingException; public Flux getFiParameters(); - public Mono getSharedFrequencyBandParametersForFrequency(FrequencyBand frequencyBand); + public Mono removeFiParameter(MdacParametersFI parameters); } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/PeakVelocityClient.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/PeakVelocityClient.java index de1d9931..55e33fb2 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/PeakVelocityClient.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/PeakVelocityClient.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -16,8 +16,13 @@ import gov.llnl.gnem.apps.coda.calibration.model.domain.PeakVelocityMeasurement; import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; public interface PeakVelocityClient { public Flux getMeasuredPeakVelocities(); + + public Flux getMeasuredPeakVelocitiesMetadata(); + + public Mono getNoiseForWaveform(Long id); } 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 71da0a0e..35a57674 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -20,6 +20,7 @@ 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; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -30,4 +31,6 @@ public interface ReferenceEventClient { public Flux getMeasuredEvents(); public Mono postReferenceEvents(List refEvents) throws JsonProcessingException; + + public Mono getEvent(String eventId); } 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 be37ebd2..06de71b0 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. 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 62d32f25..3dbb7484 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/SpectraClient.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/client/api/SpectraClient.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. 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 new file mode 100644 index 00000000..185b0fc3 --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/JsonTempFileWriter.java @@ -0,0 +1,162 @@ +/* +* 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; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.CalibrationJsonConstants; +import gov.llnl.gnem.apps.coda.calibration.gui.data.exporters.api.MeasuredMwTempFileWriter; +import gov.llnl.gnem.apps.coda.calibration.gui.data.exporters.api.ParamTempFileWriter; +import gov.llnl.gnem.apps.coda.calibration.model.domain.MeasuredMwDetails; +import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; +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 { + + private static final Logger log = LoggerFactory.getLogger(JsonTempFileWriter.class); + + private static final String CALIBRATION_JSON_NAME = "Calibration_Parameters.json"; + private static final String MW_JSON_NAME = "Measured_Events.json"; + + private ObjectMapper mapper; + + public JsonTempFileWriter() { + mapper = new ObjectMapper(); + mapper.setSerializationInclusion(Include.NON_NULL); + mapper.setSerializationInclusion(Include.NON_EMPTY); + mapper.addMixIn(SharedFrequencyBandParameters.class, SharedFrequencyBandParametersFileMixin.class); + } + + @Override + public void writeParams(Path folder, Map sharedParametersByFreqBand, Map> siteParameters) { + try { + JsonNode document = createOrGetDocument(folder, CALIBRATION_JSON_NAME); + writeParams(createOrGetFile(folder, CALIBRATION_JSON_NAME), document, sharedParametersByFreqBand, siteParameters); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } + + @Override + public void writeParams(Path folder, List measuredMwsDetails) { + try { + JsonNode document = createOrGetDocument(folder, MW_JSON_NAME); + writeMeasuredEvents(createOrGetFile(folder, MW_JSON_NAME), document, measuredMwsDetails); + } catch (IOException e) { + log.error(e.getMessage(), e); + } + } + + 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); + } + } + + private void writeMeasuredEvents(File file, JsonNode document, List measuredMwsDetails) throws IOException { + ArrayNode arrayNode = mapper.createArrayNode(); + for (MeasuredMwDetails mw : measuredMwsDetails) { + //TODO: Validation logic + //if mw is valid + arrayNode.add(mapper.valueToTree(mw)); + //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.MEASURED_EVENTS_FIELD, arrayNode); + } + } + + private void writeFieldNodeToFile(File file, JsonNode document, String field, JsonNode node) throws IOException { + if (node != null) { + Files.deleteIfExists(file.toPath()); + document = addOrReplaceNode(document, field, node); + try (BufferedWriter outstream = Files.newBufferedWriter(file.toPath())) { + mapper.writerWithDefaultPrettyPrinter().writeValue(outstream, document); + } + } + } + + private JsonNode addOrReplaceNode(JsonNode document, String field, JsonNode node) { + if (document != null && document instanceof ObjectNode) { + if (node != null) { + document = deleteNodesIfExists(document, field); + ((ObjectNode) document).set(field, node); + } + return document; + } else { + throw new IllegalStateException("Invalid document configuration encountered while creating document: " + document); + } + } + + private JsonNode deleteNodesIfExists(JsonNode document, String field) { + for (JsonNode node : document) { + if (node instanceof ObjectNode) { + ObjectNode object = (ObjectNode) node; + object.remove(field); + } + } + return document; + } + + private JsonNode createOrGetDocument(Path folder, String filename) throws JsonProcessingException, IOException { + Path filePath = folder.resolve(filename); + JsonNode rootNode; + if (Files.exists(filePath) && Files.isRegularFile(filePath)) { + rootNode = new ObjectMapper().readTree(filePath.toFile()); + } else { + rootNode = mapper.createObjectNode(); + } + return rootNode; + } + + private File createOrGetFile(Path folder, String filename) throws IOException { + 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 new file mode 100644 index 00000000..a9cbc687 --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/ParamExporter.java @@ -0,0 +1,150 @@ +/* +* 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; + +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.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.TreeMap; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.commons.compress.archivers.ArchiveException; +import org.apache.commons.compress.archivers.ArchiveOutputStream; +import org.apache.commons.compress.archivers.ArchiveStreamFactory; +import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; +import org.apache.commons.io.IOUtils; +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.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.model.domain.MeasuredMwDetails; +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.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 ParamExporter { + private final Logger log = LoggerFactory.getLogger(this.getClass()); + + private ParameterClient paramClient; + private List paramWriters; + + private ReferenceEventClient eventClient; + private List mwWriters; + + @Autowired + public ParamExporter(ParameterClient paramClient, ReferenceEventClient eventClient, List paramWriters, List mwWriters) { + this.paramClient = paramClient; + this.paramWriters = paramWriters; + + this.eventClient = eventClient; + this.mwWriters = mwWriters; + } + + public File createExportArchive() throws IOException { + Path tmpFolder = Files.createTempDirectory(Long.toString(System.currentTimeMillis())); + tmpFolder.toFile().deleteOnExit(); + + if (paramWriters != null) { + Map sharedParametersByFreqBand = paramClient.getSharedFrequencyBandParameters() + .toStream() + .filter(Objects::nonNull) + .collect( + Collectors.toMap( + s -> new FrequencyBand(s.getLowFrequency(), s.getHighFrequency()), + Function.identity(), + (a, b) -> b, + TreeMap::new)); + + Map> siteParameters = paramClient.getSiteSpecificFrequencyBandParameters() + .toStream() + .filter(Objects::nonNull) + .filter(s -> s.getStation() != null) + .collect( + Collectors.groupingBy( + SiteFrequencyBandParameters::getStation, + Collectors.toMap( + s -> new FrequencyBand(s.getLowFrequency(), s.getHighFrequency()), + Function.identity(), + (a, b) -> b, + TreeMap::new))); + + for (ParamTempFileWriter writer : paramWriters) { + writer.writeParams(tmpFolder, sharedParametersByFreqBand, siteParameters); + } + } + + 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); + } + }); + for (MeasuredMwTempFileWriter writer : mwWriters) { + writer.writeParams(tmpFolder, measuredMwsDetails); + } + } + + File zipDir = File.createTempFile("zip-dir", "tmp"); + zipDir.deleteOnExit(); + + 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))) { + for (File file : files) { + os.putArchiveEntry(new ZipArchiveEntry(file, file.getName())); + IOUtils.copy(new FileInputStream(file), os); + os.closeArchiveEntry(); + } + os.flush(); + os.close(); + } catch (ArchiveException e) { + throw new IOException(e); + } + try (Stream tmpFileStream = Files.walk(tmpFolder)) { + tmpFileStream.sorted(Comparator.reverseOrder()).forEach(t -> { + try { + Files.deleteIfExists(t); + } catch (IOException e) { + log.trace("Unable to delete temporary file {}", e.getMessage(), e); + } + }); + } + } + return zipDir; + } +} diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/SwftStyleParamExporter.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/SwftStyleParamExporter.java deleted file mode 100644 index 50e56a4f..00000000 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/SwftStyleParamExporter.java +++ /dev/null @@ -1,165 +0,0 @@ -/* -* Copyright (c) 2017, 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 java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Path; -import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; -import java.util.TreeMap; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.apache.commons.compress.archivers.ArchiveException; -import org.apache.commons.compress.archivers.ArchiveOutputStream; -import org.apache.commons.compress.archivers.ArchiveStreamFactory; -import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; -import org.apache.commons.io.IOUtils; -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.gui.util.NumberFormatFactory; -import gov.llnl.gnem.apps.coda.calibration.model.domain.FrequencyBand; -import gov.llnl.gnem.apps.coda.calibration.model.domain.SharedFrequencyBandParameters; -import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; -import gov.llnl.gnem.apps.coda.calibration.model.domain.Station; - -@Component -public class SwftStyleParamExporter { - - private NumberFormat dfmt6 = NumberFormatFactory.sixDecimalOneLeadingZero(); - - private static final double DEFAULT_SITE_TERM = 0.0; - - private ParameterClient paramClient; - - private static final char SEP = ' '; - - @Autowired - public SwftStyleParamExporter(ParameterClient paramClient) { - this.paramClient = paramClient; - } - - public File createExportArchive() throws IOException { - Path tmpFolder = Files.createTempDirectory(Long.toString(System.currentTimeMillis())); - tmpFolder.toFile().deleteOnExit(); - - List files = new ArrayList<>(); - - Map sharedParametersByFreqBand = paramClient.getSharedFrequencyBandParameters() - .toStream() - .filter(Objects::nonNull) - .collect(Collectors.toMap(s -> new FrequencyBand(s.getLowFrequency(), s.getHighFrequency()), - Function.identity(), - (a, b) -> b, - TreeMap::new)); - - Map> siteParameters = paramClient.getSiteSpecificFrequencyBandParameters() - .toStream() - .filter(Objects::nonNull) - .filter(s -> s.getStation() != null) - .collect(Collectors.groupingBy(SiteFrequencyBandParameters::getStation, - Collectors.toMap(s -> new FrequencyBand(s.getLowFrequency(), - s.getHighFrequency()), - Function.identity(), - (a, b) -> b, - TreeMap::new))); - - File sharedParamFile = new File(tmpFolder.toFile(), "Shared.param"); - sharedParamFile.deleteOnExit(); - - writeParams(sharedParamFile, sharedParametersByFreqBand); - files.add(sharedParamFile); - - for (Entry> stationEntry : siteParameters.entrySet()) { - File stationParamFile = new File(tmpFolder.toFile(), stationEntry.getKey().getStationName() + ".param"); - writeParams(stationParamFile, sharedParametersByFreqBand, stationEntry.getValue()); - stationParamFile.deleteOnExit(); - files.add(stationParamFile); - } - - File zipDir = File.createTempFile("zip-dir", "tmp"); - zipDir.deleteOnExit(); - - try (ArchiveOutputStream os = new ArchiveStreamFactory().createArchiveOutputStream("zip", new FileOutputStream(zipDir))) { - for (File file : files) { - os.putArchiveEntry(new ZipArchiveEntry(file, file.getName())); - IOUtils.copy(new FileInputStream(file), os); - os.closeArchiveEntry(); - } - os.flush(); - os.close(); - } catch (ArchiveException e) { - throw new IOException(e); - } - - return zipDir; - } - - private void writeParams(File paramFile, Map sharedParametersByFreqBand, Map stationParametersByFreqBand) - throws IOException { - try (BufferedWriter writer = Files.newBufferedWriter(paramFile.toPath(), Charset.defaultCharset())) { - StringBuilder sb = new StringBuilder(); - String header = "#fl fh vel0 vel1 vel2 min max time b0 b1 b2 g0 g1 g2 p1 p2 xc xt q site\n"; - - writer.write(header); - for (Entry entry : sharedParametersByFreqBand.entrySet()) { - FrequencyBand fb = entry.getKey(); - SharedFrequencyBandParameters shared = entry.getValue(); - sb.append(dfmt6.format(shared.getLowFrequency())).append(SEP); - sb.append(dfmt6.format(shared.getHighFrequency())).append(SEP); - sb.append(dfmt6.format(shared.getVelocity0())).append(SEP); - sb.append(dfmt6.format(shared.getVelocity1())).append(SEP); - sb.append(dfmt6.format(shared.getVelocity2())).append(SEP); - sb.append(dfmt6.format(shared.getMinSnr())).append(SEP); - sb.append(dfmt6.format(shared.getMaxLength())).append(SEP); - sb.append(dfmt6.format(shared.getMeasurementTime())).append(SEP); - sb.append(dfmt6.format(shared.getBeta0())).append(SEP); - sb.append(dfmt6.format(shared.getBeta1())).append(SEP); - sb.append(dfmt6.format(shared.getBeta2())).append(SEP); - sb.append(dfmt6.format(shared.getGamma0())).append(SEP); - sb.append(dfmt6.format(shared.getGamma1())).append(SEP); - sb.append(dfmt6.format(shared.getGamma2())).append(SEP); - sb.append(dfmt6.format(shared.getS1())).append(SEP); - sb.append(dfmt6.format(shared.getS2())).append(SEP); - sb.append(dfmt6.format(shared.getXc())).append(SEP); - sb.append(dfmt6.format(shared.getXt())).append(SEP); - sb.append(dfmt6.format(shared.getQ())).append(SEP); - - if (stationParametersByFreqBand != null && stationParametersByFreqBand.containsKey(fb)) { - sb.append(dfmt6.format(stationParametersByFreqBand.get(fb).getSiteTerm())).append("\n"); - } else { - sb.append(DEFAULT_SITE_TERM).append("\n"); - } - } - writer.write(sb.toString()); - } - } - - private void writeParams(File paramFile, Map sharedParametersByFreqBand) throws IOException { - writeParams(paramFile, sharedParametersByFreqBand, null); - } -} 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 new file mode 100644 index 00000000..c5e33339 --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/SwftStyleParamFileWriter.java @@ -0,0 +1,106 @@ +/* +* 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; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.text.NumberFormat; +import java.util.Map; +import java.util.Map.Entry; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +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.common.gui.util.NumberFormatFactory; +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 SwftStyleParamFileWriter implements ParamTempFileWriter { + + private NumberFormat dfmt6 = NumberFormatFactory.sixDecimalOneLeadingZero(); + + private static final double DEFAULT_SITE_TERM = 0.0; + private static final char SEP = ' '; + + private static final Logger log = LoggerFactory.getLogger(SwftStyleParamFileWriter.class); + + private void writeParams(File paramFile, Map sharedParametersByFreqBand, Map stationParametersByFreqBand) + throws IOException { + try (BufferedWriter writer = Files.newBufferedWriter(paramFile.toPath(), Charset.defaultCharset())) { + StringBuilder sb = new StringBuilder(); + String header = "#fl fh vel0 vel1 vel2 min max time b0 b1 b2 g0 g1 g2 p1 p2 xc xt q site\n"; + + writer.write(header); + for (Entry entry : sharedParametersByFreqBand.entrySet()) { + FrequencyBand fb = entry.getKey(); + SharedFrequencyBandParameters shared = entry.getValue(); + sb.append(dfmt6.format(shared.getLowFrequency())).append(SEP); + sb.append(dfmt6.format(shared.getHighFrequency())).append(SEP); + sb.append(dfmt6.format(shared.getVelocity0())).append(SEP); + sb.append(dfmt6.format(shared.getVelocity1())).append(SEP); + sb.append(dfmt6.format(shared.getVelocity2())).append(SEP); + sb.append(dfmt6.format(shared.getMinSnr())).append(SEP); + sb.append(dfmt6.format(shared.getMaxLength())).append(SEP); + sb.append(dfmt6.format(shared.getMeasurementTime())).append(SEP); + sb.append(dfmt6.format(shared.getBeta0())).append(SEP); + sb.append(dfmt6.format(shared.getBeta1())).append(SEP); + sb.append(dfmt6.format(shared.getBeta2())).append(SEP); + sb.append(dfmt6.format(shared.getGamma0())).append(SEP); + sb.append(dfmt6.format(shared.getGamma1())).append(SEP); + sb.append(dfmt6.format(shared.getGamma2())).append(SEP); + sb.append(dfmt6.format(shared.getS1())).append(SEP); + sb.append(dfmt6.format(shared.getS2())).append(SEP); + sb.append(dfmt6.format(shared.getXc())).append(SEP); + sb.append(dfmt6.format(shared.getXt())).append(SEP); + sb.append(dfmt6.format(shared.getQ())).append(SEP); + + if (stationParametersByFreqBand != null && stationParametersByFreqBand.containsKey(fb)) { + sb.append(dfmt6.format(stationParametersByFreqBand.get(fb).getSiteTerm())).append("\n"); + } else { + sb.append(DEFAULT_SITE_TERM).append("\n"); + } + } + writer.write(sb.toString()); + } + } + + @Override + public void writeParams(Path folder, Map sharedParametersByFreqBand, Map> siteParameters) { + File sharedParamFile = new File(folder.toFile(), "Shared.param"); + sharedParamFile.deleteOnExit(); + try { + writeParams(sharedParamFile, sharedParametersByFreqBand, null); + + for (Entry> stationEntry : siteParameters.entrySet()) { + File stationParamFile = new File(folder.toFile(), stationEntry.getKey().getStationName() + ".param"); + writeParams(stationParamFile, sharedParametersByFreqBand, stationEntry.getValue()); + stationParamFile.deleteOnExit(); + } + } catch (IOException e) { + log.error(e.getMessage(), e); + } + + } + +} 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 new file mode 100644 index 00000000..5dcf981e --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/MeasuredMwTempFileWriter.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.MeasuredMwDetails; + +public interface MeasuredMwTempFileWriter { + void writeParams(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 new file mode 100644 index 00000000..c6dba06d --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/data/exporters/api/ParamTempFileWriter.java @@ -0,0 +1,27 @@ +/* +* 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.Map; + +import gov.llnl.gnem.apps.coda.calibration.model.domain.SiteFrequencyBandParameters; +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); +} diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/events/CalibrationStageShownEvent.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/events/CalibrationStageShownEvent.java new file mode 100644 index 00000000..8450d2e4 --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/events/CalibrationStageShownEvent.java @@ -0,0 +1,18 @@ +/* +* 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.events; + +public class CalibrationStageShownEvent { +} diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/events/LoadStartingEvent.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/events/ParametersLoadedEvent.java similarity index 96% rename from calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/events/LoadStartingEvent.java rename to calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/events/ParametersLoadedEvent.java index 4fa39cbf..3ba42cb6 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/events/LoadStartingEvent.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/events/ParametersLoadedEvent.java @@ -14,5 +14,5 @@ */ package gov.llnl.gnem.apps.coda.calibration.gui.events; -public class LoadStartingEvent { +public class ParametersLoadedEvent { } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/mapping/LeafletIcon.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/mapping/LeafletIcon.java deleted file mode 100644 index 0c2ba271..00000000 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/mapping/LeafletIcon.java +++ /dev/null @@ -1,87 +0,0 @@ -/* -* Copyright (c) 2017, 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.mapping; - -import java.util.Optional; - -import gov.llnl.gnem.apps.coda.calibration.gui.mapping.api.Icon; -import gov.llnl.gnem.apps.coda.calibration.gui.mapping.api.Location; - -public class LeafletIcon implements Icon { - - private Location location; - private String friendlyName; - private IconTypes iconType; - - public LeafletIcon(Location location, String friendlyName, IconTypes iconType) { - this.location = location; - this.friendlyName = friendlyName; - this.iconType = iconType; - } - - @Override - public Location getLocation() { - return location; - } - - @Override - public Location setLocation(Location location) { - this.location = location; - return location; - } - - @Override - public String toString() { - return "LeafletIcon [location=" + location + "]"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((location == null) ? 0 : location.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; - LeafletIcon other = (LeafletIcon) obj; - if (location == null) { - if (other.location != null) - return false; - } else if (!location.equals(other.location)) - return false; - return true; - } - - @Override - public String getFriendlyName() { - return Optional.of(friendlyName).orElse(""); - } - - @Override - public IconTypes getType() { - if (iconType != null) { - return iconType; - } - return IconTypes.DEFAULT; - } -} diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/mapping/LeafletMap.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/mapping/LeafletMap.java deleted file mode 100644 index 0c60f146..00000000 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/mapping/LeafletMap.java +++ /dev/null @@ -1,146 +0,0 @@ -/* -* Copyright (c) 2017, 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.mapping; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - -import gov.llnl.gnem.apps.coda.calibration.gui.mapping.api.Icon; -import gov.llnl.gnem.apps.coda.calibration.gui.mapping.api.Map; -import javafx.application.Platform; -import javafx.collections.FXCollections; -import javafx.collections.ObservableSet; -import javafx.collections.SetChangeListener; -import javafx.scene.layout.StackPane; -import javafx.scene.web.WebView; - -@Component -@Scope("prototype") -@ConfigurationProperties("leaflet") -public class LeafletMap implements Map { - - private WebView webView; - private ObservableSet icons; - private boolean debugEnabled = false; - - public LeafletMap() { - icons = FXCollections.observableSet(new HashSet<>()); - - Platform.runLater(() -> { - webView = new WebView(); - webView.getEngine().setJavaScriptEnabled(true); - if (debugEnabled) { - webView.getEngine().load(getClass().getResource("/leaflet/leaflet-debug.html").toExternalForm()); - } else { - webView.getEngine().load(getClass().getResource("/leaflet/leaflet.html").toExternalForm()); - } - }); - } - - @Override - public boolean addIcon(Icon icon) { - return icons.add(icon); - } - - @Override - public boolean removeIcon(Icon icon) { - return icons.remove(icon); - } - - @Override - public void attach(StackPane parent) { - if (parent != null) { - parent.getChildren().add(webView); - } - icons.addListener((SetChangeListener) change -> { - clearIconLayer(); - addIconsToMap(change.getSet()); - }); - } - - protected void clearIconLayer() { - Platform.runLater(() -> webView.getEngine().executeScript("iconGroup.clearLayers()")); - } - - protected void addIconsToMap(Collection icons) { - // TODO: Need to save object references in a JavaScript map and keep IDs - // in sync on our end to add/remove efficiently. For - // now we can probably get away with clearing and re-adding the layer. - List iconCollection = new ArrayList<>(icons); - Platform.runLater(() -> { - StringBuilder sb = new StringBuilder(); - for (Icon icon : iconCollection) { - sb.append(createJsIconRepresentation(icon)); - } - webView.getEngine().executeScript(sb.toString()); - }); - } - - private String createJsIconRepresentation(Icon icon) { - StringBuilder sb = new StringBuilder(); - switch (icon.getType()) { - case TRIANGLE_UP: - sb.append("L.marker(["); - sb.append(icon.getLocation().getLatitude()); - sb.append(","); - sb.append(icon.getLocation().getLongitude()); - sb.append("], {icon: L.icon({"); - sb.append("iconUrl: 'images/triangle-up.png',"); - sb.append("iconSize: [12, 12],"); - sb.append("iconAnchor: [6, 6],"); - sb.append("popupAnchor: [-3, -3]"); - sb.append("})}).bindPopup('"); - sb.append(icon.getFriendlyName()); - sb.append("').addTo(iconGroup);"); - break; - case CIRCLE: - case DEFAULT: - sb.append("L.circleMarker(["); - sb.append(icon.getLocation().getLatitude()); - sb.append(","); - sb.append(icon.getLocation().getLongitude()); - sb.append("], { radius: 5, color: 'black', fillColor: '#ff0000', opacity: 1, fillOpacity: 1 })"); - sb.append(".bindPopup('"); - sb.append(icon.getFriendlyName()); - sb.append("').addTo(iconGroup);"); - break; - } - return sb.toString(); - } - - public boolean isDebugEnabled() { - return debugEnabled; - } - - public void setDebugEnabled(boolean debugEnabled) { - this.debugEnabled = debugEnabled; - } - - @Override - public void clearIcons() { - icons.clear(); - } - - @Override - public void addIcons(Collection icons) { - addIconsToMap(icons); - } -} 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 b6ff8b23..3251128f 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -16,10 +16,15 @@ import java.awt.Color; import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,22 +32,32 @@ import com.fasterxml.jackson.core.JsonProcessingException; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ParameterClient; +import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.PeakVelocityClient; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ShapeMeasurementClient; -import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.WaveformClient; -import gov.llnl.gnem.apps.coda.calibration.gui.util.NumberFormatFactory; -import gov.llnl.gnem.apps.coda.calibration.model.domain.Event; -import gov.llnl.gnem.apps.coda.calibration.model.domain.FrequencyBand; -import gov.llnl.gnem.apps.coda.calibration.model.domain.Station; -import gov.llnl.gnem.apps.coda.calibration.model.domain.SyntheticCoda; -import gov.llnl.gnem.apps.coda.calibration.model.domain.Waveform; -import gov.llnl.gnem.apps.coda.calibration.model.domain.WaveformPick; -import gov.llnl.gnem.apps.coda.calibration.model.domain.util.PICK_TYPES; +import gov.llnl.gnem.apps.coda.common.gui.data.client.api.WaveformClient; +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.mapping.api.Icon.IconStyles; +import gov.llnl.gnem.apps.coda.common.mapping.api.Icon.IconTypes; +import gov.llnl.gnem.apps.coda.common.mapping.api.IconFactory; +import gov.llnl.gnem.apps.coda.common.mapping.api.Location; +import gov.llnl.gnem.apps.coda.common.model.domain.Event; +import gov.llnl.gnem.apps.coda.common.model.domain.FrequencyBand; +import gov.llnl.gnem.apps.coda.common.model.domain.Station; +import gov.llnl.gnem.apps.coda.common.model.domain.SyntheticCoda; +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.util.PICK_TYPES; import llnl.gnem.core.gui.plotting.HorizPinEdge; import llnl.gnem.core.gui.plotting.Legend; +import llnl.gnem.core.gui.plotting.PenStyle; import llnl.gnem.core.gui.plotting.VertPinEdge; import llnl.gnem.core.gui.plotting.jmultiaxisplot.JSubplot; import llnl.gnem.core.gui.plotting.jmultiaxisplot.PickMovedState; import llnl.gnem.core.gui.plotting.jmultiaxisplot.VPickLine; +import llnl.gnem.core.gui.plotting.plotobject.AbstractLine; +import llnl.gnem.core.gui.plotting.plotobject.JDataRectangle; import llnl.gnem.core.gui.plotting.plotobject.Line; import llnl.gnem.core.gui.plotting.plotobject.PlotObject; import llnl.gnem.core.gui.waveform.SeriesPlot; @@ -53,229 +68,302 @@ public class CodaWaveformPlot extends SeriesPlot { - private final Logger log = LoggerFactory.getLogger(this.getClass()); - - private NumberFormat dfmt4 = NumberFormatFactory.fourDecimalOneLeadingZero(); - - private Map pickLineMap = new HashMap<>(); - - private WaveformClient waveformClient; - - private ParameterClient paramClient; - - private ShapeMeasurementClient shapeClient; - - public CodaWaveformPlot(String xLabel, WaveformClient waveformClient, ShapeMeasurementClient shapeClient, - ParameterClient paramClient, TimeSeries... seismograms) { - super(xLabel, seismograms); - this.waveformClient = waveformClient; - this.shapeClient = shapeClient; - this.paramClient = paramClient; - } - - private static final long serialVersionUID = 1L; - - public void setWaveform(Waveform waveform) { - setWaveform(waveform, null); - } - - public void setWaveform(SyntheticCoda synth) { - setWaveform(synth.getSourceWaveform(), synth); - } - - public void setWaveform(Waveform waveform, SyntheticCoda synth) { - this.clear(); - pickLineMap.clear(); - - if (waveform.getSegment() != null) { - getXaxis().setLabelText(""); - paramClient .getSharedFrequencyBandParametersForFrequency(new FrequencyBand(waveform.getLowFrequency(), - waveform.getHighFrequency())) - .subscribe(params -> { - shapeClient.getMeasuredShape(waveform.getId()).subscribe(shape -> { - TimeT beginTime = new TimeT(waveform.getBeginTime()); - float[] waveformSegment = doublesToFloats(waveform.getSegment()); - - TimeSeries series = new TimeSeries( waveformSegment, waveform.getSampleRate(), - beginTime); - - this.addSeismogram(series); - JSubplot subplot = this.getSubplot(series); - subplot.setYlimits( subplot.getYaxis().getMin() - 1.0, - subplot.getYaxis().getMax() + 1.0); - Legend legend = new Legend( getTitle().getFontName(), getTitle().getFontSize(), - HorizPinEdge.RIGHT, VertPinEdge.TOP, 5, 5); - legend.addLabeledLine( waveform.getStream().getStation().getStationName() + "_" - + waveform.getEvent().getEventId() + "_" + waveform.getLowFrequency() + "_" - + waveform.getHighFrequency(), - new Line(0, series.getDelta(), series.getData(), 1)); - subplot.AddPlotObject(legend); - - List picks = waveform.getAssociatedPicks(); - if (picks != null) { - // 1221: Plotting throws a runtime error if - // 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(); - if (pickTime >= new TimeT(waveform.getBeginTime()).getEpochTime() - && pickTime <= new TimeT(waveform.getEndTime()).getEpochTime()) { - Collection pickLines = this.addPick( pick.getPickName(), - pickTime); - for (VPickLine pickLine : pickLines) { - pickLine.setDraggable(true); - pickLineMap.put(pickLine, pick); - } - } - } - } - - if (shape != null && shape.getId() != null) { - try { - series = new TimeSeries(waveformSegment, waveform.getSampleRate(), beginTime); - series.interpolate(1.0); - float[] fitSegment = new float[series.getData().length]; - - double gamma = shape.getMeasuredGamma(); - double beta = shape.getMeasuredBeta(); - double intercept = shape.getMeasuredIntercept(); - - int timeShift = (int) (new TimeT(shape.getMeasuredTime()).subtractD(beginTime) - - 0.5); - for (int i = 0; i < series.getData().length; i++) { - fitSegment[i] = (float) (intercept - gamma * Math.log10(i + 1) - + beta * (i + 1)); - } - - TimeSeries fitSeries = new TimeSeries( fitSegment, series.getSamprate(), - series.getTime()); - subplot.AddPlotObject(createLine(timeShift, 0.0, fitSeries, Color.GRAY)); - repaint(); - } catch (IllegalArgumentException e) { - log.warn(e.getMessage(), e); - } - } - - if (synth != null && params != null) { - try { - series = new TimeSeries(waveformSegment, waveform.getSampleRate(), beginTime); - float[] synthSegment = doublesToFloats(synth.getSegment()); - TimeSeries synthSeries = new TimeSeries(synthSegment, synth.getSampleRate(), - new TimeT(synth.getBeginTime())); - WaveformPick endPick = null; - for (WaveformPick p : waveform.getAssociatedPicks()) { - if (PICK_TYPES.F.name().equals(p.getPickType())) { - endPick = p; - break; - } - } - TimeT endTime; - if (endPick != null && endPick.getPickTimeSecFromOrigin() > 0 - && waveform.getEvent() != null) { - endTime = new TimeT(waveform.getEvent() - .getOriginTime()).add(endPick.getPickTimeSecFromOrigin()); - } else { - endTime = new TimeT(synth.getEndTime()); - } - - series.interpolate(synthSeries.getSamprate()); - - Station station = synth.getSourceWaveform().getStream().getStation(); - Event event = synth.getSourceWaveform().getEvent(); - - double distance = EModel.getDistanceWGS84( event.getLatitude(), - event.getLongitude(), - station.getLatitude(), - station.getLongitude()); - 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); - TimeSeries trimmedWaveform = new TimeSeries(waveformSegment, waveform.getSampleRate(), beginTime); - try { - trimmedWaveform.cutBefore(trimTime); - trimmedWaveform.cutAfter(trimTime.add(30.0)); - - startTime = new TimeT(trimTime.getEpochTime() - + trimmedWaveform.getMaxTime()[0]); - } catch (IllegalArgumentException e) { - startTime = trimTime; - } - - if (startTime.lt(endTime)) { - series.cut(startTime, endTime); - synthSeries.cut(startTime, endTime); - - TimeSeries diffSeis = series.subtract(synthSeries); - - int timeShift = (int) (startTime.subtractD(beginTime) - 0.5); - - double median = diffSeis.getMedian(); - double baz = EModel.getBAZ( station.getLatitude(), station.getLongitude(), - event.getLatitude(), event.getLongitude()); - - getXaxis().setLabelText(getXaxis().getLabelText() + "Shift: " - + dfmt4.format(median) + ", Distance: " + dfmt4.format(distance) - + ", BAz: " + dfmt4.format(baz)); - subplot.AddPlotObject(createLine( timeShift, median, synthSeries, - Color.GREEN)); - repaint(); - } - } catch (IllegalArgumentException e) { - log.warn(e.getMessage(), e); - } - } - }); - }); - } - } - - 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; - } - - /* - * (non-Javadoc) - * - * @see - * llnl.gnem.core.gui.waveform.WaveformPlot#handlePickMovedState(java.lang. - * Object)T - */ - @Override - protected void handlePickMovedState(Object obj) { - super.handlePickMovedState(obj); - PickMovedState pms = (PickMovedState) obj; - VPickLine vpl = pms.getPickLine(); - - if (vpl != null) { - try { - WaveformPick pick = pickLineMap.get(vpl); - if (pick != null) { - pick.setPickTimeSecFromOrigin((float) (vpl.getXval() - - new TimeT(pick.getWaveform().getEvent() - .getOriginTime()).subtractD(new TimeT(pick.getWaveform().getBeginTime())))); - waveformClient.postWaveform(pick.getWaveform()).subscribe(this::setWaveform); - } - } catch (ClassCastException | JsonProcessingException e) { - log.info("Error updating Waveform, {}", e); - } - } - } - - 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(); - } - return xfloats; - } + private static final Logger log = LoggerFactory.getLogger(CodaWaveformPlot.class); + + private NumberFormat dfmt4 = NumberFormatFactory.fourDecimalOneLeadingZero(); + + private Map pickLineMap = new HashMap<>(); + + private WaveformClient waveformClient; + + private ParameterClient paramClient; + + private ShapeMeasurementClient shapeClient; + + private PeakVelocityClient velocityClient; + + private GeoMap mapImpl; + + private IconFactory iconFactory; + + private List mappedIcons = new ArrayList<>(); + + private enum PLOT_ORDERING { + BACKGROUND(0), NOISE_BOX(1), WAVEFORM(2), NOISE_LINE(3), SHAPE_FIT(4), MODEL_FIT(5), PICKS(6); + + private int zorder; + + private PLOT_ORDERING(int zorder) { + this.zorder = zorder; + } + + public int getZOrder() { + return zorder; + } + } + + public CodaWaveformPlot(WaveformClient waveformClient, ShapeMeasurementClient shapeClient, ParameterClient paramClient, PeakVelocityClient velocityClient, GeoMap map, IconFactory iconFactory, + TimeSeries... seismograms) { + super("Time (seconds from origin)", seismograms); + this.waveformClient = waveformClient; + this.shapeClient = shapeClient; + this.paramClient = paramClient; + this.velocityClient = velocityClient; + this.mapImpl = map; + this.iconFactory = iconFactory; + } + + 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); + } + + public void setWaveform(SyntheticCoda synth) { + setWaveform(synth.getSourceWaveform(), synth); + } + + public void setWaveform(Waveform waveform, SyntheticCoda synth) { + this.clear(); + pickLineMap.clear(); + + if (waveform != null && waveform.getSegment() != null && waveform.getBeginTime() != null) { + mapImpl.removeIcons(mappedIcons); + mappedIcons = new ArrayList<>(); + mappedIcons.addAll(mapWaveform(waveform)); + final TimeT beginTime = new TimeT(waveform.getBeginTime()); + final float[] waveformSegment = doublesToFloats(waveform.getSegment()); + final TimeSeries rawSeries = new TimeSeries(waveformSegment, waveform.getSampleRate(), beginTime); + this.addSeismogram(rawSeries); + + JSubplot subplot = this.getSubplot(rawSeries); + subplot.setYlimits(subplot.getYaxis().getMin() - 1.0, subplot.getYaxis().getMax() + 1.0); + Legend legend = new Legend(getTitle().getFontName(), getTitle().getFontSize(), HorizPinEdge.RIGHT, VertPinEdge.TOP, 5, 5); + legend.addLabeledLine( + waveform.getStream().getStation().getStationName() + "_" + waveform.getEvent().getEventId() + "_" + waveform.getLowFrequency() + "_" + waveform.getHighFrequency(), + new Line(0, rawSeries.getDelta(), rawSeries.getData(), 1)); + subplot.AddPlotObject(legend); + + Station station = waveform.getStream().getStation(); + Event event = waveform.getEvent(); + + double distance = EModel.getDistanceWGS84(event.getLatitude(), event.getLongitude(), station.getLatitude(), station.getLongitude()); + double baz = EModel.getBAZ(station.getLatitude(), station.getLongitude(), event.getLatitude(), event.getLongitude()); + getTitle().setText("Distance: " + dfmt4.format(distance) + "km BAz: " + dfmt4.format(baz) + "° "); + + List picks = waveform.getAssociatedPicks(); + if (picks != null) { + // 1221: Plotting throws a runtime error if + // 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(); + if (pickTime >= new TimeT(waveform.getBeginTime()).getEpochTime() && pickTime <= new TimeT(waveform.getEndTime()).getEpochTime()) { + Collection pickLines = this.addPick(pick.getPickName(), pickTime); + for (VPickLine pickLine : pickLines) { + pickLine.setDraggable(true); + pickLineMap.put(pickLine, pick); + } + } + } + } + + shapeClient.getMeasuredShape(waveform.getId()).subscribe(shape -> { + if (shape != null && shape.getId() != null) { + try { + TimeSeries interpolatedSeries = new TimeSeries(waveformSegment, waveform.getSampleRate(), beginTime); + interpolatedSeries.interpolate(1.0); + float[] fitSegment = new float[interpolatedSeries.getData().length]; + + double gamma = shape.getMeasuredGamma(); + double beta = shape.getMeasuredBeta(); + double intercept = shape.getMeasuredIntercept(); + + int timeShift = (int) (new TimeT(shape.getMeasuredTime()).subtractD(beginTime) - 0.5); + for (int i = 0; i < interpolatedSeries.getData().length; i++) { + fitSegment[i] = (float) (intercept - gamma * Math.log10(i + 1) + beta * (i + 1)); + } + + TimeSeries fitSeries = new TimeSeries(fitSegment, interpolatedSeries.getSamprate(), interpolatedSeries.getTime()); + subplot.AddPlotObject(createLine(timeShift, 0.0, fitSeries, Color.GRAY), PLOT_ORDERING.SHAPE_FIT.getZOrder()); + repaint(); + } catch (IllegalArgumentException e) { + log.warn(e.getMessage(), e); + } + } + }); + + paramClient.getSharedFrequencyBandParametersForFrequency(new FrequencyBand(waveform.getLowFrequency(), waveform.getHighFrequency())).subscribe(params -> { + if (params != null) { + try { + velocityClient.getNoiseForWaveform(waveform.getId()).checkpoint().single().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, LIGHT_RED, PenStyle.DASH), PLOT_ORDERING.NOISE_LINE.getZOrder()); + subplot.AddPlotObject(createFixedLine(measurement.getNoiseLevel() + params.getMinSnr(), lineLength, LIGHT_RED, PenStyle.SOLID), PLOT_ORDERING.NOISE_LINE.getZOrder()); + } + }); + + if (synth != null) { + TimeSeries interpolatedSeries = new TimeSeries(waveformSegment, waveform.getSampleRate(), beginTime); + float[] synthSegment = doublesToFloats(synth.getSegment()); + TimeSeries synthSeries = new TimeSeries(synthSegment, synth.getSampleRate(), new TimeT(synth.getBeginTime())); + WaveformPick endPick = null; + for (WaveformPick p : waveform.getAssociatedPicks()) { + if (PICK_TYPES.F.name().equals(p.getPickType())) { + endPick = p; + break; + } + } + TimeT endTime; + if (endPick != null && endPick.getPickTimeSecFromOrigin() > 0 && waveform.getEvent() != null) { + endTime = new TimeT(waveform.getEvent().getOriginTime()).add(endPick.getPickTimeSecFromOrigin()); + } else { + endTime = new TimeT(synth.getEndTime()); + } + + interpolatedSeries.interpolate(synthSeries.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); + TimeSeries trimmedWaveform = new TimeSeries(waveformSegment, waveform.getSampleRate(), beginTime); + try { + trimmedWaveform.cutBefore(trimTime); + trimmedWaveform.cutAfter(trimTime.add(30.0)); + startTime = new TimeT(trimTime.getEpochTime() + trimmedWaveform.getMaxTime()[0]); + } catch (IllegalArgumentException e) { + startTime = trimTime; + } + + if (startTime.lt(endTime)) { + interpolatedSeries.cut(startTime, endTime); + synthSeries.cut(startTime, endTime); + + TimeSeries diffSeis = interpolatedSeries.subtract(synthSeries); + int timeShift = (int) (startTime.subtractD(beginTime) - 0.5); + double median = diffSeis.getMedian(); + + getTitle().setText(getTitle().getText() + "Shift: " + dfmt4.format(median)); + subplot.AddPlotObject(createLine(timeShift, median, synthSeries, Color.GREEN), PLOT_ORDERING.MODEL_FIT.getZOrder()); + } + } + + } catch (IllegalArgumentException e) { + log.warn(e.getMessage(), e); + } + } + repaint(); + }); + } + } + + private Collection mapWaveform(Waveform waveform) { + return Stream.of(waveform).filter(Objects::nonNull).flatMap(w -> { + List icons = new ArrayList<>(); + if (w.getStream() != null && w.getStream().getStation() != null) { + Station station = w.getStream().getStation(); + icons.add(iconFactory.newIcon(IconTypes.TRIANGLE_UP, new Location(station.getLatitude(), station.getLongitude()), station.getStationName(), IconStyles.FOCUSED)); + } + if (w.getEvent() != null) { + icons.add(iconFactory.newIcon(IconTypes.CIRCLE, new Location(w.getEvent().getLatitude(), w.getEvent().getLongitude()), w.getEvent().getEventId(), IconStyles.FOCUSED)); + } + return icons.stream(); + }).collect(Collectors.toList()); + } + + //Only used for Waveforms + @Override + public AbstractLine addLine(TimeSeries seismogram, Color lineColor) { + Line line = new Line(0.0, seismogram.getDelta(), seismogram.getData(), 1); + line.setColor(lineColor); + getSubplot(seismogram).AddPlotObject(line, PLOT_ORDERING.WAVEFORM.getZOrder()); + return line; + } + + //Only used for Picks + @Override + protected void addPlotObject(JSubplot subplot, PlotObject object) { + subplot.AddPlotObject(object, PLOT_ORDERING.PICKS.getZOrder()); + } + + private PlotObject createRectangle(int timeStart, int timeEnd, int heightMin, int heightMax, Color pink) { + JDataRectangle rect = new JDataRectangle(timeStart, heightMin, timeEnd - timeStart, heightMax - heightMin); + rect.setFillColor(pink); + 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) + * + * @see + * llnl.gnem.core.gui.waveform.WaveformPlot#handlePickMovedState(java.lang. + * Object)T + */ + @Override + protected void handlePickMovedState(Object obj) { + super.handlePickMovedState(obj); + PickMovedState pms = (PickMovedState) obj; + VPickLine vpl = pms.getPickLine(); + + if (vpl != null) { + try { + WaveformPick pick = pickLineMap.get(vpl); + if (pick != null) { + pick.setPickTimeSecFromOrigin((float) (vpl.getXval() - new TimeT(pick.getWaveform().getEvent().getOriginTime()).subtractD(new TimeT(pick.getWaveform().getBeginTime())))); + waveformClient.postWaveform(pick.getWaveform()).subscribe(this::setWaveform); + } + } catch (ClassCastException | JsonProcessingException e) { + log.info("Error updating Waveform, {}", e); + } + } + } + + 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(); + } + return xfloats; + } + + @Override + public void setVisible(boolean visible) { + super.setVisible(visible); + if (visible) { + mapImpl.addIcons(mappedIcons); + } else { + mapImpl.removeIcons(mappedIcons); + } + } } diff --git a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/CurveFitPlot.java b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/CurveFitPlot.java index 49677fd9..eee68aad 100644 --- a/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/CurveFitPlot.java +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/plotting/CurveFitPlot.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. 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 3c761f70..e526ba00 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -22,6 +22,7 @@ import java.util.stream.Collectors; import gov.llnl.gnem.apps.coda.calibration.model.domain.Spectra; +import gov.llnl.gnem.apps.coda.common.gui.plotting.PlotPoint; import llnl.gnem.core.gui.plotting.HorizPinEdge; import llnl.gnem.core.gui.plotting.Legend; import llnl.gnem.core.gui.plotting.PaintMode; @@ -328,7 +329,7 @@ public void rescalePlot(double x, double y) { public void refreshPlotAxes() { if (properties.getAutoCalculateYaxisRange()) { - jsubplot.SetAxisLimits(xmin, xmax, ymin, ymax); + jsubplot.setAxisLimits(xmin, xmax, ymin, ymax); } else { jsubplot.getYaxis().setMin(properties.getMinYAxisValue()); jsubplot.getYaxis().setMax(properties.getMaxYAxisValue()); 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 83ca73d4..91c52759 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -25,9 +25,12 @@ import com.google.common.eventbus.Subscribe; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ParameterClient; +import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.PeakVelocityClient; import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.ShapeMeasurementClient; -import gov.llnl.gnem.apps.coda.calibration.gui.data.client.api.WaveformClient; -import gov.llnl.gnem.apps.coda.calibration.gui.events.WaveformSelectionEvent; +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.mapping.api.GeoMap; +import gov.llnl.gnem.apps.coda.common.mapping.api.IconFactory; import javafx.application.Platform; import javafx.embed.swing.SwingNode; import javafx.fxml.FXML; @@ -51,12 +54,19 @@ public class WaveformGui { private WaveformClient waveformClient; private ShapeMeasurementClient shapeClient; private ParameterClient paramsClient; + private PeakVelocityClient peakVelocityClient; + private GeoMap map; + private IconFactory iconFactory; @Autowired - public WaveformGui(WaveformClient waveformClient, ShapeMeasurementClient shapeClient, ParameterClient paramsClient, EventBus bus) { + public WaveformGui(WaveformClient waveformClient, ShapeMeasurementClient shapeClient, ParameterClient paramsClient, PeakVelocityClient peakVelocityClient, GeoMap map, IconFactory iconFactory, + EventBus bus) { this.waveformClient = waveformClient; this.shapeClient = shapeClient; this.paramsClient = paramsClient; + this.peakVelocityClient = peakVelocityClient; + this.map = map; + this.iconFactory = iconFactory; bus.register(this); Platform.runLater(() -> { FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/WaveformGui.fxml")); @@ -67,6 +77,14 @@ public WaveformGui(WaveformClient waveformClient, ShapeMeasurementClient shapeCl root = fxmlLoader.load(); scene = new Scene(root); stage.setScene(scene); + + stage.setOnHiding(e -> { + hide(); + }); + + stage.setOnShowing(e -> { + show(); + }); } catch (IOException e) { throw new IllegalStateException(e); } @@ -90,7 +108,7 @@ private void listener(WaveformSelectionEvent event) { @FXML public void initialize() { SwingUtilities.invokeLater(() -> { - waveformPlot = new CodaWaveformPlot("", waveformClient, shapeClient, paramsClient); + waveformPlot = new CodaWaveformPlot(waveformClient, shapeClient, paramsClient, peakVelocityClient, map, iconFactory); waveformPlotNode.setContent(waveformPlot); }); } @@ -98,12 +116,18 @@ public void initialize() { public void hide() { Platform.runLater(() -> { stage.hide(); + if (waveformPlot != null) { + waveformPlot.setVisible(false); + } }); } public void show() { Platform.runLater(() -> { stage.show(); + if (waveformPlot != null) { + waveformPlot.setVisible(true); + } 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 a7b99076..573e6a14 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 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2017, Lawrence Livermore National Security, LLC. Produced at the Lawrence Livermore National Laboratory +* 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. @@ -17,9 +17,10 @@ import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; -import gov.llnl.gnem.apps.coda.calibration.model.domain.messaging.CalibrationStatusEvent; -import gov.llnl.gnem.apps.coda.calibration.model.domain.messaging.CalibrationStatusEvent.Status; -import gov.llnl.gnem.apps.coda.calibration.model.domain.messaging.Progress; +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.util.ProgressListener; +import gov.llnl.gnem.apps.coda.common.model.messaging.Progress; public class CalibrationProgressListener extends ProgressListener { 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 new file mode 100644 index 00000000..9ccd669f --- /dev/null +++ b/calibration-gui/src/main/java/gov/llnl/gnem/apps/coda/calibration/gui/util/TimeLatchedGetSet.java @@ -0,0 +1,75 @@ +/* +* 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.util; + +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 final ScheduledThreadPoolExecutor scheduledGet = new ScheduledThreadPoolExecutor(1); + private final ScheduledThreadPoolExecutor scheduledSet = new ScheduledThreadPoolExecutor(1); + + private Runnable getter; + private Runnable setter; + + private long setDelay; + private long getDelay; + private long failsafeDelay; + + public TimeLatchedGetSet(Runnable getter, Runnable setter) { + this(getter, setter, 10l, 150l, 1000l); + } + + public TimeLatchedGetSet(Runnable getter, Runnable setter, long setDelay, long getDelay, long failsafeDelay) { + this.getter = getter; + this.setter = setter; + this.setDelay = setDelay; + this.getDelay = getDelay; + this.failsafeDelay = failsafeDelay; + + scheduledGet.setRemoveOnCancelPolicy(true); + scheduledSet.setRemoveOnCancelPolicy(true); + } + + 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); + } + } + + public void get() { + if (getter != null) { + scheduledGet.getQueue().clear(); + scheduledGet.schedule(() -> { + getter.run(); + }, getDelay, TimeUnit.MILLISECONDS); + } + } + +} diff --git a/calibration-gui/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/calibration-gui/src/main/resources/META-INF/additional-spring-configuration-metadata.json index 19af5b60..33ea39be 100644 --- a/calibration-gui/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/calibration-gui/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -1,34 +1,32 @@ -{ - "properties": [ - { - "name": "webclient.basePath", - "type": "java.lang.String", - "description": "The base URL to attempt to connect to for REST services if the REST clients are enabled. Should be of the form [host](:[port])." - }, - { - "name": "app.height", - "type": "java.lang.String", - "description": "Default height (in pixels) the main window will use." - }, - { - "name": "app.width", - "type": "java.lang.String", - "description": "Default width (in pixels) the main window will use." - }, - { - "name": "app.baseTitle", - "type": "java.lang.String", - "description": "Default Title Bar entry for the application (i.e. Coda Calibration)" - }, - { - "name": "app.debug", - "type": "java.lang.String", - "description": "Flag for enabling additional Application level debugging functionality. This is not intended to affect logging levels or globally enable/disable debugging but rather to turn on additional hooks, stack tracing, etc that cross-cut the application. In general this should be left at the default value of false." - }, - { - "name": "leaflet.debugEnabled", - "type": "java.lang.String", - "description": "Flag to enable the console in the Webview map when Leaflet is being used" - } - ] -} \ No newline at end of file +{"properties": [ + { + "name": "webclient.basePath", + "type": "java.lang.String", + "description": "The base URL to attempt to connect to for REST services if the REST clients are enabled. Should be of the form [host](:[port])." + }, + { + "name": "app.height", + "type": "java.lang.String", + "description": "Default height (in pixels) the main window will use." + }, + { + "name": "app.width", + "type": "java.lang.String", + "description": "Default width (in pixels) the main window will use." + }, + { + "name": "app.baseTitle", + "type": "java.lang.String", + "description": "Default Title Bar entry for the application (i.e. Coda Calibration)" + }, + { + "name": "app.debug", + "type": "java.lang.String", + "description": "Flag for enabling additional Application level debugging functionality. This is not intended to affect logging levels or globally enable/disable debugging but rather to turn on additional hooks, stack tracing, etc that cross-cut the application. In general this should be left at the default value of false." + }, + { + "name": "webclient.subscriptions", + "type": "java.util.List", + "description": "A description for 'webclient.subscriptions'" + } +]} \ No newline at end of file diff --git a/calibration-gui/src/main/resources/application.properties b/calibration-gui/src/main/resources/application.properties index db38cb04..84012dfc 100644 --- a/calibration-gui/src/main/resources/application.properties +++ b/calibration-gui/src/main/resources/application.properties @@ -1,6 +1,7 @@ logging.level.org.springframework.web.socket.*=off logging.level.org.springframework.web.reactive.function.client.*=off webclient.basePath=localhost:53921 +webclient.subscriptions=/topic/status-events,/topic/calibration-events app.height=1200 app.width=800 app.baseTitle=Coda Calibration \ No newline at end of file diff --git a/calibration-gui/src/main/resources/fxml/CodaGui.css b/calibration-gui/src/main/resources/fxml/CodaGui.css deleted file mode 100644 index 3fc3427d..00000000 --- a/calibration-gui/src/main/resources/fxml/CodaGui.css +++ /dev/null @@ -1,17 +0,0 @@ -.material-icons { - -fx-font-family: 'Material Icons'; - -fx-font-weight: normal; - -fx-font-style: normal; - -fx-font-size: 18px; /* Preferred icon size */ - -fx-display: inline-block; - -fx-line-height: 1; - -fx-text-transform: none; - -fx-letter-spacing: normal; - -fx-word-wrap: normal; - -fx-white-space: nowrap; - -fx-direction: ltr; -} - -.red-bar { - -fx-accent: red; -} \ No newline at end of file diff --git a/calibration-gui/src/main/resources/fxml/CodaGui.fxml b/calibration-gui/src/main/resources/fxml/CodaGui.fxml index b78b28c0..d11106f7 100644 --- a/calibration-gui/src/main/resources/fxml/CodaGui.fxml +++ b/calibration-gui/src/main/resources/fxml/CodaGui.fxml @@ -1,76 +1,134 @@ + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/calibration-gui/src/main/resources/fxml/SharedBand.fxml b/calibration-gui/src/main/resources/fxml/SharedBand.fxml index f6cdf5cb..fe3ea3e7 100644 --- a/calibration-gui/src/main/resources/fxml/SharedBand.fxml +++ b/calibration-gui/src/main/resources/fxml/SharedBand.fxml @@ -1,60 +1,70 @@ + + - + - + - - + + - + - + - + - + - - + + - + - + + + + + + + + + diff --git a/calibration-gui/src/main/resources/fxml/Site.fxml b/calibration-gui/src/main/resources/fxml/Site.fxml index b0f6bfd5..614fd0e1 100644 --- a/calibration-gui/src/main/resources/fxml/Site.fxml +++ b/calibration-gui/src/main/resources/fxml/Site.fxml @@ -2,7 +2,6 @@ - @@ -16,112 +15,114 @@ - + - - - - - - - - - - - - - - -