Click trian detector fixes (#48)

* 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.

* Bug fix and improvements for Ketos

Ketos models now automatically set the correct sample length when loaded.

Bug fix for the TDisplayFX - null pointer exception if no class names loaded and sorted recently introduced bug in drawing predictions.

* Updates to deep learning and FX GUI

Added some more example sounds to deep learning UI.

Updated click detector in the FX GUI.

* PAMGuard FX sound output update

* Updates to FX GUI

* Updates to FX GUI

* Update RawDataTransforms.java

* Fixes to FX UI

* Squashed commit of the following:

commit 11ba8bf91e
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Thu Aug 4 11:45:47 2022 +0100

    MErge from DG Branch (#47)

    * Variable sound output level

    Mods to SoundPlayback module to allow additional parameters. Implemented
    system for NI cards to allow changes to selected output voltage range
    meaning output can be boosted to level higher than current default.

    * Code to support nogui operations when no screens present on headless
    system

    * Fix problem of nogui headless operation trying to access screen size.

    * Click detector display fixes

    1. ICI not displaying correctly
    2. Component sizes in display dialog on hres monitors

    * Work on batch processing, after testing of options to autostart,
    autoexit and set wav file folder, database and binary store.

    * Update MHTClickTrainAlgorithm.java

    Fix unsynchronised access to a datablock in click train detector which was causing index errors.

    * Revamp of offline process messaging and control

    Includes some databsae logging of completed tasks

    * Offline task logging

    Bit more work, including notes and database storage of task
    reprocessing. Guess this could all become 'proper' PAMGuard data and be
    shown in a table on the display but that not priority enough.

    * Dialog packing

    Fix a couple of dialogs which don't back well on HDPI monitors

    * UDP Control

    Added multiport functionality

commit 9a9f542d95
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Thu Aug 4 11:42:45 2022 +0100

    Merge DG to Main (#46)

    * Variable sound output level

    Mods to SoundPlayback module to allow additional parameters. Implemented
    system for NI cards to allow changes to selected output voltage range
    meaning output can be boosted to level higher than current default.

    * Code to support nogui operations when no screens present on headless
    system

    * Fix problem of nogui headless operation trying to access screen size.

    * Click detector display fixes

    1. ICI not displaying correctly
    2. Component sizes in display dialog on hres monitors

    * Work on batch processing, after testing of options to autostart,
    autoexit and set wav file folder, database and binary store.

    * Update MHTClickTrainAlgorithm.java

    Fix unsynchronised access to a datablock in click train detector which was causing index errors.

    * Revamp of offline process messaging and control

    Includes some databsae logging of completed tasks

    * Offline task logging

    Bit more work, including notes and database storage of task
    reprocessing. Guess this could all become 'proper' PAMGuard data and be
    shown in a table on the display but that not priority enough.

    * Dialog packing

    Fix a couple of dialogs which don't back well on HDPI monitors

    * UDP Control

    Added multiport functionality

commit 49cd547aee
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Thu Aug 4 11:40:29 2022 +0100

    Merge DG branch (#45)

    * Variable sound output level

    Mods to SoundPlayback module to allow additional parameters. Implemented
    system for NI cards to allow changes to selected output voltage range
    meaning output can be boosted to level higher than current default.

    * Code to support nogui operations when no screens present on headless
    system

    * Fix problem of nogui headless operation trying to access screen size.

    * Click detector display fixes

    1. ICI not displaying correctly
    2. Component sizes in display dialog on hres monitors

    * Work on batch processing, after testing of options to autostart,
    autoexit and set wav file folder, database and binary store.

    * Update MHTClickTrainAlgorithm.java

    Fix unsynchronised access to a datablock in click train detector which was causing index errors.

    * Revamp of offline process messaging and control

    Includes some databsae logging of completed tasks

    * Offline task logging

    Bit more work, including notes and database storage of task
    reprocessing. Guess this could all become 'proper' PAMGuard data and be
    shown in a table on the display but that not priority enough.

    * Dialog packing

    Fix a couple of dialogs which don't back well on HDPI monitors

    * UDP Control

    Added multiport functionality

commit 016cfd0da5
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Thu Aug 4 11:35:06 2022 +0100

    Dialog positioning

    New functions to better positions dialogs on screen

commit c9f2ab3e97
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Mon Aug 1 11:13:24 2022 +0100

    puch to main (#44)

    * Variable sound output level

    Mods to SoundPlayback module to allow additional parameters. Implemented
    system for NI cards to allow changes to selected output voltage range
    meaning output can be boosted to level higher than current default.

    * Code to support nogui operations when no screens present on headless
    system

    * Fix problem of nogui headless operation trying to access screen size.

    * Click detector display fixes

    1. ICI not displaying correctly
    2. Component sizes in display dialog on hres monitors

    * Work on batch processing, after testing of options to autostart,
    autoexit and set wav file folder, database and binary store.

    * Update MHTClickTrainAlgorithm.java

    Fix unsynchronised access to a datablock in click train detector which was causing index errors.

    * Revamp of offline process messaging and control

    Includes some databsae logging of completed tasks

    * Offline task logging

    Bit more work, including notes and database storage of task
    reprocessing. Guess this could all become 'proper' PAMGuard data and be
    shown in a table on the display but that not priority enough.

    * Dialog packing

    Fix a couple of dialogs which don't back well on HDPI monitors

commit 55f5a3fcf1
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Mon Aug 1 10:59:36 2022 +0100

    Group detections menu

    Small changes to limit the number of menu items in "Add to existing
    group" to a maximum of 25 entries.

commit b3f6c0e665
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Fri Jul 29 10:50:45 2022 +0100

    Handle -nogui option in PamWorker

    PamWorker used to catalog files at startup (if a file folder input
    system is used). This creates a progress dialog. Stop it appearing in
    -nogui operations.

commit 8569b6b579
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Fri Jul 22 08:30:47 2022 +0100

    Click display fixes (#41)

    * Variable sound output level

    Mods to SoundPlayback module to allow additional parameters. Implemented
    system for NI cards to allow changes to selected output voltage range
    meaning output can be boosted to level higher than current default.

    * Code to support nogui operations when no screens present on headless
    system

    * Fix problem of nogui headless operation trying to access screen size.

    * Click detector display fixes

    1. ICI not displaying correctly
    2. Component sizes in display dialog on hres monitors

commit 128a512ff6
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Tue Jul 19 16:37:57 2022 +0100

    Another attempt at stopping it crashing on a headless system

    Dealing with displays that get created for clickangle vetos and a call
    to the gui in the click train detector.

commit 6eaa6e4978
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Tue Jul 19 08:20:07 2022 +0100

    nogoi fix for headless systems. (#40)

    * Variable sound output level

    Mods to SoundPlayback module to allow additional parameters. Implemented
    system for NI cards to allow changes to selected output voltage range
    meaning output can be boosted to level higher than current default.

    * Code to support nogui operations when no screens present on headless
    system

    * Fix problem of nogui headless operation trying to access screen size.

commit 9fdd30556b
Author: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date:   Tue Jul 12 15:53:07 2022 +0100

    Variable sound output level (#39)

    Mods to SoundPlayback module to allow additional parameters. Implemented
    system for NI cards to allow changes to selected output voltage range
    meaning output can be boosted to level higher than current default.

* Bug fixes to click train detector

Fixed bug with number of coasts in the MHT Kernel
Added an option for amplitude to have a maximum
Removed print statements.

Co-authored-by: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
This commit is contained in:
Jamie Mac 2022-08-08 10:32:19 +01:00 committed by GitHub
parent b4bdae94ca
commit ef0330173b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
77 changed files with 1869 additions and 462 deletions

View File

@ -1,7 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
<classpathentry including="**/*.java" kind="src" output="target/classes" path="src">
<attributes>
<attribute name="optional" value="true"/>
<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/AdoptOpenJDK 16">
<attributes>
<attribute name="module" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
@ -10,11 +17,5 @@
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry including="**/*.java" kind="src" output="target/classes" path="src">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

View File

@ -26,6 +26,7 @@ import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.PamTextField;
import pamViewFX.fxNodes.PamVBox;
import pamViewFX.fxNodes.flipPane.FlipPane;
import pamViewFX.fxNodes.flipPane.PamFlipPane;
import Acquisition.AcquisitionControl;
import Acquisition.AcquisitionParameters;
import Acquisition.ChannelListPanel;
@ -153,7 +154,7 @@ public class AcquisitionPaneFX extends SettingsPane<AcquisitionParameters>{
//create the flip pane.
flipPane=new FlipPane();
flipPane.setFlipDirection(Orientation.HORIZONTAL);
flipPane.setFlipTime(250); //default is 700ms- way too high
flipPane.setFlipTime(PamFlipPane.FLIP_TIME); //default is 700ms- way too high
//flipPane.prefWidthProperty().bind(mainPane.widthProperty());
if (aquisitionControl.isViewer()){

View File

@ -0,0 +1,136 @@
package PamController;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.paint.Color;
import pamViewFX.PamGuiManagerFX;
import pamViewFX.fxGlyphs.PamGlyphDude;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamButton;
import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.flipPane.FlipPane;
/**
* A pane which can flip to show another pane (referred to as the advanced settings pane).
* @author Jamie Macaulay
*
* @param <T>
*/
public abstract class FlipSettingsPane<T> extends SettingsPane<T> {
/**
* The holder pane.
*/
private FlipPane flipPane;
/**
* The label at the top of the advanced pane.
*/
private Label advLabel;
/**
* The advanced pane.
*/
private PamBorderPane advPane;
/**
* The button which flips back to the front pane.
*/
private PamButton backButton;
public FlipSettingsPane(Object ownerWindow) {
super(ownerWindow);
flipPane = new FlipPane();
flipPane.setFlipTime(200);
this.advPane = createAdvSettingsPane() ;
flipPane.getBack().getChildren().add(advPane);
}
@Override
public Node getContentNode() {
flipPane.getFront().getChildren().clear();
flipPane.getFront().getChildren().add(getFrontContentNode());
return flipPane;
}
/**
* Flip the pane to show the advanced settings pane.
*/
public void flipToBack() {
flipPane.flipToBack();
}
/**
* Flip the pane to show the primary pane.
*/
public void flipToFront() {
flipPane.flipToBack();
}
/**
* Set the contents of the advanced pane.
* @param contentNode - the content to set.
*/
public void setAdvPaneContents(Node contentNode) {
this.advPane.setCenter(contentNode);
}
/**
* Get the content node for the flip pane.
* @return
*/
public abstract Pane getFrontContentNode();
/**
* Create the advanced settings pane which can be accessed by DAQ panes if needed.
*/
private PamBorderPane createAdvSettingsPane() {
backButton = new PamButton();
backButton.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-left", Color.WHITE, PamGuiManagerFX.iconSize));
backButton.setOnAction((action)->{
flipPane.flipToFront();
});
PamBorderPane advPane = new PamBorderPane();
//advPane.setPadding(new Insets(5,5,5,5));
PamHBox buttonHolder = new PamHBox();
buttonHolder.setBackground(null);
//buttonHolder.setStyle("-fx-background-color: red;");
buttonHolder.setAlignment(Pos.CENTER_LEFT);
buttonHolder.getChildren().addAll(backButton, advLabel = new Label("Adv. Settings"));
advLabel.setAlignment(Pos.CENTER);
advLabel.setMaxWidth(Double.MAX_VALUE); //need to make sure label is in center.
PamGuiManagerFX.titleFont2style(advLabel);
advLabel.setAlignment(Pos.CENTER);
HBox.setHgrow(advLabel, Priority.ALWAYS);
advPane.setTop(buttonHolder);
return advPane;
}
public PamBorderPane getAdvPane() {
return advPane;
}
}

View File

@ -17,7 +17,7 @@ public abstract class PamControlledUnitGUI {
public abstract int getGUIFlag();
/**
* Allows the GUI to be notified of changes, e.g. in the PAMControlle.r
* Allows the GUI to be notified of changes, e.g. in the PAMController
* @param flag - the change flag.
*/
public void notifyGUIChange(int flag) {

View File

@ -40,7 +40,7 @@ public abstract class SettingsPane<T> {
public abstract String getName();
/**
* Get node for GUI chnage of settings.
* Get node for GUI change of settings.
*/
public abstract Node getContentNode();

View File

@ -6,6 +6,7 @@ import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Collection;
@ -62,7 +63,7 @@ public class TxtFileUtils {
boolean isNaN=false;
for (String line : lines) {
System.out.println(line);
//System.out.println(line);
String[] recordsOnLine = line.split(delimeter);
@ -82,11 +83,15 @@ public class TxtFileUtils {
// //This was causing isses with some numbers with e-06...dunno why so switched to parse double
// String input = new String(recordsOnLine[i].toCharArray());
// //System.out.println(input);
// System.out.println("|" + recordsOnLine[i] + "|");
// dat = nF.parse(input).doubleValue();
dat = Double.parseDouble(recordsOnLine[i]);
//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.]", ""));
dat = Double.valueOf(number);
//dat = DecimalFormat.getNumberInstance().parse(new String(recordsOnLine[i].strip().toCharArray())).doubleValue();
}
catch (Exception e){
e.printStackTrace();

View File

@ -99,6 +99,7 @@ public class RawDataTransforms {
*/
private int shortestFFTLength;
private Object synchObject;
/**
@ -187,31 +188,29 @@ public class RawDataTransforms {
* @param fftLength
* @return Power spectrum
*/
public double[] getPowerSpectrum(int channel, int fftLength) {
synchronized (synchObject) {
if (powerSpectra == null) {
powerSpectra = new double[PamUtils.getNumChannels(dataUnit.getChannelBitmap())][];
}
if (fftLength == 0) {
fftLength = getCurrentSpectrumLength();
}
if (powerSpectra[channel] == null
|| powerSpectra[channel].length != fftLength / 2) {
ComplexArray cData = getComplexSpectrumHann(channel, fftLength);
currentSpecLen = fftLength;
powerSpectra[channel] = cData.magsq();
if (powerSpectra==null){
System.err.println("DLDetection: could not calculate power spectra");
return null;
}
if (powerSpectra[channel].length != fftLength/2) {
powerSpectra[channel] = Arrays.copyOf(powerSpectra[channel], fftLength/2);
}
}
return powerSpectra[channel];
public synchronized double[] getPowerSpectrum(int channel, int fftLength) {
if (powerSpectra == null) {
powerSpectra = new double[PamUtils.getNumChannels(dataUnit.getChannelBitmap())][];
}
if (fftLength == 0) {
fftLength = getCurrentSpectrumLength();
}
if (powerSpectra[channel] == null
|| powerSpectra[channel].length != fftLength / 2) {
ComplexArray cData = getComplexSpectrumHann(channel, fftLength);
currentSpecLen = fftLength;
powerSpectra[channel] = cData.magsq();
if (powerSpectra==null){
System.err.println("DLDetection: could not calculate power spectra");
return null;
}
if (powerSpectra[channel].length != fftLength/2) {
powerSpectra[channel] = Arrays.copyOf(powerSpectra[channel], fftLength/2);
}
}
return powerSpectra[channel];
}
@ -221,27 +220,25 @@ public class RawDataTransforms {
* @param fftLength
* @return Sum of power spectra
*/
public double[] getTotalPowerSpectrum(int fftLength) {
synchronized (synchObject) {
if (fftLength == 0) {
fftLength = getCurrentSpectrumLength();
}
if (fftLength == 0) {
fftLength = PamUtils.getMinFftLength(getSampleDuration());
}
double[] ps;
if (totalPowerSpectrum == null
|| totalPowerSpectrum.length != fftLength / 2) {
totalPowerSpectrum = new double[fftLength / 2];
for (int c = 0; c < PamUtils.getNumChannels(this.dataUnit.getChannelBitmap()); c++) {
ps = getPowerSpectrum(c, fftLength);
for (int i = 0; i < fftLength / 2; i++) {
totalPowerSpectrum[i] += ps[i];
}
public synchronized double[] getTotalPowerSpectrum(int fftLength) {
if (fftLength == 0) {
fftLength = getCurrentSpectrumLength();
}
if (fftLength == 0) {
fftLength = PamUtils.getMinFftLength(getSampleDuration());
}
double[] ps;
if (totalPowerSpectrum == null
|| totalPowerSpectrum.length != fftLength / 2) {
totalPowerSpectrum = new double[fftLength / 2];
for (int c = 0; c < PamUtils.getNumChannels(this.dataUnit.getChannelBitmap()); c++) {
ps = getPowerSpectrum(c, fftLength);
for (int i = 0; i < fftLength / 2; i++) {
totalPowerSpectrum[i] += ps[i];
}
}
return totalPowerSpectrum;
}
return totalPowerSpectrum;
}
@ -256,17 +253,15 @@ 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) {
complexSpectrum = new ComplexArray[PamUtils.getNumChannels(dataUnit.getChannelBitmap())];
if (complexSpectrum[channel] == null
|| complexSpectrum.length != fftLength / 2) {
public synchronized ComplexArray getComplexSpectrumHann(int channel, int fftLength) {
complexSpectrum = new ComplexArray[PamUtils.getNumChannels(dataUnit.getChannelBitmap())];
if (complexSpectrum[channel] == null
|| complexSpectrum.length != fftLength / 2) {
complexSpectrum[channel] = getComplexSpectrumHann(rawData.getWaveData()[channel], fftLength);
currentSpecLen = fftLength;
}
return complexSpectrum[channel];
complexSpectrum[channel] = getComplexSpectrumHann(rawData.getWaveData()[channel], fftLength);
currentSpecLen = fftLength;
}
return complexSpectrum[channel];
}
@ -394,31 +389,29 @@ public class RawDataTransforms {
* @param fftLength
* @return the complex spectrum
*/
public ComplexArray getComplexSpectrum(int channel, int fftLength) {
synchronized (synchObject) {
double[] paddedRawData;
double[] rawData;
int i, mn;
public synchronized ComplexArray getComplexSpectrum(int channel, int fftLength) {
double[] paddedRawData;
double[] rawData;
int i, mn;
if (complexSpectrum == null) {
complexSpectrum = new ComplexArray[getNChan()];
}
if (complexSpectrum[channel] == null
|| complexSpectrum.length != fftLength / 2) {
paddedRawData = new double[fftLength];
rawData = getWaveData(channel);
//double[] rotData = getRotationCorrection(channel);
mn = Math.min(fftLength, getSampleDuration().intValue());
for (i = 0; i < mn; i++) {
paddedRawData[i] = rawData[i];//-rotData[i];
}
for (i = mn; i < fftLength; i++) {
paddedRawData[i] = 0;
}
complexSpectrum[channel] = fastFFT.rfft(paddedRawData, fftLength);
}
return complexSpectrum[channel];
if (complexSpectrum == null) {
complexSpectrum = new ComplexArray[getNChan()];
}
if (complexSpectrum[channel] == null
|| complexSpectrum.length != fftLength / 2) {
paddedRawData = new double[fftLength];
rawData = getWaveData(channel);
//double[] rotData = getRotationCorrection(channel);
mn = Math.min(fftLength, getSampleDuration().intValue());
for (i = 0; i < mn; i++) {
paddedRawData[i] = rawData[i];//-rotData[i];
}
for (i = mn; i < fftLength; i++) {
paddedRawData[i] = 0;
}
complexSpectrum[channel] = fastFFT.rfft(paddedRawData, fftLength);
}
return complexSpectrum[channel];
}
@ -427,16 +420,14 @@ public class RawDataTransforms {
* @param iChan channel index
* @return analytic waveform
*/
public double[] getAnalyticWaveform(int iChan) {
synchronized (synchObject) {
if (analyticWaveform == null) {
analyticWaveform = new double[getNChan()][];
}
// if (analyticWaveform[iChan] == null) {
analyticWaveform[iChan] = hilbert.getHilbert(getWaveData(iChan));
// }
return analyticWaveform[iChan];
public synchronized double[] getAnalyticWaveform(int iChan) {
if (analyticWaveform == null) {
analyticWaveform = new double[getNChan()][];
}
// if (analyticWaveform[iChan] == null) {
analyticWaveform[iChan] = hilbert.getHilbert(getWaveData(iChan));
// }
return analyticWaveform[iChan];
}
/**
@ -448,14 +439,12 @@ public class RawDataTransforms {
* @param fftFilterParams fft filter parameters.
* @return analystic waveform.
*/
public double[] getAnalyticWaveform(int iChan, boolean filtered, FFTFilterParams fftFilterParams) {
synchronized (synchObject) {
if (filtered == false || fftFilterParams == null) {
return getAnalyticWaveform(iChan);
}
else {
return getFilteredAnalyticWaveform(fftFilterParams, iChan);
}
public synchronized double[] getAnalyticWaveform(int iChan, boolean filtered, FFTFilterParams fftFilterParams) {
if (filtered == false || fftFilterParams == null) {
return getAnalyticWaveform(iChan);
}
else {
return getFilteredAnalyticWaveform(fftFilterParams, iChan);
}
}
@ -466,6 +455,7 @@ public class RawDataTransforms {
* @param iChan channel number
* @return envelope of the filtered data.
*/
public double[] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams, int iChan) {
synchronized (synchObject) {
if (analyticWaveform == null) {
@ -509,6 +499,7 @@ public class RawDataTransforms {
* @param channelIndex channel index
* @return filtered waveform data
*/
public double[] getFilteredWaveData(FFTFilterParams filterParams, int channelIndex) {
synchronized (synchObject) {
filteredWaveData = getFilteredWaveData(filterParams);
@ -522,6 +513,7 @@ public class RawDataTransforms {
* @param filterParams filter parameters
* @return array of filtered data
*/
public double[][] getFilteredWaveData(FFTFilterParams filterParams) {
synchronized (synchObject) {
//System.out.println("Make filterred wave data!: " + (filterParams != oldFFTFilterParams));

View File

@ -638,4 +638,24 @@
#module-pane .ikonli-font-icon {
-fx-icon-color: black;
}
/*******************************************************************************
* *
* Custom slider for volume controls *
* *
******************************************************************************/
#thickslider .track {
-fx-pref-height:14;
-fx-background-radius: 8;
}
#thickslider:vertical .track {
-fx-pref-width:12;
-fx-background-radius: 8;
}
#thickslider .thumb {
-fx-pref-height: 14;
-fx-pref-width: 14;
}

Binary file not shown.

Binary file not shown.

View File

@ -24,6 +24,7 @@ import clickDetector.ClickClassifiers.ClickIdentifier;
import clickDetector.ClickClassifiers.ClickTypeCommonParams;
import clickDetector.ClickClassifiers.basic.BasicClickIdentifier;
import clickDetector.layoutFX.clickClassifiers.ClassifyPaneFX;
import clickDetector.layoutFX.clickClassifiers.SweepClassifierPaneFX;
/**
* An improvements on the BasicClickIdentifier based on work by
@ -44,6 +45,9 @@ public class SweepClassifier implements ClickIdentifier , PamSettings {
private SweepClassifierPanel dialogPanel;
private SweepClassifierPaneFX fxPane;
private SweepClassifierWorker sweepClassifierWorker;
protected SweepClassifierParameters sweepClassifierParameters = new SweepClassifierParameters();
@ -408,8 +412,8 @@ public class SweepClassifier implements ClickIdentifier , PamSettings {
@Override
public ClassifyPaneFX getClassifierPane() {
// TODO Auto-generated method stub
return null;
if (fxPane==null) fxPane = new SweepClassifierPaneFX(this, clickControl);
return fxPane;
}
@Override

View File

@ -194,8 +194,8 @@ public class ClickDelayPane extends SettingsPane<ClickParameters> {
public ClickParameters getParams(ClickParameters clickParameters) {
if (clickParameters==null) return null;
if (delayParams[0] == null) {
return null;
if (delayParams==null || delayParams[0] == null) {
return clickParameters;
}
clickParameters.setDelayMeasurementParams(0, delayParams[0]);
for (int i = 1; i < typesList.length; i++) {

View File

@ -6,6 +6,7 @@ import java.text.ParseException;
import clickDetector.ClickControl;
import clickDetector.ClickParameters;
import clickDetector.layoutFX.clickClassifiers.ClickClassifyPaneFX;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.CheckBox;
@ -13,6 +14,7 @@ import javafx.scene.control.Label;
import javafx.scene.control.Spinner;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.paint.Color;
@ -41,6 +43,8 @@ import pamViewFX.fxNodes.utilityPanes.GroupedSourcePaneFX;
* @author Jamie Macaulay
*/
public class ClickSettingsPane extends SettingsPane<ClickParameters>{
public static double PREF_SPINNER_WIDTH = 100;
/**
* Group source pane for the click settings pane.
@ -158,7 +162,7 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
/**
* The default pane width
*/
public static double paneWidth=1050;
public static double paneWidth=500;
/**
* The default pane height.
@ -180,22 +184,17 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
pamTabbedPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
//create a combined detection and length pane
PamHBox detectionPane=new PamHBox();
PamVBox detectionPane=new PamVBox();
detectionPane.setSpacing(20);
detectionPane.getChildren().add(createClickDetectionPane());
//create a dividing line.
Line line=new Line(0,20,0,0);
line.startYProperty().bind(sourcePane.layoutYProperty().add(20));
line.endYProperty().bind(detectionPane.heightProperty().subtract(20));
line.setStroke(Color.WHITE);
line.setStrokeWidth(2);
PamHBox lineHolder=new PamHBox();
lineHolder.getChildren().add(line);
lineHolder.setAlignment(Pos.CENTER);
detectionPane.getChildren().add(lineHolder);
PamVBox holder=new PamVBox();
PamHBox holder=new PamHBox();
holder.setSpacing(20);
holder.getChildren().addAll(createClickLengthPane(), createClickTriggerPane());
detectionPane.getChildren().add(holder);
detectionPane.getChildren().add(createTriggerGraph());
//add everything to tabs.
pamTabbedPane.getTabs().add(new Tab("Click Detection", detectionPane));
@ -211,11 +210,11 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
//pre filter pane.
preFilter=new FilterPaneFX();
preFilter=new FilterPaneFX(Orientation.VERTICAL);
pamTabbedPane.getTabs().add(new Tab("Pre Filter", preFilter.getContentNode()));
//trigger pane
triggerFilter=new FilterPaneFX();
triggerFilter=new FilterPaneFX(Orientation.VERTICAL);
pamTabbedPane.getTabs().add(new Tab("Trigger Filter", triggerFilter.getContentNode()));
//echo detection pane.
@ -268,12 +267,16 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
//channels, groups and trigger are all in one pane to make it easy not to make mistakes
sourcePane=createClickSourcePane(); //create the source pane.
GridPane.setColumnSpan(sourcePane.getDataBlockBox(), 4);
//now create trigger pane. The trigger pane is added to the source pane.
Label triggerLabel = new Label("Trigger Channels");
PamGuiManagerFX.titleFont2style(triggerLabel);
sourcePane.getSourcePane().add(triggerLabel,1,2);
sourcePane.getSourcePane().add(triggerChannels=new Pane(),1,3);
triggerChannels=new Pane();
sourcePane.getSourcePane().add(triggerChannels,1,3);
createTriggerChannels();
//sourcePane.getSourcePane().add(createClickTriggerPane(), 2, 3);
@ -282,6 +285,7 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
// pamTabbedPane.getTabs().add(new Tab("Click Echoes", createEchoPane()));
// pamTabbedPane.getTabs().add(new Tab("Click Delays", createDelayPane()));
sourcePane.setPrefWidth(paneWidth);
return sourcePane;
}
@ -299,33 +303,41 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
lengthPane.setVgap(5);
lengthPane.setHgap(5);
lengthPane.add(new Label("Min click separation"),0,0);
lengthPane.add(new Label("Min separation"),0,0);
minClickSep=new PamSpinner<Integer>(0, 10000000, 100, 20);
minClickSep.setEditable(true);
minClickSep.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
minClickSep.setPrefWidth(PREF_SPINNER_WIDTH);
lengthPane.add(minClickSep,1,0);
lengthPane.add(new Label("samples"),2,0);
lengthPane.add(new Label("Max click length"),0,1);
lengthPane.add(new Label("Max length"),0,1);
maxClickLength=new PamSpinner<Integer>(0, 10000000, 100, 20);
maxClickLength.setEditable(true);
maxClickLength.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
maxClickLength.setPrefWidth(PREF_SPINNER_WIDTH);
lengthPane.add(maxClickLength,1,1);
lengthPane.add(new Label("samples"),2,1);
lengthPane.add(new Label("pre samples"),0,2);
lengthPane.add(new Label("Pre samples"),0,2);
preSampleSpinner=new PamSpinner<Integer>(0, 10000000, 100, 20);
preSampleSpinner.setEditable(true);
preSampleSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
preSampleSpinner.setPrefWidth(PREF_SPINNER_WIDTH);
lengthPane.add(preSampleSpinner,1,2);
lengthPane.add(new Label("samples"),2,2);
lengthPane.add(new Label("pre samples"),0,3);
lengthPane.add(new Label("Post samples"),0,3);
postSampleSpinner=new PamSpinner<Integer>(0, 10000000, 100, 20);
postSampleSpinner.setEditable(true);
postSampleSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
postSampleSpinner.setPrefWidth(PREF_SPINNER_WIDTH);
lengthPane.add(postSampleSpinner,1,3);
lengthPane.add(new Label("samples"),2,3);
@ -398,6 +410,7 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
});
triggerBox.add(threshold,1,0);
triggerBox.add(new Label("dB"),2,0);
threshold.setPrefWidth(PREF_SPINNER_WIDTH);
triggerBox.add(new Label("Long Filter"),0,1);
longFilter=new PamSpinner<Double>(0.0000001, 0.1, 0.000001, 0.000001);
@ -410,6 +423,7 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
clickTriggerGraph.updateWaveformGraph(this.clickParameters);
});
triggerBox.add(longFilter,1,1);
longFilter.setPrefWidth(PREF_SPINNER_WIDTH);
triggerBox.add(new Label("Long Filter 2"),0,2);
longFilter2=new PamSpinner<Double>(0.0000001, 0.1, 0.000001, 0.000001);
@ -419,6 +433,7 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
longFilter2.getValueFactory().valueProperty().addListener((obs, before, after)->{
clickParameters.longFilter2=after;
});
longFilter2.setPrefWidth(PREF_SPINNER_WIDTH);
triggerBox.add(longFilter2,1,2);
triggerBox.add(new Label("Short Filter"),0,3);
@ -431,25 +446,33 @@ public class ClickSettingsPane extends SettingsPane<ClickParameters>{
clickTriggerGraph.setShortFilter(clickParameters.shortFilter);
clickTriggerGraph.updateWaveformGraph(this.clickParameters);
});
shortFilter.setPrefWidth(PREF_SPINNER_WIDTH);
triggerBox.add(shortFilter,1,3);
triggerPane.add(triggerBox,0,1);
//trigger graph
Label graphLabel = new Label("Filter Graph");
PamGuiManagerFX.titleFont2style(graphLabel);
triggerPane.add(graphLabel,0,2);
clickTriggerGraph=new ClickTriggerGraph();
PamGridPane.setHgrow(clickTriggerGraph, Priority.ALWAYS);
PamGridPane.setVgrow(clickTriggerGraph, Priority.ALWAYS);
triggerPane.add(clickTriggerGraph,0,3);
//triggerPane.setGridLinesVisible(true);
return triggerPane;
}
private Pane createTriggerGraph() {
//trigger graph
Label graphLabel = new Label("Filter Graph");
PamGuiManagerFX.titleFont2style(graphLabel);
clickTriggerGraph=new ClickTriggerGraph();
PamGridPane.setHgrow(clickTriggerGraph, Priority.ALWAYS);
PamGridPane.setVgrow(clickTriggerGraph, Priority.ALWAYS);
PamVBox triggerGraph = new PamVBox();
triggerGraph.setSpacing(5);
triggerGraph.getChildren().addAll(graphLabel, clickTriggerGraph);
return triggerGraph;
}
/**
* Unselect all trigger channels

View File

@ -19,6 +19,9 @@ import simulatedAcquisition.sounds.SimSignal;
public class ClickTriggerGraph extends PamBorderPane {
public final static int PORPOISE_CLICK=0;
public final static int SPERM_WHALE=1;
private int currentClick=PORPOISE_CLICK;
@ -44,11 +47,15 @@ public class ClickTriggerGraph extends PamBorderPane {
private LineChart<Number, Number> plotChart;
private int freq2;
private double[] waveform;
public ClickTriggerGraph(){
this.setCenter(createWaveformGraph());
this.setPrefWidth(500);
this.setPrefWidth(400);
//FIXME - seems to a resize bug in high DPI displays. Seems fixed in 8u60.
this.waveform=generateClickWaveform(currentClick, noise);
}
/**
@ -67,7 +74,6 @@ public class ClickTriggerGraph extends PamBorderPane {
Series<Number, Number> noiseLevelSeries = new Series<Number, Number>();
double[] waveform=generateClickWaveform(currentClick, noise);
double[] signalLevel=calcFilter(waveform, shortFilter);
double[] noiseLevel=calcFilter(waveform, longFilter);
@ -111,6 +117,10 @@ public class ClickTriggerGraph extends PamBorderPane {
clickSound=new ClickSound("Porpoise", freq=140000, freq2=140000, length=0.00015, WINDOWTYPE.HANN);
sR=500000;
break;
case SPERM_WHALE:
clickSound=(new ClickSound("Beaked Whale", 30000, 60000, length = 0.3e-3, WINDOWTYPE.HANN));
sR=192000;
break;
default:
clickSound=new ClickSound("Porpoise", freq=140000, freq2=140000, length=0.00015, WINDOWTYPE.HANN);
sR=500000;

View File

@ -1,17 +1,15 @@
package clickDetector.layoutFX.clickClassifiers;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.hidingPane.HidingPane;
import pamViewFX.fxNodes.flipPane.PamFlipPane;
import pamViewFX.fxNodes.table.TableSettingsPane;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.Dialog;
import javafx.scene.control.TableColumn;
import javafx.scene.control.cell.CheckBoxTableCell;
import javafx.scene.paint.Color;
import clickDetector.BasicClickIdParameters;
import clickDetector.ClickControl;
import clickDetector.ClickTypeParams;
@ -40,10 +38,10 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX {
*/
private TableSettingsPane<ClickTypeProperty> settingsPane;
/**
* Hiding pane which slides out to allow users to change click type settings.
*/
protected HidingPane hidingPane;
// /**
// * Hiding pane which slides out to allow users to change click type settings.
// */
// protected HidingPane hidingPane;
/**
* Holds click classifier controls inside hiding pane.
@ -62,10 +60,10 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX {
*/
protected PamBorderPane mainHolderPane;
/**
* The width of the hiding pane
*/
private double hidingPaneWidth=900;
// /**
// * The width of the hiding pane
// */
// private double hidingPaneWidth=900;
/**
* Cloned copy of BasicClickIdParameters.
@ -73,10 +71,12 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX {
private BasicClickIdParameters basicClickIdParameters;
private PamBorderPane mainPane;
private PamFlipPane flipPane;
/**
* Create a BasicClickIdParameters pane which allows users to add multiple basic click identifiers to the PAMGuard click classifier.
* @param basicClickIdentifier - the ClickIdentifier.
* @param basicClickIdentifier - the ClickIdentifier. ob
* @param clickControl -a reference to the ClickControl the classifier is associated with.
*/
public BasicIdentifierPaneFX(ClickIdentifier basicClickIdentifier,
@ -84,9 +84,17 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX {
this.basicClickIdentifier= basicClickIdentifier;
this.clickControl=clickControl;
mainPane= new PamBorderPane();
mainPane.setCenter(createSettingsPane());
flipPane = new PamFlipPane();
flipPane.getFrontPane().setCenter(createSettingsPane());
flipPane.getBackPane().setCenter(clickTypeHolder);
mainPane.setCenter(flipPane);
}
/**
* Create the controls for the basic click identifier pane.
* @return node with all controls for basic click classifier.
@ -97,21 +105,23 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX {
mainHolderPane.setCenter(settingsPane=new ClickClassifierTable(clickClassifiers));
clickTypeHolder=new PamBorderPane();
clickTypeHolder.setPrefWidth(hidingPaneWidth);
//clickTypeHolder.setPrefWidth(hidingPaneWidth);
return mainHolderPane;
}
/**
* Added purely so can be override and hiding pane set in different location if required
*/
public void createHidingPane(){
hidingPane=new HidingPane(Side.RIGHT, clickTypeHolder, mainPane, false);
//hidingPane.showHidePane(false);
mainHolderPane.setRight(hidingPane);
hidingPane.showHidePane(false);
}
// /**
// * Added purely so can be override and hiding pane set in different location if required
// */
// public void createHidingPane(){
// hidingPane=new HidingPane(Side.RIGHT, clickTypeHolder, mainPane, false);
// //hidingPane.showHidePane(false);
// mainHolderPane.setRight(hidingPane);
// hidingPane.showHidePane(false);
// }
@Override
public Node getNode() {
@ -192,14 +202,14 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX {
public Dialog<ClickTypeProperty> createSettingsDialog(ClickTypeProperty data) {
//we do not use dialogs here- sliding pane instead.
setClassifierPane(data);
showHidingPane(true);
showFlipPane(true);
return null;
}
@Override
public void editData(ClickTypeProperty data){
setClassifierPane(data);
showHidingPane(true);
showFlipPane(true);
}
@Override
@ -210,16 +220,31 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX {
}
// /**
// * Show the hiding pane which contains classifier settings
// * NOTE: needed to add this to stop a stack overflow error in BasicClickIdentifier 06/09/2016
// * @param show - true to show pane.
// */
// public void showHidingPane(boolean show){
// if (hidingPane==null){
// this.createHidingPane();
// }
// hidingPane.showHidePane(true);
// }
/**
* Show the hiding pane which contains classifier settings
* Show the flip pane.
* NOTE: needed to add this to stop a stack overflow error in BasicClickIdentifier 06/09/2016
* @param show - true to show pane.
*/
public void showHidingPane(boolean show){
if (hidingPane==null){
this.createHidingPane();
public void showFlipPane(boolean show){
if (show) {
//System.out.println("Show flip pane: " + show);
flipPane.flipToBack();
}
else {
flipPane.flipToFront();
}
hidingPane.showHidePane(true);
}
/**
@ -243,7 +268,9 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX {
//now need to make sure on closing the pane that settings are saved. Need to
//remove the old click type from the list and add new one in the same position.
getHidingPaneCloseButton().setOnAction((action)->{
getFlipPaneCloseButton().setOnAction((action)->{
//System.out.println("CLOSE FLIP PANE");
showFlipPane(false);
//this should update the click type property in the observable list thus changing the table
clickTypePane.getParams(clickTypeProperty);
});
@ -253,20 +280,20 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX {
* Get the button which closes the hiding pane.
* @return button which closes the hiding pane.
*/
public Button getHidingPaneCloseButton() {
return getClickTypeHidingPane().getHideButton();
public Button getFlipPaneCloseButton() {
return flipPane.getBackButton();
}
/**
* Get the hiding pane which holds settings for different click types.
* @return the HidingPane for click classifiers.
*/
public HidingPane getClickTypeHidingPane() {
if (hidingPane==null) {
this.createHidingPane();
}
return hidingPane;
}
// /**
// * Get the hiding pane which holds settings for different click types.
// * @return the HidingPane for click classifiers.
// */
// public HidingPane getClickTypeHidingPane() {
// if (hidingPane==null) {
// this.createHidingPane();
// }
// return hidingPane;
// }
/**
* Get the pane which holds the ClickTypePaneFX.

View File

@ -4,6 +4,7 @@ import org.controlsfx.glyphfont.Glyph;
import clickDetector.ClickControl;
import clickDetector.ClickParameters;
import clickDetector.ClickClassifiers.ClickClassifierManager;
import clickDetector.ClickClassifiers.ClickIdentifier;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
@ -41,6 +42,7 @@ public class ClickClassifyPaneFX extends PamStackPane {
*/
private ClickControl clickControl;
private CheckBox runOnlineCheckBox;
private CheckBox discardClicksCheckBox;
@ -160,7 +162,11 @@ public class ClickClassifyPaneFX extends PamStackPane {
//set parameters - listener will do everything else.
currentClickIdentifier=clickControl.getClassifierManager().
getClassifier(clickParameters.clickClassifierType);
System.out.println("ClickClassifyPaneFX:setParams(): " +classifierComboBox.getSelectionModel().getSelectedIndex());
if (clickParameters.clickClassifierType == ClickClassifierManager.CLASSIFY_BASIC) {
}
//System.out.println("ClickClassifyPaneFX:setParams(): " +classifierComboBox.getSelectionModel().getSelectedIndex());
classifierComboBox.getSelectionModel().select(clickParameters.clickClassifierType);
//set classifier parameters
if (currentClickIdentifier!=null && currentClickIdentifier.getClassifierPane()!=null) {
@ -171,7 +177,7 @@ public class ClickClassifyPaneFX extends PamStackPane {
public ClickParameters getParams(ClickParameters clickParameters){
//set all parameters in classifier.
System.out.println("ClickClassifyPaneFX:getParams(): " +classifierComboBox.getSelectionModel().getSelectedIndex());
//System.out.println("ClickClassifyPaneFX:getParams(): " +classifierComboBox.getSelectionModel().getSelectedIndex());
clickParameters.clickClassifierType=classifierComboBox.getSelectionModel().getSelectedIndex();
if (currentClickIdentifier != null && currentClickIdentifier.getClassifierPane() != null) {

View File

@ -1,7 +1,6 @@
package clickDetector.layoutFX.clickClassifiers;
import pamViewFX.fxNodes.PamScrollPane;
import clickDetector.ClickControl;
import clickDetector.ClickClassifiers.basicSweep.SweepClassifier;
import clickDetector.ClickClassifiers.basicSweep.SweepClassifierParameters;
@ -9,17 +8,18 @@ import clickDetector.ClickClassifiers.basicSweep.SweepClassifierSet;
/**
* Slightly different pane for the sweep classifier.
*
* @author Jamie Macaulay
*/
public class SweepClassifierPaneFX extends BasicIdentifierPaneFX {
/**
* Reference to the sweep classifier
* Reference to the sweep classifier.
*/
SweepClassifier sweepClickClassifier;
/**
* Reference to the sweep classifier params
* Reference to the sweep classifier params.
*/
private SweepClassifierParameters sweepIdParameters;
@ -39,11 +39,12 @@ public class SweepClassifierPaneFX extends BasicIdentifierPaneFX {
public void setClassifierPane(ClickTypeProperty clickTypeProperty){
SweepClassifierSetPaneFX sweepPane=new SweepClassifierSetPaneFX(sweepClickClassifier);
sweepPane.setParams(clickTypeProperty);
super.getClickTypeHolder().setCenter(new PamScrollPane(sweepPane.getContentNode()));
super.getClickTypeHolder().setCenter(sweepPane.getContentNode());
//now need to make sure on closing the pane that settings are saved. Need to
//remove the old click type from the list and add new one in the same position.
getHidingPaneCloseButton().setOnAction((action)->{
getFlipPaneCloseButton().setOnAction((action)->{
showFlipPane(false);
sweepPane.getParams(clickTypeProperty);
});
}

View File

@ -15,21 +15,22 @@ import javafx.scene.control.Label;
import javafx.scene.control.Spinner;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TabPane.TabClosingPolicy;
import javafx.scene.control.TextField;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.Priority;
import javafx.scene.text.Font;
import pamViewFX.PamGuiManagerFX;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamGridPane;
import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.PamSpinner;
import pamViewFX.fxNodes.PamTitledPane;
import pamViewFX.fxNodes.PamVBox;
import pamViewFX.fxNodes.pamDialogFX.PamDialogFX;
import pamViewFX.fxNodes.picker.SymbolPicker;
import pamViewFX.fxNodes.utilityPanes.FreqBandPane;
import pamViewFX.fxNodes.utilityPanes.PamToggleSwitch;
import pamViewFX.fxNodes.utilityPanes.SimpleFilterPaneFX;
import pamViewFX.PamGuiManagerFX;
import PamController.SettingsPane;
import clickDetector.ClickClassifiers.basicSweep.CodeHost;
@ -38,6 +39,7 @@ import clickDetector.ClickClassifiers.basicSweep.SweepClassifierSet;
/**
* Pane which contains controls to change a SweepClassifierSet.
*
* @author Jamie Macaulay
*
*/
@ -110,14 +112,15 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
private Node createSweepPane(){
PamVBox holder=new PamVBox();
holder.setSpacing(10);
holder.setPadding(new Insets(10,5,5,40));
holder.setSpacing(15);
holder.setPadding(new Insets(10,0,0,0));
optionBox=new OptionsBox();
/*********Waveform Tab************/
Tab waveformTab=new Tab("Waveform");
PamVBox waveformHolder=new PamVBox(5);
waveformHolder.setPadding(new Insets(10,0,0,0));
clickLength=new ClickLengthBox();
filterBox=new FilterBox();
@ -134,11 +137,13 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
energyBox=new EnergyBandBox();
freqBox=new FrequencySearchBlock();
spectrumHolder.getChildren().addAll(energyBox, freqBox);
spectrumHolder.setPadding(new Insets(10,0,0,0));
spectrumTab.setContent(spectrumHolder);
/**********Main Layout**************/
TabPane tabPane= new TabPane();
tabPane.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE);
tabPane.getTabs().addAll(waveformTab, spectrumTab);
holder.getChildren().add(optionBox);
@ -153,12 +158,12 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
* @author Jamie Macaulay
*
*/
private abstract class SweepBox extends PamTitledPane {
private abstract class SweepBox extends PamBorderPane {
/**
* Check box to enable pane
*/
private CheckBox enableBox;
private PamToggleSwitch enableBox;
/**
* Border pane to hold content
@ -167,40 +172,52 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
private Font disableFont;
private Label label;
SweepBox(String borderTitle, Boolean enableButton) {
//create holder pnae
borderPane=new PamBorderPane();
this.setCenter(borderPane);
PamHBox hBox = new PamHBox();
hBox.setSpacing(5);
if (borderTitle != null) {
//Label label=new Label(borderTitle);
PamGuiManagerFX.titleFont2style(this);
//borderPane.setTop(label);
this.setText(borderTitle);
label=new Label(borderTitle);
PamGuiManagerFX.titleFont2style(label);
hBox.getChildren().add(label);
}
if (enableButton) {
enableBox = new CheckBox("Enable");
PamVBox vBox=new PamVBox();
vBox.setPadding(new Insets(0,20,0,0));
vBox.setAlignment(Pos.CENTER);
vBox.getChildren().add(enableBox);
if (enableButton.booleanValue() == true) {
enableBox = new PamToggleSwitch("");
//vBox.setPadding(new Insets(0,20,0,0));
enableBox.setTooltip(new Tooltip("Enable " + borderTitle + " measurements"));
enableBox.setOnAction((action)->{
enableBox.selectedProperty().addListener((obsVal, oldVal, newVal)->{
disbleControls(!enableBox.isSelected());
/**FIXME- this does not seem to work. If titlepane collapsed auto returns to white**/
// if (enableBox.isSelected()) this.setTextFill(Color.WHITE);
// else this.setTextFill(Color.GRAY);
});
borderPane.setLeft(vBox);
hBox.getChildren().add(0,enableBox);
// setOnAction((action)->{
// disbleControls(!enableBox.isSelected());
//
// /**FIXME- this does not seem to work. If titlepane collapsed auto returns to white**/
// if (enableBox.isSelected()) this.setTextFill(Color.WHITE);
// else this.setTextFill(Color.GRAY);
// });
//this.setDisable(!enableBox.isSelected());
}
this.setContent(borderPane);
this.setTop(hBox);
/**Don't like this in old swing version*/
//tP.setCenter( description = new Label("", JLabel.CENTER));
//this.setTop(tP);
@ -211,7 +228,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
* @param desc - a description of the control
*/
protected void setDescription(String desc) {
this.setTooltip(new Tooltip(desc));
label.setTooltip(new Tooltip(desc));
}
// private void showTopStrip() {
@ -326,7 +343,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
nameField=new TextField();
nameField.setPrefColumnCount(10);
pamGridPane.add(nameField, 1, 0);
pamGridPane.add(nameField, 0, 0);
PamGridPane.setColumnSpan(nameField, 2);
@ -334,17 +351,17 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
codeSpinner=new PamSpinner<Integer> (0, 500, 0, 1);
codeSpinner.setEditable(true);
codeSpinner.setPrefWidth(150);
//codeSpinner.setPrefWidth(150);
codeSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
pamGridPane.add(codeSpinner, 4, 0);
pamGridPane.add(codeSpinner, 1, 0);
// pamGridPane.add(new Label("Symbol"), 0,1);
//create colour picker to allow users to change symbol colour.
symbolPicker=new SymbolPicker();
pamGridPane.add(symbolPicker, 6, 0);
pamGridPane.add(symbolPicker, 2, 0);
pamGridPane.add(new Label("Symbol"), 5,0);
pamGridPane.add(new Label("Symbol"), 3,0);
// //create a button to allow users to change symbol shape.
// symbolColour=new ColorPicker();
@ -372,7 +389,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
clickLengthSpinner=new PamSpinner<Integer>(4,102400,128,32);
clickLengthSpinner.setEditable(true);
clickLengthSpinner.setPrefWidth(150);
//clickLengthSpinner.setPrefWidth(150);
clickLengthSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
clickCenterBox.getChildren().add(clickLengthSpinner);
@ -380,7 +397,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
clickCenterBox.getChildren().add(lengthMS=new Label("()"));
clickCenterBox.getChildren().add(new Label("around click center."));
clickCenterBox.setAlignment(Pos.CENTER_LEFT);
PamGridPane.setColumnSpan(clickCenterBox, 7);
PamGridPane.setColumnSpan(clickCenterBox, 4);
PamGridPane.setHgrow(clickCenterBox, Priority.ALWAYS);
pamGridPane.add(clickCenterBox, 0,2);
@ -494,7 +511,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
protected void setParams() {
//set sample rate.
simpleFilterPane.setSampleRate(sweepClassifier.getClickDetector().getSampleRate());
simpleFilterPane.setParams(sweepClassifierSet.fftFilterParams);
if (sweepClassifierSet.fftFilterParams!=null) simpleFilterPane.setParams(sweepClassifierSet.fftFilterParams);
}
@ -558,7 +575,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
// gridPane.add(new Label("Smoothing"),0,0);
smoothing=new PamSpinner<Integer>(3,101,5,2);
smoothing.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
smoothing.setPrefWidth(100);
//smoothing.setPrefWidth(100);
// gridPane.add(smoothing,1,0);
// gridPane.add(new Label("bins (must be odd)"),2,0);
@ -566,7 +583,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
// gridPane.add(new Label("Threshold"),3,0);
threshold=new PamSpinner<Double>(1., 300., 6.,1.);
threshold.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
threshold.setPrefWidth(100);
//threshold.setPrefWidth(100);
// gridPane.add(threshold,4,0);
// gridPane.add(new Label("dB"),5,0);
@ -583,12 +600,12 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
minLengthms=new PamSpinner<Double>(0.00, 1.00, 0.03,0.01);
minLengthms.setEditable(true);
minLengthms.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
minLengthms.setPrefWidth(130);
//minLengthms.setPrefWidth(130);
maxLengthms=new PamSpinner<Double>(0.00, 1.00, 0.22,0.01);
maxLengthms.setEditable(true);
maxLengthms.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
maxLengthms.setPrefWidth(130);
//maxLengthms.setPrefWidth(130);
PamHBox clickLengthHolder2=new PamHBox();
@ -752,9 +769,9 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
*/
private class FrequencySearchBlock extends SweepBox {
private CheckBox peakFreqCheckBox;
private CheckBox peakWidthCheckBox;
private CheckBox meanFreqCheckBox;
private PamToggleSwitch peakFreqCheckBox;
private PamToggleSwitch peakWidthCheckBox;
private PamToggleSwitch meanFreqCheckBox;
/**
@ -767,7 +784,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
private FreqBandPane meanFreq;
FrequencySearchBlock() {
super("Peak and Mean Frequency", false);
super("Peak and Mean Frequency", true);
this.getHolderPane().setCenter(createFreqSearchPane());
}
@ -796,8 +813,8 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
//peak frequency
peakFreqCheckBox=new CheckBox("Enable");
peakFreqCheckBox.setOnAction((action)->{
peakFreqCheckBox=new PamToggleSwitch("");
peakFreqCheckBox.selectedProperty().addListener((obsVal, oldVal, newVal)->{
peakFreqPane.setDisableFreqPane(!peakWidthCheckBox.isSelected());
});
@ -811,8 +828,8 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
//peak width
peakWidthCheckBox=new CheckBox("Enable");
peakWidthCheckBox.setOnAction((action)->{
peakWidthCheckBox=new PamToggleSwitch("");
peakWidthCheckBox.selectedProperty().addListener((obsVal, oldVal, newVal)->{
//peakWidthPane.setDisable(!peakWidthCheckBox.isSelected());
peakWidthPane.setDisableFreqPane(!peakWidthCheckBox.isSelected());
threshold.setDisable(!peakWidthCheckBox.isSelected());
@ -838,8 +855,8 @@ public class SweepClassifierSetPaneFX extends SettingsPane<ClickTypeProperty> {
//mean frequency
meanFreqCheckBox=new CheckBox("Enable");
meanFreqCheckBox.setOnAction((action)->{
meanFreqCheckBox=new PamToggleSwitch("");
meanFreqCheckBox.selectedProperty().addListener((obsVal, oldVal, newVal)->{
meanFreq.setDisableFreqPane(!peakWidthCheckBox.isSelected());
});

View File

@ -5,6 +5,7 @@ import java.util.List;
import PamUtils.PamArrayUtils;
import PamguardMVC.PamDataUnit;
import PamguardMVC.debug.Debug;
/**
* Holds some basic IDI info on the click train.
@ -47,7 +48,7 @@ public class IDIInfo {
lastNumber = dataUnits.size();
if (dataUnits.size()<3) {
System.out.println("CTDataUnit: Cannot calculate IDIInfo for less than three data units");
Debug.out.println("CTDataUnit: Cannot calculate IDIInfo for less than three data units");
return;
}

View File

@ -31,7 +31,6 @@ public class SimpleCTClassification implements CTClassification {
@Override
public String getSummaryString() {
// TODO Auto-generated method stub
return "SimpleClssf: SpeciesID: " + speciesID + " ClassifierType: " + classifierType;
}

View File

@ -1,8 +1,8 @@
package clickTrainDetector.classification.bearingClassifier;
import org.renjin.gcc.runtime.Debug;
import PamUtils.PamArrayUtils;
import PamguardMVC.debug.Debug;
import clickTrainDetector.CTDataUnit;
import clickTrainDetector.ClickTrainControl;
import clickTrainDetector.classification.CTClassification;
@ -95,7 +95,7 @@ public class BearingClassifier implements CTClassifier {
if (nullcount>clickTrain.getSubDetectionsCount()-4) {
//less than three data units with loc results
Debug.println("The bearing classifier has a null count: ");
Debug.out.println("The bearing classifier has a null count: ");
return new BearingClassification(CTClassifier.NOSPECIES, Double.NaN, Double.NaN, Double.NaN);
}
@ -111,7 +111,7 @@ public class BearingClassifier implements CTClassifier {
double medianBearingD = PamArrayUtils.median(bearingDiff);
double stdBearingD = PamArrayUtils.std(bearingDiff);
Debug.println("Bearing classifier: No. Detections: " + clickTrain.getSubDetectionsCount() + " medianBearing: " + medianBearingD);
Debug.out.println("Bearing classifier: No. Detections: " + clickTrain.getSubDetectionsCount() + " medianBearing: " + medianBearingD);
int speciesID = CTClassifier.NOSPECIES;
boolean passed= true;
@ -120,31 +120,31 @@ public class BearingClassifier implements CTClassifier {
//is the minimum and maximum bearing in range...
if ((min>=bearingClssfrParams.bearingLimMin && min<=bearingClssfrParams.bearingLimMax) ||
(max>=bearingClssfrParams.bearingLimMin && max<=bearingClssfrParams.bearingLimMax)) {
Debug.println("Passed on min max bearing");
Debug.out.println("Passed on min max bearing");
}
else passed =false;
//mean bearing derivative
if (bearingClssfrParams.useMean && meanBearingD>=bearingClssfrParams.minMeanBearingD
&& meanBearingD<=bearingClssfrParams.maxMeanBearingD) {
Debug.println("Passed on mean bearing");
Debug.out.println("Passed on mean bearing");
}
else if (bearingClssfrParams.useMean) passed=false;
//median bearing derivative
Debug.println("Median Bearing: " + Math.toDegrees(medianBearingD) +
Debug.out.println("Median Bearing: " + Math.toDegrees(medianBearingD) +
" minlim: " + Math.toDegrees(bearingClssfrParams.minMedianBearingD)+
" maxlim: " + Math.toDegrees(bearingClssfrParams.maxMedianBearingD));
if (bearingClssfrParams.useMedian && medianBearingD>=bearingClssfrParams.minMedianBearingD
&& medianBearingD<=bearingClssfrParams.maxMedianBearingD) {
Debug.println("Passed on median bearing");
Debug.out.println("Passed on median bearing");
}
else if (bearingClssfrParams.useMedian) passed = false;
//standard deviation derivative
if (bearingClssfrParams.useStD && stdBearingD>=bearingClssfrParams.minStdBearingD
&& stdBearingD<=bearingClssfrParams.maxStdBearingD) {
Debug.println("Passed on std bearing");
Debug.out.println("Passed on std bearing");
}
else if (bearingClssfrParams.useStD) passed= false;
@ -152,7 +152,7 @@ public class BearingClassifier implements CTClassifier {
speciesID = this.bearingClssfrParams.speciesFlag;
}
Debug.println("SPECIESID!! " + speciesID);
Debug.out.println("SPECIESID!! " + speciesID);
return new BearingClassification(speciesID, meanBearingD, medianBearingD, stdBearingD);

View File

@ -70,11 +70,13 @@ public class MHTGarbageBot {
double maxICI = mhtKernel.getMHTParams().maxCoast * mhtKernel.getMHTChi2Provider().getChi2Params().maxICI;
//check the current set of click train possible ICI's
//Debug.out.println("MHTGARBAGEBOT: maxICI " + maxICI + " " + iciPrev);
//we have reached the hard limit. Save click trains, wipe the detector and start again.
if (mhtKernel.getKCount()>mhtKernel.getMHTParams().nPruneBackStart && (iciPrev>maxICI || mhtKernel.getKCount()>DETECTION_HARD_LIMIT)) {
// Debug.out.println("MHTGarbageBot: KERNEL HARD LIMIT");
//Debug.out.println("MHTGARBAGEBOT: KERNEL HARD LIMIT");
//check whether the next click has a gap so big that all click trains should be restarted
//grab tracks
mhtKernel.confirmRemainingTracks();

View File

@ -158,10 +158,10 @@ public class MHTKernel<T> {
if (verbosity>0) {
Debug.out.println("Possiblity matrix size is " + possibleTracks.size() + " x " + kcount );
}
// for (int i=0; i<possibleTracks.size(); i++) {
// System.out.println("Pos " + i + " chi^2 "+ possibleTracks.get(i).chi2Track +
// " " + printBitSet(possibleTracks.get(i).trackBitSet) );
// }
// for (int i=0; i<possibleTracks.size(); i++) {
// System.out.println("Pos " + i + " chi^2 "+ possibleTracks.get(i).chi2Track.getChi2() +
// " " + MHTKernel.bitSetString(possibleTracks.get(i).trackBitSet,kcount));
// }
//prune the probability matrix.
pruneProbMatrix(false);
@ -412,6 +412,7 @@ public class MHTKernel<T> {
testBranch = newPossibleTracks.get(j);
testBitSet=testBranch.trackBitSet.get(0, kcount-(pruneback));
//now test whether the current and test branch are the same.
if (testBitSet.equals(currentBitSet)) {
indexConfirm[j]=true;
@ -423,6 +424,7 @@ public class MHTKernel<T> {
indexRemove[j]=true;
}
}
}
//long time2a=System.currentTimeMillis();
@ -437,9 +439,11 @@ public class MHTKernel<T> {
if (nCoasts>=this.mHTParams.maxCoast || confirmAll || currentBranch.flag==TrackBitSet.JUNK_TRACK) {
//the branch needs to be confirmed.
// System.out.println(i + " DONE: "+ String.format("%.3f ", possibleTracks.get(i).chi2Track.getChi2())+
// " " + String.format("%d ", possibleTracks.get(i).chi2Track.getNCoasts())
// + MHTKernel.bitSetString(possibleTracks.get(i).trackBitSet, kcount));
// System.out.println(i + " DONE: " + (nCoasts >= this.mHTParams.maxCoast) + " " + confirmAll + " "
// + (currentBranch.flag == TrackBitSet.JUNK_TRACK) + " "
// + String.format("%.3f ", currentBranch.chi2Track.getChi2()) + " "
// + String.format("%d ", currentBranch.chi2Track.getNCoasts())
// + MHTKernel.bitSetString(currentBranch.trackBitSet, kcount));
/**
* 27/02/2020
@ -460,7 +464,7 @@ public class MHTKernel<T> {
//add confirmed track
confirmedTracks.add(currentBranch);
//// //if a branch is confirmed then all the tracks which include it's clicks must also be removed.
//// //test the testBranch against all other branches. TODO - Is this the most efficient code -could add if statements to above loop?
for (int j=0; j<newPossibleTracks.size(); j++) {
@ -471,6 +475,7 @@ public class MHTKernel<T> {
indexRemove[j]=true;
}
}
}
else {
//save as an active track.
@ -678,7 +683,7 @@ public class MHTKernel<T> {
/**
*
* Set a new reference index and junk all data before that index. This can be
* useful for long data sets to save memory once all click trains in preceeding
* useful for long data sets to save memory once all click trains in preceding
* data units have been detecteded. Note that the function deletes the currently
* confirmed tracks. These should be extracted beforehand;
*

View File

@ -5,6 +5,7 @@ import java.util.BitSet;
import PamUtils.PamArrayUtils;
import PamguardMVC.PamDataUnit;
import PamguardMVC.debug.Debug;
import clickTrainDetector.clickTrainAlgorithms.CTAlgorithmInfo;
import clickTrainDetector.clickTrainAlgorithms.mht.electricalNoiseFilter.ElectricalNoiseFilter;
import clickTrainDetector.clickTrainAlgorithms.mht.electricalNoiseFilter.SimpleElectricalNoiseFilter;
@ -225,16 +226,17 @@ public class StandardMHTChi2 implements MHTChi2<PamDataUnit>, Cloneable {
getIDIManager().setForceCalc(true);
this.lastIDIData = getIDIManager().getIDIStruct(bitSet);
//System.out.println("Time diff: " + lastIDIData.timeDiff + " " + lastIDIData.medianIDI);
nCoasts=(int) Math.floor(lastIDIData.timeDiff/Math.abs(lastIDIData.medianIDI));
}
else if (bitcount==1) {
//this stops a single units being stuck in the back of the probability matrix.
nCoasts = (int) Math.floor((newdataUnit.getTimeMilliseconds()/1000.
-getIDIManager().getLastTime(bitSet)/this.getChi2Params().maxICI));
nCoasts = (int) Math.floor(((newdataUnit.getTimeMilliseconds()-getIDIManager().getFirstDataUnit().getTimeMilliseconds())/1000.
-getIDIManager().getLastTime(bitSet))/this.getChi2Params().maxICI);
}
//System.out.println("nCoasts: " + nCoasts);
return nCoasts;
}
@ -332,6 +334,8 @@ public class StandardMHTChi2 implements MHTChi2<PamDataUnit>, Cloneable {
double totalTracktime = PamArrayUtils.sum(lastIDIData.idiSeries);
//System.out.println("Total track time: " + totalTracktime);
/**
* Add a nudge towards longer tracks (remember to cast to double when dividing). Note that
* kcount coefficient is meaningless because all tracks are multiplied by it and x^2 is only used
@ -341,7 +345,7 @@ public class StandardMHTChi2 implements MHTChi2<PamDataUnit>, Cloneable {
//19/03/2020 - fixed a bug; Was multiplying instead of dividing - as such long tracks were being
//discriminated against causing fragmentation...ooops
chi2=chi2/Math.pow(totalTracktime/getIDIManager().getTotalTime(),getChi2Params().longTrackExponent);
//chi2=chi2/Math.pow(bitSet.cardinality(),getChi2Params().longTrackExponent);
}
@ -374,6 +378,8 @@ public class StandardMHTChi2 implements MHTChi2<PamDataUnit>, Cloneable {
//All done. Set the values.
//set the chi2 values.
//long time3=System.nanoTime();
//Debug.out.println("Track chi2: " + chi2 + " " + bitcount );
return chi2;
}

View File

@ -2,6 +2,9 @@ package clickTrainDetector.clickTrainAlgorithms.mht.mhtvar;
import PamguardMVC.PamDataUnit;
import clickTrainDetector.clickTrainAlgorithms.mht.StandardMHTChi2Params;
import clickTrainDetector.layout.mht.AmplitudeMHTVarPane;
import clickTrainDetector.layout.mht.MHTVarSettingsPane;
/**
* Chi^2 value for dB amplitude of tracks. Measures the chnage in track delta between
@ -13,9 +16,14 @@ import PamguardMVC.PamDataUnit;
@SuppressWarnings("rawtypes")
public class AmplitudeChi2 extends SimpleChi2VarDelta {
private double lastDiff;
private AmplitudeChi2Params amplitudeParams;
public AmplitudeChi2() {
super();
super.setSimpleChiVarParams(defaultSettings());
super.setSimpleChiVarParams(amplitudeParams = (AmplitudeChi2Params) defaultSettings());
}
/**
@ -23,7 +31,7 @@ public class AmplitudeChi2 extends SimpleChi2VarDelta {
* @return
*/
private SimpleChi2VarParams defaultSettings() {
SimpleChi2VarParams simpleChiVarParams = new SimpleChi2VarParams(getName(), getUnits());
AmplitudeChi2Params simpleChiVarParams = new AmplitudeChi2Params(getName(), getUnits());
//simpleChiVarParams.errLimits=new double[] {Double.MIN_VALUE, 100};
simpleChiVarParams.error=30;
simpleChiVarParams.minError=1;
@ -36,13 +44,15 @@ public class AmplitudeChi2 extends SimpleChi2VarDelta {
return "Amplitude";
}
@Override
public double getDiffValue(PamDataUnit pamDataUnit0, PamDataUnit pamDataUnit1) {
//System.out.println("DB: " + pamDataUnit0.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());
this.lastDiff = Math.abs(pamDataUnit0.getAmplitudeDB()-pamDataUnit1.getAmplitudeDB());
return lastDiff;
}
@Override
@ -50,6 +60,28 @@ public class AmplitudeChi2 extends SimpleChi2VarDelta {
//just a simple static error coefficient.
return super.getError();
}
@Override
public double calcDeltaChi2(double lastDelta, double newDelta, double timeDiff) {
double chi2 = super.calcDeltaChi2(lastDelta, newDelta, timeDiff);
/**
* There was a problem here with using the delta instead of the absolute difference between amplitudes.
* When using the delta there could be a slow change of amplitude gradient which could lead to giant
* changes in absolute amplitude. By ensuring this is the absolute
* value between bearings (lastdiff) then the bearingJump threshold works as it should.
*/
//System.out.println("Amplitude: " + amplitudeParams.ampJumpEnable + " " + lastDiff + " " + amplitudeParams.maxAmpJump);
if (lastDiff>amplitudeParams.maxAmpJump && amplitudeParams.ampJumpEnable ) {
chi2=chi2+StandardMHTChi2Params.JUNK_TRACK_PENALTY;
}
return chi2;
}
@Override
@ -57,6 +89,27 @@ public class AmplitudeChi2 extends SimpleChi2VarDelta {
return "dB";
}
@Override
public void setSimpleChiVarParams(SimpleChi2VarParams params) {
if (params==null) amplitudeParams = new AmplitudeChi2Params(getName(), getUnits()); //backwards compatibility
else this.amplitudeParams = (AmplitudeChi2Params) params; ;
super.setSimpleChiVarParams(params);
//save a reference to params so we don;t have to keep casting.
}
@Override
public void setSettingsObject(Object object) {
this.setSimpleChiVarParams((AmplitudeChi2Params) object);
}
@Override
public MHTVarSettingsPane<SimpleChi2VarParams> getSettingsPane() {
if (this.settingsPane==null) this.settingsPane= new AmplitudeMHTVarPane(getSimpleChiVarParams(), new ResultConverter());
settingsPane.setParams(getSimpleChiVarParams());
return settingsPane;
}
}

View File

@ -0,0 +1,46 @@
package clickTrainDetector.clickTrainAlgorithms.mht.mhtvar;
import PamModel.parametermanager.ManagedParameters;
public class AmplitudeChi2Params extends SimpleChi2VarParams implements ManagedParameters {
public AmplitudeChi2Params(String name, String unitString, double error, double minError, double errorScaleValue) {
super(name, unitString, error, minError, errorScaleValue);
// TODO Auto-generated constructor stub
}
public AmplitudeChi2Params(String name, String unitString, double error, double minError) {
super(name, unitString, error, minError);
// TODO Auto-generated constructor stub
}
public AmplitudeChi2Params(String name, String unitString) {
super(name, unitString);
// TODO Auto-generated constructor stub
}
public AmplitudeChi2Params(String name) {
super(name);
}
public AmplitudeChi2Params(SimpleChi2VarParams params) {
this(params.name, params.getUnits(), params.error, params.minError, params.errorScaleValue);
}
/**
*
*/
private static final long serialVersionUID = 1L;
/**
* Whether the bearing jump is used.
*/
public boolean ampJumpEnable = true;
/**
* The maximum allowed bearing bearing jump in a click train in RADIANS
*/
public double maxAmpJump = 10; //dB
}

View File

@ -141,7 +141,7 @@ public class BearingChi2Delta extends SimpleChi2VarDelta {
if (delta>bearingParams.maxBearingJump) {
//System.out.println("Hello!!!! Reverse Bearing");
chi2=chi2*StandardMHTChi2Params.JUNK_TRACK_PENALTY;
chi2=chi2+StandardMHTChi2Params.JUNK_TRACK_PENALTY;
}
}

View File

@ -536,6 +536,10 @@ public class IDIManager {
return (this.lastDetection.getTimeMilliseconds()- this.firstDetection.getTimeMilliseconds())/1000.;
}
public PamDataUnit getFirstDataUnit() {
return this.firstDetection;
}

View File

@ -16,7 +16,6 @@ public class LengthChi2 extends SimpleChi2Var {
@Override
public String getName() {
// TODO Auto-generated method stub
return "Click Length";
}
@ -44,7 +43,7 @@ public class LengthChi2 extends SimpleChi2Var {
//simpleChiVarParams.errLimits=new double[] {Double.MIN_VALUE, 100};
simpleChiVarParams.error=0.2;
simpleChiVarParams.minError=0.002;
simpleChiVarParams.errorScaleValue = SimpleChi2VarParams.SCALE_FACTOR_ICI;
simpleChiVarParams.errorScaleValue = SimpleChi2VarParams.SCALE_FACTOR_ICI*10;
return simpleChiVarParams;
}

View File

@ -288,7 +288,7 @@ public class CTDataSelectPanel implements PamDialogPanel {
}
// System.out.println("No. count: " + count);
currentParams.classifier = new int[count];
currentParams.classifier = new int[count];
ArrayList<CTClassifier> classifiers = ctDataSelector.getClickControl().getClassifierManager().getCurrentClassifiers();
int used = 0;
for (int i=0; i<classifierCheckBoxes.length; i++) {

View File

@ -28,7 +28,7 @@ public class AdvMHTVarPane extends DynamicSettingsPane<SimpleChi2VarParams> {
/**
* Default divisor of error for min error.
*/
private static final Double ERROR_DIVISOR = 10000.0;
private static final Double ERROR_DIVISOR = 100.0;
/**
* The main pane.

View File

@ -0,0 +1,97 @@
package clickTrainDetector.layout.mht;
import org.controlsfx.control.ToggleSwitch;
import clickTrainDetector.clickTrainAlgorithms.mht.mhtvar.AmplitudeChi2Params;
import clickTrainDetector.clickTrainAlgorithms.mht.mhtvar.IDIChi2Params;
import clickTrainDetector.clickTrainAlgorithms.mht.mhtvar.ResultConverter;
import clickTrainDetector.clickTrainAlgorithms.mht.mhtvar.SimpleChi2VarParams;
import javafx.scene.control.Label;
import javafx.scene.control.Spinner;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.GridPane;
import pamViewFX.fxNodes.PamSpinner;
public class AmplitudeChi2AdvPane extends AdvMHTVarPane {
private PamSpinner<Double> ampJumpSpinner;
private ToggleSwitch ampEnaleSwitch;
public AmplitudeChi2AdvPane(SimpleChi2VarParams simpleChi2Var2, ResultConverter resultConverter) {
super(simpleChi2Var2, resultConverter);
}
@Override
protected GridPane createAdvPane() {
GridPane gridPane = (GridPane) super.createAdvPane();
int gridY=3;
gridPane.add(ampEnaleSwitch = new ToggleSwitch("Max jump"), 0, gridY);
ampEnaleSwitch.selectedProperty().addListener((obsVal, newVal, oldVal)->{
ampJumpSpinner.setDisable(!ampEnaleSwitch.isSelected());
});
ampJumpSpinner = new PamSpinner<Double>(0.,Double.MAX_VALUE,0.,1.0);
ampJumpSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
ampJumpSpinner.setPrefWidth(90);
ampJumpSpinner.valueProperty().addListener((obs,oldVal,newVal)->{
notifySettingsListeners();
});
gridPane.add(ampJumpSpinner, 1, gridY);
gridPane.add(new Label("dB"), 2, gridY);
ampJumpSpinner.setEditable(true);
//create tool tip
Tooltip errorCoeffTip = new Tooltip(
"The minimum Amplitude defines the maximum decibel jump between two detection allowed in a click train"
+ "If an IDI below this minimum occurs in a click train it will incur"
+ "a large chi^2 penalty and so the click train is unlikely to be kept"
+ "in the hypothesis mix.");
errorCoeffTip.setWrapText(true);
errorCoeffTip.setPrefWidth(200);
ampEnaleSwitch.setTooltip(errorCoeffTip);
ampJumpSpinner.setTooltip(errorCoeffTip);
ampJumpSpinner.setDisable(!ampEnaleSwitch.isSelected());
return gridPane;
}
@Override
public AmplitudeChi2Params getParams(SimpleChi2VarParams currParams) {
System.out.println("Get params: AMPLITUDE");
AmplitudeChi2Params newParams = new AmplitudeChi2Params(super.getParams(currParams));
newParams.maxAmpJump = ampJumpSpinner.getValue();
newParams.ampJumpEnable = ampEnaleSwitch.isSelected();
return newParams;
}
@Override
public void setParams(SimpleChi2VarParams currParams) {
AmplitudeChi2Params newParams;
if (currParams instanceof AmplitudeChi2Params) {
newParams = (AmplitudeChi2Params) currParams;
}
else {
newParams = new AmplitudeChi2Params(currParams);
}
super.setParams(newParams);
ampJumpSpinner.setDisable(!ampEnaleSwitch.isSelected());
ampJumpSpinner.getValueFactory().setValue(newParams.maxAmpJump);
ampEnaleSwitch.setSelected(newParams.ampJumpEnable);
}
}

View File

@ -0,0 +1,22 @@
package clickTrainDetector.layout.mht;
import clickTrainDetector.clickTrainAlgorithms.mht.mhtvar.ResultConverter;
import clickTrainDetector.clickTrainAlgorithms.mht.mhtvar.SimpleChi2VarParams;
public class AmplitudeMHTVarPane extends SimpleMHTVarPane {
public AmplitudeMHTVarPane(SimpleChi2VarParams simpleChi2Var, ResultConverter resultsConverter) {
super(simpleChi2Var, resultsConverter);
// TODO Auto-generated constructor stub
}
/**
* Create the advanced settings pane.
* @return the advanced settings pane.
*/
@Override
public AdvMHTVarPane createAdvMHTVarPane(SimpleChi2VarParams simpleChi2VarParams, ResultConverter resultConverter) {
return new AmplitudeChi2AdvPane(simpleChi2VarParams, resultConverter);
}
}

View File

@ -8,7 +8,6 @@ public class BearingMHTVarPane extends SimpleMHTVarPane {
public BearingMHTVarPane(SimpleChi2VarParams simpleChi2Var, ResultConverter resultsConverter) {
super(simpleChi2Var, resultsConverter);
// TODO Auto-generated constructor stub
}
/**

View File

@ -86,11 +86,11 @@ public class CorrelationAdvMHTPane extends AdvMHTVarPane {
CorrelationChi2Params newParams = new CorrelationChi2Params(super.getParams(currParams));
System.out.println("GETPARAMS:fftFilterParams_OLD HIGHPASS: " + newParams.fftFilterParams.highPassFreq);
//System.out.println("GETPARAMS:fftFilterParams_OLD HIGHPASS: " + newParams.fftFilterParams.highPassFreq);
newParams.fftFilterParams=filterPane.getParams(newParams.fftFilterParams);
System.out.println("GETPARAMS:fftFilterParams_NEW HIGHPASS: " + newParams.fftFilterParams.highPassFreq);
//System.out.println("GETPARAMS:fftFilterParams_NEW HIGHPASS: " + newParams.fftFilterParams.highPassFreq);
newParams.useFilter=this.useFilterBox.isSelected();

View File

@ -42,7 +42,8 @@ public class ICIChi2AdvPane extends AdvMHTVarPane {
});
gridPane.add(minICISpinner, 1, gridY);
gridPane.add(new Label("ms"), 2, gridY);
minICISpinner.setEditable(true);
//create tool tip
Tooltip errorCoeffTip = new Tooltip( "The minimum IDI defines a minimum IDI allowed in a click train \n"
+ "If an IDI below this minimum occurs in a click train it will incur\n"

View File

@ -98,7 +98,7 @@ public class ClickTrainDetLogging extends SuperDetLogging {
//average spectrum
tableDef.addTableItem(avrg_Spectrum_max = new PamTableItem("avrg_spectrum_max", Types.DOUBLE));
tableDef.addTableItem(avrg_Spectrum = new PamTableItem("avrg_spectrum", Types.CHAR, 8*DEFAULT_SPECTRUM_LEN));
tableDef.addTableItem(classifiers = new PamTableItem("classifiers", Types.CHAR, 4096));
tableDef.addTableItem(classifiers = new PamTableItem("classifiers", Types.CHAR, 8128));
//a species flag, this is entirely for user convenience and is NOT read back - the species flag
//is read from the JSON strings when reloading the data unit. If they end being different something has gone
@ -279,7 +279,9 @@ public class ClickTrainDetLogging extends SuperDetLogging {
//set the classifications.
String classifiersData = classifiers.getStringValue();
//FIXME
//System.out.println(classifiersData);
if (classifiersData!=null && classifiersData.length()>0) {
String[] classifiersDatas = classifiersData.split(JSON_DELIMITER);

View File

@ -44,7 +44,7 @@ public class CTProcessDialog extends OLProcessDialog {
getTaskCheckBoxs()[i].setEnabled(aTask.canRun() && nr);
//added extra but here so that only one tasks can be run at a time- may change
System.out.println("A task can run: !!" + aTask.canRun() + " " + aTask.getDataBlock());
//System.out.println("A task can run: !!" + aTask.canRun() + " " + aTask.getDataBlock());
//if more tasks are added to the click train detector.
if (aTask.canRun() == false || (aTask!=task && task!=null)) {
getTaskCheckBoxs()[i].setSelected(false);

View File

@ -14,7 +14,8 @@ import pamViewFX.fxNodes.connectionPane.StandardConnectionNode;
import pamViewFX.fxNodes.connectionPane.structures.ExtensionSocketStructure;
/**
* PAM extension structure
* PAM extension structure. The extension structure allows one parent to be split into multiple
* children primarily a way to neaten up a data model display.
*
* @author Jamie Macaulay
*
@ -22,10 +23,11 @@ import pamViewFX.fxNodes.connectionPane.structures.ExtensionSocketStructure;
public class PamExtensionStructure extends ExtensionSocketStructure implements PAMConnectionNode {
private PamStructureParams groupStructureParams;
public PamExtensionStructure(ConnectionPane connectionPane) {
super(connectionPane);
groupStructureParams = new PamStructureParams(this);
final ContextMenu contextMenu = new ContextMenu();
@ -34,13 +36,18 @@ public class PamExtensionStructure extends ExtensionSocketStructure implements P
paste.setOnAction((action)->{
removeStructure();
});
this.getConnectionNodeBody().setOnMousePressed((event)->{
//this is a bit of a hack. We can't add this to the main connection body because
//it is already used for dragging. So instead at to the circle within the connection group. The event is registered
//by both the group and the circle.
circle.setOnMousePressed((event)->{
if (event.isSecondaryButtonDown()) {
contextMenu.show(this.getConnectionNodeBody(), event.getScreenX(), event.getScreenY());
}
});
}

View File

@ -41,6 +41,7 @@ public class ImportTemplateCSV implements TemplateImport {
//the first row is the waveform
double[] waveform = new double[data.get(0).size()];
for (int i=0; i<waveform.length; i++) {
//System.out.println("i: " + i + " : " + data.get(0).get(i));
waveform[i]=data.get(0).get(i);
}

View File

@ -71,7 +71,7 @@ public abstract class OfflineTask<T extends PamDataUnit> {
*/
PamControlledUnit parentControl = getTaskControlledUnit();
if (parentControl == null) {
System.out.printf("Offline task %d with datablock %s is not associated with a PAMGuard module\n", getName(), parentDataBlock);
System.out.printf("Offline task %s with datablock %s is not associated with a PAMGuard module\n", getName(), parentDataBlock==null ? "null": parentDataBlock.getDataName());
}
else {
OfflineTaskManager.getManager().registerTask(this);

View File

@ -187,11 +187,16 @@ public class TaskLogging {
String modType = moduleType.getDeblankedStringValue();
String modName = moduleName.getDeblankedStringValue();
String tskName = taskName.getDeblankedStringValue();
long dStart = SQLTypes.millisFromTimeStamp(dataStart.getValue());
long dEnd = SQLTypes.millisFromTimeStamp(dataEnd.getValue());
long procEnd = SQLTypes.millisFromTimeStamp(runEnd.getValue());
Long dEnd = null, dStart = null, procEnd = null;
dStart = SQLTypes.millisFromTimeStamp(dataStart.getValue());
dEnd = SQLTypes.millisFromTimeStamp(dataEnd.getValue());
procEnd = SQLTypes.millisFromTimeStamp(runEnd.getValue());
if (dStart==null && dEnd==null && procEnd==null) return null;
String compStatus = completionCode.getDeblankedStringValue();
TaskStatus status = null;
if (compStatus==null) return null;
try {
status = TaskStatus.valueOf(TaskStatus.class, compStatus);
}
@ -199,8 +204,13 @@ public class TaskLogging {
System.out.printf("Uknown completion code \"%s\" for task %s ended at %s\n", compStatus, tskName, PamCalendar.formatDateTime(dEnd));
}
String taskNote = note.getDeblankedStringValue();
OldTaskData monData = new OldTaskData(status, dStart, dEnd, utc, procEnd, taskNote);
return monData;
if (dStart!=null && dEnd!=null && procEnd!=null) {
OldTaskData monData = new OldTaskData(status, dStart, dEnd, utc, procEnd, taskNote);
return monData;
}
else {
return null;
}
}
/**

View File

@ -48,6 +48,11 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
*/
private PamTabPane mainTabPane;
/**
* The preferred width of the side pane.
*/
public static final double SIDE_PANE_PREF_WIDTH = 250;
// /**
// * Icon for menu
// */
@ -157,7 +162,9 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
/**create right hiding pane**/
sidePaneContent=new PamVBox();
sidePaneContent.setPrefWidth(250);
sidePaneContent.setPrefWidth(SIDE_PANE_PREF_WIDTH);
sidePaneContent.setPadding(new Insets(25,5,5,5)); //give quite abit of spacing at the top so that there is room for close button
sidePaneContent.setMinWidth(0);
hidingSidePane=new HidingPane(Side.RIGHT, sidePaneContent, this, false);
hidingSidePane.showHidePane(false);
@ -176,7 +183,7 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
// showButton.prefWidthProperty().addListener((listener)->{
// mainTabPane.layout(); //Don't need this
// });
hidingSidePane.getTimeLineShow().setOnFinished((value)->{
showButtonRight.setPrefWidth(1);
showButtonRight.setVisible(false);
@ -187,6 +194,7 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
showButtonRight.setPrefWidth(40);
showButtonRight.setVisible(true);
hidingSidePane.getHideButton().setVisible(false);
//sidePaneContent.setVisible(false);
layout.layout();
});

View File

@ -24,4 +24,5 @@ public class PamHBox extends HBox {
// TODO Auto-generated constructor stub
}
}

View File

@ -13,41 +13,55 @@ import javafx.util.StringConverter;
*/
public class PamSpinner<T> extends Spinner<T>{
/**
* Default widths are way off in JavaFX for spinners.
*/
// private static final double PAMSPINNER_PREF_WIDTH = USE_COMPUTED_SIZE;
private static final double PAMSPINNER_PREF_WIDTH = 100;
public PamSpinner() {
super();
this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
// TODO Auto-generated constructor stub
}
public PamSpinner(double min, double max, double initialValue, double amountToStepBy) {
super(min, max, initialValue, amountToStepBy);
this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
addDefocusConverter();
}
public PamSpinner(double min, double max, double initialValue) {
super(min, max, initialValue);
this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
addDefocusConverter();
}
public PamSpinner(int min, int max, int initialValue, int amountToStepBy) {
super(min, max, initialValue, amountToStepBy);
this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
addDefocusConverter();
}
public PamSpinner(int min, int max, int initialValue) {
super(min, max, initialValue);
this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
addDefocusConverter();
}
public PamSpinner(ObservableList<T> arg0) {
super(arg0);
this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
addDefocusConverter();
}
public PamSpinner(SpinnerValueFactory<T> arg0) {
super(arg0);
addDefocusConverter();
this.setPrefWidth(PAMSPINNER_PREF_WIDTH);
}
/**

View File

@ -34,6 +34,8 @@ public class ExtensionSocketStructure extends StandardConnectionNode implements
* The colour of the extension socket body
*/
private static Color bodyColour = Color.DODGERBLUE;
protected Shape circle;
/**
* Extension structure construction.
@ -69,7 +71,7 @@ public class ExtensionSocketStructure extends StandardConnectionNode implements
@Override
public ConnectionNodeBody createNodeBody() {
Circle circle = new Circle(DEFAULT_BODY_WIDTH/2,DEFAULT_BODY_WIDTH/2, DEFAULT_BODY_WIDTH/2);
circle = new Circle(DEFAULT_BODY_WIDTH/2,DEFAULT_BODY_WIDTH/2, DEFAULT_BODY_WIDTH/2);
circle.setFill(bodyColour);
ConnectionNodeBody connectionNodeBody = new ConnectionNodeBody(this);
@ -79,7 +81,6 @@ public class ExtensionSocketStructure extends StandardConnectionNode implements
connectionNodeBody.getChildren().add(circle);
connectionNodeBody.setPrefHeight(DEFAULT_BODY_WIDTH);
connectionNodeBody.setPrefWidth(DEFAULT_BODY_WIDTH);

View File

@ -0,0 +1,132 @@
package pamViewFX.fxNodes.flipPane;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.paint.Color;
import pamViewFX.PamGuiManagerFX;
import pamViewFX.fxGlyphs.PamGlyphDude;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamButton;
import pamViewFX.fxNodes.PamHBox;
/**
* Flip pane which has is supposed to be used for advanced settings. The front
* of the pane is to be used for standard settings and the pane can then flip to
* the back to show advanced settings. A back button is included in the back
* pane which can be used to flip the pane back to the standard settings. The
* front pane needs a control that calls flipPane.toBack() to show the advanced
* pane.
*
* @author Jamie Macaulay
*
*/
public class PamFlipPane extends FlipPane {
public static final double FLIP_TIME =250; //milliseconds - the default is 700ms whihc is way too long.
private PamBorderPane advPane;
private PamBorderPane frontPane;
private Label advLabel;
private PamButton backButton;
public PamFlipPane() {
super();
this.advPane = createAdvSettingsPane();
this.getFront().getChildren().add(frontPane = new PamBorderPane());
this.getBack().getChildren().add(advPane);
this.setFlipTime(FLIP_TIME);
}
public PamFlipPane(Orientation FLIP_DIRECTION) {
super(FLIP_DIRECTION);
this.advPane = createAdvSettingsPane();
this.getFront().getChildren().add(frontPane = new PamBorderPane());
this.getBack().getChildren().add(advPane);
this.setFlipTime(FLIP_TIME);
}
/**
* Get the front pane.
* @return the front pane.
*/
public PamBorderPane getFrontPane() {
return frontPane;
}
/**
* Get the back pane.
* @return the back pane.
*/
public PamBorderPane getBackPane() {
return advPane;
}
/**
* Convenience duplicate of getBackPane().
* @return the back pane.
*/
public PamBorderPane getAdvPane() {
return advPane;
}
/**
* Create the advanced settings pane which can be accessed by DAQ panes if needed.
*/
private PamBorderPane createAdvSettingsPane() {
backButton = new PamButton();
backButton.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-left", Color.WHITE, PamGuiManagerFX.iconSize));
backButton.setOnAction((action)->{
// System.out.println("FLIP BACK TO FRONT");
this.flipToFront();
});
//backButton.setPrefWidth(150);
PamBorderPane advPane = new PamBorderPane();
advPane.setPadding(new Insets(5,5,5,5));
PamHBox buttonHolder = new PamHBox();
buttonHolder.setBackground(null);
//buttonHolder.setStyle("-fx-background-color: red;");
buttonHolder.setAlignment(Pos.CENTER_LEFT);
buttonHolder.getChildren().addAll(backButton, advLabel = new Label("Adv. Settings"));
advLabel.setAlignment(Pos.CENTER);
advLabel.setMaxWidth(Double.MAX_VALUE); //need to make sure label is in center.
PamGuiManagerFX.titleFont2style(advLabel);
advLabel.setAlignment(Pos.CENTER);
HBox.setHgrow(advLabel, Priority.ALWAYS);
advPane.setTop(buttonHolder);
return advPane;
}
public Label getAdvLabel() {
return advLabel;
}
public void setAdvLabel(Label advLabel) {
this.advLabel = advLabel;
}
public PamButton getBackButton() {
return backButton;
}
}

View File

@ -1,46 +1,93 @@
package pamViewFX.fxNodes.sliders.skin;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.control.Slider;
import javafx.scene.control.skin.SliderSkin;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import pamViewFX.fxNodes.utilsFX.PamUtilsFX;
//import com.sun.javafx.scene.control.skin.SliderSkin;
public class PamSliderSkin extends SliderSkin {
/**
* Reference to the slider track.
*/
private Node track;
private Slider slider;
private Pane track;
private Slider slider;
private StackPane topBar;
private Pane thumb;
public PamSliderSkin(Slider slider) {
super(slider);
this.slider=slider;
track = slider.lookup(".track");
setTrackColor(Color.RED);
track = (Pane) slider.lookup(".track");
thumb = (Pane) slider.lookup(".thumb");
initTopBar();
setTrackColor(Color.RED);
}
/**
* Create the top bar.
*/
public void initTopBar(){
topBar=new StackPane();
//TODO-need to sort for horizontal
if (slider.getOrientation()==Orientation.VERTICAL){
topBar.layoutXProperty().bind(track.layoutXProperty());
}
else {
topBar.layoutYProperty().bind(track.layoutYProperty());
}
// topBar.setStyle("-fx-background-color: red;");
//topBar.setSty
getChildren().add(topBar);
thumb.toFront();
}
@Override
protected void layoutChildren(final double x, final double y,
final double w, final double h) {
super.layoutChildren(x, y, w, h);
double rangeStart;
if (track==null) return;
//now resize the top bar.
if (slider.getOrientation()==Orientation.VERTICAL){
rangeStart=thumb.getLayoutY()+thumb.getHeight();
topBar.layoutYProperty().setValue(0);
topBar.resize(track.getWidth(), rangeStart+1);
}
else {
rangeStart=thumb.getLayoutX()+thumb.getWidth();
topBar.layoutXProperty().setValue(0);
topBar.resize(rangeStart+1, track.getHeight());
}
};
public void setTrackColor(Color trackCol){
track = slider.lookup(".track");
// int r = (int) (trackCol.getRed() * 255);
// int g = (int) (trackCol.getGreen() * 255);
// int b = (int) (trackCol.getBlue() * 255);
// String str = String.format("#%02X%02X%02X;", r, g, b);
//28/03/2017 - had to change to css as adding to a scroll pane seemed ot override background.
track.setStyle("-fx-background-color: " + PamUtilsFX.color2Hex(trackCol));
track = (Pane) slider.lookup(".track");
thumb = (Pane) slider.lookup(".thumb");
// int r = (int) (trackCol.getRed() * 255);
// int g = (int) (trackCol.getGreen() * 255);
// int b = (int) (trackCol.getBlue() * 255);
// String str = String.format("#%02X%02X%02X;", r, g, b);
//28/03/2017 - had to change to css as adding to a scroll pane seemed ot override background.
if (topBar!=null) topBar.setStyle("-fx-background-color: " + PamUtilsFX.color2Hex(trackCol) + "; -fx-background-radius: " + 6 + "; -fx-border-radius: "
+ 6 + " ; -fx-border-color: none;");
//((Region) track).setBackground(new Background(new BackgroundFill(Color.RED, new CornerRadii(2), Insets.EMPTY)));
}

View File

@ -15,6 +15,7 @@ import pamViewFX.fxNodes.pamDialogFX.PamDialogFX;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.chart.NumberAxis;
@ -35,10 +36,10 @@ import PamController.SettingsPane;
public class FilterPaneFX extends SettingsPane<FilterParams> {
private String[] filterNames = { "None", "IIR Butterworth", "IIR Chebyshev",
"FIR Filter (Window Method)", "Arbitrary FIR Filter"};
/**
* Combo box for selecting filter types.
*/
@ -53,12 +54,12 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
* Text field for lower frequency
*/
private PamSpinner<Double> lowPass;
/**
* Spinner to allow user to change filter order.
*/
private PamSpinner<Integer> filterOrder;
/**
* Spinner to allow user to change filter order.
*/
@ -81,7 +82,7 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
private PamRadioButton logScale;
private PamRadioButton linScale;
/**
* Some default frequency values for the high and low pass frequency spinner.
*/
@ -106,12 +107,12 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
* Plot pane for the graph axis.
*/
private PamLineChart<Number, Number> plotLogChart;
/**
* Line chart without logarithmic frequency axis.
*/
private PamLineChart<Number, Number> plotLinChart;
/**
* Log axis for log chart
*/
@ -126,15 +127,28 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
* Ripple label
*/
private Label rippleLabel;
private PamBorderPane mainPane = new PamBorderPane();
public FilterPaneFX () {
super(null);
mainPane.setLeft(createFilterPane());
mainPane.setCenter(createBodeGraph());
}
private PamBorderPane mainPane = new PamBorderPane();
public FilterPaneFX () {
this(Orientation.HORIZONTAL);
}
public FilterPaneFX (Orientation orientaiton) {
super(null);
if (orientaiton == Orientation.HORIZONTAL) {
mainPane.setLeft(createFilterPane());
mainPane.setCenter(createBodeGraph());
}
else {
mainPane.setTop(createFilterPane());
mainPane.setBottom(createBodeGraph());
}
}
/**
* Create the filter pane. This contains controls to change filter types and shows a graph of the current filter.
* @return pane with controls to change filter params.
@ -142,14 +156,14 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
public Node createFilterPane(){
controlPane=new PamVBox();
controlPane.setSpacing(5);
//label title
Label title=new Label("Filter type");
PamGuiManagerFX.titleFont2style(title);
// title.setFont(PamGuiManagerFX.titleFontSize2);
// title.setFont(PamGuiManagerFX.titleFontSize2);
controlPane.getChildren().add(title);
//create combo box
filterTypes=new PamComboBox<String>();
for (int i=0; i<filterNames.length; i++){
@ -160,24 +174,24 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
updateBodeGraph();
enableControls();
});
filterTypes.setMaxWidth(Double.MAX_VALUE);
filterTypes.setMaxWidth(Double.MAX_VALUE);
HBox.setHgrow(filterTypes, Priority.ALWAYS);
controlPane.getChildren().add(filterTypes);
//Radio buttons and frequency response
Label freqResponse=new Label("Frequency Response");
// freqResponse.setFont(PamGuiManagerFX.titleFontSize2);
// freqResponse.setFont(PamGuiManagerFX.titleFontSize2);
PamGuiManagerFX.titleFont2style(freqResponse);
controlPane.getChildren().add(freqResponse);
//radio buttons
final ToggleGroup group = new ToggleGroup();
// group.selectedToggleProperty().addListener((obs, old_val, new_val)-> {
// if (group.getSelectedToggle() != null) {
//
// }
// });
// group.selectedToggleProperty().addListener((obs, old_val, new_val)-> {
// if (group.getSelectedToggle() != null) {
//
// }
// });
PamVBox radioButtonBox=new PamVBox();
radioButtonBox.setSpacing(3);
@ -198,7 +212,7 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
updateBodeGraph();
});
radioButtonBox.getChildren().add(bandPassrb);
bandStoprb = new PamRadioButton("Band Stop");
bandStoprb.setToggleGroup(group);
bandStoprb.setOnAction((action)->{
@ -207,7 +221,7 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
updateBodeGraph();
});
radioButtonBox.getChildren().add(bandStoprb);
lowPassrb = new PamRadioButton("Low Pass");
lowPassrb.setToggleGroup(group);
lowPassrb.setOnAction((action)->{
@ -216,17 +230,17 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
updateBodeGraph();
});
radioButtonBox.getChildren().add(lowPassrb);
//create frequency text boxes
PamGridPane gridPaneFreq=new PamGridPane();
gridPaneFreq.setHgap(5);
gridPaneFreq.setVgap(5);
//lost of filter order sizes- anyone using >500 will be crazy anyway
// ObservableList<Double> freqList=FXCollections.observableArrayList();
// for (int i=0; i<defaultFrequencyVals.length; i++){
// freqList.add(defaultFrequencyVals[i]);
// }
// ObservableList<Double> freqList=FXCollections.observableArrayList();
// for (int i=0; i<defaultFrequencyVals.length; i++){
// freqList.add(defaultFrequencyVals[i]);
// }
highCut=new PamSpinner<Double>(10.,500000.,2000.,2000.);
highCut.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
@ -256,21 +270,21 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
gridPaneFreq.add(new Label("Low Pass"), 0, 1);
gridPaneFreq.add(lowPass, 1, 1);
gridPaneFreq.add(new Label("Hz"), 2, 1);
PamHBox filterSettings=new PamHBox(); //holds radio buttons and frquency text fields.
filterSettings.getChildren().addAll(radioButtonBox, gridPaneFreq);
filterSettings.setSpacing(15);
controlPane.getChildren().add(filterSettings);
//next create filter order settings
Label filterOrderLabel=new Label("Filter Order");
PamGuiManagerFX.titleFont2style(filterOrderLabel);
// filterOrderLabel.setFont(PamGuiManagerFX.titleFontSize2);
// filterOrderLabel.setFont(PamGuiManagerFX.titleFontSize2);
controlPane.getChildren().add(filterOrderLabel);
PamGridPane gridPaneOrder=new PamGridPane();
gridPaneOrder.setHgap(5);
gridPaneOrder.setVgap(5);
@ -296,14 +310,14 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
});
gridPaneOrder.add(rippleLabel=new Label("Pass Band Ripple"), 0,1);
gridPaneOrder.add( ripple, 1,1);
controlPane.getChildren().add(gridPaneOrder);
// TODO Auto-generated method stub
return controlPane;
}
/**
* Set correct filter type from filter type combo box selection.
*/
@ -363,17 +377,17 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
filterParams.filterBand == FilterBand.BANDSTOP ||
filterParams.filterBand == FilterBand.LOWPASS) {
if (filterParams.lowPassFreq > niquist) {
PamController.getInstance();
PamController.getInstance();
PamDialogFX.showWarning(PamController.getMainStage(), "Filter Settings", "The low pass cut off frequency is too high");
return null;
return null;
}
}
if (filterParams.filterBand == FilterBand.BANDPASS ||
filterParams.filterBand == FilterBand.BANDSTOP ||
filterParams.filterBand == FilterBand.HIGHPASS) {
if (filterParams.highPassFreq > niquist) {
PamDialogFX.showWarning(PamController.getMainStage(),"Filter Settings", "The high pass cut off frequency is too high");
return null;
PamDialogFX.showWarning(PamController.getMainStage(),"Filter Settings", "The high pass cut off frequency is too high");
return null;
}
}
@ -385,19 +399,19 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
return filterParams;
}
public void setSampleRate(float sampleRate) {
this.sampleRate = sampleRate;
filterMethod = FilterMethod.createFilterMethod(sampleRate, filterParams);
}
public Node createBodeGraph(){
pamBorderPane=new PamBorderPane();
//pamBorderPane.setPadding(new Insets(0, 0, 0, 10));
pamBorderPane.setPrefWidth(500);
final ToggleGroup group = new ToggleGroup();
logScale = new PamRadioButton("Log Scale");
logScale.setOnAction((action)->{
@ -409,22 +423,22 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
linScale.setOnAction((action)->{
setGraphLogAxis(!linScale.isSelected());
});
final PamHBox scalePane=new PamHBox();
scalePane.setPadding(new Insets(5));
scalePane.setSpacing(5);
scalePane.getChildren().addAll(linScale, logScale);
plotLogChart=createBodeChart(logarithmAxis=new LogarithmicAxis(10,50000));
plotLinChart=createBodeChart(new NumberAxis(0, 50000, 10000));
pamBorderPane.setTop(scalePane);
pamBorderPane.setCenter(plotLogChart);
return pamBorderPane;
}
/**
* Convenience function to stop code repitition. Creates a line chart fro pane with specified x axis.
* @param xAxis - x axis
@ -434,13 +448,13 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
PamLineChart<Number, Number> plotChart=new PamLineChart<Number, Number>(xAxis, new NumberAxis());
plotChart.setLegendVisible(false);
plotChart.setCreateSymbols(false);
plotChart.getXAxis().setLabel("Frequency (Hz)");
plotChart.getYAxis().setLabel("dB");
plotChart.getYAxis().setAutoRanging(false);
plotChart.getXAxis().setSide(Side.TOP);
/**
* HACK. Make sure the graph updates once the axis has a width.
*/
@ -459,7 +473,7 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
});
return plotChart;
}
@Override
public Node getContentNode() {
return mainPane;
@ -471,7 +485,7 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
setSettings();
}
/**
* Set controls to input params.
*/
@ -516,19 +530,19 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
}
// highCut.setText(String.format("%1.1f", filterParams.highPassFreq));
// highCut.setText(String.format("%1.1f", filterParams.highPassFreq));
highCut.getValueFactory().setValue(Double.valueOf(Float.valueOf(filterParams.highPassFreq).doubleValue()));
// lowCut.setText(String.format("%1.1f", filterParams.lowPassFreq));
// lowCut.setText(String.format("%1.1f", filterParams.lowPassFreq));
lowPass.getValueFactory().setValue(Double.valueOf(Float.valueOf(filterParams.lowPassFreq).doubleValue()));
filterOrder.getValueFactory().setValue(filterParams.filterOrder);
setRippleParam();
logScale.setSelected(filterParams.scaleType == FilterParams.SCALE_LOG);
linScale.setSelected(filterParams.scaleType == FilterParams.SCALE_LIN);
filterMethod = FilterMethod.createFilterMethod(sampleRate, filterParams);
//update control disable status
enableControls();
//update graph
@ -536,7 +550,7 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
setXAxisRange(10, sampleRate/2.);
}
void setRippleParam() {
int filtType = filterTypes.getSelectionModel().getSelectedIndex();
switch(filtType) {
@ -549,7 +563,7 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
break;
}
}
private void enableControls() {
int filterType = filterTypes.getSelectionModel().getSelectedIndex();
boolean haveFilter = filterType > 0;
@ -573,15 +587,15 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
break;
}
boolean isArb = filterType == 4;
// normalPanel.setVisible(isArb == false);
// arbPanel.setVisible(isArb);
// normalPanel.setVisible(isArb == false);
// arbPanel.setVisible(isArb);
}
@Override
public String getName() {
return "Filter Pane";
}
/**
* A VBox which holds all the main controls for the pane but not the graph. Can be used to add in custom controls such
* as a source level pane.
@ -590,15 +604,15 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
public PamVBox getControlPane() {
return controlPane;
}
/************Bode Graph************/
private int yScaleIndex = 0;
private double[] yScales = {-90, -60, -30};
/**
* Set the graph axis to a log or linear scale.
* @param log - true to set chart with frequency log scale.
@ -614,7 +628,7 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
//setYAxisRange(yScales[0],10);
updateBodeGraph();
}
/**
* Update the bode graph
*/
@ -629,7 +643,7 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
plotLinChart.getData().add(createFilterPoints((ValueAxis<Number>) plotLinChart.getXAxis()));
}
}
/**
* Set y axis of graphs
*/
@ -639,7 +653,7 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
((NumberAxis) plotLinChart.getXAxis()).setLowerBound(0);
((NumberAxis) plotLinChart.getXAxis()).setUpperBound(max);
}
//Set x axis of graphs.
private void setYAxisRange(double min, double max){
//System.out.println("Set y axis range: min "+min+" max "+max);
@ -647,13 +661,13 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
((NumberAxis) plotLinChart.getYAxis()).setUpperBound(max);
plotLinChart.getYAxis().requestLayout();
plotLinChart.getYAxis().requestAxisLayout();
((NumberAxis) plotLogChart.getYAxis()).setLowerBound(min);
((NumberAxis) plotLogChart.getYAxis()).setUpperBound(max);
plotLogChart.getYAxis().requestLayout();
plotLogChart.getYAxis().requestAxisLayout();
}
/**
* Get the scale type from the graph.
* @return
@ -666,7 +680,7 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
return FilterParams.SCALE_LIN;
}
}
/**
* Create a data series for a filter. The function bases the data points on the pixel length of the chart frequency axis. This
* is important because a log scale is used which would mess up if a data point was created at regular frequency, rather than pixel
@ -675,17 +689,17 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
* @return a data series to add to the line chart
*/
private Series<Number, Number> createFilterPoints(ValueAxis<Number> axis){
Series<Number, Number> series = new Series<Number, Number>();
/*
* It's on a log scale, so set up enough points to fill the plot on
* a log scale
*/
//total number of pixels on axis
// double pixels=Math.abs(axis.getDisplayPosition(axis.getLowerBound())-axis.getDisplayPosition(axis.getUpperBound()));
// double pixels=Math.abs(axis.getDisplayPosition(axis.getLowerBound())-axis.getDisplayPosition(axis.getUpperBound()));
double pixels=axis.getWidth();
int nPoints = (int) Math.max(pixels, 1024);
//System.out.println("Update bode graph WIDTH: "+ pixels+ " height: " +this.plotLogChart.getYAxis().getHeight()+ this.plotLogChart.getWidth());
double xScale = pixels / (double) nPoints;
@ -693,7 +707,7 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
double[] freqPoints = new double[nPoints];
double[] gainPoints = new double[nPoints];
double[] phasePoints = new double[nPoints];
int i=0;
while (i < freqPoints.length) {
freqPoints[i] = axis.getValueForDisplay(i*xScale).doubleValue();
@ -702,17 +716,17 @@ public class FilterPaneFX extends SettingsPane<FilterParams> {
/ filterMethod.getFilterGainConstant();
phasePoints[i] = filterMethod.getFilterPhase(
freqPoints[i] / sampleRate * 2 * Math.PI);
// System.out.println("freqPoints[i]: "+freqPoints[i] +" gainPoints[i] "+gainPoints[i]+
// " nPoints: "+nPoints+" xScale "+xScale+ " sampleRate: "+sampleRate + " pixels "+pixels);
// System.out.println("freqPoints[i]: "+freqPoints[i] +" gainPoints[i] "+gainPoints[i]+
// " nPoints: "+nPoints+" xScale "+xScale+ " sampleRate: "+sampleRate + " pixels "+pixels);
series.getData().add(new Data<Number, Number>(freqPoints[i], 20. * Math.log10(gainPoints[i])));
i++;
}
return series;
}
private void checkYScale() {
double yScale = 0;
if (plotLogChart.getYAxis() == null) return;

View File

@ -72,7 +72,7 @@ public class FreqBandPane extends PamGridPane {
if (after>sampleRate/2.) highPassFreq.getValueFactory().setValue(sampleRate/2.);
});
highPassFreq.setEditable(true);
highPassFreq.setPrefWidth(140);
//highPassFreq.setPrefWidth(140);
//highCut.setPrefColumnCount(6);
if (orientation==Orientation.VERTICAL){
@ -94,7 +94,7 @@ public class FreqBandPane extends PamGridPane {
});
lowPassFreq.setEditable(true);
lowPassFreq.setPrefWidth(140);
//lowPassFreq.setPrefWidth(140);
if (orientation==Orientation.VERTICAL){

View File

@ -183,6 +183,7 @@ public class SimpleFilterPaneFX extends DynamicSettingsPane<FFTFilterParams>{
@Override
public FFTFilterParams getParams(FFTFilterParams fftFilterParams) {
if (fftFilterParams==null) fftFilterParams=new FFTFilterParams();
fftFilterParams.filterBand = getBand();
try {
//if (fftFilterParams.filterBand != FilterBand.HIGHPASS) {

View File

@ -110,6 +110,9 @@ public class DLPredictionPane extends PamBorderPane implements TDSettingsPane {
private void layoutColourPanes(DLClassName[] classNames){
if (classNames==null) return;
//System.out.println("Class name map: " + dlPredictionPlotInfoFX.getDlControl().getDLParams().classNameMap);
ArrayList<PredictionColourPane> colourPanes = new ArrayList<PredictionColourPane>();

View File

@ -307,7 +307,13 @@ public class DLPredictionPlotInfoFX extends GenericLinePlotInfo {
@Override
public double[][] getDetData(PamDataUnit pamDataUnit) {
double[] data = PamArrayUtils.float2Double(((DLDataUnit) pamDataUnit).getPredicitionResult().getPrediction());
return new double[][] {data};
double[][] dataD = new double[data.length][];
for (int i=0; i<data.length; i++) {
dataD[i] = new double[] {data[i]};
}
return dataD;
}
}

View File

@ -72,7 +72,8 @@ public class StandardAdvModelPane extends SettingsPane<StandardModelParams> {
defaultTogglePane = createTogglePane();
transfromPane = new DLImageTransformPane();
mainPane.setPadding(new Insets(5,5,5,5));
mainPane.setPadding(new Insets(2,2,2,2));
mainPane.setPrefWidth(400);
}

View File

@ -18,10 +18,14 @@ import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.Labeled;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.control.Spinner;
import javafx.scene.control.Tooltip;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.FileChooser;
@ -34,6 +38,7 @@ import pamViewFX.fxNodes.PamGridPane;
import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.PamSpinner;
import pamViewFX.fxNodes.PamVBox;
import pamViewFX.fxNodes.flipPane.FlipPane;
import rawDeepLearningClassifier.dlClassification.DLClassiferModel;
/**
@ -111,12 +116,14 @@ public abstract class StandardModelPane extends SettingsPane<StandardModelParams
protected PamHBox defaultSegBox;
private ProgressIndicator modelLoadIndicator;
private ProgressIndicator modelLoadIndicator;
public StandardModelPane(DLClassiferModel soundSpotClassifier) {
super(null);
this.dlClassifierModel=soundSpotClassifier;
mainPane = createPane();
//the directory chooser.
fileChooser = new FileChooser();
@ -283,7 +290,7 @@ public abstract class StandardModelPane extends SettingsPane<StandardModelParams
vBoxHolder = new PamVBox();
vBoxHolder.setSpacing(5);
vBoxHolder.getChildren().addAll(classiferInfoLabel, hBox, advSettings, classiferInfoLabel2, gridPane);
mainPane.setCenter(vBoxHolder);
return mainPane;
@ -336,6 +343,11 @@ public abstract class StandardModelPane extends SettingsPane<StandardModelParams
* @param advSettingsButton - the advanced settings.
*/
public void showAdvPane(PamButton advSettingsButton) {
// dlClassifierModel.getDLControl().getSettingsPane().setAdvPaneContents(getAdvSettingsPane().getContentNode());
// dlClassifierModel.getDLControl().getSettingsPane().flipToBack();
if (popOver==null) {
popOver = new PopOver();
@ -352,6 +364,9 @@ public abstract class StandardModelPane extends SettingsPane<StandardModelParams
popOver.show(advSettingsButton);
}
/**
* Update the path label and tool tip text;
@ -424,6 +439,15 @@ public abstract class StandardModelPane extends SettingsPane<StandardModelParams
//instead of a using changing a control.
currParams.classNames = paramsClone.classNames;
currParams.numClasses = paramsClone.numClasses;
if (paramsClone.classNames == null && speciesIDBox.getItems()!=null) {
String[] classNames = new String[speciesIDBox.getItems().size()];
for (int i=0; i<speciesIDBox.getItems().size(); i++) {
classNames[i] = speciesIDBox.getItems().get(i);
}
currParams.classNames = this.dlClassifierModel.getDLControl().getClassNameManager().makeClassNames(classNames);
}
currParams.useDefaultSegLen = usedefaultSeg.isSelected();
@ -495,8 +519,6 @@ public abstract class StandardModelPane extends SettingsPane<StandardModelParams
}
}
}
@Override

View File

@ -206,6 +206,7 @@ public class KetosClassifier implements DLClassiferModel, PamSettings {
@Override
public DLClassName[] getClassNames() {
//System.out.println("Ketos Model: " + ketosDLParams.numClasses);
return ketosDLParams.classNames;
}

View File

@ -35,20 +35,29 @@ public class KetosModelPane extends StandardModelPane {
@Override
public void newModelSelected(File file) {
//A ketos model contains information on the transforms, duration and the class names.
this.setCurrentSelectedFile(file);
this.setParamsClone(new KetosDLParams());
//prep the model with current parameters;
ketosClassifier.getKetosWorker().prepModel(getParams(getParamsClone()), ketosClassifier.getDLControl());
//get the model transforms calculated from the model by SoundSpoyWorker and apply them to our temporary params clone.
// System.out.println("Ketos transforms 1: " + this.ketosClassifier.getKetosWorker().getModelTransforms());
getParamsClone().dlTransfroms = this.ketosClassifier.getKetosWorker().getModelTransforms();
if (getParamsClone().defaultSegmentLen!=null) {
usedefaultSeg.setSelected(true);
}
//System.out.println("Ketos: " + getParamsClone().dlTransfroms.size());
///set the advanced pane parameters.
getAdvSettingsPane().setParams(getParamsClone());
}
}

View File

@ -113,7 +113,10 @@ public class KetosWorker extends DLModelWorker<KetosResult> {
ketosDLParams.binaryClassification[i] = true; //set default to true.
}
}
if (ketosParams.classNames!=null) {
ketosDLParams.classNames = dlControl.getClassNameManager().makeClassNames(ketosParams.classNames);
}
// if (dlParams.classNames!=null) {
// for (int i = 0; i<dlParams.classNames.length; i++) {

View File

@ -4,6 +4,7 @@ import java.util.ArrayList;
import org.controlsfx.control.PopOver;
import PamController.FlipSettingsPane;
import PamController.SettingsPane;
import PamDetection.RawDataUnit;
import PamView.dialog.warn.WarnOnce;
@ -14,10 +15,10 @@ import clipgenerator.ClipDataUnit;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.PopupControl;
import javafx.scene.control.Spinner;
import javafx.scene.control.Tooltip;
import javafx.scene.control.Alert.AlertType;
@ -49,6 +50,8 @@ import warnings.PamWarning;
public class RawDLSettingsPane extends SettingsPane<RawDLParams>{
public static double MAX_WIDTH = 250;
/**
* The source for the FFT data source.
*/
@ -111,6 +114,10 @@ public class RawDLSettingsPane extends SettingsPane<RawDLParams>{
private Label infoLabel;
private Object flipPane;
private PopupControl advLabel;
public RawDLSettingsPane(DLControl dlControl){
super(null);
this.dlControl=dlControl;
@ -128,8 +135,10 @@ public class RawDLSettingsPane extends SettingsPane<RawDLParams>{
mainPane.setCenter(createDLPane());
mainPane.setPadding(new Insets(5,5,5,5));
mainPane.setMinHeight(400);
mainPane.setMaxWidth(250);
mainPane.setPrefWidth(250);
mainPane.setMaxWidth(MAX_WIDTH);
mainPane.setPrefWidth(MAX_WIDTH);
//this.getAdvPane().setMaxWidth(MAX_WIDTH);
//mainPane.getStylesheets().add(PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getDialogCSS());
@ -253,7 +262,7 @@ public class RawDLSettingsPane extends SettingsPane<RawDLParams>{
return vBox;
}
/**
* Create the data selector.
@ -483,7 +492,7 @@ public class RawDLSettingsPane extends SettingsPane<RawDLParams>{
@Override
public Node getContentNode() {
public Pane getContentNode() {
return mainPane;
}
@ -501,4 +510,6 @@ public class RawDLSettingsPane extends SettingsPane<RawDLParams>{
return sourcePane.getSource();
}
}

View File

@ -39,7 +39,6 @@ import rawDeepLearningClassifier.layoutFX.exampleSounds.ExampleSoundFactory.Exam
*/
public abstract class DLTransformImage extends PamBorderPane{
/**
* Plot pane.
*/
@ -70,7 +69,6 @@ public abstract class DLTransformImage extends PamBorderPane{
*/
private SpectrogramImage specImage = null;
/**
* The current 1D transform data.
*/
@ -97,7 +95,7 @@ public abstract class DLTransformImage extends PamBorderPane{
private RangeSlider timeSlider;
/**
* tIME BINS.
* Time bins.
*/
private int[] timeBins = new int[2];
@ -139,6 +137,7 @@ public abstract class DLTransformImage extends PamBorderPane{
plotPane.repaint();
});
transformschoiceBox.setConverter(new DLTransformConverter());
transformschoiceBox.setPrefWidth(170);
plotPane.getPlotCanvas().widthProperty().addListener((obsval, oldval, newval)->{
plotPane.repaint();
@ -174,6 +173,7 @@ public abstract class DLTransformImage extends PamBorderPane{
updateExampleSound(newval);
});
speciesChoiceBox.getSelectionModel().select(0);
speciesChoiceBox.setPrefWidth(170);
PamHBox hBox = new PamHBox();
hBox.setAlignment(Pos.CENTER_RIGHT);

View File

@ -77,7 +77,7 @@ public class DataTransformPaneFactory {
((SimpleTransformPane) settingsPane).setSpinnerMinMaxValues(1, -1000.0, 1000.0, 0.1);
break;
case SPECCROPINTERP:
settingsPane = new SimpleTransformPane((SimpleTransform) dlTransfrom, new String[]{"Min. Freq. ", "Max. Freq. ", " No. bins "}, new String[]{"Hz", "Hz", ""}, 2);
settingsPane = new SimpleTransformPane((SimpleTransform) dlTransfrom, new String[]{"Min. Freq. ", "Max. Freq. ", "No. bins "}, new String[]{"Hz", "Hz", ""}, 2);
((SimpleTransformPane) settingsPane).setSpinnerMinMaxValues(0, 0.0, 500000.0, 100.); //hmmmm would be nice to have the sample rate here...
((SimpleTransformPane) settingsPane).setSpinnerMinMaxValues(1, 0.0, 500000.0, 100.);
((SimpleTransformPane) settingsPane).setSpinnerMinMaxValues(2, 0, Integer.MAX_VALUE, 10);

View File

@ -25,6 +25,7 @@ public class FFTTransformPane extends SimpleTransformPane {
//System.out.println("Create step list: " + createStepList().size());
PamSpinner<Number> spinner = new PamSpinner<Number>(createStepList());
spinner.getValueFactory().setConverter(new NumberConverter());
spinner.setPrefWidth(PREF_SPINNER_WIDITH);
return spinner;
}
else return super.createSpinner(i);

View File

@ -29,7 +29,7 @@ public class SimpleTransformPane extends DLTransformPane {
/**
* The default spinner width.
*/
protected static int prefSpinnerWidth = 80;
protected static int PREF_SPINNER_WIDITH = 70;
int nParamCol=10;
@ -80,7 +80,7 @@ public class SimpleTransformPane extends DLTransformPane {
gridPane.setHgap(5);
gridPane.setVgap(5);
gridPane.setPadding(new Insets(5,5.,5.,15));
gridPane.setPadding(new Insets(2,2,2,2));
PamSpinner<Number> spinner;
@ -139,7 +139,9 @@ public class SimpleTransformPane extends DLTransformPane {
* @return a new spinner
*/
protected PamSpinner<Number> createSpinner(int i) {
return new PamSpinner<Number>(0.0, Double.MAX_VALUE, 2, 0.01);
PamSpinner spnner = new PamSpinner<Number>(0.0, Double.MAX_VALUE, 2, 0.01);
spnner.setPrefWidth(PREF_SPINNER_WIDITH);
return spnner;
}
/**

View File

@ -15,9 +15,14 @@ public class ExampleSoundFactory {
*
*/
public enum ExampleSoundType {
BAT_CALL("Bat Call (Myotis daubentonii)"),
RIGHT_WHALE("Southern Right Whale (Eubalaena australis)");
RIGHT_WHALE("Southern Right Whale (Eubalaena australis)"),
MINKE_WHALE("Minke Whale (Balaenoptera spp.)"),
HUMPBACK_WHALE("Humpback whale (Megaptera novaeangliae) ");
private final String text;
@ -56,6 +61,16 @@ public class ExampleSoundFactory {
path = getClass().getResource("/Resources/exampleSounds/southern_right_whale_clip2.wav");
exampleSound = new SimpleExampleSound(path);
break;
case MINKE_WHALE:
//file = new File("src/rawDeepLearningClassifier/layoutFX/exampleSounds/southern_right_whale_clip2.wav");
path = getClass().getResource("/Resources/exampleSounds/Minke_whale.wav");
exampleSound = new SimpleExampleSound(path);
break;
case HUMPBACK_WHALE:
//file = new File("src/rawDeepLearningClassifier/layoutFX/exampleSounds/southern_right_whale_clip2.wav");
path = getClass().getResource("/Resources/exampleSounds/Humpback_whale.wav");
exampleSound = new SimpleExampleSound(path);
break;
default:
break;
}

View File

@ -144,6 +144,7 @@ public class PlaybackControl extends PamControlledUnit implements PamSettings {
playbackSystem = findPlaybackSystem(sourceDataBlock);
playbackProcess.noteNewSettings();
playbackSidePanel.newSettings();
if (playBackGUI!=null) playBackGUI.notifyGUIChange(PamController.CHANGED_PROCESS_SETTINGS);
// if (this.getSidePanel() != null){
// this.getSidePanel().getPanel().setVisible(!isRealTimePlayback());
// }

View File

@ -0,0 +1,110 @@
package soundPlayback.fx;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import pamViewFX.PamGuiManagerFX;
import pamViewFX.fxGlyphs.PamGlyphDude;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamButton;
import pamViewFX.fxNodes.PamHBox;
import soundPlayback.preprocess.PlaybackFilter;
import soundPlayback.preprocess.PreProcessFXPane;
public class FilterSidePane implements PreProcessFXPane {
private Label label;
private FilterSlider filterSlider;
private PlaybackFilter playBackFilter;
private PamBorderPane mainPane;
private PamButton defaultGainButton;
public FilterSidePane(PlaybackFilter playBackFilter) {
this.playBackFilter = playBackFilter;
filterSlider = new FilterSlider();
filterSlider.getSlider().setTooltip(new Tooltip("High pass filter the data before playback"));
filterSlider.addChangeListener((oldval, newVal, obsVal)->{
filterChanged();
});
defaultGainButton = new PamButton("off");
defaultGainButton.setGraphic(PamGlyphDude.createPamIcon("mdi2r-refresh", PamGuiManagerFX.iconSize-3));
defaultGainButton.setPrefWidth(70);
defaultGainButton.setOnAction((action)->{
filterSlider.setDataValue(filterSlider.getMinValue());
});
label = new Label("Filter");
//label.setGraphic(PamGlyphDude.createPamIcon("mdi2f-filter", PamGuiManagerFX.iconSize));
PamHBox hBox = new PamHBox();
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.setSpacing(5);
hBox.getChildren().addAll(PamGlyphDude.createPamIcon("mdi2f-filter", PamGuiManagerFX.iconSize), filterSlider);
filterSlider.setMaxWidth(Double.MAX_VALUE);
HBox.setHgrow(filterSlider, Priority.ALWAYS);
this.mainPane = new PamBorderPane();
this.mainPane.setCenter(hBox);
}
protected void filterChanged() {
playBackFilter.setValue(filterSlider.getDataValue());
sayFilter();
}
@Override
public void update() {
filterSlider.setDataValue(playBackFilter.getValue());
sayFilter();
}
private void sayFilter() {
//playGainSlider.setTextLabel(playbackGain.getTextValue());
label.setText(playBackFilter.getTextValue());
defaultGainButton.setDisable(false);
if (playBackFilter.getValue()==filterSlider.getMinValue()) {
defaultGainButton.setDisable(true);
}
}
@Override
public Pane getPane() {
return mainPane;
}
@Override
public Label getLabel() {
return label;
}
@Override
public Node getDefaultButton() {
return defaultGainButton;
}
}

View File

@ -0,0 +1,60 @@
package soundPlayback.fx;
/**
* Slider for the high pass filter sound out process.
* @author Jamie Macaulay
*
*/
public class FilterSlider extends PlaySliderPane {
private static final double MIN = 0.5e-3;
private static final double MAX = 0.5;
private static final double NSTEP = 100;
public FilterSlider() {
super();
}
@Override
public double valueToPos(double filter) {
if (filter <= MIN) {
return 0;
}
else {
double grad = (Math.log(MAX)-Math.log(MIN))/NSTEP;
int pos = (int) Math.round((Math.log(filter/MIN))/grad);
return pos;
}
}
@Override
public double posToValue(double pos) {
if (pos == 0) {
return 0;
}
else if (pos >= NSTEP) {
return MAX;
}
else {
double grad = (Math.log(MAX)-Math.log(MIN))/NSTEP;
return Math.exp(pos*grad)*MIN;
}
}
@Override
public double getMinValue() {
return 0;
}
@Override
public double getMaxValue() {
return 100;
}
}

View File

@ -67,6 +67,17 @@ public class PlayBackGUI extends PamControlledGUIFX {
}
/**
* Allows the GUI to be notified of changes, e.g. in the PAMController
* @param flag - the change flag.
*/
public void notifyGUIChange(int flag) {
for (Pane sidePane: sidePanes) {
((PlayBackSidePane) sidePane).newSettings();
}
}
}

View File

@ -1,11 +1,16 @@
package soundPlayback.fx;
import java.util.ArrayList;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import pamViewFX.PamGuiFX;
import pamViewFX.PamGuiManagerFX;
import pamViewFX.fxGlyphs.PamGlyphDude;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.PamVBox;
@ -13,6 +18,7 @@ import pamViewFX.fxNodes.sliders.PamSlider;
import soundPlayback.PlaybackControl;
import soundPlayback.preprocess.PlaybackPreprocess;
import soundPlayback.preprocess.PreProcessFXPane;
import soundPlayback.preprocess.PreprocessSwingComponent;
/**
* Th eplay back side pane.
@ -26,6 +32,11 @@ public class PlayBackSidePane extends BorderPane {
*/
private PlaybackControl playBackControl;
/**
* Label which shows which sound ouptut device is being used.
*/
private Label deviceLabel;
public PlayBackSidePane(PlaybackControl playBackControl) {
this.playBackControl=playBackControl;
this.setCenter(createSidePane());
@ -39,29 +50,97 @@ public class PlayBackSidePane extends BorderPane {
PamBorderPane borderPane = new PamBorderPane();
borderPane.setPrefWidth(PamGuiFX.SIDE_PANE_PREF_WIDTH-10);
borderPane.setMaxWidth(Double.MAX_VALUE);
Label titlelabel = new Label("Playback");
PamGuiManagerFX.titleFont2style(titlelabel);
// titlelabel.setGraphic(PamGlyphDude.createPamIcon("mdi2p-play", PamGuiManagerFX.iconSize));
borderPane.setTop(titlelabel);
PamHBox hBox = new PamHBox();
hBox.setSpacing(5);
PamVBox vBox = new PamVBox();
vBox.setSpacing(5);
hBox.getChildren().add(deviceLabel= new Label(""));
borderPane.setCenter(hBox);
borderPane.setBottom(vBox);
PamVBox vBox = new PamVBox();
vBox.setSpacing(0);
vBox.setPadding(new Insets(5,0,0,0));
ArrayList<PlaybackPreprocess> preProcesses = playBackControl.getPlaybackProcess().getPreProcesses();
PreProcessFXPane preProcessFXPane;
for (int i=0; i<preProcesses.size() ; i++) {
//System.out.println("PLAYBACKSIDEPANE: ADDING : " + preProcesses.get(i).toString());
preProcessFXPane = preProcesses.get(i).getSideParPane();
if (preProcessFXPane!=null) {
hBox.getChildren().add(preProcessFXPane.getPane());
PamBorderPane labelHBox = new PamBorderPane();
// labelHBox.setAlignment(Pos.CENTER_LEFT);
// labelHBox.setSpacing(5);
labelHBox.setLeft(preProcessFXPane.getLabel());
labelHBox.setRight(preProcessFXPane.getDefaultButton() == null ? new Label() : preProcessFXPane.getDefaultButton());
vBox.getChildren().add(labelHBox);
vBox.getChildren().add(preProcessFXPane.getPane());
vBox.getChildren().add(new Label(""));
// if (preProcessFXPane.getDefaultButton()!=null) {
//
// //only show the default button when the user is inside the slider to reduce clutter.
// final Node defaultButton = preProcessFXPane.getDefaultButton();
// labelHBox.setOnMouseEntered((e)->{
// defaultButton.setVisible(true);
// });
//
// labelHBox.setOnMouseExited((e)->{
// defaultButton.setVisible(false);
// });
//
// preProcessFXPane.getPane().setOnMouseEntered((e)->{
// defaultButton.setVisible(true);
// });
//
// preProcessFXPane.getPane().setOnMouseExited((e)->{
// defaultButton.setVisible(false);
// });
//
// }
}
}
borderPane.setBottom(vBox);
return borderPane;
}
public void newSettings() {
boolean isRT = playBackControl.isRealTimePlayback();
ArrayList<PlaybackPreprocess> preProcesses = playBackControl.getPlaybackProcess().getPreProcesses();
for (PlaybackPreprocess pp : preProcesses) {
PreProcessFXPane comp = pp.getSideParPane();
if (comp != null) {
comp.update();
}
}
this.setVisible(playBackControl.getPlaybackParameters().getSidebarShow() > 0);
// speedLabel.setVisible(!isRT);
// speedSlider.getSlider().setVisible(!isRT);
// PlaybackParameters params = playbackControl.getPlaybackParameters();
// gainLabel.setText(String.format("Gain %d dB", params.playbackGain));
// gainSlider.setGain(params.playbackGain);
// sayPlaySpeed(speedSlider.getSpeed());
// speedSlider.setSpeed(params.getPlaybackSpeed());
}
}

View File

@ -0,0 +1,106 @@
package soundPlayback.fx;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.Labeled;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import pamViewFX.PamGuiManagerFX;
import pamViewFX.fxGlyphs.PamGlyphDude;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamButton;
import pamViewFX.fxNodes.PamHBox;
import soundPlayback.preprocess.PlaybackDecimator;
import soundPlayback.preprocess.PlaybackGain;
import soundPlayback.preprocess.PreProcessFXPane;
public class PlayDecimatorSidePane implements PreProcessFXPane {
private static final double DEFAULT_PLAY_SPEED = 1;
private PlaybackDecimator playbackDecimator;
private PlaySpeedSlider playSpeedSlider;
private PamBorderPane mainPane;
private Label label;
private PamButton defaultSpeedButton;
public PlayDecimatorSidePane(PlaybackDecimator playbackDecimator) {
this.playbackDecimator = playbackDecimator;
playSpeedSlider = new PlaySpeedSlider();
playSpeedSlider.getSlider().setTooltip(new Tooltip("<html>Adjust the output volume.<br>"+
"N.B. You should also consider turning up the volume in the computers volume controls."));
playSpeedSlider.addChangeListener((oldval, newVal, obsVal)->{
speedChanged();
});
playSpeedSlider.getChildren().add(defaultSpeedButton = new PamButton("x 1"));
defaultSpeedButton.setGraphic(PamGlyphDude.createPamIcon("mdi2r-refresh", PamGuiManagerFX.iconSize-3));
defaultSpeedButton.setPrefWidth(70);
defaultSpeedButton.setOnAction((action)->{
playSpeedSlider.setDataValue(DEFAULT_PLAY_SPEED);
});
label = new Label("Speed");
PamHBox hBox = new PamHBox();
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.setSpacing(5);
hBox.getChildren().addAll(PamGlyphDude.createPamIcon("mdi2p-play", PamGuiManagerFX.iconSize), playSpeedSlider);
playSpeedSlider.setMaxWidth(Double.MAX_VALUE);
HBox.setHgrow(playSpeedSlider, Priority.ALWAYS);
this.mainPane = new PamBorderPane();
this.mainPane.setCenter(hBox);
}
@Override
public void update() {
playSpeedSlider.setVisible(playbackDecimator.makeVisible());
playSpeedSlider.setDataValue(playbackDecimator.getPlaySpeed());
saySpeed();
}
private void saySpeed() {
//playSpeedSlider.setTextLabel("Speed " + playSpeedSlider.getRatioString());
label.setText("Speed " + playSpeedSlider.getRatioString());
}
protected void speedChanged() {
defaultSpeedButton.setDisable(false);
playbackDecimator.setPlaySpeed(playSpeedSlider.getDataValue());
if (playSpeedSlider.getDataValue()== DEFAULT_PLAY_SPEED) {
defaultSpeedButton.setDisable(true);
}
saySpeed();
}
@Override
public Pane getPane() {
return mainPane;
}
@Override
public Label getLabel() {
return label;
}
@Override
public Node getDefaultButton() {
return defaultSpeedButton;
}
}

View File

@ -1,51 +1,153 @@
package soundPlayback.fx;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.text.Text;
import pamViewFX.PamGuiManagerFX;
import pamViewFX.fxGlyphs.PamGlyphDude;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamButton;
import pamViewFX.fxNodes.PamHBox;
import soundPlayback.preprocess.PlaybackGain;
import soundPlayback.preprocess.PreProcessFXPane;
import soundPlayback.swing.BasicSidebarLayout;
import soundPlayback.fx.PlayGainSlider;
public class PlayGainSidePane implements PreProcessFXPane {
private PlaybackGain playbackGain;
private BasicSidebarLayout basicSidebarLayout;
private PlayGainSlider playGainSlider;
private PamBorderPane mainPane;
private Label label;
private Text medVol;
private Text lowVol;
private Text highVol;
private PamButton defaultGainButton;
private Label iconLabel;
private static final double DEFAULT_GAIN = 0;
// private PamHBox labelHBox;
public PlayGainSidePane(PlaybackGain playbackGain) {
this.playbackGain = playbackGain;
playGainSlider = new PlayGainSlider();
basicSidebarLayout.setToolTipText("<html>Adjust the output volume.<br>"+
"N.B. You should also consider turning up the volume in the computers volume controls.");
playGainSlider.getSlider().setTooltip(new Tooltip("<html>Adjust the output volume.<br>"+
"N.B. You should also consider turning up the volume in the computers volume controls."));
playGainSlider.addChangeListener((oldval, newVal, obsVal)->{
gainChanged();
});
gainChanged();
});
//create the label which also has a default button
defaultGainButton = new PamButton("0 dB");
defaultGainButton.setGraphic(PamGlyphDude.createPamIcon("mdi2r-refresh", PamGuiManagerFX.iconSize-3));
defaultGainButton.setPrefWidth(70);
defaultGainButton.setOnAction((action)->{
playGainSlider.setDataValue(0);
});
label = new Label("Gain");
// labelHBox = new PamHBox();
// labelHBox.setAlignment(Pos.CENTER_LEFT);
// labelHBox.setSpacing(5);
// labelHBox.getChildren().addAll(label, defaultGainButton);
lowVol = PamGlyphDude.createPamIcon("mdi2v-volume-low", PamGuiManagerFX.iconSize);
medVol = PamGlyphDude.createPamIcon("mdi2v-volume-medium", PamGuiManagerFX.iconSize);
highVol = PamGlyphDude.createPamIcon("mdi2v-volume-high", PamGuiManagerFX.iconSize);
iconLabel = new Label();
this.mainPane = new PamBorderPane();
PamHBox hBox = new PamHBox();
hBox.setAlignment(Pos.CENTER_LEFT);
hBox.setSpacing(5);
hBox.getChildren().addAll(iconLabel, playGainSlider);
playGainSlider.setMaxWidth(Double.MAX_VALUE);
HBox.setHgrow(playGainSlider, Priority.ALWAYS);
this.mainPane.setCenter(hBox);
setLabelVolGrpahic();
}
private void setLabelVolGrpahic() {
//System.out.println("Playback gain: " + playbackGain.getGaindB());
if (playbackGain.getGaindB()<PlayGainSlider.MINGAIN+20 && iconLabel.getGraphic()!=lowVol)
iconLabel.setGraphic(lowVol);
else if (playbackGain.getGaindB()>=PlayGainSlider.MINGAIN+20 && playbackGain.getGaindB()<PlayGainSlider.MAXGAIN-20
&& iconLabel.getGraphic()!=medVol) {
iconLabel.setGraphic(medVol);
}
else if ( playbackGain.getGaindB()>=PlayGainSlider.MAXGAIN-20 && iconLabel.getGraphic()!=highVol) {
iconLabel.setGraphic(highVol);
}
}
@Override
public void update() {
playGainSlider.setDataValue(playbackGain.getGaindB());
setLabelVolGrpahic();
sayGain();
}
private void sayGain() {
basicSidebarLayout.setTextLabel(playbackGain.getTextValue());
//playGainSlider.setTextLabel(playbackGain.getTextValue());
label.setText(playbackGain.getTextValue());
}
private void gainChanged() {
defaultGainButton.setDisable(false);
playbackGain.setGaindB(playGainSlider.getDataValue());
setLabelVolGrpahic();
sayGain();
if (playbackGain.getGaindB()==DEFAULT_GAIN) {
defaultGainButton.setDisable(true);
}
}
@Override
public Pane getPane() {
return null;
return mainPane;
}
@Override
public Node getLabel() {
return label;
}
@Override
public Node getDefaultButton() {
return defaultGainButton;
}
}

View File

@ -7,9 +7,9 @@ package soundPlayback.fx;
*/
public class PlayGainSlider extends PlaySliderPane {
private static final int MINGAIN = -20;
static final int MINGAIN = -20;
private static final int MAXGAIN = 60;
static final int MAXGAIN = 60;
public PlayGainSlider() {
@ -26,4 +26,5 @@ public class PlayGainSlider extends PlaySliderPane {
return MAXGAIN;
}
}

View File

@ -1,31 +1,72 @@
package soundPlayback.fx;
import javafx.beans.value.ChangeListener;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.paint.Color;
import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.sliders.PamSlider;
/**
* Default slider pane.
* Default slider pane for the sound output sliders.
*
* @author Jamie Macaulay
*
*/
public abstract class PlaySliderPane {
public abstract class PlaySliderPane extends PamHBox {
/**
* The slider to chnage the value of something.
*/
private PamSlider slider;
/**
* The label which shows a slider value
*/
private Label sliderLabel;
public PlaySliderPane() {
slider = new PamSlider(getMinValue(), getMaxValue(), getMinValue());
//slider.setShowTickMarks(true);
slider.setMaxWidth(Double.POSITIVE_INFINITY);
//slider.setShowTickLabels(true);
//setSliderSize();
sliderLabel = new Label();
slider.setId("thickslider");
HBox.setHgrow(slider, Priority.ALWAYS);
this.setAlignment(Pos.CENTER_LEFT);
this.setSpacing(5);
slider.setTrackColor(Color.rgb(0,204,204));
slider.setTrackColor(Color.DODGERBLUE);
//slider.setTrackColor(Color.GRAY);
this.getChildren().addAll(slider,sliderLabel);
}
/**
* get the minimum value of the slider
* @return the minimum value fo the slider.
*/
public abstract double getMinValue();
/**
* Get the maximum value of the slider.
* @return the maximum value of the slider.
*/
public abstract double getMaxValue();
/**
* @return the slider
*/
public PamSlider getSlider() {
public Slider getSlider() {
return slider;
}
@ -34,7 +75,7 @@ public abstract class PlaySliderPane {
* @return the real scaled value
*/
public double getDataValue() {
return slider.getValue();
return posToValue(slider.getValue());
}
/**
@ -42,7 +83,7 @@ public abstract class PlaySliderPane {
* @param value the scaled value.
*/
public void setDataValue(double value) {
slider.setValue(value);
slider.setValue(valueToPos(value));
}
/**
@ -53,4 +94,28 @@ public abstract class PlaySliderPane {
slider.valueProperty().addListener(changeListener);
}
public void setTextLabel(String textValue) {
this.sliderLabel.setText(textValue);
}
/**
* Get the slider position from a value (usually value = out).
* @param value
* @return
*/
public double valueToPos(double value) {
return value;
}
/**
* Get the value from a slider position (usually pos = out).
* @param pos - the position of the slider.
* @return - the corresponding value.
*/
public double posToValue(double pos) {
return pos;
}
}

View File

@ -0,0 +1,59 @@
package soundPlayback.fx;
import java.text.DecimalFormat;
public class PlaySpeedSlider extends PlaySliderPane {
private static final double MINSPEED = -6;
private static final double MAXSPEED = 6;
public PlaySpeedSlider() {
this.getSlider().setBlockIncrement(1);
}
public String getRatioString() {
return getRatioString(getDataValue());
}
public static String getRatioString(double speed) {
if (speed >= 1) {
DecimalFormat df = new DecimalFormat(" x #.##");
return df.format(speed);
}
else if (speed <= 0) {
return "Err 0";
}
else {
DecimalFormat df = new DecimalFormat(" \u00F7 #.##");
return df.format(1./speed);
}
}
@Override
public double getMinValue() {
return MINSPEED;
}
@Override
public double getMaxValue() {
return MAXSPEED;
}
@Override
public double valueToPos(double value) {
return super.valueToPos(Math.log(value)/Math.log(2.));
}
@Override
public double posToValue(double pos) {
return Math.pow(2,super.posToValue(pos));
}
}

View File

@ -11,6 +11,7 @@ import soundPlayback.PBSampleRateData;
import soundPlayback.PlaybackControl;
import soundPlayback.PlaybackParameters;
import soundPlayback.PlaybackProcess;
import soundPlayback.fx.PlayDecimatorSidePane;
import soundPlayback.swing.DecimatorSideBar;
public class PlaybackDecimator implements PlaybackPreprocess {
@ -22,6 +23,8 @@ public class PlaybackDecimator implements PlaybackPreprocess {
private PlaybackControl playbackControl;
private DecimatorSideBar decimatorSideBar;
private PlayDecimatorSidePane playDecimatorSidePane;
public PlaybackDecimator(PlaybackControl playbackControl) {
this.playbackControl = playbackControl;
@ -72,7 +75,9 @@ public class PlaybackDecimator implements PlaybackPreprocess {
@Override
public PreProcessFXPane getSideParPane() {
// TODO Auto-generated method stub
return null;
if (playDecimatorSidePane==null) {
playDecimatorSidePane = new PlayDecimatorSidePane(this);
}
return playDecimatorSidePane;
}
}

View File

@ -12,6 +12,8 @@ import PamUtils.FrequencyFormat;
import PamUtils.PamUtils;
import soundPlayback.PlaybackControl;
import soundPlayback.PlaybackParameters;
import soundPlayback.fx.FilterSidePane;
import soundPlayback.fx.PlayDecimatorSidePane;
import soundPlayback.swing.PlayFilterSideBar;
/**
@ -31,6 +33,8 @@ public class PlaybackFilter implements PlaybackPreprocess {
private PlayFilterSideBar playFilterSideBar;
private FilterSidePane filterSidePane;
public PlaybackFilter(PlaybackControl playbackControl) {
this.playbackControl = playbackControl;
playFilterSideBar = new PlayFilterSideBar(this);
@ -70,6 +74,7 @@ public class PlaybackFilter implements PlaybackPreprocess {
}
public String getTextValue() {
//System.out.println("Playback control Sample rate: " + playbackControl.getSourceSampleRate() + " val: " + getValue());
double f = getValue() * playbackControl.getSourceSampleRate();
if (f == 0) {
return "High pass filter off";
@ -114,8 +119,10 @@ public class PlaybackFilter implements PlaybackPreprocess {
@Override
public PreProcessFXPane getSideParPane() {
// TODO Auto-generated method stub
return null;
if (filterSidePane==null) {
filterSidePane = new FilterSidePane(this);
}
return filterSidePane;
}
}

View File

@ -1,5 +1,7 @@
package soundPlayback.preprocess;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
/**
@ -21,4 +23,14 @@ public interface PreProcessFXPane {
*/
public void update();
/**
* Pane which shows the name of the pre-process.
*/
public Node getLabel();
/**
* Pane which allows the user to switch to a default.
*/
public Node getDefaultButton();
}