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"/>
|
||||
</attributes>
|
||||
</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>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -111,3 +111,4 @@ settings.xml
|
||||
.classpath
|
||||
.classpath
|
||||
.settings/org.eclipse.jdt.core.prefs
|
||||
.classpath
|
||||
|
@ -1,5 +1,6 @@
|
||||
eclipse.preferences.version=1
|
||||
encoding//src/rawDeepLearningClassifer/segmenter/SegmenterProcess.java=UTF-8
|
||||
encoding//src/test=UTF-8
|
||||
encoding//src/test/resources=UTF-8
|
||||
encoding/<project>=UTF-8
|
||||
encoding/src=UTF-8
|
||||
|
@ -1,9 +1,9 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
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.compliance=17
|
||||
org.eclipse.jdt.core.compiler.compliance=21
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=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.reportPreviewFeatures=warning
|
||||
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/*.DSA</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
<exclude>test/resources/**</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
|
Binary file not shown.
28
pom.xml
28
pom.xml
@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.pamguard</groupId>
|
||||
<artifactId>Pamguard</artifactId>
|
||||
<version>2.02.12</version>
|
||||
<version>2.02.11d</version>
|
||||
<name>Pamguard</name>
|
||||
<description>Pamguard using Maven to control dependencies</description>
|
||||
<url>www.pamguard.org</url>
|
||||
@ -100,8 +100,8 @@
|
||||
<excludes>
|
||||
<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/*.RSA</exclude>
|
||||
<exclude>test/resources/**</exclude>
|
||||
<exclude>META-INF/*.RSA</exclude>
|
||||
<exclude>test/resources/**</exclude><!-- get rid of deep learning moduels and wav files used for unit tests -->
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
@ -180,25 +180,7 @@
|
||||
-->
|
||||
</executions>
|
||||
</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>
|
||||
|
||||
|
||||
@ -598,7 +580,7 @@
|
||||
<dependency>
|
||||
<groupId>com.fazecast</groupId>
|
||||
<artifactId>jSerialComm</artifactId>
|
||||
<version>2.11.0</version>
|
||||
<version>2.5.3</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/edu.emory.mathcs/JTransforms -->
|
||||
|
38
readme.md
38
readme.md
@ -1,26 +1,28 @@
|
||||
# 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.
|
||||
|
||||
# Why do we need PAMGuard?
|
||||
## Why do we need PAMGuard?
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
### 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]();
|
||||
|
||||
@ -36,31 +38,35 @@ PAMGuard is designed to collect/process data from large acosutic datasets. PAMGu
|
||||
### Access to detection and classification algorithms
|
||||
PAMGuard allows users to inegrate automated detection and classification algorithms directly into their acosutic workflow. There are a multitude of differwent algorothms to choose from, including a basic click detector, whislte and moan detector, GPL detector, click train detectors and many others. The idea behind PAMGuard is allow researchers to access open source state-of-the-art algorithms devleoped within the scientific community - if you want to contribute and get your algorithm into PAMGuard get in touch.
|
||||
|
||||
###Localisation
|
||||
### Localisation
|
||||
PAMGuard has a mutltude of different options for acoustic loclaisation. There's a comprehesnive beam forming module for beam forming arrays, a large aperture localiser for 3D loclaisation and target motion analysis for towed hydrophone arrays.
|
||||
|
||||
###Soundscape analysis
|
||||
### Soundscape analysis
|
||||
PAMGuard has a noise band (which supports third octave noise bands) and long term spectral average module for soundscape analysis.
|
||||
|
||||
### GIS
|
||||
Almsot all detection data can be visualised on a map. PAMGaurd also supports plotting GPS and AIS data.
|
||||
|
||||
### 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
|
||||
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
|
||||
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
|
||||
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
|
||||
* Capabaility to export data directly from PAMGaurd e.g. as MAT files.
|
||||
* Automated test suite to make releases more stable. Note that unit and integration tests are also being slowly incorporated.
|
||||
* 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.
|
||||
* Support for ARM based computers (in progress).
|
||||
* A graphical user interface and Python library for training PAMGuard compatible deep learning models.
|
||||
|
||||
## 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.
|
||||
|
@ -181,7 +181,6 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
|
||||
|
||||
this.acquisitionDialog = acquisitionDialog;
|
||||
|
||||
|
||||
return getDialogPanel();
|
||||
}
|
||||
|
||||
@ -198,7 +197,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
|
||||
|
||||
protected JPanel createDaqDialogPanel() {
|
||||
|
||||
JPanel p = new JPanel();
|
||||
PamPanel p = new PamPanel();
|
||||
p.setBorder(new TitledBorder("Select sound file"));
|
||||
GridBagLayout layout = new GridBagLayout();
|
||||
layout.columnWidths = new int[]{100, 100, 10};
|
||||
@ -253,6 +252,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
|
||||
// constraints.gridwidth = 2;
|
||||
// addComponent(p, fileDateText = new JTextField(), constraints);
|
||||
// fileDateText.setEnabled(false);
|
||||
|
||||
return p;
|
||||
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ import javafx.application.Platform;
|
||||
import pamguard.GlobalArguments;
|
||||
import Acquisition.pamAudio.PamAudioFileManager;
|
||||
import Acquisition.pamAudio.PamAudioFileFilter;
|
||||
import Acquisition.pamAudio.PamAudioFileLoader;
|
||||
import Acquisition.pamAudio.PamAudioSystem;
|
||||
import PamController.DataInputStore;
|
||||
import PamController.InputStoreInfo;
|
||||
@ -92,6 +93,12 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
||||
* Text field for skipping initial few seconds of a file.
|
||||
*/
|
||||
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
|
||||
public boolean runFileAnalysis() {
|
||||
@ -170,6 +177,8 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected JPanel createDaqDialogPanel() {
|
||||
JPanel p = new JPanel();
|
||||
@ -228,6 +237,7 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
||||
constraints.gridwidth = 2;
|
||||
constraints.fill = GridBagConstraints.NONE;
|
||||
constraints.anchor = GridBagConstraints.WEST;
|
||||
|
||||
addComponent(p, mergeFiles = new JCheckBox("Merge contiguous files"), constraints);
|
||||
if (PamController.getInstance().getRunMode() == PamController.RUN_PAMVIEW) {
|
||||
constraints.gridx+=2;
|
||||
@ -236,18 +246,28 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
||||
checkFiles.addActionListener(new CheckFiles());
|
||||
}
|
||||
|
||||
// if (SMRUEnable.isEnable()) {
|
||||
// if (SMRUEnable.isEnable()) {
|
||||
// no reason to hide this option from users.
|
||||
constraints.gridy++;
|
||||
constraints.gridx = 0;
|
||||
constraints.gridwidth = 1;
|
||||
addComponent(p, new JLabel("Skip initial :"), constraints);
|
||||
constraints.gridx++;
|
||||
addComponent(p, skipSecondsField = new JTextField(4), constraints);
|
||||
constraints.gridx++;
|
||||
addComponent(p, new JLabel("seconds"), constraints);
|
||||
constraints.anchor = GridBagConstraints.EAST;
|
||||
// }
|
||||
constraints.gridy++;
|
||||
constraints.gridx = 0;
|
||||
constraints.gridwidth = 1;
|
||||
addComponent(p, new JLabel("Skip initial :"), constraints);
|
||||
constraints.gridx++;
|
||||
addComponent(p, skipSecondsField = new JTextField(4), constraints);
|
||||
constraints.gridx++;
|
||||
addComponent(p, new JLabel("seconds"), constraints);
|
||||
// }
|
||||
|
||||
|
||||
//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;
|
||||
}
|
||||
@ -525,10 +545,14 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
||||
List<WavFileType> asList = allFiles;
|
||||
setSelectedFileTypes(acquisitionControl.soundFileTypes.getUsedTypes(allFiles));
|
||||
|
||||
//set the date of the first file.
|
||||
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
|
||||
// and set these
|
||||
|
||||
File file = getCurrentFile();
|
||||
if (file == null) return;
|
||||
AudioInputStream audioStream;
|
||||
@ -558,7 +582,7 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
||||
/****FX GUI stuff****/
|
||||
if (folderInputPane!=null) {
|
||||
Platform.runLater(()->{
|
||||
folderInputPane.newFileList(fileListData);
|
||||
folderInputPane.newFileList(fileListData);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -572,7 +596,39 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
||||
protected int fudgeNumChannels(int 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() {
|
||||
if (allFiles.size() > 0) {
|
||||
long fileTime = getFileStartTime(getCurrentFile());
|
||||
@ -768,6 +824,17 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
||||
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();
|
||||
}
|
||||
|
||||
@ -786,6 +853,7 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
||||
if (skipSecondsField!=null) {
|
||||
skipSecondsField.setText(String.format("%.1f", fileInputParameters.skipStartFileTime/1000.));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -950,6 +1018,8 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
|
||||
String bs = String.format("%d,%d,%d,%s", nFiles,currentFile,generalStatus,currFile);
|
||||
return bs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -6,23 +6,18 @@ import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Orientation;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.util.StringConverter;
|
||||
import pamViewFX.PamGuiManagerFX;
|
||||
import pamViewFX.fxGlyphs.PamGlyphDude;
|
||||
import pamViewFX.fxNodes.PamBorderPane;
|
||||
import pamViewFX.fxNodes.PamButton;
|
||||
import pamViewFX.fxNodes.PamComboBox;
|
||||
import pamViewFX.fxNodes.PamGridPane;
|
||||
import pamViewFX.fxNodes.PamHBox;
|
||||
import pamViewFX.fxNodes.PamTextField;
|
||||
import pamViewFX.fxNodes.PamVBox;
|
||||
import pamViewFX.fxNodes.flipPane.FlipPane;
|
||||
@ -43,7 +38,7 @@ import dataMap.filemaps.OfflineFileParameters;
|
||||
*/
|
||||
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.
|
||||
@ -120,13 +115,13 @@ public class AcquisitionPaneFX extends SettingsPane<AcquisitionParameters>{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private FlipPane flipPane;
|
||||
private PamFlipPane flipPane;
|
||||
|
||||
|
||||
/**
|
||||
* Pane which can be used for advanced settings.
|
||||
*/
|
||||
private PamBorderPane advancedSettingPane;
|
||||
// private PamBorderPane advancedSettingPane;
|
||||
|
||||
/**
|
||||
* Title label for the advanced pane.
|
||||
@ -147,12 +142,13 @@ public class AcquisitionPaneFX extends SettingsPane<AcquisitionParameters>{
|
||||
super(null);
|
||||
mainPane = new PamBorderPane();
|
||||
mainPane.setPrefWidth(400);
|
||||
mainPane.setPadding(new Insets(5,5,5,5));
|
||||
|
||||
this.acquisitionControl=aquisitionControl;
|
||||
this.acquisitionParameters=acquisitionControl.getAcquisitionParameters();
|
||||
|
||||
//create the flip pane.
|
||||
flipPane=new FlipPane();
|
||||
flipPane=new PamFlipPane();
|
||||
flipPane.setFlipDirection(Orientation.HORIZONTAL);
|
||||
flipPane.setFlipTime(PamFlipPane.FLIP_TIME); //default is 700ms- way too high
|
||||
//flipPane.prefWidthProperty().bind(mainPane.widthProperty());
|
||||
@ -166,45 +162,45 @@ public class AcquisitionPaneFX extends SettingsPane<AcquisitionParameters>{
|
||||
flipPane.getFront().getChildren().add(mainPane);
|
||||
|
||||
//create the advanced flip pane.
|
||||
advancedSettingPane = createAdvSettingsPane();
|
||||
flipPane.getBack().getChildren().add(advancedSettingPane);
|
||||
// advancedSettingPane = createAdvSettingsPane();
|
||||
// flipPane.getBack().getChildren().add(advancedSettingPane);
|
||||
//System.out.println("MAKE PANE: " + acquisitionParameters.getDaqSystemType());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the advanced settings pane which can be accessed by DAQ panes if needed.
|
||||
*/
|
||||
private PamBorderPane createAdvSettingsPane() {
|
||||
|
||||
PamButton back = new PamButton();
|
||||
back.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-left", Color.WHITE, PamGuiManagerFX.iconSize));
|
||||
|
||||
back.setOnAction((action)->{
|
||||
flipPane.flipToFront();
|
||||
});
|
||||
|
||||
PamBorderPane advPane = new PamBorderPane();
|
||||
advPane.setPadding(new Insets(5,5,5,5));
|
||||
|
||||
PamHBox buttonHolder = new PamHBox();
|
||||
|
||||
buttonHolder.setBackground(null);
|
||||
//buttonHolder.setStyle("-fx-background-color: red;");
|
||||
buttonHolder.setAlignment(Pos.CENTER_LEFT);
|
||||
buttonHolder.getChildren().addAll(back, advLabel = new Label("Adv. Settings"));
|
||||
advLabel.setAlignment(Pos.CENTER);
|
||||
advLabel.setMaxWidth(Double.MAX_VALUE); //need to make sure label is in center.
|
||||
PamGuiManagerFX.titleFont2style(advLabel);
|
||||
|
||||
advLabel.setAlignment(Pos.CENTER);
|
||||
HBox.setHgrow(advLabel, Priority.ALWAYS);
|
||||
|
||||
advPane.setTop(buttonHolder);
|
||||
|
||||
return advPane;
|
||||
|
||||
}
|
||||
// /**
|
||||
// * Create the advanced settings pane which can be accessed by DAQ panes if needed.
|
||||
// */
|
||||
// private PamBorderPane createAdvSettingsPane() {
|
||||
//
|
||||
// PamButton back = new PamButton();
|
||||
// back.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-left", Color.WHITE, PamGuiManagerFX.iconSize));
|
||||
//
|
||||
// back.setOnAction((action)->{
|
||||
// flipPane.flipToFront();
|
||||
// });
|
||||
//
|
||||
// PamBorderPane advPane = new PamBorderPane();
|
||||
// advPane.setPadding(new Insets(5,5,5,5));
|
||||
//
|
||||
// PamHBox buttonHolder = new PamHBox();
|
||||
//
|
||||
// buttonHolder.setBackground(null);
|
||||
// //buttonHolder.setStyle("-fx-background-color: red;");
|
||||
// buttonHolder.setAlignment(Pos.CENTER_LEFT);
|
||||
// buttonHolder.getChildren().addAll(back, advLabel = new Label("Adv. Settings"));
|
||||
// advLabel.setAlignment(Pos.CENTER);
|
||||
// advLabel.setMaxWidth(Double.MAX_VALUE); //need to make sure label is in center.
|
||||
// PamGuiManagerFX.titleFont2style(advLabel);
|
||||
//
|
||||
// advLabel.setAlignment(Pos.CENTER);
|
||||
// HBox.setHgrow(advLabel, Priority.ALWAYS);
|
||||
//
|
||||
// advPane.setTop(buttonHolder);
|
||||
//
|
||||
// return advPane;
|
||||
//
|
||||
// }
|
||||
|
||||
/**
|
||||
* Create the Sound Aquisition pane for real time monitoring.
|
||||
@ -606,11 +602,12 @@ public class AcquisitionPaneFX extends SettingsPane<AcquisitionParameters>{
|
||||
}
|
||||
|
||||
public PamBorderPane getAdvancedPane() {
|
||||
return this.advancedSettingPane;
|
||||
return this.flipPane.getAdvContentPane()
|
||||
;
|
||||
}
|
||||
|
||||
public Label getAdvancedLabel() {
|
||||
return this.advLabel;
|
||||
public TextField getAdvancedLabel() {
|
||||
return this.flipPane.getAdvLabel();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package Acquisition.layoutFX;
|
||||
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -12,6 +13,8 @@ import Acquisition.FileInputParameters;
|
||||
import Acquisition.FolderInputParameters;
|
||||
import Acquisition.FolderInputSystem;
|
||||
import Acquisition.pamAudio.PamAudioFileFilter;
|
||||
import Acquisition.pamAudio.PamAudioFileLoader;
|
||||
import Acquisition.pamAudio.PamAudioFileManager;
|
||||
import PamController.PamController;
|
||||
import PamController.PamFolders;
|
||||
import PamUtils.PamCalendar;
|
||||
@ -48,7 +51,7 @@ import pamViewFX.fxNodes.PamProgressBar;
|
||||
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
|
||||
*
|
||||
@ -147,6 +150,8 @@ public class FolderInputPane extends DAQSettingsPane<FolderInputParameters>{
|
||||
*/
|
||||
private ToggleButton mergeContigious;
|
||||
|
||||
private PamBorderPane audioHolderloader;
|
||||
|
||||
// /**
|
||||
// * The folder input system.
|
||||
// * @param folderInputSystem - the folder system.
|
||||
@ -245,8 +250,11 @@ public class FolderInputPane extends DAQSettingsPane<FolderInputParameters>{
|
||||
Label utilsLabel=new Label("Sound file utilities");
|
||||
PamGuiManagerFX.titleFont2style(utilsLabel);
|
||||
|
||||
//
|
||||
audioHolderloader = new PamBorderPane();
|
||||
|
||||
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.
|
||||
// if (PamController.getInstance().getRunMode() == PamController.RUN_PAMVIEW) {
|
||||
@ -361,6 +369,7 @@ public class FolderInputPane extends DAQSettingsPane<FolderInputParameters>{
|
||||
return new PamBorderPane(table);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -594,6 +603,9 @@ public class FolderInputPane extends DAQSettingsPane<FolderInputParameters>{
|
||||
this.table.getItems().addAll(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.
|
||||
if (fileList!=null && fileList.size()>0) {
|
||||
@ -609,6 +621,34 @@ public class FolderInputPane extends DAQSettingsPane<FolderInputParameters>{
|
||||
// fileDateStrip.setDate(folderInputSystem.getFileStartTime(selFiles[0]));
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -637,16 +677,30 @@ public class FolderInputPane extends DAQSettingsPane<FolderInputParameters>{
|
||||
public void setParams() {
|
||||
//set the parameters for the dialog.
|
||||
this.setParams(folderInputSystem.getFolderInputParameters());
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getParams() {
|
||||
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;
|
||||
else {
|
||||
this.folderInputSystem.setFolderInputParameters(params);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -178,7 +178,7 @@ public class OfflineWavFileServer extends OfflineFileServer<FileDataMapPoint> {
|
||||
return false;
|
||||
}
|
||||
|
||||
PamAudioFileLoader audioFile = PamAudioFileManager.getInstance().getAudioLoader(mapPoint.getSoundFile());
|
||||
PamAudioFileLoader audioFile = PamAudioFileManager.getInstance().getAudioFileLoader(mapPoint.getSoundFile());
|
||||
|
||||
if (audioFile==null) {
|
||||
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"));
|
||||
}
|
||||
|
||||
@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,
|
||||
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.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.sound.sampled.AudioInputStream;
|
||||
import javax.sound.sampled.UnsupportedAudioFileException;
|
||||
|
||||
import org.codehaus.plexus.util.FileUtils;
|
||||
|
||||
import Acquisition.sud.SudAudioFile;
|
||||
|
||||
/**
|
||||
* Central class for opening sound files.
|
||||
* <p>
|
||||
@ -56,7 +59,7 @@ public class PamAudioFileManager {
|
||||
* @param soundFile - the sound file
|
||||
* @return the audio file loader.
|
||||
*/
|
||||
public PamAudioFileLoader getAudioLoader(File soundFile) {
|
||||
public PamAudioFileLoader getAudioFileLoader(File soundFile) {
|
||||
for (int i = 0; i < pamAudioFileTypes.size(); i++) {
|
||||
if (isExtension(soundFile, pamAudioFileTypes.get(i))) {
|
||||
return pamAudioFileTypes.get(i);
|
||||
@ -169,6 +172,23 @@ public class PamAudioFileManager {
|
||||
public ArrayList<PamAudioFileLoader> getAudioFileLoaders() {
|
||||
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.
|
||||
|
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.jflac.sound.spi.FlacAudioFileReader;
|
||||
|
||||
import Acquisition.sud.SudAudioFileReader;
|
||||
|
||||
/**
|
||||
* 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.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
@ -12,7 +13,13 @@ import javax.swing.SwingUtilities;
|
||||
import org.pamguard.x3.sud.ChunkHeader;
|
||||
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.PamSettingManager;
|
||||
import PamController.PamSettings;
|
||||
import PamUtils.worker.PamWorkProgressMessage;
|
||||
import PamUtils.worker.PamWorkWrapper;
|
||||
import PamUtils.worker.PamWorker;
|
||||
@ -30,16 +37,32 @@ import PamUtils.worker.PamWorker;
|
||||
* @author Jamie Macaulay
|
||||
*
|
||||
*/
|
||||
public class SudAudioFile extends WavAudioFile {
|
||||
public class SudAudioFile extends WavAudioFile implements PamSettings {
|
||||
|
||||
private Object conditionSync = new Object();
|
||||
|
||||
private volatile PamWorker<AudioInputStream> worker;
|
||||
|
||||
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() {
|
||||
super();
|
||||
fileExtensions = new ArrayList<String>(Arrays.asList(new String[] { ".sud" }));
|
||||
PamSettingManager.getInstance().registerSettings(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -63,7 +86,7 @@ public class SudAudioFile extends WavAudioFile {
|
||||
if (new File(soundFile.getAbsolutePath() + "x").exists()) {
|
||||
// System.out.println("----NO NEED TO MAP SUD FILE-----" + soundFile);
|
||||
try {
|
||||
return new SudAudioFileReader().getAudioInputStream(soundFile);
|
||||
return new SudAudioFileReader(sudParams.zeroPad).getAudioInputStream(soundFile);
|
||||
} catch (UnsupportedAudioFileException | IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
@ -181,7 +204,7 @@ public class SudAudioFile extends WavAudioFile {
|
||||
// System.out.println("START OPEN SUD FILE:");
|
||||
|
||||
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:");
|
||||
|
||||
@ -216,5 +239,51 @@ 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.IOException;
|
||||
@ -25,15 +25,32 @@ public class SudAudioFileReader {
|
||||
*/
|
||||
SudParams sudParams;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor to create an Sud Audio reader with a
|
||||
* default true to zeropad sud files.
|
||||
* */
|
||||
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();
|
||||
//set up the sud params for default. i.e. just read files and
|
||||
//don't save any decompressed or meta data.
|
||||
// sudParams.saveWav = false;
|
||||
// sudParams.saveMeta = false;
|
||||
sudParams.setFileSave(false, false, false, false);
|
||||
sudParams.zeroPad = true;
|
||||
sudParams.zeroPad = 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param arr - the array to find the position of the maximum value.
|
||||
|
@ -159,4 +159,29 @@ public class PamAWTUtils {
|
||||
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.border.EmptyBorder;
|
||||
|
||||
import PamController.PamController;
|
||||
|
||||
public class GenericSwingDialog extends PamDialog {
|
||||
|
||||
private boolean allOk;
|
||||
@ -45,6 +47,9 @@ public class GenericSwingDialog extends PamDialog {
|
||||
* @return
|
||||
*/
|
||||
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);
|
||||
swingDialog.setParams();
|
||||
swingDialog.pack();
|
||||
|
@ -5,6 +5,7 @@ import javax.swing.JComponent;
|
||||
/**
|
||||
* General class for dialog panels which will be incorporated into one or
|
||||
* more actual dialogs.
|
||||
* Can be quickly opened with GenericSwingDialog
|
||||
* @author Doug Gillespie
|
||||
*
|
||||
*/
|
||||
|
@ -5,6 +5,7 @@ import java.awt.Color;
|
||||
import PamUtils.PamUtils;
|
||||
import PamView.GeneralProjector;
|
||||
import PamView.PamSymbolType;
|
||||
import PamView.dialog.PamDialogPanel;
|
||||
import PamView.symbol.PamSymbolChooser;
|
||||
import PamView.symbol.SymbolData;
|
||||
import PamguardMVC.PamDataUnit;
|
||||
@ -45,7 +46,15 @@ public class PeakFreqModifier extends SymbolModifier {
|
||||
*/
|
||||
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) {
|
||||
super(PEAK_FREQ_MODIFIER_NAME, symbolChooser, SymbolModType.FILLCOLOUR | SymbolModType.LINECOLOUR );
|
||||
@ -130,11 +139,20 @@ public class PeakFreqModifier extends SymbolModifier {
|
||||
@Override
|
||||
public SymbolModifierPane getOptionsPane() {
|
||||
//System.out.println("PEAK FREQ COLOUR ARRAY2: " + peakFreqSymbolOptions.freqColourArray);
|
||||
if (this.peakFreqOptions==null) {
|
||||
peakFreqOptions = new PeakFreqOptionsPane(this);
|
||||
peakFreqOptions.setParams();
|
||||
if (this.peakFreqOptionsPaneFX==null) {
|
||||
peakFreqOptionsPaneFX = new PeakFreqOptionsPane(this);
|
||||
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
|
||||
|
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) {
|
||||
return null;
|
||||
}
|
||||
JMenuItem menuItem = new JMenuItem("Options ...");
|
||||
JMenuItem menuItem = new JMenuItem("More options ...");
|
||||
menuItem.setToolTipText("More symbol options");
|
||||
menuItem.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
|
@ -8,12 +8,13 @@ import java.util.Enumeration;
|
||||
import javax.swing.tree.TreeNode;
|
||||
|
||||
import PamUtils.PamUtils;
|
||||
import PamView.dialog.PamDialogPanel;
|
||||
import PamView.symbol.modifier.SymbolModifier;
|
||||
|
||||
public class ModifierTreeNode implements TreeNode {
|
||||
private SymbolModifier modifier;
|
||||
private SymbolTreeRoot rootNode;
|
||||
private ArrayList<ChoiceTreeNode> choiceNodes;
|
||||
private ArrayList<TreeNode> choiceNodes;
|
||||
|
||||
public ModifierTreeNode(SymbolTreeRoot rootNode, SymbolModifier modifier) {
|
||||
super();
|
||||
@ -22,17 +23,25 @@ public class ModifierTreeNode implements TreeNode {
|
||||
int modBits = modifier.getModifyableBits();
|
||||
int nMod = Integer.bitCount(modBits);
|
||||
choiceNodes = new ArrayList<>();
|
||||
|
||||
int leafIndex = 0;
|
||||
|
||||
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++));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreeNode getChildAt(int childIndex) {
|
||||
return choiceNodes.get(childIndex);
|
||||
// return
|
||||
// return
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -73,16 +82,22 @@ public class ModifierTreeNode implements TreeNode {
|
||||
}
|
||||
|
||||
public void setModBitmap(int modBitMap) {
|
||||
for (ChoiceTreeNode cN : choiceNodes) {
|
||||
cN.checkBox.setSelected((cN.selectionBit & modBitMap) != 0);
|
||||
for (TreeNode tN : choiceNodes) {
|
||||
if (tN instanceof ChoiceTreeNode) {
|
||||
ChoiceTreeNode cN = (ChoiceTreeNode) tN;
|
||||
cN.checkBox.setSelected((cN.selectionBit & modBitMap) != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int getModBitmap() {
|
||||
int mp = 0;
|
||||
for (ChoiceTreeNode cN : choiceNodes) {
|
||||
if (cN.checkBox.isSelected()) {
|
||||
mp |= cN.selectionBit;
|
||||
for (TreeNode tN : choiceNodes) {
|
||||
if (tN instanceof ChoiceTreeNode) {
|
||||
ChoiceTreeNode cN = (ChoiceTreeNode) tN;
|
||||
if (cN.checkBox.isSelected()) {
|
||||
mp |= cN.selectionBit;
|
||||
}
|
||||
}
|
||||
}
|
||||
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.PamDialogPanel;
|
||||
import PamView.symbol.PamSymbolChooser;
|
||||
import PamView.symbol.StandardSymbolChooser;
|
||||
import PamView.symbol.StandardSymbolOptions;
|
||||
import PamView.symbol.modifier.SymbolModifier;
|
||||
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.
|
||||
@ -137,6 +135,7 @@ public class SymbolModifierPanel implements PamDialogPanel {
|
||||
JMenuItem optsItem = modifier.getModifierOptionsMenu();
|
||||
if (optsItem != null) {
|
||||
popMenu.add(optsItem);
|
||||
popMenu.addSeparator();
|
||||
}
|
||||
}
|
||||
if (nodeInd > 0) {
|
||||
|
@ -43,6 +43,10 @@ public class SymbolTreeRenderer extends DefaultTreeCellRenderer {
|
||||
if (value instanceof ChoiceTreeNode) {
|
||||
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);
|
||||
if (value instanceof ModifierTreeNode) {
|
||||
|
@ -411,7 +411,15 @@ public class RawDataTransforms {
|
||||
paddedRawData = new double[fftLength];
|
||||
rawData = getWaveData(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++) {
|
||||
paddedRawData[i] = rawData[i];//-rotData[i];
|
||||
}
|
||||
|
@ -13,6 +13,8 @@ public class CompoundDataSelector extends DataSelector {
|
||||
|
||||
private CompoundParams compoundParams = new CompoundParams();
|
||||
|
||||
private CompoundDialogPaneFX compoundPaneFX;
|
||||
|
||||
public CompoundDataSelector(PamDataBlock pamDataBlock, ArrayList<DataSelector> allSelectors,
|
||||
String selectorName, boolean allowScores, String selectorType) {
|
||||
super(pamDataBlock, selectorName, allowScores);
|
||||
@ -57,8 +59,10 @@ public class CompoundDataSelector extends DataSelector {
|
||||
|
||||
@Override
|
||||
public DynamicSettingsPane<Boolean> getDialogPaneFX() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
if (compoundPaneFX==null) {
|
||||
compoundPaneFX = new CompoundDialogPaneFX(this);
|
||||
}
|
||||
return compoundPaneFX;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -91,6 +95,9 @@ public class CompoundDataSelector extends DataSelector {
|
||||
score = Math.max(score, score2); // take the largest
|
||||
}
|
||||
}
|
||||
|
||||
// System.out.println("Hello Compound Data selector: " + score);
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
@ -101,4 +108,25 @@ public class CompoundDataSelector extends DataSelector {
|
||||
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;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JComponent;
|
||||
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() {
|
||||
if (dataPanel != null) {
|
||||
dataPanel.setParams();
|
||||
|
@ -97,6 +97,23 @@ public abstract class DataSelector {
|
||||
*/
|
||||
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
|
||||
* 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 {
|
||||
-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.sliders.PamRangeSlider;
|
||||
|
||||
/**
|
||||
* A range slider which shows a colour gradient between two thumbs.
|
||||
*
|
||||
* @author Jamie Macaulay
|
||||
*/
|
||||
public class ColourRangeSlider extends PamRangeSlider {
|
||||
|
||||
/**
|
||||
@ -18,13 +23,29 @@ public class ColourRangeSlider extends PamRangeSlider {
|
||||
}
|
||||
|
||||
public ColourRangeSlider(int min, int max){
|
||||
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){
|
||||
((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){
|
||||
((ColourRangeSliderUI) getUI()).setColourMap(colourMap);
|
||||
}
|
||||
|
@ -8,8 +8,7 @@ import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.WritableRaster;
|
||||
|
||||
|
||||
|
||||
import javax.swing.JSlider;
|
||||
|
||||
import PamView.ColourArray;
|
||||
import PamView.ColourArray.ColourArrayType;
|
||||
@ -78,6 +77,8 @@ public class ColourRangeSliderUI extends PamRangeSliderUI {
|
||||
|
||||
|
||||
private void createColourMapImage(){
|
||||
if (b.getOrientation() == JSlider.VERTICAL) {
|
||||
|
||||
// now make a standard amplitude image
|
||||
if (colourArray != null && colourArray.length > 0) {
|
||||
amplitudeImage = new BufferedImage(1, colourArray.length,
|
||||
@ -87,6 +88,15 @@ public class ColourRangeSliderUI extends PamRangeSliderUI {
|
||||
raster.setPixel(0, colourArray.length - i - 1, colourArray[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -119,26 +129,98 @@ public class ColourRangeSliderUI extends PamRangeSliderUI {
|
||||
|
||||
Rectangle trackBounds = trackRect;
|
||||
|
||||
// Determine position of selected range by moving from the middle
|
||||
// of one thumb to the other.
|
||||
int lowerY = thumbRect.y + (thumbRect.width / 2);
|
||||
int upperY = getUpperThumbRect().y + (getUpperThumbRect().width / 2);
|
||||
|
||||
// Determine track position.
|
||||
int cx = (trackBounds.width / 2) - 2;
|
||||
|
||||
// Save colour and shift position.
|
||||
Color oldColor = g.getColor();
|
||||
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);
|
||||
int cx;
|
||||
|
||||
if (b.getOrientation() == JSlider.VERTICAL) {
|
||||
|
||||
// Determine position of selected range by moving from the middle
|
||||
// of one thumb to the other.
|
||||
int lowerY = thumbRect.y + (thumbRect.width / 2);
|
||||
int upperY = getUpperThumbRect().y + (getUpperThumbRect().width / 2);
|
||||
|
||||
// Determine track position.
|
||||
cx = (trackBounds.width / 2) - 2;
|
||||
|
||||
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);
|
||||
|
||||
cx = (trackBounds.width / 2) - 2;
|
||||
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.translate(-(trackBounds.x + cx), -trackBounds.y);
|
||||
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
|
||||
* 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.PamDialogPanel;
|
||||
import PamView.dialog.PamGridBagContraints;
|
||||
import clickDetector.dataSelector.ClickDataSelector;
|
||||
import pamMaths.HistogramDisplay;
|
||||
import pamMaths.HistogramGraphicsLayer;
|
||||
import pamMaths.PamHistogram;
|
||||
@ -59,6 +60,7 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
||||
private JCheckBox amplitudeSelect;
|
||||
private JTextField minAmplitude;
|
||||
private JFrame ownerFrame;
|
||||
private ClickDataSelector dataSelector;
|
||||
/**
|
||||
* @param btDisplay
|
||||
*/
|
||||
@ -66,6 +68,7 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
||||
super();
|
||||
this.clickControl = clickControl;
|
||||
this.btDisplay = btDisplay;
|
||||
dataSelector = btDisplay.getClickDataSelector();
|
||||
clickDataBlock = clickControl.getClickDataBlock();
|
||||
histoPlot = new HistogramDisplay();
|
||||
histoPlot.setGraphicsOverLayer(histoOverLayer = new HistoOverLayer());
|
||||
@ -125,7 +128,8 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
||||
axMin = allHistogram.getScaleMinVal();
|
||||
axMax = allHistogram.getScaleMaxVal();
|
||||
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);
|
||||
g.setColor(Color.RED);
|
||||
g.drawLine(x, 0, x, plotRectangle.height);
|
||||
@ -151,7 +155,7 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
||||
double newAmp = (double) mouseEvent.getX() / histoOverLayer.plotRectangle.width *
|
||||
(histoOverLayer.axMax-histoOverLayer.axMin) + histoOverLayer.axMin;
|
||||
BTDisplayParameters btDisplayParameters = btDisplay.getBtDisplayParameters();
|
||||
btDisplayParameters.minAmplitude = newAmp;
|
||||
dataSelector.getParams().minimumAmplitude = newAmp;
|
||||
ampCtrlPanel.setParams(btDisplayParameters);
|
||||
redrawHisto();
|
||||
//
|
||||
@ -173,7 +177,7 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
||||
if (btDisplayParameters.amplitudeSelect == false) {
|
||||
return false;
|
||||
}
|
||||
double dx = (btDisplayParameters.minAmplitude - histoOverLayer.axMin) /
|
||||
double dx = (dataSelector.getParams().minimumAmplitude - histoOverLayer.axMin) /
|
||||
(histoOverLayer.axMax-histoOverLayer.axMin) * histoOverLayer.plotRectangle.width;
|
||||
int x = (int) Math.round(dx);
|
||||
if (Math.abs(e.getX()-x) > 10) {
|
||||
@ -213,14 +217,14 @@ public class BTAmplitudeSelector implements PamDialogPanel {
|
||||
}
|
||||
private void setParams(BTDisplayParameters btParams) {
|
||||
amplitudeSelect.setSelected(btParams.amplitudeSelect);
|
||||
minAmplitude.setText(String.format("%3.1f", btParams.minAmplitude));
|
||||
minAmplitude.setText(String.format("%3.1f", dataSelector.getParams().minimumAmplitude));
|
||||
|
||||
enableControls();
|
||||
}
|
||||
private boolean getParams(BTDisplayParameters btParams) {
|
||||
btParams.amplitudeSelect = amplitudeSelect.isSelected();
|
||||
try {
|
||||
btParams.minAmplitude = Double.valueOf(minAmplitude.getText());
|
||||
dataSelector.getParams().minimumAmplitude = Double.valueOf(minAmplitude.getText());
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
return false;
|
||||
|
@ -44,17 +44,17 @@ public class BTDisplayParameters implements Serializable, Cloneable, ManagedPara
|
||||
public int nBearingGridLines = 1;
|
||||
public int nAmplitudeGridLines = 0;
|
||||
public int nICIGridLines = 0;
|
||||
public boolean showEchoes = true;
|
||||
// public boolean showEchoes = true;
|
||||
public int minClickLength = 2, maxClickLength = 12;
|
||||
public int minClickHeight = 2, maxClickHeight = 12;
|
||||
private double timeRange = 10;
|
||||
public int displayChannels = 0;
|
||||
public boolean view360;
|
||||
public boolean amplitudeSelect = false;
|
||||
public double minAmplitude = 0;
|
||||
// public double minAmplitude = 0;
|
||||
public boolean showUnassignedICI = false;
|
||||
public boolean showEventsOnly = false;
|
||||
public boolean showANDEvents = true;
|
||||
// public boolean showEventsOnly = false;
|
||||
// public boolean showANDEvents = true;
|
||||
public boolean logICIScale;
|
||||
public int angleRotation = ROTATE_TOARRAY;
|
||||
|
||||
@ -65,7 +65,7 @@ public class BTDisplayParameters implements Serializable, Cloneable, ManagedPara
|
||||
/*
|
||||
* Show identified species
|
||||
*/
|
||||
private boolean[] showSpeciesList;
|
||||
// private boolean[] showSpeciesList;
|
||||
|
||||
public int colourScheme = COLOUR_BY_TRAIN;
|
||||
|
||||
@ -83,7 +83,7 @@ public class BTDisplayParameters implements Serializable, Cloneable, ManagedPara
|
||||
} catch (CloneNotSupportedException Ex) {
|
||||
Ex.printStackTrace();
|
||||
}
|
||||
showSpeciesList = null;
|
||||
// showSpeciesList = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -107,49 +107,49 @@ public class BTDisplayParameters implements Serializable, Cloneable, ManagedPara
|
||||
/**
|
||||
* @return the showSpeciesList
|
||||
*/
|
||||
public boolean getShowSpecies(int speciesIndex) {
|
||||
if (showSpeciesList != null && showSpeciesList.length > speciesIndex) {
|
||||
return showSpeciesList[speciesIndex];
|
||||
}
|
||||
makeShowSpeciesList(speciesIndex);
|
||||
return true;
|
||||
}
|
||||
private void makeShowSpeciesList(int maxIndex) {
|
||||
if (showSpeciesList == null) {
|
||||
showSpeciesList = new boolean[0];
|
||||
}
|
||||
else if (showSpeciesList.length > maxIndex) {
|
||||
return;
|
||||
}
|
||||
int oldLength = showSpeciesList.length;
|
||||
showSpeciesList = Arrays.copyOf(showSpeciesList, maxIndex + 1);
|
||||
for (int i = oldLength; i <= maxIndex; i++) {
|
||||
showSpeciesList[i] = true;
|
||||
}
|
||||
}
|
||||
// public boolean getShowSpecies(int speciesIndex) {
|
||||
// if (showSpeciesList != null && showSpeciesList.length > speciesIndex) {
|
||||
// return showSpeciesList[speciesIndex];
|
||||
// }
|
||||
// makeShowSpeciesList(speciesIndex);
|
||||
// return true;
|
||||
// }
|
||||
// private void makeShowSpeciesList(int maxIndex) {
|
||||
// if (showSpeciesList == null) {
|
||||
// showSpeciesList = new boolean[0];
|
||||
// }
|
||||
// else if (showSpeciesList.length > maxIndex) {
|
||||
// return;
|
||||
// }
|
||||
// int oldLength = showSpeciesList.length;
|
||||
// showSpeciesList = Arrays.copyOf(showSpeciesList, maxIndex + 1);
|
||||
// for (int i = oldLength; i <= maxIndex; i++) {
|
||||
// showSpeciesList[i] = true;
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* @param showSpeciesList the showSpeciesList to set
|
||||
*/
|
||||
public void setShowSpecies(int speciesIndex, boolean showSpecies) {
|
||||
makeShowSpeciesList(speciesIndex);
|
||||
showSpeciesList[speciesIndex] = showSpecies;
|
||||
}
|
||||
// public void setShowSpecies(int speciesIndex, boolean showSpecies) {
|
||||
// makeShowSpeciesList(speciesIndex);
|
||||
// showSpeciesList[speciesIndex] = showSpecies;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public PamParameterSet getParameterSet() {
|
||||
PamParameterSet ps = PamParameterSet.autoGenerate(this, ParameterSetType.DETECTOR);
|
||||
try {
|
||||
Field field = this.getClass().getDeclaredField("showSpeciesList");
|
||||
ps.put(new PrivatePamParameterData(this, field) {
|
||||
@Override
|
||||
public Object getData() throws IllegalArgumentException, IllegalAccessException {
|
||||
return showSpeciesList;
|
||||
}
|
||||
});
|
||||
} catch (NoSuchFieldException | SecurityException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// try {
|
||||
// Field field = this.getClass().getDeclaredField("showSpeciesList");
|
||||
// ps.put(new PrivatePamParameterData(this, field) {
|
||||
// @Override
|
||||
// public Object getData() throws IllegalArgumentException, IllegalAccessException {
|
||||
// return showSpeciesList;
|
||||
// }
|
||||
// });
|
||||
// } catch (NoSuchFieldException | SecurityException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
return ps;
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ import java.awt.Insets;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.AdjustmentEvent;
|
||||
@ -115,9 +116,13 @@ import PamguardMVC.PamDataBlock;
|
||||
import PamguardMVC.PamDataUnit;
|
||||
import PamguardMVC.PamObservable;
|
||||
import PamguardMVC.PamObserver;
|
||||
import PamguardMVC.dataSelector.DataSelectDialog;
|
||||
import PamguardMVC.dataSelector.DataSelector;
|
||||
import PamguardMVC.superdet.SuperDetection;
|
||||
import clickDetector.ClickClassifiers.ClickIdInformation;
|
||||
import clickDetector.ClickClassifiers.ClickIdentifier;
|
||||
import clickDetector.alarm.ClickAlarmParameters;
|
||||
import clickDetector.dataSelector.ClickDataSelector;
|
||||
import clickDetector.dialogs.ClickDisplayDialog;
|
||||
import clickDetector.offlineFuncs.OfflineEventDataBlock;
|
||||
import clickDetector.offlineFuncs.OfflineEventDataUnit;
|
||||
@ -2240,11 +2245,15 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
if (btDisplayParameters.amplitudeSelect == false) {
|
||||
return;
|
||||
}
|
||||
ClickDataSelector clickDataSelector = getClickDataSelector();
|
||||
if (clickDataSelector == null) {
|
||||
return;
|
||||
}
|
||||
int n = countAmplitudeDeselected();
|
||||
PamDataBlock<ClickDetection> clickData = clickControl.getClickDataBlock();
|
||||
int nAll = clickData.getUnitsCount();
|
||||
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();
|
||||
int x = insets.left;
|
||||
int y = getHeight()-5;
|
||||
@ -2383,19 +2392,33 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
}
|
||||
|
||||
menuItem = new JMenuItem("Settings ...");
|
||||
menuItem.setToolTipText("Display options");
|
||||
menuItem.addActionListener(new SettingsMenuAction());
|
||||
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.setToolTipText("Graphical amplitude selector display");
|
||||
menuItem.addActionListener(new AmplitudeSelector());
|
||||
menu.add(menuItem);
|
||||
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) {
|
||||
for (JMenuItem menuIt : colOptList) {
|
||||
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",
|
||||
// btDisplayParameters.colourScheme == BTDisplayParameters.COLOUR_BY_SPECIES);
|
||||
@ -2470,7 +2493,7 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Looks through the current modules and finds if there is a target motion or static localiser
|
||||
*/
|
||||
@ -2771,7 +2794,7 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
|
||||
BTDisplayParameters newParameters =
|
||||
ClickDisplayDialog.showDialog(clickControl,
|
||||
clickControl.getGuiFrame(), btDisplayParameters);
|
||||
clickControl.getGuiFrame(), btDisplayParameters, getClickDataSelector().getClickAlarmParameters());
|
||||
if (newParameters != null){
|
||||
btDisplayParameters = newParameters.clone();
|
||||
if (getVScaleManager() != null) {
|
||||
@ -2788,6 +2811,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 {
|
||||
@Override
|
||||
@ -2795,6 +2842,13 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
showAmplitudeSelector();
|
||||
}
|
||||
}
|
||||
|
||||
class DataSelectorAction implements ActionListener {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
showDataSelector();
|
||||
}
|
||||
}
|
||||
|
||||
private void showAmplitudeSelector() {
|
||||
|
||||
@ -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() {
|
||||
if (btAmplitudeSelector == null) {
|
||||
return;
|
||||
@ -3036,15 +3122,15 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
zoomer.paintShape(g, this, true);
|
||||
}
|
||||
|
||||
// long t1 = System.nanoTime();
|
||||
synchronized (clickData.getSynchLock()) {
|
||||
// long t2 = System.nanoTime();
|
||||
// double ms = ((double) (t2-t1)) / 1000000.;
|
||||
// if (btDisplayParameters.VScale == BTDisplayParameters.DISPLAY_ICI) {
|
||||
// sortTempICIs();
|
||||
// }
|
||||
ArrayList<ClickDetection> clickCopy = clickData.getDataCopy(displayStartMillis, displayStartMillis+displayLengthMillis, true, getDataSelector());
|
||||
if (clickCopy.size() == 0) {
|
||||
return;
|
||||
}
|
||||
ListIterator<ClickDetection> clickIterator = clickCopy.listIterator(clickCopy.size()-1);
|
||||
|
||||
ListIterator<ClickDetection> clickIterator = clickData.getListIterator(PamDataBlock.ITERATOR_END);
|
||||
// synchronized (clickData.getSynchLock()) {
|
||||
//
|
||||
// ListIterator<ClickDetection> clickIterator = clickData.getListIterator(PamDataBlock.ITERATOR_END);
|
||||
while (clickIterator.hasPrevious()) {
|
||||
click = clickIterator.previous();
|
||||
if (shouldPlot(prevPlottedClick)){
|
||||
@ -3060,11 +3146,6 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
if (shouldPlot(prevPlottedClick)){ // and draw the last one !
|
||||
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
|
||||
@ -3342,7 +3423,9 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
else if (btDisplayParameters.colourScheme == BTDisplayParameters.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"));
|
||||
}
|
||||
|
||||
@ -3354,7 +3437,8 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
PamSymbol[] symbols = clickControl.getClickIdentifier().getSymbols();
|
||||
if (speciesList != null) {
|
||||
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) {
|
||||
keyPanel.add(symbols[i].makeKeyItem(speciesList[i]));
|
||||
}
|
||||
@ -3423,11 +3507,12 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
PamDataBlock<ClickDetection> clickData = clickControl.getClickDataBlock();
|
||||
ClickDetection click;
|
||||
int n = 0;
|
||||
double minAmpli = getClickDataSelector().getParams().minimumAmplitude;
|
||||
synchronized (clickData.getSynchLock()) {
|
||||
ListIterator<ClickDetection> clickIterator = clickData.getListIterator(0);
|
||||
while (clickIterator.hasNext()) {
|
||||
click = clickIterator.next();
|
||||
if (click.getAmplitudeDB() < btDisplayParameters.minAmplitude) {
|
||||
if (click.getAmplitudeDB() < minAmpli) {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
@ -3448,29 +3533,30 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
*/
|
||||
synchronized boolean shouldPlot(ClickDetection click) {
|
||||
if (click == null) return false;
|
||||
if (!clickInTimeWindow(click)) return false;
|
||||
if (btDisplayParameters.showEchoes == false && click.isEcho()) {
|
||||
return false;
|
||||
}
|
||||
// if (!clickInTimeWindow(click)) return false;
|
||||
// if (btDisplayParameters.showEchoes == false && click.isEcho()) {
|
||||
// return false;
|
||||
// }
|
||||
if (btDisplayParameters.VScale == BTDisplayParameters.DISPLAY_ICI) {
|
||||
// if (btDisplayParameters.showUnassignedICI == false && click.getICI() < 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.
|
||||
}
|
||||
if (btDisplayParameters.amplitudeSelect && click.getAmplitudeDB() < btDisplayParameters.minAmplitude) {
|
||||
return false;
|
||||
}
|
||||
// if (btDisplayParameters.amplitudeSelect && click.getAmplitudeDB() < btDisplayParameters.minAmplitude) {
|
||||
// return false;
|
||||
// }
|
||||
if (btDisplayParameters.displayChannels > 0 && (btDisplayParameters.displayChannels & click.getChannelBitmap()) == 0) return false;
|
||||
|
||||
int speciesIndex = clickControl.getClickIdentifier().codeToListIndex(click.getClickType());
|
||||
boolean showSpecies = btDisplayParameters.getShowSpecies(speciesIndex+1);
|
||||
boolean showEvents = (btDisplayParameters.showEventsOnly == false || click.getSuperDetectionsCount() > 0);
|
||||
if (btDisplayParameters.showANDEvents) {
|
||||
return showSpecies & showEvents;
|
||||
}
|
||||
else {
|
||||
return showSpecies | showEvents;
|
||||
}
|
||||
// int speciesIndex = clickControl.getClickIdentifier().codeToListIndex(click.getClickType());
|
||||
// boolean showSpecies = btDisplayParameters.getShowSpecies(speciesIndex+1);
|
||||
// boolean showEvents = (btDisplayParameters.showEventsOnly == false || click.getSuperDetectionsCount() > 0);
|
||||
// if (btDisplayParameters.showANDEvents) {
|
||||
// return showSpecies & showEvents;
|
||||
// }
|
||||
// else {
|
||||
// return showSpecies | showEvents;
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4085,7 +4171,7 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
|
||||
amplitudeSelectorLabel.setText("");
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -17,10 +17,12 @@ public class ClickAlarmParameters extends DataSelectParams implements Cloneable,
|
||||
public static final long serialVersionUID = 1L;
|
||||
private boolean[] useSpeciesList;
|
||||
private double[] speciesWeightings;
|
||||
public boolean useEchoes;
|
||||
public boolean scoreByAmplitude;
|
||||
public boolean onlineAutoEvents, onlineManualEvents;
|
||||
public boolean useEchoes = true;
|
||||
public boolean scoreByAmplitude; // alarm options, probably not used any more.
|
||||
public double minimumAmplitude;
|
||||
public boolean onlineAutoEvents = true, onlineManualEvents = true;
|
||||
public int minICIMillis;
|
||||
private boolean clicksOREvents = false;
|
||||
/*
|
||||
* Which events to use ...
|
||||
*/
|
||||
@ -165,5 +167,30 @@ public class ClickAlarmParameters extends DataSelectParams implements Cloneable,
|
||||
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
|
||||
public PamDialogPanel getDialogPanel() {
|
||||
if (clickSelectPanel == null) {
|
||||
// if (clickSelectPanel == null) {
|
||||
clickSelectPanel = new ClickSelectPanel(this, allowScores, useEventTypes);
|
||||
}
|
||||
// }
|
||||
return clickSelectPanel;
|
||||
}
|
||||
@Override
|
||||
@ -60,19 +60,25 @@ public class ClickDataSelector extends DataSelector {
|
||||
if (clickAlarmParameters.useEchoes == false && click.isEcho()) {
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* First score based on whether the event panel is in use and
|
||||
* criteria satisfied.
|
||||
*/
|
||||
|
||||
double score = scoreClick(click);
|
||||
if (useEventTypes) {
|
||||
if (wantEventType(click) == false) {
|
||||
return 0;
|
||||
double eventScore = scoreEventType(click);
|
||||
if (clickAlarmParameters.isClicksANDEvents()) {
|
||||
score = Math.min(score, eventScore);
|
||||
}
|
||||
else {
|
||||
score = Math.max(score, eventScore);
|
||||
}
|
||||
}
|
||||
return score;
|
||||
|
||||
/*
|
||||
* Now score based on whether or not it's individual click type is wanted.
|
||||
*/
|
||||
}
|
||||
|
||||
private double scoreClick(ClickDetection click) {
|
||||
if (click.getAmplitudeDB() < clickAlarmParameters.minimumAmplitude) {
|
||||
return 0;
|
||||
}
|
||||
ClickIdentifier clickIdentifier = clickControl.getClickIdentifier();
|
||||
int code = click.getClickType();
|
||||
if (code > 0 && clickIdentifier != null) {
|
||||
@ -81,13 +87,13 @@ public class ClickDataSelector extends DataSelector {
|
||||
boolean enabled = clickAlarmParameters.getUseSpecies(code);
|
||||
if (enabled == false) {
|
||||
return 0;
|
||||
}
|
||||
if (isAllowScores()) {
|
||||
}if (isAllowScores()) {
|
||||
return clickAlarmParameters.getSpeciesWeight(code);
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -95,7 +101,7 @@ public class ClickDataSelector extends DataSelector {
|
||||
* @param click
|
||||
* @return
|
||||
*/
|
||||
private boolean wantEventType(ClickDetection click) {
|
||||
private double scoreEventType(ClickDetection click) {
|
||||
OfflineEventDataUnit oev = null;
|
||||
|
||||
try {
|
||||
@ -107,7 +113,7 @@ public class ClickDataSelector extends DataSelector {
|
||||
|
||||
int eventId = click.getOfflineEventID();
|
||||
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.
|
||||
@ -118,10 +124,10 @@ public class ClickDataSelector extends DataSelector {
|
||||
isAutomatic = comment.startsWith("Automatic");
|
||||
}
|
||||
if (isAutomatic && clickAlarmParameters.onlineAutoEvents) {
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
else if (clickAlarmParameters.onlineManualEvents) {
|
||||
return true;
|
||||
return 1;
|
||||
}
|
||||
// if (clickAlarmParameters.onlineAutoEvents && comment.startsWith("Automatic")) {
|
||||
// return true;
|
||||
@ -134,7 +140,7 @@ public class ClickDataSelector extends DataSelector {
|
||||
* list of event types and see if it's wanted.
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
@Override
|
||||
public DataSelectParams getParams() {
|
||||
public ClickAlarmParameters getParams() {
|
||||
return clickAlarmParameters;
|
||||
}
|
||||
|
||||
|
@ -95,7 +95,7 @@ public class ClickSelectPaneFX extends DynamicSettingsPane<Boolean> {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Click Type Selection";
|
||||
return "Filter by click type";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -4,6 +4,7 @@ import generalDatabase.lookupTables.LookUpTables;
|
||||
import generalDatabase.lookupTables.LookupList;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
@ -13,11 +14,13 @@ import java.awt.event.ActionListener;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
import PamController.PamController;
|
||||
@ -42,6 +45,7 @@ public class ClickSelectPanel implements PamDialogPanel {
|
||||
private ClickDataSelector clickDataSelector;
|
||||
private JPanel mainPanel;
|
||||
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";
|
||||
|
||||
@ -70,10 +74,12 @@ public class ClickSelectPanel implements PamDialogPanel {
|
||||
public void setParams() {
|
||||
eventTypePanel.setParams();
|
||||
speciesPanel.setParams();
|
||||
andOrBox.setSelectedIndex(clickDataSelector.getParams().isClicksANDEvents() ? 0 : 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getParams() {
|
||||
clickDataSelector.getParams().setClicksANDEvents(andOrBox.getSelectedIndex() == 0);
|
||||
return (speciesPanel.getParams() & eventTypePanel.getParams());
|
||||
}
|
||||
|
||||
@ -163,17 +169,26 @@ public class ClickSelectPanel implements PamDialogPanel {
|
||||
// JRadioButton andEvents, orEvents;
|
||||
// JRadioButton anyEvents, onlyEvents;
|
||||
private JCheckBox useEchoes;
|
||||
private JTextField minAmplitude;
|
||||
private JCheckBox scoreByAmplitude;
|
||||
private JTextField minICI;
|
||||
|
||||
SpeciesPanel () {
|
||||
super();
|
||||
setLayout(new BorderLayout());
|
||||
// setLayout(new BorderLayout());
|
||||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||
northPanel = new JPanel();
|
||||
northPanel.setLayout(new GridBagLayout());
|
||||
GridBagConstraints c = new PamGridBagContraints();
|
||||
c.gridwidth = 3;
|
||||
c.gridwidth = 1;
|
||||
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);
|
||||
c.gridwidth = 1;
|
||||
c.gridy++;
|
||||
@ -185,35 +200,50 @@ public class ClickSelectPanel implements PamDialogPanel {
|
||||
// minICI.setToolTipText("Minimum ICI in milliseconds");
|
||||
// c.gridx++;
|
||||
// northPanel.add(new JLabel(" ms", JLabel.LEFT), c);
|
||||
c.gridwidth = 3;
|
||||
c.gridy++;
|
||||
c.gridx = 0;
|
||||
northPanel.add(scoreByAmplitude = new JCheckBox("Score by amplitude"), c);
|
||||
scoreByAmplitude.setVisible(allowScores);
|
||||
scoreByAmplitude.addActionListener(new AllSpeciesListener());
|
||||
scoreByAmplitude = new JCheckBox("Score by amplitude");
|
||||
if (allowScores) {
|
||||
c.gridwidth = 3;
|
||||
c.gridy++;
|
||||
c.gridx = 0;
|
||||
northPanel.add(scoreByAmplitude, c);
|
||||
scoreByAmplitude.setVisible(allowScores);
|
||||
scoreByAmplitude.addActionListener(new AllSpeciesListener());
|
||||
}
|
||||
WestAlignedPanel walpn;
|
||||
add(BorderLayout.NORTH, walpn = new WestAlignedPanel(northPanel));
|
||||
walpn.setBorder(new SeparatorBorder("Echoes"));
|
||||
this.add(walpn = new WestAlignedPanel(northPanel));
|
||||
walpn.setBorder(new SeparatorBorder("Click Selection"));
|
||||
|
||||
JPanel centralOuterPanel = new JPanel(new BorderLayout());
|
||||
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);
|
||||
centralOuterPanel.add(BorderLayout.CENTER, scrollPane);
|
||||
|
||||
centralEastPanel.setLayout(new GridBagLayout());
|
||||
c = new PamGridBagContraints();
|
||||
centralEastPanel.add(selectAll = new JButton("Select All"), c);
|
||||
c.gridx++;
|
||||
centralEastPanel.add(clearAll = new JButton("Clear All"), c);
|
||||
c.ipady = 0;
|
||||
c.insets.bottom = c.insets.top = c.insets.left = c.insets.right = 0;
|
||||
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));
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -254,6 +284,7 @@ public class ClickSelectPanel implements PamDialogPanel {
|
||||
}
|
||||
}
|
||||
useEchoes.setSelected(clickAlarmParameters.useEchoes);
|
||||
minAmplitude.setText(String.format("%3.1f", clickAlarmParameters.minimumAmplitude));
|
||||
minICI.setText(String.format("%d", clickAlarmParameters.minICIMillis));
|
||||
scoreByAmplitude.setSelected(clickAlarmParameters.scoreByAmplitude);
|
||||
allWeight.setText(String.format("%3.1f", clickAlarmParameters.getSpeciesWeight(0)));
|
||||
@ -279,6 +310,12 @@ public class ClickSelectPanel implements PamDialogPanel {
|
||||
|
||||
ClickAlarmParameters clickAlarmParameters = clickDataSelector.getClickAlarmParameters().clone();
|
||||
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 {
|
||||
clickAlarmParameters.minICIMillis = Integer.valueOf(minICI.getText());
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ import PamView.dialog.warn.WarnOnce;
|
||||
import clickDetector.BTDisplayParameters;
|
||||
import clickDetector.ClickControl;
|
||||
import clickDetector.ClickClassifiers.ClickIdentifier;
|
||||
import clickDetector.alarm.ClickAlarmParameters;
|
||||
|
||||
/**
|
||||
* Dialog for basic click display parameters
|
||||
@ -57,6 +58,8 @@ public class ClickDisplayDialog extends PamDialog implements ActionListener {
|
||||
private SizePanel sizePanel;
|
||||
private SpeciesPanel speciesPanel;
|
||||
private JComboBox<String> angleTypes;
|
||||
|
||||
private ClickAlarmParameters clickSelectParams;
|
||||
|
||||
private ClickDisplayDialog(Window owner) {
|
||||
|
||||
@ -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) {
|
||||
singleInstance = new ClickDisplayDialog(parentFrame);
|
||||
}
|
||||
singleInstance.clickControl = clickControl;
|
||||
singleInstance.btDisplayParameters = btDisplayParameters.clone();
|
||||
singleInstance.clickSelectParams = clickSelectParams;
|
||||
singleInstance.setParams(btDisplayParameters);
|
||||
singleInstance.setVisible(true);
|
||||
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) {
|
||||
showAll.setSelected(true);
|
||||
}
|
||||
else {
|
||||
showAll.setSelected(btDisplayParameters.getShowSpecies(0));
|
||||
// showAll.setSelected(btDisplayParameters.getShowSpecies(0));
|
||||
showAll.setSelected(clickSelectParams.getUseSpecies(0));
|
||||
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) {
|
||||
// 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(btDisplayParameters.showEventsOnly);
|
||||
andOrSelection.setSelectedIndex(btDisplayParameters.showANDEvents ? 0: 1);
|
||||
clicksInAnEvent.setSelected(clickSelectParams.onlineAutoEvents | clickSelectParams.onlineAutoEvents);
|
||||
|
||||
// clicksInAnEvent.setSelected(btDisplayParameters.showEventsOnly);
|
||||
// andOrSelection.setSelectedIndex(btDisplayParameters.showANDEvents ? 0: 1);
|
||||
// orEvents.setSelected(!btDisplayParameters.showANDEvents);
|
||||
// andEvents.setSelected(btDisplayParameters.showANDEvents);
|
||||
// anyEvents.setSelected(!btDisplayParameters.showEventsOnly);
|
||||
@ -540,19 +547,17 @@ public class ClickDisplayDialog extends PamDialog implements ActionListener {
|
||||
enableButtons();
|
||||
}
|
||||
boolean getParams() {
|
||||
btDisplayParameters.showEchoes = showEchoes.isSelected();
|
||||
btDisplayParameters.setShowSpecies(0, showAll.isSelected());
|
||||
if (species != null) {
|
||||
for (int i = 0; i < species.length; i++) {
|
||||
btDisplayParameters.setShowSpecies(i+1, species[i].isSelected());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
btDisplayParameters.showEventsOnly = clicksInAnEvent.isSelected();
|
||||
btDisplayParameters.showANDEvents = (andOrSelection.getSelectedIndex() == 0);
|
||||
// btDisplayParameters.showANDEvents = andEvents.isSelected();
|
||||
// btDisplayParameters.showEventsOnly = onlyEvents.isSelected();
|
||||
// clickSelectParams.useEchoes = showEchoes.isSelected();
|
||||
// btDisplayParameters.setShowSpecies(0, showAll.isSelected());
|
||||
// if (species != null) {
|
||||
// for (int i = 0; i < species.length; i++) {
|
||||
// btDisplayParameters.setShowSpecies(i+1, species[i].isSelected());
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// btDisplayParameters.showEventsOnly = clicksInAnEvent.isSelected();
|
||||
// btDisplayParameters.showANDEvents = (andOrSelection.getSelectedIndex() == 0);
|
||||
return true;
|
||||
}
|
||||
class AllSpeciesListener implements ActionListener {
|
||||
|
@ -31,12 +31,15 @@ import clickDetector.ClickBTDisplay;
|
||||
import clickDetector.ClickControl;
|
||||
import clickDetector.ClickDisplay;
|
||||
import clickDetector.ClickClassifiers.ClickIdentifier;
|
||||
import clickDetector.alarm.ClickAlarmParameters;
|
||||
import clickDetector.dataSelector.ClickDataSelector;
|
||||
import PamView.PamToolBar;
|
||||
import PamView.component.PamSettingsIconButton;
|
||||
import PamView.dialog.PamCheckBox;
|
||||
import PamView.dialog.PamLabel;
|
||||
import PamView.dialog.PamRadioButton;
|
||||
import PamView.panel.PamPanel;
|
||||
import PamguardMVC.dataSelector.DataSelectParams;
|
||||
|
||||
public class OfflineToolbar {
|
||||
|
||||
@ -252,19 +255,29 @@ public class OfflineToolbar {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
ClickDataSelector clickDataSelector = currentBTDisplay.getClickDataSelector();
|
||||
ClickAlarmParameters selectParams = clickDataSelector.getParams();
|
||||
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) {
|
||||
btDisplayParameters.showEventsOnly = clicksInAnEvent.isSelected();
|
||||
// btDisplayParameters.showEventsOnly = clicksInAnEvent.isSelected();
|
||||
// selectParams.onlineAutoEvents = selectParams.onlineManualEvents = true;
|
||||
selectParams.unassignedEvents =clicksInAnEvent.isSelected() == false;
|
||||
}
|
||||
if (andOrSelection != null) {
|
||||
btDisplayParameters.showANDEvents = (andOrSelection.getSelectedIndex() == 0);
|
||||
selectParams.setClicksANDEvents(andOrSelection.getSelectedIndex() == 0);
|
||||
// btDisplayParameters.showANDEvents = (andOrSelection.getSelectedIndex() == 0);
|
||||
}
|
||||
if (speciesButtons != null) {
|
||||
int n = speciesButtons.length;
|
||||
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();
|
||||
@ -275,23 +288,35 @@ public class OfflineToolbar {
|
||||
}
|
||||
|
||||
private void checkButtons(BTDisplayParameters btDisplayParameters) {
|
||||
showEchoes.setSelected(btDisplayParameters.showEchoes);
|
||||
showNonSpecies.setSelected(btDisplayParameters.getShowSpecies(0));
|
||||
ClickDataSelector clickDataSelector = currentBTDisplay.getClickDataSelector();
|
||||
ClickAlarmParameters selectParams = clickDataSelector.getParams();
|
||||
showEchoes.setSelected(selectParams.useEchoes);
|
||||
showNonSpecies.setSelected(selectParams.getUseSpecies(0));
|
||||
// showNonSpecies.setSelected(btDisplayParameters.getShowSpecies(0));
|
||||
boolean anySel = false;;
|
||||
if (clicksInAnEvent != null) {
|
||||
clicksInAnEvent.setSelected(btDisplayParameters.showEventsOnly);
|
||||
clicksInAnEvent.setSelected(selectParams.unassignedEvents == false);
|
||||
anySel |= clicksInAnEvent.isSelected();
|
||||
// clicksInAnEvent.setSelected(btDisplayParameters.showEventsOnly);
|
||||
}
|
||||
if (speciesButtons != null) {
|
||||
int n = speciesButtons.length;
|
||||
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
|
||||
// or else they will get cleared later
|
||||
if (andOrSelection != null) {
|
||||
andOrSelection.setSelectedIndex(btDisplayParameters.showANDEvents ? 0: 1);
|
||||
andOrSelection.setSelectedIndex(selectParams.isClicksANDEvents() ? 0 : 1);
|
||||
// andOrSelection.setSelectedIndex(btDisplayParameters.showANDEvents ? 0: 1);
|
||||
}
|
||||
firstSetup = true;
|
||||
if (anySel) {
|
||||
selectParams.setCombinationFlag(DataSelectParams.DATA_SELECT_AND);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,13 @@
|
||||
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.PamSymbol;
|
||||
import PamView.dialog.PamDialogPanel;
|
||||
import PamView.symbol.PamSymbolChooser;
|
||||
import PamView.symbol.SymbolData;
|
||||
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.ClickDetection;
|
||||
import clickDetector.ClickDisplayManagerParameters;
|
||||
import clickDetector.alarm.ClickAlarmParameters;
|
||||
import clickDetector.dataSelector.ClickDataSelector;
|
||||
import clickDetector.dialogs.ClickDisplayDialog;
|
||||
import PamView.GeneralProjector.ParameterType;
|
||||
import PamView.GeneralProjector.ParameterUnits;
|
||||
@ -52,6 +54,10 @@ public class ClickPlotInfo extends TDDataInfo {
|
||||
allScaleInfo[3] = slantScaleInfo;
|
||||
clickHidingDialog = new ClickHidingDialog(this);
|
||||
}
|
||||
|
||||
ClickDataSelector getDataSelector() {
|
||||
return (ClickDataSelector) clickControl.getClickDataBlock().getDataSelector("ClickTDPlots", false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getDataValue(PamDataUnit pamDataUnit) {
|
||||
@ -110,7 +116,8 @@ public class ClickPlotInfo extends TDDataInfo {
|
||||
private synchronized boolean shouldPlot(ClickDetection click) {
|
||||
|
||||
if (click == null) return false;
|
||||
if (btDisplayParams.showEchoes == false && click.isEcho()) {
|
||||
boolean showEchoes = getDataSelector().getClickAlarmParameters().useEchoes;
|
||||
if (showEchoes == false && click.isEcho()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -170,7 +177,7 @@ public class ClickPlotInfo extends TDDataInfo {
|
||||
*/
|
||||
@Override
|
||||
public boolean editOptions(Window frame) {
|
||||
BTDisplayParameters newParams = ClickDisplayDialog.showDialog(clickControl, frame, btDisplayParams);
|
||||
BTDisplayParameters newParams = ClickDisplayDialog.showDialog(clickControl, frame, btDisplayParams, getDataSelector().getClickAlarmParameters());
|
||||
if (newParams != null) {
|
||||
btDisplayParams = newParams.clone();
|
||||
updateSettings();
|
||||
|
@ -185,6 +185,7 @@ public class TemplateSpectrumPane extends PamBorderPane {
|
||||
this.currentSpectrum = new SpectrumTemplateDataUnit(spectrumTemplate);
|
||||
templateDisplay.setDataUnit(currentSpectrum);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -226,7 +227,6 @@ public class TemplateSpectrumPane extends PamBorderPane {
|
||||
if (templateImporters.get(i).getExtension()[j].equals(extension)) {
|
||||
// System.out.println("Import using the extensions: " + extension);
|
||||
template=templateImporters.get(i).importTemplate(file);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -288,7 +288,7 @@ public class TemplateSpectrumPane extends PamBorderPane {
|
||||
}
|
||||
|
||||
@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};
|
||||
}
|
||||
|
||||
@ -296,6 +296,7 @@ public class TemplateSpectrumPane extends PamBorderPane {
|
||||
@Override
|
||||
public double getSampleRate(SpectrumTemplateDataUnit data) {
|
||||
//bit of a hack to get sample rate but works.
|
||||
// System.out.println("Set sample rate: " + 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));
|
||||
|
||||
dataSelectPane = createDataSelectPane();
|
||||
dataSelectPane.addSettingsListener(()->{
|
||||
//dynamic settings pane so have to repaint whenever a control is selected.
|
||||
getParams();
|
||||
clickPlotInfo.getTDGraph().repaint(0);
|
||||
});
|
||||
dataSelectPane.setParams(true);
|
||||
|
||||
|
||||
@ -215,6 +210,7 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
|
||||
scrollPane2.setHbarPolicy(ScrollBarPolicy.NEVER);
|
||||
scrollPane2.getStyleClass().clear();
|
||||
symbolTab.setContent(scrollPane2);
|
||||
|
||||
Tab dataView=new Tab("Data");
|
||||
dataView.setContent(dataSelectHolder);
|
||||
dataView.getStyleClass().add("tab-square");
|
||||
@ -230,6 +226,21 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
|
||||
enablePane();
|
||||
setFreqType();
|
||||
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);
|
||||
|
||||
@ -242,6 +253,7 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
|
||||
* @return the data select pane.
|
||||
*/
|
||||
private DynamicSettingsPane<Boolean> createDataSelectPane(){
|
||||
// System.out.println("DATA SELECTOR: " + clickPlotInfo.getClickDataSelector());
|
||||
return clickPlotInfo.getClickDataSelector().getDialogPaneFX();
|
||||
}
|
||||
|
||||
@ -446,7 +458,7 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
|
||||
PamVBox vBox = new PamVBox();
|
||||
vBox.setSpacing(5);
|
||||
|
||||
minMaxWidthPane = new DualControlField<Double>("Min", "Max" , "", 2, 100, 1);
|
||||
minMaxWidthPane = new DualControlField<Double>("", "" , "", 2, 100, 1);
|
||||
minMaxWidthPane.addChangeListener((obsval, oldval, newval)->{
|
||||
newSettings();
|
||||
//do not allow the min ti be larger than the max.
|
||||
@ -469,7 +481,7 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
|
||||
|
||||
|
||||
//height pane
|
||||
minMaxHeightPane = new DualControlField<Double>("Min", "Max" , "", 2, 100, 1);
|
||||
minMaxHeightPane = new DualControlField<Double>("", "" , "", 2, 100, 1);
|
||||
minMaxHeightPane.addChangeListener((obsval, oldval, newval)->{
|
||||
newSettings();
|
||||
//do not allow the min ti be larger than the max.
|
||||
@ -516,7 +528,7 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
|
||||
getParams();
|
||||
|
||||
//on a parameter change must clear the FFT plot.
|
||||
clickPlotInfo.getClickFFTplotManager().clear();
|
||||
clickPlotInfo.getClickFFTPlotManager().clear();
|
||||
clickPlotInfo.getClickRawPlotManager().clear();
|
||||
|
||||
clickPlotInfo.getTDGraph().repaint(milliswait);
|
||||
@ -770,7 +782,7 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
|
||||
clickPlotInfo.getClickDisplayParams().fftHop = this.fftSpinnerHop.getValue().intValue();
|
||||
clickPlotInfo.getClickDisplayParams().fftLength = this.fftSpinnerLength.getValue().intValue();
|
||||
clickPlotInfo.getClickDisplayParams().colourMap = this.spectroControlPane.getColourArrayType();
|
||||
clickPlotInfo.getClickFFTplotManager().update();
|
||||
clickPlotInfo.getClickFFTPlotManager().update();
|
||||
/*** Data select pane****/
|
||||
|
||||
//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;
|
||||
//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;
|
||||
Double val = null;
|
||||
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.
|
||||
* @param click - the click to check.
|
||||
* @return true to plot the click.
|
||||
*/
|
||||
private synchronized boolean shouldPlot(ClickDetection click) {
|
||||
|
||||
if (click == null) return false;
|
||||
|
||||
dataSelector.scoreData(click);
|
||||
|
||||
if (clickDisplayParams.displayChannels > 0 && (clickDisplayParams.displayChannels & click.getChannelBitmap()) == 0) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
// /***
|
||||
// * Used to determine which clicks should be plotted on the display by using the click data selector.
|
||||
// * @param click - the click to check.
|
||||
// * @return true to plot the click.
|
||||
// */
|
||||
// private synchronized boolean shouldPlot(ClickDetection click) {
|
||||
//
|
||||
// if (click == null) return false;
|
||||
//
|
||||
// if (dataSelector.scoreData(click)<=0) return false;
|
||||
//
|
||||
// if (clickDisplayParams.displayChannels > 0 && (clickDisplayParams.displayChannels & click.getChannelBitmap()) == 0) return false;
|
||||
//
|
||||
// return true;
|
||||
// }
|
||||
|
||||
@Override
|
||||
public TDSymbolChooserFX getSymbolChooser() {
|
||||
@ -931,7 +931,7 @@ public class ClickPlotInfoFX extends TDDataInfoFX {
|
||||
* time/frequency displays...
|
||||
* @return The FFT plot manager.
|
||||
*/
|
||||
public ClickFFTPlotManager2 getClickFFTplotManager() {
|
||||
public ClickFFTPlotManager2 getClickFFTPlotManager() {
|
||||
return clickFFTplotManager;
|
||||
}
|
||||
|
||||
|
@ -318,7 +318,6 @@ public abstract class RawWavePlotManager {
|
||||
//check if we can plot click on this plot pane.
|
||||
if (!rawClipInfo.shouldDraw(plotNumber, pamDataUnit)) {
|
||||
//System.out.println("Shoudl not draw!");
|
||||
|
||||
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
|
||||
*
|
||||
*/
|
||||
private class TDTooltip extends Tooltip {
|
||||
|
||||
private static final double TOOL_TIP_DELAY = 60; //seconds
|
||||
private TDPlotPane plotPanel;
|
||||
|
||||
/**
|
||||
@ -917,6 +918,8 @@ public class TDGraphFX extends PamBorderPane {
|
||||
public TDTooltip(TDPlotPane aPlot) {
|
||||
super("Test tooltip");
|
||||
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
|
||||
* timing on these displys.
|
||||
|
@ -44,7 +44,7 @@ public class RExportOverlayMenu extends ExportOverlayMenu {
|
||||
* Create the export overlay
|
||||
*/
|
||||
public RExportOverlayMenu(){
|
||||
rExportManger= new RExportManager();
|
||||
rExportManger= new RExportManager(null);
|
||||
|
||||
buttonNode = createButton();
|
||||
|
||||
|
@ -74,7 +74,7 @@ public abstract class SpectrumPlot <D extends PamDataUnit> implements Detection
|
||||
private SpectrumSettingsPane spectrumSettingsPane;
|
||||
|
||||
|
||||
private double sR;
|
||||
private double storedsR;
|
||||
|
||||
|
||||
// //TODO
|
||||
@ -132,7 +132,7 @@ public abstract class SpectrumPlot <D extends PamDataUnit> implements Detection
|
||||
|
||||
if (data ==null) return;
|
||||
|
||||
this.sR=sR;
|
||||
this.storedsR=sR;
|
||||
|
||||
int[] minmax = getAxisMinMaxSamples(plotProjector);
|
||||
|
||||
@ -172,7 +172,7 @@ public abstract class SpectrumPlot <D extends PamDataUnit> implements Detection
|
||||
}
|
||||
|
||||
private double getSampleRate() {
|
||||
return sR;
|
||||
return storedsR;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -234,6 +234,8 @@ public abstract class SpectrumPlot <D extends PamDataUnit> implements Detection
|
||||
|
||||
storedSpectrum=this.getPowerSpectrum(data, minmax[0], minmax[1]);
|
||||
storedCepstrum=this.getCepstrum(data, minmax[0], minmax[1]);
|
||||
|
||||
storedsR = getSampleRate(data);
|
||||
|
||||
if (spectrumPlotParams.logScale) {
|
||||
paintLogSpectrum(gc, clipRect,projector);
|
||||
|
@ -6,6 +6,10 @@ import java.util.List;
|
||||
import PamguardMVC.PamDataUnit;
|
||||
import export.PamDataUnitExporter;
|
||||
|
||||
|
||||
/**
|
||||
* Export to CSV files which are RAVEN compatible.
|
||||
*/
|
||||
public class CSVExportManager implements PamDataUnitExporter{
|
||||
|
||||
@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.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.zip.Deflater;
|
||||
|
||||
import PamUtils.PamArrayUtils;
|
||||
import PamUtils.PamCalendar;
|
||||
import PamguardMVC.PamDataUnit;
|
||||
import export.PamDataUnitExporter;
|
||||
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.Sinks;
|
||||
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.close();
|
||||
// matFile.close(); //CAUSES AN EXCEPTION IF WRITING AGAIN
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
//write to the mat file without loading all contents into memory.
|
||||
Mat5Writer writer = Mat5.newWriter(sink);
|
||||
|
||||
@ -257,7 +254,7 @@ public class MLDetectionsManager implements PamDataUnitExporter {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
//handled in the mian funtion
|
||||
//handled in the main function
|
||||
if (sink!=null) {
|
||||
try {
|
||||
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= Mat5.newStruct();
|
||||
Struct mlStructure= Mat5.newStruct(dataUnit.getConnectedRegion().getSliceData().size(), 1);
|
||||
|
||||
//the start sample.
|
||||
Matrix sliceNumber;
|
||||
|
@ -41,15 +41,21 @@ public interface PamDataUnitExporter {
|
||||
public String getIconString();
|
||||
|
||||
/**
|
||||
* Get the name of the exporter
|
||||
* @return
|
||||
* Get the name of the exporter.
|
||||
* @return the name of the exporter.
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* Clsoe the exporter
|
||||
* Close the exporter.
|
||||
*/
|
||||
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");
|
||||
|
||||
public PamExporterManager() {
|
||||
|
||||
pamExporters = new ArrayList<PamDataUnitExporter>();
|
||||
|
||||
//add the MATLAB export
|
||||
pamExporters.add(new MLDetectionsManager());
|
||||
pamExporters.add(new RExportManager());
|
||||
pamExporters.add(new RExportManager(this));
|
||||
pamExporters.add(new WavFileExportManager());
|
||||
pamExporters.add(new CSVExportManager());
|
||||
}
|
||||
@ -72,6 +73,8 @@ public class PamExporterManager {
|
||||
public boolean exportDataUnit(PamDataUnit<?, ?> dataUnit, boolean force) {
|
||||
boolean exportOK = true;
|
||||
|
||||
System.out.println("Add data unit " + dataUnit + " to: "+ currentFile);
|
||||
|
||||
if (dataUnit==null) {
|
||||
if (force) {
|
||||
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 (currentFile == null || isFileSizeMax(currentFile)) {
|
||||
if (currentFile == null || isNeedsNewFile(currentFile, pamExporters.get(exportParams.exportChoice))) {
|
||||
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
|
||||
//so previous files should already be closed
|
||||
@ -101,7 +104,7 @@ public class PamExporterManager {
|
||||
System.out.println("Write data unit " + dataUnitBuffer.size() + " to: "+ currentFile);
|
||||
|
||||
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);
|
||||
dataUnitBuffer.clear();
|
||||
}
|
||||
@ -118,10 +121,14 @@ public class PamExporterManager {
|
||||
/**
|
||||
* Check whether the current file is greater than the maximum allowed file size.
|
||||
* @param currentFile2 - the current file
|
||||
* @param pamDataUnitExporter
|
||||
* @return true of greater than or equal to the maximum file size.
|
||||
*/
|
||||
private boolean isFileSizeMax(File currentFile2) {
|
||||
return getFileSizeMegaBytes(currentFile2) >= MAX_FILE_SIZE_MB;
|
||||
private boolean isNeedsNewFile(File currentFile2, PamDataUnitExporter pamDataUnitExporter) {
|
||||
if( getFileSizeMegaBytes(currentFile2) >= exportParams.maximumFileSize) {
|
||||
return true;
|
||||
};
|
||||
return pamDataUnitExporter.isNeedsNewFile();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -18,6 +18,7 @@ import org.renjin.sexp.PairList.Builder;
|
||||
import PamUtils.PamArrayUtils;
|
||||
import PamguardMVC.PamDataUnit;
|
||||
import export.PamDataUnitExporter;
|
||||
import export.PamExporterManager;
|
||||
import export.MLExport.MLDetectionsManager;
|
||||
|
||||
/**
|
||||
@ -29,7 +30,6 @@ import export.MLExport.MLDetectionsManager;
|
||||
public class RExportManager implements PamDataUnitExporter {
|
||||
|
||||
/**
|
||||
*
|
||||
* All the possible RDataUnit export classes.
|
||||
*/
|
||||
ArrayList<RDataUnitExport> rDataExport = new ArrayList<RDataUnitExport>();
|
||||
@ -37,10 +37,13 @@ public class RExportManager implements PamDataUnitExporter {
|
||||
private File currentFileName ;
|
||||
|
||||
|
||||
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****/
|
||||
rDataExport.add(new RClickExport());
|
||||
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.
|
||||
* So everything is stored in memory until saved.
|
||||
*/
|
||||
// then
|
||||
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());
|
||||
String entryName = "det_" + MLDetectionsManager.dataFormat.format( date);
|
||||
|
||||
// System.out.println("Save R data! "+ dataUnits.size());
|
||||
|
||||
// System.out.println("Export R file!!" + dataUnits.size());
|
||||
|
||||
//is there an existing writer? Is that writer writing to the correct file?
|
||||
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.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JFileChooser;
|
||||
@ -38,6 +37,8 @@ import export.PamExporterManager;
|
||||
import export.layoutFX.ExportParams;
|
||||
import offlineProcessing.OLProcessDialog;
|
||||
import offlineProcessing.OfflineTaskGroup;
|
||||
import offlineProcessing.TaskMonitor;
|
||||
import offlineProcessing.TaskMonitorData;
|
||||
import offlineProcessing.TaskStatus;
|
||||
|
||||
/**
|
||||
@ -75,7 +76,6 @@ public class ExportProcessDialog {
|
||||
|
||||
|
||||
public void createExportGroup() {
|
||||
|
||||
//clear current tasks.
|
||||
dlOfflineGroup.clearTasks();
|
||||
|
||||
@ -87,7 +87,6 @@ public class ExportProcessDialog {
|
||||
dlOfflineGroup.addTask(new ExportTask(dataBlocks.get(i), exportManager));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
////---Swing stuff----/// should not be here but this is how PG works.
|
||||
|
||||
@ -129,6 +128,9 @@ public class ExportProcessDialog {
|
||||
*/
|
||||
private JFileChooser fc;
|
||||
|
||||
/**
|
||||
* S hows the folder stuff is going to export to.
|
||||
*/
|
||||
private JTextField exportTo;
|
||||
|
||||
/**
|
||||
@ -268,7 +270,7 @@ public class ExportProcessDialog {
|
||||
|
||||
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.
|
||||
*/
|
||||
switch (iconString) {
|
||||
@ -351,20 +353,83 @@ public class ExportProcessDialog {
|
||||
|
||||
|
||||
}
|
||||
|
||||
class ExportTaskMonitor implements TaskMonitor {
|
||||
|
||||
private int taskIndex;
|
||||
|
||||
private ExportTaskGroup exportTaskGroup;
|
||||
|
||||
private boolean started = false;
|
||||
|
||||
|
||||
class ExportTaskGroup extends OfflineTaskGroup{
|
||||
|
||||
public ExportTaskGroup(String settingsName) {
|
||||
super(null, settingsName);
|
||||
// TODO Auto-generated constructor stub
|
||||
|
||||
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 {
|
||||
|
||||
|
||||
public ExportTaskGroup(String settingsName) {
|
||||
super(null, settingsName);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getUnitType() {
|
||||
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.PamDataUnit;
|
||||
import PamguardMVC.dataSelector.DataSelectDialog;
|
||||
import PamguardMVC.dataSelector.DataSelectParams;
|
||||
import PamguardMVC.dataSelector.DataSelector;
|
||||
import dataMap.OfflineDataMapPoint;
|
||||
import export.PamExporterManager;
|
||||
@ -16,12 +17,12 @@ import offlineProcessing.OfflineTask;
|
||||
*
|
||||
*/
|
||||
public class ExportTask extends OfflineTask<PamDataUnit<?,?>>{
|
||||
|
||||
|
||||
/**
|
||||
* Reference to the data exporter which manages exporting of data.
|
||||
*/
|
||||
private PamExporterManager exporter;
|
||||
|
||||
|
||||
/**
|
||||
* The data selector for the data block
|
||||
*/
|
||||
@ -32,8 +33,8 @@ public class ExportTask extends OfflineTask<PamDataUnit<?,?>>{
|
||||
public ExportTask(PamDataBlock<PamDataUnit<?, ?>> parentDataBlock, PamExporterManager exporter) {
|
||||
super(parentDataBlock);
|
||||
this.exporter = exporter;
|
||||
dataSelector=parentDataBlock.getDataSelectCreator().getDataSelector(this.getUnitName() +"_clicks", false, null);
|
||||
|
||||
dataSelector=parentDataBlock.getDataSelectCreator().getDataSelector(this.getUnitName() +"_export", false, null);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -44,9 +45,20 @@ public class ExportTask extends OfflineTask<PamDataUnit<?,?>>{
|
||||
|
||||
@Override
|
||||
public boolean processDataUnit(PamDataUnit<?, ?> dataUnit) {
|
||||
if (dataSelector==null) exporter.exportDataUnit(dataUnit, false);
|
||||
else if (dataSelector.scoreData(dataUnit)>0) {
|
||||
exporter.exportDataUnit(dataUnit, false);
|
||||
|
||||
// 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);
|
||||
}
|
||||
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.
|
||||
}
|
||||
@ -54,18 +66,18 @@ public class ExportTask extends OfflineTask<PamDataUnit<?,?>>{
|
||||
@Override
|
||||
public void newDataLoad(long startTime, long endTime, OfflineDataMapPoint mapPoint) {
|
||||
// TODO Auto-generated method stub
|
||||
// System.out.println("EXPORTER: new data load");
|
||||
// System.out.println("EXPORTER: new data load");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadedDataComplete() {
|
||||
System.out.println("EXPORTER: loaded data complete");
|
||||
|
||||
//force the exporter so save any renaming data units in the buffer
|
||||
exporter.exportDataUnit(null, true);
|
||||
exporter.close();
|
||||
exporter.setCurrentFile(null);
|
||||
|
||||
|
||||
}
|
||||
/**
|
||||
* task has settings which can be called
|
||||
@ -80,13 +92,13 @@ public class ExportTask extends OfflineTask<PamDataUnit<?,?>>{
|
||||
* @return true if settings may have changed.
|
||||
*/
|
||||
public boolean callSettings() {
|
||||
|
||||
|
||||
dataSelector.getDialogPanel().setParams();
|
||||
|
||||
|
||||
DataSelectDialog dataSelectDialog = new DataSelectDialog(PamController.getMainFrame(),
|
||||
this.getDataBlock(), dataSelector, null);
|
||||
return dataSelectDialog.showDialog();
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,17 +108,17 @@ public class ExportTask extends OfflineTask<PamDataUnit<?,?>>{
|
||||
public boolean canExport(int exportSelection) {
|
||||
return exporter.getExporter(exportSelection).hasCompatibleUnits(getDataBlock().getUnitClass());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canRun() {
|
||||
boolean can = getDataBlock() != null;
|
||||
|
||||
|
||||
if (can) {
|
||||
//check whether we can export based on the export selection
|
||||
can = canExport(exporter.getExportParams().exportChoice);
|
||||
}
|
||||
|
||||
|
||||
return can;
|
||||
}
|
||||
|
||||
|
@ -465,6 +465,13 @@ public class WavFileExportManager implements PamDataUnitExporter {
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isNeedsNewFile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// hello(){
|
||||
|
@ -19,6 +19,9 @@ public class SmruDaqJNI {
|
||||
static public final int SMRU_VAL_SLAVE_MASTERED = 3;
|
||||
|
||||
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
|
||||
@ -29,11 +32,6 @@ public class SmruDaqJNI {
|
||||
private static final String SILIB = "SailDaqJNI";
|
||||
// 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 int MINJNIVERSION = 5;
|
||||
@ -265,7 +263,7 @@ public class SmruDaqJNI {
|
||||
this.smruDaqSystem = smruDaqSystem;
|
||||
loadLibrary();
|
||||
if (haveLibrary()) {
|
||||
setVerbose(verboseLevel);
|
||||
setVerbose(SmruDaqSystem.VERBOSELEVEL);
|
||||
|
||||
/**
|
||||
* List the devices, but don't do any resetting and
|
||||
@ -492,7 +490,7 @@ public class SmruDaqJNI {
|
||||
public int toggleLED(int board, int led) {
|
||||
board = boardOrder[board];
|
||||
int state = getLED(board, led);
|
||||
System.out.println("state="+state);
|
||||
// System.out.println("LED state="+state);
|
||||
if (state == 0) {
|
||||
state = 1;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import java.util.List;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
@ -13,6 +14,7 @@ import soundPlayback.PlaybackControl;
|
||||
import soundPlayback.PlaybackSystem;
|
||||
import Acquisition.AcquisitionControl;
|
||||
import Acquisition.AcquisitionDialog;
|
||||
import Acquisition.AcquisitionProcess;
|
||||
import Acquisition.DaqSystem;
|
||||
import Acquisition.AudioDataQueue;
|
||||
import PamController.PamControlledUnitSettings;
|
||||
@ -49,7 +51,8 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
||||
|
||||
public static final String oldCardName = "SMRU Ltd DAQ Card";
|
||||
|
||||
private static final int VERBOSELEVEL = 0;
|
||||
public static final int VERBOSELEVEL = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @param daqControl
|
||||
@ -61,6 +64,11 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
||||
smruDaqJNI = new SmruDaqJNI(this);
|
||||
|
||||
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);
|
||||
PamSettingManager.getInstance().registerSettings(this);
|
||||
@ -275,6 +283,8 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
||||
boolean prepareDaqCard(int iBoard, boolean fullReset) {
|
||||
// devices are left closed, so will need to reopen them.
|
||||
// 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 prepOk = smruDaqJNI.prepareDevice(hardId, fullReset);
|
||||
terminalPrint("Opened daq card returned " + prepOk, 1);
|
||||
@ -313,6 +323,7 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
||||
|
||||
if (ans) {
|
||||
Thread t = new Thread(new DaqThread());
|
||||
t.setPriority(Thread.MAX_PRIORITY);
|
||||
t.start();
|
||||
keepRunning = true;
|
||||
daqThreadRunning = true;
|
||||
@ -371,18 +382,43 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
||||
boolean first = true;
|
||||
boolean needRestart = false;
|
||||
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) {
|
||||
iChan = 0;
|
||||
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++) {
|
||||
if ((loopCount % 10000) == 0) {
|
||||
// toggleLED(iBoard, 0);
|
||||
smruDaqJNI.setLED(iBoard, SmruDaqJNI.GREEN_LED, 1);
|
||||
}
|
||||
for (int i = 0; i < boardChannels[iBoard] && keepRunning; i++) {
|
||||
newData = smruDaqJNI.readSamples(iBoard, i, wantedSamples);
|
||||
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",
|
||||
iBoard, i, wantedSamples));
|
||||
// System.out.println("Issue restart ...");
|
||||
needRestart = true;
|
||||
keepRunning = false;
|
||||
// keepRunning = false;
|
||||
break;
|
||||
}
|
||||
readSamples = newData.length;
|
||||
@ -409,19 +445,47 @@ public class SmruDaqSystem extends DaqSystem implements PamSettings {
|
||||
if (++dcOffsetCalls == 100) {
|
||||
dcOffsetScale = 100.; // after a bit, increase the time constant.
|
||||
}
|
||||
|
||||
|
||||
|
||||
totalSamples += readSamples;
|
||||
|
||||
}
|
||||
};
|
||||
daqThreadRunning = false;
|
||||
if (needRestart) {
|
||||
PamController pamController = PamController.getInstance();
|
||||
pamController.pamStop();
|
||||
PamDialog.showWarning(daqControl.getGuiFrame(), daqControl.getUnitName(), "Problem with one or more SAIL DAQ Cards.\n"
|
||||
+ "Restart PAMGuard, check connections and try again." );
|
||||
// pamController.startLater();
|
||||
|
||||
for (int iBoard = 0; iBoard < nDaqCards; iBoard++) {
|
||||
smruDaqJNI.setLED(iBoard, SmruDaqJNI.GREEN_LED, 0);
|
||||
}
|
||||
|
||||
if (needRestart) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
PamController pamController = PamController.getInstance();
|
||||
pamController.pamStop();
|
||||
System.out.println("Problem with one or more SAIL DAQ Cards. "
|
||||
+ "Restart PAMGuard, check connections and try again." );
|
||||
// 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) {
|
||||
|
@ -236,9 +236,9 @@ public class NoiseBandControl extends PamControlledUnit implements PamSettings {
|
||||
@Override
|
||||
public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
|
||||
noiseBandSettings = ((NoiseBandSettings)pamControlledUnitSettings.getSettings()).clone();
|
||||
System.out.println("********************************************************");
|
||||
System.out.println("NOISE BAND SETTINGS: " + noiseBandSettings.rawDataSource);
|
||||
System.out.println("********************************************************");
|
||||
// System.out.println("********************************************************");
|
||||
// System.out.println("NOISE BAND SETTINGS: " + noiseBandSettings.rawDataSource);
|
||||
// System.out.println("********************************************************");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,7 @@ public class OfflineTaskGroup implements PamSettings {
|
||||
|
||||
private ArrayList<OfflineTask> offlineTasks = new ArrayList<OfflineTask>();
|
||||
|
||||
private TaskGroupWorker worker;
|
||||
protected TaskGroupWorker worker;
|
||||
|
||||
private OfflineSuperDetFilter superDetectionFilter;
|
||||
|
||||
@ -377,7 +377,7 @@ public class OfflineTaskGroup implements PamSettings {
|
||||
* @author Doug Gillespie
|
||||
*
|
||||
*/
|
||||
class TaskGroupWorker extends SwingWorker<Integer, TaskMonitorData> implements ViewLoadObserver {
|
||||
public class TaskGroupWorker extends SwingWorker<Integer, TaskMonitorData> implements ViewLoadObserver {
|
||||
|
||||
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
|
||||
* not being in chronological order.
|
||||
*
|
||||
* @param timeChunks - the time chunks.
|
||||
*/
|
||||
private void processAllData(ArrayList<long[]> timeChunks){
|
||||
@ -976,4 +977,6 @@ public class OfflineTaskGroup implements PamSettings {
|
||||
offlineTasks.clear();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ import dataModelFX.DataModelPaneFX;
|
||||
import org.controlsfx.control.ToggleSwitch;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A pane which holds a set of tabs.
|
||||
*
|
||||
@ -125,7 +126,7 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
|
||||
this.pamGuiManagerFX=pamGuiManagerFX;
|
||||
this.mainTabPane = mainTabPane;
|
||||
|
||||
Pane layout=createMainPane(mainTabPane, stage);
|
||||
Node layout=createMainPane(mainTabPane, stage);
|
||||
|
||||
//add main pane to PamGui
|
||||
this.getChildren().add(layout);
|
||||
@ -140,7 +141,7 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
|
||||
//create the main tab pane.
|
||||
this.mainTabPane = new PamTabPane();
|
||||
|
||||
Pane layout=createMainPane(mainTabPane, stage);
|
||||
Node layout=createMainPane(mainTabPane, stage);
|
||||
|
||||
//add main pane to PamGui
|
||||
this.getChildren().add(layout);
|
||||
@ -154,7 +155,7 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
|
||||
* @param stage - the stage holding this GUI.
|
||||
* @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
|
||||
final PamBorderPane layout = new PamBorderPane();
|
||||
@ -261,7 +262,6 @@ public class PamGuiFX extends StackPane implements PamViewInterface {
|
||||
|
||||
PamBorderPane layoutHolder=new PamBorderPane(layout);
|
||||
layoutHolder.setTop(hidingLoadPane);
|
||||
|
||||
|
||||
return layoutHolder;
|
||||
|
||||
|
@ -253,6 +253,10 @@ public class PamGuiTabFX extends PamTabFX {
|
||||
double r1 = 1 - r;
|
||||
|
||||
int smallWindows = 0;
|
||||
|
||||
|
||||
//the padding between windows
|
||||
double padding = 10;
|
||||
|
||||
ArrayList<PamGuiInternalPane> dw = internalPanes;
|
||||
|
||||
@ -268,7 +272,9 @@ public class PamGuiTabFX extends PamTabFX {
|
||||
|
||||
//now place windows in correct position
|
||||
//large windows
|
||||
double x, y, w, h = 0;
|
||||
double x, y, w, h = 0.;
|
||||
double pad =0.;
|
||||
|
||||
if (largeWindows > 0) {
|
||||
x = 0;
|
||||
y = 0;
|
||||
@ -284,7 +290,10 @@ public class PamGuiTabFX extends PamTabFX {
|
||||
if (dw.get(i).getUserDisplayNode().isMinorDisplay()== true) continue;
|
||||
|
||||
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;
|
||||
else y += h;
|
||||
}
|
||||
@ -307,7 +316,10 @@ public class PamGuiTabFX extends PamTabFX {
|
||||
for (int i = 0; i < dw.size(); i++) {
|
||||
if (dw.get(i).getUserDisplayNode().isMinorDisplay() == false) continue;
|
||||
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;
|
||||
else y +=h;
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ public class PamFlipPane extends FlipPane {
|
||||
* Convenience duplicate of getBackPane().
|
||||
* @return the back pane.
|
||||
*/
|
||||
public PamBorderPane getAdvPane() {
|
||||
public PamBorderPane getAdvContentPane() {
|
||||
return advPane;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@ import javafx.beans.property.DoubleProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.geometry.Insets;
|
||||
|
||||
/**
|
||||
* 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
|
||||
hideButton=createShowButton(false);
|
||||
styleHideButton(hideButton);
|
||||
hideButton.setOnAction(new HideButtonPressed());
|
||||
// hideButton.setOnAction(new HideButtonPressed());
|
||||
hideButton.setVisible(false);
|
||||
// hideButton.setStyle("close-button-right");
|
||||
|
||||
@ -333,8 +332,6 @@ public class HidingPane extends StackPane {
|
||||
double dragX=0;
|
||||
double dragY=0;
|
||||
double distance=0;
|
||||
|
||||
|
||||
private PamButton createShowButton(final boolean show){
|
||||
|
||||
final PamButton pamButton=new PamButton();
|
||||
@ -343,6 +340,7 @@ public class HidingPane extends StackPane {
|
||||
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
// record a delta distance for the drag and drop operation.
|
||||
// System.out.println("HidingPane.showButton - setOnMousePressed");
|
||||
dragX =mouseEvent.getSceneX();
|
||||
dragY =mouseEvent.getSceneY();
|
||||
}
|
||||
@ -350,10 +348,24 @@ public class HidingPane extends StackPane {
|
||||
|
||||
pamButton.setOnMouseReleased(new EventHandler<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;
|
||||
// System.out.println("Mouse released: HidePanel distance: "+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.
|
||||
if (!isHorizontal()){
|
||||
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? false : true);
|
||||
}
|
||||
|
||||
//reset the distance
|
||||
distance=0;
|
||||
}
|
||||
@ -370,12 +383,14 @@ public class HidingPane extends StackPane {
|
||||
|
||||
pamButton.setOnMouseDragged(new EventHandler<MouseEvent>() {
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
// System.out.println("HidingPane.showButton - setOnMouseDragged");
|
||||
if (visibleImmediatly) hidePane.setVisible(true);
|
||||
else hidePane.setVisible(false);
|
||||
// hideButton.setVisible(true);
|
||||
/**
|
||||
* Work out the distance the panel is to be dragged;
|
||||
*/
|
||||
double distance = 0;
|
||||
if (!isHorizontal()){
|
||||
if (!show) distance=(mouseEvent.getSceneX()-dragX);
|
||||
else distance=(mouseEvent.getSceneX()-dragX)+sideIndex*expandedSize;
|
||||
@ -387,26 +402,28 @@ public class HidingPane extends StackPane {
|
||||
if (!overlay) distance=expandedSize+sideIndex*distance;
|
||||
}
|
||||
// if (show && Math.abs(distance)>expandedSize) return;
|
||||
|
||||
|
||||
translatePanel(distance);
|
||||
|
||||
HidingPane.this.distance = distance ;
|
||||
}
|
||||
});
|
||||
|
||||
pamButton.setOnMouseEntered(new EventHandler<MouseEvent>() {
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
// System.out.println("HidingPane.showButton - mouse entered");
|
||||
pamButton.setOpacity(1.0);
|
||||
pamButton.setPadding(new Insets(2.,2.,2.,2.));
|
||||
}
|
||||
});
|
||||
|
||||
pamButton.setOnMouseExited(new EventHandler<MouseEvent>() {
|
||||
@Override public void handle(MouseEvent mouseEvent) {
|
||||
// System.out.println("HidingPane.showButton - mouse exited");
|
||||
if (show) pamButton.setOpacity(showButtonOpacity);
|
||||
pamButton.setPadding(new Insets(0.,0.,0.,0.));
|
||||
}
|
||||
});
|
||||
// pamButton.setOnMouseEntered(new EventHandler<MouseEvent>() {
|
||||
// @Override public void handle(MouseEvent mouseEvent) {
|
||||
//// System.out.println("HidingPane.showButton - mouse entered");
|
||||
// pamButton.setOpacity(1.0);
|
||||
// pamButton.setPadding(new Insets(2.,2.,2.,2.));
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// pamButton.setOnMouseExited(new EventHandler<MouseEvent>() {
|
||||
// @Override public void handle(MouseEvent mouseEvent) {
|
||||
//// System.out.println("HidingPane.showButton - mouse exited");
|
||||
// if (show) pamButton.setOpacity(showButtonOpacity);
|
||||
// pamButton.setPadding(new Insets(0.,0.,0.,0.));
|
||||
// }
|
||||
// });
|
||||
|
||||
// pamButton.setOnMouseClicked(new EventHandler<MouseEvent>() {
|
||||
// @Override public void handle(MouseEvent mouseEvent) {
|
||||
@ -415,15 +432,15 @@ public class HidingPane extends StackPane {
|
||||
// }
|
||||
// });
|
||||
|
||||
pamButton.addEventHandler(ActionEvent.ACTION,new EventHandler<ActionEvent>() {
|
||||
@Override
|
||||
public void handle(ActionEvent e) {
|
||||
System.out.println("HidingPane.showButton - action event clicked");
|
||||
showHidePane(show);
|
||||
}
|
||||
});
|
||||
// pamButton.addEventHandler(ActionEvent.ACTION,new EventHandler<ActionEvent>() {
|
||||
// @Override
|
||||
// public void handle(ActionEvent e) {
|
||||
// System.out.println("HidingPane.showButton - action event clicked");
|
||||
// showHidePane(show);
|
||||
// }
|
||||
// });
|
||||
|
||||
if (show) pamButton.setOpacity(showButtonOpacity);
|
||||
// if (show) pamButton.setOpacity(showButtonOpacity);
|
||||
|
||||
return pamButton;
|
||||
}
|
||||
@ -601,7 +618,7 @@ public class HidingPane extends StackPane {
|
||||
showing.setValue(true);
|
||||
if (visibleImmediatly) hidePane.setVisible(true);
|
||||
//hideButton.setVisible(true);
|
||||
//System.out.println("HidingPane: Open Hide Pane");
|
||||
// System.out.println("HidingPane: Open Hide Pane");
|
||||
//open the panel
|
||||
if (timeLineShow.getStatus()==Status.RUNNING) {
|
||||
//stops the issue with the hiding pane freezing.
|
||||
@ -613,7 +630,7 @@ public class HidingPane extends StackPane {
|
||||
else{
|
||||
showing.setValue(false);
|
||||
if (!visibleImmediatly) hidePane.setVisible(false);
|
||||
//System.out.println("HidingPane: Close Hide Pane");
|
||||
// System.out.println("HidingPane: Close Hide Pane");
|
||||
//close the panel
|
||||
timeLineHide.play();
|
||||
}
|
||||
@ -638,17 +655,17 @@ public class HidingPane extends StackPane {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called whenever the pin button is pressed.
|
||||
* @author Jamie Macaulay
|
||||
*/
|
||||
class HideButtonPressed implements EventHandler<ActionEvent>{
|
||||
|
||||
@Override
|
||||
public void handle(ActionEvent arg0) {
|
||||
showHidePane(false);
|
||||
}
|
||||
}
|
||||
// /**
|
||||
// * Called whenever the pin button is pressed.
|
||||
// * @author Jamie Macaulay
|
||||
// */
|
||||
// class HideButtonPressed implements EventHandler<ActionEvent>{
|
||||
//
|
||||
// @Override
|
||||
// public void handle(ActionEvent arg0) {
|
||||
// showHidePane(false);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Get the button which hides the pane.
|
||||
@ -732,6 +749,15 @@ public class HidingPane extends StackPane {
|
||||
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.
|
||||
* @return the opacity of the show button.
|
||||
|
@ -244,7 +244,6 @@ public class ColourArray implements Cloneable, Serializable{
|
||||
colors[4]=Color.web("#0000ff");
|
||||
colors[5]=Color.web("#ff00ff");
|
||||
colors[6]=Color.web("#ff0000");
|
||||
|
||||
return colors;
|
||||
case PATRIOTIC:
|
||||
colors=new Color[3];
|
||||
@ -254,22 +253,22 @@ public class ColourArray implements Cloneable, Serializable{
|
||||
return colors;
|
||||
case MATLAB:
|
||||
colors=new Color[7];
|
||||
colors[0]= Color.color( 0, 0.4470, 0.7410);
|
||||
colors[1]= Color.color(0.8500 , 0.3250 , 0.0980);
|
||||
colors[2]= Color.color(0.9290 , 0.6940 , 0.1250);
|
||||
colors[3]= Color.color( 0.4940 , 0.1840 , 0.5560);
|
||||
colors[4]= Color.color(0.4660 , 0.6740 , 0.1880);
|
||||
colors[5]= Color.color( 0.3010 , 0.7450 , 0.9330);
|
||||
colors[6]= Color.color( 0.6350 , 0.0780 , 0.1840);
|
||||
colors[0]= Color.color(0, 0.4470, 0.7410);
|
||||
colors[1]= Color.color(0.8500, 0.3250, 0.0980);
|
||||
colors[2]= Color.color(0.9290, 0.6940, 0.1250);
|
||||
colors[3]= Color.color(0.4940, 0.1840, 0.5560);
|
||||
colors[4]= Color.color(0.4660, 0.6740, 0.1880);
|
||||
colors[5]= Color.color(0.3010, 0.7450, 0.9330);
|
||||
colors[6]= Color.color(0.6350, 0.0780, 0.1840);
|
||||
return colors;
|
||||
case PARULA:
|
||||
colors=new Color[6];
|
||||
colors[0]= Color.color( 0.24220, 0.150400, 0.66030);
|
||||
colors[1]= Color.color( 0.264700 ,0.403000 , 0.993500);
|
||||
colors[2]= Color.color( 0.108500, 0.66690 , 0.873400);
|
||||
colors[3]= Color.color( 0.280900 , 0.796400, 0.526600);
|
||||
colors[4]= Color.color( 0.918400, 0.73080 , 0.18900);
|
||||
colors[5]= Color.color( 0.9769 , 0.98390 ,0.0805000);
|
||||
colors[0]= Color.color(0.24220, 0.150400, 0.66030);
|
||||
colors[1]= Color.color(0.264700, 0.403000, 0.993500);
|
||||
colors[2]= Color.color(0.108500, 0.66690, 0.873400);
|
||||
colors[3]= Color.color(0.280900, 0.796400, 0.526600);
|
||||
colors[4]= Color.color(0.918400, 0.73080, 0.18900);
|
||||
colors[5]= Color.color(0.9769, 0.98390, 0.0805000);
|
||||
return colors;
|
||||
case INFERNO:
|
||||
return InfernoColorMap.getInfernoColourMap();
|
||||
|
@ -16,9 +16,9 @@ import javax.swing.JMenuItem;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JPopupMenu.Separator;
|
||||
import javax.swing.JRadioButtonMenuItem;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import PamView.ColourArray.ColourArrayType;
|
||||
import PamView.PamSymbol;
|
||||
import javafx.animation.KeyFrame;
|
||||
import javafx.animation.KeyValue;
|
||||
@ -54,6 +54,26 @@ import pamViewFX.fxNodes.PamSymbolFX;
|
||||
*/
|
||||
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
|
||||
@ -632,13 +652,36 @@ public class PamUtilsFX {
|
||||
* @param color - the color.
|
||||
* @return the color.
|
||||
*/
|
||||
public static String toRGBCode( Color color )
|
||||
{
|
||||
return String.format( "#%02X%02X%02X",
|
||||
(int)( color.getRed() * 255 ),
|
||||
(int)( color.getGreen() * 255 ),
|
||||
(int)( color.getBlue() * 255 ) );
|
||||
}
|
||||
|
||||
public static String toRGBCode( Color color ){
|
||||
return String.format( "#%02X%02X%02X",
|
||||
(int)( color.getRed() * 255 ),
|
||||
(int)( color.getGreen() * 255 ),
|
||||
(int)( color.getBlue() * 255 ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
import Layout.PamAxis;
|
||||
import javafx.beans.binding.Bindings;
|
||||
import javafx.beans.property.SimpleDoubleProperty;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.geometry.Side;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.canvas.Canvas;
|
||||
@ -256,13 +259,31 @@ public class PlotPane extends PamBorderPane {
|
||||
PamHBox horzHolder=new PamHBox();
|
||||
|
||||
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;
|
||||
leftPane.prefWidthProperty().bind(yAxisLeftPane.widthProperty());
|
||||
leftPane.minWidthProperty().bind(yAxisLeftPane.widthProperty());
|
||||
leftPane.prefWidthProperty().bind(valLeft);
|
||||
leftPane.minWidthProperty().bind(valLeft);
|
||||
|
||||
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);
|
||||
//axisPane.toFront(); this changes the order of children in a PamHBox.
|
||||
@ -369,8 +390,8 @@ public class PlotPane extends PamBorderPane {
|
||||
|
||||
//holderPane.getChildren().clear();
|
||||
|
||||
//HACK- 05/08/2016 have to do this because there is a bug in switching children postions in a border pane.
|
||||
//casues a duplicate childrne error.
|
||||
//HACK- 05/08/2016 have to do this because there is a bug in switching children positions in a border pane.
|
||||
//causes duplicate children error
|
||||
holderPane.setRight(null);
|
||||
holderPane.setLeft(null);
|
||||
holderPane.setTop(null);
|
||||
@ -385,24 +406,30 @@ public class PlotPane extends PamBorderPane {
|
||||
else if (topBorder > 0) {
|
||||
// holderPane.setTopSpace(topBorder);
|
||||
}
|
||||
|
||||
if (bottom) {
|
||||
holderPane.setBottom(bottomHolder);
|
||||
}
|
||||
else if (bottomBorder > 0) {
|
||||
// holderPane.setBottomSpace(bottomBorder);
|
||||
}
|
||||
|
||||
if (right) {
|
||||
holderPane.setRight(yAxisRightPane) ;
|
||||
yAxisRightPane.setVisible(true);
|
||||
}
|
||||
else if (rightBorder > 0){
|
||||
// holderPane.setRightSpace(rightBorder);
|
||||
else {
|
||||
yAxisRightPane.setVisible(false);
|
||||
}
|
||||
|
||||
if (left) {
|
||||
holderPane.setLeft(yAxisLeftPane) ;
|
||||
yAxisLeftPane.setVisible(true);
|
||||
}
|
||||
else if (leftBorder > 0) {
|
||||
// holderPane.setLeftSpace(leftBorder);
|
||||
else {
|
||||
yAxisLeftPane.setVisible(false);
|
||||
}
|
||||
|
||||
holderPane.setCenter(canvasHolder);
|
||||
//bottomHolder.toBack();
|
||||
|
||||
|
@ -179,6 +179,17 @@ public class PeakFreqOptionsPane extends StandardSymbolModifierPane {
|
||||
|
||||
DoubleSpinnerValueFactory spinnerValFact = (DoubleSpinnerValueFactory) maxFreq.getValueFactory();
|
||||
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) {
|
||||
|
@ -561,6 +561,7 @@ public class DLControl extends PamControlledUnit implements PamSettings {
|
||||
* @return the number of classes.
|
||||
*/
|
||||
public int getNumClasses() {
|
||||
if (getDLModel()==null) return 0;
|
||||
return getDLModel().getNumClasses();
|
||||
|
||||
}
|
||||
@ -622,8 +623,9 @@ public class DLControl extends PamControlledUnit implements PamSettings {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the classifier chooser.
|
||||
* @return the classifier chooser.Take it
|
||||
* Get the classifier chooser. The classifier chooser chooses which classifier use
|
||||
* based on a selected file or URL.
|
||||
* @return the classifier chooser.
|
||||
*/
|
||||
public DLClassifierChooser getDlClassifierChooser() {
|
||||
return dlClassifierChooser;
|
||||
|
@ -19,7 +19,9 @@ import pamViewFX.fxNodes.utilityPanes.PamToggleSwitch;
|
||||
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 {
|
||||
|
||||
|
@ -1,9 +1,14 @@
|
||||
package rawDeepLearningClassifier.dataPlotFX;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
import PamController.PamController;
|
||||
import PamUtils.PamArrayUtils;
|
||||
import PamView.GeneralProjector;
|
||||
import PamView.PamSymbolType;
|
||||
import PamView.dialog.GenericSwingDialog;
|
||||
import PamView.dialog.PamDialogPanel;
|
||||
import PamView.symbol.PamSymbolChooser;
|
||||
import PamView.symbol.SymbolData;
|
||||
import PamView.symbol.modifier.SymbolModType;
|
||||
@ -20,9 +25,10 @@ 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.
|
||||
*
|
||||
*/
|
||||
public class DLSymbolModifier extends SymbolModifier {
|
||||
@ -36,12 +42,12 @@ public class DLSymbolModifier extends SymbolModifier {
|
||||
|
||||
|
||||
/**
|
||||
* The symbol options pane.
|
||||
* JavaFX symbol options pane.
|
||||
*/
|
||||
private DLSymbolOptionPane optionsPane;
|
||||
|
||||
/**
|
||||
* Rge DL annotation type.
|
||||
* The DL annotation type.
|
||||
*/
|
||||
private DLAnnotationType dlAnnotType;
|
||||
|
||||
@ -55,6 +61,11 @@ public class DLSymbolModifier extends SymbolModifier {
|
||||
|
||||
private ColourArray colourArray;
|
||||
|
||||
/**
|
||||
* Swing option panel for the symbol chooser.
|
||||
*/
|
||||
private DLSymbolOptionPanel optionsPanel;
|
||||
|
||||
|
||||
|
||||
public DLSymbolModifier(PamSymbolChooser symbolChooser, DLAnnotationType dlAnnotType) {
|
||||
@ -94,7 +105,70 @@ public class DLSymbolModifier extends SymbolModifier {
|
||||
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) {
|
||||
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.
|
||||
* @return the symbol options pane.
|
||||
*/
|
||||
@Override
|
||||
public SymbolModifierPane getOptionsPane() {
|
||||
if (optionsPane == null) {
|
||||
optionsPane = new DLSymbolOptionPane(this);
|
||||
@ -168,6 +243,23 @@ public class DLSymbolModifier extends SymbolModifier {
|
||||
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() {
|
||||
return dlAnnotType;
|
||||
|
@ -1,7 +1,10 @@
|
||||
package rawDeepLearningClassifier.dataPlotFX;
|
||||
|
||||
|
||||
import PamView.symbol.modifier.SymbolModifierParams;
|
||||
import javafx.scene.paint.Color;
|
||||
import pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType;
|
||||
import pamViewFX.fxNodes.utilsFX.PamUtilsFX;
|
||||
|
||||
/**
|
||||
* Parameters for colouring symbols by deep learning probability.
|
||||
@ -10,11 +13,28 @@ import pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType;
|
||||
*
|
||||
*/
|
||||
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.
|
||||
@ -27,16 +47,72 @@ public class DLSymbolModifierParams extends SymbolModifierParams {
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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
|
||||
protected DLSymbolModifierParams clone() {
|
||||
|
@ -1,30 +1,43 @@
|
||||
package rawDeepLearningClassifier.dataPlotFX;
|
||||
|
||||
import org.controlsfx.control.SegmentedButton;
|
||||
|
||||
import PamView.symbol.StandardSymbolOptions;
|
||||
import PamView.symbol.modifier.SymbolModifier;
|
||||
import PamView.symbol.modifier.SymbolModifierParams;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Orientation;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.ColorPicker;
|
||||
import javafx.scene.control.ComboBox;
|
||||
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.Priority;
|
||||
import pamViewFX.fxNodes.PamBorderPane;
|
||||
import pamViewFX.fxNodes.PamHBox;
|
||||
import pamViewFX.fxNodes.PamVBox;
|
||||
import pamViewFX.fxNodes.comboBox.ColorComboBox;
|
||||
import pamViewFX.fxNodes.sliders.ColourRangeSlider;
|
||||
import pamViewFX.fxNodes.utilsFX.ColourArray;
|
||||
import pamViewFX.fxNodes.utilsFX.PamUtilsFX;
|
||||
import pamViewFX.symbol.StandardSymbolModifierPane;
|
||||
import rawDeepLearningClassifier.dlClassification.DLClassName;
|
||||
|
||||
|
||||
/*
|
||||
* Symbol Options for the annotation pane
|
||||
* Symbol Options for the annotation pane.
|
||||
*
|
||||
* @author Jamie Macaulay
|
||||
*/
|
||||
public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
||||
|
||||
|
||||
private static final double CLASS_NAME_BOX_WIDTH = 130;
|
||||
|
||||
/**
|
||||
* The colour range slider for colouring probabilities.
|
||||
*/
|
||||
@ -42,20 +55,142 @@ 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;
|
||||
|
||||
/**
|
||||
* Color picker which allows a user to select colour for each class.
|
||||
*/
|
||||
private ColorPicker colourPicker;
|
||||
|
||||
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) {
|
||||
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;
|
||||
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() {
|
||||
|
||||
@ -82,6 +217,8 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
||||
//change the colour of the colour range slider.
|
||||
notifySettingsListeners();
|
||||
});
|
||||
classNameBox.setPrefWidth(CLASS_NAME_BOX_WIDTH);
|
||||
|
||||
|
||||
colourBox = new ColorComboBox(ColorComboBox.COLOUR_ARRAY_BOX);
|
||||
colourBox.setPrefWidth(50);
|
||||
@ -92,17 +229,10 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
||||
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();
|
||||
classHolder.setSpacing(5);
|
||||
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();
|
||||
colorHolder.setSpacing(5);
|
||||
@ -112,7 +242,7 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
||||
holder.getChildren().addAll(classHolder, new Label("Probability"), colorHolder);
|
||||
|
||||
|
||||
holder.getChildren().add(showOnlyBinary);
|
||||
// holder.getChildren().add(showOnlyBinary);
|
||||
holder.setPadding(new Insets(5,0,5,0));
|
||||
|
||||
setParams = false;
|
||||
@ -120,35 +250,68 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
||||
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 ) {
|
||||
|
||||
int index = classNameBox2.getSelectionModel().getSelectedIndex()>=0 ? classNameBox2.getSelectionModel().getSelectedIndex():0;
|
||||
|
||||
|
||||
//bit messy but works /
|
||||
DLSymbolModifierParams symbolOptions = dlSymbolModifier.getSymbolModifierParams();
|
||||
symbolOptions.classColors[index] = PamUtilsFX.colorToInt(colourPicker.getValue());
|
||||
|
||||
symbolOptions.classIndex2 = classNameBox2.getSelectionModel().getSelectedIndex();
|
||||
|
||||
return symbolOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param symbolOptions
|
||||
* @return
|
||||
*/
|
||||
public DLSymbolModifierParams getPredictionColParams(DLSymbolModifierParams symbolOptions ) {
|
||||
|
||||
//need to chekc this here.
|
||||
//checkClassNamesBox(symbolOptions);
|
||||
|
||||
|
||||
symbolOptions.clims=new double[] {colourRangeSlider.getLowValue(), colourRangeSlider.getHighValue()};
|
||||
|
||||
symbolOptions.colArray = ColourArray.getColorArrayType(this.colourBox.getSelectionModel().getSelectedItem());
|
||||
|
||||
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();
|
||||
|
||||
dlSymbolModifier.checkColourArray();
|
||||
|
||||
//System.out.println("Get params: " );
|
||||
|
||||
return standardSymbolOptions;
|
||||
|
||||
}
|
||||
|
||||
private void checkClassNamesBox(DLSymbolModifierParams symbolOptions) {
|
||||
|
||||
private int checkClassNamesBox(DLSymbolModifierParams symbolOptions, ComboBox<String> classNameBox) {
|
||||
|
||||
DLClassName[] classNames = dlSymbolModifier.getDLAnnotType().getDlControl().getDLModel().getClassNames();
|
||||
|
||||
@ -167,8 +330,51 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
||||
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);
|
||||
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
|
||||
@ -180,24 +386,27 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
|
||||
|
||||
setParams = true;
|
||||
|
||||
// StandardSymbolOptions standardSymbolOptions = (StandardSymbolOptions) getSymbolModifier().getSymbolChooser().getSymbolOptions();
|
||||
|
||||
//get the symbool options
|
||||
DLSymbolModifierParams symbolOptions = dlSymbolModifier.getSymbolModifierParams();
|
||||
//now set frequency parameters
|
||||
colourRangeSlider.setLowValue(symbolOptions.clims[0]);
|
||||
colourRangeSlider.setHighValue(symbolOptions.clims[1]);
|
||||
colourRangeSlider.setColourArrayType( symbolOptions.colArray);
|
||||
|
||||
|
||||
//set the combo box class types.
|
||||
checkClassNamesBox( symbolOptions);
|
||||
// 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();
|
||||
|
||||
//color box.
|
||||
colourBox.setValue(symbolOptions.colArray);
|
||||
// symbolOptions.colTypeSelection = b1.isSelected() ? DLSymbolModifierParams.PREDICITON_COL : DLSymbolModifierParams.CLASS_COL;
|
||||
|
||||
//set the parameters for colouring by prediction
|
||||
setPredictionColParams(symbolOptions);
|
||||
|
||||
//set the class colour parameters
|
||||
setClassColParams(symbolOptions);
|
||||
|
||||
//set the selected.
|
||||
showOnlyBinary.setSelected(symbolOptions.showOnlyBinary);
|
||||
|
||||
|
||||
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_
|
||||
|
||||
### 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">
|
||||
<img width="550" height="700" src = "resources/default_settings_humpback_1.png">
|
||||
</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
|
||||
|
||||
@ -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).
|
||||
|
||||
### 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
|
||||
|
||||
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