Bug fix to hiding panes

This commit is contained in:
Jamie Mac 2024-07-19 16:49:34 +01:00
parent c01e966eaf
commit 6d58cee3b3
5 changed files with 123 additions and 59 deletions

View File

@ -6,19 +6,21 @@ PAMGuard is a bioacoustics analysis program designed for use in real time resear
## 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**: Off-the-shelf autonomous PAM devices, large scale surveys involving drifters, towed arrays and 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 provides visualisation tools for a manual analyst to check the results.
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
@ -49,20 +51,22 @@ Almsot all detection data can be visualised on a map. PAMGaurd also supports plo
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.
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 much more efficient analysis of data.
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.
### Metadata standard and Tethys compatibility
PAMGuard Integrates with Tethys
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.

View File

@ -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;

View File

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

View File

@ -0,0 +1,33 @@
package test.export;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import clickDetector.ClickDetection;
/**
* Tests for export functionality.
*/
public class ExportTest {
/**
* Test exporting detections to mat files.
*/
@Test
public void matFileTest() {
System.out.println("Matched template classifier test: match corr");
//create a list of click detections.
ClickDetection clickDetection = new ClickDetection(0, 0, 0, null, null, 0);
//now open the mat file and check that we have all the data from these click detections.
}
}

View File

@ -83,8 +83,9 @@ public class MatchedTemplateClassifierTest {
}
/**
* Test the match correlation algorithm combined with click length algorithm. Here we awant to test that
* a long waveform
* Test the match correlation algorithm combined with click length algorithm. Here we want to test that
* a long waveform can be processed properly - i.e the peak of the click can be found and cross correlation performed
* on a shortened section.
*/
@Test
public void testMatchCorrLen() {