mirror of
https://github.com/PAMGuard/PAMGuard.git
synced 2024-11-21 22:52:22 +00:00
commit
3abaff0379
@ -6,7 +6,7 @@
|
|||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -111,3 +111,4 @@ settings.xml
|
|||||||
.classpath
|
.classpath
|
||||||
.classpath
|
.classpath
|
||||||
.settings/org.eclipse.jdt.core.prefs
|
.settings/org.eclipse.jdt.core.prefs
|
||||||
|
.classpath
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
eclipse.preferences.version=1
|
eclipse.preferences.version=1
|
||||||
encoding//src/rawDeepLearningClassifer/segmenter/SegmenterProcess.java=UTF-8
|
encoding//src/rawDeepLearningClassifer/segmenter/SegmenterProcess.java=UTF-8
|
||||||
|
encoding//src/test=UTF-8
|
||||||
encoding//src/test/resources=UTF-8
|
encoding//src/test/resources=UTF-8
|
||||||
encoding/<project>=UTF-8
|
encoding/<project>=UTF-8
|
||||||
encoding/src=UTF-8
|
encoding/src=UTF-8
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
eclipse.preferences.version=1
|
eclipse.preferences.version=1
|
||||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
|
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
|
||||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=17
|
org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
|
||||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||||
org.eclipse.jdt.core.compiler.compliance=17
|
org.eclipse.jdt.core.compiler.compliance=21
|
||||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||||
@ -13,4 +13,4 @@ org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
|||||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
|
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
|
||||||
org.eclipse.jdt.core.compiler.release=enabled
|
org.eclipse.jdt.core.compiler.release=enabled
|
||||||
org.eclipse.jdt.core.compiler.source=17
|
org.eclipse.jdt.core.compiler.source=21
|
||||||
|
@ -107,6 +107,7 @@
|
|||||||
<exclude>META-INF/*.SF</exclude>
|
<exclude>META-INF/*.SF</exclude>
|
||||||
<exclude>META-INF/*.DSA</exclude>
|
<exclude>META-INF/*.DSA</exclude>
|
||||||
<exclude>META-INF/*.RSA</exclude>
|
<exclude>META-INF/*.RSA</exclude>
|
||||||
|
<exclude>test/resources/**</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</filter>
|
</filter>
|
||||||
</filters>
|
</filters>
|
||||||
|
Binary file not shown.
24
pom.xml
24
pom.xml
@ -4,7 +4,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.pamguard</groupId>
|
<groupId>org.pamguard</groupId>
|
||||||
<artifactId>Pamguard</artifactId>
|
<artifactId>Pamguard</artifactId>
|
||||||
<version>2.02.12</version>
|
<version>2.02.11d</version>
|
||||||
<name>Pamguard</name>
|
<name>Pamguard</name>
|
||||||
<description>Pamguard using Maven to control dependencies</description>
|
<description>Pamguard using Maven to control dependencies</description>
|
||||||
<url>www.pamguard.org</url>
|
<url>www.pamguard.org</url>
|
||||||
@ -101,7 +101,7 @@
|
|||||||
<exclude>META-INF/*.SF</exclude> <!-- get rid of manifests from library jars - also done in orig ant build file -->
|
<exclude>META-INF/*.SF</exclude> <!-- get rid of manifests from library jars - also done in orig ant build file -->
|
||||||
<exclude>META-INF/*.DSA</exclude>
|
<exclude>META-INF/*.DSA</exclude>
|
||||||
<exclude>META-INF/*.RSA</exclude>
|
<exclude>META-INF/*.RSA</exclude>
|
||||||
<exclude>test/resources/**</exclude>
|
<exclude>test/resources/**</exclude><!-- get rid of deep learning moduels and wav files used for unit tests -->
|
||||||
</excludes>
|
</excludes>
|
||||||
</filter>
|
</filter>
|
||||||
</filters>
|
</filters>
|
||||||
@ -181,24 +181,6 @@
|
|||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
<!-- Exclude the resource folder from build
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-resources-plugin</artifactId>
|
|
||||||
<version>3.2.0</version>
|
|
||||||
<configuration>
|
|
||||||
<resources>
|
|
||||||
<resource>
|
|
||||||
<directory>src/Resources</directory>
|
|
||||||
<excludes>
|
|
||||||
<exclude>src/test/resources/**</exclude>
|
|
||||||
</excludes>
|
|
||||||
</resource>
|
|
||||||
</resources>
|
|
||||||
</configuration>
|
|
||||||
</plugin>-->
|
|
||||||
|
|
||||||
|
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|
||||||
|
|
||||||
@ -598,7 +580,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fazecast</groupId>
|
<groupId>com.fazecast</groupId>
|
||||||
<artifactId>jSerialComm</artifactId>
|
<artifactId>jSerialComm</artifactId>
|
||||||
<version>2.11.0</version>
|
<version>2.5.3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- https://mvnrepository.com/artifact/edu.emory.mathcs/JTransforms -->
|
<!-- https://mvnrepository.com/artifact/edu.emory.mathcs/JTransforms -->
|
||||||
|
32
readme.md
32
readme.md
@ -1,26 +1,28 @@
|
|||||||
# PAMGuard
|
# PAMGuard
|
||||||
|
|
||||||
|
## Introduction
|
||||||
PAMGuard is a bioacoustics analysis program designed for use in real time research contexts and for the processing of large datasets. PAMGuard provides users access to a suite of state-of-the-art auotmated analysis algorithms alongside displays for visualisation data and a comprehensive data management systems.
|
PAMGuard is a bioacoustics analysis program designed for use in real time research contexts and for the processing of large datasets. PAMGuard provides users access to a suite of state-of-the-art auotmated analysis algorithms alongside displays for visualisation data and a comprehensive data management systems.
|
||||||
|
|
||||||
# Why do we need PAMGuard?
|
## Why do we need PAMGuard?
|
||||||
PAMGuard fufills two main requirements within marine bioacoustics
|
PAMGuard fufills two main requirements within marine bioacoustics
|
||||||
|
|
||||||
1) **Real time operation** - Almost all PAMGuard features and modules work in real time - this allows scientists and industry to detect, classify and loclaise animals in real time on a standard consumer laptop, enabling mitigations and research survey without expensive bespoke software solutions and the transparncy of open source software.
|
1) **Real time operation**: Almost all PAMGuard features and modules work in real time - this allows scientists and industry to detect, classify and localise the position of animals in real time on a standard consumer laptop, enabling mitigation and research surveys without expensive bespoke software solutions and the transparncy of open source software.
|
||||||
|
|
||||||
2) **Processing and visuslisation of large datasets** -
|
|
||||||
|
|
||||||
|
2) **Processing and visuslisation of large datasets**: Off-the-shelf autonomous PAM devices, large scale surveys involving drifters, towed arrays, glidders, bottom mounted devices and real time continuous monitoring system all generate huge volumes of data whcih requires automated analysis approaches. PAMGuard allows the processing of very large passive acoustic datasets using automated algorothms and crucially provides comprehensive visualisation tools for a manual analyst to check the results.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
PAMGuard is available on Windows and can be downloaded from the [PAMGuard website](www.pamguard.org). Note that we are considering MacOS installers but they are not available at this time.
|
PAMGuard is available on Windows and can be downloaded from the [PAMGuard website](www.pamguard.org). Note that we are considering MacOS and Linux installers but they are not available at this time.
|
||||||
|
|
||||||
## Tutorial
|
## Quick start tutorial
|
||||||
PAMGuard is a modular program with two modes; real-time and viewer. Typically a user will start with real-time model, either in the field collecting data or post processing sound files from a recorder. Once data are processed, users move on to viewer mode where data can be explored and further processed.
|
PAMGuard is a modular program with two modes; real-time and viewer. Typically a user will start with real-time model, either in the field collecting data or post processing sound files from a recorder. Once data are processed, users move on to viewer mode where data can be explored and further processed.
|
||||||
|
|
||||||
Upon opening PAMGuard for the first time you are greeted with a blank screen. You must add a series of modules to create the desired acosutic workflow. For example if processing sound files then first add the Sound Acquisition module **_File->Add Modules->Sound Processing->Sound Acquisition_**. Then add the desired detection algorothms e.g. **_File->Add Modules->Detector->Click Detectors_**. Some modules (such as the click detector) have their own displays, others are added to more generalised displays. For example, the whislte and moan detector module shows detections on a spectrgram display. First add a new tab using **_File->Add Modules->Displays->User Display**. Click on the user display tab and then from the top menu select **_User display-> New Spectrgram_**. Right click on the added spectrgram and select whistle and moan contours to show whistle detections overlaid on the raw spectrgram.
|
Upon opening PAMGuard for the first time you are greeted with a blank screen. You must add a series of modules to create the desired acosutic workflow - this is referred to as PAMGuard *data model*. For example if processing sound files then first add the Sound Acquisition module **_File->Add Modules->Sound Processing->Sound Acquisition_**. Then add the desired detection algorothms e.g. **_File->Add Modules->Detector->Click Detectors_**. Some modules (such as the click detector) have their own bespoke displays, others are added to more generalised displays. For example, the whistle and moan detector module shows detections on a spectrgram display, time base display, map etc.. First add a new tab using **_File->Add Modules->Displays->User Display**. Click on the user display tab and then from the top menu select **_User display-> New Spectrogram_**. Right click on the added spectrgram and select whistle and moan contours to show whistle detections overlaid on the raw spectrgram.
|
||||||
|
|
||||||
Make sure to add the database and binary file storage modules **_File->Add Modules->Utilities->..._**) to save data then press the run button (red button) and data will process. PAMGuard can handle huge datasets so runing might take hours or even days. Progress is shown on the bottom of the screen.
|
Make sure to add the database and binary file storage modules **_File->Add Modules->Utilities->..._**) to save data then press the run button (red button) and data will process. PAMGuard can handle huge datasets so running might take hours or even days. Progress is shown on the bottom of the screen.
|
||||||
|
|
||||||
|
Once the data has run, open PAMGuard viewer mode. Select the database you used to process the data along and thebianry file storage path and PAMGuard will open, showing an overview of the dataset in a new _Data map_ tab. Right click anywhere on the data map and select "Center data here" - PAMGuard will load the data for the selected period which can be explored using whichever displays have been added to the data model.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
### Hardware integration
|
### Hardware integration
|
||||||
PAMGuard connects with hardware such as various GPS and AIS systems and a multitude of different sound cards (e.g. [National Instruments](www.ni.com) devices, [SAIL DAQ cards](www.smruconsulting.com/contact-us), almost all ASIO sound cards and standard computer sound cards) for real time data collection and processing. PAMGuard also works with some very bespoke hardware such as [DIFAR Sonobuoys]();
|
PAMGuard connects with hardware such as various GPS and AIS systems and a multitude of different sound cards (e.g. [National Instruments](www.ni.com) devices, [SAIL DAQ cards](www.smruconsulting.com/contact-us), almost all ASIO sound cards and standard computer sound cards) for real time data collection and processing. PAMGuard also works with some very bespoke hardware such as [DIFAR Sonobuoys]();
|
||||||
|
|
||||||
@ -46,21 +48,25 @@ PAMGuard has a noise band (which supports third octave noise bands) and long ter
|
|||||||
Almsot all detection data can be visualised on a map. PAMGaurd also supports plotting GPS and AIS data.
|
Almsot all detection data can be visualised on a map. PAMGaurd also supports plotting GPS and AIS data.
|
||||||
|
|
||||||
### Suite of data visualisation tools
|
### Suite of data visualisation tools
|
||||||
An important aspect of PAMGuard is the ability for users to explore porcessed data. This is
|
An important aspect of PAMGuard is the ability for users to explore porcessed data. PAMGuard allows users to visualise data at multiple different times scales, from inspecting individual waveforms microseconds long to datagrams showing detector output or soundscape metrics over days, weeks or even years.
|
||||||
|
|
||||||
### Advanced manual annotation
|
### Advanced manual annotation
|
||||||
The displays within PAMGuard support a variety of manual annottion tools. A simple spectrogram
|
The displays within PAMGuard support a variety of manual annotation tools. Users can add data to annotations in multiple ways, from simple text annotations to complex forms created by users.
|
||||||
|
|
||||||
### Deep learning integration
|
### Deep learning integration
|
||||||
|
PAMGuard allows users to run their own deep learning models using the deep learning module. AI can therfore be integrated into PAMGuard workflows, allowing for more efficient analysis of data.
|
||||||
|
|
||||||
### Meatadata standard and Tethys compatibility
|
### Metadata standard and Tethys compatibility
|
||||||
|
PAMGuard Integrates with Tethys database. Users can export processed PAMGuard data to a Tethys database seamlessly; this ifeature is great for large scale projects or organisatiosn with long term datasets.
|
||||||
|
|
||||||
## Feature roadmap
|
## Feature roadmap
|
||||||
There's lots of features we would like to add to PAMGuard. If you want to add a feature you can either code it up yourself in Java and submit a pull request or get in touch with us to discuss how to it might be integrated. Some smaller features might be in our roadmap anyway but larger features usually require funding. Some features we are thinking about (but do not necassarily have time for yet) are;
|
There's lots of features we would like to add to PAMGuard. If you want to add a feature you can either code it up yourself in Java and submit a pull request or get in touch with us to discuss how to it might be integrated. Some smaller features might be in our roadmap anyway but larger features usually require funding. Some features we are thinking about (but do not necassarily have time for yet) are;
|
||||||
|
|
||||||
* Support for decidecade noise bands (base 10 filter bank) in noise band monitor to meet Euopean standards
|
* Support for decidecade noise bands (base 10 filter bank) in noise band monitor to meet Euopean standards
|
||||||
* Capabaility to export data directly from PAMGaurd e.g. as MAT files.
|
* Capabaility to export data directly from PAMGaurd e.g. as MAT files (in progress).
|
||||||
* Automated test suite to make releases more stable. Note that unit and integration tests are also being slowly incorporated.
|
* Automated test suite to make releases more stable. Note that unit and integration tests are also being slowly incorporated.
|
||||||
|
* Support for ARM based computers (in progress).
|
||||||
|
* A graphical user interface and Python library for training PAMGuard compatible deep learning models.
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
This is the main code repository for the PAMGuard software and was created on 7 January 2022 from a [sourceforge SVN repository](https://sourceforge.net/p/pamguard/svn/HEAD/tree/) revision r6278.
|
This is the main code repository for the PAMGuard software and was created on 7 January 2022 from a [sourceforge SVN repository](https://sourceforge.net/p/pamguard/svn/HEAD/tree/) revision r6278.
|
||||||
|
@ -181,7 +181,6 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
|
|||||||
|
|
||||||
this.acquisitionDialog = acquisitionDialog;
|
this.acquisitionDialog = acquisitionDialog;
|
||||||
|
|
||||||
|
|
||||||
return getDialogPanel();
|
return getDialogPanel();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,7 +197,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
|
|||||||
|
|
||||||
protected JPanel createDaqDialogPanel() {
|
protected JPanel createDaqDialogPanel() {
|
||||||
|
|
||||||
JPanel p = new JPanel();
|
PamPanel p = new PamPanel();
|
||||||
p.setBorder(new TitledBorder("Select sound file"));
|
p.setBorder(new TitledBorder("Select sound file"));
|
||||||
GridBagLayout layout = new GridBagLayout();
|
GridBagLayout layout = new GridBagLayout();
|
||||||
layout.columnWidths = new int[]{100, 100, 10};
|
layout.columnWidths = new int[]{100, 100, 10};
|
||||||
@ -253,6 +252,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
|
|||||||
// constraints.gridwidth = 2;
|
// constraints.gridwidth = 2;
|
||||||
// addComponent(p, fileDateText = new JTextField(), constraints);
|
// addComponent(p, fileDateText = new JTextField(), constraints);
|
||||||
// fileDateText.setEnabled(false);
|
// fileDateText.setEnabled(false);
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ import javafx.application.Platform;
|
|||||||
import pamguard.GlobalArguments;
|
import pamguard.GlobalArguments;
|
||||||
import Acquisition.pamAudio.PamAudioFileManager;
|
import Acquisition.pamAudio.PamAudioFileManager;
|
||||||
import Acquisition.pamAudio.PamAudioFileFilter;
|
import Acquisition.pamAudio.PamAudioFileFilter;
|
||||||
|
import Acquisition.pamAudio.PamAudioFileLoader;
|
||||||
import Acquisition.pamAudio.PamAudioSystem;
|
import Acquisition.pamAudio.PamAudioSystem;
|
||||||
import PamController.DataInputStore;
|
import PamController.DataInputStore;
|
||||||
import PamController.InputStoreInfo;
|
import PamController.InputStoreInfo;
|
||||||
@ -93,6 +94,12 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
|||||||
*/
|
*/
|
||||||
private JTextField skipSecondsField;
|
private JTextField skipSecondsField;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Panel which shows bespoke settings for certain audio loaders. Contains nothing
|
||||||
|
* if the audio loader has no settings or no file is selected.
|
||||||
|
*/
|
||||||
|
protected PamPanel audioLoaderHolder;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean runFileAnalysis() {
|
public boolean runFileAnalysis() {
|
||||||
currentFileStart = System.currentTimeMillis();
|
currentFileStart = System.currentTimeMillis();
|
||||||
@ -170,6 +177,8 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected JPanel createDaqDialogPanel() {
|
protected JPanel createDaqDialogPanel() {
|
||||||
JPanel p = new JPanel();
|
JPanel p = new JPanel();
|
||||||
@ -228,6 +237,7 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
|||||||
constraints.gridwidth = 2;
|
constraints.gridwidth = 2;
|
||||||
constraints.fill = GridBagConstraints.NONE;
|
constraints.fill = GridBagConstraints.NONE;
|
||||||
constraints.anchor = GridBagConstraints.WEST;
|
constraints.anchor = GridBagConstraints.WEST;
|
||||||
|
|
||||||
addComponent(p, mergeFiles = new JCheckBox("Merge contiguous files"), constraints);
|
addComponent(p, mergeFiles = new JCheckBox("Merge contiguous files"), constraints);
|
||||||
if (PamController.getInstance().getRunMode() == PamController.RUN_PAMVIEW) {
|
if (PamController.getInstance().getRunMode() == PamController.RUN_PAMVIEW) {
|
||||||
constraints.gridx+=2;
|
constraints.gridx+=2;
|
||||||
@ -246,9 +256,19 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
|||||||
addComponent(p, skipSecondsField = new JTextField(4), constraints);
|
addComponent(p, skipSecondsField = new JTextField(4), constraints);
|
||||||
constraints.gridx++;
|
constraints.gridx++;
|
||||||
addComponent(p, new JLabel("seconds"), constraints);
|
addComponent(p, new JLabel("seconds"), constraints);
|
||||||
constraints.anchor = GridBagConstraints.EAST;
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
//panel to show bespoke settings for certain audio loaders.
|
||||||
|
constraints.anchor = GridBagConstraints.WEST;
|
||||||
|
constraints.gridx = 0;
|
||||||
|
constraints.gridy++;
|
||||||
|
constraints.gridwidth = 3;
|
||||||
|
addComponent(p, audioLoaderHolder = new PamPanel(), constraints);
|
||||||
|
|
||||||
|
GridBagLayout layout2 = new GridBagLayout();
|
||||||
|
audioLoaderHolder.setLayout(layout2);
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,10 +545,14 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
|||||||
List<WavFileType> asList = allFiles;
|
List<WavFileType> asList = allFiles;
|
||||||
setSelectedFileTypes(acquisitionControl.soundFileTypes.getUsedTypes(allFiles));
|
setSelectedFileTypes(acquisitionControl.soundFileTypes.getUsedTypes(allFiles));
|
||||||
|
|
||||||
|
//set the date of the first file.
|
||||||
setFileDateText();
|
setFileDateText();
|
||||||
|
|
||||||
|
//set any bespoke options for the files to be laoded.
|
||||||
|
setFileOptionPanel();
|
||||||
|
|
||||||
// also open up the first file and get the sample rate and number of channels from it
|
// also open up the first file and get the sample rate and number of channels from it
|
||||||
// and set these
|
// and set these
|
||||||
|
|
||||||
File file = getCurrentFile();
|
File file = getCurrentFile();
|
||||||
if (file == null) return;
|
if (file == null) return;
|
||||||
AudioInputStream audioStream;
|
AudioInputStream audioStream;
|
||||||
@ -573,6 +597,38 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
|||||||
return nChannels;
|
return nChannels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set bespoke options for certain file types.
|
||||||
|
*/
|
||||||
|
public void setFileOptionPanel() {
|
||||||
|
getDialogPanel(); // make sure panel is created
|
||||||
|
|
||||||
|
audioLoaderHolder.removeAll();
|
||||||
|
|
||||||
|
if (allFiles.size() > 0) {
|
||||||
|
//Get all the audio file laoders that will be used for this list of files. Usually
|
||||||
|
//just one but possible that there can be mixed files.
|
||||||
|
ArrayList<PamAudioFileLoader> loaders = PamAudioFileManager.getInstance().getAudioFileLoaders(allFiles);
|
||||||
|
|
||||||
|
GridBagConstraints constraints = new GridBagConstraints();
|
||||||
|
constraints.gridx = 0;
|
||||||
|
constraints.gridy = 0;
|
||||||
|
for (PamAudioFileLoader loader : loaders) {
|
||||||
|
if (loader.getSettingsPane()!=null) {
|
||||||
|
// System.out.println("ADD AUDIO PANEL: " +loader.getSettingsPane().getAudioLoaderPanel());
|
||||||
|
//gridbag layout
|
||||||
|
addComponent(audioLoaderHolder, loader.getSettingsPane().getAudioLoaderPanel(), constraints);
|
||||||
|
loader.getSettingsPane().setParams();
|
||||||
|
constraints.gridy++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the date of the first file in the dialog.
|
||||||
|
*/
|
||||||
public void setFileDateText() {
|
public void setFileDateText() {
|
||||||
if (allFiles.size() > 0) {
|
if (allFiles.size() > 0) {
|
||||||
long fileTime = getFileStartTime(getCurrentFile());
|
long fileTime = getFileStartTime(getCurrentFile());
|
||||||
@ -768,6 +824,17 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//get bespoke paramters from selected audio loaders.
|
||||||
|
ArrayList<PamAudioFileLoader> loaders = PamAudioFileManager.getInstance().getAudioFileLoaders(allFiles);
|
||||||
|
|
||||||
|
|
||||||
|
for (PamAudioFileLoader loader : loaders) {
|
||||||
|
if (loader.getSettingsPane()!=null) {
|
||||||
|
loader.getSettingsPane().getParams();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return super.dialogGetParams();
|
return super.dialogGetParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -786,6 +853,7 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
|||||||
if (skipSecondsField!=null) {
|
if (skipSecondsField!=null) {
|
||||||
skipSecondsField.setText(String.format("%.1f", fileInputParameters.skipStartFileTime/1000.));
|
skipSecondsField.setText(String.format("%.1f", fileInputParameters.skipStartFileTime/1000.));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -952,4 +1020,6 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,23 +6,18 @@ import javafx.collections.FXCollections;
|
|||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Orientation;
|
import javafx.geometry.Orientation;
|
||||||
import javafx.geometry.Pos;
|
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
import javafx.scene.layout.HBox;
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.scene.layout.Priority;
|
import javafx.scene.layout.Priority;
|
||||||
import javafx.scene.paint.Color;
|
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import javafx.util.StringConverter;
|
import javafx.util.StringConverter;
|
||||||
import pamViewFX.PamGuiManagerFX;
|
import pamViewFX.PamGuiManagerFX;
|
||||||
import pamViewFX.fxGlyphs.PamGlyphDude;
|
|
||||||
import pamViewFX.fxNodes.PamBorderPane;
|
import pamViewFX.fxNodes.PamBorderPane;
|
||||||
import pamViewFX.fxNodes.PamButton;
|
|
||||||
import pamViewFX.fxNodes.PamComboBox;
|
import pamViewFX.fxNodes.PamComboBox;
|
||||||
import pamViewFX.fxNodes.PamGridPane;
|
import pamViewFX.fxNodes.PamGridPane;
|
||||||
import pamViewFX.fxNodes.PamHBox;
|
|
||||||
import pamViewFX.fxNodes.PamTextField;
|
import pamViewFX.fxNodes.PamTextField;
|
||||||
import pamViewFX.fxNodes.PamVBox;
|
import pamViewFX.fxNodes.PamVBox;
|
||||||
import pamViewFX.fxNodes.flipPane.FlipPane;
|
import pamViewFX.fxNodes.flipPane.FlipPane;
|
||||||
@ -43,7 +38,7 @@ import dataMap.filemaps.OfflineFileParameters;
|
|||||||
*/
|
*/
|
||||||
public class AcquisitionPaneFX extends SettingsPane<AcquisitionParameters>{
|
public class AcquisitionPaneFX extends SettingsPane<AcquisitionParameters>{
|
||||||
|
|
||||||
private final static int TEXT_FIELD_WIDTH = 60;
|
private final static int TEXT_FIELD_WIDTH = 80;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reference to acquisition control.
|
* Reference to acquisition control.
|
||||||
@ -120,13 +115,13 @@ public class AcquisitionPaneFX extends SettingsPane<AcquisitionParameters>{
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private FlipPane flipPane;
|
private PamFlipPane flipPane;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pane which can be used for advanced settings.
|
* Pane which can be used for advanced settings.
|
||||||
*/
|
*/
|
||||||
private PamBorderPane advancedSettingPane;
|
// private PamBorderPane advancedSettingPane;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Title label for the advanced pane.
|
* Title label for the advanced pane.
|
||||||
@ -147,12 +142,13 @@ public class AcquisitionPaneFX extends SettingsPane<AcquisitionParameters>{
|
|||||||
super(null);
|
super(null);
|
||||||
mainPane = new PamBorderPane();
|
mainPane = new PamBorderPane();
|
||||||
mainPane.setPrefWidth(400);
|
mainPane.setPrefWidth(400);
|
||||||
|
mainPane.setPadding(new Insets(5,5,5,5));
|
||||||
|
|
||||||
this.acquisitionControl=aquisitionControl;
|
this.acquisitionControl=aquisitionControl;
|
||||||
this.acquisitionParameters=acquisitionControl.getAcquisitionParameters();
|
this.acquisitionParameters=acquisitionControl.getAcquisitionParameters();
|
||||||
|
|
||||||
//create the flip pane.
|
//create the flip pane.
|
||||||
flipPane=new FlipPane();
|
flipPane=new PamFlipPane();
|
||||||
flipPane.setFlipDirection(Orientation.HORIZONTAL);
|
flipPane.setFlipDirection(Orientation.HORIZONTAL);
|
||||||
flipPane.setFlipTime(PamFlipPane.FLIP_TIME); //default is 700ms- way too high
|
flipPane.setFlipTime(PamFlipPane.FLIP_TIME); //default is 700ms- way too high
|
||||||
//flipPane.prefWidthProperty().bind(mainPane.widthProperty());
|
//flipPane.prefWidthProperty().bind(mainPane.widthProperty());
|
||||||
@ -166,45 +162,45 @@ public class AcquisitionPaneFX extends SettingsPane<AcquisitionParameters>{
|
|||||||
flipPane.getFront().getChildren().add(mainPane);
|
flipPane.getFront().getChildren().add(mainPane);
|
||||||
|
|
||||||
//create the advanced flip pane.
|
//create the advanced flip pane.
|
||||||
advancedSettingPane = createAdvSettingsPane();
|
// advancedSettingPane = createAdvSettingsPane();
|
||||||
flipPane.getBack().getChildren().add(advancedSettingPane);
|
// flipPane.getBack().getChildren().add(advancedSettingPane);
|
||||||
//System.out.println("MAKE PANE: " + acquisitionParameters.getDaqSystemType());
|
//System.out.println("MAKE PANE: " + acquisitionParameters.getDaqSystemType());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Create the advanced settings pane which can be accessed by DAQ panes if needed.
|
// * Create the advanced settings pane which can be accessed by DAQ panes if needed.
|
||||||
*/
|
// */
|
||||||
private PamBorderPane createAdvSettingsPane() {
|
// private PamBorderPane createAdvSettingsPane() {
|
||||||
|
//
|
||||||
PamButton back = new PamButton();
|
// PamButton back = new PamButton();
|
||||||
back.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-left", Color.WHITE, PamGuiManagerFX.iconSize));
|
// back.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-left", Color.WHITE, PamGuiManagerFX.iconSize));
|
||||||
|
//
|
||||||
back.setOnAction((action)->{
|
// back.setOnAction((action)->{
|
||||||
flipPane.flipToFront();
|
// flipPane.flipToFront();
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
PamBorderPane advPane = new PamBorderPane();
|
// PamBorderPane advPane = new PamBorderPane();
|
||||||
advPane.setPadding(new Insets(5,5,5,5));
|
// advPane.setPadding(new Insets(5,5,5,5));
|
||||||
|
//
|
||||||
PamHBox buttonHolder = new PamHBox();
|
// PamHBox buttonHolder = new PamHBox();
|
||||||
|
//
|
||||||
buttonHolder.setBackground(null);
|
// buttonHolder.setBackground(null);
|
||||||
//buttonHolder.setStyle("-fx-background-color: red;");
|
// //buttonHolder.setStyle("-fx-background-color: red;");
|
||||||
buttonHolder.setAlignment(Pos.CENTER_LEFT);
|
// buttonHolder.setAlignment(Pos.CENTER_LEFT);
|
||||||
buttonHolder.getChildren().addAll(back, advLabel = new Label("Adv. Settings"));
|
// buttonHolder.getChildren().addAll(back, advLabel = new Label("Adv. Settings"));
|
||||||
advLabel.setAlignment(Pos.CENTER);
|
// advLabel.setAlignment(Pos.CENTER);
|
||||||
advLabel.setMaxWidth(Double.MAX_VALUE); //need to make sure label is in center.
|
// advLabel.setMaxWidth(Double.MAX_VALUE); //need to make sure label is in center.
|
||||||
PamGuiManagerFX.titleFont2style(advLabel);
|
// PamGuiManagerFX.titleFont2style(advLabel);
|
||||||
|
//
|
||||||
advLabel.setAlignment(Pos.CENTER);
|
// advLabel.setAlignment(Pos.CENTER);
|
||||||
HBox.setHgrow(advLabel, Priority.ALWAYS);
|
// HBox.setHgrow(advLabel, Priority.ALWAYS);
|
||||||
|
//
|
||||||
advPane.setTop(buttonHolder);
|
// advPane.setTop(buttonHolder);
|
||||||
|
//
|
||||||
return advPane;
|
// return advPane;
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the Sound Aquisition pane for real time monitoring.
|
* Create the Sound Aquisition pane for real time monitoring.
|
||||||
@ -606,11 +602,12 @@ public class AcquisitionPaneFX extends SettingsPane<AcquisitionParameters>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PamBorderPane getAdvancedPane() {
|
public PamBorderPane getAdvancedPane() {
|
||||||
return this.advancedSettingPane;
|
return this.flipPane.getAdvContentPane()
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Label getAdvancedLabel() {
|
public TextField getAdvancedLabel() {
|
||||||
return this.advLabel;
|
return this.flipPane.getAdvLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package Acquisition.layoutFX;
|
package Acquisition.layoutFX;
|
||||||
|
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -12,6 +13,8 @@ import Acquisition.FileInputParameters;
|
|||||||
import Acquisition.FolderInputParameters;
|
import Acquisition.FolderInputParameters;
|
||||||
import Acquisition.FolderInputSystem;
|
import Acquisition.FolderInputSystem;
|
||||||
import Acquisition.pamAudio.PamAudioFileFilter;
|
import Acquisition.pamAudio.PamAudioFileFilter;
|
||||||
|
import Acquisition.pamAudio.PamAudioFileLoader;
|
||||||
|
import Acquisition.pamAudio.PamAudioFileManager;
|
||||||
import PamController.PamController;
|
import PamController.PamController;
|
||||||
import PamController.PamFolders;
|
import PamController.PamFolders;
|
||||||
import PamUtils.PamCalendar;
|
import PamUtils.PamCalendar;
|
||||||
@ -48,7 +51,7 @@ import pamViewFX.fxNodes.PamProgressBar;
|
|||||||
import pamViewFX.fxNodes.PamVBox;
|
import pamViewFX.fxNodes.PamVBox;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pane for the folder input of the sound acquisition.
|
* JavaFX pane for the folder input of the sound acquisition.
|
||||||
*
|
*
|
||||||
* @author Jamie Macaulay
|
* @author Jamie Macaulay
|
||||||
*
|
*
|
||||||
@ -147,6 +150,8 @@ public class FolderInputPane extends DAQSettingsPane<FolderInputParameters>{
|
|||||||
*/
|
*/
|
||||||
private ToggleButton mergeContigious;
|
private ToggleButton mergeContigious;
|
||||||
|
|
||||||
|
private PamBorderPane audioHolderloader;
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
// * The folder input system.
|
// * The folder input system.
|
||||||
// * @param folderInputSystem - the folder system.
|
// * @param folderInputSystem - the folder system.
|
||||||
@ -245,8 +250,11 @@ public class FolderInputPane extends DAQSettingsPane<FolderInputParameters>{
|
|||||||
Label utilsLabel=new Label("Sound file utilities");
|
Label utilsLabel=new Label("Sound file utilities");
|
||||||
PamGuiManagerFX.titleFont2style(utilsLabel);
|
PamGuiManagerFX.titleFont2style(utilsLabel);
|
||||||
|
|
||||||
|
//
|
||||||
|
audioHolderloader = new PamBorderPane();
|
||||||
|
|
||||||
pamVBox.getChildren().addAll(fileSelectBox, subFolderPane, progressBar, createTablePane(),
|
pamVBox.getChildren().addAll(fileSelectBox, subFolderPane, progressBar, createTablePane(),
|
||||||
fileDateText=new Label(), utilsLabel, createUtilsPane());
|
fileDateText=new Label(), audioHolderloader, utilsLabel, createUtilsPane());
|
||||||
|
|
||||||
//allow users to check file headers in viewer mode.
|
//allow users to check file headers in viewer mode.
|
||||||
// if (PamController.getInstance().getRunMode() == PamController.RUN_PAMVIEW) {
|
// if (PamController.getInstance().getRunMode() == PamController.RUN_PAMVIEW) {
|
||||||
@ -361,6 +369,7 @@ public class FolderInputPane extends DAQSettingsPane<FolderInputParameters>{
|
|||||||
return new PamBorderPane(table);
|
return new PamBorderPane(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a dialog to select either a folder or a list of files.
|
* Open a dialog to select either a folder or a list of files.
|
||||||
* @param folderDir - true to use directory chooser, false to use multiple file chooser.
|
* @param folderDir - true to use directory chooser, false to use multiple file chooser.
|
||||||
@ -595,6 +604,9 @@ public class FolderInputPane extends DAQSettingsPane<FolderInputParameters>{
|
|||||||
|
|
||||||
fileDateStrip.setFileList(fileList);
|
fileDateStrip.setFileList(fileList);
|
||||||
|
|
||||||
|
//set any bespoke options for the files to be laoded.
|
||||||
|
setFileOptionPane(fileList);
|
||||||
|
|
||||||
//need to set the sample rate and channels in the main pane.
|
//need to set the sample rate and channels in the main pane.
|
||||||
if (fileList!=null && fileList.size()>0) {
|
if (fileList!=null && fileList.size()>0) {
|
||||||
this.acquisitionPaneFX.setSampleRate(fileList.get(0).getAudioInfo().getSampleRate());
|
this.acquisitionPaneFX.setSampleRate(fileList.get(0).getAudioInfo().getSampleRate());
|
||||||
@ -610,6 +622,34 @@ public class FolderInputPane extends DAQSettingsPane<FolderInputParameters>{
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set bespoke options for certain file types.
|
||||||
|
*/
|
||||||
|
public void setFileOptionPane(ObservableList<WavFileType> fileList) {
|
||||||
|
|
||||||
|
audioHolderloader.setCenter(null);
|
||||||
|
|
||||||
|
if (fileList.size() > 0) {
|
||||||
|
//Get all the audio file laoders that will be used for this list of files. Usually
|
||||||
|
//just one but possible that there can be mixed files.
|
||||||
|
ArrayList<PamAudioFileLoader> loaders = PamAudioFileManager.getInstance().getAudioFileLoaders(fileList);
|
||||||
|
|
||||||
|
PamVBox vBox = new PamVBox();
|
||||||
|
vBox.setSpacing(5);
|
||||||
|
for (PamAudioFileLoader loader : loaders) {
|
||||||
|
if (loader.getSettingsPane()!=null) {
|
||||||
|
//add the settings pane to the vbox
|
||||||
|
vBox.getChildren().add(loader.getSettingsPane().getAudioLoaderPane());
|
||||||
|
loader.getSettingsPane().setParams();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
audioHolderloader.setCenter(vBox);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called whenever a new file worker is initialised to search a folder for wav files.
|
* Called whenever a new file worker is initialised to search a folder for wav files.
|
||||||
* @param worker - the new file worker being used.
|
* @param worker - the new file worker being used.
|
||||||
@ -637,16 +677,30 @@ public class FolderInputPane extends DAQSettingsPane<FolderInputParameters>{
|
|||||||
public void setParams() {
|
public void setParams() {
|
||||||
//set the parameters for the dialog.
|
//set the parameters for the dialog.
|
||||||
this.setParams(folderInputSystem.getFolderInputParameters());
|
this.setParams(folderInputSystem.getFolderInputParameters());
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getParams() {
|
public boolean getParams() {
|
||||||
FolderInputParameters params = this.getParams(folderInputSystem.getFolderInputParameters());
|
FolderInputParameters params = this.getParams(folderInputSystem.getFolderInputParameters());
|
||||||
|
|
||||||
|
//get bespoke paramters from selected audio loaders. Note these are global and so are not part
|
||||||
|
//of the folder input system
|
||||||
|
ArrayList<PamAudioFileLoader> loaders = PamAudioFileManager.getInstance().getAudioFileLoaders();
|
||||||
|
|
||||||
|
for (PamAudioFileLoader loader : loaders) {
|
||||||
|
if (loader.getSettingsPane()!=null) {
|
||||||
|
loader.getSettingsPane().getParams();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (params == null) return false;
|
if (params == null) return false;
|
||||||
else {
|
else {
|
||||||
this.folderInputSystem.setFolderInputParameters(params);
|
this.folderInputSystem.setFolderInputParameters(params);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ public class OfflineWavFileServer extends OfflineFileServer<FileDataMapPoint> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PamAudioFileLoader audioFile = PamAudioFileManager.getInstance().getAudioLoader(mapPoint.getSoundFile());
|
PamAudioFileLoader audioFile = PamAudioFileManager.getInstance().getAudioFileLoader(mapPoint.getSoundFile());
|
||||||
|
|
||||||
if (audioFile==null) {
|
if (audioFile==null) {
|
||||||
System.err.println("OfflineWavFileServer: could not find audio loader for mapped sound file: " + mapPoint.getSoundFile());
|
System.err.println("OfflineWavFileServer: could not find audio loader for mapped sound file: " + mapPoint.getSoundFile());
|
||||||
|
@ -233,4 +233,10 @@ public class FlacAudioFile implements PamAudioFileLoader {
|
|||||||
return (end.equals(".flac"));
|
return (end.equals(".flac"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PamAudioSettingsPane getSettingsPane() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -48,5 +48,12 @@ public interface PamAudioFileLoader {
|
|||||||
public boolean loadAudioData(OfflineFileServer offlineFileServer, PamDataBlock dataBlock,
|
public boolean loadAudioData(OfflineFileServer offlineFileServer, PamDataBlock dataBlock,
|
||||||
OfflineDataLoadInfo offlineDataLoadInfo, ViewLoadObserver loadObserver);
|
OfflineDataLoadInfo offlineDataLoadInfo, ViewLoadObserver loadObserver);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a settings pane for the audio loader
|
||||||
|
* @return settings pane for audio loader - can be null.
|
||||||
|
*/
|
||||||
|
public PamAudioSettingsPane getSettingsPane();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,15 @@ package Acquisition.pamAudio;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.sound.sampled.AudioInputStream;
|
import javax.sound.sampled.AudioInputStream;
|
||||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||||
|
|
||||||
import org.codehaus.plexus.util.FileUtils;
|
import org.codehaus.plexus.util.FileUtils;
|
||||||
|
|
||||||
|
import Acquisition.sud.SudAudioFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Central class for opening sound files.
|
* Central class for opening sound files.
|
||||||
* <p>
|
* <p>
|
||||||
@ -56,7 +59,7 @@ public class PamAudioFileManager {
|
|||||||
* @param soundFile - the sound file
|
* @param soundFile - the sound file
|
||||||
* @return the audio file loader.
|
* @return the audio file loader.
|
||||||
*/
|
*/
|
||||||
public PamAudioFileLoader getAudioLoader(File soundFile) {
|
public PamAudioFileLoader getAudioFileLoader(File soundFile) {
|
||||||
for (int i = 0; i < pamAudioFileTypes.size(); i++) {
|
for (int i = 0; i < pamAudioFileTypes.size(); i++) {
|
||||||
if (isExtension(soundFile, pamAudioFileTypes.get(i))) {
|
if (isExtension(soundFile, pamAudioFileTypes.get(i))) {
|
||||||
return pamAudioFileTypes.get(i);
|
return pamAudioFileTypes.get(i);
|
||||||
@ -170,6 +173,23 @@ public class PamAudioFileManager {
|
|||||||
return this.pamAudioFileTypes;
|
return this.pamAudioFileTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the loaders which are needed to open a list of files
|
||||||
|
* @param files - the files to find audio loaders for.
|
||||||
|
* @return a list of the audio loaders required for the file list
|
||||||
|
*/
|
||||||
|
public ArrayList<PamAudioFileLoader> getAudioFileLoaders(List<? extends File> files) {
|
||||||
|
ArrayList<PamAudioFileLoader> audioLoaders = new ArrayList<PamAudioFileLoader>();
|
||||||
|
PamAudioFileLoader loader;
|
||||||
|
for (int i=0; i<files.size(); i++) {
|
||||||
|
loader = getAudioFileLoader(files.get(i));
|
||||||
|
if (!audioLoaders.contains(loader)) {
|
||||||
|
audioLoaders.add(loader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return audioLoaders;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the default file loader for raw files.
|
* Get the default file loader for raw files.
|
||||||
* @return the default file loader for raw files.
|
* @return the default file loader for raw files.
|
||||||
|
34
src/Acquisition/pamAudio/PamAudioSettingsPane.java
Normal file
34
src/Acquisition/pamAudio/PamAudioSettingsPane.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package Acquisition.pamAudio;
|
||||||
|
|
||||||
|
import PamView.panel.PamPanel;
|
||||||
|
import javafx.scene.layout.Pane;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User controls to change bespoke settings for audio loaders.
|
||||||
|
*/
|
||||||
|
public interface PamAudioSettingsPane {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the JavaFX pane for loading audio.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Pane getAudioLoaderPane();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the swing audio loader pane.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public PamPanel getAudioLoaderPanel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the parameters. This called whenever the settings dialog or pane is closed.
|
||||||
|
*/
|
||||||
|
public void getParams();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set parameters. This is called when the dialog or pane is opened.
|
||||||
|
*/
|
||||||
|
public void setParams();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -10,6 +10,8 @@ import javax.sound.sampled.UnsupportedAudioFileException;
|
|||||||
//import org.kc7bfi.jflac.sound.spi.FlacAudioFileReader;
|
//import org.kc7bfi.jflac.sound.spi.FlacAudioFileReader;
|
||||||
import org.jflac.sound.spi.FlacAudioFileReader;
|
import org.jflac.sound.spi.FlacAudioFileReader;
|
||||||
|
|
||||||
|
import Acquisition.sud.SudAudioFileReader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Now replaced with PamAudioFileManager.
|
* Now replaced with PamAudioFileManager.
|
||||||
*
|
*
|
||||||
|
@ -296,5 +296,11 @@ public class WavAudioFile implements PamAudioFileLoader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PamAudioSettingsPane getSettingsPane() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
33
src/Acquisition/sud/PamSudParams.java
Normal file
33
src/Acquisition/sud/PamSudParams.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package Acquisition.sud;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters for sud file extraction.
|
||||||
|
*/
|
||||||
|
public class PamSudParams implements Serializable, Cloneable {
|
||||||
|
|
||||||
|
public static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zero padding fills gaps in sud files with zeros - these gaps are usually due
|
||||||
|
* to errors in the recording hardware.Without zero pad then time drift within a
|
||||||
|
* file can be difficult to predict, however zero padding means the sample
|
||||||
|
* numbers in other files e.g. csv sensor files will not align.
|
||||||
|
*/
|
||||||
|
public boolean zeroPad = true;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PamSudParams clone() {
|
||||||
|
try {
|
||||||
|
PamSudParams ap = (PamSudParams) super.clone();
|
||||||
|
|
||||||
|
return ap;
|
||||||
|
}
|
||||||
|
catch (CloneNotSupportedException Ex) {
|
||||||
|
Ex.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,8 @@
|
|||||||
package Acquisition.pamAudio;
|
package Acquisition.sud;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@ -12,7 +13,13 @@ import javax.swing.SwingUtilities;
|
|||||||
import org.pamguard.x3.sud.ChunkHeader;
|
import org.pamguard.x3.sud.ChunkHeader;
|
||||||
import org.pamguard.x3.sud.SudMapListener;
|
import org.pamguard.x3.sud.SudMapListener;
|
||||||
|
|
||||||
|
import Acquisition.AcquisitionParameters;
|
||||||
|
import Acquisition.pamAudio.PamAudioSettingsPane;
|
||||||
|
import Acquisition.pamAudio.WavAudioFile;
|
||||||
|
import PamController.PamControlledUnitSettings;
|
||||||
import PamController.PamController;
|
import PamController.PamController;
|
||||||
|
import PamController.PamSettingManager;
|
||||||
|
import PamController.PamSettings;
|
||||||
import PamUtils.worker.PamWorkProgressMessage;
|
import PamUtils.worker.PamWorkProgressMessage;
|
||||||
import PamUtils.worker.PamWorkWrapper;
|
import PamUtils.worker.PamWorkWrapper;
|
||||||
import PamUtils.worker.PamWorker;
|
import PamUtils.worker.PamWorker;
|
||||||
@ -30,16 +37,32 @@ import PamUtils.worker.PamWorker;
|
|||||||
* @author Jamie Macaulay
|
* @author Jamie Macaulay
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class SudAudioFile extends WavAudioFile {
|
public class SudAudioFile extends WavAudioFile implements PamSettings {
|
||||||
|
|
||||||
private Object conditionSync = new Object();
|
private Object conditionSync = new Object();
|
||||||
|
|
||||||
private volatile PamWorker<AudioInputStream> worker;
|
private volatile PamWorker<AudioInputStream> worker;
|
||||||
|
|
||||||
private volatile SudMapWorker sudMapWorker;
|
private volatile SudMapWorker sudMapWorker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings pane to allow users to set some additional options.
|
||||||
|
*/
|
||||||
|
private SudAudioSettingsPane sudAudioSettingsPane;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters for the sud file. TODO Note: PamAudioManager is always a single
|
||||||
|
* instance referenced globally from PAMGuard. Having parameters is therefore
|
||||||
|
* slightly problematic because they will apply across SoundAcquisition modules.
|
||||||
|
* So in the case that someone is using two or more Sound Acquisition modules
|
||||||
|
* then selecting zero and non -zero pad would be impossible
|
||||||
|
*/
|
||||||
|
private PamSudParams sudParams = new PamSudParams();
|
||||||
|
|
||||||
public SudAudioFile() {
|
public SudAudioFile() {
|
||||||
super();
|
super();
|
||||||
fileExtensions = new ArrayList<String>(Arrays.asList(new String[] { ".sud" }));
|
fileExtensions = new ArrayList<String>(Arrays.asList(new String[] { ".sud" }));
|
||||||
|
PamSettingManager.getInstance().registerSettings(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -63,7 +86,7 @@ public class SudAudioFile extends WavAudioFile {
|
|||||||
if (new File(soundFile.getAbsolutePath() + "x").exists()) {
|
if (new File(soundFile.getAbsolutePath() + "x").exists()) {
|
||||||
// System.out.println("----NO NEED TO MAP SUD FILE-----" + soundFile);
|
// System.out.println("----NO NEED TO MAP SUD FILE-----" + soundFile);
|
||||||
try {
|
try {
|
||||||
return new SudAudioFileReader().getAudioInputStream(soundFile);
|
return new SudAudioFileReader(sudParams.zeroPad).getAudioInputStream(soundFile);
|
||||||
} catch (UnsupportedAudioFileException | IOException e) {
|
} catch (UnsupportedAudioFileException | IOException e) {
|
||||||
// TODO Auto-generated catch block
|
// TODO Auto-generated catch block
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -181,7 +204,7 @@ public class SudAudioFile extends WavAudioFile {
|
|||||||
// System.out.println("START OPEN SUD FILE:");
|
// System.out.println("START OPEN SUD FILE:");
|
||||||
|
|
||||||
this.sudMapListener = new SudMapProgress(pamWorker);
|
this.sudMapListener = new SudMapProgress(pamWorker);
|
||||||
stream = new SudAudioFileReader().getAudioInputStream(soundFile, sudMapListener);
|
stream = new SudAudioFileReader(sudParams.zeroPad).getAudioInputStream(soundFile, sudMapListener);
|
||||||
|
|
||||||
// System.out.println("END SUD FILE:");
|
// System.out.println("END SUD FILE:");
|
||||||
|
|
||||||
@ -217,4 +240,50 @@ public class SudAudioFile extends WavAudioFile {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PamAudioSettingsPane getSettingsPane() {
|
||||||
|
if (sudAudioSettingsPane==null) {
|
||||||
|
sudAudioSettingsPane = new SudAudioSettingsPane(this);
|
||||||
|
}
|
||||||
|
return sudAudioSettingsPane;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUnitName() {
|
||||||
|
return "PamAudioManager";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUnitType() {
|
||||||
|
return "sud_files";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Serializable getSettingsReference() {
|
||||||
|
return sudParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getSettingsVersion() {
|
||||||
|
return PamSudParams.serialVersionUID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
|
||||||
|
try {
|
||||||
|
sudParams = ((PamSudParams) pamControlledUnitSettings.getSettings()).clone();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (ClassCastException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PamSudParams getSudParams() {
|
||||||
|
return this.sudParams;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package Acquisition.pamAudio;
|
package Acquisition.sud;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -25,15 +25,32 @@ public class SudAudioFileReader {
|
|||||||
*/
|
*/
|
||||||
SudParams sudParams;
|
SudParams sudParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor to create an Sud Audio reader with a
|
||||||
|
* default true to zeropad sud files.
|
||||||
|
* */
|
||||||
public SudAudioFileReader() {
|
public SudAudioFileReader() {
|
||||||
|
this(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor to create an Sud Audio reader. Allows the option of zero padding.
|
||||||
|
* Zero padding fills gaps in sud files with zeros - these gaps are usually due
|
||||||
|
* to errors in the recording hardware.Without zero pad then time drift within a
|
||||||
|
* file can be difficult to predict, however zero padding means the sample
|
||||||
|
* numbers in other files e.g. csv sensor files will not align.
|
||||||
|
*
|
||||||
|
* @param zeroPad - true to zero pad sud files.
|
||||||
|
*/
|
||||||
|
public SudAudioFileReader(boolean zeroPad) {
|
||||||
sudParams = new SudParams();
|
sudParams = new SudParams();
|
||||||
//set up the sud params for default. i.e. just read files and
|
//set up the sud params for default. i.e. just read files and
|
||||||
//don't save any decompressed or meta data.
|
//don't save any decompressed or meta data.
|
||||||
// sudParams.saveWav = false;
|
// sudParams.saveWav = false;
|
||||||
// sudParams.saveMeta = false;
|
// sudParams.saveMeta = false;
|
||||||
sudParams.setFileSave(false, false, false, false);
|
sudParams.setFileSave(false, false, false, false);
|
||||||
sudParams.zeroPad = true;
|
sudParams.zeroPad = zeroPad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
158
src/Acquisition/sud/SudAudioSettingsPane.java
Normal file
158
src/Acquisition/sud/SudAudioSettingsPane.java
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
package Acquisition.sud;
|
||||||
|
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
|
||||||
|
import javax.swing.JCheckBox;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
import Acquisition.pamAudio.PamAudioSettingsPane;
|
||||||
|
import PamView.dialog.PamGridBagContraints;
|
||||||
|
import PamView.panel.PamPanel;
|
||||||
|
import javafx.scene.control.Tooltip;
|
||||||
|
import javafx.scene.layout.Pane;
|
||||||
|
import pamViewFX.fxNodes.PamHBox;
|
||||||
|
import pamViewFX.fxNodes.utilityPanes.PamToggleSwitch;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some Swing and FX controls to allow a user to chnage sud parameters.
|
||||||
|
*/
|
||||||
|
public class SudAudioSettingsPane implements PamAudioSettingsPane {
|
||||||
|
|
||||||
|
private SudAudioFile sudAudioFile;
|
||||||
|
|
||||||
|
private SudSettingsPanel sudAudioPanel;
|
||||||
|
|
||||||
|
private SudSettingsPane sudAudioPaneFX;
|
||||||
|
|
||||||
|
private String sudTooltip = "Zero pad sud files. Zero padding replaces sections of sud files \n"
|
||||||
|
+ "with corrupt or no data with zeros. This can improve time drift. ";
|
||||||
|
|
||||||
|
|
||||||
|
public SudAudioSettingsPane(SudAudioFile sudAudioFile) {
|
||||||
|
this.sudAudioFile=sudAudioFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Pane getAudioLoaderPane() {
|
||||||
|
if (sudAudioPaneFX==null) {
|
||||||
|
createSudAudioPaneFX();
|
||||||
|
}
|
||||||
|
return sudAudioPaneFX;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PamPanel getAudioLoaderPanel() {
|
||||||
|
if (sudAudioPanel==null) {
|
||||||
|
createSudAudioPanel();
|
||||||
|
}
|
||||||
|
return sudAudioPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createSudAudioPanel() {
|
||||||
|
sudAudioPanel = new SudSettingsPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createSudAudioPaneFX() {
|
||||||
|
sudAudioPaneFX = new SudSettingsPane();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParams(PamSudParams sudParams) {
|
||||||
|
//System.out.println("Set SUD PARAMS: " + sudParams + " " + sudParams.zeroPad);
|
||||||
|
if (sudAudioPanel!=null) sudAudioPanel.setParams(sudParams);;
|
||||||
|
if (sudAudioPaneFX!=null) sudAudioPaneFX.setParams(sudParams);;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public PamSudParams getParams(PamSudParams sudParams) {
|
||||||
|
//System.out.println("Get SUD PARAMS: " + sudParams + " " + sudParams.zeroPad);
|
||||||
|
|
||||||
|
if (sudAudioPanel!=null) return sudAudioPanel.getParams(sudParams);
|
||||||
|
if (sudAudioPaneFX!=null) return sudAudioPaneFX.getParams(sudParams);;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sud settings panel.
|
||||||
|
*/
|
||||||
|
public class SudSettingsPanel extends PamPanel {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private JCheckBox zeroPadSud;
|
||||||
|
|
||||||
|
public SudSettingsPanel() {
|
||||||
|
|
||||||
|
this.setLayout(new GridBagLayout());
|
||||||
|
// soundTrapDate.setPreferredSize(tzPanel.getPreferredSize());
|
||||||
|
GridBagConstraints c = new PamGridBagContraints();
|
||||||
|
c.gridy = 0;
|
||||||
|
c.gridx = 0;
|
||||||
|
c.gridwidth = 1;
|
||||||
|
|
||||||
|
zeroPadSud = new JCheckBox("Zero pad sud files");
|
||||||
|
zeroPadSud.setToolTipText(sudTooltip);
|
||||||
|
|
||||||
|
this.add(zeroPadSud,c);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParams(PamSudParams sudParams) {
|
||||||
|
this.zeroPadSud.setSelected(sudParams.zeroPad);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public PamSudParams getParams(PamSudParams sudParams) {
|
||||||
|
sudParams.zeroPad = zeroPadSud.isSelected();
|
||||||
|
return sudParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sud settings panel for JavaFX
|
||||||
|
*/
|
||||||
|
public class SudSettingsPane extends PamHBox {
|
||||||
|
|
||||||
|
private PamToggleSwitch zeroPadSud;
|
||||||
|
|
||||||
|
public SudSettingsPane() {
|
||||||
|
|
||||||
|
// soundTrapDate.setPreferredSize(tzPanel.getPreferredSize());
|
||||||
|
GridBagConstraints c = new PamGridBagContraints();
|
||||||
|
c.gridy = 0;
|
||||||
|
c.gridx = 0;
|
||||||
|
c.gridwidth = 1;
|
||||||
|
|
||||||
|
zeroPadSud = new PamToggleSwitch("Zero pad sud files");
|
||||||
|
zeroPadSud.setTooltip(new Tooltip(sudTooltip));
|
||||||
|
|
||||||
|
this.getChildren().add(zeroPadSud);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParams(PamSudParams sudParams) {
|
||||||
|
this.zeroPadSud.setSelected(sudParams.zeroPad);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public PamSudParams getParams(PamSudParams sudParams) {
|
||||||
|
sudParams.zeroPad = zeroPadSud.isSelected();
|
||||||
|
return sudParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void getParams() {
|
||||||
|
getParams(sudAudioFile.getSudParams());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParams() {
|
||||||
|
setParams(sudAudioFile.getSudParams());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -564,6 +564,55 @@ public class PamArrayUtils {
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the index of the maximum value in an array
|
||||||
|
* @param arr - the array to find the position of the maximum value.
|
||||||
|
* m value of.
|
||||||
|
* @return the index of the maximum value
|
||||||
|
*/
|
||||||
|
public static int maxPos(float[] arr) {
|
||||||
|
double max = Double.NEGATIVE_INFINITY;
|
||||||
|
int index = -1;
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
for(float cur: arr) {
|
||||||
|
if (cur>max) {
|
||||||
|
index = count;
|
||||||
|
max=cur;
|
||||||
|
}
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the index of the maximum value within a 2D matrix
|
||||||
|
* @param arr - the array to find the position of the maximum value.
|
||||||
|
* m value of.
|
||||||
|
* @return the index i and j of the maximum value
|
||||||
|
*/
|
||||||
|
public static int[] maxPos(float[][] arr) {
|
||||||
|
float max = Float.NEGATIVE_INFINITY;
|
||||||
|
int[] index = new int[] {-1,-1};
|
||||||
|
|
||||||
|
// int count = 0;
|
||||||
|
float cur;
|
||||||
|
for(int i=0; i<arr.length; i++) {
|
||||||
|
for(int j=0; j<arr.length; j++) {
|
||||||
|
cur = arr[i][j];
|
||||||
|
if (cur>max) {
|
||||||
|
index[0]=i;
|
||||||
|
index[1]=j;
|
||||||
|
max=cur;
|
||||||
|
}
|
||||||
|
// count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the minimum index of an array
|
* Get the minimum index of an array
|
||||||
* @param arr - the array to find the position of the maximum value.
|
* @param arr - the array to find the position of the maximum value.
|
||||||
|
@ -159,4 +159,29 @@ public class PamAWTUtils {
|
|||||||
return bestPoint;
|
return bestPoint;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a colour to an int.
|
||||||
|
* @param c - the colour to change.
|
||||||
|
* @return the int representation of the colour
|
||||||
|
*/
|
||||||
|
public static int colorToInt(java.awt.Color c) {
|
||||||
|
int r = (int) Math.round(c.getRed());
|
||||||
|
int g = (int) Math.round(c.getGreen());
|
||||||
|
int b = (int) Math.round(c.getBlue());
|
||||||
|
return (r << 16) | (g << 8) | b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an int encoded with a colour to a Color object.
|
||||||
|
* @param value - the int to convert to colour
|
||||||
|
* @return the Color object for the int
|
||||||
|
*/
|
||||||
|
public static java.awt.Color intToColor(int value) {
|
||||||
|
int r = (value >>> 16) & 0xFF;
|
||||||
|
int g = (value >>> 8) & 0xFF;
|
||||||
|
int b = value & 0xFF;
|
||||||
|
return new java.awt.Color(r,g,b);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,8 @@ import javax.swing.JComponent;
|
|||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.border.EmptyBorder;
|
import javax.swing.border.EmptyBorder;
|
||||||
|
|
||||||
|
import PamController.PamController;
|
||||||
|
|
||||||
public class GenericSwingDialog extends PamDialog {
|
public class GenericSwingDialog extends PamDialog {
|
||||||
|
|
||||||
private boolean allOk;
|
private boolean allOk;
|
||||||
@ -45,6 +47,9 @@ public class GenericSwingDialog extends PamDialog {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static boolean showDialog(Window parentFrame, String title, Point screenPoint, PamDialogPanel ...dialogPanels) {
|
public static boolean showDialog(Window parentFrame, String title, Point screenPoint, PamDialogPanel ...dialogPanels) {
|
||||||
|
if (parentFrame == null) {
|
||||||
|
parentFrame = PamController.getMainFrame();
|
||||||
|
}
|
||||||
GenericSwingDialog swingDialog = new GenericSwingDialog(parentFrame, title, dialogPanels);
|
GenericSwingDialog swingDialog = new GenericSwingDialog(parentFrame, title, dialogPanels);
|
||||||
swingDialog.setParams();
|
swingDialog.setParams();
|
||||||
swingDialog.pack();
|
swingDialog.pack();
|
||||||
|
@ -5,6 +5,7 @@ import javax.swing.JComponent;
|
|||||||
/**
|
/**
|
||||||
* General class for dialog panels which will be incorporated into one or
|
* General class for dialog panels which will be incorporated into one or
|
||||||
* more actual dialogs.
|
* more actual dialogs.
|
||||||
|
* Can be quickly opened with GenericSwingDialog
|
||||||
* @author Doug Gillespie
|
* @author Doug Gillespie
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -5,6 +5,7 @@ import java.awt.Color;
|
|||||||
import PamUtils.PamUtils;
|
import PamUtils.PamUtils;
|
||||||
import PamView.GeneralProjector;
|
import PamView.GeneralProjector;
|
||||||
import PamView.PamSymbolType;
|
import PamView.PamSymbolType;
|
||||||
|
import PamView.dialog.PamDialogPanel;
|
||||||
import PamView.symbol.PamSymbolChooser;
|
import PamView.symbol.PamSymbolChooser;
|
||||||
import PamView.symbol.SymbolData;
|
import PamView.symbol.SymbolData;
|
||||||
import PamguardMVC.PamDataUnit;
|
import PamguardMVC.PamDataUnit;
|
||||||
@ -45,7 +46,15 @@ public class PeakFreqModifier extends SymbolModifier {
|
|||||||
*/
|
*/
|
||||||
private ColourArrayType colourArrayType;
|
private ColourArrayType colourArrayType;
|
||||||
|
|
||||||
private PeakFreqOptionsPane peakFreqOptions;
|
/**
|
||||||
|
* JavaFX pane for frequency symbol options.
|
||||||
|
*/
|
||||||
|
private PeakFreqOptionsPane peakFreqOptionsPaneFX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swing panel for frequency symbol options
|
||||||
|
*/
|
||||||
|
private PamDialogPanel peakFreqOptionsPanel;
|
||||||
|
|
||||||
public PeakFreqModifier(PamSymbolChooser symbolChooser) {
|
public PeakFreqModifier(PamSymbolChooser symbolChooser) {
|
||||||
super(PEAK_FREQ_MODIFIER_NAME, symbolChooser, SymbolModType.FILLCOLOUR | SymbolModType.LINECOLOUR );
|
super(PEAK_FREQ_MODIFIER_NAME, symbolChooser, SymbolModType.FILLCOLOUR | SymbolModType.LINECOLOUR );
|
||||||
@ -130,11 +139,20 @@ public class PeakFreqModifier extends SymbolModifier {
|
|||||||
@Override
|
@Override
|
||||||
public SymbolModifierPane getOptionsPane() {
|
public SymbolModifierPane getOptionsPane() {
|
||||||
//System.out.println("PEAK FREQ COLOUR ARRAY2: " + peakFreqSymbolOptions.freqColourArray);
|
//System.out.println("PEAK FREQ COLOUR ARRAY2: " + peakFreqSymbolOptions.freqColourArray);
|
||||||
if (this.peakFreqOptions==null) {
|
if (this.peakFreqOptionsPaneFX==null) {
|
||||||
peakFreqOptions = new PeakFreqOptionsPane(this);
|
peakFreqOptionsPaneFX = new PeakFreqOptionsPane(this);
|
||||||
peakFreqOptions.setParams();
|
peakFreqOptionsPaneFX.setParams();
|
||||||
}
|
}
|
||||||
return peakFreqOptions;
|
return peakFreqOptionsPaneFX;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PamDialogPanel getDialogPanel() {
|
||||||
|
//System.out.println("PEAK FREQ COLOUR ARRAY2: " + peakFreqSymbolOptions.freqColourArray);
|
||||||
|
if (this.peakFreqOptionsPanel==null) {
|
||||||
|
peakFreqOptionsPanel = new PeakFreqOptionsPanel(this);
|
||||||
|
peakFreqOptionsPanel.setParams();
|
||||||
|
}
|
||||||
|
return peakFreqOptionsPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
203
src/PamView/symbol/modifier/PeakFreqOptionsPanel.java
Normal file
203
src/PamView/symbol/modifier/PeakFreqOptionsPanel.java
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
package PamView.symbol.modifier;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JSpinner;
|
||||||
|
import javax.swing.SpinnerNumberModel;
|
||||||
|
import javax.swing.border.TitledBorder;
|
||||||
|
|
||||||
|
import PamView.ColourComboBox;
|
||||||
|
import PamView.dialog.PamDialogPanel;
|
||||||
|
import PamView.panel.PamPanel;
|
||||||
|
import pamViewFX.fxNodes.utilsFX.PamUtilsFX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swing panel for changing parameters for the peak frequency symbol chooser.
|
||||||
|
*
|
||||||
|
* @author Jamie Macaulay
|
||||||
|
*/
|
||||||
|
public class PeakFreqOptionsPanel implements PamDialogPanel {
|
||||||
|
|
||||||
|
private PeakFreqModifier freqSymbolModifer;
|
||||||
|
|
||||||
|
private PamPanel mainPanel;
|
||||||
|
|
||||||
|
private JSpinner minFreq;
|
||||||
|
|
||||||
|
private JSpinner maxFreq;
|
||||||
|
|
||||||
|
private ColourComboBox colourBox;
|
||||||
|
|
||||||
|
public PeakFreqOptionsPanel(PeakFreqModifier symbolModifer) {
|
||||||
|
this.freqSymbolModifer=symbolModifer;
|
||||||
|
mainPanel = createFreqPaneL();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pane which changes the frequency limits.
|
||||||
|
* @return pane with controls to change freq. limits.
|
||||||
|
*/
|
||||||
|
private PamPanel createFreqPaneL(){
|
||||||
|
|
||||||
|
PamPanel holder = new PamPanel();
|
||||||
|
holder.setLayout(new GridBagLayout());
|
||||||
|
holder.setBorder(new TitledBorder("Peak frequency colour map"));
|
||||||
|
|
||||||
|
GridBagConstraints c = new GridBagConstraints();
|
||||||
|
c.gridy=0;
|
||||||
|
c.gridx=0;
|
||||||
|
|
||||||
|
//doesn't seem to work so added spaces in labels instead
|
||||||
|
c.ipadx = 5;
|
||||||
|
|
||||||
|
|
||||||
|
c.anchor =GridBagConstraints.EAST;
|
||||||
|
holder.add(new JLabel("Min. freq"), c);
|
||||||
|
|
||||||
|
c.gridx++;
|
||||||
|
c.anchor =GridBagConstraints.WEST;
|
||||||
|
minFreq = new JSpinner(new SpinnerNumberModel(0., 0., 10000000., 1000.));
|
||||||
|
//make the lock button the same height as the spinner
|
||||||
|
Dimension prefSize = minFreq.getPreferredSize();
|
||||||
|
minFreq.setPreferredSize(new Dimension(90, prefSize.height));
|
||||||
|
|
||||||
|
holder.add(minFreq, c);
|
||||||
|
|
||||||
|
c.gridx++;
|
||||||
|
c.ipadx = 5;
|
||||||
|
c.anchor =GridBagConstraints.EAST;
|
||||||
|
holder.add(new JLabel(" Max. freq"), c);
|
||||||
|
|
||||||
|
c.gridx++;
|
||||||
|
c.ipadx = 5;
|
||||||
|
c.anchor =GridBagConstraints.WEST;
|
||||||
|
maxFreq =new JSpinner(new SpinnerNumberModel(1000., 1., Math.max(1000.,freqSymbolModifer.getSymbolChooser().getPamDataBlock().getSampleRate()/2.), 1000.));
|
||||||
|
maxFreq.setPreferredSize(new Dimension(90, prefSize.height));
|
||||||
|
holder.add(maxFreq, c);
|
||||||
|
|
||||||
|
c.gridx++;
|
||||||
|
c.ipadx = 5;
|
||||||
|
c.anchor =GridBagConstraints.WEST;
|
||||||
|
holder.add(new JLabel(" Hz"), c);
|
||||||
|
|
||||||
|
|
||||||
|
c.gridy++;
|
||||||
|
c.ipadx = 5;
|
||||||
|
c.gridwidth=2;
|
||||||
|
|
||||||
|
c.gridx=0;
|
||||||
|
c.anchor =GridBagConstraints.EAST;
|
||||||
|
holder.add(new JLabel("Freq. colour map"), c);
|
||||||
|
|
||||||
|
c.gridx=2;
|
||||||
|
c.gridwidth=3;
|
||||||
|
colourBox = new ColourComboBox();
|
||||||
|
c.anchor =GridBagConstraints.WEST;
|
||||||
|
prefSize = colourBox.getPreferredSize();
|
||||||
|
colourBox.setPreferredSize(new Dimension(200, prefSize.height));
|
||||||
|
holder.add(colourBox, c);
|
||||||
|
|
||||||
|
return holder;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JComponent getDialogComponent() {
|
||||||
|
return mainPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getParams(){
|
||||||
|
|
||||||
|
//bit messy but works /
|
||||||
|
// PeakFreqSymbolOptions symbolOptions = (PeakFreqSymbolOptions) standardSymbolOptions.getModifierParams(this.getSymbolModifier().getName());
|
||||||
|
|
||||||
|
PeakFreqSymbolOptions symbolOptions = (PeakFreqSymbolOptions)freqSymbolModifer.getSymbolModifierParams().clone();
|
||||||
|
//must make sure we do not call get parameters during a set parameters - the listeners on the controls call getParams so all goes
|
||||||
|
//haywire if the setParams is not set properly.
|
||||||
|
//System.out.println("GETPARAMS: " + ColourArray.getColorArrayType(this.colourBox.getSelectionModel().getSelectedItem()) + " " + setParams);
|
||||||
|
symbolOptions.freqLimts=new double[] {(double) minFreq.getValue(), (double) maxFreq.getValue()};
|
||||||
|
symbolOptions.freqColourArray = PamUtilsFX.swingColArray2FX(this.colourBox.getSelectedColourMap());
|
||||||
|
|
||||||
|
//System.out.println("StandardSymbolModifierPane : getParams(): new mod: " +mod);
|
||||||
|
|
||||||
|
freqSymbolModifer.setSymbolModifierParams(symbolOptions);
|
||||||
|
|
||||||
|
System.out.println("Get freq limits: 1: " + symbolOptions.freqLimts[0] + " " + symbolOptions.freqLimts[1] + " " + (double) maxFreq.getValue());
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParams() {
|
||||||
|
|
||||||
|
// StandardSymbolOptions standardSymbolOptions = (StandardSymbolOptions) getSymbolModifier().getSymbolChooser().getSymbolOptions();
|
||||||
|
// PeakFreqSymbolOptions symbolOptions = (PeakFreqSymbolOptions) standardSymbolOptions.getModifierParams(this.getSymbolModifier().getName());
|
||||||
|
PeakFreqSymbolOptions symbolOptions = (PeakFreqSymbolOptions)freqSymbolModifer.getSymbolModifierParams();
|
||||||
|
|
||||||
|
//now set frequency parameters;
|
||||||
|
checkFreqLimits( symbolOptions ) ;
|
||||||
|
|
||||||
|
minFreq.setValue(symbolOptions.freqLimts[0]);
|
||||||
|
maxFreq.setValue(symbolOptions.freqLimts[1]);
|
||||||
|
|
||||||
|
colourBox.setSelectedColourMap((PamUtilsFX.fxColArray2Swing(symbolOptions.freqColourArray)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the frequency limits make sense for the given datablock
|
||||||
|
* @param symbolOptions - the peak frequency options.
|
||||||
|
*/
|
||||||
|
private void checkFreqLimits(PeakFreqSymbolOptions symbolOptions ) {
|
||||||
|
|
||||||
|
System.out.println("Check freq limits: 1: " + symbolOptions.freqLimts[0] + " " + symbolOptions.freqLimts[1]);
|
||||||
|
|
||||||
|
SpinnerNumberModel spinnerValFact = (SpinnerNumberModel) maxFreq.getModel();
|
||||||
|
spinnerValFact.setMaximum(getSampleRate() /2.);
|
||||||
|
//for some reason also need to set this
|
||||||
|
spinnerValFact.setMinimum(1.);
|
||||||
|
|
||||||
|
//set reasonable step sizes
|
||||||
|
if (getSampleRate()>=10000) {
|
||||||
|
spinnerValFact.setStepSize(1000.);
|
||||||
|
}
|
||||||
|
else if (getSampleRate()>=2000){
|
||||||
|
spinnerValFact.setStepSize(200.);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
spinnerValFact.setStepSize(50.);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (symbolOptions.freqLimts==null) {
|
||||||
|
symbolOptions.freqLimts= new double[] {0, getSampleRate() /2};
|
||||||
|
}
|
||||||
|
System.out.println("Check freq limits: 2: " + symbolOptions.freqLimts[0] + " " + symbolOptions.freqLimts[1]);
|
||||||
|
//check nyquist for upper limit
|
||||||
|
if (symbolOptions.freqLimts[1]>getSampleRate() /2) {
|
||||||
|
symbolOptions.freqLimts[1]=getSampleRate() /2;
|
||||||
|
}
|
||||||
|
//check nyquist for lower limit
|
||||||
|
if (symbolOptions.freqLimts[0]>getSampleRate() /2) {
|
||||||
|
symbolOptions.freqLimts[0]=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private float getSampleRate() {
|
||||||
|
return freqSymbolModifer.getSymbolChooser().getPamDataBlock().getSampleRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -150,7 +150,8 @@ abstract public class SymbolModifier {
|
|||||||
if (dialogPanel == null) {
|
if (dialogPanel == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
JMenuItem menuItem = new JMenuItem("Options ...");
|
JMenuItem menuItem = new JMenuItem("More options ...");
|
||||||
|
menuItem.setToolTipText("More symbol options");
|
||||||
menuItem.addActionListener(new ActionListener() {
|
menuItem.addActionListener(new ActionListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -8,12 +8,13 @@ import java.util.Enumeration;
|
|||||||
import javax.swing.tree.TreeNode;
|
import javax.swing.tree.TreeNode;
|
||||||
|
|
||||||
import PamUtils.PamUtils;
|
import PamUtils.PamUtils;
|
||||||
|
import PamView.dialog.PamDialogPanel;
|
||||||
import PamView.symbol.modifier.SymbolModifier;
|
import PamView.symbol.modifier.SymbolModifier;
|
||||||
|
|
||||||
public class ModifierTreeNode implements TreeNode {
|
public class ModifierTreeNode implements TreeNode {
|
||||||
private SymbolModifier modifier;
|
private SymbolModifier modifier;
|
||||||
private SymbolTreeRoot rootNode;
|
private SymbolTreeRoot rootNode;
|
||||||
private ArrayList<ChoiceTreeNode> choiceNodes;
|
private ArrayList<TreeNode> choiceNodes;
|
||||||
|
|
||||||
public ModifierTreeNode(SymbolTreeRoot rootNode, SymbolModifier modifier) {
|
public ModifierTreeNode(SymbolTreeRoot rootNode, SymbolModifier modifier) {
|
||||||
super();
|
super();
|
||||||
@ -22,8 +23,16 @@ public class ModifierTreeNode implements TreeNode {
|
|||||||
int modBits = modifier.getModifyableBits();
|
int modBits = modifier.getModifyableBits();
|
||||||
int nMod = Integer.bitCount(modBits);
|
int nMod = Integer.bitCount(modBits);
|
||||||
choiceNodes = new ArrayList<>();
|
choiceNodes = new ArrayList<>();
|
||||||
|
|
||||||
|
int leafIndex = 0;
|
||||||
|
|
||||||
for (int i = 0; i < nMod; i++) {
|
for (int i = 0; i < nMod; i++) {
|
||||||
choiceNodes.add(new ChoiceTreeNode(this, 1<<PamUtils.getNthChannel(i, modBits), i));
|
choiceNodes.add(new ChoiceTreeNode(this, 1<<PamUtils.getNthChannel(i, modBits), leafIndex++));
|
||||||
|
}
|
||||||
|
|
||||||
|
PamDialogPanel optionsPanel = modifier.getDialogPanel();
|
||||||
|
if (optionsPanel != null) {
|
||||||
|
choiceNodes.add(new OptionsTreeNode(this, modifier, optionsPanel, leafIndex++));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -73,18 +82,24 @@ public class ModifierTreeNode implements TreeNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setModBitmap(int modBitMap) {
|
public void setModBitmap(int modBitMap) {
|
||||||
for (ChoiceTreeNode cN : choiceNodes) {
|
for (TreeNode tN : choiceNodes) {
|
||||||
|
if (tN instanceof ChoiceTreeNode) {
|
||||||
|
ChoiceTreeNode cN = (ChoiceTreeNode) tN;
|
||||||
cN.checkBox.setSelected((cN.selectionBit & modBitMap) != 0);
|
cN.checkBox.setSelected((cN.selectionBit & modBitMap) != 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public int getModBitmap() {
|
public int getModBitmap() {
|
||||||
int mp = 0;
|
int mp = 0;
|
||||||
for (ChoiceTreeNode cN : choiceNodes) {
|
for (TreeNode tN : choiceNodes) {
|
||||||
|
if (tN instanceof ChoiceTreeNode) {
|
||||||
|
ChoiceTreeNode cN = (ChoiceTreeNode) tN;
|
||||||
if (cN.checkBox.isSelected()) {
|
if (cN.checkBox.isSelected()) {
|
||||||
mp |= cN.selectionBit;
|
mp |= cN.selectionBit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return mp;
|
return mp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
81
src/PamView/symbol/modifier/swing/OptionsTreeNode.java
Normal file
81
src/PamView/symbol/modifier/swing/OptionsTreeNode.java
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package PamView.symbol.modifier.swing;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.tree.TreeNode;
|
||||||
|
|
||||||
|
import PamView.dialog.GenericSwingDialog;
|
||||||
|
import PamView.dialog.PamDialogPanel;
|
||||||
|
import PamView.symbol.modifier.SymbolModifier;
|
||||||
|
|
||||||
|
public class OptionsTreeNode implements TreeNode {
|
||||||
|
|
||||||
|
private ModifierTreeNode parent;
|
||||||
|
private SymbolModifier modifier;
|
||||||
|
private PamDialogPanel optionsPanel;
|
||||||
|
protected JButton optionsButton;
|
||||||
|
private int leafIndex;
|
||||||
|
|
||||||
|
public OptionsTreeNode(ModifierTreeNode parent, SymbolModifier modifier, PamDialogPanel optionsPanel, int leafIndex) {
|
||||||
|
this.parent = parent;
|
||||||
|
this.modifier = modifier;
|
||||||
|
this.optionsPanel = optionsPanel;
|
||||||
|
this.leafIndex = leafIndex;
|
||||||
|
optionsButton = new JButton("more ...");
|
||||||
|
optionsButton.setToolTipText("More symbol options");
|
||||||
|
optionsButton.addActionListener(new ActionListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
showOptions();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showOptions() {
|
||||||
|
optionsPanel.setParams();
|
||||||
|
boolean ok = GenericSwingDialog.showDialog(null, "Options", optionsPanel);
|
||||||
|
if (ok) {
|
||||||
|
optionsPanel.getParams();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TreeNode getChildAt(int childIndex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChildCount() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TreeNode getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIndex(TreeNode node) {
|
||||||
|
return leafIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getAllowsChildren() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLeaf() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Enumeration<? extends TreeNode> children() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -18,12 +18,10 @@ import javax.swing.tree.TreePath;
|
|||||||
|
|
||||||
import PamView.dialog.DialogScrollPane;
|
import PamView.dialog.DialogScrollPane;
|
||||||
import PamView.dialog.PamDialogPanel;
|
import PamView.dialog.PamDialogPanel;
|
||||||
import PamView.symbol.PamSymbolChooser;
|
|
||||||
import PamView.symbol.StandardSymbolChooser;
|
import PamView.symbol.StandardSymbolChooser;
|
||||||
import PamView.symbol.StandardSymbolOptions;
|
import PamView.symbol.StandardSymbolOptions;
|
||||||
import PamView.symbol.modifier.SymbolModifier;
|
import PamView.symbol.modifier.SymbolModifier;
|
||||||
import PamView.symbol.modifier.SymbolModifierParams;
|
import PamView.symbol.modifier.SymbolModifierParams;
|
||||||
import PamguardMVC.debug.Debug;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Panel to include in a dialog with options to select and activate a variety of symbol modifiers.
|
* Panel to include in a dialog with options to select and activate a variety of symbol modifiers.
|
||||||
@ -137,6 +135,7 @@ public class SymbolModifierPanel implements PamDialogPanel {
|
|||||||
JMenuItem optsItem = modifier.getModifierOptionsMenu();
|
JMenuItem optsItem = modifier.getModifierOptionsMenu();
|
||||||
if (optsItem != null) {
|
if (optsItem != null) {
|
||||||
popMenu.add(optsItem);
|
popMenu.add(optsItem);
|
||||||
|
popMenu.addSeparator();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nodeInd > 0) {
|
if (nodeInd > 0) {
|
||||||
|
@ -44,6 +44,10 @@ public class SymbolTreeRenderer extends DefaultTreeCellRenderer {
|
|||||||
return checkboxChoice(tree, (ChoiceTreeNode) value, sel, expanded, leaf, row, hasFocus);
|
return checkboxChoice(tree, (ChoiceTreeNode) value, sel, expanded, leaf, row, hasFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (value instanceof OptionsTreeNode) {
|
||||||
|
return ((OptionsTreeNode) value).optionsButton;
|
||||||
|
}
|
||||||
|
|
||||||
Component component = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
|
Component component = super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
|
||||||
if (value instanceof ModifierTreeNode) {
|
if (value instanceof ModifierTreeNode) {
|
||||||
setModifierStuff((ModifierTreeNode) value, component);
|
setModifierStuff((ModifierTreeNode) value, component);
|
||||||
|
@ -411,7 +411,15 @@ public class RawDataTransforms {
|
|||||||
paddedRawData = new double[fftLength];
|
paddedRawData = new double[fftLength];
|
||||||
rawData = getWaveData(channel);
|
rawData = getWaveData(channel);
|
||||||
//double[] rotData = getRotationCorrection(channel);
|
//double[] rotData = getRotationCorrection(channel);
|
||||||
mn = Math.min(fftLength, getSampleDuration().intValue());
|
|
||||||
|
/**
|
||||||
|
*FIXME
|
||||||
|
* 11/07 Changed from getSampleDuration because an error sometimes occurs where the sample duration
|
||||||
|
* is not the same as the wavefom length...not sure why.
|
||||||
|
*/
|
||||||
|
//mn = Math.min(fftLength, getSampleDuration().intValue());
|
||||||
|
mn = Math.min(fftLength, rawData.length);
|
||||||
|
// System.out.println("fftLength: " + rawData.length + " " + getSampleDuration().intValue() + " mn " +mn);
|
||||||
for (i = 0; i < mn; i++) {
|
for (i = 0; i < mn; i++) {
|
||||||
paddedRawData[i] = rawData[i];//-rotData[i];
|
paddedRawData[i] = rawData[i];//-rotData[i];
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ public class CompoundDataSelector extends DataSelector {
|
|||||||
|
|
||||||
private CompoundParams compoundParams = new CompoundParams();
|
private CompoundParams compoundParams = new CompoundParams();
|
||||||
|
|
||||||
|
private CompoundDialogPaneFX compoundPaneFX;
|
||||||
|
|
||||||
public CompoundDataSelector(PamDataBlock pamDataBlock, ArrayList<DataSelector> allSelectors,
|
public CompoundDataSelector(PamDataBlock pamDataBlock, ArrayList<DataSelector> allSelectors,
|
||||||
String selectorName, boolean allowScores, String selectorType) {
|
String selectorName, boolean allowScores, String selectorType) {
|
||||||
super(pamDataBlock, selectorName, allowScores);
|
super(pamDataBlock, selectorName, allowScores);
|
||||||
@ -57,8 +59,10 @@ public class CompoundDataSelector extends DataSelector {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DynamicSettingsPane<Boolean> getDialogPaneFX() {
|
public DynamicSettingsPane<Boolean> getDialogPaneFX() {
|
||||||
// TODO Auto-generated method stub
|
if (compoundPaneFX==null) {
|
||||||
return null;
|
compoundPaneFX = new CompoundDialogPaneFX(this);
|
||||||
|
}
|
||||||
|
return compoundPaneFX;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -91,6 +95,9 @@ public class CompoundDataSelector extends DataSelector {
|
|||||||
score = Math.max(score, score2); // take the largest
|
score = Math.max(score, score2); // take the largest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// System.out.println("Hello Compound Data selector: " + score);
|
||||||
|
|
||||||
return score;
|
return score;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,4 +108,25 @@ public class CompoundDataSelector extends DataSelector {
|
|||||||
return selectorList;
|
return selectorList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataSelector findDataSelector(Class selectorClass) {
|
||||||
|
/**
|
||||||
|
* Check this, then all in the selector list. Should iterate happily back to
|
||||||
|
* a basic data selector as required even if there are multiple Compound ones.
|
||||||
|
*/
|
||||||
|
if (this.getClass() == selectorClass) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
if (selectorList == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (DataSelector aSelector : selectorList) {
|
||||||
|
DataSelector subSel = aSelector.findDataSelector(selectorClass);
|
||||||
|
if (subSel != null) {
|
||||||
|
return subSel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
89
src/PamguardMVC/dataSelector/CompoundDialogPaneFX.java
Normal file
89
src/PamguardMVC/dataSelector/CompoundDialogPaneFX.java
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
package PamguardMVC.dataSelector;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import pamViewFX.fxNodes.PamVBox;
|
||||||
|
import pamViewFX.fxSettingsPanes.DynamicSettingsPane;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shows multiple data selectors in a pane. This would be used, for example, in a situation where
|
||||||
|
* a data unit has multiple associated data selectors, for example if is annotated with an annotation
|
||||||
|
* that has a data selector.
|
||||||
|
*/
|
||||||
|
public class CompoundDialogPaneFX extends DynamicSettingsPane<Boolean> {
|
||||||
|
|
||||||
|
|
||||||
|
private CompoundDataSelector compoundDataSelector;
|
||||||
|
|
||||||
|
private ArrayList<DataSelector> selectorList;
|
||||||
|
private ArrayList<DataSelectorDialogPaneFX> selectorPanels;
|
||||||
|
|
||||||
|
private PamVBox mainPanel;
|
||||||
|
|
||||||
|
public CompoundDialogPaneFX(CompoundDataSelector compoundDataSelector) {
|
||||||
|
super(null);
|
||||||
|
|
||||||
|
this.compoundDataSelector = compoundDataSelector;
|
||||||
|
this.selectorList = compoundDataSelector.getSelectorList();
|
||||||
|
|
||||||
|
mainPanel = new PamVBox();
|
||||||
|
mainPanel.setSpacing(10);
|
||||||
|
selectorPanels = new ArrayList<DataSelectorDialogPaneFX>(selectorList.size());
|
||||||
|
int ind = 0;
|
||||||
|
for (DataSelector ds : selectorList) {
|
||||||
|
DynamicSettingsPane<Boolean> panel = ds.getDialogPaneFX();
|
||||||
|
// turn all these panels into the compound ones with the extra enable options.
|
||||||
|
|
||||||
|
DataSelectorDialogPaneFX dsp = new DataSelectorDialogPaneFX(ds, panel, ind++);
|
||||||
|
selectorPanels.add(dsp);
|
||||||
|
|
||||||
|
//need to add a listener for settings changes to these panes so it can be passed to this pane
|
||||||
|
dsp.addSettingsListener(()->{
|
||||||
|
//notify any listeners to this pane that the sub pane has changed.
|
||||||
|
notifySettingsListeners();
|
||||||
|
});
|
||||||
|
|
||||||
|
mainPanel.getChildren().add(dsp.getContentNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean getParams(Boolean currParams) {
|
||||||
|
boolean ok = true;
|
||||||
|
for (int i = 0; i < selectorPanels.size(); i++) {
|
||||||
|
DataSelectorDialogPaneFX panel = selectorPanels.get(i);
|
||||||
|
ok |= panel.getParams(currParams);
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParams(Boolean input) {
|
||||||
|
for (int i = 0; i < selectorPanels.size(); i++) {
|
||||||
|
DataSelectorDialogPaneFX panel = selectorPanels.get(i);
|
||||||
|
panel.setParams(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Compound data selector pane";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getContentNode() {
|
||||||
|
return mainPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paneInitialized() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,11 +1,9 @@
|
|||||||
package PamguardMVC.dataSelector;
|
package PamguardMVC.dataSelector;
|
||||||
|
|
||||||
import java.awt.Color;
|
|
||||||
import java.awt.GridBagConstraints;
|
import java.awt.GridBagConstraints;
|
||||||
import java.awt.GridBagLayout;
|
import java.awt.GridBagLayout;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import javax.swing.BoxLayout;
|
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
@ -76,6 +76,22 @@ public class DataSelectDialog extends PamDialog {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean setTab(int tabIndex) {
|
||||||
|
if (tabPane == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (tabIndex < 0 || tabIndex >= tabPane.getTabCount()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
tabPane.setSelectedIndex(tabIndex);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean showDialog() {
|
public boolean showDialog() {
|
||||||
if (dataPanel != null) {
|
if (dataPanel != null) {
|
||||||
dataPanel.setParams();
|
dataPanel.setParams();
|
||||||
|
@ -97,6 +97,23 @@ public abstract class DataSelector {
|
|||||||
*/
|
*/
|
||||||
abstract public DynamicSettingsPane<Boolean> getDialogPaneFX();
|
abstract public DynamicSettingsPane<Boolean> getDialogPaneFX();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a data selector within a data selector. This is primarily for use with
|
||||||
|
* ComoundDataSelector objects which may encapsulate multiple other selectors,
|
||||||
|
* particularly when annotations are in use. but it's needed here so that it
|
||||||
|
* can be called on any DataSelector object.
|
||||||
|
* @param selectorClass class to data selector to find.
|
||||||
|
* @return DataSelector or null if that class of data selector doesn't exist.
|
||||||
|
*/
|
||||||
|
public DataSelector findDataSelector(Class selectorClass) {
|
||||||
|
if (this.getClass() == selectorClass) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a menu item for the data selector that can be easily added
|
* Get a menu item for the data selector that can be easily added
|
||||||
* to any other menu.
|
* to any other menu.
|
||||||
|
213
src/PamguardMVC/dataSelector/DataSelectorDialogPaneFX.java
Normal file
213
src/PamguardMVC/dataSelector/DataSelectorDialogPaneFX.java
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
package PamguardMVC.dataSelector;
|
||||||
|
|
||||||
|
import org.controlsfx.control.SegmentedButton;
|
||||||
|
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.Separator;
|
||||||
|
import javafx.scene.control.ToggleButton;
|
||||||
|
import javafx.scene.control.ToggleGroup;
|
||||||
|
import javafx.scene.control.Tooltip;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import pamViewFX.PamGuiManagerFX;
|
||||||
|
import pamViewFX.fxNodes.PamVBox;
|
||||||
|
import pamViewFX.fxSettingsPanes.DynamicSettingsPane;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog panel to wrap around a standard dialog panel from a data selector.
|
||||||
|
* This adds a wrapper the data selector which enables or disables it based on
|
||||||
|
* whether it has been selected or not.
|
||||||
|
* @author Jamie Macaulay
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class DataSelectorDialogPaneFX extends DynamicSettingsPane<Boolean> {
|
||||||
|
|
||||||
|
private static final double PREF_TOGGLE_WIDTH = 60;
|
||||||
|
|
||||||
|
private DataSelector dataSelector;
|
||||||
|
private DynamicSettingsPane<Boolean> innerPanel;
|
||||||
|
private int setIndex;
|
||||||
|
|
||||||
|
private PamVBox dsPane;
|
||||||
|
private ToggleGroup buttonGroup;
|
||||||
|
private ToggleButton andButton, orButton, disableButton;
|
||||||
|
private HBox buttonPane;
|
||||||
|
private Node contentPane;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the DataSelectorDialogPaneFX
|
||||||
|
* @param dataSelector
|
||||||
|
* @param innerPanel
|
||||||
|
* @param setIndex
|
||||||
|
*/
|
||||||
|
public DataSelectorDialogPaneFX(DataSelector dataSelector, DynamicSettingsPane<Boolean> innerPanel, int setIndex) {
|
||||||
|
super(null);
|
||||||
|
this.dataSelector = dataSelector;
|
||||||
|
this.innerPanel = innerPanel;
|
||||||
|
this.setIndex = setIndex;
|
||||||
|
|
||||||
|
dsPane = new PamVBox(); // Use VBox for vertical layout
|
||||||
|
dsPane.setSpacing(5);
|
||||||
|
|
||||||
|
contentPane = innerPanel.getContentNode();
|
||||||
|
|
||||||
|
// Border exBorder = innerComponent.getBorder();
|
||||||
|
//
|
||||||
|
// if (exBorder instanceof TitledBorder) {
|
||||||
|
// innerComponent.setBorder(null);
|
||||||
|
// // Set a lower bevel border if desired:
|
||||||
|
// // innerComponent.setBorder(new BevelBorder(BevelBorder.LOWERED));
|
||||||
|
// dsPane.setBorder(exBorder);
|
||||||
|
// } else {
|
||||||
|
// dsPane.setBorder(new TitledBorder(dataSelector.getSelectorTitle()));
|
||||||
|
// }
|
||||||
|
|
||||||
|
Label title = new Label(innerPanel.getName());
|
||||||
|
title.setTooltip(new Tooltip("Data selector: " + dataSelector.getLongSelectorName()));
|
||||||
|
PamGuiManagerFX.titleFont2style(title);
|
||||||
|
|
||||||
|
|
||||||
|
buttonGroup = new ToggleGroup();
|
||||||
|
andButton = new ToggleButton(setIndex == 0 ? "Enable" : "AND");
|
||||||
|
andButton.setPrefWidth(PREF_TOGGLE_WIDTH);
|
||||||
|
|
||||||
|
disableButton = new ToggleButton("Skip");
|
||||||
|
disableButton.setPrefWidth(PREF_TOGGLE_WIDTH);
|
||||||
|
|
||||||
|
orButton = new ToggleButton("OR");
|
||||||
|
orButton.setPrefWidth(PREF_TOGGLE_WIDTH);
|
||||||
|
|
||||||
|
buttonGroup.getToggles().addAll(andButton, orButton, disableButton);
|
||||||
|
|
||||||
|
SegmentedButton segmentedButton ;
|
||||||
|
if (setIndex > 0) {
|
||||||
|
segmentedButton = new SegmentedButton(andButton, orButton, disableButton);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
segmentedButton = new SegmentedButton(andButton, disableButton);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
andButton.setOnAction(event -> {
|
||||||
|
enableComponent();
|
||||||
|
notifySettingsListeners();
|
||||||
|
});
|
||||||
|
orButton.setOnAction(event ->{
|
||||||
|
enableComponent();
|
||||||
|
notifySettingsListeners();
|
||||||
|
});
|
||||||
|
disableButton.setOnAction(event ->{
|
||||||
|
enableComponent();
|
||||||
|
notifySettingsListeners();
|
||||||
|
});
|
||||||
|
|
||||||
|
buttonPane = new HBox(); // Use HBox for horizontal button layout
|
||||||
|
buttonPane.setSpacing(5);
|
||||||
|
buttonPane.setAlignment(Pos.CENTER);
|
||||||
|
buttonPane.getChildren().addAll(segmentedButton);
|
||||||
|
|
||||||
|
//add everything to the main pane
|
||||||
|
if (setIndex > 0) {
|
||||||
|
dsPane.getChildren().add(new Separator());
|
||||||
|
}
|
||||||
|
dsPane.getChildren().add(title);
|
||||||
|
dsPane.getChildren().add(buttonPane); // Add button pane at top
|
||||||
|
dsPane.getChildren().add(contentPane);
|
||||||
|
|
||||||
|
|
||||||
|
//need to add a listener for settings changes to these panes so it can be passed to this pane
|
||||||
|
innerPanel.addSettingsListener(()->{
|
||||||
|
notifySettingsListeners();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
orButton.setVisible(setIndex > 0);
|
||||||
|
if (dataSelector instanceof CompoundDataSelector || setIndex < 0) {
|
||||||
|
buttonPane.setVisible(false);
|
||||||
|
dsPane.setBorder(null);
|
||||||
|
}
|
||||||
|
enableComponent();
|
||||||
|
//buttonPane.setTooltip(new Tooltip("Options for " + dataSelector.getLongSelectorName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void enableComponent() {
|
||||||
|
contentPane.setDisable(disableButton.isSelected());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParams(Boolean input) {
|
||||||
|
DataSelectParams params = dataSelector.getParams();
|
||||||
|
if (params == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (buttonPane.isVisible()) {
|
||||||
|
andButton.setSelected(params.getCombinationFlag() == DataSelectParams.DATA_SELECT_AND);
|
||||||
|
orButton.setSelected(params.getCombinationFlag() == DataSelectParams.DATA_SELECT_OR);
|
||||||
|
disableButton.setSelected(params.getCombinationFlag() == DataSelectParams.DATA_SELECT_DISABLE);
|
||||||
|
} else {
|
||||||
|
andButton.setSelected(true);
|
||||||
|
orButton.setSelected(false);
|
||||||
|
disableButton.setSelected(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
innerPanel.setParams(input);
|
||||||
|
enableComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean getParams(Boolean a) {
|
||||||
|
DataSelectParams params = dataSelector.getParams();
|
||||||
|
|
||||||
|
if (disableButton.isSelected()) {
|
||||||
|
if (params != null) {
|
||||||
|
params.setCombinationFlag(DataSelectParams.DATA_SELECT_DISABLE);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean innerOk = innerPanel.getParams(a);
|
||||||
|
if (!innerOk) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
params = dataSelector.getParams(); // Might have been recreated
|
||||||
|
|
||||||
|
if (params != null) {
|
||||||
|
if (andButton.isSelected()) {
|
||||||
|
params.setCombinationFlag(DataSelectParams.DATA_SELECT_AND);
|
||||||
|
} else if (orButton.isSelected()) {
|
||||||
|
params.setCombinationFlag(DataSelectParams.DATA_SELECT_OR);
|
||||||
|
} else if (disableButton.isSelected()) {
|
||||||
|
params.setCombinationFlag(DataSelectParams.DATA_SELECT_DISABLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return innerOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility method for disabling/enabling a Node (doesn't work recursively)
|
||||||
|
public static void setEnabled(Node node, boolean enabled) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Data selector";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getContentNode() {
|
||||||
|
return dsPane;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paneInitialized() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -987,3 +987,27 @@
|
|||||||
.spinner {
|
.spinner {
|
||||||
-fx-pref-width: 100px;
|
-fx-pref-width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************
|
||||||
|
* *
|
||||||
|
* Segmented button *
|
||||||
|
* *
|
||||||
|
*********************************************/
|
||||||
|
|
||||||
|
.segmented-button .toggle-button.left-pill {
|
||||||
|
-fx-border-radius: 5 0 0 5;
|
||||||
|
-fx-background-radius: 5 0 0 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segmented-button .toggle-button.center-pill {
|
||||||
|
-fx-border-radius: 0 0 0 0;
|
||||||
|
-fx-background-radius: 0 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.segmented-button .toggle-button.right-pill {
|
||||||
|
-fx-border-radius: 0 5 5 0;
|
||||||
|
-fx-background-radius: 0 5 5 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,6 +6,11 @@ import PamView.ColourArray;
|
|||||||
import PamView.ColourArray.ColourArrayType;
|
import PamView.ColourArray.ColourArrayType;
|
||||||
import PamView.sliders.PamRangeSlider;
|
import PamView.sliders.PamRangeSlider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A range slider which shows a colour gradient between two thumbs.
|
||||||
|
*
|
||||||
|
* @author Jamie Macaulay
|
||||||
|
*/
|
||||||
public class ColourRangeSlider extends PamRangeSlider {
|
public class ColourRangeSlider extends PamRangeSlider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,10 +26,26 @@ public class ColourRangeSlider extends PamRangeSlider {
|
|||||||
super(min, max,JSlider.VERTICAL);
|
super(min, max,JSlider.VERTICAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ColourRangeSlider(int min, int max, int orientation){
|
||||||
|
super(min, max,orientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ColourRangeSlider(int orientation){
|
||||||
|
super(orientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the colour map type to show between the two thumbs.
|
||||||
|
* @param colourMap - the colour map to show.
|
||||||
|
*/
|
||||||
public void setColourMap(ColourArrayType colourMap){
|
public void setColourMap(ColourArrayType colourMap){
|
||||||
((ColourRangeSliderUI) getUI()).setColourMap(colourMap);
|
((ColourRangeSliderUI) getUI()).setColourMap(colourMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a custom colour map type to show between the two thumbs.
|
||||||
|
* @param colourMap - the colour map to show.
|
||||||
|
*/
|
||||||
public void setColourMap(ColourArray colourMap){
|
public void setColourMap(ColourArray colourMap){
|
||||||
((ColourRangeSliderUI) getUI()).setColourMap(colourMap);
|
((ColourRangeSliderUI) getUI()).setColourMap(colourMap);
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,7 @@ import java.awt.geom.AffineTransform;
|
|||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.awt.image.WritableRaster;
|
import java.awt.image.WritableRaster;
|
||||||
|
|
||||||
|
import javax.swing.JSlider;
|
||||||
|
|
||||||
|
|
||||||
import PamView.ColourArray;
|
import PamView.ColourArray;
|
||||||
import PamView.ColourArray.ColourArrayType;
|
import PamView.ColourArray.ColourArrayType;
|
||||||
@ -78,6 +77,8 @@ public class ColourRangeSliderUI extends PamRangeSliderUI {
|
|||||||
|
|
||||||
|
|
||||||
private void createColourMapImage(){
|
private void createColourMapImage(){
|
||||||
|
if (b.getOrientation() == JSlider.VERTICAL) {
|
||||||
|
|
||||||
// now make a standard amplitude image
|
// now make a standard amplitude image
|
||||||
if (colourArray != null && colourArray.length > 0) {
|
if (colourArray != null && colourArray.length > 0) {
|
||||||
amplitudeImage = new BufferedImage(1, colourArray.length,
|
amplitudeImage = new BufferedImage(1, colourArray.length,
|
||||||
@ -88,6 +89,15 @@ public class ColourRangeSliderUI extends PamRangeSliderUI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
amplitudeImage = new BufferedImage(colourArray.length, 1,
|
||||||
|
BufferedImage.TYPE_INT_RGB);
|
||||||
|
WritableRaster raster = amplitudeImage.getRaster();
|
||||||
|
for (int i = 0; i < colourArray.length; i++) {
|
||||||
|
raster.setPixel(i, 0,colourArray[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void createColours() {
|
private void createColours() {
|
||||||
@ -119,26 +129,98 @@ public class ColourRangeSliderUI extends PamRangeSliderUI {
|
|||||||
|
|
||||||
Rectangle trackBounds = trackRect;
|
Rectangle trackBounds = trackRect;
|
||||||
|
|
||||||
|
// Save colour and shift position.
|
||||||
|
Color oldColor = g.getColor();
|
||||||
|
|
||||||
|
int cx;
|
||||||
|
|
||||||
|
if (b.getOrientation() == JSlider.VERTICAL) {
|
||||||
|
|
||||||
// Determine position of selected range by moving from the middle
|
// Determine position of selected range by moving from the middle
|
||||||
// of one thumb to the other.
|
// of one thumb to the other.
|
||||||
int lowerY = thumbRect.y + (thumbRect.width / 2);
|
int lowerY = thumbRect.y + (thumbRect.width / 2);
|
||||||
int upperY = getUpperThumbRect().y + (getUpperThumbRect().width / 2);
|
int upperY = getUpperThumbRect().y + (getUpperThumbRect().width / 2);
|
||||||
|
|
||||||
// Determine track position.
|
// Determine track position.
|
||||||
int cx = (trackBounds.width / 2) - 2;
|
cx = (trackBounds.width / 2) - 2;
|
||||||
|
|
||||||
// Save colour and shift position.
|
|
||||||
Color oldColor = g.getColor();
|
|
||||||
g.translate(trackBounds.x + cx, trackBounds.y);
|
g.translate(trackBounds.x + cx, trackBounds.y);
|
||||||
|
|
||||||
drawColourMapVert( g, lowerY - trackBounds.y, upperY - trackBounds.y, -(getUpperThumbRect().width /4)-trackBounds.x,(getUpperThumbRect().width / 2)-trackBounds.x+(trackBounds.width / 4)+2);
|
drawColourMapVert( g, lowerY - trackBounds.y, upperY - trackBounds.y, -(getUpperThumbRect().width /4)-trackBounds.x,(getUpperThumbRect().width / 2)-trackBounds.x+(trackBounds.width / 4)+2);
|
||||||
|
|
||||||
// Restore position and colour.
|
cx = (trackBounds.width / 2) - 2;
|
||||||
g.translate(-(trackBounds.x + cx), -trackBounds.y);
|
g.translate(-(trackBounds.x + cx), -trackBounds.y);
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Determine position of selected range by moving from the middle
|
||||||
|
// of one thumb to the other.
|
||||||
|
int lowerX = thumbRect.x;
|
||||||
|
int upperX = getUpperThumbRect().x;
|
||||||
|
|
||||||
|
// Determine track position.
|
||||||
|
cx = (trackBounds.width / 2) - 2;
|
||||||
|
// -(getUpperThumbRect().height /4)-trackBounds.y, (getUpperThumbRect().height / 2)-trackBounds.y+(trackBounds.height / 4)+2
|
||||||
|
drawColourMapHorz(g, trackBounds.height/2-getUpperThumbRect().height/2, trackBounds.height/2+getUpperThumbRect().height/2, lowerX + getUpperThumbRect().width/2, upperX+ getUpperThumbRect().width/2);
|
||||||
|
|
||||||
|
}
|
||||||
|
// Restore position and colour.
|
||||||
g.setColor(oldColor);
|
g.setColor(oldColor);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw the colour map between the two thumbs in the slider bar. Colour the section above the top most thumb
|
||||||
|
* and the section below the lower most thumb with the color map extremes.
|
||||||
|
* @param g- graphics
|
||||||
|
* @param y1
|
||||||
|
* @param y2
|
||||||
|
* @param x1
|
||||||
|
* @param x2
|
||||||
|
*/
|
||||||
|
private void drawColourMapHorz(Graphics g, int y1, int y2, int x1, int x2){
|
||||||
|
|
||||||
|
if (amplitudeImage == null) return;
|
||||||
|
|
||||||
|
Graphics2D g2d = (Graphics2D) g;
|
||||||
|
|
||||||
|
int width=Math.abs(x2-x1);
|
||||||
|
int height=Math.abs(y2-y1);
|
||||||
|
|
||||||
|
// System.out.println("Width: " + width + " " + height + " x1 " + x1);
|
||||||
|
|
||||||
|
//calculate the distance between thumbs
|
||||||
|
double ascaleX = width
|
||||||
|
/ (double) amplitudeImage.getWidth(null);
|
||||||
|
double ascaleY = height
|
||||||
|
/ (double) amplitudeImage.getHeight(null);
|
||||||
|
|
||||||
|
AffineTransform xform = new AffineTransform();
|
||||||
|
// xform.translate(1, amplitudeImage.getWidth(null));
|
||||||
|
xform.scale(ascaleX, ascaleY);
|
||||||
|
//translate to the correct location;
|
||||||
|
g2d.translate(x1, y1);
|
||||||
|
//now translate back for the rest of the operations;
|
||||||
|
g2d.drawImage(amplitudeImage, xform, b);
|
||||||
|
|
||||||
|
//translate back to our original position.
|
||||||
|
g2d.translate(-x1, -y1);
|
||||||
|
|
||||||
|
//go to the left of the lower thumb;
|
||||||
|
// g2d.translate(0, height);
|
||||||
|
g2d.setColor(new Color((int) colourArray[0][0],(int)colourArray[0][1],(int) colourArray[0][2]));
|
||||||
|
for (int i=y1; i<y2; i++){
|
||||||
|
g2d.drawLine(0,i,x1, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//color left of the thumb
|
||||||
|
g2d.setColor(new Color((int) colourArray[colourArray.length-1][0],(int)colourArray[colourArray.length-1][1],(int) colourArray[colourArray.length-1][2]));
|
||||||
|
for (int i=y1; i<y2; i++){
|
||||||
|
g2d.drawLine(x2,i, trackRect.width + thumbRect.width/2, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw the colour map between the two thumbs in the slider bar. Colour the section above the top most thumb
|
* Draw the colour map between the two thumbs in the slider bar. Colour the section above the top most thumb
|
||||||
* and the section below the lower most thumb with the color map extremes.
|
* and the section below the lower most thumb with the color map extremes.
|
||||||
|
@ -29,6 +29,7 @@ import PamView.PamSymbolType;
|
|||||||
import PamView.dialog.PamDialog;
|
import PamView.dialog.PamDialog;
|
||||||
import PamView.dialog.PamDialogPanel;
|
import PamView.dialog.PamDialogPanel;
|
||||||
import PamView.dialog.PamGridBagContraints;
|
import PamView.dialog.PamGridBagContraints;
|
||||||
|
import clickDetector.dataSelector.ClickDataSelector;
|
||||||
import pamMaths.HistogramDisplay;
|
import pamMaths.HistogramDisplay;
|
||||||
import pamMaths.HistogramGraphicsLayer;
|
import pamMaths.HistogramGraphicsLayer;
|
||||||
import pamMaths.PamHistogram;
|
import pamMaths.PamHistogram;
|
||||||
@ -59,6 +60,7 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
|||||||
private JCheckBox amplitudeSelect;
|
private JCheckBox amplitudeSelect;
|
||||||
private JTextField minAmplitude;
|
private JTextField minAmplitude;
|
||||||
private JFrame ownerFrame;
|
private JFrame ownerFrame;
|
||||||
|
private ClickDataSelector dataSelector;
|
||||||
/**
|
/**
|
||||||
* @param btDisplay
|
* @param btDisplay
|
||||||
*/
|
*/
|
||||||
@ -66,6 +68,7 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
|||||||
super();
|
super();
|
||||||
this.clickControl = clickControl;
|
this.clickControl = clickControl;
|
||||||
this.btDisplay = btDisplay;
|
this.btDisplay = btDisplay;
|
||||||
|
dataSelector = btDisplay.getClickDataSelector();
|
||||||
clickDataBlock = clickControl.getClickDataBlock();
|
clickDataBlock = clickControl.getClickDataBlock();
|
||||||
histoPlot = new HistogramDisplay();
|
histoPlot = new HistogramDisplay();
|
||||||
histoPlot.setGraphicsOverLayer(histoOverLayer = new HistoOverLayer());
|
histoPlot.setGraphicsOverLayer(histoOverLayer = new HistoOverLayer());
|
||||||
@ -125,7 +128,8 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
|||||||
axMin = allHistogram.getScaleMinVal();
|
axMin = allHistogram.getScaleMinVal();
|
||||||
axMax = allHistogram.getScaleMaxVal();
|
axMax = allHistogram.getScaleMaxVal();
|
||||||
plotRectangle = g.getClipBounds();
|
plotRectangle = g.getClipBounds();
|
||||||
double dx = (btDisplayParameters.minAmplitude - axMin) / (axMax-axMin) * plotRectangle.width;
|
// double dx = (btDisplayParameters.minAmplitude - axMin) / (axMax-axMin) * plotRectangle.width;
|
||||||
|
double dx = (dataSelector.getParams().minimumAmplitude - axMin) / (axMax-axMin) * plotRectangle.width;
|
||||||
int x = (int) Math.round(dx);
|
int x = (int) Math.round(dx);
|
||||||
g.setColor(Color.RED);
|
g.setColor(Color.RED);
|
||||||
g.drawLine(x, 0, x, plotRectangle.height);
|
g.drawLine(x, 0, x, plotRectangle.height);
|
||||||
@ -151,7 +155,7 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
|||||||
double newAmp = (double) mouseEvent.getX() / histoOverLayer.plotRectangle.width *
|
double newAmp = (double) mouseEvent.getX() / histoOverLayer.plotRectangle.width *
|
||||||
(histoOverLayer.axMax-histoOverLayer.axMin) + histoOverLayer.axMin;
|
(histoOverLayer.axMax-histoOverLayer.axMin) + histoOverLayer.axMin;
|
||||||
BTDisplayParameters btDisplayParameters = btDisplay.getBtDisplayParameters();
|
BTDisplayParameters btDisplayParameters = btDisplay.getBtDisplayParameters();
|
||||||
btDisplayParameters.minAmplitude = newAmp;
|
dataSelector.getParams().minimumAmplitude = newAmp;
|
||||||
ampCtrlPanel.setParams(btDisplayParameters);
|
ampCtrlPanel.setParams(btDisplayParameters);
|
||||||
redrawHisto();
|
redrawHisto();
|
||||||
//
|
//
|
||||||
@ -173,7 +177,7 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
|||||||
if (btDisplayParameters.amplitudeSelect == false) {
|
if (btDisplayParameters.amplitudeSelect == false) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
double dx = (btDisplayParameters.minAmplitude - histoOverLayer.axMin) /
|
double dx = (dataSelector.getParams().minimumAmplitude - histoOverLayer.axMin) /
|
||||||
(histoOverLayer.axMax-histoOverLayer.axMin) * histoOverLayer.plotRectangle.width;
|
(histoOverLayer.axMax-histoOverLayer.axMin) * histoOverLayer.plotRectangle.width;
|
||||||
int x = (int) Math.round(dx);
|
int x = (int) Math.round(dx);
|
||||||
if (Math.abs(e.getX()-x) > 10) {
|
if (Math.abs(e.getX()-x) > 10) {
|
||||||
@ -213,14 +217,14 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
|||||||
}
|
}
|
||||||
private void setParams(BTDisplayParameters btParams) {
|
private void setParams(BTDisplayParameters btParams) {
|
||||||
amplitudeSelect.setSelected(btParams.amplitudeSelect);
|
amplitudeSelect.setSelected(btParams.amplitudeSelect);
|
||||||
minAmplitude.setText(String.format("%3.1f", btParams.minAmplitude));
|
minAmplitude.setText(String.format("%3.1f", dataSelector.getParams().minimumAmplitude));
|
||||||
|
|
||||||
enableControls();
|
enableControls();
|
||||||
}
|
}
|
||||||
private boolean getParams(BTDisplayParameters btParams) {
|
private boolean getParams(BTDisplayParameters btParams) {
|
||||||
btParams.amplitudeSelect = amplitudeSelect.isSelected();
|
btParams.amplitudeSelect = amplitudeSelect.isSelected();
|
||||||
try {
|
try {
|
||||||
btParams.minAmplitude = Double.valueOf(minAmplitude.getText());
|
dataSelector.getParams().minimumAmplitude = Double.valueOf(minAmplitude.getText());
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e) {
|
catch (NumberFormatException e) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -44,17 +44,17 @@ public class BTDisplayParameters implements Serializable, Cloneable, ManagedPara
|
|||||||
public int nBearingGridLines = 1;
|
public int nBearingGridLines = 1;
|
||||||
public int nAmplitudeGridLines = 0;
|
public int nAmplitudeGridLines = 0;
|
||||||
public int nICIGridLines = 0;
|
public int nICIGridLines = 0;
|
||||||
public boolean showEchoes = true;
|
// public boolean showEchoes = true;
|
||||||
public int minClickLength = 2, maxClickLength = 12;
|
public int minClickLength = 2, maxClickLength = 12;
|
||||||
public int minClickHeight = 2, maxClickHeight = 12;
|
public int minClickHeight = 2, maxClickHeight = 12;
|
||||||
private double timeRange = 10;
|
private double timeRange = 10;
|
||||||
public int displayChannels = 0;
|
public int displayChannels = 0;
|
||||||
public boolean view360;
|
public boolean view360;
|
||||||
public boolean amplitudeSelect = false;
|
public boolean amplitudeSelect = false;
|
||||||
public double minAmplitude = 0;
|
// public double minAmplitude = 0;
|
||||||
public boolean showUnassignedICI = false;
|
public boolean showUnassignedICI = false;
|
||||||
public boolean showEventsOnly = false;
|
// public boolean showEventsOnly = false;
|
||||||
public boolean showANDEvents = true;
|
// public boolean showANDEvents = true;
|
||||||
public boolean logICIScale;
|
public boolean logICIScale;
|
||||||
public int angleRotation = ROTATE_TOARRAY;
|
public int angleRotation = ROTATE_TOARRAY;
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ public class BTDisplayParameters implements Serializable, Cloneable, ManagedPara
|
|||||||
/*
|
/*
|
||||||
* Show identified species
|
* Show identified species
|
||||||
*/
|
*/
|
||||||
private boolean[] showSpeciesList;
|
// private boolean[] showSpeciesList;
|
||||||
|
|
||||||
public int colourScheme = COLOUR_BY_TRAIN;
|
public int colourScheme = COLOUR_BY_TRAIN;
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ public class BTDisplayParameters implements Serializable, Cloneable, ManagedPara
|
|||||||
} catch (CloneNotSupportedException Ex) {
|
} catch (CloneNotSupportedException Ex) {
|
||||||
Ex.printStackTrace();
|
Ex.printStackTrace();
|
||||||
}
|
}
|
||||||
showSpeciesList = null;
|
// showSpeciesList = null;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,49 +107,49 @@ public class BTDisplayParameters implements Serializable, Cloneable, ManagedPara
|
|||||||
/**
|
/**
|
||||||
* @return the showSpeciesList
|
* @return the showSpeciesList
|
||||||
*/
|
*/
|
||||||
public boolean getShowSpecies(int speciesIndex) {
|
// public boolean getShowSpecies(int speciesIndex) {
|
||||||
if (showSpeciesList != null && showSpeciesList.length > speciesIndex) {
|
// if (showSpeciesList != null && showSpeciesList.length > speciesIndex) {
|
||||||
return showSpeciesList[speciesIndex];
|
// return showSpeciesList[speciesIndex];
|
||||||
}
|
// }
|
||||||
makeShowSpeciesList(speciesIndex);
|
// makeShowSpeciesList(speciesIndex);
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
private void makeShowSpeciesList(int maxIndex) {
|
// private void makeShowSpeciesList(int maxIndex) {
|
||||||
if (showSpeciesList == null) {
|
// if (showSpeciesList == null) {
|
||||||
showSpeciesList = new boolean[0];
|
// showSpeciesList = new boolean[0];
|
||||||
}
|
// }
|
||||||
else if (showSpeciesList.length > maxIndex) {
|
// else if (showSpeciesList.length > maxIndex) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
int oldLength = showSpeciesList.length;
|
// int oldLength = showSpeciesList.length;
|
||||||
showSpeciesList = Arrays.copyOf(showSpeciesList, maxIndex + 1);
|
// showSpeciesList = Arrays.copyOf(showSpeciesList, maxIndex + 1);
|
||||||
for (int i = oldLength; i <= maxIndex; i++) {
|
// for (int i = oldLength; i <= maxIndex; i++) {
|
||||||
showSpeciesList[i] = true;
|
// showSpeciesList[i] = true;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param showSpeciesList the showSpeciesList to set
|
* @param showSpeciesList the showSpeciesList to set
|
||||||
*/
|
*/
|
||||||
public void setShowSpecies(int speciesIndex, boolean showSpecies) {
|
// public void setShowSpecies(int speciesIndex, boolean showSpecies) {
|
||||||
makeShowSpeciesList(speciesIndex);
|
// makeShowSpeciesList(speciesIndex);
|
||||||
showSpeciesList[speciesIndex] = showSpecies;
|
// showSpeciesList[speciesIndex] = showSpecies;
|
||||||
}
|
// }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PamParameterSet getParameterSet() {
|
public PamParameterSet getParameterSet() {
|
||||||
PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
|
PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
|
||||||
try {
|
// try {
|
||||||
Field field = this.getClass().getDeclaredField("showSpeciesList");
|
// Field field = this.getClass().getDeclaredField("showSpeciesList");
|
||||||
ps.put(new PrivatePamParameterData(this, field) {
|
// ps.put(new PrivatePamParameterData(this, field) {
|
||||||
@Override
|
// @Override
|
||||||
public Object getData() throws IllegalArgumentException, IllegalAccessException {
|
// public Object getData() throws IllegalArgumentException, IllegalAccessException {
|
||||||
return showSpeciesList;
|
// return showSpeciesList;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
} catch (NoSuchFieldException | SecurityException e) {
|
// } catch (NoSuchFieldException | SecurityException e) {
|
||||||
e.printStackTrace();
|
// e.printStackTrace();
|
||||||
}
|
// }
|
||||||
return ps;
|
return ps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@ import java.awt.Insets;
|
|||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.RenderingHints;
|
import java.awt.RenderingHints;
|
||||||
|
import java.awt.Window;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.AdjustmentEvent;
|
import java.awt.event.AdjustmentEvent;
|
||||||
@ -115,9 +116,13 @@ import PamguardMVC.PamDataBlock;
|
|||||||
import PamguardMVC.PamDataUnit;
|
import PamguardMVC.PamDataUnit;
|
||||||
import PamguardMVC.PamObservable;
|
import PamguardMVC.PamObservable;
|
||||||
import PamguardMVC.PamObserver;
|
import PamguardMVC.PamObserver;
|
||||||
|
import PamguardMVC.dataSelector.DataSelectDialog;
|
||||||
|
import PamguardMVC.dataSelector.DataSelector;
|
||||||
import PamguardMVC.superdet.SuperDetection;
|
import PamguardMVC.superdet.SuperDetection;
|
||||||
import clickDetector.ClickClassifiers.ClickIdInformation;
|
import clickDetector.ClickClassifiers.ClickIdInformation;
|
||||||
import clickDetector.ClickClassifiers.ClickIdentifier;
|
import clickDetector.ClickClassifiers.ClickIdentifier;
|
||||||
|
import clickDetector.alarm.ClickAlarmParameters;
|
||||||
|
import clickDetector.dataSelector.ClickDataSelector;
|
||||||
import clickDetector.dialogs.ClickDisplayDialog;
|
import clickDetector.dialogs.ClickDisplayDialog;
|
||||||
import clickDetector.offlineFuncs.OfflineEventDataBlock;
|
import clickDetector.offlineFuncs.OfflineEventDataBlock;
|
||||||
import clickDetector.offlineFuncs.OfflineEventDataUnit;
|
import clickDetector.offlineFuncs.OfflineEventDataUnit;
|
||||||
@ -2240,11 +2245,15 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
|||||||
if (btDisplayParameters.amplitudeSelect == false) {
|
if (btDisplayParameters.amplitudeSelect == false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ClickDataSelector clickDataSelector = getClickDataSelector();
|
||||||
|
if (clickDataSelector == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
int n = countAmplitudeDeselected();
|
int n = countAmplitudeDeselected();
|
||||||
PamDataBlock<ClickDetection> clickData = clickControl.getClickDataBlock();
|
PamDataBlock<ClickDetection> clickData = clickControl.getClickDataBlock();
|
||||||
int nAll = clickData.getUnitsCount();
|
int nAll = clickData.getUnitsCount();
|
||||||
String txt = String.format("%d of %d loaded clicks will not be displayed because their amplitude is < %3.1fdB",
|
String txt = String.format("%d of %d loaded clicks will not be displayed because their amplitude is < %3.1fdB",
|
||||||
n, nAll, btDisplayParameters.minAmplitude);
|
n, nAll, clickDataSelector.getParams().minimumAmplitude);
|
||||||
Insets insets = getInsets();
|
Insets insets = getInsets();
|
||||||
int x = insets.left;
|
int x = insets.left;
|
||||||
int y = getHeight()-5;
|
int y = getHeight()-5;
|
||||||
@ -2383,19 +2392,33 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
|||||||
}
|
}
|
||||||
|
|
||||||
menuItem = new JMenuItem("Settings ...");
|
menuItem = new JMenuItem("Settings ...");
|
||||||
|
menuItem.setToolTipText("Display options");
|
||||||
menuItem.addActionListener(new SettingsMenuAction());
|
menuItem.addActionListener(new SettingsMenuAction());
|
||||||
menu.add(menuItem);
|
menu.add(menuItem);
|
||||||
|
menuItem = new JMenuItem("Click data selector ...");
|
||||||
|
menuItem.setToolTipText("Detailed data selection options");
|
||||||
|
menuItem.addActionListener(new DataSelectorAction());
|
||||||
|
menu.add(menuItem);
|
||||||
menuItem = new JMenuItem("Show amplitude selector ...");
|
menuItem = new JMenuItem("Show amplitude selector ...");
|
||||||
|
menuItem.setToolTipText("Graphical amplitude selector display");
|
||||||
menuItem.addActionListener(new AmplitudeSelector());
|
menuItem.addActionListener(new AmplitudeSelector());
|
||||||
menu.add(menuItem);
|
menu.add(menuItem);
|
||||||
menu.addSeparator();
|
menu.addSeparator();
|
||||||
ArrayList<JMenuItem> colOptList = getSymbolChooser().getQuickMenuItems(clickControl.getGuiFrame(), this, "Colour by ", SymbolModType.EVERYTHING, true);
|
ArrayList<JMenuItem> colOptList = getSymbolChooser().getQuickMenuItems(clickControl.getGuiFrame(), this, "Colour by ", SymbolModType.EVERYTHING, false);
|
||||||
if (colOptList != null) {
|
if (colOptList != null) {
|
||||||
for (JMenuItem menuIt : colOptList) {
|
for (JMenuItem menuIt : colOptList) {
|
||||||
menu.add(menuIt);
|
menu.add(menuIt);
|
||||||
}
|
}
|
||||||
menu.addSeparator();
|
|
||||||
}
|
}
|
||||||
|
menuItem = new JMenuItem("More symbol options ...");
|
||||||
|
menuItem.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
showDataSymbolOptions(1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
menu.add(menuItem);
|
||||||
|
menu.addSeparator();
|
||||||
|
|
||||||
// menuItem = new JCheckBoxMenuItem("Colour by species id",
|
// menuItem = new JCheckBoxMenuItem("Colour by species id",
|
||||||
// btDisplayParameters.colourScheme == BTDisplayParameters.COLOUR_BY_SPECIES);
|
// btDisplayParameters.colourScheme == BTDisplayParameters.COLOUR_BY_SPECIES);
|
||||||
@ -2771,7 +2794,7 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
|||||||
|
|
||||||
BTDisplayParameters newParameters =
|
BTDisplayParameters newParameters =
|
||||||
ClickDisplayDialog.showDialog(clickControl,
|
ClickDisplayDialog.showDialog(clickControl,
|
||||||
clickControl.getGuiFrame(), btDisplayParameters);
|
clickControl.getGuiFrame(), btDisplayParameters, getClickDataSelector().getClickAlarmParameters());
|
||||||
if (newParameters != null){
|
if (newParameters != null){
|
||||||
btDisplayParameters = newParameters.clone();
|
btDisplayParameters = newParameters.clone();
|
||||||
if (getVScaleManager() != null) {
|
if (getVScaleManager() != null) {
|
||||||
@ -2789,6 +2812,30 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a data selector specific to this display.
|
||||||
|
* @return click data selector specific to this display.
|
||||||
|
*/
|
||||||
|
public DataSelector getDataSelector() {
|
||||||
|
return clickControl.getClickDataBlock().getDataSelector(getUnitName(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get the click specific data selector which may now be burried in a
|
||||||
|
* CompoundDataSelector if annotations have been used.
|
||||||
|
* @return ClickDataSelector.
|
||||||
|
*/
|
||||||
|
public ClickDataSelector getClickDataSelector() {
|
||||||
|
DataSelector baseSel = getDataSelector();
|
||||||
|
if (baseSel == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (ClickDataSelector) baseSel.findDataSelector(ClickDataSelector.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class AmplitudeSelector implements ActionListener {
|
class AmplitudeSelector implements ActionListener {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
@ -2796,6 +2843,13 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DataSelectorAction implements ActionListener {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
showDataSelector();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void showAmplitudeSelector() {
|
private void showAmplitudeSelector() {
|
||||||
|
|
||||||
//TODO FIXME! quick fix so scales reset without scrolling/restarting
|
//TODO FIXME! quick fix so scales reset without scrolling/restarting
|
||||||
@ -2814,6 +2868,38 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a dialog with both data and symbol options, but go to the correct tab.
|
||||||
|
* @param selectedTab
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean showDataSymbolOptions(int selectedTab) {
|
||||||
|
Window javaFrame = clickControl.getGuiFrame();
|
||||||
|
DataSelectDialog dataSelectDialog = new DataSelectDialog(javaFrame, clickControl.getClickDataBlock(), getDataSelector(), symbolChooser);
|
||||||
|
if (javaFrame == null) {
|
||||||
|
dataSelectDialog.moveToMouseLocation();
|
||||||
|
}
|
||||||
|
dataSelectDialog.setTab(selectedTab);
|
||||||
|
boolean ok = dataSelectDialog.showDialog();
|
||||||
|
if (ok) {
|
||||||
|
repaintBoth();
|
||||||
|
if (clickControl.getOfflineToolbar() != null) {
|
||||||
|
clickControl.getOfflineToolbar().displayActivated(clickBTDisplay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showDataSelector() {
|
||||||
|
// if (getDataSelector().showSelectDialog(clickControl.getGuiFrame())) {
|
||||||
|
// repaintBoth();
|
||||||
|
// if (clickControl.getOfflineToolbar() != null) {
|
||||||
|
// clickControl.getOfflineToolbar().displayActivated(clickBTDisplay);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
showDataSymbolOptions(0);
|
||||||
|
}
|
||||||
|
|
||||||
private void checkBTAmplitudeSelectHisto() {
|
private void checkBTAmplitudeSelectHisto() {
|
||||||
if (btAmplitudeSelector == null) {
|
if (btAmplitudeSelector == null) {
|
||||||
return;
|
return;
|
||||||
@ -3036,15 +3122,15 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
|||||||
zoomer.paintShape(g, this, true);
|
zoomer.paintShape(g, this, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// long t1 = System.nanoTime();
|
ArrayList<ClickDetection> clickCopy = clickData.getDataCopy(displayStartMillis, displayStartMillis+displayLengthMillis, true, getDataSelector());
|
||||||
synchronized (clickData.getSynchLock()) {
|
if (clickCopy.size() == 0) {
|
||||||
// long t2 = System.nanoTime();
|
return;
|
||||||
// double ms = ((double) (t2-t1)) / 1000000.;
|
}
|
||||||
// if (btDisplayParameters.VScale == BTDisplayParameters.DISPLAY_ICI) {
|
ListIterator<ClickDetection> clickIterator = clickCopy.listIterator(clickCopy.size()-1);
|
||||||
// sortTempICIs();
|
|
||||||
// }
|
|
||||||
|
|
||||||
ListIterator<ClickDetection> clickIterator = clickData.getListIterator(PamDataBlock.ITERATOR_END);
|
// synchronized (clickData.getSynchLock()) {
|
||||||
|
//
|
||||||
|
// ListIterator<ClickDetection> clickIterator = clickData.getListIterator(PamDataBlock.ITERATOR_END);
|
||||||
while (clickIterator.hasPrevious()) {
|
while (clickIterator.hasPrevious()) {
|
||||||
click = clickIterator.previous();
|
click = clickIterator.previous();
|
||||||
if (shouldPlot(prevPlottedClick)){
|
if (shouldPlot(prevPlottedClick)){
|
||||||
@ -3060,11 +3146,6 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
|||||||
if (shouldPlot(prevPlottedClick)){ // and draw the last one !
|
if (shouldPlot(prevPlottedClick)){ // and draw the last one !
|
||||||
drawClick(g, prevPlottedClick, clipRectangle);
|
drawClick(g, prevPlottedClick, clipRectangle);
|
||||||
}
|
}
|
||||||
// g.drawString(String.format("Wait synch %3.3fms", ms), 0, 20);
|
|
||||||
}
|
|
||||||
// long t3 = System.nanoTime();
|
|
||||||
// g.drawString(String.format("Last draw %3.3fms", lastPaintTime), 0, 20);
|
|
||||||
// lastPaintTime = ((double) (t3-t0)) / 1000000.;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -3342,7 +3423,9 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
|||||||
else if (btDisplayParameters.colourScheme == BTDisplayParameters.COLOUR_BY_HYDROPHONE) {
|
else if (btDisplayParameters.colourScheme == BTDisplayParameters.COLOUR_BY_HYDROPHONE) {
|
||||||
keyPanel.add(new TextKeyItem("Colour by hydrophone"));
|
keyPanel.add(new TextKeyItem("Colour by hydrophone"));
|
||||||
}
|
}
|
||||||
if (btDisplayParameters.getShowSpecies(0)) {
|
ClickAlarmParameters selectParams = getClickDataSelector().getParams();
|
||||||
|
// if (btDisplayParameters.getShowSpecies(0)) {
|
||||||
|
if (selectParams.onlineAutoEvents | selectParams.onlineManualEvents) {
|
||||||
keyPanel.add(symbolChooser.getDefaultSymbol(true).makeKeyItem("Unidentified species"));
|
keyPanel.add(symbolChooser.getDefaultSymbol(true).makeKeyItem("Unidentified species"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3354,7 +3437,8 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
|||||||
PamSymbol[] symbols = clickControl.getClickIdentifier().getSymbols();
|
PamSymbol[] symbols = clickControl.getClickIdentifier().getSymbols();
|
||||||
if (speciesList != null) {
|
if (speciesList != null) {
|
||||||
for (int i = 0; i < speciesList.length; i++) {
|
for (int i = 0; i < speciesList.length; i++) {
|
||||||
if (btDisplayParameters.getShowSpecies(i+1)) {
|
if (selectParams.getUseSpecies(i+1)) {
|
||||||
|
// if (btDisplayParameters.getShowSpecies(i+1)) {
|
||||||
if (btDisplayParameters.colourScheme != BTDisplayParameters.COLOUR_BY_TRAIN) {
|
if (btDisplayParameters.colourScheme != BTDisplayParameters.COLOUR_BY_TRAIN) {
|
||||||
keyPanel.add(symbols[i].makeKeyItem(speciesList[i]));
|
keyPanel.add(symbols[i].makeKeyItem(speciesList[i]));
|
||||||
}
|
}
|
||||||
@ -3423,11 +3507,12 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
|||||||
PamDataBlock<ClickDetection> clickData = clickControl.getClickDataBlock();
|
PamDataBlock<ClickDetection> clickData = clickControl.getClickDataBlock();
|
||||||
ClickDetection click;
|
ClickDetection click;
|
||||||
int n = 0;
|
int n = 0;
|
||||||
|
double minAmpli = getClickDataSelector().getParams().minimumAmplitude;
|
||||||
synchronized (clickData.getSynchLock()) {
|
synchronized (clickData.getSynchLock()) {
|
||||||
ListIterator<ClickDetection> clickIterator = clickData.getListIterator(0);
|
ListIterator<ClickDetection> clickIterator = clickData.getListIterator(0);
|
||||||
while (clickIterator.hasNext()) {
|
while (clickIterator.hasNext()) {
|
||||||
click = clickIterator.next();
|
click = clickIterator.next();
|
||||||
if (click.getAmplitudeDB() < btDisplayParameters.minAmplitude) {
|
if (click.getAmplitudeDB() < minAmpli) {
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3448,29 +3533,30 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
|||||||
*/
|
*/
|
||||||
synchronized boolean shouldPlot(ClickDetection click) {
|
synchronized boolean shouldPlot(ClickDetection click) {
|
||||||
if (click == null) return false;
|
if (click == null) return false;
|
||||||
if (!clickInTimeWindow(click)) return false;
|
// if (!clickInTimeWindow(click)) return false;
|
||||||
if (btDisplayParameters.showEchoes == false && click.isEcho()) {
|
// if (btDisplayParameters.showEchoes == false && click.isEcho()) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
if (btDisplayParameters.VScale == BTDisplayParameters.DISPLAY_ICI) {
|
if (btDisplayParameters.VScale == BTDisplayParameters.DISPLAY_ICI) {
|
||||||
// if (btDisplayParameters.showUnassignedICI == false && click.getICI() < 0) return false;
|
// if (btDisplayParameters.showUnassignedICI == false && click.getICI() < 0) return false;
|
||||||
if (btDisplayParameters.showUnassignedICI == false && click.getSuperDetectionsCount() <= 0) return false;
|
if (btDisplayParameters.showUnassignedICI == false && click.getSuperDetectionsCount() <= 0) return false;
|
||||||
// otherwise may be ok, since will estimate all ici's on teh fly.
|
// otherwise may be ok, since will estimate all ici's on teh fly.
|
||||||
}
|
}
|
||||||
if (btDisplayParameters.amplitudeSelect && click.getAmplitudeDB() < btDisplayParameters.minAmplitude) {
|
// if (btDisplayParameters.amplitudeSelect && click.getAmplitudeDB() < btDisplayParameters.minAmplitude) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
if (btDisplayParameters.displayChannels > 0 && (btDisplayParameters.displayChannels & click.getChannelBitmap()) == 0) return false;
|
if (btDisplayParameters.displayChannels > 0 && (btDisplayParameters.displayChannels & click.getChannelBitmap()) == 0) return false;
|
||||||
|
|
||||||
int speciesIndex = clickControl.getClickIdentifier().codeToListIndex(click.getClickType());
|
// int speciesIndex = clickControl.getClickIdentifier().codeToListIndex(click.getClickType());
|
||||||
boolean showSpecies = btDisplayParameters.getShowSpecies(speciesIndex+1);
|
// boolean showSpecies = btDisplayParameters.getShowSpecies(speciesIndex+1);
|
||||||
boolean showEvents = (btDisplayParameters.showEventsOnly == false || click.getSuperDetectionsCount() > 0);
|
// boolean showEvents = (btDisplayParameters.showEventsOnly == false || click.getSuperDetectionsCount() > 0);
|
||||||
if (btDisplayParameters.showANDEvents) {
|
// if (btDisplayParameters.showANDEvents) {
|
||||||
return showSpecies & showEvents;
|
// return showSpecies & showEvents;
|
||||||
}
|
// }
|
||||||
else {
|
// else {
|
||||||
return showSpecies | showEvents;
|
// return showSpecies | showEvents;
|
||||||
}
|
// }
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -4085,7 +4171,7 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
|||||||
amplitudeSelectorLabel.setText("");
|
amplitudeSelectorLabel.setText("");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
String txt = String.format(" Amplitude Selector showing clicks > %3.1fdB", btDisplayParameters.minAmplitude);
|
String txt = String.format(" Amplitude Selector showing clicks > %3.1fdB", getClickDataSelector().getParams().minimumAmplitude);
|
||||||
amplitudeSelectorLabel.setText(txt);
|
amplitudeSelectorLabel.setText(txt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,12 @@ public class ClickAlarmParameters extends DataSelectParams implements Cloneable,
|
|||||||
public static final long serialVersionUID = 1L;
|
public static final long serialVersionUID = 1L;
|
||||||
private boolean[] useSpeciesList;
|
private boolean[] useSpeciesList;
|
||||||
private double[] speciesWeightings;
|
private double[] speciesWeightings;
|
||||||
public boolean useEchoes;
|
public boolean useEchoes = true;
|
||||||
public boolean scoreByAmplitude;
|
public boolean scoreByAmplitude; // alarm options, probably not used any more.
|
||||||
public boolean onlineAutoEvents, onlineManualEvents;
|
public double minimumAmplitude;
|
||||||
|
public boolean onlineAutoEvents = true, onlineManualEvents = true;
|
||||||
public int minICIMillis;
|
public int minICIMillis;
|
||||||
|
private boolean clicksOREvents = false;
|
||||||
/*
|
/*
|
||||||
* Which events to use ...
|
* Which events to use ...
|
||||||
*/
|
*/
|
||||||
@ -165,5 +167,30 @@ public class ClickAlarmParameters extends DataSelectParams implements Cloneable,
|
|||||||
return ps;
|
return ps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the clicksOREvents
|
||||||
|
*/
|
||||||
|
public boolean isClicksOREvents() {
|
||||||
|
return clicksOREvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param clicksOREvents the clicksOREvents to set
|
||||||
|
*/
|
||||||
|
public void setClicksOREvents(boolean clicksOREvents) {
|
||||||
|
this.clicksOREvents = clicksOREvents;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @return the clicksANDEvents
|
||||||
|
*/
|
||||||
|
public boolean isClicksANDEvents() {
|
||||||
|
return !clicksOREvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setClicksANDEvents(boolean clicksANDEvents) {
|
||||||
|
this.clicksOREvents = !clicksANDEvents;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -38,9 +38,9 @@ public class ClickDataSelector extends DataSelector {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PamDialogPanel getDialogPanel() {
|
public PamDialogPanel getDialogPanel() {
|
||||||
if (clickSelectPanel == null) {
|
// if (clickSelectPanel == null) {
|
||||||
clickSelectPanel = new ClickSelectPanel(this, allowScores, useEventTypes);
|
clickSelectPanel = new ClickSelectPanel(this, allowScores, useEventTypes);
|
||||||
}
|
// }
|
||||||
return clickSelectPanel;
|
return clickSelectPanel;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
@ -60,19 +60,25 @@ public class ClickDataSelector extends DataSelector {
|
|||||||
if (clickAlarmParameters.useEchoes == false && click.isEcho()) {
|
if (clickAlarmParameters.useEchoes == false && click.isEcho()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* First score based on whether the event panel is in use and
|
double score = scoreClick(click);
|
||||||
* criteria satisfied.
|
|
||||||
*/
|
|
||||||
if (useEventTypes) {
|
if (useEventTypes) {
|
||||||
if (wantEventType(click) == false) {
|
double eventScore = scoreEventType(click);
|
||||||
return 0;
|
if (clickAlarmParameters.isClicksANDEvents()) {
|
||||||
|
score = Math.min(score, eventScore);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
score = Math.max(score, eventScore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return score;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
private double scoreClick(ClickDetection click) {
|
||||||
* Now score based on whether or not it's individual click type is wanted.
|
if (click.getAmplitudeDB() < clickAlarmParameters.minimumAmplitude) {
|
||||||
*/
|
return 0;
|
||||||
|
}
|
||||||
ClickIdentifier clickIdentifier = clickControl.getClickIdentifier();
|
ClickIdentifier clickIdentifier = clickControl.getClickIdentifier();
|
||||||
int code = click.getClickType();
|
int code = click.getClickType();
|
||||||
if (code > 0 && clickIdentifier != null) {
|
if (code > 0 && clickIdentifier != null) {
|
||||||
@ -81,13 +87,13 @@ public class ClickDataSelector extends DataSelector {
|
|||||||
boolean enabled = clickAlarmParameters.getUseSpecies(code);
|
boolean enabled = clickAlarmParameters.getUseSpecies(code);
|
||||||
if (enabled == false) {
|
if (enabled == false) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}if (isAllowScores()) {
|
||||||
if (isAllowScores()) {
|
|
||||||
return clickAlarmParameters.getSpeciesWeight(code);
|
return clickAlarmParameters.getSpeciesWeight(code);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,7 +101,7 @@ public class ClickDataSelector extends DataSelector {
|
|||||||
* @param click
|
* @param click
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private boolean wantEventType(ClickDetection click) {
|
private double scoreEventType(ClickDetection click) {
|
||||||
OfflineEventDataUnit oev = null;
|
OfflineEventDataUnit oev = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -107,7 +113,7 @@ public class ClickDataSelector extends DataSelector {
|
|||||||
|
|
||||||
int eventId = click.getOfflineEventID();
|
int eventId = click.getOfflineEventID();
|
||||||
if (oev == null) {
|
if (oev == null) {
|
||||||
return clickAlarmParameters.unassignedEvents;
|
return clickAlarmParameters.unassignedEvents ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// see if there is a super detection and see if it's got a comment.
|
// see if there is a super detection and see if it's got a comment.
|
||||||
@ -118,10 +124,10 @@ public class ClickDataSelector extends DataSelector {
|
|||||||
isAutomatic = comment.startsWith("Automatic");
|
isAutomatic = comment.startsWith("Automatic");
|
||||||
}
|
}
|
||||||
if (isAutomatic && clickAlarmParameters.onlineAutoEvents) {
|
if (isAutomatic && clickAlarmParameters.onlineAutoEvents) {
|
||||||
return true;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (clickAlarmParameters.onlineManualEvents) {
|
else if (clickAlarmParameters.onlineManualEvents) {
|
||||||
return true;
|
return 1;
|
||||||
}
|
}
|
||||||
// if (clickAlarmParameters.onlineAutoEvents && comment.startsWith("Automatic")) {
|
// if (clickAlarmParameters.onlineAutoEvents && comment.startsWith("Automatic")) {
|
||||||
// return true;
|
// return true;
|
||||||
@ -134,7 +140,7 @@ public class ClickDataSelector extends DataSelector {
|
|||||||
* list of event types and see if it's wanted.
|
* list of event types and see if it's wanted.
|
||||||
*/
|
*/
|
||||||
String evType = oev.getEventType();
|
String evType = oev.getEventType();
|
||||||
return clickAlarmParameters.isUseEventType(evType);
|
return clickAlarmParameters.isUseEventType(evType) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -188,7 +194,7 @@ public class ClickDataSelector extends DataSelector {
|
|||||||
* @see PamguardMVC.dataSelector.DataSelector#getParams()
|
* @see PamguardMVC.dataSelector.DataSelector#getParams()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public DataSelectParams getParams() {
|
public ClickAlarmParameters getParams() {
|
||||||
return clickAlarmParameters;
|
return clickAlarmParameters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ public class ClickSelectPaneFX extends DynamicSettingsPane<Boolean> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Click Type Selection";
|
return "Filter by click type";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -4,6 +4,7 @@ import generalDatabase.lookupTables.LookUpTables;
|
|||||||
import generalDatabase.lookupTables.LookupList;
|
import generalDatabase.lookupTables.LookupList;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Dimension;
|
||||||
import java.awt.GridBagConstraints;
|
import java.awt.GridBagConstraints;
|
||||||
import java.awt.GridBagLayout;
|
import java.awt.GridBagLayout;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
@ -13,11 +14,13 @@ import java.awt.event.ActionListener;
|
|||||||
import javax.swing.BoxLayout;
|
import javax.swing.BoxLayout;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JCheckBox;
|
import javax.swing.JCheckBox;
|
||||||
|
import javax.swing.JComboBox;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JLabel;
|
import javax.swing.JLabel;
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
import javax.swing.JScrollPane;
|
import javax.swing.JScrollPane;
|
||||||
import javax.swing.JTextField;
|
import javax.swing.JTextField;
|
||||||
|
import javax.swing.border.EmptyBorder;
|
||||||
import javax.swing.border.TitledBorder;
|
import javax.swing.border.TitledBorder;
|
||||||
|
|
||||||
import PamController.PamController;
|
import PamController.PamController;
|
||||||
@ -42,6 +45,7 @@ public class ClickSelectPanel implements PamDialogPanel {
|
|||||||
private ClickDataSelector clickDataSelector;
|
private ClickDataSelector clickDataSelector;
|
||||||
private JPanel mainPanel;
|
private JPanel mainPanel;
|
||||||
private boolean isViewer;
|
private boolean isViewer;
|
||||||
|
private JComboBox<String> andOrBox;
|
||||||
|
|
||||||
public static final String mainTip = "You should select options in both the Click Type and the Event Type panels";
|
public static final String mainTip = "You should select options in both the Click Type and the Event Type panels";
|
||||||
|
|
||||||
@ -70,10 +74,12 @@ public class ClickSelectPanel implements PamDialogPanel {
|
|||||||
public void setParams() {
|
public void setParams() {
|
||||||
eventTypePanel.setParams();
|
eventTypePanel.setParams();
|
||||||
speciesPanel.setParams();
|
speciesPanel.setParams();
|
||||||
|
andOrBox.setSelectedIndex(clickDataSelector.getParams().isClicksANDEvents() ? 0 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getParams() {
|
public boolean getParams() {
|
||||||
|
clickDataSelector.getParams().setClicksANDEvents(andOrBox.getSelectedIndex() == 0);
|
||||||
return (speciesPanel.getParams() & eventTypePanel.getParams());
|
return (speciesPanel.getParams() & eventTypePanel.getParams());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,17 +169,26 @@ public class ClickSelectPanel implements PamDialogPanel {
|
|||||||
// JRadioButton andEvents, orEvents;
|
// JRadioButton andEvents, orEvents;
|
||||||
// JRadioButton anyEvents, onlyEvents;
|
// JRadioButton anyEvents, onlyEvents;
|
||||||
private JCheckBox useEchoes;
|
private JCheckBox useEchoes;
|
||||||
|
private JTextField minAmplitude;
|
||||||
private JCheckBox scoreByAmplitude;
|
private JCheckBox scoreByAmplitude;
|
||||||
private JTextField minICI;
|
private JTextField minICI;
|
||||||
|
|
||||||
SpeciesPanel () {
|
SpeciesPanel () {
|
||||||
super();
|
super();
|
||||||
setLayout(new BorderLayout());
|
// setLayout(new BorderLayout());
|
||||||
|
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||||
northPanel = new JPanel();
|
northPanel = new JPanel();
|
||||||
northPanel.setLayout(new GridBagLayout());
|
northPanel.setLayout(new GridBagLayout());
|
||||||
GridBagConstraints c = new PamGridBagContraints();
|
GridBagConstraints c = new PamGridBagContraints();
|
||||||
c.gridwidth = 3;
|
c.gridwidth = 1;
|
||||||
c.anchor = GridBagConstraints.WEST;
|
c.anchor = GridBagConstraints.WEST;
|
||||||
|
northPanel.add(new JLabel("Minimum amplitude ", JLabel.RIGHT), c);
|
||||||
|
c.gridx++;
|
||||||
|
northPanel.add(minAmplitude = new JTextField(4), c);
|
||||||
|
c.gridx++;
|
||||||
|
northPanel.add(new JLabel(" dB"));
|
||||||
|
c.gridx = 0;
|
||||||
|
c.gridy++;
|
||||||
northPanel.add(new PamAlignmentPanel(useEchoes = new JCheckBox("Use Echoes"), BorderLayout.WEST), c);
|
northPanel.add(new PamAlignmentPanel(useEchoes = new JCheckBox("Use Echoes"), BorderLayout.WEST), c);
|
||||||
c.gridwidth = 1;
|
c.gridwidth = 1;
|
||||||
c.gridy++;
|
c.gridy++;
|
||||||
@ -185,35 +200,50 @@ public class ClickSelectPanel implements PamDialogPanel {
|
|||||||
// minICI.setToolTipText("Minimum ICI in milliseconds");
|
// minICI.setToolTipText("Minimum ICI in milliseconds");
|
||||||
// c.gridx++;
|
// c.gridx++;
|
||||||
// northPanel.add(new JLabel(" ms", JLabel.LEFT), c);
|
// northPanel.add(new JLabel(" ms", JLabel.LEFT), c);
|
||||||
|
scoreByAmplitude = new JCheckBox("Score by amplitude");
|
||||||
|
if (allowScores) {
|
||||||
c.gridwidth = 3;
|
c.gridwidth = 3;
|
||||||
c.gridy++;
|
c.gridy++;
|
||||||
c.gridx = 0;
|
c.gridx = 0;
|
||||||
northPanel.add(scoreByAmplitude = new JCheckBox("Score by amplitude"), c);
|
northPanel.add(scoreByAmplitude, c);
|
||||||
scoreByAmplitude.setVisible(allowScores);
|
scoreByAmplitude.setVisible(allowScores);
|
||||||
scoreByAmplitude.addActionListener(new AllSpeciesListener());
|
scoreByAmplitude.addActionListener(new AllSpeciesListener());
|
||||||
|
}
|
||||||
WestAlignedPanel walpn;
|
WestAlignedPanel walpn;
|
||||||
add(BorderLayout.NORTH, walpn = new WestAlignedPanel(northPanel));
|
this.add(walpn = new WestAlignedPanel(northPanel));
|
||||||
walpn.setBorder(new SeparatorBorder("Echoes"));
|
walpn.setBorder(new SeparatorBorder("Click Selection"));
|
||||||
|
|
||||||
JPanel centralOuterPanel = new JPanel(new BorderLayout());
|
JPanel centralOuterPanel = new JPanel(new BorderLayout());
|
||||||
centralPanel.setLayout(new GridBagLayout());
|
centralPanel.setLayout(new GridBagLayout());
|
||||||
centralOuterPanel.setBorder(new SeparatorBorder("Click Type Selection"));
|
centralOuterPanel.setBorder(new SeparatorBorder("Click Types"));
|
||||||
|
|
||||||
add(BorderLayout.CENTER, centralOuterPanel);
|
this.add(centralOuterPanel);
|
||||||
JScrollPane scrollPane = new DialogScrollPane(new PamAlignmentPanel(centralPanel, BorderLayout.WEST), 10);
|
JScrollPane scrollPane = new DialogScrollPane(new PamAlignmentPanel(centralPanel, BorderLayout.WEST), 10);
|
||||||
centralOuterPanel.add(BorderLayout.CENTER, scrollPane);
|
centralOuterPanel.add(BorderLayout.CENTER, scrollPane);
|
||||||
|
|
||||||
centralEastPanel.setLayout(new GridBagLayout());
|
centralEastPanel.setLayout(new GridBagLayout());
|
||||||
c = new PamGridBagContraints();
|
c = new PamGridBagContraints();
|
||||||
centralEastPanel.add(selectAll = new JButton("Select All"), c);
|
c.ipady = 0;
|
||||||
c.gridx++;
|
c.insets.bottom = c.insets.top = c.insets.left = c.insets.right = 0;
|
||||||
centralEastPanel.add(clearAll = new JButton("Clear All"), c);
|
centralEastPanel.add(selectAll = new JButton("All"), c);
|
||||||
|
c.gridy++;
|
||||||
|
centralEastPanel.add(clearAll = new JButton("None"), c);
|
||||||
|
selectAll.setBorder(new EmptyBorder(3,3,2,3));
|
||||||
|
clearAll.setBorder(new EmptyBorder(3,3,2,3));
|
||||||
selectAll.addActionListener(new AutoSelect(true));
|
selectAll.addActionListener(new AutoSelect(true));
|
||||||
clearAll.addActionListener(new AutoSelect(false));
|
clearAll.addActionListener(new AutoSelect(false));
|
||||||
centralOuterPanel.add(BorderLayout.SOUTH, new PamAlignmentPanel(centralEastPanel, BorderLayout.WEST));
|
centralOuterPanel.add(BorderLayout.EAST, new PamAlignmentPanel(centralEastPanel, BorderLayout.NORTH));
|
||||||
|
|
||||||
centralOuterPanel.setToolTipText(mainTip);
|
centralOuterPanel.setToolTipText(mainTip);
|
||||||
|
|
||||||
|
this.add(andOrBox = new JComboBox<>());
|
||||||
|
andOrBox.setToolTipText("Select how to logically combine the click and event selections");
|
||||||
|
andOrBox.addItem("AND");
|
||||||
|
andOrBox.addItem("OR");
|
||||||
|
JPanel emptyPanel = new JPanel();
|
||||||
|
emptyPanel.setPreferredSize(new Dimension(10, 5));
|
||||||
|
this.add(emptyPanel);
|
||||||
|
|
||||||
setToolTipText(mainTip);
|
setToolTipText(mainTip);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,6 +284,7 @@ public class ClickSelectPanel implements PamDialogPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
useEchoes.setSelected(clickAlarmParameters.useEchoes);
|
useEchoes.setSelected(clickAlarmParameters.useEchoes);
|
||||||
|
minAmplitude.setText(String.format("%3.1f", clickAlarmParameters.minimumAmplitude));
|
||||||
minICI.setText(String.format("%d", clickAlarmParameters.minICIMillis));
|
minICI.setText(String.format("%d", clickAlarmParameters.minICIMillis));
|
||||||
scoreByAmplitude.setSelected(clickAlarmParameters.scoreByAmplitude);
|
scoreByAmplitude.setSelected(clickAlarmParameters.scoreByAmplitude);
|
||||||
allWeight.setText(String.format("%3.1f", clickAlarmParameters.getSpeciesWeight(0)));
|
allWeight.setText(String.format("%3.1f", clickAlarmParameters.getSpeciesWeight(0)));
|
||||||
@ -279,6 +310,12 @@ public class ClickSelectPanel implements PamDialogPanel {
|
|||||||
|
|
||||||
ClickAlarmParameters clickAlarmParameters = clickDataSelector.getClickAlarmParameters().clone();
|
ClickAlarmParameters clickAlarmParameters = clickDataSelector.getClickAlarmParameters().clone();
|
||||||
clickAlarmParameters.useEchoes = useEchoes.isSelected();
|
clickAlarmParameters.useEchoes = useEchoes.isSelected();
|
||||||
|
try {
|
||||||
|
clickAlarmParameters.minimumAmplitude = Double.valueOf(minAmplitude.getText());
|
||||||
|
}
|
||||||
|
catch (NumberFormatException e) {
|
||||||
|
return PamDialog.showWarning(null, "Minimum amplitude", "Invalid minimum amplitude value");
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
clickAlarmParameters.minICIMillis = Integer.valueOf(minICI.getText());
|
clickAlarmParameters.minICIMillis = Integer.valueOf(minICI.getText());
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ import PamView.dialog.warn.WarnOnce;
|
|||||||
import clickDetector.BTDisplayParameters;
|
import clickDetector.BTDisplayParameters;
|
||||||
import clickDetector.ClickControl;
|
import clickDetector.ClickControl;
|
||||||
import clickDetector.ClickClassifiers.ClickIdentifier;
|
import clickDetector.ClickClassifiers.ClickIdentifier;
|
||||||
|
import clickDetector.alarm.ClickAlarmParameters;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dialog for basic click display parameters
|
* Dialog for basic click display parameters
|
||||||
@ -58,6 +59,8 @@ public class ClickDisplayDialog extends PamDialog implements ActionListener {
|
|||||||
private SpeciesPanel speciesPanel;
|
private SpeciesPanel speciesPanel;
|
||||||
private JComboBox<String> angleTypes;
|
private JComboBox<String> angleTypes;
|
||||||
|
|
||||||
|
private ClickAlarmParameters clickSelectParams;
|
||||||
|
|
||||||
private ClickDisplayDialog(Window owner) {
|
private ClickDisplayDialog(Window owner) {
|
||||||
|
|
||||||
super(owner, "Click Display Parameters", true);
|
super(owner, "Click Display Parameters", true);
|
||||||
@ -86,12 +89,13 @@ public class ClickDisplayDialog extends PamDialog implements ActionListener {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BTDisplayParameters showDialog(ClickControl clickControl, Window parentFrame, BTDisplayParameters btDisplayParameters) {
|
public static BTDisplayParameters showDialog(ClickControl clickControl, Window parentFrame, BTDisplayParameters btDisplayParameters, ClickAlarmParameters clickSelectParams) {
|
||||||
if (singleInstance == null || singleInstance.getOwner() != parentFrame) {
|
if (singleInstance == null || singleInstance.getOwner() != parentFrame) {
|
||||||
singleInstance = new ClickDisplayDialog(parentFrame);
|
singleInstance = new ClickDisplayDialog(parentFrame);
|
||||||
}
|
}
|
||||||
singleInstance.clickControl = clickControl;
|
singleInstance.clickControl = clickControl;
|
||||||
singleInstance.btDisplayParameters = btDisplayParameters.clone();
|
singleInstance.btDisplayParameters = btDisplayParameters.clone();
|
||||||
|
singleInstance.clickSelectParams = clickSelectParams;
|
||||||
singleInstance.setParams(btDisplayParameters);
|
singleInstance.setParams(btDisplayParameters);
|
||||||
singleInstance.setVisible(true);
|
singleInstance.setVisible(true);
|
||||||
return singleInstance.btDisplayParameters;
|
return singleInstance.btDisplayParameters;
|
||||||
@ -514,14 +518,16 @@ public class ClickDisplayDialog extends PamDialog implements ActionListener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
showEchoes.setSelected(btDisplayParameters.showEchoes);
|
showEchoes.setSelected(clickSelectParams.useEchoes);
|
||||||
if (species == null) {
|
if (species == null) {
|
||||||
showAll.setSelected(true);
|
showAll.setSelected(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
showAll.setSelected(btDisplayParameters.getShowSpecies(0));
|
// showAll.setSelected(btDisplayParameters.getShowSpecies(0));
|
||||||
|
showAll.setSelected(clickSelectParams.getUseSpecies(0));
|
||||||
for (int i = 0; i < species.length; i++) {
|
for (int i = 0; i < species.length; i++) {
|
||||||
species[i].setSelected(btDisplayParameters.getShowSpecies(i+1));
|
species[i].setSelected(clickSelectParams.getUseSpecies(i+1));
|
||||||
|
// species[i].setSelected(btDisplayParameters.getShowSpecies(i+1));
|
||||||
}
|
}
|
||||||
// if (btDisplayParameters.showSpeciesList != null) {
|
// if (btDisplayParameters.showSpeciesList != null) {
|
||||||
// for (int i = 0; i < Math.min(species.length, btDisplayParameters.showSpeciesList.length);i++) {
|
// for (int i = 0; i < Math.min(species.length, btDisplayParameters.showSpeciesList.length);i++) {
|
||||||
@ -529,9 +535,10 @@ public class ClickDisplayDialog extends PamDialog implements ActionListener {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
clicksInAnEvent.setSelected(clickSelectParams.onlineAutoEvents | clickSelectParams.onlineAutoEvents);
|
||||||
|
|
||||||
clicksInAnEvent.setSelected(btDisplayParameters.showEventsOnly);
|
// clicksInAnEvent.setSelected(btDisplayParameters.showEventsOnly);
|
||||||
andOrSelection.setSelectedIndex(btDisplayParameters.showANDEvents ? 0: 1);
|
// andOrSelection.setSelectedIndex(btDisplayParameters.showANDEvents ? 0: 1);
|
||||||
// orEvents.setSelected(!btDisplayParameters.showANDEvents);
|
// orEvents.setSelected(!btDisplayParameters.showANDEvents);
|
||||||
// andEvents.setSelected(btDisplayParameters.showANDEvents);
|
// andEvents.setSelected(btDisplayParameters.showANDEvents);
|
||||||
// anyEvents.setSelected(!btDisplayParameters.showEventsOnly);
|
// anyEvents.setSelected(!btDisplayParameters.showEventsOnly);
|
||||||
@ -540,19 +547,17 @@ public class ClickDisplayDialog extends PamDialog implements ActionListener {
|
|||||||
enableButtons();
|
enableButtons();
|
||||||
}
|
}
|
||||||
boolean getParams() {
|
boolean getParams() {
|
||||||
btDisplayParameters.showEchoes = showEchoes.isSelected();
|
// clickSelectParams.useEchoes = showEchoes.isSelected();
|
||||||
btDisplayParameters.setShowSpecies(0, showAll.isSelected());
|
// btDisplayParameters.setShowSpecies(0, showAll.isSelected());
|
||||||
if (species != null) {
|
// if (species != null) {
|
||||||
for (int i = 0; i < species.length; i++) {
|
// for (int i = 0; i < species.length; i++) {
|
||||||
btDisplayParameters.setShowSpecies(i+1, species[i].isSelected());
|
// btDisplayParameters.setShowSpecies(i+1, species[i].isSelected());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
btDisplayParameters.showEventsOnly = clicksInAnEvent.isSelected();
|
// btDisplayParameters.showEventsOnly = clicksInAnEvent.isSelected();
|
||||||
btDisplayParameters.showANDEvents = (andOrSelection.getSelectedIndex() == 0);
|
// btDisplayParameters.showANDEvents = (andOrSelection.getSelectedIndex() == 0);
|
||||||
// btDisplayParameters.showANDEvents = andEvents.isSelected();
|
|
||||||
// btDisplayParameters.showEventsOnly = onlyEvents.isSelected();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
class AllSpeciesListener implements ActionListener {
|
class AllSpeciesListener implements ActionListener {
|
||||||
|
@ -31,12 +31,15 @@ import clickDetector.ClickBTDisplay;
|
|||||||
import clickDetector.ClickControl;
|
import clickDetector.ClickControl;
|
||||||
import clickDetector.ClickDisplay;
|
import clickDetector.ClickDisplay;
|
||||||
import clickDetector.ClickClassifiers.ClickIdentifier;
|
import clickDetector.ClickClassifiers.ClickIdentifier;
|
||||||
|
import clickDetector.alarm.ClickAlarmParameters;
|
||||||
|
import clickDetector.dataSelector.ClickDataSelector;
|
||||||
import PamView.PamToolBar;
|
import PamView.PamToolBar;
|
||||||
import PamView.component.PamSettingsIconButton;
|
import PamView.component.PamSettingsIconButton;
|
||||||
import PamView.dialog.PamCheckBox;
|
import PamView.dialog.PamCheckBox;
|
||||||
import PamView.dialog.PamLabel;
|
import PamView.dialog.PamLabel;
|
||||||
import PamView.dialog.PamRadioButton;
|
import PamView.dialog.PamRadioButton;
|
||||||
import PamView.panel.PamPanel;
|
import PamView.panel.PamPanel;
|
||||||
|
import PamguardMVC.dataSelector.DataSelectParams;
|
||||||
|
|
||||||
public class OfflineToolbar {
|
public class OfflineToolbar {
|
||||||
|
|
||||||
@ -252,19 +255,29 @@ public class OfflineToolbar {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
ClickDataSelector clickDataSelector = currentBTDisplay.getClickDataSelector();
|
||||||
|
ClickAlarmParameters selectParams = clickDataSelector.getParams();
|
||||||
BTDisplayParameters btDisplayParameters = currentBTDisplay.getBtDisplayParameters();
|
BTDisplayParameters btDisplayParameters = currentBTDisplay.getBtDisplayParameters();
|
||||||
btDisplayParameters.setShowSpecies(0, showNonSpecies.isSelected());
|
|
||||||
btDisplayParameters.showEchoes = showEchoes.isSelected();
|
selectParams.setUseSpecies(0, showNonSpecies.isSelected());
|
||||||
|
// btDisplayParameters.setShowSpecies(0, showNonSpecies.isSelected());
|
||||||
|
// btDisplayParameters.showEchoes = showEchoes.isSelected();
|
||||||
|
selectParams.useEchoes = showEchoes.isSelected();
|
||||||
|
|
||||||
if (clicksInAnEvent != null) {
|
if (clicksInAnEvent != null) {
|
||||||
btDisplayParameters.showEventsOnly = clicksInAnEvent.isSelected();
|
// btDisplayParameters.showEventsOnly = clicksInAnEvent.isSelected();
|
||||||
|
// selectParams.onlineAutoEvents = selectParams.onlineManualEvents = true;
|
||||||
|
selectParams.unassignedEvents =clicksInAnEvent.isSelected() == false;
|
||||||
}
|
}
|
||||||
if (andOrSelection != null) {
|
if (andOrSelection != null) {
|
||||||
btDisplayParameters.showANDEvents = (andOrSelection.getSelectedIndex() == 0);
|
selectParams.setClicksANDEvents(andOrSelection.getSelectedIndex() == 0);
|
||||||
|
// btDisplayParameters.showANDEvents = (andOrSelection.getSelectedIndex() == 0);
|
||||||
}
|
}
|
||||||
if (speciesButtons != null) {
|
if (speciesButtons != null) {
|
||||||
int n = speciesButtons.length;
|
int n = speciesButtons.length;
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
btDisplayParameters.setShowSpecies(i+1, speciesButtons[i].isSelected());
|
selectParams.setUseSpecies(i+1, speciesButtons[i].isSelected());
|
||||||
|
// btDisplayParameters.setShowSpecies(i+1, speciesButtons[i].isSelected());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentBTDisplay.repaintTotal();
|
currentBTDisplay.repaintTotal();
|
||||||
@ -275,23 +288,35 @@ public class OfflineToolbar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkButtons(BTDisplayParameters btDisplayParameters) {
|
private void checkButtons(BTDisplayParameters btDisplayParameters) {
|
||||||
showEchoes.setSelected(btDisplayParameters.showEchoes);
|
ClickDataSelector clickDataSelector = currentBTDisplay.getClickDataSelector();
|
||||||
showNonSpecies.setSelected(btDisplayParameters.getShowSpecies(0));
|
ClickAlarmParameters selectParams = clickDataSelector.getParams();
|
||||||
|
showEchoes.setSelected(selectParams.useEchoes);
|
||||||
|
showNonSpecies.setSelected(selectParams.getUseSpecies(0));
|
||||||
|
// showNonSpecies.setSelected(btDisplayParameters.getShowSpecies(0));
|
||||||
|
boolean anySel = false;;
|
||||||
if (clicksInAnEvent != null) {
|
if (clicksInAnEvent != null) {
|
||||||
clicksInAnEvent.setSelected(btDisplayParameters.showEventsOnly);
|
clicksInAnEvent.setSelected(selectParams.unassignedEvents == false);
|
||||||
|
anySel |= clicksInAnEvent.isSelected();
|
||||||
|
// clicksInAnEvent.setSelected(btDisplayParameters.showEventsOnly);
|
||||||
}
|
}
|
||||||
if (speciesButtons != null) {
|
if (speciesButtons != null) {
|
||||||
int n = speciesButtons.length;
|
int n = speciesButtons.length;
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
speciesButtons[i].setSelected(btDisplayParameters.getShowSpecies(i+1));
|
speciesButtons[i].setSelected(selectParams.getUseSpecies(i+1));
|
||||||
|
anySel |= speciesButtons[i].isSelected();
|
||||||
|
// speciesButtons[i].setSelected(btDisplayParameters.getShowSpecies(i+1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// setting combo box fires actionlistener, so we have to make sure that all checkboxes have been properly set first
|
// setting combo box fires actionlistener, so we have to make sure that all checkboxes have been properly set first
|
||||||
// or else they will get cleared later
|
// or else they will get cleared later
|
||||||
if (andOrSelection != null) {
|
if (andOrSelection != null) {
|
||||||
andOrSelection.setSelectedIndex(btDisplayParameters.showANDEvents ? 0: 1);
|
andOrSelection.setSelectedIndex(selectParams.isClicksANDEvents() ? 0 : 1);
|
||||||
|
// andOrSelection.setSelectedIndex(btDisplayParameters.showANDEvents ? 0: 1);
|
||||||
}
|
}
|
||||||
firstSetup = true;
|
firstSetup = true;
|
||||||
|
if (anySel) {
|
||||||
|
selectParams.setCombinationFlag(DataSelectParams.DATA_SELECT_AND);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
package clickDetector.tdPlots;
|
package clickDetector.tdPlots;
|
||||||
|
|
||||||
|
import javax.swing.JCheckBox;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.border.TitledBorder;
|
||||||
|
|
||||||
import PamView.GeneralProjector;
|
import PamView.GeneralProjector;
|
||||||
import PamView.PamSymbol;
|
import PamView.PamSymbol;
|
||||||
|
import PamView.dialog.PamDialogPanel;
|
||||||
import PamView.symbol.PamSymbolChooser;
|
import PamView.symbol.PamSymbolChooser;
|
||||||
import PamView.symbol.SymbolData;
|
import PamView.symbol.SymbolData;
|
||||||
import PamView.symbol.modifier.SymbolModType;
|
import PamView.symbol.modifier.SymbolModType;
|
||||||
@ -32,4 +38,41 @@ public class ClickClassSymbolModifier extends SymbolModifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PamDialogPanel getDialogPanel() {
|
||||||
|
// Just a play to check buttons and menus work. Not actually used at all so revert to super: returns null.
|
||||||
|
return super.getDialogPanel();
|
||||||
|
// return new DumyPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DumyPanel implements PamDialogPanel {
|
||||||
|
|
||||||
|
private JPanel mainPanel;
|
||||||
|
public DumyPanel() {
|
||||||
|
super();
|
||||||
|
mainPanel = new JPanel();
|
||||||
|
mainPanel.setBorder(new TitledBorder("More options"));
|
||||||
|
mainPanel.add(new JCheckBox("Dummy option"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JComponent getDialogComponent() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return mainPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParams() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getParams() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@ import clickDetector.BTDisplayParameters;
|
|||||||
import clickDetector.ClickControl;
|
import clickDetector.ClickControl;
|
||||||
import clickDetector.ClickDetection;
|
import clickDetector.ClickDetection;
|
||||||
import clickDetector.ClickDisplayManagerParameters;
|
import clickDetector.ClickDisplayManagerParameters;
|
||||||
|
import clickDetector.alarm.ClickAlarmParameters;
|
||||||
|
import clickDetector.dataSelector.ClickDataSelector;
|
||||||
import clickDetector.dialogs.ClickDisplayDialog;
|
import clickDetector.dialogs.ClickDisplayDialog;
|
||||||
import PamView.GeneralProjector.ParameterType;
|
import PamView.GeneralProjector.ParameterType;
|
||||||
import PamView.GeneralProjector.ParameterUnits;
|
import PamView.GeneralProjector.ParameterUnits;
|
||||||
@ -53,6 +55,10 @@ public class ClickPlotInfo extends TDDataInfo {
|
|||||||
clickHidingDialog = new ClickHidingDialog(this);
|
clickHidingDialog = new ClickHidingDialog(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClickDataSelector getDataSelector() {
|
||||||
|
return (ClickDataSelector) clickControl.getClickDataBlock().getDataSelector("ClickTDPlots", false);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Double getDataValue(PamDataUnit pamDataUnit) {
|
public Double getDataValue(PamDataUnit pamDataUnit) {
|
||||||
ClickDetection click = (ClickDetection) pamDataUnit;
|
ClickDetection click = (ClickDetection) pamDataUnit;
|
||||||
@ -110,7 +116,8 @@ public class ClickPlotInfo extends TDDataInfo {
|
|||||||
private synchronized boolean shouldPlot(ClickDetection click) {
|
private synchronized boolean shouldPlot(ClickDetection click) {
|
||||||
|
|
||||||
if (click == null) return false;
|
if (click == null) return false;
|
||||||
if (btDisplayParams.showEchoes == false && click.isEcho()) {
|
boolean showEchoes = getDataSelector().getClickAlarmParameters().useEchoes;
|
||||||
|
if (showEchoes == false && click.isEcho()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +177,7 @@ public class ClickPlotInfo extends TDDataInfo {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean editOptions(Window frame) {
|
public boolean editOptions(Window frame) {
|
||||||
BTDisplayParameters newParams = ClickDisplayDialog.showDialog(clickControl, frame, btDisplayParams);
|
BTDisplayParameters newParams = ClickDisplayDialog.showDialog(clickControl, frame, btDisplayParams, getDataSelector().getClickAlarmParameters());
|
||||||
if (newParams != null) {
|
if (newParams != null) {
|
||||||
btDisplayParams = newParams.clone();
|
btDisplayParams = newParams.clone();
|
||||||
updateSettings();
|
updateSettings();
|
||||||
|
@ -185,6 +185,7 @@ public class TemplateSpectrumPane extends PamBorderPane {
|
|||||||
this.currentSpectrum = new SpectrumTemplateDataUnit(spectrumTemplate);
|
this.currentSpectrum = new SpectrumTemplateDataUnit(spectrumTemplate);
|
||||||
templateDisplay.setDataUnit(currentSpectrum);
|
templateDisplay.setDataUnit(currentSpectrum);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -226,7 +227,6 @@ public class TemplateSpectrumPane extends PamBorderPane {
|
|||||||
if (templateImporters.get(i).getExtension()[j].equals(extension)) {
|
if (templateImporters.get(i).getExtension()[j].equals(extension)) {
|
||||||
// System.out.println("Import using the extensions: " + extension);
|
// System.out.println("Import using the extensions: " + extension);
|
||||||
template=templateImporters.get(i).importTemplate(file);
|
template=templateImporters.get(i).importTemplate(file);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -288,7 +288,7 @@ public class TemplateSpectrumPane extends PamBorderPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double[][] getPowerSpectrum(SpectrumTemplateDataUnit data, int strat, int end) {
|
public double[][] getPowerSpectrum(SpectrumTemplateDataUnit data, int start, int end) {
|
||||||
return new double[][]{data.spectrumTemplate.waveform};
|
return new double[][]{data.spectrumTemplate.waveform};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,6 +296,7 @@ public class TemplateSpectrumPane extends PamBorderPane {
|
|||||||
@Override
|
@Override
|
||||||
public double getSampleRate(SpectrumTemplateDataUnit data) {
|
public double getSampleRate(SpectrumTemplateDataUnit data) {
|
||||||
//bit of a hack to get sample rate but works.
|
//bit of a hack to get sample rate but works.
|
||||||
|
// System.out.println("Set sample rate: " + data.spectrumTemplate.sR);
|
||||||
return data.spectrumTemplate.sR;
|
return data.spectrumTemplate.sR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,11 +189,6 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
|
|||||||
dataSelectHolder.setPadding(new Insets(5,5,5,5));
|
dataSelectHolder.setPadding(new Insets(5,5,5,5));
|
||||||
|
|
||||||
dataSelectPane = createDataSelectPane();
|
dataSelectPane = createDataSelectPane();
|
||||||
dataSelectPane.addSettingsListener(()->{
|
|
||||||
//dynamic settings pane so have to repaint whenever a control is selected.
|
|
||||||
getParams();
|
|
||||||
clickPlotInfo.getTDGraph().repaint(0);
|
|
||||||
});
|
|
||||||
dataSelectPane.setParams(true);
|
dataSelectPane.setParams(true);
|
||||||
|
|
||||||
|
|
||||||
@ -215,6 +210,7 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
|
|||||||
scrollPane2.setHbarPolicy(ScrollBarPolicy.NEVER);
|
scrollPane2.setHbarPolicy(ScrollBarPolicy.NEVER);
|
||||||
scrollPane2.getStyleClass().clear();
|
scrollPane2.getStyleClass().clear();
|
||||||
symbolTab.setContent(scrollPane2);
|
symbolTab.setContent(scrollPane2);
|
||||||
|
|
||||||
Tab dataView=new Tab("Data");
|
Tab dataView=new Tab("Data");
|
||||||
dataView.setContent(dataSelectHolder);
|
dataView.setContent(dataSelectHolder);
|
||||||
dataView.getStyleClass().add("tab-square");
|
dataView.getStyleClass().add("tab-square");
|
||||||
@ -231,6 +227,21 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
|
|||||||
setFreqType();
|
setFreqType();
|
||||||
setParams();
|
setParams();
|
||||||
|
|
||||||
|
dataSelectPane.addSettingsListener(()->{
|
||||||
|
//dynamic settings pane so have to repaint whenever a control is selected.
|
||||||
|
getParams();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If there are raw amplitude or frequency panes that have a buffer of painted units then
|
||||||
|
* these have to be cleared for the data selector
|
||||||
|
*/
|
||||||
|
clickPlotInfo.getClickRawPlotManager().clear();
|
||||||
|
clickPlotInfo.getClickFFTPlotManager().clear();
|
||||||
|
|
||||||
|
|
||||||
|
clickPlotInfo.getTDGraph().repaint(50);
|
||||||
|
});
|
||||||
|
|
||||||
this.setCenter(tabPane);
|
this.setCenter(tabPane);
|
||||||
|
|
||||||
this.setPrefHeight(PREF_HEIGHT);
|
this.setPrefHeight(PREF_HEIGHT);
|
||||||
@ -242,6 +253,7 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
|
|||||||
* @return the data select pane.
|
* @return the data select pane.
|
||||||
*/
|
*/
|
||||||
private DynamicSettingsPane<Boolean> createDataSelectPane(){
|
private DynamicSettingsPane<Boolean> createDataSelectPane(){
|
||||||
|
// System.out.println("DATA SELECTOR: " + clickPlotInfo.getClickDataSelector());
|
||||||
return clickPlotInfo.getClickDataSelector().getDialogPaneFX();
|
return clickPlotInfo.getClickDataSelector().getDialogPaneFX();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,7 +458,7 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
|
|||||||
PamVBox vBox = new PamVBox();
|
PamVBox vBox = new PamVBox();
|
||||||
vBox.setSpacing(5);
|
vBox.setSpacing(5);
|
||||||
|
|
||||||
minMaxWidthPane = new DualControlField<Double>("Min", "Max" , "", 2, 100, 1);
|
minMaxWidthPane = new DualControlField<Double>("", "" , "", 2, 100, 1);
|
||||||
minMaxWidthPane.addChangeListener((obsval, oldval, newval)->{
|
minMaxWidthPane.addChangeListener((obsval, oldval, newval)->{
|
||||||
newSettings();
|
newSettings();
|
||||||
//do not allow the min ti be larger than the max.
|
//do not allow the min ti be larger than the max.
|
||||||
@ -469,7 +481,7 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
|
|||||||
|
|
||||||
|
|
||||||
//height pane
|
//height pane
|
||||||
minMaxHeightPane = new DualControlField<Double>("Min", "Max" , "", 2, 100, 1);
|
minMaxHeightPane = new DualControlField<Double>("", "" , "", 2, 100, 1);
|
||||||
minMaxHeightPane.addChangeListener((obsval, oldval, newval)->{
|
minMaxHeightPane.addChangeListener((obsval, oldval, newval)->{
|
||||||
newSettings();
|
newSettings();
|
||||||
//do not allow the min ti be larger than the max.
|
//do not allow the min ti be larger than the max.
|
||||||
@ -516,7 +528,7 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
|
|||||||
getParams();
|
getParams();
|
||||||
|
|
||||||
//on a parameter change must clear the FFT plot.
|
//on a parameter change must clear the FFT plot.
|
||||||
clickPlotInfo.getClickFFTplotManager().clear();
|
clickPlotInfo.getClickFFTPlotManager().clear();
|
||||||
clickPlotInfo.getClickRawPlotManager().clear();
|
clickPlotInfo.getClickRawPlotManager().clear();
|
||||||
|
|
||||||
clickPlotInfo.getTDGraph().repaint(milliswait);
|
clickPlotInfo.getTDGraph().repaint(milliswait);
|
||||||
@ -770,7 +782,7 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
|
|||||||
clickPlotInfo.getClickDisplayParams().fftHop = this.fftSpinnerHop.getValue().intValue();
|
clickPlotInfo.getClickDisplayParams().fftHop = this.fftSpinnerHop.getValue().intValue();
|
||||||
clickPlotInfo.getClickDisplayParams().fftLength = this.fftSpinnerLength.getValue().intValue();
|
clickPlotInfo.getClickDisplayParams().fftLength = this.fftSpinnerLength.getValue().intValue();
|
||||||
clickPlotInfo.getClickDisplayParams().colourMap = this.spectroControlPane.getColourArrayType();
|
clickPlotInfo.getClickDisplayParams().colourMap = this.spectroControlPane.getColourArrayType();
|
||||||
clickPlotInfo.getClickFFTplotManager().update();
|
clickPlotInfo.getClickFFTPlotManager().update();
|
||||||
/*** Data select pane****/
|
/*** Data select pane****/
|
||||||
|
|
||||||
//dynamic settings pane so have to repaint whenever a control is selected.
|
//dynamic settings pane so have to repaint whenever a control is selected.
|
||||||
|
@ -238,7 +238,7 @@ public class ClickPlotInfoFX extends TDDataInfoFX {
|
|||||||
|
|
||||||
ClickDetection click = (ClickDetection) pamDataUnit;
|
ClickDetection click = (ClickDetection) pamDataUnit;
|
||||||
//first check we can generally plot the click
|
//first check we can generally plot the click
|
||||||
if (!shouldPlot(click)) return null;
|
// if (!shouldPlot(click)) return null;
|
||||||
//click has passed the first test! Now get the correct data value;
|
//click has passed the first test! Now get the correct data value;
|
||||||
Double val = null;
|
Double val = null;
|
||||||
switch (getCurrentScaleInfo().getDataType()) {
|
switch (getCurrentScaleInfo().getDataType()) {
|
||||||
@ -599,21 +599,21 @@ public class ClickPlotInfoFX extends TDDataInfoFX {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
/***
|
// /***
|
||||||
* Used to determine which clicks should be plotted on the display by using the click data selector.
|
// * Used to determine which clicks should be plotted on the display by using the click data selector.
|
||||||
* @param click - the click to check.
|
// * @param click - the click to check.
|
||||||
* @return true to plot the click.
|
// * @return true to plot the click.
|
||||||
*/
|
// */
|
||||||
private synchronized boolean shouldPlot(ClickDetection click) {
|
// private synchronized boolean shouldPlot(ClickDetection click) {
|
||||||
|
//
|
||||||
if (click == null) return false;
|
// if (click == null) return false;
|
||||||
|
//
|
||||||
dataSelector.scoreData(click);
|
// if (dataSelector.scoreData(click)<=0) return false;
|
||||||
|
//
|
||||||
if (clickDisplayParams.displayChannels > 0 && (clickDisplayParams.displayChannels & click.getChannelBitmap()) == 0) return false;
|
// if (clickDisplayParams.displayChannels > 0 && (clickDisplayParams.displayChannels & click.getChannelBitmap()) == 0) return false;
|
||||||
|
//
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TDSymbolChooserFX getSymbolChooser() {
|
public TDSymbolChooserFX getSymbolChooser() {
|
||||||
@ -931,7 +931,7 @@ public class ClickPlotInfoFX extends TDDataInfoFX {
|
|||||||
* time/frequency displays...
|
* time/frequency displays...
|
||||||
* @return The FFT plot manager.
|
* @return The FFT plot manager.
|
||||||
*/
|
*/
|
||||||
public ClickFFTPlotManager2 getClickFFTplotManager() {
|
public ClickFFTPlotManager2 getClickFFTPlotManager() {
|
||||||
return clickFFTplotManager;
|
return clickFFTplotManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,7 +318,6 @@ public abstract class RawWavePlotManager {
|
|||||||
//check if we can plot click on this plot pane.
|
//check if we can plot click on this plot pane.
|
||||||
if (!rawClipInfo.shouldDraw(plotNumber, pamDataUnit)) {
|
if (!rawClipInfo.shouldDraw(plotNumber, pamDataUnit)) {
|
||||||
//System.out.println("Shoudl not draw!");
|
//System.out.println("Shoudl not draw!");
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -901,13 +901,14 @@ public class TDGraphFX extends PamBorderPane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A tgool tip for detections.
|
* A Tooltip for showing information about detections.
|
||||||
*
|
*
|
||||||
* @author Jamie Macaulay
|
* @author Jamie Macaulay
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private class TDTooltip extends Tooltip {
|
private class TDTooltip extends Tooltip {
|
||||||
|
|
||||||
|
private static final double TOOL_TIP_DELAY = 60; //seconds
|
||||||
private TDPlotPane plotPanel;
|
private TDPlotPane plotPanel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -917,6 +918,8 @@ public class TDGraphFX extends PamBorderPane {
|
|||||||
public TDTooltip(TDPlotPane aPlot) {
|
public TDTooltip(TDPlotPane aPlot) {
|
||||||
super("Test tooltip");
|
super("Test tooltip");
|
||||||
this.plotPanel = aPlot;
|
this.plotPanel = aPlot;
|
||||||
|
//make the Tooltip last a little longer
|
||||||
|
this.setShowDelay(Duration.seconds(TOOL_TIP_DELAY));
|
||||||
/*
|
/*
|
||||||
* See https://bugs.openjdk.java.net/browse/JDK-8090477 fr info about tool tip
|
* See https://bugs.openjdk.java.net/browse/JDK-8090477 fr info about tool tip
|
||||||
* timing on these displys.
|
* timing on these displys.
|
||||||
|
@ -44,7 +44,7 @@ public class RExportOverlayMenu extends ExportOverlayMenu {
|
|||||||
* Create the export overlay
|
* Create the export overlay
|
||||||
*/
|
*/
|
||||||
public RExportOverlayMenu(){
|
public RExportOverlayMenu(){
|
||||||
rExportManger= new RExportManager();
|
rExportManger= new RExportManager(null);
|
||||||
|
|
||||||
buttonNode = createButton();
|
buttonNode = createButton();
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ public abstract class SpectrumPlot <D extends PamDataUnit> implements Detection
|
|||||||
private SpectrumSettingsPane spectrumSettingsPane;
|
private SpectrumSettingsPane spectrumSettingsPane;
|
||||||
|
|
||||||
|
|
||||||
private double sR;
|
private double storedsR;
|
||||||
|
|
||||||
|
|
||||||
// //TODO
|
// //TODO
|
||||||
@ -132,7 +132,7 @@ public abstract class SpectrumPlot <D extends PamDataUnit> implements Detection
|
|||||||
|
|
||||||
if (data ==null) return;
|
if (data ==null) return;
|
||||||
|
|
||||||
this.sR=sR;
|
this.storedsR=sR;
|
||||||
|
|
||||||
int[] minmax = getAxisMinMaxSamples(plotProjector);
|
int[] minmax = getAxisMinMaxSamples(plotProjector);
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ public abstract class SpectrumPlot <D extends PamDataUnit> implements Detection
|
|||||||
}
|
}
|
||||||
|
|
||||||
private double getSampleRate() {
|
private double getSampleRate() {
|
||||||
return sR;
|
return storedsR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -235,6 +235,8 @@ public abstract class SpectrumPlot <D extends PamDataUnit> implements Detection
|
|||||||
storedSpectrum=this.getPowerSpectrum(data, minmax[0], minmax[1]);
|
storedSpectrum=this.getPowerSpectrum(data, minmax[0], minmax[1]);
|
||||||
storedCepstrum=this.getCepstrum(data, minmax[0], minmax[1]);
|
storedCepstrum=this.getCepstrum(data, minmax[0], minmax[1]);
|
||||||
|
|
||||||
|
storedsR = getSampleRate(data);
|
||||||
|
|
||||||
if (spectrumPlotParams.logScale) {
|
if (spectrumPlotParams.logScale) {
|
||||||
paintLogSpectrum(gc, clipRect,projector);
|
paintLogSpectrum(gc, clipRect,projector);
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,10 @@ import java.util.List;
|
|||||||
import PamguardMVC.PamDataUnit;
|
import PamguardMVC.PamDataUnit;
|
||||||
import export.PamDataUnitExporter;
|
import export.PamDataUnitExporter;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export to CSV files which are RAVEN compatible.
|
||||||
|
*/
|
||||||
public class CSVExportManager implements PamDataUnitExporter{
|
public class CSVExportManager implements PamDataUnitExporter{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -41,4 +45,9 @@ public class CSVExportManager implements PamDataUnitExporter{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNeedsNewFile() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,11 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
import java.util.zip.Deflater;
|
import java.util.zip.Deflater;
|
||||||
|
|
||||||
import PamUtils.PamArrayUtils;
|
import PamUtils.PamArrayUtils;
|
||||||
import PamUtils.PamCalendar;
|
|
||||||
import PamguardMVC.PamDataUnit;
|
import PamguardMVC.PamDataUnit;
|
||||||
import export.PamDataUnitExporter;
|
import export.PamDataUnitExporter;
|
||||||
import us.hebi.matlab.mat.format.Mat5;
|
import us.hebi.matlab.mat.format.Mat5;
|
||||||
@ -21,7 +18,6 @@ import us.hebi.matlab.mat.types.Matrix;
|
|||||||
import us.hebi.matlab.mat.types.Sink;
|
import us.hebi.matlab.mat.types.Sink;
|
||||||
import us.hebi.matlab.mat.types.Sinks;
|
import us.hebi.matlab.mat.types.Sinks;
|
||||||
import us.hebi.matlab.mat.types.Struct;
|
import us.hebi.matlab.mat.types.Struct;
|
||||||
import us.hebi.matlab.mat.util.Casts;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,10 +102,11 @@ public class MLDetectionsManager implements PamDataUnitExporter {
|
|||||||
|
|
||||||
matFile.writeTo(sink);
|
matFile.writeTo(sink);
|
||||||
|
|
||||||
matFile.close();
|
// matFile.close(); //CAUSES AN EXCEPTION IF WRITING AGAIN
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
//write to the mat file without loading all contents into memory.
|
//write to the mat file without loading all contents into memory.
|
||||||
Mat5Writer writer = Mat5.newWriter(sink);
|
Mat5Writer writer = Mat5.newWriter(sink);
|
||||||
|
|
||||||
@ -257,7 +254,7 @@ public class MLDetectionsManager implements PamDataUnitExporter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
//handled in the mian funtion
|
//handled in the main function
|
||||||
if (sink!=null) {
|
if (sink!=null) {
|
||||||
try {
|
try {
|
||||||
sink.close();
|
sink.close();
|
||||||
@ -269,6 +266,12 @@ public class MLDetectionsManager implements PamDataUnitExporter {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNeedsNewFile() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ public class MLWhistleMoanExport extends MLDataUnitExport<ConnectedRegionDataUni
|
|||||||
|
|
||||||
// Struct mlStructure= new MLStructure("sliceData", new int[]{dataUnit.getConnectedRegion().getSliceData().size(), 1});
|
// Struct mlStructure= new MLStructure("sliceData", new int[]{dataUnit.getConnectedRegion().getSliceData().size(), 1});
|
||||||
|
|
||||||
Struct mlStructure= Mat5.newStruct();
|
Struct mlStructure= Mat5.newStruct(dataUnit.getConnectedRegion().getSliceData().size(), 1);
|
||||||
|
|
||||||
//the start sample.
|
//the start sample.
|
||||||
Matrix sliceNumber;
|
Matrix sliceNumber;
|
||||||
|
@ -41,15 +41,21 @@ public interface PamDataUnitExporter {
|
|||||||
public String getIconString();
|
public String getIconString();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the name of the exporter
|
* Get the name of the exporter.
|
||||||
* @return
|
* @return the name of the exporter.
|
||||||
*/
|
*/
|
||||||
public String getName();
|
public String getName();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clsoe the exporter
|
* Close the exporter.
|
||||||
*/
|
*/
|
||||||
public void close();
|
public void close();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether and exporter needs a new file
|
||||||
|
* @return true if we need a new file.
|
||||||
|
*/
|
||||||
|
public boolean isNeedsNewFile();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -56,11 +56,12 @@ public class PamExporterManager {
|
|||||||
"yyyy_MM_dd_HHmmss");
|
"yyyy_MM_dd_HHmmss");
|
||||||
|
|
||||||
public PamExporterManager() {
|
public PamExporterManager() {
|
||||||
|
|
||||||
pamExporters = new ArrayList<PamDataUnitExporter>();
|
pamExporters = new ArrayList<PamDataUnitExporter>();
|
||||||
|
|
||||||
//add the MATLAB export
|
//add the MATLAB export
|
||||||
pamExporters.add(new MLDetectionsManager());
|
pamExporters.add(new MLDetectionsManager());
|
||||||
pamExporters.add(new RExportManager());
|
pamExporters.add(new RExportManager(this));
|
||||||
pamExporters.add(new WavFileExportManager());
|
pamExporters.add(new WavFileExportManager());
|
||||||
pamExporters.add(new CSVExportManager());
|
pamExporters.add(new CSVExportManager());
|
||||||
}
|
}
|
||||||
@ -72,6 +73,8 @@ public class PamExporterManager {
|
|||||||
public boolean exportDataUnit(PamDataUnit<?, ?> dataUnit, boolean force) {
|
public boolean exportDataUnit(PamDataUnit<?, ?> dataUnit, boolean force) {
|
||||||
boolean exportOK = true;
|
boolean exportOK = true;
|
||||||
|
|
||||||
|
System.out.println("Add data unit " + dataUnit + " to: "+ currentFile);
|
||||||
|
|
||||||
if (dataUnit==null) {
|
if (dataUnit==null) {
|
||||||
if (force) {
|
if (force) {
|
||||||
System.out.println("Write data 1!!" + dataUnitBuffer.size() );
|
System.out.println("Write data 1!!" + dataUnitBuffer.size() );
|
||||||
@ -83,10 +86,10 @@ public class PamExporterManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//if file is null or too large create another a file for saving.
|
//if file is null or too large create another a file for saving.
|
||||||
if (currentFile == null || isFileSizeMax(currentFile)) {
|
if (currentFile == null || isNeedsNewFile(currentFile, pamExporters.get(exportParams.exportChoice))) {
|
||||||
Date date = new Date(dataUnit.getTimeMilliseconds());
|
Date date = new Date(dataUnit.getTimeMilliseconds());
|
||||||
|
|
||||||
String newFileName = "PAM_" + dataFormat.format(date);
|
String newFileName = "PAM_" + dataFormat.format(date) + "_" + dataUnit.getParentDataBlock().getDataName().replace(" ", "_");
|
||||||
|
|
||||||
//create a new file - note each exporter is responsible for closing the file after writing
|
//create a new file - note each exporter is responsible for closing the file after writing
|
||||||
//so previous files should already be closed
|
//so previous files should already be closed
|
||||||
@ -101,7 +104,7 @@ public class PamExporterManager {
|
|||||||
System.out.println("Write data unit " + dataUnitBuffer.size() + " to: "+ currentFile);
|
System.out.println("Write data unit " + dataUnitBuffer.size() + " to: "+ currentFile);
|
||||||
|
|
||||||
if (dataUnitBuffer.size()>=BUFFER_SIZE || force) {
|
if (dataUnitBuffer.size()>=BUFFER_SIZE || force) {
|
||||||
System.out.println("Write data 2!!" + dataUnitBuffer.size());
|
// System.out.println("Write data 2!!" + dataUnitBuffer.size());
|
||||||
exportOK = pamExporters.get(exportParams.exportChoice).exportData(currentFile, dataUnitBuffer, true);
|
exportOK = pamExporters.get(exportParams.exportChoice).exportData(currentFile, dataUnitBuffer, true);
|
||||||
dataUnitBuffer.clear();
|
dataUnitBuffer.clear();
|
||||||
}
|
}
|
||||||
@ -118,10 +121,14 @@ public class PamExporterManager {
|
|||||||
/**
|
/**
|
||||||
* Check whether the current file is greater than the maximum allowed file size.
|
* Check whether the current file is greater than the maximum allowed file size.
|
||||||
* @param currentFile2 - the current file
|
* @param currentFile2 - the current file
|
||||||
|
* @param pamDataUnitExporter
|
||||||
* @return true of greater than or equal to the maximum file size.
|
* @return true of greater than or equal to the maximum file size.
|
||||||
*/
|
*/
|
||||||
private boolean isFileSizeMax(File currentFile2) {
|
private boolean isNeedsNewFile(File currentFile2, PamDataUnitExporter pamDataUnitExporter) {
|
||||||
return getFileSizeMegaBytes(currentFile2) >= MAX_FILE_SIZE_MB;
|
if( getFileSizeMegaBytes(currentFile2) >= exportParams.maximumFileSize) {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
return pamDataUnitExporter.isNeedsNewFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,6 +18,7 @@ import org.renjin.sexp.PairList.Builder;
|
|||||||
import PamUtils.PamArrayUtils;
|
import PamUtils.PamArrayUtils;
|
||||||
import PamguardMVC.PamDataUnit;
|
import PamguardMVC.PamDataUnit;
|
||||||
import export.PamDataUnitExporter;
|
import export.PamDataUnitExporter;
|
||||||
|
import export.PamExporterManager;
|
||||||
import export.MLExport.MLDetectionsManager;
|
import export.MLExport.MLDetectionsManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,7 +30,6 @@ import export.MLExport.MLDetectionsManager;
|
|||||||
public class RExportManager implements PamDataUnitExporter {
|
public class RExportManager implements PamDataUnitExporter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* All the possible RDataUnit export classes.
|
* All the possible RDataUnit export classes.
|
||||||
*/
|
*/
|
||||||
ArrayList<RDataUnitExport> rDataExport = new ArrayList<RDataUnitExport>();
|
ArrayList<RDataUnitExport> rDataExport = new ArrayList<RDataUnitExport>();
|
||||||
@ -39,8 +39,11 @@ public class RExportManager implements PamDataUnitExporter {
|
|||||||
|
|
||||||
private Builder allData;
|
private Builder allData;
|
||||||
|
|
||||||
|
private PamExporterManager pamExporterManager;
|
||||||
|
|
||||||
public RExportManager(){
|
|
||||||
|
public RExportManager(PamExporterManager pamExporterManager){
|
||||||
|
this.pamExporterManager=pamExporterManager;
|
||||||
/***Add more options here to export data units****/
|
/***Add more options here to export data units****/
|
||||||
rDataExport.add(new RClickExport());
|
rDataExport.add(new RClickExport());
|
||||||
rDataExport.add(new RWhistleExport());
|
rDataExport.add(new RWhistleExport());
|
||||||
@ -55,17 +58,14 @@ public class RExportManager implements PamDataUnitExporter {
|
|||||||
* Note - there is no way to save data units to R files wothout loading the file into memory.
|
* Note - there is no way to save data units to R files wothout loading the file into memory.
|
||||||
* So everything is stored in memory until saved.
|
* So everything is stored in memory until saved.
|
||||||
*/
|
*/
|
||||||
// then
|
|
||||||
PamDataUnit minByTime = PamArrayUtils.getMinTimeMillis(dataUnits);
|
PamDataUnit minByTime = PamArrayUtils.getMinTimeMillis(dataUnits);
|
||||||
|
|
||||||
//matlab struct must start with a letter.
|
//MATLAB struct must start with a letter.
|
||||||
Date date = new Date(minByTime.getTimeMilliseconds());
|
Date date = new Date(minByTime.getTimeMilliseconds());
|
||||||
String entryName = "det_" + MLDetectionsManager.dataFormat.format( date);
|
String entryName = "det_" + MLDetectionsManager.dataFormat.format( date);
|
||||||
|
|
||||||
// System.out.println("Save R data! "+ dataUnits.size());
|
// System.out.println("Save R data! "+ dataUnits.size());
|
||||||
|
|
||||||
// System.out.println("Export R file!!" + dataUnits.size());
|
// System.out.println("Export R file!!" + dataUnits.size());
|
||||||
|
|
||||||
//is there an existing writer? Is that writer writing to the correct file?
|
//is there an existing writer? Is that writer writing to the correct file?
|
||||||
if (allData==null || !fileName.equals(currentFileName)) {
|
if (allData==null || !fileName.equals(currentFileName)) {
|
||||||
|
|
||||||
@ -259,5 +259,19 @@ public class RExportManager implements PamDataUnitExporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNeedsNewFile() {
|
||||||
|
//Rdata can't be appended to a file so we cannot check file sizes.
|
||||||
|
|
||||||
|
// pamExporterManager.getExportParams().maximumFileSize;
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
//check file size against the export params.
|
||||||
|
System.out.println("RData length: " + allData.length());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import java.awt.Window;
|
|||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import javax.swing.BoxLayout;
|
import javax.swing.BoxLayout;
|
||||||
import javax.swing.ButtonGroup;
|
import javax.swing.ButtonGroup;
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
@ -38,6 +37,8 @@ import export.PamExporterManager;
|
|||||||
import export.layoutFX.ExportParams;
|
import export.layoutFX.ExportParams;
|
||||||
import offlineProcessing.OLProcessDialog;
|
import offlineProcessing.OLProcessDialog;
|
||||||
import offlineProcessing.OfflineTaskGroup;
|
import offlineProcessing.OfflineTaskGroup;
|
||||||
|
import offlineProcessing.TaskMonitor;
|
||||||
|
import offlineProcessing.TaskMonitorData;
|
||||||
import offlineProcessing.TaskStatus;
|
import offlineProcessing.TaskStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,7 +76,6 @@ public class ExportProcessDialog {
|
|||||||
|
|
||||||
|
|
||||||
public void createExportGroup() {
|
public void createExportGroup() {
|
||||||
|
|
||||||
//clear current tasks.
|
//clear current tasks.
|
||||||
dlOfflineGroup.clearTasks();
|
dlOfflineGroup.clearTasks();
|
||||||
|
|
||||||
@ -87,7 +87,6 @@ public class ExportProcessDialog {
|
|||||||
dlOfflineGroup.addTask(new ExportTask(dataBlocks.get(i), exportManager));
|
dlOfflineGroup.addTask(new ExportTask(dataBlocks.get(i), exportManager));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
////---Swing stuff----/// should not be here but this is how PG works.
|
////---Swing stuff----/// should not be here but this is how PG works.
|
||||||
|
|
||||||
@ -129,6 +128,9 @@ public class ExportProcessDialog {
|
|||||||
*/
|
*/
|
||||||
private JFileChooser fc;
|
private JFileChooser fc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* S hows the folder stuff is going to export to.
|
||||||
|
*/
|
||||||
private JTextField exportTo;
|
private JTextField exportTo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -268,7 +270,7 @@ public class ExportProcessDialog {
|
|||||||
|
|
||||||
Ikon icon = null;
|
Ikon icon = null;
|
||||||
/**
|
/**
|
||||||
* This is nasty but we won't have many exporters and this is the only
|
* This is NASTY but we won't have many exporters and this is the only
|
||||||
* good way to get this to work in Swing.
|
* good way to get this to work in Swing.
|
||||||
*/
|
*/
|
||||||
switch (iconString) {
|
switch (iconString) {
|
||||||
@ -352,19 +354,82 @@ public class ExportProcessDialog {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ExportTaskMonitor implements TaskMonitor {
|
||||||
|
|
||||||
|
private int taskIndex;
|
||||||
|
|
||||||
|
private ExportTaskGroup exportTaskGroup;
|
||||||
|
|
||||||
|
private boolean started = false;
|
||||||
|
|
||||||
|
public ExportTaskMonitor(int i, ExportTaskGroup exportTaskGroup) {
|
||||||
|
this.taskIndex = i;
|
||||||
|
this.exportTaskGroup = exportTaskGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTaskStatus(TaskMonitorData taskMonitorData) {
|
||||||
|
if (taskMonitorData.taskStatus== TaskStatus.COMPLETE && !started) {
|
||||||
|
System.out.println(" TASK COMPLETE:");
|
||||||
|
if (taskIndex<exportTaskGroup.getNTasks()) {
|
||||||
|
exportTaskGroup.runTaskFrom(taskIndex+1);
|
||||||
|
started = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export task
|
||||||
|
*/
|
||||||
class ExportTaskGroup extends OfflineTaskGroup {
|
class ExportTaskGroup extends OfflineTaskGroup {
|
||||||
|
|
||||||
|
|
||||||
public ExportTaskGroup(String settingsName) {
|
public ExportTaskGroup(String settingsName) {
|
||||||
super(null, settingsName);
|
super(null, settingsName);
|
||||||
// TODO Auto-generated constructor stub
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUnitType() {
|
public String getUnitType() {
|
||||||
return "Export Data";
|
return "Export Data";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs tasks from a specific task number.
|
||||||
|
* @param i - the index
|
||||||
|
*/
|
||||||
|
public void runTaskFrom(int i) {
|
||||||
|
System.out.println("RUN TASK FROM :" + i);
|
||||||
|
|
||||||
|
this.setPrimaryDataBlock(getTask(i).getDataBlock());
|
||||||
|
if (i<getNTasks()-1) {
|
||||||
|
//will start a new thread after this one has finished
|
||||||
|
this.setTaskMonitor(new ExportTaskMonitor(i, this));
|
||||||
|
}
|
||||||
|
super.runTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override the tasks o it runs through all tasks for each datablock. Usually
|
||||||
|
* task groups deal with just one parent datablock but exporters export from
|
||||||
|
* different data blocks. The only way to deal with this is to let the task run
|
||||||
|
* again and again through all tasks and letting tasks themselves check the
|
||||||
|
* correct data units are being exported.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean runTasks() {
|
||||||
|
runTaskFrom(0) ;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import PamController.PamController;
|
|||||||
import PamguardMVC.PamDataBlock;
|
import PamguardMVC.PamDataBlock;
|
||||||
import PamguardMVC.PamDataUnit;
|
import PamguardMVC.PamDataUnit;
|
||||||
import PamguardMVC.dataSelector.DataSelectDialog;
|
import PamguardMVC.dataSelector.DataSelectDialog;
|
||||||
|
import PamguardMVC.dataSelector.DataSelectParams;
|
||||||
import PamguardMVC.dataSelector.DataSelector;
|
import PamguardMVC.dataSelector.DataSelector;
|
||||||
import dataMap.OfflineDataMapPoint;
|
import dataMap.OfflineDataMapPoint;
|
||||||
import export.PamExporterManager;
|
import export.PamExporterManager;
|
||||||
@ -32,7 +33,7 @@ public class ExportTask extends OfflineTask<PamDataUnit<?,?>>{
|
|||||||
public ExportTask(PamDataBlock<PamDataUnit<?, ?>> parentDataBlock, PamExporterManager exporter) {
|
public ExportTask(PamDataBlock<PamDataUnit<?, ?>> parentDataBlock, PamExporterManager exporter) {
|
||||||
super(parentDataBlock);
|
super(parentDataBlock);
|
||||||
this.exporter = exporter;
|
this.exporter = exporter;
|
||||||
dataSelector=parentDataBlock.getDataSelectCreator().getDataSelector(this.getUnitName() +"_clicks", false, null);
|
dataSelector=parentDataBlock.getDataSelectCreator().getDataSelector(this.getUnitName() +"_export", false, null);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -44,10 +45,21 @@ public class ExportTask extends OfflineTask<PamDataUnit<?,?>>{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean processDataUnit(PamDataUnit<?, ?> dataUnit) {
|
public boolean processDataUnit(PamDataUnit<?, ?> dataUnit) {
|
||||||
if (dataSelector==null) exporter.exportDataUnit(dataUnit, false);
|
|
||||||
else if (dataSelector.scoreData(dataUnit)>0) {
|
// System.out.println("Huh? " + this.getDataBlock().getDataName() + " " + dataUnit + " " + dataUnit.getParentDataBlock().equals(this.getDataBlock()));
|
||||||
|
|
||||||
|
if (dataUnit.getParentDataBlock().equals(this.getDataBlock())) {
|
||||||
|
//this is very important because the way the exporter works is that it iterates through multiple parent data blocks
|
||||||
|
System.out.println(this.getDataBlock().getDataName() + " " + dataUnit + " " + dataSelector.scoreData(dataUnit));
|
||||||
|
if (dataSelector==null) {
|
||||||
|
// System.out.println("Data selector null: " + this.getDataBlock().getDataName() + " " + dataUnit);
|
||||||
exporter.exportDataUnit(dataUnit, false);
|
exporter.exportDataUnit(dataUnit, false);
|
||||||
}
|
}
|
||||||
|
else if (dataSelector.scoreData(dataUnit)>=0 || dataSelector.getParams().getCombinationFlag() == DataSelectParams.DATA_SELECT_DISABLE) {
|
||||||
|
// System.out.println("Data selector OK: " + this.getDataBlock().getDataName() + " " + dataUnit);
|
||||||
|
exporter.exportDataUnit(dataUnit, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
return false; //we don't need to indicate that anything has changed - we are just exporting.
|
return false; //we don't need to indicate that anything has changed - we are just exporting.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,12 +67,12 @@ public class ExportTask extends OfflineTask<PamDataUnit<?,?>>{
|
|||||||
public void newDataLoad(long startTime, long endTime, OfflineDataMapPoint mapPoint) {
|
public void newDataLoad(long startTime, long endTime, OfflineDataMapPoint mapPoint) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
// System.out.println("EXPORTER: new data load");
|
// System.out.println("EXPORTER: new data load");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadedDataComplete() {
|
public void loadedDataComplete() {
|
||||||
System.out.println("EXPORTER: loaded data complete");
|
System.out.println("EXPORTER: loaded data complete");
|
||||||
|
|
||||||
//force the exporter so save any renaming data units in the buffer
|
//force the exporter so save any renaming data units in the buffer
|
||||||
exporter.exportDataUnit(null, true);
|
exporter.exportDataUnit(null, true);
|
||||||
exporter.close();
|
exporter.close();
|
||||||
|
@ -465,6 +465,13 @@ public class WavFileExportManager implements PamDataUnitExporter {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isNeedsNewFile() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// hello(){
|
// hello(){
|
||||||
|
@ -20,6 +20,9 @@ public class SmruDaqJNI {
|
|||||||
|
|
||||||
static public final int SMRU_RET_OK = 0;
|
static public final int SMRU_RET_OK = 0;
|
||||||
|
|
||||||
|
static public final int GREEN_LED = 1;
|
||||||
|
static public final int RED_LED = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Have rebuilt SAIL Daq interface in 2022, but in principle this was
|
* Have rebuilt SAIL Daq interface in 2022, but in principle this was
|
||||||
* just a straight rebuild of the exact same JNI code. the main purpose was to check
|
* just a straight rebuild of the exact same JNI code. the main purpose was to check
|
||||||
@ -29,11 +32,6 @@ public class SmruDaqJNI {
|
|||||||
private static final String SILIB = "SailDaqJNI";
|
private static final String SILIB = "SailDaqJNI";
|
||||||
// private static final String SILIB = "SailDaqV7";
|
// private static final String SILIB = "SailDaqV7";
|
||||||
|
|
||||||
/**
|
|
||||||
* this is the verbose level for the C code part.
|
|
||||||
*/
|
|
||||||
private static final int verboseLevel = 0;
|
|
||||||
|
|
||||||
private static final String DEVNAME = "/dev/cypress_smru0";
|
private static final String DEVNAME = "/dev/cypress_smru0";
|
||||||
|
|
||||||
private static final int MINJNIVERSION = 5;
|
private static final int MINJNIVERSION = 5;
|
||||||
@ -265,7 +263,7 @@ public class SmruDaqJNI {
|
|||||||
this.smruDaqSystem = smruDaqSystem;
|
this.smruDaqSystem = smruDaqSystem;
|
||||||
loadLibrary();
|
loadLibrary();
|
||||||
if (haveLibrary()) {
|
if (haveLibrary()) {
|
||||||
setVerbose(verboseLevel);
|
setVerbose(SmruDaqSystem.VERBOSELEVEL);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List the devices, but don't do any resetting and
|
* List the devices, but don't do any resetting and
|
||||||
@ -492,7 +490,7 @@ public class SmruDaqJNI {
|
|||||||
public int toggleLED(int board, int led) {
|
public int toggleLED(int board, int led) {
|
||||||
board = boardOrder[board];
|
board = boardOrder[board];
|
||||||
int state = getLED(board, led);
|
int state = getLED(board, led);
|
||||||
System.out.println("state="+state);
|
// System.out.println("LED state="+state);
|
||||||
if (state == 0) {
|
if (state == 0) {
|
||||||
state = 1;
|
state = 1;
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
@ -13,6 +14,7 @@ import soundPlayback.PlaybackControl;
|
|||||||
import soundPlayback.PlaybackSystem;
|
import soundPlayback.PlaybackSystem;
|
||||||
import Acquisition.AcquisitionControl;
|
import Acquisition.AcquisitionControl;
|
||||||
import Acquisition.AcquisitionDialog;
|
import Acquisition.AcquisitionDialog;
|
||||||
|
import Acquisition.AcquisitionProcess;
|
||||||
import Acquisition.DaqSystem;
|
import Acquisition.DaqSystem;
|
||||||
import Acquisition.AudioDataQueue;
|
import Acquisition.AudioDataQueue;
|
||||||
import PamController.PamControlledUnitSettings;
|
import PamController.PamControlledUnitSettings;
|
||||||
@ -49,7 +51,8 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
|||||||
|
|
||||||
public static final String oldCardName = "SMRU Ltd DAQ Card";
|
public static final String oldCardName = "SMRU Ltd DAQ Card";
|
||||||
|
|
||||||
private static final int VERBOSELEVEL = 0;
|
public static final int VERBOSELEVEL = 0;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param daqControl
|
* @param daqControl
|
||||||
@ -61,6 +64,11 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
|||||||
smruDaqJNI = new SmruDaqJNI(this);
|
smruDaqJNI = new SmruDaqJNI(this);
|
||||||
|
|
||||||
nDaqCards = smruDaqJNI.getnDevices();
|
nDaqCards = smruDaqJNI.getnDevices();
|
||||||
|
for (int i = 0; i < nDaqCards; i++) {
|
||||||
|
for (int l = 0; l < 2; l++) {
|
||||||
|
smruDaqJNI.setLED(i, l, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
smruDaqDialogPanel = new SmruDaqDialogPanel(this);
|
smruDaqDialogPanel = new SmruDaqDialogPanel(this);
|
||||||
PamSettingManager.getInstance().registerSettings(this);
|
PamSettingManager.getInstance().registerSettings(this);
|
||||||
@ -275,6 +283,8 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
|||||||
boolean prepareDaqCard(int iBoard, boolean fullReset) {
|
boolean prepareDaqCard(int iBoard, boolean fullReset) {
|
||||||
// devices are left closed, so will need to reopen them.
|
// devices are left closed, so will need to reopen them.
|
||||||
// of course, there is a vile lookup table, so...
|
// of course, there is a vile lookup table, so...
|
||||||
|
smruDaqJNI.setLED(iBoard, SmruDaqJNI.GREEN_LED, 0);
|
||||||
|
smruDaqJNI.setLED(iBoard, SmruDaqJNI.RED_LED, 0);
|
||||||
int hardId = smruDaqJNI.getBoardOrder(iBoard);
|
int hardId = smruDaqJNI.getBoardOrder(iBoard);
|
||||||
int prepOk = smruDaqJNI.prepareDevice(hardId, fullReset);
|
int prepOk = smruDaqJNI.prepareDevice(hardId, fullReset);
|
||||||
terminalPrint("Opened daq card returned " + prepOk, 1);
|
terminalPrint("Opened daq card returned " + prepOk, 1);
|
||||||
@ -313,6 +323,7 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
|||||||
|
|
||||||
if (ans) {
|
if (ans) {
|
||||||
Thread t = new Thread(new DaqThread());
|
Thread t = new Thread(new DaqThread());
|
||||||
|
t.setPriority(Thread.MAX_PRIORITY);
|
||||||
t.start();
|
t.start();
|
||||||
keepRunning = true;
|
keepRunning = true;
|
||||||
daqThreadRunning = true;
|
daqThreadRunning = true;
|
||||||
@ -371,18 +382,43 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
|||||||
boolean first = true;
|
boolean first = true;
|
||||||
boolean needRestart = false;
|
boolean needRestart = false;
|
||||||
int iChan;
|
int iChan;
|
||||||
|
// some flags on checks of incoming data rate
|
||||||
|
// long recentSamples = 0;
|
||||||
|
// long recentCheckTime = System.currentTimeMillis();
|
||||||
|
int loopCount = 0;
|
||||||
|
for (int iBoard = 0; iBoard < nDaqCards; iBoard++) {
|
||||||
|
smruDaqJNI.setLED(iBoard, SmruDaqJNI.GREEN_LED, 1);
|
||||||
|
smruDaqJNI.setLED(iBoard, SmruDaqJNI.RED_LED, 0);
|
||||||
|
}
|
||||||
|
|
||||||
while (keepRunning) {
|
while (keepRunning) {
|
||||||
iChan = 0;
|
iChan = 0;
|
||||||
dataMillis = daqControl.getAcquisitionProcess().absSamplesToMilliseconds(totalSamples);
|
dataMillis = daqControl.getAcquisitionProcess().absSamplesToMilliseconds(totalSamples);
|
||||||
|
if (isStalled()) {
|
||||||
|
needRestart = true;
|
||||||
|
for (int iBoard = 0; iBoard < nDaqCards; iBoard++) {
|
||||||
|
smruDaqJNI.setLED(iBoard, SmruDaqJNI.GREEN_LED, 0);
|
||||||
|
smruDaqJNI.setLED(iBoard, SmruDaqJNI.RED_LED, 1);
|
||||||
|
}
|
||||||
|
// don't set this false or the shutdown doesn't work properly.
|
||||||
|
// keepRunning = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
loopCount++;
|
||||||
for (int iBoard = 0; iBoard < nDaqCards && keepRunning; iBoard++) {
|
for (int iBoard = 0; iBoard < nDaqCards && keepRunning; iBoard++) {
|
||||||
|
if ((loopCount % 10000) == 0) {
|
||||||
|
// toggleLED(iBoard, 0);
|
||||||
|
smruDaqJNI.setLED(iBoard, SmruDaqJNI.GREEN_LED, 1);
|
||||||
|
}
|
||||||
for (int i = 0; i < boardChannels[iBoard] && keepRunning; i++) {
|
for (int i = 0; i < boardChannels[iBoard] && keepRunning; i++) {
|
||||||
newData = smruDaqJNI.readSamples(iBoard, i, wantedSamples);
|
newData = smruDaqJNI.readSamples(iBoard, i, wantedSamples);
|
||||||
if (newData == null) {
|
if (newData == null) {
|
||||||
|
smruDaqJNI.setLED(iBoard, SmruDaqJNI.RED_LED, 1);
|
||||||
System.out.println(String.format("Null data read from smruDaqJNI.readSamples board %d, chan %d, samples %d",
|
System.out.println(String.format("Null data read from smruDaqJNI.readSamples board %d, chan %d, samples %d",
|
||||||
iBoard, i, wantedSamples));
|
iBoard, i, wantedSamples));
|
||||||
// System.out.println("Issue restart ...");
|
// System.out.println("Issue restart ...");
|
||||||
needRestart = true;
|
needRestart = true;
|
||||||
keepRunning = false;
|
// keepRunning = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
readSamples = newData.length;
|
readSamples = newData.length;
|
||||||
@ -411,17 +447,45 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
totalSamples += readSamples;
|
totalSamples += readSamples;
|
||||||
|
|
||||||
}
|
};
|
||||||
daqThreadRunning = false;
|
daqThreadRunning = false;
|
||||||
|
|
||||||
|
for (int iBoard = 0; iBoard < nDaqCards; iBoard++) {
|
||||||
|
smruDaqJNI.setLED(iBoard, SmruDaqJNI.GREEN_LED, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (needRestart) {
|
if (needRestart) {
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
PamController pamController = PamController.getInstance();
|
PamController pamController = PamController.getInstance();
|
||||||
pamController.pamStop();
|
pamController.pamStop();
|
||||||
PamDialog.showWarning(daqControl.getGuiFrame(), daqControl.getUnitName(), "Problem with one or more SAIL DAQ Cards.\n"
|
System.out.println("Problem with one or more SAIL DAQ Cards. "
|
||||||
+ "Restart PAMGuard, check connections and try again." );
|
+ "Restart PAMGuard, check connections and try again." );
|
||||||
// pamController.startLater();
|
// PamDialog.showWarning(daqControl.getGuiFrame(), daqControl.getUnitName(), "Problem with one or more SAIL DAQ Cards.\n"
|
||||||
|
// + "Restart PAMGuard, check connections and try again." );
|
||||||
|
pamController.startLater();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// private long lastFakeStall = 0;
|
||||||
|
private boolean isStalled() {
|
||||||
|
// if (lastFakeStall == 0) {
|
||||||
|
// lastFakeStall = System.currentTimeMillis();
|
||||||
|
// }
|
||||||
|
// long now = System.currentTimeMillis();
|
||||||
|
// if (now-lastFakeStall > 10000) {
|
||||||
|
// System.out.println("Random pretend stalled");
|
||||||
|
// lastFakeStall = 0;
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
return daqControl.getAcquisitionProcess().isStalled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static short getSample(byte[] buffer, int position) {
|
public static short getSample(byte[] buffer, int position) {
|
||||||
|
@ -236,9 +236,9 @@ public class NoiseBandControl extends PamControlledUnit implements PamSettings {
|
|||||||
@Override
|
@Override
|
||||||
public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
|
public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
|
||||||
noiseBandSettings = ((NoiseBandSettings)pamControlledUnitSettings.getSettings()).clone();
|
noiseBandSettings = ((NoiseBandSettings)pamControlledUnitSettings.getSettings()).clone();
|
||||||
System.out.println("********************************************************");
|
// System.out.println("********************************************************");
|
||||||
System.out.println("NOISE BAND SETTINGS: " + noiseBandSettings.rawDataSource);
|
// System.out.println("NOISE BAND SETTINGS: " + noiseBandSettings.rawDataSource);
|
||||||
System.out.println("********************************************************");
|
// System.out.println("********************************************************");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ public class OfflineTaskGroup implements PamSettings {
|
|||||||
|
|
||||||
private ArrayList<OfflineTask> offlineTasks = new ArrayList<OfflineTask>();
|
private ArrayList<OfflineTask> offlineTasks = new ArrayList<OfflineTask>();
|
||||||
|
|
||||||
private TaskGroupWorker worker;
|
protected TaskGroupWorker worker;
|
||||||
|
|
||||||
private OfflineSuperDetFilter superDetectionFilter;
|
private OfflineSuperDetFilter superDetectionFilter;
|
||||||
|
|
||||||
@ -377,7 +377,7 @@ public class OfflineTaskGroup implements PamSettings {
|
|||||||
* @author Doug Gillespie
|
* @author Doug Gillespie
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class TaskGroupWorker extends SwingWorker<Integer, TaskMonitorData> implements ViewLoadObserver {
|
public class TaskGroupWorker extends SwingWorker<Integer, TaskMonitorData> implements ViewLoadObserver {
|
||||||
|
|
||||||
volatile boolean instantKill = false;
|
volatile boolean instantKill = false;
|
||||||
|
|
||||||
@ -437,6 +437,7 @@ public class OfflineTaskGroup implements PamSettings {
|
|||||||
/**
|
/**
|
||||||
* Process all data for a list of time chunks. This is robust to the list
|
* Process all data for a list of time chunks. This is robust to the list
|
||||||
* not being in chronological order.
|
* not being in chronological order.
|
||||||
|
*
|
||||||
* @param timeChunks - the time chunks.
|
* @param timeChunks - the time chunks.
|
||||||
*/
|
*/
|
||||||
private void processAllData(ArrayList<long[]> timeChunks){
|
private void processAllData(ArrayList<long[]> timeChunks){
|
||||||
@ -976,4 +977,6 @@ public class OfflineTaskGroup implements PamSettings {
|
|||||||
offlineTasks.clear();
|
offlineTasks.clear();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ import dataModelFX.DataModelPaneFX;
|
|||||||
import org.controlsfx.control.ToggleSwitch;
|
import org.controlsfx.control.ToggleSwitch;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A pane which holds a set of tabs.
|
* A pane which holds a set of tabs.
|
||||||
*
|
*
|
||||||
@ -125,7 +126,7 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
|
|||||||
this.pamGuiManagerFX=pamGuiManagerFX;
|
this.pamGuiManagerFX=pamGuiManagerFX;
|
||||||
this.mainTabPane = mainTabPane;
|
this.mainTabPane = mainTabPane;
|
||||||
|
|
||||||
Pane layout=createMainPane(mainTabPane, stage);
|
Node layout=createMainPane(mainTabPane, stage);
|
||||||
|
|
||||||
//add main pane to PamGui
|
//add main pane to PamGui
|
||||||
this.getChildren().add(layout);
|
this.getChildren().add(layout);
|
||||||
@ -140,7 +141,7 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
|
|||||||
//create the main tab pane.
|
//create the main tab pane.
|
||||||
this.mainTabPane = new PamTabPane();
|
this.mainTabPane = new PamTabPane();
|
||||||
|
|
||||||
Pane layout=createMainPane(mainTabPane, stage);
|
Node layout=createMainPane(mainTabPane, stage);
|
||||||
|
|
||||||
//add main pane to PamGui
|
//add main pane to PamGui
|
||||||
this.getChildren().add(layout);
|
this.getChildren().add(layout);
|
||||||
@ -154,7 +155,7 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
|
|||||||
* @param stage - the stage holding this GUI.
|
* @param stage - the stage holding this GUI.
|
||||||
* @return a pane which sits in the stage.
|
* @return a pane which sits in the stage.
|
||||||
*/
|
*/
|
||||||
private Pane createMainPane(PamTabPane mainTabPane, Stage stage){
|
private Node createMainPane(PamTabPane mainTabPane, Stage stage){
|
||||||
|
|
||||||
//create the pane which holds tab pane
|
//create the pane which holds tab pane
|
||||||
final PamBorderPane layout = new PamBorderPane();
|
final PamBorderPane layout = new PamBorderPane();
|
||||||
@ -262,7 +263,6 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
|
|||||||
PamBorderPane layoutHolder=new PamBorderPane(layout);
|
PamBorderPane layoutHolder=new PamBorderPane(layout);
|
||||||
layoutHolder.setTop(hidingLoadPane);
|
layoutHolder.setTop(hidingLoadPane);
|
||||||
|
|
||||||
|
|
||||||
return layoutHolder;
|
return layoutHolder;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -254,6 +254,10 @@ public class PamGuiTabFX extends PamTabFX {
|
|||||||
|
|
||||||
int smallWindows = 0;
|
int smallWindows = 0;
|
||||||
|
|
||||||
|
|
||||||
|
//the padding between windows
|
||||||
|
double padding = 10;
|
||||||
|
|
||||||
ArrayList<PamGuiInternalPane> dw = internalPanes;
|
ArrayList<PamGuiInternalPane> dw = internalPanes;
|
||||||
|
|
||||||
if (dw.size() == 0) return;
|
if (dw.size() == 0) return;
|
||||||
@ -268,7 +272,9 @@ public class PamGuiTabFX extends PamTabFX {
|
|||||||
|
|
||||||
//now place windows in correct position
|
//now place windows in correct position
|
||||||
//large windows
|
//large windows
|
||||||
double x, y, w, h = 0;
|
double x, y, w, h = 0.;
|
||||||
|
double pad =0.;
|
||||||
|
|
||||||
if (largeWindows > 0) {
|
if (largeWindows > 0) {
|
||||||
x = 0;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
@ -284,7 +290,10 @@ public class PamGuiTabFX extends PamTabFX {
|
|||||||
if (dw.get(i).getUserDisplayNode().isMinorDisplay()== true) continue;
|
if (dw.get(i).getUserDisplayNode().isMinorDisplay()== true) continue;
|
||||||
|
|
||||||
dw.get(i).setPaneLayout(x, y);
|
dw.get(i).setPaneLayout(x, y);
|
||||||
dw.get(i).setPaneSize(w, h);
|
|
||||||
|
//set the padding if the pane is not the last pane.
|
||||||
|
pad = (i== dw.size()-1) ? 0 : padding;
|
||||||
|
dw.get(i).setPaneSize(w - (horz? pad:0), h - (horz? 0:pad));
|
||||||
if (horz) x += w;
|
if (horz) x += w;
|
||||||
else y += h;
|
else y += h;
|
||||||
}
|
}
|
||||||
@ -307,7 +316,10 @@ public class PamGuiTabFX extends PamTabFX {
|
|||||||
for (int i = 0; i < dw.size(); i++) {
|
for (int i = 0; i < dw.size(); i++) {
|
||||||
if (dw.get(i).getUserDisplayNode().isMinorDisplay() == false) continue;
|
if (dw.get(i).getUserDisplayNode().isMinorDisplay() == false) continue;
|
||||||
dw.get(i).setPaneLayout(x, y);
|
dw.get(i).setPaneLayout(x, y);
|
||||||
dw.get(i).setPaneSize(w, h);
|
|
||||||
|
//set the padding if the pane is not the last pane.
|
||||||
|
pad = (i== dw.size()-1) ? 0 : padding;
|
||||||
|
dw.get(i).setPaneSize(w- (horz? pad:0), h - (horz? 0:pad));
|
||||||
if (horz) x += w;
|
if (horz) x += w;
|
||||||
else y +=h;
|
else y +=h;
|
||||||
}
|
}
|
||||||
|
@ -128,7 +128,7 @@ public class PamFlipPane extends FlipPane {
|
|||||||
* Convenience duplicate of getBackPane().
|
* Convenience duplicate of getBackPane().
|
||||||
* @return the back pane.
|
* @return the back pane.
|
||||||
*/
|
*/
|
||||||
public PamBorderPane getAdvPane() {
|
public PamBorderPane getAdvContentPane() {
|
||||||
return advPane;
|
return advPane;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,6 @@ import javafx.beans.property.DoubleProperty;
|
|||||||
import javafx.beans.property.SimpleBooleanProperty;
|
import javafx.beans.property.SimpleBooleanProperty;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.event.EventHandler;
|
import javafx.event.EventHandler;
|
||||||
import javafx.geometry.Insets;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hiding pane which can be added to any node.
|
* Hiding pane which can be added to any node.
|
||||||
@ -156,7 +155,7 @@ public class HidingPane extends StackPane {
|
|||||||
//create a button which hides the side panel
|
//create a button which hides the side panel
|
||||||
hideButton=createShowButton(false);
|
hideButton=createShowButton(false);
|
||||||
styleHideButton(hideButton);
|
styleHideButton(hideButton);
|
||||||
hideButton.setOnAction(new HideButtonPressed());
|
// hideButton.setOnAction(new HideButtonPressed());
|
||||||
hideButton.setVisible(false);
|
hideButton.setVisible(false);
|
||||||
// hideButton.setStyle("close-button-right");
|
// hideButton.setStyle("close-button-right");
|
||||||
|
|
||||||
@ -333,8 +332,6 @@ public class HidingPane extends StackPane {
|
|||||||
double dragX=0;
|
double dragX=0;
|
||||||
double dragY=0;
|
double dragY=0;
|
||||||
double distance=0;
|
double distance=0;
|
||||||
|
|
||||||
|
|
||||||
private PamButton createShowButton(final boolean show){
|
private PamButton createShowButton(final boolean show){
|
||||||
|
|
||||||
final PamButton pamButton=new PamButton();
|
final PamButton pamButton=new PamButton();
|
||||||
@ -343,6 +340,7 @@ public class HidingPane extends StackPane {
|
|||||||
|
|
||||||
@Override public void handle(MouseEvent mouseEvent) {
|
@Override public void handle(MouseEvent mouseEvent) {
|
||||||
// record a delta distance for the drag and drop operation.
|
// record a delta distance for the drag and drop operation.
|
||||||
|
// System.out.println("HidingPane.showButton - setOnMousePressed");
|
||||||
dragX =mouseEvent.getSceneX();
|
dragX =mouseEvent.getSceneX();
|
||||||
dragY =mouseEvent.getSceneY();
|
dragY =mouseEvent.getSceneY();
|
||||||
}
|
}
|
||||||
@ -350,10 +348,24 @@ public class HidingPane extends StackPane {
|
|||||||
|
|
||||||
pamButton.setOnMouseReleased(new EventHandler<MouseEvent>() {
|
pamButton.setOnMouseReleased(new EventHandler<MouseEvent>() {
|
||||||
@Override public void handle(MouseEvent mouseEvent) {
|
@Override public void handle(MouseEvent mouseEvent) {
|
||||||
if (distance==0) return;
|
// System.out.println("HidingPane.showButton - setOnMouseReleased");
|
||||||
|
|
||||||
|
//the mouse has been pressed
|
||||||
|
if (distance==0) {
|
||||||
|
if (isShowing()) {
|
||||||
|
showHidePane(false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
showHidePane(true);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//the mouse has been dragged dragged
|
||||||
distance=sideIndex*distance;
|
distance=sideIndex*distance;
|
||||||
// System.out.println("Mouse released: HidePanel distance: "+distance);
|
// System.out.println("Mouse released: HidePanel distance: "+distance);
|
||||||
if (!overlay) distance=Math.abs(distance);
|
if (!overlay) distance=Math.abs(distance);
|
||||||
|
|
||||||
//need to see where the drag has ended-if greater than 50% then open but if less then close.
|
//need to see where the drag has ended-if greater than 50% then open but if less then close.
|
||||||
if (!isHorizontal()){
|
if (!isHorizontal()){
|
||||||
if (distance<expandedSize/2) showHidePane(overlay? true : false);
|
if (distance<expandedSize/2) showHidePane(overlay? true : false);
|
||||||
@ -363,6 +375,7 @@ public class HidingPane extends StackPane {
|
|||||||
if (distance<expandedSize/2) showHidePane(overlay? true : false);
|
if (distance<expandedSize/2) showHidePane(overlay? true : false);
|
||||||
if (distance>=expandedSize/2) showHidePane(overlay? false : true);
|
if (distance>=expandedSize/2) showHidePane(overlay? false : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//reset the distance
|
//reset the distance
|
||||||
distance=0;
|
distance=0;
|
||||||
}
|
}
|
||||||
@ -370,12 +383,14 @@ public class HidingPane extends StackPane {
|
|||||||
|
|
||||||
pamButton.setOnMouseDragged(new EventHandler<MouseEvent>() {
|
pamButton.setOnMouseDragged(new EventHandler<MouseEvent>() {
|
||||||
@Override public void handle(MouseEvent mouseEvent) {
|
@Override public void handle(MouseEvent mouseEvent) {
|
||||||
|
// System.out.println("HidingPane.showButton - setOnMouseDragged");
|
||||||
if (visibleImmediatly) hidePane.setVisible(true);
|
if (visibleImmediatly) hidePane.setVisible(true);
|
||||||
else hidePane.setVisible(false);
|
else hidePane.setVisible(false);
|
||||||
// hideButton.setVisible(true);
|
// hideButton.setVisible(true);
|
||||||
/**
|
/**
|
||||||
* Work out the distance the panel is to be dragged;
|
* Work out the distance the panel is to be dragged;
|
||||||
*/
|
*/
|
||||||
|
double distance = 0;
|
||||||
if (!isHorizontal()){
|
if (!isHorizontal()){
|
||||||
if (!show) distance=(mouseEvent.getSceneX()-dragX);
|
if (!show) distance=(mouseEvent.getSceneX()-dragX);
|
||||||
else distance=(mouseEvent.getSceneX()-dragX)+sideIndex*expandedSize;
|
else distance=(mouseEvent.getSceneX()-dragX)+sideIndex*expandedSize;
|
||||||
@ -389,24 +404,26 @@ public class HidingPane extends StackPane {
|
|||||||
// if (show && Math.abs(distance)>expandedSize) return;
|
// if (show && Math.abs(distance)>expandedSize) return;
|
||||||
|
|
||||||
translatePanel(distance);
|
translatePanel(distance);
|
||||||
|
|
||||||
|
HidingPane.this.distance = distance ;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
pamButton.setOnMouseEntered(new EventHandler<MouseEvent>() {
|
// pamButton.setOnMouseEntered(new EventHandler<MouseEvent>() {
|
||||||
@Override public void handle(MouseEvent mouseEvent) {
|
// @Override public void handle(MouseEvent mouseEvent) {
|
||||||
// System.out.println("HidingPane.showButton - mouse entered");
|
//// System.out.println("HidingPane.showButton - mouse entered");
|
||||||
pamButton.setOpacity(1.0);
|
// pamButton.setOpacity(1.0);
|
||||||
pamButton.setPadding(new Insets(2.,2.,2.,2.));
|
// pamButton.setPadding(new Insets(2.,2.,2.,2.));
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
pamButton.setOnMouseExited(new EventHandler<MouseEvent>() {
|
// pamButton.setOnMouseExited(new EventHandler<MouseEvent>() {
|
||||||
@Override public void handle(MouseEvent mouseEvent) {
|
// @Override public void handle(MouseEvent mouseEvent) {
|
||||||
// System.out.println("HidingPane.showButton - mouse exited");
|
//// System.out.println("HidingPane.showButton - mouse exited");
|
||||||
if (show) pamButton.setOpacity(showButtonOpacity);
|
// if (show) pamButton.setOpacity(showButtonOpacity);
|
||||||
pamButton.setPadding(new Insets(0.,0.,0.,0.));
|
// pamButton.setPadding(new Insets(0.,0.,0.,0.));
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
// pamButton.setOnMouseClicked(new EventHandler<MouseEvent>() {
|
// pamButton.setOnMouseClicked(new EventHandler<MouseEvent>() {
|
||||||
// @Override public void handle(MouseEvent mouseEvent) {
|
// @Override public void handle(MouseEvent mouseEvent) {
|
||||||
@ -415,15 +432,15 @@ public class HidingPane extends StackPane {
|
|||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
|
|
||||||
pamButton.addEventHandler(ActionEvent.ACTION,new EventHandler<ActionEvent>() {
|
// pamButton.addEventHandler(ActionEvent.ACTION,new EventHandler<ActionEvent>() {
|
||||||
@Override
|
// @Override
|
||||||
public void handle(ActionEvent e) {
|
// public void handle(ActionEvent e) {
|
||||||
System.out.println("HidingPane.showButton - action event clicked");
|
// System.out.println("HidingPane.showButton - action event clicked");
|
||||||
showHidePane(show);
|
// showHidePane(show);
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
if (show) pamButton.setOpacity(showButtonOpacity);
|
// if (show) pamButton.setOpacity(showButtonOpacity);
|
||||||
|
|
||||||
return pamButton;
|
return pamButton;
|
||||||
}
|
}
|
||||||
@ -638,17 +655,17 @@ public class HidingPane extends StackPane {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Called whenever the pin button is pressed.
|
// * Called whenever the pin button is pressed.
|
||||||
* @author Jamie Macaulay
|
// * @author Jamie Macaulay
|
||||||
*/
|
// */
|
||||||
class HideButtonPressed implements EventHandler<ActionEvent>{
|
// class HideButtonPressed implements EventHandler<ActionEvent>{
|
||||||
|
//
|
||||||
@Override
|
// @Override
|
||||||
public void handle(ActionEvent arg0) {
|
// public void handle(ActionEvent arg0) {
|
||||||
showHidePane(false);
|
// showHidePane(false);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the button which hides the pane.
|
* Get the button which hides the pane.
|
||||||
@ -732,6 +749,15 @@ public class HidingPane extends StackPane {
|
|||||||
return this.showing;
|
return this.showing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the hiding pane is showing.
|
||||||
|
* @return true if showing.
|
||||||
|
*/
|
||||||
|
public boolean isShowing(){
|
||||||
|
return this.showing.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the opacity of the show button when the mouse is outside the button.
|
* Get the opacity of the show button when the mouse is outside the button.
|
||||||
* @return the opacity of the show button.
|
* @return the opacity of the show button.
|
||||||
|
@ -244,7 +244,6 @@ public class ColourArray implements Cloneable, Serializable{
|
|||||||
colors[4]=Color.web("#0000ff");
|
colors[4]=Color.web("#0000ff");
|
||||||
colors[5]=Color.web("#ff00ff");
|
colors[5]=Color.web("#ff00ff");
|
||||||
colors[6]=Color.web("#ff0000");
|
colors[6]=Color.web("#ff0000");
|
||||||
|
|
||||||
return colors;
|
return colors;
|
||||||
case PATRIOTIC:
|
case PATRIOTIC:
|
||||||
colors=new Color[3];
|
colors=new Color[3];
|
||||||
|
@ -16,9 +16,9 @@ import javax.swing.JMenuItem;
|
|||||||
import javax.swing.JPopupMenu;
|
import javax.swing.JPopupMenu;
|
||||||
import javax.swing.JPopupMenu.Separator;
|
import javax.swing.JPopupMenu.Separator;
|
||||||
import javax.swing.JRadioButtonMenuItem;
|
import javax.swing.JRadioButtonMenuItem;
|
||||||
import javax.swing.JSeparator;
|
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
|
|
||||||
|
import PamView.ColourArray.ColourArrayType;
|
||||||
import PamView.PamSymbol;
|
import PamView.PamSymbol;
|
||||||
import javafx.animation.KeyFrame;
|
import javafx.animation.KeyFrame;
|
||||||
import javafx.animation.KeyValue;
|
import javafx.animation.KeyValue;
|
||||||
@ -54,6 +54,26 @@ import pamViewFX.fxNodes.PamSymbolFX;
|
|||||||
*/
|
*/
|
||||||
public class PamUtilsFX {
|
public class PamUtilsFX {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an FX based ColourArrayType to Swing. Note that swing options that do not exist in FX and vice versa will return null.
|
||||||
|
* @param arrayFX - the FX ColourArrayType.
|
||||||
|
* @return the Swing ColourArrayType;
|
||||||
|
*/
|
||||||
|
public static ColourArrayType fxColArray2Swing(pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType arrayFX) {
|
||||||
|
ColourArrayType type = ColourArrayType.valueOf(arrayFX.toString());
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an Swing based ColourArrayType to FX. Note that swing options that do not exist in FX and vice versa will return null.
|
||||||
|
* @param arraySwing - the Swing ColourArrayType.
|
||||||
|
* @return the FX ColourArrayType.
|
||||||
|
*/
|
||||||
|
public static pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType swingColArray2FX(ColourArrayType arraySwing) {
|
||||||
|
pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType type = pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType.valueOf(arraySwing.toString());
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param awtColor
|
* @param awtColor
|
||||||
@ -632,8 +652,7 @@ public class PamUtilsFX {
|
|||||||
* @param color - the color.
|
* @param color - the color.
|
||||||
* @return the color.
|
* @return the color.
|
||||||
*/
|
*/
|
||||||
public static String toRGBCode( Color color )
|
public static String toRGBCode( Color color ){
|
||||||
{
|
|
||||||
return String.format( "#%02X%02X%02X",
|
return String.format( "#%02X%02X%02X",
|
||||||
(int)( color.getRed() * 255 ),
|
(int)( color.getRed() * 255 ),
|
||||||
(int)( color.getGreen() * 255 ),
|
(int)( color.getGreen() * 255 ),
|
||||||
@ -641,4 +660,28 @@ public class PamUtilsFX {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a colour to an int.
|
||||||
|
* @param c - the colour to change.
|
||||||
|
* @return the int representation of the colour
|
||||||
|
*/
|
||||||
|
public static int colorToInt(Color c) {
|
||||||
|
int r = (int) Math.round(c.getRed() * 255);
|
||||||
|
int g = (int) Math.round(c.getGreen() * 255);
|
||||||
|
int b = (int) Math.round(c.getBlue() * 255);
|
||||||
|
return (r << 16) | (g << 8) | b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an int encoded with a colour to a Color object.
|
||||||
|
* @param value - the int to convert to colour
|
||||||
|
* @return the Color object for the int
|
||||||
|
*/
|
||||||
|
public static Color intToColor(int value) {
|
||||||
|
int r = (value >>> 16) & 0xFF;
|
||||||
|
int g = (value >>> 8) & 0xFF;
|
||||||
|
int b = value & 0xFF;
|
||||||
|
return Color.rgb(r,g,b);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package pamViewFX.fxPlotPanes;
|
package pamViewFX.fxPlotPanes;
|
||||||
|
|
||||||
import Layout.PamAxis;
|
import Layout.PamAxis;
|
||||||
|
import javafx.beans.binding.Bindings;
|
||||||
|
import javafx.beans.property.SimpleDoubleProperty;
|
||||||
|
import javafx.beans.value.ObservableValue;
|
||||||
import javafx.geometry.Side;
|
import javafx.geometry.Side;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Node;
|
||||||
import javafx.scene.canvas.Canvas;
|
import javafx.scene.canvas.Canvas;
|
||||||
@ -256,13 +259,31 @@ public class PlotPane extends PamBorderPane {
|
|||||||
PamHBox horzHolder=new PamHBox();
|
PamHBox horzHolder=new PamHBox();
|
||||||
|
|
||||||
Pane leftPane=new Pane();
|
Pane leftPane=new Pane();
|
||||||
|
|
||||||
|
//create an observable which is the size of the axis pane if the pane is visible and otherwise
|
||||||
|
//is zero.
|
||||||
|
ObservableValue<Number> valLeft = Bindings
|
||||||
|
.when(yAxisLeftPane.visibleProperty())
|
||||||
|
.then(yAxisLeftPane.widthProperty())
|
||||||
|
.otherwise(
|
||||||
|
new SimpleDoubleProperty(0.)
|
||||||
|
);
|
||||||
|
|
||||||
//need both min and pref to make binding work properly;
|
//need both min and pref to make binding work properly;
|
||||||
leftPane.prefWidthProperty().bind(yAxisLeftPane.widthProperty());
|
leftPane.prefWidthProperty().bind(valLeft);
|
||||||
leftPane.minWidthProperty().bind(yAxisLeftPane.widthProperty());
|
leftPane.minWidthProperty().bind(valLeft);
|
||||||
|
|
||||||
Pane rightPane=new Pane();
|
Pane rightPane=new Pane();
|
||||||
rightPane.prefWidthProperty().bind(yAxisRightPane.widthProperty());
|
|
||||||
rightPane.minWidthProperty().bind(yAxisRightPane.widthProperty());
|
ObservableValue<Number> valRight = Bindings
|
||||||
|
.when(yAxisRightPane.visibleProperty())
|
||||||
|
.then(yAxisRightPane.widthProperty())
|
||||||
|
.otherwise(
|
||||||
|
new SimpleDoubleProperty(0.)
|
||||||
|
);
|
||||||
|
|
||||||
|
rightPane.prefWidthProperty().bind(valRight);
|
||||||
|
rightPane.minWidthProperty().bind(valRight);
|
||||||
|
|
||||||
horzHolder.getChildren().addAll(leftPane, axisPane, rightPane);
|
horzHolder.getChildren().addAll(leftPane, axisPane, rightPane);
|
||||||
//axisPane.toFront(); this changes the order of children in a PamHBox.
|
//axisPane.toFront(); this changes the order of children in a PamHBox.
|
||||||
@ -369,8 +390,8 @@ public class PlotPane extends PamBorderPane {
|
|||||||
|
|
||||||
//holderPane.getChildren().clear();
|
//holderPane.getChildren().clear();
|
||||||
|
|
||||||
//HACK- 05/08/2016 have to do this because there is a bug in switching children postions in a border pane.
|
//HACK- 05/08/2016 have to do this because there is a bug in switching children positions in a border pane.
|
||||||
//casues a duplicate childrne error.
|
//causes duplicate children error
|
||||||
holderPane.setRight(null);
|
holderPane.setRight(null);
|
||||||
holderPane.setLeft(null);
|
holderPane.setLeft(null);
|
||||||
holderPane.setTop(null);
|
holderPane.setTop(null);
|
||||||
@ -385,24 +406,30 @@ public class PlotPane extends PamBorderPane {
|
|||||||
else if (topBorder > 0) {
|
else if (topBorder > 0) {
|
||||||
// holderPane.setTopSpace(topBorder);
|
// holderPane.setTopSpace(topBorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bottom) {
|
if (bottom) {
|
||||||
holderPane.setBottom(bottomHolder);
|
holderPane.setBottom(bottomHolder);
|
||||||
}
|
}
|
||||||
else if (bottomBorder > 0) {
|
else if (bottomBorder > 0) {
|
||||||
// holderPane.setBottomSpace(bottomBorder);
|
// holderPane.setBottomSpace(bottomBorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (right) {
|
if (right) {
|
||||||
holderPane.setRight(yAxisRightPane) ;
|
holderPane.setRight(yAxisRightPane) ;
|
||||||
|
yAxisRightPane.setVisible(true);
|
||||||
}
|
}
|
||||||
else if (rightBorder > 0){
|
else {
|
||||||
// holderPane.setRightSpace(rightBorder);
|
yAxisRightPane.setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left) {
|
if (left) {
|
||||||
holderPane.setLeft(yAxisLeftPane) ;
|
holderPane.setLeft(yAxisLeftPane) ;
|
||||||
|
yAxisLeftPane.setVisible(true);
|
||||||
}
|
}
|
||||||
else if (leftBorder > 0) {
|
else {
|
||||||
// holderPane.setLeftSpace(leftBorder);
|
yAxisLeftPane.setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
holderPane.setCenter(canvasHolder);
|
holderPane.setCenter(canvasHolder);
|
||||||
//bottomHolder.toBack();
|
//bottomHolder.toBack();
|
||||||
|
|
||||||
|
@ -180,6 +180,17 @@ public class PeakFreqOptionsPane extends StandardSymbolModifierPane {
|
|||||||
DoubleSpinnerValueFactory spinnerValFact = (DoubleSpinnerValueFactory) maxFreq.getValueFactory();
|
DoubleSpinnerValueFactory spinnerValFact = (DoubleSpinnerValueFactory) maxFreq.getValueFactory();
|
||||||
spinnerValFact.maxProperty().set(getSampleRate() /2);
|
spinnerValFact.maxProperty().set(getSampleRate() /2);
|
||||||
|
|
||||||
|
//set reasonable step sizes
|
||||||
|
if (getSampleRate()>=10000) {
|
||||||
|
spinnerValFact.amountToStepByProperty().set(1000.);
|
||||||
|
}
|
||||||
|
else if (getSampleRate()>=2000){
|
||||||
|
spinnerValFact.amountToStepByProperty().set(200.);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
spinnerValFact.amountToStepByProperty().set(50.);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (symbolOptions.freqLimts==null) {
|
if (symbolOptions.freqLimts==null) {
|
||||||
symbolOptions.freqLimts= new double[] {0, getSampleRate() /2};
|
symbolOptions.freqLimts= new double[] {0, getSampleRate() /2};
|
||||||
|
@ -561,6 +561,7 @@ public class DLControl extends PamControlledUnit implements PamSettings {
|
|||||||
* @return the number of classes.
|
* @return the number of classes.
|
||||||
*/
|
*/
|
||||||
public int getNumClasses() {
|
public int getNumClasses() {
|
||||||
|
if (getDLModel()==null) return 0;
|
||||||
return getDLModel().getNumClasses();
|
return getDLModel().getNumClasses();
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -622,8 +623,9 @@ public class DLControl extends PamControlledUnit implements PamSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the classifier chooser.
|
* Get the classifier chooser. The classifier chooser chooses which classifier use
|
||||||
* @return the classifier chooser.Take it
|
* based on a selected file or URL.
|
||||||
|
* @return the classifier chooser.
|
||||||
*/
|
*/
|
||||||
public DLClassifierChooser getDlClassifierChooser() {
|
public DLClassifierChooser getDlClassifierChooser() {
|
||||||
return dlClassifierChooser;
|
return dlClassifierChooser;
|
||||||
|
@ -19,7 +19,9 @@ import pamViewFX.fxNodes.utilityPanes.PamToggleSwitch;
|
|||||||
import rawDeepLearningClassifier.dlClassification.DLClassName;
|
import rawDeepLearningClassifier.dlClassification.DLClassName;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Symbol Options for the annotation pane
|
* Symbol Options for the annotation pane.
|
||||||
|
*
|
||||||
|
* @author Jamie Macaulay
|
||||||
*/
|
*/
|
||||||
public class DLPredictionPane extends PamBorderPane implements TDSettingsPane {
|
public class DLPredictionPane extends PamBorderPane implements TDSettingsPane {
|
||||||
|
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
package rawDeepLearningClassifier.dataPlotFX;
|
package rawDeepLearningClassifier.dataPlotFX;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
|
||||||
|
import PamController.PamController;
|
||||||
|
import PamUtils.PamArrayUtils;
|
||||||
import PamView.GeneralProjector;
|
import PamView.GeneralProjector;
|
||||||
import PamView.PamSymbolType;
|
import PamView.PamSymbolType;
|
||||||
|
import PamView.dialog.GenericSwingDialog;
|
||||||
|
import PamView.dialog.PamDialogPanel;
|
||||||
import PamView.symbol.PamSymbolChooser;
|
import PamView.symbol.PamSymbolChooser;
|
||||||
import PamView.symbol.SymbolData;
|
import PamView.symbol.SymbolData;
|
||||||
import PamView.symbol.modifier.SymbolModType;
|
import PamView.symbol.modifier.SymbolModType;
|
||||||
@ -20,7 +25,8 @@ import rawDeepLearningClassifier.logging.DLAnnotationType;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The DL symbol modifier. Colours symbols by prediction.
|
* The DL symbol modifier. Colours symbols by either the value of the prediction
|
||||||
|
* by a user selected class or by the class with the highest prediction value.
|
||||||
*
|
*
|
||||||
* @author Jamie Macaulay.
|
* @author Jamie Macaulay.
|
||||||
*
|
*
|
||||||
@ -36,12 +42,12 @@ public class DLSymbolModifier extends SymbolModifier {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The symbol options pane.
|
* JavaFX symbol options pane.
|
||||||
*/
|
*/
|
||||||
private DLSymbolOptionPane optionsPane;
|
private DLSymbolOptionPane optionsPane;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rge DL annotation type.
|
* The DL annotation type.
|
||||||
*/
|
*/
|
||||||
private DLAnnotationType dlAnnotType;
|
private DLAnnotationType dlAnnotType;
|
||||||
|
|
||||||
@ -55,6 +61,11 @@ public class DLSymbolModifier extends SymbolModifier {
|
|||||||
|
|
||||||
private ColourArray colourArray;
|
private ColourArray colourArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swing option panel for the symbol chooser.
|
||||||
|
*/
|
||||||
|
private DLSymbolOptionPanel optionsPanel;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public DLSymbolModifier(PamSymbolChooser symbolChooser, DLAnnotationType dlAnnotType) {
|
public DLSymbolModifier(PamSymbolChooser symbolChooser, DLAnnotationType dlAnnotType) {
|
||||||
@ -94,7 +105,70 @@ public class DLSymbolModifier extends SymbolModifier {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//System.out.println("Class index: " + dlSymbolOptions.classIndex);
|
|
||||||
|
//modify the default symbol
|
||||||
|
if (dlSymbolOptions.colTypeSelection == DLSymbolModifierParams.PREDICITON_COL) {
|
||||||
|
getSymbolDataPred(annotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (dlSymbolOptions.colTypeSelection == DLSymbolModifierParams.CLASS_COL) {
|
||||||
|
getSymbolDataClass(annotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
return symbolData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get symbol data for colouring by the species class with the maximum prediction
|
||||||
|
* @param annotation - the annotation
|
||||||
|
* @return symbol data for colouring by class maximum.
|
||||||
|
*/
|
||||||
|
private SymbolData getSymbolDataClass(DLAnnotation annotation ) {
|
||||||
|
|
||||||
|
boolean passed = false;
|
||||||
|
int colIndex = -1;
|
||||||
|
|
||||||
|
float[][] results = new float[ annotation.getModelResults().size()][];
|
||||||
|
|
||||||
|
//A detection might have multiple prediction results, i.e. predictions are a matrix. Need
|
||||||
|
//to iterate through all the predictions and then work out whihc is the maximum. That index is then then]
|
||||||
|
//class colour.
|
||||||
|
int i=0;
|
||||||
|
for (PredictionResult modelResult: annotation.getModelResults()) {
|
||||||
|
if (modelResult.isBinaryClassification()) passed = true;
|
||||||
|
results[i] = modelResult.getPrediction();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] indexBest = PamArrayUtils.maxPos(results);
|
||||||
|
|
||||||
|
|
||||||
|
if (passed || !dlSymbolOptions.showOnlyBinary) {
|
||||||
|
//work out the class colour...
|
||||||
|
|
||||||
|
javafx.scene.paint.Color color = PamUtilsFX.intToColor(dlSymbolOptions.classColors[indexBest[1]]);
|
||||||
|
|
||||||
|
Color colorAWT = PamUtilsFX.fxToAWTColor(color);
|
||||||
|
|
||||||
|
symbolData.setFillColor(colorAWT);
|
||||||
|
symbolData.setLineColor(colorAWT);
|
||||||
|
|
||||||
|
return symbolData;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//has data but we have only show binary option selected.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get symbol data for colouring by the prediction value for a selected species class.
|
||||||
|
* @param annotation - the annotation
|
||||||
|
* @return symbol data for colouring by prediction value for a selected species class.
|
||||||
|
*/
|
||||||
|
private SymbolData getSymbolDataPred(DLAnnotation annotation ) {
|
||||||
|
|
||||||
if (dlSymbolOptions.classIndex<0) {
|
if (dlSymbolOptions.classIndex<0) {
|
||||||
dlSymbolOptions.classIndex=0;
|
dlSymbolOptions.classIndex=0;
|
||||||
@ -161,6 +235,7 @@ public class DLSymbolModifier extends SymbolModifier {
|
|||||||
* Get the JavaFX symbol options pane that has options for the symbol pane.
|
* Get the JavaFX symbol options pane that has options for the symbol pane.
|
||||||
* @return the symbol options pane.
|
* @return the symbol options pane.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public SymbolModifierPane getOptionsPane() {
|
public SymbolModifierPane getOptionsPane() {
|
||||||
if (optionsPane == null) {
|
if (optionsPane == null) {
|
||||||
optionsPane = new DLSymbolOptionPane(this);
|
optionsPane = new DLSymbolOptionPane(this);
|
||||||
@ -168,6 +243,23 @@ public class DLSymbolModifier extends SymbolModifier {
|
|||||||
return optionsPane;
|
return optionsPane;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PamDialogPanel getDialogPanel() {
|
||||||
|
if (optionsPanel == null) {
|
||||||
|
optionsPanel = new DLSymbolOptionPanel(this);
|
||||||
|
}
|
||||||
|
return optionsPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default behaviour to show the dialog panel.
|
||||||
|
* @param e
|
||||||
|
* @param dialogPanel
|
||||||
|
*/
|
||||||
|
protected void showOptionsDialog(ActionEvent e, PamDialogPanel dialogPanel) {
|
||||||
|
GenericSwingDialog.showDialog(PamController.getMainFrame(), getName() + " options", dialogPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public DLAnnotationType getDLAnnotType() {
|
public DLAnnotationType getDLAnnotType() {
|
||||||
return dlAnnotType;
|
return dlAnnotType;
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package rawDeepLearningClassifier.dataPlotFX;
|
package rawDeepLearningClassifier.dataPlotFX;
|
||||||
|
|
||||||
|
|
||||||
import PamView.symbol.modifier.SymbolModifierParams;
|
import PamView.symbol.modifier.SymbolModifierParams;
|
||||||
|
import javafx.scene.paint.Color;
|
||||||
import pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType;
|
import pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType;
|
||||||
|
import pamViewFX.fxNodes.utilsFX.PamUtilsFX;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameters for colouring symbols by deep learning probability.
|
* Parameters for colouring symbols by deep learning probability.
|
||||||
@ -11,10 +14,27 @@ import pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType;
|
|||||||
*/
|
*/
|
||||||
public class DLSymbolModifierParams extends SymbolModifierParams {
|
public class DLSymbolModifierParams extends SymbolModifierParams {
|
||||||
|
|
||||||
|
public DLSymbolModifierParams() {
|
||||||
|
setDefaultClassColors(32);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 3L;
|
||||||
|
|
||||||
|
|
||||||
|
public static final int PREDICITON_COL = 0;
|
||||||
|
|
||||||
|
public static final int CLASS_COL = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The way to colour the predictions.
|
||||||
|
*/
|
||||||
|
public int colTypeSelection = PREDICITON_COL;
|
||||||
|
|
||||||
|
|
||||||
|
/****Prediction colours****/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The colour limits.
|
* The colour limits.
|
||||||
@ -27,16 +47,72 @@ public class DLSymbolModifierParams extends SymbolModifierParams {
|
|||||||
*/
|
*/
|
||||||
public int classIndex = 0;
|
public int classIndex = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/*******Class colours******/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show only binary.
|
* The current colours for each
|
||||||
*/
|
*/
|
||||||
public boolean showOnlyBinary = false;
|
public int[] classColors = new int[32];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The currently selected class for colour picker- just so the user sees the same selection.
|
||||||
|
*/
|
||||||
|
public int classIndex2 = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The colour array to show.
|
* The colour array to show.
|
||||||
*/
|
*/
|
||||||
public ColourArrayType colArray = ColourArrayType.FIRE;
|
public ColourArrayType colArray = ColourArrayType.FIRE;
|
||||||
|
|
||||||
|
/***************************/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show only detections which have passed a decision threshold.
|
||||||
|
*/
|
||||||
|
public boolean showOnlyBinary = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default colours.
|
||||||
|
* @param num - the number of colours to set.
|
||||||
|
*/
|
||||||
|
public void setDefaultClassColors(int num) {
|
||||||
|
if (classColors==null || classColors.length<num) {
|
||||||
|
classColors = new int[32];
|
||||||
|
}
|
||||||
|
|
||||||
|
//run through default colours
|
||||||
|
for (int i=0; i<classColors.length; i++) {
|
||||||
|
switch (i%8) {
|
||||||
|
case 0:
|
||||||
|
classColors[i]=PamUtilsFX.colorToInt(Color.RED);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
classColors[i]=PamUtilsFX.colorToInt(Color.GREEN);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
classColors[i]=PamUtilsFX.colorToInt(Color.BLUE);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
classColors[i]=PamUtilsFX.colorToInt(Color.CYAN);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
classColors[i]=PamUtilsFX.colorToInt(Color.MAGENTA);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
classColors[i]=PamUtilsFX.colorToInt(Color.YELLOW);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
classColors[i]=PamUtilsFX.colorToInt(Color.ORANGE);
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
classColors[i]=PamUtilsFX.colorToInt(Color.PURPLE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DLSymbolModifierParams clone() {
|
protected DLSymbolModifierParams clone() {
|
||||||
|
@ -1,30 +1,43 @@
|
|||||||
package rawDeepLearningClassifier.dataPlotFX;
|
package rawDeepLearningClassifier.dataPlotFX;
|
||||||
|
|
||||||
|
import org.controlsfx.control.SegmentedButton;
|
||||||
|
|
||||||
import PamView.symbol.StandardSymbolOptions;
|
import PamView.symbol.StandardSymbolOptions;
|
||||||
import PamView.symbol.modifier.SymbolModifier;
|
import PamView.symbol.modifier.SymbolModifier;
|
||||||
import PamView.symbol.modifier.SymbolModifierParams;
|
|
||||||
import javafx.geometry.Insets;
|
import javafx.geometry.Insets;
|
||||||
import javafx.geometry.Orientation;
|
import javafx.geometry.Orientation;
|
||||||
import javafx.geometry.Pos;
|
import javafx.geometry.Pos;
|
||||||
import javafx.scene.control.CheckBox;
|
import javafx.scene.control.CheckBox;
|
||||||
|
import javafx.scene.control.ColorPicker;
|
||||||
import javafx.scene.control.ComboBox;
|
import javafx.scene.control.ComboBox;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.ToggleButton;
|
||||||
|
import javafx.scene.control.Tooltip;
|
||||||
|
import javafx.scene.layout.BorderPane;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
|
import javafx.scene.layout.Priority;
|
||||||
|
import pamViewFX.fxNodes.PamBorderPane;
|
||||||
import pamViewFX.fxNodes.PamHBox;
|
import pamViewFX.fxNodes.PamHBox;
|
||||||
import pamViewFX.fxNodes.PamVBox;
|
import pamViewFX.fxNodes.PamVBox;
|
||||||
import pamViewFX.fxNodes.comboBox.ColorComboBox;
|
import pamViewFX.fxNodes.comboBox.ColorComboBox;
|
||||||
import pamViewFX.fxNodes.sliders.ColourRangeSlider;
|
import pamViewFX.fxNodes.sliders.ColourRangeSlider;
|
||||||
import pamViewFX.fxNodes.utilsFX.ColourArray;
|
import pamViewFX.fxNodes.utilsFX.ColourArray;
|
||||||
|
import pamViewFX.fxNodes.utilsFX.PamUtilsFX;
|
||||||
import pamViewFX.symbol.StandardSymbolModifierPane;
|
import pamViewFX.symbol.StandardSymbolModifierPane;
|
||||||
import rawDeepLearningClassifier.dlClassification.DLClassName;
|
import rawDeepLearningClassifier.dlClassification.DLClassName;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Symbol Options for the annotation pane
|
* Symbol Options for the annotation pane.
|
||||||
|
*
|
||||||
|
* @author Jamie Macaulay
|
||||||
*/
|
*/
|
||||||
public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
||||||
|
|
||||||
|
|
||||||
|
private static final double CLASS_NAME_BOX_WIDTH = 130;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The colour range slider for colouring probabilities.
|
* The colour range slider for colouring probabilities.
|
||||||
*/
|
*/
|
||||||
@ -42,21 +55,143 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Combo box which allows a user to select colour
|
* Color picker which allows a user to select the gradient for colouring predictions
|
||||||
*/
|
*/
|
||||||
private ColorComboBox colourBox;
|
private ColorComboBox colourBox;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Color picker which allows a user to select colour for each class.
|
||||||
|
*/
|
||||||
|
private ColorPicker colourPicker;
|
||||||
|
|
||||||
private boolean initialised=true;
|
private boolean initialised=true;
|
||||||
|
|
||||||
private DLSymbolModifier dlSymbolModifier;
|
private DLSymbolModifier dlSymbolModifier;
|
||||||
|
|
||||||
|
private ComboBox<String> classNameBox2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pane which holds controls for changing the colour based on prediciton value
|
||||||
|
*/
|
||||||
|
private Pane probPane;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pane which holds controls for changing the colour based on the highest prediction value
|
||||||
|
*/
|
||||||
|
private Pane classPane;
|
||||||
|
|
||||||
|
|
||||||
|
private PamBorderPane holder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Button to select how to colour.
|
||||||
|
*/
|
||||||
|
private ToggleButton b1, b2;
|
||||||
|
|
||||||
public DLSymbolOptionPane(SymbolModifier symbolModifer) {
|
public DLSymbolOptionPane(SymbolModifier symbolModifer) {
|
||||||
super(symbolModifer, Orientation.HORIZONTAL, true, 0);
|
super(symbolModifer, Orientation.HORIZONTAL, true, 0);
|
||||||
this.setBottom(createProbPane());
|
|
||||||
|
probPane = createProbPane();
|
||||||
|
classPane = createClassPane();
|
||||||
|
classPane.setPadding(new Insets(0,0,5,0));
|
||||||
|
|
||||||
|
b1 = new ToggleButton("Prediction");
|
||||||
|
b1.setPrefWidth(80);
|
||||||
|
// b1.setStyle("-fx-border-radius: 5 0 0 5; -fx-background-radius: 5 0 0 5;");
|
||||||
|
|
||||||
|
b2 = new ToggleButton("Class");
|
||||||
|
b2.setPrefWidth(80);
|
||||||
|
|
||||||
|
b1.setOnAction((a)->{
|
||||||
|
setSettingsPane();
|
||||||
|
//change the colour of the colour range slider.
|
||||||
|
notifySettingsListeners();
|
||||||
|
});
|
||||||
|
// b2.setStyle("-fx-border-radius: 0 5 5 0; -fx-background-radius: 0 5 5 0;");
|
||||||
|
|
||||||
|
|
||||||
|
b2.setOnAction((a)->{
|
||||||
|
setSettingsPane();
|
||||||
|
//change the colour of the colour range slider.
|
||||||
|
notifySettingsListeners();
|
||||||
|
});
|
||||||
|
|
||||||
|
SegmentedButton segmentedButton = new SegmentedButton();
|
||||||
|
segmentedButton.getButtons().addAll(b1, b2);
|
||||||
|
segmentedButton.setPadding(new Insets(5,0,5,0));
|
||||||
|
segmentedButton.getStyleClass().add(SegmentedButton.STYLE_CLASS_DARK);
|
||||||
|
|
||||||
|
|
||||||
|
BorderPane.setAlignment(segmentedButton, Pos.CENTER);
|
||||||
|
b1.setSelected(true);
|
||||||
|
|
||||||
|
showOnlyBinary = new CheckBox("Show only binary classificaiton");
|
||||||
|
showOnlyBinary.setOnAction((action)->{
|
||||||
|
getParams();
|
||||||
|
//change the colour of the colour range slider.
|
||||||
|
notifySettingsListeners();
|
||||||
|
});
|
||||||
|
showOnlyBinary.setTooltip(new Tooltip("Colour detections only if they passed decision threshold"));
|
||||||
|
|
||||||
|
holder = new PamBorderPane();
|
||||||
|
|
||||||
|
holder.setTop(segmentedButton);
|
||||||
|
holder.setCenter(probPane);
|
||||||
|
holder.setBottom(showOnlyBinary);
|
||||||
|
|
||||||
|
this.setBottom(holder);
|
||||||
|
|
||||||
this.dlSymbolModifier = (DLSymbolModifier) symbolModifer;
|
this.dlSymbolModifier = (DLSymbolModifier) symbolModifer;
|
||||||
initialised=true;
|
initialised=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setSettingsPane() {
|
||||||
|
if (b1.isSelected()) {
|
||||||
|
holder.setCenter(probPane);
|
||||||
|
}
|
||||||
|
if (b2.isSelected()) {
|
||||||
|
holder.setCenter(classPane);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Pane createClassPane() {
|
||||||
|
|
||||||
|
classNameBox2 = new ComboBox<String>();
|
||||||
|
classNameBox2.setOnAction((action)->{
|
||||||
|
getParams();
|
||||||
|
//change the colour of the colour range slider.
|
||||||
|
notifySettingsListeners();
|
||||||
|
});
|
||||||
|
classNameBox2.setMaxWidth(Double.MAX_VALUE);
|
||||||
|
|
||||||
|
classNameBox2.setOnAction((action)->{
|
||||||
|
if (classNameBox2.getSelectionModel().getSelectedIndex()>=0){
|
||||||
|
colourPicker.setValue(PamUtilsFX.intToColor(dlSymbolModifier.getSymbolModifierParams().classColors[classNameBox2.getSelectionModel().getSelectedIndex()]));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
classNameBox2.setPrefWidth(CLASS_NAME_BOX_WIDTH);
|
||||||
|
|
||||||
|
colourPicker = new ColorPicker();
|
||||||
|
colourPicker.setPrefWidth(60);
|
||||||
|
colourPicker.setOnAction((action)->{
|
||||||
|
getParams();
|
||||||
|
notifySettingsListeners();
|
||||||
|
});
|
||||||
|
|
||||||
|
HBox.setHgrow(classNameBox, Priority.ALWAYS);
|
||||||
|
|
||||||
|
PamHBox classHolder = new PamHBox();
|
||||||
|
classHolder.setSpacing(5);
|
||||||
|
classHolder.setAlignment(Pos.CENTER_LEFT);
|
||||||
|
classHolder.getChildren().addAll(classNameBox2, colourPicker);
|
||||||
|
|
||||||
|
return classHolder;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private Pane createProbPane() {
|
private Pane createProbPane() {
|
||||||
|
|
||||||
PamVBox holder = new PamVBox();
|
PamVBox holder = new PamVBox();
|
||||||
@ -82,6 +217,8 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
|||||||
//change the colour of the colour range slider.
|
//change the colour of the colour range slider.
|
||||||
notifySettingsListeners();
|
notifySettingsListeners();
|
||||||
});
|
});
|
||||||
|
classNameBox.setPrefWidth(CLASS_NAME_BOX_WIDTH);
|
||||||
|
|
||||||
|
|
||||||
colourBox = new ColorComboBox(ColorComboBox.COLOUR_ARRAY_BOX);
|
colourBox = new ColorComboBox(ColorComboBox.COLOUR_ARRAY_BOX);
|
||||||
colourBox.setPrefWidth(50);
|
colourBox.setPrefWidth(50);
|
||||||
@ -92,17 +229,10 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
|||||||
colourRangeSlider.setColourArrayType( dlSymbolModifier.getSymbolModifierParams().colArray);
|
colourRangeSlider.setColourArrayType( dlSymbolModifier.getSymbolModifierParams().colArray);
|
||||||
});
|
});
|
||||||
|
|
||||||
showOnlyBinary = new CheckBox("Show only binary classificaiton");
|
|
||||||
showOnlyBinary.setOnAction((action)->{
|
|
||||||
getParams();
|
|
||||||
//change the colour of the colour range slider.
|
|
||||||
notifySettingsListeners();
|
|
||||||
});
|
|
||||||
|
|
||||||
PamHBox classHolder = new PamHBox();
|
PamHBox classHolder = new PamHBox();
|
||||||
classHolder.setSpacing(5);
|
classHolder.setSpacing(5);
|
||||||
classHolder.setAlignment(Pos.CENTER_LEFT);
|
classHolder.setAlignment(Pos.CENTER_LEFT);
|
||||||
classHolder.getChildren().addAll(new Label("Show Class"), classNameBox);
|
classHolder.getChildren().addAll(new Label("Show class"), classNameBox);
|
||||||
|
|
||||||
PamHBox colorHolder = new PamHBox();
|
PamHBox colorHolder = new PamHBox();
|
||||||
colorHolder.setSpacing(5);
|
colorHolder.setSpacing(5);
|
||||||
@ -112,7 +242,7 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
|||||||
holder.getChildren().addAll(classHolder, new Label("Probability"), colorHolder);
|
holder.getChildren().addAll(classHolder, new Label("Probability"), colorHolder);
|
||||||
|
|
||||||
|
|
||||||
holder.getChildren().add(showOnlyBinary);
|
// holder.getChildren().add(showOnlyBinary);
|
||||||
holder.setPadding(new Insets(5,0,5,0));
|
holder.setPadding(new Insets(5,0,5,0));
|
||||||
|
|
||||||
setParams = false;
|
setParams = false;
|
||||||
@ -120,17 +250,29 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
|||||||
return holder;
|
return holder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public StandardSymbolOptions getParams(){
|
|
||||||
StandardSymbolOptions standardSymbolOptions = super.getParams();
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get parameters for colouring by class.
|
||||||
|
* @param symbolOptions - the symbol options.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public DLSymbolModifierParams getClassColParams(DLSymbolModifierParams symbolOptions ) {
|
||||||
|
|
||||||
//bit messy but works /
|
int index = classNameBox2.getSelectionModel().getSelectedIndex()>=0 ? classNameBox2.getSelectionModel().getSelectedIndex():0;
|
||||||
DLSymbolModifierParams symbolOptions = dlSymbolModifier.getSymbolModifierParams();
|
|
||||||
|
|
||||||
//need to chekc this here.
|
symbolOptions.classColors[index] = PamUtilsFX.colorToInt(colourPicker.getValue());
|
||||||
//checkClassNamesBox(symbolOptions);
|
|
||||||
|
|
||||||
|
symbolOptions.classIndex2 = classNameBox2.getSelectionModel().getSelectedIndex();
|
||||||
|
|
||||||
|
return symbolOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param symbolOptions
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public DLSymbolModifierParams getPredictionColParams(DLSymbolModifierParams symbolOptions ) {
|
||||||
|
|
||||||
symbolOptions.clims=new double[] {colourRangeSlider.getLowValue(), colourRangeSlider.getHighValue()};
|
symbolOptions.clims=new double[] {colourRangeSlider.getLowValue(), colourRangeSlider.getHighValue()};
|
||||||
|
|
||||||
@ -138,17 +280,38 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
|||||||
|
|
||||||
symbolOptions.classIndex = classNameBox.getSelectionModel().getSelectedIndex();
|
symbolOptions.classIndex = classNameBox.getSelectionModel().getSelectedIndex();
|
||||||
|
|
||||||
|
return symbolOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StandardSymbolOptions getParams(){
|
||||||
|
StandardSymbolOptions standardSymbolOptions = super.getParams();
|
||||||
|
|
||||||
|
//bit messy but works
|
||||||
|
DLSymbolModifierParams symbolOptions = dlSymbolModifier.getSymbolModifierParams();
|
||||||
|
|
||||||
|
//need to check this here.
|
||||||
|
//checkClassNamesBox(symbolOptions);
|
||||||
|
|
||||||
|
if (b1.isSelected()) symbolOptions.colTypeSelection = DLSymbolModifierParams.PREDICITON_COL;
|
||||||
|
if (b2.isSelected()) symbolOptions.colTypeSelection = DLSymbolModifierParams.CLASS_COL;
|
||||||
|
|
||||||
|
//get parameters for colouring
|
||||||
|
symbolOptions = getClassColParams(symbolOptions);
|
||||||
|
|
||||||
|
//get parameters for colouring by prediction value
|
||||||
|
symbolOptions = getPredictionColParams(symbolOptions) ;
|
||||||
|
|
||||||
symbolOptions.showOnlyBinary = showOnlyBinary.isSelected();
|
symbolOptions.showOnlyBinary = showOnlyBinary.isSelected();
|
||||||
|
|
||||||
dlSymbolModifier.checkColourArray();
|
dlSymbolModifier.checkColourArray();
|
||||||
|
|
||||||
//System.out.println("Get params: " );
|
|
||||||
|
|
||||||
return standardSymbolOptions;
|
return standardSymbolOptions;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkClassNamesBox(DLSymbolModifierParams symbolOptions) {
|
|
||||||
|
private int checkClassNamesBox(DLSymbolModifierParams symbolOptions, ComboBox<String> classNameBox) {
|
||||||
|
|
||||||
DLClassName[] classNames = dlSymbolModifier.getDLAnnotType().getDlControl().getDLModel().getClassNames();
|
DLClassName[] classNames = dlSymbolModifier.getDLAnnotType().getDlControl().getDLModel().getClassNames();
|
||||||
|
|
||||||
@ -167,8 +330,51 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
|||||||
classNameBox.getItems().add("Class: " + i);
|
classNameBox.getItems().add("Class: " + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nClass;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set parameters for controls to change the colour gradient based on prediction.
|
||||||
|
* @param symbolOptions - the symbol options
|
||||||
|
*/
|
||||||
|
private void setPredictionColParams(DLSymbolModifierParams symbolOptions) {
|
||||||
|
|
||||||
|
//now set frequency parameters
|
||||||
|
colourRangeSlider.setLowValue(symbolOptions.clims[0]);
|
||||||
|
colourRangeSlider.setHighValue(symbolOptions.clims[1]);
|
||||||
|
colourRangeSlider.setColourArrayType( symbolOptions.colArray);
|
||||||
|
|
||||||
|
|
||||||
|
int nClass = checkClassNamesBox( symbolOptions, classNameBox);
|
||||||
symbolOptions.classIndex = Math.min(symbolOptions.classIndex, nClass-1);
|
symbolOptions.classIndex = Math.min(symbolOptions.classIndex, nClass-1);
|
||||||
classNameBox.getSelectionModel().select(Math.max(symbolOptions.classIndex, 0));
|
classNameBox.getSelectionModel().select(Math.max(symbolOptions.classIndex, 0));
|
||||||
|
|
||||||
|
//color box.
|
||||||
|
colourBox.setValue(symbolOptions.colArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set parameters for controls to change the colour gradient based on prediction.
|
||||||
|
* @param symbolOptions - the symbol options
|
||||||
|
*/
|
||||||
|
private void setClassColParams(DLSymbolModifierParams symbolOptions) {
|
||||||
|
|
||||||
|
int nClass = checkClassNamesBox( symbolOptions, classNameBox2);
|
||||||
|
|
||||||
|
symbolOptions.classIndex = Math.min(symbolOptions.classIndex, nClass-1);
|
||||||
|
classNameBox2.getSelectionModel().select(Math.max(symbolOptions.classIndex2, 0));
|
||||||
|
|
||||||
|
|
||||||
|
int index = symbolOptions.classIndex2>=0 ? symbolOptions.classIndex2 : 0;
|
||||||
|
|
||||||
|
if (symbolOptions.classColors==null) {
|
||||||
|
symbolOptions.setDefaultClassColors(nClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
//set the correct colour
|
||||||
|
colourPicker.setValue(PamUtilsFX.intToColor(symbolOptions.classColors[index]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -180,25 +386,28 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
|||||||
|
|
||||||
setParams = true;
|
setParams = true;
|
||||||
|
|
||||||
// StandardSymbolOptions standardSymbolOptions = (StandardSymbolOptions) getSymbolModifier().getSymbolChooser().getSymbolOptions();
|
//get the symbool options
|
||||||
|
|
||||||
DLSymbolModifierParams symbolOptions = dlSymbolModifier.getSymbolModifierParams();
|
DLSymbolModifierParams symbolOptions = dlSymbolModifier.getSymbolModifierParams();
|
||||||
//now set frequency parameters
|
|
||||||
colourRangeSlider.setLowValue(symbolOptions.clims[0]);
|
|
||||||
colourRangeSlider.setHighValue(symbolOptions.clims[1]);
|
|
||||||
colourRangeSlider.setColourArrayType( symbolOptions.colArray);
|
|
||||||
|
|
||||||
|
// b1.setSelected(false);
|
||||||
|
// b2.setSelected(false);
|
||||||
|
if (symbolOptions.colTypeSelection == DLSymbolModifierParams.PREDICITON_COL) b1.setSelected(true);
|
||||||
|
if (symbolOptions.colTypeSelection == DLSymbolModifierParams.CLASS_COL) b2.setSelected(true);
|
||||||
|
|
||||||
//set the combo box class types.
|
setSettingsPane();
|
||||||
checkClassNamesBox( symbolOptions);
|
|
||||||
|
|
||||||
|
// symbolOptions.colTypeSelection = b1.isSelected() ? DLSymbolModifierParams.PREDICITON_COL : DLSymbolModifierParams.CLASS_COL;
|
||||||
|
|
||||||
//color box.
|
//set the parameters for colouring by prediction
|
||||||
colourBox.setValue(symbolOptions.colArray);
|
setPredictionColParams(symbolOptions);
|
||||||
|
|
||||||
|
//set the class colour parameters
|
||||||
|
setClassColParams(symbolOptions);
|
||||||
|
|
||||||
//set the selected.
|
//set the selected.
|
||||||
showOnlyBinary.setSelected(symbolOptions.showOnlyBinary);
|
showOnlyBinary.setSelected(symbolOptions.showOnlyBinary);
|
||||||
|
|
||||||
|
|
||||||
setParams = false;
|
setParams = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,424 @@
|
|||||||
|
package rawDeepLearningClassifier.dataPlotFX;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.FlowLayout;
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
|
||||||
|
import javax.swing.AbstractButton;
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.Box;
|
||||||
|
import javax.swing.BoxLayout;
|
||||||
|
import javax.swing.ButtonGroup;
|
||||||
|
import javax.swing.JCheckBox;
|
||||||
|
import javax.swing.JColorChooser;
|
||||||
|
import javax.swing.JComboBox;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JSlider;
|
||||||
|
import javax.swing.JToggleButton;
|
||||||
|
import javax.swing.border.TitledBorder;
|
||||||
|
|
||||||
|
import PamView.ColourComboBox;
|
||||||
|
import PamView.PamAWTUtils;
|
||||||
|
import PamView.dialog.GenericSwingDialog;
|
||||||
|
import PamView.dialog.PamButton;
|
||||||
|
import PamView.dialog.PamDialogPanel;
|
||||||
|
import PamView.panel.PamPanel;
|
||||||
|
import PamView.symbol.StandardSymbolOptions;
|
||||||
|
import PamView.symbol.modifier.SymbolModifier;
|
||||||
|
import Spectrogram.ColourRangeSlider;
|
||||||
|
import pamViewFX.fxNodes.utilsFX.ColourArray;
|
||||||
|
import pamViewFX.fxNodes.utilsFX.PamUtilsFX;
|
||||||
|
import rawDeepLearningClassifier.dlClassification.DLClassName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Swing symbol options for the annotation pane.
|
||||||
|
*
|
||||||
|
* @author Jamie Macaulay
|
||||||
|
*/
|
||||||
|
public class DLSymbolOptionPanel implements PamDialogPanel, ActionListener {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private static final double CLASS_NAME_BOX_WIDTH = 130;
|
||||||
|
|
||||||
|
private DLSymbolModifier dlSymbolModifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The color range slider for coloring probabilities.
|
||||||
|
*/
|
||||||
|
private ColourRangeSlider colorRangeSlider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The combo box allowing users to select which class to show.
|
||||||
|
*/
|
||||||
|
private JComboBox<String> classNameBox;
|
||||||
|
private JComboBox<String> classNameBox2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check box allowing users only to show only those detections which have passed binary classification.
|
||||||
|
*/
|
||||||
|
private JCheckBox showOnlyBinary;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Color picker which allows a user to select the gradient for coloring predictions
|
||||||
|
*/
|
||||||
|
private ColourComboBox colorComboBox;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Color picker which allows a user to select color for each class.
|
||||||
|
*/
|
||||||
|
private JColorChooser colorPicker;
|
||||||
|
|
||||||
|
private boolean initialized = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pane which holds controls for changing the colour based on prediciton value
|
||||||
|
*/
|
||||||
|
private JPanel probPane;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pane which holds controls for changing the colour based on the highest prediction value
|
||||||
|
*/
|
||||||
|
private JPanel classPane;
|
||||||
|
|
||||||
|
private PamPanel holder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Button to select how to colour.
|
||||||
|
*/
|
||||||
|
private JToggleButton b1, b2;
|
||||||
|
|
||||||
|
private PamPanel mainPanel;
|
||||||
|
|
||||||
|
private int[] classColours;
|
||||||
|
|
||||||
|
private AbstractButton colourButton;
|
||||||
|
|
||||||
|
|
||||||
|
public DLSymbolOptionPanel(SymbolModifier symbolModifer) {
|
||||||
|
this.dlSymbolModifier = (DLSymbolModifier) symbolModifer;
|
||||||
|
|
||||||
|
probPane = createProbPane();
|
||||||
|
probPane.setBorder(new TitledBorder("Colour by prediction value"));
|
||||||
|
|
||||||
|
classPane = createClassPane();
|
||||||
|
classPane.setBorder(new TitledBorder("Colour by class"));
|
||||||
|
|
||||||
|
b1 = new JToggleButton("Prediction");
|
||||||
|
b1.setPreferredSize(new Dimension(100, 25)); // Set preferred size
|
||||||
|
|
||||||
|
b2 = new JToggleButton("Class");
|
||||||
|
b2.setPreferredSize(new Dimension(100, 25));
|
||||||
|
|
||||||
|
ButtonGroup buttonGroup = new ButtonGroup(); // Group toggle buttons
|
||||||
|
buttonGroup.add(b1);
|
||||||
|
buttonGroup.add(b2);
|
||||||
|
|
||||||
|
b1.addActionListener(this);
|
||||||
|
b2.addActionListener(this);
|
||||||
|
|
||||||
|
JPanel segmentedButtonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
|
||||||
|
segmentedButtonPanel.add(b1);
|
||||||
|
segmentedButtonPanel.add(b2);
|
||||||
|
|
||||||
|
holder = new PamPanel();
|
||||||
|
holder.setLayout(new BorderLayout());
|
||||||
|
holder.add(new JLabel("Hello"), BorderLayout.NORTH);
|
||||||
|
|
||||||
|
mainPanel = new PamPanel();
|
||||||
|
mainPanel.setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
mainPanel.add(segmentedButtonPanel, BorderLayout.NORTH);
|
||||||
|
mainPanel.add(holder, BorderLayout.CENTER);
|
||||||
|
mainPanel.add(showOnlyBinary = new JCheckBox("Show only binary classification"), BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
setSettingsPane();
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JComponent getDialogComponent() {
|
||||||
|
return mainPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParams() {
|
||||||
|
//get the symbool options
|
||||||
|
DLSymbolModifierParams symbolOptions = dlSymbolModifier.getSymbolModifierParams();
|
||||||
|
|
||||||
|
// b1.setSelected(false);
|
||||||
|
// b2.setSelected(false);
|
||||||
|
if (symbolOptions.colTypeSelection == DLSymbolModifierParams.PREDICITON_COL) b1.setSelected(true);
|
||||||
|
if (symbolOptions.colTypeSelection == DLSymbolModifierParams.CLASS_COL) b2.setSelected(true);
|
||||||
|
|
||||||
|
setSettingsPane();
|
||||||
|
|
||||||
|
//set the parameters for colouring by prediction
|
||||||
|
setPredictionColParams(symbolOptions);
|
||||||
|
|
||||||
|
//set the class colour parameters
|
||||||
|
setClassColParams(symbolOptions);
|
||||||
|
|
||||||
|
//set the selected.
|
||||||
|
showOnlyBinary.setSelected(symbolOptions.showOnlyBinary);
|
||||||
|
|
||||||
|
setSettingsPane();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int checkClassNamesBox(DLSymbolModifierParams symbolOptions, JComboBox<String> classNameBox) {
|
||||||
|
|
||||||
|
DLClassName[] classNames = dlSymbolModifier.getDLAnnotType().getDlControl().getDLModel().getClassNames();
|
||||||
|
|
||||||
|
// for (int i =0; i<classNames.length; i++) {
|
||||||
|
// System.out.println("DLSymbolOptionsPane: classNames: " + i + " " + classNames[i].className);
|
||||||
|
// }
|
||||||
|
|
||||||
|
int nClass = dlSymbolModifier.getDLAnnotType().getDlControl().getDLModel().getNumClasses();
|
||||||
|
|
||||||
|
classNameBox.removeAllItems();
|
||||||
|
for (int i=0; i<nClass; i++) {
|
||||||
|
if (classNames!=null && classNames.length>i) {
|
||||||
|
classNameBox.addItem(classNames[i].className);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
classNameBox.addItem("Class: " + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nClass;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set parameters for controls to change the colour gradient based on prediction.
|
||||||
|
* @param symbolOptions - the symbol options
|
||||||
|
*/
|
||||||
|
private void setPredictionColParams(DLSymbolModifierParams symbolOptions) {
|
||||||
|
|
||||||
|
//now set frequency parameters
|
||||||
|
colorRangeSlider.setValue((int) symbolOptions.clims[0]*100);
|
||||||
|
colorRangeSlider.setUpperValue((int) symbolOptions.clims[1]*100);
|
||||||
|
// colorRangeSlider.setColourArrayType( symbolOptions.colArray);
|
||||||
|
|
||||||
|
colorRangeSlider.setColourMap(PamUtilsFX.fxColArray2Swing(symbolOptions.colArray));
|
||||||
|
|
||||||
|
|
||||||
|
int nClass = checkClassNamesBox( symbolOptions, classNameBox);
|
||||||
|
|
||||||
|
symbolOptions.classIndex = Math.min(symbolOptions.classIndex, nClass-1);
|
||||||
|
classNameBox.setSelectedIndex(Math.max(symbolOptions.classIndex, 0));
|
||||||
|
|
||||||
|
//color box.
|
||||||
|
colorComboBox.setSelectedColourMap(PamUtilsFX.fxColArray2Swing(symbolOptions.colArray));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set parameters for controls to change the colour gradient based on prediction.
|
||||||
|
* @param symbolOptions - the symbol options
|
||||||
|
*/
|
||||||
|
private void setClassColParams(DLSymbolModifierParams symbolOptions) {
|
||||||
|
|
||||||
|
//create a temporary array to save different class colours in - this needs to be
|
||||||
|
//before other params are set.
|
||||||
|
this.classColours = symbolOptions.classColors;
|
||||||
|
|
||||||
|
|
||||||
|
int nClass = checkClassNamesBox( symbolOptions, classNameBox2);
|
||||||
|
|
||||||
|
symbolOptions.classIndex = Math.min(symbolOptions.classIndex, nClass-1);
|
||||||
|
|
||||||
|
classNameBox2.setSelectedIndex(Math.max(symbolOptions.classIndex2, 0));
|
||||||
|
|
||||||
|
|
||||||
|
// int index = symbolOptions.classIndex2>=0 ? symbolOptions.classIndex2 : 0;
|
||||||
|
|
||||||
|
if (symbolOptions.classColors==null) {
|
||||||
|
symbolOptions.setDefaultClassColors(nClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (classNameBox2.getSelectedIndex()>=0) {
|
||||||
|
colourButton.setBackground(PamAWTUtils.intToColor(classColours[classNameBox2.getSelectedIndex()]));
|
||||||
|
colourButton.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// //set the correct colour
|
||||||
|
// colorPicker.setColor(symbolOptions.classColors[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get parameters for colouring by class.
|
||||||
|
* @param symbolOptions - the symbol options.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public DLSymbolModifierParams getClassColParams(DLSymbolModifierParams symbolOptions ) {
|
||||||
|
|
||||||
|
// int index = classNameBox2.getSelectedIndex()>=0 ? classNameBox2.getSelectedIndex():0;
|
||||||
|
|
||||||
|
symbolOptions.classColors = classColours;
|
||||||
|
|
||||||
|
symbolOptions.classIndex2 = classNameBox2.getSelectedIndex();
|
||||||
|
|
||||||
|
return symbolOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param symbolOptions
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public DLSymbolModifierParams getPredictionColParams(DLSymbolModifierParams symbolOptions ) {
|
||||||
|
|
||||||
|
symbolOptions.clims=new double[] {((double) colorRangeSlider.getValue())/100., ((double) colorRangeSlider.getUpperValue())/100.};
|
||||||
|
|
||||||
|
symbolOptions.colArray = PamUtilsFX.swingColArray2FX(this.colorComboBox.getSelectedColourMap());
|
||||||
|
|
||||||
|
symbolOptions.classIndex = classNameBox.getSelectedIndex();
|
||||||
|
|
||||||
|
return symbolOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getParams() {
|
||||||
|
|
||||||
|
//bit messy but works
|
||||||
|
DLSymbolModifierParams symbolOptions = dlSymbolModifier.getSymbolModifierParams().clone();
|
||||||
|
|
||||||
|
//need to check this here.
|
||||||
|
//checkClassNamesBox(symbolOptions);
|
||||||
|
|
||||||
|
if (b1.isSelected()) symbolOptions.colTypeSelection = DLSymbolModifierParams.PREDICITON_COL;
|
||||||
|
if (b2.isSelected()) symbolOptions.colTypeSelection = DLSymbolModifierParams.CLASS_COL;
|
||||||
|
|
||||||
|
//get parameters for colouring
|
||||||
|
symbolOptions = getClassColParams(symbolOptions);
|
||||||
|
|
||||||
|
//get parameters for colouring by prediction value
|
||||||
|
symbolOptions = getPredictionColParams(symbolOptions) ;
|
||||||
|
|
||||||
|
symbolOptions.showOnlyBinary = showOnlyBinary.isSelected();
|
||||||
|
|
||||||
|
dlSymbolModifier.checkColourArray();
|
||||||
|
|
||||||
|
//set the paratmers.
|
||||||
|
dlSymbolModifier.setSymbolModifierParams(symbolOptions);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void setSettingsPane() {
|
||||||
|
holder.removeAll();
|
||||||
|
//holder.setLayout(new BorderLayout());
|
||||||
|
holder.validate();
|
||||||
|
|
||||||
|
if (b1.isSelected()) {
|
||||||
|
holder.add(probPane, BorderLayout.CENTER);
|
||||||
|
} else if (b2.isSelected()) {
|
||||||
|
holder.add(classPane, BorderLayout.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.validate();
|
||||||
|
mainPanel.validate();
|
||||||
|
|
||||||
|
if (mainPanel.getRootPane()!=null) {
|
||||||
|
//pack the dialog because it is a different size
|
||||||
|
((GenericSwingDialog) mainPanel.getRootPane().getParent()).pack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private JPanel createClassPane() {
|
||||||
|
|
||||||
|
classNameBox2 = new JComboBox<>();
|
||||||
|
classNameBox2.addActionListener((action)->{
|
||||||
|
//make sure the setting button shows the colour
|
||||||
|
if (classNameBox2.getSelectedIndex()>=0) {
|
||||||
|
colourButton.setBackground(PamAWTUtils.intToColor(classColours[classNameBox2.getSelectedIndex()]));
|
||||||
|
}
|
||||||
|
setSettingsPane();
|
||||||
|
});
|
||||||
|
|
||||||
|
classNameBox2.setPreferredSize(new Dimension((int) CLASS_NAME_BOX_WIDTH, 25));
|
||||||
|
|
||||||
|
// colorPicker.setPreferredSize(new Dimension(60, 25));
|
||||||
|
colourButton = new PamButton("Color");
|
||||||
|
colourButton.addActionListener((action)->{
|
||||||
|
Color color = JColorChooser.showDialog(colourButton, "Pick colour for class", PamAWTUtils.intToColor(classColours[classNameBox2.getSelectedIndex()]));
|
||||||
|
if (color!=null) {
|
||||||
|
colourButton.setBackground(color);
|
||||||
|
// colourButton.setForeground(color);
|
||||||
|
classColours[classNameBox2.getSelectedIndex()]=PamAWTUtils.colorToInt(color);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
JPanel classHolder = new JPanel();
|
||||||
|
FlowLayout flowLayout = new FlowLayout();
|
||||||
|
classHolder.setLayout(flowLayout);
|
||||||
|
|
||||||
|
classHolder.add(classNameBox2);
|
||||||
|
classHolder.add(colourButton);
|
||||||
|
|
||||||
|
return classHolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private PamPanel createProbPane() {
|
||||||
|
PamPanel holder = new PamPanel();
|
||||||
|
holder.setLayout(new GridBagLayout());
|
||||||
|
|
||||||
|
GridBagConstraints c = new GridBagConstraints();
|
||||||
|
|
||||||
|
c.gridx = 0;
|
||||||
|
c.gridy = 0;
|
||||||
|
|
||||||
|
holder.add(new JLabel("Select class"), c);
|
||||||
|
|
||||||
|
c.gridx++;
|
||||||
|
classNameBox = new JComboBox<String>();
|
||||||
|
holder.add(classNameBox, c);
|
||||||
|
|
||||||
|
c.gridx = 0;
|
||||||
|
c.gridwidth = 1;
|
||||||
|
c.gridy++;
|
||||||
|
holder.add(new JLabel("Color map"), c);
|
||||||
|
|
||||||
|
c.gridx++;
|
||||||
|
colorComboBox = new ColourComboBox();
|
||||||
|
colorComboBox.addActionListener((action)->{
|
||||||
|
colorRangeSlider.setColourMap(colorComboBox.getSelectedColourMap());
|
||||||
|
colorRangeSlider.repaint();
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.add(colorComboBox, c);
|
||||||
|
|
||||||
|
c.gridx = 0;
|
||||||
|
c.gridy++;
|
||||||
|
c.gridwidth =2;
|
||||||
|
colorRangeSlider = new ColourRangeSlider(0, 100, JSlider.HORIZONTAL); // Min 0, Max 1 for probabilities
|
||||||
|
colorRangeSlider.setPaintTicks(true);
|
||||||
|
colorRangeSlider.setMinorTickSpacing(20);
|
||||||
|
holder.add(colorRangeSlider, c);
|
||||||
|
|
||||||
|
return holder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
setSettingsPane();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
49
src/rawDeepLearningClassifier/dataSelector/DLDataFilter.java
Normal file
49
src/rawDeepLearningClassifier/dataSelector/DLDataFilter.java
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package rawDeepLearningClassifier.dataSelector;
|
||||||
|
|
||||||
|
import PamView.dialog.PamDialogPanel;
|
||||||
|
import PamguardMVC.PamDataUnit;
|
||||||
|
import PamguardMVC.dataSelector.DataSelectParams;
|
||||||
|
import pamViewFX.fxSettingsPanes.DynamicSettingsPane;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Score a data unit with a deep learning annotation. Note that this could be an
|
||||||
|
* external data unit with an annotation e.g. a click, or deep learning
|
||||||
|
* detections generated by the deep learning module.
|
||||||
|
*
|
||||||
|
* @author Jamie Macaulay
|
||||||
|
*/
|
||||||
|
public interface DLDataFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Score a data unit with deep learning annotations
|
||||||
|
* @param dataUnit - the data unit to score
|
||||||
|
* @return 0 to reject and >0 to accept.
|
||||||
|
*/
|
||||||
|
public int scoreDLData(PamDataUnit dataUnit);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get parameters for the data filter.
|
||||||
|
* @return parameters for the data selectors.
|
||||||
|
*/
|
||||||
|
public DataSelectParams getParams();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the parameters for the data filter.
|
||||||
|
* @param params - the parameters to set.
|
||||||
|
*/
|
||||||
|
public void setParams(DataSelectParams params);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings controls for the deep learning filter.
|
||||||
|
* @return the controls for this filter.
|
||||||
|
*/
|
||||||
|
public DynamicSettingsPane<DataSelectParams> getSettingsPane();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swing settings controls for the data deep learning filter.
|
||||||
|
* @return Swing dialog for the settings
|
||||||
|
*/
|
||||||
|
public PamDialogPanel getSettingsPanel();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package rawDeepLearningClassifier.dataSelector;
|
||||||
|
|
||||||
|
import PamguardMVC.dataSelector.DataSelectParams;
|
||||||
|
import PamguardMVC.dataSelector.DataSelector;
|
||||||
|
import annotation.DataAnnotationType;
|
||||||
|
import annotation.dataselect.AnnotationDataSelCreator;
|
||||||
|
import rawDeepLearningClassifier.DLControl;
|
||||||
|
import rawDeepLearningClassifier.logging.DLAnnotation;
|
||||||
|
import rawDeepLearningClassifier.logging.DLAnnotationType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a data selector for the deep learning module.
|
||||||
|
*
|
||||||
|
* @author Jamie Macaulay
|
||||||
|
*/
|
||||||
|
public class DLDataSelectCreator extends AnnotationDataSelCreator<DLAnnotation> {
|
||||||
|
|
||||||
|
private DLControl dlcontrol;
|
||||||
|
|
||||||
|
public DLDataSelectCreator(DLControl dlcontrol, DLAnnotationType type) {
|
||||||
|
super(type);
|
||||||
|
this.dlcontrol = dlcontrol;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataSelectParams createNewParams(String name) {
|
||||||
|
return new DLDataSelectorParams();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataSelector createDataSelector(DataAnnotationType<DLAnnotation> dataAnnotationType, String selectorName,
|
||||||
|
boolean allowScores, String selectorType) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return new DLDataSelector(dlcontrol, dataAnnotationType, null,
|
||||||
|
selectorName, allowScores);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
153
src/rawDeepLearningClassifier/dataSelector/DLDataSelector.java
Normal file
153
src/rawDeepLearningClassifier/dataSelector/DLDataSelector.java
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
package rawDeepLearningClassifier.dataSelector;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import PamView.dialog.PamDialogPanel;
|
||||||
|
import PamguardMVC.PamDataBlock;
|
||||||
|
import PamguardMVC.PamDataUnit;
|
||||||
|
import PamguardMVC.dataSelector.DataSelectParams;
|
||||||
|
import PamguardMVC.dataSelector.DataSelector;
|
||||||
|
import annotation.DataAnnotationType;
|
||||||
|
import annotation.dataselect.AnnotationDataSelector;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import pamViewFX.fxSettingsPanes.DynamicSettingsPane;
|
||||||
|
import rawDeepLearningClassifier.DLControl;
|
||||||
|
import rawDeepLearningClassifier.logging.DLAnnotation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data selector of DL data units. Note that data selectors are for deep leanring annotations
|
||||||
|
* rather than deep learning data units.
|
||||||
|
* <p>
|
||||||
|
* The data selector can have different types of data selectors which can
|
||||||
|
* depend on the classifier used and user choice.
|
||||||
|
* <p>
|
||||||
|
* Note that this is slightly different from DLPredicitoDecision
|
||||||
|
* as it deals with data units that may have a more than one prediction.
|
||||||
|
* i.e.
|
||||||
|
*/
|
||||||
|
public class DLDataSelector extends AnnotationDataSelector<DLAnnotation> {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swing panel for the data selector.
|
||||||
|
*/
|
||||||
|
private DLSelectPanel dlSelectPanel;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FX panel for the data selector.
|
||||||
|
*/
|
||||||
|
private DLSelectPaneFX dlSelectPaneFX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data filter for filtering.
|
||||||
|
*/
|
||||||
|
private List<DLDataFilter> dataFilters = new ArrayList<DLDataFilter> ();
|
||||||
|
|
||||||
|
|
||||||
|
private DLDataSelectorParams dlDataSelectParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for the data selector.
|
||||||
|
* @param dlcontrol - reference to the DLControl.
|
||||||
|
* @param pamDataBlock - the data block.
|
||||||
|
* @param selectorName - the selector name.
|
||||||
|
* @param allowScores - allow all the scores.
|
||||||
|
* @param selectorType - the selector type.
|
||||||
|
*/
|
||||||
|
public DLDataSelector(DLControl dlcontrol, DataAnnotationType<DLAnnotation> annotationType, PamDataBlock pamDataBlock,
|
||||||
|
String selectorName, boolean allowScores) {
|
||||||
|
super(annotationType, pamDataBlock, selectorName, allowScores);
|
||||||
|
/****New data filters go here****/
|
||||||
|
dataFilters.add(new DLPredictionFilter(dlcontrol));
|
||||||
|
|
||||||
|
//create default params
|
||||||
|
dlDataSelectParams = new DLDataSelectorParams();
|
||||||
|
dlDataSelectParams.dataSelectorParams = new DataSelectParams[dataFilters.size()];
|
||||||
|
for (int i=0; i<dataFilters.size() ; i++) {
|
||||||
|
dlDataSelectParams.dataSelectorParams[i] = dataFilters.get(i).getParams();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PamDialogPanel getDialogPanel() {
|
||||||
|
if (dlSelectPanel == null) {
|
||||||
|
dlSelectPanel = new DLSelectPanel(this);
|
||||||
|
}
|
||||||
|
return dlSelectPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DynamicSettingsPane<Boolean> getDialogPaneFX() {
|
||||||
|
if (dlSelectPaneFX == null) {
|
||||||
|
dlSelectPaneFX = new DLSelectPaneFX(this);
|
||||||
|
}
|
||||||
|
return dlSelectPaneFX;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParams(DataSelectParams dataSelectParams) {
|
||||||
|
|
||||||
|
if (dataSelectParams instanceof DLDataSelectorParams) {
|
||||||
|
dlDataSelectParams = (DLDataSelectorParams) dataSelectParams;
|
||||||
|
|
||||||
|
checkDataFilterParamsSize(dlDataSelectParams);
|
||||||
|
|
||||||
|
//set paramters for all data filters.
|
||||||
|
for (int i=0; i<dlDataSelectParams.dataSelectorParams.length; i++) {
|
||||||
|
dataFilters.get(i).setParams((DataSelectParams) dlDataSelectParams.dataSelectorParams[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check that the data filters are the corret size.
|
||||||
|
* @param dataSelectParams - the apramters to set.
|
||||||
|
*/
|
||||||
|
private void checkDataFilterParamsSize(DLDataSelectorParams dataSelectParams) {
|
||||||
|
if (dataSelectParams.dataSelectorParams==null || dataSelectParams.dataSelectorParams.length!=dataFilters.size()) {
|
||||||
|
dataSelectParams.dataSelectorParams = new DataSelectParams[dataFilters.size()];
|
||||||
|
for (int i=0; i<dataSelectParams.dataSelectorParams.length; i++) {
|
||||||
|
dataSelectParams.dataSelectorParams[i] = dataFilters.get(i).getParams();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DLDataSelectorParams getParams() {
|
||||||
|
//get the paramters from the pane.
|
||||||
|
|
||||||
|
for (int i=0; i<dlDataSelectParams.dataSelectorParams.length; i++) {
|
||||||
|
dlDataSelectParams.dataSelectorParams[i] = dataFilters.get(i).getParams();
|
||||||
|
}
|
||||||
|
return dlDataSelectParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double scoreData(PamDataUnit pamDataUnit) {
|
||||||
|
int score = dataFilters.get(dlDataSelectParams.dataSelectorIndex).scoreDLData(pamDataUnit);
|
||||||
|
return score>=0 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected double scoreData(PamDataUnit pamDataUnit, DLAnnotation annotation) {
|
||||||
|
int score = dataFilters.get(dlDataSelectParams.dataSelectorIndex).scoreDLData(pamDataUnit);
|
||||||
|
|
||||||
|
//the score is the index of the class that scores highest or -1 if it does not pass threshold prediciton.
|
||||||
|
//Need to make more simple here as scores in PG are 0 for not passed rather than negative.
|
||||||
|
|
||||||
|
return score>=0 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DLDataFilter getCurrentDataSelector() {
|
||||||
|
return dataFilters.get(dlDataSelectParams.dataSelectorIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DLDataFilter> getDataSelectors() {
|
||||||
|
return dataFilters;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package rawDeepLearningClassifier.dataSelector;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import PamguardMVC.dataSelector.DataSelectParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paramters for the DL data seelctor
|
||||||
|
*/
|
||||||
|
public class DLDataSelectorParams extends DataSelectParams implements Serializable, Cloneable{
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public int dataSelectorIndex = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of data selector parameters for different deep learning selectors.
|
||||||
|
*/
|
||||||
|
public DataSelectParams[] dataSelectorParams;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,140 @@
|
|||||||
|
package rawDeepLearningClassifier.dataSelector;
|
||||||
|
|
||||||
|
|
||||||
|
import PamView.dialog.PamDialogPanel;
|
||||||
|
import PamguardMVC.PamDataUnit;
|
||||||
|
import PamguardMVC.dataSelector.DataSelectParams;
|
||||||
|
import pamViewFX.fxSettingsPanes.DynamicSettingsPane;
|
||||||
|
import rawDeepLearningClassifier.DLControl;
|
||||||
|
import rawDeepLearningClassifier.dlClassification.DLDetection;
|
||||||
|
import rawDeepLearningClassifier.dlClassification.PredictionResult;
|
||||||
|
import rawDeepLearningClassifier.logging.DLAnnotation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A data filter which filters data by the maximum prediction value
|
||||||
|
* for different classes.
|
||||||
|
*
|
||||||
|
* @author Jamie Macaulay
|
||||||
|
*/
|
||||||
|
public class DLPredictionFilter implements DLDataFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to the DLControl
|
||||||
|
*/
|
||||||
|
private DLControl dlcontrol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The filter parameters
|
||||||
|
*/
|
||||||
|
private DLPredictionFilterParams filterParams = new DLPredictionFilterParams();
|
||||||
|
|
||||||
|
private DLPredictonPane dlPredictonPane;
|
||||||
|
|
||||||
|
private DLPredictionPanel dlPredictonPanel;
|
||||||
|
|
||||||
|
public DLPredictionFilter(DLControl dlcontrol) {
|
||||||
|
this.dlcontrol = dlcontrol;
|
||||||
|
checkParamsClass() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int scoreDLData(PamDataUnit dataUnit) {
|
||||||
|
|
||||||
|
|
||||||
|
DLAnnotation annotation = (DLAnnotation) dataUnit. findDataAnnotation(DLAnnotation.class) ;
|
||||||
|
|
||||||
|
if (annotation==null) return -1;
|
||||||
|
|
||||||
|
//iterate through all results and check that at least one class passes data selection.
|
||||||
|
float[] results;
|
||||||
|
int maxClassIndex = -1;
|
||||||
|
int maxPred = -1;
|
||||||
|
|
||||||
|
//get the maximum prediction index which passes the minimum threshold
|
||||||
|
for (PredictionResult modelResult: annotation.getModelResults()) {
|
||||||
|
results = modelResult.getPrediction();
|
||||||
|
for (int j=0; j<results.length; j++) {
|
||||||
|
if (filterParams.classSelect[j] && results[j]>filterParams.minClassPredicton[j]) {
|
||||||
|
if (results[j]> maxPred) maxClassIndex = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return maxClassIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DLPredictionFilterParams getParams() {
|
||||||
|
checkParamsClass() ;
|
||||||
|
return filterParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParams(DataSelectParams params) {
|
||||||
|
this.filterParams = ((DLPredictionFilterParams) params).clone();
|
||||||
|
checkParamsClass();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkParamsClass() {
|
||||||
|
if (filterParams.classSelect==null || dlcontrol.getNumClasses()!=filterParams.classSelect.length) {
|
||||||
|
filterParams.classSelect = new boolean[dlcontrol.getNumClasses()];
|
||||||
|
filterParams.minClassPredicton = new double[dlcontrol.getNumClasses()];
|
||||||
|
|
||||||
|
//set default so data selector does not always prevent all classes from showing.
|
||||||
|
for (int i=0; i<filterParams.classSelect.length; i++) {
|
||||||
|
filterParams.classSelect[i]=true;
|
||||||
|
filterParams.minClassPredicton[i]=0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DynamicSettingsPane getSettingsPane() {
|
||||||
|
if (dlPredictonPane ==null) {
|
||||||
|
dlPredictonPane = new DLPredictonPane(this);
|
||||||
|
}
|
||||||
|
return dlPredictonPane;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PamDialogPanel getSettingsPanel() {
|
||||||
|
if (dlPredictonPanel ==null) {
|
||||||
|
dlPredictonPanel = new DLPredictionPanel(this);
|
||||||
|
}
|
||||||
|
return dlPredictonPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public DLControl getDLControl() {
|
||||||
|
return this.dlcontrol;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Get the index of the highest prediciton value a list of results.
|
||||||
|
// * @param predictions - index of the highest prediction within a matrix of predicitons.
|
||||||
|
// * @return an index of the hghest predictions.
|
||||||
|
// */
|
||||||
|
// public static int[] getBestClass(List<PredictionResult> predictions) {
|
||||||
|
//
|
||||||
|
// float[][] results = new float[predictions.size()][];
|
||||||
|
//
|
||||||
|
// //A detection might have multiple prediction results, i.e. predictions are a matrix. Need
|
||||||
|
// //to iterate through all the predictions and then work out whihc is the maximum. That index is then then]
|
||||||
|
// //class colour.
|
||||||
|
// int i=0;
|
||||||
|
// for (PredictionResult modelResult: predictions) {
|
||||||
|
// results[i] = modelResult.getPrediction();
|
||||||
|
// i++;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// int[] indexBest = PamArrayUtils.maxPos(results);
|
||||||
|
//
|
||||||
|
// return indexBest;
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package rawDeepLearningClassifier.dataSelector;
|
||||||
|
|
||||||
|
import PamguardMVC.dataSelector.DataSelectParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parameters for filtering by the minimum prediciton value.
|
||||||
|
*/
|
||||||
|
public class DLPredictionFilterParams extends DataSelectParams implements Cloneable{
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array indicating which classes are to be used in data selection
|
||||||
|
*/
|
||||||
|
public boolean[] classSelect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum class prediction.
|
||||||
|
*/
|
||||||
|
public double[] minClassPredicton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone the parameters.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public DLPredictionFilterParams clone() {
|
||||||
|
try {
|
||||||
|
return (DLPredictionFilterParams) super.clone();
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,183 @@
|
|||||||
|
package rawDeepLearningClassifier.dataSelector;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
import java.awt.Label;
|
||||||
|
|
||||||
|
import javax.swing.JCheckBox;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JSpinner;
|
||||||
|
import javax.swing.JToggleButton;
|
||||||
|
import javax.swing.SpinnerNumberModel;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
|
||||||
|
import org.kordamp.ikonli.materialdesign2.MaterialDesignL;
|
||||||
|
import org.kordamp.ikonli.swing.FontIcon;
|
||||||
|
|
||||||
|
import PamView.dialog.PamDialogPanel;
|
||||||
|
import PamView.dialog.PamGridBagContraints;
|
||||||
|
import PamView.panel.PamPanel;
|
||||||
|
import rawDeepLearningClassifier.dlClassification.DLClassName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swing panel for Deep learning predicitons.
|
||||||
|
*/
|
||||||
|
public class DLPredictionPanel implements PamDialogPanel {
|
||||||
|
|
||||||
|
private DLPredictionFilter predicitonFilter;
|
||||||
|
|
||||||
|
private PamPanel contentPanel;
|
||||||
|
|
||||||
|
private JCheckBox[] enableClass;
|
||||||
|
|
||||||
|
private JSpinner[] spinnerClass;
|
||||||
|
|
||||||
|
private JToggleButton lockButton;
|
||||||
|
|
||||||
|
|
||||||
|
public DLPredictionPanel(DLPredictionFilter dlPredictionFilter) {
|
||||||
|
super();
|
||||||
|
this.predicitonFilter = dlPredictionFilter;
|
||||||
|
|
||||||
|
contentPanel = new PamPanel();
|
||||||
|
contentPanel.setLayout(new GridBagLayout());
|
||||||
|
|
||||||
|
lockButton = new JToggleButton();
|
||||||
|
|
||||||
|
FontIcon iconlock = FontIcon.of(MaterialDesignL.LOCK);
|
||||||
|
iconlock.setIconSize(20);
|
||||||
|
iconlock.setIconColor(Color.DARK_GRAY);
|
||||||
|
|
||||||
|
FontIcon iconlockopen = FontIcon.of(MaterialDesignL.LOCK_OPEN);
|
||||||
|
iconlockopen.setIconSize(20);
|
||||||
|
iconlockopen.setIconColor(Color.DARK_GRAY);
|
||||||
|
|
||||||
|
lockButton.setIcon(iconlockopen);
|
||||||
|
|
||||||
|
lockButton.addActionListener((action)->{
|
||||||
|
if (lockButton.isSelected()) {
|
||||||
|
lockButton.setIcon(iconlock);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lockButton.setIcon(iconlockopen);
|
||||||
|
}
|
||||||
|
lockButton.validate();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JComponent getDialogComponent() {
|
||||||
|
return contentPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParams() {
|
||||||
|
|
||||||
|
DLPredictionFilterParams params = predicitonFilter.getParams();
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
setClassPane(params);
|
||||||
|
|
||||||
|
for (int i=0; i<params.classSelect.length ; i++) {
|
||||||
|
//set the correct params
|
||||||
|
enableClass[i].setSelected(params.classSelect[i]);
|
||||||
|
spinnerClass[i].setValue(params.minClassPredicton[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void setClassPane(DLPredictionFilterParams input) {
|
||||||
|
DLClassName[] classNames = predicitonFilter.getDLControl().getDLModel().getClassNames();
|
||||||
|
contentPanel.removeAll();
|
||||||
|
|
||||||
|
enableClass = new JCheckBox[input.classSelect.length];
|
||||||
|
spinnerClass = new JSpinner[input.classSelect.length];
|
||||||
|
|
||||||
|
GridBagConstraints c = new PamGridBagContraints();
|
||||||
|
c.ipadx =5;
|
||||||
|
|
||||||
|
c.gridwidth=2;
|
||||||
|
contentPanel.add(new Label("Min. prediciton for each class"), c);
|
||||||
|
c.gridwidth=1;
|
||||||
|
c.gridy++;
|
||||||
|
|
||||||
|
|
||||||
|
for (int i=0; i<input.classSelect.length ; i++) {
|
||||||
|
|
||||||
|
//create the row
|
||||||
|
c.gridx = 0;
|
||||||
|
|
||||||
|
enableClass[i] = new JCheckBox(classNames[i].className);
|
||||||
|
final int ii = i;
|
||||||
|
enableClass[i].addActionListener((action)->{
|
||||||
|
spinnerClass[ii].setEnabled(enableClass[ii].isSelected());
|
||||||
|
});
|
||||||
|
enableClass[i].setToolTipText(classNames[i].className);
|
||||||
|
contentPanel.add(enableClass[i], c);
|
||||||
|
|
||||||
|
c.gridx = 1;
|
||||||
|
|
||||||
|
|
||||||
|
spinnerClass[i] = new JSpinner(new SpinnerNumberModel(0., 0., 1., 0.05));
|
||||||
|
|
||||||
|
Dimension prefSize = spinnerClass[i].getPreferredSize();
|
||||||
|
prefSize = new Dimension(60, prefSize.height);
|
||||||
|
spinnerClass[i] .setPreferredSize(prefSize);
|
||||||
|
|
||||||
|
spinnerClass[i].addChangeListener(new ChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void stateChanged(ChangeEvent e) {
|
||||||
|
if (lockButton.isSelected()) {
|
||||||
|
for (int j=0; j<spinnerClass.length ; j++) {
|
||||||
|
if (j!=ii) {
|
||||||
|
spinnerClass[j].setValue(spinnerClass[ii].getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
spinnerClass[i].setToolTipText(classNames[i].className);
|
||||||
|
|
||||||
|
contentPanel.add(spinnerClass[i], c);
|
||||||
|
|
||||||
|
if (i==0 && input.classSelect.length>1) {
|
||||||
|
//set a lock button to
|
||||||
|
c.gridx=2;
|
||||||
|
contentPanel.add(lockButton, c);
|
||||||
|
|
||||||
|
//make the lock button the same height as the spinner
|
||||||
|
Dimension prefSizeB = lockButton.getPreferredSize();
|
||||||
|
lockButton.setPreferredSize(new Dimension(prefSizeB.width, prefSize.height));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
c.gridy++;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
contentPanel.validate();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getParams() {
|
||||||
|
|
||||||
|
DLPredictionFilterParams currParams = predicitonFilter.getParams();
|
||||||
|
|
||||||
|
for (int i=0; i<spinnerClass.length ; i++) {
|
||||||
|
currParams.classSelect[i] = enableClass[i].isSelected();
|
||||||
|
currParams.minClassPredicton[i] = (double) spinnerClass[i].getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
predicitonFilter.setParams(currParams);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
207
src/rawDeepLearningClassifier/dataSelector/DLPredictonPane.java
Normal file
207
src/rawDeepLearningClassifier/dataSelector/DLPredictonPane.java
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
package rawDeepLearningClassifier.dataSelector;
|
||||||
|
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.geometry.Pos;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import javafx.scene.control.CheckBox;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.Slider;
|
||||||
|
import javafx.scene.control.ToggleButton;
|
||||||
|
import javafx.scene.control.Tooltip;
|
||||||
|
import javafx.scene.layout.Priority;
|
||||||
|
import pamViewFX.PamGuiManagerFX;
|
||||||
|
import pamViewFX.fxGlyphs.PamGlyphDude;
|
||||||
|
import pamViewFX.fxNodes.PamBorderPane;
|
||||||
|
import pamViewFX.fxNodes.PamHBox;
|
||||||
|
import pamViewFX.fxNodes.PamVBox;
|
||||||
|
import pamViewFX.fxSettingsPanes.DynamicSettingsPane;
|
||||||
|
import rawDeepLearningClassifier.dlClassification.DLClassName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings pane for filtering deep learning results by class prediciton.
|
||||||
|
*/
|
||||||
|
public class DLPredictonPane extends DynamicSettingsPane<DLPredictionFilterParams>{
|
||||||
|
|
||||||
|
private DLPredictionFilter predicitonFilter;
|
||||||
|
|
||||||
|
private PamBorderPane mainPane;
|
||||||
|
|
||||||
|
private PamVBox contentPane;
|
||||||
|
|
||||||
|
private ClassDataSelector[] classPanes;
|
||||||
|
|
||||||
|
private ToggleButton toggelButton;
|
||||||
|
|
||||||
|
public DLPredictonPane(DLPredictionFilter predicitonFilter) {
|
||||||
|
super(null);
|
||||||
|
this.predicitonFilter=predicitonFilter;
|
||||||
|
createPane();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void createPane() {
|
||||||
|
mainPane = new PamBorderPane();
|
||||||
|
|
||||||
|
PamBorderPane topPane = new PamBorderPane();
|
||||||
|
|
||||||
|
Label label = new Label("Show classes above min. prediction");
|
||||||
|
PamBorderPane.setAlignment(label, Pos.BOTTOM_LEFT);
|
||||||
|
// label.setTextAlignment(TextAlignment.LEFT);
|
||||||
|
label.setAlignment(Pos.BOTTOM_LEFT);
|
||||||
|
|
||||||
|
topPane.setLeft(label);
|
||||||
|
|
||||||
|
toggelButton = new ToggleButton();
|
||||||
|
toggelButton.setTooltip(new Tooltip("Lock sliders together so one slider changes all values"));
|
||||||
|
|
||||||
|
toggelButton.setGraphic(PamGlyphDude.createPamIcon("mdi2l-lock-open", PamGuiManagerFX.iconSize));
|
||||||
|
toggelButton.selectedProperty().addListener((onsVal, oldVal,newVal)->{
|
||||||
|
if (newVal) {
|
||||||
|
toggelButton.setGraphic(PamGlyphDude.createPamIcon("mdi2l-lock", PamGuiManagerFX.iconSize));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
toggelButton.setGraphic(PamGlyphDude.createPamIcon("mdi2l-lock-open", PamGuiManagerFX.iconSize));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
toggelButton.setSelected(false);
|
||||||
|
|
||||||
|
topPane.setRight(toggelButton);
|
||||||
|
// topPane.setAlignment(Pos.CENTER_RIGHT);
|
||||||
|
|
||||||
|
contentPane = new PamVBox();
|
||||||
|
contentPane.setSpacing(5);
|
||||||
|
|
||||||
|
mainPane.setTop(topPane);
|
||||||
|
mainPane.setCenter(contentPane);
|
||||||
|
PamBorderPane.setMargin(topPane, new Insets(0,0,5.,0));
|
||||||
|
}
|
||||||
|
|
||||||
|
class ClassDataSelector extends PamHBox {
|
||||||
|
|
||||||
|
Slider slider;
|
||||||
|
|
||||||
|
CheckBox enable;
|
||||||
|
|
||||||
|
Label valueLabel;
|
||||||
|
|
||||||
|
private boolean enableListener = true;
|
||||||
|
|
||||||
|
ClassDataSelector(String classType, int index) {
|
||||||
|
|
||||||
|
enable = new CheckBox(classType);
|
||||||
|
enable.setPrefWidth(80);
|
||||||
|
enable.setTooltip(new Tooltip(classType));
|
||||||
|
enable.setOnAction((a)->{
|
||||||
|
//disable if the class is unticked.
|
||||||
|
slider.setDisable(!enable.isSelected());
|
||||||
|
valueLabel.setDisable(!enable.isSelected());
|
||||||
|
notifySettingsListeners();
|
||||||
|
});
|
||||||
|
|
||||||
|
slider = new Slider();
|
||||||
|
slider.setShowTickMarks(true);
|
||||||
|
slider.setMinorTickCount(10);
|
||||||
|
slider.setShowTickLabels(false);
|
||||||
|
slider.setMajorTickUnit(0.5);
|
||||||
|
|
||||||
|
slider.valueProperty().addListener((obsval, oldval, newval)->{
|
||||||
|
valueLabel.setText(String.format("%.2f", newval));
|
||||||
|
|
||||||
|
//if the lock button has been sleected then change all the sliders
|
||||||
|
//so that they are the same value as this slide (unless the class is disabled)
|
||||||
|
if (toggelButton.isSelected() && enableListener) {
|
||||||
|
for (int i=0; i<classPanes.length; i++) {
|
||||||
|
if (classPanes[i].enable.isSelected() && i!=index) {
|
||||||
|
|
||||||
|
classPanes[i].enableListener = false; //prevent needless calls to notify settings
|
||||||
|
classPanes[i].slider.setValue(newval.doubleValue());
|
||||||
|
classPanes[i].enableListener = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
notifySettingsListeners();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
slider.setMin(0.);
|
||||||
|
slider.setMax(1.);
|
||||||
|
|
||||||
|
PamHBox.setHgrow(slider, Priority.ALWAYS);
|
||||||
|
|
||||||
|
valueLabel = new Label();
|
||||||
|
valueLabel.setMinWidth(30);
|
||||||
|
|
||||||
|
valueLabel.setText(String.format("%.2f", slider.getValue()));
|
||||||
|
|
||||||
|
this.getChildren().addAll(enable, slider, valueLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DLPredictionFilterParams getParams(DLPredictionFilterParams currParams) {
|
||||||
|
|
||||||
|
for (int i=0; i<classPanes.length ; i++) {
|
||||||
|
currParams.classSelect[i] = classPanes[i].enable.isSelected();
|
||||||
|
currParams.minClassPredicton[i] = classPanes[i].slider.getValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return currParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParams(DLPredictionFilterParams input) {
|
||||||
|
//set the parameters. Note that class numbers should have been checked already.
|
||||||
|
setClassPane(input);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setClassPane(DLPredictionFilterParams input) {
|
||||||
|
DLClassName[] classNames = predicitonFilter.getDLControl().getDLModel().getClassNames();
|
||||||
|
contentPane.getChildren().clear();
|
||||||
|
|
||||||
|
classPanes = new ClassDataSelector[input.classSelect.length];
|
||||||
|
ClassDataSelector classPane;
|
||||||
|
for (int i=0; i<input.classSelect.length ; i++) {
|
||||||
|
classPane = new ClassDataSelector(classNames[i].className, i);
|
||||||
|
classPanes[i] = classPane;
|
||||||
|
contentPane.getChildren().add(classPane);
|
||||||
|
classPane.enable.setSelected(input.classSelect[i]);
|
||||||
|
|
||||||
|
classPane.slider.setValue(input.minClassPredicton[i]);
|
||||||
|
if (i==input.classSelect.length-1) {
|
||||||
|
classPane.slider.setShowTickLabels(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Check the class numbers are correct
|
||||||
|
// * @param input
|
||||||
|
// */
|
||||||
|
// private void checkSpeciesClassNumbers(DLPredictionFilterParams input) {
|
||||||
|
// this.predicitonFilter.getSpeciesClassList();
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Deep learning prediciton filter";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getContentNode() {
|
||||||
|
return mainPane;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paneInitialized() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
102
src/rawDeepLearningClassifier/dataSelector/DLSelectPaneFX.java
Normal file
102
src/rawDeepLearningClassifier/dataSelector/DLSelectPaneFX.java
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
package rawDeepLearningClassifier.dataSelector;
|
||||||
|
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import pamViewFX.fxNodes.PamBorderPane;
|
||||||
|
import pamViewFX.fxSettingsPanes.DynamicSettingsPane;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JavaFX pane for the deep learning data selector. This simply selects the rype
|
||||||
|
* of filter to use and sets that as the controls.
|
||||||
|
* <p>
|
||||||
|
* Note that at the moment this only implements one type of data filter and so
|
||||||
|
* essentially all controls etc. for changing filters are invisible to the user.
|
||||||
|
*
|
||||||
|
* @author Jamie Macaulay
|
||||||
|
*/
|
||||||
|
public class DLSelectPaneFX extends DynamicSettingsPane<Boolean>{
|
||||||
|
|
||||||
|
private PamBorderPane mainPane;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to the deep learning data selector.
|
||||||
|
*/
|
||||||
|
private DLDataSelector dlDataSelector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current index selected by the user - not in the params.
|
||||||
|
*/
|
||||||
|
private int currentIndex = 0;
|
||||||
|
|
||||||
|
public DLSelectPaneFX(DLDataSelector dlDataSelector) {
|
||||||
|
super(null);
|
||||||
|
this.dlDataSelector=dlDataSelector;
|
||||||
|
|
||||||
|
//there is currently one implemented fitler so no
|
||||||
|
//need for a comboBox etc. to select.
|
||||||
|
createPane();
|
||||||
|
|
||||||
|
// mainPane.getChildren().add(dlDataSelector.getDataSelectors().getSettingsPane().getContentNode());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createPane() {
|
||||||
|
mainPane = new PamBorderPane();
|
||||||
|
|
||||||
|
//need to add a settings listener to the filter panes to pass on any notification this settings listener.
|
||||||
|
for (int i=0; i<dlDataSelector.getDataSelectors().size(); i++) {
|
||||||
|
dlDataSelector.getDataSelectors().get(currentIndex).getSettingsPane().addSettingsListener(()->{
|
||||||
|
//notify any listeners to this pane that a filter pane has changed.
|
||||||
|
notifySettingsListeners();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean getParams(Boolean input) {
|
||||||
|
// System.out.println("Get params DL data selector!");
|
||||||
|
DLDataSelectorParams currParams = dlDataSelector.getParams();
|
||||||
|
|
||||||
|
//TODO - maybe should grab settings from all filters or just the selected one?
|
||||||
|
currParams.dataSelectorParams[currentIndex] = dlDataSelector.getDataSelectors().get(currentIndex).getSettingsPane().getParams(currParams.dataSelectorParams[currentIndex]);
|
||||||
|
|
||||||
|
dlDataSelector.setParams(currParams);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParams(Boolean input) {
|
||||||
|
DLDataSelectorParams currParams = dlDataSelector.getParams();
|
||||||
|
|
||||||
|
this.currentIndex = currParams.dataSelectorIndex;
|
||||||
|
|
||||||
|
dlDataSelector.getDataSelectors().get(currentIndex).getSettingsPane().setParams(currParams.dataSelectorParams[currentIndex]);
|
||||||
|
|
||||||
|
setDataFilterPane(currentIndex);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDataFilterPane(int index) {
|
||||||
|
DLDataFilter dlFilter = dlDataSelector.getDataSelectors().get(index);
|
||||||
|
mainPane.setCenter(dlFilter.getSettingsPane().getContentNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Filter by deep learning result";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Node getContentNode() {
|
||||||
|
return mainPane;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paneInitialized() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package rawDeepLearningClassifier.dataSelector;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
|
||||||
|
import PamView.dialog.PamDialogPanel;
|
||||||
|
import PamView.panel.PamPanel;
|
||||||
|
import javafx.scene.Node;
|
||||||
|
import pamViewFX.fxNodes.PamBorderPane;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swing panel for the deep learning data selector.
|
||||||
|
*/
|
||||||
|
public class DLSelectPanel implements PamDialogPanel {
|
||||||
|
|
||||||
|
private PamPanel mainPanel;
|
||||||
|
|
||||||
|
private DLDataSelector dlDataSelector;
|
||||||
|
|
||||||
|
private int currentIndex = 0;
|
||||||
|
|
||||||
|
public DLSelectPanel(DLDataSelector dlDataSelector) {
|
||||||
|
super();
|
||||||
|
this.dlDataSelector=dlDataSelector;
|
||||||
|
|
||||||
|
mainPanel = new PamPanel();
|
||||||
|
mainPanel.setLayout(new BorderLayout());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JComponent getDialogComponent() {
|
||||||
|
return mainPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void setDataFilterPane(int index) {
|
||||||
|
DLDataFilter dlFilter = dlDataSelector.getDataSelectors().get(index);
|
||||||
|
mainPanel.add(dlFilter.getSettingsPanel().getDialogComponent(), BorderLayout.CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParams() {
|
||||||
|
DLDataSelectorParams currParams = dlDataSelector.getParams();
|
||||||
|
|
||||||
|
this.currentIndex = currParams.dataSelectorIndex;
|
||||||
|
|
||||||
|
//set the stored paramters for the deep learning filter
|
||||||
|
dlDataSelector.getDataSelectors().get(currentIndex).setParams(currParams.dataSelectorParams[currentIndex]);
|
||||||
|
|
||||||
|
//set the paramters in the dialog - note the dialog will have areference ot the filter and so can access the r
|
||||||
|
//set params above.
|
||||||
|
dlDataSelector.getDataSelectors().get(currentIndex).getSettingsPanel().setParams();
|
||||||
|
|
||||||
|
//set the
|
||||||
|
setDataFilterPane(currentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getParams() {
|
||||||
|
|
||||||
|
DLDataSelectorParams currParams = dlDataSelector.getParams();
|
||||||
|
|
||||||
|
//dialog has a reference to the data filter and will change params.
|
||||||
|
boolean dataFilterOK = dlDataSelector.getDataSelectors().get(currentIndex).getSettingsPanel().getParams();
|
||||||
|
|
||||||
|
if (dataFilterOK) {
|
||||||
|
//TODO - maybe should grab settings from all filters or just the selected one?
|
||||||
|
currParams.dataSelectorParams[currentIndex] = dlDataSelector.getDataSelectors().get(currentIndex).getParams();
|
||||||
|
|
||||||
|
dlDataSelector.setParams(currParams);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -106,15 +106,15 @@ If using a deep learning model from a supported framework then all transforms ar
|
|||||||
|
|
||||||
_An AnimalSpot, Ketos or other supported deep learning model will automatically create a list of transforms with the appropriate settings. These is no need to use the advanced pane but it is there in case users wish to change transform settings for some reason_
|
_An AnimalSpot, Ketos or other supported deep learning model will automatically create a list of transforms with the appropriate settings. These is no need to use the advanced pane but it is there in case users wish to change transform settings for some reason_
|
||||||
|
|
||||||
### Default Models
|
### Exanmple Models
|
||||||
|
|
||||||
Default models are selectable from the menu button in the Deep Learning Pane. Default models are deep learning classifiers which are open source, known to be effective and have have been published in open access academic litrature; they are downloaded directly from a GitHub repository and then all associated settings are automtically applied. The default model selection pane also contains hyperlinks to the papers descirbing each model which will take users directly to the relvent website.
|
Example models are selectable from the menu button in the Deep Learning Pane. Default models are deep learning classifiers which are open source, known to be effective and have have been published in open access academic litrature; they are downloaded directly from a GitHub repository and then all associated settings are automtically applied. The default model selection pane also contains hyperlinks to the papers descirbing each model which will take users directly to the relvent website.
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img width="550" height="700" src = "resources/default_settings_humpback_1.png">
|
<img width="550" height="700" src = "resources/default_settings_humpback_1.png">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
_Default models can be downloaded. Default models are models which are published, open and have been known to work well amongst the bioacoustics community. More will be added to PAMGaurd over time. If you you would like your model to become a defualt model then drop PAMGuard support an email._
|
_Example models can be downloaded. Example models are models which are published, open and have been known to work well amongst the bioacoustics community. More will be added to PAMGaurd over time. If you you would like your model to become a defualt model then drop PAMGuard support an email._
|
||||||
|
|
||||||
## Running
|
## Running
|
||||||
|
|
||||||
@ -144,6 +144,26 @@ _An example click detection module output coloured by deep learning annotations.
|
|||||||
|
|
||||||
Other displays also show outputs from the deep learning module. Hovering over data units in the click display will, for example, show deep learning prediction values. The spectrogram will also show deep learning detections as translucent blue boxes (these must be selected in the right click menu).
|
Other displays also show outputs from the deep learning module. Hovering over data units in the click display will, for example, show deep learning prediction values. The spectrogram will also show deep learning detections as translucent blue boxes (these must be selected in the right click menu).
|
||||||
|
|
||||||
|
### Symbol Manager
|
||||||
|
|
||||||
|
The deep learning classifier has a symbol manager that is used throughtout different PAMGuard displays. The symbol manager can either display deep learning detections by the prediction values of a particular class or colour the output class with the highest prediciton class. Colouring by a prediction value requires the user to select which output class they wish to display - all detections are then coloured by the output prediction values for that particular class via a selectable colour map. If colour by class is selected then each detection is coloured by the class with the maximum prediction value. The colours for each class are selectable.
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img width="429" height="150" src = "resources/deep_learning_symbol_manager.png">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
_The options for the deep learning symbol manager_
|
||||||
|
|
||||||
|
### Data selector
|
||||||
|
|
||||||
|
The deep learning classifier has a data selector which is utilsied thorughout PAMGuard (for example for exporting detections, generating clips, showing on displays). The data selector allows users to filter detections based on a minimum prediciton values for different output classes. Classifiers with multiple classes can have different minimum predicitons values assigned to each class. The user interface allows user to use a slider to dynimically change the minimum prediciton value. The lock button clamps the minimum prediction values of all enabled output classes together.
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img width="190" height="170" src = "resources/deep_learning_data_selector.png">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
_The options for the deep learning data selector_
|
||||||
|
|
||||||
### MATLAB
|
### MATLAB
|
||||||
|
|
||||||
The easiest way to export to MATLAB is to select the desired units in the time base display, right click and select the MATLAB icon. Data units will be exported to a .mat file as list of structures which is then saved to the clipboard. This file can be saved and then dragged into MATLAB to open.
|
The easiest way to export to MATLAB is to select the desired units in the time base display, right click and select the MATLAB icon. Data units will be exported to a .mat file as list of structures which is then saved to the clipboard. This file can be saved and then dragged into MATLAB to open.
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user