mirror of
https://github.com/PAMGuard/PAMGuard.git
synced 2024-11-21 14:42:27 +00:00
Merge branch 'main' of https://github.com/macster110/PAMGuard into macster110-main
This commit is contained in:
commit
3dfe44d383
@ -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>
|
||||
|
@ -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
|
||||
|
2
README.files/colorschememapping.xml
Normal file
2
README.files/colorschememapping.xml
Normal 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
BIN
README.files/themedata.thmx
Normal file
Binary file not shown.
@ -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 {
|
||||
|
||||
@ -639,6 +639,9 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
|
||||
fileInputParameters.bitDepth = audioFormat.getSampleSizeInBits();
|
||||
|
||||
loadByteConverter(audioFormat);
|
||||
|
||||
// System.out.println("FileInputSystem - prepareInputFile done");
|
||||
|
||||
|
||||
} catch (UnsupportedAudioFileException ex) {
|
||||
ex.printStackTrace();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -172,7 +172,7 @@ public class ReprocessManager {
|
||||
choiceSummary.addChoice(ReprocessStoreChoice.STARTNORMAL);
|
||||
return choiceSummary;
|
||||
}
|
||||
|
||||
|
||||
choiceSummary.addChoice(ReprocessStoreChoice.STARTNORMAL);
|
||||
|
||||
ArrayList<PamControlledUnit> outputStores = PamController.getInstance().findControlledUnits(DataOutputStore.class, true);
|
||||
|
@ -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;
|
||||
|
@ -712,6 +712,34 @@ public class PamArrayUtils {
|
||||
// return normArr;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -1264,6 +1292,7 @@ public class PamArrayUtils {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
0
src/Resources/css/.Rhistory
Normal file
0
src/Resources/css/.Rhistory
Normal 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 |
BIN
src/Resources/screenshots/Click_detector_screenshot.png
Normal file
BIN
src/Resources/screenshots/Click_detector_screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 882 KiB |
BIN
src/Resources/screenshots/Datamap_screenshot.png
Normal file
BIN
src/Resources/screenshots/Datamap_screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 MiB |
@ -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
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
101
src/dataMap/layoutFX/DataMapScrollBar.java
Normal file
101
src/dataMap/layoutFX/DataMapScrollBar.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
489
src/dataMap/layoutFX/DataMapSettingsPane.java
Normal file
489
src/dataMap/layoutFX/DataMapSettingsPane.java
Normal 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
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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
|
||||
@ -949,6 +991,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);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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,25 +22,26 @@ 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.
|
||||
*/
|
||||
private DataMapControl dataMapControl;
|
||||
|
||||
|
||||
/**
|
||||
* Reference to the DataMapPaneFX.
|
||||
*/
|
||||
@ -49,19 +51,19 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
* The scroll pane everything sits in
|
||||
*/
|
||||
private PamScrollPane mainScrollPane;
|
||||
|
||||
|
||||
/**
|
||||
* List of panes- each shows an individual data stream.
|
||||
*/
|
||||
private ArrayList<DataStreamPaneFX> dataStreamPanels = new ArrayList<DataStreamPaneFX>();
|
||||
|
||||
|
||||
/**
|
||||
* Split pane whihc holds different graphs.
|
||||
*/
|
||||
private PamVBox dataPanePanes;
|
||||
|
||||
private ArrayList<OfflineDataStore> offlineDataStores;
|
||||
|
||||
|
||||
/**
|
||||
* Time stamp in millis of start of datamap display
|
||||
*/
|
||||
@ -71,24 +73,19 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
* Time stamp in millis of end of datamap display
|
||||
*/
|
||||
private long screenEndMillis = -1;
|
||||
|
||||
|
||||
private double screenSeconds;
|
||||
|
||||
/**
|
||||
* Scroll bar for time (horizontal)
|
||||
*/
|
||||
private ScrollBar timeScrollBar;
|
||||
private DataMapScrollBar 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;
|
||||
|
||||
/**
|
||||
* Shows the start time of the scroll position
|
||||
*/
|
||||
private Label scrollEndLabel;
|
||||
|
||||
|
||||
/**
|
||||
* Shows the end 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());
|
||||
}
|
||||
|
||||
@ -119,13 +115,14 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
* @return the scrolling pane.
|
||||
*/
|
||||
private Node createScrollingDataPane() {
|
||||
|
||||
|
||||
holder=new PamBorderPane();
|
||||
|
||||
//create the main scroll pane
|
||||
mainScrollPane = new PamScrollPane();
|
||||
|
||||
|
||||
mainScrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
|
||||
|
||||
|
||||
//create the split pane to hold the graphs.
|
||||
dataPanePanes=new PamVBox();
|
||||
//dataPanePanes.setOrientation(Orientation.VERTICAL);
|
||||
@ -134,48 +131,54 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
|
||||
mainScrollPane.setContent(dataPanePanes);
|
||||
//we have a custom scroll bar for horizontal stuff.
|
||||
// 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);
|
||||
// mainScrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
|
||||
|
||||
// ///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)->{
|
||||
notifyScrollChange(300);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
dateAxis = new PamDateAxis();
|
||||
dateAxis.setAutoRanging(false);
|
||||
dateAxis.setLabel("Time");
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Updates the scrollbar.
|
||||
@ -183,19 +186,19 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
public void updateScrollBar() {
|
||||
setupScrollBar();
|
||||
updateScrollBarText();
|
||||
|
||||
|
||||
calcStartEndMillis();
|
||||
updateScrollBarText();
|
||||
notifyScrollChange();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create the horizontal scroll bar for scrolling through time.
|
||||
* @return the horizontal scroll bar.
|
||||
*/
|
||||
private PamBorderPane createScrollBar(){
|
||||
PamBorderPane holder=new PamBorderPane();
|
||||
|
||||
|
||||
//create a pane to show start and end times
|
||||
PamBorderPane timeLabelPane=new PamBorderPane();
|
||||
scrollStartLabel=new Label();
|
||||
@ -206,32 +209,45 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
scrollEndLabel.setText(PamCalendar.formatDateTime(screenEndMillis));
|
||||
timeLabelPane.setPadding(new Insets(2, 10, 2, 10)); //bit of padding to look better
|
||||
|
||||
|
||||
|
||||
//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.getTextBox().setPrefColumnCount(15);
|
||||
timeScrollBar.getTextBox().setPrefWidth(100);
|
||||
|
||||
timeScrollBar.setPrefHeight(50);
|
||||
|
||||
timeScrollBar.setPrefHeight(20);
|
||||
|
||||
//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);
|
||||
|
||||
|
||||
return holder;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculate the start and millis based on scroll position and screen seconds.
|
||||
*/
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the text in the scroll bar. Shows the start and end time of the current screen.
|
||||
*/
|
||||
@ -248,14 +264,14 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
for (int i = 0; i < dataStreamPanels.size(); i++) {
|
||||
dataStreamPanels.get(i).scrollChanged();
|
||||
}
|
||||
settingsStrip.scrollChanged();
|
||||
|
||||
// settingsStrip.scrollChanged();
|
||||
|
||||
updateDateAxis();
|
||||
}
|
||||
|
||||
|
||||
Timeline timeline;
|
||||
long lastTime = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Notify all panels and the settings strip that the scroll bar moved - but have a timer to wait to not call too often.
|
||||
*/
|
||||
@ -273,11 +289,11 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
timeline.play();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
lastTime=currentTime;
|
||||
|
||||
|
||||
updateDateAxis();
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void 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,30 +310,30 @@ 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();
|
||||
|
||||
//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());
|
||||
}
|
||||
//clear the panes from list and split pane.
|
||||
dataStreamPanels.clear();
|
||||
dataPanePanes.getChildren().clear();
|
||||
|
||||
return 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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***
|
||||
* Get the number of panes which are expanded.
|
||||
@ -341,39 +357,50 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
createDataGraphs();
|
||||
setupScrollBar();
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -410,10 +437,14 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
public long getScreenEndMillis() {
|
||||
return screenEndMillis;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
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.);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -422,7 +453,7 @@ public class ScrollingDataPaneFX extends PamBorderPane {
|
||||
public double getScreenSeconds() {
|
||||
return screenSeconds;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a colour for the datastream.
|
||||
* @param dataSource
|
||||
@ -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();
|
||||
}
|
||||
this.notifyScrollChange();
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
else return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -79,6 +79,18 @@ public class TDGraphParametersFX implements Serializable, Cloneable, ManagedPara
|
||||
* Used only when saving as Color (javafx) is not serializable.
|
||||
*/
|
||||
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)
|
||||
|
@ -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;
|
||||
@ -1816,6 +1820,11 @@ public class TDGraphFX extends PamBorderPane {
|
||||
tdAxisSelPane.remakePane();
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
@ -255,6 +256,36 @@ public class RawClipDataInfo extends GenericDataPlotInfo {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
/* (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
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -925,6 +925,8 @@ public class Scrolling2DPlotDataFX {
|
||||
|
||||
//reset transform in case of other drawings on base canvas.
|
||||
if (orientation == Orientation.VERTICAL) g2d.setTransform(horzAffine);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
@ -276,7 +276,7 @@ public abstract class DDDataInfo<T extends PamDataUnit> {
|
||||
getCurrentDetectionPlot().setupAxis((PamDataUnit) pamDataUnit, this.getHardSampleRate(), projector);
|
||||
|
||||
getCurrentDetectionPlot().paintPlot((PamDataUnit) pamDataUnit, g, windowRect, projector, flag);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 (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);
|
||||
}
|
||||
//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();
|
||||
}
|
||||
|
||||
|
||||
currentDataInfo.drawData(dDPlotPane.getPlotCanvas().getGraphicsContext2D(),
|
||||
new Rectangle(0,0,dDPlotPane.getPlotCanvas().getWidth(),dDPlotPane.getPlotCanvas().getHeight()),
|
||||
this.detectionPlotProjector, newDataUnit);
|
||||
}
|
||||
|
||||
// //Debug.out.println("DetectionPlotDisplay DrawDataUnit: " +newDataUnit);
|
||||
// if (reDrawScroll) {
|
||||
// setupScrollBar(newDataUnit);
|
||||
// reDrawScroll=false;
|
||||
// }
|
||||
//
|
||||
//dDPlotPane.repaintAxis();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
*
|
||||
*/
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package export.layoutFX;
|
||||
package export;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
@ -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());
|
||||
|
@ -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.
|
||||
|
@ -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){
|
||||
|
@ -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;
|
||||
|
94
src/export/exporter_help.md
Normal file
94
src/export/exporter_help.md
Normal 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.
|
@ -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;
|
||||
|
BIN
src/export/resources/PAMGuard_exporter_dialog.png
Normal file
BIN
src/export/resources/PAMGuard_exporter_dialog.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 334 KiB |
BIN
src/export/resources/PAMGuard_exporter_dialog_annotated.png
Normal file
BIN
src/export/resources/PAMGuard_exporter_dialog_annotated.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 451 KiB |
BIN
src/export/resources/PAMGuard_exporter_dialog_annotated.pptx
Normal file
BIN
src/export/resources/PAMGuard_exporter_dialog_annotated.pptx
Normal file
Binary file not shown.
BIN
src/export/resources/PAMGuard_exporter_dialog_wav.png
Normal file
BIN
src/export/resources/PAMGuard_exporter_dialog_wav.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 348 KiB |
252
src/export/wavExport/WavDetExportManager.java
Normal file
252
src/export/wavExport/WavDetExportManager.java
Normal 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.
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
32
src/export/wavExport/WavExportOptions.java
Normal file
32
src/export/wavExport/WavExportOptions.java
Normal 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;
|
||||
|
||||
}
|
106
src/export/wavExport/WavOptionsPanel.java
Normal file
106
src/export/wavExport/WavOptionsPanel.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
@ -878,6 +886,17 @@ public class OLProcessDialog extends PamDialog {
|
||||
public void setNeedaNote(boolean isNeedaNote) {
|
||||
this.isNeedaNote = isNeedaNote;
|
||||
}
|
||||
|
||||
public JProgressBar getGlobalProgress() {
|
||||
return globalProgress;
|
||||
}
|
||||
|
||||
|
||||
public PamAlignmentPanel getTasksPanel() {
|
||||
return tasksPanel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
24
src/pamViewFX/PamLauncherFXApp.java
Normal file
24
src/pamViewFX/PamLauncherFXApp.java
Normal 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();
|
||||
}
|
||||
}
|
9
src/pamViewFX/PamLauncherFXAppLauncher.java
Normal file
9
src/pamViewFX/PamLauncherFXAppLauncher.java
Normal file
@ -0,0 +1,9 @@
|
||||
package pamViewFX;
|
||||
|
||||
public class PamLauncherFXAppLauncher {
|
||||
|
||||
public static void main(String[] args) {
|
||||
PamLauncherFXApp.main(args);
|
||||
}
|
||||
|
||||
}
|
106
src/pamViewFX/PamLauncherPane.java
Normal file
106
src/pamViewFX/PamLauncherPane.java
Normal 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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -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");
|
||||
@ -97,6 +104,7 @@ public class PamSettingsMenuPane extends PamVBox {
|
||||
if (PamController.getInstance().getGlobalMediumManager().getGlobalMediumParameters().currentMedium==SoundMedium.Water) return; //do nothing.
|
||||
PamController.getInstance().getGlobalMediumManager().setCurrentMedium(SoundMedium.Water);
|
||||
});
|
||||
|
||||
|
||||
ToggleButton toggleButton2 = new ToggleButton("Air");
|
||||
toggleButton2.setPrefWidth(60);
|
||||
@ -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();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,78 +258,6 @@ public class ScrollBarPane extends PamBorderPane {
|
||||
return canvas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the text field that allows to manually chage the visible amount amount property.
|
||||
*/
|
||||
private void createTextField(){
|
||||
//create the textbox
|
||||
textBox= new TextField();
|
||||
textBox.layoutXProperty().bind(rectangle.layoutXProperty().add(rectangle.widthProperty().divide(2)).subtract(textBox.widthProperty().divide(2)));
|
||||
textBox.layoutYProperty().bind(rectangle.heightProperty().divide(2).subtract(textBox.heightProperty().divide(2)));
|
||||
textBox.setOnAction((action)-> {
|
||||
double millis=this.getTextBoxValue(textBox.getText());
|
||||
if (millis<=0 || millis>(this.maxValueProperty.get()-this.minValueProperty.get())){
|
||||
textBoxErrorFlash(textBox);
|
||||
this.setTextBoxValue(visibleAmountProperty.get());
|
||||
}
|
||||
else{
|
||||
visibleAmountProperty.setValue(millis);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
ft = new FadeTransition(Duration.millis(3000), textBox);
|
||||
|
||||
textBox.getStyleClass().add("text_field_trans");
|
||||
textBox.setPrefWidth(70);
|
||||
|
||||
//the rectangle itself.
|
||||
textBox.setOnMousePressed((event)->{
|
||||
rectanglePressed(event);
|
||||
});
|
||||
|
||||
|
||||
textBox.setOnMouseReleased((event)->{
|
||||
rectangleReleased(event);
|
||||
|
||||
});
|
||||
|
||||
//text box needs to to drag the rectangle so there isn't a drag 'dead space'
|
||||
textBox.setOnMouseDragged((event)->{
|
||||
rectangleDragged(event);
|
||||
});
|
||||
|
||||
textBox.setOnMouseEntered((event)->{
|
||||
setTextBoxVisible(true);
|
||||
});
|
||||
|
||||
textBox.setOnMouseExited((event)->{
|
||||
//only set invisible if not in rectangle. This is for fast mouse movements were the exist of the rectangle may not be called
|
||||
if (!rectangle.contains(rectangle.sceneToLocal(event.getSceneX(), event.getSceneY()))){
|
||||
setTextBoxVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
setTextBoxVisible(false);
|
||||
|
||||
//show and hide text box so keeps the scroll bar beautiful
|
||||
rectangle.setOnMouseEntered((event)->{
|
||||
setTextBoxVisible(true);
|
||||
});
|
||||
|
||||
rectangle.setOnMouseExited((event)->{
|
||||
setTextBoxVisible(false);
|
||||
});
|
||||
|
||||
//make sure the text box chnages with visible amount.,
|
||||
this.visibleAmountProperty.addListener((obsVal, newVal, oldVal)->{
|
||||
setTextBoxValue(visibleAmountProperty.get());
|
||||
});
|
||||
|
||||
|
||||
setTextBoxValue(visibleAmountProperty.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the rectangle which can be dragged to change time but also dragged to change the width of time
|
||||
* shown.
|
||||
@ -382,6 +312,7 @@ public class ScrollBarPane extends PamBorderPane {
|
||||
rightDrag.getChildren().add(rightdragLine);
|
||||
rectangle.getChildren().add(rightDrag);
|
||||
|
||||
rectangle.setCursor(Cursor.OPEN_HAND); //Change cursor to hand
|
||||
|
||||
//now set behaviours
|
||||
leftDrag.setOnMousePressed((event)->{
|
||||
@ -436,15 +367,17 @@ public class ScrollBarPane extends PamBorderPane {
|
||||
});
|
||||
|
||||
//now set behaviours
|
||||
rightDrag.setOnMousePressed((event)->{
|
||||
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);
|
||||
});
|
||||
|
||||
@ -496,6 +429,7 @@ public class ScrollBarPane extends PamBorderPane {
|
||||
rectangle.setOnMouseDragged((event)->{
|
||||
rectangleDragged(event);
|
||||
});
|
||||
|
||||
|
||||
return rectangle;
|
||||
}
|
||||
@ -543,6 +477,87 @@ public class ScrollBarPane extends PamBorderPane {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the text field that allows to manually chage the visible amount amount property.
|
||||
*/
|
||||
private void createTextField(){
|
||||
//create the textbox
|
||||
textBox= new TextField();
|
||||
textBox.layoutXProperty().bind(rectangle.layoutXProperty().add(rectangle.widthProperty().divide(2)).subtract(textBox.widthProperty().divide(2)));
|
||||
textBox.layoutYProperty().bind(rectangle.heightProperty().divide(2).subtract(textBox.heightProperty().divide(2)));
|
||||
textBox.setOnAction((action)-> {
|
||||
double millis=this.getTextBoxValue(textBox.getText());
|
||||
if (millis<=0 || millis>(this.maxValueProperty.get()-this.minValueProperty.get())){
|
||||
textBoxErrorFlash(textBox);
|
||||
this.setTextBoxValue(visibleAmountProperty.get());
|
||||
}
|
||||
else{
|
||||
visibleAmountProperty.setValue(millis);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
ft = new FadeTransition(Duration.millis(3000), textBox);
|
||||
|
||||
textBox.getStyleClass().add("text_field_trans");
|
||||
textBox.setPrefWidth(70);
|
||||
|
||||
//the rectangle itself.
|
||||
textBox.setOnMousePressed((event)->{
|
||||
rectanglePressed(event);
|
||||
});
|
||||
|
||||
|
||||
textBox.setOnMouseReleased((event)->{
|
||||
rectangleReleased(event);
|
||||
|
||||
});
|
||||
|
||||
//text box needs to to drag the rectangle so there isn't a drag 'dead space'
|
||||
textBox.setOnMouseDragged((event)->{
|
||||
rectangleDragged(event);
|
||||
});
|
||||
|
||||
textBox.setOnMouseEntered((event)->{
|
||||
setTextBoxVisible(true);
|
||||
});
|
||||
|
||||
textBox.setOnMouseExited((event)->{
|
||||
//only set invisible if not in rectangle. This is for fast mouse movements were the exist of the rectangle may not be called
|
||||
if (!rectangle.contains(rectangle.sceneToLocal(event.getSceneX(), event.getSceneY()))){
|
||||
setTextBoxVisible(false);
|
||||
}
|
||||
});
|
||||
|
||||
setTextBoxVisible(false);
|
||||
|
||||
//show and hide text box so keeps the scroll bar beautiful
|
||||
rectangle.setOnMouseEntered((event)->{
|
||||
setTextBoxVisible(true);
|
||||
});
|
||||
|
||||
rectangle.setOnMouseExited((event)->{
|
||||
setTextBoxVisible(false);
|
||||
});
|
||||
|
||||
//make sure the text box chnages with visible amount.,
|
||||
this.visibleAmountProperty.addListener((obsVal, newVal, oldVal)->{
|
||||
setTextBoxValue(visibleAmountProperty.get());
|
||||
});
|
||||
|
||||
|
||||
setTextBoxValue(visibleAmountProperty.get());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the text box that shows the visible amount
|
||||
* @return - the text field
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -37,6 +37,13 @@ public class RawDLParams implements Serializable, Cloneable {
|
||||
* Holds channel and grouping information
|
||||
*/
|
||||
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
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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() {
|
||||
@ -22,7 +31,7 @@ public class GenericModelTest {
|
||||
|
||||
//the audio file to test
|
||||
String wavFilePath = "/Users/au671271/Google Drive/PAMGuard_dev/Deep_Learning/Right_whales_DG/SouthernRightWhale001-v1/sar98_trk3_8000.wav";
|
||||
|
||||
|
||||
wavFilePath = "/Users/au671271/Google Drive/PAMGuard_dev/Deep_Learning/Right_whales_DG/SouthernRightWhale001-v1/wav_files_timestamp/PAM_20010327_113000.wav";
|
||||
wavFilePath = "/Users/au671271/git/PAMGuard_resources/deep_learning/right_whale_tutorial/wav/wav_files_timestamp/PAM_20010327_113200.wav";
|
||||
|
||||
@ -74,11 +83,11 @@ public class GenericModelTest {
|
||||
for (int i=0; i<10; i++) {
|
||||
//long time1 = System.currentTimeMillis();
|
||||
data = new float[][][] {DLUtils.toFloatArray(((FreqTransform) transform).getSpecTransfrom().getTransformedData())};
|
||||
|
||||
|
||||
//data = new float[][][] { DLUtils.makeDummySpectrogram(40, 40)};
|
||||
|
||||
|
||||
//System.out.println("data len: " + data.length + " " + data[0].length + " " + data[0][0].length);
|
||||
|
||||
|
||||
output = genericModel.runModel(data);
|
||||
//long time2 = System.currentTimeMillis();
|
||||
//System.out.println("Time to run model: " + (time2-time1) + " ms");
|
||||
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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] = transformedDataStack[i][0];
|
||||
// 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));
|
||||
@ -117,7 +120,7 @@ public class GenericModelWorker extends DLModelWorker<StandardPrediction> {
|
||||
|
||||
((GenericModelParams) genericParams).defaultShape = longArr2Long(genericModel.getInputShape().getShape());
|
||||
((GenericModelParams) genericParams).defualtOuput = longArr2Long(genericModel.getOutShape().getShape());
|
||||
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -380,11 +396,11 @@ public class DLSettingsPane extends SettingsPane<RawDLParams>{
|
||||
* Set the classifier pane.
|
||||
*/
|
||||
protected void setClassifierPane() {
|
||||
|
||||
|
||||
|
||||
|
||||
//set the classifier Pane.class
|
||||
if (modelSelectPane.currentClassifierModel!=null && modelSelectPane.currentClassifierModel.getModelUI()!=null) {
|
||||
|
||||
|
||||
classifierPane.setCenter(modelSelectPane.currentClassifierModel.getModelUI().getSettingsPane().getContentNode());
|
||||
|
||||
if (modelSelectPane.currentClassifierModel!=null) {
|
||||
@ -456,7 +472,7 @@ public class DLSettingsPane extends SettingsPane<RawDLParams>{
|
||||
// }
|
||||
|
||||
currParams.useDataSelector = dataSelectorCheckBox.isSelected();
|
||||
|
||||
|
||||
if (dlControl.getDataSelector()!=null) {
|
||||
dlControl.getDataSelector().getDialogPaneFX().getParams(true);
|
||||
}
|
||||
@ -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();
|
||||
|
@ -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));
|
||||
|
@ -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());
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -114,6 +114,15 @@ public class GroupedRawData extends PamDataUnit implements PamDetection, Cloneab
|
||||
public double[][] getRawData() {
|
||||
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.
|
||||
|
@ -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,9 +485,20 @@ 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
|
||||
//don't get their last hop...
|
||||
@ -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,11 +736,12 @@ 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***/
|
||||
|
156
src/test/rawDeepLearningClassifier/ClickDLTest.java
Normal file
156
src/test/rawDeepLearningClassifier/ClickDLTest.java
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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");
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -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() {
|
||||
@ -20,5 +20,8 @@ public class PamZipDLClassifierTest {
|
||||
//metadata says it should be used with Koogu classifier.
|
||||
KooguDLClassifierTest.runKooguClassifier( relModelPath, relWavPath, relMatPath);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -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. }
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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 {
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user