Merge branch 'main' of https://github.com/macster110/PAMGuard into macster110-main

This commit is contained in:
Douglas Gillespie 2024-08-23 15:23:17 +01:00
commit 3dfe44d383
87 changed files with 2576 additions and 893 deletions

View File

@ -6,8 +6,9 @@
<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.launching.macosx.MacOSXType/Amazon Corretto 21 [21.0.2]">
<attributes>
<attribute name="module" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>

View File

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

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<a:clrMap xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" bg1="lt1" tx1="dk1" bg2="lt2" tx2="dk2" accent1="accent1" accent2="accent2" accent3="accent3" accent4="accent4" accent5="accent5" accent6="accent6" hlink="hlink" folHlink="folHlink"/>

BIN
README.files/themedata.thmx Normal file

Binary file not shown.

View File

@ -595,7 +595,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
System.out.println("The current file was null");
return false;
}
// System.out.printf("*********************************** Opening file %s\n", currentFile.getName());
System.out.printf("*********************************** Opening file %s\n", currentFile.getName());
try {
@ -640,6 +640,9 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
loadByteConverter(audioFormat);
// System.out.println("FileInputSystem - prepareInputFile done");
} catch (UnsupportedAudioFileException ex) {
ex.printStackTrace();
return false;

View File

@ -933,6 +933,7 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
@Override
public InputStoreInfo getStoreInfo(boolean detail) {
System.out.println("FolderInputSystem: Get store info start:");
if (allFiles == null || allFiles.size() == 0) {
return null;
}
@ -967,6 +968,7 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
storeInfo.setFileStartTimes(allFileStarts);
storeInfo.setFileEndTimes(allFileEnds);
}
System.out.println("FolderInputSystem: Get store info complete:");
return storeInfo;
}

View File

@ -851,7 +851,7 @@ public class PamController implements PamControllerInterface, PamSettings {
String help = null;
int ans = WarnOnce.showWarning(title, msg, WarnOnce.WARNING_MESSAGE, help, e);
System.err.println("Exception while loading " + moduleName);
this.removeControlledUnt(unitBeingLoaded);
//this.removeControlledUnt(unitBeingLoaded);
this.clearLoadedUnit();
;
}

View File

