Squashed commit of the following:

commit f2860d8154
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Fri Jun 3 08:48:16 2022 +0100

    Small changes to support Genesis work

commit 91a8e5fec0
Author: Jamie Mac <macster110@gmail.com>
Date:   Fri May 27 06:39:20 2022 -0600

    Added data selectors to Click Train Detector (#34)

    * Updates to click train detector

    New GUI for click train classification - more intuitive and allows users to build more powerful classifiers.
    CPOD data can now build average waveforms.
    CPOD click trains can be viewed in TDisplayFX pop up menu displays
    Fixed Peak Frequency symbol chooser so it saves the colour box settings

    * Create click_train_help.md

    * Update click_train_help.md

    * Screenshots

    * Update click_train_help.md

    * Update click_train_help.md

    * Update click_train_help.md

    * More screenshots

    * Add screenshots

    * Update click_train_help.md

    * Add classifier screenshot

    * Update click_train_help.md

    * Update click_train_help.md

    * Update click_train_help.md

    * Updates and bug fixes to click train detector and CPOD importer

    * Update click_train_help.md

    * Update POM with latest jdl4pam

    * Add screenshots for click train detector help

    * Screenshots

    * Update click_train_help.md

    * Defult option for CPOD and porpoise to click train detector.

    Also a minor

    * Update pom.xml

    * Bug fix for raw spectrogram in TDDisplayFX

    * Update KetosClassifier.java

    * Updates to click train detector

    New GUI for click train classification - more intuitive and allows users to build more powerful classifiers.
    CPOD data can now build average waveforms.
    CPOD click trains can be viewed in TDisplayFX pop up menu displays
    Fixed Peak Frequency symbol chooser so it saves the colour box settings

    * Create click_train_help.md

    * Update click_train_help.md

    * Screenshots

    * Update click_train_help.md

    * More screenshots

    * Update click_train_help.md

    * Update click_train_help.md

    * Add screenshots

    * Add classifier screenshot

    * Update click_train_help.md

    * Updates and bug fixes to click train detector and CPOD importer

    * Update click_train_help.md

    * Update click_train_help.md

    * Update click_train_help.md

    * Update click_train_help.md

    * Add screenshots for click train detector help

    * Screenshots

    * Update click_train_help.md

    * Defult option for CPOD and porpoise to click train detector.

    Also a minor

    * Bug fix for raw spectrogram in TDDisplayFX

    * Update KetosClassifier.java

    * Fix standard classifier JSON logging

    * Update click_train_help.md

    * Fixed bug in sweep classifier when using SoundTrap click detections

    * Added some colour averaging in the TFDisplayFX spectrgoram

    * Bug fix for rainbow click bearings

    Bug fix when rainbow clicks are imported mean bearings cannot be calculated - was an array size issue in DelayGroup

    * Google humpback whale deep learning classifier

    Google's humpback whale deep learning classifier can now be imported.
    Updated TDisplayFX to make the data selection panes cleaner and clearer.
    Updated the TDisplayFX so that predicitons from deep learning models now have some display options e.g. changing colour.

    * Updated the prediction plots on time display

    Deep learning prediciton plots on the time display have now been updated to have some colour options and also act as a legend.

    * Updates to TDisplayFX

    yFIshmael now owrks with TDisplayFX
    TDisplayFX UI changes to make simpler.
    Some abstraction for drawing lines on TDisplayFX

    * Updates to click train detector

    New GUI for click train classification - more intuitive and allows users to build more powerful classifiers.
    CPOD data can now build average waveforms.
    CPOD click trains can be viewed in TDisplayFX pop up menu displays
    Fixed Peak Frequency symbol chooser so it saves the colour box settings

    * Create click_train_help.md

    * Update click_train_help.md

    * Screenshots

    * Update click_train_help.md

    * More screenshots

    * Update click_train_help.md

    * Update click_train_help.md

    * Add screenshots

    * Add classifier screenshot

    * Update click_train_help.md

    * Updates and bug fixes to click train detector and CPOD importer

    * Update click_train_help.md

    * Update click_train_help.md

    * Update click_train_help.md

    * Update click_train_help.md

    * Add screenshots for click train detector help

    * Screenshots

    * Update click_train_help.md

    * Defult option for CPOD and porpoise to click train detector.

    Also a minor

    * Updates to click train detector

    New GUI for click train classification - more intuitive and allows users to build more powerful classifiers.
    CPOD data can now build average waveforms.
    CPOD click trains can be viewed in TDisplayFX pop up menu displays
    Fixed Peak Frequency symbol chooser so it saves the colour box settings

    * Create click_train_help.md

    * Update click_train_help.md

    * Update click_train_help.md

    * Updates and bug fixes to click train detector and CPOD importer

    * Bug fix for raw spectrogram in TDDisplayFX

    * Update KetosClassifier.java

    * Fix standard classifier JSON logging

    * Fixed bug in sweep classifier when using SoundTrap click detections

    * Added some colour averaging in the TFDisplayFX spectrgoram

    * Bug fix for rainbow click bearings

    Bug fix when rainbow clicks are imported mean bearings cannot be calculated - was an array size issue in DelayGroup

    * Google humpback whale deep learning classifier

    Google's humpback whale deep learning classifier can now be imported.
    Updated TDisplayFX to make the data selection panes cleaner and clearer.
    Updated the TDisplayFX so that predicitons from deep learning models now have some display options e.g. changing colour.

    * Updated the prediction plots on time display

    Deep learning prediciton plots on the time display have now been updated to have some colour options and also act as a legend.

    * Updates to TDisplayFX

    yFIshmael now owrks with TDisplayFX
    TDisplayFX UI changes to make simpler.
    Some abstraction for drawing lines on TDisplayFX

    * Merge fixes to click train detector

    * Bug fix to UI

    * Updates to FX GUI

    * Updates to click train detector

    New GUI for click train classification - more intuitive and allows users to build more powerful classifiers.
    CPOD data can now build average waveforms.
    CPOD click trains can be viewed in TDisplayFX pop up menu displays
    Fixed Peak Frequency symbol chooser so it saves the colour box settings

    * Screenshots

    * Updates and bug fixes to click train detector and CPOD importer

    * Updates to click train detector

    New GUI for click train classification - more intuitive and allows users to build more powerful classifiers.
    CPOD data can now build average waveforms.
    CPOD click trains can be viewed in TDisplayFX pop up menu displays
    Fixed Peak Frequency symbol chooser so it saves the colour box settings

    * Updates and bug fixes to click train detector and CPOD importer

    * Fix standard classifier JSON logging

    * Merge fixes to click train detector

    * Updates to click train detector

    New GUI for click train classification - more intuitive and allows users to build more powerful classifiers.
    CPOD data can now build average waveforms.
    CPOD click trains can be viewed in TDisplayFX pop up menu displays
    Fixed Peak Frequency symbol chooser so it saves the colour box settings

    * Screenshots

    * Updates and bug fixes to click train detector and CPOD importer

    * Updates to click train detector

    New GUI for click train classification - more intuitive and allows users to build more powerful classifiers.
    CPOD data can now build average waveforms.
    CPOD click trains can be viewed in TDisplayFX pop up menu displays
    Fixed Peak Frequency symbol chooser so it saves the colour box settings

    * Screenshots

    * Updates and bug fixes to click train detector and CPOD importer

    * Fix standard classifier JSON logging

    * Google humpback whale deep learning classifier

    Google's humpback whale deep learning classifier can now be imported.
    Updated TDisplayFX to make the data selection panes cleaner and clearer.
    Updated the TDisplayFX so that predicitons from deep learning models now have some display options e.g. changing colour.

    * Bug fix to UI

    * Bug fixes to FX GUI

    * Updates to click train detector

    * Squashed commit of the following:

    commit 9f998165ee
    Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
    Date:   Mon May 2 19:40:24 2022 +0100

        Updates to support ContactCollator plugin (#33)

        * Change synchronization on RawDataTransforms soit uses the owner data
        holder, not itself for synchronization. Otherwise you get thread locks.

        * fix problem in SummaryComand

        * Update command line options

        * Change synchronization on RawDataTransforms soit uses the owner data
        holder, not itself for synchronization. Otherwise you get thread locks.

        * Update command line options

        * Update DecimatorParams.java

        * couple of updates to support new contact collator plugin

        * Sorting out sample rate info in clip display to support Contact Collator
        plugin

        * FLAC Speed

        Improve flac speed

        * Update .gitignore

        * Update .gitignore

        * Updates to support new features in Contact Collator

        * Small update to RawDatautils to handle null data

    * Updates to click train detector

    * Squashed commit of the following:

    commit 62b020b320
    Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
    Date:   Sat May 14 06:52:20 2022 +0100

        Add a new offlinefileslist function

    commit 3a9a5311aa
    Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
    Date:   Wed Apr 27 09:43:31 2022 +0100

        Update .gitignore

    commit 9f998165ee
    Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
    Date:   Mon May 2 19:40:24 2022 +0100

        Updates to support ContactCollator plugin (#33)

        * Change synchronization on RawDataTransforms soit uses the owner data
        holder, not itself for synchronization. Otherwise you get thread locks.

        * fix problem in SummaryComand

        * Update command line options

        * Change synchronization on RawDataTransforms soit uses the owner data
        holder, not itself for synchronization. Otherwise you get thread locks.

        * Update command line options

        * Update DecimatorParams.java

        * couple of updates to support new contact collator plugin

        * Sorting out sample rate info in clip display to support Contact Collator
        plugin

        * FLAC Speed

        Improve flac speed

        * Update .gitignore

        * Update .gitignore

        * Updates to support new features in Contact Collator

        * Small update to RawDatautils to handle null data

    * Updated data selector for click train detector

    * Click train detector updates and bug fixes

    Fixed very annoying bug which meant templates did not show properly when the dialog was first opened in swing.

    Added feature to simple classifier were % of clicks of one click classification (or other data selector paramter) can be used to classify.

    Co-authored-by: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>

commit 7a08005ba8
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Fri May 27 13:18:02 2022 +0100

    Sort out a couple of issues with scroll play mode timing

commit e2b48c8e07
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Tue May 17 21:06:48 2022 +0100

    Changes to corner layout

commit 62b020b320
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Sat May 14 06:52:20 2022 +0100

    Add a new offlinefileslist function

commit 3a9a5311aa
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Wed Apr 27 09:43:31 2022 +0100

    Update .gitignore

commit 9f998165ee
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Mon May 2 19:40:24 2022 +0100

    Updates to support ContactCollator plugin (#33)

    * Change synchronization on RawDataTransforms soit uses the owner data
    holder, not itself for synchronization. Otherwise you get thread locks.

    * fix problem in SummaryComand

    * Update command line options

    * Change synchronization on RawDataTransforms soit uses the owner data
    holder, not itself for synchronization. Otherwise you get thread locks.

    * Update command line options

    * Update DecimatorParams.java

    * couple of updates to support new contact collator plugin

    * Sorting out sample rate info in clip display to support Contact Collator
    plugin

    * FLAC Speed

    Improve flac speed

    * Update .gitignore

    * Update .gitignore

    * Updates to support new features in Contact Collator

    * Small update to RawDatautils to handle null data
This commit is contained in:
Douglas Gillespie 2022-06-04 11:00:30 +01:00
parent a0900a667e
commit 8a34362261
48 changed files with 826 additions and 294 deletions

View File

@ -6,8 +6,10 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk-16.0.2">
<attributes>
<attribute name="module" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>

1
.gitignore vendored
View File

@ -21,6 +21,7 @@
*.zip
*.tar.gz
*.rar
*.dll
# eclipse project file
.project

View File

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.m2e.Maven2LaunchConfigurationType">
<booleanAttribute key="M2_DEBUG_OUTPUT" value="false"/>
<stringAttribute key="M2_GOALS" value="package shade:shade"/>
<booleanAttribute key="M2_NON_RECURSIVE" value="false"/>
<booleanAttribute key="M2_OFFLINE" value="false"/>
<stringAttribute key="M2_PROFILES" value=""/>
<listAttribute key="M2_PROPERTIES"/>
<stringAttribute key="M2_RUNTIME" value="EMBEDDED"/>
<booleanAttribute key="M2_SKIP_TESTS" value="true"/>
<intAttribute key="M2_THREADS" value="1"/>
<booleanAttribute key="M2_UPDATE_SNAPSHOTS" value="false"/>
<stringAttribute key="M2_USER_SETTINGS" value=""/>
<booleanAttribute key="M2_WORKSPACE_RESOLUTION" value="false"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_ATTR_USE_ARGFILE" value="false"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_SHOW_CODEDETAILS_IN_EXCEPTION_MESSAGES" value="true"/>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_CLASSPATH_ONLY_JAR" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-13/"/>
<stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-mx6000m&#13;&#10;-Djava.library.path=lib64"/>
<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${workspace_loc:/PamGuard Main}"/>
</launchConfiguration>

View File

@ -7,6 +7,7 @@ import Acquisition.FolderInputSystem;
import Acquisition.WavFileFuncs;
import PamUtils.PamAudioFileFilter;
import javafx.geometry.Insets;
import javafx.application.Platform;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.concurrent.Task;
import javafx.geometry.Pos;
@ -89,6 +90,8 @@ public class CheckWavHeadersPane extends PamBorderPane {
*/
private SimpleDoubleProperty progressProperty = new SimpleDoubleProperty(0);
private PamButton runButton;
/**
* Constructor for the CheckWavHeadersPane
* @param folderInputSystem - the folder input system.
@ -102,20 +105,19 @@ public class CheckWavHeadersPane extends PamBorderPane {
this.folderInputSystem=folderInputSystem;
folderName = new Label(" ");
PamGuiManagerFX.titleFont2style(folderName);
//PamGuiManagerFX.titleFont2style(folderName);
textArea = new TextArea();
textArea.setEditable(false);
ScrollPane scrollPane = new ScrollPane(textArea);
scrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
//scrollPane.setPrefSize(322, 300);
this.setCenter(scrollPane);
PamHBox pamHBox = new PamHBox();
pamHBox.setAlignment(Pos.CENTER_LEFT);
pamHBox.setSpacing(5);
PamButton runButton = new PamButton();
runButton = new PamButton();
runButton.setGraphic(PamGlyphDude.createPamIcon("mdi2p-play"));
runButton.setOnAction((action)->{
checkFiles();
@ -128,15 +130,15 @@ public class CheckWavHeadersPane extends PamBorderPane {
pamHBox.getChildren().addAll(runButton, progressBar);
progressBar.setMaxWidth(Double.MAX_VALUE);
mainPane.getChildren().addAll(folderName, textArea, pamHBox);
this.setPadding(new Insets(5,0,5,15));
this.setCenter(mainPane);
this.setPadding(new Insets(5,0,5,15));
}
private void setParams() {
void setParams() {
running = ran = false;
subFolders = folderInputSystem.getFolderInputParameters().subFolders;
if (subFolders) {
@ -149,7 +151,7 @@ public class CheckWavHeadersPane extends PamBorderPane {
textArea.setText(" ");
allFiles.clear();
nFiles = countFiles(folder);
progressBar.setProgress(0);
progressProperty.setValue(0);
progressBar.progressProperty().bind(progressProperty);
//progressBar.setMaximum(Math.max(nFiles, 1));
enableControls();
@ -213,6 +215,10 @@ public class CheckWavHeadersPane extends PamBorderPane {
nErrors = 0;
enableControls();
checkFilesWorker = new CheckFiles();
Thread th = new Thread(checkFilesWorker);
th.setDaemon(true);
th.start();
}
@ -245,10 +251,16 @@ public class CheckWavHeadersPane extends PamBorderPane {
* for each file, report on progress with it's name and
* whether or not it had an error
*/
int error;
File aFile;
System.out.println("Analaysing files: Start: " + allFiles.size() );
for (int i = 0; i < allFiles.size(); i++) {
error = checkFile(aFile = allFiles.get(i));
System.out.println("Analaysing files: " + i);
final int error = checkFile(aFile = allFiles.get(i));
final File aFile1 = aFile;
Platform.runLater(()->{
textArea.appendText(String.format("\n File %s %s" , aFile1.getName() ,
error == AudioFileFuncs.FILE_OK ? "OK" : ("Error " + error)));
});
//progressBar.progressProperty().bind(null);
progressProperty.setValue(100*i/(double) allFiles.size());
}

View File

@ -304,6 +304,7 @@ public class FolderInputPane extends DAQSettingsPane<FolderInputParameters>{
wavFix.setOnAction((action)->{
acquisitionPaneFX.getAdvancedLabel().setText("Fix Wave Files");
acquisitionPaneFX.getAdvancedPane().setCenter(this.fixWavPane);
fixWavPane.setParams();
acquisitionPaneFX.getFlipPane().flipToBack();
});

View File

@ -344,7 +344,7 @@ public class ColourArray implements Cloneable, Serializable, ManagedParameters {
* @return a contrasting colour.
*/
private Color createContrastingColour() {
Color[] tryCols = {Color.white, Color.red, Color.blue, Color.green, Color.black};
Color[] tryCols = {Color.white, Color.red, Color.CYAN, Color.blue, Color.green, Color.black};
if (colours == null) {
return tryCols[0];
}

View File

@ -81,6 +81,15 @@ public class ColourComboBox extends PamPanel {
}
// private void createImages() {
// for (int i = 0; i < ColourArray.ColourArrayType.values().length; i++) {
// intArray[i] = new Integer(i);
// colourStrings[i]=ColourArray.getName(types[i]);
// colourArray=ColourArray.createStandardColourArray(256, ColourArray.ColourArrayType.values()[i]);
// images[i]=new ImageIcon(createColourMapImage(colourArray, height, width));
// }
// }
public void addActionListener(ActionListener actionListener){
colourBox.addActionListener(actionListener);
}
@ -161,7 +170,7 @@ public class ColourComboBox extends PamPanel {
for (int i = 0; i < ColourArray.ColourArrayType.values().length; i++) {
intArray[i] = new Integer(i);
colourStrings[i]=ColourArray.getName(types[i]);
colourArray=ColourArray.createStandardColourArray(256, ColourArray.ColourArrayType.values()[i]);
colourArray=ColourArray.createStandardColourArray(width, ColourArray.ColourArrayType.values()[i]);
images[i]=new ImageIcon(createColourMapImage(colourArray, height, width));
}
}

View File

@ -85,7 +85,7 @@ public abstract class GeneralProjector<T extends PamCoordinate> {
TIME ("Time"), FREQUENCY ("Frequency"), AMPLITUDE ("Amplitude"), LATITUDE ("Latitude"), LONGITUDE ("Longitude") ,
BEARING ("Bearing"), RANGE ("Range"), SLANTANGLE ("Slant angle"), ICI ("Inter-click-interval"),
DEPTH ("Depth"), SLANTBEARING ("Slant bearing"), AMPLITUDE_STEM ("Amplitude (stem)"), AMPLITUDE_LIN ("Linear Amplitude"),
SPEED ("Speed"), PROBABILITY ("Probability"), NCYCLES ("No. cycles"), BANDWIDTH("Bandwidth"), ISHDET("Detector Output");
SPEED ("Speed"), PROBABILITY ("Probability"), NCYCLES ("No. cycles"), BANDWIDTH("Bandwidth"), ISHDET("Detector Output"), X("x coordinate"), Y("y coordinate");
private String unit;

View File

@ -23,6 +23,24 @@ public class CornerLayoutContraint implements Serializable, Cloneable {
public int anchor = FIRST_LINE_START;
/**
* Construct a corner layout constraint with the given anchor
* @param anchor
*/
public CornerLayoutContraint(int anchor) {
super();
this.anchor = anchor;
}
/**
* construct a corner layout constraint with the default anchor
*/
public CornerLayoutContraint() {
super();
this.anchor = anchor;
}
@Override
protected CornerLayoutContraint clone() {
try {

View File

@ -986,7 +986,9 @@ public class PamDataBlock<Tunit extends PamDataUnit> extends PamObservable {
}
/**
* Instruction from the viewer scroll manager to load new data.
* Instruction from the viewer scroll manager to load new data. <p>This just calls through
* to loadViewerData(OfflineDataLoadInfo ...) so this should not be overridden. Override
* the other function instead.
*
* @param dataStart data start time in millis
* @param dataEnd data end time in millis.

View File

@ -99,35 +99,11 @@ public class RawDataTransforms {
*/
private int shortestFFTLength;
/**
* Object for synchronization. Get thread lock if this isn't the same as
* the object holding the data.
*/
private Object synchObject;
/**
* Raw Data Transforms for a RawDataHolder using the rawDataHolder as the synchronization
* object.
* @param rawDataHolder RawDataHolder object (e.g. a click)
*/
public RawDataTransforms(@SuppressWarnings("rawtypes") PamDataUnit rawDataHolder) {
this(rawDataHolder, rawDataHolder);
}
/**
* Raw Data Transforms for a RawDataHolder.
* @param rawDataHolder RawDataHolder object (e.g. a click)
* @param synchObject synchronization object, which is most likely the RawDataHolder object.
*/
public RawDataTransforms(@SuppressWarnings("rawtypes") PamDataUnit rawDataHolder, Object synchObject) {
this.rawData=(RawDataHolder) rawDataHolder;
this.dataUnit = rawDataHolder;
this.synchObject = synchObject;
if (this.synchObject == null) {
this.synchObject = this;
}
}
@ -167,8 +143,7 @@ public class RawDataTransforms {
* @param fftLength
* @return Power spectrum
*/
public double[] getPowerSpectrum(int channel, int minBin, int maxBin, int fftLength) {
synchronized (synchObject) {
public synchronized double[] getPowerSpectrum(int channel, int minBin, int maxBin, int fftLength) {
if (minBin==0 && maxBin>=this.getWaveData(0).length-1) {
return getPowerSpectrum(channel, fftLength);
}
@ -178,7 +153,7 @@ public class RawDataTransforms {
double[] waveformTrim = new double[maxBin-minBin];
// System.out.println("minBin: " + minBin + " maxBin: " + maxBin + " raw waveform: " + this.getWaveData(channel).length);
//System.out.println("minBin: " + minBin + " maxBin: " + maxBin + " raw waveform: " + this.getWaveData(channel).length);
System.arraycopy(this.getWaveData(channel), minBin, waveformTrim, 0, Math.min(this.getWaveData(channel).length-minBin-1, waveformTrim.length));
@ -186,7 +161,6 @@ public class RawDataTransforms {
return cData.magsq();
}
}
/**
* Returns the power spectrum for a given channel (square of magnitude of
@ -196,8 +170,7 @@ public class RawDataTransforms {
* @param fftLength
* @return Power spectrum
*/
public double[] getPowerSpectrum(int channel, int fftLength) {
synchronized (synchObject) {
public synchronized double[] getPowerSpectrum(int channel, int fftLength) {
if (powerSpectra == null) {
powerSpectra = new double[PamUtils.getNumChannels(dataUnit.getChannelBitmap())][];
}
@ -221,7 +194,6 @@ public class RawDataTransforms {
}
return powerSpectra[channel];
}
}
/**
@ -230,8 +202,7 @@ public class RawDataTransforms {
* @param fftLength
* @return Sum of power spectra
*/
public double[] getTotalPowerSpectrum(int fftLength) {
synchronized (synchObject) {
public synchronized double[] getTotalPowerSpectrum(int fftLength) {
if (fftLength == 0) {
fftLength = getCurrentSpectrumLength();
}
@ -251,7 +222,6 @@ public class RawDataTransforms {
}
return totalPowerSpectrum;
}
}
@ -265,8 +235,7 @@ public class RawDataTransforms {
* @param fftLength - the FFT length to use.
* @return the complex spectrum - the comnplex spectrum of the wave data from the specified channel.
*/
public ComplexArray getComplexSpectrumHann(int channel, int fftLength) {
synchronized (synchObject) {
public synchronized ComplexArray getComplexSpectrumHann(int channel, int fftLength) {
complexSpectrum = new ComplexArray[PamUtils.getNumChannels(dataUnit.getChannelBitmap())];
if (complexSpectrum[channel] == null
|| complexSpectrum.length != fftLength / 2) {
@ -276,7 +245,6 @@ public class RawDataTransforms {
}
return complexSpectrum[channel];
}
}
@ -314,13 +282,11 @@ public class RawDataTransforms {
* @return the spectrogram length.
*/
private int getCurrentSpectrumLength() {
synchronized (synchObject) {
if (currentSpecLen<=0) {
currentSpecLen = PamUtils.getMinFftLength(dataUnit.getSampleDuration());
}
return currentSpecLen;
}
}
@ -405,8 +371,7 @@ public class RawDataTransforms {
* @param fftLength
* @return the complex spectrum
*/
public ComplexArray getComplexSpectrum(int channel, int fftLength) {
synchronized (synchObject) {
public synchronized ComplexArray getComplexSpectrum(int channel, int fftLength) {
double[] paddedRawData;
double[] rawData;
int i, mn;
@ -430,7 +395,6 @@ public class RawDataTransforms {
}
return complexSpectrum[channel];
}
}
/**
@ -438,8 +402,7 @@ public class RawDataTransforms {
* @param iChan channel index
* @return analytic waveform
*/
public double[] getAnalyticWaveform(int iChan) {
synchronized (synchObject) {
public synchronized double[] getAnalyticWaveform(int iChan) {
if (analyticWaveform == null) {
analyticWaveform = new double[getNChan()][];
}
@ -448,7 +411,6 @@ public class RawDataTransforms {
// }
return analyticWaveform[iChan];
}
}
/**
* Get filtered or unfiltered analytic waveform. Easy access method for click
@ -459,8 +421,7 @@ public class RawDataTransforms {
* @param fftFilterParams fft filter parameters.
* @return analystic waveform.
*/
public double[] getAnalyticWaveform(int iChan, boolean filtered, FFTFilterParams fftFilterParams) {
synchronized (synchObject) {
public synchronized double[] getAnalyticWaveform(int iChan, boolean filtered, FFTFilterParams fftFilterParams) {
if (filtered == false || fftFilterParams == null) {
return getAnalyticWaveform(iChan);
}
@ -468,7 +429,6 @@ public class RawDataTransforms {
return getFilteredAnalyticWaveform(fftFilterParams, iChan);
}
}
}
/**
* Get a filtered version of the analytic waveform. In principle, this could be made more efficient
@ -477,8 +437,7 @@ public class RawDataTransforms {
* @param iChan channel number
* @return envelope of the filtered data.
*/
public double[] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams, int iChan) {
synchronized (synchObject) {
public synchronized double[] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams, int iChan) {
if (analyticWaveform == null) {
analyticWaveform = new double[getNChan()][];
}
@ -488,7 +447,6 @@ public class RawDataTransforms {
// }
return analyticWaveform[iChan];
}
}
/**
* Get the analytic waveform for all channels
@ -497,7 +455,6 @@ public class RawDataTransforms {
* @return analystic waveforms
*/
public double[][] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams) {
synchronized (synchObject) { // new
if (analyticWaveform == null) {
analyticWaveform = new double[getNChan()][];
}
@ -512,7 +469,6 @@ public class RawDataTransforms {
}
return analyticWaveform;
}
}
/**
@ -522,7 +478,7 @@ public class RawDataTransforms {
* @param channelIndex channel index
* @return filtered waveform data
*/
public double[] getFilteredWaveData(FFTFilterParams filterParams, int channelIndex) {
public synchronized double[] getFilteredWaveData(FFTFilterParams filterParams, int channelIndex) {
filteredWaveData = getFilteredWaveData(filterParams);
return filteredWaveData[channelIndex];
}
@ -533,15 +489,13 @@ public class RawDataTransforms {
* @param filterParams filter parameters
* @return array of filtered data
*/
public double[][] getFilteredWaveData(FFTFilterParams filterParams) {
synchronized (synchObject) {
public synchronized double[][] getFilteredWaveData(FFTFilterParams filterParams) {
//System.out.println("Make filterred wave data!: " + (filterParams != oldFFTFilterParams));
if (filteredWaveData == null || filterParams != oldFFTFilterParams) {
filteredWaveData = makeFilteredWaveData(filterParams);
}
return filteredWaveData;
}
}
private double[][] makeFilteredWaveData(FFTFilterParams filterParams) {
double[][] waveData = this.rawData.getWaveData();
@ -579,7 +533,6 @@ public class RawDataTransforms {
* @return FFT filter object.
*/
public FFTFilter getFFTFilter(FFTFilterParams fftFilterParams) {
synchronized (synchObject) {
if (fftFilter == null) {
fftFilter = new FFTFilter(fftFilterParams, this.dataUnit.getParentDataBlock().getSampleRate());
}
@ -588,7 +541,6 @@ public class RawDataTransforms {
}
return fftFilter;
}
}
/**
@ -654,10 +606,8 @@ public class RawDataTransforms {
* @return
*/
private int getNChan() {
synchronized (synchObject) { // new
return this.rawData.getWaveData().length;
}
}
/**
* Get the current power spectra. Can be null if it has not been calculated using
@ -689,12 +639,10 @@ public class RawDataTransforms {
* Free eup some memory by deleting the filtered wave data, power spectra and analytic waveform.
*/
public void freeMemory() {
synchronized (synchObject) {
filteredWaveData = null;
powerSpectra = null;
analyticWaveform = null;
}
}

View File

@ -32,7 +32,7 @@ public class DataSelectorSettings implements Serializable, ManagedParameters {
* @return Params or null if they don't exist.
*/
public DataSelectParams getParams(String name) {
if (selectorParams == null) {
if (selectorParams == null || name == null) {
return null;
}
return selectorParams.get(name);

View File

@ -615,7 +615,7 @@
-fx-background: -fx-darkbackground;
-fx-background-color: -fx-darkbackground;
-fx-border-radius: 0 0 0 0;
-fx-padding: 7 0 7 0;
-fx-padding: 5 0 5 0;
-fx-border-color: transparent;
}
@ -623,9 +623,9 @@
-fx-text-fill: white;
-fx-background-color: -fx-darkbackground;
-fx-border-color: -fx-border_col;
-fx-background-radius: 6 6 0 0;
-fx-border-radius: 6 6 0 0;
-fx-padding: 7 0 7 0;
-fx-background-radius: 5 5 0 0;
-fx-border-radius: 5 5 0 0;
-fx-padding: 5 0 5 0;
}
.spinner .increment-arrow {
@ -635,16 +635,16 @@
.spinner .increment-arrow-button:hover {
-fx-background-color: -fx-highlight;
-fx-border-color: -fx-highlight_border;
-fx-background-radius: 6 6 0 0;
-fx-border-radius: 6 6 0 0;
-fx-background-radius: 5 5 0 0;
-fx-border-radius: 5 5 0 0;
}
.spinner .decrement-arrow-button {
-fx-text-fill: white;
-fx-background-color: -fx-darkbackground;
-fx-border-color: -fx-border_col;
-fx-background-radius: 0 0 6 6;
-fx-border-radius: 0 0 6 6
-fx-background-radius: 0 0 5 5;
-fx-border-radius: 0 0 5 5
}
.spinner .decrement-arrow {
@ -654,8 +654,8 @@
.spinner .decrement-arrow-button:hover {
-fx-background-color: -fx-highlight;
-fx-border-color: -fx-highlight_border;
-fx-background-radius: 0 0 6 6;
-fx-border-radius: 0 0 6 6;
-fx-background-radius: 0 0 5 5;
-fx-border-radius: 0 0 5 5;
}
/*Arrows are horizontal either side of text box*/
@ -663,7 +663,7 @@
-fx-text-fill: white;
-fx-background-color: -fx-darkbackground;
-fx-border-color: -fx-border_col;
-fx-border-radius: 0 6 6 0
-fx-border-radius: 0 5 5 0
}
@ -671,22 +671,22 @@
-fx-text-fill: white;
-fx-background-color: -fx-darkbackground;
-fx-border-color: -fx-border_col;
-fx-border-radius: 6 0 0 6
-fx-border-radius: 5 0 0 5
}
.spinner.split-arrows-horizontal .increment-arrow-button:hover {
-fx-background-color: -fx-highlight;
-fx-border-color: -fx-highlight_border;
-fx-background-radius: 0 6 6 0;
-fx-border-radius: 0 6 6 0;
-fx-background-radius: 0 5 5 0;
-fx-border-radius: 0 5 5 0;
}
.spinner.split-arrows-horizontal .decrement-arrow-button:hover {
-fx-background-color: -fx-highlight;
-fx-border-color: -fx-highlight_border;
-fx-background-radius: 6 0 0 6;
-fx-border-radius: 6 0 0 6;
-fx-background-radius: 5 0 0 5;
-fx-border-radius: 5 0 0 5;
}
.spinner.split-arrows-horizontal .text-field {

View File

@ -1572,6 +1572,9 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
}
private double clickAngleToY(ClickDetection click) {
AbstractLocalisation loc = click.getLocalisation();
// if (click.getUID() == 110006089) {
// System.out.println("Click 110006089 angle " + click.getAngle());
// }
if (loc == null) return 0;
double angle = 0;
GpsData oll;

View File

@ -210,8 +210,8 @@ public class ClickBinaryDataSource extends BinaryDataSource {
// long uid = binaryObjectData.getDataUnitBaseData().getUID();
// System.out.printf("Loading click with UID %d at %s\n", uid,
// PamCalendar.formatDateTime(binaryObjectData.getTimeMilliseconds()));
// if (uid == lastUID) {
// System.out.println("Click repeat UID: " + lastUID);
// if (uid == 110006089) {
// System.out.println("Click UID: " + 110006089);
// }
// else {
// lastUID = binaryObjectData.getDataUnitBaseData().getUID();

View File

@ -1328,6 +1328,8 @@ public class ClickDetection extends PamDataUnit<PamDataUnit, PamDataUnit> implem
/**
* Returns the angle in degrees for compatibilty with older version of click detector
* This is really bad to use for anything apart from two element arrays and it would be
* sensible to remove the function entirely.
* @return angle of the click detection in degrees
*/
public double getAngle() {

View File

@ -218,6 +218,7 @@ public class ClickSelectPaneFX extends DynamicSettingsPane<Boolean> {
ClickAlarmParameters clickAlarmParameters = clickDataSelector.getClickAlarmParameters();
speciesSelect.getChildren().clear();
//species pane setup
species = null;
weights = null;
@ -351,6 +352,7 @@ public class ClickSelectPaneFX extends DynamicSettingsPane<Boolean> {
boolean getParams() {
ClickAlarmParameters clickAlarmParameters = clickDataSelector.getClickAlarmParameters().clone();
clickAlarmParameters.useEchoes = useEchoes.isSelected();
try {
@ -397,6 +399,7 @@ public class ClickSelectPaneFX extends DynamicSettingsPane<Boolean> {
// btDisplayParameters.showANDEvents = andEvents.isSelected();
// btDisplayParameters.showEventsOnly = onlyEvents.isSelected();
clickDataSelector.setClickAlarmParameters(clickAlarmParameters);
return true;
}

View File

@ -1,9 +1,8 @@
package clickTrainDetector.classification;
import java.util.ArrayList;
import java.util.UUID;
import PamUtils.PamCalendar;
import PamguardMVC.debug.Debug;
import clickTrainDetector.CTDataUnit;
import clickTrainDetector.ClickTrainControl;
import clickTrainDetector.classification.bearingClassifier.BearingClassification;
@ -158,10 +157,10 @@ public class CTClassifierManager {
//first check the pre-classifier
Chi2CTClassification classification = this.preClassifier.classifyClickTrain(ctDataUnit);
System.out.println("Pre classifier: " + PamCalendar.formatDateTime(ctDataUnit.getTimeMilliseconds()) + " N. " + ctDataUnit.getSubDetectionsCount() + "UID first: " + ctDataUnit.getSubDetection(0).getUID() );
//System.out.println("Pre classifier: " + PamCalendar.formatDateTime(ctDataUnit.getTimeMilliseconds()) + " N. " + ctDataUnit.getSubDetectionsCount() + "UID first: " + ctDataUnit.getSubDetection(0).getUID() );
if (classification.getSpeciesID()==CTClassifier.NOSPECIES) {
System.out.println("No SPECIES: chi^2" + ctDataUnit.getCTChi2());
//System.out.println("No SPECIES: chi^2" + ctDataUnit.getCTChi2());
ctDataUnit.setJunkTrain(true);
//no need to do any more classification- the click train has been flagged for deletion.
ctDataUnit.clearClassifiers();
@ -189,17 +188,17 @@ public class CTClassifierManager {
ctDataUnit.clearClassifiers();
ctDataUnit.setClassificationIndex(-1);
System.out.println("Classify species: Num classifier " + this.cTClassifiers.size());
//System.out.println("Classify species: Num classifier " + this.cTClassifiers.size());
for (int i=0; i<this.cTClassifiers.size(); i++) {
System.out.println("Classifier: " + i);
//System.out.println("Classifier: " + i);
//the first classifier
ctclassification = this.cTClassifiers.get(i).classifyClickTrain(ctDataUnit);
System.out.println("Classifier complete: SPECIES: " + ctclassification.getSpeciesID());
//System.out.println("Classifier complete: SPECIES: " + ctclassification.getSpeciesID());
// Debug.out.println(i + " ClassifierManager: Classify a click train data unit: " + ctDataUnit + " parent data block: " +
@ -208,7 +207,7 @@ public class CTClassifierManager {
//set the species flag but only if this is the first time the ct data unit has been classified.
if (ctclassification.getSpeciesID()>CTClassifier.NOSPECIES && !hasBeenClssfd) {
System.out.println("Set classiifcation index: " + i);
//System.out.println("Set classiifcation index: " + i);
ctDataUnit.setClassificationIndex(i); //set the classification index.
hasBeenClssfd = true;
}
@ -238,12 +237,26 @@ public class CTClassifierManager {
System.err.println("CTCLassifier manager: the classifier is null");
continue;
}
if (ctParams[i].uniqueID ==null) {
//old versions may not have a unique ID so needs to be added.
ctParams[i].uniqueID = UUID.randomUUID().toString();
}
aClassifier.setParams(ctParams[i]);
cTClassifiers.add(aClassifier);
}
}
/**
* Get the pre-classifer. This is an intial very broad classifier that is used to determine
* whether a click train should be saved or dumped from memory.
* @return the pre-classifier.
*/
public Chi2ThresholdClassifier getPreClassifier() {
return preClassifier;
}

View File

@ -1,6 +1,7 @@
package clickTrainDetector.classification;
import java.io.Serializable;
import java.util.UUID;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
@ -20,12 +21,23 @@ public class CTClassifierParams implements Cloneable, Serializable, ManagedParam
private static final long serialVersionUID = 1L;
public CTClassifierParams() {
this.uniqueID = UUID.randomUUID().toString();
}
/**
* A very simple species flag to indicate what classifier was used. 0 means not classified.
* The name of the classifier.
*/
public String classifierName = "";
/**
* A unique ID for the classifier that never changes. This is important for accessing data selectors.
*/
public String uniqueID;
/**
* A very simple species flag to indicate what classifier was used. 0 means not classified.
*/

View File

@ -15,6 +15,7 @@ public class BearingClassifierParams extends CTClassifierParams implements Manag
public BearingClassifierParams(){
super();
type = CTClassifierType.BEARINGCLASSIFIER;
}

View File

@ -4,9 +4,15 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import clickTrainDetector.classification.CTClassifierParams;
import clickTrainDetector.classification.CTClassifierType;
public class IDIClassifierParams extends CTClassifierParams implements Serializable, Cloneable, ManagedParameters {
public IDIClassifierParams(){
super();
type = CTClassifierType.IDICLASSIFIER;
}
/**
*
*/

View File

@ -1,5 +1,7 @@
package clickTrainDetector.classification.simplechi2classifier;
import PamguardMVC.PamDataBlock;
import PamguardMVC.dataSelector.DataSelector;
import clickTrainDetector.classification.CTClassification;
import clickTrainDetector.classification.CTClassifierType;
import clickTrainDetector.classification.ClassifierJSONLogging;
@ -25,7 +27,6 @@ public class Chi2CTClassification implements CTClassification {
private SimpleClassifierJSONLogging simpleClassifierJSONLogging;
public Chi2CTClassification(int speciesCode) {
this.speciesCode = speciesCode;
simpleClassifierJSONLogging=new SimpleClassifierJSONLogging();
@ -63,4 +64,6 @@ public class Chi2CTClassification implements CTClassification {
return simpleClassifierJSONLogging;
}
}

View File

@ -1,6 +1,8 @@
package clickTrainDetector.classification.simplechi2classifier;
import PamUtils.PamCalendar;
import PamguardMVC.PamDataBlock;
import PamguardMVC.dataSelector.DataSelector;
import PamguardMVC.debug.Debug;
import clickTrainDetector.CTDataUnit;
import clickTrainDetector.ClickTrainControl;
@ -33,9 +35,16 @@ public class Chi2ThresholdClassifier implements CTClassifier {
private ClickTrainControl clickTrainControl;
/**
* Data selector for the chi2 threshold classifier.
*/
private DataSelector dataSelector;
public Chi2ThresholdClassifier(ClickTrainControl clickTrainControl, int defaultSpeciesID) {
this.clickTrainControl=clickTrainControl;
clssfrParams.speciesFlag=defaultSpeciesID;
createDataSelector(clickTrainControl.getParentDataBlock());
}
@ -65,9 +74,63 @@ public class Chi2ThresholdClassifier implements CTClassifier {
return new Chi2CTClassification(CTClassifier.NOSPECIES); //no classification
}
if (!isPercClicks(clickTrain)) {
// Debug.out.println("Failed on chi2Threshold");
return new Chi2CTClassification(CTClassifier.NOSPECIES); //no classification
}
return new Chi2CTClassification(clssfrParams.speciesFlag);
}
/**
* Check the percentage of clicks which are correctly classified by the data selector.
* @param clickTrain - the click train
* @return true if the percentage critera is passed
*
*/
private boolean isPercClicks(CTDataUnit clickTrain) {
//no point iterating through click if we do not need to.
if (clssfrParams.minPercentage==0) return true;
double count = 0;
for (int i=0; i<clickTrain.getSubDetectionsCount(); i++) {
if (this.getDataSelector().scoreData(clickTrain.getSubDetection(i))>0) {
count = count+1.;
}
}
if (count/clickTrain.getSubDetectionsCount()>=clssfrParams.minPercentage) {
return true;
}
else {
return false;
}
}
/**
* Get the data selector.
* @param source - the source data block
* @return the data selector.
*/
public void createDataSelector(PamDataBlock<?> source) {
if (dataSelector==null || dataSelector.getPamDataBlock()!=source) {
//create the data selector
//System.out.println("Data selector: " + dataSelector);
if (source!=null) {
dataSelector=source.getDataSelectCreator().getDataSelector(clickTrainControl.getUnitName() + " " + clssfrParams.uniqueID
+ "_X2_threshold_classifier", false, null);
//System.out.println("Data selector: " + dataSelector);
}
else {
dataSelector=null;
}
}
}
@Override
public String getName() {
return "X\u00b2 threshold classifier";
@ -122,7 +185,6 @@ public class Chi2ThresholdClassifier implements CTClassifier {
public void setParams(Chi2ThresholdParams clssfrParams) {
//System.out.println("HELLO CLASSIFIER PARAMS: " + clssfrParams.chi2Threahold );
this.clssfrParams=clssfrParams;
}
/**
@ -145,4 +207,10 @@ public class Chi2ThresholdClassifier implements CTClassifier {
}
public DataSelector getDataSelector() {
createDataSelector(clickTrainControl.getParentDataBlock());
return dataSelector;
}
}

View File

@ -1,5 +1,8 @@
package clickTrainDetector.classification.simplechi2classifier;
import java.io.Serializable;
import java.util.UUID;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import clickTrainDetector.classification.CTClassifierParams;
@ -12,9 +15,10 @@ import clickTrainDetector.classification.CTClassifierType;
* @author Jamie Macaulay
*
*/
public class Chi2ThresholdParams extends CTClassifierParams implements ManagedParameters {
public class Chi2ThresholdParams extends CTClassifierParams implements ManagedParameters, Serializable, Cloneable {
public Chi2ThresholdParams(){
super();
super.type=CTClassifierType.CHI2THRESHOLD;
}
@ -25,7 +29,7 @@ public class Chi2ThresholdParams extends CTClassifierParams implements ManagedPa
/**
* The chi2 threshold to set. This is the chi2 value divided by the number of clicks in the train.
* If zero then the classification always passes...A bit fo a hack for testing
* If zero then the classification always passes...A bit of a hack for testing
*/
public double chi2Threshold = 1500.;
@ -34,6 +38,12 @@ public class Chi2ThresholdParams extends CTClassifierParams implements ManagedPa
*/
public int minClicks = 5;
/**
* The minimum %percentage which must the parent data selector of clicks/
*. values are 0-1.
*/
public double minPercentage = 0;
/**
* The minimum time in seconds.
*/

View File

@ -130,7 +130,7 @@ public class StandardClassifier implements CTClassifier {
int speciesID = standardClssfrParams.speciesFlag;
System.out.println("Standard Classificiation: " );
//System.out.println("Standard Classificiation: " );
//all classifiers have to pass.
CTClassification[] ctClassification = new CTClassification[classifiers.size()];
@ -138,8 +138,8 @@ public class StandardClassifier implements CTClassifier {
ctClassification[i] = classifiers.get(i).classifyClickTrain(clickTrain);
System.out.println("Standard Classificiation: " + i + " speciesID: " + ctClassification[i].getSpeciesID()
+ " sub species: "+ classifiers.get(i).getParams().speciesFlag + " standard species: " +speciesID + " use? : " + standardClssfrParams.enable[i]);
// System.out.println("Standard Classificiation: " + i + " speciesID: " + ctClassification[i].getSpeciesID()
// + " sub species: "+ classifiers.get(i).getParams().speciesFlag + " standard species: " +speciesID + " use? : " + standardClssfrParams.enable[i]);
if (standardClssfrParams.enable[i]) {
if (ctClassification[i].getSpeciesID() != SUB_CLASSIFIER_SPECIESID){
@ -148,7 +148,7 @@ public class StandardClassifier implements CTClassifier {
}
}
System.out.println("SPECIES ID: " + speciesID);
//System.out.println("SPECIES ID: " + speciesID);
//create the classification.
StandardClassification classification = new StandardClassification(ctClassification, speciesID);

View File

@ -1,5 +1,7 @@
package clickTrainDetector.classification.standardClassifier;
import java.util.UUID;
import clickTrainDetector.classification.CTClassifierParams;
import clickTrainDetector.classification.CTClassifierType;
@ -27,6 +29,7 @@ public class StandardClassifierParams extends CTClassifierParams {
public StandardClassifierParams(){
super();
///very important to set this or else the clasifier manager does not
//know which classifier to create.
type = CTClassifierType.STANDARDCLASSIFIER;

View File

@ -22,6 +22,7 @@ public class TemplateClassifierParams extends CTClassifierParams implements Mana
private static final long serialVersionUID = 10L;
public TemplateClassifierParams(){
super();
super.type=CTClassifierType.TEMPLATECLASSIFIER;
// chi2ThresholdParams = new Chi2ThresholdParams();
// template = DefualtSpectrumTemplates.getTemplate(SpectrumTemplateType.BEAKED_WHALE);

View File

@ -39,7 +39,10 @@ public class AmplitudeChi2 extends SimpleChi2VarDelta {
@Override
public double getDiffValue(PamDataUnit pamDataUnit0, PamDataUnit pamDataUnit1) {
//System.out.println("DB: " + pamDataUnit0.getAmplitudeDB());
return pamDataUnit0.getAmplitudeDB()-pamDataUnit1.getAmplitudeDB();
//made this abs so it can deal with increasing then decreasing click trains. i.e.
//the click trian is not penalised if it gradually increasing then starts to gradually decrease
//in amplitude.
return Math.abs(pamDataUnit0.getAmplitudeDB()-pamDataUnit1.getAmplitudeDB());
}
@Override

View File

@ -1,9 +1,12 @@
package clickTrainDetector.dataselector;
import java.util.Arrays;
import PamDetection.LocContents;
import PamguardMVC.PamDataUnit;
import PamguardMVC.dataSelector.DataSelectParams;
import PamguardMVC.dataSelector.DataSelector;
import clickTrainDetector.CTDataUnit;
import clickTrainDetector.CTDetectionGroupDataUnit;
import clickTrainDetector.ClickTrainControl;
import clickTrainDetector.ClickTrainDataBlock;
@ -43,6 +46,8 @@ public class CTDataSelector extends DataSelector {
private boolean allowScores;
private boolean[] useSpeciesList;
public CTDataSelector(ClickTrainControl clickTrainControl, ClickTrainDataBlock clickTrainDataBlock,
String selectorName, boolean allowScores) {
super(clickTrainDataBlock, selectorName, allowScores);
@ -83,6 +88,7 @@ public class CTDataSelector extends DataSelector {
@Override
public DataSelectParams getParams() {
getDialogPanel().getParams(ctSelectParams);
return ctSelectParams;
}
@ -100,6 +106,8 @@ public class CTDataSelector extends DataSelector {
if (ctDataUnit.getSubDetectionsCount()<ctSelectParams.minSubDetections) return 0;
if (!isClassified(ctDataUnit)) return 0;
if (ctSelectParams.needsLoc && pamDataUnit.getLocalisation()==null) return 0;
if (ctSelectParams.needsLoc && !pamDataUnit.getLocalisation().hasLocContent(LocContents.HAS_RANGE)) return 0;
@ -108,4 +116,31 @@ public class CTDataSelector extends DataSelector {
return 1;
}
/**
* Check whether a click train passes the data selector classification criteria.
* @param ctDataUnit - the click train data unit to test.
* @return true of the click train passes detection criterea.
*/
private boolean isClassified(CTDetectionGroupDataUnit ctDataUnit) {
if (!ctSelectParams.needsClassification) return true;
if (ctDataUnit instanceof CTDataUnit) {
CTDataUnit clickTrain = (CTDataUnit) ctDataUnit;
if (clickTrain.ctClassifications==null) return false;
//iterate through all the classifiers and allowed classification types.
for (int i=0; i<ctSelectParams.classifier.length; i++) {
for (int j=0; j<clickTrain.ctClassifications.size(); j++) {
if (clickTrain.ctClassifications.get(j).getSpeciesID()==ctSelectParams.classifier[i]) {
return true;
}
}
}
}
return false;
}
}

View File

@ -34,6 +34,16 @@ public class CTSelectParams extends DataSelectParams implements Serializable, Cl
*/
public int minSubDetections = 10;
/**
* True of the click train detector needs a classifcation
*/
public boolean needsClassification = false;
/**
* The classifier type(s) to select
*/
public int[] classifier = null;
/**
* The plotting works as follows: Data is plotted either after a minTime has passed and bearing change has exceeded
@ -56,6 +66,8 @@ public class CTSelectParams extends DataSelectParams implements Serializable, Cl
*/
public double maxAngleChange = Math.toRadians(5);
@Override
public ClickTrainSelectParameters clone() {
try {

View File

@ -73,7 +73,7 @@ public class CTSwingGUI extends PamControlledGUISwing {
settingsDialog = new PamDialogFX2AWT<ClickTrainParams>(parentFrame, setPane, false);
}
if (classificationTab!=null) settingsPane.setTab(classificationTab ? 2 : 0); //set the tab to the classification tab
if (classificationTab!=null && classificationTab) settingsPane.setTab(2); //set the tab to the classification tab
ClickTrainParams newParams = settingsDialog.showDialog(this.clickTrainControl.getClickTrainParams());

View File

@ -324,8 +324,14 @@ public class ClickTrainAlgorithmPaneFX extends SettingsPane<ClickTrainParams> {
popOver.showingProperty().addListener((obs, old, newval)->{
if (newval) {
//the dialog has opened
clickTrainControl.getDataSelector().getDialogPaneFX().setParams(true);
}
else {
//the dialog has closed
clickTrainControl.getDataSelector().getDialogPaneFX().getParams(true);
}
});
popOver.show(dataSelectorButton);

View File

@ -34,7 +34,7 @@ public class PreClassifierPane extends PamBorderPane {
private Pane createClassifierPane() {
simpleCTClassifierPane = new SimpleCTClassifierPane(null);
simpleCTClassifierPane = new SimpleCTClassifierPane(clickTrainControl.getClassifierManager().getPreClassifier());
return (Pane) simpleCTClassifierPane.getContentNode();
}

View File

@ -35,14 +35,15 @@ public class SimpleCTClassifierGraphics implements CTClassifierGraphics {
if (simpleCTClassiferPane==null) {
simpleCTClassiferPane = new SimpleCTClassifierPane(simpleChi2Classifier);
}
//params are set here.
simpleCTClassiferPane.setParams(simpleChi2Classifier.getParams());
//System.out.println("SimpleCTClassifierGraphics getCTClassifierPane: " + simpleChi2Classifier.getParams().chi2Threshold);
//params are set here. <- do not do this because you may wish to store the classifier params somewhere else.
//simpleCTClassiferPane.setParams(simpleChi2Classifier.getParams());
return (Pane) simpleCTClassiferPane.getContentNode();
}
@Override
public CTClassifierParams getParams() {
Chi2ThresholdParams clssfrParams = simpleCTClassiferPane.getParams(simpleChi2Classifier.getParams());
Chi2ThresholdParams clssfrParams = simpleCTClassiferPane.getParams(simpleChi2Classifier.getParams()).clone();
if (clssfrParams==null) {
System.err.print("Simple Chi2 Classifier returned null params");
return null;
@ -51,13 +52,14 @@ public class SimpleCTClassifierGraphics implements CTClassifierGraphics {
// simpleChi2Classifier.setParams(clssfrParams);
// return clssfrParams;
// }
//System.out.println("SimpleCTClassifierGraphics - getParams: " + clssfrParams.chi2Threshold);
return clssfrParams;
}
@Override
public void setParams(CTClassifierParams params) {
simpleCTClassiferPane.setParams((Chi2ThresholdParams) params);
//System.out.println("SimpleCTClassifierGraphics - setParams: " + ((Chi2ThresholdParams) params).chi2Threshold);
}
}

View File

@ -1,18 +1,32 @@
package clickTrainDetector.layout.classification.simplechi2classifier;
import java.text.DecimalFormat;
import org.controlsfx.control.PopOver;
import PamController.SettingsPane;
import PamguardMVC.PamDataBlock;
import clickTrainDetector.classification.simplechi2classifier.Chi2ThresholdClassifier;
import clickTrainDetector.classification.simplechi2classifier.Chi2ThresholdParams;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Control;
import javafx.scene.control.Spinner;
import javafx.scene.control.SpinnerValueFactory;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.Pane;
import javafx.util.StringConverter;
import pamViewFX.PamGuiManagerFX;
import pamViewFX.fxGlyphs.PamGlyphDude;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamButton;
import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.PamSpinner;
import pamViewFX.fxNodes.PamVBox;
import pamViewFX.fxNodes.utilityPanes.PamToggleSwitch;
import pamViewFX.fxNodes.utilsFX.ControlField;
/**
@ -51,6 +65,17 @@ public class SimpleCTClassifierPane extends SettingsPane<Chi2ThresholdParams> {
*/
private ControlField<Double> minTime;
private PamToggleSwitch dataSelectorCheckBox;
private PamButton dataSelectorButton;
private PopOver popOver;
/**
* The minimum percentage of clicks for a certain class.
*/
private ControlField<Double> minPercClicks;
public SimpleCTClassifierPane(Chi2ThresholdClassifier simpleChi2Classifier) {
super(null);
this.simpleChi2Classifier=simpleChi2Classifier;
@ -96,17 +121,35 @@ public class SimpleCTClassifierPane extends SettingsPane<Chi2ThresholdParams> {
chi2Threshold.getSpinner().getValueFactory().setConverter(PamSpinner.createStringConverter(0));
chi2Threshold.setTooltip(new Tooltip(
"A click train has a X\u00b2 value which is based on the consistancy of inter detection interval \n"
+ "amplitude and other factors. The calculation of X\\\\u00b2 changes depending on the click train \n"
+ "amplitude and other factors. The calculation of X\u00b2 changes depending on the click train \n"
+ "detector is used."));
chi2Threshold.getLabel1().setPrefWidth(LABEL_WIDTH);
minClicks = new ControlField<Double>("Min. Clicks ", "", 0, Integer.MAX_VALUE, 5);
minClicks = new ControlField<Double>("Min. clicks ", "", 0, Integer.MAX_VALUE, 5);
minClicks.setTooltip(new Tooltip(
"The minimum number of detections."));
minClicks.getSpinner().setEditable(true);
minClicks.getLabel1().setPrefWidth(LABEL_WIDTH);
minTime = new ControlField<Double>("Min. Time ", "s", 0.0, Double.MAX_VALUE, 1.0);
minPercClicks = new ControlField<Double>("Min. % clicks ", "", 0, 100., 1.);
minPercClicks.setTooltip(new Tooltip(
"The minimum number of detections."));
minPercClicks.getSpinner().setEditable(true);
SpinnerValueFactory<Double> valueFactory = new SpinnerValueFactory.DoubleSpinnerValueFactory(0, 100., 0., 1.);
valueFactory.setConverter(doubleConverter);
minPercClicks.getSpinner().setValueFactory(valueFactory);
minPercClicks.getSpinner().setEditable(true);
///HACK to get the percentage sign to show?
minPercClicks.getSpinner().increment();
minPercClicks.getSpinner().decrement();
minPercClicks.getLabel1().setPrefWidth(LABEL_WIDTH);
minPercClicks.getChildren().add( createDataSelectorPane());
minTime = new ControlField<Double>("Min. time ", "s", 0.0, Double.MAX_VALUE, 1.0);
minTime.getSpinner().getValueFactory().setConverter(PamSpinner.createStringConverter(2));
minTime.setTooltip(new Tooltip(
"The minimum time for a click train."));
@ -115,29 +158,83 @@ public class SimpleCTClassifierPane extends SettingsPane<Chi2ThresholdParams> {
chi2Threshold.getSpinner().setEditable(true);
vBox.getChildren().addAll(chi2Threshold, minClicks, minTime);
vBox.getChildren().addAll(chi2Threshold, minClicks, minPercClicks, minTime);
return vBox;
}
/**
* Create the data selector.
* @return the data selector.
*/
private Pane createDataSelectorPane() {
PamHBox hbox = new PamHBox();
hbox.setSpacing(5);
hbox.setAlignment(Pos.CENTER_LEFT);
dataSelectorButton = new PamButton();
// dataSelectorButton.setGraphic(PamGlyphDude.createPamGlyph(MaterialIcon.SETTINGS, PamGuiManagerFX.iconSize));
dataSelectorButton.setGraphic(PamGlyphDude.createPamIcon("mdi2c-cog", PamGuiManagerFX.iconSize));
dataSelectorButton.setOnAction((action)->{
showDataSelectorPane();
});
hbox.getChildren().addAll(dataSelectorButton);
return hbox;
}
/**
* Creates pane allowing the user to change fine scale things such as error limits.
* @return the pop over pane.
*/
public void showDataSelectorPane() {
if (popOver==null) {
popOver = new PopOver();
PamBorderPane holder = new PamBorderPane(simpleChi2Classifier.getDataSelector().getDialogPaneFX().getContentNode());
holder.setPadding(new Insets(5,5,5,5));
popOver.setContentNode(holder);
}
popOver.showingProperty().addListener((obs, old, newval)->{
if (newval) {
// System.out.println("Data Selector: " + simpleChi2Classifier.getDataSelector());
simpleChi2Classifier.getDataSelector().getDialogPaneFX().setParams(true);
}
else {
simpleChi2Classifier.getDataSelector().getDialogPaneFX().getParams(true);
}
});
popOver.show(dataSelectorButton);
}
@Override
public Chi2ThresholdParams getParams(Chi2ThresholdParams currParams) {
//System.out.println("Get PERC spinner value; " + minPercClicks.getSpinner().getValue());
currParams.chi2Threshold=chi2Threshold.getSpinner().getValue();
//HACK - for some reason Integer spinner is returning a double
currParams.minClicks=minClicks.getSpinner().getValue().intValue();
currParams.minTime=minTime.getSpinner().getValue();
currParams.minPercentage=minPercClicks.getSpinner().getValue()/100;
if (simpleChi2Classifier!=null && simpleChi2Classifier.getDataSelector()!=null) {
simpleChi2Classifier.getDataSelector().getDialogPaneFX().getParams(true);
}
return currParams;
}
@Override
public void setParams(Chi2ThresholdParams input) {
chi2Threshold.getSpinner().getValueFactory().setValue(input.chi2Threshold);
//HACK - for some reason Integer spinner is returning a double
minClicks.getSpinner().getValueFactory().setValue((double) input.minClicks);
minTime.getSpinner().getValueFactory().setValue(input.minTime);
minPercClicks.getSpinner().getValueFactory().setValue(input.minPercentage*100.);
}
@Override
@ -165,6 +262,24 @@ public class SimpleCTClassifierPane extends SettingsPane<Chi2ThresholdParams> {
}
StringConverter<Double> doubleConverter = new StringConverter<Double>() {
private final DecimalFormat df = new DecimalFormat("###.#");
@Override
public String toString(Double object) {
if (object == null) {return "";}
return df.format(object)+"%";}
@Override
public Double fromString(String string) {
try {
if (string == null) {return null;}
string = string.trim();
if (string.length() < 1) {return null;}
return df.parse(string).doubleValue();
} catch (Exception ex) {throw new RuntimeException(ex);}
}
};
}

View File

@ -118,6 +118,8 @@ public class TemplateClassifierPane extends SettingsPane<TemplateClassifierParam
spectrumPane.getChildren().addAll(spectrumthreshold, spectrumTemplatePane);
spectrumPane.setPadding(new Insets(5,5,5,5));
spectrumTemplatePane.prefWidthProperty().bind(spectrumPane.widthProperty());
// tabPane.setSide(Side.LEFT);
@ -136,6 +138,10 @@ public class TemplateClassifierPane extends SettingsPane<TemplateClassifierParam
// tabPane.minWidthProperty().bind(generalPane.widthProperty());
// tabPane.getTabs().addAll(tab1, tab2);
spectrumTemplatePane.drawCurrentUnit();
return new PamVBox(generalPane, spectrumPane);
}

View File

@ -122,11 +122,13 @@ public class TemplateSpectrumPane extends PamBorderPane {
stackPane.setMaxWidth(Double.MAX_VALUE);
stackPane.setPrefWidth(500); //need this for some reason to make the plot resize.
//stackPane.setStyle("-fx-background-color: red;");
detectionPlot.prefWidthProperty().bind(stackPane.widthProperty());
PamVBox holder = new PamVBox();
holder.setSpacing(5);
holder.getChildren().addAll(stackPane);
@ -363,4 +365,9 @@ public class TemplateSpectrumPane extends PamBorderPane {
}
public void drawCurrentUnit() {
templateDisplay.drawCurrentUnit();
}
}

View File

@ -15,6 +15,7 @@ import PamView.dialog.PamDialog;
import PamView.dialog.PamDialogPanel;
import PamView.dialog.PamGridBagContraints;
import PamguardMVC.dataSelector.DataSelectParams;
import clickTrainDetector.classification.CTClassifierManager;
import clickTrainDetector.dataselector.CTDataSelector;
import clickTrainDetector.dataselector.CTSelectParams;
import javafx.scene.control.CheckBox;
@ -71,8 +72,15 @@ public class CTDataSelectPanel implements PamDialogPanel {
*/
private JTextField minUnitsField;
private JPanel classification;
private JCheckBox[] classifierCheckBoxes;
private JCheckBox unclassifiedCheckBox;
private JPanel classificationFilter;
public CTDataSelectPanel(CTDataSelector ctDataSelector, boolean allowScores) {
// TODO Auto-generated constructor stub
this.ctDataSelector=ctDataSelector;
mainPanel = createPanel();
}
@ -84,7 +92,7 @@ public class CTDataSelectPanel implements PamDialogPanel {
private JPanel createPanel() {
//panel for map options
JPanel dataFilter=new JPanel();
dataFilter.setBorder(new TitledBorder("ClickTrain Filter"));
dataFilter.setBorder(new TitledBorder("General"));
GridBagLayout layout = new GridBagLayout();
GridBagConstraints constraints = new PamGridBagContraints();
dataFilter.setLayout(layout);
@ -108,9 +116,20 @@ public class CTDataSelectPanel implements PamDialogPanel {
PamDialog.addComponent(dataFilter, minUnitsField = new JTextField(4), constraints);
classificationFilter=new JPanel();
classificationFilter.setBorder(new TitledBorder("Species classification"));
layout = new GridBagLayout();
constraints = new PamGridBagContraints();
classificationFilter.setLayout(layout);
constraints.gridy = 0;
constraints.gridx = 0;
constraints.gridwidth=3;
PamDialog.addComponent(classificationFilter, classification = createClassificationPanel(), constraints);
//panel for map options
JPanel filterPanel=new JPanel();
filterPanel.setBorder(new TitledBorder("Sub Detection Filter"));
filterPanel.setBorder(new TitledBorder("Sub Detections"));
layout = new GridBagLayout();
constraints = new PamGridBagContraints();
filterPanel.setLayout(layout);
@ -163,11 +182,120 @@ public class CTDataSelectPanel implements PamDialogPanel {
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BorderLayout());
mainPanel.add(dataFilter, BorderLayout.NORTH); //preferred
mainPanel.add(classificationFilter, BorderLayout.CENTER); //changes size.
mainPanel.add(filterPanel, BorderLayout.SOUTH); //preferred
return mainPanel;
}
private JPanel createClassificationPanel() {
JPanel panel = new JPanel();
GridBagLayout layout = new GridBagLayout();
panel.setLayout(layout);
return panel;
}
/**
* Set up the classification pane with the right species check boxes etc.
*/
private void setClassificationPane() {
GridBagConstraints constraints = new PamGridBagContraints();
constraints.gridy = 0;
constraints.gridx = 0;
constraints.gridwidth=3;
classification.removeAll(); //clear all previous check boxes.
CTClassifierManager classifcationManager = ctDataSelector.getClickControl().getClassifierManager();
if (classifcationManager.getCurrentClassifiers().size()<1) {
//don't show the classification pane if there are no classiifcations.
this.classificationFilter.setVisible(false);
}
this.classificationFilter.setVisible(true);
PamDialog.addComponent(classification, unclassifiedCheckBox = new JCheckBox("All"), constraints);
unclassifiedCheckBox.addActionListener((action)->{
setCheckBoxEnable();
});
constraints.gridy++;
classifierCheckBoxes = new JCheckBox[classifcationManager.getCurrentClassifiers().size()];
for (int i=0; i<classifcationManager.getCurrentClassifiers().size(); i++) {
//System.out.println("Classifications: " + i);
PamDialog.addComponent(classification, classifierCheckBoxes[i] = new JCheckBox(classifcationManager.getCurrentClassifiers().get(i).getParams().classifierName), constraints);
classifierCheckBoxes[i].setSelected(true); //default should be selected
constraints.gridy++;
}
classification.validate(); //make sure everything is laid out properly.
setClassifierParams();
setCheckBoxEnable();
}
private void setCheckBoxEnable() {
if (classifierCheckBoxes!=null) {
for (int i=0; i<classifierCheckBoxes.length; i++) {
classifierCheckBoxes[i].setEnabled(!unclassifiedCheckBox.isSelected());
}
}
}
/**
* Set the classifier parameters.
*/
private void setClassifierParams() {
unclassifiedCheckBox.setSelected(currentParams.needsClassification );
if (currentParams.classifier==null ) {
for (int i=0; i<classifierCheckBoxes.length; i++) {
classifierCheckBoxes[i].setSelected(true);
}
return;
}
for (int i=0; i<classifierCheckBoxes.length; i++) {
classifierCheckBoxes[i].setSelected(false);
for (int j=0; j<currentParams.classifier.length; j++) {
if (ctDataSelector.getClickControl().getClassifierManager().getCurrentClassifiers().get(i).getSpeciesID()==currentParams.classifier[j]) {
classifierCheckBoxes[i].setSelected(true);
}
}
}
}
/**
* Get the parameters for the classifiers to use.
*/
private void getClassifierParams() {
currentParams.needsClassification = unclassifiedCheckBox.isSelected();
int count = 0;
for (int i=0; i<classifierCheckBoxes.length; i++) {
if (classifierCheckBoxes[i].isSelected()) {
count++;
}
}
// System.out.println("No. count: " + count);
currentParams.classifier = new int[count];
for (int i=0; i<classifierCheckBoxes.length; i++) {
if (classifierCheckBoxes[i].isSelected()) {
currentParams.classifier[i] = ctDataSelector.getClickControl().getClassifierManager().getCurrentClassifiers().get(i).getSpeciesID();
}
}
}
@Override
public JComponent getDialogComponent() {
return mainPanel;
@ -182,11 +310,17 @@ public class CTDataSelectPanel implements PamDialogPanel {
maxAngleField.setText(String.format("%.2f", Math.toDegrees(currentParams.maxAngleChange)));
maxTimeField.setText(String.format("%.2f", currentParams.maxTime/1000.));
//click train plotting
minUnitsField.setText(String.format("%d", currentParams.minSubDetections));
hasLoc.setSelected(currentParams.needsLoc);
// System.out.println("No. set classiifers: " + currentParams.classifier.length);
setClassificationPane();
}
}
/**
@ -206,6 +340,8 @@ public class CTDataSelectPanel implements PamDialogPanel {
currentParams = new CTSelectParams();
}
try {
//System.out.println("Get Params: ");
Double minTime = (Double.valueOf(minTimeField.getText())*1000.); //millis
Double maxTime = (Double.valueOf(maxTimeField.getText())*1000.); //millis
Double maxAngleChange = Double.valueOf(maxAngleField.getText());
@ -218,6 +354,11 @@ public class CTDataSelectPanel implements PamDialogPanel {
currentParams.minSubDetections = Integer.valueOf(minUnitsField.getText());
currentParams.needsLoc = hasLoc.isSelected();
// get the classifier parameters.
getClassifierParams();
//System.out.println("No. getParams classifiers: " + currentParams.classifier.length);
return true;
}
catch (Exception e) {

View File

@ -159,25 +159,25 @@ public class MHTSettingsPane extends SettingsPane<MHTParams> {
pruneStartSpinner.setEditable(true);
pruneBackSpinner.setTooltip(new Tooltip("The minimum number of detections before pruning starts."));
gridPane.add(pruneStartSpinner, 1, gridY);
gridY++;
gridY=0;
gridPane.add(new Label("Max no. coasts"), 0, gridY);
gridPane.add(new Label(" Max no. coasts"), 2, gridY);
nCoastsSpinner = new PamSpinner<Integer>(0,Integer.MAX_VALUE,3,1);
nCoastsSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
nCoastsSpinner.setPrefWidth(70);
nCoastsSpinner.setEditable(true);
nCoastsSpinner.setTooltip(new Tooltip("The maximum number of missing detections before a track is closed"));
gridPane.add(nCoastsSpinner, 1, gridY);
gridPane.add(nCoastsSpinner, 3, gridY);
gridY++;
gridPane.add(new Label("Max no. trains"), 0, gridY);
gridPane.add(new Label(" Max no. trains"), 2, gridY);
nHoldSpinner = new PamSpinner<Integer>(0,1000,3,1);
nHoldSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
nHoldSpinner.setPrefWidth(70);
nHoldSpinner.setEditable(true);
nHoldSpinner.setTooltip(new Tooltip("The maximum number of unique click trains that can be tracked at the same time."));
gridPane.add(nHoldSpinner, 1, gridY);
gridPane.add(nHoldSpinner, 3, gridY);
pamVBox.getChildren().addAll(label, gridPane);

View File

@ -447,6 +447,11 @@ public class DetectionPlotDisplay extends PamBorderPane implements UserDisplayNo
private void drawDataUnit(PamDataUnit newDataUnit) {
//Debug.out.println("DetectionPlotDisplay DrawDataUnit: " +newDataUnit);
if (currentDataInfo!=null){
//sometimes the axis just need a little push to make sure the pane and axis object bindings have been updated
for (int i=0; i<Side.values().length; i++) {
dDPlotPane.getAxisPane(Side.values()[i]).layout();
}
currentDataInfo.drawData(dDPlotPane.getPlotCanvas().getGraphicsContext2D(),
new Rectangle(0,0,dDPlotPane.getPlotCanvas().getWidth(),dDPlotPane.getPlotCanvas().getHeight()),
this.detectionPlotProjector, newDataUnit);

View File

@ -326,7 +326,7 @@ public abstract class SpectrumPlot <D extends PamDataUnit> implements Detection
}
g2.strokePolyline(scaledDataX, scaledDataY, scaledDataY.length-1);
if (fillSpectrum) {
// System.out.println("Last point: " + x0 + " y0 " + r.getHeight());
//System.out.println("Last point: " + x0 + " y0 " + y0 + " " + scale + " " + clickLineData[iChan][0] + " " + projector.getAxis(Side.LEFT).getMinVal() + " " +projector.getAxis(Side.LEFT).getTotalPixels());
scaledDataX[scaledDataX.length-1]=x0; // the last x position
scaledDataY[scaledDataY.length-1]= r.getHeight() ; //return the line to zero for polygon drawing
// PamUtils.PamArrayUtils.printArray(scaledDataY);

View File

@ -0,0 +1,88 @@
package fileOfflineData;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
/**
* Make a list of files with the given file filter.
* @author dg50
*
*/
public class OfflineFileList {
private ArrayList<File> files = new ArrayList<>();
private String folder;
private FileFilter fileFilter;
private boolean includeSubFolders;
public OfflineFileList(String folder, FileFilter fileFilter, boolean includeSubFolders) {
this.folder = folder;
this.fileFilter = fileFilter;
this.includeSubFolders = includeSubFolders;
updateCatalog();
}
public int updateCatalog() {
files.clear();
File current = new File(this.folder);
addFiles(current);
return files.size();
}
private void addFiles(File current) {
if (current.exists() == false) {
return;
}
if (current.isFile() && checkFilter(current)) {
/*
* This can only really happen if the root passed in is a file, not a
* folder, since files within the folder structure will get
* added from the loop below.
*/
files.add(current);
}
else if (current.isDirectory()) {
File[] filesList = current.listFiles();
if (filesList == null) {
return;
}
for (int i = 0; i < filesList.length; i++) {
File aFile = filesList[i];
if (aFile.isFile() && checkFilter(aFile)) {
files.add(aFile);
}
else if (aFile.isDirectory() && includeSubFolders) {
addFiles(aFile);
}
}
}
}
/**
* Check that if there is a filter, the file is accepted.
* @param aFile
* @return
*/
private boolean checkFilter(File aFile) {
if (fileFilter == null) {
return true;
}
return fileFilter.accept(aFile);
}
/**
* Get a list of files in the catalog as a simple string list.
* @return files as strings
*/
public String[] asStringList() {
if (files == null) {
return null;
}
String[] str = new String[files.size()];
for (int i = 0; i < files.size(); i++) {
str[i] = files.get(i).getAbsolutePath();
}
return str;
}
}

View File

@ -120,6 +120,9 @@ public class DatabaseBackupStream extends FileBackupStream {
public FileLocation getSourceLocation() {
File dbFile = getDatabaesFile();
if (dbFile == null) {
return null;
}
FileLocation sl = new FileLocation();
sl.path = dbFile.getAbsolutePath();
sl.canEditMask = false;

View File

@ -44,6 +44,14 @@ public abstract class AbstractPamScroller implements DataTimeLimits {
*/
protected double[] playSpeeds = {.1, 0.25, .5, 1.0, 2, 5, 10};
// private long realTimerStart;
//
// private long timerStartPosition;
private long timerLastCurrentTime;
// private long timerTimeMillis;
public AbstractPamScroller(String name, int orientation, int stepSizeMillis, long defaultLoadTime, boolean hasMenu){
@ -630,6 +638,8 @@ public abstract class AbstractPamScroller implements DataTimeLimits {
playTimerAction();
}
});
timerLastCurrentTime = System.currentTimeMillis();
// timeLastValue = getValueMillis();
playTimer.start();
playbackStarted();
}
@ -671,11 +681,17 @@ public abstract class AbstractPamScroller implements DataTimeLimits {
stopPlayback();
return;
}
long step = Math.max((long) (timerInterval * scrollerData.getPlaySpeed()), 1);
setValueMillis(pos+step);
if (pos == getValueMillis()) {
playTimer.setDelay(playTimer.getDelay()*2);
}
/**
* Since the action on setValue can take quite some time, the timer can run slow
* if we just increment by what we think this delay is, so increment the value
* based on how much system time has elapsed between the last call and now
*/
long now = System.currentTimeMillis();
int elapsed = (int) (now - timerLastCurrentTime);
int toAdd = (int) (elapsed*scrollerData.getPlaySpeed());
timerLastCurrentTime = now;
setValueMillis(getValueMillis()+toAdd);
}
}

View File

@ -93,7 +93,7 @@ public class PamAxisPane2 extends StackPane {
this.getChildren().add(mainPane);
}
private void layoutAxis(){
public void layoutAxis(){
mainPane.setCenter(null);

View File

@ -1,7 +1,6 @@
package pamViewFX.fxNodes.utilityPanes;
import java.io.Serializable;
import javafx.geometry.Pos;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;

View File

@ -3,12 +3,10 @@ package spectrogramNoiseReduction.layoutFX;
import java.util.ArrayList;
import org.controlsfx.control.ToggleSwitch;
import pamViewFX.PamGuiManagerFX;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.PamVBox;
import pamViewFX.fxNodes.utilityPanes.PamToggleSwitch;
import pamViewFX.fxNodes.utilityPanes.SourcePaneFX;
import spectrogramNoiseReduction.SpecNoiseMethod;
import spectrogramNoiseReduction.SpectrogramNoiseProcess;
@ -16,10 +14,8 @@ import spectrogramNoiseReduction.SpectrogramNoiseSettings;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.Pane;
import PamController.SettingsPane;
import PamguardMVC.PamDataBlock;
@ -39,7 +35,7 @@ public class SpectrogramNoisePaneFX extends SettingsPane<SpectrogramNoiseSetting
private SpectrogramNoiseSettings spectrogramNoiseSettings=new SpectrogramNoiseSettings();
private ToggleSwitch[] enableMethod;
private PamToggleSwitch[] enableMethod;
private PamDataBlock dataSource;
@ -58,7 +54,7 @@ public class SpectrogramNoisePaneFX extends SettingsPane<SpectrogramNoiseSetting
PamVBox methodPane;
SpecNoiseNodeFX dC;
Node node;
enableMethod = new ToggleSwitch[methods.size()];
enableMethod = new PamToggleSwitch[methods.size()];
for (int i = 0; i < methods.size(); i++) {
@ -66,13 +62,14 @@ public class SpectrogramNoisePaneFX extends SettingsPane<SpectrogramNoiseSetting
methodPane.setSpacing(10);
//create name
Label title=new Label(methods.get(i).getName());
PamGuiManagerFX.titleFont2style(title);
// title.setFont(PamGuiManagerFX.titleFontSize2);
PamHBox toggleHolder = new PamHBox();
toggleHolder.setSpacing(5);
toggleHolder.getChildren().addAll(enableMethod[i] =
new ToggleSwitch(), title);
new PamToggleSwitch(methods.get(i).getName()));
PamGuiManagerFX.titleFont2style(enableMethod[i].getLabel());
enableMethod[i].setAlignment(Pos.CENTER_LEFT);
toggleHolder.setAlignment(Pos.CENTER_LEFT);