From 76433fea7af9522f1515441fa201736afbec383c Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Thu, 28 Mar 2024 14:47:56 +0000
Subject: [PATCH 1/3] Click offline linking
Corrupted database not linking offline clicks back to binary data so
added some new search features which match on file and click number if
other links on UID fail.
---
dependency-reduced-pom.xml | 2 +-
pom.xml | 2 +-
src/PamController/PamController.java | 2 +-
src/PamController/PamguardVersionInfo.java | 6 +--
src/PamguardMVC/PamDataBlock.java | 2 +-
.../superdet/SubdetectionInfo.java | 36 ++++++++++++++++
.../superdet/SuperDetDataBlock.java | 43 ++++++++++++++++++-
src/generalDatabase/PamSubtableData.java | 18 ++++++++
src/generalDatabase/SQLLogging.java | 6 ++-
9 files changed, 108 insertions(+), 9 deletions(-)
diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml
index 73fb08dd..217f240b 100644
--- a/dependency-reduced-pom.xml
+++ b/dependency-reduced-pom.xml
@@ -4,7 +4,7 @@
org.pamguard
Pamguard
Pamguard Java12+
- 2.02.10b
+ 2.02.10ae
Pamguard for Java 12+, using Maven to control dependcies
www.pamguard.org
diff --git a/pom.xml b/pom.xml
index bbb2fbe6..8051e75d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
4.0.0
org.pamguard
Pamguard
- 2.02.10ad
+ 2.02.10ae
Pamguard Java12+
Pamguard for Java 12+, using Maven to control dependcies
www.pamguard.org
diff --git a/src/PamController/PamController.java b/src/PamController/PamController.java
index 447c876e..54f7735f 100644
--- a/src/PamController/PamController.java
+++ b/src/PamController/PamController.java
@@ -196,7 +196,7 @@ public class PamController implements PamControllerInterface, PamSettings {
private Timer diagnosticTimer;
- private boolean debugDumpBufferAtRestart = true;
+ private boolean debugDumpBufferAtRestart = false;
private NetworkController networkController;
private int nNetPrepared;
diff --git a/src/PamController/PamguardVersionInfo.java b/src/PamController/PamguardVersionInfo.java
index 12814aa5..f4710929 100644
--- a/src/PamController/PamguardVersionInfo.java
+++ b/src/PamController/PamguardVersionInfo.java
@@ -16,7 +16,7 @@ public class PamguardVersionInfo {
* @return release type
*/
static public ReleaseType getReleaseType() {
- return ReleaseType.OTHER;
+ return ReleaseType.BETA;
}
/**
@@ -31,12 +31,12 @@ public class PamguardVersionInfo {
* Version number, major version.minorversion.sub-release.
* Note: can't go higher than sub-release 'f'
*/
- static public final String version = "2.02.10ad";
+ static public final String version = "2.02.10ae";
/**
* Release date
*/
- static public final String date = "13 March 2024";
+ static public final String date = "15 March 2024";
// /**
// * Release type - Beta or Core
diff --git a/src/PamguardMVC/PamDataBlock.java b/src/PamguardMVC/PamDataBlock.java
index ddc42abe..ba5d6a29 100644
--- a/src/PamguardMVC/PamDataBlock.java
+++ b/src/PamguardMVC/PamDataBlock.java
@@ -636,7 +636,7 @@ public class PamDataBlock extends PamObservable {
/**
* Find a dataunit based on it's database index. If there have been no updates,
- * then database indexes should be in order and a fast find canbe used. If
+ * then database indexes should be in order and a fast find can be used. If
* however, there have been updates, then things will not be in order so it's
* necessary to go through everything from start to end.
*
diff --git a/src/PamguardMVC/superdet/SubdetectionInfo.java b/src/PamguardMVC/superdet/SubdetectionInfo.java
index 228f9ccc..396dea7d 100644
--- a/src/PamguardMVC/superdet/SubdetectionInfo.java
+++ b/src/PamguardMVC/superdet/SubdetectionInfo.java
@@ -63,6 +63,13 @@ public class SubdetectionInfo implements Comparable implements Comparable implements Comparable1 in a millisecond.
+ */
+ Integer clickNo = subTableData.getClickNumber();
+ if (clickNo == null) {
+ return 0;
+ }
+ else {
+ subTableData.setChildUID(dataUnit.getUID());
+ dataUnit.updateDataUnit(System.currentTimeMillis());
+ return (int) (clickNo - duFileInfo.getIndexInFile());
+ }
+
}
}
diff --git a/src/generalDatabase/PamSubtableData.java b/src/generalDatabase/PamSubtableData.java
index 35a8dc27..a05a6c1e 100644
--- a/src/generalDatabase/PamSubtableData.java
+++ b/src/generalDatabase/PamSubtableData.java
@@ -81,6 +81,11 @@ public class PamSubtableData {
* subdetection table, and not the index from the Click_Detector_Clicks table)
*/
private long dbIndex;
+
+ /**
+ * Click number. only exists for clicks table, but needed for corrupt database.
+ */
+ private Integer clickNumber;
/**
*
@@ -158,5 +163,18 @@ public class PamSubtableData {
this.childUTC = childUTC;
}
+ /**
+ * @return the clickNumber
+ */
+ public Integer getClickNumber() {
+ return clickNumber;
+ }
+
+ /**
+ * @param clickNumber the clickNumber to set
+ */
+ public void setClickNumber(Integer clickNumber) {
+ this.clickNumber = clickNumber;
+ }
}
diff --git a/src/generalDatabase/SQLLogging.java b/src/generalDatabase/SQLLogging.java
index 905ee28f..087a039f 100644
--- a/src/generalDatabase/SQLLogging.java
+++ b/src/generalDatabase/SQLLogging.java
@@ -2077,8 +2077,9 @@ public abstract class SQLLogging {
ArrayList tableList = new ArrayList();
int n = 0;
try {
+ PamSubtableDefinition subtableTableDef = (PamSubtableDefinition) getTableDefinition();
+ PamTableItem clickNoItem = subtableTableDef.findTableItem("ClickNo");
while (subtableResults.next()) {
- PamSubtableDefinition subtableTableDef = (PamSubtableDefinition) getTableDefinition();
PamTableItem tableItem;
// transferDataFromResult(con.getSqlTypes(), subtableResults);
for (int i = 0; i < subtableTableDef.getTableItemCount(); i++) {
@@ -2102,6 +2103,9 @@ public abstract class SQLLogging {
subtableData.setLongName(subtableTableDef.getLongName().getStringValue());
subtableData.setBinaryFilename(subtableTableDef.getBinaryfile().getStringValue());
subtableData.setDbIndex(subtableTableDef.getIndexItem().getIntegerValue());
+ if (clickNoItem != null) {
+ subtableData.setClickNumber(clickNoItem.getIntegerValue());
+ }
try {
subtableData.setChildUID(subtableTableDef.getUidItem().getLongObject());
}
From 8252034f13bf542ffa7d263fffd06fb8f4183086 Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Thu, 28 Mar 2024 16:43:21 +0000
Subject: [PATCH 2/3] Merge updates from Tethys branch (#133)
* Tidying
Lots of GUI improvement and code tidying. Functionality to export
gzipped documents to reduce traffic.
* V 2.02.10ba for user testing
* Tidy up click selector
Improve layout and tips on dialog and improve logic for manual and
automatic event types.
* Menu tide up
---
.classpath | 3 +-
dependency-reduced-pom.xml | 2 +-
pom.xml | 2 +-
src/PamController/DataIntegrityChecker.java | 12 +
src/PamController/DataOutputStore.java | 7 +
src/PamController/PamguardVersionInfo.java | 4 +-
src/PamUtils/worker/PamWorkDialog.java | 17 +
src/PamView/panel/SeparatorBorder.java | 27 ++
.../species/RWTethysDataProvider.java | 1 +
src/binaryFileStorage/BinaryStore.java | 8 +
.../checker/BinaryIntegrityChecker.java | 54 +++
.../dataSelector/ClickDataSelector.java | 21 +-
.../dataSelector/ClickSelectPanel.java | 28 +-
src/dataMap/OfflineDataMap.java | 19 +
src/generalDatabase/DBControlUnit.java | 6 +
src/tethys/CollectionHandler.java | 38 ++
src/tethys/TethysControl.java | 45 +-
src/tethys/TethysTimeFuncs.java | 13 +
.../calibration/CalibrationHandler.java | 17 +-
.../swing/CalibrationsContactCard.java | 33 +-
.../swing/CalibrationsExportWizard.java | 4 +-
.../swing/CalibrationsMainPanel.java | 98 +++--
.../calibration/swing/CalibrationsTable.java | 1 +
src/tethys/dbxml/DBXMLConnect.java | 120 ++++--
src/tethys/dbxml/DBXMLQueries.java | 3 +
src/tethys/deployment/DeploymentHandler.java | 98 +++--
src/tethys/deployment/DeploymentOverview.java | 110 ++---
src/tethys/deployment/EffortFunctions.java | 242 +++++------
src/tethys/deployment/RecordingList.java | 211 ++++++++-
src/tethys/deployment/RecordingPeriod.java | 7 +
.../deployment/swing/EffortProblemDialog.java | 163 +++++++
.../swing/ProjectInformationPanel.java | 7 +
.../deployment/swing/RecordingGapDialog.java | 3 +-
.../detection/BinnedGranularityHandler.java | 12 +
.../detection/CallGranularityHandler.java | 6 +
.../detection/DetectionExportProgress.java | 17 +-
src/tethys/detection/DetectionsHandler.java | 157 +++++--
.../EncounterGranularityHandler.java | 35 +-
src/tethys/detection/GranularityHandler.java | 97 +++++
.../localization/LocalizationHandler.java | 17 +
src/tethys/niluswraps/NilusChecker.java | 2 +-
.../niluswraps/NilusSettingsWrapper.java | 4 +-
src/tethys/output/StreamExportParams.java | 6 +-
src/tethys/output/TethysExportParams.java | 18 +
src/tethys/pamdata/AutoTethysProvider.java | 1 +
.../species/DataBlockSpeciesManager.java | 26 +-
src/tethys/species/ITISFunctions.java | 41 +-
src/tethys/species/ITISTypes.java | 4 +-
src/tethys/species/SpeciesMapItem.java | 14 +
.../species/swing/DataBlockSpeciesDialog.java | 11 +-
.../species/swing/SpeciesSearchDialog.java | 33 +-
src/tethys/species/swing/SpeciesSubPanel.java | 20 +-
.../swing/DatablockDetectionsPanel.java | 99 ++++-
src/tethys/swing/DatablockSynchPanel.java | 101 ++++-
src/tethys/swing/DeploymentExportPanel.java | 5 +-
src/tethys/swing/DeploymentsPanel.java | 112 +++--
src/tethys/swing/FancyClientButton.java | 30 +-
.../swing/PAMGuardDeploymentsTable.java | 45 +-
src/tethys/swing/TethysConnectionPanel.java | 11 +-
src/tethys/swing/TethysDeploymentsTable.java | 9 +-
src/tethys/swing/TethysExportPanel.java | 227 ++++++++++
src/tethys/swing/TippedButton.java | 77 ++++
src/tethys/swing/XMLStringView.java | 5 +-
.../swing/export/DeploymentPeriodPanel.java | 4 +
.../swing/export/DescriptionTypePanel.java | 5 +
src/tethys/swing/export/ExportWorkerCard.java | 14 +-
.../swing/export/ResponsiblePartyPanel.java | 6 +
src/tethys/tooltips/TethysTips.java | 403 ++++++++++++++++++
68 files changed, 2534 insertions(+), 564 deletions(-)
create mode 100644 src/PamController/DataIntegrityChecker.java
create mode 100644 src/PamView/panel/SeparatorBorder.java
create mode 100644 src/binaryFileStorage/checker/BinaryIntegrityChecker.java
create mode 100644 src/tethys/CollectionHandler.java
create mode 100644 src/tethys/deployment/swing/EffortProblemDialog.java
create mode 100644 src/tethys/localization/LocalizationHandler.java
create mode 100644 src/tethys/swing/TethysExportPanel.java
create mode 100644 src/tethys/swing/TippedButton.java
create mode 100644 src/tethys/tooltips/TethysTips.java
diff --git a/.classpath b/.classpath
index 26c568d7..188c7291 100644
--- a/.classpath
+++ b/.classpath
@@ -6,9 +6,8 @@
-
+
-
diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml
index 217f240b..fd1fe9e4 100644
--- a/dependency-reduced-pom.xml
+++ b/dependency-reduced-pom.xml
@@ -4,7 +4,7 @@
org.pamguard
Pamguard
Pamguard Java12+
- 2.02.10ae
+ 2.02.10bb
Pamguard for Java 12+, using Maven to control dependcies
www.pamguard.org
diff --git a/pom.xml b/pom.xml
index 8051e75d..e6b66c5f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
4.0.0
org.pamguard
Pamguard
- 2.02.10ae
+ 2.02.10bb
Pamguard Java12+
Pamguard for Java 12+, using Maven to control dependcies
www.pamguard.org
diff --git a/src/PamController/DataIntegrityChecker.java b/src/PamController/DataIntegrityChecker.java
new file mode 100644
index 00000000..566298e4
--- /dev/null
+++ b/src/PamController/DataIntegrityChecker.java
@@ -0,0 +1,12 @@
+package PamController;
+
+/**
+ * Provides a set of functions that can check and repair data.
+ * @author dg50
+ *
+ */
+public interface DataIntegrityChecker {
+
+ public boolean checkDataStore();
+
+}
diff --git a/src/PamController/DataOutputStore.java b/src/PamController/DataOutputStore.java
index a3536410..05c88d66 100644
--- a/src/PamController/DataOutputStore.java
+++ b/src/PamController/DataOutputStore.java
@@ -29,4 +29,11 @@ public interface DataOutputStore extends OfflineDataStore {
*/
public boolean deleteDataFrom(long timeMillis);
+ /**
+ * Get a data integrity checker. This can be called at startup to see if there is a problem.
+ * @return
+ */
+ public DataIntegrityChecker getInegrityChecker();
+
+
}
diff --git a/src/PamController/PamguardVersionInfo.java b/src/PamController/PamguardVersionInfo.java
index f4710929..f579eca6 100644
--- a/src/PamController/PamguardVersionInfo.java
+++ b/src/PamController/PamguardVersionInfo.java
@@ -31,12 +31,12 @@ public class PamguardVersionInfo {
* Version number, major version.minorversion.sub-release.
* Note: can't go higher than sub-release 'f'
*/
- static public final String version = "2.02.10ae";
+ static public final String version = "2.02.10bb";
/**
* Release date
*/
- static public final String date = "15 March 2024";
+ static public final String date = "22 March 2024";
// /**
// * Release type - Beta or Core
diff --git a/src/PamUtils/worker/PamWorkDialog.java b/src/PamUtils/worker/PamWorkDialog.java
index b4a41d3f..2a3d89c8 100644
--- a/src/PamUtils/worker/PamWorkDialog.java
+++ b/src/PamUtils/worker/PamWorkDialog.java
@@ -1,5 +1,7 @@
package PamUtils.worker;
+import java.awt.Dimension;
+import java.awt.Point;
import java.awt.Window;
import javax.swing.BoxLayout;
@@ -23,6 +25,9 @@ public class PamWorkDialog extends PamDialog {
mainPanel.setBorder(new TitledBorder("Task Progress"));
// GridBagConstraints c = new PamGridBagContraints();
mainPanel.add(progressBar = new JProgressBar(0, 100));
+ Dimension sz = progressBar.getPreferredSize();
+ sz.width = 300;
+ progressBar.setPreferredSize(sz);
textRows = new PamTextDisplay[nTextRows];
for (int i = 0; i < nTextRows; i++) {
// c.gridy++;
@@ -35,6 +40,18 @@ public class PamWorkDialog extends PamDialog {
getButtonPanel().setVisible(false);
setDialogComponent(mainPanel);
setResizable(true);
+
+ if (parentFrame != null) {
+ Dimension prefSize = this.getPreferredSize();
+ Point screenLoc = parentFrame.getLocationOnScreen();
+ int x = (parentFrame.getWidth()-prefSize.width)/2;
+ int y = (parentFrame.getHeight()-prefSize.height)/2;
+ if (screenLoc != null) {
+ x += screenLoc.x;
+ y += screenLoc.y;
+ }
+ setLocation(x, y);
+ }
}
public void update(PamWorkProgressMessage progressMsg) {
diff --git a/src/PamView/panel/SeparatorBorder.java b/src/PamView/panel/SeparatorBorder.java
new file mode 100644
index 00000000..f42192d4
--- /dev/null
+++ b/src/PamView/panel/SeparatorBorder.java
@@ -0,0 +1,27 @@
+package PamView.panel;
+
+import java.awt.Component;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+
+import javax.swing.border.TitledBorder;
+
+public class SeparatorBorder extends TitledBorder {
+
+ private static final long serialVersionUID = 1L;
+
+ public SeparatorBorder(String title) {
+ super(title);
+ // TODO Auto-generated constructor stub
+ }
+ public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
+ FontMetrics fm = g.getFontMetrics();
+ if (fm != null) {
+ height = fm.getHeight()-EDGE_SPACING*2-1;
+ }
+ else {
+ height = 12;
+ }
+ super.paintBorder(c, g, x, y, width, height);
+ }
+}
diff --git a/src/RightWhaleEdgeDetector/species/RWTethysDataProvider.java b/src/RightWhaleEdgeDetector/species/RWTethysDataProvider.java
index 3577bd12..caff472e 100644
--- a/src/RightWhaleEdgeDetector/species/RWTethysDataProvider.java
+++ b/src/RightWhaleEdgeDetector/species/RWTethysDataProvider.java
@@ -29,6 +29,7 @@ public class RWTethysDataProvider extends AutoTethysProvider {
Parameters parameters = detection.getParameters();
parameters.setScore((double) rweDataUnit.rweSound.soundType);
double snr = 20.*Math.log10(rweDataUnit.rweSound.signal/rweDataUnit.rweSound.noise);
+ snr = AutoTethysProvider.roundDecimalPlaces(snr, 1);
parameters.setSNRDB(snr);
return detection;
diff --git a/src/binaryFileStorage/BinaryStore.java b/src/binaryFileStorage/BinaryStore.java
index 96b89b3f..1785eb6f 100644
--- a/src/binaryFileStorage/BinaryStore.java
+++ b/src/binaryFileStorage/BinaryStore.java
@@ -37,6 +37,7 @@ import dataMap.OfflineDataMap;
import dataMap.OfflineDataMapPoint;
import PamController.AWTScheduler;
import PamController.DataInputStore;
+import PamController.DataIntegrityChecker;
import PamController.DataOutputStore;
import PamController.OfflineDataStore;
import PamController.PamControlledUnit;
@@ -74,6 +75,7 @@ import annotation.binary.AnnotationBinaryData;
import annotation.handler.AnnotationHandler;
import backupmanager.BackupInformation;
import binaryFileStorage.backup.BinaryBackupStream;
+import binaryFileStorage.checker.BinaryIntegrityChecker;
import binaryFileStorage.layoutFX.BinaryStoreGUIFX;
/**
@@ -946,6 +948,8 @@ PamSettingsSource, DataOutputStore {
PamController.getInstance().notifyModelChanged(PamControllerInterface.CHANGED_OFFLINE_DATASTORE);
// System.out.println("BinaryDataMapMaker really done " + this);
dataMapMaker = null;
+
+ getInegrityChecker().checkDataStore();
}
@Override
@@ -2593,5 +2597,9 @@ PamSettingsSource, DataOutputStore {
public String getDataLocation() {
return binaryStoreSettings.getStoreLocation();
}
+ @Override
+ public DataIntegrityChecker getInegrityChecker() {
+ return new BinaryIntegrityChecker(this);
+ }
}
diff --git a/src/binaryFileStorage/checker/BinaryIntegrityChecker.java b/src/binaryFileStorage/checker/BinaryIntegrityChecker.java
new file mode 100644
index 00000000..011b9c05
--- /dev/null
+++ b/src/binaryFileStorage/checker/BinaryIntegrityChecker.java
@@ -0,0 +1,54 @@
+package binaryFileStorage.checker;
+
+import java.util.ArrayList;
+
+import PamController.DataIntegrityChecker;
+import PamController.PamController;
+import PamView.dialog.warn.WarnOnce;
+import PamguardMVC.PamDataBlock;
+import binaryFileStorage.BinaryStore;
+import dataMap.OfflineDataMap;
+
+public class BinaryIntegrityChecker implements DataIntegrityChecker {
+
+ private BinaryStore binaryStore;
+
+ public BinaryIntegrityChecker(BinaryStore binaryStore) {
+ this.binaryStore = binaryStore;
+ }
+
+ public boolean checkDataStore() {
+ checkMapOverlaps();
+
+
+ return true;
+ }
+
+ private boolean checkMapOverlaps() {
+ boolean ok = true;
+ ArrayList dataBlocks = binaryStore.getStreamingDataBlocks(false);
+ for (PamDataBlock aBlock : dataBlocks) {
+ ok &= checkMapOverlaps(aBlock);
+ }
+ return ok;
+ }
+
+ private boolean checkMapOverlaps(PamDataBlock aBlock) {
+ OfflineDataMap dataMap = aBlock.getOfflineDataMap(binaryStore);
+ if (dataMap == null) {
+ return true;
+ }
+ long overlaps = dataMap.checkOverlaps();
+ if (overlaps <= 0) {
+ return true;
+ }
+ String warn = String.format("Binary data %s has overlapping data files, with a maximum overlap of %3.1fs
"
+ + "This can occur when data have been reprocessed multiple times offline into "
+ + "the same folders.
Since files sometimes get slightly different names, old files are"
+ + "not always overwritten.
"
+ + "You should determine which files are 'old' by looking at file creation dates and delete them.",
+ aBlock.getLongDataName(), (double) overlaps / 1000.);
+ WarnOnce.showNamedWarning("BINOVERLAPWARNING", PamController.getMainFrame(), "Data Integrity Warning", warn, WarnOnce.WARNING_MESSAGE);
+ return false;
+ }
+}
diff --git a/src/clickDetector/dataSelector/ClickDataSelector.java b/src/clickDetector/dataSelector/ClickDataSelector.java
index a7a1d4d8..5be77c2a 100644
--- a/src/clickDetector/dataSelector/ClickDataSelector.java
+++ b/src/clickDetector/dataSelector/ClickDataSelector.java
@@ -112,14 +112,23 @@ public class ClickDataSelector extends DataSelector {
// see if there is a super detection and see if it's got a comment.
String comment = oev.getComment();
+
+ boolean isAutomatic = false;
if (comment != null) {
- if (clickAlarmParameters.onlineAutoEvents && comment.startsWith("Automatic")) {
- return true;
- }
- if (clickAlarmParameters.onlineManualEvents && comment.startsWith("Manual")) {
- return true;
- }
+ isAutomatic = comment.startsWith("Automatic");
}
+ if (isAutomatic && clickAlarmParameters.onlineAutoEvents) {
+ return true;
+ }
+ else if (clickAlarmParameters.onlineManualEvents) {
+ return true;
+ }
+// if (clickAlarmParameters.onlineAutoEvents && comment.startsWith("Automatic")) {
+// return true;
+// }
+// if (clickAlarmParameters.onlineManualEvents && comment.startsWith("Manual")) {
+// return true;
+// }
/*
* Otherwise need to work out where the hell the event type is in the
* list of event types and see if it's wanted.
diff --git a/src/clickDetector/dataSelector/ClickSelectPanel.java b/src/clickDetector/dataSelector/ClickSelectPanel.java
index 859ee841..512e088d 100644
--- a/src/clickDetector/dataSelector/ClickSelectPanel.java
+++ b/src/clickDetector/dataSelector/ClickSelectPanel.java
@@ -30,6 +30,8 @@ import PamView.dialog.PamDialog;
import PamView.dialog.PamDialogPanel;
import PamView.dialog.PamGridBagContraints;
import PamView.panel.PamAlignmentPanel;
+import PamView.panel.SeparatorBorder;
+import PamView.panel.WestAlignedPanel;
public class ClickSelectPanel implements PamDialogPanel {
@@ -40,6 +42,8 @@ public class ClickSelectPanel implements PamDialogPanel {
private ClickDataSelector clickDataSelector;
private JPanel mainPanel;
private boolean isViewer;
+
+ public static final String mainTip = "You should select options in both the Click Type and the Event Type panels";
public ClickSelectPanel(ClickDataSelector clickDataSelector, boolean allowScores, boolean useEventTypes) {
this.clickDataSelector = clickDataSelector;
@@ -79,7 +83,9 @@ public class ClickSelectPanel implements PamDialogPanel {
private LookupList lutList;
public EventTypePanel() {
- setBorder(new TitledBorder("Event Type Selection"));
+ setBorder(new SeparatorBorder("Event Type Selection"));
+
+ setToolTipText(mainTip);
}
void setParams() {
@@ -102,16 +108,24 @@ public class ClickSelectPanel implements PamDialogPanel {
boxPanel.add(onlineAuto = new JCheckBox("Automatically detected click trains"), c);
onlineAuto.setSelected(clickAlarmParameters.onlineAutoEvents);
+ useUnassigned.setToolTipText("Clicks that are NOT part of a manual or automatic click train");
+ onlineManual.setToolTipText("Clicks that are part of a manually marked click train");
+ onlineAuto.setToolTipText("Clicks that are part of an automatically detected click train");
+
lutList = LookUpTables.getLookUpTables().getLookupList(ClicksOffline.ClickTypeLookupName);
if (lutList == null) {
return;
}
+ c.gridy++;
+ boxPanel.add(new JLabel("OR the following click train types ...", JLabel.LEFT), c);
useType = new JCheckBox[lutList.getList().size()];
for (int i = 0; i < useType.length; i++) {
c.gridy++;
boxPanel.add(useType[i] = new JCheckBox(lutList.getList().get(i).getText()), c);
useType[i].setSelected(clickAlarmParameters.isUseEventType(lutList.getList().get(i).getCode()));
+ String tip = String.format("Clicks that are part of a click train labelled as %s", lutList.getList().get(i).getText());
+ useType[i].setToolTipText(tip);
}
}
@@ -158,10 +172,9 @@ public class ClickSelectPanel implements PamDialogPanel {
northPanel = new JPanel();
northPanel.setLayout(new GridBagLayout());
GridBagConstraints c = new PamGridBagContraints();
- northPanel.setBorder(new TitledBorder("Echoes"));
c.gridwidth = 3;
c.anchor = GridBagConstraints.WEST;
- northPanel.add(useEchoes = new JCheckBox("Use Echoes"), c);
+ northPanel.add(new PamAlignmentPanel(useEchoes = new JCheckBox("Use Echoes"), BorderLayout.WEST), c);
c.gridwidth = 1;
c.gridy++;
c.gridx = 0;
@@ -178,11 +191,13 @@ public class ClickSelectPanel implements PamDialogPanel {
northPanel.add(scoreByAmplitude = new JCheckBox("Score by amplitude"), c);
scoreByAmplitude.setVisible(allowScores);
scoreByAmplitude.addActionListener(new AllSpeciesListener());
- add(BorderLayout.NORTH, northPanel);
+ WestAlignedPanel walpn;
+ add(BorderLayout.NORTH, walpn = new WestAlignedPanel(northPanel));
+ walpn.setBorder(new SeparatorBorder("Echoes"));
JPanel centralOuterPanel = new JPanel(new BorderLayout());
centralPanel.setLayout(new GridBagLayout());
- centralOuterPanel.setBorder(new TitledBorder("Click Type Selection"));
+ centralOuterPanel.setBorder(new SeparatorBorder("Click Type Selection"));
add(BorderLayout.CENTER, centralOuterPanel);
JScrollPane scrollPane = new DialogScrollPane(new PamAlignmentPanel(centralPanel, BorderLayout.WEST), 10);
@@ -197,6 +212,9 @@ public class ClickSelectPanel implements PamDialogPanel {
clearAll.addActionListener(new AutoSelect(false));
centralOuterPanel.add(BorderLayout.SOUTH, new PamAlignmentPanel(centralEastPanel, BorderLayout.WEST));
+ centralOuterPanel.setToolTipText(mainTip);
+
+ setToolTipText(mainTip);
}
void setParams() {
diff --git a/src/dataMap/OfflineDataMap.java b/src/dataMap/OfflineDataMap.java
index d51ee120..d62f2224 100644
--- a/src/dataMap/OfflineDataMap.java
+++ b/src/dataMap/OfflineDataMap.java
@@ -844,4 +844,23 @@ abstract public class OfflineDataMap {
obs.updateDataMap(this, mapPoint);
}
}
+
+ /**
+ * Check to see if any data maps overlap in time.
+ * @return largest overlap between maps. 0 or -ve means no overlap.
+ */
+ public long checkOverlaps() {
+ long bigLap = Long.MIN_VALUE;
+ TmapPoint prevPoint = null;
+ for (TmapPoint mapPoint : mapPoints) {
+ if (prevPoint != null) {
+ long olap = prevPoint.getEndTime() - mapPoint.getStartTime();
+// if (mapPoint.getStartTime() < prevPoint.getEndTime()) {
+ bigLap = Math.max(olap, bigLap);
+// }
+ }
+ prevPoint = mapPoint;
+ }
+ return bigLap;
+ }
}
diff --git a/src/generalDatabase/DBControlUnit.java b/src/generalDatabase/DBControlUnit.java
index 0b4239b8..a48971da 100644
--- a/src/generalDatabase/DBControlUnit.java
+++ b/src/generalDatabase/DBControlUnit.java
@@ -18,6 +18,7 @@ import generalDatabase.backup.DatabaseBackupStream;
import pamScrollSystem.ViewLoadObserver;
import pamViewFX.pamTask.PamTaskUpdate;
import PamController.AWTScheduler;
+import PamController.DataIntegrityChecker;
import PamController.DataOutputStore;
import PamController.OfflineDataStore;
import PamController.PamConfiguration;
@@ -524,5 +525,10 @@ public class DBControlUnit extends DBControl implements DataOutputStore {
}
return state;
}
+ @Override
+ public DataIntegrityChecker getInegrityChecker() {
+ // TODO Auto-generated method stub
+ return null;
+ }
}
diff --git a/src/tethys/CollectionHandler.java b/src/tethys/CollectionHandler.java
new file mode 100644
index 00000000..66208fa0
--- /dev/null
+++ b/src/tethys/CollectionHandler.java
@@ -0,0 +1,38 @@
+package tethys;
+
+abstract public class CollectionHandler {
+
+ private Collection collection;
+
+ protected TethysControl tethysControl;
+
+ /**
+ * @param tethysControl
+ * @param collection
+ */
+ public CollectionHandler(TethysControl tethysControl, Collection collection) {
+ this.tethysControl = tethysControl;
+ this.collection = collection;
+ }
+
+ public String collectionName() {
+ return collection.collectionName();
+ }
+
+ /**
+ * @return the collection
+ */
+ public Collection getCollection() {
+ return collection;
+ }
+
+ /**
+ * @return the tethysControl
+ */
+ public TethysControl getTethysControl() {
+ return tethysControl;
+ }
+
+ public abstract String getHelpPoint();
+
+}
diff --git a/src/tethys/TethysControl.java b/src/tethys/TethysControl.java
index 83e445b7..42889f45 100644
--- a/src/tethys/TethysControl.java
+++ b/src/tethys/TethysControl.java
@@ -32,6 +32,8 @@ import PamController.PamSettingManager;
import PamController.PamSettings;
import PamUtils.PamFileChooser;
import PamUtils.PamFileFilter;
+import PamUtils.worker.PamWorkWrapper;
+import PamUtils.worker.PamWorker;
import PamView.PamTabPanel;
import PamView.dialog.warn.WarnOnce;
import PamguardMVC.PamDataBlock;
@@ -104,7 +106,9 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
serverCheckTimer = new Timer(10000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- checkServer();
+ ServerStatus serverState = checkServer();
+ // check less often when it's OK to generate less debug output.
+ serverCheckTimer.setDelay(serverState.ok ? 600000 : 5000);
}
});
serverCheckTimer.setInitialDelay(0);
@@ -469,6 +473,8 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
// case PamControllerInterface.INITIALIZATION_COMPLETE:
initializationStuff();
break;
+ case PamControllerInterface.HYDROPHONE_ARRAY_CHANGED:
+ sendStateUpdate(new TethysState(StateType.UPDATEMETADATA));
}
}
@@ -525,7 +531,32 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
}
}
- private void countProjectDetections() {
+// /**
+// * Count project detections in a worker thread;
+// */
+// public void countProjectDetectionsT() {
+// sendStateUpdate(new TethysState(StateType.EXPORTRDATA, Collection.Detections));
+// PamWorker worker = new PamWorker(new PamWorkWrapper() {
+//
+// @Override
+// public String runBackgroundTask(PamWorker pamWorker) {
+// countProjectDetections();
+// return null;
+// }
+//
+// @Override
+// public void taskFinished(String result) {
+// sendStateUpdate(new TethysState(StateType.NEWPAMGUARDSELECTION, Collection.Detections));
+//
+// }
+// }, getGuiFrame(), 0, "Updating detections counts");
+// worker.start();
+// }
+
+ /**
+ * Count project detections in the current thread.
+ */
+ private synchronized void countProjectDetections() {
if (dataBlockSynchInfos == null) {
return;
}
@@ -549,12 +580,6 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
i++;
}
-// int[] counts = dbxmlQueries.countDataForProject(deplData.getProject(), dataPrefixes);
-// if (counts != null) {
-// for ( i = 0; i < counts.length; i++ ) {
-// dataBlockSynchInfos.get(i).setDataCount(counts[i]);
-// }
-// }
}
/**
@@ -688,11 +713,9 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet
* @param dataBlock
*/
public void exportedDetections(PamDataBlock dataBlock) {
- sendStateUpdate(new TethysState(StateType.EXPORTRDATA, Collection.Detections));
countProjectDetections();
- sendStateUpdate(new TethysState(StateType.NEWPAMGUARDSELECTION, Collection.Detections));
+// sendStateUpdate(new TethysState(StateType.NEWPAMGUARDSELECTION, Collection.Detections));
}
-
/**
* @return the calibrationHandler
*/
diff --git a/src/tethys/TethysTimeFuncs.java b/src/tethys/TethysTimeFuncs.java
index 70d11704..e238fb22 100644
--- a/src/tethys/TethysTimeFuncs.java
+++ b/src/tethys/TethysTimeFuncs.java
@@ -12,6 +12,7 @@ import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import PamUtils.PamCalendar;
+import nilus.Helper;
public class TethysTimeFuncs {
@@ -54,6 +55,18 @@ public class TethysTimeFuncs {
* @return
*/
public static XMLGregorianCalendar fromGregorianXML(String gregorianString) {
+
+ try {
+ XMLGregorianCalendar xmlCal = Helper.timestamp(gregorianString);
+ return xmlCal;
+ } catch (DatatypeConfigurationException e1) {
+ // TODO Auto-generated catch block
+// e1.printStackTrace();
+ }
+ /**
+ * Above should work just fine. If it doesn't use my own code below...
+ */
+
// typical string is 2018-10-20T00:00:00Z
if (gregorianString == null) {
return null;
diff --git a/src/tethys/calibration/CalibrationHandler.java b/src/tethys/calibration/CalibrationHandler.java
index 37dc186e..2aff00d8 100644
--- a/src/tethys/calibration/CalibrationHandler.java
+++ b/src/tethys/calibration/CalibrationHandler.java
@@ -1,6 +1,5 @@
package tethys.calibration;
-import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -37,6 +36,7 @@ import nilus.MetadataInfo;
import nilus.QualityValueBasic;
import nilus.ResponsibleParty;
import tethys.Collection;
+import tethys.CollectionHandler;
import tethys.DocumentInfo;
import tethys.DocumentNilusObject;
import tethys.TethysControl;
@@ -52,9 +52,7 @@ import tethys.niluswraps.NilusUnpacker;
import tethys.pamdata.AutoTethysProvider;
import tethys.reporter.TethysReporter;
-public class CalibrationHandler implements TethysStateObserver {
-
- private TethysControl tethysControl;
+public class CalibrationHandler extends CollectionHandler implements TethysStateObserver {
private ArrayList> calibrationsList;
@@ -65,10 +63,14 @@ public class CalibrationHandler implements TethysStateObserver {
public static final String[] qaTypes = {"unverified", "valid", "invalid"};
private Helper nilusHelper;
+
+ public static final String helpPoint = "utilities.tethys.docs.calibrations";
+
/**
* @param tethysControl
*/
public CalibrationHandler(TethysControl tethysControl) {
+ super(tethysControl, Collection.Calibrations);
this.tethysControl = tethysControl;
calibrationsList = new ArrayList();
tethysControl.addStateObserver(this); try {
@@ -504,7 +506,7 @@ public class CalibrationHandler implements TethysStateObserver {
}
String seachPattern = makeChannelNamePart(iChan);
for (int i = 0; i < calibrationsList.size(); i++) {
- String docName = calibrationsList.get(i).getDocumentName();
+ String docName = calibrationsList.get(i).getDocumentId();
if (docName.endsWith(seachPattern)) {
return true;
}
@@ -570,4 +572,9 @@ public class CalibrationHandler implements TethysStateObserver {
}
return theseCals;
}
+
+ @Override
+ public String getHelpPoint() {
+ return helpPoint;
+ }
}
diff --git a/src/tethys/calibration/swing/CalibrationsContactCard.java b/src/tethys/calibration/swing/CalibrationsContactCard.java
index 2dc6e581..0ad03c36 100644
--- a/src/tethys/calibration/swing/CalibrationsContactCard.java
+++ b/src/tethys/calibration/swing/CalibrationsContactCard.java
@@ -5,6 +5,7 @@ import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.util.ArrayList;
import java.util.Date;
import javax.swing.BoxLayout;
@@ -18,6 +19,9 @@ import javax.xml.datatype.XMLGregorianCalendar;
import org.jdesktop.swingx.JXDatePicker;
+import Array.ArrayManager;
+import Array.Hydrophone;
+import Array.PamArray;
import PamView.dialog.PamDialog;
import PamView.dialog.PamGridBagContraints;
import PamView.panel.WestAlignedPanel;
@@ -43,6 +47,8 @@ public class CalibrationsContactCard extends CalibrationsCard {
private JButton copyDown, copyUp;
+ private JComboBox hydrophoneSelection;
+
public CalibrationsContactCard(PamWizard pamWizard) {
super(pamWizard, "Contact Details");
// TODO Auto-generated constructor stub
@@ -57,17 +63,26 @@ public class CalibrationsContactCard extends CalibrationsCard {
JPanel datePanel = new JPanel(new GridBagLayout());
JPanel lp = new WestAlignedPanel(datePanel);
- lp.setBorder(new TitledBorder("Calibration date"));
+ lp.setBorder(new TitledBorder("Date and hydrophones"));
GridBagConstraints c = new PamGridBagContraints();
datePanel.add(new JLabel("Calibration date: ", JLabel.RIGHT), c);
datePicker = new JXDatePicker();
c.gridx++;
datePanel.add(datePicker, c);
- c.gridx = 0;
- c.gridy++;
- datePanel.add(new JLabel("Update Frequency", JLabel.RIGHT), c);
+// c.gridx = 0;
+ c.gridx++;
+ datePanel.add(new JLabel(" Update Frequency ", JLabel.RIGHT), c);
c.gridx++;
datePanel.add(updateInterval, c);
+ c.gridx = 0;
+ c.gridy++;
+ datePanel.add(new JLabel(" Hydrophones ", JLabel.RIGHT), c);
+ c.gridwidth = 5;
+ c.gridx++;
+ hydrophoneSelection = new JComboBox<>();
+ datePanel.add(hydrophoneSelection, c);
+ hydrophoneSelection.setToolTipText("Select which hydrophone calibrations to export");
+
calibrator = new ResponsiblePartyPanel("Technical Person");
dataManager = new ResponsiblePartyPanel("Data Manager");
@@ -202,6 +217,16 @@ public class CalibrationsContactCard extends CalibrationsCard {
datePicker.setDate(new Date(TethysTimeFuncs.millisFromGregorianXML(ts)));
}
+ hydrophoneSelection.removeAllItems();
+ hydrophoneSelection.addItem("All hydrophones");
+ PamArray array = ArrayManager.getArrayManager().getCurrentArray();
+ ArrayList phones = array.getHydrophoneArray();
+ int i = 0;
+ for (Hydrophone phone : phones) {
+ String txt = String.format("Hydrophone %d, %s, %3.1f dBre1\u00B5Pa", i, phone.getType(), phone.getSensitivity());
+ hydrophoneSelection.addItem(txt);
+ i++;
+ }
}
diff --git a/src/tethys/calibration/swing/CalibrationsExportWizard.java b/src/tethys/calibration/swing/CalibrationsExportWizard.java
index 74bb356a..1ab7bc6e 100644
--- a/src/tethys/calibration/swing/CalibrationsExportWizard.java
+++ b/src/tethys/calibration/swing/CalibrationsExportWizard.java
@@ -5,6 +5,7 @@ import java.awt.Window;
import PamView.wizard.PamWizard;
import PamView.wizard.PamWizardCard;
import nilus.Calibration;
+import tethys.calibration.CalibrationHandler;
public class CalibrationsExportWizard extends PamWizard {
@@ -13,8 +14,9 @@ public class CalibrationsExportWizard extends PamWizard {
private CalibrationsExportWizard(Window parentFrame, Calibration sampleDocument) {
super(parentFrame, "Calibrations Export");
this.sampleDocument = sampleDocument;
- addCard(new CalibrationProcessCard(this));
addCard(new CalibrationsContactCard(this));
+ addCard(new CalibrationProcessCard(this));
+ setHelpPoint(CalibrationHandler.helpPoint);
}
public static Calibration showWizard(Window parentFrame, Calibration sampleDocument) {
diff --git a/src/tethys/calibration/swing/CalibrationsMainPanel.java b/src/tethys/calibration/swing/CalibrationsMainPanel.java
index e13365ef..cd1275f7 100644
--- a/src/tethys/calibration/swing/CalibrationsMainPanel.java
+++ b/src/tethys/calibration/swing/CalibrationsMainPanel.java
@@ -15,53 +15,47 @@ import PamView.panel.PamPanel;
import tethys.TethysControl;
import tethys.TethysState;
import tethys.calibration.CalibrationHandler;
+import tethys.deployment.PInstrument;
+import tethys.swing.TethysExportPanel;
import tethys.swing.TethysGUIPanel;
+import tethys.swing.TippedButton;
-public class CalibrationsMainPanel extends TethysGUIPanel {
+public class CalibrationsMainPanel extends TethysExportPanel {
private CalibrationHandler calibrationHandler;
private CalibrationsTable calibrationsTable;
- private JPanel mainPanel;
-
- private JPanel ctrlPanel;
-
- private JButton exportButton;
-
- private JLabel warning;
+// private JPanel mainPanel;
+//
+// private JPanel ctrlPanel;
+//
+// private TippedButton exportButton;
+//
+// private JLabel warning;
public CalibrationsMainPanel(TethysControl tethysControl, CalibrationHandler calibrationHandler) {
- super(tethysControl);
+ super(tethysControl, calibrationHandler, false);
this.calibrationHandler = calibrationHandler;
- mainPanel = new PamPanel(new BorderLayout());
+ JPanel mainPanel = getMainPanel();
+// mainPanel = new PamPanel(new BorderLayout());
mainPanel.setBorder(new TitledBorder("Instrument calibration information"));
calibrationsTable = new CalibrationsTable(tethysControl, calibrationHandler);
mainPanel.add(BorderLayout.CENTER, calibrationsTable.getComponent());
- ctrlPanel = new PamPanel(new BorderLayout());
- exportButton = new JButton("Export ...");
- ctrlPanel.add(BorderLayout.WEST, exportButton);
- warning = new JLabel();
- ctrlPanel.add(BorderLayout.CENTER, warning);
- mainPanel.add(BorderLayout.NORTH, ctrlPanel);
- exportButton.setToolTipText("Export calibration data to database");
- exportButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- exportCalibrations();
- }
- });
- }
-
- protected void exportCalibrations() {
- calibrationHandler.exportAllCalibrations();
- }
-
- @Override
- public JComponent getComponent() {
- return mainPanel;
+// ctrlPanel = new PamPanel(new BorderLayout());
+// exportButton = new TippedButton("Export ...", "Export calibration data to database");
+// ctrlPanel.add(BorderLayout.WEST, exportButton);
+// warning = new JLabel();
+// ctrlPanel.add(BorderLayout.CENTER, warning);
+// mainPanel.add(BorderLayout.NORTH, ctrlPanel);
+// exportButton.addActionListener(new ActionListener() {
+// @Override
+// public void actionPerformed(ActionEvent e) {
+// exportCalibrations();
+// }
+// });
}
@Override
@@ -71,7 +65,45 @@ public class CalibrationsMainPanel extends TethysGUIPanel {
}
private void enableControls() {
- exportButton.setEnabled(getTethysControl().isServerOk());
+ if (getTethysControl().isServerOk() == false) {
+ disableExport("Tethys Server not running");
+ return;
+ }
+ if (isHydrophoneNamed() == false) {
+ disableExport("Can't export calibrations until the Hydrophone array has been correctly named");
+ return;
+ };
+ enableExport(true);
+ }
+
+ /**
+ * Check to see if hydrophone is named correctly.
+ * @return
+ */
+ private boolean isHydrophoneNamed() {
+ PInstrument currentInstrument = getTethysControl().getDeploymentHandler().getCurrentArrayInstrument();
+ if (currentInstrument == null) {
+ return false;
+ }
+ if (currentInstrument.instrumentId == null || currentInstrument.instrumentType == null) {
+ return false;
+ }
+
+ if (currentInstrument.instrumentId.length() == 0 || currentInstrument.instrumentType.length() == 0) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ protected void exportButtonPressed(ActionEvent e) {
+ calibrationHandler.exportAllCalibrations();
+ }
+
+ @Override
+ protected void optionsButtonPressed(ActionEvent e) {
+ // TODO Auto-generated method stub
+
}
}
diff --git a/src/tethys/calibration/swing/CalibrationsTable.java b/src/tethys/calibration/swing/CalibrationsTable.java
index 45b91f18..c9405f1a 100644
--- a/src/tethys/calibration/swing/CalibrationsTable.java
+++ b/src/tethys/calibration/swing/CalibrationsTable.java
@@ -120,6 +120,7 @@ public class CalibrationsTable extends TethysGUIPanel {
});
popMenu.add(menuItem);
}
+ popMenu.addSeparator();
if (n > 1) {
menuItem = new JMenuItem("Delete selected documents");
menuItem.addActionListener(new ActionListener() {
diff --git a/src/tethys/dbxml/DBXMLConnect.java b/src/tethys/dbxml/DBXMLConnect.java
index 9b12ecd5..1da977f0 100644
--- a/src/tethys/dbxml/DBXMLConnect.java
+++ b/src/tethys/dbxml/DBXMLConnect.java
@@ -3,14 +3,17 @@ package tethys.dbxml;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
+import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.nio.file.Files;
import java.util.ArrayList;
+import java.util.zip.GZIPOutputStream;
import javax.xml.bind.JAXBException;
@@ -67,7 +70,7 @@ public class DBXMLConnect {
}
return true;
}
-
+
/**
* Get the client. The client will only be recreated if the url changes
@@ -113,9 +116,9 @@ public class DBXMLConnect {
}
return file;
}
-
+
/**
- * Create a temporary nilus file.
+ * Create a temporary nilus file.
* @param nilusObject
* @return
* @throws TethysException
@@ -124,20 +127,20 @@ public class DBXMLConnect {
String tempName = getTempFileName(nilusObject);
tempName = tempDirectory.getAbsolutePath() + File.separator + tempName + ".xml";
File tempFile = new File(tempName);
- File retFile = createXMLDocument(nilusObject, tempFile);
+ File retFile = createXMLDocument(nilusObject, tempFile);
retFile.deleteOnExit();
return retFile;
}
-
-
+
+
public boolean postAndLog(Object nilusObject) throws TethysException
{
return postAndLog(nilusObject, null);
}
-
+
/**
* I don't think this should ever be used since everything goes a bit pear
- * shaped if the documentName isn't the same as the Id. However, for Calibration
+ * shaped if the documentName isn't the same as the Id. However, for Calibration
* documents this is no longer the case, since a Calibration can have multiple
* entries on different dates, so allow it !
* @param nilusObject
@@ -145,11 +148,11 @@ public class DBXMLConnect {
* @return
* @throws TethysException
*/
- public boolean postAndLog(Object nilusObject, String documentName) throws TethysException
- {
+ public boolean postAndLog(Object nilusObject, String documentName) throws TethysException
+ {
boolean ok = NilusChecker.warnEmptyFields(tethysControl.getGuiFrame(), nilusObject);
-
-
+
+
TethysException e = null;
boolean success = false;
try {
@@ -168,13 +171,13 @@ public class DBXMLConnect {
}
return success;
}
-
+
/**
* take a nilus object loaded with PamGuard data and post it to the Tethys database
*
* @param pamGuardObjs a nilus object loaded with PamGuard data
* @return error string, null string means there are no errors
- * @throws TethysException
+ * @throws TethysException
*/
private boolean postToTethys(Object nilusObject, String documentName) throws TethysException
{
@@ -192,12 +195,35 @@ public class DBXMLConnect {
MarshalXML marshal = new MarshalXML();
marshal.createInstance(objClass);
marshal.marshal(nilusObject, tempFile.toString());
+ // above lines have made a file. Are now going to gzip it before sending to Tethys
+ File zipFile = null;
+ try {
+ zipFile = zipOutputFile(tempFile);
+ }
+ catch (FileNotFoundException e1){
+ System.out.println(e1.getMessage());
+ }
+ catch (IOException e2) {
+ System.out.println(e2.getMessage());
+ }
+ String finalName;
+ if (zipFile == null) {
+ finalName = bodgeName;
+ }
+ else {
+ finalName = zipFile.toString();
+ }
+
+
// tempFile = stripXMLHeader(tempFile);
importReturn = Importer.ImportFiles(params.getFullServerName(), collection.collectionName(),
- new String[] { bodgeName }, "", "", false);
+ new String[] { finalName }, "", "", false);
tempFile.deleteOnExit();
+ if (zipFile != null) {
+ zipFile.deleteOnExit();
+ }
} catch(IllegalArgumentException e) {
throw new TethysException("IllegalArgumentException posting to Tethys: " + e.getMessage(), null);
} catch (IOException e) {
@@ -207,21 +233,49 @@ public class DBXMLConnect {
}
/*
- * The returned string consists of the file name, then an XML report.
- * Quite hard to see much common structure in this, so just look for
+ * The returned string consists of the file name, then an XML report.
+ * Quite hard to see much common structure in this, so just look for
* two words, and
*/
boolean error = importReturn.contains("");
String name = tempFile.getName();
TethysReporter.getTethysReporter().addReport(new TethysReport(success, collection, name, name));
-// error = !success; might be a better options.
+// error = !success; might be a better options.
if (error) {
throw new TethysException("Error posting to Tethys", importReturn);
}
return success;
}
+ /**
+ * Zip an xml file (or any file) into a gz file with a new end
+ * @param xmlFile
+ * @return
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
+ private File zipOutputFile(File xmlFile) throws FileNotFoundException, IOException {
+ String zipName = xmlFile.toString() + "-temp-.gz";
+ File zipFile = new File(zipName);
+ GZIPOutputStream opStream = new GZIPOutputStream(new FileOutputStream(zipFile));
+ InputStream fis = new FileInputStream(xmlFile);
+ int chunkSize = 100*1024;
+ byte[] buffer = new byte[chunkSize];
+// ZipEntry zipEntry = new ZipEntry(xmlFile.getName());
+ int bytesRead;
+ while ((bytesRead = fis.read(buffer)) >= 0) {
+ opStream.write(buffer, 0, bytesRead);
+ }
+
+ opStream.close();
+
+ fis.close();
+
+
+ return zipFile;
+ }
+
/**
* Update a document within Tethys. We're assuming that a
* document with the same name in the same collection already
@@ -229,7 +283,7 @@ public class DBXMLConnect {
* the removedocument function
* @param nilusDocument
* @return
- * @throws TethysException
+ * @throws TethysException
*/
public boolean updateDocument(Object nilusDocument) throws TethysException {
deleteDocument(nilusDocument);
@@ -242,7 +296,7 @@ public class DBXMLConnect {
* class to identify the correct collection.
* @param nilusDocument
* @return
- * @throws TethysException
+ * @throws TethysException
*/
public boolean deleteDocument(Object nilusDocument) throws TethysException {
@@ -259,7 +313,7 @@ public class DBXMLConnect {
- ['ECoastNARW0']
-An error will throw an exception.
+An error will throw an exception.
*/
}
catch (Exception e) {
@@ -275,7 +329,7 @@ An error will throw an exception.
* Delete a Deploymnet and any contained Detections document. Doesn't work !
* @param deploymentId
* @return
- * @throws TethysException
+ * @throws TethysException
*/
public boolean deleteDeployment(String deploymentId) throws TethysException {
ArrayList detDocNames = tethysControl.getDbxmlQueries().getDetectionsDocuments(deploymentId);
@@ -292,8 +346,8 @@ An error will throw an exception.
}
/**
- * Remove a document based on a collection name and a cdocument Id.
- * @param collection collection name.
+ * Remove a document based on a collection name and a cdocument Id.
+ * @param collection collection name.
* @param documentName document name (not the internal Document Id)
* @return
* @throws TethysException
@@ -303,8 +357,8 @@ An error will throw an exception.
}
/**
- * Remove a document based on a collection name and a document namw.
- * @param collectionName collection name.
+ * Remove a document based on a collection name and a document namw.
+ * @param collectionName collection name.
* @param documentName document name (not the internal Document Id)
* @return
* @throws TethysException
@@ -319,7 +373,7 @@ An error will throw an exception.
- ['ECoastNARW0']
- An error will throw an exception.
+ An error will throw an exception.
*/
}
catch (Exception e) {
@@ -330,14 +384,14 @@ An error will throw an exception.
}
/**
- * check the return string from importFiles and if it's an
- * error, throw an exception. Otherwise do nothing.
+ * check the return string from importFiles and if it's an
+ * error, throw an exception. Otherwise do nothing.
* @param fileError
*/
private void checkReturnString(String fileError) {
/**
* Example good string is
- *
+ *
C:\Users\dg50\AppData\Local\Temp\PAMGuardTethys\20080311_2DSimplex_0.xml: 7360 bytes
@@ -367,7 +421,7 @@ C:\Users\dg50\AppData\Local\Temp\PAMGuardTethys\20080311_2DSimplex_0.xmlnot: 0 b
/**
* Seems we have to get rid of the line
- * which is being put there by the marshaller ?
+ * which is being put there by the marshaller ?
* @param tempFile
*/
private File stripXMLHeader(File tempFile) {
@@ -377,7 +431,7 @@ C:\Users\dg50\AppData\Local\Temp\PAMGuardTethys\20080311_2DSimplex_0.xmlnot: 0 b
try {
BufferedReader reader = new BufferedReader(new FileReader(tempFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(tempTemp));
- String line = reader.readLine();
+ String line = reader.readLine();
while (line != null) {
// see if the line has any unicode in it
int len = line.length();
diff --git a/src/tethys/dbxml/DBXMLQueries.java b/src/tethys/dbxml/DBXMLQueries.java
index 460fbc66..d4c0be9a 100644
--- a/src/tethys/dbxml/DBXMLQueries.java
+++ b/src/tethys/dbxml/DBXMLQueries.java
@@ -515,6 +515,9 @@ public class DBXMLQueries {
* first query for Detections documents associated with this deployment and datablock.
* updated May 23
*/
+ if (dataBlock == null) {
+ return null;
+ }
String queryNoDepl = "{\"species\":{\"query\":{\"op\":\"lib:completename2tsn\",\"optype\":\"function\",\"operands\":[\"%s\"]},\"return\":{\"op\":\"lib:tsn2completename\",\"optype\":\"function\",\"operands\":[\"%s\"]}},\"return\":[\"Detections/Id\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Algorithm/Software\",\"LongDataName\"],\"optype\":\"binary\"}],\"enclose\":1}";
String queryWithDepl = "{\"species\":{\"query\":{\"op\":\"lib:completename2tsn\",\"optype\":\"function\",\"operands\":[\"%s\"]},\"return\":{\"op\":\"lib:tsn2completename\",\"optype\":\"function\",\"operands\":[\"%s\"]}},\"return\":[\"Detections/Id\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/DataSource/DeploymentId\",\"TheDeploymentId\"],\"optype\":\"binary\"},{\"op\":\"=\",\"operands\":[\"Detections/Algorithm/Software\",\"LongDataName\"],\"optype\":\"binary\"}],\"enclose\":1}";
String query;
diff --git a/src/tethys/deployment/DeploymentHandler.java b/src/tethys/deployment/DeploymentHandler.java
index 0c435fc0..8d82ac48 100644
--- a/src/tethys/deployment/DeploymentHandler.java
+++ b/src/tethys/deployment/DeploymentHandler.java
@@ -73,6 +73,7 @@ import nilus.UnknownSensor;
import pamMaths.PamVector;
import pamMaths.STD;
import tethys.Collection;
+import tethys.CollectionHandler;
import tethys.TethysControl;
import tethys.TethysLocationFuncs;
import tethys.TethysState;
@@ -83,6 +84,7 @@ import tethys.TethysState.StateType;
import tethys.dbxml.DBXMLConnect;
import tethys.dbxml.TethysException;
import tethys.deployment.swing.DeploymentWizard;
+import tethys.deployment.swing.EffortProblemDialog;
import tethys.deployment.swing.RecordingGapDialog;
import tethys.niluswraps.PDeployment;
import tethys.output.TethysExportParams;
@@ -98,16 +100,9 @@ import tethys.swing.DeploymentTableObserver;
* @author dg50
*
*/
-public class DeploymentHandler implements TethysStateObserver, DeploymentTableObserver {
+public class DeploymentHandler extends CollectionHandler implements TethysStateObserver, DeploymentTableObserver {
- private TethysControl tethysControl;
-
- /**
- * @return the tethysControl
- */
- public TethysControl getTethysControl() {
- return tethysControl;
- }
+// private TethysControl tethysControl;
private EffortFunctions effortFunctions;
@@ -119,8 +114,11 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
private DeploymentExportOpts deploymentExportOptions = new DeploymentExportOpts();
+ public static final String helpPoint = "utilities.tethys.docs.deployments";
+
public DeploymentHandler(TethysControl tethysControl) {
- super();
+
+ super(tethysControl, Collection.Deployments);
this.tethysControl = tethysControl;
@@ -368,8 +366,39 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
public void createPamguardOverview() {
deploymentOverview = effortFunctions.makeRecordingOverview();
+
+ checkDeploymentOverview(deploymentOverview);
+
updateProjectDeployments();
matchPamguard2Tethys(deploymentOverview, projectDeployments);
+
+ tethysControl.sendStateUpdate(new TethysState(StateType.NEWPAMGUARDSELECTION));
+ }
+
+ /**
+ * Check the deployment overview for consistency.
+ * Take the raw audio information and the binary information and check they are similar.
+ * if not, ask the user what to do.
+ * @param deploymentOverview
+ */
+ private void checkDeploymentOverview(DeploymentOverview overview) {
+ RecordingList rawList = overview.getRawDataList();
+ RecordingList binList = overview.getBinaryDataList();
+ if (rawList == null || binList == null) {
+ return; // nothing to do
+ }
+ double similarity = rawList.getSimilarity(binList);
+ if (similarity > 0.95) {
+ return;
+ }
+ /*
+ * if we get here, it seems like the two lists are very different, so
+ * show a dialog to ask the user what to do.
+ */
+ RecordingList selList = EffortProblemDialog.showDialog(tethysControl.getGuiFrame(), overview);
+ if (selList != null) {
+ tethysControl.getTethysExportParams().setEffortSourceName(selList.getSourceName());
+ }
}
/**
@@ -381,22 +410,22 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
if (exportOptions != null) {
this.deploymentExportOptions = exportOptions;
deploymentOverview = getDeploymentOverview();
- ArrayList allPeriods = deploymentOverview.getRecordingPeriods();
+ RecordingList allPeriods = deploymentOverview.getMasterList(getTethysControl());
exportDeployments(allPeriods);
}
}
/**
* Export deployments docs. Playing with a couple of different ways of doing this.
- * @param selectedDeployments
+ * @param allPeriods
*/
- public void exportDeployments(ArrayList selectedDeployments) {
+ public void exportDeployments(RecordingList allPeriods) {
TethysReporter.getTethysReporter().clear();
if (deploymentExportOptions.separateDeployments) {
- exportSeparateDeployments(selectedDeployments);
+ exportSeparateDeployments(allPeriods);
}
else {
- exportOneDeploymnet(selectedDeployments);
+ exportOneDeploymnet(allPeriods);
}
TethysReporter.getTethysReporter().showReport(tethysControl.getGuiFrame(), true);
}
@@ -404,7 +433,7 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
/**
* Make one big deployment document with all the recording periods in it.
*/
- private void exportOneDeploymnet(ArrayList selectedDeployments) {
+ private void exportOneDeploymnet(RecordingList recordingList) {
// do the lot, whatever ...
Float sampleRate = null;
AcquisitionControl daq = (AcquisitionControl) PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
@@ -414,10 +443,9 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
sampleRate = daqParams.sampleRate;
}
- selectedDeployments = getDeploymentOverview().getRecordingPeriods();
int freeId = getTethysControl().getDeploymentHandler().getFirstFreeDeploymentId();
- RecordingPeriod onePeriod = new RecordingPeriod(selectedDeployments.get(0).getRecordStart(),
- selectedDeployments.get(selectedDeployments.size()-1).getRecordStop());
+ RecordingPeriod onePeriod = new RecordingPeriod(recordingList.getStart(),
+ recordingList.getEnd());
TethysExportParams exportParams = tethysControl.getTethysExportParams();
String id = String.format("%s_%s", exportParams.getDatasetName(), "all");
Deployment deployment = createDeploymentDocument(freeId, onePeriod, id);
@@ -425,7 +453,8 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
Deployment globalMeta = getTethysControl().getGlobalDeplopymentData();
deployment.setCruise(globalMeta.getCruise());
deployment.setSite(globalMeta.getSite());
- if (selectedDeployments.size() > 1) {
+ ArrayList effortPeriods = recordingList.getEffortPeriods();
+ if (recordingList.size() > 1) {
// // now need to remove the sampling details - don't though, add invalid periods instead.
// SamplingDetails samplingDetails = deployment.getSamplingDetails();
// samplingDetails.getChannel().clear();
@@ -440,9 +469,9 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
deployment.setQualityAssurance(qa = new AcousticDataQAType());
}
List qualityList = qa.getQuality();
- for (int i = 1; i < selectedDeployments.size(); i++) {
- long end = selectedDeployments.get(i-1).getRecordStop();
- long start = selectedDeployments.get(i).getRecordStart();
+ for (int i = 1; i < recordingList.size(); i++) {
+ long end = effortPeriods.get(i-1).getRecordStop();
+ long start = effortPeriods.get(i).getRecordStart();
Quality q = new Quality();
q.setStart(TethysTimeFuncs.xmlGregCalFromMillis(end));
q.setEnd(TethysTimeFuncs.xmlGregCalFromMillis(start));
@@ -479,14 +508,15 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
/**
* Make a separate deployment document for every recording period.
*/
- private void exportSeparateDeployments(ArrayList selectedDeployments) {
+ private void exportSeparateDeployments(RecordingList recordingList) {
int freeId = getTethysControl().getDeploymentHandler().getFirstFreeDeploymentId();
// fill in a few things from here
Deployment globalMeta = getTethysControl().getGlobalDeplopymentData();
TethysExportParams exportParams = tethysControl.getTethysExportParams();
- for (int i = 0; i < selectedDeployments.size(); i++) {
- RecordingPeriod recordPeriod = selectedDeployments.get(i);
+ ArrayList effortPeriods = recordingList.getEffortPeriods();
+ for (int i = 0; i < recordingList.size(); i++) {
+ RecordingPeriod recordPeriod = effortPeriods.get(i);
PDeployment exDeploymnet = recordPeriod.getMatchedTethysDeployment();
Deployment deployment = null;
String id = String.format("%s_%d", exportParams.getDatasetName(), i);
@@ -532,8 +562,9 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
if (deployments == null || deploymentOverview == null) {
return;
}
- ArrayList recordingPeriods = deploymentOverview.getRecordingPeriods();
- for (RecordingPeriod aPeriod : recordingPeriods) {
+ RecordingList recordingList = deploymentOverview.getMasterList(getTethysControl());
+ ArrayList effortPeriods = recordingList.getEffortPeriods();
+ for (RecordingPeriod aPeriod : effortPeriods) {
PDeployment closestDeployment = findClosestDeployment(aPeriod, deployments);
aPeriod.setMatchedTethysDeployment(closestDeployment);
if (closestDeployment != null) {
@@ -592,7 +623,8 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
if (deploymentOverview == null) {
return matched;
}
- for (RecordingPeriod period : deploymentOverview.getRecordingPeriods()) {
+ ArrayList effortPeriods = deploymentOverview.getMasterList(getTethysControl()).getEffortPeriods();
+ for (RecordingPeriod period : effortPeriods) {
PDeployment deployment = period.getMatchedTethysDeployment();
if (deployment != null) {
if (matched.contains(deployment) == false) {
@@ -1230,7 +1262,8 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
}
regimens.add(regimen);
- DutyCycleInfo dutyCycleInf = deploymentOverview.getDutyCycleInfo();
+ RecordingList recordingList = deploymentOverview.getMasterList(getTethysControl());
+ DutyCycleInfo dutyCycleInf = recordingList.assessDutyCycle();
boolean isDS = dutyCycleInf != null && dutyCycleInf.isDutyCycled;
if (isDS) {
DutyCycle dutyCycle = new DutyCycle();
@@ -1307,4 +1340,9 @@ public class DeploymentHandler implements TethysStateObserver, DeploymentTableOb
return deploymentExportOptions;
}
+ @Override
+ public String getHelpPoint() {
+ return helpPoint;
+ }
+
}
diff --git a/src/tethys/deployment/DeploymentOverview.java b/src/tethys/deployment/DeploymentOverview.java
index f296df8e..3f39c653 100644
--- a/src/tethys/deployment/DeploymentOverview.java
+++ b/src/tethys/deployment/DeploymentOverview.java
@@ -1,16 +1,6 @@
package tethys.deployment;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.ListIterator;
-
-import Acquisition.AcquisitionControl;
-import Acquisition.AcquisitionParameters;
-import Acquisition.DaqStatusDataUnit;
-import PamController.PamControlledUnit;
-import PamController.PamController;
-import PamguardMVC.PamDataBlock;
+import tethys.TethysControl;
/**
* Class to give a general overview of all the effort in PAMGuard which will form the
@@ -22,59 +12,83 @@ import PamguardMVC.PamDataBlock;
*/
public class DeploymentOverview {
- private ArrayList recordingPeriods = new ArrayList<>();
+ private RecordingList rawDataList;
- private DutyCycleInfo dutyCycleInfo;
+ private RecordingList binaryDataList;
+
+// private DutyCycleInfo dutyCycleInfo;
- public DeploymentOverview(DutyCycleInfo dutyCycleInfo) {
- super();
- this.dutyCycleInfo = dutyCycleInfo;
- }
+// public DeploymentOverview(DutyCycleInfo dutyCycleInfo) {
+// super();
+// this.dutyCycleInfo = dutyCycleInfo;
+// }
- public DeploymentOverview(DutyCycleInfo dutyCycleInfo, ArrayList tempPeriods) {
- this.dutyCycleInfo = dutyCycleInfo;
- this.recordingPeriods = tempPeriods;
- }
-
-
- public void addRecordingPeriod(long start, long stop) {
- addRecordingPeriod(new RecordingPeriod(start, stop));
+ public DeploymentOverview(DutyCycleInfo dutyCycleInfo, RecordingList rawDataList, RecordingList binaryDataList) {
+// this.dutyCycleInfo = dutyCycleInfo;
+ this.rawDataList = rawDataList;
+ this.binaryDataList = binaryDataList;
}
- private void addRecordingPeriod(RecordingPeriod recordingPeriod) {
- recordingPeriods.add(recordingPeriod);
+ /**
+ * @return the rawDataList
+ */
+ public RecordingList getRawDataList() {
+ return rawDataList;
}
- public ArrayList getRecordingPeriods() {
- return recordingPeriods;
+ /**
+ * @return the binaryDataList
+ */
+ public RecordingList getBinaryDataList() {
+ return binaryDataList;
}
- public DutyCycleInfo getDutyCycleInfo() {
- return dutyCycleInfo;
+// /**
+// * @return the dutyCycleInfo
+// */
+// public DutyCycleInfo getDutyCycleInfo() {
+// return dutyCycleInfo;
+// }
+
+ public RecordingList getMasterList(TethysControl tethysControl) {
+ return getMasterList(tethysControl.getTethysExportParams().getEffortSourceName());
+ }
+
+ public RecordingList getMasterList(String effortSourceName) {
+ if (effortSourceName == null) {
+ return getLongestList();
+ }
+ if (binaryDataList != null & binaryDataList.getSourceName().equals(effortSourceName)) {
+ return binaryDataList;
+ }
+ if (rawDataList != null & rawDataList.getSourceName().equals(effortSourceName)) {
+ return rawDataList;
+ }
+ return getLongestList();
}
/**
- * Get the start time of the first recording
+ * Get the recording list with the greatest duration (start to end)
+ * not looking at coverage between those times.
* @return
*/
- public Long getFirstStart() {
- if (recordingPeriods.size() > 0) {
- return recordingPeriods.get(0).getRecordStart();
+ public RecordingList getLongestList() {
+ if (binaryDataList == null) {
+ return rawDataList;
}
- return null;
- }
-
- /**
- * Get the end time of the last recording
- * @return
- */
- public Long getLastEnd() {
- if (recordingPeriods.size() > 0) {
- return recordingPeriods.get(recordingPeriods.size()-1).getRecordStop();
+ if (rawDataList == null) {
+ return binaryDataList;
+ }
+ long lRaw = rawDataList.duration();
+ long lBin = binaryDataList.duration();
+
+ if (lRaw > lBin) {
+ return rawDataList;
+ }
+ else {
+ return binaryDataList;
}
- return null;
}
-
-
+
}
diff --git a/src/tethys/deployment/EffortFunctions.java b/src/tethys/deployment/EffortFunctions.java
index 2fd8f383..b7e5b260 100644
--- a/src/tethys/deployment/EffortFunctions.java
+++ b/src/tethys/deployment/EffortFunctions.java
@@ -41,36 +41,40 @@ public class EffortFunctions {
this.tethysControl = tethysControl;
}
- private DeploymentOverview createOverview(RecordingList tempPeriods) {
-
- DutyCycleInfo dutyCycleinfo = assessDutyCycle(tempPeriods);
- if (dutyCycleinfo == null) {
- return null;
- }
-
- // if it's duty cycles, then we only want a single entry.
- RecordingList deploymentPeriods;
- if (dutyCycleinfo.isDutyCycled == false) {
- deploymentPeriods = tempPeriods;
- }
- else {
- deploymentPeriods = new RecordingList();
- deploymentPeriods.add(new RecordingPeriod(tempPeriods.get(0).getRecordStart(), tempPeriods.get(tempPeriods.size()-1).getRecordStop()));
- }
- /*
- * do another sort of the deploymentPeriods. The start stops were in the order they went into the
- * database in the hope that pairs were the right way round. Now check all data are/
- */
- Collections.sort(deploymentPeriods, new Comparator() {
- @Override
- public int compare(RecordingPeriod o1, RecordingPeriod o2) {
- return (int) (o1.getRecordStart()-o2.getRecordStart());
- }
- });
-
- DeploymentOverview deploymentOverview = new DeploymentOverview(dutyCycleinfo, deploymentPeriods);
- return deploymentOverview;
- }
+// private DeploymentOverview createOverview(RecordingList tempPeriods) {
+//
+// tempPeriods.sort();
+//
+// DutyCycleInfo dutyCycleinfo = assessDutyCycle(tempPeriods);
+// if (dutyCycleinfo == null) {
+// return null;
+// }
+//
+//
+// // if it's duty cycles, then we only want a single entry.
+// RecordingList deploymentPeriods;
+// if (dutyCycleinfo.isDutyCycled == false) {
+// deploymentPeriods = tempPeriods;
+// }
+// else {
+// deploymentPeriods = new RecordingList(tempPeriods.getSourceName());
+// deploymentPeriods.add(new RecordingPeriod(tempPeriods.get(0).getRecordStart(), tempPeriods.get(tempPeriods.size()-1).getRecordStop()));
+// }
+// /*
+// * do another sort of the deploymentPeriods. The start stops were in the order they went into the
+// * database in the hope that pairs were the right way round. Now check all data are/
+// */
+// deploymentPeriods.sort();
+//// Collections.sort(deploymentPeriods, new Comparator() {
+//// @Override
+//// public int compare(RecordingPeriod o1, RecordingPeriod o2) {
+//// return (int) (o1.getRecordStart()-o2.getRecordStart());
+//// }
+//// });
+//
+// DeploymentOverview deploymentOverview = new DeploymentOverview(dutyCycleinfo, deploymentPeriods);
+// return deploymentOverview;
+// }
public DeploymentOverview makeRecordingOverview() {
@@ -79,13 +83,18 @@ public class EffortFunctions {
RecordingList binaryPeriods = listBinaryFiles();
- long l1 = listDuration(recordingPeriods);
- long l2 = listDuration(binaryPeriods);
- if (listDuration(binaryPeriods) > listDuration(recordingPeriods)) {
- recordingPeriods = binaryPeriods;
- }
+ // see what the similarity is between them
+// double sim = recordingPeriods.getSimilarity(binaryPeriods);
+// double testSim = recordingPeriods.getSimilarity(recordingPeriods);
- DeploymentOverview deploymentOverview = createOverview(recordingPeriods);
+// long l1 = listDuration(recordingPeriods);
+// long l2 = listDuration(binaryPeriods);
+// if (listDuration(binaryPeriods) > listDuration(recordingPeriods)) {
+// recordingPeriods = binaryPeriods;
+// }
+//
+// DeploymentOverview deploymentOverview = createOverview(recordingPeriods);
+ DeploymentOverview deploymentOverview = new DeploymentOverview(null, recordingPeriods, binaryPeriods);
return deploymentOverview;
}
@@ -128,7 +137,8 @@ public class EffortFunctions {
}
}
}
- bestList = mergeRecordings(bestList);
+ DeploymentExportOpts exportOptions = tethysControl.getDeploymentHandler().getDeploymentExportOptions();
+ bestList.mergeRecordingPeriods(exportOptions.maxRecordingGapSeconds*1000);
return bestList;
}
@@ -138,7 +148,7 @@ public class EffortFunctions {
if (mapPoints == null) {
return null;
}
- RecordingList periods = new RecordingList();
+ RecordingList periods = new RecordingList(dataMap.getDataMapName());
for (OfflineDataMapPoint mapPoint : mapPoints) {
periods.add(new RecordingPeriod(mapPoint.getStartTime(), mapPoint.getEndTime()));
}
@@ -219,117 +229,60 @@ public class EffortFunctions {
// PamCalendar.formatDBDateTime(aP.getRecordStop()));
// }
- tempPeriods = mergeRecordings(tempPeriods);
-
- return tempPeriods;
- }
-
- /**
- * Merge close recordings and discard ones that are too short.
- * @param tempPeriods all recording periods, may be from consecutive files.
- * @return merged list.
- */
- private RecordingList mergeRecordings(RecordingList tempPeriods) {
- // now go through those and merge into longer periods where there is no gap between files.
- if (tempPeriods == null) {
- return null;
- }
-
+ tempPeriods.sort();
DeploymentExportOpts exportOptions = tethysControl.getDeploymentHandler().getDeploymentExportOptions();
-
- ListIterator iterator = tempPeriods.listIterator();
- RecordingPeriod prevPeriod = null;
- while (iterator.hasNext()) {
- RecordingPeriod nextPeriod = iterator.next();
- long nextDur = nextPeriod.getRecordStop()-nextPeriod.getRecordStart();
- if (nextDur == 0) {
- continue;
- }
- if (prevPeriod != null) {
- long gap = nextPeriod.getRecordStart() - prevPeriod.getRecordStop();
- long prevDur = prevPeriod.getRecordStop()-prevPeriod.getRecordStart();
- if (gap < exportOptions.maxRecordingGapSeconds*1000) {
- // ignoring up to 3s gap or a sample error < 2%.Dunno if this is sensible or not.
- prevPeriod.setRecordStop(nextPeriod.getRecordStop());
- iterator.remove();
- nextPeriod = prevPeriod;
- }
- }
- prevPeriod = nextPeriod;
- }
- // now remove ones which are too short even after merging.
- iterator = tempPeriods.listIterator();
- while (iterator.hasNext()) {
- RecordingPeriod nextPeriod = iterator.next();
- long duration = nextPeriod.getDuration();
- if (duration < exportOptions.minRecordingLengthSeconds*1000L) {
- iterator.remove();
- }
- }
+ tempPeriods.mergeRecordingPeriods(exportOptions.maxRecordingGapSeconds*1000);
return tempPeriods;
}
- /**
- * Work out whether or not the data are evenly duty cycled by testing the
- * distributions of on and off times.
- * @param tempPeriods
- * @return
- */
- private DutyCycleInfo assessDutyCycle(RecordingList tempPeriods) {
- if (tempPeriods == null) {
- return null;
- }
- int n = tempPeriods.size();
- if (n < 2) {
- return new DutyCycleInfo(false, 0,0,n);
- }
- double[] ons = new double[n-1]; // ignore the last one since it may be artificially shortened which is OK
- double[] gaps = new double[n-1];
- for (int i = 0; i < n-1; i++) {
- ons[i] = tempPeriods.get(i).getDuration()/1000.;
- gaps[i] = (tempPeriods.get(i+1).getRecordStart()-tempPeriods.get(i).getRecordStop())/1000.;
- }
- /* now look at how consistent those values are
- * But some data gets messed by small gaps, so want to
- * remove outliers and concentrate on say 80% of the data.
- */
- ons = getDistributionCentre(ons, 80);
- gaps = getDistributionCentre(gaps, 80);
- Arrays.sort(gaps);
+// /**
+// * Merge close recordings and discard ones that are too short.
+// * @param tempPeriods all recording periods, may be from consecutive files.
+// * @return merged list.
+// */
+// private RecordingList mergeRecordings(RecordingList tempPeriods) {
+// // now go through those and merge into longer periods where there is no gap between files.
+// if (tempPeriods == null) {
+// return null;
+// }
+//
+// DeploymentExportOpts exportOptions = tethysControl.getDeploymentHandler().getDeploymentExportOptions();
+//
+// ListIterator iterator = tempPeriods.listIterator();
+// RecordingPeriod prevPeriod = null;
+// while (iterator.hasNext()) {
+// RecordingPeriod nextPeriod = iterator.next();
+// long nextDur = nextPeriod.getRecordStop()-nextPeriod.getRecordStart();
+// if (nextDur == 0) {
+// continue;
+// }
+// if (prevPeriod != null) {
+// long gap = nextPeriod.getRecordStart() - prevPeriod.getRecordStop();
+// long prevDur = prevPeriod.getRecordStop()-prevPeriod.getRecordStart();
+// if (gap < exportOptions.maxRecordingGapSeconds*1000) {
+// // ignoring up to 3s gap or a sample error < 2%.Dunno if this is sensible or not.
+// prevPeriod.setRecordStop(nextPeriod.getRecordStop());
+// iterator.remove();
+// nextPeriod = prevPeriod;
+// }
+// }
+// prevPeriod = nextPeriod;
+// }
+// // now remove ones which are too short even after merging.
+// iterator = tempPeriods.listIterator();
+// while (iterator.hasNext()) {
+// RecordingPeriod nextPeriod = iterator.next();
+// long duration = nextPeriod.getDuration();
+// if (duration < exportOptions.minRecordingLengthSeconds*1000L) {
+// iterator.remove();
+// }
+// }
+//
+// return tempPeriods;
+// }
- STD std = new STD();
- double onsMean = std.getMean(ons);
- double onsSTD = std.getSTD(ons);
- double gapsMean = std.getMean(gaps);
- double gapsSTD = std.getSTD(gaps);
- boolean dutyCycle = onsSTD/onsMean < .05 && gapsSTD/gapsMean < 0.05;
- DutyCycleInfo cycleInfo = new DutyCycleInfo(dutyCycle, onsMean, gapsMean, tempPeriods.size());
- return cycleInfo;
- }
-
- /**
- * Get the central part of a distribution without any outliers so
- * that we can get a better assessment of duty cycle.
- * @param data unsorted distribution data.
- * @param percent percentage to include (half this removed from top and bottom)
- * @return
- */
- private double[] getDistributionCentre(double[] data, double percent) {
- if (data == null) {
- return null;
- }
- Arrays.sort(data);
- int nRem = (int) Math.round(data.length * (100-percent)/200);
- int newLen = data.length-nRem*2;
- double[] subdata = Arrays.copyOfRange(data, nRem, data.length-2*nRem);
- if (subdata.length < 2) {
- return data;
- }
- return subdata;
- }
-
/**
* Get data times from any other datamap, since this will generally match the acquisition anyway
@@ -360,16 +313,17 @@ public class EffortFunctions {
return null;
}
// get the times out of it.
- RecordingList recPeriods = new RecordingList();
+ RecordingList recPeriods = new RecordingList(bestMap.getDataMapName());
List mapPoints = bestMap.getMapPoints();
for (OfflineDataMapPoint mapPoint : mapPoints) {
recPeriods.add(new RecordingPeriod(mapPoint.getStartTime(), mapPoint.getEndTime()));
+ recPeriods.add(mapPoint.getStartTime(), mapPoint.getEndTime());
}
return recPeriods;
}
private RecordingList extractTimesFromStatus(ArrayList allStatusData) {
- RecordingList tempPeriods = new RecordingList();
+ RecordingList tempPeriods = new RecordingList("Data acquisition status");
long dataStart = Long.MAX_VALUE;
long dataEnd = Long.MIN_VALUE;
Long lastStart = null;
diff --git a/src/tethys/deployment/RecordingList.java b/src/tethys/deployment/RecordingList.java
index 34b41c1d..038c0e69 100644
--- a/src/tethys/deployment/RecordingList.java
+++ b/src/tethys/deployment/RecordingList.java
@@ -1,12 +1,43 @@
package tethys.deployment;
+import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
+import java.util.Iterator;
-public class RecordingList extends ArrayList {
+import PamUtils.PamCalendar;
+import pamMaths.STD;
+
+/**
+ * Information about periods of effort that might come from either the raw data recordings or
+ * an analysis of binary data maps.
+ * @author dg50
+ *
+ */
+public class RecordingList implements Serializable {
private static final long serialVersionUID = 1L;
+
+ private ArrayList effortPeriods = new ArrayList();
+
+ /**
+ * Name / source of this list.
+ */
+ private String sourceName;
+
+ /**
+ * @param sourceName
+ */
+ public RecordingList(String sourceName) {
+ this.sourceName = sourceName;
+ }
+
+ public RecordingList(String sourceName, ArrayList selectedDeployments) {
+ this.sourceName = sourceName;
+ this.effortPeriods = selectedDeployments;
+ }
/**
* Get the duration of the recording periods from start to end.
@@ -21,27 +52,27 @@ public class RecordingList extends ArrayList {
* @return
*/
public long getStart() {
- if (size() == 0) {
+ if (effortPeriods.size() == 0) {
return 0;
}
- return get(0).getRecordStart();
+ return effortPeriods.get(0).getRecordStart();
}
/**
* get the end of the last in the list.
*/
public long getEnd() {
- if (size() == 0) {
+ if (effortPeriods.size() == 0) {
return 0;
}
- return get(size()-1).getRecordStop();
+ return effortPeriods.get(effortPeriods.size()-1).getRecordStop();
}
/**
* Sort the list in ascending order.
*/
public void sort() {
- Collections.sort(this, new Comparator() {
+ Collections.sort(effortPeriods, new Comparator() {
@Override
public int compare(RecordingPeriod o1, RecordingPeriod o2) {
@@ -49,4 +80,172 @@ public class RecordingList extends ArrayList {
}
});
}
+
+ /**
+ * Get the coverage as a fraction. This is the sum of the individual periods divided
+ * by the start to end times
+ * @return
+ */
+ public double getCoverage() {
+ long cov = 0;
+ long durTot = 0;
+ if (effortPeriods.size() == 0) {
+ return 0;
+ }
+ Iterator it = effortPeriods.iterator();
+ while (it.hasNext()) {
+ RecordingPeriod rp = it.next();
+ cov += rp.getDuration();
+ }
+ durTot = getEnd()-getStart();
+ return (double) cov / (double) durTot;
+ }
+
+ /**
+ * Merge recording periods, with a max gap between periods in milliseconds.
+ * @param maxGap
+ * @return the number of periods removed.
+ */
+ public int mergeRecordingPeriods(long maxGap) {
+ if (effortPeriods.size() < 2) {
+ return 0;
+ }
+ Iterator it = effortPeriods.iterator();
+ RecordingPeriod prev = it.next();
+ int removed = 0;
+ while (it.hasNext()) {
+ RecordingPeriod curr = it.next();
+ if (curr.getRecordStart() - prev.getRecordStop() <= maxGap) {
+ prev.setRecordStop(curr.getRecordStop());
+ it.remove();
+ removed++;
+ }
+ else {
+ prev = curr;
+ }
+ }
+ return removed;
+ }
+
+ /**
+ * Work out whether or not the data are evenly duty cycled by testing the
+ * distributions of on and off times.
+ * @param tempPeriods
+ * @return
+ */
+ public DutyCycleInfo assessDutyCycle() {
+ if (effortPeriods == null) {
+ return null;
+ }
+ int n = effortPeriods.size();
+ if (n < 2) {
+ return new DutyCycleInfo(false, 0,0,n);
+ }
+ double[] ons = new double[n-1]; // ignore the last one since it may be artificially shortened which is OK
+ double[] gaps = new double[n-1];
+ for (int i = 0; i < n-1; i++) {
+ ons[i] = effortPeriods.get(i).getDuration()/1000.;
+ gaps[i] = (effortPeriods.get(i+1).getRecordStart()-effortPeriods.get(i).getRecordStop())/1000.;
+ }
+ /* now look at how consistent those values are
+ * But some data gets messed by small gaps, so want to
+ * remove outliers and concentrate on say 80% of the data.
+ */
+ ons = getDistributionCentre(ons, 80);
+ gaps = getDistributionCentre(gaps, 80);
+ Arrays.sort(gaps);
+
+ STD std = new STD();
+ double onsMean = std.getMean(ons);
+ double onsSTD = std.getSTD(ons);
+ double gapsMean = std.getMean(gaps);
+ double gapsSTD = std.getSTD(gaps);
+ boolean dutyCycle = onsSTD/onsMean < .05 && gapsSTD/gapsMean < 0.05;
+ DutyCycleInfo cycleInfo = new DutyCycleInfo(dutyCycle, onsMean, gapsMean, effortPeriods.size());
+ return cycleInfo;
+ }
+ /**
+ * Get the central part of a distribution without any outliers so
+ * that we can get a better assessment of duty cycle.
+ * @param data unsorted distribution data.
+ * @param percent percentage to include (half this removed from top and bottom)
+ * @return
+ */
+ private double[] getDistributionCentre(double[] data, double percent) {
+ if (data == null) {
+ return null;
+ }
+ Arrays.sort(data);
+ int nRem = (int) Math.round(data.length * (100-percent)/200);
+ int newLen = data.length-nRem*2;
+ double[] subdata = Arrays.copyOfRange(data, nRem, data.length-2*nRem);
+ if (subdata.length < 2) {
+ return data;
+ }
+ return subdata;
+ }
+
+ /**
+ * @return the sourceName
+ */
+ public String getSourceName() {
+ return sourceName;
+ }
+
+ @Override
+ public String toString() {
+ if (effortPeriods.size() == 0) {
+ return "Empty recording list";
+ }
+ String str = String.format("%s: %s to %s, %3.1f%% coverage", getSourceName(),
+ PamCalendar.formatDBDateTime(getStart()),
+ PamCalendar.formatDBDateTime(getEnd()), getCoverage()*100);
+ return str;
+ }
+
+ /**
+ * Get similarity to another recording list. 1 = identical, 0 means not even overlapping.
+ * @param other other recording list.
+ * @return measure of similarity.
+ */
+ public double getSimilarity(RecordingList other) {
+ double sim1 = (double) other.duration() / (double) this.duration();
+ if (sim1 > 1) {
+ sim1 = 1./sim1;
+ }
+ long overlap = Math.min(other.getEnd(), this.getEnd()) - Math.max(other.getStart(), this.getStart());
+ overlap = Math.max(0, overlap);
+ long longest = Math.max(other.duration(), this.duration());
+ double sim2 = (double) overlap / (double) longest;
+
+ return Math.min(sim1, sim2);
+ }
+
+ /**
+ * Add a recording period to the list.
+ * @param recordingPeriod
+ */
+ public void add(RecordingPeriod recordingPeriod) {
+ effortPeriods.add(recordingPeriod);
+ }
+
+ /**
+ * Add a recording period to the list.
+ * @param startTime
+ * @param endTime
+ */
+ public void add(long startTime, long endTime) {
+ add (new RecordingPeriod(startTime, endTime));
+ }
+
+ public int size() {
+ return effortPeriods.size();
+ }
+
+ /**
+ * @return the effortPeriods
+ */
+ public ArrayList getEffortPeriods() {
+ return effortPeriods;
+ }
}
diff --git a/src/tethys/deployment/RecordingPeriod.java b/src/tethys/deployment/RecordingPeriod.java
index ad010827..ae985347 100644
--- a/src/tethys/deployment/RecordingPeriod.java
+++ b/src/tethys/deployment/RecordingPeriod.java
@@ -1,5 +1,6 @@
package tethys.deployment;
+import PamUtils.PamCalendar;
import tethys.niluswraps.PDeployment;
public class RecordingPeriod {
@@ -71,5 +72,11 @@ public class RecordingPeriod {
selected = !selected;
return selected;
}
+
+ @Override
+ public String toString() {
+ return String.format("%s to %s, %s", PamCalendar.formatDBDateTime(recordStart),
+ PamCalendar.formatDBDateTime(recordStop), PamCalendar.formatDuration(getDuration()));
+ }
}
diff --git a/src/tethys/deployment/swing/EffortProblemDialog.java b/src/tethys/deployment/swing/EffortProblemDialog.java
new file mode 100644
index 00000000..5fafa71b
--- /dev/null
+++ b/src/tethys/deployment/swing/EffortProblemDialog.java
@@ -0,0 +1,163 @@
+package tethys.deployment.swing;
+
+import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.GridLayout;
+import java.awt.Window;
+
+import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.border.TitledBorder;
+
+import PamUtils.PamCalendar;
+import PamView.dialog.PamDialog;
+import PamView.dialog.PamGridBagContraints;
+import tethys.deployment.DeploymentOverview;
+import tethys.deployment.RecordingList;
+
+/**
+ * Handle problems when binary and raw effort don't add up
+ * @author dg50
+ *
+ */
+public class EffortProblemDialog extends PamDialog {
+
+ private JRadioButton useRaw, useBinary, useNeither;
+
+ private JLabel generalInfo;
+
+ private InfoSet[] infoSets = new InfoSet[2];
+
+ private RecordingList chosenList;
+
+ private DeploymentOverview deploymentOverview;
+
+ private static EffortProblemDialog singleInstance;
+
+ private static final String[] setNames = {"Raw data", "Binary data"};
+
+ private EffortProblemDialog(Window parentFrame) {
+ super(parentFrame, "Deployment Effort", false);
+ JPanel mainPanel = new JPanel();
+ mainPanel.setLayout(new BorderLayout());
+ mainPanel.setBorder(new TitledBorder("Effort information"));
+ String info = "There is a mismatch between the time period covered by the raw
"
+ + "data recordings and the time covered in the binary data.
"
+ + "Select the one you wish to use, or Cancel and sort out your data
"
+ + "prior to restarting the Tethys export process";
+ generalInfo = new JLabel(info);
+// generalInfo.setBorder(new TitledBorder("General"));
+ mainPanel.add(generalInfo, BorderLayout.NORTH);
+ JPanel botPanel = new JPanel(new GridLayout(2, 1));
+ mainPanel.add(botPanel, BorderLayout.CENTER);
+ ButtonGroup bg = new ButtonGroup();
+ for (int i = 0; i < 2; i++) {
+ GridBagConstraints c = new PamGridBagContraints();
+ JPanel subPanel = new JPanel(new GridBagLayout());
+ botPanel.add(subPanel);
+ infoSets[i] = new InfoSet(setNames[i]);
+ c.gridwidth = 2;
+ subPanel.add(infoSets[i].name, c);
+ c.gridx += c.gridwidth;
+ subPanel.add(infoSets[i].select, c);
+ c.gridx = 0;
+ c.gridy++;
+ c.gridwidth = 1;
+ subPanel.add(new JLabel("Start: ", JLabel.RIGHT), c);
+ c.gridx++;
+ subPanel.add(infoSets[i].start, c);
+ c.gridx++;
+ subPanel.add(new JLabel("End: ", JLabel.RIGHT), c);
+ c.gridx++;
+ subPanel.add(infoSets[i].end, c);
+ c.gridy++;
+ c.gridx = 0;
+ subPanel.add(new JLabel("Duration: ", JLabel.RIGHT), c);
+ c.gridx++;
+ subPanel.add(infoSets[i].duration, c);
+ c.gridx++;
+ subPanel.add(new JLabel("Coverage: ", JLabel.RIGHT), c);
+ c.gridx++;
+ subPanel.add(infoSets[i].occupancy, c);
+
+ bg.add(infoSets[i].select);
+ }
+
+ setDialogComponent(mainPanel);
+ setResizable(true);
+ }
+
+ public static RecordingList showDialog(Window parentFrame, DeploymentOverview deploymentOverview) {
+ singleInstance = new EffortProblemDialog(parentFrame);
+ singleInstance.setData(deploymentOverview);
+ singleInstance.setVisible(true);
+ return singleInstance.chosenList;
+ }
+
+ private void setData(DeploymentOverview deploymentOverview) {
+ this.deploymentOverview = deploymentOverview;
+ RecordingList rl;
+ for (int i = 0; i < 2; i++) {
+ if (i == 0) {
+ rl = deploymentOverview.getRawDataList();
+ }
+ else {
+ rl = deploymentOverview.getBinaryDataList();
+ }
+ infoSets[i].start.setText(PamCalendar.formatDBDateTime(rl.getStart()));
+ infoSets[i].end.setText(PamCalendar.formatDBDateTime(rl.getEnd()));
+ infoSets[i].duration.setText(PamCalendar.formatDuration(rl.duration()));
+ infoSets[i].occupancy.setText(String.format("%3.0f%%", rl.getCoverage()*100.));
+ }
+ invalidate();
+ pack();
+ }
+
+ @Override
+ public boolean getParams() {
+ if (infoSets[0].select.isSelected()) {
+ chosenList = deploymentOverview.getRawDataList();
+ return true;
+ }
+ if (infoSets[1].select.isSelected()) {
+ chosenList = deploymentOverview.getBinaryDataList();
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void cancelButtonPressed() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void restoreDefaultSettings() {
+ // TODO Auto-generated method stub
+
+ }
+
+ private class InfoSet {
+ JLabel name, start, end, duration, occupancy;
+ JCheckBox select;
+ /**
+ *
+ */
+ public InfoSet(String name) {
+ super();
+ this.name = new JLabel(name);
+ this.start = new JLabel(" ");
+ this.end = new JLabel(" ");
+ this.select = new JCheckBox("Select " + name);
+ duration = new JLabel(" ");
+ occupancy = new JLabel(" ");
+ }
+ }
+
+}
diff --git a/src/tethys/deployment/swing/ProjectInformationPanel.java b/src/tethys/deployment/swing/ProjectInformationPanel.java
index 1ced05b1..12a88a9a 100644
--- a/src/tethys/deployment/swing/ProjectInformationPanel.java
+++ b/src/tethys/deployment/swing/ProjectInformationPanel.java
@@ -23,6 +23,7 @@ import nilus.Deployment;
import tethys.TethysControl;
import tethys.swing.NewProjectDialog;
import tethys.swing.SelectProjectDialog;
+import tethys.tooltips.TethysTips;
/**
* Panel for entering project information
@@ -109,6 +110,12 @@ public class ProjectInformationPanel {
});
}
+ project.setToolTipText(TethysTips.findTip(Deployment.class, "Project"));
+ cruise.setToolTipText(TethysTips.findTip(Deployment.class, "Cruise"));
+ region.setToolTipText(TethysTips.findTip(Deployment.class, "Region"));
+ site.setToolTipText(TethysTips.findTip(Deployment.class, "Site"));
+
+
}
/**
diff --git a/src/tethys/deployment/swing/RecordingGapDialog.java b/src/tethys/deployment/swing/RecordingGapDialog.java
index 399eb3bc..9915a0e4 100644
--- a/src/tethys/deployment/swing/RecordingGapDialog.java
+++ b/src/tethys/deployment/swing/RecordingGapDialog.java
@@ -36,7 +36,7 @@ public class RecordingGapDialog extends PamDialog {
c.gridx++;
mainPanel.add(new JLabel(" seconds", JLabel.RIGHT), c);
- maxGap.setToolTipText("Maximum gap between recording periods. Periods with a gap less than this will be counted as one");
+ maxGap.setToolTipText("Maximum gap between recording periods. Sequential periods with a gap less than this will be counted as one");
minLength.setToolTipText("Minimum recording length. Recording sections shorter than this will be ignored");
setDialogComponent(mainPanel);
@@ -80,6 +80,7 @@ public class RecordingGapDialog extends PamDialog {
@Override
public void restoreDefaultSettings() {
DeploymentExportOpts defaults = new DeploymentExportOpts();
+ setParams(defaults);
}
}
diff --git a/src/tethys/detection/BinnedGranularityHandler.java b/src/tethys/detection/BinnedGranularityHandler.java
index db984b27..13b92d58 100644
--- a/src/tethys/detection/BinnedGranularityHandler.java
+++ b/src/tethys/detection/BinnedGranularityHandler.java
@@ -6,11 +6,16 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
+
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.XMLGregorianCalendar;
+
import java.util.Set;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
import nilus.Detection;
+import nilus.Detections;
import nilus.SpeciesIDType;
import tethys.TethysControl;
import tethys.TethysTimeFuncs;
@@ -54,6 +59,8 @@ public class BinnedGranularityHandler extends GranularityHandler {
public void prepare(long timeMillis) {
// long binStart = DetectionsHandler.roundDownBinStart(timeMillis, binDurationMillis);
// startBin(binStart);
+// startBin(timeMillis);
+ currentDetections.clear();
}
// private void startBin(long timeMillis) {
@@ -169,4 +176,9 @@ public class BinnedGranularityHandler extends GranularityHandler {
return closeBins(timeMillis);
}
+ @Override
+ protected boolean autoEffortFix(Detections detections, Detection det) {
+ return contractDetection(detections, det);
+ }
+
}
diff --git a/src/tethys/detection/CallGranularityHandler.java b/src/tethys/detection/CallGranularityHandler.java
index 4ff9a888..03397596 100644
--- a/src/tethys/detection/CallGranularityHandler.java
+++ b/src/tethys/detection/CallGranularityHandler.java
@@ -3,6 +3,7 @@ package tethys.detection;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
import nilus.Detection;
+import nilus.Detections;
import tethys.TethysControl;
import tethys.output.StreamExportParams;
import tethys.output.TethysExportParams;
@@ -37,4 +38,9 @@ public class CallGranularityHandler extends GranularityHandler {
return null;
}
+ @Override
+ protected boolean autoEffortFix(Detections detections, Detection det) {
+ return expandEffort(detections, det);
+ }
+
}
diff --git a/src/tethys/detection/DetectionExportProgress.java b/src/tethys/detection/DetectionExportProgress.java
index abfa74b8..24a982a5 100644
--- a/src/tethys/detection/DetectionExportProgress.java
+++ b/src/tethys/detection/DetectionExportProgress.java
@@ -6,10 +6,11 @@ import tethys.niluswraps.PDeployment;
public class DetectionExportProgress {
public static final int STATE_GATHERING = 1;
- public static final int STATE_CANCELED = 2;
- public static final int STATE_COMPLETE = 3;
- public static final int STATE_WRITING = 4;
- public static final int STATE_COUNTING = 5;
+ public static final int STATE_COUNTING = 2;
+ public static final int STATE_WRITING = 3;
+ public static final int STATE_CANCELED = 4;
+ public static final int STATE_COMPLETE = 5;
+
public PDeployment currentDeployment;
public Detections currentDetections;
public long lastUnitTime;
@@ -17,12 +18,18 @@ public class DetectionExportProgress {
public int exportCount;
public int skipCount;
public int state;
+ public int totalDeployments, deploymentsDone;
+ public int nMapPoints;
+ public int doneMapPoints;
- public DetectionExportProgress(PDeployment currentDeployment, Detections currentDetections, long lastUnitTime,
+ public DetectionExportProgress(PDeployment currentDeployment, Detections currentDetections, int nMapPoints, int doneMapPoints,
+ long lastUnitTime,
long totalUnits, int exportCount, int skipCount, int state) {
super();
this.currentDeployment = currentDeployment;
this.currentDetections = currentDetections;
+ this.nMapPoints = nMapPoints;
+ this.doneMapPoints = doneMapPoints;
this.lastUnitTime = lastUnitTime;
this.totalUnits = totalUnits;
this.exportCount = exportCount;
diff --git a/src/tethys/detection/DetectionsHandler.java b/src/tethys/detection/DetectionsHandler.java
index f797c8ee..cd995bbb 100644
--- a/src/tethys/detection/DetectionsHandler.java
+++ b/src/tethys/detection/DetectionsHandler.java
@@ -1,9 +1,13 @@
package tethys.detection;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+import java.util.ListIterator;
import javax.swing.SwingWorker;
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.XMLGregorianCalendar;
import PamController.PamControlledUnit;
import PamController.PamController;
@@ -32,6 +36,7 @@ import nilus.Detections;
import nilus.GranularityEnumType;
import nilus.Helper;
import tethys.Collection;
+import tethys.CollectionHandler;
import tethys.TethysControl;
import tethys.TethysTimeFuncs;
import tethys.dbxml.DBXMLConnect;
@@ -39,7 +44,6 @@ import tethys.dbxml.TethysException;
import tethys.deployment.DeploymentHandler;
import tethys.niluswraps.PDeployment;
import tethys.niluswraps.PDetections;
-import tethys.output.DatablockSynchInfo;
import tethys.output.StreamExportParams;
import tethys.output.TethysExportParams;
import tethys.pamdata.TethysDataProvider;
@@ -54,9 +58,7 @@ import tethys.swing.export.DetectionsExportWizard;
* @author dg50
*
*/
-public class DetectionsHandler {
-
- private TethysControl tethysControl;
+public class DetectionsHandler extends CollectionHandler {
public int uniqueDetectionsId=1;
public int uniqueDetectionId;
@@ -65,12 +67,14 @@ public class DetectionsHandler {
private ExportWorker exportWorker;
+ public static final String helpPoint = "utilities.tethys.docs.detect_localize";
+
/**
*
* @param tethysControl
*/
public DetectionsHandler(TethysControl tethysControl) {
- super();
+ super(tethysControl, Collection.Detections);
this.tethysControl = tethysControl;
}
@@ -296,9 +300,14 @@ public class DetectionsHandler {
viewerLoadPolicy = ViewerLoadPolicy.LOAD_UTCNORMAL;
}
GranularityHandler granularityHandler = GranularityHandler.getHandler(streamExportParams.granularity, tethysControl, dataBlock, exportParams, streamExportParams);
+ int totalMaps = 0;
+ int totalMappedPoints = 0;
+ int totalLoadedDatas = 0;
+ int totalMapPoints = dataMap.getNumMapPoints();
+ int doneMapPoints = 0;
for (PDeployment deployment : deployments) {
int documentCount = 0;
- prog = new DetectionExportProgress(deployment, null,
+ prog = new DetectionExportProgress(deployment, null, totalMapPoints, doneMapPoints,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_COUNTING);
exportObserver.update(prog);
granularityHandler.prepare(deployment.getAudioStart());
@@ -308,9 +317,10 @@ public class DetectionsHandler {
for (OfflineDataMapPoint mapPoint : mapPoints) {
if (!activeExport) {
- prog = new DetectionExportProgress(deployment, null,
+ prog = new DetectionExportProgress(deployment, null,totalMapPoints, doneMapPoints,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_CANCELED);
exportObserver.update(prog);
+ break;
}
if (mapPoint.getEndTime() < deployment.getAudioStart()) {
@@ -319,10 +329,13 @@ public class DetectionsHandler {
if (mapPoint.getStartTime() >= deployment.getAudioEnd()) {
break;
}
+ totalMaps ++;
+ totalMappedPoints += mapPoint.getNDatas();
dataBlock.loadViewerData(mapPoint.getStartTime(), mapPoint.getEndTime(), null);
ArrayList dataCopy = dataBlock.getDataCopy(deployment.getAudioStart(), deployment.getAudioEnd(), true, dataSelector);
-// System.out.printf("%d loaded from %s to %s %d kept\n", dataBlock.getUnitsCount(), PamCalendar.formatDateTime(mapPoint.getStartTime()),
-// PamCalendar.formatDateTime(mapPoint.getEndTime()), dataCopy.size());
+ totalLoadedDatas += dataCopy.size();
+ System.out.printf("%d loaded from %s to %s %d kept\n", dataBlock.getUnitsCount(), PamCalendar.formatDateTime(mapPoint.getStartTime()),
+ PamCalendar.formatDateTime(mapPoint.getEndTime()), dataCopy.size());
skipCount += dataBlock.getUnitsCount() - dataCopy.size();
for (PamDataUnit dataUnit : dataCopy) {
/*
@@ -334,7 +347,7 @@ public class DetectionsHandler {
documentCount+=dets.length;
if (exportCount % 100 == 0) {
- prog = new DetectionExportProgress(deployment, null,
+ prog = new DetectionExportProgress(deployment, null,totalMapPoints, doneMapPoints,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_COUNTING);
exportObserver.update(prog);
}
@@ -345,15 +358,17 @@ public class DetectionsHandler {
// onEffort.getDetection().add(det);
lastUnitTime = dataUnit.getTimeMilliseconds();
}
-
- prog = new DetectionExportProgress(deployment, null,
+ doneMapPoints++;
+ prog = new DetectionExportProgress(deployment, null,totalMapPoints, doneMapPoints,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_COUNTING);
exportObserver.update(prog);
if (viewerLoadPolicy == ViewerLoadPolicy.LOAD_ALWAYS_EVERYTHING) {
break;
}
-
+ if (!activeExport) {
+ return 0;
+ }
}
Detection dets[] = granularityHandler.cleanup(deployment.getAudioEnd());
if (dets != null) {
@@ -397,28 +412,33 @@ public class DetectionsHandler {
if (viewerLoadPolicy == null) {
viewerLoadPolicy = ViewerLoadPolicy.LOAD_UTCNORMAL;
}
+ int totalMapPoints = dataMap.getNumMapPoints();
+ int doneMapPoints = 0;
GranularityHandler granularityHandler = GranularityHandler.getHandler(streamExportParams.granularity, tethysControl, dataBlock, exportParams, streamExportParams);
for (PDeployment deployment : deployments) {
int documentCount = 0;
- prog = new DetectionExportProgress(deployment, null,
+ prog = new DetectionExportProgress(deployment, null,totalMapPoints, doneMapPoints,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_COUNTING);
exportObserver.update(prog);
granularityHandler.prepare(deployment.getAudioStart());
- if (currentDetections == null) {
- currentDetections = startDetectionsDocument(deployment, dataBlock, streamExportParams);
- currentDetections.getEffort().setStart(TethysTimeFuncs.xmlGregCalFromMillis(deployment.getAudioStart()));
- }
// export everything in that deployment.
// need to loop through all map points in this interval.
List mapPoints = dataMap.getMapPoints();
for (OfflineDataMapPoint mapPoint : mapPoints) {
if (!activeExport) {
- prog = new DetectionExportProgress(deployment, currentDetections,
+ prog = new DetectionExportProgress(deployment, currentDetections,totalMapPoints, doneMapPoints,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_CANCELED);
exportObserver.update(prog);
+ break;
}
+ if (currentDetections == null) {
+ // needed in inner loop in case doc gets written at 500000.
+ currentDetections = startDetectionsDocument(deployment, dataBlock, streamExportParams);
+ currentDetections.getEffort().setStart(TethysTimeFuncs.xmlGregCalFromMillis(deployment.getAudioStart()));
+ }
+
if (mapPoint.getEndTime() < deployment.getAudioStart()) {
continue;
}
@@ -427,6 +447,7 @@ public class DetectionsHandler {
}
dataBlock.loadViewerData(mapPoint.getStartTime(), mapPoint.getEndTime(), null);
ArrayList dataCopy = dataBlock.getDataCopy(deployment.getAudioStart(), deployment.getAudioEnd(), true, dataSelector);
+ Collections.sort(dataCopy);
skipCount += dataBlock.getUnitsCount() - dataCopy.size();
DetectionGroup onEffort = currentDetections.getOnEffort();
for (PamDataUnit dataUnit : dataCopy) {
@@ -442,24 +463,27 @@ public class DetectionsHandler {
}
}
if (exportCount % 100 == 0) {
- prog = new DetectionExportProgress(deployment, null,
+ prog = new DetectionExportProgress(deployment, currentDetections, totalMapPoints, doneMapPoints,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_GATHERING);
exportObserver.update(prog);
}
lastUnitTime = dataUnit.getTimeMilliseconds();
}
- prog = new DetectionExportProgress(deployment, currentDetections,
+ doneMapPoints ++;
+ prog = new DetectionExportProgress(deployment, currentDetections,totalMapPoints, doneMapPoints,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_GATHERING);
exportObserver.update(prog);
- if (documentCount > 500000 && mapPoint != dataMap.getLastMapPoint()) {
- prog = new DetectionExportProgress(deployment, currentDetections,
+ if (documentCount > 50000000 && mapPoint != dataMap.getLastMapPoint()) {
+ prog = new DetectionExportProgress(deployment, currentDetections,totalMapPoints, doneMapPoints,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_WRITING);
exportObserver.update(prog);
closeDetectionsDocument(currentDetections, mapPoint.getEndTime());
try {
- dbxmlConnect.postAndLog(currentDetections);
+ if (checkDetectionsDocument(currentDetections, granularityHandler)) {
+ dbxmlConnect.postAndLog(currentDetections);
+ }
} catch (TethysException e) {
tethysControl.showException(e);
}
@@ -469,8 +493,14 @@ public class DetectionsHandler {
if (viewerLoadPolicy == ViewerLoadPolicy.LOAD_ALWAYS_EVERYTHING) {
break;
}
+ if (!activeExport) {
+ break;
+ }
+ }
+
+ if (!activeExport) {
+ return DetectionExportProgress.STATE_CANCELED;
}
-
if (currentDetections != null) {
Detection dets[] = granularityHandler.cleanup(deployment.getAudioEnd());
@@ -481,11 +511,13 @@ public class DetectionsHandler {
currentDetections.getOnEffort().getDetection().add(dets[dd]);
}
}
- prog = new DetectionExportProgress(deployment, currentDetections,
+ prog = new DetectionExportProgress(deployment, currentDetections,totalMapPoints, doneMapPoints,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_WRITING);
closeDetectionsDocument(currentDetections, deployment.getAudioEnd());
try {
- dbxmlConnect.postAndLog(currentDetections);
+ if (checkDetectionsDocument(currentDetections, granularityHandler)) {
+ dbxmlConnect.postAndLog(currentDetections);
+ }
} catch (TethysException e) {
tethysControl.showException(e);
}
@@ -493,7 +525,7 @@ public class DetectionsHandler {
}
}
- prog = new DetectionExportProgress(null, null,
+ prog = new DetectionExportProgress(null, null,totalMapPoints, totalMapPoints,
lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_COMPLETE);
exportObserver.update(prog);
return DetectionExportProgress.STATE_COMPLETE;
@@ -552,7 +584,7 @@ public class DetectionsHandler {
supportSoft.setVersion(getSupportSoftwareVersion(dataBlock));
supSoft.add(supportSoft);
detections.setAlgorithm(algorithm);
- detections.setUserId("Unknown user");
+ detections.setUserId("PAMGuard user");
detections.setEffort(getDetectorEffort(deployment, dataBlock, exportParams));
return detections;
@@ -567,6 +599,50 @@ public class DetectionsHandler {
private void closeDetectionsDocument(Detections detections, Long audioEnd) {
detections.getEffort().setEnd(TethysTimeFuncs.xmlGregCalFromMillis(audioEnd));
}
+
+ /**
+ * Run some checks on the Detections document prior to submission.
+ * Currently, is is just a check that the detections are within the effort times.
+ * @param detections Detections document
+ * @return false if there is an outstanding problem.
+ */
+ private boolean checkDetectionsDocument(Detections detections, GranularityHandler granularityHandler) {
+ XMLGregorianCalendar effStart = detections.getEffort().getStart();
+ XMLGregorianCalendar effEnd = detections.getEffort().getEnd();
+ DetectionGroup dets = detections.getOnEffort();
+ List detList = dets.getDetection();
+ ListIterator detIt = detList.listIterator();
+ while (detIt.hasNext()) {
+ Detection det = detIt.next();
+ XMLGregorianCalendar detS = det.getStart();
+ XMLGregorianCalendar detE = det.getEnd();
+ if (effStart.compare(detS) == DatatypeConstants.GREATER) {
+ if (granularityHandler.autoEffortFix(detections, det)) {
+ continue;
+ }
+ String str = String.format("A Detection at %s starts before the document effort start at %s
"
+ + "Do you want to adjust the effort start time or abort export ?", detS, effStart);
+ int ans = WarnOnce.showNamedWarning("TETHYSDETNOTINEFFORT", tethysControl.getGuiFrame(), "Detection Document Warning", str, WarnOnce.OK_CANCEL_OPTION);
+ if (ans == WarnOnce.CANCEL_OPTION) {
+ return false;
+ }
+ detections.getEffort().setStart(detS);
+ }
+ if (effEnd.compare(detE) == DatatypeConstants.LESSER) {
+ if (granularityHandler.autoEffortFix(detections, det)) {
+ continue;
+ }
+ String str = String.format("A Detection at %s-%s ends
after the document effort end at %s
"
+ + "Do you want to adjust the effort end time or abort export ?", detS, detE, effStart);
+ int ans = WarnOnce.showNamedWarning("TETHYSDETNOTINEFFORT", tethysControl.getGuiFrame(), "Detection Document Warning", str, WarnOnce.OK_CANCEL_OPTION);
+ if (ans == WarnOnce.CANCEL_OPTION) {
+ return false;
+ }
+ detections.getEffort().setEnd(detE);
+ }
+ }
+ return true;
+ }
/**
* Worker thread for exporting detections.
@@ -599,13 +675,16 @@ public class DetectionsHandler {
protected Integer doInBackground() throws Exception {
Integer ans = null;
try {
- int count = countDetections(dataBlock, exportParams, exportObserver);
- String msg = String.format("Do you want to go ahead and output %d %s detections to Tethys?",
- count, exportParams.granularity);
- int doit = WarnOnce.showWarning("Tethys Detections Export", msg, WarnOnce.OK_CANCEL_OPTION);
- if (doit == WarnOnce.OK_OPTION) {
+// int count = countDetections(dataBlock, exportParams, exportObserver);
+// if (activeExport == false) {
+// return 0;
+// }
+// String msg = String.format("Do you want to go ahead and output %d %s detections to Tethys?",
+// count, exportParams.granularity);
+// int doit = WarnOnce.showWarning("Tethys Detections Export", msg, WarnOnce.OK_CANCEL_OPTION);
+// if (doit == WarnOnce.OK_OPTION) {
ans = exportDetections(dataBlock, exportParams, this);
- }
+// }
}
catch (Exception e) {
e.printStackTrace();
@@ -616,7 +695,7 @@ public class DetectionsHandler {
@Override
protected void done() {
// this.
- DetectionExportProgress prog = new DetectionExportProgress(null, null, 0, 0, 0, 0, DetectionExportProgress.STATE_COMPLETE);
+ DetectionExportProgress prog = new DetectionExportProgress(null, null, 0, 0, 0, 0, 0, 0, DetectionExportProgress.STATE_COMPLETE);
tethysControl.exportedDetections(dataBlock);
exportObserver.update(prog);
TethysReporter.getTethysReporter().showReport(tethysControl.getGuiFrame(), true);
@@ -661,4 +740,10 @@ public class DetectionsHandler {
DetectionsExportWizard.showDialog(tethysControl.getGuiFrame(), tethysControl, dataBlock);
}
+
+
+ @Override
+ public String getHelpPoint() {
+ return helpPoint;
+ }
}
diff --git a/src/tethys/detection/EncounterGranularityHandler.java b/src/tethys/detection/EncounterGranularityHandler.java
index 57dd8757..54e70db5 100644
--- a/src/tethys/detection/EncounterGranularityHandler.java
+++ b/src/tethys/detection/EncounterGranularityHandler.java
@@ -11,6 +11,7 @@ import java.util.Map.Entry;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
import nilus.Detection;
+import nilus.Detections;
import nilus.SpeciesIDType;
import tethys.TethysControl;
import tethys.TethysTimeFuncs;
@@ -48,7 +49,7 @@ public class EncounterGranularityHandler extends GranularityHandler {
@Override
public void prepare(long timeMillis) {
-
+ currentDetections.clear();
}
@Override
@@ -77,6 +78,7 @@ public class EncounterGranularityHandler extends GranularityHandler {
currentDetections.put(groupName, det);
}
else {
+
// add to current detection. Set new end time and increment count
det.setEnd(TethysTimeFuncs.xmlGregCalFromMillis(dataUnit.getEndTimeInMilliseconds()));
int count = det.getCount().intValue() + 1;
@@ -122,34 +124,17 @@ public class EncounterGranularityHandler extends GranularityHandler {
}
}
- // private Detection[] checkCurrentEncounters(long timeMilliseconds) {
- // if (currentDetections == null || currentDetections.size() == 0) {
- // return null;
- // }
- // int nGood = 0;
- // Detection[] newDetections = new Detection[currentDetections.size()];
- // Iterator detIt = currentDetections.iterator();
- // while (detIt.hasNext()) {
- // Detection aDet = detIt.next();
- // Long detEnd = TethysTimeFuncs.millisFromGregorianXML(aDet.getEnd());
- // if (timeMilliseconds-detEnd > maxGapMillis) {
- // detIt.remove();
- // newDetections[nGood++] = aDet;
- // }
- // }
- //
- // if (nGood == 0) {
- // return null;
- // }
- // else {
- // return Arrays.copyOf(newDetections, nGood);
- // }
- // }
@Override
public Detection[] cleanup(long timeMillis) {
// get everything still on the go.
- return checkCurrentEncounters(timeMillis + maxGapMillis);
+ return checkCurrentEncounters(timeMillis + maxGapMillis*10);
}
+ @Override
+ protected boolean autoEffortFix(Detections detections, Detection det) {
+ return expandEffort(detections, det);
+ }
+
+
}
diff --git a/src/tethys/detection/GranularityHandler.java b/src/tethys/detection/GranularityHandler.java
index d172405e..47ef87e3 100644
--- a/src/tethys/detection/GranularityHandler.java
+++ b/src/tethys/detection/GranularityHandler.java
@@ -1,8 +1,16 @@
package tethys.detection;
+import java.util.List;
+import java.util.ListIterator;
+
+import javax.xml.datatype.DatatypeConstants;
+import javax.xml.datatype.XMLGregorianCalendar;
+
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
import nilus.Detection;
+import nilus.DetectionGroup;
+import nilus.Detections;
import nilus.GranularityEnumType;
import tethys.TethysControl;
import tethys.output.StreamExportParams;
@@ -118,4 +126,93 @@ public abstract class GranularityHandler {
}
return null;
}
+
+ /**
+ * Automatically fix mismatches between effort and detections. This will be called if a
+ * detection or part of a detection is outside of the start and end defined by the effort. If it's a
+ * small difference, i.e. if the detection at least overlaps the effort then it can be automatically
+ * fixed by truncating the detection (for binned types) or by a small extension to the effort (for encounter
+ * and call types).
+ * @param detections nilus Detections object
+ * @param det a single detection
+ * @return true if it was fixed automatically. False otherwise.
+ */
+ protected abstract boolean autoEffortFix(Detections detections, Detection det);
+
+ /**
+ * Check that the detection at least overlaps the effort period.
+ * @param detections nilus Detections object
+ * @param det a single detection
+ * @return true if the overlap
+ */
+ protected boolean effortOverlap(Detections detections, Detection det) {
+ XMLGregorianCalendar effStart = detections.getEffort().getStart();
+ XMLGregorianCalendar effEnd = detections.getEffort().getEnd();
+ XMLGregorianCalendar detStart = det.getStart();
+ XMLGregorianCalendar detEnd = det.getEnd();
+ if (effStart.compare(detEnd) == DatatypeConstants.GREATER) {
+ return false;
+ }
+ if (effEnd.compare(detStart) == DatatypeConstants.LESSER) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Fix effort / detection problem but contracting the start / end times of the detection
+ * @param detections nilus Detections object
+ * @param det a single detection
+ * @return true if fixed automatically
+ */
+ protected boolean contractDetection(Detections detections, Detection det) {
+ if (effortOverlap(detections, det) == false) {
+ return false;
+ }
+ // at least some overlap, so fix it.
+ // going to fix it my shortening the detection, and leave the effort alone.
+ XMLGregorianCalendar effStart = detections.getEffort().getStart();
+ XMLGregorianCalendar effEnd = detections.getEffort().getEnd();
+ XMLGregorianCalendar detStart = det.getStart();
+ XMLGregorianCalendar detEnd = det.getEnd();
+
+
+ if (effStart.compare(detStart) == DatatypeConstants.GREATER) {
+ System.out.printf("Fix Detections change detection start from %s to %s\n", detStart, effStart);
+ det.setStart(effStart);
+ }
+ if (effEnd.compare(detEnd) == DatatypeConstants.LESSER) {
+ System.out.printf("Fix Detections change detection end from %s to %s\n", detEnd, effEnd);
+ det.setEnd(effEnd);
+ }
+ return true;
+ }
+
+ /**
+ * Fix effort / detection problem but expanding the start / end times of the effort
+ * @param detections nilus Detections object
+ * @param det a single detection
+ * @return true if fixed automatically
+ */
+ protected boolean expandEffort(Detections detections, Detection det) {
+ if (effortOverlap(detections, det) == false) {
+ return false;
+ }
+ // at least some overlap, so fix it.
+ // going to fix it my shortening the detection, and leave the effort alone.
+ XMLGregorianCalendar effStart = detections.getEffort().getStart();
+ XMLGregorianCalendar effEnd = detections.getEffort().getEnd();
+ XMLGregorianCalendar detStart = det.getStart();
+ XMLGregorianCalendar detEnd = det.getEnd();
+
+ if (effStart.compare(detStart) == DatatypeConstants.GREATER) {
+ System.out.printf("Fix Detections change effort start from %s to %s\n", effStart, detStart);
+ detections.getEffort().setStart(detStart);
+ }
+ if (effEnd.compare(detEnd) == DatatypeConstants.LESSER) {
+ System.out.printf("Fix Detections change effort end from %s to %s\n", effEnd, detEnd);
+ detections.getEffort().setEnd(detEnd);
+ }
+ return true;
+ }
}
diff --git a/src/tethys/localization/LocalizationHandler.java b/src/tethys/localization/LocalizationHandler.java
new file mode 100644
index 00000000..69105b5e
--- /dev/null
+++ b/src/tethys/localization/LocalizationHandler.java
@@ -0,0 +1,17 @@
+package tethys.localization;
+
+import nilus.CylindricalCoordinateType;
+import nilus.LocalizationType;
+import nilus.Localize.Effort.CoordinateReferenceSystem;
+
+public class LocalizationHandler {
+
+
+ public LocalizationType getLoc() {
+ LocalizationType lt = new LocalizationType();
+ CylindricalCoordinateType cct = new CylindricalCoordinateType();
+// cct.set
+ CoordinateReferenceSystem cr;
+ return null;
+ }
+}
diff --git a/src/tethys/niluswraps/NilusChecker.java b/src/tethys/niluswraps/NilusChecker.java
index 43a53e97..e9107540 100644
--- a/src/tethys/niluswraps/NilusChecker.java
+++ b/src/tethys/niluswraps/NilusChecker.java
@@ -56,7 +56,7 @@ public class NilusChecker {
for (Field f : emptyFields) {
msg += String.format("
Field %s in object %s", f.getName(), f.getDeclaringClass().getName());
}
- msg += "
It is likely that this document will fail to write to the Tethys database.";
+ msg += "
It is possible that this document will fail to write to the Tethys database.