From 2953d82b58448f1e41c8f18a7eb878bf9945a175 Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Wed, 3 May 2023 19:06:45 +0100
Subject: [PATCH] update X3 to get Detector parameters
X3 and PAMguard updated to get and save the SoundTrap click detector
parameters.
---
.classpath | 2 +-
pom.xml | 2 +-
src/soundtrap/ImportBCLDialog.java | 12 ++-
src/soundtrap/STClickControl.java | 62 ++++++++++++-
src/soundtrap/STXMLFile.java | 28 +++++-
src/soundtrap/sud/SUDParamsDialog.java | 107 +++++++++++++++++++++++
src/soundtrap/sud/SudFileDWVHandler.java | 17 +++-
7 files changed, 219 insertions(+), 11 deletions(-)
create mode 100644 src/soundtrap/sud/SUDParamsDialog.java
diff --git a/.classpath b/.classpath
index a5d40376..26c568d7 100644
--- a/.classpath
+++ b/.classpath
@@ -6,7 +6,7 @@
-
+
diff --git a/pom.xml b/pom.xml
index 2a916ff3..7ca73d0d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -784,7 +784,7 @@
pamguard.org
x3
- 2.2.1
+ 2.2.2
diff --git a/src/soundtrap/ImportBCLDialog.java b/src/soundtrap/ImportBCLDialog.java
index a0396d8c..3de2e6ee 100644
--- a/src/soundtrap/ImportBCLDialog.java
+++ b/src/soundtrap/ImportBCLDialog.java
@@ -453,12 +453,18 @@ public class ImportBCLDialog extends PamDialog {
int nFiles = 0;
int nCDET = 0;
int nDWV = 0;
+
+ STClickControl clickControl = (STClickControl) PamController.getInstance().findControlledUnit(STClickControl.STUNITTYPE, stToolsParams.clickDetName);
+
for (File xmlFile:xmlFiles) {
Debug.out.println("Opening xml file " + xmlFile.getAbsolutePath());
- if (xmlFile.getAbsolutePath().equals("E:\\STOctober2016\\335839252\\335839252.161031002807.log.xml")) {
- System.out.println("Opening xml file " + xmlFile.getAbsolutePath());
- }
+// if (xmlFile.getAbsolutePath().equals("E:\\STOctober2016\\335839252\\335839252.161031002807.log.xml")) {
+// System.out.println("Opening xml file " + xmlFile.getAbsolutePath());
+// }
STXMLFile xmlFileInfo = STXMLFile.openXMLFile(xmlFile, customDateTimeFormat.getText());
+ if (clickControl != null && xmlFileInfo.getSudDetectorInfo() != null) {
+ clickControl.setSudClickDetectorInfo(xmlFileInfo.getSudDetectorInfo());
+ }
if (xmlFileInfo == null || xmlFileInfo.getDwvInfo() == null) {
String title = "Error with Soundtrap file";
diff --git a/src/soundtrap/STClickControl.java b/src/soundtrap/STClickControl.java
index f80c1ca6..f210c765 100644
--- a/src/soundtrap/STClickControl.java
+++ b/src/soundtrap/STClickControl.java
@@ -25,19 +25,26 @@
package soundtrap;
import java.awt.Frame;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.Serializable;
import java.util.ArrayList;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
+import javax.swing.JSeparator;
+
+import org.pamguard.x3.sud.SUDClickDetectorInfo;
import Acquisition.AcquisitionControl;
-import Acquisition.sud.SUDNotificationManager;
+import PamController.PamControlledUnitSettings;
import PamController.PamController;
import PamguardMVC.PamRawDataBlock;
import clickDetector.ClickBTDisplay;
import clickDetector.ClickControl;
import clickDetector.ClickDisplay;
import clickDetector.ClickDisplayManager;
+import soundtrap.sud.SUDParamsDialog;
import soundtrap.sud.SudFileDWVHandler;
/**
@@ -46,6 +53,8 @@ import soundtrap.sud.SudFileDWVHandler;
*/
public class STClickControl extends ClickControl {
+ private SUDClickDetectorInfo sudClickDetectorInfo;
+
public static final String STUNITTYPE = "SoundTrap Click Detector";
/**
@@ -117,9 +126,23 @@ public class STClickControl extends ClickControl {
}
}
+ JMenuItem sudItem = new JMenuItem("Sound Trap settings ...");
+ sudItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ showSudParameters(parentFrame);
+ }
+ });
+ newMenu.add(sudItem, 0);
+ newMenu.add(new JSeparator(), 1);
+
return newMenu;
}
+ protected void showSudParameters(Frame parentFrame) {
+ SUDParamsDialog.showDialog(parentFrame, this);
+ }
+
@Override
public void pamStart() {
sudFileDWVHandler.pamStart();
@@ -157,6 +180,43 @@ public class STClickControl extends ClickControl {
}
}
}
+
+ @Override
+ public long getSettingsVersion() {
+ return SUDClickDetectorInfo.serialVersionUID;
+ }
+
+ @Override
+ public Serializable getSettingsReference() {
+ return getSudClickDetectorInfo();
+ }
+
+ @Override
+ public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
+ Object o = pamControlledUnitSettings.getSettings();
+ if (o instanceof SUDClickDetectorInfo) {
+ sudClickDetectorInfo = (SUDClickDetectorInfo) o;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @return the sudClickDetectorInfo
+ */
+ public SUDClickDetectorInfo getSudClickDetectorInfo() {
+ if (sudClickDetectorInfo == null) {
+ sudClickDetectorInfo = new SUDClickDetectorInfo();
+ }
+ return sudClickDetectorInfo;
+ }
+
+ /**
+ * @param sudClickDetectorInfo the sudClickDetectorInfo to set
+ */
+ public void setSudClickDetectorInfo(SUDClickDetectorInfo sudClickDetectorInfo) {
+ this.sudClickDetectorInfo = sudClickDetectorInfo;
+ }
}
diff --git a/src/soundtrap/STXMLFile.java b/src/soundtrap/STXMLFile.java
index a63a21f2..20ad30a9 100644
--- a/src/soundtrap/STXMLFile.java
+++ b/src/soundtrap/STXMLFile.java
@@ -12,6 +12,8 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+import org.pamguard.x3.sud.SUDClickDetectorInfo;
+import org.pamguard.x3.sud.SUDXMLUtils;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
@@ -41,6 +43,7 @@ public class STXMLFile {
private WAVInfo wavInfo;
private String soundTrapId;
private String dateFormat = defaultDateFormat;
+ private SUDClickDetectorInfo sudDetectorInfo;
public static void main(String[] args) {
@@ -70,6 +73,9 @@ public class STXMLFile {
}
private void unpackXMLDoc() throws Exception{
+ // try to get the new format complete settings as has been developed for the
+ // SUD direct reader.
+
cfgNodes = doc.getElementsByTagName("CFG");
NodeList procEvents = doc.getElementsByTagName("PROC_EVENT");
@@ -231,8 +237,14 @@ public class STXMLFile {
return null;
}
doc.getDocumentElement().normalize();
+
+ STXMLFile stXMLFile = new STXMLFile(doc, xmlFile, dateTimeFormat);
+
+ SUDXMLUtils sudXml = new SUDXMLUtils();
+ SUDClickDetectorInfo detectorInfo = sudXml.extractDetectorInfo(doc);
+ stXMLFile.setSudDetectorInfo(detectorInfo);
- return new STXMLFile(doc, xmlFile, dateTimeFormat);
+ return stXMLFile;
}
/**
@@ -299,4 +311,18 @@ public class STXMLFile {
}
return null;
}
+
+ /**
+ * @return the sudDetectorInfo
+ */
+ public SUDClickDetectorInfo getSudDetectorInfo() {
+ return sudDetectorInfo;
+ }
+
+ /**
+ * @param sudDetectorInfo the sudDetectorInfo to set
+ */
+ public void setSudDetectorInfo(SUDClickDetectorInfo sudDetectorInfo) {
+ this.sudDetectorInfo = sudDetectorInfo;
+ }
}
diff --git a/src/soundtrap/sud/SUDParamsDialog.java b/src/soundtrap/sud/SUDParamsDialog.java
new file mode 100644
index 00000000..335b20b9
--- /dev/null
+++ b/src/soundtrap/sud/SUDParamsDialog.java
@@ -0,0 +1,107 @@
+package soundtrap.sud;
+
+import java.awt.GridBagConstraints;
+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 org.pamguard.x3.sud.SUDClickDetectorInfo;
+
+import PamView.dialog.PamDialog;
+import PamView.dialog.PamGridBagContraints;
+import soundtrap.STClickControl;
+
+/**
+ * Display ST detection parameters. These cannot be changed so all boxes are disabled.
+ * @author dg50
+ *
+ */
+public class SUDParamsDialog extends PamDialog {
+
+ private STClickControl stClickControl;
+
+ private JTextField sampleRate, channels, threshold, blanking, preSamps, postSamps, len;
+
+ private static SUDParamsDialog singleInstance;
+
+ private SUDParamsDialog(Window parentFrame, STClickControl stClickControl) {
+ super(parentFrame, stClickControl.getUnitName(), false);
+ this.stClickControl = stClickControl;
+ JPanel mainPanel = new JPanel(new GridBagLayout());
+ mainPanel.setBorder(new TitledBorder("SoundTrap Detector Configuration"));
+ GridBagConstraints c = new PamGridBagContraints();
+ sampleRate = addThing(mainPanel, "Sample Rate", "Hz", c);
+ channels = addThing(mainPanel, "Num Channels", null, c);
+ threshold = addThing(mainPanel, "Threshold", "dB", c);
+ blanking = addThing(mainPanel, "Blanking", "samples", c);
+ preSamps = addThing(mainPanel, "Pre Samples", "samples", c);
+ postSamps = addThing(mainPanel, "Post Samples", "samples", c);
+ len = addThing(mainPanel, "Length", "samples", c);
+
+ setDialogComponent(mainPanel);
+ }
+
+ public static void showDialog(Window parent, STClickControl stClickControl) {
+// if (singleInstance == null) {
+ singleInstance = new SUDParamsDialog(parent, stClickControl);
+// }
+ singleInstance.setParams(stClickControl.getSudClickDetectorInfo());
+ singleInstance.setVisible(true);
+ return;
+ }
+
+ private void setParams(SUDClickDetectorInfo sudClickDetectorInfo) {
+ sampleRate.setText(String.format("%d", sudClickDetectorInfo.sampleRate));
+ channels.setText(String.format("%d", sudClickDetectorInfo.nChan));
+ threshold.setText(String.format("%3.1f", sudClickDetectorInfo.detThr));
+ blanking.setText(String.format("%d", sudClickDetectorInfo.blankingSamples));
+ preSamps.setText(String.format("%d", sudClickDetectorInfo.preSamples));
+ postSamps.setText(String.format("%d", sudClickDetectorInfo.postSamples));
+ len.setText(String.format("%d", sudClickDetectorInfo.lenSamples));
+ }
+
+ private JTextField addThing(JPanel mainPanel, String title, String postTit, GridBagConstraints c) {
+ c.gridx = 0;
+ mainPanel.add(new JLabel(title, JLabel.RIGHT), c);
+ c.gridx++;
+ STField field = new STField(5);
+ mainPanel.add(field, c);
+ if (postTit != null) {
+ c.gridx++;
+ mainPanel.add(new JLabel(postTit, JLabel.LEFT), c);
+ }
+ c.gridy++;
+ return field;
+ }
+
+ @Override
+ public boolean getParams() {
+ return true;
+ }
+
+ @Override
+ public void cancelButtonPressed() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void restoreDefaultSettings() {
+ // TODO Auto-generated method stub
+
+ }
+
+ private class STField extends JTextField {
+
+ public STField(int columns) {
+ super(columns);
+ setEditable(false);
+ }
+
+ }
+
+}
diff --git a/src/soundtrap/sud/SudFileDWVHandler.java b/src/soundtrap/sud/SudFileDWVHandler.java
index 11abd304..f03238a1 100644
--- a/src/soundtrap/sud/SudFileDWVHandler.java
+++ b/src/soundtrap/sud/SudFileDWVHandler.java
@@ -10,6 +10,7 @@ import java.util.List;
import org.pamguard.x3.sud.Chunk;
import org.pamguard.x3.sud.SudAudioInputStream;
import org.pamguard.x3.sud.SudDataInputStream;
+import org.pamguard.x3.sud.SudFileMap;
import Acquisition.AcquisitionControl;
import Acquisition.sud.SUDNotificationHandler;
@@ -73,7 +74,15 @@ public class SudFileDWVHandler implements SUDNotificationHandler {
// this is the wav sample rate, not the detector sample rate, so don't use it
// sampleRate = sudAudioInputStream.getFormat().getFrameRate();
// this is the right one
- sampleRate = sudAudioInputStream.getSudMap().clickDetSampleRate;
+ SudFileMap sudMap = sudAudioInputStream.getSudMap();
+ sampleRate = 0;
+ if (sudMap.detectorInfo != null) {
+ sampleRate = sudMap.detectorInfo.sampleRate;
+ stClickControl.setSudClickDetectorInfo(sudMap.detectorInfo);
+ }
+ if (sampleRate == 0) {
+ sampleRate = sudAudioInputStream.getSudMap().clickDetSampleRate;
+ }
fileStartMicros = sudAudioInputStream.getSudMap().getFirstChunkTimeMicros();
stClickControl.findRawDataBlock().setChannelMap(1);
stClickControl.findRawDataBlock().setSampleRate((float) sampleRate, true);
@@ -81,7 +90,7 @@ public class SudFileDWVHandler implements SUDNotificationHandler {
stClickControl.getSTAcquisition().acquisitionParameters.voltsPeak2Peak = STAcquisitionControl.SOUNDTRAPVP2P;
stClickControl.getSTAcquisition().getAcquisitionProcess().setSampleRate((float) sampleRate, true);
// System.out.printf("Open input stream fs = %3.1f\n", sampleRate);
-
+
}
@Override
@@ -104,10 +113,10 @@ public class SudFileDWVHandler implements SUDNotificationHandler {
String chunkName = "Unknown";
int chunkSize = sudChunk.buffer.length;
if (sudAudioInputStream.getChunkIDString(chunkID).equals("wav")) {
-
+
long millis = sudChunk.getChunkHeader().getMillisTime();
stClickControl.updateDisplayScrollers(millis);
-
+
if (sudAudioInputStream.isChunkIDWav(chunkID)) {
// chunkName = "RECORDINGS";
// System.out.printf("Chunk ID %d, size %d, type %s\n", chunkID, chunkSize,