@ -55,16 +55,6 @@ import pamguard.GlobalArguments;
//import org.w3c.dom.Node;
//import com.thoughtworks.xstream.XStream;
import java.io.StringWriter;
//import javax.xml.transform.OutputKeys;
//import javax.xml.transform.Transformer;
//import javax.xml.transform.TransformerException;
@ -73,13 +63,6 @@ import java.io.StringWriter;
//import javax.xml.transform.stream.StreamResult;
//import sun.jdbc.odbc.OdbcDef;
import tipOfTheDay.TipOfTheDayManager;
//import javax.swing.filechooser.FileFilter;
@ -90,11 +73,7 @@ import PamController.settings.SettingsNameChanger;
import PamUtils.PamCalendar;
import PamUtils.PamFileChooser;
import PamUtils.PamFileFilter;
import PamUtils.Splash;
import PamView.PamGui;
import PamView.dialog.warn.WarnOnce;
import amplifier.AmpDialog;
import amplifier.AmpParameters;
//import PamUtils.PamFileFilter;
@ -172,6 +151,7 @@ public class PamSettingManager {
static public final String fileEnd = "psf";
static public final String fileEndx = "psfx";
static public final String fileEndXML = "psfxml";
private static boolean saveAsPSFX = true;
static public String getCurrentSettingsFileEnd() {
@ -220,11 +200,12 @@ public class PamSettingManager {
/**
* Save settings to a psf file
*/
static private final int SAVE_PSF = 0x1;
static public final int SAVE_PSF = 0x1;
/**
* Save settings to database tables (if available).
*/
static private final int SAVE_DATABASE = 0x2;
static public final int SAVE_DATABASE = 0x2;
/**
* running in remote mode, default normal
@ -800,7 +781,6 @@ public class PamSettingManager {
/*
* then save it to a single XML file
*/
//XML file test
objectToXMLFile(pamSettingsList,file);

View File

@ -24,7 +24,6 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
@ -52,8 +51,6 @@ import rockBlock.RockBlockControl;
import tethys.TethysControl;
import turbineops.TurbineOperationControl;
import GPS.GpsDataUnit;
import Map.MapController;
import Map.gridbaselayer.GridbaseControl;
import NMEA.NMEADataUnit;
import PamController.PamControlledUnitSettings;
import PamController.PamController;
@ -67,7 +64,6 @@ import PamguardMVC.PamDataBlock;
import analogarraysensor.ArraySensorControl;
import backupmanager.BackupManager;
import beamformer.continuous.BeamFormerControl;
import beamformer.localiser.BeamFormLocaliserControl;
import bearinglocaliser.BearingLocaliserControl;
import binaryFileStorage.SecondaryBinaryStore;
import cepstrum.CepstrumControl;

View File

@ -713,6 +713,34 @@ public class PamArrayUtils {
}
/**
* Normalise an array
* @param arr - the array to normalise
* @param scaleFactor - multiply the resulting array by a scale factor.
* @return normalised copy of the array
*/
public static float[] normalise(float[] arr, double scaleFactor) {
// //first find the sum of the square of the wave
if (arr != null) {
int n = arr.length;
double sum = 0.0;
for (int i = 0; i < n; i++) {
sum += arr[i] * arr[i];
}
sum = Math.pow(sum, 0.5);
float[] normArr=new float[arr.length];
for (int i=0; i<normArr.length; i++) {
normArr[i]=(float) (scaleFactor*arr[i]/sum);
}
return normArr;
}
else return null;
}
/**
* Flip a double array so that it is in the reverse order. Note the array is
* cloned.
@ -1274,6 +1302,7 @@ public class PamArrayUtils {
}

View File

View File

@ -1,114 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="150mm"
height="150mm"
viewBox="0 0 150 150"
version="1.1"
id="svg5"
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
sodipodi:docname="logo01.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="0.74564394"
inkscape:cx="379.53772"
inkscape:cy="512.97943"
inkscape:window-width="1242"
inkscape:window-height="1008"
inkscape:window-x="649"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="layer1" />
<defs
id="defs2">
<inkscape:path-effect
effect="bspline"
id="path-effect3117"
is_visible="true"
lpeversion="1"
weight="33.333333"
steps="2"
helper_size="0"
apply_no_weight="true"
apply_with_weight="true"
only_selected="false" />
<inkscape:path-effect
effect="bspline"
id="path-effect3117-7"
is_visible="true"
lpeversion="1"
weight="33.333333"
steps="2"
helper_size="0"
apply_no_weight="true"
apply_with_weight="true"
only_selected="false" />
<inkscape:path-effect
effect="bspline"
id="path-effect3117-6"
is_visible="true"
lpeversion="1"
weight="33.333333"
steps="2"
helper_size="0"
apply_no_weight="true"
apply_with_weight="true"
only_selected="false" />
</defs>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<text
xml:space="preserve"
style="font-size:3.175px;fill:#000000;stroke-width:0.264583"
x="11.709678"
y="81.967743"
id="text113"><tspan
sodipodi:role="line"
id="tspan111"
style="font-style:normal;font-variant:normal;font-weight:300;font-stretch:normal;font-size:25.4px;font-family:Calibri;-inkscape-font-specification:'Calibri, Light';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;stroke-width:0.264583"
x="11.709678"
y="81.967743"><tspan
style="fill:#6f916f"
id="tspan167">delphin</tspan><tspan
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:25.4px;font-family:Calibri;-inkscape-font-specification:'Calibri, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;fill:#0b2817"
id="tspan165">ID</tspan></tspan></text>
<path
style="fill:#6f916f;stroke-width:0.264583"
d="m 27.322579,38.322579 6.741938,2.838712"
id="path535" />
<path
style="fill:none;stroke:#000000;stroke-width:0.85;stroke-dasharray:none;stroke-opacity:1"
d="m 120.67435,61.080456 c 1.55411,1.367612 3.10801,2.735039 4.219,4.735608 1.11098,2.00057 1.77914,4.634082 1.8024,7.356282 0.0232,2.7222 -0.5983,5.53298 -1.65497,7.685367 -1.05667,2.152388 -2.5484,3.646416 -4.0401,5.140414"
id="path3115"
inkscape:path-effect="#path-effect3117"
inkscape:original-d="m 120.67435,61.080456 c 1.55406,1.367671 3.10796,2.735101 4.66173,4.102301 0.66832,2.63386 1.33649,5.26737 2.00453,7.90072 -0.62143,2.81111 -1.24298,5.62189 -1.86469,8.43252 -1.49163,1.49428 -2.98336,2.98831 -4.47524,4.48213" />
<path
style="fill:none;stroke:#000000;stroke-width:0.85;stroke-dasharray:none;stroke-opacity:1"
d="m 115.99401,66.369877 c 0.93292,0.812059 1.86573,1.624027 2.53264,2.81193 0.66692,1.187903 1.06802,2.751664 1.08197,4.368074 0.014,1.61641 -0.35915,3.285393 -0.99347,4.563459 -0.63431,1.278066 -1.52976,2.165182 -2.42524,3.052317"
id="path3115-4"
inkscape:path-effect="#path-effect3117-6"
inkscape:original-d="m 115.99401,66.369877 c 0.93289,0.81209 1.8657,1.62406 2.79841,2.43588 0.4012,1.56394 0.8023,3.1277 1.20331,4.69134 -0.37304,1.66922 -0.74616,3.3382 -1.11936,5.00712 -0.89543,0.88729 -1.79089,1.7744 -2.68646,2.66144" />
<path
style="fill:none;stroke:#000000;stroke-width:0.85;stroke-dasharray:none;stroke-opacity:1"
d="m 125.65039,55.168033 c 2.46165,2.066818 4.923,4.133391 6.68278,7.156798 1.75977,3.023407 2.81814,7.003389 2.85497,11.117374 0.0368,4.113986 -0.9477,8.361845 -2.62144,11.614689 -1.67374,3.252844 -4.03659,5.51072 -6.39943,7.768583"
id="path3115-8"
inkscape:path-effect="#path-effect3117-7"
inkscape:original-d="m 125.65039,55.168033 c 2.46157,2.06691 4.92292,4.133487 7.38405,6.199707 1.05862,3.980467 2.11699,7.960447 3.17515,11.940157 -0.98434,4.24836 -1.96886,8.49622 -2.95363,12.74383 -2.36272,2.2583 -4.72558,4.51617 -7.08869,6.77375" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

View File

@ -27,6 +27,7 @@ public class DataMapGUIFX extends PamControlledGUIFX implements DataMapControlGU
* The data map displays to add.
*/
public ArrayList<UserDisplayNodeFX> getDisplays(){
try {
if (dataMapDisplays==null){
dataMapPaneFX = new DataMapPaneFX(dataMapControl);
dataMapDisplays=new ArrayList<UserDisplayNodeFX>();
@ -34,6 +35,11 @@ public class DataMapGUIFX extends PamControlledGUIFX implements DataMapControlGU
dataMapDisplays.add(dataMapPaneFX);
}
return dataMapDisplays;
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override

View File

@ -55,7 +55,7 @@ public class DataMapPaneFX extends PamBorderPane implements UserDisplayNodeFX {
/**
* The hiding pane which holds the summary pane.
*/
private HidingPane hidingSummaryPane;
private HidingPane hidingSettingsPane;
/**
* The buttons which shows the top hiding pane.
@ -65,7 +65,7 @@ public class DataMapPaneFX extends PamBorderPane implements UserDisplayNodeFX {
/**
* Pane which allows users to change scale on datamap.
*/
private ScalePaneFX scalePane;
private DataMapSettingsPane dataMapSettingsPane;
private PamVBox settingsPane;
@ -87,14 +87,14 @@ public class DataMapPaneFX extends PamBorderPane implements UserDisplayNodeFX {
//create all the different panes,
summaryPane = new SummaryPaneFX(dataMapControl, this);
scalePane=new ScalePaneFX(dataMapControl,this);
scrollingDataPanel= new ScrollingDataPaneFX(dataMapControl, this);
dataMapSettingsPane=new DataMapSettingsPane(dataMapControl,this);
//create the setting spane
settingsPane=new PamVBox();
// settingsPane.getChildren().add(summaryPane);
settingsPane.getChildren().add(scalePane);
settingsPane.getChildren().add(dataMapSettingsPane.getContentNode());
settingsPane.setPadding(new Insets(40,10,10,10));
settingsPane.setPrefWidth(HIDE_PANE_WIDTH);
@ -105,16 +105,16 @@ public class DataMapPaneFX extends PamBorderPane implements UserDisplayNodeFX {
//topHolder.prefHeightProperty().bind(summaryPane.prefHeightProperty());
//hiding summary pane
hidingSummaryPane=new HidingPane(Side.RIGHT, settingsPane, this, true);
hidingSummaryPane.setVisibleImmediatly(false);
hidingSummaryPane.showHidePane(true);
hidingSummaryPane.getStyleClass().add("pane-trans");
hidingSummaryPane.getStylesheets().addAll(PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getSlidingDialogCSS());
StackPane.setAlignment(hidingSummaryPane, Pos.TOP_RIGHT);
hidingSummaryPane.setPrefWidth(HIDE_PANE_WIDTH);
hidingSettingsPane=new HidingPane(Side.RIGHT, settingsPane, this, true);
hidingSettingsPane.setVisibleImmediatly(false);
hidingSettingsPane.showHidePane(true);
hidingSettingsPane.getStyleClass().add("pane-trans");
hidingSettingsPane.getStylesheets().addAll(PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getSlidingDialogCSS());
StackPane.setAlignment(hidingSettingsPane, Pos.TOP_RIGHT);
hidingSettingsPane.setPrefWidth(HIDE_PANE_WIDTH);
//style the show button.
showButton=hidingSummaryPane.getShowButton();
showButton=hidingSettingsPane.getShowButton();
showButton.getStyleClass().add("close-button-left");
showButton.getStylesheets().addAll(PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getSlidingDialogCSS());
@ -127,7 +127,7 @@ public class DataMapPaneFX extends PamBorderPane implements UserDisplayNodeFX {
StackPane.setAlignment(showButton, Pos.CENTER_RIGHT);
StackPane stackPane = new StackPane();
stackPane.getChildren().addAll(scrollingDataPanel, hidingSummaryPane, showButton);
stackPane.getChildren().addAll(scrollingDataPanel, hidingSettingsPane, showButton);
dateAxis = new PamDateAxis();
dateAxis.setMinHeight(50);
@ -179,11 +179,11 @@ public class DataMapPaneFX extends PamBorderPane implements UserDisplayNodeFX {
* to do with scaling changes.
*/
public void scaleChanged() {
if (scalePane == null || scrollingDataPanel == null) {
if (dataMapSettingsPane == null || scrollingDataPanel == null) {
return;
}
scalePane.getParams(dataMapControl.dataMapParameters);
scrollingDataPanel.scaleChange();
dataMapSettingsPane.getParams(dataMapControl.dataMapParameters);
//scrollingDataPanel.scaleChange();
}
@Override
@ -227,24 +227,30 @@ public class DataMapPaneFX extends PamBorderPane implements UserDisplayNodeFX {
switch (changeType) {
case PamControllerInterface.INITIALIZATION_COMPLETE:
scrollingDataPanel.updateScrollBar();
scalePane.checkDataGramPane();
dataMapSettingsPane.setParams(dataMapControl.dataMapParameters);
this.repaintAll();
break;
case PamControllerInterface.CHANGED_OFFLINE_DATASTORE:
scrollingDataPanel.updateScrollBar();
scalePane.checkDataGramPane();
dataMapSettingsPane.checkDataGramPane();
dataMapSettingsPane.setParams(dataMapControl.dataMapParameters);
break;
case PamControllerInterface.ADD_CONTROLLEDUNIT:
scalePane.checkDataGramPane();
case PamControllerInterface.REMOVE_CONTROLLEDUNIT:
scalePane.checkDataGramPane();
dataMapSettingsPane.checkDataGramPane();
dataMapSettingsPane.setParams(dataMapControl.dataMapParameters);
break;
case PamControllerInterface.INITIALIZE_LOADDATA:
case PamControllerInterface.EXTERNAL_DATA_IMPORTED:
scrollingDataPanel.updateScrollBar();
scalePane.checkDataGramPane();
dataMapSettingsPane.checkDataGramPane();
dataMapSettingsPane.setParams(dataMapControl.dataMapParameters);
this.repaintAll();
break;
case PamControllerInterface.OFFLINE_DATA_LOADED:
scrollingDataPanel.updateScrollBar();
scalePane.checkDataGramPane();
dataMapSettingsPane.checkDataGramPane();
dataMapSettingsPane.setParams(dataMapControl.dataMapParameters);
this.repaintAll();
break;
case PamControllerInterface.DATA_LOAD_COMPLETE:
@ -303,4 +309,22 @@ public class DataMapPaneFX extends PamBorderPane implements UserDisplayNodeFX {
return null;
}
/**
* Get the current number of data stream panes
* @return the number of data stream panes
*/
public int getNumDataStreamPanes() {
return this.scrollingDataPanel.getNumDataStreamPanes();
}
/**
* Get a data stream pane.
* @param n - the index of the data stream pane
* @return the data stream pane or null if the index is out of bounds.
*/
public DataStreamPaneFX getDataStreamPane(int n) {
return this.scrollingDataPanel.getDataSyreamPane( n);
}
}

View File

@ -0,0 +1,101 @@
package dataMap.layoutFX;
import java.util.ArrayList;
import PamController.OfflineDataStore;
import PamController.PamController;
import dataMap.DataMapControl;
import dataMap.OfflineDataMap;
import dataMap.OfflineDataMapPoint;
import javafx.scene.paint.Color;
import pamViewFX.fxNodes.pamScrollers.acousticScroller.ScrollBarPane;
/**
* A scroll bar whihc shows a summary fo the data.
*/
public class DataMapScrollBar extends ScrollBarPane {
private DataMapControl dataMapControl;
public DataMapScrollBar(DataMapControl dataMapControl) {
super();
this.dataMapControl=dataMapControl;
}
/**
* Paint a summary of the data
*/
public void paintDataSummary() {
ArrayList<OfflineDataStore> offlineDataStores = PamController.getInstance().findOfflineDataStores();
OfflineDataStore aSource;
Color color = Color.DODGERBLUE;
this.getDrawCanvas().getGraphicsContext2D().setStroke(color);
this.getDrawCanvas().getGraphicsContext2D().setGlobalAlpha(0.3);
for (int i = 0; i < offlineDataStores.size(); i++) {
aSource = offlineDataStores.get(i);
paintOfflineDataSource(aSource);
}
}
/**
* Paint the data on the canvas.
* @param dataSource - the dta source.
*/
private void paintOfflineDataSource(OfflineDataStore dataSource) {
if (dataMapControl.getMappedDataBlocks()==null) return;
OfflineDataMap aMap;
for (int i = 0; i < dataMapControl.getMappedDataBlocks().size(); i++) {
aMap = dataMapControl.getMappedDataBlocks().get(i).getOfflineDataMap(dataSource);
if (aMap == null) {
continue;
}
long lastTime;
OfflineDataMapPoint aPoint;
for (int j=0; j<aMap.getMapPoints().size(); j++) {
aPoint= (OfflineDataMapPoint) aMap.getMapPoints().get(j);
//now have to paint the canvas. To be efficient find the start pixel, then iterate through all the
//the other pixels.
double startPixel = time2Pixel(aPoint.getStartTime());
double endPixel = time2Pixel(aPoint.getEndTime());
for (double k=startPixel; k<endPixel ; k++) {
this.getDrawCanvas().getGraphicsContext2D().strokeLine(k, 0, k, this.getDrawCanvas().getHeight());
}
}
}
}
/**
* Convert a time in millis to a pixel on the canvas.
* @param time
* @return
*/
private double time2Pixel(long time) {
double timeRangemillis = this.getMaxVal() - this.getMinVal();
double frac = ((double) (time - dataMapControl.getFirstTime()))/timeRangemillis;
return frac*this.getDrawCanvas().getWidth();
}
private long pixel2Time(double pixel) {
double frac = pixel/this.getDrawCanvas().getWidth();
double timeRangemillis = this.getMaxVal() - this.getMinVal();
long timeMillis = (long) (frac*timeRangemillis) + dataMapControl.getFirstTime();
return timeMillis;
}
}

View File

@ -0,0 +1,489 @@
package dataMap.layoutFX;
import dataGram.DatagramManager;
import dataGram.DatagramScaleInformation;
import dataGram.DatagramSettings;
import dataMap.DataMapControl;
import dataMap.DataMapParameters;
import PamController.PamController;
import PamUtils.PamCalendar;
import binaryFileStorage.BinaryStore;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
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.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import pamViewFX.PamGuiManagerFX;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamGridPane;
import pamViewFX.fxNodes.PamVBox;
import pamViewFX.fxNodes.comboBox.ColorComboBox;
import pamViewFX.fxNodes.pamDialogFX.PamDialogFX;
import pamViewFX.fxNodes.sliders.ColourRangeSlider;
import pamViewFX.fxNodes.utilityPanes.PamToggleSwitch;
import pamViewFX.fxNodes.utilsFX.ColourArray;
import pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType;
import pamViewFX.fxSettingsPanes.DynamicSettingsPane;
/**
* Settings pane which allows users to change settings for data maps.
*
* @author Jamie Macaulay
*
*/
public class DataMapSettingsPane extends DynamicSettingsPane<DataMapParameters> {
/*
* Reference to the data map control.
*/
private DataMapControl dataMapControl;
/**
* Reference to the dataMapPane.
*/
private DataMapPaneFX dataMapPane;
// /**
// * The slider which determines time scale.
// */
// private Slider timeSlider;
/**
* Shows the time scale in pix/hour
*/
private Label timeScaleLabel;
/**
* Selects unit count on vertical scale
*/
private ComboBox<String> scaleBox;
/**
* Check box for log vertical scale.
*/
private PamToggleSwitch logScaleToggle;
// /**
// * The chosen time values.
// */
// private double[] timeScaleChoices = DataMapParameters.hScaleChoices;
/**
* Combo box holding options to channge the datargam bin size
*/
private ComboBox<String> datagramBox;
/**
* Holds a list of times for the datagram bin size.
*/
private ComboBox<String> dataGramComboBox;
/**
* Holds everything.
*/
private PamVBox holder;
/**
* Grid pane with settings for the data scales
*/
private PamGridPane scaleSettingsPane;
private Label dataGramLabel;
private ComboBox<String> dataGramBox;
/**
* Holdes datagram settings.
*/
private PamVBox dataGramSettingsPane;
private DataGramColPane dataGramColPane;
private PamBorderPane mainPain;
public DataMapSettingsPane(DataMapControl dataMapControl, DataMapPaneFX dataMapPane) {
super(null);
this.dataMapControl = dataMapControl;
this.dataMapPane = dataMapPane;
// //create the holder pane.
// PamVBox vBoxHolder=new PamVBox();
// vBoxHolder.setSpacing(5);
// Label title=new Label("Scales");
// PamGuiManagerFX.titleFont2style(title);
// vBoxHolder.getChildren().addAll(title, controlPane);
//add the scale
holder=new PamVBox();
holder.setSpacing(5);
Label scaleLabel = new Label("Data Scale");
PamGuiManagerFX.titleFont2style(scaleLabel);
holder.getChildren().add(scaleLabel);
holder.getChildren().add(scaleSettingsPane = createScalePane());
//adds the datagram settings pane which is dependent on binary storage.
checkDataGramPane();
mainPain = new PamBorderPane();
mainPain.setCenter(holder);
//set params for the pane
setParams(dataMapControl.dataMapParameters);
checkDataGramPane(); // create datagram pane if a binary store already added.
sayHScale();
}
/**
* Adds a settings pane for the data gram if a binary store is present.
*/
public void checkDataGramPane(){
if (BinaryStore.findBinaryStoreControl()!=null){
DatagramManager dataGramManager=BinaryStore.findBinaryStoreControl().getDatagramManager();
if (dataGramManager!=null && dataGramSettingsPane==null) {
PamVBox datagramholder = new PamVBox();
datagramholder.setSpacing(5);
Label datagramLabel = new Label("Datagrams");
PamGuiManagerFX.titleFont2style(datagramLabel);
datagramholder.getChildren().add(datagramLabel);
datagramholder.getChildren().add(createDatagramPane(dataGramManager));
holder.getChildren().add(this.dataGramSettingsPane = datagramholder);
}
}
else {
holder.getChildren().remove(this.dataGramSettingsPane);
datagramBox=null;
}
}
/**
* Create the a datagram combo box to change the size of the datagram
* @param dataGramManager - the datagram manager for the current biinary store.
* @return a combo box with datagram bin sizes.
*/
private ComboBox<String> createDataGramBinPane(DatagramManager dataGramManager){
dataGramComboBox=new ComboBox<String>(createDurationList(dataGramManager));
dataGramComboBox.getSelectionModel().select(durationToString(dataGramManager.getDatagramSettings().datagramSeconds*1000L));
dataGramComboBox.valueProperty().addListener(( ov, t, t1) -> {
if (t==t1) return;
else {
PamController.getInstance();
boolean ans=PamDialogFX.showWarning(PamController.getMainStage(), "Warning", "Recalculating the datagram for a large dataset may take a long time" +
"Are you sure you want to continue");
if (ans){
int index=dataGramComboBox.getSelectionModel().getSelectedIndex();
//messy- datagramSeconfds should be in millis but left for backwards compatibility.
dataGramManager.getDatagramSettings().datagramSeconds=(int) (DatagramSettings.defaultDatagramSeconds[index]/1000);
dataGramManager.updateDatagrams();
dataMapPane.repaintAll();
}
}
});
return dataGramComboBox;
}
/**
* Convert duration to string.
* @param duration in millis.
*/
private String durationToString(long duration){
return (" " + PamCalendar.formatDuration(duration));
}
/**
* Create list of load times.
* @return list of load times duration.
*/
private ObservableList<String> createDurationList(DatagramManager dataGramManager){
ObservableList<String> loadTimeList=FXCollections.observableArrayList();
for (int i=0; i<DatagramSettings.defaultDatagramSeconds.length; i++){
loadTimeList.add(durationToString(DatagramSettings.defaultDatagramSeconds[i]));
}
return loadTimeList;
}
private Pane createDatagramPane(DatagramManager dataGramManager) {
dataGramLabel= new Label("Datagram bin size");
ComboBox<String> datagramBinsBox = createDataGramBinPane(dataGramManager);
//Pane for colouring datagrams.
dataGramBox=new ComboBox<String> ();
//find all datagrams.
updateDataStreamBox();
dataGramBox.setOnAction((action)->{
dataGramColPane.setDataStreamPanel(dataMapPane.getDataStreamPane(dataGramBox.getSelectionModel().getSelectedIndex()));
});
//holds settings for the datagram
dataGramColPane = new DataGramColPane();
PamGridPane holder = new PamGridPane();
holder.setHgap(5);
holder.setVgap(5);
//holder.setGridLinesVisible(true);
int row = 0;
holder.add(dataGramLabel, 0,row);
holder.add(datagramBinsBox, 1, row);
row++;
holder.add(new Label("Select datagram"), 0, row);
holder.add(dataGramBox, 1, row);
row++;
GridPane.setHgrow(dataGramColPane, Priority.ALWAYS);
holder.add(dataGramColPane, 0, row);
//dunno why this always had to be set after the child has been added to work.
GridPane.setColumnSpan(dataGramColPane, 3);
//hack to make sure the third column of the gris expands to fit the pane
ColumnConstraints rightCol = new ColumnConstraints();
rightCol.setHgrow(Priority.ALWAYS);
holder.getColumnConstraints().addAll(new ColumnConstraints(), new ColumnConstraints(), rightCol);
return holder;
}
private void updateDataStreamBox() {
System.out.println("UPDATE DATA STREAM BOX: " + this.dataMapPane.getNumDataStreamPanes());
for (int i=0; i<this.dataMapPane.getNumDataStreamPanes(); i++) {
if (dataMapPane.getDataStreamPane(i).getScaleType() == DatagramScaleInformation.PLOT_3D) {
dataGramBox.getItems().add(dataMapPane.getDataStreamPane(i).getDataName().getName());
}
}
}
/**
* Allows the user to change datagram colours.
*
*/
public class DataGramColPane extends PamBorderPane {
private ColourRangeSlider colourSlider;
private Label ampLabel;
private ColorComboBox colorBox;
private ColourArrayType colorArray = ColourArrayType.HSV;
private DataStreamPaneFX dataStreamPane;
public DataGramColPane() {
//create colour slider
//colour slider
colourSlider=new ColourRangeSlider();
colourSlider.setShowTickMarks(false);
colourSlider.setShowTickLabels(false);
colourSlider.setOrientation(Orientation.HORIZONTAL);
//amplifier label
// String dBRef = GlobalMedium.getdBRefString(PamController.getInstance().getGlobalMediumManager().getCurrentMedium());
Label ampLabel = new Label("Colour scale");
colorBox=new ColorComboBox(ColorComboBox.COLOUR_ARRAY_BOX);
colorBox.setPrefWidth(80);
colourSlider.highValueProperty().addListener((obsVal, oldVal, newVal)->{
});
//Change the colour of the colour slider when combo box is changed.
colorBox.valueProperty().addListener(new ChangeListener<String>() {
@Override public void changed(ObservableValue<? extends String> ov, String t, String t1) {
//change the colour of the colour range slider.
setColours();
}
});
colorBox.setValue(ColourArray.getName(getColourArrayType()));
//need to set up alignment properly. //FIXME- a bit messy
BorderPane.setAlignment(colorBox, Pos.CENTER);
//sliderPane.setPadding(new Insets(10,0,0,0));
BorderPane.setMargin(colorBox, new Insets(0,5,0,5));
this.setCenter(colourSlider);
this.setRight(colorBox);
//set up so the correct color
colorBox.setValue(ColourArray.getName(getColourArrayType()));
colourSlider.setColourArrayType(getColourArrayType());
}
public void setDataStreamPanel(DataStreamPaneFX selectedItem) {
this.dataStreamPane=selectedItem;
//TODO - set the colours here.
}
/**
* Set colours depending on current colour selection in combo box.
*/
private void setColours(){
this.setColourArrayType(ColourArray.getColourArrayType(colorBox.getValue()));
colourSlider.setColourArrayType(getColourArrayType());
}
public ColourArrayType getColourArrayType() {
return colorArray;
}
public void setColourArrayType(ColourArrayType colourArrayType) {
this.colorArray = colourArrayType;
}
}
/**
* Create a pane to change vertical scales.
* @return pamne with controls to change vertical scales.
*/
private PamGridPane createScalePane() {
PamGridPane controlPane=new PamGridPane();
controlPane.setHgap(5);
controlPane.setVgap(5);
// //create time scale controls
// controlPane.add(new Label("Time window"),0,1);
//
// //create time slider
// timeSlider=new Slider(0, timeScaleChoices.length-1, 1);
// timeSlider.setShowTickLabels(true);
// timeSlider.setShowTickMarks(true);
// timeSlider.setMajorTickUnit(1);
//
// timeSlider.setLabelFormatter(new ScaleStringConverter());
//
//// PamGridPane.setHalignment(timeSlider, Pos.BOTTOM_CENTER);
//
// controlPane.add(timeSlider,1,1);
// //add listener to time slider to change datamap.
// timeSlider.valueProperty().addListener((ov, oldVal, newVal)->{
// sayHScale();
// dataMapPane.scaleChanged();
// });
//
// controlPane.add(timeScaleLabel=new Label(""),3,1);
//create vertical scale controls
scaleBox=new ComboBox<String> ();
scaleBox.getItems().add("No Scaling");
scaleBox.getItems().add("per Second");
scaleBox.getItems().add("per Minute");
scaleBox.getItems().add("per Hour");
scaleBox.getItems().add("per Day");
controlPane.add(new Label("Show detections "),0,0);
controlPane.add(scaleBox,1,0);
// scaleBox.setPrefWidth(200);
scaleBox.valueProperty().addListener((ov, oldVal, newVal)->{
dataMapPane.scaleChanged();
});
logScaleToggle=new PamToggleSwitch("Log Scale");
logScaleToggle.selectedProperty().addListener((obsVal, oldVal, newVal)->{
dataMapPane.scaleChanged();
});
controlPane.add(logScaleToggle,0,1);
return controlPane;
}
/**
* Show the horizontal scale.
*/
private void sayHScale() {
// double hChoice = timeScaleChoices[this.];
// timeScaleLabel.setText(String.format("%s pixs/hour", new Double(timeScaleChoices[(int) hChoice]).toString()));
}
//HACK use setting flag to avoid immediate callback which overwrites changes 2 and 3 !
boolean setting = false;
public void setParams(DataMapParameters dataMapParameters) {
setting = true;
// timeSlider.setValue(dataMapParameters.hScaleChoice);
scaleBox.getSelectionModel().select(dataMapParameters.vScaleChoice);
logScaleToggle.setSelected(dataMapParameters.vLogScale);
//make sure the combo box has correct datastreams
updateDataStreamBox();
setting = false;
}
public DataMapParameters getParams(DataMapParameters dataMapParameters) {
if (setting) return dataMapParameters;
// dataMapParameters.hScaleChoice = (int) timeSlider.getValue();
dataMapParameters.vScaleChoice = scaleBox.getSelectionModel().getSelectedIndex();
dataMapParameters.vLogScale = logScaleToggle.isSelected();
return dataMapParameters;
}
@Override
public String getName() {
return "Datamap settings";
}
@Override
public Node getContentNode() {
// TODO Auto-generated method stub
return mainPain;
}
@Override
public void paneInitialized() {
// TODO Auto-generated method stub
}
}

View File

@ -13,7 +13,6 @@ import dataMap.DataMapControl;
import dataMap.DataMapDrawing;
import dataMap.OfflineDataMap;
import dataMap.OfflineDataMapPoint;
import dataPlotsFX.layout.AxisPane;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.geometry.Orientation;
@ -29,9 +28,10 @@ import javafx.scene.paint.Color;
import javafx.util.Duration;
import PamController.OfflineDataStore;
import PamController.PamController;
import PamUtils.PamCalendar;
import PamguardMVC.PamDataBlock;
import pamViewFX.fxGlyphs.PamGlyphDude;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamButton;
import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.pamAxis.PamAxisFX;
import pamViewFX.fxNodes.pamAxis.PamAxisPane;
@ -42,7 +42,9 @@ public class DataStreamPaneFX extends PamBorderPane {
/**
* The preferred width of the axis.
*/
public static double axisPrefWidth=80;
public static double PREF_AXIS_WIDTH=80;
public static double PREF_HEADER_HEIGHT=20;
/**
* Reference to the data map control
@ -119,6 +121,8 @@ public class DataStreamPaneFX extends PamBorderPane {
*/
private Timeline timeline;
private PamButton showButton;
/**
* Constructor for the data stream pane.
* @param dataMapControl - the DataMapControl control the DataStreamPaneFX belongs to
@ -134,6 +138,7 @@ public class DataStreamPaneFX extends PamBorderPane {
dataGraph = new DataGraphFX();
dataGraph.setupAxis();
dataName = new DataName();
dataName.setName(dataBlock.getDataName());
this.setTop(topPane=createTopPane());
this.setCenter(dataGraph);
@ -147,10 +152,39 @@ public class DataStreamPaneFX extends PamBorderPane {
topPane.getStyleClass().add("pane-opaque");
topPane.getChildren().add(new Label(this.dataBlock.getDataName()));
topPane.setAlignment(Pos.CENTER);
return topPane;
PamBorderPane pane = new PamBorderPane();
pane.setCenter(topPane);
showButton = new PamButton();
showButton.setStyle("-fx-padding: 0 10 0 10; -fx-border-radius: 0 0 0 0; -fx-background-radius: 0 0 0 0;");
showButton.setOnAction((action)->{
this.setCollapsed(!this.isCollapsed());
setButtonGraphic();
});
setButtonGraphic();
pane.setLeft(showButton);
pane.setPrefHeight(PREF_HEADER_HEIGHT);
return pane;
}
private void setButtonGraphic() {
if (this.isCollapsed()) {
showButton.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-down", (int) PREF_HEADER_HEIGHT-2));
}
else {
showButton.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-up", (int) PREF_HEADER_HEIGHT-2));
}
}
/**
* @return the dataGraph
*/
@ -242,6 +276,8 @@ public class DataStreamPaneFX extends PamBorderPane {
private DataGraphFX() {
createDataGraph();
addDataGraphMouse();
}
@ -269,7 +305,10 @@ public class DataStreamPaneFX extends PamBorderPane {
});
canvasHolder.setOnScroll(e->{
wheelMoved(e);
//only change colours of the control key is down.
if (e.isControlDown()) {
wheelMoved(e);
}
});
}
@ -308,6 +347,8 @@ public class DataStreamPaneFX extends PamBorderPane {
//create canvas for overlaid drawings
drawCanvas=new Canvas(90,90);
plotCanvas. getGraphicsContext2D(). setImageSmoothing(false);
Pane pane = new Pane();
pane.getChildren().add(plotCanvas);
pane.getChildren().add(drawCanvas);
@ -349,7 +390,7 @@ public class DataStreamPaneFX extends PamBorderPane {
axisPane=new PamAxisPane(datastreamAxis, Orientation.VERTICAL);
axisPane.getStyleClass().add("pane");
axisPane.setOrientation(Orientation.VERTICAL);
axisPane.setPrefWidth(DataStreamPaneFX.axisPrefWidth);
axisPane.setPrefWidth(DataStreamPaneFX.PREF_AXIS_WIDTH);
axisPane.setStrokeColor(Color.BLACK);
this.setLeft(axisPane);
@ -386,7 +427,7 @@ public class DataStreamPaneFX extends PamBorderPane {
long time2 = System.currentTimeMillis();
//System.out.println("Paint Canvas: " + this + " " + System.currentTimeMillis() + " " + (time2-time1));
// System.out.println("Paint Canvas: " + this + " " + System.currentTimeMillis() + " " + (time2-time1));
}
@ -536,7 +577,8 @@ public class DataStreamPaneFX extends PamBorderPane {
}
private void datagramPaint3D(GraphicsContext g) {
private synchronized void datagramPaint3D(GraphicsContext g) {
// System.out.println("Paint 3D Canvas: " + this + " " + System.currentTimeMillis());
/*
* hopefully, there will be datagram data for this block, so do a pretty
@ -950,6 +992,16 @@ public class DataStreamPaneFX extends PamBorderPane {
public class DataName {
private String name;
public String getName() {
return name;
}
public void setName(String dataName) {
this.name=dataName;
}
}
/**
@ -1056,6 +1108,16 @@ public class DataStreamPaneFX extends PamBorderPane {
*/
public void setCollapsed(boolean collapsed) {
this.collapsed=collapsed;
if (collapsed) {
this.setCenter(null);
this.setMaxHeight(PREF_HEADER_HEIGHT);
}
else {
this.setCenter(dataGraph);
this.setMaxHeight(-1);
}
}
/**

View File

@ -1,293 +0,0 @@
package dataMap.layoutFX;
import dataGram.DatagramManager;
import dataGram.DatagramSettings;
import dataMap.DataMapControl;
import dataMap.DataMapParameters;
import PamController.PamController;
import PamUtils.PamCalendar;
import binaryFileStorage.BinaryStore;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.util.StringConverter;
import pamViewFX.PamGuiManagerFX;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamGridPane;
import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.PamVBox;
import pamViewFX.fxNodes.pamDialogFX.PamDialogFX;
import pamViewFX.fxNodes.sliders.PamSlider;
import pamViewFX.fxNodes.utilityPanes.PamToggleSwitch;
/**
* Allows uses to change the horizontal and vertical scales on the data map.
*
* @author Jamie Macaulay
*
*/
public class ScalePaneFX extends PamBorderPane {
/*
* Reference to the data map control.
*/
private DataMapControl dataMapControl;
/**
* Reference to the dataMapPane.
*/
private DataMapPaneFX dataMapPane;
/**
* The slider which determines time scale.
*/
private Slider timeSlider;
/**
* Shows the time scale in pix/hour
*/
private Label timeScaleLabel;
/**
* Selects unit count on vertical scale
*/
private ComboBox<String> scaleBox;
/**
* Check box for log vertical scale.
*/
private PamToggleSwitch logScaleBox;
/**
* The chosen time values.
*/
private double[] timeScaleChoices = DataMapParameters.hScaleChoices;
/**
* Combo box holding options to channge the datargam bin size
*/
private ComboBox<String> datagramBox;
/**
* Holds a list of times for the datagram bin size.
*/
private ComboBox<String> dataGramComboBox;
/**
* Holds everything.
*/
private PamVBox holder;
/**
* Grid pane with settings for the data scales
*/
private PamGridPane scaleSettingsPane;
private Label dataGramLabel;
public ScalePaneFX(DataMapControl dataMapControl, DataMapPaneFX dataMapPane) {
this.dataMapControl = dataMapControl;
this.dataMapPane = dataMapPane;
// //create the holder pane.
// PamVBox vBoxHolder=new PamVBox();
// vBoxHolder.setSpacing(5);
// Label title=new Label("Scales");
// PamGuiManagerFX.titleFont2style(title);
// vBoxHolder.getChildren().addAll(title, controlPane);
holder=new PamVBox();
holder.setSpacing(20);
holder.getChildren().add(scaleSettingsPane = createScalePane());
this.setCenter(holder);
//set params for the pane
setParams(dataMapControl.dataMapParameters);
checkDataGramPane(); // create datagram pane if a binary store already added.
sayHScale();
}
/**
* Adds a settings pane for the datagram if a binary store is present.
*/
public void checkDataGramPane(){
if (BinaryStore.findBinaryStoreControl()!=null){
DatagramManager dataGramManager=BinaryStore.findBinaryStoreControl().getDatagramManager();
if (dataGramManager!=null && datagramBox==null) {
datagramBox=createDatagramPane(dataGramManager);
scaleSettingsPane.add(dataGramLabel= new Label("Datagram bin size"), 0, 2);
scaleSettingsPane.add(dataGramComboBox, 1, 2);
}
}
else {
scaleSettingsPane.getChildren().remove(dataGramLabel);
scaleSettingsPane.getChildren().remove(dataGramComboBox);
datagramBox=null;
}
}
/**
* Create the a datagram combo box to change the size of the datagram
* @param dataGramManager - the datagram manager for the current biinary store.
* @return a combo box with datagram bin sizes.
*/
private ComboBox<String> createDatagramPane(DatagramManager dataGramManager){
dataGramComboBox=new ComboBox<String>(createDurationList(dataGramManager));
dataGramComboBox.getSelectionModel().select(durationToString(dataGramManager.getDatagramSettings().datagramSeconds*1000L));
dataGramComboBox.valueProperty().addListener(( ov, t, t1) -> {
if (t==t1) return;
else {
PamController.getInstance();
boolean ans=PamDialogFX.showWarning(PamController.getMainStage(), "Warning", "<html>Recalculating the datagram for a large dataset may take a long time<br>" +
"Are you sure you want to continue ?</html>");
if (ans){
int index=dataGramComboBox.getSelectionModel().getSelectedIndex();
//messy- datagramSeconfds should be in millis but left for backwards compatibility.
dataGramManager.getDatagramSettings().datagramSeconds=(int) (DatagramSettings.defaultDatagramSeconds[index]/1000);
dataGramManager.updateDatagrams();
dataMapPane.repaintAll();
}
}
});
return dataGramComboBox;
}
/**
* Convert duration to string.
* @param duration in millis.
*/
private String durationToString(long duration){
return (" " + PamCalendar.formatDuration(duration));
}
/**
* Create list of load times.
* @return list of load times duration.
*/
private ObservableList<String> createDurationList(DatagramManager dataGramManager){
ObservableList<String> loadTimeList=FXCollections.observableArrayList();
for (int i=0; i<DatagramSettings.defaultDatagramSeconds.length; i++){
loadTimeList.add(durationToString(DatagramSettings.defaultDatagramSeconds[i]));
}
return loadTimeList;
}
private PamGridPane createScalePane() {
PamGridPane controlPane=new PamGridPane();
controlPane.setHgap(5);
controlPane.setVgap(5);
//create time scale controls
controlPane.add(new Label("Time window"),0,1);
//create time slider
timeSlider=new Slider(0, timeScaleChoices.length-1, 1);
timeSlider.setShowTickLabels(true);
timeSlider.setShowTickMarks(true);
timeSlider.setMajorTickUnit(1);
timeSlider.setLabelFormatter(new ScaleStringConverter());
// PamGridPane.setHalignment(timeSlider, Pos.BOTTOM_CENTER);
controlPane.add(timeSlider,1,1);
//add listener to time slider to change datamap.
timeSlider.valueProperty().addListener((ov, oldVal, newVal)->{
sayHScale();
dataMapPane.scaleChanged();
});
controlPane.add(timeScaleLabel=new Label(""),3,1);
//create vertical scale controls
controlPane.add(new Label("Data counts"),0,0);
scaleBox=new ComboBox<String> ();
scaleBox.getItems().add("No Scaling");
scaleBox.getItems().add("per Second");
scaleBox.getItems().add("per Minute");
scaleBox.getItems().add("per Hour");
scaleBox.getItems().add("per Day");
controlPane.add(scaleBox,1,0);
scaleBox.setPrefWidth(200);
scaleBox.valueProperty().addListener((ov, oldVal, newVal)->{
dataMapPane.scaleChanged();
});
logScaleBox=new PamToggleSwitch("Log Scale");
logScaleBox.selectedProperty().addListener((obsVal, oldVal, newVal)->{
dataMapPane.scaleChanged();
});
controlPane.add(logScaleBox,3,0);
return controlPane;
}
class ScaleStringConverter extends StringConverter<Double> {
@Override
public String toString(Double object) {
return String.valueOf(timeScaleChoices[object.intValue()]);
}
@Override
public Double fromString(String string) {
return Double.valueOf(string);
}
}
/**
* Show the horizontal scale.
*/
private void sayHScale() {
double hChoice = timeSlider.getValue();
timeScaleLabel.setText(String.format("%s pixs/hour", new Double(timeScaleChoices[(int) hChoice]).toString()));
}
//HACK use setting flag to avoid immediate callback which overwrites changes 2 and 3 !
boolean setting = false;
public void setParams(DataMapParameters dataMapParameters) {
setting = true;
timeSlider.setValue(dataMapParameters.hScaleChoice);
scaleBox.getSelectionModel().select(dataMapParameters.vScaleChoice);
logScaleBox.setSelected(dataMapParameters.vLogScale);
setting = false;
}
public void getParams(DataMapParameters dataMapParameters) {
if (setting) return;
dataMapParameters.hScaleChoice = (int) timeSlider.getValue();
dataMapParameters.vScaleChoice = scaleBox.getSelectionModel().getSelectedIndex();
dataMapParameters.vLogScale = logScaleBox.isSelected();
}
}

View File

@ -12,6 +12,7 @@ import javafx.geometry.Side;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollBar;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.paint.Color;
import javafx.util.Duration;
import PamguardMVC.PamDataBlock;
@ -21,19 +22,20 @@ import pamViewFX.fxNodes.PamColorsFX;
import pamViewFX.fxNodes.PamScrollPane;
import pamViewFX.fxNodes.PamVBox;
import pamViewFX.fxNodes.pamAxis.PamDateAxis;
import pamViewFX.fxNodes.pamScrollers.acousticScroller.ScrollBarPane;
public class ScrollingDataPaneFX extends PamBorderPane {
/**
* Standard millis to wait for repaint.
* Do not ake this too high i.e. above 50 or the display gets very jerky
* Do not make this too high i.e. above 50 or the display gets very jerky
*/
public static final long REPAINTMILLIS = 50;
/**
* The default expanded hieght for each pane.
*/
private static final int DATASTREAMPANE_HEIGHT = 200;
private static final int DATASTREAMPANE_HEIGHT = 220;
/**
* Reference to the DataMapControl.
@ -77,12 +79,7 @@ public class ScrollingDataPaneFX extends PamBorderPane {
/**
* Scroll bar for time (horizontal)
*/
private ScrollBar timeScrollBar;
/**
* Settings strip at top of the display. Shows all sorts of detailed info such cursor position and start and end times.
*/
private SettingsStripFX settingsStrip;
private DataMapScrollBar timeScrollBar;
/**
* Shows the start time of the scroll position
@ -110,7 +107,6 @@ public class ScrollingDataPaneFX extends PamBorderPane {
DataMapPaneFX dataMapPaneFX) {
this.dataMapControl = dataMapControl;
this.dataMapPaneFX = dataMapPaneFX;
settingsStrip=new SettingsStripFX(this);
this.setCenter(createScrollingDataPane());
}
@ -124,6 +120,7 @@ public class ScrollingDataPaneFX extends PamBorderPane {
//create the main scroll pane
mainScrollPane = new PamScrollPane();
mainScrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
//create the split pane to hold the graphs.
@ -134,27 +131,24 @@ public class ScrollingDataPaneFX extends PamBorderPane {
mainScrollPane.setContent(dataPanePanes);
//we have a custom scroll bar for horizontal stuff.
// mainScrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
// mainScrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
// ///TEMP///
// Button buttonTest=new Button("Test Map");
// buttonTest.setOnAction((action)->{
// this.dataMapControl.findDataSources();
// });
// holder.setTop(buttonTest);
// //////////
holder.setCenter(mainScrollPane);
holder.setBottom(createScrollBar());
// PamButton test = new PamButton("Test");
// test.setOnAction((action)->{
// updateScrollBar();
// });
// holder.setLeft(test);
// ///TEMP///
// Button buttonTest=new Button("Test Map");
// buttonTest.setOnAction((action)->{
// this.dataMapControl.findDataSources();
// });
// holder.setTop(buttonTest);
// //////////
// PamButton test = new PamButton("Test");
// test.setOnAction((action)->{
// updateScrollBar();
// });
// holder.setLeft(test);
setupScrollBar();
//finally make sure the scroll bar recalculates stuff when holder changes size
holder.widthProperty().addListener((change)->{
@ -168,10 +162,19 @@ public class ScrollingDataPaneFX extends PamBorderPane {
dateAxis.setSide(Side.TOP);
dateAxis.setAnimated(false);
dateAxis.setMinHeight(50);
// dateAxis.prefWidthProperty().bind(scrollingDataPanel.widthProperty());
// dateAxis.setStyle("-fx-background-color: ORANGE;");
// dateAxis.prefWidthProperty().bind(scrollingDataPanel.widthProperty());
// dateAxis.setStyle("-fx-background-color: ORANGE;");
dateAxis.setForceZeroInRange(false);
holder.setTop(dateAxis);
PamVBox vBox = new PamVBox();
vBox.getChildren().add(createScrollBar());
vBox.getChildren().add(dateAxis);
holder.setTop(vBox);
holder.setCenter(mainScrollPane);
setupScrollBar();
return holder;
}
@ -208,14 +211,21 @@ public class ScrollingDataPaneFX extends PamBorderPane {
//create the scroll bar and listeners.
timeScrollBar=new ScrollBar();
timeScrollBar.valueProperty().addListener((obs_val, old_val, new_val)->{
timeScrollBar=new DataMapScrollBar(this.dataMapControl);
timeScrollBar.addValueListener((obs_val, old_val, new_val)->{
// System.out.println("Scroll bar seconds: " + timeScrollBar.getCurrentValue() + " vis amount: " + timeScrollBar.visibleAmountProperty().get());
calcStartEndMillis();
updateScrollBarText();
notifyScrollChange();
});
timeScrollBar.setPrefHeight(20);
timeScrollBar.getTextBox().setPrefColumnCount(15);
timeScrollBar.getTextBox().setPrefWidth(100);
timeScrollBar.setPrefHeight(50);
//set this to zero just so that we know if it has been set or not
timeScrollBar.setVisibleAmount(0.);
holder.setCenter(timeScrollBar);
holder.setBottom(timeLabelPane);
@ -228,8 +238,14 @@ public class ScrollingDataPaneFX extends PamBorderPane {
*/
private void calcStartEndMillis(){
screenStartMillis = (long) (dataMapControl.getFirstTime() +
timeScrollBar.getValue() * 1000L);
screenEndMillis = screenStartMillis + (long) (screenSeconds * 1000);
timeScrollBar.getCurrentValue());
screenEndMillis = (long) (screenStartMillis + timeScrollBar.getVisibleAmount());
double pixsPerHour = getPixelsPerHour();
double pixsPerSecond = pixsPerHour / 3600;
double screenWidth = getPlotWidth();
screenSeconds = screenWidth / Math.min(600. / 3600, pixsPerSecond);
}
/**
@ -248,7 +264,7 @@ public class ScrollingDataPaneFX extends PamBorderPane {
for (int i = 0; i < dataStreamPanels.size(); i++) {
dataStreamPanels.get(i).scrollChanged();
}
settingsStrip.scrollChanged();
// settingsStrip.scrollChanged();
updateDateAxis();
}
@ -285,7 +301,7 @@ public class ScrollingDataPaneFX extends PamBorderPane {
dateAxis.setUpperBound(screenEndMillis);
dateAxis.setLowerBound(screenStartMillis);
double[] ticks = dateAxis.recalculateTicks();
// System.out.println("Ticks: " + (ticks[3]/1000/3600) + "hours");
// System.out.println("Ticks: " + (ticks[3]/1000/3600) + "hours");
dateAxis.setTickUnit(ticks[3]);
}
@ -294,28 +310,28 @@ public class ScrollingDataPaneFX extends PamBorderPane {
* @return the number of DataStreamPanes created.
*/
public synchronized int createDataGraphs() {
//clear the panes from list and split pane.
dataStreamPanels.clear();
dataPanePanes.getChildren().clear();
//clear the panes from list and split pane.
dataStreamPanels.clear();
dataPanePanes.getChildren().clear();
//now create new set of data stream panes.
ArrayList<PamDataBlock> dataBlocks = dataMapControl.getMappedDataBlocks();
if (dataBlocks == null) {
System.out.println("DataMapPaneFX:Create Data Graphs: Datablocks are null");
return 0;
}
DataStreamPaneFX aStreamPanel;
for (int i = 0; i < dataBlocks.size(); i++) {
aStreamPanel = new DataStreamPaneFX(dataMapControl, this, dataBlocks.get(i));
dataStreamPanels.add(aStreamPanel);
dataStreamPanels.get(i).setMinHeight(DATASTREAMPANE_HEIGHT);
//now add to a split pane.
//SplitPane.setResizableWithParent(aStreamPanel, true);
dataPanePanes.getChildren().add(aStreamPanel);
//dataPanePanes.setDividerPosition(0,1.0/dataBlocks.size());
}
//now create new set of data stream panes.
ArrayList<PamDataBlock> dataBlocks = dataMapControl.getMappedDataBlocks();
if (dataBlocks == null) {
System.out.println("DataMapPaneFX:Create Data Graphs: Datablocks are null");
return 0;
}
DataStreamPaneFX aStreamPanel;
for (int i = 0; i < dataBlocks.size(); i++) {
aStreamPanel = new DataStreamPaneFX(dataMapControl, this, dataBlocks.get(i));
dataStreamPanels.add(aStreamPanel);
dataStreamPanels.get(i).setPrefHeight(DATASTREAMPANE_HEIGHT);
//now add to a split pane.
//SplitPane.setResizableWithParent(aStreamPanel, true);
dataPanePanes.getChildren().add(aStreamPanel);
//dataPanePanes.setDividerPosition(0,1.0/dataBlocks.size());
}
return dataBlocks.size();
return dataBlocks.size();
}
@ -343,37 +359,48 @@ public class ScrollingDataPaneFX extends PamBorderPane {
}
private void setupScrollBar() {
/**
* Do scrolling in seconds - will give up to 68 years with a
* 32 bit integer control of scroll bar. milliseconds would give < 1 year !
*/
double currentPos = timeScrollBar.getValue();
double currentPos = timeScrollBar.getCurrentValue();
long dataStart = dataMapControl.getFirstTime();
long dataEnd = dataMapControl.getLastTime();
double dataSeconds = ((dataEnd-dataStart)/1000) + 1;
double pixsPerHour = getPixelsPerHour();
double pixsPerSecond = pixsPerHour / 3600;
double screenWidth = getPlotWidth();
screenSeconds = screenWidth / pixsPerSecond;
if (dataStart == Long.MAX_VALUE || screenSeconds >= dataSeconds) {
//System.out.println("dataSeconds: "+dataSeconds+ " pixsPerHour: " +pixsPerHour+" screenWidth: "+screenWidth+" screenSeconds "+screenSeconds+ " holder width: "+holder.getWidth());
/*
* hide the scroll bar and stretch the display to fit the window
*/
timeScrollBar.setVisible(false);
screenStartMillis = dataStart;
screenEndMillis = dataEnd;
}
else {
//System.out.println("dataSeconds: "+dataSeconds+ " pixsPerHour: " +pixsPerHour+" screenWidth: "+screenWidth+" screenSeconds "+screenSeconds+" holder width: "+holder.getWidth());
timeScrollBar.setVisible(true);
timeScrollBar.setMax(0);
timeScrollBar.setMax(Math.ceil(dataSeconds));
timeScrollBar.setBlockIncrement(Math.max(1, screenSeconds * 4/5));
timeScrollBar.setUnitIncrement(Math.max(1, screenSeconds / 20));
timeScrollBar.setVisibleAmount(screenSeconds);
timeScrollBar.setValue(currentPos);
calcStartEndMillis();
// if (dataStart == Long.MAX_VALUE || screenSeconds >= dataSeconds) {
// System.out.println("dataSeconds1: "+dataSeconds+ " pixsPerHour: " +pixsPerHour+" screenWidth: "+screenWidth+" screenSeconds "+screenSeconds+ " holder width: "+holder.getWidth());
// /*
// * hide the scroll bar and stretch the display to fit the window
// */
// timeScrollBar.setVisible(true);
// screenStartMillis = dataStart;
// screenEndMillis = dataEnd;
// }
// else {
// System.out.println("dataSeconds2: "+dataSeconds+ " pixsPerHour: " +pixsPerHour+" screenWidth: "+screenWidth+" screenSeconds "+screenSeconds+" holder width: "+holder.getWidth());
timeScrollBar.setVisible(true);
timeScrollBar.setMinVal(0);
timeScrollBar.setMaxVal(Math.max(dataSeconds, screenSeconds)*1000L);
timeScrollBar.setBlockIncrement(Math.max(1, screenSeconds * 4/5));
// timeScrollBar.setUnitIncrement(Math.max(1, screenSeconds / 20));
//there might already have a visible amount in which case we do not wish to change. This is a bit of a hack
//to figure out whether the visible amount has already been set.
if (timeScrollBar.getVisibleAmount()==0) {
timeScrollBar.setVisibleAmount(screenSeconds*1000L);
}
timeScrollBar.setCurrentValue(currentPos);
//now paint the canvas to show the data.
timeScrollBar.paintDataSummary();
}
@ -383,18 +410,18 @@ public class ScrollingDataPaneFX extends PamBorderPane {
*/
private double getPlotWidth() {
//HACK- seems like there is a lyout delay in datstream panes.
return this.holder.getWidth()-DataStreamPaneFX.axisPrefWidth;
// if (dataStreamPanels.size()>0){
// dataStreamPanels.get(0).layout();
// return dataStreamPanels.get(0).getDataGraph().getPlotWidth();
// }
// return 0;
return this.holder.getWidth()-DataStreamPaneFX.PREF_AXIS_WIDTH;
// if (dataStreamPanels.size()>0){
// dataStreamPanels.get(0).layout();
// return dataStreamPanels.get(0).getDataGraph().getPlotWidth();
// }
// return 0;
}
public void scrollToData(PamDataBlock dataBlock) {
long startTime = dataBlock.getCurrentViewDataStart();
int val = (int) ((startTime - getScreenStartMillis())/1000 - getScreenSeconds()/5) ;
timeScrollBar.setValue(val);
timeScrollBar.setCurrentValue(val);
}
/**
@ -413,7 +440,11 @@ public class ScrollingDataPaneFX extends PamBorderPane {
public double getPixelsPerHour() {
return dataMapControl.dataMapParameters.getPixeslPerHour();
// System.out.println("Pixels per hour: " + dataMapControl.dataMapParameters.getPixeslPerHour() + " " + this.getPlotWidth()/(this.timeScrollBar.getVisibleAmount()/1000./3600.));
//return dataMapControl.dataMapParameters.getPixeslPerHour();
return this.getPlotWidth()/(this.timeScrollBar.getVisibleAmount()/1000./3600.);
}
/**
@ -456,13 +487,33 @@ public class ScrollingDataPaneFX extends PamBorderPane {
return dataMapPaneFX;
}
int lastHScaleChoice=-1;
public void scaleChange() {
if (lastHScaleChoice != dataMapControl.dataMapParameters.hScaleChoice) {
lastHScaleChoice = dataMapControl.dataMapParameters.hScaleChoice;
setupScrollBar();
// int lastHScaleChoice=-1;
// public void scaleChange() {
// if (lastHScaleChoice != dataMapControl.dataMapParameters.hScaleChoice) {
// lastHScaleChoice = dataMapControl.dataMapParameters.hScaleChoice;
// setupScrollBar();
// }
// this.notifyScrollChange();
// }
/**
* Get the current number of data stream panes
* @return the number of data stream panes
*/
public int getNumDataStreamPanes() {
return this.dataStreamPanels.size();
}
/**
* Get a data stream pane.
* @param n - the index of the data stream pane
* @return the data stream pane or null if the index is out of bounds.
*/
public DataStreamPaneFX getDataSyreamPane(int n) {
if (n<this.dataStreamPanels.size()) {
return dataStreamPanels.get(n);
}
this.notifyScrollChange();
else return null;
}
}

View File

@ -1,16 +0,0 @@
package dataMap.layoutFX;
import pamViewFX.fxNodes.PamBorderPane;
public class SettingsStripFX extends PamBorderPane {
public SettingsStripFX(ScrollingDataPaneFX scrollingDataPaneFX) {
// TODO Auto-generated constructor stub
}
public void scrollChanged() {
// TODO Auto-generated method stub
}
}

View File

@ -80,6 +80,18 @@ public class TDGraphParametersFX implements Serializable, Cloneable, ManagedPara
*/
public String plotFillS = "white";
/**
* Show the hide panel on the left on start up. Note only used when first opening
* saved settings or saving settings.
*/
public boolean showHidePaneLeft = true;
/**
* Show the hide panel on the right on start up. Note only used when first opening
* saved settings or saving settings.
*/
public boolean showHidePaneRight = false;
/* (non-Javadoc)
* @see java.lang.Object#clone()

View File

@ -350,8 +350,8 @@ public class TDGraphFX extends PamBorderPane {
setOverlayColour(LIGHT_TD_DISPLAY);
//show the left hiding pane byu default.
stackPane.getLeftHidingPane().showHidePane(true);
// //show the left hiding pane byu default.
// stackPane.getLeftHidingPane().showHidePane(true);
}
/**
@ -1699,8 +1699,7 @@ public class TDGraphFX extends PamBorderPane {
/**
* A bit different to the standard getter in that this only gets called just
* before the configuration is serialized into the .psf. It's time to pull any
* configuration information out about every line drawn on this boomin' thing !
* before the configuration is serialized into the .psfx.
*
* @return graph parameters ready to serialised.
*/
@ -1733,6 +1732,11 @@ public class TDGraphFX extends PamBorderPane {
graphParameters.setScaleInfoData(scaleInfo.getDataTypeInfo(), scaleInfo.getScaleInfoData());
}
}
//Finally save whether the hiding panels are open or not.
graphParameters.showHidePaneLeft = stackPane.getLeftHidingPane().isShowing();
graphParameters.showHidePaneRight = stackPane.getRightHidingPane().isShowing();
}
return graphParameters;
@ -1817,6 +1821,11 @@ public class TDGraphFX extends PamBorderPane {
tdAxisSelPane.selectAxisType();
setAxisName(graphParameters.currentDataType);
//Open hide panes if needed.
//Finally save whether the hiding panels are open or not.
stackPane.getLeftHidingPane().showHidePane(graphParameters.showHidePaneLeft);
stackPane.getRightHidingPane().showHidePane(graphParameters.showHidePaneRight);
}
/**

View File

@ -7,16 +7,13 @@ import PamView.paneloverlay.overlaymark.OverlayMark;
import PamguardMVC.PamDataUnit;
import PamguardMVC.PamRawDataBlock;
import detectiongrouplocaliser.DetectionGroupSummary;
import export.wavExport.WavFileExportManager;
import javafx.animation.Timeline;
import export.wavExport.WavDetExport;
import javafx.application.Platform;
import javafx.scene.control.Labeled;
import javafx.scene.control.Tooltip;
import javafx.scene.effect.ColorInput;
import javafx.scene.text.Text;
import pamViewFX.fxGlyphs.PamGlyphDude;
import pamViewFX.fxNodes.PamButton;
import wavFiles.WavFileWriter;
/**
* Export a .wav clip.
@ -27,27 +24,27 @@ public class WavExportOverlayMenu extends ExportOverlayMenu {
private Text wavFileGlyph;
/**
* The wav file write
*/
private WavFileWriter wavFile;
// /**
// * The wav file write
// */
// private WavFileWriter wavFile;
//
// private String defaultPath;
//
// private String currentFolder;
private String defaultPath;
private WavDetExport wavExportManager;
private String currentFolder;
private WavFileExportManager wavExportManager;
private ColorInput shadow;
private Timeline timline;
// private ColorInput shadow;
//
// private Timeline timline;
private PamButton pamButton;
public WavExportOverlayMenu(){
// wavFileGlyph=PamGlyphDude.createPamGlyph(MaterialDesignIcon.FILE_MUSIC, standardIconSize);
wavFileGlyph=PamGlyphDude.createPamIcon("mdi2f-file-music", standardIconSize+14);
wavExportManager= new WavFileExportManager();
wavExportManager= new WavDetExport();
//set a callback when saving is finsihed.
wavExportManager.setOnWavSaved((saveFile, flag)->{
@ -132,7 +129,7 @@ public class WavExportOverlayMenu extends ExportOverlayMenu {
*/
private void writeWavFile(DetectionGroupSummary foundDataUnits, int selectedIndex, OverlayMark mark) {
// animateButton() ; //start button animation.
wavExportManager.dataUnits2Wav(foundDataUnits, selectedIndex, mark);
wavExportManager.writeOverlayMarkWav(foundDataUnits, selectedIndex, mark);
}
@ -148,7 +145,7 @@ public class WavExportOverlayMenu extends ExportOverlayMenu {
rawDataBlock=foundDataUnits.getDataList().get(0).getParentDataBlock().getRawSourceDataBlock();
}
//is there available raw data
if (mark!=null && WavFileExportManager.haveRawData(rawDataBlock, (long) mark.getLimits()[0], (long) mark.getLimits()[1])) {
if (mark!=null && WavDetExport.haveRawData(rawDataBlock, (long) mark.getLimits()[0], (long) mark.getLimits()[1])) {
return true;
}

View File

@ -12,7 +12,7 @@ import dataPlotsFX.layout.TDGraphFX.TDPlotPane;
import dataPlotsFX.overlaymark.menuOptions.OverlayMenuItem;
import dataPlotsFX.overlaymark.menuOptions.OverlayMenuManager;
import detectiongrouplocaliser.DetectionGroupSummary;
import export.wavExport.WavFileExportManager;
import export.wavExport.WavDetExport;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
@ -546,7 +546,7 @@ public class TDMenuPane extends PamBorderPane {
PamRawDataBlock pamRawBlock = findRawSourceBlock();
// System.out.println("Pam raw data block: " + pamRawBlock);
if (WavFileExportManager.haveRawData(pamRawBlock, (long) overlayMarker.getCurrentMark().getLimits()[0], (long) overlayMarker.getCurrentMark().getLimits()[1])) {
if (WavDetExport.haveRawData(pamRawBlock, (long) overlayMarker.getCurrentMark().getLimits()[0], (long) overlayMarker.getCurrentMark().getLimits()[1])) {
//System.out.println("Overaly Marker start X: " + overlayMarker.getCurrentMark().getLimits()[0] + " end: " + overlayMarker.getCurrentMark().getLimits()[1]);
//System.out.println("Overlay Marker start Y: " + overlayMarker.getCurrentMark().getLimits()[2] + " end: " + overlayMarker.getCurrentMark().getLimits()[3]);
groupDetectionDisplay.showRawData(pamRawBlock, overlayMarker.getCurrentMark().getLimits(), overlayMarker.getCurrentMark().getMarkChannels());

View File

@ -2,6 +2,7 @@ package dataPlotsFX.rawClipDataPlot;
import java.awt.geom.Path2D;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
@ -14,7 +15,7 @@ import PamguardMVC.PamDataUnit;
import PamguardMVC.RawDataHolder;
import clipgenerator.ClipSpectrogram;
import dataPlotsFX.TDSymbolChooserFX;
import dataPlotsFX.clickPlotFX.ClickSymbolChooserFX;
import dataPlotsFX.clickPlotFX.ClickDisplayParams;
import dataPlotsFX.data.TDDataProviderFX;
import dataPlotsFX.data.TDScaleInfo;
import dataPlotsFX.data.generic.GenericDataPlotInfo;
@ -256,5 +257,35 @@ public class RawClipDataInfo extends GenericDataPlotInfo {
}
/* (non-Javadoc)
* @see dataPlots.data.TDDataInfo#getStoredSettings()
*/
@Override
public Serializable getStoredSettings() {
return rawClipParams;
}
/* (non-Javadoc)
* @see dataPlots.data.TDDataInfo#setStoredSettings(java.io.Serializable)
*/
@Override
public boolean setStoredSettings(Serializable storedSettings) {
if (RawClipParams.class.isAssignableFrom(storedSettings.getClass())) {
rawClipParams = (RawClipParams) storedSettings;
updateSettings();
return true;
}
return false;
}
/**
* Called whenever settings are updated.
*/
private void updateSettings() {
// TODO Auto-generated method stub
}
}

View File

@ -926,6 +926,8 @@ public class Scrolling2DPlotDataFX {
//reset transform in case of other drawings on base canvas.
if (orientation == Orientation.VERTICAL) g2d.setTransform(horzAffine);
}
/**

View File

@ -22,9 +22,13 @@ import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
/**
* A general pane with a frequency slider, colour bar slider and colour combo box. These nodes are interconnected so when colour combo box is changed colours change.
* Other than that this pane does nothing but all slider value properties are available to be used in another class or subclass. This means this control pane should be
* available to be used for any spectrogram/3D colour image.
* A general pane with a frequency slider, colour bar slider and colour combo
* box. These nodes are interconnected so when colour combo box is changed
* colours change. Other than that this pane does nothing but all slider value
* properties are available to be used in another class or subclass. This means
* this control pane should be available to be used for any spectrogram/3D
* colour image.
*
* @author Jamie Macaulay
*
*/

View File

@ -226,7 +226,7 @@ public class DetectionPlotDisplay extends PamBorderPane {
* Called whenever the scroll values change
*/
void scrollBarChanged() {
if (detectionPlotProjector.enableScrollBar) {
if (detectionPlotProjector.isEnableScrollBar()) {
detectionPlotProjector.setAxisMinMax(scrollBarPane.getCurrentValue(),
scrollBarPane.getCurrentValue()+scrollBarPane.getVisibleAmount(), detectionPlotProjector.getScrollAxis());
drawCurrentUnit();
@ -237,7 +237,7 @@ public class DetectionPlotDisplay extends PamBorderPane {
* Repaint the scroll bar.
*/
private void repainScrollBar() {
if (currentDataInfo!=null && detectionPlotProjector.enableScrollBar && lastDetection!=null) {
if (currentDataInfo!=null && detectionPlotProjector.isEnableScrollBar() && lastDetection!=null) {
currentDataInfo.drawData(scrollBarPane.getDrawCanvas().getGraphicsContext2D(),
new Rectangle(0,0,scrollBarPane.getDrawCanvas().getWidth(),scrollBarPane.getDrawCanvas().getHeight()),
this.detectionPlotProjector, this.lastDetection, DetectionPlot.SCROLLPANE_DRAW);
@ -355,6 +355,7 @@ public class DetectionPlotDisplay extends PamBorderPane {
* the current data unit.
*/
public void setupScrollBar(PamDataUnit newDataUnit){
System.out.println("SETUP SCROLL BAR:");
if (currentDataInfo!=null) {
//important we put this here as it allows the plot to set up the scroll bar pane.
@ -382,12 +383,18 @@ public class DetectionPlotDisplay extends PamBorderPane {
this.detectionPlotProjector, newDataUnit, DetectionPlot.SCROLLPANE_DRAW);
}
}
else {
System.out.println("Min scroll limit: " + detectionPlotProjector.getMinScrollLimit() + "max: " + detectionPlotProjector.getMaxScrollLimit());
//need this to ensure the axis change when scroll bar is not longer displayed.
detectionPlotProjector.setAxisMinMax(detectionPlotProjector.getMinScrollLimit(),
detectionPlotProjector.getMaxScrollLimit(), detectionPlotProjector.getScrollAxis());
//need to setup the axis as it takes it data fom the ploit projector.
if (currentDataInfo!=null) {
this.currentDataInfo.setupAxis(detectionPlotProjector, newDataUnit);
}
this.setTop(null);
}
}
@ -411,27 +418,32 @@ public class DetectionPlotDisplay extends PamBorderPane {
*Draw the data unit.
*/
private void drawDataUnit(PamDataUnit newDataUnit) {
//Debug.out.println("DetectionPlotDisplay DrawDataUnit: " +newDataUnit);
if (reDrawScroll) {
setupScrollBar(newDataUnit);
reDrawScroll=false;
}
if (currentDataInfo!=null){
//sometimes the axis just need a little push to make sure the pane and axis object bindings have been updated
for (int i=0; i<Side.values().length; i++) {
dDPlotPane.getAxisPane(Side.values()[i]).layout();
}
// System.out.println("Axis Width: " + dDPlotPane.getAxisPane(Side.BOTTOM).getWidth() + " canvas width " + dDPlotPane.getPlotCanvas().getWidth());
currentDataInfo.drawData(dDPlotPane.getPlotCanvas().getGraphicsContext2D(),
new Rectangle(0,0,dDPlotPane.getPlotCanvas().getWidth(),dDPlotPane.getPlotCanvas().getHeight()),
this.detectionPlotProjector, newDataUnit);
}
if (reDrawScroll) {
setupScrollBar(newDataUnit);
reDrawScroll=false;
}
// //Debug.out.println("DetectionPlotDisplay DrawDataUnit: " +newDataUnit);
// if (reDrawScroll) {
// setupScrollBar(newDataUnit);
// reDrawScroll=false;
// }
//
//dDPlotPane.repaintAxis();
}

View File

@ -93,7 +93,7 @@ public abstract class WaveformPlot<D extends PamDataUnit> implements DetectionPl
*/
@Override
public void setupAxis(D pamDetection, double sR, DetectionPlotProjector plotProjector){
//System.out.println("WaveformPlot: plotting the waveform" + waveform.length);
System.out.println("WaveformPlot.setupAxis plotting the waveform: " + getWaveform(pamDetection)[0].length);
//all axis are used in the waveform plot except the right axis.
double[][] waveform=getWaveform(pamDetection);
@ -107,20 +107,23 @@ public abstract class WaveformPlot<D extends PamDataUnit> implements DetectionPl
else binLength=waveform[0].length;
//System.out.println("Waveform Length: " + binLength);
// plotProjector.setEnableScrollBar(true);
//set the scroller minimum and maximum
plotProjector.setMinScrollLimit(0);
plotProjector.setMaxScrollLimit((binLength*1000.)/sR);
plotProjector.setEnableScrollBar(true);
plotProjector.setScrollAxis(Side.BOTTOM);
// System.out.println("Waveform Time Axis: min " + (plotProjector.getAxis(Side.BOTTOM).getMinVal()/1000.)*sR +
// " max: " + (plotProjector.getAxis(Side.BOTTOM).getMaxVal()/1000)*sR);
//set the min and max value.
//set the min and max value from the bottom axis on the top axis. This essentially means that the scroller can
//set the top axis.
plotProjector.setAxisMinMax((plotProjector.getAxis(Side.BOTTOM).getMinVal()/1000.)*sR,
(plotProjector.getAxis(Side.BOTTOM).getMaxVal()/1000)*sR, Side.TOP);
System.out.println("WaveformPlot.setupAxis: min " + (plotProjector.getAxis(Side.BOTTOM).getMinVal()/1000.)*sR +
" max: " + (plotProjector.getAxis(Side.BOTTOM).getMaxVal()/1000)*sR);
// plotProjector.setAxisMinMax(0, (binLength*1000.)/sR, Side.BOTTOM);
plotProjector.setAxisMinMax(-1, 1, Side.LEFT); //TODO
@ -182,6 +185,7 @@ public abstract class WaveformPlot<D extends PamDataUnit> implements DetectionPl
* @param projector - the projector
*/
private void forcePaintPlot(D pamDetection, GraphicsContext gc, Rectangle rectangle, DetectionPlotProjector projector){
System.out.println("WaveformPlot.forcePaintPlot:");
currentWaveform=getWaveform(pamDetection);
if (currentWaveform==null) return;
@ -255,6 +259,7 @@ public abstract class WaveformPlot<D extends PamDataUnit> implements DetectionPl
synchronized (storedWaveformLock) {
if (currentDetection == null || waveform==null || waveform.length==0 || waveform[0]==null)
return;
paintWaveform(waveform, currentDetection.getSequenceBitmap(), g, clipRect, (int) projector.getAxis(Side.TOP).getMinVal(), (int) projector.getAxis(Side.TOP).getMaxVal(),
log2Amplitude, color, !waveformPlotParams.showSperateWaveform || waveform.length==1, waveformPlotParams.invert);
}
@ -274,7 +279,7 @@ public abstract class WaveformPlot<D extends PamDataUnit> implements DetectionPl
*/
public static void paintWaveform(double[][] waveform, int channelBitMap, GraphicsContext g, Rectangle clipRect,
int minbin, int maxbin, double yScaleInfo, Color color, boolean singlePlot, boolean invert) {
//System.out.println("Paint the waveform: " + clipRect.getWidth());
System.out.println("Paint the waveform: " + waveform[0].length);
g.setLineWidth(1);
// boolean singlePlot=!waveformPlotParams.showSperateWaveform;

View File

@ -7,7 +7,7 @@ import detectionPlotFX.layout.DetectionPlotDisplay;
import detectionPlotFX.plots.WaveformPlot;
/**
* Plot a click waveform.
* Plot for any RawDataHolder to show a waveform.
* @author Jamie Macaulay
*
*/

View File

@ -7,7 +7,6 @@ import PamController.PamControlledUnitSettings;
import PamController.PamSettingManager;
import PamController.PamSettings;
import PamController.StorageParameters;
import export.layoutFX.ExportParams;
import export.swing.ExportProcessDialog;
/**
@ -20,10 +19,10 @@ public class ExportOptions implements PamSettings {
private static ExportOptions singleInstance;
/**
* Parameters for the exporter.
*/
private ExportParams storageParameters = new ExportParams();
// /**
// * Parameters for the exporter.
// */
// private ExportParams storageParameters = new ExportParams();
/**
* Swing dialog for exporting data.
@ -57,7 +56,7 @@ public class ExportOptions implements PamSettings {
if (exportProcessDialog==null) {
exportProcessDialog= new ExportProcessDialog(exportManager);
}
this.exportProcessDialog.showOfflineDialog(parentFrame, this.storageParameters);
this.exportProcessDialog.showOfflineDialog(parentFrame, exportManager.getExportParams());
// ExportParams newParams = StorageOptionsDialog.showDialog(parentFrame, storageParameters);
// if (newParams != null) {
@ -73,7 +72,7 @@ public class ExportOptions implements PamSettings {
@Override
public Serializable getSettingsReference() {
return storageParameters;
return exportManager.getExportParams();
}
@Override
@ -94,20 +93,21 @@ public class ExportOptions implements PamSettings {
@Override
public boolean restoreSettings(
PamControlledUnitSettings pamControlledUnitSettings) {
storageParameters = ((ExportParams) pamControlledUnitSettings.getSettings()).clone();
ExportParams storageParameters = ((ExportParams) pamControlledUnitSettings.getSettings()).clone();
exportManager.setExportParams(storageParameters);
return true;
}
public void setStorageParameters(ExportParams storageParameters) {
this.storageParameters = storageParameters;
public void setExportParameters(ExportParams storageParameters) {
exportManager.setExportParams(storageParameters);
}
/**
* Get storage parameters settings.
* @return the storage paramters settings
*/
public ExportParams getStorageParameters() {
return storageParameters;
public ExportParams getExportParameters() {
return exportManager.getExportParams();
}
}

View File

@ -1,4 +1,4 @@
package export.layoutFX;
package export;
import java.io.Serializable;

View File

@ -48,8 +48,12 @@ public abstract class MLDataUnitExport<T extends PamDataUnit<?, ?>> {
//UID for the detection.
Matrix UID = Mat5.newScalar(dataUnit.getUID());
//the start sample.
Matrix startSample = Mat5.newScalar(dataUnit.getStartSample());
Matrix startSample = Mat5.newScalar(0);
if (dataUnit.getStartSample()!=null) {
//the start sample.
startSample = Mat5.newScalar(dataUnit.getStartSample());
}
//the duration of the detection in samples.
Matrix sampleDuration = Mat5.newScalar(dataUnit.getSampleDuration());

View File

@ -47,10 +47,10 @@ public class MLWhistleMoanExport extends MLDataUnitExport<ConnectedRegionDataUni
/**
* Calculate summary contour information to allow people to conveniently plot whisltle data
* @param dataUnit - the connected regio data unit.
* @param dataUnit - the connected region data unit.
* @return peak contour frequency int[0] and contour width int[1].
*/
private int[][] calcPeakContourWidths(ConnectedRegionDataUnit dataUnit){
public static int[][] calcPeakContourWidths(ConnectedRegionDataUnit dataUnit){
SliceData sliceData;
// should change this to use iterators, not get since sliceList is linked list.

View File

@ -33,7 +33,10 @@ public abstract class RDataUnitExport<T extends PamDataUnit<?, ?>> {
rData.add("UID", dataUnit.getUID());
rData.add("startSample", dataUnit.getStartSample());
rData.add("sampleDuration", dataUnit.getSampleDuration());
rData.add("freqLimits", new DoubleArrayVector(dataUnit.getBasicData().getFrequency()));
// rData.add("freqLimits", new DoubleArrayVector(dataUnit.getBasicData().getFrequency()));
rData.add("minFreq", dataUnit.getBasicData().getFrequency()[0]);
rData.add("maxFreq", dataUnit.getBasicData().getFrequency()[1]);
rData.add("amplitude", dataUnit.getBasicData().getCalculatedAmlitudeDB());
//there may be no delay info
if (dataUnit.getBasicData().getTimeDelaysSeconds()!=null && dataUnit.getBasicData().getTimeDelaysSeconds().length>=1){

View File

@ -1,8 +1,14 @@
package export.RExport;
import org.renjin.sexp.AttributeMap;
import org.renjin.sexp.IntArrayVector;
import org.renjin.sexp.ListVector;
import export.MLExport.MLWhistleMoanExport;
import org.renjin.sexp.ListVector.NamedBuilder;
import PamUtils.PamArrayUtils;
import whistlesAndMoans.ConnectedRegionDataUnit;
import whistlesAndMoans.SliceData;
/***
* Export whisltes to RData
@ -13,8 +19,27 @@ public class RWhistleExport extends RDataUnitExport<ConnectedRegionDataUnit> {
@Override
public NamedBuilder addDetectionSpecificFields(NamedBuilder rData, ConnectedRegionDataUnit dataUnit, int index) {
rData.add("nSlices", dataUnit.getConnectedRegion().getNumSlices());
int[][] contourData = MLWhistleMoanExport.calcPeakContourWidths( dataUnit);
IntArrayVector contours = new IntArrayVector(contourData[0]);
IntArrayVector contourWidth = new IntArrayVector(contourData[0]);
//need to generate a slice struct
ListVector.NamedBuilder peakDatas = createSliceStruct( dataUnit);
rData.add("nSlices", dataUnit.getConnectedRegion().getNumSlices());
rData.add("sliceData", peakDatas);
rData.add("contour", contours);
rData.add("contWidth", contourWidth);
rData.add("meanWidth", PamArrayUtils.mean(contourData[0]));
// TODO Auto-generated method stub
// //nSlices int
//nSlices int
// MLInt32 nSlices = new MLInt32(null, new Integer[]{dataUnit.getConnectedRegion().getNumSlices()}, 1);
//
// //list of structures: sliceNumber int, nPeaks int, peakData
@ -42,6 +67,69 @@ public class RWhistleExport extends RDataUnitExport<ConnectedRegionDataUnit> {
return rData;
}
/**
* Create array of slice structures for output.
* @param dataUnit
* @return
*/
private ListVector.NamedBuilder createSliceStruct(ConnectedRegionDataUnit dataUnit){
// Struct mlStructure= new MLStructure("sliceData", new int[]{dataUnit.getConnectedRegion().getSliceData().size(), 1});
ListVector.NamedBuilder peakDatas = new ListVector.NamedBuilder(); ;
//the start sample.
int sliceNumber;
int nPeaks;
int[][] peakData;
SliceData sliceData;
ListVector.NamedBuilder rData;
for (int i=0; i<dataUnit.getConnectedRegion().getSliceData().size(); i++){
rData = new ListVector.NamedBuilder();
//slice data
sliceData= dataUnit.getConnectedRegion().getSliceData().get(i);
//the start sample.
sliceNumber = sliceData.getSliceNumber();
//the duration of the detection in samples.
nPeaks = sliceData.getnPeaks();
//the frequency limits.
peakData = sliceData.getPeakInfo();
int n=0;
int nbins =peakData.length*peakData[0].length;
int[] flattenedArr = new int[nbins];
//System.out.println("Number of bins: " + nbins);
for (int ii=0; ii<peakData.length; ii++) {
for (int j=0; j<peakData[ii].length; j++) {
// System.out.println("Current: " + i + " "+ j
// + " nchan: " + dataUnit.getNChan() + " wave size: "
// + dataUnit.getWaveLength() +"len concat: " + concatWaveform.length);
flattenedArr[n++] = peakData[ii][j];
}
}
IntArrayVector peakDataR = new IntArrayVector(flattenedArr, AttributeMap.builder().setDim(peakData.length, peakData[0].length).build());
rData.add("sliceNumber", sliceNumber);
rData.add("nPeaks", nPeaks);
rData.add("peakData", peakDataR);
peakDatas.add("[["+String.valueOf(i)+"]]", rData);
}
return peakDatas;
}
@Override
public Class<?> getUnitClass() {
return ConnectedRegionDataUnit.class;

View File

@ -0,0 +1,94 @@
# PAMGuard exporter
## Introduction
The PAMGuard exporter allows users to export PAMGuard data, such as detections, to a variety of different formats. The exporter is a convenient solution for exporting sections or large chunks of a PAMGuard datasets without requiring any code. For more bespoke data management please see the [PAMGuard-MATLAB](https://github.com/PAMGuard/PAMGuardMatlab) library and [PAMBinaries package](https://github.com/TaikiSan21/PamBinaries) which can be used for more bespoke data management. Note that the exporter only exports a sub set of data types - this will expand in future releases.
## Exporting
The PAMGuard exporter can be accessed from *File->Export*. This brings up the Export dialog. The export dialog allows users to select which data to export, where to export it and the file format to export as. Each data block also has a settings icon which opens the data block's unique data selector. So for example, users can export only specific types of clicks or whistles between certain frequencies.
<p align="center">
<img width="920" height="450" src = "resources/PAMGuard_exporter_dialog_annotated.png">
</p>
<center><em> Diagram of the exporter dialog. The dialog allows users to select which part of the dataset to export, how to export it and which type of data to export </em></center>
The main parts of the dialog are as follows.
### Data Options
Select which part of the dataset to export
- Loaded Data : the data currently loaded into memory i.e. usually what you can see in the displays - may be different time oeriods depending on the data type.
- All data : the entire dataset.
- Select data : manually enter a period between two times.
- Specify time chunks : import a csv file with a list of time chunks.
### Export Options
Select where to export the data to using _Browse..._ and select the maximum allowed file size using the _Maximum file size_ selector. Select the format by toggling one of the data format buttons. Hover over each button to see more info.
### Export Data
Select which data to export. If a data type has a cog icon next to it then it has a data selector. The data selector settings can be used to filter which detections are exported. For example you may wish only to export clicks of a certain type or perhaps deep learning detections with a prediction value above a certain threshold. Each data selector is unique to the type of data. Note that the exporter only exports a sub set of data types - this will expand in future.
### Progress
Once _Start_ is selected then the progress bars show progress in exporting the selected data.
## Export formats
Currently the exporter has three possible output formats.
### MAT files
MAT files are files which can be opened easily in MATLAB and Python. They can store multiple different data formats e.g. tables, arrays, structures. Each PAMGuard detection is saved as a single structure and then the file contains an array of these structures for each data type. The fields within the structure contains the relevant data unique to each data unit. Whilst data units have unique fields depending on their type e.g. a click or a whistle, there are some fields that are shared between almost all data units - an example of a click detection structure is shown below
*General fields shared by most data units in PAMGuard*
- *millis*: the unix*1000 start time of the click, whistle, clip etc. in milliseconds; this number can be converted to a date/time with millisecond accuracy.
- *date*: the start time of the click in MATLAB datenum format. Use datastr(date) to show a time string.
- *UID*: a unique serial number for the detection. Within a processed dataset no other detection will have this number.
- *startSample*: The first sample of this detection - often used for finer scale time delay measurements. Samples refers to the number of samples in total the sound card has taken since processing begun or a new file has been created.
- *channelMap*: The channel map for this detection. One number which represents which channels this detection is from: To get the true channels use the getChannels(channelMap) function.
*Unique to clicks*
- *triggerMap*: which channel triggered the detection.
- *type*: Classification type. Must use database or settings to see what species this refers to.
- *duration*: Duration of this click detection in samples.
- *nChan*: Number of channels the detection was made on.
- *wave*: Waveform data for each channel.
Note that the format of each struct is the same as the format if extracting data using the [PAMGuard-MATLAB](https://github.com/PAMGuard/PAMGuardMatlab) library.
To open an exported .mat file simply drag it into **MATLAB** or use the function;
```Matlab
load(/my/path/to/file.mat)
```
To open a .mat file in **Python** use
```Python
import scipy.io
mat = scipy.io.loadmat('/my/path/to/file.mat')
clkstruct = mat['det_20170704_204536_580'] #The name of the struct array within the file
#Extract the third waveform from a click example
nwaves = len(clkstruct[0]) #Number of clicks
thirdwaveform = clkstruct[0, 2]['wave'] #Waveform from third click in samples between -1 and 1.
```
### R
Data can be exported to an RData frame. The data are exported as R structs with the same fields as in MATLAB (and PAMBinaries package). To open a an RData frame open RStudio and import the file or use;
```R
load("/my/path/to/file.RData")
```
### Wav files
Any detection which contains raw sound data, for example a click, clip or deep learning detection, can be exported as a wav file. When wav files are selected three options are presented for saving files.
<p align="center">
<img width="300" height="450" src = "resources/PAMGuard_exporter_dialog_wav.png">
</p>
<center><em> When wav files are selected additional options are presented on how to save the file </em></center>
- *Zero pad* : Here detections are saved as wav files with the time in between detections zero padded. The resulting files will be as large as the initial wav files processed to create the data. This can be useful if for example opening the files in another acoustic analysis program.
- *Concatenate* : The detections are saved to a wav file without any zero padding. This saves storage space but temporal information is lost within the wav file. The sample positions of each detection are saved in a text file along with the wav file so that temporal info is available if needed. This is same format as SoundTrap click detection data.
- *Individual* : Each detection is saved in it's own time stamped individual sound file.
## After export
Once data are exported, the exported files are not part of PAMGuard's data management system i.e. PAMGuard has no record they exist and they are not shown in the data model etc. If you export the same data again to the same location, then previous exported files may be overwritten without warning.

View File

@ -1,6 +1,7 @@
package export.layoutFX;
import PamController.SettingsPane;
import export.ExportParams;
import javafx.scene.Node;
import javafx.scene.control.Label;
import pamViewFX.fxNodes.PamBorderPane;

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 451 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 KiB

View File

@ -0,0 +1,252 @@
package export.wavExport;
import java.awt.Component;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.sound.sampled.AudioFormat;
import javax.swing.filechooser.FileSystemView;
import PamController.PamController;
import PamDetection.RawDataUnit;
import PamUtils.PamCalendar;
import PamUtils.PamUtils;
import PamView.paneloverlay.overlaymark.OverlayMark;
import PamguardMVC.LoadObserver;
import PamguardMVC.PamDataUnit;
import PamguardMVC.PamObservable;
import PamguardMVC.PamObserver;
import PamguardMVC.PamObserverAdapter;
import PamguardMVC.PamRawDataBlock;
import PamguardMVC.RawDataHolder;
import PamguardMVC.dataOffline.OfflineDataLoading;
import dataMap.OfflineDataMapPoint;
import detectiongrouplocaliser.DetectionGroupSummary;
import export.PamDataUnitExporter;
import javafx.scene.layout.Pane;
import wavFiles.Wav16AudioFormat;
import wavFiles.WavFileWriter;
/**
* Writes data units and/or ordered raw data to a wav file. Has functions to
* handle .wav file writing based on overlay marks and detection groups with
* functions to make decisions based on what type of data unit is selected and
* whether raw data is available.
* <p>
* There are two primary use cases; <br>
* 1) Order raw data from an overlay mark and save as a wav file <br>
* 2) Save a list of data units to wav files - either a single file with zero
* pads, a concatenated file or separate files.
*
* @author Jamie Macaulay
*
*/
public class WavDetExportManager implements PamDataUnitExporter {
/**
* Options for exporting wav files.
*/
private WavExportOptions wavFileoptions = new WavExportOptions();
/**
* Settings panel for wav file exporting
*/
private WavOptionsPanel wavOptionsPanel;
/**
* Exporter of wav files.
*/
private WavDetExport wavDetExport = new WavDetExport();
private File currentFile;
public WavDetExportManager() {
}
@Override
public boolean hasCompatibleUnits(Class dataUnitType) {
// boolean implementsInterface = Arrays.stream(dataUnitType.getInterfaces()).anyMatch(i -> i == RawDataHolder.class);
if ( RawDataHolder.class.isAssignableFrom(dataUnitType)) return true;
return false;
}
@Override
public boolean exportData(File fileName,
List<PamDataUnit> dataUnits, boolean append) {
if (fileName==null) return false;
if (this.currentFile==null || this.currentFile.compareTo(fileName)!=0) {
//we have a new .wav file to create.
if (fileName.exists()) {
//we need to delete it
System.out.println("PAMGuard export: wav file already existed and has been deleted: " + fileName.getName());
fileName.delete();
}
}
this.currentFile = fileName;
//make sure we have the latest options.
if (wavOptionsPanel!=null) {
//means the options panel has been opened.
wavFileoptions = wavOptionsPanel.getParams(wavFileoptions);
}
//should we zeropad?
//saveDataUnitWav(dataUnits);
switch (wavFileoptions.wavSaveChoice) {
case WavExportOptions.SAVEWAV_CONCAT:
wavDetExport.writeDataUnitWav(dataUnits, fileName, false);
break;
case WavExportOptions.SAVEWAV_INDIVIDUAL:
//here the filename will not be used but the parent folder will be used instead to write
//lots of wav files to.
wavDetExport.writeDataUnitWavs(dataUnits, fileName);
break;
case WavExportOptions.SAVEWAV_ZERO_PAD:
wavDetExport.writeDataUnitWav(dataUnits, fileName, true);
break;
}
return true;
}
@Override
public String getFileExtension() {
return "wav";
}
@Override
public String getIconString() {
return "mdi2f-file-music";
}
@Override
public String getName() {
return "raw sound";
}
@Override
public void close() {
// TODO Auto-generated method stub
}
@Override
public boolean isNeedsNewFile() {
return false;
}
@Override
public Component getOptionsPanel() {
if (this.wavOptionsPanel==null) {
this.wavOptionsPanel = new WavOptionsPanel();
}
wavOptionsPanel.setParams(this.wavFileoptions) ;
return wavOptionsPanel;
}
@Override
public Pane getOptionsPane() {
// TODO - make FX version of settings.
return null;
}
@Override
public void prepareExport() {
this.currentFile = null;
}
// hello(){
//
//
// if (mark==null) {
// start= foundDataUnits.getFirstTimeMillis();
// end= foundDataUnits.getLastTimeMillis();
// }
//
// File folder = new File(currentFolder);
//
// //save a .wav file clip.
// if (!folder.exists()){
// if (!folder.mkdir()){
// //TODO- warning message.
// return;
// }
// }
//
// String currentPath = PamCalendar.formatFileDateTime();
// //add data types to the filen,ae
// for (int i=0 ;i<mlData.size(); i++ ){
// currentPath=currentPath + "_" + mlData.get(i).getName();
// }
// //add correct file type.
// currentPath = currentPath + ".mat";
// currentPath = currentFolder+"\\"+currentPath;
//
//
// if (append && clipControl.clipSettings.storageOption == ClipSettings.STORE_WAVFILES) {
// wavFile.append(rawData);
// lastClipDataUnit.setSampleDuration(rawEnd-lastClipDataUnit.getStartSample());
// clipDataBlock.updatePamData(lastClipDataUnit, dataUnit.getTimeMilliseconds());
// // System.out.println(String.format("%d samples added to file", rawData[0].length));
// }
// else {
// ClipDataUnit clipDataUnit;
// long startMillis = dataUnit.getTimeMilliseconds() - (long) (clipGenSetting.preSeconds*1000.);
// if (clipControl.clipSettings.storageOption == ClipSettings.STORE_WAVFILES) {
// String folderName = getClipFileFolder(dataUnit.getTimeMilliseconds(), true);
// String fileName = getClipFileName(startMillis);
// AudioFormat af = new Wav16AudioFormat(getSampleRate(), rawData.length);
// wavFile = new WavFileWriter(folderName+fileName, af);
// wavFile.write(rawData);
// wavFile.close();
// // make a data unit to go with it.
// clipDataUnit = new ClipDataUnit(startMillis, dataUnit.getTimeMilliseconds(), rawStart,
// (int)(rawEnd-rawStart), channelMap, fileName, dataBlock.getDataName(), rawData, getSampleRate());
// }
// else {
// clipDataUnit = new ClipDataUnit(startMillis, dataUnit.getTimeMilliseconds(), rawStart,
// (int)(rawEnd-rawStart), channelMap, "", dataBlock.getDataName(), rawData, getSampleRate());
// }
// clipDataUnit.setFrequency(dataUnit.getFrequency());
// lastClipDataUnit = clipDataUnit;
// if (bearingLocaliser != null) {
// localiseClip(clipDataUnit, bearingLocaliser, hydrophoneMap);
// }
// clipDataBlock.addPamData(clipDataUnit);
// }
//
// return 0; // no error.
// }
//
// }
// }
}

View File

@ -0,0 +1,32 @@
package export.wavExport;
import java.io.Serializable;
/**
* Options for exporting wav files
*/
public class WavExportOptions implements Serializable, Cloneable {
private static final long serialVersionUID = 1L;
/**
* Save detections as zero padded.
*/
public static final int SAVEWAV_ZERO_PAD = 0;
/**
* Save detections as concatenated.
*/
public static final int SAVEWAV_CONCAT = 1;
/**
* Save detections as individual wav files.
*/
public static final int SAVEWAV_INDIVIDUAL = 2;
/**
* Flag to indicate how to save files
*/
public int wavSaveChoice = SAVEWAV_CONCAT;
}

View File

@ -0,0 +1,106 @@
package export.wavExport;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JRadioButton;
import PamView.dialog.PamGridBagContraints;
import PamView.panel.PamPanel;
/**
*
*/
public class WavOptionsPanel extends PamPanel {
private static final long serialVersionUID = 1L;
private JRadioButton zeroPad;
private JRadioButton noZeroPad;
private JRadioButton indvidualWav;
public WavOptionsPanel() {
super();
GridBagConstraints c = new PamGridBagContraints();
c.gridwidth = 1;
c.gridx = 0;
c.gridy = 0;
this.setLayout((new GridBagLayout()));
addComponent(this, zeroPad = new JRadioButton("Zero Pad"), c);
c.gridx++;
addComponent(this, noZeroPad = new JRadioButton("Concatenate"), c);
c.gridx++;
addComponent(this, indvidualWav = new JRadioButton("Individual"), c);
// c.gridx++;
// addComponent(this, new JLabel(" wav"), c);
// Initialization of object of "ButtonGroup" class.
ButtonGroup buttonGroup = new ButtonGroup();
buttonGroup.add(zeroPad);
buttonGroup.add(noZeroPad);
buttonGroup.add(indvidualWav);
noZeroPad.setToolTipText(
"<html>"
+ "Concatonate detections within wav files. If selected, then the wav files are concatenated"
+ "<br>"
+ "and a seperate text file encodes the detection times - this saves a lot of storage space!"
+ "</html>");
zeroPad.setToolTipText(
"<html>"
+ "Zero pad wav files. If selected, then the wav files are zero padding between detections "
+ "<br>"
+ "so they appear at the right time - this can be very storage space intensive. "
+ "</html>");
indvidualWav.setToolTipText(
"<html>"
+ "Save each detection as an individual time stamped wav file"
+ "</html>");
}
public void setParams(WavExportOptions wavExportOptions) {
switch (wavExportOptions.wavSaveChoice) {
case WavExportOptions.SAVEWAV_CONCAT:
noZeroPad.setSelected(true);
break;
case WavExportOptions.SAVEWAV_ZERO_PAD:
zeroPad.setSelected(true);
break;
case WavExportOptions.SAVEWAV_INDIVIDUAL:
indvidualWav.setSelected(true);
break;
}
}
public WavExportOptions getParams(WavExportOptions wavExportOptions) {
if (zeroPad.isSelected()) wavExportOptions.wavSaveChoice = WavExportOptions.SAVEWAV_ZERO_PAD;
if (noZeroPad.isSelected()) wavExportOptions.wavSaveChoice = WavExportOptions.SAVEWAV_CONCAT;
if (indvidualWav.isSelected()) wavExportOptions.wavSaveChoice = WavExportOptions.SAVEWAV_INDIVIDUAL;
return wavExportOptions;
}
}

View File

@ -2,6 +2,7 @@ package offlineProcessing;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
@ -63,6 +64,7 @@ public class OLProcessDialog extends PamDialog {
private JButton[] settingsButton;
private JLabel status, currFile;
private JProgressBar globalProgress; // file by file progress 1: nFiles
private JProgressBar loadedProgress; // progress throgh loaded data
private JCheckBox deleteOldData;
private JLabel dataInfo;
@ -111,6 +113,10 @@ public class OLProcessDialog extends PamDialog {
*/
private boolean isNeedaNote = true;
/**
* Tasks panel
*/
private PamAlignmentPanel tasksPanel;
public OLProcessDialog(Window parentFrame, OfflineTaskGroup taskGroup, String title) {
super(parentFrame, title, false);
@ -149,7 +155,7 @@ public class OLProcessDialog extends PamDialog {
dataSelectPanel.add(BorderLayout.SOUTH, southPanel);
JPanel tasksPanel = new PamAlignmentPanel(BorderLayout.WEST);
tasksPanel = new PamAlignmentPanel(BorderLayout.WEST);
tasksPanel.setLayout(new GridBagLayout());
tasksPanel.setBorder(new TitledBorder("Tasks"));
int nTasks = taskGroup.getNTasks();
@ -723,7 +729,7 @@ public class OLProcessDialog extends PamDialog {
* @author Doug Gillespie
*
*/
class OLMonitor implements TaskMonitor {
public class OLMonitor implements TaskMonitor {
@Override
public void setTaskStatus(TaskMonitorData taskMonitorData) {
@ -734,6 +740,7 @@ public class OLProcessDialog extends PamDialog {
else {
currFile.setText(taskMonitorData.fileOrStatus);
}
switch (taskMonitorData.taskActivity) {
case LINKING:
case LOADING:
@ -755,6 +762,7 @@ public class OLProcessDialog extends PamDialog {
default:
break;
}
switch (taskMonitorData.taskStatus) {
case COMPLETE:
globalProgress.setValue(100);
@ -879,6 +887,17 @@ public class OLProcessDialog extends PamDialog {
this.isNeedaNote = isNeedaNote;
}
public JProgressBar getGlobalProgress() {
return globalProgress;
}
public PamAlignmentPanel getTasksPanel() {
return tasksPanel;
}
}

View File

@ -0,0 +1,24 @@
package pamViewFX;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class PamLauncherFXApp extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("PAMGuard Launcher");
StackPane root = new StackPane();
root.getChildren().add(new PamLauncherPane());
primaryStage.setScene(new Scene(root, 500, 250));
primaryStage.show();
}
}

View File

@ -0,0 +1,9 @@
package pamViewFX;
public class PamLauncherFXAppLauncher {
public static void main(String[] args) {
PamLauncherFXApp.main(args);
}
}

View File

@ -0,0 +1,106 @@
package pamViewFX;
import java.net.MalformedURLException;
import java.nio.file.Path;
import java.nio.file.Paths;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.ContentDisplay;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamButton;
import pamViewFX.fxNodes.utilityPanes.PamToggleSwitch;
import pamViewFX.fxStyles.PamAtlantaStyle;
import pamViewFX.fxStyles.PamDefaultStyle;
import pamViewFX.fxStyles.PamStylesManagerFX;
/**
* Shows a launcher pane which allows a user to open a real time or viewer configuration.
*/
public class PamLauncherPane extends PamBorderPane {
public static final double BUTTON_SIZE = 120;
public PamLauncherPane() {
PamButton buttonNormal = new PamButton("Real time");
buttonNormal.setPrefSize(BUTTON_SIZE, BUTTON_SIZE);
PamButton buttonViewer = new PamButton("Post processing");
buttonViewer.setPrefSize(BUTTON_SIZE, BUTTON_SIZE);
Path pathNormal = Paths.get("./src/Resources/pamguardIcon.png");
Path pathViewer = Paths.get("./src/Resources/pamguardIconV.png");
Image img;
//create the normal mode button
try {
img = new Image(pathNormal.toUri().toURL().toExternalForm());
ImageView view = new ImageView(img);
buttonNormal.setGraphic(view);
} catch (MalformedURLException e) {
e.printStackTrace();
}
buttonNormal.setContentDisplay(ContentDisplay.TOP);
//create the viewer mode button
try {
img = new Image(pathViewer.toUri().toURL().toExternalForm());
ImageView view = new ImageView(img);
buttonViewer.setGraphic(view);
} catch (MalformedURLException e) {
e.printStackTrace();
}
buttonViewer.setContentDisplay(ContentDisplay.TOP);
HBox butttonBox = new HBox();
butttonBox.setSpacing(40);
butttonBox.setPadding(new Insets(40,40,40,40));
butttonBox.getChildren().addAll(buttonNormal, buttonViewer);
PamToggleSwitch newVersionSwitch = new PamToggleSwitch("PAMGuardFX");
newVersionSwitch.selectedProperty().addListener((obsVal, oldVal, newVal)->{
this.getStylesheets().clear();
if (newVal) {
//this.getStylesheets().add(new PrimerDark().getUserAgentStylesheet());
// Platform.runLater(()->{
// Application.setUserAgentStylesheet(new PrimerDark().getUserAgentStylesheet());
// });
PamStylesManagerFX.getPamStylesManagerFX().setCurStyle(new PamAtlantaStyle());
this.getStylesheets().addAll(PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getDialogCSS());
this.setStyle("-fx-background-color: -fx-darkbackground");
}
});
BorderPane.setAlignment(newVersionSwitch, Pos.CENTER_RIGHT);
newVersionSwitch.setAlignment(Pos.CENTER_RIGHT);
this.setTop(newVersionSwitch);
this.setCenter(butttonBox);
this.setPadding(new Insets(5,5,5,5));
// Application.setUserAgentStylesheet(new PrimerDark().getUserAgentStylesheet());
// this.getStylesheets().add(getClass().getResource(primerPAMGuard).toExternalForm());
// this.getStylesheets().add(getClass().getResource(new PrimerDark().getUserAgentStylesheet()).toExternalForm());
PamStylesManagerFX.getPamStylesManagerFX().setCurStyle(new PamDefaultStyle());
}
private void setStyle(boolean PAMGuardFX) {
this.getStylesheets().clear();
if (PAMGuardFX) {
PamStylesManagerFX.getPamStylesManagerFX().setCurStyle(new PamAtlantaStyle());
this.getStylesheets().addAll(PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getDialogCSS());
this.setStyle("-fx-background-color: -fx-darkbackground");
}
}
}

View File

@ -2,6 +2,7 @@ package pamViewFX;
import generalDatabase.DBControlUnit;
import java.io.File;
import java.util.Optional;
import binaryFileStorage.BinaryStore;
@ -16,7 +17,8 @@ import PamController.StorageParameters;
import PamController.soundMedium.GlobalMedium;
import PamController.soundMedium.GlobalMedium.SoundMedium;
import PamModel.PamModuleInfo;
import PamView.dialog.warn.WarnOnce;
import PamUtils.PamFileFilter;
import pamViewFX.fxGlyphs.PamGlyphDude;
import pamViewFX.fxNodes.PamButton;
import pamViewFX.fxNodes.PamVBox;
import pamViewFX.fxNodes.PamHBox;
@ -34,6 +36,8 @@ import javafx.scene.control.MenuButton;
import javafx.scene.control.MenuItem;
import javafx.scene.control.Separator;
import javafx.scene.text.TextAlignment;
import javafx.stage.FileChooser;
import javafx.stage.FileChooser.ExtensionFilter;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.control.Tooltip;
@ -81,13 +85,16 @@ public class PamSettingsMenuPane extends PamVBox {
PamSettingManager.getInstance().saveSettings(null);
});
styleButton(saveConfig);
saveConfig.setGraphic(PamGlyphDude.createPamIcon("mdi2c-content-save-outline",
PamGuiManagerFX.iconSize));
PamButton saveConfigAs=new PamButton("Save as...");
saveConfigAs.setOnAction((action)->{
PamSettingManager.getInstance().saveSettingsAs(null);
saveSettingsAs();
});
styleButton(saveConfigAs);
saveConfigAs.setGraphic(PamGlyphDude.createPamIcon("mdi2c-content-save-move-outline",
PamGuiManagerFX.iconSize));
//Air or water mode
ToggleButton toggleButton1 = new ToggleButton("Water");
@ -98,6 +105,7 @@ public class PamSettingsMenuPane extends PamVBox {
PamController.getInstance().getGlobalMediumManager().setCurrentMedium(SoundMedium.Water);
});
ToggleButton toggleButton2 = new ToggleButton("Air");
toggleButton2.setPrefWidth(60);
toggleButton2.setTooltip(new Tooltip(GlobalMedium.getToolTip(SoundMedium.Air)));
@ -114,6 +122,8 @@ public class PamSettingsMenuPane extends PamVBox {
Label mediumLabel = new Label("Sound Medium");
mediumLabel.setAlignment(Pos.CENTER_LEFT);
mediumLabel.setPadding(new Insets(0,0,0,15));
mediumLabel.setGraphic(PamGlyphDude.createPamIcon("mdi2w-waves",
PamGuiManagerFX.iconSize));
//styleButton(mediumLabel);
@ -132,9 +142,13 @@ public class PamSettingsMenuPane extends PamVBox {
PamButton generalSettings=new PamButton("General Settings...");
styleButton(generalSettings);
generalSettings.setGraphic(PamGlyphDude.createPamIcon("mdi2c-cog",
PamGuiManagerFX.iconSize));
MenuButton settings=new MenuButton("Module Settings");
settings.setPopupSide(Side.RIGHT);
settings.setGraphic(PamGlyphDude.createPamIcon("mdi2c-cogs",
PamGuiManagerFX.iconSize));
// settings.setStyle("-fx-background-radius: 0;"
// + " -fx-border-color: transparent; -fx-padding: 0 0 0 0;");
@ -173,6 +187,8 @@ public class PamSettingsMenuPane extends PamVBox {
}
});
styleButton(database);
database.setGraphic(PamGlyphDude.createPamIcon("mdi2d-database",
PamGuiManagerFX.iconSize));
PamButton binaryStorage=new PamButton("Binary Storage...");
binaryStorage.setOnAction((action)->{
@ -193,6 +209,8 @@ public class PamSettingsMenuPane extends PamVBox {
}
});
styleButton(binaryStorage);
binaryStorage.setGraphic(PamGlyphDude.createPamIcon("mdi2f-file-table",
PamGuiManagerFX.iconSize));
PamButton storageManager=new PamButton("Storage Manager...");
storageManager.setOnAction((action)->{
@ -204,24 +222,35 @@ public class PamSettingsMenuPane extends PamVBox {
}
});
styleButton(storageManager);
storageManager.setGraphic(PamGlyphDude.createPamIcon("mdi2d-database-cog",
PamGuiManagerFX.iconSize));
PamButton help=new PamButton("Help...");
styleButton(help);
help.setGraphic(PamGlyphDude.createPamIcon("mdi2h-help-circle-outline",
PamGuiManagerFX.iconSize));
PamButton about=new PamButton("About...");
styleButton(about);
about.setGraphic(PamGlyphDude.createPamIcon("mdi2i-information-outline",
PamGuiManagerFX.iconSize));
// PamButton tip=new PamButton("Tip of the day...");
// styleButton(tip);
PamButton website=new PamButton("Website");
styleButton(website);
website.setGraphic(PamGlyphDude.createPamIcon("mdi2e-earth",
PamGuiManagerFX.iconSize));
PamButton contact=new PamButton("Found a bug?");
styleButton(contact);
contact.setGraphic(PamGlyphDude.createPamIcon("mdi2b-bug",
PamGuiManagerFX.iconSize));
PamButton checkForUpdates=new PamButton("Check for updates");
styleButton(checkForUpdates);
checkForUpdates.setGraphic(PamGlyphDude.createPamIcon("mdi2r-refresh",
PamGuiManagerFX.iconSize));
this.getChildren().addAll(settingsLabel,saveConfig,saveConfigAs, new Separator(), mediumToggleBox, generalSettings, settings, new Separator(),
storageManager, database, binaryStorage, new Separator(), help, checkForUpdates, website, contact, about);
@ -268,4 +297,55 @@ public class PamSettingsMenuPane extends PamVBox {
}
}
/**
* Save settings to a new psf file.
* @param frame parent frame for dialog.
*/
public void saveSettingsAs() {
/*
* get a new file name, set that as the current file
* then write all settings to it.
*/
File file = null;
String currentfileName = PamSettingManager.getInstance().getSettingsFileName();
if (currentfileName != null) {
file =new File(currentfileName);
}
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("Open Resource File");
fileChooser.getExtensionFilters().addAll(
new ExtensionFilter("PAMGuard settings files", "*.xml", "*.psfx"));
if (currentfileName!=null) {
fileChooser.setInitialDirectory(file);
}
File selectedFile = fileChooser.showOpenDialog(this.getScene().getWindow());
if (selectedFile == null) {
return;
}
selectedFile = PamFileFilter.checkFileEnd(selectedFile, PamSettingManager.getCurrentSettingsFileEnd(), true);
System.out.println("Saving settings to file " + selectedFile.getAbsolutePath());
// Insert the new file into the top of the recent psf file list. Also check
// if we are running remotely, which probably means the user double-clicked on
// a psf to start Pamguard. In that case, change the remotePSF pointer to
// the new file as well
PamSettingManager.getInstance().setDefaultFile(selectedFile.getAbsolutePath());
if (PamSettingManager.remote_psf != null) {
PamSettingManager.remote_psf = selectedFile.getAbsolutePath();
}
PamSettingManager.getInstance().saveSettings(PamSettingManager.SAVE_PSF);
PamController.getInstance().getGuiFrameManager().sortFrameTitles();
}
}

View File

@ -33,8 +33,9 @@ public class PamDateAxis extends ValueAxis<Long> {
/** We use these for auto ranging to pick a user friendly tick unit. (must be increasingly bigger)*/
private static final double[] TICK_UNIT_DEFAULTS = {
3600000, // 1 hour
86400000, // 1 day
172800000, // 2 das
172800000, // 2 days
259200000, // 3 days
345600000, // 4 days
432000000, // 5 days
@ -63,8 +64,9 @@ public class PamDateAxis extends ValueAxis<Long> {
/** These are matching date formatter strings */
private static final String[] TICK_UNIT_FORMATTER_DEFAULTS = {
"MM/dd/yy", // 1 day
"MM/dd/yy", // 2 das
"HH:mm:SS", // 1 hour
"HH:mm:SS", // 1 day
"MM/dd/yy", // 2 days
"MM/dd/yy", // 3 days
"MM/dd/yy", // 4 days
"MM/dd/yy", // 5 days

View File

@ -6,6 +6,8 @@ import javafx.beans.property.BooleanProperty;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Point2D;
import javafx.scene.Cursor;
import javafx.scene.Node;
@ -256,6 +258,225 @@ public class ScrollBarPane extends PamBorderPane {
return canvas;
}
/**
* Create the rectangle which can be dragged to change time but also dragged to change the width of time
* shown.
* @return a rectangle which can be dragged and changed size within the scroll bar pane.
*/
private Pane createDragRectangle(){
double dragWidth=5;
double lineInset=5;
double minPixelWidth=10;
String cursorColour = "-fx-background-color: rgba(255, 255, 255, 0.5)";
Pane rectangle=new Pane();
//rectangle.setStrokeWidth(10);
rectangle.layoutYProperty().setValue(0);
rectangle.prefHeightProperty().bind(scrollBarPane.heightProperty());
rectangle.setStyle(cursorColour);
rectangle.setPrefWidth(100);
//create two panes either side of this pane.
Pane leftDrag=new Pane();
leftDrag.setCursor(Cursor.W_RESIZE);
leftDrag.prefHeightProperty().bind(rectangle.heightProperty());
//the layout of the left rectangle is 0,0;
leftDrag.setPrefWidth(dragWidth);
leftDrag.setStyle(cursorColour);
//add line decoration to left drag.
Line leftdragLine=new Line();
leftdragLine.startXProperty().bind(leftDrag.widthProperty().divide(2));
leftdragLine.startYProperty().setValue(5);
leftdragLine.endXProperty().bind(leftDrag.widthProperty().divide(2));
leftdragLine.endYProperty().bind(leftDrag.heightProperty().subtract(lineInset));
leftDrag.getChildren().add(leftdragLine);
rectangle.getChildren().add(leftDrag);
Pane rightDrag=new Pane();
rightDrag.setCursor(Cursor.E_RESIZE);
rightDrag.prefHeightProperty().bind(rectangle.heightProperty());
rightDrag.layoutXProperty().bind(rectangle.widthProperty().subtract(rightDrag.widthProperty()));
rightDrag.setPrefWidth(dragWidth);
rightDrag.setStyle(cursorColour);
//add line decoration to left drag.
Line rightdragLine=new Line();
rightdragLine.startXProperty().bind(rightDrag.widthProperty().divide(2));
rightdragLine.startYProperty().setValue(5);
rightdragLine.endXProperty().bind(rightDrag.widthProperty().divide(2));
rightdragLine.endYProperty().bind(rightDrag.heightProperty().subtract(lineInset));
rightDrag.getChildren().add(rightdragLine);
rectangle.getChildren().add(rightDrag);
rectangle.setCursor(Cursor.OPEN_HAND); //Change cursor to hand
//now set behaviours
leftDrag.setOnMousePressed((event)->{
rightLayoutX=rectangle.getLayoutX()+rectangle.getWidth();
isChanging.set(true);
dragStarted(event, leftDrag);
});
leftDrag.setOnMouseReleased((event)->{
isChanging.set(false);
dragging(event);
});
//left drag
leftDrag.setOnMouseDragged((event)->{
isChanging.set(true);
Point2D newPos=scrollBarPane.sceneToLocal(event.getSceneX(), event.getSceneY());
double dragPosX=newPos.getX();
double widthVal=rectangle.getWidth();
double currentVal=rectangle.getLayoutX();
//only move rectangle if the mouse has started dragging from inside.
if (dragPosX-dragX<0){
//don;t let the drag go past left
currentVal=0;
}
else if (dragPosX-dragX>scrollBarPane.getWidth()-minPixelWidth) {
//don;t let the drag
//System.out.println("AcousticScrollerFX: 2 widthVal: "+widthVal+ " currentVal: "+(dragPosX-dragX)+ " rightLayoutX "+rightLayoutX);
widthVal=minPixelWidth;
currentVal=scrollBarPane.getWidth()-widthVal;
}
else{
//System.out.println("AcousticScrollerFX: 1 widthVal: "+widthVal+ " currentVal: "+(dragPosX-dragX)+ " rightLayoutX "+rightLayoutX);
widthVal=rightLayoutX-(dragPosX-dragX);
currentVal=dragPosX-dragX;
}
//the width cannot be less than 1 pixel
widthVal=Math.max(minPixelWidth, widthVal);
double visAmount=calcScrollBarVal(widthVal)-this.minValueProperty.get();
//set the visible amount property;
this.visibleAmountProperty.setValue(visAmount);
this.currentValueProperty.setValue(calcScrollBarVal(currentVal));
//need to consume the event so does not pass through node.
event.consume();
});
//now set behaviours
rightDrag.setOnMousePressed((event)->{
leftLayoutX=rectangle.getLayoutX();
isChanging.set(true);
rectangle.setCursor(Cursor.CLOSED_HAND); //Change cursor to hand
dragStarted(event, rightDrag);
});
rightDrag.setOnMouseReleased((event)->{
currentValueProperty.setValue(calcScrollBarVal(rectangle.getLayoutX()));
isChanging.set(false);
rectangle.setCursor(Cursor.OPEN_HAND); //Change cursor to hand
dragging(event);
});
//right drag handle
rightDrag.setOnMouseDragged((event)->{
isChanging.set(true);
Point2D newPos=scrollBarPane.sceneToLocal(event.getSceneX(), event.getSceneY());
double dragPosX=newPos.getX();
double widthVal;
if ((dragPosX-leftLayoutX)<leftDrag.getWidth()){
widthVal=minPixelWidth;
}
else if (dragPosX>scrollBarPane.getWidth()){
widthVal=scrollBarPane.getWidth()-leftLayoutX;
}
else{
widthVal=dragPosX+dragX-leftLayoutX;
}
widthVal=Math.max(minPixelWidth, widthVal);
// System.out.println("AcousticScrollerFX: visbleAmount: min: "+minValueProperty.get()+
// " max: "+maxValueProperty.get() + " visble: "+calcScrollBarVal(rectangle.getWidth())+
// " rectange width: "+rectangle.getWidth());
//set the visible amount- the width of the rectangle is changed in the property listener.
// System.out.println("AcousticScrollerFX: calcScrollBarVal(widthVal) " + calcScrollBarVal(widthVal)
// + " this.minValueProperty.get() " + this.minValueProperty.get() + " this.maxValueProperty.get() " + this.maxValueProperty.get());
double visAmount=calcScrollBarVal(widthVal)-this.minValueProperty.get();
this.visibleAmountProperty.setValue(visAmount);
//need to consume the event so does not pass through node.
event.consume();
});
//the rectangle itself.
rectangle.setOnMousePressed((event)->{
rectanglePressed(event);
});
rectangle.setOnMouseReleased((event)->{
rectangleReleased(event);
});
rectangle.setOnMouseDragged((event)->{
rectangleDragged(event);
});
return rectangle;
}
private void rectanglePressed(MouseEvent event){
isChanging.set(true);
dragStarted(event, rectangle);
dragging(event);
}
private void rectangleReleased(MouseEvent event){
isChanging.set(false);
dragging(event);
}
private void rectangleDragged(MouseEvent event){
isChanging.set(true);
dragging(event);
Point2D newPos=scrollBarPane.sceneToLocal(event.getSceneX(), event.getSceneY());
double dragPosX=newPos.getX();
//only move rectangle if the mouse has started dragging from inside.
//move the rectangle
if (dragPosX-dragX<0) rectangle.setLayoutX(0);
else if (dragPosX-dragX>scrollBarPane.getWidth()-rectangle.getWidth()) rectangle.setLayoutX(scrollBarPane.getWidth()-rectangle.getWidth());
else rectangle.setLayoutX(dragPosX-dragX);
//now must set the scroll bar value.
currentValueProperty.setValue(calcScrollBarVal(rectangle.getLayoutX()));
event.consume();
}
/**
* Set the value in the text box
* @param visAmount - the visible amount
*/
private void setTextBoxValue(double visAmount) {
if (isShowMillis()){
textBox.setText(String.format("%.2fms", visAmount));
}
else {
textBox.setText(PamCalendar.formatDuration((long) visAmount));
}
}
/**
* Create the text field that allows to manually chage the visible amount amount property.
*/
@ -328,219 +549,13 @@ public class ScrollBarPane extends PamBorderPane {
setTextBoxValue(visibleAmountProperty.get());
}
/**
* Create the rectangle which can be dragged to change time but also dragged to change the width of time
* shown.
* @return a rectangle which can be dragged and changed size within the scroll bar pane.
*/
private Pane createDragRectangle(){
double dragWidth=5;
double lineInset=5;
double minPixelWidth=10;
String cursorColour = "-fx-background-color: rgba(255, 255, 255, 0.5)";
Pane rectangle=new Pane();
//rectangle.setStrokeWidth(10);
rectangle.layoutYProperty().setValue(0);
rectangle.prefHeightProperty().bind(scrollBarPane.heightProperty());
rectangle.setStyle(cursorColour);
rectangle.setPrefWidth(100);
//create two panes either side of this pane.
Pane leftDrag=new Pane();
leftDrag.setCursor(Cursor.W_RESIZE);
leftDrag.prefHeightProperty().bind(rectangle.heightProperty());
//the layout of the left rectangle is 0,0;
leftDrag.setPrefWidth(dragWidth);
leftDrag.setStyle(cursorColour);
//add line decoration to left drag.
Line leftdragLine=new Line();
leftdragLine.startXProperty().bind(leftDrag.widthProperty().divide(2));
leftdragLine.startYProperty().setValue(5);
leftdragLine.endXProperty().bind(leftDrag.widthProperty().divide(2));
leftdragLine.endYProperty().bind(leftDrag.heightProperty().subtract(lineInset));
leftDrag.getChildren().add(leftdragLine);
rectangle.getChildren().add(leftDrag);
Pane rightDrag=new Pane();
rightDrag.setCursor(Cursor.E_RESIZE);
rightDrag.prefHeightProperty().bind(rectangle.heightProperty());
rightDrag.layoutXProperty().bind(rectangle.widthProperty().subtract(rightDrag.widthProperty()));
rightDrag.setPrefWidth(dragWidth);
rightDrag.setStyle(cursorColour);
//add line decoration to left drag.
Line rightdragLine=new Line();
rightdragLine.startXProperty().bind(rightDrag.widthProperty().divide(2));
rightdragLine.startYProperty().setValue(5);
rightdragLine.endXProperty().bind(rightDrag.widthProperty().divide(2));
rightdragLine.endYProperty().bind(rightDrag.heightProperty().subtract(lineInset));
rightDrag.getChildren().add(rightdragLine);
rectangle.getChildren().add(rightDrag);
//now set behaviours
leftDrag.setOnMousePressed((event)->{
rightLayoutX=rectangle.getLayoutX()+rectangle.getWidth();
isChanging.set(true);
dragStarted(event, leftDrag);
});
leftDrag.setOnMouseReleased((event)->{
isChanging.set(false);
dragging(event);
});
//left drag
leftDrag.setOnMouseDragged((event)->{
isChanging.set(true);
Point2D newPos=scrollBarPane.sceneToLocal(event.getSceneX(), event.getSceneY());
double dragPosX=newPos.getX();
double widthVal=rectangle.getWidth();
double currentVal=rectangle.getLayoutX();
//only move rectangle if the mouse has started dragging from inside.
if (dragPosX-dragX<0){
//don;t let the drag go past left
currentVal=0;
}
else if (dragPosX-dragX>scrollBarPane.getWidth()-minPixelWidth) {
//don;t let the drag
//System.out.println("AcousticScrollerFX: 2 widthVal: "+widthVal+ " currentVal: "+(dragPosX-dragX)+ " rightLayoutX "+rightLayoutX);
widthVal=minPixelWidth;
currentVal=scrollBarPane.getWidth()-widthVal;
}
else{
//System.out.println("AcousticScrollerFX: 1 widthVal: "+widthVal+ " currentVal: "+(dragPosX-dragX)+ " rightLayoutX "+rightLayoutX);
widthVal=rightLayoutX-(dragPosX-dragX);
currentVal=dragPosX-dragX;
}
//the width cannot be less than 1 pixel
widthVal=Math.max(minPixelWidth, widthVal);
double visAmount=calcScrollBarVal(widthVal)-this.minValueProperty.get();
//set the visible amount property;
this.visibleAmountProperty.setValue(visAmount);
this.currentValueProperty.setValue(calcScrollBarVal(currentVal));
//need to consume the event so does not pass through node.
event.consume();
});
//now set behaviours
rightDrag.setOnMousePressed((event)->{
leftLayoutX=rectangle.getLayoutX();
isChanging.set(true);
dragStarted(event, rightDrag);
});
rightDrag.setOnMouseReleased((event)->{
currentValueProperty.setValue(calcScrollBarVal(rectangle.getLayoutX()));
isChanging.set(false);
dragging(event);
});
//right drag handle
rightDrag.setOnMouseDragged((event)->{
isChanging.set(true);
Point2D newPos=scrollBarPane.sceneToLocal(event.getSceneX(), event.getSceneY());
double dragPosX=newPos.getX();
double widthVal;
if ((dragPosX-leftLayoutX)<leftDrag.getWidth()){
widthVal=minPixelWidth;
}
else if (dragPosX>scrollBarPane.getWidth()){
widthVal=scrollBarPane.getWidth()-leftLayoutX;
}
else{
widthVal=dragPosX+dragX-leftLayoutX;
}
widthVal=Math.max(minPixelWidth, widthVal);
// System.out.println("AcousticScrollerFX: visbleAmount: min: "+minValueProperty.get()+
// " max: "+maxValueProperty.get() + " visble: "+calcScrollBarVal(rectangle.getWidth())+
// " rectange width: "+rectangle.getWidth());
//set the visible amount- the width of the rectangle is changed in the property listener.
// System.out.println("AcousticScrollerFX: calcScrollBarVal(widthVal) " + calcScrollBarVal(widthVal)
// + " this.minValueProperty.get() " + this.minValueProperty.get() + " this.maxValueProperty.get() " + this.maxValueProperty.get());
double visAmount=calcScrollBarVal(widthVal)-this.minValueProperty.get();
this.visibleAmountProperty.setValue(visAmount);
//need to consume the event so does not pass through node.
event.consume();
});
//the rectangle itself.
rectangle.setOnMousePressed((event)->{
rectanglePressed(event);
});
rectangle.setOnMouseReleased((event)->{
rectangleReleased(event);
});
rectangle.setOnMouseDragged((event)->{
rectangleDragged(event);
});
return rectangle;
}
private void rectanglePressed(MouseEvent event){
isChanging.set(true);
dragStarted(event, rectangle);
dragging(event);
}
private void rectangleReleased(MouseEvent event){
isChanging.set(false);
dragging(event);
}
private void rectangleDragged(MouseEvent event){
isChanging.set(true);
dragging(event);
Point2D newPos=scrollBarPane.sceneToLocal(event.getSceneX(), event.getSceneY());
double dragPosX=newPos.getX();
//only move rectangle if the mouse has started dragging from inside.
//move the rectangle
if (dragPosX-dragX<0) rectangle.setLayoutX(0);
else if (dragPosX-dragX>scrollBarPane.getWidth()-rectangle.getWidth()) rectangle.setLayoutX(scrollBarPane.getWidth()-rectangle.getWidth());
else rectangle.setLayoutX(dragPosX-dragX);
//now must set the scroll bar value.
currentValueProperty.setValue(calcScrollBarVal(rectangle.getLayoutX()));
event.consume();
}
/**
* Set the value in the text box
* @param visAmount - the visible amount
* Get the text box that shows the visible amount
* @return - the text field
*/
private void setTextBoxValue(double visAmount) {
if (isShowMillis()){
textBox.setText(String.format("%.2fms", visAmount));
}
else {
textBox.setText(PamCalendar.formatDuration((long) visAmount));
}
public TextField getTextBox() {
return textBox;
}
@ -844,5 +859,18 @@ public class ScrollBarPane extends PamBorderPane {
this.showMillis = showMillis;
}
/**
* Convenience function which adds a change listener to the current value and visible amount prooperty.
* @param val - the change listener to add.
*/
public void addValueListener(ChangeListener val) {
//add listener to visible amount property.
visibleAmountProperty.addListener(val);
//add listener to current value amount property.
currentValueProperty.addListener(val);
}
}

View File

@ -4,6 +4,8 @@ import java.util.ArrayList;
import PamView.ColourScheme;
import PamView.PamColors;
import atlantafx.base.theme.CupertinoDark;
import atlantafx.base.theme.CupertinoLight;
import atlantafx.base.theme.PrimerDark;
import atlantafx.base.theme.PrimerLight;
@ -53,6 +55,7 @@ public class PamAtlantaStyle extends PamDefaultStyle {
// private String guiCSS = new NordDark().getUserAgentStylesheet();
// protected String primerlight = "/Resources/css/primer-light.css";
protected String primerlight = new PrimerLight().getUserAgentStylesheet();
// protected String primerlight = new CupertinoLight().getUserAgentStylesheet();
/**
* Relative location of the CSS style sheet to be used for the Pamguard standard
@ -62,6 +65,7 @@ public class PamAtlantaStyle extends PamDefaultStyle {
// private String dialogCSS = new PrimerDark().getUserAgentStylesheet();
// protected String primerdark = "/Resources/css/primer-dark.css";
protected String primerdark = new PrimerDark().getUserAgentStylesheet();
// protected String primerdark = new CupertinoDark().getUserAgentStylesheet();
/**

View File

@ -153,7 +153,7 @@ public class PeakFreqOptionsPane extends StandardSymbolModifierPane {
super.setParams();
//important to have here because the super.setParams set this bak to false.
//important to have here because the super.setParams set this back to false.
setParams = true;
// StandardSymbolOptions standardSymbolOptions = (StandardSymbolOptions) getSymbolModifier().getSymbolChooser().getSymbolOptions();

View File

@ -1,39 +0,0 @@
package pamguard;
import java.sql.Connection;
import java.sql.SQLException;
import org.sqlite.SQLiteConfig;
import generalDatabase.sqlite.SqliteSQLTypes;
public class PAMGuard_sqlite {
public static void main(String[] args) {
String dbName = "/Users/jdjm/Desktop/section2_cpod/hyskeir_pamguard.sqlite3";
/*
* Don't use the driver manager, but open from the built in command in
* SQLiteConfig. This will then correctly set the dateformat of the database.
*/
SQLiteConfig config = new SQLiteConfig();
config.setSharedCache(true);
config.enableRecursiveTriggers(true);
config.enableLoadExtension(true);
config.setDateClass(SqliteSQLTypes.dateClass.getValue());
config.setDateStringFormat(SQLiteConfig.DEFAULT_DATE_STRING_FORMAT);
Connection con = null;
try {
con = config.createConnection("jdbc:sqlite:" + dbName);
con.setAutoCommit(false);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Connection: " + con);
}
}

View File

@ -38,6 +38,13 @@ public class RawDLParams implements Serializable, Cloneable {
*/
public GroupedSourceParameters groupedSourceParams = new GroupedSourceParameters();
/**
* True to enable segmentation. If segmentation is disabled then the raw waveform from
* a data unit is passed directly to the model. Note that this is not an option for raw sound
* data.
*/
public boolean enableSegmentation = true;
/**
* The number of raw samples to send to the classifier.
*/
@ -85,7 +92,7 @@ public class RawDLParams implements Serializable, Cloneable {
* different class names. If we change model then the class names may change.
* Previously annotated data will then be messed up. But, in a giant dataset
* that may be an issue. Perhaps users wish to run a new model on some chunk of
* data without messing up all the other classified detectionS which have used
* data without messing up all the other classified detections which have used
* that module. So store the data in binary files? That is super inefficient as
* the same string is stored many times. So instead store a short which
* identifies the string that sits in this table. Everytime a new model is added

View File

@ -382,6 +382,7 @@ public class DelphinIDUtils {
// String modelPath = "/Users/au671271/Library/CloudStorage/Dropbox/PAMGuard_dev/Deep_Learning/delphinID/testencounter415/whistle_model_2/whistle_4s_415.zip";
String modelPath = "D:/Dropbox/PAMGuard_dev/Deep_Learning/delphinID/testencounter415/whistle_model_2/whistle_4s_415.zip";
//line widths in pixels
double[] lineWidths = new double[] {6, 7, 10, 15, 20};
for (double lineWidth:lineWidths) {

View File

@ -53,7 +53,7 @@ public abstract class DLModelWorker<T> {
public float[][][] dataUnits2ModelInput(ArrayList<? extends PamDataUnit> dataUnits, float sampleRate, int iChan){
@SuppressWarnings("unchecked")
ArrayList<GroupedRawData> rawDataUnits = ( ArrayList<GroupedRawData>) dataUnits;
ArrayList<GroupedRawData> rawDataUnits = (ArrayList<GroupedRawData>) dataUnits;
//the number of chunks.
int numChunks = rawDataUnits.size();

View File

@ -1,5 +1,7 @@
package rawDeepLearningClassifier.dlClassification.genericModel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import org.jamdev.jdl4pam.genericmodel.GenericModel;
@ -13,6 +15,13 @@ import org.jamdev.jdl4pam.transforms.WaveTransform;
import org.jamdev.jdl4pam.utils.DLUtils;
import org.jamdev.jpamutils.wavFiles.AudioData;
import PamUtils.PamArrayUtils;
import rawDeepLearningClassifier.segmenter.GroupedRawData;
import us.hebi.matlab.mat.format.Mat5;
import us.hebi.matlab.mat.format.Mat5File;
import us.hebi.matlab.mat.types.Matrix;
import us.hebi.matlab.mat.types.Struct;
public class GenericModelTest {
public static void rightWhaleTest() {
@ -98,9 +107,126 @@ public class GenericModelTest {
} catch (Exception e) {
e.printStackTrace();
}
}
public static void clickDLTest() {
float SAMPLE_RATE = 500000;
//relative paths to the resource folders.
System.out.println("*****Click classification Deep Learning C*****");
//relative paths to the resource folders.
String relModelPath = "./src/test/resources/rawDeepLearningClassifier/Generic/risso_click/uniform_model/saved_model.pb";
String clicksPath = "./src/test/resources/rawDeepLearningClassifier/Generic/risso_click/clicks.mat";
Path path = Paths.get(relModelPath);
GenericModelWorker genericModelWorker = new GenericModelWorker();
GenericModelParams genericModelParams = new GenericModelParams();
genericModelParams.modelPath = path.toAbsolutePath().normalize().toString();
//create the transforms.
ArrayList<DLTransfromParams> dlTransformParamsArr = new ArrayList<DLTransfromParams>();
//waveform transforms.
dlTransformParamsArr.add(new SimpleTransformParams(DLTransformType.DECIMATE_SCIPY, 250000.));
dlTransformParamsArr.add(new SimpleTransformParams(DLTransformType.PEAK_TRIM, 128, 1));
dlTransformParamsArr.add(new SimpleTransformParams(DLTransformType.NORMALISE_WAV, 0., 1, AudioData.ZSCORE));
genericModelParams.dlTransfromParams = dlTransformParamsArr;
genericModelParams.dlTransfroms = DLTransformsFactory.makeDLTransforms((ArrayList<DLTransfromParams>)genericModelParams.dlTransfromParams);
//create the clicks.
path = Paths.get(clicksPath);
ArrayList<GroupedRawData> clicks = importClicks(path.toAbsolutePath().normalize().toString(), SAMPLE_RATE);
//prep the model
genericModelWorker.prepModel(genericModelParams, null);
System.out.println("Model has loaded");
ArrayList<GroupedRawData> groupedData = new ArrayList<GroupedRawData>();
float prediction = 0;
for (int i=0; i<clicks.size() ; i++) {
groupedData = new ArrayList<GroupedRawData>();
groupedData.add(clicks.get(i)); //TODO for loop
// System.out.println("Waveform input: " + groupedData.get(i).getRawData().length + " " + groupedData.get(i).getRawData()[0].length + " " + + groupedData.get(i).getRawData()[0][0]);
//RUN THE RAW MODEL
// System.out.println("Min max before: ");
// PamArrayUtils.printArray(PamArrayUtils.minmax(groupedData.get(i).getRawData()[0]));
// double[] wav = PamArrayUtils.normalise(groupedData.get(i).getRawData()[0]);
//
// System.out.println("Min max: ");
// PamArrayUtils.printArray(PamArrayUtils.minmax(wav));
// float[][] input1 = new float[][] {PamArrayUtils.double2Float(wav)};
// float[] output1 = genericModelWorker.getModel().runModel(input1);
// System.out.println("Output1: " );
// PamArrayUtils.printArray(output1);
//RUN THROUGH THE GENERIC MODEL CLASSIIFER.
ArrayList<StandardPrediction> genericPrediction = genericModelWorker.runModel(groupedData,SAMPLE_RATE, 0);
float[] output = genericPrediction.get(0).getPrediction();
System.out.println(String.format("Click %d Predicted output: %.6f true output: %.6f passed: %b", clicks.get(i).getUID(),
output[0], prediction, output[0]>prediction*0.9 && output[0]<prediction*1.1));
}
}
/**
* Import a bunch of clicks from a .mat file
*/
public static ArrayList<GroupedRawData> importClicks(String filePath, float sR) {
try {
Mat5File mfr = Mat5.readFromFile(filePath);
// //get array of a name "my_array" from file
Struct mlArrayRetrived = mfr.getStruct( "clickpreds" );
int numClicks= mlArrayRetrived.getNumCols();
ArrayList<GroupedRawData> clicks = new ArrayList<GroupedRawData>(numClicks);
GroupedRawData clickData;
for (int i=0; i<numClicks; i++) {
Matrix clickWav= mlArrayRetrived.get("wave", i);
double[][] clickwaveform= PamArrayUtils.matrix2array(clickWav);
clickwaveform = PamArrayUtils.transposeMatrix(clickwaveform);
//System.out.println("click: " + click[0].length + " num: " + numClicks);
Matrix clickUID= mlArrayRetrived.get("UID", i);
Matrix clickmillis= mlArrayRetrived.get("millis", i);
Matrix channelMap= mlArrayRetrived.get("channelMap", i);
Matrix startSample= mlArrayRetrived.get("startSample", i);
Matrix sampleDuration= mlArrayRetrived.get("sampleDuration", i);
clickData = new GroupedRawData(clickmillis.getLong(0), channelMap.getInt(0), startSample.getLong(0), sampleDuration.getLong(0), sampleDuration.getInt(0));
clickData.setUID(clickUID.getLong(0));
clickData.setRawData(clickwaveform);
clicks.add(clickData);
}
return clicks;
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
/**
* The bat Pytorch test.
*/
@ -110,7 +236,8 @@ public class GenericModelTest {
}
public static void main(String args[]) {
rightWhaleTest();
// rightWhaleTest();
clickDLTest();
}
}

View File

@ -6,6 +6,7 @@ import org.apache.commons.io.FilenameUtils;
import org.jamdev.jdl4pam.genericmodel.GenericModel;
import org.jamdev.jdl4pam.transforms.DLTransform;
import org.jamdev.jdl4pam.transforms.FreqTransform;
import org.jamdev.jpamutils.JamArr;
import PamModel.PamModel;
import PamModel.PamModel.PluginClassloader;
@ -42,10 +43,12 @@ public class GenericModelWorker extends DLModelWorker<StandardPrediction> {
//run a model if it is waveform info.
float[][] waveStack = new float[transformedDataStack.length][];
for (int i=0; i<waveStack.length; i++) {
// waveStack[i] = PamArrayUtils.double2Float(JamArr.product(PamArrayUtils.float2Double(transformedDataStack[i][0]), 0.99));
waveStack[i] = transformedDataStack[i][0];
}
//System.out.println("RUN GENERIC MODEL WAVE: " + waveStack.length + " " + waveStack[0].length + " " + waveStack[0][0]);
// System.out.println("RUN GENERIC MODEL WAVE: " + waveStack.length + " " + waveStack[0].length + " " + waveStack[0][0]);
// PamArrayUtils.printArray(waveStack[0]);
results = getModel().runModel(waveStack);
}
// System.out.println("GENERIC MODEL RESULTS: " + (results== null ? null : results.length));

View File

@ -3,12 +3,14 @@ package rawDeepLearningClassifier.layoutFX;
import java.util.ArrayList;
import org.controlsfx.control.PopOver;
import org.controlsfx.control.ToggleSwitch;
import PamController.PamGUIManager;
import PamController.SettingsPane;
import PamDetection.RawDataUnit;
import PamView.dialog.warn.WarnOnce;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamRawDataBlock;
import PamguardMVC.dataSelector.NullDataSelectorCreator;
import clickDetector.ClickDetection;
import clipgenerator.ClipDataUnit;
@ -116,6 +118,10 @@ public class DLSettingsPane extends SettingsPane<RawDLParams>{
private DLModelSelectPane modelSelectPane;
private PamToggleSwitch segEnableSwitch;
private PamGridPane segmenterGridPane;
public DLSettingsPane(DLControl dlControl){
@ -178,11 +184,26 @@ public class DLSettingsPane extends SettingsPane<RawDLParams>{
vBox.getChildren().add(createDataSelectorPane());
// the segmentation params
Label label = new Label("Segmentation");
PamGuiManagerFX.titleFont2style(label);
// the segmentation parameters
Label segLabel = new Label("Segmentation");
PamGuiManagerFX.titleFont2style(segLabel);
vBox.getChildren().add(label);
segEnableSwitch = new PamToggleSwitch("Enable");
segEnableSwitch.selectedProperty().addListener((obsVal, oldVal, newVal)->{
enableControls();
});
segEnableSwitch.setVisible(false); //set visible by default
segEnableSwitch.setAlignment(Pos.CENTER_RIGHT);
//segmentation can have an option to disable for certain input datablocks
PamBorderPane segmenterPane = new PamBorderPane();
segmenterPane.setLeft(segLabel);
segmenterPane.setRight(segEnableSwitch);
//add to the main pane
vBox.getChildren().add(segmenterPane);
windowLength = new PamSpinner<Integer>(0, Integer.MAX_VALUE, 10, 10000);
windowLength.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
@ -211,7 +232,7 @@ public class DLSettingsPane extends SettingsPane<RawDLParams>{
hopLength.getValueFactory().setValue(Math.round(windowLength.getValue()/2));
});
PamGridPane segmenterGridPane = new PamGridPane();
segmenterGridPane = new PamGridPane();
segmenterGridPane.setHgap(5);
ColumnConstraints col1 = new ColumnConstraints();
@ -244,35 +265,16 @@ public class DLSettingsPane extends SettingsPane<RawDLParams>{
vBox.getChildren().add(label2);
/**
* Pane which allows users to select a model type.
*/
//Pane which allows users to select a model from a file, link or default model.
modelSelectPane = new DLModelSelectPane(this);
// //add the possible deep learning models.
// dlModelBox= new ComboBox<String>();
// for (int i=0; i<dlControl.getDLModels().size(); i++) {
// dlModelBox.getItems().add(dlControl.getDLModels().get(i).getName());
// }
// dlModelBox.prefWidthProperty().bind(vBox.widthProperty());
//
// dlModelBox.setOnAction((action)->{
// setClassifierPane();
// if (mainPane!=null) {
// if (mainPane.getScene().getWindow() instanceof Stage) {
// Stage stage = (Stage) mainPane.getScene().getWindow();
// stage.sizeToScene();
// }
// }
// //this.dlControl.getAnnotationType().getSymbolModifier(symbolChooser).
// });
//
// vBox.getChildren().add(dlModelBox);
//create pane which shows the classifier settings
classifierPane = new PamBorderPane();
vBox.getChildren().addAll(modelSelectPane, classifierPane);
//bump this in case no settings
segEnableSwitch.setSelected(true);
vBox.getChildren().addAll(modelSelectPane, classifierPane);
return vBox;
}
@ -354,6 +356,20 @@ public class DLSettingsPane extends SettingsPane<RawDLParams>{
}
dataSelectorButton.setDisable(!dataSelectorCheckBox.isSelected());
boolean segEnable = true; //should we enable segmenter controls
if (sourcePane.getSource() instanceof PamRawDataBlock) {
//if a raw data block then we always enable segmentation no matter what
segEnable=true;
segEnableSwitch.setVisible(false);
}
else {
segEnable = segEnableSwitch.isSelected();
segEnableSwitch.setVisible(true);
}
segmenterGridPane.setDisable(!segEnable);
infoLabel.setDisable(!segEnable);
}
@ -471,6 +487,8 @@ public class DLSettingsPane extends SettingsPane<RawDLParams>{
currParams.modelURI = this.modelSelectPane.currentSelectedFile;
currParams.enableSegmentation = segEnableSwitch.isSelected();
return currParams;
}
@ -555,10 +573,12 @@ public class DLSettingsPane extends SettingsPane<RawDLParams>{
setClassifierPane();
enableControls();
setSegInfoLabel();
segEnableSwitch.setSelected(currParams.enableSegmentation);
enableControls();
// //set up the model and the custom pane if necessary.
this.modelSelectPane.loadNewModel(currParams.modelURI);
//this.modelSelectPane.updatePathLabel();

View File

@ -66,6 +66,10 @@ public class DataTransformPaneFactory {
settingsPane = new FilterTransformPane(dlTransfrom);
settingsPane.setParams(dlTransfrom);
break;
case PEAK_TRIM:
settingsPane = new PeakTrimTransformPane(dlTransfrom);
settingsPane.setParams(dlTransfrom);
break;
case SPEC2DB:
// settingsPane = new LabelTransfromPane(dlTransfrom, DLTransformType.SPEC2DB.toString());
// settingsPane.setPadding(new Insets(0,0,0,20));

View File

@ -0,0 +1,115 @@
package rawDeepLearningClassifier.layoutFX.dlTransfroms;
import org.jamdev.jdl4pam.transforms.DLTransform;
import org.jamdev.jdl4pam.transforms.SimpleTransform;
import org.jamdev.jpamutils.wavFiles.AudioData;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.Spinner;
import javafx.scene.control.TitledPane;
import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.utilityPanes.SimpleFilterPaneFX;
/**
* Pane for a peak search trim transform.
*
* @author Jamie Macaulay
*
*/
public class PeakTrimTransformPane extends DLTransformPane {
/**
* The transform associated with the settings pane.
*/
private DLTransform simpleTransfrom;
/**
* Controls for changing peak search settings.
*/
private SimpleFilterPaneFX filterPane;
/**
* Choice box for changing the type of peak search algorithm
*/
private ComboBox<String> peakSelectionBox;
/**
* Spinner for changing the target length
*/
private Spinner<Integer> targetLenSpinner;
public PeakTrimTransformPane(DLTransform dlTransfrom) {
super();
this.simpleTransfrom= dlTransfrom;
this.setCenter(createFilterPane());
// this.setStyle("-fx-background-color:orangered;");
}
private Node createFilterPane() {
peakSelectionBox = new ComboBox<String>();
peakSelectionBox.getItems().add(AudioData.PEAK_MAX, "Max. Peak");
peakSelectionBox.valueProperty().addListener((obsVal, oldVal, newVal)->{
this.notifySettingsListeners();
});
//spinner for changing filter order.
targetLenSpinner = new Spinner<Integer>(1,50,4,1);
targetLenSpinner.valueProperty().addListener((obsVal, oldVal, newVal)->{
this.notifySettingsListeners();
});
targetLenSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
PamHBox filterTypeHolder = new PamHBox();
filterTypeHolder.setSpacing(5);
filterTypeHolder.setAlignment(Pos.CENTER_LEFT);
filterTypeHolder.getChildren().addAll(peakSelectionBox, new Label("Target length"), targetLenSpinner);
TitledPane titledPane = new TitledPane(simpleTransfrom.getDLTransformType().toString(), filterTypeHolder);
// PamBorderPane borderPane = new PamBorderPane();
// borderPane.setTop(new Label(simpleTransfrom.getDLTransformType().toString()));
// borderPane.setCenter(hBox);
titledPane.setExpanded(false);
return titledPane;
}
@Override
public DLTransform getDLTransform() {
return this.getParams(simpleTransfrom) ;
}
@Override
public DLTransform getParams(DLTransform dlTransform) {
// System.out.println("GET PARAMS: FILTER");
SimpleTransform simpleTransform = (SimpleTransform) dlTransform;
simpleTransform.setParams(new Number[]{targetLenSpinner.getValue(), peakSelectionBox.getSelectionModel().getSelectedIndex()});
return simpleTransform;
}
@Override
public void setParams(DLTransform dlTransform) {
// System.out.println("SET PARAMS: FILTER");
SimpleTransform simpleTransform = (SimpleTransform) dlTransform;
//get the selection model.
peakSelectionBox.getSelectionModel().select(simpleTransform.getParams()[1].intValue());
targetLenSpinner.getValueFactory().setValue(simpleTransform.getParams()[0].intValue());
}
}

View File

@ -115,6 +115,15 @@ public class GroupedRawData extends PamDataUnit implements PamDetection, Cloneab
return rawData;
}
/**
* Set the raw data grouped by channel.
* @param the raw acoustic data to set
*/
public void setRawData(double[][] rawData) {
this.rawData=rawData;
}
/**
* Get the current pointer for rawData.
* @return the data pointer per channel.

View File

@ -6,7 +6,6 @@ import java.util.Arrays;
import PamController.PamController;
import PamDetection.RawDataUnit;
import PamUtils.PamArrayUtils;
import PamUtils.PamUtils;
import PamView.GroupedSourceParameters;
import PamView.PamDetectionOverlayGraphics;
@ -486,8 +485,19 @@ public class SegmenterProcess extends PamProcess {
//pass the raw click data to the segmenter
for (int i=0;i<chans.length; i++) {
newRawData(pamDataUnit,
rawDataChunk[i], chans[i], true);
if (dlControl.getDLParams().enableSegmentation) {
//segment the data unit into different chunks.
newRawData(pamDataUnit,
rawDataChunk[i], chans[i], dlControl.getDLParams().rawSampleSize, dlControl.getDLParams().sampleHop, true);
}
else {
// //send the whole data chunk to the deep learning unit
newRawData(pamDataUnit,
rawDataChunk[i], chans[i], rawDataChunk[i].length, rawDataChunk[i].length, true);
// currentRawChunks[i] = new GroupedRawData(pamDataUnit.getTimeMilliseconds(), getSourceParams().getGroupChannels(i),
// pamDataUnit.getStartSample(), rawDataChunk[i].length, rawDataChunk[i].length);
}
//the way that the newRawdata works is it waits for the next chunk and copies all relevant bits
//from previous chunks into segments. This is fine for continuous data but means that chunks of data
@ -512,7 +522,7 @@ public class SegmenterProcess extends PamProcess {
* @param iChan - the channel that is being segmented
*/
public void newRawData(PamDataUnit unit, double[] rawDataChunk, int iChan) {
newRawData(unit, rawDataChunk, iChan, false);
newRawData(unit, rawDataChunk, iChan, dlControl.getDLParams().rawSampleSize ,dlControl.getDLParams().sampleHop , false);
}
/**
@ -523,15 +533,17 @@ public class SegmenterProcess extends PamProcess {
*
* @param unit - the data unit which contains relevant metadata on time
* etc.
* @param rawDataChunk - the sound chunk to segment extracted from the data
* @param rawDataChunk - the sound chunk extracted from the data
* unit.
* @param iChan - the channel that is being segmented
* @param rawSampleSize - the segment size in samples i.e. the size of the segmenting window.
* @param rawSampleHop - the segment hop in samples i.e. how far the window jumps for each segment.
* @param forceSave - make sure that all data is passed into the buffers and
* do not wait for the next data unit. This is used to make
* sure that discrete chunks have their full number of
* segments saved.
*/
public synchronized void newRawData(PamDataUnit unit, double[] rawDataChunk, int iChan, boolean forcesave) {
public synchronized void newRawData(PamDataUnit unit, double[] rawDataChunk, int iChan, int rawSampleSize, int rawSampleHop, boolean forcesave) {
long timeMilliseconds = unit.getTimeMilliseconds();
long startSampleTime = unit.getStartSample();
@ -555,7 +567,7 @@ public class SegmenterProcess extends PamProcess {
if (currentRawChunks[i]==null) {
//create a new data unit - should only be called once after initial start.
currentRawChunks[i] = new GroupedRawData(timeMilliseconds, getSourceParams().getGroupChannels(i),
startSampleTime, dlControl.getDLParams().rawSampleSize, dlControl.getDLParams().rawSampleSize);
startSampleTime, rawSampleSize, rawSampleSize);
currentRawChunks[i].setParentDataUnit(unit);;
}
@ -615,7 +627,7 @@ public class SegmenterProcess extends PamProcess {
//segments which do not include any last zero padded segmen- zeros can confuse deep learning models so it may be better to keep use
//this instead of zero padding end chunks.
int nChunks = (int) Math.ceil((overFlow)/(double) dlControl.getDLParams().sampleHop);
int nChunks = (int) Math.ceil((overFlow)/(double) rawSampleHop);
nChunks = Math.max(nChunks, 1); //cannot be less than one (if forceSave is used then can be zero if no overflow)
nextRawChunks[i]=new GroupedRawData[nChunks];
@ -638,19 +650,19 @@ public class SegmenterProcess extends PamProcess {
//go from current raw chunks tim millis to try and minimise compounding time errors.
// long timeMillis = (long) (currentRawChunks[i].getTimeMilliseconds() + j*(1000.*(dlControl.getDLParams().sampleHop)/this.getSampleRate()));
long startSample = lastRawDataChunk.getStartSample() + dlControl.getDLParams().sampleHop;
long startSample = lastRawDataChunk.getStartSample() + rawSampleHop;
long timeMillis = this.absSamplesToMilliseconds(startSample);
nextRawChunks[i][j] = new GroupedRawData(timeMillis, getSourceParams().getGroupChannels(i),
startSample, dlControl.getDLParams().rawSampleSize, dlControl.getDLParams().rawSampleSize);
startSample, rawSampleSize, rawSampleSize);
nextRawChunks[i][j].setParentDataUnit(unit);
}
//add the hop from the current grouped raw data unit to the new grouped raw data unit
// System.out.println("Pointer to copy from: " + (currentRawChunks[i].rawData[groupChan].length - dlControl.getDLParams().sampleHop ));
int overFlow2 = nextRawChunks[i][j].copyRawData(lastRawDataChunk.rawData[groupChan], lastRawDataChunk.rawData[groupChan].length - getBackSmapleHop() ,
getBackSmapleHop() , groupChan);
int overFlow2 = nextRawChunks[i][j].copyRawData(lastRawDataChunk.rawData[groupChan], lastRawDataChunk.rawData[groupChan].length - getBackSmapleHop(rawSampleSize, rawSampleHop) ,
getBackSmapleHop(rawSampleSize, rawSampleHop) , groupChan);
// System.arraycopy(currentRawChunks[i].rawData[groupChan], currentRawChunks[i].rawData[groupChan].length - dlControl.getDLParams().sampleHop,
// nextRawChunks[i].rawData[groupChan], 0, dlControl.getDLParams().sampleHop);
@ -724,12 +736,13 @@ public class SegmenterProcess extends PamProcess {
//add some extra metadata to the chunks
packageSegmenterDataUnit(currentRawChunks[i]);
//System.out.println("Segmenter process: Save current segments to datablock: " + currentRawChunks[i].getParentDataUnit().getUID());
System.out.println("Segmenter process: Save current segments to datablock: " + currentRawChunks[i].getParentDataUnit().getUID() + " " + i + currentRawChunks[i].getRawData()[0][0]);
//send the raw data unit off to be classified!
this.segmenterDataBlock.addPamData(currentRawChunks[i]);
if (nextRawChunks[i]!=null) {
int n = nextRawChunks[i].length-1;
@ -761,8 +774,9 @@ public class SegmenterProcess extends PamProcess {
}
private int getBackSmapleHop() {
return dlControl.getDLParams().rawSampleSize - dlControl.getDLParams().sampleHop;
private int getBackSmapleHop(int segSize, int segHop) {
return segSize-segHop;
// return dlControl.getDLParams().rawSampleSize - dlControl.getDLParams().sampleHop;
}
// /***TODO - hand small windows***/

View File

@ -0,0 +1,156 @@
package test.rawDeepLearningClassifier;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import org.jamdev.jdl4pam.transforms.DLTransformsFactory;
import org.jamdev.jdl4pam.transforms.DLTransfromParams;
import org.jamdev.jdl4pam.transforms.SimpleTransformParams;
import org.jamdev.jpamutils.wavFiles.AudioData;
import org.jamdev.jdl4pam.transforms.DLTransform.DLTransformType;
import org.junit.jupiter.api.Test;
import PamUtils.PamArrayUtils;
import rawDeepLearningClassifier.dlClassification.genericModel.GenericModelParams;
import rawDeepLearningClassifier.dlClassification.genericModel.GenericModelWorker;
import rawDeepLearningClassifier.dlClassification.genericModel.StandardPrediction;
import rawDeepLearningClassifier.segmenter.GroupedRawData;
import us.hebi.matlab.mat.format.Mat5;
import us.hebi.matlab.mat.format.Mat5File;
import us.hebi.matlab.mat.types.Matrix;
import us.hebi.matlab.mat.types.Struct;
public class ClickDLTest {
@Test
public void clickDLTest() {
float SAMPLE_RATE = 500000;
//relative paths to the resource folders.
System.out.println("*****Click classification Deep Learning C*****");
//relative paths to the resource folders.
String relModelPath = "./src/test/resources/rawDeepLearningClassifier/Generic/risso_click/uniform_model/saved_model.pb";
String clicksPath = "./src/test/resources/rawDeepLearningClassifier/Generic/risso_click/clicks.mat";
Path path = Paths.get(relModelPath);
GenericModelWorker genericModelWorker = new GenericModelWorker();
GenericModelParams genericModelParams = new GenericModelParams();
genericModelParams.modelPath = path.toAbsolutePath().normalize().toString();
//create the transforms.
ArrayList<DLTransfromParams> dlTransformParamsArr = new ArrayList<DLTransfromParams>();
//waveform transforms.
dlTransformParamsArr.add(new SimpleTransformParams(DLTransformType.DECIMATE_SCIPY, 248000.));
dlTransformParamsArr.add(new SimpleTransformParams(DLTransformType.PEAK_TRIM, 128, 1));
dlTransformParamsArr.add(new SimpleTransformParams(DLTransformType.NORMALISE_WAV, 0., 1, AudioData.ZSCORE));
genericModelParams.dlTransfromParams = dlTransformParamsArr;
genericModelParams.dlTransfroms = DLTransformsFactory.makeDLTransforms((ArrayList<DLTransfromParams>)genericModelParams.dlTransfromParams);
//create the clicks.
path = Paths.get(clicksPath);
ArrayList<PredGroupedRawData> clicks = importClicks(path.toAbsolutePath().normalize().toString(), SAMPLE_RATE);
//prep the model
genericModelWorker.prepModel(genericModelParams, null);
System.out.println("Model has loaded");
ArrayList<GroupedRawData> groupedData = new ArrayList<GroupedRawData>();
for (int i=0; i<1; i++) {
float prediction = (float) clicks.get(i).getPrediction()[0];
groupedData.add(clicks.get(i)); //TODO for loop
//System.out.println("Waveform input: " + groupedData.get(i).getRawData().length + " " + groupedData.get(i).getRawData()[0].length);
ArrayList<StandardPrediction> genericPrediction = genericModelWorker.runModel(groupedData,SAMPLE_RATE, 0);
float[] output = genericPrediction.get(i).getPrediction();
System.out.println(String.format("Click %d Predicted output: %.2f true output: %.2f passed: %b", clicks.get(i).getUID(),
output[0], prediction, output[0]>prediction*0.9 && output[0]<prediction*1.1));
}
}
/**
* Import a bunch of clicks from a .mat file
*/
public static ArrayList<PredGroupedRawData> importClicks(String filePath, float sR) {
try {
Mat5File mfr = Mat5.readFromFile(filePath);
// //get array of a name "my_array" from file
Struct mlArrayRetrived = mfr.getStruct( "clickpreds" );
int numClicks= mlArrayRetrived.getNumCols();
ArrayList<PredGroupedRawData> clicks = new ArrayList<PredGroupedRawData>(numClicks);
PredGroupedRawData clickData;
for (int i=0; i<numClicks; i++) {
Matrix clickWav= mlArrayRetrived.get("wave", i);
double[][] clickwaveform= PamArrayUtils.matrix2array(clickWav);
clickwaveform = PamArrayUtils.transposeMatrix(clickwaveform);
//System.out.println("click: " + click[0].length + " num: " + numClicks);
Matrix clickUID= mlArrayRetrived.get("UID", i);
Matrix clickmillis= mlArrayRetrived.get("millis", i);
Matrix channelMap= mlArrayRetrived.get("channelMap", i);
Matrix startSample= mlArrayRetrived.get("startSample", i);
Matrix sampleDuration= mlArrayRetrived.get("sampleDuration", i);
Matrix pred= mlArrayRetrived.get("pred", i);
clickData = new PredGroupedRawData(clickmillis.getLong(0), channelMap.getInt(0), startSample.getLong(0), sampleDuration.getLong(0), sampleDuration.getInt(0));
clickData.setUID(clickUID.getLong(0));
clickData.setRawData(clickwaveform);
clickData.setPrediction(new double[] {pred.getDouble(0), pred.getDouble(1)});
clicks.add(clickData);
}
return clicks;
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
public static class PredGroupedRawData extends GroupedRawData {
private double[] prediction;
public double[] getPrediction() {
return prediction;
}
public void setPrediction(double[] prediction) {
this.prediction = prediction;
}
public PredGroupedRawData(long timeMilliseconds, int channelBitmap, long startSample, long duration, int samplesize) {
super(timeMilliseconds, channelBitmap, startSample, duration, samplesize);
}
}
}

View File

@ -218,8 +218,7 @@ public class DelphinIDTest {
//the values for the whistle detector.
double[][] pamguardWhistleImage = whistleScatter2Image(whistleValues);
System.out.println("Size python: " + compressedWhistleImage.length + " x " + compressedWhistleImage[0].length);
//System.out.println("Size python: " + compressedWhistleImage.length + " x " + compressedWhistleImage[0].length);
float[][][] input = new float[1][][];
input[0] = JamArr.doubleToFloat(compressedWhistleImage);
@ -255,7 +254,6 @@ public class DelphinIDTest {
System.out.println("DelphinID mode test end");
}

View File

@ -5,8 +5,8 @@ import org.junit.jupiter.api.Test;
public class PamZipDLClassifierTest {
/**
* Test the koogu classifier and tests are working properly. This tests loading the koogu model and also using
* functions in KooguWorker.
* Test the koogu classifier and tests are working properly for a PAMGuard zip model - i.e. this is a very similar model to Koogu but zipped with a .zip
* filename instead of .kgu.
*/
@Test
public void zipClassifierTest() {
@ -21,4 +21,7 @@ public class PamZipDLClassifierTest {
KooguDLClassifierTest.runKooguClassifier( relModelPath, relWavPath, relMatPath);
}
}

View File

@ -0,0 +1,9 @@
{\rtf1\ansi\ansicpg1252\cocoartf2761
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 Menlo-Regular;}
{\colortbl;\red255\green255\blue255;\red0\green0\blue0;\red255\green255\blue255;}
{\*\expandedcolortbl;;\cssrgb\c0\c0\c0;\cssrgb\c100000\c100000\c99985\c0;}
\paperw11900\paperh16840\margl1440\margr1440\vieww11220\viewh8100\viewkind0
\deftab720
\pard\pardeftab720\partightenfactor0
\f0\fs24 \cf2 \cb3 clickwave.wav is a Rissos dolphin click with a prediction of 0.8221 for channel 0 and 0.9631 for channel 1. }

File diff suppressed because one or more lines are too long

View File

@ -1,23 +1,10 @@
package wavFiles;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import javax.swing.JOptionPane;
//import org.kc7bfi.jflac.util.ByteData;
import org.jflac.util.ByteData;
import clickDetector.WindowsFile;
import java.io.ByteArrayInputStream;
import java.util.Arrays;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
public class WavFile {