mirror of
https://github.com/PAMGuard/PAMGuard.git
synced 2024-11-21 22:52:22 +00:00
Squashed commit of the following:
commit840e6c89a1
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com> Date: Thu Nov 16 20:36:14 2023 +0000 R2.02.09d Fix matched template classifier import fix azigram help file image display commitacc806d375
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com> Date: Wed Nov 15 13:08:02 2023 +0000 Updated X3 library to 2.2.6 commita4f484c76c
Merge:8e60ad2e
d7c4c278
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com> Date: Wed Nov 15 09:44:09 2023 +0000 Merge branch 'main' of https://github.com/PAMGuard/PAMGuard.git into main commit8e60ad2eff
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com> Date: Wed Nov 15 09:43:39 2023 +0000 update to array diagnostics and sensor control commitd7c4c278d8
Author: m2oswald <45486636+m2oswald@users.noreply.github.com> Date: Wed Nov 15 09:17:49 2023 +0000 Added code to Rocca for training/testing classifier (#114) * allow Rocca to run without classifiers Fixed bug that threw an error if no classifier files were specified in Rocca Params dialog * add rocca switch to enable dev mode currently only shows/hides extra buttons in the Params dialog, but will extend to more options in the future * Fix memory issue with RoccaContourDataBlocks not being released for garbage collection Set RoccaContourDataBlock objects to null and stop PamObserver Timer to force release * Fix problem tracing whistles in Rocca spectrogram pop-up Whistle and raw data were being cleared before the user had time to trace out the whistle, causing PAMGuard to throw an exception. Both were already being cleared when the pop-up window is closed, so no need to do it here. * updated for training/testing classifiers commitd5f504dcd1
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com> Date: Fri Nov 10 18:08:31 2023 +0000 Bearing localiser offline save Bug stopping it correctly saving data from the offline task to the database fixed. commit7a44d49e27
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com> Date: Fri Oct 27 09:59:28 2023 +0100 X3 Version 2.2.3 Add maven jar files for X3/SUD version 2.2.3 commitfa5fe9943d
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com> Date: Thu Oct 26 14:44:41 2023 +0100 update sud file management to more efficiently skip to the correct part of a sud file when reading data offline. commit60435e567a
Author: Brian S Miller <93690136+BrianSMiller@users.noreply.github.com> Date: Fri Sep 8 21:54:40 2023 +1000 Fixes issues #111 and fixes #112 (DIFAR module crashes and ability to use Deep Learning Detections in DIFAR module) (#110) * Bugfix for OverlayMarks Check for a null pointer exception in OverlayMarks that was causing a crash on startup. * Bugfix for null pointer in symbol manager Fix a bug that I found where the DIFAR module was crashing the symbol manager. Seems that this was due to this subclass of clip generator having a null value for it's uniqueName. I've fixed by checking for null values and assigning a generic symbol when null. * DeepLearning detections canGenerateClips=true Set flag in DeepLearning detector so that detections are considered 'clips' by Pamguard. This allows them to be processed automatically in the DIFAR Localisation module (and maybe others). * DIFAR: bugfix frequency limits for auto-detections Fix a bug in DIFAR module where the frequency limits of automated detections were not being set properly by the DIFAR module. * DeepLearning - Bugfix to detection duration Fix bug in deep learning detector where duration (in samples) was being set to number of samples in a hop instead of the number of samples in a segment.
This commit is contained in:
parent
a235619edd
commit
54264a689b
@ -8,6 +8,7 @@
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
|
||||
<attributes>
|
||||
<attribute name="module" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<groupId>org.pamguard</groupId>
|
||||
<artifactId>Pamguard</artifactId>
|
||||
<name>Pamguard Java12+</name>
|
||||
<version>2.02.09e</version>
|
||||
<version>2.02.09c</version>
|
||||
<description>Pamguard for Java 12+, using Maven to control dependcies</description>
|
||||
<url>www.pamguard.org</url>
|
||||
<organization>
|
||||
@ -53,16 +53,16 @@
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<version>3.8.1</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>tycho-compiler-jdt</artifactId>
|
||||
<version>4.0.3</version>
|
||||
<version>1.5.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<configuration>
|
||||
<release>17</release>
|
||||
<release>11</release>
|
||||
<compilerId>jdt</compilerId>
|
||||
<compilerArguments>
|
||||
<properties>.settings/org.eclipse.jdt.core.prefs</properties>
|
||||
@ -72,11 +72,16 @@
|
||||
<plugin>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-maven-plugin</artifactId>
|
||||
<version>0.0.8</version>
|
||||
<version>0.0.6</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<release>17</release>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
@ -189,8 +194,8 @@
|
||||
</plugins>
|
||||
</reporting>
|
||||
<properties>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<javafx.version>17</javafx.version>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<javafx.version>16</javafx.version>
|
||||
</properties>
|
||||
</project>
|
||||
|
36
pom.xml
36
pom.xml
@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.pamguard</groupId>
|
||||
<artifactId>Pamguard</artifactId>
|
||||
<version>2.02.09e</version>
|
||||
<version>2.02.09d</version>
|
||||
<name>Pamguard Java12+</name>
|
||||
<description>Pamguard for Java 12+, using Maven to control dependcies</description>
|
||||
<url>www.pamguard.org</url>
|
||||
@ -15,9 +15,9 @@
|
||||
|
||||
|
||||
<properties>
|
||||
<javafx.version>17</javafx.version>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<javafx.version>16</javafx.version>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
@ -49,10 +49,11 @@
|
||||
-->
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
|
||||
<!-- set compiler to use Java version 11 API https://docs.oracle.com/javase/9/tools/javac.htm#JSWOR627 -->
|
||||
<release>17</release>
|
||||
<release>11</release>
|
||||
<compilerId>jdt</compilerId>
|
||||
<compilerArguments>
|
||||
<properties>.settings/org.eclipse.jdt.core.prefs</properties> <!-- make sure to use same params as what Eclipse uses -->
|
||||
@ -64,7 +65,7 @@
|
||||
<dependency>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>tycho-compiler-jdt</artifactId>
|
||||
<version>4.0.3</version>
|
||||
<version>1.5.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@ -73,7 +74,12 @@
|
||||
<plugin>
|
||||
<groupId>org.openjfx</groupId>
|
||||
<artifactId>javafx-maven-plugin</artifactId>
|
||||
<version>0.0.8</version>
|
||||
<version>0.0.6</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<release>17</release>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Maven Shade plugin - for creating the uberjar / fatjar -->
|
||||
@ -81,7 +87,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<version>3.2.1</version>
|
||||
<configuration>
|
||||
<transformers>
|
||||
<transformer
|
||||
@ -312,7 +318,7 @@
|
||||
<dependency>
|
||||
<groupId>io.github.macster110</groupId>
|
||||
<artifactId>jpamutils</artifactId>
|
||||
<version>0.0.57</version>
|
||||
<version>0.0.56</version>
|
||||
</dependency>
|
||||
|
||||
<!--jpam project - Deep learning java library
|
||||
@ -323,7 +329,7 @@
|
||||
<dependency>
|
||||
<groupId>io.github.macster110</groupId>
|
||||
<artifactId>jdl4pam</artifactId>
|
||||
<version>0.0.97</version>
|
||||
<version>0.0.94</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/gov.nist.math/jama -->
|
||||
@ -389,7 +395,7 @@
|
||||
<dependency>
|
||||
<groupId>net.synedra</groupId>
|
||||
<artifactId>validatorfx</artifactId>
|
||||
<version>0.4.2</version>
|
||||
<version>0.4.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-compress -->
|
||||
@ -776,13 +782,13 @@
|
||||
|
||||
<!-- not in Maven repository
|
||||
you may need to copy files from your downloaded PAMGuard source code, e.g. C:\Users\*yourreposfolder*\source\repos\PAMGuardPAMGuard\repo\pamguard\org\x3\2.2.2 to
|
||||
C:\Users\*yourusername*\.m2\repository\pamguard\org\x3\2.2.2
|
||||
-->
|
||||
C:\Users\*yourusername*\.m2\repository\pamguard\org\x3\2.2.2-->
|
||||
<dependency>
|
||||
<groupId>org.pamguard</groupId>
|
||||
<groupId>pamguard.org</groupId>
|
||||
<artifactId>x3</artifactId>
|
||||
<version>2.2.6</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/it.sauronsoftware/jave -->
|
||||
<dependency>
|
||||
|
4
repo/pamguard/org/x3/2.2.6/_remote.repositories
Normal file
4
repo/pamguard/org/x3/2.2.6/_remote.repositories
Normal file
@ -0,0 +1,4 @@
|
||||
#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice.
|
||||
#Wed Nov 15 12:43:42 GMT 2023
|
||||
x3-2.2.6.jar>=
|
||||
x3-2.2.6.pom>=
|
BIN
repo/pamguard/org/x3/2.2.6/x3-2.2.6.jar
Normal file
BIN
repo/pamguard/org/x3/2.2.6/x3-2.2.6.jar
Normal file
Binary file not shown.
9
repo/pamguard/org/x3/2.2.6/x3-2.2.6.pom
Normal file
9
repo/pamguard/org/x3/2.2.6/x3-2.2.6.pom
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>pamguard.org</groupId>
|
||||
<artifactId>x3</artifactId>
|
||||
<version>2.2.6</version>
|
||||
<description>POM was created from install:install-file</description>
|
||||
</project>
|
@ -20,29 +20,26 @@ import PamUtils.worker.PamWorker;
|
||||
/**
|
||||
* Opens a .sud audio file.
|
||||
* <p>
|
||||
* Sud files contain X3 compressed audio data. The sud
|
||||
* file reader opens files, creating a map of the file and saving
|
||||
* the map as a.sudx file so it can be read more rapidly when the file
|
||||
* is next accessed.
|
||||
* Sud files contain X3 compressed audio data. The sud file reader opens files,
|
||||
* creating a map of the file and saving the map as a.sudx file so it can be
|
||||
* read more rapidly when the file is next accessed.
|
||||
* <p>
|
||||
* The SudioAudioInput stream fully implements AudioInputStream and so
|
||||
* sud files can be accessed using much of the same code as .wav files.
|
||||
*
|
||||
* The SudioAudioInput stream fully implements AudioInputStream and so sud files
|
||||
* can be accessed using much of the same code as .wav files.
|
||||
*
|
||||
* @author Jamie Macaulay
|
||||
*
|
||||
*/
|
||||
public class SudAudioFile extends WavAudioFile {
|
||||
|
||||
private Object conditionSync = new Object();
|
||||
|
||||
private Object conditionSync = new Object();
|
||||
|
||||
private volatile PamWorker<AudioInputStream> worker;
|
||||
private volatile SudMapWorker sudMapWorker;
|
||||
|
||||
|
||||
public SudAudioFile() {
|
||||
super();
|
||||
fileExtensions = new ArrayList<String>(Arrays.asList(new String[]{".sud"}));
|
||||
super();
|
||||
fileExtensions = new ArrayList<String>(Arrays.asList(new String[] { ".sud" }));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -50,96 +47,96 @@ public class SudAudioFile extends WavAudioFile {
|
||||
return "SUD";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AudioInputStream getAudioStream(File soundFile) {
|
||||
|
||||
synchronized(conditionSync) {
|
||||
|
||||
//System.out.println("Get SUD getAudioStream : " + soundFile.getName());
|
||||
synchronized (conditionSync) {
|
||||
|
||||
if (soundFile.exists() == false) {
|
||||
System.err.println("The sud file does not exist: " + soundFile);
|
||||
return null;
|
||||
}
|
||||
if (soundFile != null) {
|
||||
|
||||
|
||||
if (new File(soundFile.getAbsolutePath()+"x").exists()) {
|
||||
System.out.println("----NO NEED TO MAP SUD FILE-----" + soundFile);
|
||||
try {
|
||||
return new SudAudioFileReader().getAudioInputStream(soundFile);
|
||||
} catch (UnsupportedAudioFileException | IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
// System.out.println("Get SUD getAudioStream : " + soundFile.getName());
|
||||
|
||||
if (soundFile.exists() == false) {
|
||||
System.err.println("The sud file does not exist: " + soundFile);
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
|
||||
System.out.println("----MAP SUD FILE ON OTHER THREAD-----" + soundFile);
|
||||
if (soundFile != null) {
|
||||
|
||||
/**
|
||||
* We need to map the sud file. But we don't want this to just freeze the current GUI thread. Therefore
|
||||
* add a listener to the mapping process and show a blocking dialog to indicate that something is happening.
|
||||
* The mapping is put on a separate thread and blocks stuff from happening until the mapping process has completed.
|
||||
*/
|
||||
if (sudMapWorker==null || !sudMapWorker.getSudFile().equals(soundFile)) {
|
||||
|
||||
sudMapWorker = new SudMapWorker(soundFile);
|
||||
worker = new PamWorker<AudioInputStream>(sudMapWorker, PamController.getInstance().getMainFrame(),1, "Mapping sud file: " + soundFile.getName());
|
||||
// System.out.println("Sud Audio Stream STARTED: " + soundFile.getName());
|
||||
|
||||
SwingUtilities.invokeLater(()->{
|
||||
worker.start();
|
||||
});
|
||||
//this should block AWT thread but won't block if called on another thread..
|
||||
}
|
||||
|
||||
//this is only ever called if this function is called on another thread other than the event dispatch thread.
|
||||
while (sudMapWorker==null || !sudMapWorker.isDone()) {
|
||||
//do nothing
|
||||
System.out.println("Waiting for the SUD file map: " + soundFile.getName() + " worker: " + worker);
|
||||
if (new File(soundFile.getAbsolutePath() + "x").exists()) {
|
||||
// System.out.println("----NO NEED TO MAP SUD FILE-----" + soundFile);
|
||||
try {
|
||||
// Thread.sleep(100);
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
return new SudAudioFileReader().getAudioInputStream(soundFile);
|
||||
} catch (UnsupportedAudioFileException | IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
AudioInputStream stream = sudMapWorker.getSudAudioStream();
|
||||
|
||||
} else {
|
||||
|
||||
// System.out.println("----MAP SUD FILE ON OTHER THREAD-----" + soundFile);
|
||||
|
||||
/**
|
||||
* We need to map the sud file. But we don't want this o just freeze the current
|
||||
* GUI thread. Therefore add a listener to the mapping process and show a
|
||||
* blocking dialog to indicate that something is happening. The mapping is put
|
||||
* on a separate thread and blocks stuff from happening until the mapping
|
||||
* process has completed.
|
||||
*/
|
||||
if (sudMapWorker == null || !sudMapWorker.getSudFile().equals(soundFile)) {
|
||||
|
||||
sudMapWorker = new SudMapWorker(soundFile);
|
||||
worker = new PamWorker<AudioInputStream>(sudMapWorker,
|
||||
PamController.getInstance().getMainFrame(), 1,
|
||||
"Mapping sud file: " + soundFile.getName());
|
||||
// System.out.println("Sud Audio Stream STARTED: " + soundFile.getName());
|
||||
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
worker.start();
|
||||
});
|
||||
// this should block AWT thread but won't block if called on another thread..
|
||||
}
|
||||
|
||||
// this is only ever called if this function is called on another thread other
|
||||
// than the event dispatch thread.
|
||||
while (sudMapWorker == null || !sudMapWorker.isDone()) {
|
||||
// do nothing
|
||||
// System.out.println("Waiting for the SUD file map: " + soundFile.getName() + " worker: " + worker);
|
||||
try {
|
||||
// Thread.sleep(100);
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
AudioInputStream stream = sudMapWorker.getSudAudioStream();
|
||||
|
||||
// sudMapWorker= null;
|
||||
// worker = null;
|
||||
|
||||
System.out.println("----RETURN SUD FILE ON OTHER THREAD-----" + stream);
|
||||
// worker = null;
|
||||
|
||||
|
||||
return stream;
|
||||
// System.out.println("----RETURN SUD FILE ON OTHER THREAD-----" + stream);
|
||||
|
||||
return stream;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public class SudMapProgress implements SudMapListener {
|
||||
|
||||
PamWorker<AudioInputStream> sudMapWorker;
|
||||
PamWorker<AudioInputStream> sudMapWorker;
|
||||
|
||||
public SudMapProgress(PamWorker<AudioInputStream> sudMapWorker) {
|
||||
this.sudMapWorker=sudMapWorker;
|
||||
public SudMapProgress(PamWorker<AudioInputStream> sudMapWorker) {
|
||||
this.sudMapWorker = sudMapWorker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chunkProcessed(ChunkHeader chunkHeader, int count) {
|
||||
//System.out.println("Sud Map Progress: " + count);
|
||||
if (count%500 == 0) {
|
||||
//don't update too often or everything just freezes
|
||||
sudMapWorker.update(new PamWorkProgressMessage(-1, ("Mapped " +count + " sud file chunks")));
|
||||
// System.out.println("Sud Map Progress: " + count);
|
||||
if (count % 500 == 0) {
|
||||
// don't update too often or everything just freezes
|
||||
sudMapWorker.update(new PamWorkProgressMessage(-1, ("Mapped " + count + " sud file chunks")));
|
||||
}
|
||||
if (count == -1) {
|
||||
sudMapWorker.update(new PamWorkProgressMessage(-1, ("Mapping sud file finished")));
|
||||
@ -149,12 +146,13 @@ public class SudAudioFile extends WavAudioFile {
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens an sud file on a different thread and adds a listener for a mapping. This allows
|
||||
* a callback to show map progress.
|
||||
* Opens an sud file on a different thread and adds a listener for a mapping.
|
||||
* This allows a callback to show map progress.
|
||||
*
|
||||
* @author Jamie Macaulay
|
||||
*
|
||||
*/
|
||||
public class SudMapWorker implements PamWorkWrapper<AudioInputStream>{
|
||||
public class SudMapWorker implements PamWorkWrapper<AudioInputStream> {
|
||||
|
||||
private File soundFile;
|
||||
|
||||
@ -165,7 +163,7 @@ public class SudAudioFile extends WavAudioFile {
|
||||
private AudioInputStream result;
|
||||
|
||||
public SudMapWorker(File soundFile) {
|
||||
this.soundFile = soundFile;
|
||||
this.soundFile = soundFile;
|
||||
}
|
||||
|
||||
public File getSudFile() {
|
||||
@ -180,28 +178,26 @@ public class SudAudioFile extends WavAudioFile {
|
||||
public AudioInputStream runBackgroundTask(PamWorker<AudioInputStream> pamWorker) {
|
||||
AudioInputStream stream;
|
||||
try {
|
||||
System.out.println("START OPEN SUD FILE:");
|
||||
// System.out.println("START OPEN SUD FILE:");
|
||||
|
||||
this.sudMapListener = new SudMapProgress(pamWorker);
|
||||
this.sudMapListener = new SudMapProgress(pamWorker);
|
||||
stream = new SudAudioFileReader().getAudioInputStream(soundFile, sudMapListener);
|
||||
|
||||
System.out.println("END SUD FILE:");
|
||||
|
||||
|
||||
//for some reason - task finished may not be called on other
|
||||
//thread so put this here.
|
||||
this.result = stream;
|
||||
this.done = true;
|
||||
// System.out.println("END SUD FILE:");
|
||||
|
||||
// for some reason - task finished may not be called on other
|
||||
// thread so put this here.
|
||||
this.result = stream;
|
||||
this.done = true;
|
||||
|
||||
return stream;
|
||||
}
|
||||
catch (UnsupportedAudioFileException e) {
|
||||
System.err.println("UnsupportedAudioFileException: Could not open sud file: not a supported file " + soundFile.getName());
|
||||
} catch (UnsupportedAudioFileException e) {
|
||||
System.err.println("UnsupportedAudioFileException: Could not open sud file: not a supported file "
|
||||
+ soundFile.getName());
|
||||
System.err.println(e.getMessage());
|
||||
// e.printStackTrace();
|
||||
// e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
System.err.println("Could not open sud file: IO Exception: " + soundFile.getName());
|
||||
System.err.println("Could not open sud file: IO Exception: " + soundFile.getName());
|
||||
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -210,9 +206,9 @@ public class SudAudioFile extends WavAudioFile {
|
||||
|
||||
@Override
|
||||
public void taskFinished(AudioInputStream result) {
|
||||
System.out.println("TASK FINSIHED:");
|
||||
this.result = result;
|
||||
this.done = true;
|
||||
// System.out.println("TASK FINSIHED:");
|
||||
this.result = result;
|
||||
this.done = true;
|
||||
}
|
||||
|
||||
public boolean isDone() {
|
||||
@ -221,7 +217,4 @@ public class SudAudioFile extends WavAudioFile {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -27,48 +27,50 @@ public class SudAudioFileReader {
|
||||
|
||||
|
||||
public SudAudioFileReader() {
|
||||
sudParams = new SudParams();
|
||||
//set up the sud params for default. i.e. just read files and
|
||||
//don't save any decompressed or meta data.
|
||||
// sudParams.saveWav = false;
|
||||
// sudParams.saveMeta = false;
|
||||
sudParams = new SudParams();
|
||||
//set up the sud params for default. i.e. just read files and
|
||||
//don't save any decompressed or meta data.
|
||||
// sudParams.saveWav = false;
|
||||
// sudParams.saveMeta = false;
|
||||
sudParams.setFileSave(false, false, false, false);
|
||||
sudParams.zeroPad = true;
|
||||
}
|
||||
sudParams.zeroPad = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the audio input stream for a sud file.
|
||||
* Get the audio input streamn.
|
||||
* @param file - the .sud file to open.
|
||||
* @return the sud AudioStream.
|
||||
* @throws UnsupportedAudioFileException
|
||||
* @throws IOException
|
||||
*/
|
||||
public AudioInputStream getAudioInputStream(File file) throws UnsupportedAudioFileException, IOException {
|
||||
return getAudioInputStream( file, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the audio input stream for a sud file.
|
||||
* @param file - the .sud file to open.
|
||||
* @param mapListener- a listener for the sud file maps - can be null.
|
||||
* @return the sud AudioStream.
|
||||
* @throws UnsupportedAudioFileException
|
||||
* @throws IOException
|
||||
*/
|
||||
public AudioInputStream getAudioInputStream(File file, SudMapListener mapListener) throws UnsupportedAudioFileException, IOException {
|
||||
|
||||
// System.out.println("Get SUD getAudioInputStream");
|
||||
|
||||
try {
|
||||
sudAudioInputStream = SudAudioInputStream.openInputStream(file, sudParams, mapListener, false);
|
||||
sudAudioInputStream = SudAudioInputStream.openInputStream(file, sudParams, false);
|
||||
} catch (Exception e) {
|
||||
String msg = String.format("Corrupt sud file %s: %s", file.getName(), e.getMessage());
|
||||
throw new UnsupportedAudioFileException(msg);
|
||||
}
|
||||
return sudAudioInputStream;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the audio input stream for a sud file.
|
||||
* @param file - the .sud file to open.
|
||||
* @param mapListener- a listener for the sud file maps - can be null.
|
||||
* @return the sud AudioStream.
|
||||
* @throws UnsupportedAudioFileException
|
||||
* @throws IOException
|
||||
*/
|
||||
public AudioInputStream getAudioInputStream(File file, SudMapListener mapListener) throws UnsupportedAudioFileException, IOException {
|
||||
|
||||
// System.out.println("Get SUD getAudioInputStream");
|
||||
|
||||
try {
|
||||
sudAudioInputStream = SudAudioInputStream.openInputStream(file, sudParams, mapListener, false);
|
||||
} catch (Exception e) {
|
||||
String msg = String.format("Corrupt sud file %s: %s", file.getName(), e.getMessage());
|
||||
throw new UnsupportedAudioFileException(msg);
|
||||
}
|
||||
return sudAudioInputStream;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
package Acquisition.sud;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
import org.pamguard.x3.sud.SudAudioInputStream;
|
||||
|
||||
|
||||
public class SUDFileTime {
|
||||
|
||||
|
||||
private static long sudTime;
|
||||
|
||||
private static String lastFilePath = "";
|
||||
/**
|
||||
* Temp measure to get the time from the first available sud record.
|
||||
@ -15,9 +14,7 @@ public class SUDFileTime {
|
||||
* @return
|
||||
*/
|
||||
public static long getSUDFileTime(File file) {
|
||||
|
||||
//System.out.println("Get sud file time: " + file.getName());
|
||||
|
||||
if (file == null || file.exists() == false) {
|
||||
return Long.MIN_VALUE;
|
||||
}
|
||||
@ -48,15 +45,12 @@ public class SUDFileTime {
|
||||
// return Long.MIN_VALUE;
|
||||
// }
|
||||
// long t = sudMap.getFirstChunkTimeMillis();
|
||||
|
||||
long t = SudAudioInputStream.quickFileTime(file);
|
||||
|
||||
t=t/1000; //turn to milliseconds.
|
||||
if (t != 0) {
|
||||
sudTime = t;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// sudAudioInputStream.addSudFileListener((chunkID, sudChunk)->{
|
||||
// ChunkHeader chunkHead = sudChunk.chunkHeader;
|
||||
// if (chunkHead == null || sudTime != Long.MIN_VALUE) {
|
||||
@ -78,15 +72,13 @@ public class SUDFileTime {
|
||||
// sudAudioInputStream.close();
|
||||
// long t2 = System.currentTimeMillis();
|
||||
// System.out.printf("SUD file time %s extracted in %d milliseconds\n", PamCalendar.formatDBDateTime(sudTime), t2-t1);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error getting time from SUD file: " + file + " " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return sudTime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -24,19 +24,19 @@ public class PamguardVersionInfo {
|
||||
* PAMGuard can work with.
|
||||
*/
|
||||
static public final String minJavaVersion = "11.0.0";
|
||||
static public final String maxJavaVersion = "21.99.99";
|
||||
static public final String maxJavaVersion = "19.99.99";
|
||||
|
||||
|
||||
/**
|
||||
* Version number, major version.minorversion.sub-release.
|
||||
* Note: can't go higher than sub-release 'f'
|
||||
*/
|
||||
static public final String version = "2.02.09e";
|
||||
static public final String version = "2.02.09c";
|
||||
|
||||
/**
|
||||
* Release date
|
||||
*/
|
||||
static public final String date = "29 June 2023";
|
||||
static public final String date = "10 November 2023";
|
||||
|
||||
// /**
|
||||
// * Release type - Beta or Core
|
||||
|
@ -89,7 +89,8 @@ public class TxtFileUtils {
|
||||
//5/08/2022 - there was a bug here where there is some sort of invisible character that does not appear on the
|
||||
//print screen - the only way you can tell is the char array is greater than the number of digits - removed all non numeric
|
||||
//characters.
|
||||
String number = new String(recordsOnLine[i].strip().replaceAll("[^\\d.]", ""));
|
||||
// updated again on 15/11/23 to include - signs, or you end up with the abs(of every number!)
|
||||
String number = new String(recordsOnLine[i].strip().replaceAll("[^\\d.-]", ""));
|
||||
dat = Double.valueOf(number);
|
||||
//dat = DecimalFormat.getNumberInstance().parse(new String(recordsOnLine[i].strip().toCharArray())).doubleValue();
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ public class ArraySensorParams implements Serializable, Cloneable, ManagedParame
|
||||
|
||||
public static final long serialVersionUID = 1L;
|
||||
|
||||
public int readIntervalMillis = 1000;
|
||||
public volatile int readIntervalMillis = 1000;
|
||||
|
||||
private ArrayDisplayParameters arrayDisplayParameters;
|
||||
|
||||
|
@ -45,7 +45,8 @@ public class ArraySensorProcess extends PamProcess {
|
||||
while(true) {
|
||||
readData();
|
||||
try {
|
||||
Thread.sleep(analogSensorControl.getAnalogSensorParams().readIntervalMillis);
|
||||
int slptime = analogSensorControl.getAnalogSensorParams().readIntervalMillis;
|
||||
Thread.sleep(slptime);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -139,7 +139,7 @@ public class BrainBoxDevices implements AnalogDeviceType, PamSettings{
|
||||
double sensData = BBED549.hexToEngineering(bbRanges[item], sensInts);
|
||||
double paramValue = calibration.rawToValue(sensData, calibrationData[item]);
|
||||
analogDevicesManager.notifyData(new ItemAllData(item, sensInts, sensData, paramValue));
|
||||
// System.out.printf("Read item %d, chan %d, int %d, real %3.5f, param %3.5f\n", iChan, chan, sensInts, sensData, paramValue);
|
||||
// System.out.printf("Read item %d, chan %d, int %d, real %3.5f, param %3.5f\n", 0, chan, sensInts, sensData, paramValue);
|
||||
sayError(null);
|
||||
return new AnalogSensorData(sensData, paramValue);
|
||||
|
||||
|
@ -221,7 +221,7 @@ public class AnalogDiagnosticsDisplay extends UserDisplayComponentAdapter implem
|
||||
break;
|
||||
case 3:
|
||||
if (lastUpdate[rowIndex] > 0) {
|
||||
return PamCalendar.formatTime(lastUpdate[rowIndex]);
|
||||
return PamCalendar.formatTime(lastUpdate[rowIndex], true);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
|
@ -1041,6 +1041,9 @@ public abstract class SQLLogging {
|
||||
* @return a result set
|
||||
*/
|
||||
protected ResultSet createViewResultSet(PamConnection con, PamViewParameters pamViewParameters) {
|
||||
if (con == null) {
|
||||
return null;
|
||||
}
|
||||
String viewerClause = getViewerLoadClause(con.getSqlTypes(), pamViewParameters);
|
||||
return createViewResultSet(con, viewerClause);
|
||||
}
|
||||
|
@ -36,11 +36,11 @@ The Azigram plugin is version 0.0.1 and has been tested on Pamguard version 2.01
|
||||
|
||||
<p>The sample rate of the Azigram output can be chosen from the Output panel of the settings. The plugin uses frequency domain downsampling in order to acheive the selected sample rate. When selecting the output sample rate, the output FFT length and FFT hop will be altered in order to maintain the same time and frequency resolution as the upstream FFT module.</p>
|
||||
|
||||
<p><img src="AzigramSettings.png" /></p>
|
||||
<p><img src="./images/AzigramSettings.png" /></p>
|
||||
|
||||
<p>The Azigram can be viewed on a Spectrogram Display. The HSV colour model is recommended for viewing Azigrams. This colour model is circular so will better illustrate the circular nature of the angular data (e.g. sounds from 359 degrees will be similar in colour to sounds from 1 degree). The limits of the Amplitude Range on the "Scales" tab of the "Spectrogram Parameters" should be manually set to Min 0 and Max 360. While this tab suggests that the Min and Max are in dB, the Azigram module will treat these values as degrees if an Azigram is being displayed.</p>
|
||||
|
||||
<p><img src="AzigramDisplay.png" /></p>
|
||||
<p><img src="./images/AzigramDisplay.png" /></p>
|
||||
|
||||
<p> </p>
|
||||
|
||||
@ -48,7 +48,7 @@ The Azigram plugin is version 0.0.1 and has been tested on Pamguard version 2.01
|
||||
|
||||
<p>The screenshot below shows the DIFAR Azigram Module displaying the Azigram output (top graph) and regular spectrogram ouput (middle panel) of a synthetic test signal. The test signal is a simulated DIFAR source with 8 short FM downsweeps arriving from 0-315 degrees in 45 degree increments. The bottom panel shows the PAMGuard Data Model.</p>
|
||||
|
||||
<p><img src="AzigramExample.png" /></p>
|
||||
<p><img src="./images/AzigramExample.png" /></p>
|
||||
|
||||
<p> </p>
|
||||
|
||||
|
@ -32,6 +32,7 @@ import java.io.IOException;
|
||||
import java.util.EnumMap;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
|
||||
import PamUtils.PamCalendar;
|
||||
|
||||
@ -126,31 +127,34 @@ public class RoccaClassifyThis {
|
||||
/** the field in the RoccaContourStats object which contains all the stats measures */
|
||||
private EnumMap<RoccaContourStats.ParamIndx, Double> contourStats;
|
||||
|
||||
private String dirIn;
|
||||
|
||||
/** the input filename */
|
||||
private String csvIn;
|
||||
|
||||
/** the input file */
|
||||
private File statsFileIn;
|
||||
|
||||
/** the output filename */
|
||||
private String csvOut;
|
||||
|
||||
/** the output file */
|
||||
private File statsFileOut;
|
||||
|
||||
/** Constructor */
|
||||
/**
|
||||
* Constructor used when allowing user to select training dataset
|
||||
* */
|
||||
public RoccaClassifyThis(RoccaProcess roccaProcess) {
|
||||
|
||||
// initialize the BufferedReader
|
||||
BufferedReader inputFile = null;
|
||||
|
||||
File statsFileIn = getTheFile();
|
||||
if (statsFileIn!=null) {
|
||||
runTheClassifier(statsFileIn, roccaProcess);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor when we pass in the training dataset
|
||||
*/
|
||||
public RoccaClassifyThis() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ask the user to select the file containing the testing dataset
|
||||
*
|
||||
* @return File the csv file containing the testing dataset
|
||||
*/
|
||||
public File getTheFile() {
|
||||
// set the directory
|
||||
// this.dirIn = new String("C:\\Users\\Mike\\Documents\\Work\\Java\\EclipseWorkspace\\testing\\RoccaClassifyThis_testing");
|
||||
// this.dirIn = new String("C:\\Users\\Mike\\Documents\\Work\\Tom\\Atlantic Classifier\\manual 2-stage data");
|
||||
// this.dirIn = new String("C:\\Users\\Mike\\Documents\\Work\\Tom\\Hawaii dataset problems");
|
||||
this.dirIn = new String("C:\\Users\\SCANS\\Documents\\Work\\Biowaves\\ONR classifier");
|
||||
// this.dirIn = new String("C:\\Users\\SCANS\\Documents\\Work\\Biowaves\\ONR classifier");
|
||||
|
||||
// Define the input and output filenames
|
||||
// Hard-coded for now. To Do: query the user for the filename
|
||||
@ -158,35 +162,54 @@ public class RoccaClassifyThis {
|
||||
// this.csvIn = new String("Manual_5sp_April 9 2013.csv");
|
||||
// this.csvIn = new String("CombinedContourStats-fixed.csv");
|
||||
// this.csvOut = new String("RoccaContourStatsReclassified.csv");
|
||||
this.csvIn = new String("Atl_TestDFNoTrain_Call_W_160831.csv");
|
||||
statsFileIn = new File(dirIn, csvIn);
|
||||
this.csvOut = new String("Atl_TestDFNoTrain_Call_W_160829-classified.csv");
|
||||
statsFileOut = new File(dirIn, csvOut);
|
||||
// this.csvIn = new String("Atl_TestDFNoTrain_Call_W_160831.csv");
|
||||
// statsFileIn = new File(dirIn, csvIn);
|
||||
// this.csvOut = new String("Atl_TestDFNoTrain_Call_W_160829-classified.csv");
|
||||
// statsFileOut = new File(dirIn, csvOut);
|
||||
|
||||
// let the user select the arff file
|
||||
JFileChooser fileChooser = new JFileChooser();
|
||||
fileChooser.setDialogTitle("Select spreadsheet to recalculate...");
|
||||
fileChooser.setFileHidingEnabled(true);
|
||||
fileChooser.setApproveButtonText("Select");
|
||||
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
FileNameExtensionFilter restrict = new FileNameExtensionFilter("Only .csv files", "csv");
|
||||
fileChooser.addChoosableFileFilter(restrict);
|
||||
|
||||
int state = fileChooser.showOpenDialog(null);
|
||||
File statsFileIn = null;
|
||||
if (state == JFileChooser.APPROVE_OPTION) {
|
||||
|
||||
// load the file
|
||||
statsFileIn = fileChooser.getSelectedFile();
|
||||
return statsFileIn;
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run the classifier
|
||||
* @param statsFileIn the File containing the testing dataset
|
||||
* @param roccaProcess the RoccaProcess instance
|
||||
*/
|
||||
public void runTheClassifier(File statsFileIn, RoccaProcess roccaProcess) {
|
||||
|
||||
// JFileChooser fileChooser = new JFileChooser();
|
||||
// fileChooser.setDialogTitle("Select spreadsheet to recalculate...");
|
||||
// fileChooser.setFileHidingEnabled(true);
|
||||
// fileChooser.setApproveButtonText("Select");
|
||||
// fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
//
|
||||
// int state = fileChooser.showOpenDialog(this.dirIn);
|
||||
// if (state == JFileChooser.APPROVE_OPTION) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int index = statsFileIn.getAbsolutePath().lastIndexOf(".");
|
||||
String csvOut = statsFileIn.getAbsolutePath().substring(0,index) + "-classified.csv";
|
||||
File statsFileOut = new File(csvOut);
|
||||
|
||||
|
||||
// load the classifier
|
||||
System.out.println("Loading classifier...");
|
||||
roccaProcess.setClassifierLoaded
|
||||
(roccaProcess.roccaClassifier.setUpClassifier());
|
||||
|
||||
// initialize the BufferedReader
|
||||
BufferedReader inputFile = null;
|
||||
|
||||
// open the input file
|
||||
try {
|
||||
System.out.println("Opening input file "+statsFileIn);
|
||||
@ -263,12 +286,45 @@ public class RoccaClassifyThis {
|
||||
contourStats.put(RoccaContourStats.ParamIndx.FREQPOSSLOPEMEAN, Double.parseDouble(dataArray[34]));
|
||||
contourStats.put(RoccaContourStats.ParamIndx.FREQNEGSLOPEMEAN, Double.parseDouble(dataArray[35]));
|
||||
contourStats.put(RoccaContourStats.ParamIndx.FREQSLOPERATIO, Double.parseDouble(dataArray[36]));
|
||||
contourStats.put(RoccaContourStats.ParamIndx.FREQBEGSWEEP, Double.parseDouble(dataArray[37]));
|
||||
//contourStats.put(RoccaContourStats.ParamIndx.FREQBEGUP, Double.parseDouble(dataArray[38]));
|
||||
//contourStats.put(RoccaContourStats.ParamIndx.FREQBEGDWN, Double.parseDouble(dataArray[39]));
|
||||
contourStats.put(RoccaContourStats.ParamIndx.FREQENDSWEEP, Double.parseDouble(dataArray[40]));
|
||||
//contourStats.put(RoccaContourStats.ParamIndx.FREQENDUP, Double.parseDouble(dataArray[41]));
|
||||
//contourStats.put(RoccaContourStats.ParamIndx.FREQENDDWN, Double.parseDouble(dataArray[42]));
|
||||
|
||||
// Note that we have to modify the FREQBEGSWEEP value. Weka is trained with the FREQBEGSWEEP param
|
||||
// as -1=down, 0=flat and 1=up, and that would be how the test data comes through as well. HOWEVER,
|
||||
// Weka assumes that for nominal parameters, the value is the index location (0,1 or 2) and NOT the actual trained
|
||||
// value (-1,0 or 1). So if the whistle has a down sweep, Weka needs the FREQBEGSWEEP value to be 0 indicating the
|
||||
// first location in the array (which was 'down'). If it was up, the value would need to be 2 indicating the third
|
||||
// location in the array (which was 'up').
|
||||
// Ideally we would map the values in the test data to the positions in the training array, but as a quick and
|
||||
// dirty hack we'll simply add 1 to the value since the difference between the nominal values (-1,0,1) and the
|
||||
/// index positions (0,1,2) is an offset of 1
|
||||
// Note also that we don't have to do the same thing for FREQBEGUP and FREQBEGDWN since, by coincidence, the training
|
||||
// values of 0 and 1 happen to match the index locations of 0 and 1
|
||||
//contourStats.put(RoccaContourStats.ParamIndx.FREQBEGSWEEP, Double.parseDouble(dataArray[37]));
|
||||
double tempVal = Double.parseDouble(dataArray[37]);
|
||||
tempVal++;
|
||||
contourStats.put(RoccaContourStats.ParamIndx.FREQBEGSWEEP, tempVal);
|
||||
contourStats.put(RoccaContourStats.ParamIndx.FREQBEGUP, Double.parseDouble(dataArray[38]));
|
||||
contourStats.put(RoccaContourStats.ParamIndx.FREQBEGDWN, Double.parseDouble(dataArray[39]));
|
||||
|
||||
// Note that we have to modify the FREQENDSWEEP value. Weka is trained with the FREQENDSWEEP param
|
||||
// as -1=down, 0=flat and 1=up, and that would be how the test data comes through as well. HOWEVER,
|
||||
// Weka assumes that for nominal parameters, the value is the index location (0,1 or 2) and NOT the actual trained
|
||||
// value (-1,0 or 1). So if the whistle has a down sweep, Weka needs the FREQENDSWEEP value to be 0 indicating the
|
||||
// first location in the array (which was 'down'). If it was up, the value would need to be 2 indicating the third
|
||||
// location in the array (which was 'up').
|
||||
// Ideally we would map the values in the test data to the positions in the training array, but as a quick and
|
||||
// dirty hack we'll simply add 1 to the value since the difference between the nominal values (-1,0,1) and the
|
||||
/// index positions (0,1,2) is an offset of 1
|
||||
// Note also that we don't have to do the same thing for FREQENDUP and FREQENDDWN since, by coincidence, the training
|
||||
// values of 0 and 1 happen to match the index locations of 0 and 1
|
||||
//contourStats.put(RoccaContourStats.ParamIndx.FREQENDSWEEP, Double.parseDouble(dataArray[40]));
|
||||
tempVal = Double.parseDouble(dataArray[40]);
|
||||
tempVal++;
|
||||
contourStats.put(RoccaContourStats.ParamIndx.FREQENDSWEEP, tempVal);
|
||||
contourStats.put(RoccaContourStats.ParamIndx.FREQENDUP, Double.parseDouble(dataArray[41]));
|
||||
contourStats.put(RoccaContourStats.ParamIndx.FREQENDDWN, Double.parseDouble(dataArray[42]));
|
||||
// end of hack
|
||||
|
||||
|
||||
contourStats.put(RoccaContourStats.ParamIndx.NUMSWEEPSUPDWN, Double.parseDouble(dataArray[43]));
|
||||
contourStats.put(RoccaContourStats.ParamIndx.NUMSWEEPSDWNUP, Double.parseDouble(dataArray[44]));
|
||||
contourStats.put(RoccaContourStats.ParamIndx.NUMSWEEPSUPFLAT, Double.parseDouble(dataArray[45]));
|
||||
@ -285,8 +341,8 @@ public class RoccaClassifyThis {
|
||||
contourStats.put(RoccaContourStats.ParamIndx.INFLMEANDELTA, Double.parseDouble(dataArray[56]));
|
||||
contourStats.put(RoccaContourStats.ParamIndx.INFLSTDDEVDELTA, Double.parseDouble(dataArray[57]));
|
||||
contourStats.put(RoccaContourStats.ParamIndx.INFLMEDIANDELTA, Double.parseDouble(dataArray[58]));
|
||||
contourStats.put(RoccaContourStats.ParamIndx.INFLDUR, Double.parseDouble(dataArray[59]));
|
||||
contourStats.put(RoccaContourStats.ParamIndx.STEPDUR, Double.parseDouble(dataArray[60]));
|
||||
//contourStats.put(RoccaContourStats.ParamIndx.INFLDUR, Double.parseDouble(dataArray[59]));
|
||||
//contourStats.put(RoccaContourStats.ParamIndx.STEPDUR, Double.parseDouble(dataArray[60]));
|
||||
|
||||
// Run the classifier
|
||||
roccaProcess.roccaClassifier.classifyContour2(rcdb);
|
||||
|
@ -169,6 +169,7 @@ public class RoccaParametersDialog extends PamDialog implements ActionListener,
|
||||
JButton classifier2Button;
|
||||
JButton recalcButton;
|
||||
JButton reclassifyButton;
|
||||
JButton trainThenTestButton;
|
||||
JButton clearClassifier;
|
||||
JComboBox<DefaultComboBoxModel<Vector<String>>> stage1Classes;
|
||||
DefaultComboBoxModel<Vector<String>> stage1ClassModel;
|
||||
@ -513,6 +514,10 @@ public class RoccaParametersDialog extends PamDialog implements ActionListener,
|
||||
reclassifyButton.addActionListener(this);
|
||||
reclassifyButton.setToolTipText("Load the whistle data from the contour stats output file, and run it through the current Classifier");
|
||||
reclassifyButton.setVisible(true);
|
||||
trainThenTestButton = new JButton("Train then Test");
|
||||
trainThenTestButton.addActionListener(this);
|
||||
trainThenTestButton.setToolTipText("Train a classifier on a set of training data, then test it with a set of testing data");
|
||||
trainThenTestButton.setVisible(true);
|
||||
|
||||
// ******** THIS LINES CONTROLS THE VISIBILITY ********
|
||||
if (RoccaDev.isEnabled()) {
|
||||
@ -528,13 +533,15 @@ public class RoccaParametersDialog extends PamDialog implements ActionListener,
|
||||
extraPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
|
||||
.addGroup(extraPanelLayout.createSequentialGroup()
|
||||
.addComponent(recalcButton)
|
||||
.addComponent(reclassifyButton))
|
||||
.addComponent(reclassifyButton)
|
||||
.addComponent(trainThenTestButton))
|
||||
);
|
||||
extraPanelLayout.setVerticalGroup(
|
||||
extraPanelLayout.createSequentialGroup()
|
||||
.addGroup(extraPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(recalcButton)
|
||||
.addComponent(reclassifyButton))
|
||||
.addComponent(reclassifyButton)
|
||||
.addComponent(trainThenTestButton))
|
||||
);
|
||||
classifierPanel.add(extraButtonsSubPanel);
|
||||
|
||||
@ -892,7 +899,9 @@ public class RoccaParametersDialog extends PamDialog implements ActionListener,
|
||||
} else if (e.getSource() == recalcButton) {
|
||||
RoccaFixParams recalc = new RoccaFixParams(roccaControl.roccaProcess);
|
||||
} else if (e.getSource() == reclassifyButton) {
|
||||
RoccaClassifyThisEvent reclassify = new RoccaClassifyThisEvent(roccaControl.roccaProcess);
|
||||
RoccaClassifyThis reclassify = new RoccaClassifyThis(roccaControl.roccaProcess);
|
||||
} else if (e.getSource() == trainThenTestButton) {
|
||||
RoccaTrainThenTest trainThenTest = new RoccaTrainThenTest(roccaControl.roccaProcess);
|
||||
} else if (e.getSource() == fftButton) {
|
||||
roccaParameters.setUseFFT(true);
|
||||
this.enableTheCorrectSource();
|
||||
|
@ -145,6 +145,7 @@ public class RoccaRFModel implements java.io.Serializable {
|
||||
|
||||
} catch (Exception ex) {
|
||||
System.err.println("1st Classification failed: " + ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
rcdb.setClassifiedAs("Err");
|
||||
}
|
||||
}
|
||||
|
@ -24,10 +24,14 @@
|
||||
package rocca;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
|
||||
import weka.classifiers.trees.RandomForest;
|
||||
import weka.core.Instances;
|
||||
import weka.core.SerializationHelper;
|
||||
@ -42,13 +46,64 @@ import weka.core.SerializationHelper;
|
||||
*/
|
||||
public class RoccaTrainClassifier {
|
||||
|
||||
|
||||
/**
|
||||
* Standalone implementation
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
|
||||
RoccaTrainClassifier rtc = new RoccaTrainClassifier();
|
||||
File arffFile = rtc.getArff();
|
||||
if (arffFile!=null) {
|
||||
String modelName = rtc.trainClassifier(arffFile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Let user choose arff file training dataset
|
||||
*
|
||||
* @return File the arff file containing the training dataset
|
||||
*/
|
||||
public File getArff() {
|
||||
// String arffFile = "C:\\Users\\SCANS\\Documents\\Work\\Biowaves\\ONR classifier\\TP_TrainEvtDF_170408";
|
||||
|
||||
// let the user select the arff file
|
||||
JFileChooser fileChooser = new JFileChooser();
|
||||
fileChooser.setDialogTitle("Select arff file containing training data");
|
||||
fileChooser.setFileHidingEnabled(true);
|
||||
fileChooser.setApproveButtonText("Select");
|
||||
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
FileNameExtensionFilter restrict = new FileNameExtensionFilter("Only .arff files", "arff");
|
||||
fileChooser.addChoosableFileFilter(restrict);
|
||||
File arffFile;
|
||||
|
||||
int state = fileChooser.showOpenDialog(null);
|
||||
if (state == JFileChooser.APPROVE_OPTION) {
|
||||
|
||||
// load the file
|
||||
arffFile = fileChooser.getSelectedFile();
|
||||
return arffFile;
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Actual code to train the classifier
|
||||
*
|
||||
*/
|
||||
public String trainClassifier(File arffFile) {
|
||||
|
||||
RandomForest model = new RandomForest ();
|
||||
Instances trainData = null;
|
||||
String arffFile = "C:\\Users\\SCANS\\Documents\\Work\\Biowaves\\ONR classifier\\TP_TrainEvtDF_170408";
|
||||
|
||||
// load the ARFF file containing the training set
|
||||
System.out.println("Loading data...");
|
||||
System.out.println("Loading data..." + arffFile.getAbsolutePath());
|
||||
try {
|
||||
trainData = new Instances
|
||||
(new BufferedReader
|
||||
@ -56,10 +111,13 @@ public class RoccaTrainClassifier {
|
||||
// ("C:\\Users\\Mike\\Documents\\Work\\Java\\WEKA\\allwhists 12 vars 8sp update 1-28-10.arff")));
|
||||
// ("C:\\Users\\Mike\\Documents\\Work\\Java\\WEKA\\weka vs R\\ETP_orcawale_whists2 modified-subset110perspecies-no_harm_ratios.arff")));
|
||||
// ("C:\\Users\\SCANS\\Documents\\Work\\Biowaves\\ONR classifier\\Atl_TrainDF_Event_160829.arff")));
|
||||
(arffFile + ".arff")));
|
||||
// (arffFile + ".arff")));
|
||||
(arffFile)));
|
||||
trainData.setClassIndex(trainData.numAttributes()-1);
|
||||
} catch (Exception ex) {
|
||||
System.out.println("Error Loading...");
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
// set the classifier parameters
|
||||
@ -78,6 +136,8 @@ public class RoccaTrainClassifier {
|
||||
model.setOptions(options);
|
||||
} catch (Exception ex) {
|
||||
System.out.println("Error setting options...");
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
// train the classifier
|
||||
@ -90,23 +150,29 @@ public class RoccaTrainClassifier {
|
||||
new Date());
|
||||
} catch (Exception ex) {
|
||||
System.out.println("Error training classifier...");
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
// save the classifier
|
||||
String[] curOptions = model.getOptions();
|
||||
Enumeration test = model.listOptions();
|
||||
System.out.println("Saving Classifier...");
|
||||
// String[] curOptions = model.getOptions();
|
||||
// Enumeration test = model.listOptions();
|
||||
Instances header = new Instances(trainData,0);
|
||||
int index = arffFile.getAbsolutePath().lastIndexOf(".");
|
||||
String modelName = arffFile.getAbsolutePath().substring(0,index) + ".model";
|
||||
System.out.println("Saving Classifier..." + modelName);
|
||||
try {
|
||||
SerializationHelper.writeAll
|
||||
// ("C:\\Users\\Mike\\Documents\\Work\\Java\\WEKA\\weka vs R\\RF_8sp_54att_110whistle-subset.model",
|
||||
(arffFile + ".model",
|
||||
// (arffFile + ".model",
|
||||
(modelName,
|
||||
new Object[]{model,header});
|
||||
System.out.println("Finished!");
|
||||
return modelName;
|
||||
} catch (Exception ex) {
|
||||
System.out.println("Error saving classifier...");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
System.out.println("Finished!");
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
109
src/rocca/RoccaTrainThenTest.java
Normal file
109
src/rocca/RoccaTrainThenTest.java
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* PAMGUARD - Passive Acoustic Monitoring GUARDianship.
|
||||
* To assist in the Detection Classification and Localisation
|
||||
* of marine mammals (cetaceans).
|
||||
*
|
||||
* Copyright (C) 2006
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
package rocca;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
|
||||
public class RoccaTrainThenTest {
|
||||
|
||||
RoccaTrainClassifier roccaTrainClassifier;
|
||||
|
||||
RoccaClassifyThis roccaClassifyThis;
|
||||
|
||||
|
||||
/**
|
||||
* Main Constructor
|
||||
* @param roccaProcess
|
||||
*/
|
||||
public RoccaTrainThenTest(RoccaProcess roccaProcess) {
|
||||
|
||||
|
||||
// let the user select the csv file containing the training and testing dataset(s)
|
||||
JFileChooser fileChooser = new JFileChooser();
|
||||
fileChooser.setDialogTitle("Select csv file with the training/testing pairs");
|
||||
fileChooser.setFileHidingEnabled(true);
|
||||
fileChooser.setApproveButtonText("Select");
|
||||
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
FileNameExtensionFilter restrict = new FileNameExtensionFilter("Only .csv files", "csv");
|
||||
fileChooser.addChoosableFileFilter(restrict);
|
||||
|
||||
int state = fileChooser.showOpenDialog(null);
|
||||
if (state == JFileChooser.APPROVE_OPTION) {
|
||||
|
||||
// load the file
|
||||
try {
|
||||
File csvDataPairs = fileChooser.getSelectedFile();
|
||||
BufferedReader br = new BufferedReader(new FileReader(csvDataPairs));
|
||||
String curPath = csvDataPairs.getParent();
|
||||
|
||||
// main loop
|
||||
// read through the csv file one line at a time. The first column should contain the training dataset filename,
|
||||
// and the second column the testing dataset filename. Paths should be relative to the path containing
|
||||
// the csv file
|
||||
String line = "";
|
||||
String splitBy = ",";
|
||||
while ((line=br.readLine())!=null) {
|
||||
|
||||
String[] filenames = line.split(splitBy);
|
||||
|
||||
// train the classifier
|
||||
File arffFile = new File(curPath + File.separator + filenames[0]);
|
||||
roccaTrainClassifier = new RoccaTrainClassifier();
|
||||
String modelName = roccaTrainClassifier.trainClassifier(arffFile);
|
||||
if (modelName == null) {
|
||||
System.out.println("ERROR: could not create classifier model from "+arffFile);
|
||||
continue;
|
||||
}
|
||||
|
||||
// set the classifier as the current one in RoccaParameters
|
||||
roccaProcess.roccaControl.roccaParameters.setRoccaClassifierModelFilename(new File(modelName));
|
||||
|
||||
|
||||
// test the classifier with the testing dataset
|
||||
File testFile = new File(curPath + File.separator + filenames[1]);
|
||||
roccaClassifyThis = new RoccaClassifyThis();
|
||||
roccaClassifyThis.runTheClassifier(testFile, roccaProcess);
|
||||
|
||||
}
|
||||
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user