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,