makeSettingsList() {
PamSettingManager settingsManager = PamSettingManager.getInstance();
settingsSets = settingsManager.getOwners();
if (settingsSets == null) {
@@ -850,6 +946,14 @@ public class PamguardXMLWriter implements PamSettings {
return doc;
}
+ /**
+ * Is this element a writable type ? Basically, this means
+ * that it's a primitive of some sort. Otherwise it's
+ * probably an object and may even be a list in which case
+ * it will need treating differently.
+ * @param clazz
+ * @return
+ */
public static boolean isWritableType(Class> clazz)
{
if (clazz.isEnum()) return true;
@@ -940,5 +1044,23 @@ public class PamguardXMLWriter implements PamSettings {
return true;
}
+ /**
+ * @return the excludeDisplaySettings
+ */
+ public boolean isExcludeDisplaySettings() {
+ return excludeDisplaySettings;
+ }
+
+ /**
+ * @param excludeDisplaySettings the excludeDisplaySettings to set
+ */
+ public void setExcludeDisplaySettings(boolean excludeDisplaySettings) {
+ this.excludeDisplaySettings = excludeDisplaySettings;
+ }
+
+// public void setStaticNameSpace(String xmlNameSpace) {
+// this.xmlNameSpace = xmlNameSpace;
+// }
+
}
diff --git a/src/PamController/settings/output/xml/XMLWriterSettings.java b/src/PamController/settings/output/xml/XMLWriterSettings.java
index 8e5d0969..dcd60b83 100644
--- a/src/PamController/settings/output/xml/XMLWriterSettings.java
+++ b/src/PamController/settings/output/xml/XMLWriterSettings.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class XMLWriterSettings implements Serializable, Cloneable, ManagedParameters {
@@ -34,7 +35,7 @@ public class XMLWriterSettings implements Serializable, Cloneable, ManagedParame
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/PamController/soundMedium/GlobalMediumParams.java b/src/PamController/soundMedium/GlobalMediumParams.java
index 0a52ac83..8bf10f27 100644
--- a/src/PamController/soundMedium/GlobalMediumParams.java
+++ b/src/PamController/soundMedium/GlobalMediumParams.java
@@ -5,6 +5,7 @@ import java.io.Serializable;
import PamController.soundMedium.GlobalMedium.SoundMedium;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Stores parameters for the current medium.
@@ -41,7 +42,7 @@ public class GlobalMediumParams implements Serializable, Cloneable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/PamModel/PamModel.java b/src/PamModel/PamModel.java
index 3b0aa6d0..774611e5 100644
--- a/src/PamModel/PamModel.java
+++ b/src/PamModel/PamModel.java
@@ -44,11 +44,15 @@ import whistlesAndMoans.AbstractWhistleDataUnit;
import fftManager.FFTDataUnit;
import fftManager.PamFFTControl;
import group3dlocaliser.Group3DLocaliserControl;
+import metadata.MetaDataContol;
import meygenturbine.MeygenTurbine;
import printscreen.PrintScreenControl;
import rockBlock.RockBlockControl;
+import tethys.TethysControl;
import turbineops.TurbineOperationControl;
import GPS.GpsDataUnit;
+import Map.MapController;
+import Map.gridbaselayer.GridbaseControl;
import NMEA.NMEADataUnit;
import PamController.PamControlledUnitSettings;
import PamController.PamController;
@@ -62,6 +66,7 @@ import PamguardMVC.PamDataBlock;
import analogarraysensor.ArraySensorControl;
import backupmanager.BackupManager;
import beamformer.continuous.BeamFormerControl;
+import beamformer.localiser.BeamFormLocaliserControl;
import bearinglocaliser.BearingLocaliserControl;
import binaryFileStorage.SecondaryBinaryStore;
import cepstrum.CepstrumControl;
@@ -454,6 +459,19 @@ final public class PamModel implements PamSettings {
mi.setToolTipText("Manage automated data backups");
mi.setModulesMenuGroup(utilitiesGroup);
mi.setMaxNumber(1);
+
+
+// mi = PamModuleInfo.registerControlledUnit(MetaDataContol.class.getName(), MetaDataContol.unitType);
+// mi.setToolTipText("Project Meta Data");
+// mi.setModulesMenuGroup(utilitiesGroup);
+// mi.setMaxNumber(1);
+
+ if (isViewer) {
+ mi = PamModuleInfo.registerControlledUnit(TethysControl.class.getName(), TethysControl.defaultName);
+ mi.setToolTipText("Interface to Tethys Database");
+ mi.setModulesMenuGroup(utilitiesGroup);
+ mi.setMaxNumber(1);
+ }
/*
* ************* End Utilities Group *******************
@@ -1064,7 +1082,7 @@ final public class PamModel implements PamSettings {
// clear the current list
pluginList.clear();
daqList.clear();
-
+
/*
* If developing a new PAMPlugin in eclipse, the easiest way to do it is to make a new
* Eclipse project for your plugin code. Within that project, copy this PamModel class
@@ -1079,6 +1097,8 @@ final public class PamModel implements PamSettings {
* When you export the code for your plugin to a jar file, remember to NOT inlcude the copy of
* PamModel !
*/
+
+// pluginList.add(new MorlaisWP1aPlugin());
// Load up whatever default classloader was used to create this class. Must use the same classloader
// for all plugins, or else we will not be able to create proper dependencies between them or be able
@@ -1146,11 +1166,30 @@ final public class PamModel implements PamSettings {
// to add that URL to the default classloader path.
URL newURL = jarList.get(i).toURI().toURL();
+ // original method
+// Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
+// method.setAccessible(true);
+// method.invoke(cl, newURL);
+
+ // first fix attempt - create a brand new URLClassLoader. As expected, we get a ClassCastException when trying
+ // to load the parameters so we can't save params using this method
+// URL[] newURLArray = new URL[1];
+// newURLArray[0] = newURL;
+// cl = new URLClassLoader(newURLArray);
// second attempt - custom class loader with the system app loader specified as the parent. Loads controlled unit, but
// as before it doesn't load the parameters
classLoader.addURL(newURL);
+ // third attempt
+// Class> genericClass = cl.getClass();
+// Method method = genericClass.getSuperclass().getDeclaredMethod("addURL", new Class[] {URL.class});
+// method.setAccessible(true);
+// method.invoke(cl, new Object[] {newURL});
+
+
+
+
// Save the name of the class to the global pluginBeingLoaded variable, and load the class.
this.setPluginBeingLoaded(className);
// Class c = cl.loadClass(className);
@@ -1231,8 +1270,9 @@ final public class PamModel implements PamSettings {
"for help." +
"This plug-in will not be available for loading";
String help = null;
- int ans = WarnOnce.showWarning(PamController.getInstance().getGuiFrameManager().getFrame(0), title, msg, WarnOnce.WARNING_MESSAGE, help, e1);
+ int ans = WarnOnce.showWarning(PamController.getMainFrame(), title, msg, WarnOnce.WARNING_MESSAGE, help, e1);
System.err.println("Exception while loading " + className);
+ System.err.println(e1.getMessage());
continue;
}
}
@@ -1245,7 +1285,7 @@ final public class PamModel implements PamSettings {
"for help.
" +
"This plug-in will not be available for loading";
String help = null;
- int ans = WarnOnce.showWarning(PamController.getInstance().getGuiFrameManager().getFrame(0), title, msg, WarnOnce.WARNING_MESSAGE, help, ex);
+ int ans = WarnOnce.showWarning(PamController.getMainFrame(), title, msg, WarnOnce.WARNING_MESSAGE, help, ex);
System.err.println("Exception while loading " + jarList.get(i).getName());
continue;
}
@@ -1270,7 +1310,7 @@ final public class PamModel implements PamSettings {
// instantiate the plugin control class using the custom class loader
try {
-// File classFile = new File(pf.getJarFile());
+ File classFile = new File(pf.getJarFile());
//URLClassLoader cl = new URLClassLoader(new URL[]{classFile.toURI().toURL()});
// mi = PamModuleInfo.registerControlledUnit(pf.getClassName(), pf.getDescription(),cl);
mi = PamModuleInfo.registerControlledUnit(pf.getClassName(), pf.getDescription(),classLoader);
@@ -1336,7 +1376,7 @@ final public class PamModel implements PamSettings {
"for help.
" +
"This plug-in will not be available for loading";
String help = null;
- int ans = WarnOnce.showWarning(PamController.getInstance().getGuiFrameManager().getFrame(0), title, msg, WarnOnce.WARNING_MESSAGE, help, e1);
+ int ans = WarnOnce.showWarning(PamController.getMainFrame(), title, msg, WarnOnce.WARNING_MESSAGE, help, e1);
System.err.println("Exception while loading " + pf.getDefaultName());
pluginList.remove(pf);
continue;
diff --git a/src/PamModel/PamModelSettings.java b/src/PamModel/PamModelSettings.java
index 9e4b0632..667747b8 100644
--- a/src/PamModel/PamModelSettings.java
+++ b/src/PamModel/PamModelSettings.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class PamModelSettings implements Cloneable, Serializable, ManagedParameters {
@@ -74,7 +75,7 @@ public class PamModelSettings implements Cloneable, Serializable, ManagedParamet
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/PamModel/parametermanager/PamParameterData.java b/src/PamModel/parametermanager/PamParameterData.java
index a15a3c15..79944a90 100644
--- a/src/PamModel/parametermanager/PamParameterData.java
+++ b/src/PamModel/parametermanager/PamParameterData.java
@@ -34,6 +34,11 @@ abstract public class PamParameterData {
*/
private String postTitle;
+ /**
+ * field length for automatic dialogs.
+ */
+ private int fieldLength;
+
/**
* @param parentObject
@@ -45,6 +50,21 @@ abstract public class PamParameterData {
this.field = field;
}
+ /**
+ * @param parentObject
+ * @param field
+ * @param shortName
+ * @param toolTip
+ * @param fieldLength length of text in automatic dialogs.
+ */
+ public PamParameterData(Object parentObject, Field field, String shortName, String toolTip, int fieldLength) {
+ super();
+ this.field = field;
+ this.shortName = shortName;
+ this.toolTip = toolTip;
+ this.fieldLength = fieldLength;
+ }
+
/**
* @param parentObject
* @param field
@@ -58,7 +78,6 @@ abstract public class PamParameterData {
this.toolTip = toolTip;
}
-
/**
* @param shortName the shortName to set
*/
@@ -66,6 +85,20 @@ abstract public class PamParameterData {
this.shortName = shortName;
}
+ /**
+ * Set info about a parameter
+ * @param shortName short name, e.g. to use in a dialog
+ * @param postTitle post title, e.g. text coming after a data entry field in a dialog
+ * @param toolTip tool tip to display over the component in a dialog.
+ * @param fieldLength length of text in automatic dialogs.
+ */
+ public void setInfo(String shortName, String postTitle, String toolTip, int fieldLength) {
+ this.shortName = shortName;
+ this.postTitle = postTitle;
+ this.toolTip = toolTip;
+ this.fieldLength = fieldLength;
+ }
+
/**
* Set info about a parameter
* @param shortName short name, e.g. to use in a dialog
@@ -136,6 +169,9 @@ abstract public class PamParameterData {
* @return a short name for the field, suitable for use in dialogs.
*/
public String getShortName() {
+ if (shortName == null) {
+ return getFieldName();
+ }
return shortName;
}
@@ -166,5 +202,19 @@ abstract public class PamParameterData {
return String.format("Param %s class %s", getFieldName(), getDataClass());
}
+ /**
+ * @return the fieldLength
+ */
+ public int getFieldLength() {
+ return fieldLength;
+ }
+
+ /**
+ * @param fieldLength the fieldLength to set
+ */
+ public void setFieldLength(int fieldLength) {
+ this.fieldLength = fieldLength;
+ }
+
}
diff --git a/src/PamModel/parametermanager/PamParameterDataGetter.java b/src/PamModel/parametermanager/PamParameterDataGetter.java
index 3947f2dc..9a3e99b0 100644
--- a/src/PamModel/parametermanager/PamParameterDataGetter.java
+++ b/src/PamModel/parametermanager/PamParameterDataGetter.java
@@ -59,9 +59,12 @@ public class PamParameterDataGetter extends PrivatePamParameterData {
if (setter == null) {
return false;
}
+ // need to convert the type
+ Object convObj = convertStringType(data);
try {
- setter.invoke(getParentObject(), data);
- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ Object parentObj = getParentObject();
+ setter.invoke(parentObj, convObj);
+ } catch (InvocationTargetException e) {
e.printStackTrace();
return false;
}
diff --git a/src/PamModel/parametermanager/PamParameterSet.java b/src/PamModel/parametermanager/PamParameterSet.java
index 751f3d27..c7108e0a 100644
--- a/src/PamModel/parametermanager/PamParameterSet.java
+++ b/src/PamModel/parametermanager/PamParameterSet.java
@@ -29,6 +29,9 @@ public class PamParameterSet {
private static boolean printDebug = false;
+ public enum ParameterSetType {DETECTOR, DISPLAY};
+
+ private ParameterSetType parameterSetType;
/**
* Standard modifiers to exclude. This is important for many classes which will tend to
* do crazy things such as incorporate ALL of their final fields, e.g. when a Color
@@ -55,8 +58,10 @@ public class PamParameterSet {
* in the STANDARD_MODIFIER_EXCLUSIONS list (FINAL or STATIC).
* @return Created parameter set.
*/
- public static PamParameterSet autoGenerate(Object parentObject) {
- return autoGenerate(parentObject, STANDARD_MODIFIER_EXCLUSIONS);
+ public static PamParameterSet autoGenerate(Object parentObject, ParameterSetType parameterSetType) {
+ PamParameterSet paramSet = autoGenerate(parentObject, STANDARD_MODIFIER_EXCLUSIONS);
+ paramSet.setParameterSetType(parameterSetType);
+ return paramSet;
}
/**
@@ -286,4 +291,19 @@ public class PamParameterSet {
public PamParameterData removeParameterData(String paramName) {
return parameterDatas.remove(paramName);
}
+
+ /**
+ * @return the parameterSetType
+ */
+ public ParameterSetType getParameterSetType() {
+ return parameterSetType;
+ }
+
+ /**
+ * @param parameterSetType the parameterSetType to set
+ */
+ public void setParameterSetType(ParameterSetType parameterSetType) {
+ this.parameterSetType = parameterSetType;
+ }
+
}
diff --git a/src/PamModel/parametermanager/ParameterSetManager.java b/src/PamModel/parametermanager/ParameterSetManager.java
new file mode 100644
index 00000000..3420a7c4
--- /dev/null
+++ b/src/PamModel/parametermanager/ParameterSetManager.java
@@ -0,0 +1,73 @@
+package PamModel.parametermanager;
+
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JMenuItem;
+
+import PamModel.parametermanager.swing.ManagedParameterDialog;
+import generalDatabase.parameterstore.ParameterDatabaseStore;
+
+/**
+ * Just about everything giving overall control of some managed parameters.
+ * May be a bit too specific on first cut and need to be abstracted.
+ * Testing on 'Deployment' data.
+ * @author dg50
+ *
+ * @param
+ */
+public class ParameterSetManager {
+
+ private T managedParams;
+ private String name;
+
+ public ParameterSetManager(T defaultParams, String name) {
+ setManagedParams(defaultParams);
+ this.name = name;
+// if (managedParams == null) {
+// managedParams = new T();
+// }
+ }
+
+ /**
+ * @return the managedParams
+ */
+ public T getManagedParams() {
+ return managedParams;
+ }
+
+ /**
+ * @param managedParams the managedParams to set
+ */
+ public void setManagedParams(T managedParams) {
+ this.managedParams = managedParams;
+ }
+
+ public JMenuItem getMenuItem(Window parent) {
+ if (managedParams == null) {
+ return null;
+ }
+ JMenuItem menuItem = new JMenuItem(name + " ...");
+ menuItem.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ showDialog(parent);
+ }
+ });
+
+ return menuItem;
+ }
+
+ protected void showDialog(Window parent) {
+ ManagedParameterDialog dialog = new ManagedParameterDialog(parent, name, managedParams);
+ T newParams = dialog.showDialog(parent, name, managedParams);
+
+ if (newParams != null) {
+ ParameterDatabaseStore paramDatabase = new ParameterDatabaseStore("MetaData");
+ paramDatabase.saveParameterSet(newParams);
+ }
+ }
+
+}
diff --git a/src/PamModel/parametermanager/PrivatePamParameterData.java b/src/PamModel/parametermanager/PrivatePamParameterData.java
index e3fed547..6b29d9cd 100644
--- a/src/PamModel/parametermanager/PrivatePamParameterData.java
+++ b/src/PamModel/parametermanager/PrivatePamParameterData.java
@@ -1,6 +1,7 @@
package PamModel.parametermanager;
import java.lang.reflect.Field;
+import java.lang.reflect.Type;
/**
* Abstract instance of PamParameterDataInterface which implements everything
@@ -36,9 +37,48 @@ public abstract class PrivatePamParameterData extends PamParameterData {
* This should really be implemented in every concrete class, but no time to do that now. Aim to delete
* this function here, then go through and implement everywhere ...
*/
- return false;
+// return false;
+ Object convData = convertStringType(data);
+ getField().set(this, convData);
+
+ return true;
}
+ /**
+ * convert a string type to a different type appropriate for the field in
+ * question.
+ * @param value
+ * @return
+ */
+ public Object convertStringType(Object value) {
+ if (value == null) {
+ return null;
+ }
+ if (value instanceof String == false) {
+ return value;
+ }
+ String str = (String) value;
+ Type type = getField().getGenericType();
+ Class> cls = getField().getType();
+ String clsName = cls.getName();
+ switch (clsName) {
+ case "int":
+ case "Integer":
+ return Integer.valueOf(str);
+ case "double":
+ case "Double":
+ return Double.valueOf(str);
+ case "float":
+ case "Float":
+ return Float.valueOf(str);
+ case "short":
+ case "Short":
+ return Short.valueOf(str);
+
+ }
+
+ return value;
+ }
}
diff --git a/src/PamModel/parametermanager/swing/ManagedParameterDialog.java b/src/PamModel/parametermanager/swing/ManagedParameterDialog.java
new file mode 100644
index 00000000..9a3aa995
--- /dev/null
+++ b/src/PamModel/parametermanager/swing/ManagedParameterDialog.java
@@ -0,0 +1,49 @@
+package PamModel.parametermanager.swing;
+
+import java.awt.Window;
+
+import PamModel.parametermanager.ManagedParameters;
+import PamView.dialog.PamDialog;
+
+public class ManagedParameterDialog extends PamDialog {
+
+ private T params;
+
+ private ManagedParameterPanel parameterPanel;
+
+ public ManagedParameterDialog(Window parentFrame, String title, T params) {
+ super(parentFrame, title, false);
+ parameterPanel = new ManagedParameterPanel(params);
+ setDialogComponent(parameterPanel.getPanel());
+ }
+
+ public T showDialog(Window parentFrame, String title, T parameters) {
+// ManagedParameterDialog dialog = new ManagedParameterDialog<>(parentFrame, title, parameters);
+ setParams(parameters);
+ setVisible(true);
+
+ return params;
+ }
+
+ private void setParams(T params) {
+ this.params = params;
+ this.parameterPanel.setParams(params);
+ }
+
+ @Override
+ public boolean getParams() {
+ return parameterPanel.getParams(params);
+ }
+
+ @Override
+ public void cancelButtonPressed() {
+ params = null;
+ }
+
+ @Override
+ public void restoreDefaultSettings() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/src/PamModel/parametermanager/swing/ManagedParameterPanel.java b/src/PamModel/parametermanager/swing/ManagedParameterPanel.java
new file mode 100644
index 00000000..416bef77
--- /dev/null
+++ b/src/PamModel/parametermanager/swing/ManagedParameterPanel.java
@@ -0,0 +1,149 @@
+package PamModel.parametermanager.swing;
+
+import java.awt.Color;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.Collection;
+
+import javax.swing.BorderFactory;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.text.JTextComponent;
+
+import PamModel.parametermanager.FieldNotFoundException;
+import PamModel.parametermanager.ManagedParameters;
+import PamModel.parametermanager.PamParameterData;
+import PamModel.parametermanager.PamParameterSet;
+import PamView.dialog.PamDialog;
+import PamView.dialog.PamGridBagContraints;
+
+public class ManagedParameterPanel {
+
+ private JPanel mainPanel;
+ private Collection parameterSet;
+
+ private static final int DEFAULT_TEXT_LENGTH = 6;
+ private static final int MAX_SINGLE_LINE_LENGTH = 40;
+
+ private JTextComponent[] textComponents;
+
+ public ManagedParameterPanel(T parameterExample) {
+
+ mainPanel = new JPanel(new GridBagLayout());
+ GridBagConstraints c = new PamGridBagContraints();
+ PamParameterSet exampleSet = parameterExample.getParameterSet();
+ parameterSet = exampleSet.getParameterCollection();
+ int n = parameterSet.size();
+ textComponents = new JTextComponent[n];
+ int i = 0;
+ for (PamParameterData paramData : parameterSet) {
+ textComponents[i] = createComponent(paramData);
+ c.gridx = 0;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.NORTHEAST;
+ mainPanel.add(new JLabel(paramData.getShortName(), JLabel.RIGHT), c);
+ c.gridx++;
+ if (textComponents[i] instanceof JTextArea) {
+ c.fill = GridBagConstraints.HORIZONTAL;
+ }
+ else {
+ c.fill = GridBagConstraints.NONE;
+ }
+ c.anchor = GridBagConstraints.WEST;
+ mainPanel.add(textComponents[i], c);
+
+ textComponents[i].setToolTipText(getTipText(paramData));
+
+ c.gridy++;
+ i++;
+ }
+ }
+
+ private String getTipText(PamParameterData paramData) {
+ String tip = paramData.getToolTip();
+ if (tip != null) {
+ return tip;
+ }
+ else {
+ return paramData.getFieldName();
+ }
+ }
+
+ private JTextComponent createComponent(PamParameterData paramData) {
+ int textLen = paramData.getFieldLength();
+ if (textLen == 0) {
+ textLen = DEFAULT_TEXT_LENGTH;
+ }
+ if (textLen <= MAX_SINGLE_LINE_LENGTH) {
+ return new JTextField(textLen);
+ }
+ else {
+ JTextField dummyField = new JTextField(2);
+// dummyField.getBorder().
+ JTextArea textArea = new JTextArea(textLen/MAX_SINGLE_LINE_LENGTH+1, MAX_SINGLE_LINE_LENGTH);
+ textArea.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
+ return textArea;
+ }
+ }
+
+ public JComponent getPanel() {
+ return mainPanel;
+ }
+
+ public void setParams(T params) {
+ int i = 0;
+ PamParameterData newParamData = null;
+ Object data = null;
+ for (PamParameterData paramData : this.parameterSet) {
+ // find the parameter in the new parameters (parameterSet is just a formatting placeholder)
+ try {
+ newParamData = params.getParameterSet().findParameterData(paramData.getFieldName());
+ } catch (FieldNotFoundException e) {
+ e.printStackTrace();
+ }
+ try {
+ data = newParamData.getData();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ }
+ if (data != null) {
+ textComponents[i].setText(data.toString());
+ }
+ else {
+ textComponents[i].setText(null);
+ }
+ i++;
+ }
+ }
+
+ public boolean getParams(T params) {
+ int i = 0;
+ PamParameterData newParamData = null;
+ Object data = null;
+ for (PamParameterData paramData : this.parameterSet) {
+ // find the parameter in the new parameters (parameterSet is just a formatting placeholder)
+ try {
+ newParamData = params.getParameterSet().findParameterData(paramData.getFieldName());
+ } catch (FieldNotFoundException e) {
+ e.printStackTrace();
+ }
+ String txt = textComponents[i].getText();
+ try {
+ newParamData.setData(txt);
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ String msg = "Invalid parameter. Data type should be " + paramData.getField().getType().getName();
+ return PamDialog.showWarning(null, newParamData.getShortName(), msg);
+ }
+
+ i++;
+ }
+
+ return true;
+ }
+
+}
diff --git a/src/PamUtils/Coordinate3d.java b/src/PamUtils/Coordinate3d.java
index 57a859f4..a8b6d156 100644
--- a/src/PamUtils/Coordinate3d.java
+++ b/src/PamUtils/Coordinate3d.java
@@ -26,6 +26,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Class definition for a x,y coordinate number type.
@@ -168,7 +169,7 @@ public class Coordinate3d implements Serializable , Cloneable, PamCoordinate, Ma
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/PamUtils/LatLong.java b/src/PamUtils/LatLong.java
index 6b8f9df9..6d465ee6 100644
--- a/src/PamUtils/LatLong.java
+++ b/src/PamUtils/LatLong.java
@@ -15,6 +15,7 @@ import java.text.NumberFormat;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamguardMVC.PamConstants;
import net.sf.geographiclib.Geodesic;
import net.sf.geographiclib.PolygonArea;
@@ -833,7 +834,7 @@ public class LatLong implements Serializable, Cloneable, Transferable, PamCoordi
*/
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("height");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/PamUtils/PamCalendar.java b/src/PamUtils/PamCalendar.java
index 452e06e5..7c4c3eb8 100644
--- a/src/PamUtils/PamCalendar.java
+++ b/src/PamUtils/PamCalendar.java
@@ -47,10 +47,7 @@ public class PamCalendar {
public static TimeZone defaultTimeZone = TimeZone.getTimeZone("UTC");
- /*
- * Not used: all now handled in PamCalendar.
- */
-// private static TimeZone localTimeZone = defaultTimeZone;// TimeZone.getDefault();
+ private static TimeZone localTimeZone = defaultTimeZone;// TimeZone.getDefault();
public static final long millisPerDay = 1000L*24L*3600L;
@@ -63,7 +60,7 @@ public class PamCalendar {
private static boolean soundFile;
/**
- * time from the start of the file to the current moment.
+ * time from the start of the file to the currentmoment.
* This is updated every time data re read from the file, so is
* accurate to about 1/10 second.
* For accurate timing within detectors, always try to use sample number
@@ -180,44 +177,8 @@ public class PamCalendar {
public static TimeZone getDisplayTimeZone(boolean useLocal) {
// return TimeZone.getTimeZone("UTC");
- return useLocal ? CalendarControl.getInstance().getChosenTimeZone() : defaultTimeZone;
-// return useLocal ? localTimeZone : defaultTimeZone;
- }
-
- /**
- * Get the display time zone offset in milliseconds.
- * @param useLocal
- * @return
- */
- public static long getDisplayTimeZoneOffest(boolean useLocal) {
- TimeZone tz = getDisplayTimeZone(useLocal);
- return tz.getOffset(getTimeInMillis());
- }
-
- /**
- * Get a short string describing the time zone. This should be less than
- * 10 characters. So if the full name of the TZ is long, then write it
- * in the format "UTC+..."
- * @param useLocal
- * @return
- */
- public static String getShortDisplayTimeZoneString(boolean useLocal) {
- TimeZone tz = getDisplayTimeZone(useLocal);
- String str = tz.getDisplayName();
- str = CalendarControl.getInstance().getTZCode(true);
- if (str.length() <= 10) {
- return str;
- }
- // otherwise make up a string.
- long offset = getDisplayTimeZoneOffest(useLocal) / 1000;
- boolean isInt = offset % 3600 == 0;
- if (isInt) {
- str = String.format("UTC%+d", offset/3600);
- }
- else {
- str = String.format("UTC%+3.1f", (double) offset/3600.);
- }
- return str;
+// return useLocal ? CalendarControl.getInstance().getChosenTimeZone() : defaultTimeZone;
+ return useLocal ? localTimeZone : defaultTimeZone;
}
public static String formatDateTime(Date date) {
@@ -430,13 +391,8 @@ public class PamCalendar {
public static String formatDBStyleTime(long timeInMillis, boolean showMillis, boolean useLocal) {
Calendar c = Calendar.getInstance();
- TimeZone tz = getDisplayTimeZone(useLocal);
-// if (tz != null) {
-// long offs = tz.getOffset(timeInMillis);
-// timeInMillis += tz.getOffset(timeInMillis);
-// }
c.setTimeInMillis(timeInMillis);
- c.setTimeZone(tz);
+ c.setTimeZone(getDisplayTimeZone(useLocal));
DateFormat df;
if (showMillis) {
df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
@@ -444,7 +400,7 @@ public class PamCalendar {
else {
df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
- df.setTimeZone(tz);
+ df.setTimeZone(getDisplayTimeZone(useLocal));
Date d = c.getTime();
// return String.format("%tY-% {
JComponent toolTipComponent;
+ /**
+ * Gets an adapter that can provide tooltips automatically based on plotted data units.
+ * @param component
+ * @return
+ */
public MouseHoverAdapter getMouseHoverAdapter(JComponent component) {
ToolTipManager tt = ToolTipManager.sharedInstance();
tt.registerComponent(component);
@@ -384,7 +389,9 @@ public abstract class GeneralProjector {
}
String hintText = dataBlock.getHoverText(this, hoveredDataUnit, hoverData.get(unitIndex).getAmbiguity());
- if (hintText == null) return null;
+ if (hintText == null) {
+ return null;
+ }
// System.out.println(hintText);
return hintText;
}
diff --git a/src/PamView/GroupedSourceParameters.java b/src/PamView/GroupedSourceParameters.java
index f26cdafd..fb0b7509 100644
--- a/src/PamView/GroupedSourceParameters.java
+++ b/src/PamView/GroupedSourceParameters.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamUtils.PamUtils;
import PamView.dialog.GroupedSourcePanel;
@@ -210,7 +211,7 @@ public class GroupedSourceParameters implements Serializable, Cloneable, Managed
*/
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/PamView/GuiFrameSettings.java b/src/PamView/GuiFrameSettings.java
index d367c1e3..3445c790 100644
--- a/src/PamView/GuiFrameSettings.java
+++ b/src/PamView/GuiFrameSettings.java
@@ -7,6 +7,7 @@ import java.util.ArrayList;
import PamController.PamControlledUnit;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
/**
@@ -55,7 +56,7 @@ public class GuiFrameSettings implements Serializable, Cloneable, ManagedParamet
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("unitFrameInfo");
ps.put(new PrivatePamParameterData(this, field) {
@@ -89,7 +90,7 @@ public class GuiFrameSettings implements Serializable, Cloneable, ManagedParamet
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("guiFrame");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/PamView/PamGui.java b/src/PamView/PamGui.java
index bbb4fc73..b5d91e8f 100644
--- a/src/PamView/PamGui.java
+++ b/src/PamView/PamGui.java
@@ -61,6 +61,7 @@ import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
+import javax.swing.JRootPane;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
@@ -73,6 +74,7 @@ import javax.swing.event.MenuListener;
import Acquisition.DaqSystemInterface;
import annotation.tasks.AnnotationManager;
+import metadata.MetaDataContol;
import performanceTests.PerformanceDialog;
import tipOfTheDay.TipOfTheDayManager;
import Array.ArrayManager;
@@ -601,6 +603,7 @@ public class PamGui extends PamView implements WindowListener, PamSettings {
fileMenu.add(menuItem);
}
+ // if (SMRUEnable.isEnable()) {
menuItem = new JMenuItem("Import PAMGuard Modules");
menuItem.setToolTipText("Import module settings from a different PAMGuard configuration (psfx files only");
menuItem.addActionListener(new ActionListener() {
@@ -610,6 +613,7 @@ public class PamGui extends PamView implements WindowListener, PamSettings {
}
});
fileMenu.add(menuItem);
+// }
fileMenu.addSeparator();
@@ -759,6 +763,7 @@ public class PamGui extends PamView implements WindowListener, PamSettings {
//for changing "hydrophones" to "microphone" and vice versa if medium changes.
menu.addMenuListener(new SettingsMenuListener());
+ menu.add(MetaDataContol.getMetaDataControl().createMenu(frame));
menu.addSeparator();
@@ -1664,10 +1669,10 @@ public class PamGui extends PamView implements WindowListener, PamSettings {
protected void getGuiParameters() {
guiParameters.extendedState = frame.getExtendedState();
guiParameters.state = frame.getState();
- if (guiParameters.state != Frame.MAXIMIZED_BOTH) {
+// if (guiParameters.state != Frame.MAXIMIZED_BOTH) {
guiParameters.size = frame.getSize();
guiParameters.bounds = frame.getBounds();
- }
+// }
}
/**
@@ -1982,6 +1987,30 @@ public class PamGui extends PamView implements WindowListener, PamSettings {
public PamTabbedPane getTabbedPane() {
return this.mainTab;
}
+
+ /**
+ * find a parent window for a JComponent. This can be useful in
+ * finding windows to open child dialogs when the object holding
+ * the component may not have a direct reference back to it's dialog.
+ * @param component any Swing component
+ * @return parent Window (or frame) if it can be found
+ */
+ public static Window findComponentWindow(JComponent component) {
+ if (component == null) {
+ return null;
+ }
+ JRootPane root = component.getRootPane();
+ if (root == null) {
+ return null;
+ }
+ Container rootP = root.getParent();
+ if (rootP instanceof Window) {
+ return (Window) rootP;
+ }
+ else {
+ return null;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/PamView/PamSymbol.java b/src/PamView/PamSymbol.java
index 00c471f6..2a4f4061 100644
--- a/src/PamView/PamSymbol.java
+++ b/src/PamView/PamSymbol.java
@@ -38,6 +38,7 @@ import javax.swing.JPanel;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamView.PamColors.PamColor;
import PamView.symbol.SymbolData;
@@ -808,7 +809,7 @@ public class PamSymbol extends PamSymbolBase implements Serializable, Icon, Clon
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/PamView/dialog/warn/WarnOnce.java b/src/PamView/dialog/warn/WarnOnce.java
index 93ed4618..cd7ad08d 100644
--- a/src/PamView/dialog/warn/WarnOnce.java
+++ b/src/PamView/dialog/warn/WarnOnce.java
@@ -48,6 +48,7 @@ public class WarnOnce implements PamSettings {
int ans = showWarning(parent, "Warning Messages", "Show all PAMGuard warning messages", WarnOnce.OK_CANCEL_OPTION);
if (ans == WarnOnce.CANCEL_OPTION) return;
singleInstance.warnOnceList.clearList();
+ singleInstance.showThisSess.clear();
}
@Override
diff --git a/src/PamView/paneloverlay/OverlayDataInfo.java b/src/PamView/paneloverlay/OverlayDataInfo.java
index 3c3ed86b..fd590d82 100644
--- a/src/PamView/paneloverlay/OverlayDataInfo.java
+++ b/src/PamView/paneloverlay/OverlayDataInfo.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class OverlayDataInfo implements Serializable, Cloneable, ManagedParameters {
@@ -31,7 +32,7 @@ public class OverlayDataInfo implements Serializable, Cloneable, ManagedParamete
*/
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/PamView/paneloverlay/overlaymark/MarkDataSelectorParams.java b/src/PamView/paneloverlay/overlaymark/MarkDataSelectorParams.java
index f6c8d446..ae081fc1 100644
--- a/src/PamView/paneloverlay/overlaymark/MarkDataSelectorParams.java
+++ b/src/PamView/paneloverlay/overlaymark/MarkDataSelectorParams.java
@@ -6,6 +6,7 @@ import java.util.Hashtable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import PamguardMVC.PamDataBlock;
@@ -73,7 +74,7 @@ public class MarkDataSelectorParams implements Serializable, Cloneable, ManagedP
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("overlayChoices");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/PamView/symbol/ManagedSymbolData.java b/src/PamView/symbol/ManagedSymbolData.java
index 23bb555d..19789f61 100644
--- a/src/PamView/symbol/ManagedSymbolData.java
+++ b/src/PamView/symbol/ManagedSymbolData.java
@@ -3,7 +3,11 @@ package PamView.symbol;
import java.io.Serializable;
import java.util.Hashtable;
-public class ManagedSymbolData implements Cloneable, Serializable {
+import PamModel.parametermanager.ManagedParameters;
+import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
+
+public class ManagedSymbolData implements Cloneable, Serializable, ManagedParameters {
public static final long serialVersionUID = 1L;
@@ -34,5 +38,10 @@ public class ManagedSymbolData implements Cloneable, Serializable {
return symbolOptions;
}
+ @Override
+ public PamParameterSet getParameterSet() {
+ return PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
+ }
+
}
diff --git a/src/PamView/wizard/PamWizard.java b/src/PamView/wizard/PamWizard.java
new file mode 100644
index 00000000..9ba67e01
--- /dev/null
+++ b/src/PamView/wizard/PamWizard.java
@@ -0,0 +1,160 @@
+package PamView.wizard;
+
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Component;
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+
+import javax.swing.JButton;
+import javax.swing.JPanel;
+
+import PamView.dialog.PamDialog;
+import tethys.swing.export.ExportStreamInfoPanel;
+import tethys.swing.export.ExportWizardCard;
+
+abstract public class PamWizard extends PamDialog {
+
+ private static final long serialVersionUID = 1L;
+
+ private JPanel cardPanel;
+
+ private CardLayout cardLayout;
+
+ private JPanel mainPanel;
+
+ private JButton prevButton;
+
+ private ArrayList wizardCards = new ArrayList();
+
+ public PamWizard(Window parentFrame, String title) {
+ super(parentFrame, title, false);
+
+ cardLayout = new CardLayout();
+ mainPanel = new JPanel(new BorderLayout());
+ cardPanel = new JPanel(cardLayout);
+ mainPanel.add(BorderLayout.CENTER, cardPanel);
+
+ setDialogComponent(mainPanel);
+
+ getOkButton().setText("Finish");
+ prevButton = new JButton("Previous");
+ getButtonPanel().add(prevButton, 0);
+ prevButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ previousButton();
+ }
+ });
+
+ setResizable(true);
+ }
+
+ public void addCard(PamWizardCard wizPanel) {
+ cardPanel.add(wizPanel, wizPanel.getTitle());
+ wizardCards.add(wizPanel);
+ }
+
+ /**
+ * Get the main panel. This is the main dialog panel and uses a borderlayout
+ * with the cards in the CENTER of the panel. Additional information panels
+ * (generally fixed and not changing with the dialog) can be added NORTH, SOUTH, WEST and EAST.
+ * @return main Panel.
+ */
+ public JPanel getMainPanel() {
+ return mainPanel;
+ }
+
+ /**
+ * Called when 'previous' button is clicked.
+ */
+ protected void previousButton() {
+ cardLayout.previous(cardPanel);
+ enableControls();
+ }
+
+ public void enableControls() {
+ int iCard = getCardIndex();
+ prevButton.setEnabled(iCard > 0);
+ boolean isLast = iCard == wizardCards.size()-1;
+// getOkButton().setEnabled(!isLast);
+ getOkButton().setText(isLast ? "Finish" : "Next");
+ }
+
+ private boolean checkCurrentCard() {
+ int iCard = getCardIndex();
+ if (iCard < 0) {
+ return true;
+ }
+ return getCardParams(wizardCards.get(iCard));
+ }
+
+ abstract public void setCardParams(PamWizardCard wizardCard);
+
+ abstract public boolean getCardParams(PamWizardCard wizardCard);
+
+ public int getCardIndex() {
+ for (int i = 0; i < cardPanel.getComponentCount(); i++) {
+ Component component = cardPanel.getComponent(i);
+ if (component.isVisible()) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public JButton getPreviousButton() {
+ return prevButton;
+ }
+
+ public void setParams() {
+ for (PamWizardCard wizCard : wizardCards) {
+ setCardParams(wizCard);
+ }
+ enableControls();
+ }
+
+ @Override
+ public boolean getParams() {
+ /**
+ * This is the OK button, so we need to NOT return OK, which would close the
+ * dialog until we're on the last card.
+ */
+ if (checkCurrentCard() == false) {
+ return false;
+ }
+ int iCard = getCardIndex();
+ if (iCard < wizardCards.size()-1) {
+ cardLayout.next(cardPanel);
+ enableControls();
+ return false;
+ }
+
+ return true;
+ }
+
+
+
+ @Override
+ public void restoreDefaultSettings() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * Move to the first card in the stack
+ */
+ public void moveFirst() {
+ cardLayout.first(cardPanel);
+ }
+
+ /**
+ * Move to the last card in the stack
+ */
+ public void moveLast() {
+ cardLayout.last(cardPanel);
+ }
+
+}
diff --git a/src/PamView/wizard/PamWizardCard.java b/src/PamView/wizard/PamWizardCard.java
new file mode 100644
index 00000000..bc0d9e14
--- /dev/null
+++ b/src/PamView/wizard/PamWizardCard.java
@@ -0,0 +1,45 @@
+package PamView.wizard;
+
+import java.io.Serializable;
+
+import javax.swing.JPanel;
+
+
+/**
+ * Base class for PAMGuard wizard cards.
+ * @author dg50
+ *
+ * @param class type for parameters to set and get.
+ */
+abstract public class PamWizardCard extends JPanel {
+
+ private static final long serialVersionUID = 1L;
+
+ private String title;
+
+ private PamWizard pamWizard;
+
+ /**
+ * @param title
+ */
+ public PamWizardCard(PamWizard pamWizard, String title) {
+ this.pamWizard = pamWizard;
+ this.title = title;
+ }
+
+ public abstract boolean getParams(T cardParams);
+
+ public abstract void setParams(T cardParams);
+
+ public String getTitle() {
+ return title;
+ }
+
+ /**
+ * @return the pamWizard
+ */
+ public PamWizard getPamWizard() {
+ return pamWizard;
+ }
+
+}
diff --git a/src/PamguardMVC/AcousticDataBlock.java b/src/PamguardMVC/AcousticDataBlock.java
index ec7477c1..f7fb5c8e 100644
--- a/src/PamguardMVC/AcousticDataBlock.java
+++ b/src/PamguardMVC/AcousticDataBlock.java
@@ -1,5 +1,8 @@
package PamguardMVC;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
import PamController.PamControllerInterface;
import PamguardMVC.nanotime.NanosFromSamples;
@@ -90,5 +93,12 @@ abstract public class AcousticDataBlock extends PamD
return parentSourceData;
}
+ @Override
+ public Element getDataBlockXML(Document doc) {
+ Element el = super.getDataBlockXML(doc);
+ el.setAttribute("SampleRate", String.format("%3.1f", getSampleRate()));
+ return el;
+ }
+
}
diff --git a/src/PamguardMVC/DataAutomation.java b/src/PamguardMVC/DataAutomation.java
new file mode 100644
index 00000000..cd424c60
--- /dev/null
+++ b/src/PamguardMVC/DataAutomation.java
@@ -0,0 +1,29 @@
+package PamguardMVC;
+
+/**
+ * @author dg50
+ * Levels of automation for the various datas in PAMGuard.
+ * Should be used within DataAutomationInfo to perhaps combine with other info in the future.
+ *
+ */
+public enum DataAutomation {
+
+ AUTOMATIC, MANUAL, MANUALANDAUTOMATIC;
+
+ @Override
+ public String toString() {
+ switch (this) {
+ case AUTOMATIC:
+ return "Automatic";
+ case MANUAL:
+ return "Manual";
+ case MANUALANDAUTOMATIC:
+ return "Manual and automatic";
+ default:
+ break;
+
+ }
+ return null;
+ }
+
+}
diff --git a/src/PamguardMVC/DataAutomationInfo.java b/src/PamguardMVC/DataAutomationInfo.java
new file mode 100644
index 00000000..42c7e42d
--- /dev/null
+++ b/src/PamguardMVC/DataAutomationInfo.java
@@ -0,0 +1,44 @@
+package PamguardMVC;
+
+/**
+ * Returned by datablocks, though default is null, to give information on how
+ * automatic the process was.
+ * @author dg50
+ *
+ */
+public class DataAutomationInfo {
+
+
+ private DataAutomation automation;
+
+ /**
+ * @param automation
+ */
+ public DataAutomationInfo(DataAutomation automation) {
+ this.setAutomation(automation);
+ }
+
+ /**
+ * @return the automation
+ */
+ public DataAutomation getAutomation() {
+ return automation;
+ }
+
+ /**
+ * @param automation the automation to set
+ */
+ public void setAutomation(DataAutomation automation) {
+ this.automation = automation;
+ }
+
+ @Override
+ public String toString() {
+ if (automation == null) {
+ return "Unknown data automation";
+ }
+ return automation.toString();
+ }
+
+
+}
diff --git a/src/PamguardMVC/DataBlock2D.java b/src/PamguardMVC/DataBlock2D.java
index beae1e15..89eb0ec9 100644
--- a/src/PamguardMVC/DataBlock2D.java
+++ b/src/PamguardMVC/DataBlock2D.java
@@ -1,5 +1,8 @@
package PamguardMVC;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
import dataPlotsFX.data.DataTypeInfo;
abstract public class DataBlock2D extends AcousticDataBlock {
@@ -39,4 +42,18 @@ abstract public class DataBlock2D extends AcousticDat
* @return data type information.
*/
abstract public DataTypeInfo getScaleInfo();
+
+ public Element getDataBlockXML(Document doc) {
+ Element el = super.getDataBlockXML(doc);
+ DataTypeInfo dti = getScaleInfo();
+ if (dti != null) {
+ if (dti.dataType != null) {
+ el.setAttribute("DataType", dti.dataType.toString());
+ }
+ if (dti.dataUnits != null) {
+ el.setAttribute("DataUnits", dti.dataUnits.toString());
+ }
+ }
+ return el;
+ }
}
diff --git a/src/PamguardMVC/PamDataBlock.java b/src/PamguardMVC/PamDataBlock.java
index 97bd709c..b865d572 100644
--- a/src/PamguardMVC/PamDataBlock.java
+++ b/src/PamguardMVC/PamDataBlock.java
@@ -44,10 +44,16 @@ import javax.swing.Timer;
import javax.swing.border.EmptyBorder;
import org.springframework.core.GenericTypeResolver;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
import Acquisition.AcquisitionControl;
import Acquisition.AcquisitionProcess;
import pamScrollSystem.ViewLoadObserver;
+import tethys.TethysControl;
+import tethys.pamdata.AutoTethysProvider;
+import tethys.pamdata.TethysDataProvider;
+import tethys.species.DataBlockSpeciesManager;
import dataGram.DatagramProvider;
import dataMap.BespokeDataMapGraphic;
import dataMap.OfflineDataMap;
@@ -62,6 +68,7 @@ import PamController.PamController;
import PamController.PamControllerInterface;
import PamDetection.LocContents;
import PamDetection.LocalisationInfo;
+import PamDetection.PamDetection;
import PamUtils.PamCalendar;
import PamUtils.PamUtils;
import PamView.symbol.PamSymbolManager;
@@ -69,8 +76,10 @@ import PamguardMVC.background.BackgroundDataBlock;
import PamguardMVC.background.BackgroundManager;
import PamguardMVC.dataOffline.OfflineDataLoadInfo;
import PamguardMVC.dataOffline.OfflineDataLoading;
+import PamguardMVC.dataSelector.DataSelectParams;
import PamguardMVC.dataSelector.DataSelector;
import PamguardMVC.dataSelector.DataSelectorCreator;
+import PamguardMVC.dataSelector.DataSelectorSettings;
import PamguardMVC.dataSelector.NullDataSelectorCreator;
import PamguardMVC.datamenus.DataMenuParent;
import PamguardMVC.nanotime.NanoTimeCalculator;
@@ -2833,7 +2842,7 @@ public class PamDataBlock extends PamObservable {
* @return temporary copy of the data
*/
public ArrayList getDataCopy(long t1, long t2, boolean assumeOrder, DataSelector dataSelector) {
- if (dataSelector == null) {
+ if (dataSelector == null || dataSelector.getParams().getCombinationFlag() == DataSelectParams.DATA_SELECT_DISABLE) {
return getDataCopy(t1, t2, assumeOrder);
}
else {
@@ -2865,6 +2874,7 @@ public class PamDataBlock extends PamObservable {
private SQLLogging logging;
private JSONObjectDataSource jsonDataSource;
+
public Vector getProcessAnnotations() {
return processAannotations;
@@ -3074,6 +3084,34 @@ public class PamDataBlock extends PamObservable {
public SQLLogging getLogging() {
return logging;
}
+
+ /**
+ * Gets a data provider for Tethys. These will probably need
+ * to be bespoke, but for now will autogenerate based on the SQLLogging information.
+ * @return the tethysDataProvider
+ */
+ public TethysDataProvider getTethysDataProvider(TethysControl tethysControl) {
+ return null;
+ }
+
+ /**
+ * Get the level of automation employed by the generation of these data.
+ * Should ideally be completed for everything providing data to Tethys.
+ * @return level of automation for this data block.
+ */
+ public DataAutomationInfo getDataAutomationInfo() {
+ return null;
+ }
+
+ /**
+ * Get information about species types that may occur within this data
+ * block. Primarily for conversion into Tethys compatible data, but may
+ * prove to have other uses.
+ * @return Types of species information available within this datablock.
+ */
+ public DataBlockSpeciesManager getDatablockSpeciesManager() {
+ return null;
+ }
final public boolean getCanLog() {
return (logging != null);
@@ -4229,4 +4267,23 @@ public class PamDataBlock extends PamObservable {
public void setBackgroundManager(BackgroundManager backgroundManager) {
this.backgroundManager = backgroundManager;
}
+
+ /**
+ * Get a brief summary of datablock to include in XML descriptions.
+ * Basic output is very simple. Expect other datablock to extend this by
+ * adding additional attributes.
+ * @param doc
+ * @return XML element with description of data.
+ */
+ public Element getDataBlockXML(Document doc) {
+ Element inputEl = doc.createElement("Input");
+ if (getParentProcess() != null && getParentProcess().getPamControlledUnit() != null) {
+ PamControlledUnit pcu = getParentProcess().getPamControlledUnit();
+ inputEl.setAttribute("ModuleType", pcu.getUnitType());
+ inputEl.setAttribute("ModuleName", pcu.getUnitName());
+ }
+ inputEl.setAttribute("Name", getLongDataName());
+ inputEl.setAttribute("Channels", String.format("0x%X", getChannelMap()));
+ return inputEl;
+ }
}
diff --git a/src/PamguardMVC/PamDataUnit.java b/src/PamguardMVC/PamDataUnit.java
index 3295381f..8630a7d1 100644
--- a/src/PamguardMVC/PamDataUnit.java
+++ b/src/PamguardMVC/PamDataUnit.java
@@ -974,8 +974,13 @@ abstract public class PamDataUnit
// add frequency and amplitude information
- str += "Frequency: " + FrequencyFormat.formatFrequencyRange(this.getFrequency(), true) + " ";
- str += String.format("Amplitude: %3.1fdB ", getAmplitudeDB());
+ double[] frequency = this.getFrequency();
+ if (frequency != null) {
+ str += "Frequency: " + FrequencyFormat.formatFrequencyRange(this.getFrequency(), true) + " ";
+ }
+ if (getAmplitudeDB() != 0) {
+ str += String.format("Amplitude: %3.1fdB ", getAmplitudeDB());
+ }
if (getSignalSPL() != null) {
str += String.format("SPL: %3.1fdBre1uPa ",linAmplitudeToDB(getSignalSPL()));
}
diff --git a/src/PamguardMVC/RawDataDisplayOptions.java b/src/PamguardMVC/RawDataDisplayOptions.java
index 9ed8355c..6ff49562 100644
--- a/src/PamguardMVC/RawDataDisplayOptions.java
+++ b/src/PamguardMVC/RawDataDisplayOptions.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class RawDataDisplayOptions implements Serializable, Cloneable, ManagedParameters {
@@ -13,7 +14,7 @@ public class RawDataDisplayOptions implements Serializable, Cloneable, ManagedPa
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/PamguardMVC/RawDataUnavailableException.java b/src/PamguardMVC/RawDataUnavailableException.java
index 581f981d..37e4275a 100644
--- a/src/PamguardMVC/RawDataUnavailableException.java
+++ b/src/PamguardMVC/RawDataUnavailableException.java
@@ -61,7 +61,7 @@ public class RawDataUnavailableException extends Exception {
return String.format("Samples %d length %d requested from %s have not yet arrived",
startSample, duration, rawDataBlock.getDataName());
case INVALID_CHANNEL_LIST:
- return String.format("Samples %d length %d requested from %s do not contain the reqeusted channels %s",
+ return String.format("Samples %d length %d requested from %s do not contain the reqeusted channels",
startSample, duration, rawDataBlock.getDataName());
case NEGATIVE_DURATION:
return String.format("Negative data duration request for %d samples" , duration);
diff --git a/src/PamguardMVC/blockprocess/PamBlockParams.java b/src/PamguardMVC/blockprocess/PamBlockParams.java
index 249d98e1..aaaed713 100644
--- a/src/PamguardMVC/blockprocess/PamBlockParams.java
+++ b/src/PamguardMVC/blockprocess/PamBlockParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import gpl.GPLParameters;
/**
@@ -44,7 +45,7 @@ public class PamBlockParams implements Cloneable, Serializable, ManagedParameter
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/PamguardMVC/dataSelector/DataSelectParams.java b/src/PamguardMVC/dataSelector/DataSelectParams.java
index da0f5e74..0d4af3fb 100644
--- a/src/PamguardMVC/dataSelector/DataSelectParams.java
+++ b/src/PamguardMVC/dataSelector/DataSelectParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Data select parameters.
@@ -53,7 +54,7 @@ abstract public class DataSelectParams implements Serializable, ManagedParameter
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/PamguardMVC/dataSelector/DataSelector.java b/src/PamguardMVC/dataSelector/DataSelector.java
index 0503479f..b033976c 100644
--- a/src/PamguardMVC/dataSelector/DataSelector.java
+++ b/src/PamguardMVC/dataSelector/DataSelector.java
@@ -9,7 +9,10 @@ import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JMenuItem;
+import org.w3c.dom.Document;
+
import PamController.PamController;
+import PamController.settings.output.xml.PamguardXMLWriter;
import PamView.dialog.PamDialogPanel;
import PamView.dialog.SettingsButton;
import PamguardMVC.PamDataBlock;
@@ -39,7 +42,7 @@ public abstract class DataSelector {
private String selectorTitle;
private boolean allowScores;
-
+
/**
* Create a data selector for a DataBlock. If allowScores is
* true, then the selector MAY (but may not) offer a more complicated
@@ -104,18 +107,8 @@ public abstract class DataSelector {
if (parentFrame == null) {
parentFrame = PamController.getMainFrame();
}
- Window localWin = parentFrame;
- DataSelectorChangeListener localChangeListener = changeListener;
JMenuItem menuItem = new JMenuItem("Data selection ...");
- menuItem.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- boolean ok = showSelectDialog(localWin);
- if (ok && changeListener != null) {
- changeListener.selectorChange(DataSelector.this);
- }
- }
- });
+ menuItem.addActionListener(new ShowSettingsButton(parentFrame, changeListener));
return menuItem;
}
@@ -129,6 +122,24 @@ public abstract class DataSelector {
return ok;
}
+ /**
+ * Get descriptive text about the data selector which can be
+ * added to dialogs and other information panels.
+ * @return descriptive text. Default is a xml dump of params.
+ */
+ public String getDescription() {
+ if (getParams() == null) {
+ return null;
+ }
+ PamguardXMLWriter xmlWriter = PamguardXMLWriter.getXMLWriter();
+ Document doc = xmlWriter.writeOneObject(getParams());
+ if (doc != null) {
+ String str = xmlWriter.getAsString(doc, true);
+ return str;
+ }
+ return null;
+ }
+
/**
* Score a PAMDataUnit. this is used in preference
* to a boolean select function so that the user can add different
@@ -228,25 +239,40 @@ public abstract class DataSelector {
* @param parentWindow
*/
public JButton getDialogButton(Window parentWindow) {
+ return getDialogButton(parentWindow, null);
+ }
+ /**
+ * Create a settings type button that can be inserted into a
+ * larger dialog.
+ * @param parentWindow
+ */
+
+ public JButton getDialogButton(Window parentWindow, DataSelectorChangeListener changeListener) {
JButton button = new SettingsButton();
- button.addActionListener(new ShowSettingsButton(parentWindow));
+ button.addActionListener(new ShowSettingsButton(parentWindow, changeListener));
button.setToolTipText("Data selection options for " + getSelectorTitle());
return button;
}
private class ShowSettingsButton implements ActionListener {
private Window parentWindow;
+ private DataSelectorChangeListener changeListener;
/**
* @param parentWindow
+ * @param changeListener
*/
- public ShowSettingsButton(Window parentWindow) {
+ public ShowSettingsButton(Window parentWindow, DataSelectorChangeListener changeListener) {
super();
this.parentWindow = parentWindow;
+ this.changeListener = changeListener;
}
@Override
public void actionPerformed(ActionEvent e) {
- showSelectDialog(parentWindow);
+ boolean ok = showSelectDialog(parentWindow);
+ if (ok && changeListener != null) {
+ changeListener.selectorChange(DataSelector.this);
+ }
}
}
diff --git a/src/PamguardMVC/dataSelector/DataSelectorSettings.java b/src/PamguardMVC/dataSelector/DataSelectorSettings.java
index f29c8103..df66d20e 100644
--- a/src/PamguardMVC/dataSelector/DataSelectorSettings.java
+++ b/src/PamguardMVC/dataSelector/DataSelectorSettings.java
@@ -7,6 +7,7 @@ import java.util.Hashtable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class DataSelectorSettings implements Serializable, ManagedParameters {
@@ -42,7 +43,7 @@ public class DataSelectorSettings implements Serializable, ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("selectorParams");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/PamguardMVC/datakeeper/DataKeeperSettings.java b/src/PamguardMVC/datakeeper/DataKeeperSettings.java
index 446669c6..3765ef72 100644
--- a/src/PamguardMVC/datakeeper/DataKeeperSettings.java
+++ b/src/PamguardMVC/datakeeper/DataKeeperSettings.java
@@ -7,6 +7,7 @@ import java.util.Hashtable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class DataKeeperSettings implements Serializable, Cloneable, ManagedParameters {
@@ -51,7 +52,7 @@ public class DataKeeperSettings implements Serializable, Cloneable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("keepTimeData");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/PamguardMVC/toad/GenericTOADSourceParams.java b/src/PamguardMVC/toad/GenericTOADSourceParams.java
index e0c2237c..cd12140a 100644
--- a/src/PamguardMVC/toad/GenericTOADSourceParams.java
+++ b/src/PamguardMVC/toad/GenericTOADSourceParams.java
@@ -6,6 +6,7 @@ import Localiser.DelayMeasurementParams;
import Localiser.controls.RawOrFFTParams;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* General parameters for detection TOAD measurement. Is split
@@ -67,7 +68,7 @@ public class GenericTOADSourceParams implements Cloneable, Serializable, Managed
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/RightWhaleEdgeDetector/RWEBinaryDataSource.java b/src/RightWhaleEdgeDetector/RWEBinaryDataSource.java
index c08a3f68..3b7546c2 100644
--- a/src/RightWhaleEdgeDetector/RWEBinaryDataSource.java
+++ b/src/RightWhaleEdgeDetector/RWEBinaryDataSource.java
@@ -218,7 +218,7 @@ public class RWEBinaryDataSource extends BinaryDataSource {
binaryObjectData.getDataUnitBaseData().setSampleDuration(duration);
// rweDataUnit = new RWEDataUnit(aSound.timeMilliseconds, channelMap,
// startSample, duration, aSound);
- rweDataUnit = new RWEDataUnit(binaryObjectData.getDataUnitBaseData(), aSound);
+ rweDataUnit = new RWEDataUnit(rweProcess, binaryObjectData.getDataUnitBaseData(), aSound);
rweDataUnit.setSequenceBitmap(sequenceMap);
double f[] = new double[2];
f[0] = aSound.minFreq * rweDataBlock.getSampleRate()/rweDataBlock.getFftLength();
diff --git a/src/RightWhaleEdgeDetector/RWEDataBlock.java b/src/RightWhaleEdgeDetector/RWEDataBlock.java
index 1969bca0..90c9a616 100644
--- a/src/RightWhaleEdgeDetector/RWEDataBlock.java
+++ b/src/RightWhaleEdgeDetector/RWEDataBlock.java
@@ -2,19 +2,29 @@ package RightWhaleEdgeDetector;
import PamView.GroupedDataSource;
import PamView.GroupedSourceParameters;
+import PamguardMVC.DataAutomation;
+import PamguardMVC.DataAutomationInfo;
import PamguardMVC.PamProcess;
import PamguardMVC.dataOffline.OfflineDataLoadInfo;
import PamguardMVC.dataSelector.DataSelectorCreator;
import RightWhaleEdgeDetector.datasel.RWDataSelCreator;
+import RightWhaleEdgeDetector.species.RWSpeciesManager;
+import RightWhaleEdgeDetector.species.RWTethysDataProvider;
import pamScrollSystem.ViewLoadObserver;
+import tethys.TethysControl;
+import tethys.pamdata.TethysDataProvider;
+import tethys.species.DataBlockSpeciesManager;
import whistlesAndMoans.AbstractWhistleDataBlock;
-public class RWEDataBlock extends AbstractWhistleDataBlock implements GroupedDataSource {
+public class RWEDataBlock extends AbstractWhistleDataBlock implements GroupedDataSource {
private double[] rwFreqRange = {50., 250.};
private RWEControl rweControl;
private RWEProcess rweProcess;
private RWDataSelCreator dataSelCreator;
+
+ private RWSpeciesManager rwSpeciesManager;
+ private RWTethysDataProvider rwTethysDataProvider;
public RWEDataBlock(RWEControl rweControl, String dataName,
RWEProcess rweProcess, int channelMap) {
@@ -53,4 +63,25 @@ public class RWEDataBlock extends AbstractWhistleDataBlock implements GroupedDat
return dataSelCreator;
}
+ @Override
+ public DataBlockSpeciesManager getDatablockSpeciesManager() {
+ if (rwSpeciesManager == null) {
+ rwSpeciesManager = new RWSpeciesManager(this);
+ }
+ return rwSpeciesManager;
+ }
+
+ @Override
+ public TethysDataProvider getTethysDataProvider(TethysControl tethysControl) {
+ if (rwTethysDataProvider == null) {
+ rwTethysDataProvider = new RWTethysDataProvider(tethysControl, rweProcess.getRweDataBlock());
+ }
+ return rwTethysDataProvider;
+ }
+
+ @Override
+ public DataAutomationInfo getDataAutomationInfo() {
+ return new DataAutomationInfo(DataAutomation.AUTOMATIC);
+ }
+
}
diff --git a/src/RightWhaleEdgeDetector/RWEDataUnit.java b/src/RightWhaleEdgeDetector/RWEDataUnit.java
index 226e0f64..c3144ebf 100644
--- a/src/RightWhaleEdgeDetector/RWEDataUnit.java
+++ b/src/RightWhaleEdgeDetector/RWEDataUnit.java
@@ -6,26 +6,31 @@ import whistlesAndMoans.AbstractWhistleDataUnit;
public class RWEDataUnit extends AbstractWhistleDataUnit {
public RWESound rweSound;
+ private RWEProcess rweProcess;
- public RWEDataUnit(long timeMilliseconds, int channelBitmap,
+ public RWEDataUnit(RWEProcess rweProcess, long timeMilliseconds, int channelBitmap,
long startSample, long duration, RWESound rweSound) {
super(timeMilliseconds, channelBitmap, startSample, duration);
this.rweSound = rweSound;
+ this.rweProcess = rweProcess;
// TODO Auto-generated constructor stub
}
- public RWEDataUnit(DataUnitBaseData basicData, RWESound rweSound) {
+ public RWEDataUnit(RWEProcess rweProcess, DataUnitBaseData basicData, RWESound rweSound) {
super(basicData);
this.rweSound = rweSound;
+ this.rweProcess = rweProcess;
}
- double[] freqsHz;
@Override
public double[] getFreqsHz() {
- if (freqsHz == null) {
- freqsHz = new double[rweSound.sliceCount];
+ double[] f = new double[rweSound.sliceCount];
+ RWEDataBlock rweDataBlock = rweProcess.getRweDataBlock();
+ double binToHz = rweDataBlock.getSampleRate() / rweDataBlock.getFftLength();
+ for (int i = 0; i < f.length; i++) {
+ f[i] = (double) rweSound.peakFreq[i] * binToHz;
}
- return null;
+ return f;
}
@Override
@@ -35,8 +40,16 @@ public class RWEDataUnit extends AbstractWhistleDataUnit {
@Override
public double[] getTimesInSeconds() {
- // TODO Auto-generated method stub
- return null;
+ if (rweSound == null) {
+ return null;
+ }
+ double[] t = new double[rweSound.sliceCount];
+ RWEDataBlock rweDataBlock = rweProcess.getRweDataBlock();
+ double binToT = rweDataBlock.getFftHop() / rweDataBlock.getSampleRate();
+ for (int i = 0; i < t.length; i++) {
+ t[i] = (double) rweSound.sliceList[i] * binToT;
+ }
+ return t;
}
@Override
diff --git a/src/RightWhaleEdgeDetector/RWEParameters.java b/src/RightWhaleEdgeDetector/RWEParameters.java
index 8bb661a4..4b179378 100644
--- a/src/RightWhaleEdgeDetector/RWEParameters.java
+++ b/src/RightWhaleEdgeDetector/RWEParameters.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class RWEParameters implements Serializable, Cloneable, ManagedParameters {
@@ -41,7 +42,7 @@ public class RWEParameters implements Serializable, Cloneable, ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/RightWhaleEdgeDetector/RWEProcess.java b/src/RightWhaleEdgeDetector/RWEProcess.java
index ccc766bb..081489c9 100644
--- a/src/RightWhaleEdgeDetector/RWEProcess.java
+++ b/src/RightWhaleEdgeDetector/RWEProcess.java
@@ -42,6 +42,10 @@ public class RWEProcess extends PamProcess {
private FFTDataBlock sourceDataBlock;
private RWEDataBlock rweDataBlock;
+ public RWEDataBlock getRweDataBlock() {
+ return rweDataBlock;
+ }
+
private Hashtable bearingLocalisers;
private StandardSymbolManager symbolManager;
/**
@@ -212,7 +216,7 @@ public class RWEProcess extends PamProcess {
// System.out.println(String.format("Detected sound type %d on channel %d",
// soundType, this.iChannel));
duration = sourceDataBlock.getFftHop() * aSound.duration;
- rweDataUnit = new RWEDataUnit(aSound.timeMilliseconds,
+ rweDataUnit = new RWEDataUnit(RWEProcess.this, aSound.timeMilliseconds,
1< {
+
+ private RWSpeciesTypes rwSpeciesTypes = new RWSpeciesTypes();
+
+ public RWSpeciesManager(PamDataBlock dataBlock) {
+ super(dataBlock);
+ setDefaultDefaultSpecies(new SpeciesMapItem(RWSpeciesTypes.eubalaena, RWSpeciesTypes.onlyType, RWSpeciesTypes.defaultName));
+ }
+
+ @Override
+ public DataBlockSpeciesCodes getSpeciesCodes() {
+ return null;
+ }
+
+ @Override
+ public String getSpeciesCode(RWEDataUnit dataUnit) {
+ return RWSpeciesTypes.defaultName;
+ }
+
+}
diff --git a/src/RightWhaleEdgeDetector/species/RWSpeciesTypes.java b/src/RightWhaleEdgeDetector/species/RWSpeciesTypes.java
new file mode 100644
index 00000000..654fe24c
--- /dev/null
+++ b/src/RightWhaleEdgeDetector/species/RWSpeciesTypes.java
@@ -0,0 +1,17 @@
+package RightWhaleEdgeDetector.species;
+
+import tethys.species.DataBlockSpeciesCodes;
+
+public class RWSpeciesTypes extends DataBlockSpeciesCodes {
+
+ public static final String onlyType = "Up call";
+
+ public static final int eubalaena = 180536;
+
+ public static final String defaultName = "Right Whale";
+
+ public RWSpeciesTypes() {
+ super(eubalaena, defaultName, onlyType);
+ }
+
+}
diff --git a/src/RightWhaleEdgeDetector/species/RWTethysDataProvider.java b/src/RightWhaleEdgeDetector/species/RWTethysDataProvider.java
new file mode 100644
index 00000000..3577bd12
--- /dev/null
+++ b/src/RightWhaleEdgeDetector/species/RWTethysDataProvider.java
@@ -0,0 +1,37 @@
+package RightWhaleEdgeDetector.species;
+
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamDataUnit;
+import RightWhaleEdgeDetector.RWEDataUnit;
+import nilus.Detection;
+import nilus.Detection.Parameters;
+import tethys.TethysControl;
+import tethys.output.StreamExportParams;
+import tethys.output.TethysExportParams;
+import tethys.pamdata.AutoTethysProvider;
+
+public class RWTethysDataProvider extends AutoTethysProvider {
+
+ public RWTethysDataProvider(TethysControl tethysControl, PamDataBlock pamDataBlock) {
+ super(tethysControl, pamDataBlock);
+ }
+
+ @Override
+ public Detection createDetection(PamDataUnit dataUnit, TethysExportParams tethysExportParams,
+ StreamExportParams streamExportParams) {
+ Detection detection = super.createDetection(dataUnit, tethysExportParams, streamExportParams);
+ if (detection == null) {
+ return null;
+ }
+
+ RWEDataUnit rweDataUnit = (RWEDataUnit) dataUnit;
+
+ Parameters parameters = detection.getParameters();
+ parameters.setScore((double) rweDataUnit.rweSound.soundType);
+ double snr = 20.*Math.log10(rweDataUnit.rweSound.signal/rweDataUnit.rweSound.noise);
+ parameters.setSNRDB(snr);
+
+ return detection;
+ }
+
+}
diff --git a/src/SoundRecorder/RecorderSettings.java b/src/SoundRecorder/RecorderSettings.java
index 72c9576d..4fcd6eec 100644
--- a/src/SoundRecorder/RecorderSettings.java
+++ b/src/SoundRecorder/RecorderSettings.java
@@ -16,6 +16,7 @@ import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterData;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamUtils.PamUtils;
import PamguardMVC.PamRawDataBlock;
import SoundRecorder.trigger.RecorderTrigger;
@@ -443,7 +444,7 @@ public class RecorderSettings implements Serializable, Cloneable, ManagedParamet
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("channelBitmap");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/SoundRecorder/trigger/RecorderTriggerData.java b/src/SoundRecorder/trigger/RecorderTriggerData.java
index 2192afc9..9b0cb32c 100644
--- a/src/SoundRecorder/trigger/RecorderTriggerData.java
+++ b/src/SoundRecorder/trigger/RecorderTriggerData.java
@@ -6,6 +6,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Information for triggered recordings to tell each recorder how long
@@ -271,7 +272,7 @@ public class RecorderTriggerData implements Serializable, Cloneable, ManagedPara
*/
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("lastTriggerStart");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/Spectrogram/SpectrogramDisplay.java b/src/Spectrogram/SpectrogramDisplay.java
index 5c86913a..08a7bf2d 100644
--- a/src/Spectrogram/SpectrogramDisplay.java
+++ b/src/Spectrogram/SpectrogramDisplay.java
@@ -1652,6 +1652,9 @@ InternalFrameListener, DisplayPanelContainer, SpectrogramParametersUser, PamSett
return;
}
long t1 = dataUnit.getTimeMilliseconds()-viewerScroller.getValueMillis();
+ if (timeAxis == null) {
+ return;
+ }
int x1 = (int) Math.floor(timeAxis.getPosition(t1/1000));
int x2 = x1;
if (dataUnit.getDurationInMilliseconds() != null) {
diff --git a/src/alarm/AlarmParameters.java b/src/alarm/AlarmParameters.java
index df89b940..0694adfc 100644
--- a/src/alarm/AlarmParameters.java
+++ b/src/alarm/AlarmParameters.java
@@ -6,6 +6,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
public class AlarmParameters implements Serializable, Cloneable, ManagedParameters {
@@ -103,7 +104,7 @@ public class AlarmParameters implements Serializable, Cloneable, ManagedParamete
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("hadHold");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/alarm/actions/email/SendEmailSettings.java b/src/alarm/actions/email/SendEmailSettings.java
index dcd4dc0b..da558c85 100644
--- a/src/alarm/actions/email/SendEmailSettings.java
+++ b/src/alarm/actions/email/SendEmailSettings.java
@@ -28,6 +28,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import alarm.actions.serial.AlarmSerialSettings;
/**
@@ -158,7 +159,7 @@ public class SendEmailSettings implements Serializable, Cloneable, ManagedParame
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/alarm/actions/serial/AlarmSerialSettings.java b/src/alarm/actions/serial/AlarmSerialSettings.java
index b14e785c..801cc765 100644
--- a/src/alarm/actions/serial/AlarmSerialSettings.java
+++ b/src/alarm/actions/serial/AlarmSerialSettings.java
@@ -8,6 +8,7 @@ import com.fazecast.jSerialComm.SerialPort;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import serialComms.SerialPortConstants;
import serialComms.jserialcomm.PJSerialComm;
@@ -68,7 +69,7 @@ public class AlarmSerialSettings implements Serializable, Cloneable, ManagedPar
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/alarm/actions/sound/PlaySoundParams.java b/src/alarm/actions/sound/PlaySoundParams.java
index c9f97970..6481e41d 100644
--- a/src/alarm/actions/sound/PlaySoundParams.java
+++ b/src/alarm/actions/sound/PlaySoundParams.java
@@ -6,6 +6,7 @@ import java.util.Arrays;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import alarm.AlarmParameters;
public class PlaySoundParams implements Cloneable, Serializable, ManagedParameters {
@@ -33,7 +34,7 @@ public class PlaySoundParams implements Cloneable, Serializable, ManagedParamete
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/alarm/actions/udp/AlarmUDPParams.java b/src/alarm/actions/udp/AlarmUDPParams.java
index 10728bb2..7a7bfa61 100644
--- a/src/alarm/actions/udp/AlarmUDPParams.java
+++ b/src/alarm/actions/udp/AlarmUDPParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class AlarmUDPParams implements Serializable, Cloneable, ManagedParameters {
@@ -25,7 +26,7 @@ public class AlarmUDPParams implements Serializable, Cloneable, ManagedParameter
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/amplifier/AmpParameters.java b/src/amplifier/AmpParameters.java
index 98e52a63..89aac38c 100644
--- a/src/amplifier/AmpParameters.java
+++ b/src/amplifier/AmpParameters.java
@@ -5,6 +5,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import PamguardMVC.PamConstants;
@@ -41,7 +42,7 @@ public class AmpParameters implements Cloneable, Serializable, ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("rawDataSource");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/analogarraysensor/ArraySensorLogging.java b/src/analogarraysensor/ArraySensorLogging.java
index e4eba2e9..ca13752a 100644
--- a/src/analogarraysensor/ArraySensorLogging.java
+++ b/src/analogarraysensor/ArraySensorLogging.java
@@ -56,7 +56,8 @@ public class ArraySensorLogging extends SQLLogging {
AnalogSensorData aData = new AnalogSensorData(rawValue, calValue);
sensorData[i] = aData;
}
- int chanMap = getTableDefinition().getChannelBitmap().getIntegerValue();
+ PamTableDefinition pamTableDef = (PamTableDefinition) getTableDefinition();
+ int chanMap = pamTableDef.getChannelBitmap().getIntegerValue();
int streamer = PamUtils.getSingleChannel(chanMap);
if (streamer < 0) streamer = 0;
AnalogArraySensorDataUnit asdu = new AnalogArraySensorDataUnit(timeMilliseconds, streamer, sensorData);
diff --git a/src/analogarraysensor/ArraySensorParams.java b/src/analogarraysensor/ArraySensorParams.java
index c59d31eb..b84081a6 100644
--- a/src/analogarraysensor/ArraySensorParams.java
+++ b/src/analogarraysensor/ArraySensorParams.java
@@ -5,6 +5,7 @@ import java.io.Serializable;
import Array.sensors.ArrayDisplayParameters;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class ArraySensorParams implements Serializable, Cloneable, ManagedParameters {
@@ -47,7 +48,7 @@ public class ArraySensorParams implements Serializable, Cloneable, ManagedParame
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/analoginput/AnalogDeviceParams.java b/src/analoginput/AnalogDeviceParams.java
index 1b43c7b9..cae97232 100644
--- a/src/analoginput/AnalogDeviceParams.java
+++ b/src/analoginput/AnalogDeviceParams.java
@@ -6,6 +6,7 @@ import java.util.Hashtable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import analoginput.calibration.CalibrationData;
@@ -63,7 +64,7 @@ public class AnalogDeviceParams implements Serializable, Cloneable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("calibrationTable");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/analoginput/AnalogInputParams.java b/src/analoginput/AnalogInputParams.java
index acd041e4..a64d51ba 100644
--- a/src/analoginput/AnalogInputParams.java
+++ b/src/analoginput/AnalogInputParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class AnalogInputParams implements Serializable, Cloneable, ManagedParameters {
@@ -13,7 +14,7 @@ public class AnalogInputParams implements Serializable, Cloneable, ManagedParame
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/analoginput/AnalogRangeData.java b/src/analoginput/AnalogRangeData.java
index 00043994..7a7d7109 100644
--- a/src/analoginput/AnalogRangeData.java
+++ b/src/analoginput/AnalogRangeData.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class AnalogRangeData implements Serializable, Cloneable, Comparable, ManagedParameters {
@@ -119,7 +120,7 @@ public class AnalogRangeData implements Serializable, Cloneable, Comparable 0) {
diff --git a/src/annotation/timestamp/TimestampSQLLogging.java b/src/annotation/timestamp/TimestampSQLLogging.java
index fd1d7be6..2f6b0728 100644
--- a/src/annotation/timestamp/TimestampSQLLogging.java
+++ b/src/annotation/timestamp/TimestampSQLLogging.java
@@ -3,6 +3,7 @@ package annotation.timestamp;
import java.sql.Types;
import PamguardMVC.PamDataUnit;
+import generalDatabase.EmptyTableDefinition;
import generalDatabase.PamTableDefinition;
import generalDatabase.PamTableItem;
import generalDatabase.SQLLoggingAddon;
@@ -22,12 +23,12 @@ public class TimestampSQLLogging implements SQLLoggingAddon {
}
@Override
- public void addTableItems(PamTableDefinition pamTableDefinition) {
+ public void addTableItems(EmptyTableDefinition pamTableDefinition) {
pamTableDefinition.addTableItem(timestamp);
}
@Override
- public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
+ public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
TimestampAnnotation timestampAnnotation = (TimestampAnnotation) pamDataUnit.findDataAnnotation(TimestampAnnotation.class,
timestampAnnotationType.getAnnotationName());
if (timestampAnnotation == null) {
@@ -40,7 +41,7 @@ public class TimestampSQLLogging implements SQLLoggingAddon {
}
@Override
- public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
+ public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
try {
TimestampAnnotation timestampAnnotation = new TimestampAnnotation(timestampAnnotationType);
Long note = sqlTypes.millisFromTimeStamp(timestamp.getValue());
diff --git a/src/annotation/userforms/UserFormSQLAddon.java b/src/annotation/userforms/UserFormSQLAddon.java
index fb5a20f0..8156bfda 100644
--- a/src/annotation/userforms/UserFormSQLAddon.java
+++ b/src/annotation/userforms/UserFormSQLAddon.java
@@ -3,6 +3,7 @@ package annotation.userforms;
import java.util.ArrayList;
import PamguardMVC.PamDataUnit;
+import generalDatabase.EmptyTableDefinition;
import generalDatabase.PamTableDefinition;
import generalDatabase.PamTableItem;
import generalDatabase.SQLLoggingAddon;
@@ -32,7 +33,7 @@ public class UserFormSQLAddon implements SQLLoggingAddon {
@Override
- public void addTableItems(PamTableDefinition pamTableDefinition) {
+ public void addTableItems(EmptyTableDefinition pamTableDefinition) {
loggerTableItems.clear();
FormDescription formDescription = userFormAnnotationType.findFormDescription();
if (formDescription == null) {
@@ -58,7 +59,7 @@ public class UserFormSQLAddon implements SQLLoggingAddon {
}
@Override
- public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
+ public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
if (pamDataUnit == null) {
clearTableItems();
return false;
@@ -103,7 +104,7 @@ public class UserFormSQLAddon implements SQLLoggingAddon {
}
@Override
- public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
+ public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
FormDescription formDescription = userFormAnnotationType.findFormDescription();
if (formDescription == null) {
return false;
diff --git a/src/annotationMark/spectrogram/SpectrogramMarkParams.java b/src/annotationMark/spectrogram/SpectrogramMarkParams.java
index 0d65e6e4..89540c01 100644
--- a/src/annotationMark/spectrogram/SpectrogramMarkParams.java
+++ b/src/annotationMark/spectrogram/SpectrogramMarkParams.java
@@ -5,6 +5,7 @@ import java.util.List;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import annotation.DataAnnotationType;
import annotation.handler.AnnotationChoices;
@@ -31,7 +32,7 @@ public class SpectrogramMarkParams implements Serializable, ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/backupmanager/FileLocation.java b/src/backupmanager/FileLocation.java
index 1508125a..6557821d 100644
--- a/src/backupmanager/FileLocation.java
+++ b/src/backupmanager/FileLocation.java
@@ -5,6 +5,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Information on a file path or folder path that can be used with the
@@ -42,7 +43,7 @@ public class FileLocation implements Serializable, Cloneable, ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/backupmanager/settings/BackupSettings.java b/src/backupmanager/settings/BackupSettings.java
index 71b90fda..bc9ac14c 100644
--- a/src/backupmanager/settings/BackupSettings.java
+++ b/src/backupmanager/settings/BackupSettings.java
@@ -6,6 +6,7 @@ import java.util.List;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public abstract class BackupSettings implements Serializable, Cloneable, ManagedParameters {
@@ -40,7 +41,7 @@ public abstract class BackupSettings implements Serializable, Cloneable, Managed
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/beamformer/BeamAlgorithmParams.java b/src/beamformer/BeamAlgorithmParams.java
index 7cde91b4..eabdb943 100644
--- a/src/beamformer/BeamAlgorithmParams.java
+++ b/src/beamformer/BeamAlgorithmParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import beamformer.algorithms.basicFreqDomain.BasicFreqDomParams;
/*
@@ -336,7 +337,7 @@ public abstract class BeamAlgorithmParams implements Serializable, Cloneable, Ma
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/beamformer/BeamFormerParams.java b/src/beamformer/BeamFormerParams.java
index f5cc3f5d..d6082a1d 100644
--- a/src/beamformer/BeamFormerParams.java
+++ b/src/beamformer/BeamFormerParams.java
@@ -6,6 +6,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import PamUtils.DeepCloner;
import PamView.GroupedSourceParameters;
@@ -325,7 +326,7 @@ public class BeamFormerParams implements Cloneable, Serializable, ManagedParamet
*/
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("algorithmParamsTable");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/beamformer/annotation/BFAnnotationLogging.java b/src/beamformer/annotation/BFAnnotationLogging.java
index 83d7641a..ba9bed54 100644
--- a/src/beamformer/annotation/BFAnnotationLogging.java
+++ b/src/beamformer/annotation/BFAnnotationLogging.java
@@ -6,6 +6,7 @@ import PamDetection.LocContents;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
import beamformer.loc.BeamFormerLocalisation;
+import generalDatabase.EmptyTableDefinition;
import generalDatabase.PamTableDefinition;
import generalDatabase.PamTableItem;
import generalDatabase.SQLLoggingAddon;
@@ -29,7 +30,7 @@ public class BFAnnotationLogging implements SQLLoggingAddon {
}
@Override
- public void addTableItems(PamTableDefinition pamTableDefinition) {
+ public void addTableItems(EmptyTableDefinition pamTableDefinition) {
pamTableDefinition.addTableItem(bfPhones);
pamTableDefinition.addTableItem(bfArrayType);
pamTableDefinition.addTableItem(bfContents);
@@ -38,7 +39,7 @@ public class BFAnnotationLogging implements SQLLoggingAddon {
}
@Override
- public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
+ public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
bfPhones.setValue(null);
bfArrayType.setValue(null);
bfContents.setValue(null);
@@ -64,7 +65,7 @@ public class BFAnnotationLogging implements SQLLoggingAddon {
}
@Override
- public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
+ public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
Float[] Angles = new Float[2];
for (int i = 0; i < 2; i++) {
Angles[i] = (Float) angle[i].getFloatValue();
diff --git a/src/bearinglocaliser/BearingLocaliserParams.java b/src/bearinglocaliser/BearingLocaliserParams.java
index 277c8e5d..d697781c 100644
--- a/src/bearinglocaliser/BearingLocaliserParams.java
+++ b/src/bearinglocaliser/BearingLocaliserParams.java
@@ -8,6 +8,7 @@ import java.util.HashMap;
import Localiser.controls.RawOrFFTParamsInterface;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import PamView.GroupedSourceParameters;
import bearinglocaliser.algorithms.BearingAlgorithmParams;
@@ -188,7 +189,7 @@ public class BearingLocaliserParams implements Serializable, Cloneable, RawOrFFT
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("algorithmParamsTable");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/bearinglocaliser/algorithms/BearingAlgorithmParams.java b/src/bearinglocaliser/algorithms/BearingAlgorithmParams.java
index 3b6c0bed..cea3e25f 100644
--- a/src/bearinglocaliser/algorithms/BearingAlgorithmParams.java
+++ b/src/bearinglocaliser/algorithms/BearingAlgorithmParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class BearingAlgorithmParams implements Serializable, Cloneable, ManagedParameters {
@@ -60,7 +61,7 @@ public class BearingAlgorithmParams implements Serializable, Cloneable, ManagedP
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/bearinglocaliser/annotation/BearingAnnotationSQL.java b/src/bearinglocaliser/annotation/BearingAnnotationSQL.java
index bc4b88bb..d56e8be7 100644
--- a/src/bearinglocaliser/annotation/BearingAnnotationSQL.java
+++ b/src/bearinglocaliser/annotation/BearingAnnotationSQL.java
@@ -4,6 +4,7 @@ import java.sql.Types;
import PamguardMVC.PamDataUnit;
import bearinglocaliser.BearingLocalisation;
+import generalDatabase.EmptyTableDefinition;
import generalDatabase.PamTableDefinition;
import generalDatabase.PamTableItem;
import generalDatabase.SQLLoggingAddon;
@@ -34,7 +35,7 @@ public class BearingAnnotationSQL implements SQLLoggingAddon {
}
@Override
- public void addTableItems(PamTableDefinition pamTableDefinition) {
+ public void addTableItems(EmptyTableDefinition pamTableDefinition) {
pamTableDefinition.addTableItem(algoName);
pamTableDefinition.addTableItem(bfPhones);
pamTableDefinition.addTableItem(bfArrayType);
@@ -48,7 +49,7 @@ public class BearingAnnotationSQL implements SQLLoggingAddon {
}
@Override
- public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
+ public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
algoName.setValue(null);
bfPhones.setValue(null);
bfArrayType.setValue(null);
@@ -96,7 +97,7 @@ public class BearingAnnotationSQL implements SQLLoggingAddon {
}
@Override
- public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
+ public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
Float[] Angles = new Float[2];
int nNans = 0;
for (int i = 0; i < 2; i++) {
diff --git a/src/binaryFileStorage/BinaryFooter.java b/src/binaryFileStorage/BinaryFooter.java
index 98142a16..f410998b 100644
--- a/src/binaryFileStorage/BinaryFooter.java
+++ b/src/binaryFileStorage/BinaryFooter.java
@@ -7,6 +7,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamUtils.PamCalendar;
public class BinaryFooter implements Serializable, ManagedParameters {
@@ -230,7 +231,7 @@ public class BinaryFooter implements Serializable, ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/binaryFileStorage/BinaryHeader.java b/src/binaryFileStorage/BinaryHeader.java
index b27652ec..b1d7a986 100644
--- a/src/binaryFileStorage/BinaryHeader.java
+++ b/src/binaryFileStorage/BinaryHeader.java
@@ -9,6 +9,7 @@ import java.lang.reflect.Field;
import PamController.PamguardVersionInfo;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import PamUtils.PamCalendar;
@@ -289,7 +290,7 @@ public class BinaryHeader implements Serializable, ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("pamguard");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/binaryFileStorage/BinarySettingsStorage.java b/src/binaryFileStorage/BinarySettingsStorage.java
index 48278c1d..c59992d8 100644
--- a/src/binaryFileStorage/BinarySettingsStorage.java
+++ b/src/binaryFileStorage/BinarySettingsStorage.java
@@ -110,6 +110,12 @@ public class BinarySettingsStorage implements PamSettingsSource {
return false;*/
}
+ @Override
+ public boolean saveEndSettings(long timeNow) {
+ // do nothing at the end of a run with binary store.
+ return true;
+ }
+
// private boolean writeData(DataOutputStream dos, int objectId, byte[] data) {
// int totalLen = data.length + 16;
// int dataLen = data.length;
diff --git a/src/binaryFileStorage/BinaryStore.java b/src/binaryFileStorage/BinaryStore.java
index 3db5fd66..e01cc9b4 100644
--- a/src/binaryFileStorage/BinaryStore.java
+++ b/src/binaryFileStorage/BinaryStore.java
@@ -561,6 +561,12 @@ PamSettingsSource, DataOutputStore {
return binarySettingsStorage.saveStartSettings(timeNow);
}
+ @Override
+ public boolean saveEndSettings(long timeNow) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
@Override
public int getNumSettings() {
if (binarySettingsStorage == null) {
@@ -2583,5 +2589,9 @@ PamSettingsSource, DataOutputStore {
}
return state;
}
+
+ public String getDataLocation() {
+ return binaryStoreSettings.getStoreLocation();
+ }
}
diff --git a/src/binaryFileStorage/BinaryStoreSettings.java b/src/binaryFileStorage/BinaryStoreSettings.java
index 441baddd..78c42e99 100644
--- a/src/binaryFileStorage/BinaryStoreSettings.java
+++ b/src/binaryFileStorage/BinaryStoreSettings.java
@@ -6,6 +6,7 @@ import java.io.Serializable;
import PamController.PamFolders;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class BinaryStoreSettings implements Serializable, Cloneable, ManagedParameters {
@@ -90,7 +91,7 @@ public class BinaryStoreSettings implements Serializable, Cloneable, ManagedPara
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/cepstrum/CepstrumParams.java b/src/cepstrum/CepstrumParams.java
index a24fab3a..59f6fbb9 100644
--- a/src/cepstrum/CepstrumParams.java
+++ b/src/cepstrum/CepstrumParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class CepstrumParams implements Serializable, Cloneable, ManagedParameters {
@@ -25,7 +26,7 @@ public class CepstrumParams implements Serializable, Cloneable, ManagedParameter
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
}
diff --git a/src/clickDetector/BTDisplayParameters.java b/src/clickDetector/BTDisplayParameters.java
index 143b3eab..bf9604f7 100644
--- a/src/clickDetector/BTDisplayParameters.java
+++ b/src/clickDetector/BTDisplayParameters.java
@@ -6,6 +6,7 @@ import java.util.Arrays;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import clickDetector.tdPlots.ClickSymbolOptions;
@@ -137,7 +138,7 @@ public class BTDisplayParameters implements Serializable, Cloneable, ManagedPara
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("showSpeciesList");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/clickDetector/BasicClickIdParameters.java b/src/clickDetector/BasicClickIdParameters.java
index feeefb67..6cc5925c 100644
--- a/src/clickDetector/BasicClickIdParameters.java
+++ b/src/clickDetector/BasicClickIdParameters.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
@@ -83,7 +84,7 @@ public class BasicClickIdParameters implements Serializable, Cloneable, ManagedP
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/clickDetector/ClickAlarm.java b/src/clickDetector/ClickAlarm.java
index f9459296..515945ab 100644
--- a/src/clickDetector/ClickAlarm.java
+++ b/src/clickDetector/ClickAlarm.java
@@ -33,6 +33,7 @@ import javax.sound.sampled.Clip;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
/**
@@ -209,7 +210,7 @@ public class ClickAlarm implements Comparable, Serializable, Cloneab
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("fileIsLoaded");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/clickDetector/ClickBinaryModuleFooter.java b/src/clickDetector/ClickBinaryModuleFooter.java
index 35718e17..f24ed53c 100644
--- a/src/clickDetector/ClickBinaryModuleFooter.java
+++ b/src/clickDetector/ClickBinaryModuleFooter.java
@@ -12,6 +12,7 @@ import PamController.PamController;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import binaryFileStorage.BinaryHeader;
import binaryFileStorage.BinaryObjectData;
import binaryFileStorage.ModuleFooter;
@@ -128,7 +129,7 @@ public class ClickBinaryModuleFooter extends ModuleFooter implements ManagedPara
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("clickDetectorName");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/clickDetector/ClickBinaryModuleHeader.java b/src/clickDetector/ClickBinaryModuleHeader.java
index 1cb7f8d8..f36f7854 100644
--- a/src/clickDetector/ClickBinaryModuleHeader.java
+++ b/src/clickDetector/ClickBinaryModuleHeader.java
@@ -2,6 +2,7 @@ package clickDetector;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import binaryFileStorage.BinaryHeader;
import binaryFileStorage.BinaryObjectData;
import binaryFileStorage.ModuleHeader;
@@ -28,7 +29,7 @@ public class ClickBinaryModuleHeader extends ModuleHeader implements ManagedPara
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
}
diff --git a/src/clickDetector/ClickClassifiers/ClickBlockSpeciesManager.java b/src/clickDetector/ClickClassifiers/ClickBlockSpeciesManager.java
new file mode 100644
index 00000000..89812008
--- /dev/null
+++ b/src/clickDetector/ClickClassifiers/ClickBlockSpeciesManager.java
@@ -0,0 +1,52 @@
+package clickDetector.ClickClassifiers;
+
+import clickDetector.ClickControl;
+import clickDetector.ClickDataBlock;
+import clickDetector.ClickDetection;
+import tethys.species.DataBlockSpeciesManager;
+import tethys.species.DataBlockSpeciesCodes;
+import tethys.species.ITISTypes;
+import tethys.species.SpeciesMapItem;
+
+public class ClickBlockSpeciesManager extends DataBlockSpeciesManager {
+
+ private ClickControl clickControl;
+
+ public ClickBlockSpeciesManager(ClickControl clickControl, ClickDataBlock clickDataBlock) {
+ super(clickDataBlock);
+ this.clickControl = clickControl;
+ setDefaultDefaultSpecies(new SpeciesMapItem(ITISTypes.UNKNOWN, "Unknown", "Unknown"));
+ setDefaultSpeciesCode("Unknown");
+ }
+
+ @Override
+ public DataBlockSpeciesCodes getSpeciesCodes() {
+ ClickTypeMasterManager masterManager = clickControl.getClickTypeMasterManager();
+ if (masterManager == null) {
+ return null;
+ }
+ String[] speciesList = masterManager.getSpeciesList();
+ // add the default
+ String[] fullList = new String[speciesList.length+1];
+ fullList[0] = getDefaultSpeciesCode();
+ for (int i = 0; i < speciesList.length; i++) {
+ fullList[i+1] = speciesList[i];
+ }
+
+ return new DataBlockSpeciesCodes("Click", fullList);
+ }
+
+ @Override
+ public String getSpeciesCode(ClickDetection dataUnit) {
+ ClickTypeMasterManager masterManager = clickControl.getClickTypeMasterManager();
+ if (masterManager == null) {
+ return null;
+ }
+ int listIndex = masterManager.codeToListIndex(dataUnit.getClickType());
+ if (listIndex < 0) {
+ return null;
+ }
+ return masterManager.getSpeciesList()[listIndex];
+ }
+
+}
diff --git a/src/clickDetector/ClickClassifiers/ClickTypeCommonParams.java b/src/clickDetector/ClickClassifiers/ClickTypeCommonParams.java
index d937b164..78b56316 100644
--- a/src/clickDetector/ClickClassifiers/ClickTypeCommonParams.java
+++ b/src/clickDetector/ClickClassifiers/ClickTypeCommonParams.java
@@ -28,6 +28,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Superclass for click parameters, including the ClickTypeParms and
@@ -191,7 +192,7 @@ abstract public class ClickTypeCommonParams implements Cloneable, Serializable,
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/clickDetector/ClickClassifiers/annotation/ClickAnnotationSQL.java b/src/clickDetector/ClickClassifiers/annotation/ClickAnnotationSQL.java
index baa057ac..840d2086 100644
--- a/src/clickDetector/ClickClassifiers/annotation/ClickAnnotationSQL.java
+++ b/src/clickDetector/ClickClassifiers/annotation/ClickAnnotationSQL.java
@@ -3,6 +3,7 @@ package clickDetector.ClickClassifiers.annotation;
import java.sql.Types;
import PamguardMVC.PamDataUnit;
+import generalDatabase.EmptyTableDefinition;
import generalDatabase.PamTableDefinition;
import generalDatabase.PamTableItem;
import generalDatabase.SQLLoggingAddon;
@@ -33,12 +34,12 @@ public class ClickAnnotationSQL implements SQLLoggingAddon {
}
@Override
- public void addTableItems(PamTableDefinition pamTableDefinition) {
+ public void addTableItems(EmptyTableDefinition pamTableDefinition) {
pamTableDefinition.addTableItem(classifierSetTable);
}
@Override
- public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
+ public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
ClickClassifierAnnotation clickAnnotation = (ClickClassifierAnnotation) pamDataUnit.findDataAnnotation(ClickClassificationType.class);
//create a comma delimited string
@@ -53,7 +54,7 @@ public class ClickAnnotationSQL implements SQLLoggingAddon {
@Override
- public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
+ public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
String array = classifierSetTable.getDeblankedStringValue();
//read in the classification set. This a list of all the classifiers the clicks passed.
diff --git a/src/clickDetector/ClickClassifiers/basicSweep/SweepClassifierParameters.java b/src/clickDetector/ClickClassifiers/basicSweep/SweepClassifierParameters.java
index 9c925607..6cc4f1b5 100644
--- a/src/clickDetector/ClickClassifiers/basicSweep/SweepClassifierParameters.java
+++ b/src/clickDetector/ClickClassifiers/basicSweep/SweepClassifierParameters.java
@@ -7,6 +7,7 @@ import java.util.Vector;
import PamModel.SMRUEnable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
public class SweepClassifierParameters implements Serializable, Cloneable, ManagedParameters {
@@ -72,7 +73,7 @@ public class SweepClassifierParameters implements Serializable, Cloneable, Manag
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("classifierSets");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/clickDetector/ClickControl.java b/src/clickDetector/ClickControl.java
index e03b73a7..9787c59f 100644
--- a/src/clickDetector/ClickControl.java
+++ b/src/clickDetector/ClickControl.java
@@ -26,6 +26,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.List;
import java.util.ListIterator;
import javax.swing.JMenu;
@@ -1071,7 +1072,7 @@ public class ClickControl extends PamControlledUnit implements PamSettings {
subDet.removeSuperDetection(event);
}
}
- clickDetector.getOfflineEventDataBlock().remove(event);
+ clickDetector.getOfflineEventDataBlock().remove(event, true);
}
@Override
@@ -1168,6 +1169,31 @@ public class ClickControl extends PamControlledUnit implements PamSettings {
return targetMotionLocaliser;
}
+ /**
+ * Remove clicks from existing events, if they have any. They may not.
+ * This is called whenever clicks are assigned to a new event to make
+ * sure that they don't end up in two events.
+ * @param markedClicks
+ */
+ public void removeFromEvents(List markedClicks) {
+ if (markedClicks == null) {
+ return;
+ }
+ for (PamDataUnit dataUnit : markedClicks) {
+ OfflineEventDataUnit anEvent = (OfflineEventDataUnit) dataUnit.getSuperDetection(OfflineEventDataUnit.class);
+ if (anEvent == null) {
+ continue;
+ }
+ anEvent.removeSubDetection(dataUnit);
+ if (anEvent.getSubDetectionsCount() == 0) {
+ deleteEvent(anEvent);
+ }
+ else {
+ anEvent.updateDataUnit(System.currentTimeMillis());
+ }
+ }
+
+ }
/**
* Reassign all the clicks on one event to a different event
@@ -1199,7 +1225,7 @@ public class ClickControl extends PamControlledUnit implements PamSettings {
}
clickEvent.setComment(clickEvent.getComment() + " Clicks reassigned to event " + reassignEvent.getEventId());
offlineEventDataBlock.updatePamData(clickEvent, PamCalendar.getTimeInMillis());
- offlineEventDataBlock.remove(clickEvent);
+ offlineEventDataBlock.remove(clickEvent, true);
reassignEvent.sortSubDetections();
offlineEventDataBlock.updatePamData(reassignEvent, now);
if (ClickTrainDetection.class.isAssignableFrom(reassignEvent.getClass())) {
diff --git a/src/clickDetector/ClickDataBlock.java b/src/clickDetector/ClickDataBlock.java
index 3e650b85..5536aa79 100644
--- a/src/clickDetector/ClickDataBlock.java
+++ b/src/clickDetector/ClickDataBlock.java
@@ -3,6 +3,9 @@ package clickDetector;
import java.util.ListIterator;
import pamScrollSystem.ViewLoadObserver;
+import tethys.TethysControl;
+import tethys.pamdata.TethysDataProvider;
+import tethys.species.DataBlockSpeciesManager;
//import staticLocaliser.StaticLocaliserControl;
//import staticLocaliser.StaticLocaliserProvider;
//import staticLocaliser.panels.AbstractLocaliserControl;
@@ -10,8 +13,10 @@ import pamScrollSystem.ViewLoadObserver;
import alarm.AlarmCounterProvider;
import alarm.AlarmDataSource;
import binaryFileStorage.BinaryStore;
+import clickDetector.ClickClassifiers.ClickBlockSpeciesManager;
import clickDetector.dataSelector.ClickDataSelectCreator;
import clickDetector.offlineFuncs.OfflineClickLogging;
+import clickDetector.tethys.ClickTethysDataProvider;
import clickDetector.toad.ClickTOADCalculator;
import dataMap.OfflineDataMap;
import fftManager.fftorganiser.FFTDataOrganiser;
@@ -24,6 +29,8 @@ import PamUtils.PamUtils;
import PamView.GroupedDataSource;
import PamView.GroupedSourceParameters;
import PamguardMVC.AcousticDataBlock;
+import PamguardMVC.DataAutomation;
+import PamguardMVC.DataAutomationInfo;
import PamguardMVC.FFTDataHolderBlock;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
@@ -41,6 +48,8 @@ public class ClickDataBlock extends AcousticDataBlock implement
private boolean isViewer;
+ private ClickBlockSpeciesManager clickBlockSpeciesManager;
+
public ClickDataBlock(ClickControl clickControl, PamProcess parentProcess, int channelMap) {
@@ -65,6 +74,8 @@ public class ClickDataBlock extends AcousticDataBlock implement
private ClickTOADCalculator clickTOADCalculator;
+ private ClickTethysDataProvider clickTethysDataProvider;
+
/**
* Click detector loading has to be a bit different to normal - first
* data are loaded from the binary store, then a subset of these data
@@ -304,5 +315,26 @@ public class ClickDataBlock extends AcousticDataBlock implement
}
}
+ @Override
+ public DataBlockSpeciesManager getDatablockSpeciesManager() {
+ if (clickBlockSpeciesManager == null) {
+ clickBlockSpeciesManager = new ClickBlockSpeciesManager(clickControl, this);
+ }
+ return clickBlockSpeciesManager;
+ }
+
+ @Override
+ public TethysDataProvider getTethysDataProvider(TethysControl tethysControl) {
+ if (clickTethysDataProvider == null) {
+ clickTethysDataProvider = new ClickTethysDataProvider(tethysControl, this);
+ }
+ return clickTethysDataProvider;
+ }
+
+ @Override
+ public DataAutomationInfo getDataAutomationInfo() {
+ return new DataAutomationInfo(DataAutomation.AUTOMATIC);
+ }
+
}
diff --git a/src/clickDetector/ClickDisplayManager.java b/src/clickDetector/ClickDisplayManager.java
index f46aeca8..f992ef2d 100644
--- a/src/clickDetector/ClickDisplayManager.java
+++ b/src/clickDetector/ClickDisplayManager.java
@@ -28,6 +28,7 @@ import PamController.PamSettingManager;
import PamController.PamSettings;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import PamView.MenuItemEnabler;
@@ -302,7 +303,7 @@ public class ClickDisplayManager implements PamSettings {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("className");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/clickDetector/ClickDisplayManagerParameters2.java b/src/clickDetector/ClickDisplayManagerParameters2.java
index 86ccbca6..d8fd18cf 100644
--- a/src/clickDetector/ClickDisplayManagerParameters2.java
+++ b/src/clickDetector/ClickDisplayManagerParameters2.java
@@ -9,6 +9,7 @@ import PamController.PamController;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class ClickDisplayManagerParameters2 implements Cloneable, Serializable, ManagedParameters {
@@ -181,7 +182,7 @@ public class ClickDisplayManagerParameters2 implements Cloneable, Serializable,
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("initialised");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/clickDetector/ClickParameters.java b/src/clickDetector/ClickParameters.java
index 3146b0e4..118eaf21 100644
--- a/src/clickDetector/ClickParameters.java
+++ b/src/clickDetector/ClickParameters.java
@@ -38,6 +38,7 @@ import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterData;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamView.GroupedSourceParameters;
import PamView.dialog.GroupedSourcePanel;
import PamView.paneloverlay.overlaymark.MarkDataSelectorParams;
@@ -441,7 +442,7 @@ public class ClickParameters implements Serializable, Cloneable, ManagedParamete
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
PamParameterData param = ps.findParameterData("dbThreshold");
param.setShortName("Detection Threshold");
diff --git a/src/clickDetector/ClickSpectrumParams.java b/src/clickDetector/ClickSpectrumParams.java
index 6784c9fa..d18927e3 100644
--- a/src/clickDetector/ClickSpectrumParams.java
+++ b/src/clickDetector/ClickSpectrumParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class ClickSpectrumParams implements Serializable, Cloneable, ManagedParameters {
@@ -38,7 +39,7 @@ public class ClickSpectrumParams implements Serializable, Cloneable, ManagedPara
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/clickDetector/ClickSpectrumTemplateParams.java b/src/clickDetector/ClickSpectrumTemplateParams.java
index ff156b0e..caad2b6e 100644
--- a/src/clickDetector/ClickSpectrumTemplateParams.java
+++ b/src/clickDetector/ClickSpectrumTemplateParams.java
@@ -7,6 +7,7 @@ import java.util.ArrayList;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
@@ -39,7 +40,7 @@ public class ClickSpectrumTemplateParams implements Serializable, Cloneable, Man
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("clickTemplateArray");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/clickDetector/ConcatenatedSpectParams.java b/src/clickDetector/ConcatenatedSpectParams.java
index 6bf67108..db3f6a0b 100644
--- a/src/clickDetector/ConcatenatedSpectParams.java
+++ b/src/clickDetector/ConcatenatedSpectParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamView.ColourArray.ColourArrayType;
public class ConcatenatedSpectParams implements Serializable, Cloneable, ManagedParameters {
@@ -44,7 +45,7 @@ public class ConcatenatedSpectParams implements Serializable, Cloneable, Manage
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/clickDetector/IDI_DisplayParams.java b/src/clickDetector/IDI_DisplayParams.java
index 0198fe92..e7641768 100644
--- a/src/clickDetector/IDI_DisplayParams.java
+++ b/src/clickDetector/IDI_DisplayParams.java
@@ -29,6 +29,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
/**
@@ -270,7 +271,7 @@ public class IDI_DisplayParams implements Serializable, Cloneable, ManagedParame
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("saveOutput");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/clickDetector/TrackedClickGroupLogging.java b/src/clickDetector/TrackedClickGroupLogging.java
index 6016f704..90e7af9a 100644
--- a/src/clickDetector/TrackedClickGroupLogging.java
+++ b/src/clickDetector/TrackedClickGroupLogging.java
@@ -1,5 +1,6 @@
package clickDetector;
+import generalDatabase.PamTableDefinition;
import generalDatabase.SQLTypes;
import PamguardMVC.PamDataUnit;
import clickDetector.offlineFuncs.OfflineEventDataUnit;
@@ -30,7 +31,8 @@ public class TrackedClickGroupLogging extends ClickGroupLogging {
boolean isUpdate = true;
// Timestamp ts = (Timestamp) getTableDefinition().getTimeStampItem().getValue();
// long t = PamCalendar.millisFromTimeStamp(ts);
- int updateIndex = (Integer) getTableDefinition().getUpdateReference().getValue();
+ PamTableDefinition tableDef = (PamTableDefinition) getTableDefinition();
+ int updateIndex = (Integer) tableDef.getUpdateReference().getValue();
if (updateIndex > 0) {
tcg = this.clickGroupDataBlock.findByDatabaseIndex(updateIndex);
}
diff --git a/src/clickDetector/WignerPlotOptions.java b/src/clickDetector/WignerPlotOptions.java
index 0ef46f2e..e05640a6 100644
--- a/src/clickDetector/WignerPlotOptions.java
+++ b/src/clickDetector/WignerPlotOptions.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class WignerPlotOptions implements Serializable, Cloneable, ManagedParameters {
@@ -25,7 +26,7 @@ public class WignerPlotOptions implements Serializable, Cloneable, ManagedParame
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/clickDetector/alarm/ClickAlarmParameters.java b/src/clickDetector/alarm/ClickAlarmParameters.java
index 3cc714b2..8bed53c6 100644
--- a/src/clickDetector/alarm/ClickAlarmParameters.java
+++ b/src/clickDetector/alarm/ClickAlarmParameters.java
@@ -7,6 +7,7 @@ import java.util.Hashtable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import PamguardMVC.dataSelector.DataSelectParams;
@@ -127,7 +128,7 @@ public class ClickAlarmParameters extends DataSelectParams implements Cloneable,
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("eventTypes");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/clickDetector/clicktrains/ClickTrainIdParams.java b/src/clickDetector/clicktrains/ClickTrainIdParams.java
index 9f9b03c2..c6d4746f 100644
--- a/src/clickDetector/clicktrains/ClickTrainIdParams.java
+++ b/src/clickDetector/clicktrains/ClickTrainIdParams.java
@@ -5,6 +5,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
/**
@@ -59,7 +60,7 @@ public class ClickTrainIdParams implements Serializable, Cloneable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("dataVersion");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/clickDetector/dataSelector/ClickTrainDataSelect2Params.java b/src/clickDetector/dataSelector/ClickTrainDataSelect2Params.java
index 668fec3e..a8cc198c 100644
--- a/src/clickDetector/dataSelector/ClickTrainDataSelect2Params.java
+++ b/src/clickDetector/dataSelector/ClickTrainDataSelect2Params.java
@@ -8,6 +8,7 @@ import java.util.Hashtable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import PamguardMVC.dataSelector.DataSelectParams;
@@ -91,7 +92,7 @@ public class ClickTrainDataSelect2Params extends DataSelectParams implements Clo
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("wantType");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/clickDetector/dataSelector/ClickTrainDataSelector2.java b/src/clickDetector/dataSelector/ClickTrainDataSelector2.java
index 0520b4fb..9bde5123 100644
--- a/src/clickDetector/dataSelector/ClickTrainDataSelector2.java
+++ b/src/clickDetector/dataSelector/ClickTrainDataSelector2.java
@@ -82,7 +82,7 @@ public class ClickTrainDataSelector2 extends DataSelector {
}
SQLLogging logging = getPamDataBlock().getLogging();
if (logging == null) return null; //cannot happen!
- PamTableDefinition tableDef = logging.getTableDefinition();
+ EmptyTableDefinition tableDef = logging.getTableDefinition();
if (params.isIncludeUnclassified()) {
return null;
}
diff --git a/src/clickDetector/dataSelector/ClickTrainSelectParameters.java b/src/clickDetector/dataSelector/ClickTrainSelectParameters.java
index 3cfc5189..75462778 100644
--- a/src/clickDetector/dataSelector/ClickTrainSelectParameters.java
+++ b/src/clickDetector/dataSelector/ClickTrainSelectParameters.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamguardMVC.dataSelector.DataSelectParams;
import clickDetector.ClickParameters;
@@ -32,7 +33,7 @@ public class ClickTrainSelectParameters extends DataSelectParams implements Seri
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/clickDetector/echoDetection/JamieEchoParams.java b/src/clickDetector/echoDetection/JamieEchoParams.java
index ec00df42..e3cbadb5 100644
--- a/src/clickDetector/echoDetection/JamieEchoParams.java
+++ b/src/clickDetector/echoDetection/JamieEchoParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class JamieEchoParams implements Serializable, Cloneable, ManagedParameters {
@@ -31,7 +32,7 @@ public static final long serialVersionUID = 3L;
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/clickDetector/echoDetection/SimpleEchoParams.java b/src/clickDetector/echoDetection/SimpleEchoParams.java
index fe5eae8e..eb6095a1 100644
--- a/src/clickDetector/echoDetection/SimpleEchoParams.java
+++ b/src/clickDetector/echoDetection/SimpleEchoParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class SimpleEchoParams implements Serializable, Cloneable, ManagedParameters {
@@ -26,7 +27,7 @@ public class SimpleEchoParams implements Serializable, Cloneable, ManagedParamet
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierSetPaneFX.java b/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierSetPaneFX.java
index e11aec29..a86f27f5 100644
--- a/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierSetPaneFX.java
+++ b/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierSetPaneFX.java
@@ -1628,8 +1628,6 @@ public class SweepClassifierSetPaneFX extends SettingsPane {
p.setLayout(new GridBagLayout());
GridBagConstraints c = new PamGridBagContraints();
-
-
// c.gridx = 0;
// addComponent(p, enableBearings, c);
// c.gridx += c.gridwidth;
@@ -1736,7 +1734,6 @@ public class SweepClassifierSetPaneFX extends SettingsPane {
// }
// }
// }
-// else multiChan = true;
// Debug.out.println("Check multi-channel: " + multiChan);
return multiChan;
diff --git a/src/clickDetector/localisation/ClickLocParams.java b/src/clickDetector/localisation/ClickLocParams.java
index fcfaaff6..6a597258 100644
--- a/src/clickDetector/localisation/ClickLocParams.java
+++ b/src/clickDetector/localisation/ClickLocParams.java
@@ -7,6 +7,7 @@ import java.util.Arrays;
import Localiser.detectionGroupLocaliser.DetectionGroupOptions;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
public class ClickLocParams implements Serializable, Cloneable, DetectionGroupOptions, ManagedParameters {
@@ -110,7 +111,7 @@ public class ClickLocParams implements Serializable, Cloneable, DetectionGroupOp
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("internalVersion");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/clickDetector/offlineFuncs/ClicksOffline.java b/src/clickDetector/offlineFuncs/ClicksOffline.java
index 4423c721..6b72da91 100644
--- a/src/clickDetector/offlineFuncs/ClicksOffline.java
+++ b/src/clickDetector/offlineFuncs/ClicksOffline.java
@@ -632,6 +632,7 @@ public class ClicksOffline {
OfflineEventDataUnit newUnit = new OfflineEventDataUnit(null, getNextEventColourIndex(), null);
newUnit = OfflineEventDialog.showDialog(win, clickControl, newUnit);
if (newUnit != null) {
+ clickControl.removeFromEvents(markedClicks);
newUnit.addSubDetections(markedClicks);
offlineEventDataBlock.addPamData(newUnit);
clickControl.setLatestOfflineEvent(newUnit);
diff --git a/src/clickDetector/offlineFuncs/DatabaseChecks.java b/src/clickDetector/offlineFuncs/DatabaseChecks.java
index 38bfe6a5..585bbf50 100644
--- a/src/clickDetector/offlineFuncs/DatabaseChecks.java
+++ b/src/clickDetector/offlineFuncs/DatabaseChecks.java
@@ -102,16 +102,17 @@ public class DatabaseChecks {
long resultTime;
long firstTime = Long.MAX_VALUE;
long lastTime = Long.MIN_VALUE;
+ PamTableDefinition pamTableDef = (PamTableDefinition) clickLogging.getTableDefinition();
try {
Statement stmt = con.getConnection().createStatement();
ResultSet result = stmt.executeQuery(sqlStr);
while (result.next()) {
nClicks++;
clickLogging.transferDataFromResult(sqlTypes, result);
- ts = clickLogging.getTableDefinition().getTimeStampItem().getValue();
+ ts = pamTableDef.getTimeStampItem().getValue();
resultTime = sqlTypes.millisFromTimeStamp(ts);
if (resultTime%1000 == 0) {
- resultTime += clickLogging.getTableDefinition().getTimeStampMillis().getIntegerValue();
+ resultTime += pamTableDef.getTimeStampMillis().getIntegerValue();
}
firstTime = Math.min(firstTime, resultTime);
lastTime = Math.max(lastTime, resultTime);
@@ -188,7 +189,7 @@ public class DatabaseChecks {
eventDataBlock.addPamData(event);
PamConnection con = DBControlUnit.findConnection();
// now find a cursor and save it.
- PamTableDefinition eventTableDef = eventDataBlock.getLogging().getTableDefinition();
+ PamTableDefinition eventTableDef = (PamTableDefinition) eventDataBlock.getLogging().getTableDefinition();
PamCursor cursor = eventDataBlock.getLogging().getViewerCursorFinder().getCursor(con, eventTableDef);
cursor.immediateInsert(con);
int newId = event.getDatabaseIndex();
diff --git a/src/clickDetector/offlineFuncs/LabelClicksDialog.java b/src/clickDetector/offlineFuncs/LabelClicksDialog.java
index 0e25b495..113f7864 100644
--- a/src/clickDetector/offlineFuncs/LabelClicksDialog.java
+++ b/src/clickDetector/offlineFuncs/LabelClicksDialog.java
@@ -146,6 +146,7 @@ public class LabelClicksDialog extends PamDialog {
* @param thenClose option to close dialog
*/
private void addClicksToEvent(OfflineEventDataUnit event, boolean thenClose) {
+ removeFromOldEvent(markedClicks);
event.addSubDetections(markedClicks);
offlineEventListPanel.tableDataChanged();
clickControl.setLatestOfflineEvent(event);
@@ -154,6 +155,15 @@ public class LabelClicksDialog extends PamDialog {
}
}
+ /**
+ * clicks may have already been part of an event, so need to remove them from that
+ * event first, and if there is nothing left in that event, delete the event.
+ * @param markedClicks2
+ */
+ private void removeFromOldEvent(List markedClicks) {
+ clickControl.removeFromEvents(markedClicks);
+ }
+
@Override
public void restoreDefaultSettings() {
// TODO Auto-generated method stub
diff --git a/src/clickDetector/offlineFuncs/OfflineClickLogging.java b/src/clickDetector/offlineFuncs/OfflineClickLogging.java
index a75897f7..43a73fea 100644
--- a/src/clickDetector/offlineFuncs/OfflineClickLogging.java
+++ b/src/clickDetector/offlineFuncs/OfflineClickLogging.java
@@ -51,7 +51,7 @@ public class OfflineClickLogging extends SQLLogging {
tableDef.addTableItem(clickNumber = new PamTableItem("ClickNo", Types.INTEGER));
tableDef.addTableItem(amplitude = new PamTableItem("Amplitude", Types.DOUBLE));
tableDef.addTableItem(channelNumbers = new PamTableItem("Channels", Types.INTEGER));
- tableDef.setUseCheatIndexing(true);
+ tableDef.setUseCheatIndexing(false);
setTableDefinition(tableDef);
}
@@ -277,13 +277,14 @@ public class OfflineClickLogging extends SQLLogging {
Integer millis;
Object ts;
SQLTypes sqlTypes = dbControl.getConnection().getSqlTypes();
+ PamTableDefinition tableDef = (PamTableDefinition) getTableDefinition();
try {
while (resultSet.next()) {
transferDataFromResult(sqlTypes, resultSet);
- ts = getTableDefinition().getTimeStampItem().getValue();
+ ts = tableDef.getTimeStampItem().getValue();
long m = SQLTypes.millisFromTimeStamp(ts);
if (m%1000 == 0) {
- millis = (Integer) getTableDefinition().getTimeStampMillis().getValue();
+ millis = (Integer) tableDef.getTimeStampMillis().getValue();
if (millis != null) {
m += millis;
}
diff --git a/src/clickDetector/offlineFuncs/OfflineEventDataBlock.java b/src/clickDetector/offlineFuncs/OfflineEventDataBlock.java
index 4af5872b..afc60ec7 100644
--- a/src/clickDetector/offlineFuncs/OfflineEventDataBlock.java
+++ b/src/clickDetector/offlineFuncs/OfflineEventDataBlock.java
@@ -16,6 +16,10 @@ import PamController.PamViewParameters;
import PamUtils.PamCalendar;
import PamView.symbol.StandardSymbolManager;
import pamScrollSystem.ViewLoadObserver;
+import tethys.TethysControl;
+import tethys.pamdata.TethysDataProvider;
+import tethys.species.DataBlockSpeciesManager;
+import clickDetector.ClickDetection;
//import staticLocaliser.StaticLocaliserControl;
//import staticLocaliser.StaticLocaliserProvider;
//import staticLocaliser.panels.AbstractLocaliserControl;
@@ -23,7 +27,12 @@ import pamScrollSystem.ViewLoadObserver;
import clickDetector.ClickDetector;
import clickDetector.ClickTrainDetection;
import clickDetector.dataSelector.ClickTrainDataSelectorCreator;
+import clickDetector.tethys.ClickEventSpeciesManager;
+import clickDetector.tethys.ClickEventTethysDataProvider;
+import clickDetector.tethys.ClickTethysDataProvider;
import dataMap.OfflineDataMap;
+import PamguardMVC.DataAutomation;
+import PamguardMVC.DataAutomationInfo;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
import PamguardMVC.dataOffline.OfflineDataLoadInfo;
@@ -49,6 +58,8 @@ public class OfflineEventDataBlock extends SuperDetDataBlock getDatablockSpeciesManager() {
+ if (eventSpeciesManager == null) {
+ eventSpeciesManager = new ClickEventSpeciesManager(clickDetector, this);
+ }
+ return eventSpeciesManager;
+ }
+
+ @Override
+ public TethysDataProvider getTethysDataProvider(TethysControl tethysControl) {
+ if (eventTethysDataProvider == null) {
+ eventTethysDataProvider = new ClickEventTethysDataProvider(tethysControl, this);
+ }
+ return eventTethysDataProvider;
+ }
+
+ @Override
+ public DataAutomationInfo getDataAutomationInfo() {
+ return new DataAutomationInfo(DataAutomation.MANUALANDAUTOMATIC);
+ }
+
}
diff --git a/src/clickDetector/offlineFuncs/OfflineParameters.java b/src/clickDetector/offlineFuncs/OfflineParameters.java
index 2ab82962..0c4b2c71 100644
--- a/src/clickDetector/offlineFuncs/OfflineParameters.java
+++ b/src/clickDetector/offlineFuncs/OfflineParameters.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class OfflineParameters implements Serializable, Cloneable, ManagedParameters {
@@ -28,7 +29,7 @@ public class OfflineParameters implements Serializable, Cloneable, ManagedParame
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/clickDetector/offlineFuncs/rcImport/RainbowDatabseConverter.java b/src/clickDetector/offlineFuncs/rcImport/RainbowDatabseConverter.java
index d4fb6fb2..0b9b0996 100644
--- a/src/clickDetector/offlineFuncs/rcImport/RainbowDatabseConverter.java
+++ b/src/clickDetector/offlineFuncs/rcImport/RainbowDatabseConverter.java
@@ -148,7 +148,7 @@ public class RainbowDatabseConverter {
ClickDataBlock clickDataBlock = clickControl.getClickDataBlock();
clickLogging = new ClickImportLogging(clickControl);
- PamTableDefinition tableDef = clickLogging.getTableDefinition();
+ PamTableDefinition tableDef = (PamTableDefinition) clickLogging.getTableDefinition();
boolean ok = checkTable(pamConnection, tableDef);
if (!ok) {
System.out.println("Error in Pamguard clicks table");
@@ -156,7 +156,7 @@ public class RainbowDatabseConverter {
}
eventLogging = new OfflineEventLogging(clickControl, clickControl.getClickDetector().getOfflineEventDataBlock());
- tableDef = eventLogging.getTableDefinition();
+ tableDef = (PamTableDefinition) eventLogging.getTableDefinition();
ok = checkTable(pamConnection, tableDef);
if (!ok) {
System.out.println("Error in Pamguard events table");
diff --git a/src/clickDetector/tethys/ClickEventSpeciesManager.java b/src/clickDetector/tethys/ClickEventSpeciesManager.java
new file mode 100644
index 00000000..c0ee92fd
--- /dev/null
+++ b/src/clickDetector/tethys/ClickEventSpeciesManager.java
@@ -0,0 +1,57 @@
+package clickDetector.tethys;
+
+import java.util.Vector;
+
+import PamguardMVC.PamDataUnit;
+import clickDetector.ClickControl;
+import clickDetector.ClickDetector;
+import clickDetector.offlineFuncs.ClicksOffline;
+import clickDetector.offlineFuncs.OfflineEventDataBlock;
+import clickDetector.offlineFuncs.OfflineEventDataUnit;
+import generalDatabase.lookupTables.LookUpTables;
+import generalDatabase.lookupTables.LookupItem;
+import generalDatabase.lookupTables.LookupList;
+import tethys.species.DataBlockSpeciesCodes;
+import tethys.species.DataBlockSpeciesManager;
+
+public class ClickEventSpeciesManager extends DataBlockSpeciesManager {
+
+ private OfflineEventDataBlock eventDataBlock;
+ private ClickDetector clickDetector;
+ private ClickControl clickControl;
+ private ClicksOffline clicksOffline;
+
+ public ClickEventSpeciesManager(ClickDetector clickDetector, OfflineEventDataBlock eventDataBlock) {
+ super(eventDataBlock);
+ this.clickDetector = clickDetector;
+ this.eventDataBlock = eventDataBlock;
+ clickControl = clickDetector.getClickControl();
+ clicksOffline = clickControl.getClicksOffline();
+ }
+
+ @Override
+ public DataBlockSpeciesCodes getSpeciesCodes() {
+ LookupList lutList = LookUpTables.getLookUpTables().getLookupList(ClicksOffline.ClickTypeLookupName);
+ if (lutList == null || lutList.getLutList().size() == 0) {
+ return new DataBlockSpeciesCodes("Unknown");
+ }
+ Vector spList = lutList.getLutList();
+ String[] spNames = new String[spList.size()];
+ int i = 0;
+ for (LookupItem lItem : spList) {
+ spNames[i++] = lItem.getCode();
+ }
+ return new DataBlockSpeciesCodes("Unknown", spNames);
+ }
+
+ @Override
+ public String getSpeciesCode(PamDataUnit dataUnit) {
+ OfflineEventDataUnit eventDataUnit = (OfflineEventDataUnit) dataUnit;
+ String eventType = eventDataUnit.getEventType();
+ if (eventType == null) {
+ eventType = "Unknown";
+ }
+ return eventType;
+ }
+
+}
diff --git a/src/clickDetector/tethys/ClickEventTethysDataProvider.java b/src/clickDetector/tethys/ClickEventTethysDataProvider.java
new file mode 100644
index 00000000..bbc5d1fd
--- /dev/null
+++ b/src/clickDetector/tethys/ClickEventTethysDataProvider.java
@@ -0,0 +1,72 @@
+package clickDetector.tethys;
+
+import java.math.BigInteger;
+
+import PamguardMVC.PamDataUnit;
+import clickDetector.offlineFuncs.OfflineEventDataBlock;
+import clickDetector.offlineFuncs.OfflineEventDataUnit;
+import nilus.Detection;
+import nilus.GranularityEnumType;
+import nilus.Detection.Parameters;
+import nilus.Detection.Parameters.UserDefined;
+import tethys.TethysControl;
+import tethys.output.StreamExportParams;
+import tethys.output.TethysExportParams;
+import tethys.pamdata.AutoTethysProvider;
+import tethys.swing.export.ExportWizardCard;
+import tethys.swing.export.GranularityCard;
+
+public class ClickEventTethysDataProvider extends AutoTethysProvider {
+
+ private OfflineEventDataBlock eventDataBlock;
+
+ public ClickEventTethysDataProvider(TethysControl tethysControl, OfflineEventDataBlock eventDataBlock) {
+ super(tethysControl, eventDataBlock);
+ this.eventDataBlock = eventDataBlock;
+ }
+
+ @Override
+ public GranularityEnumType[] getAllowedGranularities() {
+ GranularityEnumType[] allowed = {GranularityEnumType.GROUPED};
+ return allowed;
+ }
+ @Override
+ public Detection createDetection(PamDataUnit dataUnit, TethysExportParams tethysExportParams,
+ StreamExportParams streamExportParams) {
+ Detection detection = super.createDetection(dataUnit, tethysExportParams, streamExportParams);
+ if (detection == null) {
+ return null;
+ }
+ OfflineEventDataUnit eventDataUnit = (OfflineEventDataUnit) dataUnit;
+ detection.setCount(BigInteger.valueOf(eventDataUnit.getSubDetectionsCount()));
+ String comment = eventDataUnit.getComment();
+ if (comment != null && comment.length() > 0) {
+ detection.setComment(comment);
+ }
+ Parameters params = detection.getParameters();
+ addUserNumber(params, "MinNumber", eventDataUnit.getMinNumber());
+ addUserNumber(params, "BestNumber", eventDataUnit.getBestNumber());
+ addUserNumber(params, "MaxNumber", eventDataUnit.getMaxNumber());
+
+
+ return detection;
+ }
+
+ private void addUserNumber(Parameters params, String numName, Short number) {
+ if (number == null) {
+ return;
+ }
+ addUserDefined(params, numName, number.toString());
+ }
+
+ @Override
+ public boolean wantExportDialogCard(ExportWizardCard wizPanel) {
+ if (wizPanel.getClass() == GranularityCard.class) {
+ return false;
+ }
+ else {
+ return true;
+ }
+ }
+
+}
diff --git a/src/clickDetector/tethys/ClickTethysDataProvider.java b/src/clickDetector/tethys/ClickTethysDataProvider.java
new file mode 100644
index 00000000..44e1c8c8
--- /dev/null
+++ b/src/clickDetector/tethys/ClickTethysDataProvider.java
@@ -0,0 +1,22 @@
+package clickDetector.tethys;
+
+import clickDetector.ClickDataBlock;
+import nilus.GranularityEnumType;
+import tethys.TethysControl;
+import tethys.pamdata.AutoTethysProvider;
+
+public class ClickTethysDataProvider extends AutoTethysProvider {
+
+ private ClickDataBlock clickDataBlock;
+
+ public ClickTethysDataProvider(TethysControl tethysControl, ClickDataBlock clickDataBlock) {
+ super(tethysControl, clickDataBlock);
+ this.clickDataBlock = clickDataBlock;
+ }
+
+ @Override
+ public GranularityEnumType[] getAllowedGranularities() {
+ return GranularityEnumType.values(); // everything !
+ }
+
+}
diff --git a/src/clickTrainDetector/ClickTrainParams.java b/src/clickTrainDetector/ClickTrainParams.java
index 1200883d..0a3663b9 100644
--- a/src/clickTrainDetector/ClickTrainParams.java
+++ b/src/clickTrainDetector/ClickTrainParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamUtils.PamUtils;
import clickTrainDetector.classification.CTClassifierParams;
import clickTrainDetector.classification.simplechi2classifier.Chi2ThresholdParams;
@@ -127,7 +128,7 @@ public class ClickTrainParams implements Serializable, Cloneable, ManagedParamet
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/clickTrainDetector/classification/CTClassifierParams.java b/src/clickTrainDetector/classification/CTClassifierParams.java
index 91d4e8a7..64fa96e9 100644
--- a/src/clickTrainDetector/classification/CTClassifierParams.java
+++ b/src/clickTrainDetector/classification/CTClassifierParams.java
@@ -5,6 +5,7 @@ import java.util.UUID;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
@@ -68,7 +69,7 @@ public class CTClassifierParams implements Cloneable, Serializable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/clickTrainDetector/classification/templateClassifier/SpectrumTemplateParams.java b/src/clickTrainDetector/classification/templateClassifier/SpectrumTemplateParams.java
index 83a326c8..b3e26d12 100644
--- a/src/clickTrainDetector/classification/templateClassifier/SpectrumTemplateParams.java
+++ b/src/clickTrainDetector/classification/templateClassifier/SpectrumTemplateParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
*
@@ -53,7 +54,7 @@ public class SpectrumTemplateParams implements Serializable, Cloneable, ManagedP
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTChi2Params.java b/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTChi2Params.java
index 499fee9f..046c6478 100644
--- a/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTChi2Params.java
+++ b/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTChi2Params.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Parameters class must extend this.
@@ -38,7 +39,7 @@ public class MHTChi2Params implements Cloneable, Serializable, ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTKernelParams.java b/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTKernelParams.java
index 964073dc..d40d95e0 100644
--- a/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTKernelParams.java
+++ b/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTKernelParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Options for the MHT algorithm
@@ -63,7 +64,7 @@ public class MHTKernelParams implements Cloneable, Serializable, ManagedParamet
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTParams.java b/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTParams.java
index 06f6e6f4..cd75fc67 100644
--- a/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTParams.java
+++ b/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Parameters for the MHT algorithm, contains two serializable parameter
@@ -47,7 +48,7 @@ public class MHTParams implements Serializable, Cloneable, ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/clickTrainDetector/clickTrainAlgorithms/mht/electricalNoiseFilter/SimpleElectricalNoiseParams.java b/src/clickTrainDetector/clickTrainAlgorithms/mht/electricalNoiseFilter/SimpleElectricalNoiseParams.java
index 6a6c3611..8773e368 100644
--- a/src/clickTrainDetector/clickTrainAlgorithms/mht/electricalNoiseFilter/SimpleElectricalNoiseParams.java
+++ b/src/clickTrainDetector/clickTrainAlgorithms/mht/electricalNoiseFilter/SimpleElectricalNoiseParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
*
@@ -29,7 +30,7 @@ public class SimpleElectricalNoiseParams implements Serializable, ManagedParamet
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/SimpleChi2VarParams.java b/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/SimpleChi2VarParams.java
index 94a578df..01b877d5 100644
--- a/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/SimpleChi2VarParams.java
+++ b/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/SimpleChi2VarParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Parameters class for a simple chi2 variable. Contains the expected error in the
@@ -194,7 +195,7 @@ public class SimpleChi2VarParams implements Serializable, Cloneable, ManagedPara
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/clickTrainDetector/dataselector/CTSelectParams.java b/src/clickTrainDetector/dataselector/CTSelectParams.java
index 5343f020..fa6f26dd 100644
--- a/src/clickTrainDetector/dataselector/CTSelectParams.java
+++ b/src/clickTrainDetector/dataselector/CTSelectParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamguardMVC.dataSelector.DataSelectParams;
import clickDetector.dataSelector.ClickTrainSelectParameters;
@@ -93,7 +94,7 @@ public class CTSelectParams extends DataSelectParams implements Serializable, Cl
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/clipgenerator/ClipGenSetting.java b/src/clipgenerator/ClipGenSetting.java
index ee834658..eb0dd0e0 100644
--- a/src/clipgenerator/ClipGenSetting.java
+++ b/src/clipgenerator/ClipGenSetting.java
@@ -5,6 +5,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
/**
@@ -115,7 +116,7 @@ public class ClipGenSetting implements Serializable, Cloneable, ManagedParameter
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("hadMapLine");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/clipgenerator/ClipSettings.java b/src/clipgenerator/ClipSettings.java
index 8636600a..aada971c 100644
--- a/src/clipgenerator/ClipSettings.java
+++ b/src/clipgenerator/ClipSettings.java
@@ -6,6 +6,7 @@ import java.util.ArrayList;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
/**
@@ -135,7 +136,7 @@ public class ClipSettings implements Serializable, Cloneable, ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("clipGenSettings");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/clipgenerator/clipDisplay/ClipDisplayParameters.java b/src/clipgenerator/clipDisplay/ClipDisplayParameters.java
index 15571e2d..15858716 100644
--- a/src/clipgenerator/clipDisplay/ClipDisplayParameters.java
+++ b/src/clipgenerator/clipDisplay/ClipDisplayParameters.java
@@ -5,6 +5,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import PamView.ColourArray.ColourArrayType;
@@ -88,7 +89,7 @@ public class ClipDisplayParameters implements Cloneable, Serializable, ManagedPa
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("maxClips");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/crossedbearinglocaliser/CBLocaliserSettngs.java b/src/crossedbearinglocaliser/CBLocaliserSettngs.java
index e296f276..a323eee3 100644
--- a/src/crossedbearinglocaliser/CBLocaliserSettngs.java
+++ b/src/crossedbearinglocaliser/CBLocaliserSettngs.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamguardMVC.PamDataBlock;
import annotation.localise.targetmotion.TMAnnotationOptions;
@@ -78,7 +79,7 @@ public class CBLocaliserSettngs implements Serializable, Cloneable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/d3/D3DataMapPoint.java b/src/d3/D3DataMapPoint.java
index c42595f2..78962aa1 100644
--- a/src/d3/D3DataMapPoint.java
+++ b/src/d3/D3DataMapPoint.java
@@ -5,6 +5,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import fileOfflineData.OfflineFileMapPoint;
@@ -30,7 +31,7 @@ public class D3DataMapPoint extends OfflineFileMapPoint implements ManagedParame
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("fileOffsetStart");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/dataGram/Datagram.java b/src/dataGram/Datagram.java
index 33b72d42..eaafcf3f 100644
--- a/src/dataGram/Datagram.java
+++ b/src/dataGram/Datagram.java
@@ -8,6 +8,7 @@ import java.util.ArrayList;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import binaryFileStorage.BinaryTypes;
import dataMap.OfflineDataMapPoint;
@@ -175,7 +176,7 @@ public class Datagram implements Serializable, ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/dataGram/DatagramDataPoint.java b/src/dataGram/DatagramDataPoint.java
index 92da4033..dc27f4c6 100644
--- a/src/dataGram/DatagramDataPoint.java
+++ b/src/dataGram/DatagramDataPoint.java
@@ -5,6 +5,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
public class DatagramDataPoint implements Serializable, ManagedParameters {
@@ -89,7 +90,7 @@ public class DatagramDataPoint implements Serializable, ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("nDataUnits");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/dataGram/DatagramSettings.java b/src/dataGram/DatagramSettings.java
index e466d55d..a3b5a4df 100644
--- a/src/dataGram/DatagramSettings.java
+++ b/src/dataGram/DatagramSettings.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class DatagramSettings implements Serializable, Cloneable, ManagedParameters {
@@ -33,7 +34,7 @@ public class DatagramSettings implements Serializable, Cloneable, ManagedParamet
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/dataMap/DataMapParameters.java b/src/dataMap/DataMapParameters.java
index 22eed747..cd714199 100644
--- a/src/dataMap/DataMapParameters.java
+++ b/src/dataMap/DataMapParameters.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class DataMapParameters implements Cloneable, Serializable, ManagedParameters {
@@ -36,7 +37,7 @@ public class DataMapParameters implements Cloneable, Serializable, ManagedParame
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/dataMap/DataStreamPanel.java b/src/dataMap/DataStreamPanel.java
index 957eadfd..275be1f5 100644
--- a/src/dataMap/DataStreamPanel.java
+++ b/src/dataMap/DataStreamPanel.java
@@ -747,11 +747,20 @@ public class DataStreamPanel extends JPanel implements DataMapObserver {
String tipText;
if (startTimeArrow != null && startTimeArrow.contains(me.getPoint())) {
- tipText = "Data Start: " + PamCalendar.formatDateTime(dataBlock.getCurrentViewDataStart(), true);
+ tipText = "Data Start: " + PamCalendar.formatDateTime(dataBlock.getCurrentViewDataStart(), false);
} else if (endTimeArrow != null && endTimeArrow.contains(me.getPoint())) {
- tipText = "Data End: " + PamCalendar.formatDateTime(dataBlock.getCurrentViewDataEnd(), true);
+ tipText = "Data End: " + PamCalendar.formatDateTime(dataBlock.getCurrentViewDataEnd(), false);
} else {
- tipText = "Cursor: " + PamCalendar.formatDateTime(tm, true);
+ OfflineDataMap dMap = dataBlock.getPrimaryDataMap();
+ if (dMap != null) {
+ tipText = String.format("%s Data from%s to %s
Cursor: %s", dataBlock.getDataName(),
+ PamCalendar.formatDateTime(dMap.getFirstDataTime(), false),
+ PamCalendar.formatDateTime(dMap.getLastDataTime(), false),
+ PamCalendar.formatDateTime(tm, true));
+ }
+ else {
+ tipText = "Cursor: " + PamCalendar.formatDateTime(tm, true);
+ }
}
// tipText += " Panel height = " + getHeight();
diff --git a/src/dataMap/OfflineDataMap.java b/src/dataMap/OfflineDataMap.java
index 2295af01..d51ee120 100644
--- a/src/dataMap/OfflineDataMap.java
+++ b/src/dataMap/OfflineDataMap.java
@@ -84,6 +84,8 @@ abstract public class OfflineDataMap {
public static final int POINT_END = 0x8; // 8
public static final int IN_DATA = 0x10; // 16
public static final int NO_DATA = 0x20; // 32
+
+ private static final long oneDayInMillis = 3600L*24L*1000L;
public OfflineDataMap(OfflineDataStore offlineDataStore, PamDataBlock parentDataBlock) {
super();
@@ -145,10 +147,10 @@ abstract public class OfflineDataMap {
*/
synchronized public void addDataPoint(TmapPoint mapPoint) {
boolean first = (mapPoints.size() == 0);
- if (mapPoint.getStartTime() > 0) {
+ if (mapPoint.getStartTime() > oneDayInMillis) {
firstDataTime = Math.min(firstDataTime, mapPoint.getStartTime());
}
- if (mapPoint.getEndTime() > 0) {
+ if (mapPoint.getEndTime() > oneDayInMillis) {
lastDataTime = Math.max(lastDataTime, mapPoint.getEndTime());
// if (mapPoint.getEndTime() > System.currentTimeMillis()) {
// System.out.println("Stupid large data time in " + mapPoint.getName());
@@ -273,10 +275,10 @@ abstract public class OfflineDataMap {
while (it.hasNext()) {
aPoint = it.next();
- if (aPoint.getStartTime() > 0) {
+ if (aPoint.getStartTime() > oneDayInMillis) {
firstDataTime = Math.min(firstDataTime, aPoint.getStartTime());
}
- if (aPoint.getEndTime() > 0) {
+ if (aPoint.getEndTime() > oneDayInMillis) {
lastDataTime = Math.max(lastDataTime, aPoint.getEndTime());
}
n = aPoint.getNDatas();
@@ -361,6 +363,28 @@ abstract public class OfflineDataMap {
}
}
+ /**
+ * Get the start time of the first datamap point or Long.minval
+ * @return
+ */
+ public long getMapStartTime() {
+ if (mapPoints == null || mapPoints.size() == 0) {
+ return Long.MIN_VALUE;
+ }
+ return mapPoints.get(0).getStartTime();
+ }
+
+ /**
+ * Get the start time of the first datamap point or Long.minval
+ * @return
+ */
+ public long getMapEndTime() {
+ if (mapPoints == null || mapPoints.size() == 0) {
+ return Long.MIN_VALUE;
+ }
+ return mapPoints.get(mapPoints.size()-1).getEndTime();
+ }
+
/**
* @return the lowestPoint
*/
diff --git a/src/dataMap/OfflineDataMapPoint.java b/src/dataMap/OfflineDataMapPoint.java
index af9e1910..d1e8917c 100644
--- a/src/dataMap/OfflineDataMapPoint.java
+++ b/src/dataMap/OfflineDataMapPoint.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamUtils.PamCalendar;
/**
@@ -251,7 +252,7 @@ abstract public class OfflineDataMapPoint implements Comparable impl
// TODO Auto-generated method stub
return "Sound Files";
}
+
+ @Override
+ public String getDataLocation() {
+ getOfflineFileParameters();
+ return offlineFileParameters.folderName;
+ }
public TmapPoint findFirstMapPoint(Iterator mapIterator, long startMillis, long endMillis) {
TmapPoint mapPoint, prevMapPoint = null;
diff --git a/src/dataPlots/TDParameters.java b/src/dataPlots/TDParameters.java
index 80d67871..bb7f14db 100644
--- a/src/dataPlots/TDParameters.java
+++ b/src/dataPlots/TDParameters.java
@@ -5,6 +5,7 @@ import java.util.ArrayList;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import dataPlots.layout.GraphParameters;
import pamScrollSystem.PamScroller;
@@ -45,7 +46,7 @@ public class TDParameters implements Serializable, Cloneable, ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/dataPlots/layout/DataListInfo.java b/src/dataPlots/layout/DataListInfo.java
index 05edd3f8..d506fe64 100644
--- a/src/dataPlots/layout/DataListInfo.java
+++ b/src/dataPlots/layout/DataListInfo.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* TDDataInfo objects can't be serialised since they contain
@@ -44,7 +45,7 @@ public class DataListInfo implements Serializable, Cloneable, ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/dataPlots/layout/GraphParameters.java b/src/dataPlots/layout/GraphParameters.java
index f505422e..5fc3fe2a 100644
--- a/src/dataPlots/layout/GraphParameters.java
+++ b/src/dataPlots/layout/GraphParameters.java
@@ -6,6 +6,7 @@ import java.util.ArrayList;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import dataPlots.data.TDDataInfo;
@@ -41,7 +42,7 @@ public class GraphParameters implements Serializable, Cloneable, ManagedParamete
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("dataListInfos");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/dataPlotsFX/TDGraphParametersFX.java b/src/dataPlotsFX/TDGraphParametersFX.java
index c4d6de46..f3f6c691 100644
--- a/src/dataPlotsFX/TDGraphParametersFX.java
+++ b/src/dataPlotsFX/TDGraphParametersFX.java
@@ -8,6 +8,7 @@ import java.util.Hashtable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamView.GeneralProjector.ParameterType;
import PamView.GeneralProjector.ParameterUnits;
import javafx.scene.paint.Color;
@@ -137,7 +138,7 @@ public class TDGraphParametersFX implements Serializable, Cloneable, ManagedPara
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("channels");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/dataPlotsFX/TDParametersFX.java b/src/dataPlotsFX/TDParametersFX.java
index c87320bc..8b614dcc 100644
--- a/src/dataPlotsFX/TDParametersFX.java
+++ b/src/dataPlotsFX/TDParametersFX.java
@@ -5,6 +5,7 @@ import java.util.ArrayList;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import javafx.geometry.Orientation;
import userDisplayFX.UserDisplayNodeParams;
@@ -122,7 +123,7 @@ public class TDParametersFX implements Serializable, Cloneable, ManagedParameter
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/dataPlotsFX/data/TDScaleInfoData.java b/src/dataPlotsFX/data/TDScaleInfoData.java
index a0d54dba..9cd2ea3c 100644
--- a/src/dataPlotsFX/data/TDScaleInfoData.java
+++ b/src/dataPlotsFX/data/TDScaleInfoData.java
@@ -5,6 +5,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import PamguardMVC.PamConstants;
@@ -105,7 +106,7 @@ public class TDScaleInfoData implements Serializable, Cloneable, ManagedParamete
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("autoDivisor");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/dataPlotsFX/rawClipDataPlot/FFTPlotSettings.java b/src/dataPlotsFX/rawClipDataPlot/FFTPlotSettings.java
index 388ea462..ec6a1030 100644
--- a/src/dataPlotsFX/rawClipDataPlot/FFTPlotSettings.java
+++ b/src/dataPlotsFX/rawClipDataPlot/FFTPlotSettings.java
@@ -5,6 +5,7 @@ import java.io.Serializable;
import PamController.PamController;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType;
@@ -48,7 +49,7 @@ public class FFTPlotSettings implements ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/dataPlotsFX/scroller/TDAcousticScrollerParams.java b/src/dataPlotsFX/scroller/TDAcousticScrollerParams.java
index c39aeb96..de80f049 100644
--- a/src/dataPlotsFX/scroller/TDAcousticScrollerParams.java
+++ b/src/dataPlotsFX/scroller/TDAcousticScrollerParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import dataPlotsFX.scrollingPlot2D.StandardPlot2DColours;
import pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType;
@@ -55,7 +56,7 @@ public class TDAcousticScrollerParams implements Cloneable, Serializable, Manage
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/dataPlotsFX/scrollingPlot2D/PlotParams2D.java b/src/dataPlotsFX/scrollingPlot2D/PlotParams2D.java
index 159fa2ad..40aed7c7 100644
--- a/src/dataPlotsFX/scrollingPlot2D/PlotParams2D.java
+++ b/src/dataPlotsFX/scrollingPlot2D/PlotParams2D.java
@@ -5,6 +5,7 @@ import java.io.Serializable;
import PamController.PamController;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.scene.paint.Color;
@@ -156,7 +157,7 @@ public class PlotParams2D implements Serializable, Cloneable, ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/dataPlotsFX/spectrogramPlotFX/SpectrogramParamsFX.java b/src/dataPlotsFX/spectrogramPlotFX/SpectrogramParamsFX.java
index 7aafc8ad..a8f2faa2 100644
--- a/src/dataPlotsFX/spectrogramPlotFX/SpectrogramParamsFX.java
+++ b/src/dataPlotsFX/spectrogramPlotFX/SpectrogramParamsFX.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import dataPlotsFX.scrollingPlot2D.PlotParams2D;
import pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType;
import javafx.beans.property.DoubleProperty;
@@ -125,7 +126,7 @@ public class SpectrogramParamsFX extends PlotParams2D implements Serializable,
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/dbht/DbHtDisplayParams.java b/src/dbht/DbHtDisplayParams.java
index 61e8386c..fb7cab16 100644
--- a/src/dbht/DbHtDisplayParams.java
+++ b/src/dbht/DbHtDisplayParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class DbHtDisplayParams implements Serializable, Cloneable, ManagedParameters {
@@ -40,7 +41,7 @@ public class DbHtDisplayParams implements Serializable, Cloneable, ManagedParame
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/dbht/DbHtParameters.java b/src/dbht/DbHtParameters.java
index 7ef321f7..2e32bb3e 100644
--- a/src/dbht/DbHtParameters.java
+++ b/src/dbht/DbHtParameters.java
@@ -9,6 +9,7 @@ import PamModel.parametermanager.FieldNotFoundException;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterData;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
public class DbHtParameters implements Serializable, Cloneable, ManagedParameters {
@@ -186,7 +187,7 @@ public class DbHtParameters implements Serializable, Cloneable, ManagedParameter
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("frequencyPoints");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/dbht/alarm/DbHtAlarmParameters.java b/src/dbht/alarm/DbHtAlarmParameters.java
index beb98589..5023e1ae 100644
--- a/src/dbht/alarm/DbHtAlarmParameters.java
+++ b/src/dbht/alarm/DbHtAlarmParameters.java
@@ -5,6 +5,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
public class DbHtAlarmParameters implements Serializable, Cloneable, ManagedParameters {
@@ -25,7 +26,7 @@ public class DbHtAlarmParameters implements Serializable, Cloneable, ManagedPara
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("returnedMeasure");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/dbht/offline/DbHtSummaryParams.java b/src/dbht/offline/DbHtSummaryParams.java
index b77adf17..34c4951a 100644
--- a/src/dbht/offline/DbHtSummaryParams.java
+++ b/src/dbht/offline/DbHtSummaryParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class DbHtSummaryParams implements Serializable, Cloneable, ManagedParameters {
@@ -23,7 +24,7 @@ public class DbHtSummaryParams implements Serializable, Cloneable, ManagedParame
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/decimator/DecimatorControl.java b/src/decimator/DecimatorControl.java
index 7bf9f8ac..1b7d2758 100644
--- a/src/decimator/DecimatorControl.java
+++ b/src/decimator/DecimatorControl.java
@@ -193,6 +193,15 @@ public class DecimatorControl extends PamControlledUnit implements PamSettings,
}
return offlineFileServer.getDataSourceName();
}
+
+ @Override
+ public String getDataLocation() {
+ if (offlineFileServer == null) {
+ return getUnitName();
+ }
+ return offlineFileServer.getDataLocation();
+ }
+
@Override
public boolean loadData(PamDataBlock dataBlock, OfflineDataLoadInfo offlineDataLoadInfo, ViewLoadObserver loadObserver) {
if (offlineFileServer == null) {
diff --git a/src/decimator/DecimatorParams.java b/src/decimator/DecimatorParams.java
index 8fe72caf..472d758a 100644
--- a/src/decimator/DecimatorParams.java
+++ b/src/decimator/DecimatorParams.java
@@ -26,6 +26,7 @@ import Filters.FilterBand;
import Filters.FilterParams;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class DecimatorParams implements Serializable, Cloneable, ManagedParameters {
@@ -102,7 +103,7 @@ public class DecimatorParams implements Serializable, Cloneable, ManagedParamete
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
}
diff --git a/src/depthReadout/DepthParameters.java b/src/depthReadout/DepthParameters.java
index 1e40df4e..99dcdd25 100644
--- a/src/depthReadout/DepthParameters.java
+++ b/src/depthReadout/DepthParameters.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class DepthParameters implements Serializable, Cloneable, ManagedParameters {
@@ -37,7 +38,7 @@ public class DepthParameters implements Serializable, Cloneable, ManagedParamete
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/depthReadout/MccDepthParameters.java b/src/depthReadout/MccDepthParameters.java
index 7859a1a7..d027670a 100644
--- a/src/depthReadout/MccDepthParameters.java
+++ b/src/depthReadout/MccDepthParameters.java
@@ -5,6 +5,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import mcc.MccJniInterface;
import mcc.mccjna.MCCConstants;
@@ -44,7 +45,7 @@ public class MccDepthParameters implements Serializable, Cloneable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
}
@@ -62,7 +63,7 @@ public class MccDepthParameters implements Serializable, Cloneable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("mccSensorParameters");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/detectionPlotFX/plots/FFTPlotParams.java b/src/detectionPlotFX/plots/FFTPlotParams.java
index 483f9051..3b8a428d 100644
--- a/src/detectionPlotFX/plots/FFTPlotParams.java
+++ b/src/detectionPlotFX/plots/FFTPlotParams.java
@@ -5,6 +5,7 @@ import java.io.Serializable;
import PamController.PamController;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType;
public class FFTPlotParams implements Serializable, Cloneable, ManagedParameters {
@@ -98,7 +99,7 @@ public class FFTPlotParams implements Serializable, Cloneable, ManagedParameter
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/detectionPlotFX/plots/SpectrumPlotParams.java b/src/detectionPlotFX/plots/SpectrumPlotParams.java
index 36d1807e..c0790a9a 100644
--- a/src/detectionPlotFX/plots/SpectrumPlotParams.java
+++ b/src/detectionPlotFX/plots/SpectrumPlotParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class SpectrumPlotParams implements Serializable, Cloneable, ManagedParameters {
@@ -38,7 +39,7 @@ public class SpectrumPlotParams implements Serializable, Cloneable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/detectionPlotFX/plots/WaveformPlotParams.java b/src/detectionPlotFX/plots/WaveformPlotParams.java
index 0c631272..fefc68b5 100644
--- a/src/detectionPlotFX/plots/WaveformPlotParams.java
+++ b/src/detectionPlotFX/plots/WaveformPlotParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import depthReadout.DepthParameters;
import fftFilter.FFTFilterParams;
@@ -63,7 +64,7 @@ public class WaveformPlotParams implements Serializable, Cloneable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/detectionPlotFX/plots/WignerPlotParams.java b/src/detectionPlotFX/plots/WignerPlotParams.java
index 0dece899..15f38498 100644
--- a/src/detectionPlotFX/plots/WignerPlotParams.java
+++ b/src/detectionPlotFX/plots/WignerPlotParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType;
@@ -51,7 +52,7 @@ public class WignerPlotParams implements Serializable, Cloneable, ManagedParamet
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/detectiongrouplocaliser/DetectionGroupSettings.java b/src/detectiongrouplocaliser/DetectionGroupSettings.java
index 318d2b8c..3bc28816 100644
--- a/src/detectiongrouplocaliser/DetectionGroupSettings.java
+++ b/src/detectiongrouplocaliser/DetectionGroupSettings.java
@@ -6,6 +6,7 @@ import java.util.Hashtable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import PamView.paneloverlay.overlaymark.OverlayMarkDataInfo;
import annotation.handler.AnnotationChoices;
@@ -109,7 +110,7 @@ public class DetectionGroupSettings implements Serializable, Cloneable, ManagedP
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("overlayMarkInfo");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/difar/DifarParameters.java b/src/difar/DifarParameters.java
index c54774e9..b8b8dc8c 100644
--- a/src/difar/DifarParameters.java
+++ b/src/difar/DifarParameters.java
@@ -15,6 +15,7 @@ import Filters.FilterType;
import PamController.PamController;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import PamUtils.PamCalendar;
import PamView.PamGui;
@@ -588,7 +589,7 @@ public class DifarParameters implements Serializable, Cloneable, ManagedParamete
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
@@ -659,7 +660,7 @@ public class DifarParameters implements Serializable, Cloneable, ManagedParamete
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
@@ -773,7 +774,7 @@ public class DifarParameters implements Serializable, Cloneable, ManagedParamete
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("groupList");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/difar/beamforming/BeamformControl.java b/src/difar/beamforming/BeamformControl.java
index edf3507b..bf04ea05 100644
--- a/src/difar/beamforming/BeamformControl.java
+++ b/src/difar/beamforming/BeamformControl.java
@@ -88,6 +88,16 @@ public class BeamformControl extends PamControlledUnit implements PamSettings, O
return DifarParameters.serialVersionUID;
}
+ @Override
+ public String getDataLocation() {
+ if (offlineFileServer != null) {
+ return offlineFileServer.getDataLocation();
+ }
+ else {
+ return null;
+ }
+ }
+
@Override
public boolean restoreSettings(
PamControlledUnitSettings pamControlledUnitSettings) {
diff --git a/src/difar/beamforming/BeamformParameters.java b/src/difar/beamforming/BeamformParameters.java
index 6688d309..2d65e576 100644
--- a/src/difar/beamforming/BeamformParameters.java
+++ b/src/difar/beamforming/BeamformParameters.java
@@ -5,6 +5,8 @@ import Filters.FilterParams;
import Filters.FilterType;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
+import PamUtils.DeepCloner;
import PamUtils.PamUtils;
public class BeamformParameters implements Serializable, Cloneable, ManagedParameters {
@@ -110,7 +112,7 @@ public class BeamformParameters implements Serializable, Cloneable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/difar/dataSelector/DifarSelectParameters.java b/src/difar/dataSelector/DifarSelectParameters.java
index bc9814ad..af1c703e 100644
--- a/src/difar/dataSelector/DifarSelectParameters.java
+++ b/src/difar/dataSelector/DifarSelectParameters.java
@@ -6,6 +6,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamUtils.PamUtils;
import PamguardMVC.dataSelector.DataSelectParams;
@@ -61,7 +62,7 @@ public class DifarSelectParameters extends DataSelectParams implements Cloneable
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/difar/demux/GreenridgeParams.java b/src/difar/demux/GreenridgeParams.java
index d86fa2da..470357df 100644
--- a/src/difar/demux/GreenridgeParams.java
+++ b/src/difar/demux/GreenridgeParams.java
@@ -5,6 +5,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class GreenridgeParams implements Serializable, Cloneable, ManagedParameters {
@@ -144,7 +145,7 @@ public class GreenridgeParams implements Serializable, Cloneable, ManagedParamet
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/difar/trackedGroups/TrackedGroupSqlLogging.java b/src/difar/trackedGroups/TrackedGroupSqlLogging.java
index 54bd708b..e3b8b15b 100644
--- a/src/difar/trackedGroups/TrackedGroupSqlLogging.java
+++ b/src/difar/trackedGroups/TrackedGroupSqlLogging.java
@@ -125,7 +125,7 @@ public class TrackedGroupSqlLogging extends SQLLogging {
*/
protected void updateData(SQLTypes sqlTypes, PamDataUnit pamDataUnit) {
- PamTableDefinition tableDef = getTableDefinition();
+ PamTableDefinition tableDef = (PamTableDefinition) getTableDefinition();
PamTableItem tableItem;
tableDef.getIndexItem().setValue(pamDataUnit.getDatabaseIndex());
diff --git a/src/effortmonitor/EffortParams.java b/src/effortmonitor/EffortParams.java
index fcd5bcb5..d19d3e36 100644
--- a/src/effortmonitor/EffortParams.java
+++ b/src/effortmonitor/EffortParams.java
@@ -5,6 +5,7 @@ import java.util.LinkedList;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class EffortParams implements Cloneable, Serializable, ManagedParameters {
@@ -100,7 +101,7 @@ public class EffortParams implements Cloneable, Serializable, ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/effortmonitor/swing/EffortDialog.java b/src/effortmonitor/swing/EffortDialog.java
index 4f4d8b7f..6850415f 100644
--- a/src/effortmonitor/swing/EffortDialog.java
+++ b/src/effortmonitor/swing/EffortDialog.java
@@ -43,7 +43,7 @@ public class EffortDialog extends PamDialog {
mainPanel.add(new JLabel("Observer name or initials"), c);
c.gridx++;
mainPanel.add(observer = new JComboBox(), c);
- outerOnly = new JRadioButton("Log uter scroll only");
+ outerOnly = new JRadioButton("Log outer scroll only");
allActions = new JRadioButton("Log all scroll actions");
ButtonGroup bg = new ButtonGroup();
bg.add(allActions);
diff --git a/src/envelopeTracer/EnvelopeParams.java b/src/envelopeTracer/EnvelopeParams.java
index 09b427f9..6076deb9 100644
--- a/src/envelopeTracer/EnvelopeParams.java
+++ b/src/envelopeTracer/EnvelopeParams.java
@@ -5,6 +5,7 @@ import java.io.Serializable;
import Filters.FilterParams;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class EnvelopeParams implements Serializable, Cloneable, ManagedParameters {
@@ -34,7 +35,7 @@ public class EnvelopeParams implements Serializable, Cloneable, ManagedParameter
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/fftFilter/FFTFilterParams.java b/src/fftFilter/FFTFilterParams.java
index dd4d8ab0..bae3a3b6 100644
--- a/src/fftFilter/FFTFilterParams.java
+++ b/src/fftFilter/FFTFilterParams.java
@@ -8,6 +8,7 @@ import org.w3c.dom.Element;
import Filters.FilterBand;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamUtils.FrequencyFormat;
public class FFTFilterParams implements Serializable, Cloneable, ManagedParameters {
@@ -62,7 +63,7 @@ public class FFTFilterParams implements Serializable, Cloneable, ManagedParamete
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
}
diff --git a/src/fftManager/Complex.java b/src/fftManager/Complex.java
index 25b53edd..e2e13ded 100644
--- a/src/fftManager/Complex.java
+++ b/src/fftManager/Complex.java
@@ -25,6 +25,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Class definition for a Complex number type.
@@ -349,7 +350,7 @@ public class Complex implements Cloneable, Serializable, Comparable, Ma
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/fftManager/FFTDataBlock.java b/src/fftManager/FFTDataBlock.java
index db04f8d6..3bf0b7b1 100644
--- a/src/fftManager/FFTDataBlock.java
+++ b/src/fftManager/FFTDataBlock.java
@@ -4,6 +4,9 @@ import java.util.List;
import java.util.ListIterator;
import java.util.Vector;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
import PamView.GeneralProjector.ParameterType;
import PamView.GeneralProjector.ParameterUnits;
import PamguardMVC.DataBlock2D;
@@ -186,6 +189,13 @@ public class FFTDataBlock extends DataBlock2D {
public DataTypeInfo getScaleInfo() {
return dataTypeInfo;
}
+ @Override
+ public Element getDataBlockXML(Document doc) {
+ Element el = super.getDataBlockXML(doc);
+ el.setAttribute("FFTLength", String.format("%d", getFftLength()));
+ el.setAttribute("FFTHop", String.format("%d", getFftHop()));
+ return el;
+ }
diff --git a/src/fftManager/FFTDataDisplayOptions.java b/src/fftManager/FFTDataDisplayOptions.java
index a6d17619..969a7a81 100644
--- a/src/fftManager/FFTDataDisplayOptions.java
+++ b/src/fftManager/FFTDataDisplayOptions.java
@@ -5,6 +5,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
public class FFTDataDisplayOptions implements Serializable, Cloneable, ManagedParameters {
@@ -45,7 +46,7 @@ public class FFTDataDisplayOptions implements Serializable, Cloneable, ManagedPa
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("maxVal");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/fileOfflineData/OfflineFileControl.java b/src/fileOfflineData/OfflineFileControl.java
index cb408652..45998aaf 100644
--- a/src/fileOfflineData/OfflineFileControl.java
+++ b/src/fileOfflineData/OfflineFileControl.java
@@ -54,6 +54,11 @@ public abstract class OfflineFileControl extends PamControlledUnit implements Of
}
+ @Override
+ public String getDataLocation() {
+ return fileParams.offlineFolder;
+ }
+
/* (non-Javadoc)
* @see PamController.PamControlledUnit#notifyModelChanged(int)
*/
diff --git a/src/fileOfflineData/OfflineFileParams.java b/src/fileOfflineData/OfflineFileParams.java
index b31d547b..82e4d61a 100644
--- a/src/fileOfflineData/OfflineFileParams.java
+++ b/src/fileOfflineData/OfflineFileParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class OfflineFileParams implements Serializable, Cloneable, ManagedParameters {
@@ -28,7 +29,7 @@ public class OfflineFileParams implements Serializable, Cloneable, ManagedParame
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/generalDatabase/DBControl.java b/src/generalDatabase/DBControl.java
index fa49abac..70e0d549 100644
--- a/src/generalDatabase/DBControl.java
+++ b/src/generalDatabase/DBControl.java
@@ -578,10 +578,16 @@ PamSettingsSource {
*/
@Override
public boolean saveStartSettings(long timeNow) {
- return dbProcess.saveStartSettings();
+ return dbProcess.saveStartSettings(timeNow);
}
+ @Override
+ public boolean saveEndSettings(long timeNow) {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
@Override
public int getNumSettings() {
if (dbSettingsStore == null) {
diff --git a/src/generalDatabase/DBControlUnit.java b/src/generalDatabase/DBControlUnit.java
index e3f9e625..0b4239b8 100644
--- a/src/generalDatabase/DBControlUnit.java
+++ b/src/generalDatabase/DBControlUnit.java
@@ -411,6 +411,11 @@ public class DBControlUnit extends DBControl implements DataOutputStore {
return getUnitName();
}
+ @Override
+ public String getDataLocation() {
+ return getDatabaseName();
+ }
+
@Override
public boolean loadData(PamDataBlock dataBlock, OfflineDataLoadInfo offlineDataLoadInfo, ViewLoadObserver loadObserver) {
SQLLogging logging = dataBlock.getLogging();
diff --git a/src/generalDatabase/DBParameters.java b/src/generalDatabase/DBParameters.java
index ce8103d7..ab06c212 100644
--- a/src/generalDatabase/DBParameters.java
+++ b/src/generalDatabase/DBParameters.java
@@ -5,6 +5,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
public class DBParameters implements Cloneable, Serializable, ManagedParameters {
@@ -75,7 +76,7 @@ public class DBParameters implements Cloneable, Serializable, ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
if (databaseName != null) {
try {
Field field = this.getClass().getDeclaredField("databaseName");
diff --git a/src/generalDatabase/DBProcess.java b/src/generalDatabase/DBProcess.java
index 167d49f5..597b1a10 100644
--- a/src/generalDatabase/DBProcess.java
+++ b/src/generalDatabase/DBProcess.java
@@ -102,6 +102,8 @@ public class DBProcess extends PamProcess {
dbSpecials.add(logSettings = new LogSettings(databaseControll, "Pamguard Settings", false));
dbSpecials.add(logLastSettings = new LogSettings(databaseControll, "Pamguard Settings Last", true));
dbSpecials.add(logViewerSettings = new LogSettings(databaseControll, "Pamguard Settings Viewer", true));
+
+ dbSpecials.add(new LogXMLSettings(databaseControll));
}
@@ -113,9 +115,13 @@ public class DBProcess extends PamProcess {
}
}
- protected boolean saveStartSettings() {
+ protected boolean saveStartSettings(long timeNow) {
PamConnection con = databaseControll.getConnection();
if (con != null) {
+ /**
+ * This first one is the 'old' pre 2022 method which saves a serialised lump of all
+ * the settings in the database. It ain't broke, so not fixing it.
+ */
for (int i = 0; i < dbSpecials.size(); i++) {
dbSpecials.get(i).pamStart(con);
}
@@ -124,6 +130,11 @@ public class DBProcess extends PamProcess {
return false;
}
+ protected boolean saveEndSettings(long timeNow) {
+
+ return true;
+ }
+
@Override
public void pamStop() {
PamConnection con = databaseControll.getConnection();
@@ -212,7 +223,7 @@ public class DBProcess extends PamProcess {
}
dataBlocks = PamController.getInstance().getDataBlocks();
- PamTableDefinition tableDefinition;
+ EmptyTableDefinition tableDefinition;
SQLLogging logging;
// for each datablock, check that the process can log (ignoring GPS process)
diff --git a/src/generalDatabase/DBSchemaWriter.java b/src/generalDatabase/DBSchemaWriter.java
index f602ad5c..a29a90b5 100644
--- a/src/generalDatabase/DBSchemaWriter.java
+++ b/src/generalDatabase/DBSchemaWriter.java
@@ -48,7 +48,7 @@ public class DBSchemaWriter {
}
- PamTableDefinition tableDef = logging.getTableDefinition();
+ EmptyTableDefinition tableDef = logging.getTableDefinition();
tableDef = logging.getBaseTableDefinition();
if (tableDef instanceof PamTableDefinition) {
@@ -63,13 +63,14 @@ public class DBSchemaWriter {
return true;
}
- private void exportDatabaseSchema(File outputFolder, PamDataBlock dataBlock, SQLLogging logging, PamTableDefinition tableDef) {
-
- /**
- * write a parent item, e.g. if tableDef is a sub class of PamTableDefinition
- */
- // String parentName = writeParentTableSchema(outputFolder, dataBlock, tableDef);
-
+ /**
+ * Generate an xml schema for a datablock.
+ * @param dataBlock
+ * @param logging
+ * @param tableDef
+ * @return
+ */
+ public Document generateDatabaseSchema(PamDataBlock dataBlock, SQLLogging logging, EmptyTableDefinition tableDef) {
String tableName = tableDef.getTableName();
Document doc = PamUtils.XMLUtils.createBlankDoc();
Element schemaEl = doc.createElement("xs:schema");
@@ -95,7 +96,20 @@ public class DBSchemaWriter {
}
}
}
+ return doc;
+ }
+
+ private void exportDatabaseSchema(File outputFolder, PamDataBlock dataBlock, SQLLogging logging, EmptyTableDefinition tableDef) {
+ /**
+ * write a parent item, e.g. if tableDef is a sub class of PamTableDefinition
+ */
+ // String parentName = writeParentTableSchema(outputFolder, dataBlock, tableDef);
+
+ Document doc = generateDatabaseSchema(dataBlock, logging, tableDef);
+
+ String tableName = tableDef.getTableName();
+
try {
File outputFile = new File(outputFolder, tableName+".xsd");
XMLUtils.writeToFile(doc, outputFile);
diff --git a/src/generalDatabase/DbSpecial.java b/src/generalDatabase/DbSpecial.java
index 05400f7a..401eac1a 100644
--- a/src/generalDatabase/DbSpecial.java
+++ b/src/generalDatabase/DbSpecial.java
@@ -9,7 +9,7 @@ import PamguardMVC.PamDataUnit;
* @author Doug Gillespie
*
*/
-abstract public class DbSpecial extends SQLLogging{
+abstract public class DbSpecial extends SQLLogging {
private DBControl dbControl;
diff --git a/src/generalDatabase/EmptyTableDefinition.java b/src/generalDatabase/EmptyTableDefinition.java
index 9e10753e..53cfd1fb 100644
--- a/src/generalDatabase/EmptyTableDefinition.java
+++ b/src/generalDatabase/EmptyTableDefinition.java
@@ -300,7 +300,7 @@ public class EmptyTableDefinition implements Cloneable {
* @param tableName
* @return reference to the database deinition if it exists, or null
*/
- static PamTableDefinition findTableDefinition(String tableName) {
+ static EmptyTableDefinition findTableDefinition(String tableName) {
String searchName = EmptyTableDefinition.deblankString(tableName);
SQLLogging log = SQLLogging.findLogger(searchName);
if (log == null) return null;
@@ -389,6 +389,15 @@ public class EmptyTableDefinition implements Cloneable {
this.updatePolicy = updatePolicy;
}
+ public PamConnection getCheckedConnection() {
+ return checkedConnection;
+ }
+
+ public void setCheckedConnection(PamConnection checkedConnection) {
+ this.checkedConnection = checkedConnection;
+ }
+
+
@Override
protected EmptyTableDefinition clone() {
try {
diff --git a/src/generalDatabase/LogSettings.java b/src/generalDatabase/LogSettings.java
index af5305e9..23b713be 100644
--- a/src/generalDatabase/LogSettings.java
+++ b/src/generalDatabase/LogSettings.java
@@ -23,7 +23,7 @@ import PamUtils.PamCalendar;
import PamguardMVC.PamDataUnit;
/**
- * Functions for writing Pamguard Settings into any database as character data
+ * Functions for writing serialised Pamguard Settings into any database as character data
* Runs at DAQ start, goes through the settings manager list and for each
* set of settings, it serialises the settings data into a binary array, this
* is then converted from binary data to 6 bit ascii data (using the character set
@@ -185,6 +185,7 @@ public class LogSettings extends DbSpecial {
DeserialisationWarning dsWarning = new DeserialisationWarning(getDbControl().getDatabaseName());
SQLTypes sqlTypes = con.getSqlTypes();
+
boolean haveData;
if (result != null) try {
haveData = result.next();
@@ -193,7 +194,7 @@ public class LogSettings extends DbSpecial {
// transfer data back into the tableItems store.
transferDataFromResult(sqlTypes, result);
- tableItem = getTableDefinition().getTimeStampItem();
+ tableItem = tableDef.getTimeStampItem();
// timestamp = (Timestamp) tableItem.getTimestampValue();
timeMillis = sqlTypes.millisFromTimeStamp(tableItem.getValue());
diff --git a/src/generalDatabase/LogXMLDataUnit.java b/src/generalDatabase/LogXMLDataUnit.java
new file mode 100644
index 00000000..63189784
--- /dev/null
+++ b/src/generalDatabase/LogXMLDataUnit.java
@@ -0,0 +1,75 @@
+package generalDatabase;
+
+import PamController.PamSettings;
+import PamguardMVC.PamDataUnit;
+
+/**
+ * simple data unit for use with the LogXMLSettings class
+ * @author dg50
+ *
+ */
+public class LogXMLDataUnit extends PamDataUnit {
+
+ private long processTime;
+ private PamSettings pamSettings;
+ private String xml;
+ private Long dataEnd, processEnd;
+
+ public LogXMLDataUnit(long timeMilliseconds, long processTime, PamSettings pamSettings, String xml) {
+ super(timeMilliseconds);
+ this.processTime = processTime;
+ this.pamSettings = pamSettings;
+ this.xml = xml;
+ }
+
+ /**
+ * @return the dataEnd
+ */
+ public Long getDataEnd() {
+ return dataEnd;
+ }
+
+ /**
+ * @param dataEnd the dataEnd to set
+ */
+ public void setDataEnd(Long dataEnd) {
+ this.dataEnd = dataEnd;
+ }
+
+ /**
+ * @return the processEnd
+ */
+ public Long getProcessEnd() {
+ return processEnd;
+ }
+
+ /**
+ * @param processEnd the processEnd to set
+ */
+ public void setProcessEnd(Long processEnd) {
+ this.processEnd = processEnd;
+ }
+
+ /**
+ * @return the processTime
+ */
+ public long getProcessTime() {
+ return processTime;
+ }
+
+ /**
+ * @return the pamSettings
+ */
+ public PamSettings getPamSettings() {
+ return pamSettings;
+ }
+
+ /**
+ * @return the xml
+ */
+ public String getXml() {
+ return xml;
+ }
+
+
+}
diff --git a/src/generalDatabase/LogXMLSettings.java b/src/generalDatabase/LogXMLSettings.java
new file mode 100644
index 00000000..3f33c188
--- /dev/null
+++ b/src/generalDatabase/LogXMLSettings.java
@@ -0,0 +1,123 @@
+package generalDatabase;
+
+import java.io.Serializable;
+import java.util.HashMap;
+
+import org.w3c.dom.Document;
+
+import PamController.PamControlledUnit;
+import PamController.PamController;
+import PamController.PamSettings;
+import PamController.PamguardVersionInfo;
+import PamController.settings.output.xml.PamguardXMLWriter;
+import PamUtils.PamCalendar;
+import PamguardMVC.PamDataUnit;
+/**
+ * 2022 Additional way of saving settings for each module into the database in more human readable
+ * XML format.
+ * In other ways, similar to LogSettings which saves serialised Java. This will write a line
+ * per module. A main difference is that on pamStop it will update the end time for each line, so
+ * that we have a record of analysis effort for each module. Will therefore need to store the last
+ * index of the entry for each module, so that we can update the appropriate row.
+ * @author dg50
+ *
+ */
+public class LogXMLSettings extends DbSpecial {
+
+ private XMLSettingsTableDefinition xmlTableDef;
+
+ private HashMap moduleRows;
+
+ private PamguardXMLWriter xmlWriter;
+
+ public LogXMLSettings(DBControl dbControl) {
+ super(dbControl);
+ xmlTableDef = new XMLSettingsTableDefinition("Module Effort");
+ setTableDefinition(xmlTableDef);
+ moduleRows = new HashMap<>();
+ xmlWriter = PamguardXMLWriter.getXMLWriter();
+ }
+
+ @Override
+ public void pamStart(PamConnection con) {
+ long time = PamCalendar.getTimeInMillis();
+ saveModuleSettings(con, time);
+ }
+
+ @Override
+ public void pamStop(PamConnection con) {
+ long time = PamCalendar.getTimeInMillis();
+ updateModuleSettings(con, time);
+ }
+
+ private void saveModuleSettings(PamConnection con, long dataTime) {
+ int n = PamController.getInstance().getNumControlledUnits();
+ long now = System.currentTimeMillis();
+ for (int i = 0; i < n; i++) {
+ saveModuleSettings(con, dataTime, now, PamController.getInstance().getControlledUnit(i));
+ }
+
+ }
+
+ private void saveModuleSettings(PamConnection con, long dataTime, long now, PamControlledUnit controlledUnit) {
+ if (controlledUnit instanceof PamSettings == false) {
+ return;
+ }
+ PamSettings pamSettings = (PamSettings) controlledUnit;
+ Serializable settings = pamSettings.getSettingsReference();
+ Document doc = xmlWriter.writeOneModule(pamSettings, dataTime);
+ String xmlString = xmlWriter.getAsString(doc, true);
+ LogXMLDataUnit logXMLDataUnit = new LogXMLDataUnit(dataTime, now, pamSettings, xmlString);
+
+ logData(logXMLDataUnit);
+ int dbIndex = logXMLDataUnit.getDatabaseIndex();
+ moduleRows.put(getModuleHash(pamSettings), logXMLDataUnit);
+ }
+
+ private void updateModuleSettings(PamConnection con, long dataTime) {
+ int n = PamController.getInstance().getNumControlledUnits();
+ long now = System.currentTimeMillis();
+ for (int i = 0; i < n; i++) {
+ updateModuleSettings(con, dataTime, now, PamController.getInstance().getControlledUnit(i));
+ }
+
+ }
+
+ private void updateModuleSettings(PamConnection con, long dataTime, long now, PamControlledUnit controlledUnit) {
+ if (controlledUnit instanceof PamSettings == false) {
+ return;
+ }
+ PamSettings pamSettings = (PamSettings) controlledUnit;
+ LogXMLDataUnit logXMLDataUnit = moduleRows.get(getModuleHash(pamSettings));
+ if (logXMLDataUnit == null) {
+ return;
+ }
+ logXMLDataUnit.setDataEnd(dataTime);
+ logXMLDataUnit.setProcessEnd(now);
+ reLogData(con, logXMLDataUnit);
+ }
+
+ private String getModuleHash(PamSettings pamSettings) {
+ if (pamSettings == null) {
+ return null;
+ }
+ return pamSettings.getUnitName()+pamSettings.getUnitType();
+ }
+
+ @Override
+ public void setTableData(SQLTypes sqlTypes, PamDataUnit pamDataUnit) {
+ LogXMLDataUnit logXMLDataUnit = (LogXMLDataUnit) pamDataUnit;
+ PamSettings pamSettings = logXMLDataUnit.getPamSettings();
+
+ xmlTableDef.getDataStart().setValue(sqlTypes.getTimeStamp(pamDataUnit.getTimeMilliseconds()));
+ xmlTableDef.getDataEnd().setValue(sqlTypes.getTimeStamp(logXMLDataUnit.getDataEnd()));
+ xmlTableDef.getProcessStart().setValue(sqlTypes.getTimeStamp(logXMLDataUnit.getProcessTime()));
+ xmlTableDef.getProcessEnd().setValue(sqlTypes.getTimeStamp(logXMLDataUnit.getProcessEnd()));
+ xmlTableDef.getName().setValue(pamSettings.getUnitName());
+ xmlTableDef.getType().setValue(pamSettings.getUnitType());
+ xmlTableDef.getPamGuardVersion().setValue(PamguardVersionInfo.version);
+ xmlTableDef.getSettingsVersion().setValue(pamSettings.getSettingsVersion());
+ xmlTableDef.getXmlSettings().setValue(logXMLDataUnit.getXml());
+ }
+
+}
diff --git a/src/generalDatabase/MySQLParameters.java b/src/generalDatabase/MySQLParameters.java
index 9491a6da..cadd498f 100644
--- a/src/generalDatabase/MySQLParameters.java
+++ b/src/generalDatabase/MySQLParameters.java
@@ -6,6 +6,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class MySQLParameters implements Cloneable, Serializable, ManagedParameters {
@@ -37,7 +38,7 @@ public class MySQLParameters implements Cloneable, Serializable, ManagedParamete
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("databaseName");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/generalDatabase/PamSubtableDefinition.java b/src/generalDatabase/PamSubtableDefinition.java
index 0aa20215..ec3780b0 100644
--- a/src/generalDatabase/PamSubtableDefinition.java
+++ b/src/generalDatabase/PamSubtableDefinition.java
@@ -51,6 +51,7 @@ public class PamSubtableDefinition extends PamTableDefinition {
addTableItem(parentUID = new PamTableItem(PARENTUIDNAME, Types.BIGINT));
addTableItem(longName = new PamTableItem(LONGDATANAME, Types.CHAR, DATANAME_LENGTH));
addTableItem(binaryFilename = new PamTableItem(BINARYFILE, Types.CHAR, BINARY_FILE_NAME_LENGTH));
+ setUseCheatIndexing(false);
}
public PamTableItem getParentID() {
diff --git a/src/generalDatabase/PamTableDefinition.java b/src/generalDatabase/PamTableDefinition.java
index e8a2b5dc..8424b683 100644
--- a/src/generalDatabase/PamTableDefinition.java
+++ b/src/generalDatabase/PamTableDefinition.java
@@ -192,14 +192,7 @@ public class PamTableDefinition extends EmptyTableDefinition implements Cloneabl
public PamTableItem getUidItem() {
return uid;
}
- public PamConnection getCheckedConnection() {
- return checkedConnection;
- }
-
- public void setCheckedConnection(PamConnection checkedConnection) {
- this.checkedConnection = checkedConnection;
- }
-
+
public PamTableItem getUpdateReference() {
return updateReference;
}
diff --git a/src/generalDatabase/PamTableItem.java b/src/generalDatabase/PamTableItem.java
index 2a046623..e73772e8 100644
--- a/src/generalDatabase/PamTableItem.java
+++ b/src/generalDatabase/PamTableItem.java
@@ -377,7 +377,7 @@ public class PamTableItem implements Cloneable {
* column for use in cross referencing.
*/
public static PamTableItem findTableItem(String tableName, String columnName) {
- PamTableDefinition tableDef = EmptyTableDefinition.
+ EmptyTableDefinition tableDef = EmptyTableDefinition.
findTableDefinition(EmptyTableDefinition.deblankString(tableName));
if (tableDef == null) return null;
return tableDef.findTableItem(EmptyTableDefinition.deblankString(columnName));
diff --git a/src/generalDatabase/SQLLogging.java b/src/generalDatabase/SQLLogging.java
index e9c094ed..8f8b9f84 100644
--- a/src/generalDatabase/SQLLogging.java
+++ b/src/generalDatabase/SQLLogging.java
@@ -190,7 +190,7 @@ public abstract class SQLLogging {
ArrayList blockList = PamController.getInstance()
.getDataBlocks();
SQLLogging logger;
- PamTableDefinition tableDef;
+ EmptyTableDefinition tableDef;
for (int i = 0; i < blockList.size(); i++) {
if ((logger = blockList.get(i).getLogging()) != null) {
tableDef = logger.getTableDefinition();
@@ -293,37 +293,42 @@ public abstract class SQLLogging {
* @param superDetection
*/
protected void fillTableData(SQLTypes sqlTypes, PamDataUnit pamDataUnit, PamDataUnit superDetection) {
+
+ EmptyTableDefinition emptyTableDef = getTableDefinition();
- PamTableDefinition tableDef = getTableDefinition();
PamTableItem tableItem;
- tableDef.getIndexItem().setValue(pamDataUnit.getDatabaseIndex());
- /*
- * All tables have a timestamp near the front of the table. And all data
- * units have a time in milliseconds, so always fill this in !
- */
- tableDef.getTimeStampItem().setValue(
- sqlTypes.getTimeStamp(pamDataUnit.getTimeMilliseconds()));
+ emptyTableDef.getIndexItem().setValue(pamDataUnit.getDatabaseIndex());
+
+ if (emptyTableDef instanceof PamTableDefinition) {
+ PamTableDefinition tableDef = (PamTableDefinition) emptyTableDef;
+ /*
+ * All tables have a timestamp near the front of the table. And all data
+ * units have a time in milliseconds, so always fill this in !
+ */
+ tableDef.getTimeStampItem().setValue(
+ sqlTypes.getTimeStamp(pamDataUnit.getTimeMilliseconds()));
- tableDef.getTimeStampMillis().setValue((int) (pamDataUnit.getTimeMilliseconds()%1000));
+ tableDef.getTimeStampMillis().setValue((int) (pamDataUnit.getTimeMilliseconds()%1000));
- tableDef.getLocalTimeItem().setValue(sqlTypes.getLocalTimeStamp(pamDataUnit.getTimeMilliseconds()));
+ tableDef.getLocalTimeItem().setValue(sqlTypes.getLocalTimeStamp(pamDataUnit.getTimeMilliseconds()));
- tableDef.getPCTimeItem().setValue(sqlTypes.getTimeStamp(System.currentTimeMillis()));
+ tableDef.getPCTimeItem().setValue(sqlTypes.getTimeStamp(System.currentTimeMillis()));
- tableDef.getUidItem().setValue(pamDataUnit.getUID());
+ tableDef.getUidItem().setValue(pamDataUnit.getUID());
- tableDef.getChannelBitmap().setValue(pamDataUnit.getChannelBitmap());
+ tableDef.getChannelBitmap().setValue(pamDataUnit.getChannelBitmap());
- tableDef.getSequenceBitmap().setValue(pamDataUnit.getSequenceBitmapObject());
+ tableDef.getSequenceBitmap().setValue(pamDataUnit.getSequenceBitmapObject());
- if (tableDef.getUpdateReference() != null) {
- tableDef.getUpdateReference().setValue(pamDataUnit.getDatabaseIndex());
+ if (tableDef.getUpdateReference() != null) {
+ tableDef.getUpdateReference().setValue(pamDataUnit.getDatabaseIndex());
+ }
}
- for (int i = 0; i < tableDef.getTableItemCount(); i++) {
+ for (int i = 0; i < emptyTableDef.getTableItemCount(); i++) {
- tableItem = tableDef.getTableItem(i);
+ tableItem = emptyTableDef.getTableItem(i);
// if (tableItem.isCounter()) {
// tableItem.setValue(1);
// }
@@ -333,8 +338,8 @@ public abstract class SQLLogging {
}
}
- if (tableDef instanceof PamSubtableDefinition) {
- PamSubtableDefinition subTableDef = (PamSubtableDefinition) tableDef;
+ if (emptyTableDef instanceof PamSubtableDefinition) {
+ PamSubtableDefinition subTableDef = (PamSubtableDefinition) emptyTableDef;
fillSubTableData(subTableDef, pamDataUnit, superDetection);
}
@@ -525,7 +530,7 @@ public abstract class SQLLogging {
}
// now put some sql into the statement
// if (resultSet == null) {
- PamTableDefinition tableDef = getTableDefinition();
+ EmptyTableDefinition tableDef = getTableDefinition();
String sqlString = tableDef.getSQLSelectString(con.getSqlTypes());
// sqlString = "select \"comment\" from userinput";
try {
@@ -546,6 +551,71 @@ public abstract class SQLLogging {
// }
return resultSet;
}
+
+ /**
+ * Find the data point which is closest in time to that given, or null
+ * returning whatever type of data unit this deals with.
+ * @param timeMillis
+ * @return
+ */
+ public PamDataUnit findClosestDataPoint(PamConnection con, long timeMillis) {
+
+ PamCursor pamCursor = loggingCursorFinder.getCursor(con, pamTableDefinition);
+
+ // can't really do any math with the string based dates, so will have to query from
+ // a few s before the time we want.
+ PamDataUnit[] beforeNafter = new PamDataUnit[2];
+
+ SQLTypes sqlTypes = con.getSqlTypes();
+
+ for (int i = 0; i < 2; i++) {
+ String clause;
+
+ if (i == 0) {
+ clause = String.format("WHERE UTC <= %s ORDER BY UTC DESC", sqlTypes.formatDBDateTimeQueryString(timeMillis));
+ }
+ else {
+ clause = String.format("WHERE UTC >= %s ORDER BY UTC ASC", sqlTypes.formatDBDateTimeQueryString(timeMillis));
+ }
+
+ ResultSet result = pamCursor.openReadOnlyCursor(con, clause);
+ if (result==null) {
+ return null;
+ }
+
+ PamTableItem tableItem;
+ try {
+ if (result.next()) {
+ // for (int i = 0; i < pamTableDefinition.getTableItemCount(); i++) {
+ // tableItem = pamTableDefinition.getTableItem(i);
+ // tableItem.setValue(result.getObject(i + 1));
+ // }
+ // return true;
+ boolean ok = transferDataFromResult(con.getSqlTypes(), result);
+ result.close();
+ beforeNafter[i] = createDataUnit(sqlTypes, lastTime, lastLoadIndex);
+ }
+ } catch (SQLException ex) {
+ ex.printStackTrace();
+ continue;
+ }
+ }
+ // now pick the closest
+ if (beforeNafter[0] == null) {
+ return beforeNafter[1];
+ }
+ if (beforeNafter[1] == null) {
+ return beforeNafter[0];
+ }
+ long t1 = timeMillis-beforeNafter[0].getTimeMilliseconds();
+ long t2 = beforeNafter[1].getTimeMilliseconds()-timeMillis;
+ if (t1 < t2) {
+ return beforeNafter[0];
+ }
+ else {
+ return beforeNafter[1];
+ }
+ }
/**
* Called when a new database is connected to read the last values back in
@@ -1079,7 +1149,7 @@ public abstract class SQLLogging {
public boolean transferDataFromResult(SQLTypes sqlTypes, ResultSet resultSet) {
- PamTableDefinition tableDef = getTableDefinition();
+ EmptyTableDefinition tableDef = getTableDefinition();
PamTableItem tableItem;
try {
for (int i = 0; i < tableDef.getTableItemCount(); i++) {
@@ -1090,17 +1160,20 @@ public abstract class SQLLogging {
// Timestamp ts = (Timestamp) getTableDefinition().getTimeStampItem().getValue();
// Timestamp ts = getTableDefinition().getTimeStampItem().getTimestampValue();
// lastTime = sqlTypes.millisFromTimeStamp(ts);
- lastTime = sqlTypes.millisFromTimeStamp(getTableDefinition().getTimeStampItem().getValue());
- if (lastTime%1000 == 0) {
- // some databases may have stored the milliseconds, in which
- // case this next bit is redundant.
- lastTime += getTableDefinition().getTimeStampMillis().getIntegerValue();
- }
-
lastLoadIndex = getTableDefinition().getIndexItem().getIntegerValue();
- lastLoadUID = getTableDefinition().getUidItem().getLongObject();
- lastChannelBitmap = getTableDefinition().getChannelBitmap().getIntegerValue();
- lastSequenceBitmap = getTableDefinition().getSequenceBitmap().getIntegerObject();
+ if (tableDef instanceof PamTableDefinition) {
+ PamTableDefinition pamTableDef = (PamTableDefinition) tableDef;
+ lastTime = sqlTypes.millisFromTimeStamp(pamTableDef.getTimeStampItem().getValue());
+ if (lastTime%1000 == 0) {
+ // some databases may have stored the milliseconds, in which
+ // case this next bit is redundant.
+ lastTime += pamTableDef.getTimeStampMillis().getIntegerValue();
+ }
+
+ lastLoadUID = pamTableDef.getUidItem().getLongObject();
+ lastChannelBitmap = pamTableDef.getChannelBitmap().getIntegerValue();
+ lastSequenceBitmap = pamTableDef.getSequenceBitmap().getIntegerObject();
+ }
return true;
} catch (SQLException ex) {
diff --git a/src/generalDatabase/SQLLoggingAddon.java b/src/generalDatabase/SQLLoggingAddon.java
index 6d347fb4..ff8bd561 100644
--- a/src/generalDatabase/SQLLoggingAddon.java
+++ b/src/generalDatabase/SQLLoggingAddon.java
@@ -15,7 +15,7 @@ public interface SQLLoggingAddon {
* Add a load of columns to an existing table definition
* @param pamTableDefinition
*/
- public void addTableItems(PamTableDefinition pamTableDefinition);
+ public void addTableItems(EmptyTableDefinition pamTableDefinition);
/**
* Save data - that is transfer data from the pamDataUnit to the data objects
@@ -24,7 +24,7 @@ public interface SQLLoggingAddon {
* @param pamDataUnit data unit
* @return true if successful
*/
- public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit);
+ public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit);
/**
* Load data - that is read data from the table definition and turn it into something sensible
@@ -33,7 +33,7 @@ public interface SQLLoggingAddon {
* @param pamDataUnit data unit
* @return true if successful
*/
- public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit);
+ public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit);
/**
* Get a name for the SQLLogging Addon. this is used
diff --git a/src/generalDatabase/SQLTypes.java b/src/generalDatabase/SQLTypes.java
index a81edd89..fd8ccb56 100644
--- a/src/generalDatabase/SQLTypes.java
+++ b/src/generalDatabase/SQLTypes.java
@@ -387,6 +387,7 @@ public class SQLTypes {
return timestamp.getTime() + tz.getOffset(timestamp.getTime());
}
else if (timeValue instanceof String) {
+ timeValue = ((String) timeValue).replace("'", "");
return PamCalendar.millisFromDateString((String) timeValue, false);
}
if (timeValue instanceof Long) {
diff --git a/src/generalDatabase/XMLSettingsTableDefinition.java b/src/generalDatabase/XMLSettingsTableDefinition.java
new file mode 100644
index 00000000..8d40bc55
--- /dev/null
+++ b/src/generalDatabase/XMLSettingsTableDefinition.java
@@ -0,0 +1,94 @@
+package generalDatabase;
+
+import java.sql.Types;
+
+import PamguardMVC.PamConstants;
+
+public class XMLSettingsTableDefinition extends PamTableDefinition {
+
+ private PamTableItem dataStart, dataEnd, processStart, processEnd, type, name, pamGuardVersion, settingsVersion, xmlSettings;
+
+ public XMLSettingsTableDefinition(String tableName) {
+ super(tableName, SQLLogging.UPDATE_POLICY_WRITENEW);
+ pamTableItems.add(dataStart = new PamTableItem("Data Start", Types.TIMESTAMP, "Data start time"));
+ pamTableItems.add(dataEnd = new PamTableItem("Data End", Types.TIMESTAMP, "Data end time"));
+ pamTableItems.add(processStart = new PamTableItem("Process Start", Types.TIMESTAMP, "Process start time"));
+ pamTableItems.add(processEnd = new PamTableItem("Process End", Types.TIMESTAMP, "Process end time"));
+ addTableItem(type = new PamTableItem("unitType", Types.CHAR, PamConstants.MAX_ITEM_NAME_LENGTH));
+ addTableItem(name = new PamTableItem("unitName", Types.CHAR, PamConstants.MAX_ITEM_NAME_LENGTH));
+ addTableItem(pamGuardVersion = new PamTableItem("PAMGuardVersion", Types.INTEGER));
+ addTableItem(settingsVersion = new PamTableItem("SettingsVersion", Types.INTEGER));
+ addTableItem(xmlSettings = new PamTableItem("XMLSettings", Types.VARCHAR));
+ setUseCheatIndexing(false);
+ }
+
+
+ /**
+ * @return the dataStart
+ */
+ public PamTableItem getDataStart() {
+ return dataStart;
+ }
+
+
+ /**
+ * @return the dataEnd
+ */
+ public PamTableItem getDataEnd() {
+ return dataEnd;
+ }
+
+
+ /**
+ * @return the processStart
+ */
+ public PamTableItem getProcessStart() {
+ return processStart;
+ }
+
+
+ /**
+ * @return the processEnd
+ */
+ public PamTableItem getProcessEnd() {
+ return processEnd;
+ }
+
+
+ /**
+ * @return the type
+ */
+ public PamTableItem getType() {
+ return type;
+ }
+
+ /**
+ * @return the name
+ */
+ public PamTableItem getName() {
+ return name;
+ }
+
+ /**
+ * @return the pamGuardVersion
+ */
+ public PamTableItem getPamGuardVersion() {
+ return pamGuardVersion;
+ }
+
+ /**
+ * @return the settingsVersion
+ */
+ public PamTableItem getSettingsVersion() {
+ return settingsVersion;
+ }
+
+ /**
+ * @return the xmlSettings
+ */
+ public PamTableItem getXmlSettings() {
+ return xmlSettings;
+ }
+
+
+}
diff --git a/src/generalDatabase/dataExport/ValueFilterParams.java b/src/generalDatabase/dataExport/ValueFilterParams.java
index 15ffdfbd..52c57cfd 100644
--- a/src/generalDatabase/dataExport/ValueFilterParams.java
+++ b/src/generalDatabase/dataExport/ValueFilterParams.java
@@ -6,6 +6,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Abstract class for ValueFilters for filtering database data tables.
@@ -110,7 +111,7 @@ public abstract class ValueFilterParams implements Cloneable, Serializable, Mana
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/generalDatabase/lookupTables/LookupItem.java b/src/generalDatabase/lookupTables/LookupItem.java
index 7115406e..9ee05094 100644
--- a/src/generalDatabase/lookupTables/LookupItem.java
+++ b/src/generalDatabase/lookupTables/LookupItem.java
@@ -5,6 +5,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamView.PamSymbol;
import PamView.PamSymbolType;
@@ -232,7 +233,7 @@ public class LookupItem implements Cloneable, Serializable, ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/generalDatabase/lookupTables/LookupList.java b/src/generalDatabase/lookupTables/LookupList.java
index 8e0a0e0c..7714cdd3 100644
--- a/src/generalDatabase/lookupTables/LookupList.java
+++ b/src/generalDatabase/lookupTables/LookupList.java
@@ -7,6 +7,7 @@ import java.util.Vector;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Handles information for a single list from the look up table
@@ -253,7 +254,7 @@ public class LookupList implements Cloneable, Serializable, ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/generalDatabase/parameterstore/ParameterDatabaseStore.java b/src/generalDatabase/parameterstore/ParameterDatabaseStore.java
new file mode 100644
index 00000000..29c740eb
--- /dev/null
+++ b/src/generalDatabase/parameterstore/ParameterDatabaseStore.java
@@ -0,0 +1,187 @@
+package generalDatabase.parameterstore;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+import java.util.Arrays;
+import java.util.Collection;
+
+import PamModel.parametermanager.ManagedParameters;
+import PamModel.parametermanager.PamParameterData;
+import PamModel.parametermanager.PamParameterSet;
+import generalDatabase.DBControlUnit;
+import generalDatabase.EmptyTableDefinition;
+import generalDatabase.PamConnection;
+import generalDatabase.PamTableItem;
+import generalDatabase.SQLTypes;
+
+/**
+ * Store parameters from a managed parameter set in the PAMGuard database. These go into a dead simple table, which has
+ * two columns. The first is a name, the second a string value. Each parameter can only appear once.
+ * This works with ManagedParameters using the same names and field names that go into the xml output.
+ * @author dg50
+ *
+ */
+public class ParameterDatabaseStore {
+
+
+ private EmptyTableDefinition tableDef;
+ private PamTableItem nameItem, dataItem;
+
+ public ParameterDatabaseStore(String tableName) {
+ tableDef = new EmptyTableDefinition(tableName);
+ tableDef.addTableItem(nameItem = new PamTableItem("ParameterName", Types.VARCHAR));
+ tableDef.addTableItem(dataItem = new PamTableItem("Value", Types.VARCHAR));
+ }
+
+ public boolean saveParameterSet(ManagedParameters managedParameters) {
+ if (managedParameters == null) {
+ return false;
+ }
+ return saveParameterSet(managedParameters.getClass().getSimpleName(), managedParameters);
+ }
+
+ private boolean saveParameterSet(String name, ManagedParameters managedParameters) {
+ DBControlUnit dbControl = DBControlUnit.findDatabaseControl();
+ if (dbControl == null) {
+ return false;
+ }
+ PamConnection con = dbControl.getConnection();
+ if (checkTable(con) == false) {
+ return false;
+ }
+
+ String prefix;
+ if (name == null) {
+ prefix = "";
+ }
+ else {
+ prefix = name + ".";
+ }
+ PamParameterSet paramSet = managedParameters.getParameterSet();
+ Collection params = paramSet.getParameterCollection();
+ for (PamParameterData paramData : params) {
+ String paramName = paramData.getFieldName();
+ paramName = prefix + paramName;
+ Object data = null;
+ try {
+ data = paramData.getData();// .getField().get(managedParameters);
+ } catch (IllegalArgumentException | IllegalAccessException e) {
+ e.printStackTrace();
+ }
+// System.out.printf("Store param \"%s\" as \"%s\"\n", paramName, data);
+ saveToDatabase(con, paramName, data);
+ }
+ dbControl.commitChanges();
+
+ return true;
+ }
+
+ private boolean saveToDatabase(PamConnection con, String name, Object data) {
+ int[] existing = findExistingRows(con, name);
+ boolean ok = true;
+ if (existing == null || existing.length == 0) {
+ ok |= newRecord(con, name, data);
+ }
+ else {
+ ok |= updateRecord(con, existing[0], name, data);
+ if (existing.length > 1) {
+ for (int i = 1; i < existing.length; i++) {
+ ok |= deleteDuplicateRow(con, existing[i]);
+ }
+ }
+ }
+ return true;
+ }
+
+ private int[] findExistingRows(PamConnection con, String name) {
+ /**
+ * Find existing rows with that name.
+ */
+ int[] rows = new int[0];
+ if (con == null) {
+ return rows;
+ }
+ String qStr = String.format("SELECT Id FROM %s WHERE %s='%s'", tableDef.getTableName(), nameItem.getName(), name);
+ try {
+ Statement stmt = con.getConnection().createStatement();
+ ResultSet res = stmt.executeQuery(qStr);
+ while (res.next()) {
+ int rowId = res.getInt(1);
+ rows = Arrays.copyOf(rows, rows.length+1);
+ rows[rows.length-1] = rowId;
+ }
+ res.close();
+ stmt.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ return rows;
+ }
+
+ private boolean newRecord(PamConnection con, String name, Object data) {
+
+ String insertStr = tableDef.getSQLInsertString(con.getSqlTypes());
+ try {
+ PreparedStatement stmt = con.getConnection().prepareStatement(insertStr);
+ stmt.setString(1, name);
+ if (data == null) {
+ stmt.setNull(2, Types.VARCHAR);
+ }
+ else {
+ stmt.setString(2, data.toString());
+ }
+ stmt.executeUpdate();
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean updateRecord(PamConnection con, int iRow, String name, Object data) {
+ SQLTypes st = con.getSqlTypes();
+ String updateString = String.format("UPDATE %s SET %s = '%s' WHERE Id = %d", tableDef.getTableName(),
+ st.formatColumnName(dataItem.getName()), data, iRow);
+
+ try {
+ PreparedStatement stmt = con.getConnection().prepareStatement(updateString);
+ stmt.executeUpdate();
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean deleteDuplicateRow(PamConnection con, int rowId) {
+
+ String delStr = String.format("DELETE FROM %s WHERE Id=%d", tableDef.getTableName(), rowId);
+
+ try {
+ PreparedStatement stmt = con.getConnection().prepareStatement(delStr);
+ stmt.executeUpdate();
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ return false;
+ }
+ return true;
+ }
+
+ private boolean checkTable(PamConnection con) {
+ DBControlUnit dbControl = DBControlUnit.findDatabaseControl();
+ if (dbControl == null) {
+ return false;
+ }
+ dbControl.commitChanges();
+ return dbControl.getDbProcess().checkTable(tableDef);
+ }
+
+}
diff --git a/src/generalDatabase/sqlite/SqliteSQLTypes.java b/src/generalDatabase/sqlite/SqliteSQLTypes.java
index 580c8c5e..4f2baf73 100644
--- a/src/generalDatabase/sqlite/SqliteSQLTypes.java
+++ b/src/generalDatabase/sqlite/SqliteSQLTypes.java
@@ -10,7 +10,7 @@ import PamUtils.PamCalendar;
public class SqliteSQLTypes extends SQLTypes {
- protected static final SQLiteConfig.DateClass dateClass = SQLiteConfig.DateClass.TEXT;
+ public static final SQLiteConfig.DateClass dateClass = SQLiteConfig.DateClass.TEXT;
@Override
public String typeToString(int sqlType, int length, boolean counter) {
diff --git a/src/gpl/GPLParameters.java b/src/gpl/GPLParameters.java
index 666c559e..fcda34d9 100644
--- a/src/gpl/GPLParameters.java
+++ b/src/gpl/GPLParameters.java
@@ -6,6 +6,7 @@ import java.io.Serializable;
import PamModel.parametermanager.FieldNotFoundException;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamguardMVC.blockprocess.PamBlockParams;
import gpl.contour.ContourMerge;
@@ -198,7 +199,7 @@ public class GPLParameters implements Serializable, Cloneable, ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
ps.findParameterData("minPeakGap").setInfo("Minimum gap", "bins", "Minimum gap between peaks (FFT time bins)");
ps.findParameterData("minCallLengthSeconds").setInfo("Minimum length", "bins", "Minimum length of a detection in seconds");
diff --git a/src/gpl/io/GPLLogging.java b/src/gpl/io/GPLLogging.java
index d8817bdc..c407193f 100644
--- a/src/gpl/io/GPLLogging.java
+++ b/src/gpl/io/GPLLogging.java
@@ -5,6 +5,7 @@ import java.sql.Types;
import PamDetection.AcousticSQLLogging;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
+import generalDatabase.EmptyTableDefinition;
import generalDatabase.PamTableDefinition;
import generalDatabase.PamTableItem;
import generalDatabase.SQLTypes;
@@ -22,7 +23,7 @@ public class GPLLogging extends AcousticSQLLogging {
super(gplDetectionBlock, gplControlledUnit.getUnitName() + " Detections");
this.gplControlledUnit = gplControlledUnit;
- PamTableDefinition pamTable = getTableDefinition();
+ EmptyTableDefinition pamTable = getTableDefinition();
pamTable.addTableItem(peakValue = new PamTableItem("PeakValue", Types.REAL));
pamTable.addTableItem(contourArea = new PamTableItem("ContourArea", Types.REAL));
}
diff --git a/src/group3dlocaliser/Group3DParams.java b/src/group3dlocaliser/Group3DParams.java
index fbf75743..6467a9ad 100644
--- a/src/group3dlocaliser/Group3DParams.java
+++ b/src/group3dlocaliser/Group3DParams.java
@@ -6,6 +6,7 @@ import java.util.Hashtable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import PamView.GroupedSourceParameters;
import group3dlocaliser.algorithm.LocaliserAlgorithm3D;
@@ -126,7 +127,7 @@ public class Group3DParams implements Serializable, Cloneable, ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("algorithmSpecificParams");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/group3dlocaliser/algorithm/gridsearch/MFPGridSearchParams.java b/src/group3dlocaliser/algorithm/gridsearch/MFPGridSearchParams.java
index 7f7e1371..735d70f1 100644
--- a/src/group3dlocaliser/algorithm/gridsearch/MFPGridSearchParams.java
+++ b/src/group3dlocaliser/algorithm/gridsearch/MFPGridSearchParams.java
@@ -5,6 +5,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
public class MFPGridSearchParams implements Serializable, Cloneable, ManagedParameters {
@@ -25,7 +26,7 @@ public class MFPGridSearchParams implements Serializable, Cloneable, ManagedPara
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("fftLength");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/group3dlocaliser/algorithm/gridsearch/TOADGridParams.java b/src/group3dlocaliser/algorithm/gridsearch/TOADGridParams.java
index 6f2a0fb2..8c845ffe 100644
--- a/src/group3dlocaliser/algorithm/gridsearch/TOADGridParams.java
+++ b/src/group3dlocaliser/algorithm/gridsearch/TOADGridParams.java
@@ -6,6 +6,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import group3dlocaliser.grids.SphericalGrid;
import pamMaths.PamVector;
@@ -49,7 +50,7 @@ public class TOADGridParams implements Serializable, Cloneable, ManagedParameter
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("gridType");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/group3dlocaliser/algorithm/toadbase/TOADBaseParams.java b/src/group3dlocaliser/algorithm/toadbase/TOADBaseParams.java
index 1aa70f8a..b0e11190 100644
--- a/src/group3dlocaliser/algorithm/toadbase/TOADBaseParams.java
+++ b/src/group3dlocaliser/algorithm/toadbase/TOADBaseParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Parameters that apply to all TOAD based localisers.
@@ -117,7 +118,7 @@ public class TOADBaseParams implements Cloneable, Serializable, ManagedParameter
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/group3dlocaliser/dataselector/Group3DDataSelectParams.java b/src/group3dlocaliser/dataselector/Group3DDataSelectParams.java
index 879eae8b..86e2397d 100644
--- a/src/group3dlocaliser/dataselector/Group3DDataSelectParams.java
+++ b/src/group3dlocaliser/dataselector/Group3DDataSelectParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamguardMVC.dataSelector.DataSelectParams;
public class Group3DDataSelectParams extends DataSelectParams implements Serializable, Cloneable, ManagedParameters {
@@ -28,7 +29,7 @@ public class Group3DDataSelectParams extends DataSelectParams implements Seriali
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/group3dlocaliser/grids/SphericalGridParams.java b/src/group3dlocaliser/grids/SphericalGridParams.java
index f323ee53..5ece7b39 100644
--- a/src/group3dlocaliser/grids/SphericalGridParams.java
+++ b/src/group3dlocaliser/grids/SphericalGridParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class SphericalGridParams implements Serializable, Cloneable, ManagedParameters {
@@ -88,7 +89,7 @@ public class SphericalGridParams implements Serializable, Cloneable, ManagedPara
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/group3dlocaliser/grouper/DetectionGrouperParams.java b/src/group3dlocaliser/grouper/DetectionGrouperParams.java
index 5d92afd1..d789b054 100644
--- a/src/group3dlocaliser/grouper/DetectionGrouperParams.java
+++ b/src/group3dlocaliser/grouper/DetectionGrouperParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class DetectionGrouperParams implements Serializable, Cloneable, ManagedParameters {
@@ -38,7 +39,7 @@ public class DetectionGrouperParams implements Serializable, Cloneable, ManagedP
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/help/JavaHelpSearch/DOCS b/src/help/JavaHelpSearch/DOCS
index aece1f43..aa2227fe 100644
Binary files a/src/help/JavaHelpSearch/DOCS and b/src/help/JavaHelpSearch/DOCS differ
diff --git a/src/help/JavaHelpSearch/DOCS.TAB b/src/help/JavaHelpSearch/DOCS.TAB
index fcb0be96..ad72b66e 100644
Binary files a/src/help/JavaHelpSearch/DOCS.TAB and b/src/help/JavaHelpSearch/DOCS.TAB differ
diff --git a/src/help/JavaHelpSearch/OFFSETS b/src/help/JavaHelpSearch/OFFSETS
index 7aeaea18..8a7b9b88 100644
Binary files a/src/help/JavaHelpSearch/OFFSETS and b/src/help/JavaHelpSearch/OFFSETS differ
diff --git a/src/help/JavaHelpSearch/POSITIONS b/src/help/JavaHelpSearch/POSITIONS
index 168a00c2..91375b46 100644
Binary files a/src/help/JavaHelpSearch/POSITIONS and b/src/help/JavaHelpSearch/POSITIONS differ
diff --git a/src/help/JavaHelpSearch/SCHEMA b/src/help/JavaHelpSearch/SCHEMA
index f1bcbb62..0de6873b 100644
--- a/src/help/JavaHelpSearch/SCHEMA
+++ b/src/help/JavaHelpSearch/SCHEMA
@@ -1,2 +1,2 @@
JavaSearch 1.0
-TMAP bs=2048 rt=1 fl=-1 id1=6700 id2=1
+TMAP bs=2048 rt=1 fl=-1 id1=6709 id2=1
diff --git a/src/help/JavaHelpSearch/TMAP b/src/help/JavaHelpSearch/TMAP
index 0f4d546b..a083f8e0 100644
Binary files a/src/help/JavaHelpSearch/TMAP and b/src/help/JavaHelpSearch/TMAP differ
diff --git a/src/help/Map.jhm b/src/help/Map.jhm
index 176022cb..a3886c8c 100644
--- a/src/help/Map.jhm
+++ b/src/help/Map.jhm
@@ -528,6 +528,8 @@
+
+
@@ -644,6 +646,8 @@
+
+
diff --git a/src/help/PAMGUARDHelpProject.xml b/src/help/PAMGUARDHelpProject.xml
index 69b52d84..fe06f32b 100644
--- a/src/help/PAMGUARDHelpProject.xml
+++ b/src/help/PAMGUARDHelpProject.xml
@@ -6,7 +6,7 @@
PAMGUARD
- C:\Users\dg50\source\repos\PAMGuardDG\src\help
+ C:\Users\dg50\source\repos\PAMGuardDG_2\src\help
index.html
diff --git a/src/help/PAMGUARDIndex.xml b/src/help/PAMGUARDIndex.xml
index 18d93123..c9cf5489 100644
--- a/src/help/PAMGUARDIndex.xml
+++ b/src/help/PAMGUARDIndex.xml
@@ -2,6 +2,10 @@
+
+
+
+
diff --git a/src/help/PAMGUARDTOC.xml b/src/help/PAMGUARDTOC.xml
index 73590bca..e1eeb6dc 100644
--- a/src/help/PAMGUARDTOC.xml
+++ b/src/help/PAMGUARDTOC.xml
@@ -195,6 +195,12 @@
+
+
+
+
+
+
diff --git a/src/help/pamHelpStylesheet.css b/src/help/pamHelpStylesheet.css
index e2174daf..d2d474b9 100644
--- a/src/help/pamHelpStylesheet.css
+++ b/src/help/pamHelpStylesheet.css
@@ -52,7 +52,9 @@ ol {
FONT-SIZE: 14;
}
+
img.wrap {float: left}
+img.wrapright {float: right}
table, th, td {
border: 1px solid black;
diff --git a/src/help/utilities/tethys/docs/images/Tethys-200.png b/src/help/utilities/tethys/docs/images/Tethys-200.png
new file mode 100644
index 00000000..19e3c48f
Binary files /dev/null and b/src/help/utilities/tethys/docs/images/Tethys-200.png differ
diff --git a/src/help/utilities/tethys/docs/tethys_overview.html b/src/help/utilities/tethys/docs/tethys_overview.html
new file mode 100644
index 00000000..da30d095
--- /dev/null
+++ b/src/help/utilities/tethys/docs/tethys_overview.html
@@ -0,0 +1,70 @@
+
+
+
+
+
+Tethys Module Overview
+
+
+
+ Tethys Interface
+ Overview
+
+
+
+
+
+
+ Tethys is a freely
+ available open source temporal-spatial database for metadata related
+ to acoustic recordings. The database is intended to house the metadata
+ from marine mammal detection and localization studies, allowing the
+ user to perform meta analyses or to aggregate data from many
+ experimental efforts based on a common attribute. This resulting
+ database can then be queried based on time, space, or any desired
+ attribute and the results can be integrated with external datasets
+ such as NASA's Ocean Color, lunar illumination, etc. in a consistent
+ manner. While Tethys is designed primarily for acoustic metadata from
+ marine mammals, the design is general enough to permit use in other
+ areas as well.
+
+
+ PAMGuard is compatible with Tethys 3.0, released early in 2024.
+ The Tethys database is not a replacement for the existing
+
+ PAMGuard Database.
+ Where the PAMGuard database only contains data from a single instrument or cruise, the Tethys
+ database contains data from many cruises and projects and can be used to hold a summary of all data
+ from a lab or organisation.
+
+
+ Before using the module in PAMGuard, you should install the Tethys Server, which runs under
+ Windows.
+ Instructions for installing the Tethys Server can be found here.
+
+
+
+
+
+ Next: Configuring the Tethys
+ Module
+
+
+
+
+
+
diff --git a/src/help/utilities/tethys/docs/tethys_server.html b/src/help/utilities/tethys/docs/tethys_server.html
new file mode 100644
index 00000000..50a61a06
--- /dev/null
+++ b/src/help/utilities/tethys/docs/tethys_server.html
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+ Tethys Module Overview
+
+
+ Tethys Interface
+ Tethys Server
+
+ Tethys is ...
+
+
+
+
+ Next: Configuring the Tethys Module
+
+
+
+
+
diff --git a/src/landMarks/LandmarkData.java b/src/landMarks/LandmarkData.java
index 2be20e55..ef0cb561 100644
--- a/src/landMarks/LandmarkData.java
+++ b/src/landMarks/LandmarkData.java
@@ -5,6 +5,7 @@ import java.io.Serializable;
import PamController.masterReference.MasterReferencePoint;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamUtils.LatLong;
import PamView.PamSymbol;
@@ -49,7 +50,7 @@ public class LandmarkData extends Object implements Serializable, Cloneable, Man
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/landMarks/LandmarkDatas.java b/src/landMarks/LandmarkDatas.java
index d4cd386d..73fb4785 100644
--- a/src/landMarks/LandmarkDatas.java
+++ b/src/landMarks/LandmarkDatas.java
@@ -5,6 +5,7 @@ import java.util.ArrayList;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class LandmarkDatas implements Serializable, Cloneable, ManagedParameters {
@@ -76,7 +77,7 @@ public class LandmarkDatas implements Serializable, Cloneable, ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/levelMeter/LevelMeterParams.java b/src/levelMeter/LevelMeterParams.java
index dd1b6752..c25860dc 100644
--- a/src/levelMeter/LevelMeterParams.java
+++ b/src/levelMeter/LevelMeterParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class LevelMeterParams implements Cloneable, Serializable, ManagedParameters {
@@ -35,7 +36,7 @@ public class LevelMeterParams implements Cloneable, Serializable, ManagedParamet
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/likelihoodDetectionModule/AcquisitionSettings.java b/src/likelihoodDetectionModule/AcquisitionSettings.java
index abf61481..10033395 100644
--- a/src/likelihoodDetectionModule/AcquisitionSettings.java
+++ b/src/likelihoodDetectionModule/AcquisitionSettings.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* The AcquisitionSettings class provides a module-local storage object for holding
@@ -48,7 +49,7 @@ public class AcquisitionSettings implements Serializable, ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/likelihoodDetectionModule/ConfigurationDialogSettings.java b/src/likelihoodDetectionModule/ConfigurationDialogSettings.java
index 6856e501..9011ffbd 100644
--- a/src/likelihoodDetectionModule/ConfigurationDialogSettings.java
+++ b/src/likelihoodDetectionModule/ConfigurationDialogSettings.java
@@ -6,6 +6,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* The Class ConfigurationDialogSettings holds parameters about the
@@ -28,7 +29,7 @@ public class ConfigurationDialogSettings implements Serializable, ManagedParamet
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("expandedState");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/likelihoodDetectionModule/GuardBand.java b/src/likelihoodDetectionModule/GuardBand.java
index ccd9a6c0..cb07df7b 100644
--- a/src/likelihoodDetectionModule/GuardBand.java
+++ b/src/likelihoodDetectionModule/GuardBand.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Represents the parameters that make up a guard band, used as
@@ -106,7 +107,7 @@ public class GuardBand implements Serializable, ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/likelihoodDetectionModule/LikelihoodDetectionParameters.java b/src/likelihoodDetectionModule/LikelihoodDetectionParameters.java
index 9c405cdd..9481c26c 100644
--- a/src/likelihoodDetectionModule/LikelihoodDetectionParameters.java
+++ b/src/likelihoodDetectionModule/LikelihoodDetectionParameters.java
@@ -11,6 +11,7 @@ import java.util.Iterator;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* The Class LikelihoodDetectionParameters provides the standard PamGuard
@@ -271,7 +272,7 @@ public class LikelihoodDetectionParameters implements Serializable, Cloneable, M
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/likelihoodDetectionModule/LikelihoodFFTParameters.java b/src/likelihoodDetectionModule/LikelihoodFFTParameters.java
index e90e51c8..13b85fda 100644
--- a/src/likelihoodDetectionModule/LikelihoodFFTParameters.java
+++ b/src/likelihoodDetectionModule/LikelihoodFFTParameters.java
@@ -6,6 +6,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import fftManager.FFTParameters;
import Spectrogram.WindowFunction;
@@ -270,7 +271,7 @@ public class LikelihoodFFTParameters implements Serializable, ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("sourceNumber");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/likelihoodDetectionModule/SignalBand.java b/src/likelihoodDetectionModule/SignalBand.java
index 00e7af96..3b3150d6 100644
--- a/src/likelihoodDetectionModule/SignalBand.java
+++ b/src/likelihoodDetectionModule/SignalBand.java
@@ -6,6 +6,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Represents the parameters that make up a signal band, used as
@@ -151,7 +152,7 @@ public class SignalBand implements Serializable, ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
}
diff --git a/src/likelihoodDetectionModule/TargetConfiguration.java b/src/likelihoodDetectionModule/TargetConfiguration.java
index 29c82890..0cc0e398 100644
--- a/src/likelihoodDetectionModule/TargetConfiguration.java
+++ b/src/likelihoodDetectionModule/TargetConfiguration.java
@@ -5,6 +5,7 @@ import java.util.ArrayList;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import likelihoodDetectionModule.normalizer.NormalizerProcess.NormalizerAlgorithm;
/**
@@ -453,7 +454,7 @@ public class TargetConfiguration implements Serializable, ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/loc3d_Thode/TowedArray3DSQLLogging.java b/src/loc3d_Thode/TowedArray3DSQLLogging.java
index c5a8b1f7..95bc98e6 100644
--- a/src/loc3d_Thode/TowedArray3DSQLLogging.java
+++ b/src/loc3d_Thode/TowedArray3DSQLLogging.java
@@ -1,5 +1,6 @@
package loc3d_Thode;
+import generalDatabase.EmptyTableDefinition;
import generalDatabase.PamDetectionLogging;
import generalDatabase.PamTableDefinition;
import generalDatabase.PamTableItem;
@@ -17,7 +18,6 @@ public class TowedArray3DSQLLogging extends PamDetectionLogging {
TowedArray3DController towedArray3DController;
- PamTableDefinition tableDefinition;
PamTableItem dateItem, range_boat_Item, range_f_Item, range_r_Item, depthItem, azi_boat_Item,azi_f_Item, azi_r_Item, tdd_Item,
bearing_f_Item,bearing_r_Item, tds_f_Item, tds_r_Item, za_f_Item, za_r_Item;
@@ -34,7 +34,7 @@ public class TowedArray3DSQLLogging extends PamDetectionLogging {
this.towedArray3DController = towedArray3DController;
// create the table definition.
- tableDefinition = createTableDefinition();
+ PamTableDefinition tableDefinition = createTableDefinition();
}
public PamTableDefinition createTableDefinition() {
diff --git a/src/loggerForms/FormPlotOptions.java b/src/loggerForms/FormPlotOptions.java
index 8f55f828..9763d8ba 100644
--- a/src/loggerForms/FormPlotOptions.java
+++ b/src/loggerForms/FormPlotOptions.java
@@ -6,6 +6,7 @@ import java.util.Arrays;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
/**
@@ -95,7 +96,7 @@ public class FormPlotOptions implements Serializable, Cloneable, ManagedParamete
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("controlChoices");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/loggerForms/FormSettings.java b/src/loggerForms/FormSettings.java
index 199edfe4..f7553e13 100644
--- a/src/loggerForms/FormSettings.java
+++ b/src/loggerForms/FormSettings.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Manage a bit of persistent data for a single Logger form description.
@@ -32,7 +33,7 @@ public class FormSettings implements Cloneable, Serializable, ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/loggerForms/FormsDataDisplayTable.java b/src/loggerForms/FormsDataDisplayTable.java
index 26e2f5b3..1300fc79 100644
--- a/src/loggerForms/FormsDataDisplayTable.java
+++ b/src/loggerForms/FormsDataDisplayTable.java
@@ -261,6 +261,7 @@ public class FormsDataDisplayTable {
+
/**
* Called when data have changed in the datablock.
*/
diff --git a/src/loggerForms/monitor/FormsSelectorParams.java b/src/loggerForms/monitor/FormsSelectorParams.java
index d691af0c..d1797798 100644
--- a/src/loggerForms/monitor/FormsSelectorParams.java
+++ b/src/loggerForms/monitor/FormsSelectorParams.java
@@ -7,6 +7,7 @@ import java.util.Hashtable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamguardMVC.dataSelector.DataSelectParams;
public class FormsSelectorParams extends DataSelectParams implements Cloneable, Serializable, ManagedParameters {
@@ -30,7 +31,7 @@ public class FormsSelectorParams extends DataSelectParams implements Cloneable,
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("formSelection");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/ltsa/LtsaModuleHeader.java b/src/ltsa/LtsaModuleHeader.java
index 0b5d888e..50c1034d 100644
--- a/src/ltsa/LtsaModuleHeader.java
+++ b/src/ltsa/LtsaModuleHeader.java
@@ -6,6 +6,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import binaryFileStorage.BinaryHeader;
import binaryFileStorage.BinaryObjectData;
import binaryFileStorage.ModuleHeader;
@@ -37,7 +38,7 @@ public class LtsaModuleHeader extends ModuleHeader implements ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("fftLength");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/ltsa/LtsaParameters.java b/src/ltsa/LtsaParameters.java
index 2dfd9a62..dbf62ec0 100644
--- a/src/ltsa/LtsaParameters.java
+++ b/src/ltsa/LtsaParameters.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class LtsaParameters implements Cloneable, Serializable, ManagedParameters {
@@ -35,7 +36,7 @@ public class LtsaParameters implements Cloneable, Serializable, ManagedParameter
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
}
diff --git a/src/mapgrouplocaliser/MapGrouperSettings.java b/src/mapgrouplocaliser/MapGrouperSettings.java
index 955542dc..440700b7 100644
--- a/src/mapgrouplocaliser/MapGrouperSettings.java
+++ b/src/mapgrouplocaliser/MapGrouperSettings.java
@@ -7,6 +7,7 @@ import java.util.Hashtable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamView.paneloverlay.OverlayDataInfo;
import PamView.paneloverlay.overlaymark.MarkDataSelectorParams;
import PamView.paneloverlay.overlaymark.OverlayMarkDataInfo;
@@ -64,7 +65,7 @@ public class MapGrouperSettings implements Serializable, Cloneable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("markDataSelectorParams");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/matchedTemplateClassifer/MTClassifier.java b/src/matchedTemplateClassifer/MTClassifier.java
index ddde2bc7..9065daac 100644
--- a/src/matchedTemplateClassifer/MTClassifier.java
+++ b/src/matchedTemplateClassifer/MTClassifier.java
@@ -15,6 +15,7 @@ import Localiser.DelayMeasurementParams;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamUtils.PamArrayUtils;
import PamUtils.PamInterp;
import PamUtils.complex.ComplexArray;
@@ -629,7 +630,7 @@ public class MTClassifier implements Serializable, Cloneable, ManagedParameters
*/
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("inteprWaveformReject");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/matchedTemplateClassifer/MatchTemplate.java b/src/matchedTemplateClassifer/MatchTemplate.java
index 7f758ddf..0990a22d 100644
--- a/src/matchedTemplateClassifer/MatchTemplate.java
+++ b/src/matchedTemplateClassifer/MatchTemplate.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamguardMVC.RawDataHolder;
import PamguardMVC.RawDataTransforms;
@@ -51,7 +52,7 @@ public class MatchTemplate implements RawDataHolder, Serializable, Cloneable, Ma
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/matchedTemplateClassifer/MatchedTemplateParams.java b/src/matchedTemplateClassifer/MatchedTemplateParams.java
index 05f8b107..edd2b912 100644
--- a/src/matchedTemplateClassifer/MatchedTemplateParams.java
+++ b/src/matchedTemplateClassifer/MatchedTemplateParams.java
@@ -8,6 +8,7 @@ import java.util.ArrayList;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamView.PamSymbolType;
import PamView.symbol.SymbolData;
import fftFilter.FFTFilterParams;
@@ -150,7 +151,7 @@ public class MatchedTemplateParams implements Serializable, Cloneable, ManagedPa
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("fftFilterParams");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/matchedTemplateClassifer/annotation/MatchedClickAnnotationSQL.java b/src/matchedTemplateClassifer/annotation/MatchedClickAnnotationSQL.java
index acf38f67..3b248ea9 100644
--- a/src/matchedTemplateClassifer/annotation/MatchedClickAnnotationSQL.java
+++ b/src/matchedTemplateClassifer/annotation/MatchedClickAnnotationSQL.java
@@ -7,6 +7,7 @@ import java.util.List;
import PamUtils.PamArrayUtils;
import PamguardMVC.PamDataUnit;
import PamguardMVC.debug.Debug;
+import generalDatabase.EmptyTableDefinition;
import generalDatabase.PamTableDefinition;
import generalDatabase.PamTableItem;
import generalDatabase.SQLLoggingAddon;
@@ -49,7 +50,7 @@ public class MatchedClickAnnotationSQL implements SQLLoggingAddon {
}
@Override
- public void addTableItems(PamTableDefinition pamTableDefinition) {
+ public void addTableItems(EmptyTableDefinition pamTableDefinition) {
pamTableDefinition.addTableItem(typeTable);
pamTableDefinition.addTableItem(mtThresholdsTable);
pamTableDefinition.addTableItem(mtMatchCorrsTable);
@@ -58,7 +59,7 @@ public class MatchedClickAnnotationSQL implements SQLLoggingAddon {
}
@Override
- public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
+ public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
MatchedClickAnnotation clickAnnotation =
(MatchedClickAnnotation) pamDataUnit.findDataAnnotation(MatchedClickAnnotation.class);
@@ -95,7 +96,7 @@ public class MatchedClickAnnotationSQL implements SQLLoggingAddon {
}
@Override
- public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
+ public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
String threshold = mtThresholdsTable.getDeblankedStringValue();
String mtMatchCorrs = mtMatchCorrsTable.getDeblankedStringValue();
diff --git a/src/mcc/mccacquisition/MCCDaqParams.java b/src/mcc/mccacquisition/MCCDaqParams.java
index f1fc3450..ba44c99e 100644
--- a/src/mcc/mccacquisition/MCCDaqParams.java
+++ b/src/mcc/mccacquisition/MCCDaqParams.java
@@ -5,6 +5,7 @@ import java.io.Serializable;
import Acquisition.DaqSystemXMLManager;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import analoginput.AnalogRangeData;
import simulatedAcquisition.SimProcess;
@@ -51,7 +52,7 @@ public class MCCDaqParams implements Serializable, Cloneable, ManagedParameters
return null;
}
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/metadata/MetaDataContol.java b/src/metadata/MetaDataContol.java
new file mode 100644
index 00000000..98093b08
--- /dev/null
+++ b/src/metadata/MetaDataContol.java
@@ -0,0 +1,114 @@
+package metadata;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.Serializable;
+
+import javax.swing.JFrame;
+import javax.swing.JMenuItem;
+
+import PamController.PamControlledUnit;
+import PamController.PamControlledUnitSettings;
+import PamController.PamController;
+import PamController.PamSettingManager;
+import PamController.PamSettings;
+import metadata.swing.MetaDataDialog;
+
+/**
+ * Class to handle Project MetaData. Am making this a PAMControlledUnit, but may never
+ * register it with the model ? Will see what advantages and disadvantages there are.
+ * @author dg50
+ *
+ */
+public class MetaDataContol extends PamControlledUnit implements PamSettings {
+
+ public static final String unitType = "Meta Data";
+
+ private static MetaDataContol singleInstance;
+
+ private PamguardMetaData pamguardMetaData = new PamguardMetaData();
+
+// private ParameterSetManager deploymentSetManager;
+
+
+ private MetaDataContol(String unitName) {
+ super(unitType, unitName);
+// deploymentSetManager = new ParameterSetManager(deploymentData, "Deployment Data");
+ PamSettingManager.getInstance().registerSettings(this);
+ }
+
+ /**
+ * Easy getter for singleton MetaData controller.
+ * @return meta data controller
+ */
+ public static MetaDataContol getMetaDataControl() {
+ if (singleInstance == null) {
+ singleInstance = new MetaDataContol(unitType);
+ // add this line to add it to the main modules list. Then it will get menu's, etc.
+ PamController.getInstance().addControlledUnit(singleInstance);
+ }
+ return singleInstance;
+ }
+
+ /**
+ * Get PAMGuard Metadata. This contains a nilus Deployment object wrapped up
+ * so that it can be serialised into other PAMGuard settings.
+ * @return PAMGuard meta data
+ */
+ public PamguardMetaData getMetaData() {
+ return pamguardMetaData;
+ }
+
+ /**
+ * Set the meta data object.
+ * @param metaData
+ */
+ public void setMetaData(PamguardMetaData metaData) {
+ this.pamguardMetaData = metaData;
+ }
+
+ @Override
+ public Serializable getSettingsReference() {
+ pamguardMetaData.checkSerialisation();
+ return pamguardMetaData;
+ }
+
+ @Override
+ public long getSettingsVersion() {
+ return PamguardMetaData.serialVersionUID;
+ }
+
+ @Override
+ public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
+ Object obj = pamControlledUnitSettings.getSettings();
+ if (obj instanceof PamguardMetaData) {
+ pamguardMetaData = (PamguardMetaData) obj;
+ return true;
+ }
+ return false;
+ }
+
+// @Override
+ public JMenuItem createMenu(JFrame parentFrame) {
+ JMenuItem menuItem = new JMenuItem("Project information ...");
+ menuItem.setToolTipText("General project objectives, region, etc.");
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ showDialog(parentFrame);
+ }
+ });
+ return menuItem;
+ }
+
+ protected void showDialog(JFrame parentFrame) {
+ PamguardMetaData newData = MetaDataDialog.showDialog(parentFrame, pamguardMetaData);
+ if (newData != null) {
+ this.pamguardMetaData = newData;
+ // send around a notification ?
+ }
+ }
+
+
+
+}
diff --git a/src/metadata/PamguardMetaData.java b/src/metadata/PamguardMetaData.java
new file mode 100644
index 00000000..ae4064ab
--- /dev/null
+++ b/src/metadata/PamguardMetaData.java
@@ -0,0 +1,111 @@
+package metadata;
+
+import java.io.Serializable;
+
+import PamUtils.LatLong;
+import nilus.ContactInfo;
+import nilus.Deployment;
+import nilus.DeploymentRecoveryDetails;
+import nilus.DescriptionType;
+import nilus.Helper;
+import nilus.MetadataInfo;
+import nilus.ResponsibleParty;
+import tethys.niluswraps.NilusSettingsWrapper;
+
+/**
+ * Meta data for a PAMGuard data set. This is based around serialisable versions of
+ * nilus classes to be compliant with both Tethys and PAMGuard settings files. May only
+ * need a Deployment object, but scope for adding others / other fields if it's useful.
+ * @author dg50
+ *
+ */
+public class PamguardMetaData implements Serializable {
+
+ public static final long serialVersionUID = 1L;
+
+ private NilusSettingsWrapper deploymentWrapper;
+
+ public boolean useAudioForDeploymentTimes = true;
+
+// /**
+// * Deployment time (used if different
+// */
+// private Long deploymentMillis;
+//
+// private Long recoverMillis;
+//
+// private LatLong recoverLatLong;
+
+ /**
+ * Get the deployment data
+ * @return nilus deployment
+ */
+ public Deployment getDeployment() {
+ if (deploymentWrapper == null) {
+ deploymentWrapper = new NilusSettingsWrapper<>();
+ }
+ Deployment deployment = deploymentWrapper.getNilusObject(Deployment.class);
+ if (deployment == null) {
+ deployment = new Deployment();
+ try {
+ Helper.createRequiredElements(deployment);
+ } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) {
+ e.printStackTrace();
+ }
+ deploymentWrapper.setNilusObject(deployment);
+ }
+ // check some fields we know we'll need that the Helper may not have managed.
+ if (deployment.getDescription() == null) {
+ deployment.setDescription(new DescriptionType());
+ }
+ if (deployment.getMetadataInfo() == null) {
+ deployment.setMetadataInfo(new MetadataInfo());
+ }
+ if (deployment.getMetadataInfo().getContact() == null) {
+ deployment.getMetadataInfo().setContact(new ResponsibleParty());
+ }
+ if (deployment.getMetadataInfo().getContact().getContactInfo() == null) {
+ deployment.getMetadataInfo().getContact().setContactInfo(new ContactInfo());
+ }
+
+ if (deployment.getDeploymentDetails() == null) {
+ deployment.setDeploymentDetails(new DeploymentRecoveryDetails());
+ }
+ if (deployment.getRecoveryDetails() == null) {
+ deployment.setRecoveryDetails(new DeploymentRecoveryDetails());
+ }
+ return deployment;
+ }
+
+ /**
+ * Set the deployment data.
+ * @param deployment nilus deployment
+ */
+ public void setDeployment(Deployment deployment) {
+ if (deploymentWrapper == null) {
+ deploymentWrapper = new NilusSettingsWrapper<>();
+ }
+ deploymentWrapper.setNilusObject(deployment);
+ }
+
+ /**
+ * @return the deploymentWrapper
+ */
+ public NilusSettingsWrapper getDeploymentWrapper() {
+ if (deploymentWrapper == null) {
+ deploymentWrapper = new NilusSettingsWrapper<>();
+ }
+ return deploymentWrapper;
+ }
+
+ public void checkSerialisation() {
+ // check that all wrappers have their xml up to date.
+ if (deploymentWrapper == null) {
+ deploymentWrapper = new NilusSettingsWrapper<>();
+ }
+ deploymentWrapper.reSerialise();
+ }
+
+
+
+}
diff --git a/src/metadata/swing/MetaDataDialog.java b/src/metadata/swing/MetaDataDialog.java
new file mode 100644
index 00000000..9f744391
--- /dev/null
+++ b/src/metadata/swing/MetaDataDialog.java
@@ -0,0 +1,121 @@
+package metadata.swing;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.Window;
+
+import javax.swing.BoxLayout;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.border.TitledBorder;
+
+import PamController.PamController;
+import PamView.dialog.PamDialog;
+import PamView.panel.PamNorthPanel;
+import PamView.panel.WestAlignedPanel;
+import metadata.PamguardMetaData;
+import nilus.Deployment;
+import tethys.TethysControl;
+import tethys.TethysState;
+import tethys.TethysState.StateType;
+import tethys.deployment.swing.ProjectInformationPanel;
+import tethys.swing.export.DeploymentPeriodPanel;
+import tethys.swing.export.DescriptionTypePanel;
+import tethys.swing.export.ResponsiblePartyPanel;
+
+public class MetaDataDialog extends PamDialog {
+
+ private static MetaDataDialog singleInstance;
+
+ private PamguardMetaData pamguardMetaData;
+
+ private DescriptionTypePanel descriptionPanel;
+
+ private ProjectInformationPanel projectInformationPanel;
+
+ private DeploymentPeriodPanel deploymentPeriodPanel;
+
+ private ResponsiblePartyPanel responsiblePanel;
+
+ private TethysControl tethysControl;
+
+ private MetaDataDialog(Window parentFrame) {
+ super(parentFrame, "Project information", false);
+
+ JPanel mainPanel = new JPanel();
+ mainPanel.setLayout(new BorderLayout());
+ JTabbedPane tabbedPane = new JTabbedPane();
+
+ tethysControl = (TethysControl) PamController.getInstance().findControlledUnit(TethysControl.unitType);
+
+ projectInformationPanel = new ProjectInformationPanel(parentFrame, null);
+ descriptionPanel = new DescriptionTypePanel(null, false, false, false);
+ deploymentPeriodPanel = new DeploymentPeriodPanel(parentFrame);
+ descriptionPanel.getMainPanel().setPreferredSize(new Dimension(400,300));
+
+ responsiblePanel = new ResponsiblePartyPanel();
+ JPanel northPanel = new JPanel();
+ WestAlignedPanel wp;
+ northPanel.setLayout(new BoxLayout(northPanel, BoxLayout.Y_AXIS));
+
+ northPanel.add(wp = new WestAlignedPanel(projectInformationPanel.getMainPanel()));
+ wp.setBorder(new TitledBorder("General project information"));
+ northPanel.add(wp = new WestAlignedPanel(responsiblePanel.getMainPanel()));
+ wp.setBorder(new TitledBorder("Contact information"));
+
+ JPanel dpPanel = new WestAlignedPanel(deploymentPeriodPanel.getMainPanel());
+ dpPanel.setBorder(new TitledBorder("Deployment period"));
+
+ mainPanel.add(tabbedPane, BorderLayout.CENTER);
+ tabbedPane.add(northPanel, "General");
+ tabbedPane.add(descriptionPanel.getMainPanel(), "Description");
+ tabbedPane.add(dpPanel, "Deployment");
+
+ setResizable(true);
+
+ setDialogComponent(mainPanel);
+ }
+
+
+
+
+ public static PamguardMetaData showDialog(Window frame, PamguardMetaData pamguardMetaData) {
+ singleInstance = new MetaDataDialog(frame);
+ singleInstance.setParams(pamguardMetaData);
+ singleInstance.setVisible(true);
+ return singleInstance.pamguardMetaData;
+ }
+
+ private void setParams(PamguardMetaData pamguardMetaData) {
+ this.pamguardMetaData = pamguardMetaData;
+ Deployment deployment = pamguardMetaData.getDeployment();
+ projectInformationPanel.setParams(deployment);
+ descriptionPanel.setParams(deployment.getDescription());
+ responsiblePanel.setParams(deployment.getMetadataInfo().getContact());
+ deploymentPeriodPanel.setParams(pamguardMetaData);
+ }
+
+ @Override
+ public boolean getParams() {
+ Deployment deployment = pamguardMetaData.getDeployment();
+ boolean ok = descriptionPanel.getParams(deployment.getDescription());
+ ok &= responsiblePanel.getParams(deployment.getMetadataInfo().getContact());
+ ok &= deploymentPeriodPanel.getParams(pamguardMetaData);
+
+ if (tethysControl != null) {
+ tethysControl.sendStateUpdate(new TethysState(StateType.NEWPROJECTSELECTION));
+ }
+ return ok;
+ }
+
+ @Override
+ public void cancelButtonPressed() {
+ pamguardMetaData = null;
+ }
+
+ @Override
+ public void restoreDefaultSettings() {
+
+ }
+
+}
diff --git a/src/networkTransfer/emulator/EmulatorParams.java b/src/networkTransfer/emulator/EmulatorParams.java
index e4fe0f74..3f38266a 100644
--- a/src/networkTransfer/emulator/EmulatorParams.java
+++ b/src/networkTransfer/emulator/EmulatorParams.java
@@ -8,6 +8,7 @@ import PamController.PamControlledUnitSettings;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamUtils.LatLong;
public class EmulatorParams implements Cloneable, Serializable, ManagedParameters {
@@ -50,7 +51,7 @@ public class EmulatorParams implements Cloneable, Serializable, ManagedParameter
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("circleRadius");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/networkTransfer/receive/BuoyStatusData.java b/src/networkTransfer/receive/BuoyStatusData.java
index 6b17a6ad..8138f4bf 100644
--- a/src/networkTransfer/receive/BuoyStatusData.java
+++ b/src/networkTransfer/receive/BuoyStatusData.java
@@ -5,6 +5,7 @@ import java.util.Hashtable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamUtils.PamCalendar;
/**
@@ -140,7 +141,7 @@ public class BuoyStatusData implements Serializable, ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/networkTransfer/receive/BuoyStatusValue.java b/src/networkTransfer/receive/BuoyStatusValue.java
index d73a5acd..a42ea7ff 100644
--- a/src/networkTransfer/receive/BuoyStatusValue.java
+++ b/src/networkTransfer/receive/BuoyStatusValue.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamUtils.PamCalendar;
public class BuoyStatusValue implements Serializable, ManagedParameters {
@@ -53,7 +54,7 @@ public class BuoyStatusValue implements Serializable, ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/networkTransfer/receive/NetworkReceiveParams.java b/src/networkTransfer/receive/NetworkReceiveParams.java
index f067c789..488899c5 100644
--- a/src/networkTransfer/receive/NetworkReceiveParams.java
+++ b/src/networkTransfer/receive/NetworkReceiveParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class NetworkReceiveParams implements Cloneable, Serializable, ManagedParameters {
@@ -40,7 +41,7 @@ public class NetworkReceiveParams implements Cloneable, Serializable, ManagedPar
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/networkTransfer/send/NetworkSendParams.java b/src/networkTransfer/send/NetworkSendParams.java
index 9e0024d8..87e25b0c 100644
--- a/src/networkTransfer/send/NetworkSendParams.java
+++ b/src/networkTransfer/send/NetworkSendParams.java
@@ -7,6 +7,7 @@ import java.util.ArrayList;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamguardMVC.PamDataBlock;
public class NetworkSendParams implements Serializable, Cloneable, ManagedParameters {
@@ -108,7 +109,7 @@ public class NetworkSendParams implements Serializable, Cloneable, ManagedParame
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("selectedDataBlocks");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/nidaqdev/networkdaq/NIDaqLogging.java b/src/nidaqdev/networkdaq/NIDaqLogging.java
index dc12309b..75022e5c 100644
--- a/src/nidaqdev/networkdaq/NIDaqLogging.java
+++ b/src/nidaqdev/networkdaq/NIDaqLogging.java
@@ -3,6 +3,7 @@ package nidaqdev.networkdaq;
import java.sql.Types;
import PamguardMVC.PamDataUnit;
+import generalDatabase.EmptyTableDefinition;
import generalDatabase.PamTableDefinition;
import generalDatabase.PamTableItem;
import generalDatabase.SQLLoggingAddon;
@@ -20,12 +21,12 @@ public class NIDaqLogging implements SQLLoggingAddon {
}
@Override
- public void addTableItems(PamTableDefinition pamTableDefinition) {
+ public void addTableItems(EmptyTableDefinition pamTableDefinition) {
pamTableDefinition.addTableItem(crioTemperature);
}
@Override
- public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
+ public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
Double lastTemp = niNetworkDaq.getLastTemperature();
if (lastTemp == null) {
crioTemperature.setValue(null);
@@ -38,7 +39,7 @@ public class NIDaqLogging implements SQLLoggingAddon {
}
@Override
- public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
+ public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
// TODO Auto-generated method stub
return false;
}
diff --git a/src/nidaqdev/networkdaq/NINetworkDaqParams.java b/src/nidaqdev/networkdaq/NINetworkDaqParams.java
index 7458739e..a7f67845 100644
--- a/src/nidaqdev/networkdaq/NINetworkDaqParams.java
+++ b/src/nidaqdev/networkdaq/NINetworkDaqParams.java
@@ -6,6 +6,7 @@ import java.util.ArrayList;
import Acquisition.DaqSystemXMLManager;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class NINetworkDaqParams implements Serializable, Cloneable, ManagedParameters {
@@ -169,7 +170,7 @@ public class NINetworkDaqParams implements Serializable, Cloneable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
if (DaqSystemXMLManager.isSelected(NINetworkDaq.systemName)) {
- return PamParameterSet.autoGenerate(this);
+ return PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
}
return null;
}
diff --git a/src/nmeaEmulator/NMEAEmulatorParams.java b/src/nmeaEmulator/NMEAEmulatorParams.java
index 1889ca17..d7b89529 100644
--- a/src/nmeaEmulator/NMEAEmulatorParams.java
+++ b/src/nmeaEmulator/NMEAEmulatorParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class NMEAEmulatorParams implements Serializable, Cloneable, ManagedParameters {
@@ -23,7 +24,7 @@ public class NMEAEmulatorParams implements Serializable, Cloneable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/noiseBandMonitor/NoiseBandSettings.java b/src/noiseBandMonitor/NoiseBandSettings.java
index d905c536..8f00571c 100644
--- a/src/noiseBandMonitor/NoiseBandSettings.java
+++ b/src/noiseBandMonitor/NoiseBandSettings.java
@@ -7,6 +7,7 @@ import Filters.FilterType;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class NoiseBandSettings implements Serializable, Cloneable, ManagedParameters {
@@ -59,7 +60,7 @@ public class NoiseBandSettings implements Serializable, Cloneable, ManagedParame
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("showStandard");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/noiseMonitor/NoiseDataBlock.java b/src/noiseMonitor/NoiseDataBlock.java
index b5e7f628..effbd591 100644
--- a/src/noiseMonitor/NoiseDataBlock.java
+++ b/src/noiseMonitor/NoiseDataBlock.java
@@ -2,11 +2,18 @@ package noiseMonitor;
import noiseMonitor.alarm.NoiseAlarmCounter;
import noiseMonitor.alarm.NoiseAlarmProvider;
+import noiseMonitor.species.TethysNoiseDataProvider;
+import tethys.TethysControl;
+import tethys.pamdata.TethysDataProvider;
+import tethys.species.DataBlockSpeciesManager;
+import tethys.species.FixedSpeciesManager;
import alarm.AlarmCounter;
import alarm.AlarmCounterProvider;
import alarm.AlarmDataSource;
import PamUtils.FrequencyFormat;
import PamUtils.PamUtils;
+import PamguardMVC.DataAutomation;
+import PamguardMVC.DataAutomationInfo;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamProcess;
@@ -32,13 +39,15 @@ public class NoiseDataBlock extends PamDataBlock implements Alarm
private NoiseAlarmProvider noiseAlarmCounter;
/**
- * These are the names used in the database columns, so dont' change them on pain of
+ * These are the names used in the database columns, so don't change them on pain of
* nothing ever working ever again !
*/
public static final String[] measureNames = {"mean", "median", "low95", "high95", "Min", "Max", "Peak"};
public static final String[] displayNames = {"Mean", "Median", "Lower 95%", "Upper 95%", "Minimum", "Maximim", "Peak"};
private int statisticTypes;
+ private TethysNoiseDataProvider tethysNoiseDataProvider;
+ private FixedSpeciesManager fixedSpeciesManager;
public NoiseDataBlock(String dataName,
PamProcess parentProcess, int channelMap) {
@@ -244,6 +253,27 @@ public class NoiseDataBlock extends PamDataBlock implements Alarm
}
return noiseAlarmCounter;
}
+
+ @Override
+ public DataAutomationInfo getDataAutomationInfo() {
+ return new DataAutomationInfo(DataAutomation.AUTOMATIC);
+ }
+
+ @Override
+ public TethysDataProvider getTethysDataProvider(TethysControl tethysControl) {
+ if (tethysNoiseDataProvider == null) {
+ tethysNoiseDataProvider = new TethysNoiseDataProvider(tethysControl, this);
+ }
+ return tethysNoiseDataProvider;
+ }
+
+ @Override
+ public DataBlockSpeciesManager getDatablockSpeciesManager() {
+ if (fixedSpeciesManager == null) {
+ fixedSpeciesManager = new FixedSpeciesManager(this, -10, "anthropogenic", "noise");
+ }
+ return fixedSpeciesManager;
+ }
}
diff --git a/src/noiseMonitor/NoiseDisplaySettings.java b/src/noiseMonitor/NoiseDisplaySettings.java
index 7ef4f5de..b70db3ac 100644
--- a/src/noiseMonitor/NoiseDisplaySettings.java
+++ b/src/noiseMonitor/NoiseDisplaySettings.java
@@ -6,6 +6,7 @@ import java.util.Arrays;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
public class NoiseDisplaySettings implements Serializable, Cloneable, ManagedParameters {
@@ -70,7 +71,7 @@ public class NoiseDisplaySettings implements Serializable, Cloneable, ManagedPar
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("displayLengthSeconds");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/noiseMonitor/NoiseLogging.java b/src/noiseMonitor/NoiseLogging.java
index 4bbc0cfd..a3a62d61 100644
--- a/src/noiseMonitor/NoiseLogging.java
+++ b/src/noiseMonitor/NoiseLogging.java
@@ -116,5 +116,27 @@ public class NoiseLogging extends SQLLogging {
}
}
}
+
+ private long lastTime;
+
+ @Override
+ protected PamDataUnit createDataUnit(SQLTypes sqlTypes, long timeMilliseconds, int databaseIndex) {
+ int chan = channelNumber.getIntegerValue();
+ int nBands = noiseDataBlock.getBandLoEdges().length;
+ int nMeasures = noiseDataBlock.getUsedMeasureNames().length;
+ if (nMeasures * nBands != bandItems.length) {
+ return null;
+ }
+ double[][] bandData = new double[nBands][nMeasures];
+ for (int iBand = 0, iCol = 0; iBand < nBands; iBand++) {
+ for (int iMeasure = 0; iMeasure < nMeasures; iMeasure++, iCol++) {
+ bandData[iBand][iMeasure] = bandItems[iCol].getDoubleValue();
+ }
+ }
+
+ NoiseDataUnit noiseDataUnit = new NoiseDataUnit(timeMilliseconds, 1< measurements = params.getFrequencyMeasurementsDB();
+ double[][] noiseData = noiseDataUnit.getNoiseBandData();
+ int meanIndex = -1;
+ for (int i = 0; i < nTypes; i++) {
+ int type = PamUtils.getNthChannel(i, statTypes);
+ String name = noiseDataBlock.getMeasureName(type);
+ if (1< effortKinds,
+ StreamExportParams exportParams) {
+ super.getEffortKinds(pDeployment, effortKinds, exportParams);
+ DetectionEffortKind kind = effortKinds.get(0);
+ nilus.DetectionEffortKind.Parameters params = kind.getParameters();
+ if (params == null) {
+ params = new nilus.DetectionEffortKind.Parameters();
+ try {
+ Helper.createRequiredElements(params);
+ } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ kind.setParameters(params);
+ }
+ List fMeasures = params.getFrequencyMeasurementsHz();
+ double[] loEdges = noiseDataBlock.getBandLoEdges();
+ double[] hiEdges = noiseDataBlock.getBandHiEdges();
+ // put lot mean into the array
+ for (int i = 0; i < loEdges.length; i++) {
+ fMeasures.add(roundSignificantFigures(Math.sqrt(loEdges[i]*hiEdges[i]), 4));
+ }
+ }
+
+ @Override
+ public boolean wantExportDialogCard(ExportWizardCard wizPanel) {
+ if (wizPanel.getClass() == GranularityCard.class) {
+ return false;
+ }
+ return super.wantExportDialogCard(wizPanel);
+ }
+
+}
diff --git a/src/noiseOneBand/OneBandAlarmParameters.java b/src/noiseOneBand/OneBandAlarmParameters.java
index 90a1659c..3e4e5a69 100644
--- a/src/noiseOneBand/OneBandAlarmParameters.java
+++ b/src/noiseOneBand/OneBandAlarmParameters.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class OneBandAlarmParameters implements Serializable, Cloneable, ManagedParameters {
@@ -37,7 +38,7 @@ public class OneBandAlarmParameters implements Serializable, Cloneable, ManagedP
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/noiseOneBand/OneBandDisplayParams.java b/src/noiseOneBand/OneBandDisplayParams.java
index 04cf01d7..fe9b7a82 100644
--- a/src/noiseOneBand/OneBandDisplayParams.java
+++ b/src/noiseOneBand/OneBandDisplayParams.java
@@ -5,6 +5,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
public class OneBandDisplayParams implements Serializable, Cloneable, ManagedParameters {
@@ -61,7 +62,7 @@ public class OneBandDisplayParams implements Serializable, Cloneable, ManagedPar
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("displayChannels");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/noiseOneBand/OneBandParameters.java b/src/noiseOneBand/OneBandParameters.java
index b35e4f68..ea2f3320 100644
--- a/src/noiseOneBand/OneBandParameters.java
+++ b/src/noiseOneBand/OneBandParameters.java
@@ -10,6 +10,7 @@ import Filters.FilterType;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class OneBandParameters implements Serializable, Cloneable, ManagedParameters {
@@ -235,7 +236,7 @@ public class OneBandParameters implements Serializable, Cloneable, ManagedParame
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("filterParams");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/noiseOneBand/offline/OneBandSummaryParams.java b/src/noiseOneBand/offline/OneBandSummaryParams.java
index 7565c6e7..14e71708 100644
--- a/src/noiseOneBand/offline/OneBandSummaryParams.java
+++ b/src/noiseOneBand/offline/OneBandSummaryParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class OneBandSummaryParams implements Serializable, Cloneable, ManagedParameters {
@@ -23,7 +24,7 @@ public class OneBandSummaryParams implements Serializable, Cloneable, ManagedPar
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/offlineProcessing/TaskGroupParams.java b/src/offlineProcessing/TaskGroupParams.java
index 25497c24..c04a88cc 100644
--- a/src/offlineProcessing/TaskGroupParams.java
+++ b/src/offlineProcessing/TaskGroupParams.java
@@ -8,6 +8,7 @@ import java.util.Arrays;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Parameter control for offline task groups.
@@ -137,7 +138,7 @@ public class TaskGroupParams implements Cloneable, Serializable, ManagedParamete
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("taskSelection");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/pamMaths/PamVector.java b/src/pamMaths/PamVector.java
index 910e0bc9..d491f01e 100644
--- a/src/pamMaths/PamVector.java
+++ b/src/pamMaths/PamVector.java
@@ -382,7 +382,7 @@ public class PamVector implements Serializable, Cloneable, PamCoordinate, Manage
* @return magnitude of those dimensions only.
*/
public double norm(int nDim) {
- return Math.sqrt(normSquared(2));
+ return Math.sqrt(normSquared(nDim));
}
/**
*
diff --git a/src/pamguard/Pamguard.java b/src/pamguard/Pamguard.java
index 0a6da447..33009522 100644
--- a/src/pamguard/Pamguard.java
+++ b/src/pamguard/Pamguard.java
@@ -731,6 +731,47 @@ public class Pamguard {
}
}
}
+ /*
+ * Some bits that need added to Maven POM.
+ *
+
+
+ org.eclipse.persistence
+ org.eclipse.persistence.moxy
+ 2.5.0
+
+
+ javax.xml.bind
+ jaxb-api
+ 2.4.0-b180830.0359
+
+
+ org.glassfish.jaxb
+ jaxb-runtime
+ 2.4.0-b180830.0438
+
+
+ org.glassfish.jaxb
+ jaxb-xjc
+ 2.4.0-b180830.0438
+
+
+
+ */
}
diff --git a/src/quickAnnotation/QuickAnnotationParameters.java b/src/quickAnnotation/QuickAnnotationParameters.java
index fd8ed2a7..65e3b05b 100644
--- a/src/quickAnnotation/QuickAnnotationParameters.java
+++ b/src/quickAnnotation/QuickAnnotationParameters.java
@@ -9,6 +9,7 @@ import PamController.PamSettingManager;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import difar.DifarControl;
import difar.DifarParameters;
import generalDatabase.lookupTables.LookupItem;
@@ -96,7 +97,7 @@ public class QuickAnnotationParameters implements Serializable, Cloneable, Manag
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("exportClips");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/rawDeepLearningClassifier/dataPlotFX/DLPredDisplayParams.java b/src/rawDeepLearningClassifier/dataPlotFX/DLPredDisplayParams.java
index 7ad1ffb9..41ef495e 100644
--- a/src/rawDeepLearningClassifier/dataPlotFX/DLPredDisplayParams.java
+++ b/src/rawDeepLearningClassifier/dataPlotFX/DLPredDisplayParams.java
@@ -3,6 +3,7 @@ package rawDeepLearningClassifier.dataPlotFX;
import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import javafx.scene.paint.Color;
/**
@@ -25,7 +26,7 @@ public class DLPredDisplayParams implements Serializable, Cloneable, ManagedPara
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/rawDeepLearningClassifier/logging/DLAnnotationSQL.java b/src/rawDeepLearningClassifier/logging/DLAnnotationSQL.java
index 72761199..b046b27b 100644
--- a/src/rawDeepLearningClassifier/logging/DLAnnotationSQL.java
+++ b/src/rawDeepLearningClassifier/logging/DLAnnotationSQL.java
@@ -1,6 +1,7 @@
package rawDeepLearningClassifier.logging;
import PamguardMVC.PamDataUnit;
+import generalDatabase.EmptyTableDefinition;
import generalDatabase.PamTableDefinition;
import generalDatabase.SQLLoggingAddon;
import generalDatabase.SQLTypes;
@@ -12,19 +13,19 @@ public class DLAnnotationSQL implements SQLLoggingAddon {
}
@Override
- public void addTableItems(PamTableDefinition pamTableDefinition) {
+ public void addTableItems(EmptyTableDefinition pamTableDefinition) {
// TODO Auto-generated method stub
}
@Override
- public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
+ public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
// TODO Auto-generated method stub
return false;
}
@Override
- public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
+ public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition, PamDataUnit pamDataUnit) {
// TODO Auto-generated method stub
return false;
}
diff --git a/src/rocca/RoccaParameters.java b/src/rocca/RoccaParameters.java
index bec1fecb..c7db4aae 100644
--- a/src/rocca/RoccaParameters.java
+++ b/src/rocca/RoccaParameters.java
@@ -30,6 +30,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Parameters for Rocca
@@ -856,7 +857,7 @@ public class RoccaParameters implements Serializable, Cloneable, ManagedParamete
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("runAncCalcs4Clicks");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/seismicVeto/VetoParameters.java b/src/seismicVeto/VetoParameters.java
index 0ca08357..e41907f7 100644
--- a/src/seismicVeto/VetoParameters.java
+++ b/src/seismicVeto/VetoParameters.java
@@ -6,6 +6,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class VetoParameters implements Serializable, Cloneable, ManagedParameters {
@@ -40,7 +41,7 @@ public class VetoParameters implements Serializable, Cloneable, ManagedParameter
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("backgroundConstant");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/serialComms/SerialPortParameters.java b/src/serialComms/SerialPortParameters.java
index bb9d699c..373852fd 100644
--- a/src/serialComms/SerialPortParameters.java
+++ b/src/serialComms/SerialPortParameters.java
@@ -29,6 +29,7 @@ import com.fazecast.jSerialComm.SerialPort;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* @author David McLaren, Paul Redmond
@@ -166,7 +167,7 @@ public class SerialPortParameters implements Serializable, Cloneable, ManagedPar
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/simulatedAcquisition/SimObject.java b/src/simulatedAcquisition/SimObject.java
index 053c8a9b..335139fb 100644
--- a/src/simulatedAcquisition/SimObject.java
+++ b/src/simulatedAcquisition/SimObject.java
@@ -5,6 +5,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
import PamModel.parametermanager.PrivatePamParameterData;
import simulatedAcquisition.movement.MovementModel;
import simulatedAcquisition.movement.MovementModels;
@@ -150,7 +151,7 @@ public class SimObject implements Serializable, Cloneable, ManagedParameters {
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
try {
Field field = this.getClass().getDeclaredField("depth");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/simulatedAcquisition/movement/CircularMovementParams.java b/src/simulatedAcquisition/movement/CircularMovementParams.java
index 4fe63e95..c956209e 100644
--- a/src/simulatedAcquisition/movement/CircularMovementParams.java
+++ b/src/simulatedAcquisition/movement/CircularMovementParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class CircularMovementParams implements Serializable, Cloneable, ManagedParameters {
@@ -84,7 +85,7 @@ public class CircularMovementParams implements Serializable, Cloneable, ManagedP
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/simulatedAcquisition/movement/GridMovementParams.java b/src/simulatedAcquisition/movement/GridMovementParams.java
index 210ac943..72ae6cb2 100644
--- a/src/simulatedAcquisition/movement/GridMovementParams.java
+++ b/src/simulatedAcquisition/movement/GridMovementParams.java
@@ -6,6 +6,7 @@ import java.lang.reflect.Field;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class GridMovementParams implements Serializable, Cloneable, ManagedParameters {
@@ -42,7 +43,7 @@ public class GridMovementParams implements Serializable, Cloneable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("distRangeMetres");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/soundPlayback/PlaybackParameters.java b/src/soundPlayback/PlaybackParameters.java
index 08c1e56a..2d7d22d1 100644
--- a/src/soundPlayback/PlaybackParameters.java
+++ b/src/soundPlayback/PlaybackParameters.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
/**
* Parameters controlling sound playback
@@ -165,7 +166,7 @@ public class PlaybackParameters implements Cloneable, Serializable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/soundPlayback/preprocess/EnvelopeParams.java b/src/soundPlayback/preprocess/EnvelopeParams.java
index b3e0587c..7dd143e9 100644
--- a/src/soundPlayback/preprocess/EnvelopeParams.java
+++ b/src/soundPlayback/preprocess/EnvelopeParams.java
@@ -7,6 +7,7 @@ import Filters.FilterParams;
import Filters.FilterType;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class EnvelopeParams implements Cloneable, Serializable, ManagedParameters {
@@ -87,7 +88,7 @@ public class EnvelopeParams implements Cloneable, Serializable, ManagedParameter
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DISPLAY);
return ps;
}
diff --git a/src/soundtrap/STClickControl.java b/src/soundtrap/STClickControl.java
index 203357fe..8e7ca7b0 100644
--- a/src/soundtrap/STClickControl.java
+++ b/src/soundtrap/STClickControl.java
@@ -37,6 +37,7 @@ import javax.swing.JSeparator;
import org.pamguard.x3.sud.SUDClickDetectorInfo;
import Acquisition.AcquisitionControl;
+import PamController.PamSensor;
import PamController.PamControlledUnitSettings;
import PamController.PamController;
import PamController.PamSettingManager;
@@ -54,7 +55,7 @@ import soundtrap.sud.SudFileDWVHandler;
* @author mo55
*
*/
-public class STClickControl extends ClickControl {
+public class STClickControl extends ClickControl implements PamSensor {
private SUDClickDetectorInfo sudClickDetectorInfo;
@@ -229,6 +230,17 @@ public class STClickControl extends ClickControl {
public void setSudClickDetectorInfo(SUDClickDetectorInfo sudClickDetectorInfo) {
this.sudClickDetectorInfo = sudClickDetectorInfo;
}
+
+ @Override
+ public String getSensorDescription() {
+ String desc = String.format("SoundTrap Click Detector at %dHz", (int) getClickDataBlock().getSampleRate());
+ return desc;
+ }
+
+ @Override
+ public String getSensorId() {
+ return null;
+ }
/**
* Class to handle SoundTrap click detector settings without messing up
diff --git a/src/soundtrap/STToolsParams.java b/src/soundtrap/STToolsParams.java
index 722c6fb6..514b96d6 100644
--- a/src/soundtrap/STToolsParams.java
+++ b/src/soundtrap/STToolsParams.java
@@ -5,6 +5,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class STToolsParams implements Serializable, Cloneable, ManagedParameters {
@@ -62,7 +63,7 @@ public class STToolsParams implements Serializable, Cloneable, ManagedParameters
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/spectrogramNoiseReduction/SpectrogramNoiseSettings.java b/src/spectrogramNoiseReduction/SpectrogramNoiseSettings.java
index 0931c963..9cfa3765 100644
--- a/src/spectrogramNoiseReduction/SpectrogramNoiseSettings.java
+++ b/src/spectrogramNoiseReduction/SpectrogramNoiseSettings.java
@@ -7,6 +7,7 @@ import java.util.ArrayList;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import PamModel.parametermanager.PrivatePamParameterData;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class SpectrogramNoiseSettings implements Serializable, Cloneable, ManagedParameters {
@@ -79,7 +80,7 @@ public class SpectrogramNoiseSettings implements Serializable, Cloneable, Manage
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
try {
Field field = this.getClass().getDeclaredField("runMethod");
ps.put(new PrivatePamParameterData(this, field) {
diff --git a/src/spectrogramNoiseReduction/averageSubtraction/AverageSubtractionParameters.java b/src/spectrogramNoiseReduction/averageSubtraction/AverageSubtractionParameters.java
index 23e9f1f7..18f1811e 100644
--- a/src/spectrogramNoiseReduction/averageSubtraction/AverageSubtractionParameters.java
+++ b/src/spectrogramNoiseReduction/averageSubtraction/AverageSubtractionParameters.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class AverageSubtractionParameters implements Serializable, Cloneable, ManagedParameters {
@@ -25,7 +26,7 @@ public class AverageSubtractionParameters implements Serializable, Cloneable, Ma
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/spectrogramNoiseReduction/medianFilter/MedianFilterParams.java b/src/spectrogramNoiseReduction/medianFilter/MedianFilterParams.java
index fe91beba..c24aed99 100644
--- a/src/spectrogramNoiseReduction/medianFilter/MedianFilterParams.java
+++ b/src/spectrogramNoiseReduction/medianFilter/MedianFilterParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class MedianFilterParams implements Serializable, Cloneable, ManagedParameters {
@@ -25,7 +26,7 @@ public class MedianFilterParams implements Serializable, Cloneable, ManagedParam
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/spectrogramNoiseReduction/threshold/ThresholdParams.java b/src/spectrogramNoiseReduction/threshold/ThresholdParams.java
index 8842e6e0..5674d577 100644
--- a/src/spectrogramNoiseReduction/threshold/ThresholdParams.java
+++ b/src/spectrogramNoiseReduction/threshold/ThresholdParams.java
@@ -4,6 +4,7 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
+import PamModel.parametermanager.PamParameterSet.ParameterSetType;
public class ThresholdParams implements Serializable, Cloneable, ManagedParameters {
@@ -27,7 +28,7 @@ public class ThresholdParams implements Serializable, Cloneable, ManagedParamete
@Override
public PamParameterSet getParameterSet() {
- PamParameterSet ps = PamParameterSet.autoGenerate(this);
+ PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
return ps;
}
diff --git a/src/targetMotionOld/TargetMotionSQLLogging.java b/src/targetMotionOld/TargetMotionSQLLogging.java
index 6017a12b..4f4f133e 100644
--- a/src/targetMotionOld/TargetMotionSQLLogging.java
+++ b/src/targetMotionOld/TargetMotionSQLLogging.java
@@ -15,6 +15,7 @@ import PamDetection.AbstractLocalisation;
import PamDetection.LocContents;
import PamUtils.LatLong;
import PamguardMVC.PamDataUnit;
+import generalDatabase.EmptyTableDefinition;
import generalDatabase.PamTableDefinition;
import generalDatabase.PamTableItem;
import generalDatabase.SQLLoggingAddon;
@@ -119,7 +120,7 @@ public class TargetMotionSQLLogging implements SQLLoggingAddon {
}
@Override
- public void addTableItems(PamTableDefinition pamTableDefinition) {
+ public void addTableItems(EmptyTableDefinition pamTableDefinition) {
pamTableDefinition.addTableItem(modelName);
@@ -146,7 +147,7 @@ public class TargetMotionSQLLogging implements SQLLoggingAddon {
}
@Override
- public boolean saveData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition,
+ public boolean saveData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition,
PamDataUnit pamDataUnit) {
AbstractLocalisation tmResult = pamDataUnit.getLocalisation();
clearEverything();
@@ -218,7 +219,7 @@ public class TargetMotionSQLLogging implements SQLLoggingAddon {
return true;
}
- private boolean saveGroupLocalisation(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition,
+ private boolean saveGroupLocalisation(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition,
PamDataUnit pamDataUnit, GroupLocalisation groupLocalisation) {
int nAmbiguities = groupLocalisation.getAmbiguityCount();
@@ -239,7 +240,7 @@ public class TargetMotionSQLLogging implements SQLLoggingAddon {
return true;
}
- private boolean saveGroupLocalisation(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition,
+ private boolean saveGroupLocalisation(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition,
PamDataUnit pamDataUnit, int resultIndex, GroupLocResult tmResult) {
@@ -323,7 +324,7 @@ public class TargetMotionSQLLogging implements SQLLoggingAddon {
}
@Override
- public boolean loadData(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition,
+ public boolean loadData(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition,
PamDataUnit pamDataUnit) {
GroupLocalisation tml = new GroupLocalisation(pamDataUnit, null);
@@ -341,7 +342,7 @@ public class TargetMotionSQLLogging implements SQLLoggingAddon {
return true;
}
- private GroupLocResult loadLocResult(SQLTypes sqlTypes, PamTableDefinition pamTableDefinition,
+ private GroupLocResult loadLocResult(SQLTypes sqlTypes, EmptyTableDefinition pamTableDefinition,
PamDataUnit pamDataUnit, GroupLocalisation tml, int resultIndex) {
double latVal, longVal;
diff --git a/src/tethys/Collection.java b/src/tethys/Collection.java
new file mode 100644
index 00000000..93a6acb2
--- /dev/null
+++ b/src/tethys/Collection.java
@@ -0,0 +1,136 @@
+package tethys;
+
+/**
+ * Names of Tethys Collections. These are the plural names, though contain functionality
+ * to get the document names, which are generally the singular of the enum
+ * @author dg50
+ *
+ */
+public enum Collection {
+
+ Deployments, Detections, Calibrations, Localizations, SpeciesAbbreviations, Ensembles, SourceMaps, ITIS, ITIS_ranks, OTHER;
+
+ /**
+ * A list of the main collections in the database, i.e. ones the user will
+ * possibly want to interract with through the GUI.
+ * @return list of main collections.
+ */
+ public static Collection[] mainList() {
+ Collection[] cs = {Deployments, Detections, Calibrations, Localizations, SpeciesAbbreviations, Ensembles};
+ return cs;
+ }
+ /**
+ * Get the name of a document in this collection, this is generally the singular
+ * of the collection name.
+ * @return Document name, e.g. Detection for Detections
+ */
+ public String documentName() {
+ switch (this) {
+ case Calibrations:
+ return "Calibration";
+ case Deployments:
+ return "Deployment";
+ case Detections:
+ return "Detections"; // this one is plural !
+ case Localizations:
+ return "Localize";
+ case SpeciesAbbreviations:
+ return "SpeciesAbbreviation";
+ case Ensembles:
+ return "Ensemble";
+ default:
+ break;
+ }
+ return null;
+ }
+
+ public String collectionName() {
+ return this.toString();
+ }
+
+ /**
+ * Find a collection for the given name. This does
+ * a bit more than the simple 'valueof' since it also
+ * allows the user to input a documentname in place, which
+ * is just the collection name without the plural 's' on the end
+ * @param name Collection name.
+ * @return Collection or null.
+ */
+ public static Collection fromName(String name) {
+ Collection c = Collection.valueOf(name);
+ if (c != null) {
+ return c;
+ }
+ /**
+ * Otherwise, may need to do a longer search to see if the user has passed
+ * the singular document name.
+ */
+ if (name.endsWith("s") == false) {
+ c = Collection.valueOf(name+"s");
+ if (c != null) {
+ return c;
+ }
+ }
+ return null;
+ }
+ /**
+ * get Tethys collection name from nilus collection objects
+ * @param className nilus object Class Name
+ * @return name of Tethys collection
+ */
+ public static Collection fromClass(Class nilusClass) {
+ String className = nilusClass.getName();
+ switch(className) {
+ case "nilus.Deployment":
+ return Deployments;
+ case "nilus.Detections":
+ return Detections;
+ case "nilus.Calibration":
+ return Calibrations;
+ case "nilus.Ensemble":
+ return Ensembles;
+ case "nilus.Localization":
+ return Localizations;
+ case "nilus.SpeciesAbbreviation":
+ return SpeciesAbbreviations;
+ case "nilus.SourceMap":
+ return SourceMaps;
+ case "nilus.ITIS":
+ return ITIS;
+ case "nilus.ranks":
+ return ITIS_ranks;
+ default:
+ return null;
+ }
+ }
+// /**
+// * get Tethys collection name from nilus collection objects
+// * @param className nilus object Class Name
+// * @return name of Tethys collection
+// */
+// public static String getCollection(Class nilusClass) {
+// String className = nilusClass.getName();
+// switch(className) {
+// case "nilus.Deployment":
+// return "Deployments";
+// case "nilus.Detections":
+// return "Detections";
+// case "nilus.Calibration":
+// return "Calibrations";
+// case "nilus.Ensemble":
+// return "Ensembles";
+// case "nilus.Localization":
+// return "Localizations";
+// case "nilus.SpeciesAbbreviation":
+// return "SpeciesAbbreviations";
+// case "nilus.SourceMap":
+// return "SourceMaps";
+// case "nilus.ITIS":
+// return "ITIS";
+// case "nilus.ranks":
+// return "ITIS_ranks";
+// default:
+// return "";
+// }
+// }
+}
diff --git a/src/tethys/DocumentInfo.java b/src/tethys/DocumentInfo.java
new file mode 100644
index 00000000..7ad2d750
--- /dev/null
+++ b/src/tethys/DocumentInfo.java
@@ -0,0 +1,49 @@
+package tethys;
+
+/**
+ * Basic information about a document that can be used to
+ * make document lists.
+ * @author dg50
+ *
+ */
+public class DocumentInfo implements Comparable {
+
+ private Collection collection;
+ private String documentName;
+ private String documentId;
+
+ /**
+ * @param collection
+ * @param documentName
+ * @param documentId
+ */
+ public DocumentInfo(Collection collection, String documentName, String documentId) {
+ this.collection = collection;
+ this.documentName = documentName;
+ this.documentId = documentId;
+ }
+ @Override
+ public int compareTo(DocumentInfo o) {
+ return this.documentName.compareTo(o.documentName);
+ }
+ /**
+ * @return the collection
+ */
+ public Collection getCollection() {
+ return collection;
+ }
+ /**
+ * @return the documentName
+ */
+ public String getDocumentName() {
+ return documentName;
+ }
+ /**
+ * @return the documentId
+ */
+ public String getDocumentId() {
+ return documentId;
+ }
+
+
+}
diff --git a/src/tethys/DocumentNilusObject.java b/src/tethys/DocumentNilusObject.java
new file mode 100644
index 00000000..c6b5a402
--- /dev/null
+++ b/src/tethys/DocumentNilusObject.java
@@ -0,0 +1,32 @@
+package tethys;
+
+/**
+ * information about a document AND the nilus object to go with it.
+ * @author dg50
+ *
+ * @param
+ */
+public class DocumentNilusObject extends DocumentInfo {
+
+ private T nilusObject;
+
+ public DocumentNilusObject(Collection collection, String documentName, String documentId, T nilusObject) {
+ super(collection, documentName, documentId);
+ this.nilusObject = nilusObject;
+ }
+
+ /**
+ * @return the nilusObject
+ */
+ public T getNilusObject() {
+ return nilusObject;
+ }
+
+ /**
+ * @param nilusObject the nilusObject to set
+ */
+ public void setNilusObject(T nilusObject) {
+ this.nilusObject = nilusObject;
+ }
+
+}
diff --git a/src/tethys/TethysControl.java b/src/tethys/TethysControl.java
new file mode 100644
index 00000000..446face1
--- /dev/null
+++ b/src/tethys/TethysControl.java
@@ -0,0 +1,703 @@
+package tethys;
+
+import java.awt.Desktop;
+import java.awt.Frame;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;
+import javax.swing.Timer;
+
+import PamController.PamControlledUnit;
+import PamController.PamControlledUnitSettings;
+import PamController.PamController;
+import PamController.PamControllerInterface;
+import PamController.PamFolders;
+import PamController.PamSettingManager;
+import PamController.PamSettings;
+import PamUtils.PamFileChooser;
+import PamUtils.PamFileFilter;
+import PamView.PamTabPanel;
+import PamView.dialog.warn.WarnOnce;
+import PamguardMVC.PamDataBlock;
+import metadata.MetaDataContol;
+import metadata.PamguardMetaData;
+import nilus.Deployment;
+import tethys.TethysState.StateType;
+import tethys.calibration.CalibrationHandler;
+import tethys.dbxml.DBXMLConnect;
+import tethys.dbxml.DBXMLQueries;
+import tethys.dbxml.ServerStatus;
+import tethys.dbxml.TethysException;
+import tethys.dbxml.TethysQueryException;
+import tethys.deployment.DeploymentHandler;
+import tethys.detection.DetectionsHandler;
+import tethys.niluswraps.PDeployment;
+import tethys.output.DatablockSynchInfo;
+import tethys.output.TethysExportParams;
+import tethys.species.ITISFunctions;
+import tethys.species.SpeciesMapManager;
+import tethys.swing.ProjectDeploymentsDialog;
+import tethys.swing.TethysTabPanel;
+import tethys.swing.XMLStringView;
+import tethys.swing.documents.TethysDocumentsFrame;
+
+/**
+ * Quick play with a simple system for outputting data to Tethys. At it's start
+ * this is simply going to offer a dialog and have a few functions which show how
+ * to access data within PAMGuard.
+ * @author dg50
+ *
+ */
+public class TethysControl extends PamControlledUnit implements PamSettings, TethysStateObserver {
+
+ public static final String unitType = "Tethys Interface";
+ public static String defaultName = "Tethys";
+ public static String xmlNameSpace = "http://tethys.sdsu.edu/schema/1.0";
+
+ private TethysExportParams tethysExportParams = new TethysExportParams();
+
+ private DBXMLConnect dbxmlConnect;
+
+ private TethysTabPanel tethysTabPanel;
+
+ private DBXMLQueries dbxmlQueries;
+
+ private ArrayList stateObservers;
+
+ private Timer serverCheckTimer;
+
+ private ServerStatus lastServerStatus;
+
+ private ArrayList dataBlockSynchInfos;
+
+ private DeploymentHandler deploymentHandler;
+ private DetectionsHandler detectionsHandler;
+ private CalibrationHandler calibrationHandler;
+
+ private ITISFunctions itisFunctions;
+
+ public TethysControl(String unitName) {
+ super(unitType, unitName);
+ stateObservers = new ArrayList();
+ dbxmlConnect = new DBXMLConnect(this);
+ dbxmlQueries = new DBXMLQueries(this, dbxmlConnect);
+ deploymentHandler = new DeploymentHandler(this);
+ detectionsHandler = new DetectionsHandler(this);
+ calibrationHandler = new CalibrationHandler(this);
+
+ serverCheckTimer = new Timer(10000, new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ checkServer();
+ }
+ });
+ serverCheckTimer.setInitialDelay(0);
+ PamSettingManager.getInstance().registerSettings(this);
+ addStateObserver(this);
+
+ if (PamController.getInstance().isInitializationComplete()) {
+ // must be adding module later on ...
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ initializationStuff();
+ }
+ });
+ }
+ }
+
+ /**
+ * Get DBXML Connector. This class contains all the functions that are needed
+ * to talk to the database.
+ * @return DBXML functions.
+ */
+ public DBXMLConnect getDbxmlConnect() {
+ return dbxmlConnect;
+ }
+ @Override
+ public JMenuItem createDetectionMenu(Frame parentFrame) {
+ return createTethysMenu(parentFrame);
+ }
+
+ @Override
+ public JMenuItem createFileMenu(JFrame parentFrame) {
+ // TODO Auto-generated method stub
+ return super.createFileMenu(parentFrame);
+ }
+
+ /**
+ * Make a menu. Can go either in File or Settings. TBD.
+ * @param parentFrame
+ * @return
+ */
+ public JMenuItem createTethysMenu(Frame parentFrame) {
+ JMenu tethysMenu = new JMenu("Tethys");
+// JMenuItem tethysExport = new JMenuItem("Export ...");
+// tethysMenu.add(tethysExport);
+// tethysExport.addActionListener(new ActionListener() {
+// @Override
+// public void actionPerformed(ActionEvent e) {
+// tethysExport(parentFrame);
+// }
+// });
+ JMenuItem menuItem;
+ menuItem = new JMenuItem("Open client in browser");
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ openTethysClient();
+ }
+ });
+
+ tethysMenu.add(menuItem);
+ menuItem = new JMenuItem("Open temp document folder");
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ openTempDocuments();
+ }
+ });
+ tethysMenu.add(menuItem);
+
+
+ JMenuItem collections = new JMenu("Collections");
+ Collection[] mainCollections = Collection.mainList();
+ for (int i = 0; i < mainCollections.length; i++) {
+ Collection col = mainCollections[i];
+ menuItem = new JMenuItem("Open " + col.collectionName() + " collection in browser");
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ openTethysCollection(col);
+ }
+ });
+ collections.add(menuItem);
+ }
+
+ tethysMenu.add(collections);
+ tethysMenu.addSeparator();
+ JMenuItem showDeps = new JMenuItem("Show project deployments");
+ showDeps.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ showProjectDeploymentsDialog();
+ }
+ });
+ tethysMenu.add(showDeps);
+
+ JMenuItem cals = new JMenuItem("Export calibrations");
+ cals.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ calibrationHandler.exportAllCalibrations();
+ }
+ });
+ tethysMenu.add(cals);
+
+ tethysMenu.addSeparator();
+ JMenuItem mapItem = new JMenuItem("Export species maps ...");
+ mapItem.setToolTipText("Export all species maps (PAMGuard codes to ITIS codes to file for import into other configurations");
+ mapItem.addActionListener(SpeciesMapManager.getInstance().getExportAction(parentFrame));
+ tethysMenu.add(mapItem);
+
+ mapItem = new JMenuItem("Import species maps ...");
+ mapItem.setToolTipText("Import species maps (PAMGuard codes to ITIS codes to file for import into other configurations");
+ mapItem.addActionListener(SpeciesMapManager.getInstance().getImportAction(parentFrame));
+ tethysMenu.add(mapItem);
+
+ return tethysMenu;
+ }
+
+ protected void openTempDocuments() {
+ File tempFolder = dbxmlConnect.checkTempFolder();
+ if (tempFolder == null) {
+ WarnOnce.showWarning("Tethys Error", "Unable to obtain a temporary folder name", WarnOnce.WARNING_MESSAGE);
+ return;
+ }
+ try {
+// String cmd = "explorer.exe /select," + tempFolder.getAbsolutePath() + File.separator;
+// Runtime.getRuntime().exec(cmd);
+ Desktop.getDesktop().open(tempFolder);
+ }
+ catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void showProjectDeploymentsDialog() {
+ ProjectDeploymentsDialog.showDialog(getGuiFrame(), this);
+ }
+
+ public ArrayList getExportableDataBlocks() {
+ ArrayList sets = new ArrayList<>();
+ ArrayList allDataBlocks = PamController.getInstance().getDataBlocks();
+ for (PamDataBlock aDataBlock : allDataBlocks) {
+ if (aDataBlock.getTethysDataProvider(this) != null) {
+ sets.add(aDataBlock);
+ }
+ }
+ return sets;
+ }
+
+ /**
+ * Get the synchronisation info for all datablocks.
+ * This list should be static, but check it in case something has been
+ * added or removed.
+ * @return
+ */
+ public ArrayList getSynchronisationInfos() {
+ if (dataBlockSynchInfos == null) {
+ dataBlockSynchInfos = new ArrayList<>();
+ }
+ ArrayList dataBlocks = getExportableDataBlocks();
+ // check all datablocks are in there ...
+ for (PamDataBlock aBlock : dataBlocks) {
+ if (findDatablockSynchInfo(aBlock) == null) {
+ dataBlockSynchInfos.add(new DatablockSynchInfo(this, aBlock));
+ }
+ }
+ // and remove any which are no longer there.
+ for (DatablockSynchInfo synchInfo : dataBlockSynchInfos) {
+ if (!dataBlocks.contains(synchInfo.getDataBlock())) {
+ dataBlockSynchInfos.remove(synchInfo);
+ }
+ }
+
+ return dataBlockSynchInfos;
+ }
+
+ public DatablockSynchInfo findDatablockSynchInfo(PamDataBlock dataBlock) {
+ if (dataBlockSynchInfos == null) {
+ return null;
+ }
+ for (DatablockSynchInfo synchInfo : dataBlockSynchInfos) {
+ if (synchInfo.getDataBlock() == dataBlock) {
+ return synchInfo;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * open client in the default web browser
+ */
+ public void openTethysClient() {
+// String urlString = tethysExportParams.getFullServerName() + "/Client";
+// System.out.println("Opening url " + urlString);
+// URL url = null;
+// try {
+// url = new URL(urlString);
+// } catch (MalformedURLException e) {
+// e.printStackTrace();
+// }
+// if (url == null) {
+// return;
+// }
+// try {
+// Desktop.getDesktop().browse(url.toURI());
+// } catch (IOException e) {
+// e.printStackTrace();
+// } catch (URISyntaxException e) {
+// e.printStackTrace();
+// }
+ openCollectionInBrowser("Client");
+ }
+ /**
+ * open client in the default web browser
+ */
+ public void openTethysCollection(Collection collection) {
+ if (collection == null) {
+ return;
+ }
+ if (getTethysExportParams().listDocsInPamguard) {
+ openCollectionInPAMGuard(collection);
+ }
+ else {
+ openCollectionInBrowser(collection.collectionName());
+ }
+ }
+ public void openCollectionInPAMGuard(Collection collection) {
+ TethysDocumentsFrame.showTable(getGuiFrame(), this, collection);
+ }
+
+ public void openCollectionInBrowser(String collectionName) {
+ String urlString = tethysExportParams.getFullServerName() + "/" + collectionName;
+// System.out.println("Opening url " + urlString);
+ URL url = null;
+ try {
+ url = new URL(urlString);
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ if (url == null) {
+ return;
+ }
+ try {
+ Desktop.getDesktop().browse(url.toURI());
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (URISyntaxException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public PamTabPanel getTabPanel() {
+ if (tethysTabPanel == null) {
+ tethysTabPanel = new TethysTabPanel(this);
+ }
+ return tethysTabPanel;
+ }
+
+ /**
+ * @return the tethysExportParams
+ */
+ public TethysExportParams getTethysExportParams() {
+ return tethysExportParams;
+ }
+
+// /**
+// * We'll probably want to
+// * @param parentFrame
+// */
+// protected void tethysExport(JFrame parentFrame) {
+// TethysExportParams newExportParams = TethysExportDialog.showDialog(parentFrame, this);
+// if (newExportParams != null) {
+// // dialog returns null if cancel was pressed.
+// tethysExportParams = newExportParams;
+// exportTethysData(tethysExportParams);
+// }
+// }
+//
+// /**
+// * We'll arrive here if the dialog has been opened and we want to export Tethys data.
+// * @param tethysExportParams2
+// */
+// private void exportTethysData(TethysExportParams tethysExportParams) {
+// TethysExporter tethysExporter = new TethysExporter(this, tethysExportParams);
+// tethysExporter.doExport();
+//
+// sendStateUpdate(new TethysState(StateType.TRANSFERDATA));
+// countProjectDetections();
+// sendStateUpdate(new TethysState(StateType.NEWPAMGUARDSELECTION));
+// }
+
+ /**
+ * Get global deployment data. This is a bit of a mess, trying to use a separate module
+ * so that the rest of PAMGuard can use it, but creating the
+ * @return
+ */
+ public Deployment getGlobalDeplopymentData() {
+
+ MetaDataContol metaControl = MetaDataContol.getMetaDataControl();
+ PamguardMetaData metaData = metaControl.getMetaData();
+ return metaData.getDeployment();
+// Deployment deploymentData = metaControl != null ? metaData.getDeployment() : getTethysProjectData();
+//
+//// deploymentData.setProject("thisIsAProject");
+////// deploymentData.setPlatform("Yay a platform");
+//// deploymentData.setCruise("cruisey");
+//// deploymentData.setDeploymentId(142536);
+////// deploymentData.setInstrumentId("super instrument");
+//// deploymentData.setSite("in the ocean somewhere");
+//// deploymentData.setRegion("ocean water");
+////// deploymentData.setInstrumentType("sensor of sorts");
+//
+// return deploymentData;
+ }
+
+ /**
+ * Add a new state observer.
+ * @param stateObserver
+ */
+ public void addStateObserver(TethysStateObserver stateObserver) {
+ stateObservers.add(stateObserver);
+ }
+
+ /**
+ * Remove a state observer.
+ * @param stateObserver
+ * @return true if it existed.
+ */
+ public boolean removeStateObserver(TethysStateObserver stateObserver) {
+ return stateObservers.remove(stateObserver);
+ }
+
+ /**
+ * Send state updates around to all state observers.
+ * @param tethysState
+ */
+ public void sendStateUpdate(TethysState tethysState) {
+ for (TethysStateObserver stateObserver : this.stateObservers) {
+ stateObserver.updateState(tethysState);
+ }
+ }
+ /**
+ * A name for any deta selectors.
+ * @return
+ */
+ public String getDataSelectName() {
+ return getUnitName();
+ }
+
+ public DBXMLQueries getDbxmlQueries() {
+ return dbxmlQueries;
+ }
+
+ @Override
+ public void notifyModelChanged(int changeType) {
+ super.notifyModelChanged(changeType);
+ switch (changeType) {
+ case PamControllerInterface.INITIALIZE_LOADDATA:
+// case PamControllerInterface.INITIALIZATION_COMPLETE:
+ initializationStuff();
+ break;
+ }
+ }
+
+ /**
+ * Stuff to do on initial load (initialization complete or addition of
+ * a Tethys module after initialisation).
+ */
+ private void initializationStuff() {
+ deploymentHandler.createPamguardOverview();
+ serverCheckTimer.start();
+ sendStateUpdate(new TethysState(StateType.NEWPAMGUARDSELECTION));
+ }
+
+ /**
+ * Check the server. This will send around a notification if the state
+ * has changed since the last call to this function, so it's unlikely you'll
+ * need to use the return value
+ * @return server status.
+ */
+ public ServerStatus checkServer() {
+ ServerStatus serverState = dbxmlConnect.pingServer();
+ if (lastServerStatus == null || lastServerStatus.ok != serverState.ok) {
+ sendStateUpdate(new TethysState(StateType.UPDATESERVER));
+ }
+ lastServerStatus = serverState;
+ return serverState;
+ }
+
+ @Override
+ public Serializable getSettingsReference() {
+ return tethysExportParams;
+ }
+
+ @Override
+ public long getSettingsVersion() {
+ return TethysExportParams.serialVersionUID;
+ }
+
+ @Override
+ public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
+ tethysExportParams = (TethysExportParams) pamControlledUnitSettings.getSettings();
+ return true;
+ }
+
+ @Override
+ public void updateState(TethysState tethysState) {
+ switch (tethysState.stateType) {
+ case NEWPROJECTSELECTION:
+ case EXPORTRDATA:
+ case DELETEDATA:
+ countProjectDetections();
+ break;
+ }
+ }
+
+ private void countProjectDetections() {
+ if (dataBlockSynchInfos == null) {
+ return;
+ }
+ Deployment deplData = getGlobalDeplopymentData();
+ String[] dataPrefixes = new String[dataBlockSynchInfos.size()];
+ int i = 0;
+ ArrayList matchedDeployments = deploymentHandler.getMatchedDeployments();
+ for (DatablockSynchInfo synchInfo : dataBlockSynchInfos) {
+// dataPrefixes[i] = DetectionsHandler.getDetectionsDocIdPrefix(deplData.getProject(), synchInfo.getDataBlock());
+ int detectionCount = 0;
+ int documentCount = 0;
+ for (PDeployment pDepl : matchedDeployments) {
+ detectionCount += dbxmlQueries.countData(synchInfo.getDataBlock(), pDepl.deployment.getId());
+ ArrayList detectionsNames = getDbxmlQueries().getDetectionsDocuments(synchInfo.getDataBlock(), pDepl.deployment.getId());
+ if (detectionsNames != null) {
+ documentCount += detectionsNames.size();
+ }
+ }
+ synchInfo.setDataCount(detectionCount);
+ synchInfo.setDetectionDocumentCount(documentCount);
+
+ i++;
+ }
+// int[] counts = dbxmlQueries.countDataForProject(deplData.getProject(), dataPrefixes);
+// if (counts != null) {
+// for ( i = 0; i < counts.length; i++ ) {
+// dataBlockSynchInfos.get(i).setDataCount(counts[i]);
+// }
+// }
+ }
+
+ /**
+ * One stop place to get Deployment information. Will provide
+ * both information on record periods in PAMGuard and also Deployment docs in Tethys.
+ * @return set of functions for handling deployments.
+ */
+ public DeploymentHandler getDeploymentHandler() {
+ return deploymentHandler;
+ }
+
+ public DetectionsHandler getDetectionsHandler() {
+ return detectionsHandler;
+ }
+
+ public void showException(TethysException tethysException) {
+ String title = tethysException.getMessage();
+ StackTraceElement[] stack = tethysException.getStackTrace();
+ String msg = "";
+ if (stack != null) {
+ msg = "Caused in";
+ for (int i = 0; i < Math.min(stack.length, 3); i++) {
+ msg += " " + stack[i].getClassName() + "." + stack[i].getMethodName();
+ }
+ }
+ if (tethysException instanceof TethysQueryException) {
+ TethysQueryException tqe = (TethysQueryException) tethysException;
+// msg += tqe.
+ }
+
+ String xml = tethysException.getXmlError();
+ if (xml != null) {
+ /**
+ * html can't handle the < and > in xml without getting very confused
+ * but it seems to work fine if they are replaced with their html codes.
+ */
+ xml = xml.replace("<", "<");
+ xml = xml.replace(">", ">");
+ xml = xml.replace("\n", " ");
+ msg += ""+xml+" ";
+ }
+ WarnOnce.showWarning(title, msg, WarnOnce.WARNING_MESSAGE);
+ }
+
+ public void displayDocument(DocumentInfo docInfo) {
+ String collectionName = docInfo.getCollection().collectionName();
+ String docId = docInfo.getDocumentName();
+ displayDocument(collectionName, docId);
+ }
+ /**
+ * Load a document from the database and display it in a popup window
+ * @param collection
+ * @param documentId
+ */
+ public void displayDocument(String collection, String documentId) {
+ String doc = getDbxmlQueries().getDocument(collection, documentId);
+ if (doc == null | doc.length() == 0) {
+ doc = String.format("Unable to retrieve document %s/%s from database\n", collection, documentId);
+
+ }
+ XMLStringView.showDialog(getGuiFrame(), collection, documentId, doc);
+ }
+
+ /**
+ * Load a document from the database and write to a file selected by the user
+ * @param collection
+ * @param documentId
+ */
+ public void exportDocument(String collection, String documentId) {
+ String doc = getDbxmlQueries().getDocument(collection, documentId);
+ if (doc == null | doc.length() == 0) {
+ String msg = String.format("Unable to retrieve document %s/%s from database\n", collection, documentId);
+ WarnOnce.showWarning("Error", msg, WarnOnce.WARNING_MESSAGE);
+ }
+
+ PamFileFilter fileFilter = new PamFileFilter("XML documents", ".xml");
+// fileFilter
+ JFileChooser fileChooser = new JFileChooser();
+ fileChooser.setFileFilter(fileFilter);
+ fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+ // make a default name based on the document id and the dataset directory.
+ String defFolder = PamFolders.getDefaultProjectFolder();
+ File defFile = null;
+ if (defFolder != null) {
+ defFolder = String.format("%s%s%s_%s.xml", defFolder,File.separator,collection,documentId);
+ defFile = new File(defFolder);
+ fileChooser.setAcceptAllFileFilterUsed(true);
+ fileChooser.setSelectedFile(defFile);
+
+// fileChooser.setSelectedFile(new File(String.format("%s.xml", documentId)));
+// fileChooser.set
+ }
+ int state = fileChooser.showSaveDialog(getGuiFrame());
+ if (state != JFileChooser.APPROVE_OPTION) return;
+ File newFile = fileChooser.getSelectedFile();
+ if (newFile == null) return;
+ newFile = PamFileFilter.checkFileEnd(newFile, "xml", true);
+ if (newFile == null) {
+ return;
+ }
+ if (newFile.exists()) {
+ int ans2 = WarnOnce.showWarning(newFile.getAbsolutePath(),
+ "The file already exists. Do you want to overwrite it ?", WarnOnce.OK_CANCEL_OPTION);
+ if (ans2 == WarnOnce.CANCEL_OPTION) {
+ return;
+ }
+ }
+ try {
+ BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(newFile));
+ bos.write(doc.getBytes());
+ bos.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @return the itisFunctions
+ */
+ public ITISFunctions getItisFunctions() {
+ if (itisFunctions == null) {
+ itisFunctions = new ITISFunctions(this);
+ }
+ return itisFunctions;
+ }
+
+ /**
+ * Called when a detections document has been exported.
+ * @param dataBlock
+ */
+ public void exportedDetections(PamDataBlock dataBlock) {
+ sendStateUpdate(new TethysState(StateType.EXPORTRDATA, Collection.Detections));
+ countProjectDetections();
+ sendStateUpdate(new TethysState(StateType.NEWPAMGUARDSELECTION, Collection.Detections));
+ }
+
+ /**
+ * @return the calibrationHandler
+ */
+ public CalibrationHandler getCalibrationHandler() {
+ return calibrationHandler;
+ }
+
+
+}
diff --git a/src/tethys/TethysLocationFuncs.java b/src/tethys/TethysLocationFuncs.java
new file mode 100644
index 00000000..dbfa68d8
--- /dev/null
+++ b/src/tethys/TethysLocationFuncs.java
@@ -0,0 +1,83 @@
+package tethys;
+
+import Array.ArrayManager;
+import Array.HydrophoneLocator;
+import Array.PamArray;
+import Array.Streamer;
+import GPS.GPSControl;
+import GPS.GpsDataUnit;
+import PamUtils.LatLong;
+import PamUtils.PamUtils;
+import generalDatabase.DBControlUnit;
+import generalDatabase.PamConnection;
+import nilus.Deployment;
+import nilus.DeploymentRecoveryDetails;
+
+/**
+ * Function(s) to get location information for Tethys in the required format.
+ * @author dg50
+ *
+ */
+public class TethysLocationFuncs {
+
+
+ /**
+ * Get everything we need for a deployment document including the track #
+ * and the deployment / recovery information. Basically this means we
+ * have to load the GPS data, then potentially filter it. Slight risk this
+ * may all be too much for memory, but give it a go by loading GPS data for
+ * the deployment times.
+ * @param deployment
+ */
+ public static void getTrackAndPositionData(Deployment deployment) {
+ long start = TethysTimeFuncs.millisFromGregorianXML(deployment.getDeploymentDetails().getAudioTimeStamp());
+ long end = TethysTimeFuncs.millisFromGregorianXML(deployment.getRecoveryDetails().getAudioTimeStamp());
+ /*
+ * Need to load data for GPS, Hydrophones and Streamers datablocks for this time period. Can then use
+ * the snapshot geomentry classes to do the rest from the array manager ?
+ */
+ boolean ok = true;
+ ok &= addPositionData(deployment.getDeploymentDetails());
+ ok &= addPositionData(deployment.getRecoveryDetails());
+
+ }
+
+ /**
+ * Add position data to DeploymentRecoveryDetails.
+ * @param drd
+ * @return
+ */
+ public static boolean addPositionData(DeploymentRecoveryDetails drd) {
+ long timeMillis = TethysTimeFuncs.millisFromGregorianXML(drd.getAudioTimeStamp());
+ LatLong pos = getLatLongData(timeMillis);
+ if (pos == null) {
+ return false;
+ }
+ drd.setLongitude(PamUtils.constrainedAngle(pos.getLongitude(), 360));
+ drd.setLatitude(pos.getLatitude());
+ drd.setElevationInstrumentM(pos.getHeight());
+ drd.setDepthInstrumentM(-pos.getHeight());
+ return true;
+ }
+
+ public static LatLong getLatLongData(long timeMillis) {
+ // check the array time.
+ PamArray array = ArrayManager.getArrayManager().getCurrentArray();
+ Streamer aStreamer = array.getStreamer(0);
+ GPSControl gpsControl = GPSControl.getGpsControl();
+ PamConnection con = DBControlUnit.findConnection();
+ if (gpsControl != null) {
+// check GPS data are loaded for times around this.
+ GpsDataUnit gpsData = (GpsDataUnit) gpsControl.getGpsDataBlock().getLogging().findClosestDataPoint(con, timeMillis);
+ if (gpsData != null) {
+ return gpsData.getGpsData();
+ }
+ }
+ HydrophoneLocator hydrophoneLocator = aStreamer.getHydrophoneLocator();
+ if (hydrophoneLocator == null) {
+ return null;
+ }
+ return hydrophoneLocator.getStreamerLatLong(timeMillis);
+ }
+
+}
diff --git a/src/tethys/TethysMenuActions.java b/src/tethys/TethysMenuActions.java
new file mode 100644
index 00000000..625096a9
--- /dev/null
+++ b/src/tethys/TethysMenuActions.java
@@ -0,0 +1,70 @@
+package tethys;
+
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+
+import tethys.dbxml.TethysException;
+import tethys.niluswraps.PDeployment;
+
+/*
+ * Some standard meny dirven functions which we may want to call from
+ * a few different places.
+ */
+public class TethysMenuActions {
+
+ private TethysControl tethysControl;
+
+ public TethysMenuActions(TethysControl tethysControl) {
+ super();
+ this.tethysControl = tethysControl;
+ }
+
+ public void deploymentMouseActions(MouseEvent e, PDeployment pDeployment) {
+ ArrayList detDocNames = tethysControl.getDbxmlQueries().getDetectionsDocuments(pDeployment.deployment.getId());
+// System.out.println("Detections for deployment " + pDeployment.deployment.getId());
+// for (String detName : detDocNames) {
+// System.out.println(detName);
+// }
+ JPopupMenu menu = new JPopupMenu();
+ if (detDocNames.size() == 0) {
+ JMenuItem menuItem = new JMenuItem("Delete deployment " + pDeployment.deployment.getId());
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ try {
+ deleteDeployment(pDeployment);
+ } catch (TethysException e1) {
+ tethysControl.showException(e1);
+ }
+ }
+ });
+ menu.add(menuItem);
+ }
+ else {
+ String str = String.format("Delete deployment %s and %d Detections documents", pDeployment.deployment.getId(), detDocNames.size());
+ JMenuItem menuItem = new JMenuItem(str);
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ try {
+ deleteDeployment(pDeployment);
+ } catch (TethysException e1) {
+ tethysControl.showException(e1);
+ }
+ }
+ });
+ menu.add(menuItem);
+ }
+ menu.show(e.getComponent(), e.getX(), e.getY());
+ }
+
+ protected void deleteDeployment(PDeployment pDeployment) throws TethysException {
+ tethysControl.getDbxmlConnect().deleteDeployment(pDeployment.deployment.getId());
+ }
+}
diff --git a/src/tethys/TethysState.java b/src/tethys/TethysState.java
new file mode 100644
index 00000000..ea2f2746
--- /dev/null
+++ b/src/tethys/TethysState.java
@@ -0,0 +1,54 @@
+package tethys;
+
+/**
+ * Basis for a message system which will get passed around whenever something happens in
+ * Tethys, whether it be a new connection, progress during data output, etc.
+ * @author dg50
+ *
+ */
+public class TethysState {
+
+ public enum StateType {UPDATESERVER, // Server connection or status has changed
+ EXPORTRDATA, // data have been transferred from PAMGuard to Tethys
+ NEWPROJECTSELECTION, // a new Tethys project has been selected in the GUI
+ NEWPAMGUARDSELECTION, // new PAMGuard data are available (called once on first load)
+ UPDATEMETADATA, // META Data being prepared for output have changed (so may be able to enable output!)
+ EXPORTING, // currently exporting data. may be a while ...
+ DELETEDATA // data were deleted
+ }
+
+ public StateType stateType;
+
+ public Collection collection;
+
+ public TethysState(StateType stateType) {
+ super();
+ this.stateType = stateType;
+ collection = Collection.OTHER;
+ }
+
+ public TethysState(StateType stateType, Collection collection) {
+ this.stateType = stateType;
+ this.collection = collection;
+ if (this.collection == null) {
+ this.collection = Collection.OTHER;
+ }
+ }
+
+ /**
+ * @return the collection associated with this notification. Note that there is
+ * an OTHER category in Collections which is used for server / project updates, making
+ * it easier to switch on the collection type when notifications are received.
+ */
+ public Collection getCollection() {
+ return collection;
+ }
+
+ /**
+ * @return the stateType
+ */
+ public StateType getStateType() {
+ return stateType;
+ }
+
+}
diff --git a/src/tethys/TethysStateObserver.java b/src/tethys/TethysStateObserver.java
new file mode 100644
index 00000000..33a9de5c
--- /dev/null
+++ b/src/tethys/TethysStateObserver.java
@@ -0,0 +1,13 @@
+package tethys;
+
+public interface TethysStateObserver {
+
+ /**
+ * Receive state updates when Tethys has done something (made a connection, moved some data, etc.)
+ * Note that this is for RECEIVING state updates, not for sending them. To avoid infinite notifications
+ * loops, use tethysControl.sendStateUpdate(TethysState) to send out state notifications.
+ * @param tethysState
+ */
+ public void updateState(TethysState tethysState);
+
+}
diff --git a/src/tethys/TethysTimeFuncs.java b/src/tethys/TethysTimeFuncs.java
new file mode 100644
index 00000000..70d11704
--- /dev/null
+++ b/src/tethys/TethysTimeFuncs.java
@@ -0,0 +1,90 @@
+package tethys;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+import javax.xml.datatype.DatatypeConfigurationException;
+import javax.xml.datatype.DatatypeFactory;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import PamUtils.PamCalendar;
+
+public class TethysTimeFuncs {
+
+ private static TimeZone timeZone = TimeZone.getTimeZone("UTC");
+
+ /*
+ * Copied from http://www.java2s.com/Code/Java/Development-Class/ConvertsagiventimeinmillisecondsintoaXMLGregorianCalendarobject.htm
+ */
+ public static XMLGregorianCalendar xmlGregCalFromMillis(long millis) {
+ try {
+ final GregorianCalendar calendar = new GregorianCalendar();
+ calendar.setTimeZone(timeZone);
+ calendar.setTimeInMillis(millis);
+ return DatatypeFactory.newInstance().newXMLGregorianCalendar(
+ calendar);
+ }
+ catch (final DatatypeConfigurationException ex) {
+ System.out.println("Unable to convert date '%s' to an XMLGregorianCalendar object");
+ return null;
+ }
+ }
+
+ /**
+ * Convert a Gregorian calendar value back to milliseconds.
+ * @param xmlGregorian
+ * @return
+ */
+ public static Long millisFromGregorianXML(XMLGregorianCalendar xmlGregorian) {
+ if (xmlGregorian == null) {
+ return null;
+ }
+ GregorianCalendar gc2 = xmlGregorian.toGregorianCalendar();
+ gc2.setTimeZone(timeZone);
+ return gc2.getTimeInMillis();
+ }
+
+ /**
+ * Make a Gregorian calendar object from a returned XML string.
+ * @param gregorianString
+ * @return
+ */
+ public static XMLGregorianCalendar fromGregorianXML(String gregorianString) {
+ // typical string is 2018-10-20T00:00:00Z
+ if (gregorianString == null) {
+ return null;
+ }
+// GregorianCalendar gCal = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
+ gregorianString = gregorianString.replace("T", " ");
+ gregorianString = gregorianString.replace("Z", "");
+ DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ df.setTimeZone(TimeZone.getTimeZone("UTC"));
+ Date date = null;
+ try {
+ date = df.parse(gregorianString);
+ } catch (ParseException e) {
+ System.out.printf("Unparsable date string:\"%s\"", gregorianString);
+ e.printStackTrace();
+ return null;
+ }
+ return xmlGregCalFromMillis(date.getTime());
+// gCal.setTimeInMillis(date.getTime());
+//// gCal.se
+// return gCal;
+ }
+
+ public static String formatGregorianTime(XMLGregorianCalendar gregCal) {
+ if (gregCal == null) {
+ return null;
+ }
+ Long millis = millisFromGregorianXML(gregCal);
+ if (millis == null) {
+ return gregCal.toString();
+ }
+ return PamCalendar.formatDBDateTime(millis);
+ }
+}
diff --git a/src/tethys/calibration/CalibrationHandler.java b/src/tethys/calibration/CalibrationHandler.java
new file mode 100644
index 00000000..15f3ece4
--- /dev/null
+++ b/src/tethys/calibration/CalibrationHandler.java
@@ -0,0 +1,545 @@
+package tethys.calibration;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.datatype.XMLGregorianCalendar;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+
+import Acquisition.AcquisitionControl;
+import Acquisition.AcquisitionParameters;
+import Acquisition.AcquisitionProcess;
+import Array.ArrayManager;
+import Array.Hydrophone;
+import Array.PamArray;
+import Array.Preamplifier;
+import PamController.PamController;
+import PamController.soundMedium.GlobalMedium;
+import PamController.soundMedium.GlobalMedium.SoundMedium;
+import PamUtils.PamCalendar;
+import PamView.dialog.warn.WarnOnce;
+import dbxml.Queries;
+import PamController.soundMedium.GlobalMediumManager;
+import nilus.AlgorithmType.Parameters;
+import nilus.Calibration;
+import nilus.Calibration.FrequencyResponse;
+import nilus.Calibration.QualityAssurance;
+import nilus.Helper;
+import nilus.MetadataInfo;
+import nilus.QualityValueBasic;
+import nilus.ResponsibleParty;
+import tethys.Collection;
+import tethys.DocumentInfo;
+import tethys.DocumentNilusObject;
+import tethys.TethysControl;
+import tethys.TethysState;
+import tethys.TethysStateObserver;
+import tethys.TethysTimeFuncs;
+import tethys.calibration.swing.CalibrationsExportWizard;
+import tethys.dbxml.DBXMLConnect;
+import tethys.dbxml.TethysException;
+import tethys.niluswraps.NilusSettingsWrapper;
+import tethys.niluswraps.NilusUnpacker;
+import tethys.pamdata.AutoTethysProvider;
+
+public class CalibrationHandler implements TethysStateObserver {
+
+ private TethysControl tethysControl;
+
+ private ArrayList> calibrationsList;
+
+ public static final String[] updateOptions = {"as-needed", "unplanned", "yearly"};
+
+ public static final String[] calibrationMethods = {"Reference hydrophone", "Manufacturers specification", "Piston phone", "Other calibrated source", "Unknown"};
+
+ public static final String[] qaTypes = {"unverified", "valid", "invalid"};
+
+ private Helper nilusHelper;
+ /**
+ * @param tethysControl
+ */
+ public CalibrationHandler(TethysControl tethysControl) {
+ this.tethysControl = tethysControl;
+ calibrationsList = new ArrayList();
+ tethysControl.addStateObserver(this); try {
+ nilusHelper = new Helper();
+ } catch (JAXBException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void updateState(TethysState tethysState) {
+ switch (tethysState.stateType) {
+ case EXPORTING:
+ break;
+ case NEWPAMGUARDSELECTION:
+ case NEWPROJECTSELECTION:
+ case EXPORTRDATA:
+ case DELETEDATA:
+ case UPDATEMETADATA:
+ case UPDATESERVER:
+ if (isWantedState(tethysState)) {
+ updateDocumentsList();
+ }
+ default:
+ break;
+
+ }
+ }
+
+ /**
+ * Is it a state notification we want to respond to
+ * @param state
+ * @return true if worth it.
+ */
+ protected boolean isWantedState(TethysState state) {
+ if (state.collection == null) {
+ return true;
+ }
+ switch (state.collection) {
+ case OTHER:
+ case Calibrations:
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Update the list of documents associated with the selected instrument.
+ */
+ private void updateDocumentsList() {
+
+ calibrationsList.clear();
+
+ ArrayList docsList = getArrayCalibrations();
+ // now immediately read the calibrations in again.
+ if (docsList == null) {
+ return;
+ }
+ NilusUnpacker unpacker = new NilusUnpacker();
+ for (DocumentInfo aDoc : docsList) {
+ Queries queries = tethysControl.getDbxmlConnect().getTethysQueries();
+ String result = null;
+ Calibration calObj = null;
+ try {
+ result = queries.getDocument(Collection.Calibrations.toString(), aDoc.getDocumentName());
+ if (result != null) {
+ // create a document and convert it into a Nilus calibrations document.
+ Document doc = tethysControl.getDbxmlQueries().convertStringToXMLDocument(result);
+ if (doc == null) {
+ System.out.println("Unable to convert Calibration result to Document\n " + result);
+ continue;
+ }
+ calObj = (Calibration) unpacker.unpackDocument(doc, Calibration.class);
+ if (calObj == null) {
+ System.out.println("Unable to convert Calibration document to nilus object\n " + result);
+ continue;
+ }
+ }
+ long t = System.currentTimeMillis();
+ try {
+ XMLGregorianCalendar gt = calObj.getMetadataInfo().getDate();
+ if (gt != null) {
+ t = TethysTimeFuncs.millisFromGregorianXML(gt);
+ }
+ }
+ catch (Exception e) {
+
+ }
+ DocumentNilusObject calDataUnit = new DocumentNilusObject(Collection.Calibrations, aDoc.getDocumentName(), calObj.getId(), calObj);
+ calibrationsList.add(calDataUnit);
+// System.out.println(result);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public int exportAllCalibrations() {
+
+ Calibration sampleCal = new Calibration();
+ try {
+ Helper.createRequiredElements(sampleCal);
+ } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e1) {
+ e1.printStackTrace();
+ }
+ sampleCal = CalibrationsExportWizard.showWizard(tethysControl.getGuiFrame(), sampleCal);
+ if (sampleCal == null) {
+ return 0;
+ }
+
+ NilusSettingsWrapper wrappedSample = new NilusSettingsWrapper();
+ wrappedSample.setNilusObject(sampleCal);
+
+ PamArray array = ArrayManager.getArrayManager().getCurrentArray();
+ int nPhone = array.getHydrophoneCount();
+ DBXMLConnect dbxml = tethysControl.getDbxmlConnect();
+ int nExport = 0;
+ boolean overwrite = false;
+ boolean exists;
+ for (int i = 0; i < nPhone; i++) {
+// String docName = getHydrophoneId(i);
+ NilusSettingsWrapper clonedWrap = wrappedSample.clone();
+ sampleCal = clonedWrap.getNilusObject(Calibration.class);
+ Calibration calDoc = createCalibrationDocument(i);
+ if (sampleCal != null) {
+ calDoc.setMetadataInfo(sampleCal.getMetadataInfo());
+ calDoc.setProcess(sampleCal.getProcess());
+ calDoc.setQualityAssurance(sampleCal.getQualityAssurance());
+ calDoc.setResponsibleParty(sampleCal.getResponsibleParty());
+ calDoc.setTimeStamp(sampleCal.getTimeStamp());
+ }
+
+ addParameterDetails(calDoc, i);
+
+ String calDocName = createDocumentName(calDoc, i);
+ exists = calDocumentExists(calDocName);
+ if (exists && overwrite == false) {
+ String msg = String.format("Calibration document %s already exists. Do you want to overwrite it and other documents from this date?", calDocName);
+ int ans = WarnOnce.showWarning("Calibration Export", msg, WarnOnce.OK_CANCEL_OPTION);
+ if (ans == WarnOnce.OK_OPTION) {
+ overwrite = true;
+ }
+ else {
+ return nExport;
+ }
+ }
+ boolean ok = false;
+ if (exists == true && overwrite == false) {
+ continue;
+ }
+ try {
+ if (exists) {
+ ok = dbxml.removeDocument(Collection.Calibrations, calDocName);
+ }
+ ok = dbxml.postAndLog(calDoc, calDocName);
+ } catch (TethysException e) {
+ e.printStackTrace();
+ tethysControl.showException(e);
+ ok = false;
+ break;
+ }
+ if (ok) {
+ nExport++;
+ }
+ }
+ tethysControl.sendStateUpdate(new TethysState(TethysState.StateType.EXPORTRDATA, Collection.Calibrations));
+ return nExport;
+ }
+
+ /**
+ * Add the separate pamguard parameters to the document which are used
+ * to make up the overall calibration.
+ * @param calDoc
+ * @param i hydrophone number
+ */
+ private void addParameterDetails(Calibration calDoc, int i) {
+ Parameters params = calDoc.getProcess().getParameters();
+ PamArray array = ArrayManager.getArrayManager().getCurrentArray();
+ AcquisitionControl daqControl = (AcquisitionControl) PamController.getInstance().findControlledUnit(AcquisitionControl.unitType);
+ AcquisitionParameters daqParams = daqControl.getAcquisitionParameters();
+ Hydrophone phone = array.getHydrophoneArray().get(i);
+ try {
+ nilusHelper.AddAnyElement(params.getAny(), "HydrophoneType", phone.getType());
+ nilusHelper.AddAnyElement(params.getAny(), "Sensitivity", String.format("%3.1f", phone.getSensitivity()));
+ nilusHelper.AddAnyElement(params.getAny(), "PreampGain", String.format("%3.1f", phone.getPreampGain()));
+ nilusHelper.AddAnyElement(params.getAny(), "ADCp-p", String.format("%3.2fV", daqParams.getVoltsPeak2Peak()));
+ Preamplifier preamp = daqParams.preamplifier;
+ if (preamp != null) {
+ nilusHelper.AddAnyElement(params.getAny(), "ADCAmplifier", String.format("%3.2fdB", preamp.getGain()));
+ }
+ } catch (JAXBException e) {
+ e.printStackTrace();
+ } catch (ParserConfigurationException e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * Format the data in the dd MMMM yyyy format
+ * @param timeInMillis time in milliseconds
+ * @return formatted string.
+ */
+ public static String formatDate(long timeInMillis) {
+ Calendar c = Calendar.getInstance();
+ c.setTimeInMillis(timeInMillis);
+ c.setTimeZone(PamCalendar.defaultTimeZone);
+ DateFormat df = new SimpleDateFormat("yyMMdd");
+ df.setTimeZone(PamCalendar.defaultTimeZone);
+ Date d = c.getTime();
+ return df.format(d);
+ }
+
+
+ /**
+ * Get a name for the document, which is a bit like the id within
+ * the document, but also contain a yymmdd data string.
+ * @param calDoc
+ * @param i channel
+ * @return document name
+ */
+ private String createDocumentName(Calibration calDoc, int iChan) {
+ long docDate = System.currentTimeMillis();
+ XMLGregorianCalendar date = calDoc.getMetadataInfo().getDate();
+ if (date != null) {
+ docDate = TethysTimeFuncs.millisFromGregorianXML(date);
+ }
+ String dateStr = formatDate(docDate);
+ String name = String.format("%s_%s_ch%d", createCalibrationDocumentRoot(), dateStr, iChan);
+ return name;
+ }
+
+ /**
+ * Get a start of name for a calibration document. This will be used in the document name
+ * with a date and a channel, and the document Id just of the root and the channel.
+ * @return root string for document names and document id's.
+ */
+ public String createCalibrationDocumentRoot() {
+ PamArray array = ArrayManager.getArrayManager().getCurrentArray();
+ if (array == null) {
+ return null;
+ }
+ String root = String.format("%s %s", array.getInstrumentType(), array.getInstrumentId());
+ root = root.replace(" ", "_");
+ return root;
+ }
+
+ /**
+ * Create a calibration document for a single hydrophone channel.
+ * @param pDeployment deployment, for cross referencing.
+ * @param channelIndex channel id. One document per channel for a multi hydrophone array.
+ * @return Calibration document.
+ */
+ public Calibration createCalibrationDocument(int channelIndex) {
+ AcquisitionControl daqControl = (AcquisitionControl) PamController.getInstance().findControlledUnit(AcquisitionControl.unitType);
+ return createCalibrationDocument(daqControl, channelIndex);
+ }
+
+ /**
+ * Create a calibration document for a single hydrophone channel.
+ * @param pDeployment deployment, for cross referencing.
+ * @param soundAcquisition Daq information - needed to get the ADC calibration information.
+ * @param channelIndex channel id. One document per channel for a multi hydrophone array.
+ * @return Calibration document.
+ */
+ public Calibration createCalibrationDocument(AcquisitionControl soundAcquisition, int channelIndex) {
+ /**
+ * Calibrations document id and cross referencing to Deploymnet documents:
+ * Identifier of instrument, preamplifier, or hydrophone.
+ * Corresponds to elements in Deployment:
+ * Deployment/Instrument/Id,
+ * Deployment/Sensors/Audio/HydrophoneId,
+ * Deployment/Sensors/Audio[i]/PreampId.
+ * As instruments may be calibrated multiple times, it is not an error for duplicate Id values to appear.
+ * It is recommended that the three different types of identifiers (instrument, hydrophone, preamp) be distinct,
+ * but the Type element may be used to distinguish them if they are not.
+ */
+
+ /*
+ * very remote possibility that DAQ doesn't exist. What to do in this case ? It's also possible that some configurations may
+ * have to have >1 DAQ's ?
+ */
+ PamArray array = ArrayManager.getArrayManager().getCurrentArray();
+ if (array == null) {
+ return null;
+ }
+ if (channelIndex < 0 || channelIndex >= array.getHydrophoneCount()) {
+ return null;
+ }
+// ArrayManager.getArrayManager().get
+// hydrophones = array.
+ Hydrophone hydrophone = array.getHydrophoneArray().get(channelIndex);
+ double hSens = hydrophone.getSensitivity();
+ double preampGain = hydrophone.getPreampGain();
+
+ GlobalMediumManager mediumManager = PamController.getInstance().getGlobalMediumManager();
+ SoundMedium currentMedium = mediumManager.getCurrentMedium();
+ double dbRef = GlobalMedium.getdBreference(currentMedium); // probably in Pa, so multiply by 1e6. 20 (air) or 0 (water)
+
+ /**
+ * The calibration id can be a bit tricky, it will need to be cross referenced from the
+ * Deployment document, and it is likely that a deployment document will have to reference several
+ * calibration documents for different channels.
+ * Make the name from the Array name (new), the array Instrument Id (unique to the array)
+ * and the channel number. These will then all have to go into the Deployment document in
+ * the list of audio devices, cross referenced as the SensorId field.
+ *
+ */
+
+ Calibration calibration = new Calibration();
+
+ try {
+ Helper.createRequiredElements(calibration);
+ } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) {
+ e.printStackTrace();
+ }
+ String id = getHydrophoneId(channelIndex);
+// id = String.format("%d", channelIndex);
+ calibration.setId(id);
+ calibration.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(System.currentTimeMillis()));
+// calibration.setType(GlobalMedium.getRecieverString(currentMedium, false, false));
+ calibration.setType("end-to-end");
+ calibration.setIntensityReferenceUPa(AutoTethysProvider.roundSignificantFigures(dbRef*1e6,3));
+// String sensRef = GlobalMedium.getdBRefString(currentMedium);
+ // it doesn't like this since it has a unicode character. Leave it or change the micro to 'u'
+// calibration.setSensitivityReference(sensRef);
+ calibration.setSensitivityDBV(hSens+preampGain);
+ if (soundAcquisition != null) {
+ AcquisitionProcess daqProcess = soundAcquisition.getAcquisitionProcess();
+ double fullScale = daqProcess.rawAmplitude2dB(1, channelIndex, false);
+ calibration.setSensitivityDBFS(fullScale);
+ }
+ FrequencyResponse frs = calibration.getFrequencyResponse();
+ List hz = frs.getHz();
+ List db = frs.getDB();
+ hz.add(Double.valueOf(0));
+ db.add(Double.valueOf(hSens+preampGain));
+
+ MetadataInfo metaInf = calibration.getMetadataInfo();
+ if (metaInf == null) {
+ metaInf = new MetadataInfo();
+ calibration.setMetadataInfo(metaInf);
+ }
+ metaInf.setDate(TethysTimeFuncs.xmlGregCalFromMillis(System.currentTimeMillis()));
+ metaInf.setUpdateFrequency("as-needed");
+ ResponsibleParty contact = metaInf.getContact();
+ if (contact == null) {
+ contact = new ResponsibleParty();
+ metaInf.setContact(contact);
+ }
+ contact.setIndividualName("Unknown");
+ contact.setOrganizationName("unknown");
+
+ QualityAssurance qa = calibration.getQualityAssurance();
+ if (qa == null) {
+ qa = new QualityAssurance();
+ calibration.setQualityAssurance(qa);
+ }
+ qa.setQuality(QualityValueBasic.VALID);
+ qa.setComment("Unknown calibration");
+
+
+ return calibration;
+ }
+
+ /**
+ * See if a document already exists. This should only occur if you
+ * try to export the same document twice with the same calibration date.
+ * @param documentName
+ * @return true if a document already exists.
+ */
+ public boolean calDocumentExists(String documentName) {
+ if (calibrationsList == null) {
+ return false;
+ }
+ for (int i = 0; i < calibrationsList.size(); i++) {
+ if (calibrationsList.get(i).getDocumentName().equalsIgnoreCase(documentName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Return if we have at least one document for every channel.
+ * @return true if all cal documents exist.
+ */
+ public boolean haveAllChannelCalibrations() {
+ PamArray array = ArrayManager.getArrayManager().getCurrentArray();
+ int nPhone = array.getHydrophoneCount();
+ for (int i = 0; i < nPhone; i++) {
+ if (haveChannelCalibration(i) == false) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Find whether we have a document for this instrument and channel.
+ * @param iChan
+ * @return true if we have an appropriate doc.
+ */
+ public boolean haveChannelCalibration(int iChan) {
+ if (calibrationsList == null) {
+ return false;
+ }
+ String seachPattern = makeChannelNamePart(iChan);
+ for (int i = 0; i < calibrationsList.size(); i++) {
+ String docName = calibrationsList.get(i).getDocumentName();
+ if (docName.endsWith(seachPattern)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get an id based on the instrument identifiers and channel number.
+ * This is the internal id of the document, not the document name which
+ * includes an additional date part in the name.
+ * @param channelIndex
+ * @return id string - instrument type + instrument id + channel
+ */
+ public String getHydrophoneId(int channelIndex) {
+ PamArray array = ArrayManager.getArrayManager().getCurrentArray();
+ if (array == null) {
+ return null;
+ }
+ String id = String.format("%s_%s", createCalibrationDocumentRoot(), makeChannelNamePart(channelIndex));
+ id = id.replace(" ", "_");
+ return id;
+ }
+
+ /**
+ * Make the final part of the document name / id which is the channel number.
+ * @param channelIndex channel index
+ * @return string in the form ch%02d (e.g. ch03)
+ */
+ public String makeChannelNamePart(int channelIndex) {
+ return String.format("ch%02d", channelIndex);
+ }
+
+ /**
+ * @return the calibrationDataBlock
+ */
+ public ArrayList> getCalibrationDataList() {
+ return calibrationsList;
+ }
+
+ /**
+ * Make a list of document names associated with this instrument.
+ * @return list of calibration documents using this instrument, based on the start of the document name.
+ */
+ private ArrayList getArrayCalibrations() {
+ ArrayList allCals = null;
+ try {
+ allCals = tethysControl.getDbxmlQueries().getCollectionDocumentList(Collection.Calibrations);
+ }
+ catch (Exception e) {
+
+ }
+ if (allCals == null) {
+ return null;
+ }
+ String prefix = createCalibrationDocumentRoot(); // find doc names that have that root.
+ ArrayList theseCals = new ArrayList<>();
+ for (DocumentInfo aDoc : allCals) {
+ if (aDoc.getDocumentName().startsWith(prefix)) {
+ theseCals.add(aDoc);
+ }
+ }
+ return theseCals;
+ }
+}
diff --git a/src/tethys/calibration/swing/CalibrationProcessCard.java b/src/tethys/calibration/swing/CalibrationProcessCard.java
new file mode 100644
index 00000000..30e37ba7
--- /dev/null
+++ b/src/tethys/calibration/swing/CalibrationProcessCard.java
@@ -0,0 +1,170 @@
+package tethys.calibration.swing;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.List;
+
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.border.TitledBorder;
+
+import PamView.dialog.PamGridBagContraints;
+import PamView.panel.WestAlignedPanel;
+import PamView.wizard.PamWizard;
+import nilus.AlgorithmType;
+import nilus.AlgorithmType.Parameters;
+import nilus.AlgorithmType.SupportSoftware;
+import nilus.Calibration;
+import nilus.Calibration.QualityAssurance;
+import nilus.QualityValueBasic;
+import tethys.calibration.CalibrationHandler;
+
+public class CalibrationProcessCard extends CalibrationsCard {
+
+ private JPanel processPanel;
+
+ private JComboBox calMethod;
+
+ private JTextArea software;
+
+ private JTextField version;
+
+ private JComboBox qaQuality;
+
+ private JTextField qaComment;
+
+ public CalibrationProcessCard(PamWizard pamWizard) {
+ super(pamWizard, "Calibration Process");
+ this.setLayout(new BorderLayout());
+ processPanel = new JPanel(new GridBagLayout());
+ WestAlignedPanel wp;
+ this.add(BorderLayout.NORTH, wp = new WestAlignedPanel(processPanel));
+ wp.setBorder(new TitledBorder("Calibration Process"));
+
+ GridBagConstraints c = new PamGridBagContraints();
+
+ calMethod = new JComboBox();
+ String[] meths = CalibrationHandler.calibrationMethods;
+ for (int i = 0; i < meths.length; i++) {
+ calMethod.addItem(meths[i]);
+ }
+
+ qaQuality = new JComboBox<>();
+ String[] vals = CalibrationHandler.qaTypes;
+ for (int i = 0; i < vals.length; i++) {
+ qaQuality.addItem(vals[i]);
+ }
+
+ software = new JTextArea(5, 25);
+ software.setLineWrap(true);
+ software.setWrapStyleWord(true);
+ software.setToolTipText("Details of calibration method and software used");
+
+ version = new JTextField(20);
+ version.setToolTipText("Serial number of calibration device");
+
+ qaComment = new JTextField(20);
+ qaComment.setToolTipText("Comment on calibration quality");
+
+ processPanel.add(new JLabel("Method ", JLabel.RIGHT), c);
+ c.gridx++;
+ processPanel.add(calMethod, c);
+ c.gridx = 0;
+ c.gridy++;
+ c.gridwidth = 1;
+ processPanel.add(new JLabel("Serial number ", JLabel.RIGHT), c);
+ c.gridx++;
+ c.gridwidth = 2;
+ processPanel.add(version, c);
+ c.gridx = 0;
+ c.gridy++;
+ c.gridwidth = 1;
+ processPanel.add(new JLabel("Quality ", JLabel.RIGHT), c);
+ c.gridx++;
+ processPanel.add(qaQuality, c);
+ c.gridx = 0;
+ c.gridy++;
+ processPanel.add(new JLabel("QA Comment ", JLabel.RIGHT), c);
+ c.gridx++;
+ c.gridwidth = 2;
+ processPanel.add(qaComment, c);
+
+ this.add(BorderLayout.CENTER, makeScrollablePanel(software, "Calibration method"));
+
+ }
+
+ private JScrollPane makeScrollablePanel(JTextArea textArea, String title) {
+ // TODO Auto-generated method stub
+// mainPanel.add(new Label(title, JLabel.LEFT));
+// textArea.setMinimumSize(new Dimension(200, 200));
+ JScrollPane scrollPane = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ scrollPane.setBorder(new TitledBorder(title));
+ scrollPane.setPreferredSize(new Dimension(scrollPane.getPreferredSize().height/2, 0));
+ return scrollPane;
+ }
+
+
+ @Override
+ public boolean getParams(Calibration calibration) {
+ if (calibration == null) {
+ return false;
+ }
+ AlgorithmType process = calibration.getProcess();
+ if (process == null) {
+ process = new AlgorithmType();
+ calibration.setProcess(process);
+ }
+ process.setMethod((String) calMethod.getSelectedItem());
+ process.setVersion(version.getText());
+ process.setSoftware(software.getText());
+ if (software.getText() == null) {
+ getPamWizard().showWarning("You must specify the calibratin method used");
+ }
+
+ QualityAssurance qa = calibration.getQualityAssurance();
+ if (qa == null) {
+ qa = new QualityAssurance();
+ calibration.setQualityAssurance(qa);
+ }
+ qa.setComment(qaComment.getText());
+ qa.setQuality(QualityValueBasic.fromValue((String) qaQuality.getSelectedItem()));
+
+ // need to add a few fixed things for this to work...
+// List supportSoftware = process.getSupportSoftware();
+ Parameters params = process.getParameters();
+ if (params == null) {
+ params = new Parameters();
+ process.setParameters(params);
+ }
+
+ return true;
+ }
+
+ @Override
+ public void setParams(Calibration calibration) {
+ if (calibration == null) {
+ return;
+ }
+ AlgorithmType process = calibration.getProcess();
+ if (process != null) {
+ calMethod.setSelectedItem(process.getMethod());
+ version.setText(process.getVersion());
+ software.setText(process.getSoftware());
+ }
+ QualityAssurance qa = calibration.getQualityAssurance();
+ if (qa != null) {
+ QualityValueBasic qb = qa.getQuality();
+ if (qb != null) {
+ qaQuality.setSelectedItem(qb.value());
+ }
+ qaComment.setText(qa.getComment());
+ }
+ }
+}
diff --git a/src/tethys/calibration/swing/CalibrationsCard.java b/src/tethys/calibration/swing/CalibrationsCard.java
new file mode 100644
index 00000000..b97221d3
--- /dev/null
+++ b/src/tethys/calibration/swing/CalibrationsCard.java
@@ -0,0 +1,13 @@
+package tethys.calibration.swing;
+
+import PamView.wizard.PamWizard;
+import PamView.wizard.PamWizardCard;
+import nilus.Calibration;
+
+abstract public class CalibrationsCard extends PamWizardCard {
+
+ public CalibrationsCard(PamWizard pamWizard, String title) {
+ super(pamWizard, title);
+ }
+
+}
diff --git a/src/tethys/calibration/swing/CalibrationsContactCard.java b/src/tethys/calibration/swing/CalibrationsContactCard.java
new file mode 100644
index 00000000..3adc9f33
--- /dev/null
+++ b/src/tethys/calibration/swing/CalibrationsContactCard.java
@@ -0,0 +1,198 @@
+package tethys.calibration.swing;
+
+import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Date;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.border.TitledBorder;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.jdesktop.swingx.JXDatePicker;
+
+import PamView.dialog.PamDialog;
+import PamView.dialog.PamGridBagContraints;
+import PamView.panel.WestAlignedPanel;
+import PamView.wizard.PamWizard;
+import nilus.Calibration;
+import nilus.ContactInfo;
+import nilus.MetadataInfo;
+import nilus.ResponsibleParty;
+import tethys.TethysTimeFuncs;
+import tethys.calibration.CalibrationHandler;
+import tethys.swing.export.ResponsiblePartyPanel;
+
+public class CalibrationsContactCard extends CalibrationsCard {
+
+ private JXDatePicker datePicker;
+
+ private ResponsiblePartyPanel calibrator, dataManager;
+
+ private JComboBox updateInterval;
+
+ private MetadataInfo metaData;
+
+ private JButton copyDown, copyUp;
+
+ public CalibrationsContactCard(PamWizard pamWizard) {
+ super(pamWizard, "Contact Details");
+ // TODO Auto-generated constructor stub
+// setBorder(new TitledBorder("Contact"));
+ setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+
+ updateInterval = new JComboBox<>();
+ String[] vals = CalibrationHandler.updateOptions;
+ for (int i = 0; i < vals.length; i++) {
+ updateInterval.addItem(vals[i]);
+ }
+
+ JPanel datePanel = new JPanel(new GridBagLayout());
+ JPanel lp = new WestAlignedPanel(datePanel);
+ lp.setBorder(new TitledBorder("Calibration date"));
+ 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++;
+ datePanel.add(updateInterval, c);
+
+ calibrator = new ResponsiblePartyPanel("Technical Person");
+ dataManager = new ResponsiblePartyPanel("Data Manager");
+
+ JPanel copyPanel = new JPanel(new GridBagLayout());
+ c = new PamGridBagContraints();
+ copyPanel.add(copyDown = new JButton("Copy down"),c);
+ c.gridx++;
+ copyPanel.add(copyUp = new JButton("Copy up"), c);
+
+ add(lp);
+ add(calibrator.getMainPanel());
+ add(copyPanel);
+ add(dataManager.getMainPanel());
+
+ copyDown.setToolTipText("Copy technical person to data manager");
+ copyUp.setToolTipText("Copy data manager to technical person");
+ copyDown.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ copyRPDown();
+ }
+ });
+ copyUp.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ copyRPUp();
+ }
+
+ });
+ }
+
+ protected void copyRPDown() {
+ copyRPData(calibrator, dataManager);
+ }
+ private void copyRPUp() {
+ copyRPData(dataManager, calibrator);
+ }
+
+ private void copyRPData(ResponsiblePartyPanel rFrom, ResponsiblePartyPanel rTo) {
+ ResponsibleParty rp = checkRPChildren(null);
+ rFrom.getParams(rp);
+ rTo.setParams(rp);
+ }
+
+ @Override
+ public boolean getParams(Calibration cardParams) {
+ ResponsibleParty rp = checkRPChildren(cardParams.getResponsibleParty());
+ cardParams.setResponsibleParty(rp);
+ calibrator.getParams(rp);
+
+ metaData = cardParams.getMetadataInfo();
+ if (metaData == null) {
+ metaData = new MetadataInfo();
+ cardParams.setMetadataInfo(metaData);
+ }
+ metaData.setContact(checkRPChildren(metaData.getContact()));
+ dataManager.getParams(metaData.getContact());
+
+ metaData.setUpdateFrequency((String) updateInterval.getSelectedItem());
+ metaData.setDate(TethysTimeFuncs.xmlGregCalFromMillis(System.currentTimeMillis()));
+
+ Date date = datePicker.getDate();
+ if (date == null) {
+ return getPamWizard().showWarning("You must specify the data of the calibration");
+ }
+ long millis = date.getTime();
+ cardParams.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(millis));
+
+ return true;
+ }
+
+ private ResponsibleParty checkRPChildren(ResponsibleParty rp) {
+ if (rp == null) {
+ rp = new ResponsibleParty();
+ }
+ if (rp.getContactInfo() == null) {
+ rp.setContactInfo(new ContactInfo());
+ }
+ if (rp.getContactInfo().getAddress() == null) {
+// rp.getContactInfo().setAddress(new Address());
+ }
+ return rp;
+ }
+
+ private ResponsibleParty findResponsibleParty(Calibration cal) {
+ if (cal == null) {
+ return null;
+ }
+ MetadataInfo metaInfo = cal.getMetadataInfo();
+ if (metaInfo != null) {
+ ResponsibleParty resp = metaInfo.getContact();
+ if (resp != null && resp.getIndividualName() != null) {
+ return resp;
+ }
+ }
+ return cal.getResponsibleParty();
+
+ }
+
+ @Override
+ public void setParams(Calibration cardParams) {
+ // fill in as much as possible from the existing Calibration
+ ResponsibleParty resp = cardParams.getResponsibleParty();
+ if (resp != null) {
+ calibrator.setParams(resp);
+ }
+
+ MetadataInfo metaInf = cardParams.getMetadataInfo();
+ if (metaInf != null) {
+ resp = metaInf.getContact();
+ if (resp != null) {
+ dataManager.getParams(resp);
+ }
+ String uf = metaInf.getUpdateFrequency();
+ if (uf != null) {
+ updateInterval.setSelectedItem(uf);
+ }
+ }
+
+ XMLGregorianCalendar ts = cardParams.getTimeStamp();
+ if (ts != null) {
+ datePicker.setDate(new Date(TethysTimeFuncs.millisFromGregorianXML(ts)));
+ }
+
+
+ }
+
+}
diff --git a/src/tethys/calibration/swing/CalibrationsExportWizard.java b/src/tethys/calibration/swing/CalibrationsExportWizard.java
new file mode 100644
index 00000000..74bb356a
--- /dev/null
+++ b/src/tethys/calibration/swing/CalibrationsExportWizard.java
@@ -0,0 +1,42 @@
+package tethys.calibration.swing;
+
+import java.awt.Window;
+
+import PamView.wizard.PamWizard;
+import PamView.wizard.PamWizardCard;
+import nilus.Calibration;
+
+public class CalibrationsExportWizard extends PamWizard {
+
+ private Calibration sampleDocument;
+
+ private CalibrationsExportWizard(Window parentFrame, Calibration sampleDocument) {
+ super(parentFrame, "Calibrations Export");
+ this.sampleDocument = sampleDocument;
+ addCard(new CalibrationProcessCard(this));
+ addCard(new CalibrationsContactCard(this));
+ }
+
+ public static Calibration showWizard(Window parentFrame, Calibration sampleDocument) {
+ CalibrationsExportWizard wiz = new CalibrationsExportWizard(parentFrame, sampleDocument);
+ wiz.setParams();
+ wiz.setVisible(true);
+ return wiz.sampleDocument;
+ }
+
+ @Override
+ public void setCardParams(PamWizardCard wizardCard) {
+ wizardCard.setParams(sampleDocument);
+ }
+
+ @Override
+ public boolean getCardParams(PamWizardCard wizardCard) {
+ return wizardCard.getParams(sampleDocument);
+ }
+
+ @Override
+ public void cancelButtonPressed() {
+ sampleDocument = null;
+ }
+
+}
diff --git a/src/tethys/calibration/swing/CalibrationsMainPanel.java b/src/tethys/calibration/swing/CalibrationsMainPanel.java
new file mode 100644
index 00000000..385ca9ef
--- /dev/null
+++ b/src/tethys/calibration/swing/CalibrationsMainPanel.java
@@ -0,0 +1,66 @@
+package tethys.calibration.swing;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.border.TitledBorder;
+
+
+import PamView.panel.PamPanel;
+import tethys.TethysControl;
+import tethys.calibration.CalibrationHandler;
+import tethys.swing.TethysGUIPanel;
+
+public class CalibrationsMainPanel extends TethysGUIPanel {
+
+ private CalibrationHandler calibrationHandler;
+
+ private CalibrationsTable calibrationsTable;
+
+ private JPanel mainPanel;
+
+ private JPanel ctrlPanel;
+
+ private JButton exportButton;
+
+ private JLabel warning;
+
+ public CalibrationsMainPanel(TethysControl tethysControl, CalibrationHandler calibrationHandler) {
+ super(tethysControl);
+ this.calibrationHandler = calibrationHandler;
+ 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;
+ }
+
+}
diff --git a/src/tethys/calibration/swing/CalibrationsTable.java b/src/tethys/calibration/swing/CalibrationsTable.java
new file mode 100644
index 00000000..45b91f18
--- /dev/null
+++ b/src/tethys/calibration/swing/CalibrationsTable.java
@@ -0,0 +1,285 @@
+package tethys.calibration.swing;
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+import javax.swing.JComponent;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.border.TitledBorder;
+import javax.swing.table.AbstractTableModel;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import PamController.PamController;
+import PamController.soundMedium.GlobalMedium;
+import PamController.soundMedium.GlobalMediumManager;
+import PamUtils.PamCalendar;
+import PamView.dialog.warn.WarnOnce;
+import PamView.panel.PamPanel;
+import PamView.tables.SwingTableColumnWidths;
+import nilus.Calibration;
+import tethys.Collection;
+import tethys.DocumentNilusObject;
+import tethys.TethysControl;
+import tethys.TethysState;
+import tethys.TethysState.StateType;
+import tethys.TethysTimeFuncs;
+import tethys.calibration.CalibrationHandler;
+import tethys.dbxml.TethysException;
+import tethys.swing.TethysGUIPanel;
+
+public class CalibrationsTable extends TethysGUIPanel {
+
+ private CalibrationHandler calibrationHandler;
+
+ private CalibrationsTableModel calTableModel;
+
+ private JPanel mainPanel;
+
+ private JTable calTable;
+
+ private TethysControl tethysControl;
+
+ /**
+ * @param calibrationHandler
+ */
+ public CalibrationsTable(TethysControl tethysControl, CalibrationHandler calibrationHandler) {
+ super(tethysControl);
+ this.tethysControl = tethysControl;
+ this.calibrationHandler = calibrationHandler;
+ calTableModel = new CalibrationsTableModel();
+ calTable = new JTable(calTableModel);
+ calTable.setRowSelectionAllowed(true);
+ calTable.addMouseListener(new TableMouse());
+
+ JScrollPane scrollPane = new JScrollPane(calTable);
+
+ mainPanel = new PamPanel(new BorderLayout());
+ mainPanel.add(BorderLayout.CENTER, scrollPane);
+
+ calTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+ new SwingTableColumnWidths(tethysControl.getUnitName()+"CalibrationsTable", calTable);
+
+ }
+
+
+ @Override
+ public JComponent getComponent() {
+ return mainPanel;
+ }
+
+
+ @Override
+ public void updateState(TethysState tethysState) {
+ super.updateState(tethysState);
+ calTableModel.fireTableDataChanged();
+ }
+
+ private class TableMouse extends MouseAdapter {
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ if (e.isPopupTrigger()) {
+ showPopupMenu(e);
+ }
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ if (e.isPopupTrigger()) {
+ showPopupMenu(e);
+ }
+ }
+
+ }
+
+ public void showPopupMenu(MouseEvent e) {
+ int[] rows = calTable.getSelectedRows();
+ if (rows == null || rows.length == 0) {
+ return;
+ }
+ int n = rows.length;
+ DocumentNilusObject doc = calibrationHandler.getCalibrationDataList().get(rows[0]);
+
+ JPopupMenu popMenu = new JPopupMenu();
+ JMenuItem menuItem;
+ if (n == 1) {
+ menuItem = new JMenuItem("Show document " + doc.getDocumentName());
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ showCalibration(doc);
+ }
+ });
+ popMenu.add(menuItem);
+ }
+ if (n > 1) {
+ menuItem = new JMenuItem("Delete selected documents");
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ deleteCalibrations(rows);
+ }
+ });
+ popMenu.add(menuItem);
+ }
+ else {
+ menuItem = new JMenuItem("Delete document " + doc.getDocumentName());
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ deleteCalibration(doc);
+ }
+ });
+ popMenu.add(menuItem);
+ }
+ popMenu.show(e.getComponent(), e.getX(), e.getY());
+ }
+
+ protected void deleteCalibration(DocumentNilusObject doc) {
+ String docName = doc.getDocumentName();
+ int ans = WarnOnce.showNamedWarning("delete doc " + Collection.Calibrations.collectionName(),
+ PamController.getMainFrame(), "Delete document",
+ "Are you sure you want to delete the document " + docName, WarnOnce.OK_CANCEL_OPTION);
+ if (ans == WarnOnce.OK_OPTION) {
+ try {
+ tethysControl.getDbxmlConnect().removeDocument(Collection.Calibrations.collectionName(), docName);
+ } catch (TethysException e) {
+ System.out.println("Failed to delete " + docName);
+ System.out.println(e.getMessage());
+ }
+ }
+ updateEverything();
+ calTableModel.fireTableDataChanged();
+ }
+
+
+ protected void showCalibration(DocumentNilusObject docInfo) {
+ tethysControl.displayDocument(docInfo);
+
+ }
+
+
+ protected void deleteCalibrations(int[] rows) {
+ String msg = String.format("Are you sure you want to delete %d calibrations documents ?", rows.length);
+ int ans = WarnOnce.showNamedWarning("Deletemanycalibrations", PamController.getMainFrame(), "Delete multiple documents", msg, WarnOnce.OK_CANCEL_OPTION);
+ if (ans != WarnOnce.OK_OPTION) {
+ return;
+ }
+ for (int i = 0; i < rows.length; i++) {
+ String docName = null;
+ try {
+ DocumentNilusObject doc = calibrationHandler.getCalibrationDataList().get(rows[i]);
+ docName = doc.getDocumentName();
+ tethysControl.getDbxmlConnect().removeDocument(Collection.Calibrations, docName);
+ } catch (TethysException e) {
+ System.out.println("Failed to delete " + docName);
+ System.out.println(e.getMessage());
+ }
+ }
+
+ updateEverything();
+
+ }
+
+ private void updateEverything() {
+ getTethysControl().sendStateUpdate(new TethysState(StateType.DELETEDATA, Collection.Calibrations));
+ }
+
+ class CalibrationsTableModel extends AbstractTableModel {
+
+ private static final long serialVersionUID = 1L;
+
+ private String[] columnNames = {"Document", "Id", "Date", "End to End", "Hydrophone"};
+
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ DocumentNilusObject dataUnit = null;
+ try {
+ dataUnit = calibrationHandler.getCalibrationDataList().get(rowIndex);
+ }
+ catch (Exception e) {
+ return null;
+ }
+ if (dataUnit == null) {
+ return null;
+ }
+ Calibration cal = dataUnit.getNilusObject();
+ switch (columnIndex) {
+ case 0:
+ return dataUnit.getDocumentName();
+ case 1:
+ return cal.getId();
+ case 2:
+ XMLGregorianCalendar ts = cal.getTimeStamp();
+ if (ts == null) {
+ return null;
+ }
+ long ms = TethysTimeFuncs.millisFromGregorianXML(ts);
+ return PamCalendar.formatDBDate(ms);
+ case 3:
+ return getFSString(cal);
+ case 4:
+ return getPhoneString(cal);
+// return String.format("%3.1fdB %s", cal.getSensitivityV(), cal.getType());
+ }
+ return null;
+ }
+
+ @Override
+ public int getRowCount() {
+ return calibrationHandler.getCalibrationDataList().size();
+ }
+
+ @Override
+ public int getColumnCount() {
+ return columnNames.length;
+ }
+
+ @Override
+ public String getColumnName(int column) {
+ if (column == 4) {
+ return PamController.getInstance().getGlobalMediumManager().getRecieverString();
+ }
+ else {
+ return columnNames[column];
+ }
+ }
+ }
+
+ public String getFSString(Calibration cal) {
+ Double fs = cal.getSensitivityDBFS();
+ if (fs == null) {
+ return null;
+ }
+ double ir = cal.getIntensityReferenceUPa();
+ String str = String.format("%3.1fdB", fs);
+ if (ir != 0) {
+ str += String.format(" re%.0f\u00B5Pa", ir);
+ }
+ return str;
+ }
+
+ public Object getPhoneString(Calibration cal) {
+ Double dbV = cal.getSensitivityV();
+ if (dbV == null) {
+ dbV = cal.getSensitivityDBV();
+ }
+ if (dbV == null) {
+ return null;
+ }
+ double ir = cal.getIntensityReferenceUPa();
+ String str = String.format("%3.1fdB", dbV);
+ if (ir != 0) {
+ str += String.format(" re%.0fV/\u00B5Pa", ir);
+ }
+ return str;
+ }
+}
diff --git a/src/tethys/database/TethysActions.java b/src/tethys/database/TethysActions.java
new file mode 100644
index 00000000..0c9ece36
--- /dev/null
+++ b/src/tethys/database/TethysActions.java
@@ -0,0 +1,27 @@
+package tethys.database;
+
+/**
+ * Possible document actions
+ * @author dg50
+ *
+ */
+public enum TethysActions {
+
+ ADDDOCUMENT, DELETEDOCUMENT, UPDATEDOCUMENT;
+
+// @Override
+// public String toString() {
+// switch (this) {
+// case ADDDOCUMENT:
+// return "Add document";
+// case DELETEDOCUMENT:
+// return "Delete document";
+// case UPDATEDOCUMENT:
+// return "Update document";
+// default:
+// return null;
+// }
+// }
+
+
+}
diff --git a/src/tethys/database/TethysLogDataBlock.java b/src/tethys/database/TethysLogDataBlock.java
new file mode 100644
index 00000000..7a3639d6
--- /dev/null
+++ b/src/tethys/database/TethysLogDataBlock.java
@@ -0,0 +1,16 @@
+package tethys.database;
+
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamProcess;
+import tethys.TethysControl;
+
+public class TethysLogDataBlock extends PamDataBlock {
+
+ private TethysControl tethysControl;
+
+ public TethysLogDataBlock(TethysControl tethysControl) {
+ super(TethysLogDataUnit.class, "Tethys Log", null, 0);
+ this.tethysControl = tethysControl;
+ }
+
+}
diff --git a/src/tethys/database/TethysLogDataUnit.java b/src/tethys/database/TethysLogDataUnit.java
new file mode 100644
index 00000000..e1998c2b
--- /dev/null
+++ b/src/tethys/database/TethysLogDataUnit.java
@@ -0,0 +1,59 @@
+package tethys.database;
+
+import PamguardMVC.PamDataUnit;
+
+public class TethysLogDataUnit extends PamDataUnit {
+
+ private String collection;
+ private String documentId;
+ private TethysActions action;
+ private String comment;
+ private boolean success;
+
+ public TethysLogDataUnit(long timeMilliseconds, String collection, String documentId, TethysActions action, boolean success, String comment) {
+ super(timeMilliseconds);
+ this.collection = collection;
+ this.documentId = documentId;
+ this.action = action;
+ this.success = success;
+ this.comment = comment;
+
+ }
+
+ /**
+ * @return the collection
+ */
+ public String getCollection() {
+ return collection;
+ }
+
+ /**
+ * @return the documentId
+ */
+ public String getDocumentId() {
+ return documentId;
+ }
+
+ /**
+ * @return the action
+ */
+ public TethysActions getAction() {
+ return action;
+ }
+
+ /**
+ * @return the comment
+ */
+ public String getComment() {
+ return comment;
+ }
+
+ /**
+ * @return the success
+ */
+ public boolean isSuccess() {
+ return success;
+ }
+
+
+}
diff --git a/src/tethys/database/TethysLogger.java b/src/tethys/database/TethysLogger.java
new file mode 100644
index 00000000..9e7ae2ad
--- /dev/null
+++ b/src/tethys/database/TethysLogger.java
@@ -0,0 +1,128 @@
+package tethys.database;
+
+import java.sql.Types;
+
+import PamguardMVC.PamDataUnit;
+import generalDatabase.DBControlUnit;
+import generalDatabase.DBProcess;
+import generalDatabase.PamConnection;
+import generalDatabase.PamTableDefinition;
+import generalDatabase.PamTableItem;
+import generalDatabase.SQLLogging;
+import generalDatabase.SQLTypes;
+import tethys.TethysControl;
+
+/**
+ * Logging everything we put into Tethys in our own database.
+ * @author dg50
+ *
+ */
+public class TethysLogger extends SQLLogging {
+
+ private static TethysLogger tethysLogger;
+
+ private TethysControl tethysControl;
+
+ private TethysLogDataBlock logDataBlock;
+
+ private PamTableDefinition tableDefinition;
+
+ private PamTableItem collection, documentId, action, status, comment;
+
+ private boolean tableChecked = false;
+
+ private TethysLogger(TethysControl tethysControl, TethysLogDataBlock pamDataBlock) {
+ super(pamDataBlock);
+ this.tethysControl = tethysControl;
+ this.logDataBlock = pamDataBlock;
+ tableDefinition = new PamTableDefinition("TethysLog");
+ tableDefinition.addTableItem(collection = new PamTableItem("Collection", Types.VARCHAR));
+ tableDefinition.addTableItem(documentId = new PamTableItem("DocumentId", Types.VARCHAR));
+ tableDefinition.addTableItem(action = new PamTableItem("Action", Types.VARCHAR));
+ tableDefinition.addTableItem(status = new PamTableItem("Status", Types.VARCHAR));
+ tableDefinition.addTableItem(comment = new PamTableItem("Comment", Types.VARCHAR));
+ tableDefinition.setUpdatePolicy(UPDATE_POLICY_OVERWRITE);
+ setTableDefinition(tableDefinition);
+ }
+
+ public static TethysLogger getTethysLogger(TethysControl tethysControl) {
+ if (tethysLogger == null) {
+ tethysLogger = createTethysLogger(tethysControl);
+ }
+ return tethysLogger;
+ }
+
+ private boolean checkTable() {
+ if (tableChecked == true) {
+ return true;
+ }
+ if (findDBProcess() == null) {
+ return false;
+ }
+ else {
+ tableChecked = findDBProcess().checkTable(tableDefinition);
+ }
+ return tableChecked;
+ }
+
+ public boolean logAction(String collection, String documentId, TethysActions action, boolean success, String comment) {
+ PamConnection con = findDBConnection();
+ if (con == null) {
+ return false;
+ }
+ if (checkTable() == false) {
+ return false;
+ }
+
+ TethysLogDataUnit dataUnit = new TethysLogDataUnit(System.currentTimeMillis(), collection, documentId, action, success, comment);
+ return this.logData(con, dataUnit);
+ }
+
+ private PamConnection findDBConnection() {
+ return DBControlUnit.findConnection();
+ }
+
+ /**
+ * Find the database controlled unit. Must exist in viewer mode surely, but perhaps
+ * created after the Tethys module if the user is really crafty !
+ * @return the DB controlled unit.
+ */
+ private DBControlUnit findDBControl() {
+ return DBControlUnit.findDatabaseControl();
+ }
+
+ /**
+ * Fine the database process. Should exist.
+ * @return
+ */
+ private DBProcess findDBProcess() {
+ DBControlUnit dbControl = findDBControl();
+ if (dbControl == null) {
+ return null;
+ }
+ return dbControl.getDbProcess();
+ }
+
+ private static TethysLogger createTethysLogger(TethysControl tethysControl) {
+ TethysLogDataBlock datablock = new TethysLogDataBlock(tethysControl);
+ TethysLogger newLogger = new TethysLogger(tethysControl, datablock);
+ return newLogger;
+ }
+
+
+ @Override
+ public void setTableData(SQLTypes sqlTypes, PamDataUnit pamDataUnit) {
+ TethysLogDataUnit tldu = (TethysLogDataUnit) pamDataUnit;
+ collection.setValue(tldu.getCollection());
+ documentId.setValue(tldu.getDocumentId());
+ action.setValue(tldu.getAction().toString());
+ status.setValue(tldu.isSuccess() ? "Success" : "Fail");
+ comment.setValue(tldu.getComment());
+ }
+
+// public TethysLogger(TethysControl tethysControl) {
+// this.tethysControl = tethysControl;
+// }
+
+
+}
diff --git a/src/tethys/dbxml/DBQueryResult.java b/src/tethys/dbxml/DBQueryResult.java
new file mode 100644
index 00000000..80a27246
--- /dev/null
+++ b/src/tethys/dbxml/DBQueryResult.java
@@ -0,0 +1,62 @@
+package tethys.dbxml;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+public class DBQueryResult {
+
+ public long queryTimeMillis;
+
+ public String queryResult;
+
+ public String schemaPlan;
+
+ public Exception queryException;
+
+ public DBQueryResult(long queryTimeMillis, String queryResult, String schemaPlan) {
+ super();
+ this.queryTimeMillis = queryTimeMillis;
+ this.queryResult = queryResult;
+ this.schemaPlan = schemaPlan;
+ }
+
+ public DBQueryResult(long queryTimeMillis, Exception queryException) {
+ super();
+ this.queryTimeMillis = queryTimeMillis;
+ this.queryException = queryException;
+ }
+
+ /**
+ * Get the result as an XML document.
+ * @return XML document
+ * @throws ParserConfigurationException
+ * @throws SAXException
+ * @throws IOException
+ */
+ public Document getDocument() throws ParserConfigurationException, SAXException, IOException {
+ if (queryResult == null) {
+ return null;
+ }
+
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+
+ //API to obtain DOM Document instance
+ DocumentBuilder builder = null;
+
+ //Create DocumentBuilder with default configuration
+ builder = factory.newDocumentBuilder();
+
+ //Parse the content to Document object
+ Document doc = builder.parse(new InputSource(new StringReader(queryResult)));
+ return doc;
+ }
+
+}
diff --git a/src/tethys/dbxml/DBXMLConnect.java b/src/tethys/dbxml/DBXMLConnect.java
new file mode 100644
index 00000000..e13b05fd
--- /dev/null
+++ b/src/tethys/dbxml/DBXMLConnect.java
@@ -0,0 +1,546 @@
+package tethys.dbxml;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.util.ArrayList;
+
+import javax.xml.bind.JAXBException;
+
+import dbxml.JerseyClient;
+import dbxml.Queries;
+import dbxml.uploader.Importer;
+import nilus.MarshalXML;
+import tethys.Collection;
+import tethys.TethysControl;
+import tethys.database.TethysActions;
+import tethys.database.TethysLogger;
+import tethys.output.TethysExportParams;
+
+/**
+ * Class containing functions for managing the database connection. Opening, closing,
+ * writing, keeping track of performance, etc.
+ * @author Doug Gillespie, Katie O'Laughlin
+ *
+ */
+public class DBXMLConnect {
+
+ private TethysControl tethysControl;
+ private File tempDirectory;
+
+ private JerseyClient jerseyClient;
+
+ private Queries queries;
+
+ private String currentSiteURL;
+
+// public static String[] collections = {"Deployments", "Detections", "Localizations", "Calibrations", "SpeciesAbbreviations"};
+
+ public DBXMLConnect(TethysControl tethysControl) {
+ this.tethysControl = tethysControl;
+
+ checkTempFolder();
+ }
+
+ /**
+ * Check the jersey client and the queries. Need to recreate
+ * if the url has changed.
+ * @return
+ */
+ private boolean checkClient() {
+ if (jerseyClient == null || queries == null || currentSiteURL == null) {
+ return false;
+ }
+ TethysExportParams params = tethysControl.getTethysExportParams();
+ if (!currentSiteURL.equalsIgnoreCase(params.getFullServerName())) {
+ return false;
+ }
+ return true;
+ }
+
+
+ /**
+ * Get the client. The client will only be recreated if the url changes
+ * @return Jersy client
+ */
+ public synchronized JerseyClient getJerseyClient() {
+ if (!checkClient()) {
+ openConnections();
+ }
+ return jerseyClient;
+ }
+
+ /**
+ * Get the Queries object. This will only be recreated if the client changes.
+ * @return
+ */
+ public synchronized Queries getTethysQueries() {
+ if (!checkClient()) {
+ openConnections();
+ }
+ return queries;
+ }
+
+ /**
+ * Convert a nilus Object into a file
+ * @param nilusObject nilus object
+ * @param file file (should not exist)
+ * @return file (will be the same as input file)
+ * @throws TethysException
+ */
+ public File createXMLDocument(Object nilusObject, File file) throws TethysException {
+ Class objClass = nilusObject.getClass();
+ try {
+ MarshalXML marshal = new MarshalXML();
+ marshal.createInstance(objClass);
+ marshal.marshal(nilusObject, file.toString());
+ } catch(IllegalArgumentException e) {
+ throw new TethysException("IllegalArgumentException posting to Tethys: " + e.getMessage(), null);
+ } catch (IOException e) {
+ throw new TethysException("IOException posting to Tethys: " + e.getMessage(), null);
+ } catch (JAXBException e) {
+ throw new TethysException("JAXBException posting to Tethys: " + e.getMessage(), null);
+ }
+ return file;
+ }
+
+ /**
+ * Create a temporary nilus file.
+ * @param nilusObject
+ * @return
+ * @throws TethysException
+ */
+ public File createTempXMLDocument(Object nilusObject) throws TethysException {
+ String tempName = getTempFileName(nilusObject);
+ tempName = tempDirectory.getAbsolutePath() + File.separator + tempName + ".xml";
+ File tempFile = new File(tempName);
+ 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
+ * documents this is no longer the case, since a Calibration can have multiple
+ * entries on different dates, so allow it !
+ * @param nilusObject
+ * @param documentName
+ * @return
+ * @throws TethysException
+ */
+ public boolean postAndLog(Object nilusObject, String documentName) throws TethysException
+ {
+ TethysException e = null;
+ boolean success = false;
+ try {
+ success = postToTethys(nilusObject, documentName);
+ }
+ catch (TethysException ex) {
+ e = ex;
+ }
+ TethysLogger logger = TethysLogger.getTethysLogger(tethysControl);
+ Class objClass = nilusObject.getClass();
+ Collection collection = Collection.fromClass(objClass);
+ String documentId = getDocumentId(nilusObject);
+ logger.logAction(collection.collectionName(), documentId, TethysActions.ADDDOCUMENT, success, "");
+ if (e != null) {
+ throw (e);
+ }
+ 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
+ */
+ private boolean postToTethys(Object nilusObject, String documentName) throws TethysException
+ {
+ Class objClass = nilusObject.getClass();
+ Collection collection = Collection.fromClass(nilusObject.getClass());
+ TethysExportParams params = new TethysExportParams();
+ String importReturn = null;
+ if (documentName == null) {
+ documentName = getTempFileName(nilusObject);
+ }
+ documentName = tempDirectory.getAbsolutePath() + File.separator + documentName + ".xml";
+ File tempFile = new File(documentName);
+ String bodgeName = documentName;//"C:\\Users\\dg50\\AppData\\Local\\Temp\\PAMGuardTethys\\Meygen2022_10a.xml";
+ try {
+ MarshalXML marshal = new MarshalXML();
+ marshal.createInstance(objClass);
+ marshal.marshal(nilusObject, tempFile.toString());
+ // tempFile = stripXMLHeader(tempFile);
+ importReturn = Importer.ImportFiles(params.getFullServerName(), collection.collectionName(),
+ new String[] { bodgeName }, "", "", false);
+
+
+ tempFile.deleteOnExit();
+ } catch(IllegalArgumentException e) {
+ throw new TethysException("IllegalArgumentException posting to Tethys: " + e.getMessage(), null);
+ } catch (IOException e) {
+ throw new TethysException("IOException posting to Tethys: " + e.getMessage(), null);
+ } catch (JAXBException e) {
+ throw new TethysException("JAXBException posting to Tethys: " + e.getMessage(), null);
+ }
+
+ /*
+ * 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("");
+// error = !success; might be a better options.
+ if (error) {
+ throw new TethysException("Error posting to Tethys", importReturn);
+ }
+ return success;
+ }
+
+ /**
+ * Update a document within Tethys. We're assuming that a
+ * document with the same name in the same collection already
+ * exists. If it doesn't / has a different name, then use
+ * the removedocument function
+ * @param nilusDocument
+ * @return
+ * @throws TethysException
+ */
+ public boolean updateDocument(Object nilusDocument) throws TethysException {
+ deleteDocument(nilusDocument);
+ return postToTethys(nilusDocument, null);
+ }
+
+ /**
+ * Delete a nilus document from the database. The only field which
+ * needs to be populated here is the Id. The code also uses the object
+ * class to identify the correct collection.
+ * @param nilusDocument
+ * @return
+ * @throws TethysException
+ */
+ public boolean deleteDocument(Object nilusDocument) throws TethysException {
+
+ Class objClass = nilusDocument.getClass();
+ Collection collection = Collection.fromClass(objClass);
+ String docId = getDocumentId(nilusDocument);
+ String result = null;
+ try {
+ result = jerseyClient.removeDocument(collection.collectionName(), docId );
+ /**
+ * Return from a sucessful delete is something like
+ *
+ deployment = getTethysControl().getDeploymentHandler().createDeploymentDocument(freeId++, recordPeriod);
+
+ - ['ECoastNARW0']
+
+An error will throw an exception.
+ */
+ }
+ catch (Exception e) {
+// System.out.printf("Error deleting %s %s: %s\n", collection, docId, e.getMessage());
+ String msg = String.format("Error deleting %s:%s", collection, docId);
+ throw new TethysException(msg, e.getLocalizedMessage());
+ }
+ // forceFlush();
+ return true;
+ }
+
+ /**
+ * Delete a Deploymnet and any contained Detections document. Doesn't work !
+ * @param deploymentId
+ * @return
+ * @throws TethysException
+ */
+ public boolean deleteDeployment(String deploymentId) throws TethysException {
+ ArrayList detDocNames = tethysControl.getDbxmlQueries().getDetectionsDocuments(deploymentId);
+ JerseyClient jerseyClient = getJerseyClient();
+ Queries queries = null;
+ String result = null;
+ try {
+ result = jerseyClient.removeDocument("Deployments", deploymentId );
+ }
+ catch (Exception e) {
+ throw new TethysException("Error deleting deployment document " + deploymentId, e.getMessage());
+ }
+ return true;
+ }
+
+ /**
+ * 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
+ */
+ public boolean removeDocument(Collection collection, String documentName) throws TethysException {
+ return removeDocument(collection.collectionName(), documentName);
+ }
+
+ /**
+ * 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
+ */
+ public boolean removeDocument(String collectionName, String documentName) throws TethysException {
+ try {
+ Object result = jerseyClient.removeDocument(collectionName, documentName );
+ /**
+ * Return from a sucessful delete is something like
+ *
+ deployment = getTethysControl().getDeploymentHandler().createDeploymentDocument(freeId++, recordPeriod);
+
+ - ['ECoastNARW0']
+
+ An error will throw an exception.
+ */
+ }
+ catch (Exception e) {
+ String msg = String.format("Error deleting %s:%s", collectionName, documentName);
+ throw new TethysException(msg, e.getLocalizedMessage());
+ }
+ return true;
+ }
+
+ /**
+ * 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
+
+
+ added
+
+
+ 20080311_2DSimplex_0
+
+
+
+
+Example error (file not existing)
+C:\Users\dg50\AppData\Local\Temp\PAMGuardTethys\20080311_2DSimplex_0.xmlnot: 0 bytes
+
+
+ C:\Users\dg50\AppData\Local\Temp\PAMGuardTethys\20080311_2DSimplex_0.xmlnot
+ does not exist
+
+
+
+
+
+ */
+
+
+ }
+
+ /**
+ * Seems we have to get rid of the line
+ * which is being put there by the marshaller ?
+ * @param tempFile
+ */
+ private File stripXMLHeader(File tempFile) {
+ // TODO Auto-generated method stub
+
+ File tempTemp = new File(tempFile.getAbsolutePath().replace(".temp.xml", ".xml"));
+ try {
+ BufferedReader reader = new BufferedReader(new FileReader(tempFile));
+ BufferedWriter writer = new BufferedWriter(new FileWriter(tempTemp));
+ String line = reader.readLine();
+ while (line != null) {
+ // see if the line has any unicode in it
+ int len = line.length();
+ byte[] bytes = line.getBytes();
+ if (len == bytes.length) {
+ System.out.println(line);
+ }
+
+ if (line.startsWith(" getCollectionDocumentList(Collection collection) {
+ if (collection == null) {
+ return null;
+ }
+
+ /**
+ * xQuery string based on examples in email from MR on 27/9/2023
+ */
+// String baseQuery = " {\r\n"
+ String baseQuery = " {\r\n"
+ + " for $doc in collection(\"COLLECTIONAME\")/DOCUMENTNAME\r\n"
+ + " return\r\n"
+ + " {\r\n"
+ + " base-uri($doc), \r\n"
+ + " $doc/Id\r\n"
+ + " }\r\n"
+ + " \r\n"
+ + "} \r\n"
+ + "";
+ String xQuery = baseQuery.replace("COLLECTIONAME", collection.collectionName());
+ xQuery = xQuery.replace("DOCUMENTNAME", collection.documentName());
+
+ Queries queries = dbXMLConnect.getTethysQueries();
+ String result = null;
+ try {
+ result = queries.QueryTethys(xQuery);
+ }
+ catch (Exception e) {
+// e.printStackTrace();
+ }
+ if (result == null) {
+ return null;
+ }
+// System.out.println(result);
+ ArrayList documentInfos = new ArrayList<>();
+
+ Document doc = convertStringToXMLDocument(result);
+ if (doc == null) {
+ return null;
+ }
+// PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter();
+// System.out.println(pamXMLWriter.getAsString(doc));
+ /**
+ * lots of elements along lines of
+ * dbxml:///Deployments/Meygen20229Meygen20229
+ */
+ NodeList returns = doc.getElementsByTagName("doc");
+ int n = returns.getLength();
+ String toStrip = "dbxml:///"+collection.collectionName()+"/";
+ for (int i = 0; i < n; i++) {
+ Node aNode = returns.item(i);
+ String nameStr = null;
+ String id = null;
+ NodeList kids = aNode.getChildNodes();
+ for (int k = 0; k < kids.getLength(); k++) {
+ Node kidNode = kids.item(k);
+ String name = kidNode.getNodeName();
+ String cont = kidNode.getTextContent();
+ switch(name) {
+ case "#text":
+ nameStr = cont;
+ nameStr = nameStr.replaceFirst(toStrip, "");
+ break;
+ case "Id":
+ id = kidNode.getTextContent();
+ break;
+ default:
+ System.out.printf("Uknonwn node in Collection list %s item %d, Node %d name %s content %s\n",
+ collection, i, k, name, cont);
+ }
+ }
+// if (i > 428) {
+// System.out.println("MARU cal doc");
+// }
+ // this is the doc name with a load of stuff in front,
+ // e.g. dbxml:///Deployments/1705_Array-2017-09-261705_Array-2017-09-26
+ if (nameStr == null) {
+ nameStr = aNode.getTextContent();
+ nameStr = nameStr.replaceFirst(toStrip, "");
+ }
+// if (aNode instanceof Element) {
+ // nameStr = getElementData((Element) aNode, "#text");
+ // }
+
+ if (id == null) {
+ if (aNode instanceof Element) {
+ id = getElementData((Element) aNode, "Id");
+ }
+ }
+
+ DocumentInfo docInfo = new DocumentInfo(collection, nameStr, id);
+ documentInfos.add(docInfo);
+// System.out.println(nameStr + " : " + id);
+ }
+ return documentInfos;
+
+
+
+ // if (collection.endsWith("s")) {
+ // collection = collection.substring(0, collection.length()-1);
+ // }
+// String baseQuery = "{\"return\":[\"COLLECTIONNAME/Id\"],\"select\":[],\"enclose\":1}";
+// baseQuery = baseQuery.replace("COLLECTIONNAME", collection);
+// String tagName = "Id";
+//
+// if (collection.equals("SpeciesAbbreviations")) {
+// baseQuery = "{\"return\":[\"Abbreviations/Name\"],\"select\":[],\"enclose\":1}";
+// tagName = "Name";
+// }
+//
+// DBQueryResult result;
+// try {
+// result = executeQuery(baseQuery);
+// } catch (TethysQueryException e) {
+// System.out.println("Error with query: " + baseQuery);
+// tethysControl.showException(e);
+// return null;
+// }
+//
+// if (result == null || result.queryResult == null) {
+// return null;
+// }
+// Document doc = convertStringToXMLDocument(result.queryResult);
+// if (doc == null) {
+// return null;
+// }
+// NodeList returns = doc.getElementsByTagName(tagName);
+// ArrayList docIds = new ArrayList<>();
+// int n = returns.getLength();
+// for (int i = 0; i < n; i++) {
+// Node aNode = returns.item(i);
+// String docId = aNode.getTextContent();
+// docIds.add(docId);
+// }
+//
+// return docIds;
+ }
+
+ /**
+ * Get a list of project names.
+ * @return
+ */
+ public ArrayList getProjectNames() {
+
+ String projectQuery = "{\"return\":[\"Deployment/Project\"],\"select\":[],\"enclose\":1}";
+
+ DBQueryResult result;
+ try {
+ result = executeQuery(projectQuery);
+ } catch (TethysQueryException e) {
+ tethysControl.showException(e);
+ return null;
+ }
+
+ if (result == null || result.queryResult == null) {
+ return null;
+ }
+
+ // System.out.println("Project query execution time millis = " + result.queryTimeMillis);
+
+ ArrayList projectNames = new ArrayList<>();
+ // iterate through the document and make a list of names, then make them unique.
+ /* looking for elements like this:
+ *
+ * check out the jaxb unmarshaller ...
+
+
+ LJ
+
+
+ */
+ Document doc = convertStringToXMLDocument(result.queryResult);
+ if (doc == null) {
+ return null;
+ }
+ NodeList returns = doc.getElementsByTagName("Project");
+ // System.out.println("N projects = " + returns.getLength());
+ int n = returns.getLength();
+ for (int i = 0; i < n; i++) {
+ Node aNode = returns.item(i);
+ String projName = aNode.getTextContent();
+ if (projName != null) {
+ if (!projectNames.contains(projName)) {
+ projectNames.add(projName);
+ }
+ }
+ // }
+ // if (aNode instanceof Element) {
+ // Node depEl = ((Element) aNode).getFirstChild();
+ // if (depEl == null) {
+ // continue;
+ // }
+ // if (depEl instanceof Element) {
+ // Element projEl = (Element) ((Element) depEl).getFirstChild();
+ // String projName = projEl.getTextContent();
+ // if (projName != null) {
+ // if (!projectNames.contains(projName)) {
+ // projectNames.add(projName);
+ // }
+ // }
+ // }
+ // }
+ }
+
+ Collections.sort(projectNames);
+
+ return projectNames;
+ }
+
+ /**
+ * Get project deployments that use a specific instrument id. More use than the call without this
+ * extra clause since it can handle overlapping deployments.
+ * @param projectName
+ * @param instrumentId
+ * @return
+ */
+ public ArrayList getProjectDeployments(String projectName, String instrumentId) {
+ if (projectName == null) {
+ return null;
+ }
+ String qBase = "{\"return\":[\"Deployment\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Deployment/Project\",\"%s\"],\"optype\":\"binary\"},{\"op\":\"=\","
+ + "\"operands\":[\"Deployment/Instrument/InstrumentId\",\"%s\"],\"optype\":\"binary\"}],\"enclose\":1}";
+ String qStr = String.format(qBase, projectName, instrumentId);
+
+ return runProjectDeploymentsQuery(projectName, qStr);
+ }
+ /**
+ * Get some basic (not all) data for deployments associated with a project. Note that
+ * this may include deployments which are NOT part of the current dataset. That requires
+ * a search on Instrument as well.
+ * @param projectName
+ * @return
+ */
+ public ArrayList getProjectDeployments(String projectName) {
+ if (projectName == null) {
+ return null;
+ }
+ String qBase = "{\"return\":[\"Deployment\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Deployment/Project\",\"%s\"],\"optype\":\"binary\"}],\"enclose\":1}";
+ String qStr = String.format(qBase, projectName);
+ return runProjectDeploymentsQuery(projectName, qStr);
+ }
+
+ /**
+ * Run the actual projects query from either of the two above functions.
+ * @param projectName
+ * @param qStr
+ * @return
+ */
+ private ArrayList runProjectDeploymentsQuery(String projectName, String qStr) {
+ DBQueryResult result = null;
+ try {
+ result = executeQuery(qStr);
+ } catch (TethysQueryException e1) {
+ tethysControl.showException(e1);
+ }
+ if (result == null) {
+ return null;
+ }
+ // System.out.println("Deployment query execution time millis = " + result.queryTimeMillis);
+
+ PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter();
+
+ Document doc = convertStringToXMLDocument(result.queryResult);
+ if (doc == null) {
+ return null;
+ }
+
+ // System.out.println(pamXMLWriter.getAsString(doc));
+
+ ArrayList deployments = new ArrayList<>();
+
+ NodeList returns = doc.getElementsByTagName("Deployment");
+ // if (returns.getLength() == 0) {
+ // // try REsult instead !
+ // returns = doc.getElementsByTagName("Result");
+ // }
+ // System.out.println("N projects = " + returns.getLength());
+ int n = returns.getLength();
+
+ // Queries queries = new Queries(null)
+ for (int i = 0; i < n; i++) {
+ Node aNode = returns.item(i);
+ if (aNode instanceof Element) {
+ Element returnedEl = (Element) aNode;
+
+ String Id = getElementData(returnedEl, "Id");
+ String project = getElementData(returnedEl, "Project");
+ String DeploymentId = getElementData(returnedEl, "DeploymentId");
+ String instrType = getElementData(returnedEl, "Instrument.Type");
+ String instrId = getElementData(returnedEl, "Instrument.InstrumentId");
+ String geometry = getElementData(returnedEl, "Instrument.GeometryType");
+ String audioStart = getElementData(returnedEl, "DeploymentDetails.AudioTimeStamp");
+ String audioEnd = getElementData(returnedEl, "RecoveryDetails.AudioTimeStamp");
+ String region = getElementData(returnedEl, "Region");
+ Deployment deployment = new Deployment();
+ try {
+ Helper.createRequiredElements(deployment);
+ } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) {
+ e.printStackTrace();
+ }
+ deployment.setId(Id);
+ deployment.setProject(projectName);
+ deployment.setDeploymentId(Integer.valueOf(DeploymentId));
+ XMLGregorianCalendar gcStart = TethysTimeFuncs.fromGregorianXML(audioStart);
+ XMLGregorianCalendar gcEnd = TethysTimeFuncs.fromGregorianXML(audioEnd);
+ // System.out.printf("Converted %s to %s\n", audioStart,
+ // PamCalendar.formatDBDateTime(TethysTimeFuncs.millisFromGregorianXML(gcStart), true));
+ deployment.getDeploymentDetails().setAudioTimeStamp(gcStart);
+ if (deployment.getRecoveryDetails() == null) {
+ deployment.setRecoveryDetails(new DeploymentRecoveryDetails());
+ }
+ deployment.getRecoveryDetails().setAudioTimeStamp(gcEnd);
+ if (instrType != null || instrId != null) {
+ Instrument instrument = new Instrument();
+ instrument.setType(instrType);
+ instrument.setInstrumentId(instrId);
+ instrument.setGeometryType(geometry);
+ deployment.setInstrument(instrument);
+ }
+ deployment.setRegion(region);
+ deployments.add(deployment);
+ }
+ }
+ return deployments;
+ }
+
+ /**
+ * Get a list of Detections documents which associate with a datablock and a deploymentId.
+ * @param dataBlock
+ * @param deploymentId can be null to get all docs for data block
+ * @return
+ */
+ public ArrayList getDetectionsDocuments(PamDataBlock dataBlock, String deploymentId) {
+ /**
+ * first query for Detections documents associated with this deployment and datablock.
+ * updated May 23
+ */
+ 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;
+ if (deploymentId == null) {
+ query = queryNoDepl;
+ }
+ else {
+ query = queryWithDepl.replace("TheDeploymentId", deploymentId);
+ }
+ query = query.replace("LongDataName", dataBlock.getLongDataName());
+ DBQueryResult queryResult = null;
+ try {
+ queryResult = executeQuery(query);
+ } catch (TethysQueryException e1) {
+ tethysControl.showException(e1);
+ return null;
+ }
+ if (queryResult ==null) {
+ return null;
+ }
+ Document doc;
+ try {
+ doc = queryResult.getDocument();
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ if (doc == null) {
+ return null;
+ }
+ ArrayList detectionsNames = new ArrayList();
+ int count = 0;
+ NodeList returns = doc.getElementsByTagName("Detections");
+ // if (returns.getLength() == 0) {
+ // returns = doc.getElementsByTagName("Result");
+ // }
+ for (int i = 0; i < returns.getLength(); i++) {
+ Node aNode = returns.item(i);
+ String docName = aNode.getTextContent();
+ detectionsNames.add(docName);
+ }
+ return detectionsNames;
+ }
+
+
+ /**
+ * Get the names of all detection documents for a given deployment for all data streams.
+ * @param deploymentId
+ * @return
+ */
+ public ArrayList getDetectionsDocuments(String deploymentId) {
+ String queryBase = "{\"species\":{\"query\":{\"op\":\"lib:abbrev2tsn\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]},\"return\":{\"op\":\"lib:tsn2abbrev\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]}},\"return\":[\"Detections/Id\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/DataSource/DeploymentId\",\"SomeDeploymentId\"],\"optype\":\"binary\"}],\"enclose\":1}";
+ String queryStr = queryBase.replace("SomeDeploymentId", deploymentId);
+ DBQueryResult queryResult = null;
+ try {
+ queryResult = executeQuery(queryStr);
+ } catch (TethysQueryException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ if (queryResult == null || queryResult.queryException != null) {
+ return null;
+ }
+
+ // PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter();
+
+ Document doc = convertStringToXMLDocument(queryResult.queryResult);
+ if (doc == null) {
+ return null;
+ }
+
+ ArrayList detectionDocs = new ArrayList<>();
+
+ NodeList returns = doc.getElementsByTagName("Record");
+ if (returns.getLength() == 0) {
+ returns = doc.getElementsByTagName("Record");
+ }
+ for (int i = 0; i < returns.getLength(); i++) {
+ Node aNode = returns.item(i);
+ detectionDocs.add(aNode.getTextContent());
+ }
+ return detectionDocs;
+ }
+
+ public int countData(PamDataBlock dataBlock, String deploymentId) {
+ // /**
+ // * first query for Detections documents associated with this deployment and datablock.
+ // */
+ // String queryNoDepl = "{\"species\":{\"query\":{\"op\":\"lib:abbrev2tsn\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]},\"return\":{\"op\":\"lib:tsn2abbrev\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]}},\"return\":[\"Detections/Id\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Algorithm/Software\",\"LongDataName\"],\"optype\":\"binary\"}],\"enclose\":1}";
+ // String queryWithDepl = "{\"species\":{\"query\":{\"op\":\"lib:abbrev2tsn\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]},\"return\":{\"op\":\"lib:tsn2abbrev\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]}},\"return\":[\"Detections/Id\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Algorithm/Software\",\"LongDataName\"],\"optype\":\"binary\"},{\"op\":\"=\",\"operands\":[\"Detections/DataSource/DeploymentId\",\"TheDeploymentId\"],\"optype\":\"binary\"}],\"enclose\":1}";
+ // String query;
+ // if (deploymentId == null) {
+ // query = queryNoDepl;
+ // }
+ // else {
+ // query = queryWithDepl.replace("TheDeploymentId", deploymentId);
+ // }
+ // query = query.replace("LongDataName", dataBlock.getLongDataName());
+ // DBQueryResult queryResult = executeQuery(query);
+ // if (queryResult ==null) {
+ // return 0;
+ // }
+ // Document doc;
+ // try {
+ // doc = queryResult.getDocument();
+ // } catch (ParserConfigurationException | SAXException | IOException e) {
+ // e.printStackTrace();
+ // return 0;
+ // }
+ //
+ // int count = 0;
+ // NodeList returns = doc.getElementsByTagName("Return");
+ ArrayList documentNames = getDetectionsDocuments(dataBlock, deploymentId);
+ if (documentNames == null) {
+ return 0;
+ }
+ int count = 0;
+ for (String docName : documentNames) {
+ // System.out.println(aNode.getTextContent());
+ int count2 = countDetections2(docName);
+ count += count2; //countDetecionsData(docName);
+
+ }
+ return count;
+ }
+
+ public String getDocument(String collection, String documentId) {
+ // String queryBase = "return:(collection(\"replaceCollectionName\")/Detections[Id=\"ReplaceDocumentId\"])";
+ // queryBase = queryBase.replace("replaceCollectionName", collection);
+ // queryBase = queryBase.replace("ReplaceDocumentId", documentId);
+ //
+ // String result = null;
+ // try {
+ // Queries queries = dbXMLConnect.getTethysQueries();
+ // result = queries.QueryTethys(queryBase);
+ //// System.out.println(result);
+ // }
+ // catch (Exception e) {
+ // System.out.println("Error executing " + queryBase);
+ //// e.printStackTrace();
+ // return null;
+ // }
+ // return result;
+
+ Queries queries = dbXMLConnect.getTethysQueries();
+ String result = null;
+ try {
+ result = queries.getDocument(collection, documentId);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return result;
+
+ // String queryBase = "{\"return\":[\"Deployment/Project\"],\"select\":[],\"enclose\":1}";
+ }
+
+ /**
+ * Find out if a document exists ?
+ * @param collection
+ * @param documentId
+ * @return
+ */
+ public boolean documentExists(String collection, String documentId) {
+ Queries queries = dbXMLConnect.getTethysQueries();
+ String result = null;
+ try {
+ result = queries.getDocument(collection, documentId);
+ } catch (Exception e) {
+ return false;
+ }
+ if (result == null || result.length() == 0) {
+ return false;
+ }
+
+ return result.contains(documentId);
+ }
+
+ /**
+ * Count on effort detections in a Detections document
+ * @param docName
+ * @return
+ */
+ public int countDetections2(String docName) {
+ TethysExportParams params = tethysControl.getTethysExportParams();
+ String queryBase = "count(collection(\"Detections\")/Detections[Id=\"ReplaceDocumentId\"]/OnEffort/Detection)";
+ String query = queryBase.replace("ReplaceDocumentId", docName);
+
+ String result = null;
+ try {
+ Queries queries = dbXMLConnect.getTethysQueries();
+ result = queries.QueryTethys(query);
+ // System.out.println(result);
+ }
+ catch (Exception e) {
+ System.out.println("Error executing " + query);
+ // e.printStackTrace();
+ return -1;
+ }
+ int count = 0;
+ try {
+ count = Integer.valueOf(result);
+ }
+ catch (NumberFormatException e) {
+ System.out.println("Unable to interpret count data " + result);
+ return 0;
+ }
+ return count;
+ }
+
+ // /**
+ // * Get a count of the detections in a detections document.
+ // * Only looking in onEffort so far.
+ // * @param deploymentId
+ // * @param detectionDocId
+ // * @param dataBlock
+ // * @return
+ // */
+ // public int getDetectionsDetectionCount(String deploymentId, String detectionDocId, PamDataBlock dataBlock) {
+ // String queryBase = "{\"species\":{\"query\":{\"op\":\"lib:abbrev2tsn\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]},\"return\":{\"op\":\"lib:tsn2abbrev\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]}},\"return\":[\"Detections/OnEffort/Detection/Start\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Id\",\"SomeDetectionsId\"],\"optype\":\"binary\"},{\"op\":\"=\",\"operands\":[\"Detections/DataSource/DeploymentId\",\"SomeDeploymentId\"],\"optype\":\"binary\"}],\"enclose\":1}";
+ // String queryStr = queryBase.replace("SomeDetectionsId", detectionDocId);
+ // queryStr = queryStr.replace("SomeDeploymentId", deploymentId);
+ // DBQueryResult queryResult = executeQuery(queryStr);
+ // if (queryResult == null || queryResult.queryException != null) {
+ // return 0;
+ // }
+ //// System.out.println("Detections query time ms = " + queryResult.queryTimeMillis);
+ //
+ // PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter();
+ //
+ // Document doc = convertStringToXMLDocument(queryResult.queryResult);
+ // if (doc == null) {
+ // return 0;
+ // }
+ //
+ //// System.out.println(pamXMLWriter.getAsString(doc));
+ //
+ //// ArrayList detectionDocs = new ArrayList<>();
+ //
+ // NodeList returns = doc.getElementsByTagName("Start");
+ // int n = returns.getLength();
+ // return n;
+ // }
+
+ // /**
+ // * This is the quickest way of counting data in a project, but it will load the start
+ // * times for every detection in a project at once, so might use a lot of memory. Also
+ // * it wll probably get data for all deployments in a project, which may not be what we want.
+ // * @param projectName
+ // * @param dataPrefixes
+ // * @return
+ // */
+ // public int[] countDataForProject(String projectName, String[] dataPrefixes) {
+ // int[] n = new int[dataPrefixes.length];
+ // ArrayList matchedDeployments = tethysControl.getDeploymentHandler().getMatchedDeployments();
+ //// ArrayList deployments = getProjectDeployments(projectName);
+ // if (matchedDeployments == null) {
+ // return null;
+ // }
+ // for (PDeployment aDeployment : matchedDeployments) {
+ //// ArrayList detectionsIds = getDetectionsDocsIds(aDeployment.getId());
+ //// for (String detId : detectionsIds) {
+ //// n += getDetectionsDetectionCount(aDeployment.getId(), detId, dataBlock);
+ //// }
+ // int[] newN = countDataForDeployment(projectName, aDeployment.deployment.getId(), dataPrefixes);
+ // for (int i = 0; i < n.length; i++) {
+ // n[i] += newN[i];
+ // }
+ // }
+ // return n;
+ // }
+
+ /**
+ * Count data within a deployment document which is associated with a set of datablocks
+ * Since the detections all come back in one query, it's easier to count all datablocks at once so
+ * that it can all happen off a single query.
+ * @param id
+ * @param dataBlockPrefixes
+ * @return
+ */
+ private int[] countDataForDeployment(String projectId, String deploymentId, String[] dataPrefixes) {
+ String queryBase = "{\"species\":{\"query\":{\"op\":\"lib:abbrev2tsn\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]},\"return\":{\"op\":\"lib:tsn2abbrev\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]}},\"return\":[\"Detections/Id\",\"Detections/OnEffort/Detection/Start\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/DataSource/DeploymentId\",\"ReplaceDeploymentIdString\"],\"optype\":\"binary\"}],\"enclose\":1}";
+ String queryString = queryBase.replace("ReplaceDeploymentIdString", deploymentId);
+ DBQueryResult result;
+ try {
+ result = executeQuery(queryString);
+ } catch (TethysQueryException e) {
+ tethysControl.showException(e);
+ return null;
+ }
+ if (result == null || result.queryResult == null) {
+ return null;
+ }
+ PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter();
+
+ Document doc = convertStringToXMLDocument(result.queryResult);
+ if (doc == null) {
+ return null;
+ }
+
+ // System.out.println(pamXMLWriter.getAsString(doc));
+
+ NodeList detsDocs = doc.getElementsByTagName("Detections");
+ int[] blockCounts = new int[dataPrefixes.length];
+
+ // String detDocPrefix = projectId + "_" + dataBlock.getDataName();
+
+ // int totalCalls = 0;
+ int detCount = 0;
+ int dataIndex;
+ for (int i = 0; i < detsDocs.getLength(); i++) {
+ Node detNode = detsDocs.item(i);
+
+ NodeList childNodes = detNode.getChildNodes();
+ detCount = childNodes.getLength()-1;
+ dataIndex = -1;
+ for (int n = 0; n < childNodes.getLength(); n++) {
+ Node aNode = childNodes.item(n);
+ if (aNode instanceof Element) {
+ Element el = (Element) aNode;
+ String nodeName = el.getNodeName();
+ if (nodeName.equals("Id")) {
+ String id = el.getTextContent();
+ for (int j = 0; j < dataPrefixes.length; j++) {
+ if (id != null && id.startsWith(dataPrefixes[j])) {
+ dataIndex = j;
+ }
+ }
+ // if (id != null && id.startsWith(detDocPrefix) == false) {
+ // detCount = 0;
+ // break;
+ // }
+ }
+ }
+ }
+ if (dataIndex >= 0) {
+ blockCounts[dataIndex] += detCount;
+ }
+ // System.out.printf("%d Added %d for new total %d\n",i, detCount, totalCalls);
+ }
+
+ return blockCounts;
+ }
+
+ public String getElementData(Element root, String elName) {
+ String[] tree = elName.split("\\.");
+ for (String element : tree) {
+ NodeList nodeList = root.getElementsByTagName(element);
+ // should only be one node for what we're unpacking.
+ if (nodeList == null || nodeList.getLength() == 0) {
+ return null;
+ }
+ int count = nodeList.getLength();
+ for (int i = 0; i < count; i++) {
+ Node firstNode = nodeList.item(i);
+ if (firstNode instanceof Element) {
+ root = (Element) firstNode;
+ break;
+ }
+ }
+ }
+ return root.getTextContent();
+ }
+
+
+ public String getElementAttribute(Element root, String elName, String attribute) {
+ String[] tree = elName.split("\\.");
+ for (String element : tree) {
+ NodeList nodeList = root.getElementsByTagName(element);
+ // should only be one node for what we're unpacking.
+ if (nodeList == null || nodeList.getLength() == 0) {
+ return null;
+ }
+ int count = nodeList.getLength();
+ for (int i = 0; i < count; i++) {
+ Node firstNode = nodeList.item(i);
+ if (firstNode instanceof Element) {
+ root = (Element) firstNode;
+ break;
+ }
+ }
+ }
+ return root.getAttribute(attribute);
+ }
+
+ public Document convertStringToXMLDocument(String xmlString) {
+ //Parser that produces DOM object trees from XML content
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+
+ //API to obtain DOM Document instance
+ DocumentBuilder builder = null;
+ try {
+ //Create DocumentBuilder with default configuration
+ builder = factory.newDocumentBuilder();
+
+ //Parse the content to Document object
+ Document doc = builder.parse(new InputSource(new StringReader(xmlString)));
+ return doc;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /**
+ * Get the basic information about a Detections document. This is basically everything apart from
+ * the actual detections themselves.
+ * @param aDoc
+ * @return
+ */
+ public Detections getDetectionsDocInfo(String detectionsDocName) {
+// String oldqueryBase = "{\"species\":{\"query\":{\"op\":\"lib:abbrev2tsn\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]},\"return\":{\"op\":\"lib:tsn2abbrev\",\"optype\":\"function\",\"operands\":[\"%s\",\"SIO.SWAL.v1\"]}},\"return\":[\"Detections/Id\",\"Detections/Description\",\"Detections/DataSource\",\"Detections/Algorithm\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Id\",\"DetectionsDocName\"],\"optype\":\"binary\"}],\"enclose\":1}";
+ // updated May 23
+ String queryBase = "{\"species\":{\"query\":{\"op\":\"lib:completename2tsn\",\"optype\":\"function\",\"operands\":[\"%s\"]},\"return\":{\"op\":\"lib:tsn2completename\",\"optype\":\"function\",\"operands\":[\"%s\"]}},\"return\":[\"Detections/Id\",\"Detections/Description\",\"Detections/DataSource\",\"Detections/Algorithm\",\"Detections/QualityAssurance\",\"Detections/UserId\",\"Detections/MetadataInfo\",\"Detections/Effort\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Detections/Id\",\"DetectionsDocName\"],\"optype\":\"binary\"}],\"enclose\":1}";
+ String query = queryBase.replace("DetectionsDocName", detectionsDocName);
+ DBQueryResult queryResult;
+ try {
+ queryResult = executeQuery(query);
+ } catch (TethysQueryException e) {
+ tethysControl.showException(e);
+ return null;
+ }
+ Document doc;
+ try {
+ doc = queryResult.getDocument();
+ } catch (ParserConfigurationException | SAXException | IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ }
+ // System.out.println(queryResult.queryResult);
+
+ Detections detections = new Detections();
+ try {
+ Helper.createRequiredElements(detections);
+ } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) {
+ e.printStackTrace();
+ }
+
+ NodeList returns = doc.getElementsByTagName("Result");
+ // System.out.println("N projects = " + returns.getLength());
+ int n = returns.getLength();
+ if (n == 0) {
+ return null;
+ }
+ Element result = (Element) returns.item(0);
+
+ DescriptionType description = detections.getDescription();
+ if (description == null) {
+ description = new DescriptionType();
+ detections.setDescription(description);
+ }
+ detections.setId(getElementData(result, "Id"));
+ description.setAbstract(getElementData(result, "Description.Abstract"));
+ description.setMethod(getElementData(result, "Description.Method"));
+ description.setObjectives(getElementData(result, "Description.Objectives"));
+
+ String deployment = getElementData(result, "DataSource.DeploymentId");
+ if (deployment != null) {
+ DataSourceType dataSource = detections.getDataSource();
+ if (dataSource == null) {
+ dataSource = new DataSourceType();
+ detections.setDataSource(dataSource);
+ }
+ dataSource.setDeploymentId(deployment);
+ }
+
+ // get the effort start an end
+ String effStart = getElementData(result, "Effort.Start");
+ String effEnd = getElementData(result, "Effort.End");
+ detections.getEffort().setStart(TethysTimeFuncs.fromGregorianXML(effStart));
+ detections.getEffort().setEnd(TethysTimeFuncs.fromGregorianXML(effEnd));
+ // try to find the granularity.
+ String granularityString = getElementData(result, "Effort.Kind.Granularity");
+ GranularityEnumType granularity = null;
+ if (granularityString != null) {
+ granularity = GranularityEnumType.fromValue(granularityString);
+ List kinds = detections.getEffort().getKind();
+ DetectionEffortKind kind = new DetectionEffortKind();
+ GranularityType granularityType = new GranularityType();
+ granularityType.setValue(granularity);
+ kind.setGranularity(granularityType);
+ // try to find the rest of the granularity information.
+ String binSize_m = getElementAttribute(result, "Effort.Kind.Granularity", "BinSize_m");
+ String encounterGap_m = getElementAttribute(result, "Effort.Kind.Granularity", "EncounterGap_m");
+ String firstBinStart = getElementAttribute(result, "Effort.Kind.Granularity", "FirstBinStart");
+ try {
+ granularityType.setBinSizeMin(Double.valueOf(binSize_m));
+ }
+ catch (NumberFormatException e) {
+ }
+ try {
+ granularityType.setEncounterGapMin(Double.valueOf(encounterGap_m));
+ }
+ catch (NumberFormatException e) {
+ }
+
+ kinds.add(kind);
+ }
+ // String
+
+
+
+ // TODO Auto-generated method stub
+ return detections;
+ }
+
+}
diff --git a/src/tethys/dbxml/DMXMLQueryTest.java b/src/tethys/dbxml/DMXMLQueryTest.java
new file mode 100644
index 00000000..e16e202a
--- /dev/null
+++ b/src/tethys/dbxml/DMXMLQueryTest.java
@@ -0,0 +1,79 @@
+package tethys.dbxml;
+
+import java.io.StringReader;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+
+import PamController.settings.output.xml.PamguardXMLWriter;
+import dbxml.JerseyClient;
+import tethys.output.TethysExportParams;
+
+public class DMXMLQueryTest {
+
+ public static void main(String[] args) {
+ new DMXMLQueryTest().runTest();
+ }
+
+ private void runTest() {
+ TethysExportParams params = new TethysExportParams();
+
+ JerseyClient jerseyClient = new JerseyClient(params.getFullServerName());
+
+// String testJson = "{\"return\":[\"Deployment/Project\",\"Deployment/DeploymentId\",\"Deployment/Site\",\"Deployment/DeploymentDetails/AudioTimeStamp\",\"Deployment/RecoveryDetails/AudioTimeStamp\"],\"select\":[],\"enclose\":1}";
+// String testJson = "{\"return\":[\"Deployment/Project\",\"Deployment/Region\",\"Deployment/DeploymentDetails/AudioTimeStamp\",\"Deployment/RecoveryDetails/AudioTimeStamp\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Deployment/DeploymentId\",\"2\"],\"optype\":\"binary\"}],\"enclose\":1}";
+ //String testJson = "{\"return\":[\"Deployment/Project\",\"Deployment/Region\",\"Deployment/DeploymentDetails/AudioTimeStamp\",\"Deployment/RecoveryDetails/AudioTimeStamp\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Deployment/DeploymentId\",\"2\"],\"optype\":\"binary\"},{\"op\":\"=\",\"operands\":[\"Deployment/Project\",\"DCLDE2022\"],\"optype\":\"binary\"}],\"enclose\":1}";
+// String testJson = "{\"return\":[\"Deployment/Project\",\"Deployment/Region\",\"Deployment/DeploymentDetails/AudioTimeStamp\",\"Deployment/RecoveryDetails/AudioTimeStamp\",\"Deployment/DeploymentId\"],\"select\":[{\"op\":\"=\",\"operands\":[\"Deployment/DeploymentId\",\"2\"],\"optype\":\"binary\"},{\"op\":\"=\",\"operands\":[\"Deployment/Project\",\"DCLDE2022\"],\"optype\":\"binary\"}],\"enclose\":1}";
+ String testJson = "{\"return\":[\"Deployment/Project\"],\"select\":[],\"enclose\":1}";
+ // web browse to http://localhost:9779/Client
+
+ String testResult = jerseyClient.queryJSON(testJson);
+
+ Document doc = convertStringToXMLDocument(testResult);
+
+ PamguardXMLWriter pamXMLWriter = PamguardXMLWriter.getXMLWriter();
+ String formettedXML = pamXMLWriter.getAsString(doc, true);
+
+ System.out.println(testResult);
+ System.out.println(formettedXML);
+// try {
+// Transformer serializer = SAXTransformerFactory.newInstance()
+// .newTransformer();
+// Source source = new StreamSource(testResult);
+// ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+// StreamResult res = new StreamResult(bytes);
+// serializer.transform(source, res);
+// System.out.println(bytes.toString());
+// } catch (TransformerConfigurationException | TransformerFactoryConfigurationError e) {
+// e.printStackTrace();
+// }
+// // System.err.println(testResult);
+// catch (TransformerException e) {
+// // TODO Auto-generated catch block
+// e.printStackTrace();
+// }
+
+ }
+
+ private Document convertStringToXMLDocument(String xmlString) {
+ //Parser that produces DOM object trees from XML content
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+
+ //API to obtain DOM Document instance
+ DocumentBuilder builder = null;
+ try {
+ //Create DocumentBuilder with default configuration
+ builder = factory.newDocumentBuilder();
+
+ //Parse the content to Document object
+ Document doc = builder.parse(new InputSource(new StringReader(xmlString)));
+ return doc;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+}
diff --git a/src/tethys/dbxml/ServerStatus.java b/src/tethys/dbxml/ServerStatus.java
new file mode 100644
index 00000000..25c9ebbf
--- /dev/null
+++ b/src/tethys/dbxml/ServerStatus.java
@@ -0,0 +1,35 @@
+package tethys.dbxml;
+
+public class ServerStatus {
+
+ public boolean ok;
+
+ public Exception error;
+
+ public ServerStatus(boolean ok, Exception error) {
+ super();
+ this.ok = ok;
+ this.error = error;
+ }
+
+ public String getFormatted() {
+ if (ok) {
+ return "Server OK";
+ }
+ if (error == null) {
+ return "Unknown error";
+ }
+ String msg = error.getLocalizedMessage();
+ if (msg.startsWith("Exception")) {
+ msg.substring(9);
+ }
+ return msg;
+ }
+
+ @Override
+ public String toString() {
+ return getFormatted();
+ }
+
+
+}
diff --git a/src/tethys/dbxml/TethysException.java b/src/tethys/dbxml/TethysException.java
new file mode 100644
index 00000000..034a1970
--- /dev/null
+++ b/src/tethys/dbxml/TethysException.java
@@ -0,0 +1,18 @@
+package tethys.dbxml;
+
+public class TethysException extends Exception {
+
+ private static final long serialVersionUID = 1L;
+
+ private String xmlError;
+
+ public TethysException(String message, String xmlError) {
+ super(message);
+ this.xmlError = xmlError;
+ }
+
+ public String getXmlError() {
+ return xmlError;
+ }
+
+}
diff --git a/src/tethys/dbxml/TethysQueryException.java b/src/tethys/dbxml/TethysQueryException.java
new file mode 100644
index 00000000..7f46d7bc
--- /dev/null
+++ b/src/tethys/dbxml/TethysQueryException.java
@@ -0,0 +1,19 @@
+package tethys.dbxml;
+
+public class TethysQueryException extends TethysException {
+
+
+ private static final long serialVersionUID = 1L;
+
+ private String queryString;
+
+ public TethysQueryException(String message, String queryString) {
+ super(message, null);
+ this.queryString = queryString;
+ }
+
+ public String getQueryString() {
+ return queryString;
+ }
+
+}
diff --git a/src/tethys/deployment/DeploymentExportOpts.java b/src/tethys/deployment/DeploymentExportOpts.java
new file mode 100644
index 00000000..18fa461f
--- /dev/null
+++ b/src/tethys/deployment/DeploymentExportOpts.java
@@ -0,0 +1,43 @@
+package tethys.deployment;
+
+import java.io.Serializable;
+
+/**
+ * options for Deployment export collected by the export Wizard.
+ * @author dg50
+ *
+ */
+public class DeploymentExportOpts implements Serializable, Cloneable {
+
+ public static final long serialVersionUID = 1L;
+
+ public boolean separateDeployments;
+
+ /**
+ * Minimum number of seconds between GPS points in a track.
+ */
+ public double trackPointInterval;
+
+ /**
+ * Max gap before recording periods are separated, potentially into
+ * separate Deployment documents
+ */
+ public int maxRecordingGapSeconds = 60;
+
+ /**
+ * A recording section after joining with max gap parameter is too short
+ * to be worth keeping.
+ */
+ public int minRecordingLengthSeconds = 10;
+
+ @Override
+ protected DeploymentExportOpts clone() {
+ try {
+ return (DeploymentExportOpts) super.clone();
+ } catch (CloneNotSupportedException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+}
diff --git a/src/tethys/deployment/DeploymentHandler.java b/src/tethys/deployment/DeploymentHandler.java
new file mode 100644
index 00000000..85f834c3
--- /dev/null
+++ b/src/tethys/deployment/DeploymentHandler.java
@@ -0,0 +1,1270 @@
+package tethys.deployment;
+
+import java.awt.Window;
+import java.io.Serializable;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.ListIterator;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.apache.commons.beanutils.converters.BigIntegerConverter;
+
+import Acquisition.AcquisitionControl;
+import Acquisition.AcquisitionParameters;
+import Acquisition.DaqStatusDataUnit;
+import Acquisition.DaqSystem;
+import Acquisition.FolderInputSystem;
+import Array.ArrayManager;
+import Array.Hydrophone;
+import Array.HydrophoneLocator;
+import Array.PamArray;
+import Array.Streamer;
+import Array.ThreadingHydrophoneLocator;
+import GPS.GPSControl;
+import GPS.GPSDataBlock;
+import GPS.GpsData;
+import GPS.GpsDataUnit;
+import PamController.PamSensor;
+import PamController.PamSettingManager;
+import PamController.PamSettings;
+import PamController.PamControlledUnit;
+import PamController.PamControlledUnitSettings;
+import PamController.PamController;
+import PamUtils.PamUtils;
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamRawDataBlock;
+import binaryFileStorage.BinaryStore;
+import dataMap.OfflineDataMap;
+import dataMap.OfflineDataMapPoint;
+import generalDatabase.DBControlUnit;
+import metadata.MetaDataContol;
+import metadata.PamguardMetaData;
+import nilus.Audio;
+import nilus.ChannelInfo;
+import nilus.ChannelInfo.DutyCycle;
+import nilus.ChannelInfo.DutyCycle.Regimen.RecordingDurationS;
+import nilus.ChannelInfo.DutyCycle.Regimen.RecordingIntervalS;
+import nilus.ChannelInfo.Sampling;
+import nilus.ChannelInfo.Sampling.Regimen;
+import nilus.Deployment;
+import nilus.Deployment.Data;
+import nilus.Deployment.Data.Tracks;
+import nilus.Deployment.Data.Tracks.Track;
+import nilus.Deployment.Data.Tracks.Track.Point;
+import nilus.Deployment.Data.Tracks.Track.Point.BearingDegN;
+import nilus.Deployment.Instrument;
+import nilus.Deployment.SamplingDetails;
+import nilus.Deployment.Sensors;
+import nilus.DeploymentRecoveryDetails;
+import nilus.DescriptionType;
+import nilus.GeometryTypeM;
+import nilus.Helper;
+import nilus.MetadataInfo;
+import nilus.UnknownSensor;
+import pamMaths.PamVector;
+import pamMaths.STD;
+import tethys.Collection;
+import tethys.TethysControl;
+import tethys.TethysLocationFuncs;
+import tethys.TethysState;
+import tethys.TethysStateObserver;
+import tethys.TethysTimeFuncs;
+import tethys.calibration.CalibrationHandler;
+import tethys.TethysState.StateType;
+import tethys.dbxml.DBXMLConnect;
+import tethys.dbxml.TethysException;
+import tethys.deployment.swing.DeploymentWizard;
+import tethys.deployment.swing.RecordingGapDialog;
+import tethys.niluswraps.PDeployment;
+import tethys.output.TethysExportParams;
+import tethys.pamdata.AutoTethysProvider;
+import tethys.swing.DeploymentTableObserver;
+
+/**
+ * Functions to gather data for the deployment document from all around PAMGuard.
+ * There should be just one of these, available from TethysControl and it will try
+ * to sensible handle when and how it updates it's list of PAMGuard and Tethys information
+ * Any part of PAMGuard wanting information on Deployments should come here.
+ * @author dg50
+ *
+ */
+public class DeploymentHandler implements TethysStateObserver, DeploymentTableObserver {
+
+ private TethysControl tethysControl;
+
+ /**
+ * @return the tethysControl
+ */
+ public TethysControl getTethysControl() {
+ return tethysControl;
+ }
+
+ private EffortFunctions effortFunctions;
+
+ private DeploymentOverview deploymentOverview;
+
+ private ArrayList projectDeployments;
+
+ private Helper nilusHelper;
+
+ private DeploymentExportOpts deploymentExportOptions = new DeploymentExportOpts();
+
+ public DeploymentHandler(TethysControl tethysControl) {
+ super();
+
+ this.tethysControl = tethysControl;
+
+ this.effortFunctions = new EffortFunctions(tethysControl);
+
+ tethysControl.addStateObserver(this);
+ try {
+ nilusHelper = new Helper();
+ } catch (JAXBException e) {
+ e.printStackTrace();
+ }
+
+ PamSettingManager.getInstance().registerSettings(new SettingsHandler());
+ }
+
+ /**
+ * Gather up all track information both from the GPS module (if it exists) and
+ * the type of hydrophone array (or many!)
+ * @return
+ */
+ public TrackInformation getTrackInformation() {
+ PamArray array = ArrayManager.getArrayManager().getCurrentArray();
+ int nStreamers = array.getStreamerCount();
+ HydrophoneLocator locator = null;
+ for (int i = 0; i < nStreamers; i++) {
+ Streamer aStreamer = array.getStreamer(i);
+ locator = aStreamer.getHydrophoneLocator();
+// locator.getLocatorSettings().
+ }
+ // try to find a GPS datablock and see what's in it's datamap.
+ OfflineDataMap gpsDataMap = null;
+ GPSControl gpsControl = (GPSControl) PamController.getInstance().findControlledUnit(GPSControl.gpsUnitType);
+ if (gpsControl != null) {
+ GPSDataBlock gpsDataBlock = gpsControl.getGpsDataBlock();
+ gpsDataMap = gpsDataBlock.getPrimaryDataMap();
+ }
+ TrackInformation trackInformation = new TrackInformation(gpsDataMap, locator);
+ return trackInformation;
+ }
+
+ @Override
+ public void updateState(TethysState tethysState) {
+ switch (tethysState.stateType) {
+ case NEWPROJECTSELECTION:
+ updateProjectDeployments();
+ break;
+ case EXPORTRDATA:
+ case DELETEDATA:
+ updateProjectDeployments();
+ break;
+ case UPDATESERVER:
+ updateProjectDeployments();
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Update the list of Tethys deployments
+ * @return true if OK
+ */
+ public boolean updateProjectDeployments() {
+ Deployment projData = tethysControl.getGlobalDeplopymentData();
+ ArrayList tethysDocs = tethysControl.getDbxmlQueries().getProjectDeployments(projData.getProject(), getInstrumentId());
+ if (tethysDocs == null) {
+ return false;
+ }
+ projectDeployments = new ArrayList<>();
+ for (Deployment deployment : tethysDocs) {
+ projectDeployments.add(new PDeployment(deployment));
+ }
+ matchPamguard2Tethys(deploymentOverview, projectDeployments);
+ tethysControl.sendStateUpdate(new TethysState(TethysState.StateType.NEWPAMGUARDSELECTION));
+ return true;
+ }
+
+ /**
+ * Get a list of Tethys deployment docs. Note that this
+ * doesn't update the list, but uses the one currently in memory
+ * so call updateTethysDeployments() first if necessary.
+ * @return list of (wrapped) nilus Deployment objects.
+ */
+ public ArrayList getProjectDeployments() {
+ if (projectDeployments == null) {
+ updateProjectDeployments();
+ }
+ return projectDeployments;
+ }
+
+// /**
+// * Get an overview of all the deployments.
+// * @return
+// */
+// public DeploymentOverview createPamguardOverview() {
+// // first find an acquisition module.
+// PamControlledUnit aModule = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
+// if (!(aModule instanceof AcquisitionControl)) {
+// // will return if it's null. Impossible for it to be the wrong type.
+// // but it's good practice to check anyway before casting.
+// return null;
+// }
+// // cast it to the right type.
+// AcquisitionControl daqControl = (AcquisitionControl) aModule;
+// AcquisitionParameters daqParams = daqControl.getAcquisitionParameters();
+// /**
+// * The daqParams class has most of what we need about the set up in terms of sample rate,
+// * number of channels, instrument type, ADC input range (part of calibration), etc.
+// * It also has a hydrophone list, which maps the input channel numbers to the hydrophon numbers.
+// * Realistically, this list is always 0,1,2,etc or it goes horribly wrong !
+// */
+// // so write functions here to get information from the daqParams.
+//// System.out.printf("Sample regime: %s input with rate %3.1fHz, %d channels, gain %3.1fdB, ADCp-p %3.1fV\n", daqParams.getDaqSystemType(),
+//// daqParams.getSampleRate(), daqParams.getNChannels(), daqParams.preamplifier.getGain(), daqParams.voltsPeak2Peak);
+// /**
+// * then there is the actual sampling. This is a bit harder to find. I thought it would be in the data map
+// * but the datamap is a simple count of what's in the databasase which is not quite what we want.
+// * we're going to have to query the database to get more detailed informatoin I think.
+// * I'll do that here for now, but we may want to move this when we better organise the code.
+// * It also seems that there are 'bad' dates in the database when it starts new files, which are the date
+// * data were analysed at. So we really need to check the start and stop records only.
+// */
+// PamDataBlock daqInfoDataBlock = daqControl.getAcquisitionProcess().getDaqStatusDataBlock();
+// // just load everything. Probably OK for the acqusition, but will bring down
+// daqInfoDataBlock.loadViewerData(0, Long.MAX_VALUE, null);
+// ArrayList allStatusData = daqInfoDataBlock.getDataCopy();
+// /**
+// * Due to seird file overlaps we need to resort this by id if we can.
+// *
+// */
+// Collections.sort(allStatusData, new Comparator() {
+//
+// @Override
+// public int compare(DaqStatusDataUnit o1, DaqStatusDataUnit o2) {
+// if (o1.getDatabaseIndex() == 0) {
+// return (int) (o1.getTimeMilliseconds()-o2.getTimeMilliseconds());
+// }
+// return o1.getDatabaseIndex()-o2.getDatabaseIndex();
+// }
+// });
+//
+// ArrayList tempPeriods = null;
+//
+// if (allStatusData == null || allStatusData.size() == 0) {
+// System.out.println("Data appear to have no logged recording periods. Try to extract from raw audio ...");
+// tempPeriods = extractTimesFromFiles(daqControl);
+// }
+// else {
+// tempPeriods = extractTimesFromStatus(allStatusData);
+// }
+// if (tempPeriods == null || tempPeriods.size() == 0) {
+// System.out.println("Data appear to have no logged recording periods available either from the database or the raw recordings.");
+// tempPeriods = extractTimesFromOutputMaps();
+// }
+// if (tempPeriods == null || tempPeriods.size() == 0) {
+// System.out.println("Data appear to have no logged recording periods available either from the database or the raw recordings.");
+// return null;
+// }
+//
+// int nPeriods = tempPeriods.size();
+//// int i = 0;
+//// for (RecordingPeriod aP : tempPeriods) {
+//// System.out.printf("Pre merge %d : %s to %s\n", i++, PamCalendar.formatDBDateTime(aP.getRecordStart()),
+//// PamCalendar.formatDBDateTime(aP.getRecordStop()));
+//// }
+// // now go through those and merge into longer periods where there is no gap between files.
+// 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.maxGapSeconds*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.minLengthSeconds*1000L) {
+// iterator.remove();
+// }
+// }
+//// i = 0;
+//// for (RecordingPeriod aP : tempPeriods) {
+//// System.out.printf("Post merge %d : %s to %s\n", i++, PamCalendar.formatDBDateTime(aP.getRecordStart()),
+//// PamCalendar.formatDBDateTime(aP.getRecordStop()));
+//// }
+//// System.out.printf("Data have %d distinct files, but only %d distinct recording periods\n", nPeriods, tempPeriods.size());
+// DutyCycleInfo dutyCycleinfo = assessDutyCycle(tempPeriods);
+// // if it's duty cycles, then we only want a single entry.
+// ArrayList deploymentPeriods;
+// if (dutyCycleinfo.isDutyCycled == false) {
+// deploymentPeriods = tempPeriods;
+// }
+// else {
+// deploymentPeriods = new ArrayList<>();
+// 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);
+// matchPamguard2Tethys(deploymentOverview, projectDeployments);
+// this.deploymentOverview = deploymentOverview;
+// return deploymentOverview;
+// // find the number of times it started and stopped ....
+//// System.out.printf("Input map of sound data indicates data from %s to %s with %d starts and %d stops over %d files\n",
+//// PamCalendar.formatDateTime(dataStart), PamCalendar.formatDateTime(dataEnd), nStart, nStop, nFile+1);
+// // now work out where there are genuine gaps and make up a revised list of recording periods.
+//
+//
+// }
+
+ public void showOptions(Window parent) {
+ if (parent == null) {
+ parent = tethysControl.getGuiFrame();
+ }
+ DeploymentExportOpts newOpts = RecordingGapDialog.showDiloag(parent, deploymentExportOptions);
+ if (newOpts != null) {
+ deploymentExportOptions = newOpts;
+ createPamguardOverview();
+ }
+ }
+
+ public void createPamguardOverview() {
+ deploymentOverview = effortFunctions.makeRecordingOverview();
+ updateProjectDeployments();
+ matchPamguard2Tethys(deploymentOverview, projectDeployments);
+ }
+
+ /**
+ * Export button pressed on GUI. Run wizard....
+ */
+ public void exportDeployments() {
+ Deployment deployment = MetaDataContol.getMetaDataControl().getMetaData().getDeployment();
+ DeploymentExportOpts exportOptions = DeploymentWizard.showWizard(getTethysControl().getGuiFrame(), tethysControl, deployment, this.deploymentExportOptions);
+ if (exportOptions != null) {
+ this.deploymentExportOptions = exportOptions;
+ deploymentOverview = getDeploymentOverview();
+ ArrayList allPeriods = deploymentOverview.getRecordingPeriods();
+ exportDeployments(allPeriods);
+ }
+ }
+
+ /**
+ * Export deployments docs. Playing with a couple of different ways of doing this.
+ * @param selectedDeployments
+ */
+ public void exportDeployments(ArrayList selectedDeployments) {
+ if (deploymentExportOptions.separateDeployments) {
+ exportSeparateDeployments(selectedDeployments);
+ }
+ else {
+ exportOneDeploymnet(selectedDeployments);
+ }
+ }
+
+ /**
+ * Make one big deployment document with all the recording periods in it.
+ */
+ private void exportOneDeploymnet(ArrayList selectedDeployments) {
+ // do the lot, whatever ...
+ selectedDeployments = getDeploymentOverview().getRecordingPeriods();
+ int freeId = getTethysControl().getDeploymentHandler().getFirstFreeDeploymentId();
+ RecordingPeriod onePeriod = new RecordingPeriod(selectedDeployments.get(0).getRecordStart(),
+ selectedDeployments.get(selectedDeployments.size()-1).getRecordStop());
+ TethysExportParams exportParams = tethysControl.getTethysExportParams();
+ String id = String.format("%s_%s", exportParams.getDatasetName(), "all");
+ Deployment deployment = createDeploymentDocument(freeId, onePeriod, id);
+ // fill in a few things from here
+ Deployment globalMeta = getTethysControl().getGlobalDeplopymentData();
+ deployment.setCruise(globalMeta.getCruise());
+ deployment.setSite(globalMeta.getSite());
+ if (selectedDeployments.size() > 1) {
+ // now need to remove the
+ SamplingDetails samplingDetails = deployment.getSamplingDetails();
+ samplingDetails.getChannel().clear();
+ for (int i = 0; i < selectedDeployments.size(); i++) {
+ addSamplingDetails(deployment, selectedDeployments.get(i));
+ }
+ }
+ DBXMLConnect dbxmlConnect = getTethysControl().getDbxmlConnect();
+ PDeployment exDeploymnet = onePeriod.getMatchedTethysDeployment();
+ try {
+ if (exDeploymnet != null) {
+ deployment.setId(exDeploymnet.deployment.getId());
+ dbxmlConnect.updateDocument(deployment);
+ }
+ else {
+ dbxmlConnect.postAndLog(deployment);
+ }
+ }
+ catch (TethysException e) {
+ getTethysControl().showException(e);
+ }
+ getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATESERVER, Collection.Deployments));
+ }
+
+ /**
+ * Make a separate deployment document for every recording period.
+ */
+ private void exportSeparateDeployments(ArrayList selectedDeployments) {
+
+ 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);
+ PDeployment exDeploymnet = recordPeriod.getMatchedTethysDeployment();
+ Deployment deployment = null;
+ String id = String.format("%s_%d", exportParams.getDatasetName(), i);
+ if (exDeploymnet != null) {
+ deployment = createDeploymentDocument(freeId, recordPeriod, id);
+ deployment.setId(exDeploymnet.deployment.getId());
+ }
+ if (deployment == null) {
+ deployment = createDeploymentDocument(freeId++, recordPeriod, id);
+ }
+ deployment.setCruise(globalMeta.getCruise());
+ deployment.setSite(globalMeta.getSite());
+ // also need to sort out track data here, etc.
+ DBXMLConnect dbxmlConnect = getTethysControl().getDbxmlConnect();
+ try {
+ if (exDeploymnet != null) {
+ dbxmlConnect.updateDocument(deployment);
+ }
+ else {
+ dbxmlConnect.postAndLog(deployment);
+ }
+ }
+ catch (TethysException e) {
+ getTethysControl().showException(e);
+ }
+ }
+ getTethysControl().sendStateUpdate(new TethysState(StateType.UPDATESERVER, Collection.Deployments));
+ }
+
+
+
+ public DeploymentOverview getDeploymentOverview() {
+ return deploymentOverview;
+ }
+
+ /**
+ * Match what we think the PAMGuard deployment times are with Tethys Deployments read back
+ * from the database.
+ * @param deploymentOverview
+ * @param deployments
+ */
+ private void matchPamguard2Tethys(DeploymentOverview deploymentOverview, ArrayList deployments) {
+ if (deployments == null || deploymentOverview == null) {
+ return;
+ }
+ ArrayList recordingPeriods = deploymentOverview.getRecordingPeriods();
+ for (RecordingPeriod aPeriod : recordingPeriods) {
+ PDeployment closestDeployment = findClosestDeployment(aPeriod, deployments);
+ aPeriod.setMatchedTethysDeployment(closestDeployment);
+ if (closestDeployment != null) {
+ closestDeployment.setMatchedPAMGaurdPeriod(aPeriod);
+ }
+ }
+ }
+
+ /**
+ * find the Tethys deployment that most closely matches the PAMGuard recording period.
+ * @param aPeriod
+ * @param deployments
+ * @return
+ */
+ private PDeployment findClosestDeployment(RecordingPeriod aPeriod, ArrayList deployments) {
+ double overlap = -1;
+ PDeployment bestDeployment = null;
+ for (PDeployment aDeployment : deployments) {
+ double newOverlap = getDeploymentOverlap(aDeployment, aPeriod);
+ if (newOverlap > overlap) {
+ bestDeployment = aDeployment;
+ overlap = newOverlap;
+ }
+ }
+ return bestDeployment;
+ }
+
+ /**
+ * Get the overlap in mills between a nilus Deployment and a PAMGuard recording period
+ * @param aDeployment nilus Deployment from Tethys
+ * @param aPeriod PAMGuard recording period
+ * @return overlap in milliseconds
+ */
+ public long getDeploymentOverlap(PDeployment aDeployment, RecordingPeriod aPeriod) {
+ long start = aPeriod.getRecordStart(); // recording period.
+ long stop = aPeriod.getRecordStop();
+ Long depStart = aDeployment.getAudioStart();
+ Long depStop = aDeployment.getAudioEnd();
+ if (depStart == null || depStop == null) {
+ return -1;
+ }
+ long overlap = (Math.min(stop, depStop)-Math.max(start, depStart));
+ return overlap;
+ }
+
+
+
+
+ /**
+ * Get a list of Tethys Deployment docs that match the current PAMGuard data. Watch for repeats
+ * if a single deployment doc covers many perdiods.
+ * @return
+ */
+ public ArrayList getMatchedDeployments() {
+ ArrayList matched = new ArrayList<>();
+ if (deploymentOverview == null) {
+ return matched;
+ }
+ for (RecordingPeriod period : deploymentOverview.getRecordingPeriods()) {
+ PDeployment deployment = period.getMatchedTethysDeployment();
+ if (deployment != null) {
+ if (matched.contains(deployment) == false) {
+ matched.add(period.getMatchedTethysDeployment());
+ }
+ }
+ }
+ return matched;
+ }
+
+ /**
+ * Get a list of instruments from the current project deployments.
+ * This may be a shorter list than the list of deployments.
+ * @return
+ */
+ public ArrayList getProjectInstruments() {
+ if (projectDeployments == null) {
+ return null;
+ }
+ ArrayList instruments = new ArrayList<>();
+ for (PDeployment aDepl : projectDeployments) {
+ Instrument intr = aDepl.deployment.getInstrument();
+ if (intr == null) {
+ continue;
+ }
+ PInstrument pInstr = new PInstrument(intr.getType(), intr.getInstrumentId());
+ if (instruments.contains(pInstr) == false) {
+ instruments.add(pInstr);
+ }
+ }
+ return instruments;
+ }
+ //in each channel
+// public ArrayList getDeployments() {
+//
+// DeploymentOverview recordingOverview = this.deploymentOverview;
+//
+// // first find an acquisition module.
+// PamControlledUnit aModule = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
+// if (!(aModule instanceof AcquisitionControl)) {
+// // will return if it's null. Impossible for it to be the wrong type.
+// // but it's good practice to check anyway before casting.
+// return null;
+// }
+// // cast it to the right type.
+// AcquisitionControl daqControl = (AcquisitionControl) aModule;
+// AcquisitionParameters daqParams = daqControl.getAcquisitionParameters();
+// /**
+// * The daqParams class has most of what we need about the set up in terms of sample rate,
+// * number of channels, instrument type, ADC input range (part of calibration), etc.
+// * It also has a hydrophone list, which maps the input channel numbers to the hydrophon numbers.
+// * Realistically, this list is always 0,1,2,etc or it goes horribly wrong !
+// */
+// // so write functions here to get information from the daqParams.
+//// System.out.printf("Sample regime: %s input with rate %3.1fHz, %d channels, gain %3.1fdB, ADCp-p %3.1fV\n", daqParams.getDaqSystemType(),
+//// daqParams.getSampleRate(), daqParams.getNChannels(), daqParams.preamplifier.getGain(), daqParams.voltsPeak2Peak);
+// /**
+// * then there is the actual sampling. This is a bit harder to find. I thought it would be in the data map
+// * but the datamap is a simple count of what's in the databasase which is not quite what we want.
+// * we're going to have to query the database to get more detailed informatoin I think.
+// * I'll do that here for now, but we may want to move this when we better organise the code.
+// * It also seems that there are 'bad' dates in the database when it starts new files, which are the date
+// * data were analysed at. So we really need to check the start and stop records only.
+// */
+// PamDataBlock daqInfoDataBlock = daqControl.getAcquisitionProcess().getDaqStatusDataBlock();
+// // just load everything. Probably OK for the acqusition, but will bring down
+// daqInfoDataBlock.loadViewerData(0, Long.MAX_VALUE, null);
+// ArrayList allStatusData = daqInfoDataBlock.getDataCopy();
+// long dataStart = Long.MAX_VALUE;
+// long dataEnd = Long.MIN_VALUE;
+// if (allStatusData != null && allStatusData.size() > 0) {
+// // find the number of times it started and stopped ....
+// int nStart = 0, nStop = 0, nFile=0;
+// for (DaqStatusDataUnit daqStatus : allStatusData) {
+// switch (daqStatus.getStatus()) {
+// case "Start":
+// nStart++;
+// dataStart = Math.min(dataStart, daqStatus.getTimeMilliseconds());
+// break;
+// case "Stop":
+// nStop++;
+// dataEnd = Math.max(dataEnd, daqStatus.getEndTimeInMilliseconds());
+// break;
+// case "NextFile":
+// nFile++;
+// break;
+// }
+// }
+//
+//// System.out.printf("Input map of sound data indicates data from %s to %s with %d starts and %d stops over %d files\n",
+//// PamCalendar.formatDateTime(dataStart), PamCalendar.formatDateTime(dataEnd), nStart, nStop, nFile+1);
+//
+// }
+//
+//// // and we find the datamap within that ...
+//// OfflineDataMap daqMap = daqInfoDataBlock.getOfflineDataMap(DBControlUnit.findDatabaseControl());
+//// if (daqMap != null) {
+//// // iterate through it.
+//// long dataStart = daqMap.getFirstDataTime();
+//// long dataEnd = daqMap.getLastDataTime();
+//// List mapPoints = daqMap.getMapPoints();
+//// System.out.printf("Input map of sound data indicates data from %s to %s with %d individual files\n",
+//// PamCalendar.formatDateTime(dataStart), PamCalendar.formatDateTime(dataEnd), mapPoints.size());
+//// /*
+//// * clearly in the first database I've been looking at of Tinas data, this is NOT getting sensible start and
+//// * end times. Print them out to see what's going on.
+//// */
+////// for ()
+//// }
+// DeploymentRecoveryPair pair = new DeploymentRecoveryPair();
+// DeploymentRecoveryDetails deployment = new DeploymentRecoveryDetails();
+// DeploymentRecoveryDetails recovery = new DeploymentRecoveryDetails();
+// pair.deploymentDetails = deployment;
+// pair.recoveryDetails = recovery;
+//
+// deployment.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataStart));
+// deployment.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataStart));
+// recovery.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataEnd));
+// recovery.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataEnd));
+//
+// ArrayList drPairs = new ArrayList<>();
+// drPairs.add(pair);
+// return drPairs;
+//
+// }
+
+ /**
+ * Get the first free deploymendId. This will get appended to
+ * the ProjectName to make and id for each Deployment document
+ * @return
+ */
+ public int getFirstFreeDeploymentId() {
+ /**
+ * This is an integer used for the DeploymentId. Note that the String Id (currentl9) is just the Project name
+ * appended with this number.
+ */
+ int firstFree = 0;
+ if (projectDeployments != null) {
+ for (PDeployment dep : projectDeployments) {
+ firstFree = Math.max(firstFree, dep.deployment.getDeploymentId()+1);
+ }
+ }
+ return firstFree;
+ }
+
+ public Deployment createDeploymentDocument(int i, RecordingPeriod recordingPeriod, String deploymentId) {
+ Deployment deployment = new Deployment();
+ try {
+ nilus.Helper.createRequiredElements(deployment);
+ } catch (IllegalArgumentException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (InstantiationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ PamguardMetaData pamguardMetaData = MetaDataContol.getMetaDataControl().getMetaData();
+ Deployment templateDeployment = pamguardMetaData.getDeployment();
+
+// Deployment globalDeplData = tethysControl.getGlobalDeplopymentData();
+ deployment.setId(deploymentId);
+ deployment.setDeploymentId(i);
+
+ DeploymentRecoveryDetails deploymentDetails = deployment.getDeploymentDetails();
+ if (deploymentDetails == null) {
+ deploymentDetails = new DeploymentRecoveryDetails();
+ }
+ DeploymentRecoveryDetails recoveryDetails = deployment.getRecoveryDetails();
+ if (recoveryDetails == null) {
+ recoveryDetails = new DeploymentRecoveryDetails();
+ }
+
+ deploymentDetails.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStart()));
+ recoveryDetails.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStop()));
+ // handle situation where deployment and recovery times are not the same as the audio times.
+ if (pamguardMetaData.useAudioForDeploymentTimes == false) {
+ if (templateDeployment.getDeploymentDetails().getAudioTimeStamp() != null) {
+ deploymentDetails.setTimeStamp(templateDeployment.getDeploymentDetails().getAudioTimeStamp());
+ }
+ if (templateDeployment.getRecoveryDetails().getAudioTimeStamp() != null) {
+ recoveryDetails.setTimeStamp(templateDeployment.getRecoveryDetails().getAudioTimeStamp());
+ }
+ }
+
+ deploymentDetails.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStart()));
+ recoveryDetails.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStop()));
+
+ deployment.setDeploymentDetails(deploymentDetails);
+ deployment.setRecoveryDetails(recoveryDetails);
+
+ getProjectData(deployment);
+
+ TethysLocationFuncs.getTrackAndPositionData(deployment);
+
+ getTrackDetails(deployment);
+
+ /**
+ * Get some of the meta data from the centralised source.
+ */
+ MetadataInfo metaData = templateDeployment.getMetadataInfo();
+ metaData.setDate(TethysTimeFuncs.xmlGregCalFromMillis(System.currentTimeMillis()));
+ metaData.setUpdateFrequency("as-needed");
+ deployment.setMetadataInfo(metaData);
+
+ deployment.setDescription(templateDeployment.getDescription());
+// DescriptionType description = deployment.getDescription();
+// if (description == null ) {
+// description = new DescriptionType();
+// deployment.setDescription(description);
+// description.setAbstract("No abstract");
+// description.setMethod("no methods");
+// description.setObjectives("No objectives");
+// }
+// description.set
+
+ addSamplingDetails(deployment, recordingPeriod);
+
+ getSensorDetails(deployment);
+
+ getSensors(deployment);
+
+ /**
+ * Stuff that may need to be put into the UI:
+ * Audio: can easily get current loc of raw and binary data, but may need to override these. I think
+ * this may be for the export UI ?
+ * Tracks: trackline information. General problem in PAMGUard.
+ */
+ getDataDetails(deployment);
+
+
+ return deployment;
+ }
+
+ /**
+ * Add the track to the deployment, if there is one (i.e. not for
+ * a fixed sensor).
+ * @param deployment
+ */
+ private void getTrackDetails(Deployment deployment) {
+ TrackInformation trackInfo = getTrackInformation();
+ if (trackInfo.haveGPSTrack() == false) {
+ return;
+ }
+ GPSDataBlock gpsDataBlock = (GPSDataBlock) trackInfo.getGpsDataMap().getParentDataBlock();
+ if (gpsDataBlock == null) {
+ return;
+ }
+ /*
+ * should have some track information. Do a load from the
+ * database for the whole deployment. this may be the entire GPS record, but
+ * we should be able to cope with that.
+ */
+ long trackStart = TethysTimeFuncs.millisFromGregorianXML(deployment.getDeploymentDetails().getTimeStamp());
+ long trackEnd = TethysTimeFuncs.millisFromGregorianXML(deployment.getRecoveryDetails().getTimeStamp());
+ long dataWin =(long) (Math.max(1./trackInfo.getGPSDataRate(), deploymentExportOptions.trackPointInterval));
+
+ // get the tracks object.
+ Tracks tracks = deployment.getData().getTracks();
+ if (tracks == null) {
+ tracks = new Tracks();
+ deployment.getData().setTracks(tracks);
+ }
+ List trackList = tracks.getTrack(); // lists are usually there.
+
+ Track aTrack = new Track();
+ trackList.add(aTrack);
+ List points = aTrack.getPoint();
+
+ gpsDataBlock.loadViewerData(trackStart-dataWin, trackEnd+dataWin, null);
+ long lastPointTime = 0;
+ ListIterator it = gpsDataBlock.getListIterator(0);
+ while (it.hasNext()) {
+ GpsDataUnit gpsDataUnit = it.next();
+ if (gpsDataUnit.getTimeMilliseconds()-lastPointTime < deploymentExportOptions.trackPointInterval*1000) {
+ continue;
+ }
+ GpsData gpsData = gpsDataUnit.getGpsData();
+ Point gpsPoint = new Point();
+ gpsPoint.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(gpsDataUnit.getTimeMilliseconds()));
+ gpsPoint.setLatitude(gpsData.getLatitude());
+ gpsPoint.setLongitude(PamUtils.constrainedAngle(gpsData.getLongitude()));
+ BearingDegN bdn = gpsPoint.getBearingDegN();
+ if (bdn == null) {
+ bdn = new BearingDegN();
+ gpsPoint.setBearingDegN(bdn);
+ }
+ bdn.setValue(AutoTethysProvider.roundDecimalPlaces(PamUtils.constrainedAngle(gpsData.getHeading()),1));
+ gpsPoint.setSpeedKn(AutoTethysProvider.roundDecimalPlaces(gpsData.getSpeed(),2));
+
+ points.add(gpsPoint);
+ lastPointTime = gpsDataUnit.getTimeMilliseconds();
+ }
+ }
+
+ public String getBinaryDataURI() {
+ BinaryStore binStore = BinaryStore.findBinaryStoreControl();
+ if (binStore != null) {
+ return binStore.getBinaryStoreSettings().getStoreLocation();
+ }
+ return null;
+ }
+
+ public String getDatabaseURI() {
+ DBControlUnit databaseControl = DBControlUnit.findDatabaseControl();
+ if (databaseControl != null) {
+ return databaseControl.getLongDatabaseName();
+ }
+ return null;
+ }
+
+ public String getRawDataURI() {
+ try {
+ PamControlledUnit daq = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
+ if (daq instanceof AcquisitionControl) {
+ AcquisitionControl daqCtrl = (AcquisitionControl) daq;
+ DaqSystem system = daqCtrl.findDaqSystem(null);// getAcquisitionProcess().getRunningSystem();
+ if (system instanceof FolderInputSystem) {
+ FolderInputSystem fip = (FolderInputSystem) system;
+ return fip.getFolderInputParameters().recentFiles.get(0);
+ }
+ }
+ }
+ catch (Exception e) {
+ }
+ return "unknown";
+ }
+
+ private void getDataDetails(Deployment deployment) {
+ Data data = deployment.getData();
+ if (data == null) {
+ data = new Data();
+ deployment.setData(data);
+ }
+ nilus.Deployment.Data.Audio audio = data.getAudio();
+ if (audio == null) {
+ audio = new nilus.Deployment.Data.Audio();
+ data.setAudio(audio);
+ }
+ audio.setURI(getRawDataURI());
+ String processed = "Database:"+getDatabaseURI();
+ String binary = getBinaryDataURI();
+ if (binary != null) {
+ binary += ";Binary:"+binary;
+ }
+ audio.setProcessed(processed);
+
+ }
+
+ /**
+ * Get sensor information. The Soundtrap CTD will count as a sensor.
+ * Modules that are sensors will have to implement a PAMSensor interface
+ * @param deployment
+ */
+ private void getSensors(Deployment deployment) {
+ ArrayList sensorModules = PamController.getInstance().findControlledUnits(PamSensor.class, true);
+ if (sensorModules == null || sensorModules.size() == 0) {
+ return;
+ }
+ Sensors sensors = deployment.getSensors();
+ if (sensors == null) {
+ sensors = new Sensors();
+ deployment.setSensors(sensors);
+ }
+ List sensorList = sensors.getSensor();
+ for (PamControlledUnit aUnit : sensorModules) {
+ PamSensor pamSensor = (PamSensor) aUnit;
+ UnknownSensor nilusSensor = new UnknownSensor();
+ try {
+ Helper.createRequiredElements(nilusSensor);
+ } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+// nilusSensor.setName(pamSensor.getUnitName());
+ nilusSensor.setType(pamSensor.getUnitType());
+ nilusSensor.setNumber(BigInteger.ZERO);
+ nilusSensor.setDescription(pamSensor.getSensorDescription());
+ nilusSensor.setSensorId(pamSensor.getUnitType());
+
+ sensorList.add(nilusSensor);
+ }
+ }
+
+ /**
+ * Add project Metadata to a Deploymnet document. This is currently being
+ * made available in the MetaDataControl module which should be added to PAMGuard
+ * as well as the Tethys output module.
+ * @param deployment
+ */
+ private boolean getProjectData(Deployment deployment) {
+// PamControlledUnit aUnit = PamController.getInstance().findControlledUnit(MetaDataContol.class, null);
+// if (aUnit instanceof MetaDataContol == false || true) {
+// deployment.setProject("thisIsAProject");
+// deployment.setPlatform("Yay a platform");
+// Instrument instrument = new Instrument();
+// instrument.setType("machiney");
+// instrument.setInstrumentId("12345555");
+// deployment.setInstrument(instrument);
+// return false;
+// }
+//
+// MetaDataContol metaControl = (MetaDataContol) aUnit;
+ PamguardMetaData metaData = MetaDataContol.getMetaDataControl().getMetaData();
+ Deployment deploymentData = tethysControl.getGlobalDeplopymentData();
+ deployment.setProject(deploymentData.getProject());
+ deployment.setDeploymentAlias(deploymentData.getDeploymentAlias());
+ deployment.setSite(deploymentData.getSite());
+ deployment.setCruise(deploymentData.getCruise());
+ deployment.setPlatform(getPlatform());
+ deployment.setRegion(deploymentData.getRegion());
+ Instrument instrument = new Instrument();
+ instrument.setType(getInstrumentType());
+ instrument.setInstrumentId(getInstrumentId());
+ // get the geometry type from the array manager.
+ String geomType = getGeometryType();
+ instrument.setGeometryType(geomType);
+ deployment.setInstrument(instrument);
+
+ // overwrite the default deployment and recovery times if there is non null data
+ XMLGregorianCalendar depTime = deploymentData.getDeploymentDetails().getTimeStamp();
+ if (depTime != null) {
+ deployment.getDeploymentDetails().setTimeStamp(depTime);
+ }
+ if (deploymentData.getRecoveryDetails() != null) {
+ XMLGregorianCalendar recMillis = deploymentData.getRecoveryDetails().getTimeStamp();
+ if (recMillis != null) {
+ deployment.getRecoveryDetails().setTimeStamp(recMillis);
+ }
+ double recLat = deploymentData.getRecoveryDetails().getLatitude();
+ double recLong = deploymentData.getRecoveryDetails().getLongitude();
+ if (recLat != 0 & recLong != 0.) {
+ deployment.getRecoveryDetails().setLatitude(recLat);
+ deployment.getRecoveryDetails().setLongitude(PamUtils.constrainedAngle(recLong));
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Instrument identifier, e.g. serial number
+ * @return
+ */
+ private String getInstrumentId() {
+ return ArrayManager.getArrayManager().getCurrentArray().getInstrumentId();
+ }
+
+ /**
+ * Test to see if it's possible to export Deployment documents. This is basically a test of
+ * various metadata fields that are required, such as instrument id's.
+ * @return null if OK, or a string describing the first encountered error
+ */
+ public String canExportDeployments() {
+
+ Deployment globalDeplData = tethysControl.getGlobalDeplopymentData();
+ if (globalDeplData.getProject() == null) {
+ return "You must set a project name";
+ }
+
+ PInstrument arrayInstrument = getCurrentArrayInstrument();
+ if (arrayInstrument == null) {
+ return "No 'Instrument' set. Goto array manager";
+ }
+ return null;
+ }
+
+ /**
+ * Get the Instrument info for the current array.
+ * @return
+ */
+ public PInstrument getCurrentArrayInstrument() {
+ PamArray currentArray = ArrayManager.getArrayManager().getCurrentArray();
+ String currType = currentArray.getInstrumentType();
+ String currId = currentArray.getInstrumentId();
+ PInstrument currentInstrument = null;
+ if (currType != null || currId != null) {
+ currentInstrument = new PInstrument(currType, currId);
+ }
+ return currentInstrument;
+ }
+
+ /**
+ * On what platform is the instrument deployed? (e.g. mooring, tag)
+ * @return
+ */
+ private String getPlatform() {
+ return getGeometryType();
+ }
+ /**
+ * Instrument type, e.g. HARP, EAR, Popup, DMON, Rock Hopper, etc.
+ * @return
+ */
+ private String getInstrumentType() {
+ return ArrayManager.getArrayManager().getCurrentArray().getInstrumentType();
+ }
+
+ /**
+ * Get a geometry type string for Tethys based on information in the array manager.
+ * @return
+ */
+ private String getGeometryType() {
+ PamArray array = ArrayManager.getArrayManager().getCurrentArray();
+ int nStreamer = array.getStreamerCount();
+ for (int i = 0; i < nStreamer; i++) {
+ Streamer streamer = array.getStreamer(i);
+ HydrophoneLocator locator = streamer.getHydrophoneLocator();
+ if (locator == null) {
+ continue;
+ }
+ if (locator instanceof ThreadingHydrophoneLocator) {
+ return "cabled";
+ }
+ else {
+ return "rigid";
+ }
+ }
+ return "unknown";
+ }
+
+ private boolean getSensorDetails(Deployment deployment) {
+ PamArray array = ArrayManager.getArrayManager().getCurrentArray();
+ Sensors sensors = new Sensors();
+ List audioList = sensors.getAudio();
+ ArrayList phones = array.getHydrophoneArray();
+ int iPhone = 0;
+ long timeMillis = TethysTimeFuncs.millisFromGregorianXML(deployment.getDeploymentDetails().getAudioTimeStamp());
+ CalibrationHandler calibrationHandler = tethysControl.getCalibrationHandler();
+
+ for (Hydrophone aPhone : phones) {
+ PamVector hydLocs = array.getAbsHydrophoneVector(iPhone, timeMillis);
+ Audio audio = new Audio();
+ audio.setNumber(BigInteger.valueOf(iPhone));
+ String id = calibrationHandler.getHydrophoneId(iPhone);
+// audio.setSensorId(String.format("Hydrophone %d", iPhone)); // should replace with serial number if it exists.
+ audio.setSensorId(id);
+ GeometryTypeM geom = new GeometryTypeM();
+ geom.setXM(hydLocs.getCoordinate(0));
+ geom.setYM(hydLocs.getCoordinate(1));
+ geom.setZM(hydLocs.getCoordinate(2));
+// Geometry geom = new Geometry();
+// audio.setGeometry(geom);
+//// nilusHelper.
+// List geomCont = geom.getContent();
+// for (int iCoord = 0; iCoord < 3; iCoord++) {
+// geom.getContent().add(Double.valueOf(hydLocs.getCoordinate(iCoord)));
+// }
+// try {
+// MarshalXML mXML = new MarshalXML();
+// mXML.marshal(geom);
+// } catch (JAXBException e) {
+// // TODO Auto-generated catch block
+// e.printStackTrace();
+// }
+ /**
+ * Need to be able to add the values from hydLocs to the geometry object, but can't.
+ */
+ audioList.add(audio);
+ iPhone++;
+ }
+// try {
+// MarshalXML mXML = new MarshalXML();
+// mXML.marshal(sensors);
+// } catch (JAXBException e) {
+// // TODO Auto-generated catch block
+// e.printStackTrace();
+// }
+ deployment.setSensors(sensors);
+ return true;
+ }
+
+ /**
+ * Fill in the sampling details in a Deployment document.
+ * @param deployment
+ * @param recordingPeriod
+ */
+ private boolean addSamplingDetails(Deployment deployment, RecordingPeriod recordingPeriod) {
+
+ SamplingDetails samplingDetails = deployment.getSamplingDetails();
+ if (samplingDetails == null) {
+ samplingDetails = new SamplingDetails();
+ deployment.setSamplingDetails(samplingDetails);
+ }
+ // this is basically going to be a list of almost identical channel information
+ // currently just for the first acquisition. May extend to more.
+ // see if there is > 1 acquisition. May want to include many.
+ ArrayList daqUnits = PamController.getInstance().findControlledUnits(AcquisitionControl.class);
+
+ AcquisitionControl daq = (AcquisitionControl) PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
+ if (daq == null) {
+ return false;
+ }
+ DaqSystem system = daq.findDaqSystem(null);
+ AcquisitionParameters daqParams = daq.acquisitionParameters;
+ int nChan = daqParams.nChannels;
+ float fs = daqParams.sampleRate;
+ int[] hydroMap = daqParams.getHydrophoneList();
+ int[] inputMap = daqParams.getHardwareChannelList();
+ double vp2p = daqParams.getVoltsPeak2Peak();
+
+ List channelInfos = samplingDetails.getChannel();
+ for (int i = 0; i < nChan; i++) {
+ ChannelInfo channelInfo = new ChannelInfo();
+ channelInfo.setStart(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStart()));
+ channelInfo.setEnd(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStop()));
+
+ BigIntegerConverter biCon = new BigIntegerConverter();
+ BigInteger chanNum = BigInteger.valueOf(i);
+ channelInfo.setChannelNumber(chanNum);
+ if (hydroMap != null) {
+ channelInfo.setSensorNumber(hydroMap[i]);
+ }
+ else {
+ channelInfo.setSensorNumber(i);
+ }
+ /*
+ * Gain - may have to cycle through and see if this ever changes (or
+ * if was recorded that it changed which may not be the same!)
+ */
+ ChannelInfo.Gain gain = new ChannelInfo.Gain();
+ List gainList = gain.getRegimen();
+ nilus.ChannelInfo.Gain.Regimen aGain = new nilus.ChannelInfo.Gain.Regimen();
+ aGain.setGainDB(daqParams.getPreamplifier().getGain());
+ channelInfo.setGain(gain);
+
+ Sampling sampling = new Sampling();
+ List regimens = sampling.getRegimen();
+ Sampling.Regimen regimen = new Sampling.Regimen();
+ regimen.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(recordingPeriod.getRecordStart()));
+ regimen.setSampleRateKHz(fs/1000.);
+ if (system != null) {
+ regimen.setSampleBits(system.getSampleBits());
+ }
+ regimens.add(regimen);
+
+ DutyCycleInfo dutyCycleInf = deploymentOverview.getDutyCycleInfo();
+ boolean isDS = dutyCycleInf != null && dutyCycleInf.isDutyCycled;
+ if (isDS) {
+ DutyCycle dutyCycle = new DutyCycle();
+ List reg = dutyCycle.getRegimen();
+ nilus.ChannelInfo.DutyCycle.Regimen dsr = new nilus.ChannelInfo.DutyCycle.Regimen();
+ reg.add(dsr);
+ RecordingDurationS ssss = new RecordingDurationS();
+ // round to a second ... or .1s if short duty cycle.
+ int dp = 1;
+ if (dutyCycleInf.meanOnTimeS > 59) {
+ dp = 0;
+ }
+ ssss.setValue(AutoTethysProvider.roundDecimalPlaces(dutyCycleInf.meanOnTimeS,dp));
+ dsr.setRecordingDurationS(ssss);
+ RecordingIntervalS ris = new RecordingIntervalS();
+ ris.setValue(AutoTethysProvider.roundDecimalPlaces(dutyCycleInf.meanOnTimeS + dutyCycleInf.meanGapS,dp));
+ dsr.setRecordingIntervalS(ris);
+ dsr.setTimeStamp(deployment.getDeploymentDetails().getAudioTimeStamp());
+ channelInfo.setDutyCycle(dutyCycle);
+ }
+
+ channelInfo.setSampling(sampling);
+
+ channelInfos.add(channelInfo);
+
+ /**
+ * Need something about duty cycling. this is probably something that will have to be added
+ * earlier to a wrapper around the Deployment class.
+ */
+ }
+ return true;
+ }
+
+ @Override
+ public void selectionChanged() {
+ // TODO Auto-generated method stub
+
+ }
+
+ private class SettingsHandler implements PamSettings {
+
+ @Override
+ public String getUnitName() {
+ return tethysControl.getUnitName();
+ }
+
+ @Override
+ public String getUnitType() {
+ return "Tethys Deployment Handler";
+ }
+
+ @Override
+ public Serializable getSettingsReference() {
+ return deploymentExportOptions;
+ }
+
+ @Override
+ public long getSettingsVersion() {
+ return DeploymentExportOpts.serialVersionUID;
+ }
+
+ @Override
+ public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
+ deploymentExportOptions = (DeploymentExportOpts) pamControlledUnitSettings.getSettings();
+ return true;
+ }
+
+ }
+
+ /**
+ * @return the deploymentExportOptions
+ */
+ public DeploymentExportOpts getDeploymentExportOptions() {
+ return deploymentExportOptions;
+ }
+
+}
diff --git a/src/tethys/deployment/DeploymentOverview.java b/src/tethys/deployment/DeploymentOverview.java
new file mode 100644
index 00000000..f296df8e
--- /dev/null
+++ b/src/tethys/deployment/DeploymentOverview.java
@@ -0,0 +1,80 @@
+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;
+
+/**
+ * Class to give a general overview of all the effort in PAMGuard which will form the
+ * basis for Deployment Documents.
+ * This will tell us if data were on a regular duty cycle or more adhoc and also provide
+ * a list of all start and end times for these periods.
+ * @author dg50
+ *
+ */
+public class DeploymentOverview {
+
+ private ArrayList recordingPeriods = new ArrayList<>();
+
+ private 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));
+ }
+
+ private void addRecordingPeriod(RecordingPeriod recordingPeriod) {
+ recordingPeriods.add(recordingPeriod);
+ }
+
+ public ArrayList getRecordingPeriods() {
+ return recordingPeriods;
+ }
+
+ public DutyCycleInfo getDutyCycleInfo() {
+ return dutyCycleInfo;
+ }
+
+ /**
+ * Get the start time of the first recording
+ * @return
+ */
+ public Long getFirstStart() {
+ if (recordingPeriods.size() > 0) {
+ return recordingPeriods.get(0).getRecordStart();
+ }
+ 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();
+ }
+ return null;
+ }
+
+
+
+}
diff --git a/src/tethys/deployment/DeploymentRecoveryPair.java b/src/tethys/deployment/DeploymentRecoveryPair.java
new file mode 100644
index 00000000..8e168a2a
--- /dev/null
+++ b/src/tethys/deployment/DeploymentRecoveryPair.java
@@ -0,0 +1,11 @@
+package tethys.deployment;
+
+import nilus.DeploymentRecoveryDetails;
+
+public class DeploymentRecoveryPair {
+
+// public DeploymentRecoveryDetails deploymentDetails;
+//
+// public DeploymentRecoveryDetails recoveryDetails;
+
+}
diff --git a/src/tethys/deployment/DeploymentWrapper.java b/src/tethys/deployment/DeploymentWrapper.java
new file mode 100644
index 00000000..01126c92
--- /dev/null
+++ b/src/tethys/deployment/DeploymentWrapper.java
@@ -0,0 +1,85 @@
+package tethys.deployment;
+
+import java.io.ByteArrayOutputStream;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedType;
+import java.util.List;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.Marshaller;
+import javax.xml.namespace.QName;
+import javax.xml.validation.Schema;
+
+//import nilus.Deployment.Data.Audio;
+//import nilus.Deployment;
+//import nilus.Deployment.Data;
+//import nilus.Deployment.Instrument;
+
+public class DeploymentWrapper {
+
+ public DeploymentWrapper(T tethysObject) {
+
+ }
+
+ public List getFieldNames() {
+ return null;
+ }
+
+ public List getComplexObjects() {
+
+ return null;
+ }
+
+ public static void main(String[] args) {
+ // quick play with some JAXB objects to see what they can do.
+// Deployment deployment = new Deployment();
+//
+// Class extends Deployment> deploymentClass = deployment.getClass();
+// Annotation[] annots = deploymentClass.getAnnotations();
+// AnnotatedType[] annotInterfaces = deploymentClass.getAnnotatedInterfaces();
+// Annotation[] declAnnots = deploymentClass.getDeclaredAnnotations();
+//
+// Instrument instrument = new Instrument();
+// instrument.setID("22");
+// instrument.setType("SoundTrap");
+// QName qName = new QName("Instrument");
+// JAXBElement jInst = new JAXBElement(qName, Instrument.class, instrument);
+// deployment.getContent().add(jInst);
+//
+// Deployment.Data data = new Data();
+// Audio audio = new Audio();
+// audio.setProcessed("??");
+// data.setAudio(audio);
+// JAXBElement jData = new JAXBElement(new QName("Data"), Data.class, data);
+// deployment.getContent().add(jData);
+//
+// String project = "Project Name";
+// JAXBElement jProj = new JAXBElement(new QName("Project"), String.class, project);
+// deployment.getContent().add(jProj);
+//
+// String aaa = "Project Something else";
+// JAXBElement jProj2 = new JAXBElement(new QName("Region"), String.class, aaa);
+// deployment.getContent().add(jProj2);
+//
+//
+// try {
+// JAXBContext jContext = JAXBContext.newInstance(Deployment.class);
+// Marshaller mar = (Marshaller) jContext.createMarshaller();
+// mar.setProperty(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true);
+//
+// ByteArrayOutputStream bos = new ByteArrayOutputStream();
+// mar.marshal(deployment, bos);
+// String xml = new String(bos.toByteArray());
+// System.out.println(xml);
+//// Schema schema = mar.getSchema(); // is null. Can't generate it's own it seems.
+//
+// } catch (Exception e) {
+// // TODO Auto-generated catch block
+// e.printStackTrace();
+// }
+//
+ }
+
+}
diff --git a/src/tethys/deployment/DutyCycleInfo.java b/src/tethys/deployment/DutyCycleInfo.java
new file mode 100644
index 00000000..5bdbe89f
--- /dev/null
+++ b/src/tethys/deployment/DutyCycleInfo.java
@@ -0,0 +1,36 @@
+package tethys.deployment;
+
+import PamUtils.PamCalendar;
+
+public class DutyCycleInfo {
+
+ public boolean isDutyCycled;
+
+ public double meanOnTimeS;
+
+ public double meanGapS;
+
+ int nCycles;
+
+ public DutyCycleInfo(boolean isDutyCycled, double meanOnTimeS, double meanGapS, int nCycles) {
+ super();
+ this.isDutyCycled = isDutyCycled;
+ this.meanOnTimeS = meanOnTimeS;
+ this.meanGapS = meanGapS;
+ this.nCycles = nCycles;
+ }
+
+ @Override
+ public String toString() {
+ if (isDutyCycled == false) {
+ return "No duty cycle";
+ }
+ else {
+ return String.format("%s on, %s off, for %d cycles", PamCalendar.formatDuration((long) (meanOnTimeS*1000)),
+ PamCalendar.formatDuration((long) (meanGapS*1000)), nCycles);
+ }
+ }
+
+
+
+}
diff --git a/src/tethys/deployment/EffortFunctions.java b/src/tethys/deployment/EffortFunctions.java
new file mode 100644
index 00000000..2fd8f383
--- /dev/null
+++ b/src/tethys/deployment/EffortFunctions.java
@@ -0,0 +1,413 @@
+package tethys.deployment;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.ListIterator;
+
+import Acquisition.AcquisitionControl;
+import Acquisition.AcquisitionParameters;
+import Acquisition.DaqStatusDataUnit;
+import PamController.PamControlledUnit;
+import PamController.PamController;
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamRawDataBlock;
+import SoundRecorder.RecordingInfo;
+import binaryFileStorage.BinaryStore;
+import dataMap.OfflineDataMap;
+import dataMap.OfflineDataMapPoint;
+import pamMaths.STD;
+import tethys.TethysControl;
+import tethys.output.TethysExportParams;
+import tethys.pamdata.TethysDataProvider;
+
+/**
+ * functions for working out total effort and periods of recording from a variety of sources, which may be
+ * the recordings database, binary files, etc.
+ * @author dg50
+ *
+ */
+public class EffortFunctions {
+
+ private TethysControl tethysControl;
+
+
+ /**
+ * @param tethysControl
+ */
+ public EffortFunctions(TethysControl tethysControl) {
+ 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;
+ }
+
+
+ public DeploymentOverview makeRecordingOverview() {
+
+ RecordingList recordingPeriods = listSoundAcquisitionDatabase();
+
+ RecordingList binaryPeriods = listBinaryFiles();
+
+ long l1 = listDuration(recordingPeriods);
+ long l2 = listDuration(binaryPeriods);
+ if (listDuration(binaryPeriods) > listDuration(recordingPeriods)) {
+ recordingPeriods = binaryPeriods;
+ }
+
+ DeploymentOverview deploymentOverview = createOverview(recordingPeriods);
+
+ return deploymentOverview;
+ }
+
+ private long listDuration(RecordingList recordingList) {
+ if (recordingList == null) {
+ return -1;
+ }
+ return recordingList.duration();
+ }
+
+ public RecordingList listBinaryFiles() {
+ BinaryStore binaryStore = BinaryStore.findBinaryStoreControl();
+ if (binaryStore == null) {
+ return null;
+ }
+ RecordingList bestList = null;
+ ArrayList allBlocks = PamController.getInstance().getDataBlocks();
+ for (PamDataBlock aBlock : allBlocks) {
+ OfflineDataMap dataMap = aBlock.getOfflineDataMap(binaryStore);
+ if (dataMap == null) {
+ continue;
+ }
+ TethysDataProvider tethysProvider = aBlock.getTethysDataProvider(tethysControl);
+ if (tethysProvider == null) {
+ continue; // do we really need this ?
+ }
+ RecordingList blockList = listMapPoints(dataMap);
+ if (blockList == null) {
+ continue;
+ }
+ if (bestList == null) {
+ bestList = blockList;
+ }
+ else {
+ long l1 = bestList.duration();
+ long l2 = blockList.duration();
+ if (l2>l1) {
+ bestList = blockList;
+ }
+ }
+ }
+ bestList = mergeRecordings(bestList);
+ return bestList;
+ }
+
+
+ public RecordingList listMapPoints(OfflineDataMap dataMap) {
+ List mapPoints = dataMap.getMapPoints();
+ if (mapPoints == null) {
+ return null;
+ }
+ RecordingList periods = new RecordingList();
+ for (OfflineDataMapPoint mapPoint : mapPoints) {
+ periods.add(new RecordingPeriod(mapPoint.getStartTime(), mapPoint.getEndTime()));
+ }
+ return periods;
+ }
+
+
+
+ public RecordingList listSoundAcquisitionDatabase() {
+ // first find an acquisition module.
+ PamControlledUnit aModule = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
+ if (!(aModule instanceof AcquisitionControl)) {
+ // will return if it's null. Impossible for it to be the wrong type.
+ // but it's good practice to check anyway before casting.
+ return null;
+ }
+ // cast it to the right type.
+ AcquisitionControl daqControl = (AcquisitionControl) aModule;
+ AcquisitionParameters daqParams = daqControl.getAcquisitionParameters();
+ /**
+ * The daqParams class has most of what we need about the set up in terms of sample rate,
+ * number of channels, instrument type, ADC input range (part of calibration), etc.
+ * It also has a hydrophone list, which maps the input channel numbers to the hydrophon numbers.
+ * Realistically, this list is always 0,1,2,etc or it goes horribly wrong !
+ */
+ // so write functions here to get information from the daqParams.
+ // System.out.printf("Sample regime: %s input with rate %3.1fHz, %d channels, gain %3.1fdB, ADCp-p %3.1fV\n", daqParams.getDaqSystemType(),
+ // daqParams.getSampleRate(), daqParams.getNChannels(), daqParams.preamplifier.getGain(), daqParams.voltsPeak2Peak);
+ /**
+ * then there is the actual sampling. This is a bit harder to find. I thought it would be in the data map
+ * but the datamap is a simple count of what's in the databasase which is not quite what we want.
+ * we're going to have to query the database to get more detailed informatoin I think.
+ * I'll do that here for now, but we may want to move this when we better organise the code.
+ * It also seems that there are 'bad' dates in the database when it starts new files, which are the date
+ * data were analysed at. So we really need to check the start and stop records only.
+ */
+ PamDataBlock daqInfoDataBlock = daqControl.getAcquisitionProcess().getDaqStatusDataBlock();
+ // just load everything. Probably OK for the acqusition, but will bring down
+ daqInfoDataBlock.loadViewerData(0, Long.MAX_VALUE, null);
+ ArrayList allStatusData = daqInfoDataBlock.getDataCopy();
+ /**
+ * Due to weird file overlaps we need to resort this by id if we can.
+ *
+ */
+ Collections.sort(allStatusData, new Comparator() {
+
+ @Override
+ public int compare(DaqStatusDataUnit o1, DaqStatusDataUnit o2) {
+ if (o1.getDatabaseIndex() == 0) {
+ return (int) (o1.getTimeMilliseconds()-o2.getTimeMilliseconds());
+ }
+ return o1.getDatabaseIndex()-o2.getDatabaseIndex();
+ }
+ });
+
+ RecordingList tempPeriods = null;
+
+ if (allStatusData == null || allStatusData.size() == 0) {
+ System.out.println("Data appear to have no logged recording periods. Try to extract from raw audio ...");
+ tempPeriods = extractTimesFromFiles(daqControl);
+ }
+ else {
+ tempPeriods = extractTimesFromStatus(allStatusData);
+ }
+ if (tempPeriods == null || tempPeriods.size() == 0) {
+ System.out.println("Data appear to have no logged recording periods available either from the database or the raw recordings.");
+ tempPeriods = extractTimesFromOutputMaps();
+ }
+ if (tempPeriods == null || tempPeriods.size() == 0) {
+ System.out.println("Data appear to have no logged recording periods available either from the database or the raw recordings.");
+ return null;
+ }
+
+ int nPeriods = tempPeriods.size();
+ // int i = 0;
+ // for (RecordingPeriod aP : tempPeriods) {
+ // System.out.printf("Pre merge %d : %s to %s\n", i++, PamCalendar.formatDBDateTime(aP.getRecordStart()),
+ // 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;
+ }
+
+ 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;
+ }
+
+ /**
+ * 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);
+
+
+ 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
+ * @return
+ */
+ private RecordingList extractTimesFromOutputMaps() {
+ OfflineDataMap bestMap = null;
+ PamDataBlock bestBlock = null;
+ long firstStart = Long.MAX_VALUE;
+ long lastEnd = Long.MIN_VALUE;
+ ArrayList dataBlocks = PamController.getInstance().getDetectorDataBlocks();
+ for (PamDataBlock aBlock : dataBlocks) {
+ if (aBlock instanceof PamRawDataBlock) {
+ continue; // don't want acquisition !
+ }
+ OfflineDataMap dataMap = aBlock.getPrimaryDataMap();
+ if (dataMap == null) {
+ continue;
+ }
+ if (dataMap.getFirstDataTime() < firstStart && dataMap.getLastDataTime() > lastEnd) {
+ bestMap = dataMap;
+ bestBlock = aBlock;
+ firstStart = dataMap.getFirstDataTime();
+ lastEnd = dataMap.getLastDataTime();
+ }
+ }
+ if (bestMap == null) {
+ return null;
+ }
+ // get the times out of it.
+ RecordingList recPeriods = new RecordingList();
+ List mapPoints = bestMap.getMapPoints();
+ for (OfflineDataMapPoint mapPoint : mapPoints) {
+ recPeriods.add(new RecordingPeriod(mapPoint.getStartTime(), mapPoint.getEndTime()));
+ }
+ return recPeriods;
+ }
+
+ private RecordingList extractTimesFromStatus(ArrayList allStatusData) {
+ RecordingList tempPeriods = new RecordingList();
+ long dataStart = Long.MAX_VALUE;
+ long dataEnd = Long.MIN_VALUE;
+ Long lastStart = null;
+ int nStart = 0;
+ int nStop = 0;
+ int nFile = 0;
+ for (DaqStatusDataUnit daqStatus : allStatusData) {
+ switch (daqStatus.getStatus()) {
+ case "Start":
+ nStart++;
+ dataStart = Math.min(dataStart, daqStatus.getTimeMilliseconds());
+ lastStart = daqStatus.getTimeMilliseconds();
+ // System.out.println("Start at " + PamCalendar.formatDBDateTime(lastStart));
+ break;
+ case "Stop":
+ nStop++;
+ dataEnd = Math.max(dataEnd, daqStatus.getEndTimeInMilliseconds());
+ long lastEnd = daqStatus.getEndTimeInMilliseconds();
+ if (lastStart != null) {
+ // System.out.printf("Adding period %s to %s\n", PamCalendar.formatDBDateTime(lastStart),
+ // PamCalendar.formatDBDateTime(lastEnd));
+ tempPeriods.add(new RecordingPeriod(lastStart, lastEnd));
+ }
+ else {
+ // System.out.println("Skipping stop at " + PamCalendar.formatDBDateTime(lastEnd));
+ }
+ lastStart = null;
+ break;
+ case "NextFile":
+ nFile++;
+ break;
+ }
+ }
+ return tempPeriods;
+ }
+
+ private RecordingList extractTimesFromFiles(AcquisitionControl daqControl) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/src/tethys/deployment/PInstrument.java b/src/tethys/deployment/PInstrument.java
new file mode 100644
index 00000000..15fd3c31
--- /dev/null
+++ b/src/tethys/deployment/PInstrument.java
@@ -0,0 +1,49 @@
+package tethys.deployment;
+
+/**
+ * Class to handle instrument information
+ * @author dg50
+ *
+ */
+public class PInstrument {
+
+ public String instrumentType;
+
+ public String instrumentId;
+
+ public PInstrument(String instrumentType, String instrumentId) {
+ super();
+ this.instrumentType = instrumentType;
+ this.instrumentId = instrumentId;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof PInstrument == false) {
+ return false;
+ }
+ PInstrument other = (PInstrument) obj;
+ boolean eq = true;
+ if (this.instrumentType != null) {
+ eq &= this.instrumentType.equals(other.instrumentType);
+ }
+ if (this.instrumentId != null) {
+ eq &= this.instrumentId.equals(other.instrumentId);
+ }
+ if (other.instrumentType != null) {
+ eq &= other.instrumentType.equals(this.instrumentType);
+ }
+ if (other.instrumentId != null) {
+ eq &= other.instrumentId.equals(this.instrumentId);
+ }
+
+ return eq;
+
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s : %s", instrumentType == null ? "Undefined" : instrumentType, instrumentId);
+ }
+
+}
diff --git a/src/tethys/deployment/PamDeployment.java b/src/tethys/deployment/PamDeployment.java
new file mode 100644
index 00000000..24a17065
--- /dev/null
+++ b/src/tethys/deployment/PamDeployment.java
@@ -0,0 +1,64 @@
+package tethys.deployment;
+
+import java.io.Serializable;
+
+//import nilus.DeploymentRecoveryDetails;
+
+/**
+ * Wrapper and functions associated with the Tethys Deployment object which can
+ * exchange these with the PAMGuard database and display Everything is just held
+ * within a list, in no particular order, which getContent public
+ *
+ * This is from the Deployment JavaDoc. TBH it's pretty horrible, since it's possible to have
+ * more than one of each type of object in the list, so not sure what to do about that. Would be nicer
+ * as a HashTable. however we are where we're are for now. Start by focussing on getting the
+ * content saved for each type
+ *
+ * List getContent()
+ *
+ * Gets the value of the content property. This accessor method returns a
+ * reference to the live list,not a snapshot. Therefore any modification you
+ * make to the returned list will be present inside the JAXB object.This is why
+ * there is not a set method for the content property.
+ *
+ * For example, to add a new item, do as follows: getContent().add(newItem);
+ *
+ *
+ * Objects of the following type(s) are allowed in the list JAXBElement
+ * JAXBElement
+ * JAXBElement
+ * JAXBElement
+ * JAXBElement
+ * JAXBElement
+ * JAXBElement
+ * JAXBElement
+ * JAXBElement
+ * JAXBElement
+ * JAXBElement String
+ * JAXBElement
+ * JAXBElement
+ * JAXBElement
+ * JAXBElement
+ *
+ *
+ * @author dg50
+ *
+ */
+public class PamDeployment {
+
+ public PamDeployment() {
+
+ }
+//
+// public DeploymentRecoveryDetails getDeploymentRecoveryDetails() {
+// DeploymentRecoveryDetails drd = new DeploymentRecoveryDetails();
+//
+// return null;
+// }
+
+ private void ripApart(Serializable object) {
+ Class cls = object.getClass();
+// cls.get
+ }
+
+}
diff --git a/src/tethys/deployment/RecordingList.java b/src/tethys/deployment/RecordingList.java
new file mode 100644
index 00000000..34b41c1d
--- /dev/null
+++ b/src/tethys/deployment/RecordingList.java
@@ -0,0 +1,52 @@
+package tethys.deployment;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+
+public class RecordingList extends ArrayList {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Get the duration of the recording periods from start to end.
+ * @return
+ */
+ public long duration() {
+ return getEnd()-getStart();
+ }
+
+ /**
+ * Get the start of the first in the list.
+ * @return
+ */
+ public long getStart() {
+ if (size() == 0) {
+ return 0;
+ }
+ return get(0).getRecordStart();
+ }
+
+ /**
+ * get the end of the last in the list.
+ */
+ public long getEnd() {
+ if (size() == 0) {
+ return 0;
+ }
+ return get(size()-1).getRecordStop();
+ }
+
+ /**
+ * Sort the list in ascending order.
+ */
+ public void sort() {
+ Collections.sort(this, new Comparator() {
+
+ @Override
+ public int compare(RecordingPeriod o1, RecordingPeriod o2) {
+ return (int) Math.signum(o1.getRecordStart()-o2.getRecordStart());
+ }
+ });
+ }
+}
diff --git a/src/tethys/deployment/RecordingPeriod.java b/src/tethys/deployment/RecordingPeriod.java
new file mode 100644
index 00000000..ad010827
--- /dev/null
+++ b/src/tethys/deployment/RecordingPeriod.java
@@ -0,0 +1,75 @@
+package tethys.deployment;
+
+import tethys.niluswraps.PDeployment;
+
+public class RecordingPeriod {
+
+ private long recordStart;
+
+ private long recordStop;
+
+ private boolean selected; // selected in the table or elsewhere for export.
+ /**
+ * Reference to a matched nilus Deployment document retrieved
+ * from the database.
+ */
+ private PDeployment matchedTethysDeployment;
+
+ public RecordingPeriod(long recordStart, long recordStop) {
+ super();
+ this.recordStart = recordStart;
+ this.recordStop = recordStop;
+ }
+
+ public long getRecordStart() {
+ return recordStart;
+ }
+
+ public void setRecordStart(long recordStart) {
+ this.recordStart = recordStart;
+ }
+
+ public long getRecordStop() {
+ return recordStop;
+ }
+
+ public void setRecordStop(long recordStop) {
+ this.recordStop = recordStop;
+ }
+
+ public long getDuration() {
+ return recordStop-recordStart;
+ }
+
+ public PDeployment getMatchedTethysDeployment() {
+ return matchedTethysDeployment;
+ }
+
+ public void setMatchedTethysDeployment(PDeployment closestDeployment) {
+ this.matchedTethysDeployment = closestDeployment;
+ }
+
+ /**
+ * @return the selected
+ */
+ public boolean isSelected() {
+ return selected;
+ }
+
+ /**
+ * @param selected the selected to set
+ */
+ public void setSelected(boolean selected) {
+ this.selected = selected;
+ }
+
+ /**
+ * toggle the selected state
+ * @return the new state
+ */
+ public boolean toggleSelected() {
+ selected = !selected;
+ return selected;
+ }
+
+}
diff --git a/src/tethys/deployment/TrackInformation.java b/src/tethys/deployment/TrackInformation.java
new file mode 100644
index 00000000..1acb7ce9
--- /dev/null
+++ b/src/tethys/deployment/TrackInformation.java
@@ -0,0 +1,85 @@
+package tethys.deployment;
+
+import java.util.Iterator;
+
+import Array.HydrophoneLocator;
+import GPS.GPSDataBlock;
+import PamguardMVC.PamDataBlock;
+import dataMap.OfflineDataMap;
+import dataMap.OfflineDataMapPoint;
+
+/**
+ * Some general information about the track: whether it exists and
+ * the frequency of GPS points.
+ * @author dg50
+ *
+ */
+public class TrackInformation {
+
+ private HydrophoneLocator hydrophoneLocator;
+ private OfflineDataMap gpsDataMap;
+
+ public TrackInformation(OfflineDataMap gpsDataMap, HydrophoneLocator locator) {
+ this.gpsDataMap = gpsDataMap;
+ this.hydrophoneLocator = locator;
+ }
+
+ public boolean haveGPSTrack() {
+ if (gpsDataMap == null) {
+ return false;
+ }
+ return (gpsDataMap.getDataCount() > 0);
+ }
+
+ /**
+ * Get an estimate of the highest GPS data rate in points per second. This is obtained from the
+ * datamap, taking the highest rate for all data map points (typically an hour of
+ * database data).
+ * @return
+ */
+ public double getGPSDataRate() {
+ if (gpsDataMap == null) {
+ return 0;
+ }
+ GPSDataBlock gpsDataBlock = (GPSDataBlock) gpsDataMap.getParentDataBlock();
+ Iterator mPs = gpsDataMap.getListIterator();
+ double highRate = 0;
+ while (mPs.hasNext()) {
+ OfflineDataMapPoint mP = mPs.next();
+ int n = mP.getNDatas();
+ double dur = (mP.getEndTime()-mP.getStartTime())/1000.;
+ double rate = n/dur;
+ highRate = Math.max(highRate, rate);
+ }
+ return highRate;
+ }
+
+ /**
+ * @return the hydrophoneLocator
+ */
+ public HydrophoneLocator getHydrophoneLocator() {
+ return hydrophoneLocator;
+ }
+
+ /**
+ * @param hydrophoneLocator the hydrophoneLocator to set
+ */
+ public void setHydrophoneLocator(HydrophoneLocator hydrophoneLocator) {
+ this.hydrophoneLocator = hydrophoneLocator;
+ }
+
+ /**
+ * @return the gpsDataMap
+ */
+ public OfflineDataMap getGpsDataMap() {
+ return gpsDataMap;
+ }
+
+ /**
+ * @param gpsDataMap the gpsDataMap to set
+ */
+ public void setGpsDataMap(OfflineDataMap gpsDataMap) {
+ this.gpsDataMap = gpsDataMap;
+ }
+
+}
diff --git a/src/tethys/deployment/swing/DeploymentDataCard.java b/src/tethys/deployment/swing/DeploymentDataCard.java
new file mode 100644
index 00000000..57c41b4d
--- /dev/null
+++ b/src/tethys/deployment/swing/DeploymentDataCard.java
@@ -0,0 +1,103 @@
+package tethys.deployment.swing;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.ArrayList;
+
+import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+import javax.swing.border.TitledBorder;
+
+import PamController.OfflineDataStore;
+import PamController.PamController;
+import PamView.dialog.PamGridBagContraints;
+import PamView.wizard.PamWizard;
+import PamView.wizard.PamWizardCard;
+import nilus.Deployment;
+import tethys.TethysControl;
+import tethys.deployment.DeploymentExportOpts;
+import tethys.deployment.DeploymentHandler;
+
+public class DeploymentDataCard extends PamWizardCard {
+
+ private TethysControl tethysControl;
+ private DeploymentHandler deploymentHandler;
+
+ private JRadioButton exportOne, exportMany;
+
+ private JTextField[] dataStores;
+// private JTextField rawURI, binaryURI, databaseURI;
+ private ArrayList offlineDataStores;
+
+ public DeploymentDataCard(PamWizard pamWizard, TethysControl tethysControl) {
+ super(pamWizard, "Data");
+ this.tethysControl = tethysControl;
+ deploymentHandler = tethysControl.getDeploymentHandler();
+ ButtonGroup bg = new ButtonGroup();
+ exportOne = new JRadioButton("Export a single detection document for all data");
+ exportMany = new JRadioButton("Export separate documents for each ad-hoc recording period");
+ bg.add(exportOne);
+ bg.add(exportMany);
+
+ JPanel optsPanel = new JPanel(new GridBagLayout());
+ optsPanel.setBorder(new TitledBorder("Number of documents"));
+ GridBagConstraints c = new PamGridBagContraints();
+ optsPanel.add(exportOne, c);
+ c.gridy++;
+ optsPanel.add(exportMany, c);
+
+ JPanel dataPanel = new JPanel(new GridBagLayout());
+ dataPanel.setBorder(new TitledBorder("Data location"));
+
+ // automatically generate fields for every offline data store.
+ offlineDataStores = PamController.getInstance().findOfflineDataStores();
+ dataStores = new JTextField[offlineDataStores.size()];
+ c = new PamGridBagContraints();
+ for (int i = 0; i < offlineDataStores.size(); i++) {
+ OfflineDataStore aStore = offlineDataStores.get(i);
+ dataPanel.add(new JLabel(aStore.getDataSourceName() + " ", JLabel.RIGHT), c);
+ c.gridx++;
+ dataStores[i] = new JTextField(40);
+ dataPanel.add(dataStores[i], c);
+ c.gridx = 0;
+ c.gridy++;
+ }
+
+ this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+ this.add(optsPanel);
+ this.add(dataPanel);
+ }
+
+
+ @Override
+ public boolean getParams(Object cardParams) {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+ @Override
+ public void setParams(Object cardParams) {
+ for (int i = 0; i < offlineDataStores.size(); i++) {
+ OfflineDataStore aStore = offlineDataStores.get(i);
+ dataStores[i].setText(aStore.getDataLocation());
+ }
+
+ }
+
+ public boolean getParams(DeploymentExportOpts exportOptions, Deployment deployment) {
+ exportOptions.separateDeployments = exportMany.isSelected();
+ return true;
+ }
+
+ public void setParams(DeploymentExportOpts exportOptions, Deployment deployment) {
+ exportOne.setSelected(exportOptions.separateDeployments == false);
+ exportMany.setSelected(exportOptions.separateDeployments == true);
+ setParams(deployment);
+ }
+
+}
diff --git a/src/tethys/deployment/swing/DeploymentInfoCard.java b/src/tethys/deployment/swing/DeploymentInfoCard.java
new file mode 100644
index 00000000..f8d7938e
--- /dev/null
+++ b/src/tethys/deployment/swing/DeploymentInfoCard.java
@@ -0,0 +1,47 @@
+package tethys.deployment.swing;
+
+import javax.swing.BoxLayout;
+
+import PamView.wizard.PamWizard;
+import PamView.wizard.PamWizardCard;
+import nilus.Deployment;
+import tethys.deployment.DeploymentExportOpts;
+import tethys.swing.export.ResponsiblePartyPanel;
+
+public class DeploymentInfoCard extends PamWizardCard {
+
+ private ResponsiblePartyPanel responsiblePartyPanel;
+
+ private ProjectInformationPanel projectInformationPanel;
+
+ public DeploymentInfoCard(PamWizard pamWizard, String title) {
+ super(pamWizard, title);
+ this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+
+ projectInformationPanel = new ProjectInformationPanel(pamWizard, title);
+ this.add(projectInformationPanel.getMainPanel());
+ responsiblePartyPanel = new ResponsiblePartyPanel("Responsible Party");
+ this.add(responsiblePartyPanel.getMainPanel());
+ }
+
+ @Override
+ public boolean getParams(Deployment cardParams) {
+ boolean ok = responsiblePartyPanel.getParams(cardParams.getMetadataInfo().getContact());
+ ok &= projectInformationPanel.getParams(cardParams);
+
+ return ok;
+ }
+
+ @Override
+ public void setParams(Deployment cardParams) {
+ projectInformationPanel.setParams(cardParams);
+ responsiblePartyPanel.setParams(cardParams.getMetadataInfo().getContact());
+ }
+
+ public boolean getParams(DeploymentExportOpts exportOptions, Deployment deployment) {
+ boolean ok = getParams(deployment);
+
+ return ok;
+ }
+
+}
diff --git a/src/tethys/deployment/swing/DeploymentTrackCard.java b/src/tethys/deployment/swing/DeploymentTrackCard.java
new file mode 100644
index 00000000..20856fca
--- /dev/null
+++ b/src/tethys/deployment/swing/DeploymentTrackCard.java
@@ -0,0 +1,183 @@
+package tethys.deployment.swing;
+
+import java.awt.BorderLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+
+import javax.swing.BoxLayout;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.border.TitledBorder;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+
+import PamUtils.PamCalendar;
+import PamView.dialog.PamGridBagContraints;
+import PamView.panel.WestAlignedPanel;
+import PamView.wizard.PamWizard;
+import PamView.wizard.PamWizardCard;
+import dataMap.OfflineDataMap;
+import tethys.TethysControl;
+import tethys.deployment.DeploymentExportOpts;
+import tethys.deployment.TrackInformation;
+
+public class DeploymentTrackCard extends PamWizardCard {
+
+ private static final long serialVersionUID = 1L;
+
+ private TethysControl tethysControl;
+
+ private TrackInformation trackInfo;
+
+ private JTextField totalPoints, startDate, endDate, highestRate;
+
+ private JTextField exportInterval, exportCount;
+
+ public DeploymentTrackCard(PamWizard pamWizard, TethysControl tethysControl, TrackInformation trackInfo) {
+ super(pamWizard, "Track Data");
+ this.tethysControl = tethysControl;
+ this.trackInfo = trackInfo;
+ JPanel trackPanel = new JPanel();
+ WestAlignedPanel wp = new WestAlignedPanel(trackPanel);
+ wp.setBorder(new TitledBorder("Track data summary"));
+ setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+ add(wp);
+ trackPanel.setLayout(new GridBagLayout());
+ GridBagConstraints c = new PamGridBagContraints();
+ c.gridx = 1;
+ trackPanel.add(new JLabel("PAMGuard data content .... ", JLabel.LEFT), c);
+ c.gridx = 0;
+ c.gridy++;
+ trackPanel.add(new JLabel("Track Start ", JLabel.RIGHT), c);
+ c.gridx++;
+ trackPanel.add(startDate = new TrackField(20), c);
+ c.gridx = 0;
+ c.gridy++;
+ trackPanel.add(new JLabel("Track End ", JLabel.RIGHT), c);
+ c.gridx++;
+ trackPanel.add(endDate = new TrackField(20), c);
+ c.gridx = 0;
+ c.gridy++;
+ trackPanel.add(new JLabel("Total Points ", JLabel.RIGHT), c);
+ c.gridx++;
+ trackPanel.add(totalPoints = new TrackField(20), c);
+ c.gridx = 0;
+ c.gridy++;
+ trackPanel.add(new JLabel("Interval ", JLabel.RIGHT), c);
+ c.gridx++;
+ trackPanel.add(highestRate = new TrackField(20), c);
+
+ c.gridx = 1;
+ c.gridy++;
+ c.gridwidth = 1;
+ trackPanel.add(new JLabel("Export .... ", JLabel.LEFT), c);
+ c.gridx = 0;
+ c.gridy++;
+ c.gridwidth = 1;
+ trackPanel.add(new JLabel("Export interval ", JLabel.RIGHT), c);
+ c.gridx++;
+ trackPanel.add(exportInterval = new JTextField(12), c);
+ c.gridx = 0;
+ c.gridy++;
+ trackPanel.add(new JLabel("Estimated elements ", JLabel.RIGHT), c);
+ c.gridx++;
+ trackPanel.add(exportCount = new TrackField(12), c);
+ c.gridx = 0;
+ c.gridy++;
+
+ IntervalListener il = new IntervalListener();
+// exportInterval.addActionListener(il);
+// exportInterval.addKeyListener(il);
+// exportInterval.addFocusListener(il);
+ exportInterval.getDocument().addDocumentListener(il);
+
+
+// c.gridx++;
+// trackPanel.add(new JLabel(" per minute ", JLabel.LEFT), c);
+// c.gridy++;
+
+ }
+
+ private class IntervalListener implements DocumentListener {
+
+ @Override
+ public void insertUpdate(DocumentEvent e) {
+ updateExportCount();
+ }
+
+ @Override
+ public void removeUpdate(DocumentEvent e) {
+ updateExportCount();
+ }
+
+ @Override
+ public void changedUpdate(DocumentEvent e) {
+ updateExportCount();
+ }
+
+ }
+
+ private class TrackField extends JTextField {
+
+ /**
+ * @param columns
+ */
+ public TrackField(int columns) {
+ super(columns);
+ setEditable(false);
+ }
+
+ }
+
+ @Override
+ public boolean getParams(DeploymentExportOpts cardParams) {
+ try {
+ cardParams.trackPointInterval = Double.valueOf(exportInterval.getText());
+ }
+ catch (Exception e) {
+ return getPamWizard().showWarning("Invalid track point interval");
+ }
+ return true;
+ }
+
+ public void updateExportCount() {
+ OfflineDataMap dataMap = trackInfo.getGpsDataMap();
+ if (dataMap == null) {
+ return;
+ }
+ try {
+// System.out.println(exportInterval.getText());
+ double intval = Double.valueOf(exportInterval.getText());
+ double highRate = trackInfo.getGPSDataRate();
+ int nCount = dataMap.getDataCount();
+ int newEst = (int) Math.round(Math.min(nCount/(intval*highRate), nCount));
+ exportCount.setText(String.format("%d", newEst));
+ }
+ catch (Exception e) {
+ exportCount.setText(null);
+ }
+
+ }
+
+ @Override
+ public void setParams(DeploymentExportOpts cardParams) {
+ OfflineDataMap dataMap = trackInfo.getGpsDataMap();
+ if (dataMap == null) {
+ return;
+ }
+ startDate.setText(PamCalendar.formatDBDateTime(dataMap.getFirstDataTime()));
+ endDate.setText(PamCalendar.formatDBDateTime(dataMap.getLastDataTime()));
+ totalPoints.setText(String.format("%d", dataMap.getDataCount()));
+ double rate = trackInfo.getGPSDataRate();
+ highestRate.setText(PamCalendar.formatDuration((long) (1000/rate)));
+
+ }
+
+}
diff --git a/src/tethys/deployment/swing/DeploymentWizard.java b/src/tethys/deployment/swing/DeploymentWizard.java
new file mode 100644
index 00000000..d7ca83dc
--- /dev/null
+++ b/src/tethys/deployment/swing/DeploymentWizard.java
@@ -0,0 +1,100 @@
+package tethys.deployment.swing;
+
+import java.awt.Dimension;
+import java.awt.Window;
+
+import PamView.wizard.PamWizard;
+import PamView.wizard.PamWizardCard;
+import metadata.MetaDataContol;
+import nilus.Deployment;
+import tethys.TethysControl;
+import tethys.deployment.DeploymentExportOpts;
+import tethys.deployment.DeploymentHandler;
+import tethys.deployment.TrackInformation;
+import tethys.swing.export.DescriptionCard;
+import tethys.swing.export.ResponsiblePartyCard;
+
+public class DeploymentWizard extends PamWizard {
+
+ private static final long serialVersionUID = 1L;
+
+ private Deployment deployment;
+
+ private DeploymentExportOpts exportOptions;
+
+ private DescriptionCard descriptionCard;
+
+ private DeploymentInfoCard deploymentInfoCard;
+
+ private DeploymentDataCard deploymentDataCard;
+
+ private DeploymentTrackCard deploymentTrackCard;
+// private
+
+ private DeploymentWizard(Window parentFrame, TethysControl tethysControl, Deployment deployment, DeploymentExportOpts exportOptions) {
+ super(parentFrame, "Deployment Export");
+ this.deployment = deployment;
+ this.exportOptions = exportOptions;
+ DeploymentHandler deploymentHandler = tethysControl.getDeploymentHandler();
+ TrackInformation trackInfo = deploymentHandler.getTrackInformation();
+
+ addCard(deploymentInfoCard = new DeploymentInfoCard(this, "Responsible Party"));
+ addCard(deploymentDataCard = new DeploymentDataCard(this, tethysControl));
+ addCard(descriptionCard = new DescriptionCard(this, tethysControl));
+ boolean haveGPS = trackInfo.haveGPSTrack();
+ if (haveGPS) {
+ deploymentTrackCard = new DeploymentTrackCard(this, tethysControl, trackInfo);
+ addCard(deploymentTrackCard);
+ }
+ descriptionCard.setPreferredSize(new Dimension(10, 300));
+ }
+
+ public static DeploymentExportOpts showWizard(Window parentFrame, TethysControl tethysControl, Deployment deployment, DeploymentExportOpts exportOptions) {
+ if (deployment == null) {
+ deployment = MetaDataContol.getMetaDataControl().getMetaData().getDeployment();
+ }
+ DeploymentWizard wiz = new DeploymentWizard(parentFrame, tethysControl, deployment, exportOptions);
+ wiz.setParams();
+ wiz.setVisible(true);
+ return wiz.exportOptions;
+ }
+
+ @Override
+ public void setCardParams(PamWizardCard wizardCard) {
+ if (wizardCard == descriptionCard) {
+ descriptionCard.setParams(deployment.getDescription());
+ }
+ if (wizardCard == deploymentInfoCard) {
+ deploymentInfoCard.setParams(deployment);
+ }
+ if (wizardCard == deploymentDataCard) {
+ deploymentDataCard.setParams(exportOptions, deployment);
+ }
+ if (wizardCard == deploymentTrackCard) {
+ deploymentTrackCard.setParams(exportOptions);
+ }
+ }
+
+ @Override
+ public boolean getCardParams(PamWizardCard wizardCard) {
+ if (wizardCard == descriptionCard) {
+ return descriptionCard.getParams(deployment.getDescription());
+ }
+ if (wizardCard == deploymentInfoCard) {
+ return deploymentInfoCard.getParams(exportOptions, deployment);
+ }
+ if (wizardCard == deploymentDataCard) {
+ return deploymentDataCard.getParams(exportOptions, deployment);
+ }
+ if (wizardCard == deploymentTrackCard) {
+ return deploymentTrackCard.getParams(exportOptions);
+ }
+ return false;
+ }
+
+ @Override
+ public void cancelButtonPressed() {
+ this.exportOptions = null;
+ }
+
+}
diff --git a/src/tethys/deployment/swing/ProjectInformationPanel.java b/src/tethys/deployment/swing/ProjectInformationPanel.java
new file mode 100644
index 00000000..1ced05b1
--- /dev/null
+++ b/src/tethys/deployment/swing/ProjectInformationPanel.java
@@ -0,0 +1,222 @@
+package tethys.deployment.swing;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Point;
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JTextField;
+import javax.swing.border.TitledBorder;
+
+import PamController.PamController;
+import PamView.dialog.PamGridBagContraints;
+import metadata.PamguardMetaData;
+import nilus.Deployment;
+import tethys.TethysControl;
+import tethys.swing.NewProjectDialog;
+import tethys.swing.SelectProjectDialog;
+
+/**
+ * Panel for entering project information
+ * @author dg50
+ *
+ */
+public class ProjectInformationPanel {
+
+ private JPanel projectPanel;
+
+ private JTextField project, site, cruise, region;
+
+ private JButton newProject, selectProject;
+
+ private TethysControl tethysControl;
+
+ private Deployment deployment;
+
+ private Window owner;
+
+ public ProjectInformationPanel(Window owner, String title) {
+ super();
+ this.owner = owner;
+
+ tethysControl = (TethysControl) PamController.getInstance().findControlledUnit(TethysControl.unitType);
+
+ int txtWidth = 1;
+ if (tethysControl != null) {
+ txtWidth = 3;
+ }
+ projectPanel = new JPanel(new GridBagLayout());
+ if (title != null) {
+ projectPanel.setBorder(new TitledBorder(title));
+ }
+ GridBagConstraints c = new PamGridBagContraints();
+ projectPanel.add(new JLabel("Project Name ", JLabel.RIGHT), c);
+ c.gridx++;
+ projectPanel.add(project = new JTextField(30), c);
+ if (tethysControl != null) {
+ c.gridx++;
+ projectPanel.add(selectProject = new JButton("Select"));
+ c.gridx++;
+ projectPanel.add(newProject = new JButton("New"));
+ }
+ c.gridx = 0;
+ c.gridy++;
+ c.gridwidth = 1;
+ projectPanel.add(new JLabel("Region ", JLabel.RIGHT), c);
+ c.gridx++;
+ c.gridwidth = txtWidth;
+ projectPanel.add(region = new JTextField(20), c);
+ c.gridx = 0;
+ c.gridy++;
+ c.gridwidth = 1;
+ projectPanel.add(new JLabel("Cruise name ", JLabel.RIGHT), c);
+ c.gridx++;
+ c.gridwidth = txtWidth;
+ projectPanel.add(cruise = new JTextField(40), c);
+ c.gridx = 0;
+ c.gridy++;
+ c.gridwidth = 1;
+ projectPanel.add(new JLabel("Site ", JLabel.RIGHT), c);
+ c.gridx++;
+ c.gridwidth = txtWidth;
+ projectPanel.add(site = new JTextField(20), c);
+ c.gridx = 0;
+ c.gridy++;
+
+
+ if (newProject != null) {
+ newProject.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ selNewProject(e);
+ }
+ });
+ }
+ if (selectProject != null) {
+ selectProject.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ selProjectPressed(e);
+ }
+ });
+ }
+
+ }
+
+ /**
+ * @return the mainPanel
+ */
+ public JPanel getMainPanel() {
+ return projectPanel;
+ }
+
+ public void setParams(Deployment deployment) {
+ this.deployment = deployment;
+ cruise.setText(deployment.getCruise());
+ region.setText(deployment.getRegion());
+ site.setText(deployment.getSite());
+ project.setText(deployment.getProject());
+ }
+
+ public boolean getParams(Deployment deployment) {
+ if (deployment == null) {
+ return false;
+ }
+ deployment.setCruise(cruise.getText());
+ deployment.setRegion(region.getText());
+ deployment.setSite(site.getText());
+ deployment.setProject(project.getText());
+ return true;
+ }
+ /**
+ * Select a new project, uses a dialog from Tethys. Only enabled
+ * when the tethys database is present to allow this.
+ * @param e
+ */
+ protected void selNewProject(ActionEvent e) {
+ if (tethysControl == null) {
+ return;
+ }
+ getParams(deployment);
+ Deployment newDeployment = NewProjectDialog.showDialog(owner, tethysControl, deployment);
+ if (newDeployment != null) {
+ deployment.setProject(newDeployment.getProject());
+ deployment.setRegion(newDeployment.getRegion());
+ }
+ setParams(deployment);
+ }
+
+ protected void selProjectPressed(ActionEvent e) {
+ if (tethysControl == null) {
+ return;
+ }
+ getParams(deployment);
+ // will this be fast enough, or do we need to get Tethys to hold this list in memory ?
+ ArrayList projectNames = tethysControl.getDbxmlQueries().getProjectNames();
+ if (projectNames.size() < 12) {
+ showAsMenu(projectNames);
+ }
+ else {
+ showAsDialog(projectNames);
+ }
+
+ }
+
+ private void showAsDialog(ArrayList projectNames) {
+ Point p = selectProject.getLocationOnScreen();
+ String selName = SelectProjectDialog.showDialog(owner, projectNames, project.getText(), p);
+ if (selName != null) {
+ project.setText(selName);
+ }
+ }
+
+ private void showAsMenu(ArrayList projectNames) {
+ String currentName = project.getText();
+ JPopupMenu popMenu = new JPopupMenu();
+ JMenuItem menuItem;
+ if (currentName != null && currentName.length()>0) {
+ addProjMenuItem(popMenu, currentName);
+ }
+ for (String projName : projectNames) {
+ if (projName.equals(currentName)) {
+ continue;
+ }
+ addProjMenuItem(popMenu, projName);
+ }
+
+ popMenu.show(selectProject, selectProject.getWidth()/2, selectProject.getHeight()/2);
+ }
+
+ private void addProjMenuItem(JPopupMenu popMenu, String projectName) {
+ JMenuItem menuItem = new JMenuItem(projectName);
+ menuItem.addActionListener(new SelectProject(projectName));
+ popMenu.add(menuItem);
+ }
+
+ private class SelectProject implements ActionListener {
+
+ private String projectName;
+
+ /**
+ * @param projectName
+ */
+ public SelectProject(String projectName) {
+ this.projectName = projectName;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ project.setText(projectName);
+ }
+
+ }
+
+}
diff --git a/src/tethys/deployment/swing/RecordingGapDialog.java b/src/tethys/deployment/swing/RecordingGapDialog.java
new file mode 100644
index 00000000..399eb3bc
--- /dev/null
+++ b/src/tethys/deployment/swing/RecordingGapDialog.java
@@ -0,0 +1,85 @@
+package tethys.deployment.swing;
+
+import java.awt.GridBagLayout;
+import java.awt.Window;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.border.TitledBorder;
+
+import PamView.dialog.PamDialog;
+import PamView.dialog.PamGridBagContraints;
+import tethys.deployment.DeploymentExportOpts;
+
+public class RecordingGapDialog extends PamDialog {
+
+ private JTextField maxGap, minLength;
+
+ private DeploymentExportOpts exportOpts;
+
+ private RecordingGapDialog(Window parentFrame) {
+ super(parentFrame, "Maximum Gap", true);
+ JPanel mainPanel = new JPanel(new GridBagLayout());
+ mainPanel.setBorder(new TitledBorder("Max recording gap"));
+ PamGridBagContraints c = new PamGridBagContraints();
+ mainPanel.add(new JLabel("Maximum gap ", JLabel.RIGHT), c);
+ c.gridx++;
+ mainPanel.add(maxGap = new JTextField(3), c);
+ c.gridx++;
+ mainPanel.add(new JLabel(" seconds", JLabel.RIGHT), c);
+ c.gridx = 0;
+ c.gridy++;
+ mainPanel.add(new JLabel("Minimum length ", JLabel.RIGHT), c);
+ c.gridx++;
+ mainPanel.add(minLength = new JTextField(3), c);
+ 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");
+ minLength.setToolTipText("Minimum recording length. Recording sections shorter than this will be ignored");
+
+ setDialogComponent(mainPanel);
+ }
+
+ public static DeploymentExportOpts showDiloag(Window parent, DeploymentExportOpts exportOpts) {
+ RecordingGapDialog dialog = new RecordingGapDialog(parent);
+ dialog.setParams(exportOpts);
+ dialog.setVisible(true);
+ return dialog.exportOpts;
+ }
+
+ private void setParams(DeploymentExportOpts exportOpts) {
+ this.exportOpts = exportOpts;
+ maxGap.setText(String.format("%d", exportOpts.maxRecordingGapSeconds));
+ minLength.setText(String.format("%d", exportOpts.minRecordingLengthSeconds));
+ }
+
+ @Override
+ public boolean getParams() {
+ try {
+ exportOpts.maxRecordingGapSeconds = Integer.valueOf(maxGap.getText());
+ }
+ catch (NumberFormatException e) {
+ return showWarning("Invalid inter recording interval");
+ }
+ try {
+ exportOpts.minRecordingLengthSeconds = Integer.valueOf(minLength.getText());
+ }
+ catch (NumberFormatException e) {
+ return showWarning("Invalid minimum recording length");
+ }
+ return true;
+ }
+
+ @Override
+ public void cancelButtonPressed() {
+ exportOpts = null;
+ }
+
+ @Override
+ public void restoreDefaultSettings() {
+ DeploymentExportOpts defaults = new DeploymentExportOpts();
+ }
+
+}
diff --git a/src/tethys/detection/BinnedGranularityHandler.java b/src/tethys/detection/BinnedGranularityHandler.java
new file mode 100644
index 00000000..db984b27
--- /dev/null
+++ b/src/tethys/detection/BinnedGranularityHandler.java
@@ -0,0 +1,172 @@
+package tethys.detection;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamDataUnit;
+import nilus.Detection;
+import nilus.SpeciesIDType;
+import tethys.TethysControl;
+import tethys.TethysTimeFuncs;
+import tethys.output.StreamExportParams;
+import tethys.output.TethysExportParams;
+import tethys.pamdata.TethysDataProvider;
+import tethys.species.DataBlockSpeciesCodes;
+import tethys.species.DataBlockSpeciesManager;
+import tethys.species.DataBlockSpeciesMap;
+import tethys.species.SpeciesMapItem;
+
+/**
+ * Binned granularity
+ * Will have to collect different counts for each type of call for each datablock (if there
+ * are such things) so a little more complicated than might be expected.
+ * @author dg50
+ *
+ */
+public class BinnedGranularityHandler extends GranularityHandler {
+
+ private long binDurationMillis;
+
+ private TethysDataProvider dataProvider;
+
+ private DataBlockSpeciesManager speciesManager;
+
+ private HashMap currentDetections;
+
+ public BinnedGranularityHandler(TethysControl tethysControl, PamDataBlock dataBlock,
+ TethysExportParams tethysExportParams, StreamExportParams streamExportParams) {
+ super(tethysControl, dataBlock, tethysExportParams, streamExportParams);
+
+ binDurationMillis = (long) (streamExportParams.binDurationS*1000.);
+ dataProvider = dataBlock.getTethysDataProvider(tethysControl);
+ speciesManager = dataBlock.getDatablockSpeciesManager();
+
+ currentDetections = new HashMap();
+ }
+
+ @Override
+ public void prepare(long timeMillis) {
+// long binStart = DetectionsHandler.roundDownBinStart(timeMillis, binDurationMillis);
+// startBin(binStart);
+ }
+
+// private void startBin(long timeMillis) {
+// binStartMillis = timeMillis;
+// binEndMillis = binStartMillis + binDurationMillis;
+// /*
+// * now make a Detection object for every possible species that
+// * this might throw out.
+// */
+// ArrayList speciesCodes = speciesManager.getAllSpeciesCodes();
+// String defaultCode = speciesManager.getDefaultSpeciesCode();
+// Detection det;
+// currentDetections.put(defaultCode, det = new Detection());
+// det.setStart(TethysTimeFuncs.xmlGregCalFromMillis(binStartMillis));
+// det.setEnd(TethysTimeFuncs.xmlGregCalFromMillis(binEndMillis));
+// det.setCount(BigInteger.ZERO);
+// det.setChannel(BigInteger.ZERO);
+// // add codes at end, just before output.
+// if (speciesCodes != null) {
+// for (String code : speciesCodes) {
+// currentDetections.put(code, det = new Detection());
+// det.setStart(TethysTimeFuncs.xmlGregCalFromMillis(binStartMillis));
+// det.setEnd(TethysTimeFuncs.xmlGregCalFromMillis(binEndMillis));
+// det.setCount(BigInteger.ZERO);
+// det.setChannel(BigInteger.ZERO);
+// }
+// }
+// }
+
+ @Override
+ public Detection[] addDataUnit(PamDataUnit dataUnit) {
+ Detection[] completeDetections = closeBins(dataUnit.getTimeMilliseconds());
+ // now look for new ones. First get the species of the dataUnit and find it in the hashmap
+ String groupName = getCallGroupName(dataUnit);
+ Detection det = currentDetections.get(groupName);
+ if (det == null) {
+ // need to make a new one.
+ det = new Detection();
+ long binStart = DetectionsHandler.roundDownBinStart(dataUnit.getTimeMilliseconds(), binDurationMillis);
+ det.setStart(TethysTimeFuncs.xmlGregCalFromMillis(binStart));
+ det.setEnd(TethysTimeFuncs.xmlGregCalFromMillis(binStart + binDurationMillis));
+ det.setCount(BigInteger.ONE);
+ det.setChannel(BigInteger.valueOf(dataUnit.getChannelBitmap()));
+ // this should always return something, so am going to crash if it doesn't.
+ // may revisit this later on if we've unassigned things we don't want to label
+ // in which case they should be rejected earlier than this.
+ SpeciesMapItem speciesStuff = speciesManager.getSpeciesItem(dataUnit);
+ SpeciesIDType species = new SpeciesIDType();
+ species.setValue(BigInteger.valueOf(speciesStuff.getItisCode()));
+ det.setSpeciesId(species);
+ if (speciesStuff.getCallType() != null) {
+ det.getCall().add(speciesStuff.getCallType());
+ }
+ currentDetections.put(groupName, det);
+ }
+ else {
+ // add to current detection. Set new end time and increment count
+ int count = det.getCount().intValue() + 1;
+ det.setCount(BigInteger.valueOf(count));
+ int chan = det.getChannel().intValue();
+ chan |= dataUnit.getChannelBitmap();
+ det.setChannel(BigInteger.valueOf(chan));
+ }
+
+
+ return completeDetections;
+ }
+
+ /**
+ * Called when units arrive after end of current bin, and also
+ * at end of deployment output, to get that last bine.
+ * @param timeMilliseconds
+ * @return
+ */
+ private synchronized Detection[] closeBins(long timeMilliseconds) {
+ Set speciesKeys = currentDetections.keySet();
+ int n = speciesKeys.size();
+ int nGood = 0;
+ DataBlockSpeciesMap speciesMap = speciesManager.getDatablockSpeciesMap();
+ Detection detections[] = new Detection[n];
+ Iterator> iter = currentDetections.entrySet().iterator();
+ while (iter.hasNext()) {
+ Entry entry = iter.next();
+ Detection det = entry.getValue();
+ long detEnd = TethysTimeFuncs.millisFromGregorianXML(det.getEnd());
+ if (timeMilliseconds < detEnd) {
+ // we're not at the end of the bin, so carry on.
+ continue;
+ }
+ // we've reached the end of the bin, so remove it from the map
+ iter.remove();
+ // now decide if we want to keep it or not.
+ int callCount = det.getCount().intValue();
+ if (callCount < Math.max(streamExportParams.minBinCount,1)) {
+ continue; // won't add to output list
+ }
+
+ detections[nGood++] = det;
+ }
+
+ /*
+ * Clean up the end of the array and return detections that have enough calls.
+ */
+ if (nGood == 0) {
+ return null;
+ }
+ detections = Arrays.copyOf(detections, nGood);
+ return detections;
+ }
+
+ @Override
+ public Detection[] cleanup(long timeMillis) {
+ return closeBins(timeMillis);
+ }
+
+}
diff --git a/src/tethys/detection/CallGranularityHandler.java b/src/tethys/detection/CallGranularityHandler.java
new file mode 100644
index 00000000..4ff9a888
--- /dev/null
+++ b/src/tethys/detection/CallGranularityHandler.java
@@ -0,0 +1,40 @@
+package tethys.detection;
+
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamDataUnit;
+import nilus.Detection;
+import tethys.TethysControl;
+import tethys.output.StreamExportParams;
+import tethys.output.TethysExportParams;
+import tethys.pamdata.TethysDataProvider;
+
+public class CallGranularityHandler extends GranularityHandler {
+
+ private TethysDataProvider dataProvider;
+
+ public CallGranularityHandler(TethysControl tethysControl, PamDataBlock dataBlock,
+ TethysExportParams tethysExportParams, StreamExportParams streamExportParams) {
+ super(tethysControl, dataBlock, tethysExportParams, streamExportParams);
+
+ dataProvider = dataBlock.getTethysDataProvider(tethysControl);
+
+ }
+
+ @Override
+ public void prepare(long timeMillis) {
+ // never anything to do here for call level granularity.
+ }
+
+ @Override
+ public Detection[] addDataUnit(PamDataUnit dataUnit) {
+ Detection det = dataProvider.createDetection(dataUnit, tethysExportParams, streamExportParams);
+ return toDetectionArray(det);
+ }
+
+ @Override
+ public Detection[] cleanup(long timeMillis) {
+ // never anything to do here for call level granularity.
+ return null;
+ }
+
+}
diff --git a/src/tethys/detection/DetectionExportObserver.java b/src/tethys/detection/DetectionExportObserver.java
new file mode 100644
index 00000000..29ed1fe7
--- /dev/null
+++ b/src/tethys/detection/DetectionExportObserver.java
@@ -0,0 +1,11 @@
+package tethys.detection;
+
+public interface DetectionExportObserver {
+
+ /**
+ * Update message and state of export
+ * @param progress
+ */
+ public void update(DetectionExportProgress progress);
+
+}
diff --git a/src/tethys/detection/DetectionExportProgress.java b/src/tethys/detection/DetectionExportProgress.java
new file mode 100644
index 00000000..abfa74b8
--- /dev/null
+++ b/src/tethys/detection/DetectionExportProgress.java
@@ -0,0 +1,32 @@
+package tethys.detection;
+
+import nilus.Detections;
+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 PDeployment currentDeployment;
+ public Detections currentDetections;
+ public long lastUnitTime;
+ public long totalUnits;
+ public int exportCount;
+ public int skipCount;
+ public int state;
+
+ public DetectionExportProgress(PDeployment currentDeployment, Detections currentDetections, long lastUnitTime,
+ long totalUnits, int exportCount, int skipCount, int state) {
+ super();
+ this.currentDeployment = currentDeployment;
+ this.currentDetections = currentDetections;
+ this.lastUnitTime = lastUnitTime;
+ this.totalUnits = totalUnits;
+ this.exportCount = exportCount;
+ this.skipCount = skipCount;
+ this.state = state;
+ }
+}
diff --git a/src/tethys/detection/DetectionsHandler.java b/src/tethys/detection/DetectionsHandler.java
new file mode 100644
index 00000000..b5740ea7
--- /dev/null
+++ b/src/tethys/detection/DetectionsHandler.java
@@ -0,0 +1,661 @@
+package tethys.detection;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.SwingWorker;
+
+import PamController.PamControlledUnit;
+import PamController.PamController;
+import PamController.PamguardVersionInfo;
+import PamModel.PamPluginInterface;
+import PamUtils.PamCalendar;
+import PamView.dialog.PamDialog;
+import PamView.dialog.warn.WarnOnce;
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamDataUnit;
+import PamguardMVC.PamProcess;
+import PamguardMVC.dataSelector.DataSelector;
+import PamguardMVC.superdet.SuperDetDataBlock;
+import PamguardMVC.superdet.SuperDetDataBlock.ViewerLoadPolicy;
+import dataMap.OfflineDataMap;
+import dataMap.OfflineDataMapPoint;
+import nilus.AlgorithmType;
+import nilus.AlgorithmType.SupportSoftware;
+import nilus.DataSourceType;
+import nilus.Deployment;
+import nilus.Detection;
+import nilus.DetectionEffort;
+import nilus.DetectionEffortKind;
+import nilus.DetectionGroup;
+import nilus.Detections;
+import nilus.GranularityEnumType;
+import nilus.Helper;
+import tethys.Collection;
+import tethys.TethysControl;
+import tethys.TethysTimeFuncs;
+import tethys.dbxml.DBXMLConnect;
+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;
+import tethys.species.DataBlockSpeciesManager;
+import tethys.swing.export.DetectionsExportWizard;
+
+/**
+ * Functions for handling output of Detections documents.
+ * Works closely with a TethysDataProvider and DataBlockSpeciesManager
+ * to generate Detections elements for an xml doc to export to Tethys.
+ * @author dg50
+ *
+ */
+public class DetectionsHandler {
+
+ private TethysControl tethysControl;
+
+ public int uniqueDetectionsId=1;
+ public int uniqueDetectionId;
+
+ private volatile boolean activeExport;
+
+ private ExportWorker exportWorker;
+
+ /**
+ *
+ * @param tethysControl
+ */
+ public DetectionsHandler(TethysControl tethysControl) {
+ super();
+ this.tethysControl = tethysControl;
+ }
+
+
+ /**
+ * Get a list of Detections documents associated with a particular data stream for
+ * this data set (not the entire project).
+ * @param dataBlock
+ */
+ public StreamDetectionsSummary getStreamDetections(PamDataBlock dataBlock) {
+ ArrayList deployments = tethysControl.getDeploymentHandler().getMatchedDeployments();
+ return getStreamDetections(dataBlock, deployments);
+ }
+
+ /**
+ * Get a list of Detections documents associated with a particular data block for the list of deployments
+ * documents. Group them by abstract or something
+ * @param dataBlock
+ * @param deployments
+ * @return
+ */
+ public StreamDetectionsSummary getStreamDetections(PamDataBlock dataBlock, ArrayList deployments) {
+ // get the basic data for each document including it's Description.
+
+ ArrayList detectionsDocs = new ArrayList<>();
+ for (PDeployment aDep : deployments) {
+ ArrayList someNames = tethysControl.getDbxmlQueries().getDetectionsDocuments(dataBlock, aDep.deployment.getId());
+ if (someNames == null) {
+ continue;
+ }
+ // no have a list of all the Detections documents of interest for this datablock.
+ for (String aDoc : someNames) {
+ Detections detections = tethysControl.getDbxmlQueries().getDetectionsDocInfo(aDoc);
+ int count = tethysControl.getDbxmlQueries().countDetections2(aDoc);
+ PDetections pDetections = new PDetections(detections, dataBlock, aDep, count);
+ detectionsDocs.add(pDetections);
+ }
+ }
+ return new StreamDetectionsSummary(detectionsDocs);
+ }
+
+ /**
+ * Get the Detection Effort part of a Detections document
+ * @param pDeployment
+ * @param dataBlock
+ * @param exportParams
+ * @return
+ */
+ private DetectionEffort getDetectorEffort(PDeployment pDeployment, PamDataBlock dataBlock, StreamExportParams exportParams) {
+ DetectionEffort effort = new DetectionEffort();
+ Deployment deployment = pDeployment.deployment;
+ Long effortStart = pDeployment.getAudioStart();
+ Long effortEnd = pDeployment.getAudioEnd();
+ effort.setStart(TethysTimeFuncs.xmlGregCalFromMillis(effortStart));
+ effort.setEnd(TethysTimeFuncs.xmlGregCalFromMillis(effortEnd));
+// effort.set // no setter for DetectionEffortKind
+ List effortKinds = effort.getKind();
+
+ TethysDataProvider dataProvider = dataBlock.getTethysDataProvider(tethysControl);
+ dataProvider.getEffortKinds(pDeployment, effortKinds, exportParams);
+
+
+ return effort;
+ }
+
+ /**
+ * Method string for Detections Algorithm documents.
+ * @param dataBlock
+ * @return
+ */
+ public String getMethodString(PamDataBlock dataBlock) {
+ if (dataBlock == null) {
+ return null;
+ }
+ PamProcess process = dataBlock.getParentProcess();
+ return "PAMGuard " + process.getProcessName();
+
+ }
+
+ /**
+ * Software string for Detections Algorithm documents.
+ * @param dataBlock
+ * @return
+ */
+ public String getSoftwareString(PamDataBlock dataBlock) {
+ if (dataBlock == null) {
+ return null;
+ }
+ return dataBlock.getLongDataName();
+ }
+
+ /**
+ * Software string for Detections Algorithm documents.
+ * @param dataBlock
+ * @return
+ */
+ public String getVersionString(PamDataBlock dataBlock) {
+ if (dataBlock == null) {
+ return null;
+ }
+ PamProcess process = dataBlock.getParentProcess();
+ PamControlledUnit pcu = process.getPamControlledUnit();
+ PamPluginInterface plugin = pcu.getPlugin();
+ if (plugin == null) {
+ return PamguardVersionInfo.version;
+ }
+ else {
+ return plugin.getVersion();
+ }
+ }
+
+ /**
+ *
+ * @param dataBlock
+ * @return default value is PAMGuard
+ */
+ public String getSupportSoftware(PamDataBlock dataBlock) {
+ return "PAMGuard";
+ }
+
+ /**
+ *
+ * @param dataBlock
+ * @return PAMGuard version
+ */
+ public String getSupportSoftwareVersion(PamDataBlock dataBlock) {
+// should try to dig into the binary store and get the version from there.
+ return PamguardVersionInfo.version;
+ }
+
+ /**
+ * Detections will be exported in a separate worker thread since export may take some time and
+ * the user should be given ample opportunity to cancel it.
+ * @param pamDataBlock
+ * @param streamExportParams
+ * @param exportWorkerCard
+ */
+ public void startExportThread(PamDataBlock pamDataBlock, StreamExportParams streamExportParams, DetectionExportObserver exportObserver) {
+
+ checkGranularity(pamDataBlock, streamExportParams);
+ tethysControl.getTethysExportParams().setStreamParams(pamDataBlock, streamExportParams);
+ activeExport = true;
+ exportWorker = new ExportWorker(pamDataBlock, streamExportParams, exportObserver);
+ exportWorker.execute();
+ }
+
+ /**
+ * Fudge because some outputs don't show the granularity card, but need to
+ * make sure that it's set to the correct only option ..
+ * @param pamDataBlock
+ * @param streamExportParams
+ */
+ private void checkGranularity(PamDataBlock pamDataBlock, StreamExportParams streamExportParams) {
+ if (streamExportParams == null) {
+ return;
+ }
+ TethysDataProvider tethysProvider = pamDataBlock.getTethysDataProvider(tethysControl);
+ if (tethysProvider == null) return;
+ GranularityEnumType[] allowed = tethysProvider.getAllowedGranularities();
+ if (allowed == null || allowed.length == 0) {
+ return;
+ }
+ for (int i = 0; i < allowed.length; i++) {
+ if (allowed[i] == streamExportParams.granularity) {
+ return; // matches allowed value, so OK
+ }
+ }
+ /*
+ * if we get here, it's all wrong, so set to the first allowed value
+ * which will be the only one if the card wasn't shown
+ */
+ streamExportParams.granularity = allowed[0];
+ }
+
+ /**
+ * send a cancel command to export thread if it's running
+ */
+ public void cancelExport() {
+ activeExport = false;
+ }
+
+ /**
+ * Round a bin start so that it's aligned correctly with
+ * day starts.
+ * @param binStart in milliseconds
+ * @param binInterval in milliseconds
+ * @return rounded time.
+ */
+ public static long roundDownBinStart(long binStart, long binInterval) {
+ binStart/=binInterval;
+ return binStart*binInterval;
+ }
+
+ /**
+ * Export detections in all deployments for this PAMGuard dataset.
+ * @param dataBlock
+ * @param streamExportParams
+ * @param exportObserver
+ * @return
+ */
+ private int countDetections(PamDataBlock dataBlock, StreamExportParams streamExportParams, DetectionExportObserver exportObserver) {
+ /*
+ * This is currently called for the entire dataset, but we will need to loop over specific Deployment documents
+ * and export the content of each separately.
+ */
+ TethysExportParams exportParams = tethysControl.getTethysExportParams();
+ DeploymentHandler depHandler = tethysControl.getDeploymentHandler();
+ ArrayList deployments = depHandler.getMatchedDeployments();
+// Detections currentDetections = null;
+ OfflineDataMap dataMap = dataBlock.getPrimaryDataMap();
+ DataSelector dataSelector = dataBlock.getDataSelector(tethysControl.getDataSelectName(), false);
+ int totalCount = dataMap.getDataCount();
+ int skipCount = 0;
+ int exportCount = 0;
+ long lastUnitTime = 0;
+ DetectionExportProgress prog;
+ ViewerLoadPolicy viewerLoadPolicy = ViewerLoadPolicy.LOAD_UTCNORMAL;
+ if (dataBlock instanceof SuperDetDataBlock) {
+ SuperDetDataBlock superDataBlock = (SuperDetDataBlock) dataBlock;
+ viewerLoadPolicy = superDataBlock.getViewerLoadPolicy();
+ }
+ if (viewerLoadPolicy == null) {
+ viewerLoadPolicy = ViewerLoadPolicy.LOAD_UTCNORMAL;
+ }
+ GranularityHandler granularityHandler = GranularityHandler.getHandler(streamExportParams.granularity, tethysControl, dataBlock, exportParams, streamExportParams);
+ for (PDeployment deployment : deployments) {
+ int documentCount = 0;
+ prog = new DetectionExportProgress(deployment, null,
+ lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_COUNTING);
+ exportObserver.update(prog);
+ granularityHandler.prepare(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, null,
+ lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_CANCELED);
+ exportObserver.update(prog);
+ }
+
+ if (mapPoint.getEndTime() < deployment.getAudioStart()) {
+ continue;
+ }
+ if (mapPoint.getStartTime() >= deployment.getAudioEnd()) {
+ break;
+ }
+ 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());
+ skipCount += dataBlock.getUnitsCount() - dataCopy.size();
+ for (PamDataUnit dataUnit : dataCopy) {
+ /*
+ * Here is where we need to handle the different granularities.
+ */
+ Detection dets[] = granularityHandler.addDataUnit(dataUnit);
+ if (dets != null) {
+ exportCount+=dets.length;
+ documentCount+=dets.length;
+
+ if (exportCount % 100 == 0) {
+ prog = new DetectionExportProgress(deployment, null,
+ lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_COUNTING);
+ exportObserver.update(prog);
+ }
+ }
+// Detection det = dataProvider.createDetection(dataUnit, exportParams, streamExportParams);
+// exportCount++;
+// documentCount++;
+// onEffort.getDetection().add(det);
+ lastUnitTime = dataUnit.getTimeMilliseconds();
+ }
+
+ prog = new DetectionExportProgress(deployment, null,
+ lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_COUNTING);
+ exportObserver.update(prog);
+
+ if (viewerLoadPolicy == ViewerLoadPolicy.LOAD_ALWAYS_EVERYTHING) {
+ break;
+ }
+
+ }
+ Detection dets[] = granularityHandler.cleanup(deployment.getAudioEnd());
+ if (dets != null) {
+ exportCount += dets.length;
+ }
+
+
+
+ }
+
+ return exportCount;
+ }/**
+ * Export detections in all deployments for this PAMGuard dataset.
+ * @param dataBlock
+ * @param streamExportParams
+ * @param exportObserver
+ * @return
+ */
+ private int exportDetections(PamDataBlock dataBlock, StreamExportParams streamExportParams, DetectionExportObserver exportObserver) {
+ /*
+ * This is currently called for the entire dataset, but we will need to loop over specific Deployment documents
+ * and export the content of each separately.
+ */
+ TethysExportParams exportParams = tethysControl.getTethysExportParams();
+ DBXMLConnect dbxmlConnect = tethysControl.getDbxmlConnect();
+ DeploymentHandler depHandler = tethysControl.getDeploymentHandler();
+ ArrayList deployments = depHandler.getMatchedDeployments();
+ Detections currentDetections = null;
+ OfflineDataMap dataMap = dataBlock.getPrimaryDataMap();
+ DataSelector dataSelector = dataBlock.getDataSelector(tethysControl.getDataSelectName(), false);
+ int totalCount = dataMap.getDataCount();
+ int skipCount = 0;
+ int exportCount = 0;
+ long lastUnitTime = 0;
+ DetectionExportProgress prog;
+ ViewerLoadPolicy viewerLoadPolicy = ViewerLoadPolicy.LOAD_UTCNORMAL;
+ if (dataBlock instanceof SuperDetDataBlock) {
+ SuperDetDataBlock superDataBlock = (SuperDetDataBlock) dataBlock;
+ viewerLoadPolicy = superDataBlock.getViewerLoadPolicy();
+ }
+ if (viewerLoadPolicy == null) {
+ viewerLoadPolicy = ViewerLoadPolicy.LOAD_UTCNORMAL;
+ }
+ GranularityHandler granularityHandler = GranularityHandler.getHandler(streamExportParams.granularity, tethysControl, dataBlock, exportParams, streamExportParams);
+ for (PDeployment deployment : deployments) {
+ int documentCount = 0;
+ prog = new DetectionExportProgress(deployment, null,
+ 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,
+ lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_CANCELED);
+ exportObserver.update(prog);
+ }
+
+ if (mapPoint.getEndTime() < deployment.getAudioStart()) {
+ continue;
+ }
+ if (mapPoint.getStartTime() >= deployment.getAudioEnd()) {
+ break;
+ }
+ dataBlock.loadViewerData(mapPoint.getStartTime(), mapPoint.getEndTime(), null);
+ ArrayList dataCopy = dataBlock.getDataCopy(deployment.getAudioStart(), deployment.getAudioEnd(), true, dataSelector);
+ skipCount += dataBlock.getUnitsCount() - dataCopy.size();
+ DetectionGroup onEffort = currentDetections.getOnEffort();
+ for (PamDataUnit dataUnit : dataCopy) {
+ /*
+ * Here is where we need to handle the different granularities.
+ */
+ Detection dets[] = granularityHandler.addDataUnit(dataUnit);
+ if (dets != null) {
+ for (int dd = 0; dd < dets.length; dd++) {
+ exportCount++;
+ documentCount++;
+ onEffort.getDetection().add(dets[dd]);
+ }
+ }
+ if (exportCount % 100 == 0) {
+ prog = new DetectionExportProgress(deployment, null,
+ lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_GATHERING);
+ exportObserver.update(prog);
+ }
+ lastUnitTime = dataUnit.getTimeMilliseconds();
+ }
+
+ prog = new DetectionExportProgress(deployment, currentDetections,
+ lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_GATHERING);
+ exportObserver.update(prog);
+
+ if (documentCount > 500000 && mapPoint != dataMap.getLastMapPoint()) {
+ prog = new DetectionExportProgress(deployment, currentDetections,
+ lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_WRITING);
+ exportObserver.update(prog);
+ closeDetectionsDocument(currentDetections, mapPoint.getEndTime());
+ try {
+ dbxmlConnect.postAndLog(currentDetections);
+ } catch (TethysException e) {
+ tethysControl.showException(e);
+ }
+ currentDetections = null;
+ }
+
+ if (viewerLoadPolicy == ViewerLoadPolicy.LOAD_ALWAYS_EVERYTHING) {
+ break;
+ }
+ }
+
+
+ if (currentDetections != null) {
+ Detection dets[] = granularityHandler.cleanup(deployment.getAudioEnd());
+ if (dets != null) {
+ for (int dd = 0; dd < dets.length; dd++) {
+ exportCount++;
+ documentCount++;
+ currentDetections.getOnEffort().getDetection().add(dets[dd]);
+ }
+ }
+ prog = new DetectionExportProgress(deployment, currentDetections,
+ lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_WRITING);
+ closeDetectionsDocument(currentDetections, deployment.getAudioEnd());
+ try {
+ dbxmlConnect.postAndLog(currentDetections);
+ } catch (TethysException e) {
+ tethysControl.showException(e);
+ }
+ currentDetections = null;
+ }
+ }
+
+ prog = new DetectionExportProgress(null, null,
+ lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_COMPLETE);
+ exportObserver.update(prog);
+ return DetectionExportProgress.STATE_COMPLETE;
+ }
+
+ /**
+ * Start a new detections document for the deployment and datablock.
+ * Add all the standard information to the top of the Document
+ * @param deployment
+ * @param dataBlock
+ * @param exportParams
+ * @return new Detections document
+ */
+ private Detections startDetectionsDocument(PDeployment deployment, PamDataBlock dataBlock,
+ StreamExportParams exportParams) {
+ Detections detections = new Detections();
+ try {
+ Helper.createRequiredElements(detections);
+ } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) {
+ e.printStackTrace();
+ return null;
+ }
+ TethysDataProvider dataProvider = dataBlock.getTethysDataProvider(tethysControl);
+
+ String prefix = deployment.deployment.getId() + "_" + dataProvider.getDetectionsName();
+ String fullId = "";
+ /*
+ * Check the document name isn't already used and increment id as necessary.
+ */
+ while (true) {
+ fullId = String.format("%s_%d", prefix, uniqueDetectionsId++);
+ if (!tethysControl.getDbxmlQueries().documentExists(Collection.Detections.toString(), fullId)) {
+ break;
+ }
+ }
+ detections.setId(fullId);
+// detections.setDescription(dataProvider.getDescription(deployment, tethysExportParams));
+ detections.setDescription(exportParams.getNilusDetectionDescription());
+ DataSourceType dataSource = new DataSourceType();
+ dataSource.setDeploymentId(deployment.deployment.getId());
+// dataSource.setEnsembleId(""); ToDo
+ detections.setDataSource(dataSource);
+ AlgorithmType algorithm = detections.getAlgorithm();
+
+ if (dataProvider != null) {
+ algorithm = dataProvider.getAlgorithm();
+// detections.setAlgorithm(algorithm);
+ }
+ algorithm.setMethod(getMethodString(dataBlock));
+ algorithm.setSoftware(getSoftwareString(dataBlock));
+ algorithm.setVersion(getVersionString(dataBlock));
+
+ List supSoft = algorithm.getSupportSoftware();
+ SupportSoftware supportSoft = new SupportSoftware();
+ supportSoft.setSoftware(getSupportSoftware(dataBlock));
+ supportSoft.setVersion(getSupportSoftwareVersion(dataBlock));
+ supSoft.add(supportSoft);
+ detections.setAlgorithm(algorithm);
+ detections.setUserId("Unknown user");
+ detections.setEffort(getDetectorEffort(deployment, dataBlock, exportParams));
+
+ return detections;
+ }
+
+ /**
+ * Close a detections document. This basically just means rewriting the end time and it's only
+ * important in the event that a document got too big and has to be restarted.
+ * @param detections
+ * @param audioEnd
+ */
+ private void closeDetectionsDocument(Detections detections, Long audioEnd) {
+ detections.getEffort().setEnd(TethysTimeFuncs.xmlGregCalFromMillis(audioEnd));
+ }
+
+ /**
+ * Worker thread for exporting detections.
+ * Currently, it counts them first, then checks the user wants to export
+ * This requires going through the data twice, but may be sensible to avoid
+ * people outputting stupidly large documents.
+ * @author dg50
+ *
+ */
+ private class ExportWorker extends SwingWorker implements DetectionExportObserver {
+
+ private PamDataBlock dataBlock;
+ private StreamExportParams exportParams;
+ private DetectionExportObserver exportObserver;
+
+ public ExportWorker(PamDataBlock dataBlock, StreamExportParams exportParams,
+ DetectionExportObserver exportObserver) {
+ super();
+ this.dataBlock = dataBlock;
+ this.exportParams = exportParams;
+ this.exportObserver = exportObserver;
+ }
+
+ public void publish(DetectionExportProgress exportProgress) {
+ super.publish(exportProgress);
+ }
+
+ @Override
+ 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) {
+ ans = exportDetections(dataBlock, exportParams, this);
+ }
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ return ans;
+ }
+
+ @Override
+ protected void done() {
+// this.
+ DetectionExportProgress prog = new DetectionExportProgress(null, null, 0, 0, 0, 0, DetectionExportProgress.STATE_COMPLETE);
+ tethysControl.exportedDetections(dataBlock);
+ exportObserver.update(prog);
+ }
+
+ @Override
+ protected void process(List chunks) {
+ for (DetectionExportProgress prog : chunks) {
+ exportObserver.update(prog);
+ }
+ }
+
+ @Override
+ public void update(DetectionExportProgress progress) {
+ publish(progress);
+ }
+
+ }
+
+ /**
+ * Export data from given block, using appropriate species checks and other dialogs.
+ * @param dataBlock
+ */
+ public void exportDataBlock(PamDataBlock dataBlock) {
+ if (dataBlock == null) {
+ return;
+ }
+
+ /**
+ * Check the species map is OK before doing anything.
+ */
+ DataBlockSpeciesManager spManager = dataBlock.getDatablockSpeciesManager();
+ if (spManager != null) {
+ String error = spManager.checkSpeciesMapError();
+ if (error != null) {
+ PamDialog.showWarning(PamController.getMainFrame(), "Datablock species manager error", error);
+ spManager.showSpeciesDialog();
+ return;
+ }
+ }
+
+ DetectionsExportWizard.showDialog(tethysControl.getGuiFrame(), tethysControl, dataBlock);
+
+ }
+}
diff --git a/src/tethys/detection/EncounterGranularityHandler.java b/src/tethys/detection/EncounterGranularityHandler.java
new file mode 100644
index 00000000..57dd8757
--- /dev/null
+++ b/src/tethys/detection/EncounterGranularityHandler.java
@@ -0,0 +1,155 @@
+package tethys.detection;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamDataUnit;
+import nilus.Detection;
+import nilus.SpeciesIDType;
+import tethys.TethysControl;
+import tethys.TethysTimeFuncs;
+import tethys.output.StreamExportParams;
+import tethys.output.TethysExportParams;
+import tethys.pamdata.TethysDataProvider;
+import tethys.species.DataBlockSpeciesManager;
+import tethys.species.SpeciesMapItem;
+
+/**
+ * As with the binned Detections, this may generate multiple encounters
+ * at the same time for different types of sounds.
+ * @author dg50
+ *
+ */
+public class EncounterGranularityHandler extends GranularityHandler {
+
+
+ private HashMap currentDetections;
+ private TethysDataProvider dataProvider;
+ private DataBlockSpeciesManager speciesManager;
+ private long maxGapMillis;
+
+ public EncounterGranularityHandler(TethysControl tethysControl, PamDataBlock dataBlock,
+ TethysExportParams tethysExportParams, StreamExportParams streamExportParams) {
+ super(tethysControl, dataBlock, tethysExportParams, streamExportParams);
+
+ dataProvider = dataBlock.getTethysDataProvider(tethysControl);
+ speciesManager = dataBlock.getDatablockSpeciesManager();
+
+ maxGapMillis = (long) (streamExportParams.encounterGapS*1000);
+
+ currentDetections = new HashMap();
+ }
+
+ @Override
+ public void prepare(long timeMillis) {
+
+ }
+
+ @Override
+ public Detection[] addDataUnit(PamDataUnit dataUnit) {
+ Detection[] completeDetections = checkCurrentEncounters(dataUnit.getTimeMilliseconds());
+ // now look for new ones. First get the species of the dataUnit and find it in the hashmap
+ String groupName = getCallGroupName(dataUnit);
+ Detection det = currentDetections.get(groupName);
+ if (det == null) {
+ // need to make a new one.
+ det = new Detection();
+ det.setStart(TethysTimeFuncs.xmlGregCalFromMillis(dataUnit.getTimeMilliseconds()));
+ det.setEnd(TethysTimeFuncs.xmlGregCalFromMillis(dataUnit.getEndTimeInMilliseconds()));
+ det.setCount(BigInteger.ONE);
+ det.setChannel(BigInteger.valueOf(dataUnit.getChannelBitmap()));
+ // this should always return something, so am going to crash if it doesn't.
+ // may revisit this later on if we've unassigned things we don't want to label
+ // in which case they should be rejected earlier than this.
+ SpeciesMapItem speciesStuff = speciesManager.getSpeciesItem(dataUnit);
+ SpeciesIDType species = new SpeciesIDType();
+ species.setValue(BigInteger.valueOf(speciesStuff.getItisCode()));
+ det.setSpeciesId(species);
+ if (speciesStuff.getCallType() != null) {
+ det.getCall().add(speciesStuff.getCallType());
+ }
+ 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;
+ det.setCount(BigInteger.valueOf(count));
+ int chan = det.getChannel().intValue();
+ chan |= dataUnit.getChannelBitmap();
+ det.setChannel(BigInteger.valueOf(chan));
+ }
+
+
+ return completeDetections;
+ }
+
+ /**
+ * See if it's time to close off any encounters.
+ * @param timeMilliseconds current time
+ * @return list of complete encounters.
+ */
+ private Detection[] checkCurrentEncounters(long timeMilliseconds) {
+ Set keys = currentDetections.keySet();
+ int nGood = 0;
+ Detection[] newDetections = new Detection[currentDetections.size()];
+ Iterator> iter = currentDetections.entrySet().iterator();
+ while (iter.hasNext()) {
+ Entry entry = iter.next();
+ Detection aDet = entry.getValue();
+ long detEnd = TethysTimeFuncs.millisFromGregorianXML(aDet.getEnd());
+ if (timeMilliseconds-detEnd > maxGapMillis) {
+ // only keep if it's got a min number of calls.
+ if (aDet.getCount().intValue() >= streamExportParams.minBinCount) {
+ newDetections[nGood++] = aDet;
+ }
+ // remove from set. A new one will be created only when required.
+ iter.remove();
+ }
+ }
+
+ if (nGood == 0) {
+ return null;
+ }
+ else {
+ return Arrays.copyOf(newDetections, nGood);
+ }
+ }
+
+ // 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);
+ }
+
+}
diff --git a/src/tethys/detection/GranularityHandler.java b/src/tethys/detection/GranularityHandler.java
new file mode 100644
index 00000000..d172405e
--- /dev/null
+++ b/src/tethys/detection/GranularityHandler.java
@@ -0,0 +1,121 @@
+package tethys.detection;
+
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamDataUnit;
+import nilus.Detection;
+import nilus.GranularityEnumType;
+import tethys.TethysControl;
+import tethys.output.StreamExportParams;
+import tethys.output.TethysExportParams;
+import tethys.species.DataBlockSpeciesManager;
+
+public abstract class GranularityHandler {
+
+ protected TethysControl tethysControl;
+
+ protected PamDataBlock dataBlock;
+
+ protected TethysExportParams tethysExportParams;
+
+ protected StreamExportParams streamExportParams;
+
+ private DataBlockSpeciesManager speciesManager;
+
+ /**
+ * @param tethysControl
+ * @param dataBlock
+ * @param tethysExportParams
+ * @param streamExportParams
+ */
+ public GranularityHandler(TethysControl tethysControl, PamDataBlock dataBlock,
+ TethysExportParams tethysExportParams, StreamExportParams streamExportParams) {
+ this.tethysControl = tethysControl;
+ this.dataBlock = dataBlock;
+ this.tethysExportParams = tethysExportParams;
+ this.streamExportParams = streamExportParams;
+ speciesManager = dataBlock.getDatablockSpeciesManager();
+ }
+
+ /**
+ * Prepare to start, passing the start time of the effort
+ * or of the first time bin for binned granularity types.
+ * @param timeMillis
+ */
+ public abstract void prepare(long timeMillis);
+
+ /**
+ * Put a data unit into a Detection object. for Call granularity
+ * this will probably return every time. For binned and encounter
+ * types this will only return at the end of a bin / encounter
+ * @param dataUnit
+ * @return Detection object, but only when ready to be added to Detections
+ */
+ public abstract Detection[] addDataUnit(PamDataUnit dataUnit);
+
+ /**
+ * Get a grouping name for the call. This may just be the calls species code,
+ * or it may be appended with the channel number. This is used to find bin and
+ * encounter data in HashMaps in
+ * @param dataUnit
+ * @return
+ */
+ public String getCallGroupName(PamDataUnit dataUnit) {
+ String groupName = speciesManager.getSpeciesCode(dataUnit);
+ if (groupName == null) {
+ groupName = "NullSpecies";
+ }
+ if (streamExportParams.separateChannels) {
+ groupName += String.format("Chan%d", dataUnit.getChannelBitmap());
+ }
+ return groupName;
+ }
+ /**
+ * Called after end end of all data units to get the last bin / encounter.
+ *
+ * @param timeMillis end time of effort or last bin in milliseconds.
+ * @return null for Call granularity, otherwise may be non null for binned or encounter.
+ */
+ public abstract Detection[] cleanup(long timeMillis);
+
+ /**
+ * Convert a single detection to a one element array since that's what'
+ * most functions need to return.
+ * @param det
+ * @return
+ */
+ protected Detection[] toDetectionArray(Detection det) {
+ if (det == null) {
+ return null;
+ }
+ Detection[] dets = new Detection[1];
+ dets[0] = det;
+ return dets;
+ }
+
+ /**
+ * Create the correct type of granularity handler to put individual data units into
+ * Detection objects.
+ * @param granularity
+ * @param tethysControl
+ * @param dataBlock
+ * @param tethysExportParams
+ * @param streamExportParams
+ * @return
+ */
+ public static GranularityHandler getHandler(GranularityEnumType granularity, TethysControl tethysControl, PamDataBlock dataBlock,
+ TethysExportParams tethysExportParams, StreamExportParams streamExportParams) {
+ switch (granularity) {
+ case BINNED:
+ return new BinnedGranularityHandler(tethysControl, dataBlock, tethysExportParams, streamExportParams);
+ case CALL:
+ return new CallGranularityHandler(tethysControl, dataBlock, tethysExportParams, streamExportParams);
+ case ENCOUNTER:
+ return new EncounterGranularityHandler(tethysControl, dataBlock, tethysExportParams, streamExportParams);
+ case GROUPED:
+ return new GroupedGranularityHandler(tethysControl, dataBlock, tethysExportParams, streamExportParams);
+ default:
+ break;
+ }
+ return null;
+ }
+}
diff --git a/src/tethys/detection/GroupedGranularityHandler.java b/src/tethys/detection/GroupedGranularityHandler.java
new file mode 100644
index 00000000..93dbbd99
--- /dev/null
+++ b/src/tethys/detection/GroupedGranularityHandler.java
@@ -0,0 +1,32 @@
+package tethys.detection;
+
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.PamDataUnit;
+import nilus.Detection;
+import tethys.TethysControl;
+import tethys.output.StreamExportParams;
+import tethys.output.TethysExportParams;
+
+public class GroupedGranularityHandler extends CallGranularityHandler {
+
+ public GroupedGranularityHandler(TethysControl tethysControl, PamDataBlock dataBlock,
+ TethysExportParams tethysExportParams, StreamExportParams streamExportParams) {
+ super(tethysControl, dataBlock, tethysExportParams, streamExportParams);
+ }
+
+ @Override
+ public void prepare(long timeMillis) {
+ super.prepare(timeMillis);
+ }
+
+ @Override
+ public Detection[] addDataUnit(PamDataUnit dataUnit) {
+ return super.addDataUnit(dataUnit);
+ }
+
+ @Override
+ public Detection[] cleanup(long timeMillis) {
+ return super.cleanup(timeMillis);
+ }
+
+}
diff --git a/src/tethys/detection/StreamDetectionsSummary.java b/src/tethys/detection/StreamDetectionsSummary.java
new file mode 100644
index 00000000..70c11618
--- /dev/null
+++ b/src/tethys/detection/StreamDetectionsSummary.java
@@ -0,0 +1,21 @@
+package tethys.detection;
+
+import java.util.ArrayList;
+
+import tethys.niluswraps.PDetections;
+
+/**
+ * Summary information on all Detections documents for a Stream for this
+ * PAMGuard dataset.
+ * @author dg50
+ *
+ */
+public class StreamDetectionsSummary {
+
+ public ArrayList