extends PamObservable {
}
/**
- * Instruction from the viewer scroll manager to load new data.
+ * Instruction from the viewer scroll manager to load new data. This just calls through
+ * to loadViewerData(OfflineDataLoadInfo ...) so this should not be overridden. Override
+ * the other function instead.
*
* @param dataStart data start time in millis
* @param dataEnd data end time in millis.
diff --git a/src/PamguardMVC/RawDataTransforms.java b/src/PamguardMVC/RawDataTransforms.java
index ed371072..c0684730 100644
--- a/src/PamguardMVC/RawDataTransforms.java
+++ b/src/PamguardMVC/RawDataTransforms.java
@@ -99,35 +99,11 @@ public class RawDataTransforms {
*/
private int shortestFFTLength;
- /**
- * Object for synchronization. Get thread lock if this isn't the same as
- * the object holding the data.
- */
- private Object synchObject;
-
- /**
- * Raw Data Transforms for a RawDataHolder using the rawDataHolder as the synchronization
- * object.
- * @param rawDataHolder RawDataHolder object (e.g. a click)
- */
public RawDataTransforms(@SuppressWarnings("rawtypes") PamDataUnit rawDataHolder) {
- this(rawDataHolder, rawDataHolder);
- }
-
- /**
- * Raw Data Transforms for a RawDataHolder.
- * @param rawDataHolder RawDataHolder object (e.g. a click)
- * @param synchObject synchronization object, which is most likely the RawDataHolder object.
- */
- public RawDataTransforms(@SuppressWarnings("rawtypes") PamDataUnit rawDataHolder, Object synchObject) {
this.rawData=(RawDataHolder) rawDataHolder;
this.dataUnit = rawDataHolder;
- this.synchObject = synchObject;
- if (this.synchObject == null) {
- this.synchObject = this;
- }
}
@@ -167,25 +143,23 @@ public class RawDataTransforms {
* @param fftLength
* @return Power spectrum
*/
- public double[] getPowerSpectrum(int channel, int minBin, int maxBin, int fftLength) {
- synchronized (synchObject) {
- if (minBin==0 && maxBin>=this.getWaveData(0).length-1) {
- return getPowerSpectrum(channel, fftLength);
- }
- if (fftLength == 0) {
- fftLength = getCurrentSpectrumLength();
- }
-
- double[] waveformTrim = new double[maxBin-minBin];
-
- // System.out.println("minBin: " + minBin + " maxBin: " + maxBin + " raw waveform: " + this.getWaveData(channel).length);
-
- System.arraycopy(this.getWaveData(channel), minBin, waveformTrim, 0, Math.min(this.getWaveData(channel).length-minBin-1, waveformTrim.length));
-
- ComplexArray cData = getComplexSpectrumHann(waveformTrim, fftLength);
-
- return cData.magsq();
+ public synchronized double[] getPowerSpectrum(int channel, int minBin, int maxBin, int fftLength) {
+ if (minBin==0 && maxBin>=this.getWaveData(0).length-1) {
+ return getPowerSpectrum(channel, fftLength);
+ }
+ if (fftLength == 0) {
+ fftLength = getCurrentSpectrumLength();
}
+
+ double[] waveformTrim = new double[maxBin-minBin];
+
+ //System.out.println("minBin: " + minBin + " maxBin: " + maxBin + " raw waveform: " + this.getWaveData(channel).length);
+
+ System.arraycopy(this.getWaveData(channel), minBin, waveformTrim, 0, Math.min(this.getWaveData(channel).length-minBin-1, waveformTrim.length));
+
+ ComplexArray cData = getComplexSpectrumHann(waveformTrim, fftLength);
+
+ return cData.magsq();
}
/**
@@ -196,31 +170,29 @@ public class RawDataTransforms {
* @param fftLength
* @return Power spectrum
*/
- public double[] getPowerSpectrum(int channel, int fftLength) {
- synchronized (synchObject) {
- if (powerSpectra == null) {
- powerSpectra = new double[PamUtils.getNumChannels(dataUnit.getChannelBitmap())][];
- }
- if (fftLength == 0) {
- fftLength = getCurrentSpectrumLength();
- }
-
- if (powerSpectra[channel] == null
- || powerSpectra[channel].length != fftLength / 2) {
- ComplexArray cData = getComplexSpectrumHann(channel, fftLength);
- currentSpecLen = fftLength;
- powerSpectra[channel] = cData.magsq();
- if (powerSpectra==null){
- System.err.println("DLDetection: could not calculate power spectra");
- return null;
-
- }
- if (powerSpectra[channel].length != fftLength/2) {
- powerSpectra[channel] = Arrays.copyOf(powerSpectra[channel], fftLength/2);
- }
- }
- return powerSpectra[channel];
+ public synchronized double[] getPowerSpectrum(int channel, int fftLength) {
+ if (powerSpectra == null) {
+ powerSpectra = new double[PamUtils.getNumChannels(dataUnit.getChannelBitmap())][];
}
+ if (fftLength == 0) {
+ fftLength = getCurrentSpectrumLength();
+ }
+
+ if (powerSpectra[channel] == null
+ || powerSpectra[channel].length != fftLength / 2) {
+ ComplexArray cData = getComplexSpectrumHann(channel, fftLength);
+ currentSpecLen = fftLength;
+ powerSpectra[channel] = cData.magsq();
+ if (powerSpectra==null){
+ System.err.println("DLDetection: could not calculate power spectra");
+ return null;
+
+ }
+ if (powerSpectra[channel].length != fftLength/2) {
+ powerSpectra[channel] = Arrays.copyOf(powerSpectra[channel], fftLength/2);
+ }
+ }
+ return powerSpectra[channel];
}
@@ -230,27 +202,25 @@ public class RawDataTransforms {
* @param fftLength
* @return Sum of power spectra
*/
- public double[] getTotalPowerSpectrum(int fftLength) {
- synchronized (synchObject) {
- if (fftLength == 0) {
- fftLength = getCurrentSpectrumLength();
- }
- if (fftLength == 0) {
- fftLength = PamUtils.getMinFftLength(getSampleDuration());
- }
- double[] ps;
- if (totalPowerSpectrum == null
- || totalPowerSpectrum.length != fftLength / 2) {
- totalPowerSpectrum = new double[fftLength / 2];
- for (int c = 0; c < PamUtils.getNumChannels(this.dataUnit.getChannelBitmap()); c++) {
- ps = getPowerSpectrum(c, fftLength);
- for (int i = 0; i < fftLength / 2; i++) {
- totalPowerSpectrum[i] += ps[i];
- }
+ public synchronized double[] getTotalPowerSpectrum(int fftLength) {
+ if (fftLength == 0) {
+ fftLength = getCurrentSpectrumLength();
+ }
+ if (fftLength == 0) {
+ fftLength = PamUtils.getMinFftLength(getSampleDuration());
+ }
+ double[] ps;
+ if (totalPowerSpectrum == null
+ || totalPowerSpectrum.length != fftLength / 2) {
+ totalPowerSpectrum = new double[fftLength / 2];
+ for (int c = 0; c < PamUtils.getNumChannels(this.dataUnit.getChannelBitmap()); c++) {
+ ps = getPowerSpectrum(c, fftLength);
+ for (int i = 0; i < fftLength / 2; i++) {
+ totalPowerSpectrum[i] += ps[i];
}
}
- return totalPowerSpectrum;
}
+ return totalPowerSpectrum;
}
@@ -265,17 +235,15 @@ public class RawDataTransforms {
* @param fftLength - the FFT length to use.
* @return the complex spectrum - the comnplex spectrum of the wave data from the specified channel.
*/
- public ComplexArray getComplexSpectrumHann(int channel, int fftLength) {
- synchronized (synchObject) {
- complexSpectrum = new ComplexArray[PamUtils.getNumChannels(dataUnit.getChannelBitmap())];
- if (complexSpectrum[channel] == null
- || complexSpectrum.length != fftLength / 2) {
+ public synchronized ComplexArray getComplexSpectrumHann(int channel, int fftLength) {
+ complexSpectrum = new ComplexArray[PamUtils.getNumChannels(dataUnit.getChannelBitmap())];
+ if (complexSpectrum[channel] == null
+ || complexSpectrum.length != fftLength / 2) {
- complexSpectrum[channel] = getComplexSpectrumHann(rawData.getWaveData()[channel], fftLength);
- currentSpecLen = fftLength;
- }
- return complexSpectrum[channel];
+ complexSpectrum[channel] = getComplexSpectrumHann(rawData.getWaveData()[channel], fftLength);
+ currentSpecLen = fftLength;
}
+ return complexSpectrum[channel];
}
@@ -314,12 +282,10 @@ public class RawDataTransforms {
* @return the spectrogram length.
*/
private int getCurrentSpectrumLength() {
- synchronized (synchObject) {
- if (currentSpecLen<=0) {
- currentSpecLen = PamUtils.getMinFftLength(dataUnit.getSampleDuration());
- }
- return currentSpecLen;
+ if (currentSpecLen<=0) {
+ currentSpecLen = PamUtils.getMinFftLength(dataUnit.getSampleDuration());
}
+ return currentSpecLen;
}
@@ -405,31 +371,29 @@ public class RawDataTransforms {
* @param fftLength
* @return the complex spectrum
*/
- public ComplexArray getComplexSpectrum(int channel, int fftLength) {
- synchronized (synchObject) {
- double[] paddedRawData;
- double[] rawData;
- int i, mn;
+ public synchronized ComplexArray getComplexSpectrum(int channel, int fftLength) {
+ double[] paddedRawData;
+ double[] rawData;
+ int i, mn;
- if (complexSpectrum == null) {
- complexSpectrum = new ComplexArray[getNChan()];
- }
- if (complexSpectrum[channel] == null
- || complexSpectrum.length != fftLength / 2) {
- paddedRawData = new double[fftLength];
- rawData = getWaveData(channel);
- //double[] rotData = getRotationCorrection(channel);
- mn = Math.min(fftLength, getSampleDuration().intValue());
- for (i = 0; i < mn; i++) {
- paddedRawData[i] = rawData[i];//-rotData[i];
- }
- for (i = mn; i < fftLength; i++) {
- paddedRawData[i] = 0;
- }
- complexSpectrum[channel] = fastFFT.rfft(paddedRawData, fftLength);
- }
- return complexSpectrum[channel];
+ if (complexSpectrum == null) {
+ complexSpectrum = new ComplexArray[getNChan()];
}
+ if (complexSpectrum[channel] == null
+ || complexSpectrum.length != fftLength / 2) {
+ paddedRawData = new double[fftLength];
+ rawData = getWaveData(channel);
+ //double[] rotData = getRotationCorrection(channel);
+ mn = Math.min(fftLength, getSampleDuration().intValue());
+ for (i = 0; i < mn; i++) {
+ paddedRawData[i] = rawData[i];//-rotData[i];
+ }
+ for (i = mn; i < fftLength; i++) {
+ paddedRawData[i] = 0;
+ }
+ complexSpectrum[channel] = fastFFT.rfft(paddedRawData, fftLength);
+ }
+ return complexSpectrum[channel];
}
@@ -438,16 +402,14 @@ public class RawDataTransforms {
* @param iChan channel index
* @return analytic waveform
*/
- public double[] getAnalyticWaveform(int iChan) {
- synchronized (synchObject) {
- if (analyticWaveform == null) {
- analyticWaveform = new double[getNChan()][];
- }
- // if (analyticWaveform[iChan] == null) {
- analyticWaveform[iChan] = hilbert.getHilbert(getWaveData(iChan));
- // }
- return analyticWaveform[iChan];
+ public synchronized double[] getAnalyticWaveform(int iChan) {
+ if (analyticWaveform == null) {
+ analyticWaveform = new double[getNChan()][];
}
+ // if (analyticWaveform[iChan] == null) {
+ analyticWaveform[iChan] = hilbert.getHilbert(getWaveData(iChan));
+ // }
+ return analyticWaveform[iChan];
}
/**
@@ -459,14 +421,12 @@ public class RawDataTransforms {
* @param fftFilterParams fft filter parameters.
* @return analystic waveform.
*/
- public double[] getAnalyticWaveform(int iChan, boolean filtered, FFTFilterParams fftFilterParams) {
- synchronized (synchObject) {
- if (filtered == false || fftFilterParams == null) {
- return getAnalyticWaveform(iChan);
- }
- else {
- return getFilteredAnalyticWaveform(fftFilterParams, iChan);
- }
+ public synchronized double[] getAnalyticWaveform(int iChan, boolean filtered, FFTFilterParams fftFilterParams) {
+ if (filtered == false || fftFilterParams == null) {
+ return getAnalyticWaveform(iChan);
+ }
+ else {
+ return getFilteredAnalyticWaveform(fftFilterParams, iChan);
}
}
@@ -477,8 +437,7 @@ public class RawDataTransforms {
* @param iChan channel number
* @return envelope of the filtered data.
*/
- public double[] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams, int iChan) {
- synchronized (synchObject) {
+ public synchronized double[] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams, int iChan) {
if (analyticWaveform == null) {
analyticWaveform = new double[getNChan()][];
}
@@ -487,7 +446,6 @@ public class RawDataTransforms {
getHilbert(getFilteredWaveData(fftFilterParams, iChan));
// }
return analyticWaveform[iChan];
- }
}
/**
@@ -497,21 +455,19 @@ public class RawDataTransforms {
* @return analystic waveforms
*/
public double[][] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams) {
- synchronized (synchObject) { // new
- if (analyticWaveform == null) {
- analyticWaveform = new double[getNChan()][];
- }
- for (int iChan = 0; iChan < getNChan(); iChan++) {
- if (fftFilterParams != null) {
- analyticWaveform[iChan] = hilbert.
- getHilbert(getFilteredWaveData(fftFilterParams, iChan));
- }
- else {
- analyticWaveform[iChan] = getAnalyticWaveform(iChan);
- }
- }
- return analyticWaveform;
+ if (analyticWaveform == null) {
+ analyticWaveform = new double[getNChan()][];
}
+ for (int iChan = 0; iChan < getNChan(); iChan++) {
+ if (fftFilterParams != null) {
+ analyticWaveform[iChan] = hilbert.
+ getHilbert(getFilteredWaveData(fftFilterParams, iChan));
+ }
+ else {
+ analyticWaveform[iChan] = getAnalyticWaveform(iChan);
+ }
+ }
+ return analyticWaveform;
}
@@ -522,7 +478,7 @@ public class RawDataTransforms {
* @param channelIndex channel index
* @return filtered waveform data
*/
- public double[] getFilteredWaveData(FFTFilterParams filterParams, int channelIndex) {
+ public synchronized double[] getFilteredWaveData(FFTFilterParams filterParams, int channelIndex) {
filteredWaveData = getFilteredWaveData(filterParams);
return filteredWaveData[channelIndex];
}
@@ -533,14 +489,12 @@ public class RawDataTransforms {
* @param filterParams filter parameters
* @return array of filtered data
*/
- public double[][] getFilteredWaveData(FFTFilterParams filterParams) {
- synchronized (synchObject) {
+ public synchronized double[][] getFilteredWaveData(FFTFilterParams filterParams) {
//System.out.println("Make filterred wave data!: " + (filterParams != oldFFTFilterParams));
if (filteredWaveData == null || filterParams != oldFFTFilterParams) {
filteredWaveData = makeFilteredWaveData(filterParams);
}
return filteredWaveData;
- }
}
private double[][] makeFilteredWaveData(FFTFilterParams filterParams) {
@@ -579,15 +533,13 @@ public class RawDataTransforms {
* @return FFT filter object.
*/
public FFTFilter getFFTFilter(FFTFilterParams fftFilterParams) {
- synchronized (synchObject) {
- if (fftFilter == null) {
- fftFilter = new FFTFilter(fftFilterParams, this.dataUnit.getParentDataBlock().getSampleRate());
- }
- else {
- fftFilter.setParams(fftFilterParams, this.dataUnit.getParentDataBlock().getSampleRate());
- }
- return fftFilter;
+ if (fftFilter == null) {
+ fftFilter = new FFTFilter(fftFilterParams, this.dataUnit.getParentDataBlock().getSampleRate());
}
+ else {
+ fftFilter.setParams(fftFilterParams, this.dataUnit.getParentDataBlock().getSampleRate());
+ }
+ return fftFilter;
}
@@ -654,9 +606,7 @@ public class RawDataTransforms {
* @return
*/
private int getNChan() {
- synchronized (synchObject) { // new
- return this.rawData.getWaveData().length;
- }
+ return this.rawData.getWaveData().length;
}
/**
@@ -689,11 +639,9 @@ public class RawDataTransforms {
* Free eup some memory by deleting the filtered wave data, power spectra and analytic waveform.
*/
public void freeMemory() {
- synchronized (synchObject) {
- filteredWaveData = null;
- powerSpectra = null;
- analyticWaveform = null;
- }
+ filteredWaveData = null;
+ powerSpectra = null;
+ analyticWaveform = null;
}
diff --git a/src/PamguardMVC/dataSelector/DataSelectorSettings.java b/src/PamguardMVC/dataSelector/DataSelectorSettings.java
index 273812d8..7d593f4d 100644
--- a/src/PamguardMVC/dataSelector/DataSelectorSettings.java
+++ b/src/PamguardMVC/dataSelector/DataSelectorSettings.java
@@ -32,7 +32,7 @@ public class DataSelectorSettings implements Serializable, ManagedParameters {
* @return Params or null if they don't exist.
*/
public DataSelectParams getParams(String name) {
- if (selectorParams == null) {
+ if (selectorParams == null || name == null) {
return null;
}
return selectorParams.get(name);
diff --git a/src/Resources/css/pamSettingsCSS.css b/src/Resources/css/pamSettingsCSS.css
index 605da31c..d635ea5b 100644
--- a/src/Resources/css/pamSettingsCSS.css
+++ b/src/Resources/css/pamSettingsCSS.css
@@ -35,8 +35,8 @@
-fx-font-color: -fx-text;
-fx-font-family: "Ubuntu";
- -fx-border-radius: 5 5 5 5;
- -fx-background-radius: 5 5 5 5;
+ -fx-border-radius: 5 5 5 5;
+ -fx-background-radius: 5 5 5 5;
-icons-color: -fx-icon_col;
}
@@ -615,7 +615,7 @@
-fx-background: -fx-darkbackground;
-fx-background-color: -fx-darkbackground;
-fx-border-radius: 0 0 0 0;
- -fx-padding: 7 0 7 0;
+ -fx-padding: 5 0 5 0;
-fx-border-color: transparent;
}
@@ -623,9 +623,9 @@
-fx-text-fill: white;
-fx-background-color: -fx-darkbackground;
-fx-border-color: -fx-border_col;
- -fx-background-radius: 6 6 0 0;
- -fx-border-radius: 6 6 0 0;
- -fx-padding: 7 0 7 0;
+ -fx-background-radius: 5 5 0 0;
+ -fx-border-radius: 5 5 0 0;
+ -fx-padding: 5 0 5 0;
}
.spinner .increment-arrow {
@@ -635,16 +635,16 @@
.spinner .increment-arrow-button:hover {
-fx-background-color: -fx-highlight;
-fx-border-color: -fx-highlight_border;
- -fx-background-radius: 6 6 0 0;
- -fx-border-radius: 6 6 0 0;
+ -fx-background-radius: 5 5 0 0;
+ -fx-border-radius: 5 5 0 0;
}
.spinner .decrement-arrow-button {
-fx-text-fill: white;
-fx-background-color: -fx-darkbackground;
-fx-border-color: -fx-border_col;
- -fx-background-radius: 0 0 6 6;
- -fx-border-radius: 0 0 6 6
+ -fx-background-radius: 0 0 5 5;
+ -fx-border-radius: 0 0 5 5
}
.spinner .decrement-arrow {
@@ -654,8 +654,8 @@
.spinner .decrement-arrow-button:hover {
-fx-background-color: -fx-highlight;
-fx-border-color: -fx-highlight_border;
- -fx-background-radius: 0 0 6 6;
- -fx-border-radius: 0 0 6 6;
+ -fx-background-radius: 0 0 5 5;
+ -fx-border-radius: 0 0 5 5;
}
/*Arrows are horizontal either side of text box*/
@@ -663,7 +663,7 @@
-fx-text-fill: white;
-fx-background-color: -fx-darkbackground;
-fx-border-color: -fx-border_col;
- -fx-border-radius: 0 6 6 0
+ -fx-border-radius: 0 5 5 0
}
@@ -671,22 +671,22 @@
-fx-text-fill: white;
-fx-background-color: -fx-darkbackground;
-fx-border-color: -fx-border_col;
- -fx-border-radius: 6 0 0 6
+ -fx-border-radius: 5 0 0 5
}
.spinner.split-arrows-horizontal .increment-arrow-button:hover {
-fx-background-color: -fx-highlight;
-fx-border-color: -fx-highlight_border;
- -fx-background-radius: 0 6 6 0;
- -fx-border-radius: 0 6 6 0;
+ -fx-background-radius: 0 5 5 0;
+ -fx-border-radius: 0 5 5 0;
}
.spinner.split-arrows-horizontal .decrement-arrow-button:hover {
-fx-background-color: -fx-highlight;
-fx-border-color: -fx-highlight_border;
- -fx-background-radius: 6 0 0 6;
- -fx-border-radius: 6 0 0 6;
+ -fx-background-radius: 5 0 0 5;
+ -fx-border-radius: 5 0 0 5;
}
.spinner.split-arrows-horizontal .text-field {
diff --git a/src/clickDetector/ClickBTDisplay.java b/src/clickDetector/ClickBTDisplay.java
index 1f797971..a8556bdd 100644
--- a/src/clickDetector/ClickBTDisplay.java
+++ b/src/clickDetector/ClickBTDisplay.java
@@ -1572,6 +1572,9 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
}
private double clickAngleToY(ClickDetection click) {
AbstractLocalisation loc = click.getLocalisation();
+// if (click.getUID() == 110006089) {
+// System.out.println("Click 110006089 angle " + click.getAngle());
+// }
if (loc == null) return 0;
double angle = 0;
GpsData oll;
diff --git a/src/clickDetector/ClickBinaryDataSource.java b/src/clickDetector/ClickBinaryDataSource.java
index 62e64810..b9294cbd 100644
--- a/src/clickDetector/ClickBinaryDataSource.java
+++ b/src/clickDetector/ClickBinaryDataSource.java
@@ -210,8 +210,8 @@ public class ClickBinaryDataSource extends BinaryDataSource {
// long uid = binaryObjectData.getDataUnitBaseData().getUID();
// System.out.printf("Loading click with UID %d at %s\n", uid,
// PamCalendar.formatDateTime(binaryObjectData.getTimeMilliseconds()));
-// if (uid == lastUID) {
-// System.out.println("Click repeat UID: " + lastUID);
+// if (uid == 110006089) {
+// System.out.println("Click UID: " + 110006089);
// }
// else {
// lastUID = binaryObjectData.getDataUnitBaseData().getUID();
diff --git a/src/clickDetector/ClickDetection.java b/src/clickDetector/ClickDetection.java
index a0528738..330fdca9 100644
--- a/src/clickDetector/ClickDetection.java
+++ b/src/clickDetector/ClickDetection.java
@@ -1328,6 +1328,8 @@ public class ClickDetection extends PamDataUnit implem
/**
* Returns the angle in degrees for compatibilty with older version of click detector
+ * This is really bad to use for anything apart from two element arrays and it would be
+ * sensible to remove the function entirely.
* @return angle of the click detection in degrees
*/
public double getAngle() {
diff --git a/src/clickDetector/dataSelector/ClickSelectPaneFX.java b/src/clickDetector/dataSelector/ClickSelectPaneFX.java
index 743fa946..0c1d661d 100644
--- a/src/clickDetector/dataSelector/ClickSelectPaneFX.java
+++ b/src/clickDetector/dataSelector/ClickSelectPaneFX.java
@@ -217,7 +217,8 @@ public class ClickSelectPaneFX extends DynamicSettingsPane {
void setParams() {
ClickAlarmParameters clickAlarmParameters = clickDataSelector.getClickAlarmParameters();
speciesSelect.getChildren().clear();
-
+
+
//species pane setup
species = null;
weights = null;
@@ -350,6 +351,7 @@ public class ClickSelectPaneFX extends DynamicSettingsPane {
}
boolean getParams() {
+
ClickAlarmParameters clickAlarmParameters = clickDataSelector.getClickAlarmParameters().clone();
clickAlarmParameters.useEchoes = useEchoes.isSelected();
@@ -397,6 +399,7 @@ public class ClickSelectPaneFX extends DynamicSettingsPane {
// btDisplayParameters.showANDEvents = andEvents.isSelected();
// btDisplayParameters.showEventsOnly = onlyEvents.isSelected();
+
clickDataSelector.setClickAlarmParameters(clickAlarmParameters);
return true;
}
diff --git a/src/clickTrainDetector/classification/CTClassifierManager.java b/src/clickTrainDetector/classification/CTClassifierManager.java
index 1c0af211..2389d8ab 100644
--- a/src/clickTrainDetector/classification/CTClassifierManager.java
+++ b/src/clickTrainDetector/classification/CTClassifierManager.java
@@ -1,9 +1,8 @@
package clickTrainDetector.classification;
import java.util.ArrayList;
+import java.util.UUID;
-import PamUtils.PamCalendar;
-import PamguardMVC.debug.Debug;
import clickTrainDetector.CTDataUnit;
import clickTrainDetector.ClickTrainControl;
import clickTrainDetector.classification.bearingClassifier.BearingClassification;
@@ -158,10 +157,10 @@ public class CTClassifierManager {
//first check the pre-classifier
Chi2CTClassification classification = this.preClassifier.classifyClickTrain(ctDataUnit);
- System.out.println("Pre classifier: " + PamCalendar.formatDateTime(ctDataUnit.getTimeMilliseconds()) + " N. " + ctDataUnit.getSubDetectionsCount() + "UID first: " + ctDataUnit.getSubDetection(0).getUID() );
+ //System.out.println("Pre classifier: " + PamCalendar.formatDateTime(ctDataUnit.getTimeMilliseconds()) + " N. " + ctDataUnit.getSubDetectionsCount() + "UID first: " + ctDataUnit.getSubDetection(0).getUID() );
if (classification.getSpeciesID()==CTClassifier.NOSPECIES) {
- System.out.println("No SPECIES: chi^2" + ctDataUnit.getCTChi2());
+ //System.out.println("No SPECIES: chi^2" + ctDataUnit.getCTChi2());
ctDataUnit.setJunkTrain(true);
//no need to do any more classification- the click train has been flagged for deletion.
ctDataUnit.clearClassifiers();
@@ -189,17 +188,17 @@ public class CTClassifierManager {
ctDataUnit.clearClassifiers();
ctDataUnit.setClassificationIndex(-1);
- System.out.println("Classify species: Num classifier " + this.cTClassifiers.size());
+ //System.out.println("Classify species: Num classifier " + this.cTClassifiers.size());
for (int i=0; iCTClassifier.NOSPECIES && !hasBeenClssfd) {
- System.out.println("Set classiifcation index: " + i);
+ //System.out.println("Set classiifcation index: " + i);
ctDataUnit.setClassificationIndex(i); //set the classification index.
hasBeenClssfd = true;
}
@@ -238,12 +237,26 @@ public class CTClassifierManager {
System.err.println("CTCLassifier manager: the classifier is null");
continue;
}
+
+ if (ctParams[i].uniqueID ==null) {
+ //old versions may not have a unique ID so needs to be added.
+ ctParams[i].uniqueID = UUID.randomUUID().toString();
+ }
aClassifier.setParams(ctParams[i]);
cTClassifiers.add(aClassifier);
}
}
+ /**
+ * Get the pre-classifer. This is an intial very broad classifier that is used to determine
+ * whether a click train should be saved or dumped from memory.
+ * @return the pre-classifier.
+ */
+ public Chi2ThresholdClassifier getPreClassifier() {
+ return preClassifier;
+ }
+
diff --git a/src/clickTrainDetector/classification/CTClassifierParams.java b/src/clickTrainDetector/classification/CTClassifierParams.java
index 81af2483..2841b1ab 100644
--- a/src/clickTrainDetector/classification/CTClassifierParams.java
+++ b/src/clickTrainDetector/classification/CTClassifierParams.java
@@ -1,6 +1,7 @@
package clickTrainDetector.classification;
import java.io.Serializable;
+import java.util.UUID;
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
@@ -20,12 +21,23 @@ public class CTClassifierParams implements Cloneable, Serializable, ManagedParam
private static final long serialVersionUID = 1L;
+ public CTClassifierParams() {
+ this.uniqueID = UUID.randomUUID().toString();
+ }
+
+
/**
- * A very simple species flag to indicate what classifier was used. 0 means not classified.
+ * The name of the classifier.
*/
public String classifierName = "";
+ /**
+ * A unique ID for the classifier that never changes. This is important for accessing data selectors.
+ */
+ public String uniqueID;
+
+
/**
* A very simple species flag to indicate what classifier was used. 0 means not classified.
*/
diff --git a/src/clickTrainDetector/classification/bearingClassifier/BearingClassifierParams.java b/src/clickTrainDetector/classification/bearingClassifier/BearingClassifierParams.java
index 0bff0c6f..08031d6b 100644
--- a/src/clickTrainDetector/classification/bearingClassifier/BearingClassifierParams.java
+++ b/src/clickTrainDetector/classification/bearingClassifier/BearingClassifierParams.java
@@ -15,6 +15,7 @@ public class BearingClassifierParams extends CTClassifierParams implements Manag
public BearingClassifierParams(){
+ super();
type = CTClassifierType.BEARINGCLASSIFIER;
}
diff --git a/src/clickTrainDetector/classification/idiClassifier/IDIClassifierParams.java b/src/clickTrainDetector/classification/idiClassifier/IDIClassifierParams.java
index a2bca3cb..4862c3dc 100644
--- a/src/clickTrainDetector/classification/idiClassifier/IDIClassifierParams.java
+++ b/src/clickTrainDetector/classification/idiClassifier/IDIClassifierParams.java
@@ -4,9 +4,15 @@ import java.io.Serializable;
import PamModel.parametermanager.ManagedParameters;
import clickTrainDetector.classification.CTClassifierParams;
+import clickTrainDetector.classification.CTClassifierType;
public class IDIClassifierParams extends CTClassifierParams implements Serializable, Cloneable, ManagedParameters {
+ public IDIClassifierParams(){
+ super();
+ type = CTClassifierType.IDICLASSIFIER;
+ }
+
/**
*
*/
diff --git a/src/clickTrainDetector/classification/simplechi2classifier/Chi2CTClassification.java b/src/clickTrainDetector/classification/simplechi2classifier/Chi2CTClassification.java
index 22ef818e..c3c667a4 100644
--- a/src/clickTrainDetector/classification/simplechi2classifier/Chi2CTClassification.java
+++ b/src/clickTrainDetector/classification/simplechi2classifier/Chi2CTClassification.java
@@ -1,5 +1,7 @@
package clickTrainDetector.classification.simplechi2classifier;
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.dataSelector.DataSelector;
import clickTrainDetector.classification.CTClassification;
import clickTrainDetector.classification.CTClassifierType;
import clickTrainDetector.classification.ClassifierJSONLogging;
@@ -22,15 +24,14 @@ public class Chi2CTClassification implements CTClassification {
private int speciesCode = -1;
- private SimpleClassifierJSONLogging simpleClassifierJSONLogging;
+ private SimpleClassifierJSONLogging simpleClassifierJSONLogging;
-
public Chi2CTClassification(int speciesCode) {
this.speciesCode = speciesCode;
simpleClassifierJSONLogging=new SimpleClassifierJSONLogging();
}
-
+
/**
* Create the classification from a JSON string
@@ -62,5 +63,7 @@ public class Chi2CTClassification implements CTClassification {
public ClassifierJSONLogging getJSONLogging() {
return simpleClassifierJSONLogging;
}
+
+
}
diff --git a/src/clickTrainDetector/classification/simplechi2classifier/Chi2ThresholdClassifier.java b/src/clickTrainDetector/classification/simplechi2classifier/Chi2ThresholdClassifier.java
index 9577e5a9..20473840 100644
--- a/src/clickTrainDetector/classification/simplechi2classifier/Chi2ThresholdClassifier.java
+++ b/src/clickTrainDetector/classification/simplechi2classifier/Chi2ThresholdClassifier.java
@@ -1,6 +1,8 @@
package clickTrainDetector.classification.simplechi2classifier;
import PamUtils.PamCalendar;
+import PamguardMVC.PamDataBlock;
+import PamguardMVC.dataSelector.DataSelector;
import PamguardMVC.debug.Debug;
import clickTrainDetector.CTDataUnit;
import clickTrainDetector.ClickTrainControl;
@@ -32,10 +34,17 @@ public class Chi2ThresholdClassifier implements CTClassifier {
*/
private ClickTrainControl clickTrainControl;
+
+ /**
+ * Data selector for the chi2 threshold classifier.
+ */
+ private DataSelector dataSelector;
+
public Chi2ThresholdClassifier(ClickTrainControl clickTrainControl, int defaultSpeciesID) {
this.clickTrainControl=clickTrainControl;
clssfrParams.speciesFlag=defaultSpeciesID;
+ createDataSelector(clickTrainControl.getParentDataBlock());
}
@@ -65,8 +74,62 @@ public class Chi2ThresholdClassifier implements CTClassifier {
return new Chi2CTClassification(CTClassifier.NOSPECIES); //no classification
}
+ if (!isPercClicks(clickTrain)) {
+// Debug.out.println("Failed on chi2Threshold");
+ return new Chi2CTClassification(CTClassifier.NOSPECIES); //no classification
+ }
+
+
return new Chi2CTClassification(clssfrParams.speciesFlag);
}
+
+
+ /**
+ * Check the percentage of clicks which are correctly classified by the data selector.
+ * @param clickTrain - the click train
+ * @return true if the percentage critera is passed
+ *
+ */
+ private boolean isPercClicks(CTDataUnit clickTrain) {
+
+ //no point iterating through click if we do not need to.
+ if (clssfrParams.minPercentage==0) return true;
+
+ double count = 0;
+ for (int i=0; i0) {
+ count = count+1.;
+ }
+ }
+ if (count/clickTrain.getSubDetectionsCount()>=clssfrParams.minPercentage) {
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+
+
+ /**
+ * Get the data selector.
+ * @param source - the source data block
+ * @return the data selector.
+ */
+ public void createDataSelector(PamDataBlock> source) {
+ if (dataSelector==null || dataSelector.getPamDataBlock()!=source) {
+ //create the data selector
+ //System.out.println("Data selector: " + dataSelector);
+ if (source!=null) {
+ dataSelector=source.getDataSelectCreator().getDataSelector(clickTrainControl.getUnitName() + " " + clssfrParams.uniqueID
+ + "_X2_threshold_classifier", false, null);
+ //System.out.println("Data selector: " + dataSelector);
+ }
+ else {
+ dataSelector=null;
+ }
+ }
+ }
+
@Override
public String getName() {
@@ -122,7 +185,6 @@ public class Chi2ThresholdClassifier implements CTClassifier {
public void setParams(Chi2ThresholdParams clssfrParams) {
//System.out.println("HELLO CLASSIFIER PARAMS: " + clssfrParams.chi2Threahold );
this.clssfrParams=clssfrParams;
-
}
/**
@@ -145,4 +207,10 @@ public class Chi2ThresholdClassifier implements CTClassifier {
}
+ public DataSelector getDataSelector() {
+ createDataSelector(clickTrainControl.getParentDataBlock());
+ return dataSelector;
+ }
+
+
}
diff --git a/src/clickTrainDetector/classification/simplechi2classifier/Chi2ThresholdParams.java b/src/clickTrainDetector/classification/simplechi2classifier/Chi2ThresholdParams.java
index 83f4d6e5..a174a915 100644
--- a/src/clickTrainDetector/classification/simplechi2classifier/Chi2ThresholdParams.java
+++ b/src/clickTrainDetector/classification/simplechi2classifier/Chi2ThresholdParams.java
@@ -1,5 +1,8 @@
package clickTrainDetector.classification.simplechi2classifier;
+import java.io.Serializable;
+import java.util.UUID;
+
import PamModel.parametermanager.ManagedParameters;
import PamModel.parametermanager.PamParameterSet;
import clickTrainDetector.classification.CTClassifierParams;
@@ -12,9 +15,10 @@ import clickTrainDetector.classification.CTClassifierType;
* @author Jamie Macaulay
*
*/
-public class Chi2ThresholdParams extends CTClassifierParams implements ManagedParameters {
+public class Chi2ThresholdParams extends CTClassifierParams implements ManagedParameters, Serializable, Cloneable {
public Chi2ThresholdParams(){
+ super();
super.type=CTClassifierType.CHI2THRESHOLD;
}
@@ -25,7 +29,7 @@ public class Chi2ThresholdParams extends CTClassifierParams implements ManagedPa
/**
* The chi2 threshold to set. This is the chi2 value divided by the number of clicks in the train.
- * If zero then the classification always passes...A bit fo a hack for testing
+ * If zero then the classification always passes...A bit of a hack for testing
*/
public double chi2Threshold = 1500.;
@@ -33,7 +37,13 @@ public class Chi2ThresholdParams extends CTClassifierParams implements ManagedPa
* The minimum number of clicks.
*/
public int minClicks = 5;
-
+
+ /**
+ * The minimum %percentage which must the parent data selector of clicks/
+ *. values are 0-1.
+ */
+ public double minPercentage = 0;
+
/**
* The minimum time in seconds.
*/
diff --git a/src/clickTrainDetector/classification/standardClassifier/StandardClassifier.java b/src/clickTrainDetector/classification/standardClassifier/StandardClassifier.java
index f340d9d3..eef29887 100644
--- a/src/clickTrainDetector/classification/standardClassifier/StandardClassifier.java
+++ b/src/clickTrainDetector/classification/standardClassifier/StandardClassifier.java
@@ -130,7 +130,7 @@ public class StandardClassifier implements CTClassifier {
int speciesID = standardClssfrParams.speciesFlag;
- System.out.println("Standard Classificiation: " );
+ //System.out.println("Standard Classificiation: " );
//all classifiers have to pass.
CTClassification[] ctClassification = new CTClassification[classifiers.size()];
@@ -138,8 +138,8 @@ public class StandardClassifier implements CTClassifier {
ctClassification[i] = classifiers.get(i).classifyClickTrain(clickTrain);
- System.out.println("Standard Classificiation: " + i + " speciesID: " + ctClassification[i].getSpeciesID()
- + " sub species: "+ classifiers.get(i).getParams().speciesFlag + " standard species: " +speciesID + " use? : " + standardClssfrParams.enable[i]);
+// System.out.println("Standard Classificiation: " + i + " speciesID: " + ctClassification[i].getSpeciesID()
+// + " sub species: "+ classifiers.get(i).getParams().speciesFlag + " standard species: " +speciesID + " use? : " + standardClssfrParams.enable[i]);
if (standardClssfrParams.enable[i]) {
if (ctClassification[i].getSpeciesID() != SUB_CLASSIFIER_SPECIESID){
@@ -148,7 +148,7 @@ public class StandardClassifier implements CTClassifier {
}
}
- System.out.println("SPECIES ID: " + speciesID);
+ //System.out.println("SPECIES ID: " + speciesID);
//create the classification.
StandardClassification classification = new StandardClassification(ctClassification, speciesID);
diff --git a/src/clickTrainDetector/classification/standardClassifier/StandardClassifierParams.java b/src/clickTrainDetector/classification/standardClassifier/StandardClassifierParams.java
index a3d13e0e..25eb5775 100644
--- a/src/clickTrainDetector/classification/standardClassifier/StandardClassifierParams.java
+++ b/src/clickTrainDetector/classification/standardClassifier/StandardClassifierParams.java
@@ -1,5 +1,7 @@
package clickTrainDetector.classification.standardClassifier;
+import java.util.UUID;
+
import clickTrainDetector.classification.CTClassifierParams;
import clickTrainDetector.classification.CTClassifierType;
@@ -27,6 +29,7 @@ public class StandardClassifierParams extends CTClassifierParams {
public StandardClassifierParams(){
+ super();
///very important to set this or else the clasifier manager does not
//know which classifier to create.
type = CTClassifierType.STANDARDCLASSIFIER;
diff --git a/src/clickTrainDetector/classification/templateClassifier/TemplateClassifierParams.java b/src/clickTrainDetector/classification/templateClassifier/TemplateClassifierParams.java
index cd781ca7..e4d15845 100644
--- a/src/clickTrainDetector/classification/templateClassifier/TemplateClassifierParams.java
+++ b/src/clickTrainDetector/classification/templateClassifier/TemplateClassifierParams.java
@@ -22,6 +22,7 @@ public class TemplateClassifierParams extends CTClassifierParams implements Mana
private static final long serialVersionUID = 10L;
public TemplateClassifierParams(){
+ super();
super.type=CTClassifierType.TEMPLATECLASSIFIER;
// chi2ThresholdParams = new Chi2ThresholdParams();
// template = DefualtSpectrumTemplates.getTemplate(SpectrumTemplateType.BEAKED_WHALE);
diff --git a/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/AmplitudeChi2.java b/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/AmplitudeChi2.java
index 68f45902..cff7d705 100644
--- a/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/AmplitudeChi2.java
+++ b/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/AmplitudeChi2.java
@@ -39,7 +39,10 @@ public class AmplitudeChi2 extends SimpleChi2VarDelta {
@Override
public double getDiffValue(PamDataUnit pamDataUnit0, PamDataUnit pamDataUnit1) {
//System.out.println("DB: " + pamDataUnit0.getAmplitudeDB());
- return pamDataUnit0.getAmplitudeDB()-pamDataUnit1.getAmplitudeDB();
+ //made this abs so it can deal with increasing then decreasing click trains. i.e.
+ //the click trian is not penalised if it gradually increasing then starts to gradually decrease
+ //in amplitude.
+ return Math.abs(pamDataUnit0.getAmplitudeDB()-pamDataUnit1.getAmplitudeDB());
}
@Override
diff --git a/src/clickTrainDetector/dataselector/CTDataSelector.java b/src/clickTrainDetector/dataselector/CTDataSelector.java
index d607c87d..97e14554 100644
--- a/src/clickTrainDetector/dataselector/CTDataSelector.java
+++ b/src/clickTrainDetector/dataselector/CTDataSelector.java
@@ -1,9 +1,12 @@
package clickTrainDetector.dataselector;
+import java.util.Arrays;
+
import PamDetection.LocContents;
import PamguardMVC.PamDataUnit;
import PamguardMVC.dataSelector.DataSelectParams;
import PamguardMVC.dataSelector.DataSelector;
+import clickTrainDetector.CTDataUnit;
import clickTrainDetector.CTDetectionGroupDataUnit;
import clickTrainDetector.ClickTrainControl;
import clickTrainDetector.ClickTrainDataBlock;
@@ -43,6 +46,8 @@ public class CTDataSelector extends DataSelector {
private boolean allowScores;
+ private boolean[] useSpeciesList;
+
public CTDataSelector(ClickTrainControl clickTrainControl, ClickTrainDataBlock clickTrainDataBlock,
String selectorName, boolean allowScores) {
super(clickTrainDataBlock, selectorName, allowScores);
@@ -83,6 +88,7 @@ public class CTDataSelector extends DataSelector {
@Override
public DataSelectParams getParams() {
+ getDialogPanel().getParams(ctSelectParams);
return ctSelectParams;
}
@@ -99,6 +105,8 @@ public class CTDataSelector extends DataSelector {
CTDetectionGroupDataUnit ctDataUnit = (CTDetectionGroupDataUnit) pamDataUnit;
if (ctDataUnit.getSubDetectionsCount()(parentFrame, setPane, false);
}
- if (classificationTab!=null) settingsPane.setTab(classificationTab ? 2 : 0); //set the tab to the classification tab
+ if (classificationTab!=null && classificationTab) settingsPane.setTab(2); //set the tab to the classification tab
ClickTrainParams newParams = settingsDialog.showDialog(this.clickTrainControl.getClickTrainParams());
diff --git a/src/clickTrainDetector/layout/ClickTrainAlgorithmPaneFX.java b/src/clickTrainDetector/layout/ClickTrainAlgorithmPaneFX.java
index f31c03eb..50af611e 100644
--- a/src/clickTrainDetector/layout/ClickTrainAlgorithmPaneFX.java
+++ b/src/clickTrainDetector/layout/ClickTrainAlgorithmPaneFX.java
@@ -324,7 +324,13 @@ public class ClickTrainAlgorithmPaneFX extends SettingsPane {
popOver.showingProperty().addListener((obs, old, newval)->{
if (newval) {
- clickTrainControl.getDataSelector().getDialogPaneFX().setParams(true);
+ //the dialog has opened
+ clickTrainControl.getDataSelector().getDialogPaneFX().setParams(true);
+ }
+ else {
+ //the dialog has closed
+ clickTrainControl.getDataSelector().getDialogPaneFX().getParams(true);
+
}
});
diff --git a/src/clickTrainDetector/layout/PreClassifierPane.java b/src/clickTrainDetector/layout/PreClassifierPane.java
index 3344ed93..9abca195 100644
--- a/src/clickTrainDetector/layout/PreClassifierPane.java
+++ b/src/clickTrainDetector/layout/PreClassifierPane.java
@@ -34,7 +34,7 @@ public class PreClassifierPane extends PamBorderPane {
private Pane createClassifierPane() {
- simpleCTClassifierPane = new SimpleCTClassifierPane(null);
+ simpleCTClassifierPane = new SimpleCTClassifierPane(clickTrainControl.getClassifierManager().getPreClassifier());
return (Pane) simpleCTClassifierPane.getContentNode();
}
diff --git a/src/clickTrainDetector/layout/classification/simplechi2classifier/SimpleCTClassifierGraphics.java b/src/clickTrainDetector/layout/classification/simplechi2classifier/SimpleCTClassifierGraphics.java
index 1e5f9c7e..8a27c478 100644
--- a/src/clickTrainDetector/layout/classification/simplechi2classifier/SimpleCTClassifierGraphics.java
+++ b/src/clickTrainDetector/layout/classification/simplechi2classifier/SimpleCTClassifierGraphics.java
@@ -35,14 +35,15 @@ public class SimpleCTClassifierGraphics implements CTClassifierGraphics {
if (simpleCTClassiferPane==null) {
simpleCTClassiferPane = new SimpleCTClassifierPane(simpleChi2Classifier);
}
- //params are set here.
- simpleCTClassiferPane.setParams(simpleChi2Classifier.getParams());
+ //System.out.println("SimpleCTClassifierGraphics getCTClassifierPane: " + simpleChi2Classifier.getParams().chi2Threshold);
+ //params are set here. <- do not do this because you may wish to store the classifier params somewhere else.
+ //simpleCTClassiferPane.setParams(simpleChi2Classifier.getParams());
return (Pane) simpleCTClassiferPane.getContentNode();
}
@Override
public CTClassifierParams getParams() {
- Chi2ThresholdParams clssfrParams = simpleCTClassiferPane.getParams(simpleChi2Classifier.getParams());
+ Chi2ThresholdParams clssfrParams = simpleCTClassiferPane.getParams(simpleChi2Classifier.getParams()).clone();
if (clssfrParams==null) {
System.err.print("Simple Chi2 Classifier returned null params");
return null;
@@ -51,13 +52,14 @@ public class SimpleCTClassifierGraphics implements CTClassifierGraphics {
// simpleChi2Classifier.setParams(clssfrParams);
// return clssfrParams;
// }
+ //System.out.println("SimpleCTClassifierGraphics - getParams: " + clssfrParams.chi2Threshold);
return clssfrParams;
}
@Override
public void setParams(CTClassifierParams params) {
simpleCTClassiferPane.setParams((Chi2ThresholdParams) params);
-
+ //System.out.println("SimpleCTClassifierGraphics - setParams: " + ((Chi2ThresholdParams) params).chi2Threshold);
}
}
diff --git a/src/clickTrainDetector/layout/classification/simplechi2classifier/SimpleCTClassifierPane.java b/src/clickTrainDetector/layout/classification/simplechi2classifier/SimpleCTClassifierPane.java
index f7999529..d11e4c63 100644
--- a/src/clickTrainDetector/layout/classification/simplechi2classifier/SimpleCTClassifierPane.java
+++ b/src/clickTrainDetector/layout/classification/simplechi2classifier/SimpleCTClassifierPane.java
@@ -1,18 +1,32 @@
package clickTrainDetector.layout.classification.simplechi2classifier;
+import java.text.DecimalFormat;
+
+import org.controlsfx.control.PopOver;
+
import PamController.SettingsPane;
+import PamguardMVC.PamDataBlock;
import clickTrainDetector.classification.simplechi2classifier.Chi2ThresholdClassifier;
import clickTrainDetector.classification.simplechi2classifier.Chi2ThresholdParams;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
+import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.CheckBox;
+import javafx.scene.control.Control;
import javafx.scene.control.Spinner;
+import javafx.scene.control.SpinnerValueFactory;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.Pane;
+import javafx.util.StringConverter;
+import pamViewFX.PamGuiManagerFX;
+import pamViewFX.fxGlyphs.PamGlyphDude;
+import pamViewFX.fxNodes.PamBorderPane;
+import pamViewFX.fxNodes.PamButton;
import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.PamSpinner;
import pamViewFX.fxNodes.PamVBox;
+import pamViewFX.fxNodes.utilityPanes.PamToggleSwitch;
import pamViewFX.fxNodes.utilsFX.ControlField;
/**
@@ -51,6 +65,17 @@ public class SimpleCTClassifierPane extends SettingsPane {
*/
private ControlField minTime;
+ private PamToggleSwitch dataSelectorCheckBox;
+
+ private PamButton dataSelectorButton;
+
+ private PopOver popOver;
+
+ /**
+ * The minimum percentage of clicks for a certain class.
+ */
+ private ControlField minPercClicks;
+
public SimpleCTClassifierPane(Chi2ThresholdClassifier simpleChi2Classifier) {
super(null);
this.simpleChi2Classifier=simpleChi2Classifier;
@@ -96,17 +121,35 @@ public class SimpleCTClassifierPane extends SettingsPane {
chi2Threshold.getSpinner().getValueFactory().setConverter(PamSpinner.createStringConverter(0));
chi2Threshold.setTooltip(new Tooltip(
"A click train has a X\u00b2 value which is based on the consistancy of inter detection interval \n"
- + "amplitude and other factors. The calculation of X\\\\u00b2 changes depending on the click train \n"
+ + "amplitude and other factors. The calculation of X\u00b2 changes depending on the click train \n"
+ "detector is used."));
chi2Threshold.getLabel1().setPrefWidth(LABEL_WIDTH);
- minClicks = new ControlField("Min. Clicks ", "", 0, Integer.MAX_VALUE, 5);
+ minClicks = new ControlField("Min. clicks ", "", 0, Integer.MAX_VALUE, 5);
minClicks.setTooltip(new Tooltip(
"The minimum number of detections."));
minClicks.getSpinner().setEditable(true);
minClicks.getLabel1().setPrefWidth(LABEL_WIDTH);
+
+
+ minPercClicks = new ControlField("Min. % clicks ", "", 0, 100., 1.);
+ minPercClicks.setTooltip(new Tooltip(
+ "The minimum number of detections."));
+ minPercClicks.getSpinner().setEditable(true);
+ SpinnerValueFactory valueFactory = new SpinnerValueFactory.DoubleSpinnerValueFactory(0, 100., 0., 1.);
+ valueFactory.setConverter(doubleConverter);
+ minPercClicks.getSpinner().setValueFactory(valueFactory);
+ minPercClicks.getSpinner().setEditable(true);
+ ///HACK to get the percentage sign to show?
+ minPercClicks.getSpinner().increment();
+ minPercClicks.getSpinner().decrement();
- minTime = new ControlField("Min. Time ", "s", 0.0, Double.MAX_VALUE, 1.0);
+ minPercClicks.getLabel1().setPrefWidth(LABEL_WIDTH);
+
+ minPercClicks.getChildren().add( createDataSelectorPane());
+
+
+ minTime = new ControlField("Min. time ", "s", 0.0, Double.MAX_VALUE, 1.0);
minTime.getSpinner().getValueFactory().setConverter(PamSpinner.createStringConverter(2));
minTime.setTooltip(new Tooltip(
"The minimum time for a click train."));
@@ -115,29 +158,83 @@ public class SimpleCTClassifierPane extends SettingsPane {
chi2Threshold.getSpinner().setEditable(true);
- vBox.getChildren().addAll(chi2Threshold, minClicks, minTime);
+ vBox.getChildren().addAll(chi2Threshold, minClicks, minPercClicks, minTime);
return vBox;
}
+
+ /**
+ * Create the data selector.
+ * @return the data selector.
+ */
+ private Pane createDataSelectorPane() {
+ PamHBox hbox = new PamHBox();
+ hbox.setSpacing(5);
+ hbox.setAlignment(Pos.CENTER_LEFT);
+
+ dataSelectorButton = new PamButton();
+// dataSelectorButton.setGraphic(PamGlyphDude.createPamGlyph(MaterialIcon.SETTINGS, PamGuiManagerFX.iconSize));
+ dataSelectorButton.setGraphic(PamGlyphDude.createPamIcon("mdi2c-cog", PamGuiManagerFX.iconSize));
+ dataSelectorButton.setOnAction((action)->{
+ showDataSelectorPane();
+ });
+ hbox.getChildren().addAll(dataSelectorButton);
+ return hbox;
+ }
+
+
+ /**
+ * Creates pane allowing the user to change fine scale things such as error limits.
+ * @return the pop over pane.
+ */
+ public void showDataSelectorPane() {
+
+ if (popOver==null) {
+ popOver = new PopOver();
+ PamBorderPane holder = new PamBorderPane(simpleChi2Classifier.getDataSelector().getDialogPaneFX().getContentNode());
+ holder.setPadding(new Insets(5,5,5,5));
+ popOver.setContentNode(holder);
+ }
+
+ popOver.showingProperty().addListener((obs, old, newval)->{
+ if (newval) {
+// System.out.println("Data Selector: " + simpleChi2Classifier.getDataSelector());
+ simpleChi2Classifier.getDataSelector().getDialogPaneFX().setParams(true);
+ }
+ else {
+ simpleChi2Classifier.getDataSelector().getDialogPaneFX().getParams(true);
+ }
+ });
+
+ popOver.show(dataSelectorButton);
+ }
@Override
public Chi2ThresholdParams getParams(Chi2ThresholdParams currParams) {
+ //System.out.println("Get PERC spinner value; " + minPercClicks.getSpinner().getValue());
currParams.chi2Threshold=chi2Threshold.getSpinner().getValue();
//HACK - for some reason Integer spinner is returning a double
currParams.minClicks=minClicks.getSpinner().getValue().intValue();
currParams.minTime=minTime.getSpinner().getValue();
+ currParams.minPercentage=minPercClicks.getSpinner().getValue()/100;
+
+ if (simpleChi2Classifier!=null && simpleChi2Classifier.getDataSelector()!=null) {
+ simpleChi2Classifier.getDataSelector().getDialogPaneFX().getParams(true);
+ }
return currParams;
}
@Override
public void setParams(Chi2ThresholdParams input) {
+
chi2Threshold.getSpinner().getValueFactory().setValue(input.chi2Threshold);
//HACK - for some reason Integer spinner is returning a double
minClicks.getSpinner().getValueFactory().setValue((double) input.minClicks);
minTime.getSpinner().getValueFactory().setValue(input.minTime);
+ minPercClicks.getSpinner().getValueFactory().setValue(input.minPercentage*100.);
}
@Override
@@ -164,6 +261,24 @@ public class SimpleCTClassifierPane extends SettingsPane {
}
+
+ StringConverter doubleConverter = new StringConverter() {
+ private final DecimalFormat df = new DecimalFormat("###.#");
+ @Override
+ public String toString(Double object) {
+ if (object == null) {return "";}
+ return df.format(object)+"%";}
+ @Override
+ public Double fromString(String string) {
+ try {
+ if (string == null) {return null;}
+ string = string.trim();
+ if (string.length() < 1) {return null;}
+ return df.parse(string).doubleValue();
+ } catch (Exception ex) {throw new RuntimeException(ex);}
+ }
+ };
+
diff --git a/src/clickTrainDetector/layout/classification/templateClassifier/TemplateClassifierPane.java b/src/clickTrainDetector/layout/classification/templateClassifier/TemplateClassifierPane.java
index b7d9f913..77193e4b 100644
--- a/src/clickTrainDetector/layout/classification/templateClassifier/TemplateClassifierPane.java
+++ b/src/clickTrainDetector/layout/classification/templateClassifier/TemplateClassifierPane.java
@@ -118,6 +118,8 @@ public class TemplateClassifierPane extends SettingsPane{
+ setCheckBoxEnable();
+ });
+ constraints.gridy++;
+
+ classifierCheckBoxes = new JCheckBox[classifcationManager.getCurrentClassifiers().size()];
+ for (int i=0; i {
pruneStartSpinner.setEditable(true);
pruneBackSpinner.setTooltip(new Tooltip("The minimum number of detections before pruning starts."));
gridPane.add(pruneStartSpinner, 1, gridY);
- gridY++;
+ gridY=0;
- gridPane.add(new Label("Max no. coasts"), 0, gridY);
+ gridPane.add(new Label(" Max no. coasts"), 2, gridY);
nCoastsSpinner = new PamSpinner(0,Integer.MAX_VALUE,3,1);
nCoastsSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
nCoastsSpinner.setPrefWidth(70);
nCoastsSpinner.setEditable(true);
nCoastsSpinner.setTooltip(new Tooltip("The maximum number of missing detections before a track is closed"));
- gridPane.add(nCoastsSpinner, 1, gridY);
+ gridPane.add(nCoastsSpinner, 3, gridY);
gridY++;
- gridPane.add(new Label("Max no. trains"), 0, gridY);
+ gridPane.add(new Label(" Max no. trains"), 2, gridY);
nHoldSpinner = new PamSpinner(0,1000,3,1);
nHoldSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL);
nHoldSpinner.setPrefWidth(70);
nHoldSpinner.setEditable(true);
nHoldSpinner.setTooltip(new Tooltip("The maximum number of unique click trains that can be tracked at the same time."));
- gridPane.add(nHoldSpinner, 1, gridY);
+ gridPane.add(nHoldSpinner, 3, gridY);
pamVBox.getChildren().addAll(label, gridPane);
diff --git a/src/dataMap/SummaryPanel.java b/src/dataMap/SummaryPanel.java
index abc1e993..5786a331 100644
--- a/src/dataMap/SummaryPanel.java
+++ b/src/dataMap/SummaryPanel.java
@@ -99,8 +99,8 @@ public class SummaryPanel extends HidingDialogComponent {
dataEnds[i].setText(" ---No data---");
}
else {
- dataStarts[i].setText(PamCalendar.formatDateTime2(dataExtent[0], true));
- dataEnds[i].setText(PamCalendar.formatDateTime(dataExtent[1], true));
+ dataStarts[i].setText(PamCalendar.formatDateTime2(dataExtent[0], true));
+ dataEnds[i].setText(PamCalendar.formatDateTime(dataExtent[1], true));
}
}
for (int i = offlineDataStores.size(); i < maxDataSources; i++) {
diff --git a/src/detectionPlotFX/layout/DetectionPlotDisplay.java b/src/detectionPlotFX/layout/DetectionPlotDisplay.java
index 713274d4..865eecb9 100644
--- a/src/detectionPlotFX/layout/DetectionPlotDisplay.java
+++ b/src/detectionPlotFX/layout/DetectionPlotDisplay.java
@@ -447,6 +447,11 @@ public class DetectionPlotDisplay extends PamBorderPane implements UserDisplayNo
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 implements Detection
}
g2.strokePolyline(scaledDataX, scaledDataY, scaledDataY.length-1);
if (fillSpectrum) {
- // System.out.println("Last point: " + x0 + " y0 " + r.getHeight());
+ //System.out.println("Last point: " + x0 + " y0 " + y0 + " " + scale + " " + clickLineData[iChan][0] + " " + projector.getAxis(Side.LEFT).getMinVal() + " " +projector.getAxis(Side.LEFT).getTotalPixels());
scaledDataX[scaledDataX.length-1]=x0; // the last x position
scaledDataY[scaledDataY.length-1]= r.getHeight() ; //return the line to zero for polygon drawing
// PamUtils.PamArrayUtils.printArray(scaledDataY);
diff --git a/src/fileOfflineData/OfflineFileList.java b/src/fileOfflineData/OfflineFileList.java
new file mode 100644
index 00000000..5395c230
--- /dev/null
+++ b/src/fileOfflineData/OfflineFileList.java
@@ -0,0 +1,88 @@
+package fileOfflineData;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.ArrayList;
+
+/**
+ * Make a list of files with the given file filter.
+ * @author dg50
+ *
+ */
+public class OfflineFileList {
+
+ private ArrayList files = new ArrayList<>();
+ private String folder;
+ private FileFilter fileFilter;
+ private boolean includeSubFolders;
+
+ public OfflineFileList(String folder, FileFilter fileFilter, boolean includeSubFolders) {
+ this.folder = folder;
+ this.fileFilter = fileFilter;
+ this.includeSubFolders = includeSubFolders;
+ updateCatalog();
+ }
+
+ public int updateCatalog() {
+ files.clear();
+ File current = new File(this.folder);
+ addFiles(current);
+ return files.size();
+ }
+
+ private void addFiles(File current) {
+ if (current.exists() == false) {
+ return;
+ }
+ if (current.isFile() && checkFilter(current)) {
+ /*
+ * This can only really happen if the root passed in is a file, not a
+ * folder, since files within the folder structure will get
+ * added from the loop below.
+ */
+ files.add(current);
+ }
+ else if (current.isDirectory()) {
+ File[] filesList = current.listFiles();
+ if (filesList == null) {
+ return;
+ }
+ for (int i = 0; i < filesList.length; i++) {
+ File aFile = filesList[i];
+ if (aFile.isFile() && checkFilter(aFile)) {
+ files.add(aFile);
+ }
+ else if (aFile.isDirectory() && includeSubFolders) {
+ addFiles(aFile);
+ }
+ }
+ }
+ }
+
+ /**
+ * Check that if there is a filter, the file is accepted.
+ * @param aFile
+ * @return
+ */
+ private boolean checkFilter(File aFile) {
+ if (fileFilter == null) {
+ return true;
+ }
+ return fileFilter.accept(aFile);
+ }
+
+ /**
+ * Get a list of files in the catalog as a simple string list.
+ * @return files as strings
+ */
+ public String[] asStringList() {
+ if (files == null) {
+ return null;
+ }
+ String[] str = new String[files.size()];
+ for (int i = 0; i < files.size(); i++) {
+ str[i] = files.get(i).getAbsolutePath();
+ }
+ return str;
+ }
+}
diff --git a/src/generalDatabase/backup/DatabaseBackupStream.java b/src/generalDatabase/backup/DatabaseBackupStream.java
index fc6f4d47..d7808a96 100644
--- a/src/generalDatabase/backup/DatabaseBackupStream.java
+++ b/src/generalDatabase/backup/DatabaseBackupStream.java
@@ -120,6 +120,9 @@ public class DatabaseBackupStream extends FileBackupStream {
public FileLocation getSourceLocation() {
File dbFile = getDatabaesFile();
+ if (dbFile == null) {
+ return null;
+ }
FileLocation sl = new FileLocation();
sl.path = dbFile.getAbsolutePath();
sl.canEditMask = false;
diff --git a/src/pamScrollSystem/AbstractPamScroller.java b/src/pamScrollSystem/AbstractPamScroller.java
index 95afb5eb..54f441e7 100644
--- a/src/pamScrollSystem/AbstractPamScroller.java
+++ b/src/pamScrollSystem/AbstractPamScroller.java
@@ -44,6 +44,14 @@ public abstract class AbstractPamScroller implements DataTimeLimits {
*/
protected double[] playSpeeds = {.1, 0.25, .5, 1.0, 2, 5, 10};
+// private long realTimerStart;
+//
+// private long timerStartPosition;
+
+ private long timerLastCurrentTime;
+
+// private long timerTimeMillis;
+
public AbstractPamScroller(String name, int orientation, int stepSizeMillis, long defaultLoadTime, boolean hasMenu){
@@ -630,6 +638,8 @@ public abstract class AbstractPamScroller implements DataTimeLimits {
playTimerAction();
}
});
+ timerLastCurrentTime = System.currentTimeMillis();
+// timeLastValue = getValueMillis();
playTimer.start();
playbackStarted();
}
@@ -671,11 +681,17 @@ public abstract class AbstractPamScroller implements DataTimeLimits {
stopPlayback();
return;
}
- long step = Math.max((long) (timerInterval * scrollerData.getPlaySpeed()), 1);
- setValueMillis(pos+step);
- if (pos == getValueMillis()) {
- playTimer.setDelay(playTimer.getDelay()*2);
- }
+ /**
+ * Since the action on setValue can take quite some time, the timer can run slow
+ * if we just increment by what we think this delay is, so increment the value
+ * based on how much system time has elapsed between the last call and now
+ */
+ long now = System.currentTimeMillis();
+ int elapsed = (int) (now - timerLastCurrentTime);
+ int toAdd = (int) (elapsed*scrollerData.getPlaySpeed());
+ timerLastCurrentTime = now;
+
+ setValueMillis(getValueMillis()+toAdd);
}
}
diff --git a/src/pamViewFX/fxNodes/pamAxis/PamAxisPane2.java b/src/pamViewFX/fxNodes/pamAxis/PamAxisPane2.java
index 3b80847b..905109bc 100644
--- a/src/pamViewFX/fxNodes/pamAxis/PamAxisPane2.java
+++ b/src/pamViewFX/fxNodes/pamAxis/PamAxisPane2.java
@@ -93,7 +93,7 @@ public class PamAxisPane2 extends StackPane {
this.getChildren().add(mainPane);
}
- private void layoutAxis(){
+ public void layoutAxis(){
mainPane.setCenter(null);
diff --git a/src/pamViewFX/fxNodes/utilityPanes/MinMaxPane.java b/src/pamViewFX/fxNodes/utilityPanes/MinMaxPane.java
index 82f64c6d..b4942247 100644
--- a/src/pamViewFX/fxNodes/utilityPanes/MinMaxPane.java
+++ b/src/pamViewFX/fxNodes/utilityPanes/MinMaxPane.java
@@ -1,7 +1,6 @@
package pamViewFX.fxNodes.utilityPanes;
import java.io.Serializable;
-
import javafx.geometry.Pos;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
diff --git a/src/spectrogramNoiseReduction/layoutFX/SpectrogramNoisePaneFX.java b/src/spectrogramNoiseReduction/layoutFX/SpectrogramNoisePaneFX.java
index cdc4d836..60f67120 100644
--- a/src/spectrogramNoiseReduction/layoutFX/SpectrogramNoisePaneFX.java
+++ b/src/spectrogramNoiseReduction/layoutFX/SpectrogramNoisePaneFX.java
@@ -3,12 +3,10 @@ package spectrogramNoiseReduction.layoutFX;
import java.util.ArrayList;
-import org.controlsfx.control.ToggleSwitch;
-
import pamViewFX.PamGuiManagerFX;
-import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.PamVBox;
+import pamViewFX.fxNodes.utilityPanes.PamToggleSwitch;
import pamViewFX.fxNodes.utilityPanes.SourcePaneFX;
import spectrogramNoiseReduction.SpecNoiseMethod;
import spectrogramNoiseReduction.SpectrogramNoiseProcess;
@@ -16,10 +14,8 @@ import spectrogramNoiseReduction.SpectrogramNoiseSettings;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
-import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
-import javafx.scene.layout.Pane;
import PamController.SettingsPane;
import PamguardMVC.PamDataBlock;
@@ -39,7 +35,7 @@ public class SpectrogramNoisePaneFX extends SettingsPane
Date: Tue, 7 Jun 2022 18:06:47 +0100
Subject: [PATCH 18/37] sorting sup and super detections (again)
---
src/PamguardMVC/superdet/SuperDetDataBlock.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/PamguardMVC/superdet/SuperDetDataBlock.java b/src/PamguardMVC/superdet/SuperDetDataBlock.java
index 560ade53..581c0b92 100644
--- a/src/PamguardMVC/superdet/SuperDetDataBlock.java
+++ b/src/PamguardMVC/superdet/SuperDetDataBlock.java
@@ -471,6 +471,7 @@ public class SuperDetDataBlock
Date: Wed, 8 Jun 2022 10:06:25 +0100
Subject: [PATCH 19/37] Merge pull request #3 from PAMGuard/main (#35)
From cc3889a95f66991ece93791f87ba818e1121b61b Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Thu, 9 Jun 2022 16:06:00 +0100
Subject: [PATCH 20/37] Extra option in Generic dialog to specify location on
screen.
---
src/PamView/dialog/GenericSwingDialog.java | 46 +++++++++++++++++--
.../paneloverlay/OverlayDataManager.java | 1 -
2 files changed, 41 insertions(+), 6 deletions(-)
diff --git a/src/PamView/dialog/GenericSwingDialog.java b/src/PamView/dialog/GenericSwingDialog.java
index 8d0177a9..208bd386 100644
--- a/src/PamView/dialog/GenericSwingDialog.java
+++ b/src/PamView/dialog/GenericSwingDialog.java
@@ -1,5 +1,8 @@
package PamView.dialog;
+import java.awt.Dimension;
+import java.awt.Point;
+import java.awt.Toolkit;
import java.awt.Window;
import javax.swing.BoxLayout;
@@ -8,9 +11,9 @@ import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class GenericSwingDialog extends PamDialog {
-
+
private boolean allOk;
-
+
private PamDialogPanel[] dialogPanels;
private GenericSwingDialog(Window parentFrame, String title, PamDialogPanel ...dialogPanels) {
@@ -25,15 +28,48 @@ public class GenericSwingDialog extends PamDialog {
}
mainPanel.add(comp);
}
-
+
setDialogComponent(mainPanel);
}
-
- public static boolean showDialog(Window parentFrame, String title, PamDialogPanel ...dialogPanels) {
+ public static boolean showDialog(Window parentFrame, String title, PamDialogPanel ...dialogPanels) {
+ return showDialog(parentFrame, title, null, dialogPanels);
+ }
+
+ /**
+ * Show dialog at a specific location on the screen.
+ * @param parentFrame
+ * @param title
+ * @param screenPoint
+ * @param dialogPanels
+ * @return
+ */
+ public static boolean showDialog(Window parentFrame, String title, Point screenPoint, PamDialogPanel ...dialogPanels) {
GenericSwingDialog swingDialog = new GenericSwingDialog(parentFrame, title, dialogPanels);
swingDialog.setParams();
swingDialog.pack();
+ if (screenPoint != null) {
+ try {
+ // check we're not going too far off the screen.
+ Dimension sz = swingDialog.getPreferredSize();
+ Dimension screen = null;
+ if (parentFrame != null) {
+ screen = parentFrame.getSize();
+ }
+ else {
+ screen = Toolkit.getDefaultToolkit().getScreenSize();
+ }
+ screenPoint.y = Math.min(screenPoint.y, screen.height-sz.height-10);
+ screenPoint.y = Math.max(screenPoint.y, 0);
+ screenPoint.x = Math.min(screenPoint.x, screen.width-sz.width-10);
+ screenPoint.x = Math.max(screenPoint.x, 0);
+
+ swingDialog.setLocation(screenPoint);
+ }
+ catch (Exception e) {
+ // shouldn't happen, but if it does, it doesn't matter much
+ }
+ }
swingDialog.setVisible(true);
return swingDialog.allOk;
}
diff --git a/src/PamView/paneloverlay/OverlayDataManager.java b/src/PamView/paneloverlay/OverlayDataManager.java
index 75d7a1a4..c633ed3d 100644
--- a/src/PamView/paneloverlay/OverlayDataManager.java
+++ b/src/PamView/paneloverlay/OverlayDataManager.java
@@ -42,7 +42,6 @@ public abstract class OverlayDataManager
Date: Sat, 11 Jun 2022 11:36:36 +0100
Subject: [PATCH 21/37] Fixes to ROCCA memory problem. See
https://github.com/PAMGuard/PAMGuard/issues/36 Made a temp build of this for
testing.
---
.settings/org.eclipse.jdt.core.prefs | 5 +++++
pom.xml | 2 +-
src/IshmaelLocator/IshLocProcess.java | 4 ++++
src/PamController/PamguardVersionInfo.java | 4 ++--
src/PamModel/PamDependency.java | 14 +++++++++++---
src/PamModel/PamPluginInterface.java | 2 ++
src/rocca/RoccaControl.java | 19 +++++++++++++++++++
src/rocca/RoccaProcess.java | 8 ++++++++
src/rocca/RoccaSidePanel.java | 3 +++
src/rocca/RoccaWhistleSelect.java | 10 ++++++++++
10 files changed, 65 insertions(+), 6 deletions(-)
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index e8c450c0..fbf1aacf 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -1,7 +1,12 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=11
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
diff --git a/pom.xml b/pom.xml
index 324409a6..cfccc70f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
org.pamguard
Pamguard
- 2.02.03
+ 2.02.04
Pamguard Java12+
Pamguard for Java 12+, using Maven to control dependcies
www.pamguard.org
diff --git a/src/IshmaelLocator/IshLocProcess.java b/src/IshmaelLocator/IshLocProcess.java
index 144dec7a..cdec7212 100644
--- a/src/IshmaelLocator/IshLocProcess.java
+++ b/src/IshmaelLocator/IshLocProcess.java
@@ -380,6 +380,10 @@ abstract public class IshLocProcess extends PamProcess implements SpectrogramMar
} else {
newTime = oldTime*2;
}
+ /*
+ * Above causes same error as in Rocca and needs fixing
+ */
+ newTime = Math.min(newTime, 600000); // don't let this exceed 10 minutes.
// System.out.println("Adjusting raw data natural lifetime from " + oldTime + " ms to " + newTime + " ms");
daqBlock.setNaturalLifetimeMillis(newTime); // increase the lifetime to try and prevent this from happening again
return;
diff --git a/src/PamController/PamguardVersionInfo.java b/src/PamController/PamguardVersionInfo.java
index 1217f1d8..2c91e596 100644
--- a/src/PamController/PamguardVersionInfo.java
+++ b/src/PamController/PamguardVersionInfo.java
@@ -31,12 +31,12 @@ public class PamguardVersionInfo {
* Version number, major version.minorversion.sub-release.
* Note: can't go higher than sub-release 'f'
*/
- static public final String version = "2.02.03";
+ static public final String version = "2.02.04";
/**
* Release date
*/
- static public final String date = "8 February 2022";
+ static public final String date = "11 June 2022";
// /**
// * Release type - Beta or Core
diff --git a/src/PamModel/PamDependency.java b/src/PamModel/PamDependency.java
index a6818972..072a0b0f 100644
--- a/src/PamModel/PamDependency.java
+++ b/src/PamModel/PamDependency.java
@@ -20,12 +20,22 @@ public class PamDependency {
private String dataBlockName;
+ /**
+ *
+ * @param requiredDataType Class of Data unit
+ * @param defaultProvider Class name of default provider.
+ * @param dataBlockName Specific data block name
+ */
public PamDependency(Class requiredDataType, String defaultProvider, String dataBlockName) {
this.requiredDataType = requiredDataType;
this.defaultProvider = defaultProvider;
this.dataBlockName = dataBlockName;
}
+ /**
+ * @param requiredDataType Class of Data unit
+ * @param defaultProvider Class name of default provider.
+ */
public PamDependency(Class requiredDataType, String defaultProvider) {
this.requiredDataType = requiredDataType;
this.defaultProvider = defaultProvider;
@@ -41,12 +51,10 @@ public class PamDependency {
/**
* @return Returns the requiredDataType.
*/
-// public DataType getRequiredDataType() {
-// return requiredDataType;
-// }
public Class getRequiredDataType() {
return requiredDataType;
}
+
/**
* @return Returns the dataBlockName.
*/
diff --git a/src/PamModel/PamPluginInterface.java b/src/PamModel/PamPluginInterface.java
index 84d76c17..13539613 100644
--- a/src/PamModel/PamPluginInterface.java
+++ b/src/PamModel/PamPluginInterface.java
@@ -67,6 +67,8 @@ public interface PamPluginInterface extends CommonPluginInterface {
* A short description of the plug in module. This text is used in various informational
* windows displayed to the user. The value returned here is typically the same as the text returned
* from the {@link #getDefaultName() getDefaultName()} method (e.g. Click Detector or FFT (Spectrogram) Engine).
+ *
This is the text used in the main 'Add Modules' menus and is used as the
+ * second argument to PamModuleInfo.registerControlledUnit
*
* This field cannot be null.
* @return String describing the plugin. Cannot be null.
diff --git a/src/rocca/RoccaControl.java b/src/rocca/RoccaControl.java
index 2d67789b..c3881b17 100644
--- a/src/rocca/RoccaControl.java
+++ b/src/rocca/RoccaControl.java
@@ -69,6 +69,11 @@ public class RoccaControl extends PamControlledUnit implements PamSettings {
*/
public static final String unitType = "Rocca";
+ /*
+ * Max max data keep time to avoid memory overflows. Currently at 15 minutes.
+ */
+ private static final int MAXMAXDATAKEEPTIME = 900000;
+
/**
* reference to the ClickControl module when it is loaded in Viewer mode
*/
@@ -193,6 +198,17 @@ public class RoccaControl extends PamControlledUnit implements PamSettings {
return 1;
}
+ /**
+ * A bit of a fudge to deal with some old code which kept doubling the
+ * keep time of the raw data, which eventually led to raw data using too
+ * much memory and bringing down PG. I don't fully understand that code so
+ * have left as much of it as possible, but put this in as an absolute
+ * maximum which cannot be exceeded.
+ * @return max in milliseconds as int, which is what's used in PAMDataBlock.
+ */
+ public int getMaxDataKeepTime() {
+ return MAXMAXDATAKEEPTIME;
+ }
/**
*
* @param eventList
@@ -242,18 +258,21 @@ public class RoccaControl extends PamControlledUnit implements PamSettings {
(rcdb.getContour().get(RoccaContourStats.ParamIndx.SNR) > 35. ||
rcdb.getContour().get(RoccaContourStats.ParamIndx.DURATION) < 0.005 ||
rcdb.getContour().get(RoccaContourStats.ParamIndx.DURATION) > 0.6 )) {
+ rcdb.setNaturalLifetimeMillis(0);
return;
}
if (roccaParameters.roccaClassifierModelFilename.getName().equals("HIClick.model") &&
(rcdb.getContour().get(RoccaContourStats.ParamIndx.SNR) > 40. ||
rcdb.getContour().get(RoccaContourStats.ParamIndx.DURATION) < 0.01 ||
rcdb.getContour().get(RoccaContourStats.ParamIndx.DURATION) > 0.6 )) {
+ rcdb.setNaturalLifetimeMillis(0);
return;
}
if (roccaParameters.roccaClassifierModelFilename.getName().equals("NWAtlClick.model") &&
(rcdb.getContour().get(RoccaContourStats.ParamIndx.SNR) > 35. ||
rcdb.getContour().get(RoccaContourStats.ParamIndx.DURATION) < 0.005 ||
rcdb.getContour().get(RoccaContourStats.ParamIndx.DURATION) > 0.6 )) {
+ rcdb.setNaturalLifetimeMillis(0);
return;
}
diff --git a/src/rocca/RoccaProcess.java b/src/rocca/RoccaProcess.java
index e5f3d50d..86b5502b 100644
--- a/src/rocca/RoccaProcess.java
+++ b/src/rocca/RoccaProcess.java
@@ -363,6 +363,9 @@ public class RoccaProcess extends PamProcess {
// 2017/12/4 set the natural lifetime to Integer.Max, so that we definitely keep all of the data
// units during this code block. Set the lifetime back to 0 at the end of the block
+ /*
+ * DG June '22 made sure this is the case when the function returns early !
+ */
rcdb.setNaturalLifetimeMillis(Integer.MAX_VALUE);
rcdb.calculateStatistics();
@@ -385,6 +388,7 @@ public class RoccaProcess extends PamProcess {
rcdb.getContour().get(RoccaContourStats.ParamIndx.DURATION) > 1.5 ||
rcdb.getContour().get(RoccaContourStats.ParamIndx.FREQABSSLOPEMEAN) < 2000. ||
rcdb.getContour().get(RoccaContourStats.ParamIndx.FREQABSSLOPEMEAN) > 28000. )) {
+ rcdb.setNaturalLifetimeMillis(0);
return;
}
if (roccaControl.roccaParameters.roccaClassifierModelFilename.getName().equals("HIWhist.model") &&
@@ -398,6 +402,7 @@ public class RoccaProcess extends PamProcess {
rcdb.getContour().get(RoccaContourStats.ParamIndx.FREQABSSLOPEMEAN) > 60000. ||
rcdb.getContour().get(RoccaContourStats.ParamIndx.FREQRANGE) < 800. ||
rcdb.getContour().get(RoccaContourStats.ParamIndx.FREQRANGE) > 14000. )) {
+ rcdb.setNaturalLifetimeMillis(0);
return;
}
if (roccaControl.roccaParameters.roccaClassifierModelFilename.getName().equals("NWAtlWhist.model") &&
@@ -407,6 +412,7 @@ public class RoccaProcess extends PamProcess {
rcdb.getContour().get(RoccaContourStats.ParamIndx.DURATION) > 2.5 ||
rcdb.getContour().get(RoccaContourStats.ParamIndx.FREQABSSLOPEMEAN) < 9100. ||
rcdb.getContour().get(RoccaContourStats.ParamIndx.FREQABSSLOPEMEAN) > 82000. )) {
+ rcdb.setNaturalLifetimeMillis(0);
return;
}
}
@@ -743,6 +749,8 @@ public class RoccaProcess extends PamProcess {
} else {
newTime = prdb.getNaturalLifetimeMillis()*2;
}
+ // stop it getting silly.
+ newTime = Math.min(newTime, roccaControl.getMaxDataKeepTime());
prdb.setNaturalLifetimeMillis(newTime); // increase the lifetime to try and prevent this from happening again
return null;
}
diff --git a/src/rocca/RoccaSidePanel.java b/src/rocca/RoccaSidePanel.java
index 879c5fee..281724cc 100644
--- a/src/rocca/RoccaSidePanel.java
+++ b/src/rocca/RoccaSidePanel.java
@@ -114,7 +114,10 @@ public class RoccaSidePanel extends PamObserverAdapter implements PamSidePanel
this.rsdb = new RoccaSightingDataBlock
(roccaControl.roccaProcess,
roccaControl.roccaParameters.getChannelMap());
+
+ // this one probably OK to never delete ?
rsdb.setNaturalLifetimeMillis(Integer.MAX_VALUE);
+
rdl = new RoccaDetectionLogger(this, rsdb);
rsdb.SetLogging(rdl);
rsdb.setMixedDirection(PamDataBlock.MIX_INTODATABASE);
diff --git a/src/rocca/RoccaWhistleSelect.java b/src/rocca/RoccaWhistleSelect.java
index f75438a0..72f1f59e 100644
--- a/src/rocca/RoccaWhistleSelect.java
+++ b/src/rocca/RoccaWhistleSelect.java
@@ -171,6 +171,8 @@ public class RoccaWhistleSelect extends PamProcess implements SpectrogramMarkObs
roccaControl.roccaSidePanel.sidePanel.addASighting(false);
// if the user hit cancel, just exit
if (dummy == RoccaSightingDataUnit.NONE) {
+ selectedWhistle.setNaturalLifetimeMillis(0);
+ selectedWhistleRaw.setNaturalLifetimeMillis(0);
return;
}
}
@@ -198,6 +200,14 @@ public class RoccaWhistleSelect extends PamProcess implements SpectrogramMarkObs
selectedWhistleRaw,
display,
channel);
+
+ /**
+ * DG June '22.
+ * I hope IT's K to set these back here. It's possible it's also
+ * done elsewhere.
+ */
+ selectedWhistle.setNaturalLifetimeMillis(0);
+ selectedWhistleRaw.setNaturalLifetimeMillis(0);
}
}
From d88da616822aa540af216868eba2949b276d6be4 Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Sat, 11 Jun 2022 19:06:34 +0100
Subject: [PATCH 22/37] Fix but in string annotation updates and a couple of
features to allow gradual building of datamap in background while work
continues.
---
.classpath | 9 ++-
dependency-reduced-pom.xml | 2 +-
src/PamguardMVC/PamDataUnit.java | 66 +++++++++++++++-----
src/annotation/string/StringDialogPanel.java | 17 +++--
src/dataMap/DataMapControl.java | 27 +++++++-
src/dataMap/DataMapPanel.java | 7 +++
src/warnings/SingleLineWarningDisplay.java | 3 +-
7 files changed, 106 insertions(+), 25 deletions(-)
diff --git a/.classpath b/.classpath
index 3558670a..b2a2497b 100644
--- a/.classpath
+++ b/.classpath
@@ -1,8 +1,7 @@
-
+
-
@@ -11,5 +10,11 @@
+
+
+
+
+
+
diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml
index 3d87c487..7ee84c51 100644
--- a/dependency-reduced-pom.xml
+++ b/dependency-reduced-pom.xml
@@ -4,7 +4,7 @@
org.pamguard
Pamguard
Pamguard Java12+
- 2.02.03
+ 2.02.04
Pamguard for Java 12+, using Maven to control dependcies
www.pamguard.org
diff --git a/src/PamguardMVC/PamDataUnit.java b/src/PamguardMVC/PamDataUnit.java
index 94514773..2a9994a6 100644
--- a/src/PamguardMVC/PamDataUnit.java
+++ b/src/PamguardMVC/PamDataUnit.java
@@ -943,23 +943,27 @@ abstract public class PamDataUnit
}
}
- int nAttotations = getNumDataAnnotations();
- for (int i = 0; i < nAttotations; i++) {
- DataAnnotation an = getDataAnnotation(i);
- DataAnnotationType ant = an.getDataAnnotationType();
- String anName = ant.getAnnotationName();
- String anString = an.toString();
- if (anString == null) {
- continue;
- }
- if (anString.contains("")) {
- anString = anString.replace("", "");
- }
- if (anString.contains("")) {
- anString = anString.replace("", "");
- }
- str += anName + ": " + anString + "
";
+ String annotString = getAnnotationsSummaryString();
+ if (annotString != null) {
+ str += annotString;
}
+// int nAttotations = getNumDataAnnotations();
+// for (int i = 0; i < nAttotations; i++) {
+// DataAnnotation an = getDataAnnotation(i);
+// DataAnnotationType ant = an.getDataAnnotationType();
+// String anName = ant.getAnnotationName();
+// String anString = an.toString();
+// if (anString == null) {
+// continue;
+// }
+// if (anString.contains("")) {
+// anString = anString.replace("", "");
+// }
+// if (anString.contains("")) {
+// anString = anString.replace("", "");
+// }
+// str += anName + ": " + anString + "
";
+// }
// add frequency and amplitude information
@@ -999,6 +1003,36 @@ abstract public class PamDataUnit
return str;
}
+ /**
+ * Get string information for the annotations. Kept separate so
+ * it can be called in overridden version of getSummaryString()
+ * @return
+ */
+ public String getAnnotationsSummaryString() {
+ int nAnnotations = getNumDataAnnotations();
+ if (nAnnotations == 0) {
+ return null;
+ }
+ String str = "";
+ for (int i = 0; i < nAnnotations; i++) {
+ DataAnnotation an = getDataAnnotation(i);
+ DataAnnotationType ant = an.getDataAnnotationType();
+ String anName = ant.getAnnotationName();
+ String anString = an.toString();
+ if (anString == null) {
+ continue;
+ }
+ if (anString.contains("")) {
+ anString = anString.replace("", "");
+ }
+ if (anString.contains("")) {
+ anString = anString.replace("", "");
+ }
+ str += anName + ": " + anString + "
";
+ }
+ return str.length() > 0 ? str : null;
+ }
+
/**
* Some functions to do with data annotations
*/
diff --git a/src/annotation/string/StringDialogPanel.java b/src/annotation/string/StringDialogPanel.java
index ccee5943..6aaafd93 100644
--- a/src/annotation/string/StringDialogPanel.java
+++ b/src/annotation/string/StringDialogPanel.java
@@ -10,6 +10,7 @@ import java.awt.event.WindowEvent;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
+import PamUtils.PamCalendar;
import annotation.AnnotationDialogPanel;
import PamView.DBTextArea;
import PamView.dialog.PamDialogPanel;
@@ -51,13 +52,21 @@ public class StringDialogPanel implements AnnotationDialogPanel {
note = note.trim();
}
if (note != null && note.length() > 0) {
- StringAnnotation an = (StringAnnotation) pamDataUnit.findDataAnnotation(StringAnnotation.class,
- stringAnnotationType.getAnnotationName());
- if (an == null) {
+ StringAnnotation an;
+ /*
+ * always add a new annotation rather than editing the old one since
+ * the old one will get removed to handle annotation types which really
+ * do need to make a new one each time.
+ */
+
+// = (StringAnnotation) pamDataUnit.findDataAnnotation(StringAnnotation.class,
+// stringAnnotationType.getAnnotationName());
+// if (an == null) {
an = new StringAnnotation(stringAnnotationType);
pamDataUnit.addDataAnnotation(an);
- }
+// }
an.setString(textArea.getText());
+ pamDataUnit.setLastUpdateTime(PamCalendar.getTimeInMillis());
}
return true;
}
diff --git a/src/dataMap/DataMapControl.java b/src/dataMap/DataMapControl.java
index 1005e999..af4de85e 100644
--- a/src/dataMap/DataMapControl.java
+++ b/src/dataMap/DataMapControl.java
@@ -8,7 +8,6 @@ import java.util.ArrayList;
import javax.swing.SwingUtilities;
import pamScrollSystem.AbstractScrollManager;
-
import generalDatabase.DBControlUnit;
import binaryFileStorage.BinaryStore;
import dataMap.layoutFX.DataMapGUIFX;
@@ -240,6 +239,32 @@ public class DataMapControl extends PamControlledUnit implements PamSettings {
public ArrayList getMappedDataBlocks() {
return mappedDataBlocks;
}
+
+ /**
+ * Update a single data map. Useful when bringing in data
+ * from 'non standard' sources. Check overall time limits and
+ * redraw, but no total map creation.
+ * @param singleDataMap
+ */
+ public void updateSingleDataMap(OfflineDataMap> singleDataMap) {
+ long newLastTime = singleDataMap.getLastDataTime();
+ long newFirstTime = singleDataMap.getFirstDataTime();
+ if (mappedDataBlocks == null) {
+ return;
+ }
+ for (PamDataBlock aBlock : mappedDataBlocks) {
+ int nMaps = aBlock.getNumOfflineDataMaps();
+ for (int iMap = 0; iMap < nMaps; iMap++) {
+ OfflineDataMap aMap = aBlock.getOfflineDataMap(iMap);
+ newFirstTime = Math.min(newFirstTime, aMap.getFirstDataTime());
+ newLastTime = Math.max(newLastTime, aMap.getLastDataTime());
+ }
+ }
+ firstTime = newFirstTime;
+ lastTime = newLastTime;
+ dataMapPanel.repaintAll();
+ dataMapPanel.getSummaryPanel().newDataSources();
+ }
/**
* @return the firstTime for any data in any data block
diff --git a/src/dataMap/DataMapPanel.java b/src/dataMap/DataMapPanel.java
index f5331804..7074ac9d 100644
--- a/src/dataMap/DataMapPanel.java
+++ b/src/dataMap/DataMapPanel.java
@@ -167,5 +167,12 @@ public class DataMapPanel extends PamBorderPanel implements PamTabPanel {
}
summaryPanel.newDataSources();
}
+
+ /**
+ * @return the summaryPanel
+ */
+ public SummaryPanel getSummaryPanel() {
+ return summaryPanel;
+ }
}
diff --git a/src/warnings/SingleLineWarningDisplay.java b/src/warnings/SingleLineWarningDisplay.java
index 69b70b2a..1765f372 100644
--- a/src/warnings/SingleLineWarningDisplay.java
+++ b/src/warnings/SingleLineWarningDisplay.java
@@ -67,7 +67,8 @@ public class SingleLineWarningDisplay implements WarningDisplay {
lastWarning.setToolTipText(null);
}
else {
- String str = String.format("Warning: %s-%s ", w.getWarningSource(), w.getWarningMessage());
+ String str = w.getWarnignLevel() > 0 ? "Warning: " : "";
+ str += String.format("%s-%s ", w.getWarningSource(), w.getWarningMessage());
lastWarning.setText(str);
lastWarning.setWarningLevel(w.getWarnignLevel());
lastWarning.setToolTipText(w.getWarningTip());
From 768840c76e63b5ee9dc241f851ebb5bb54325b71 Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Mon, 13 Jun 2022 09:25:00 +0100
Subject: [PATCH 23/37] ROCCA bug - I missed one setting of RawDataLifeTime.
Have updated
---
src/rocca/RoccaProcess.java | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/rocca/RoccaProcess.java b/src/rocca/RoccaProcess.java
index 86b5502b..f49ff04d 100644
--- a/src/rocca/RoccaProcess.java
+++ b/src/rocca/RoccaProcess.java
@@ -742,7 +742,6 @@ public class RoccaProcess extends PamProcess {
PamUtils.makeChannelMap(lowestChanList));
int firstIndx = prdb.getUnitIndex(firstRDU);
if (firstIndx==-1) {
- System.out.println("RoccaProcess: Cannot determine firstIndx, raw data lifetime = " + prdb.getNaturalLifetimeMillis() + " ms");
int newTime;
if (prdb.getNaturalLifetimeMillis() > Integer.MAX_VALUE/2) {
newTime = Integer.MAX_VALUE;
@@ -751,6 +750,7 @@ public class RoccaProcess extends PamProcess {
}
// stop it getting silly.
newTime = Math.min(newTime, roccaControl.getMaxDataKeepTime());
+ System.out.println("RoccaProcess: Cannot determine firstIndx, raw data lifetime = " + prdb.getNaturalLifetimeMillis() + " ms");
prdb.setNaturalLifetimeMillis(newTime); // increase the lifetime to try and prevent this from happening again
return null;
}
@@ -777,13 +777,14 @@ public class RoccaProcess extends PamProcess {
PamUtils.makeChannelMap(highestChanList));
int lastIndx = prdb.getUnitIndex(lastRDU);
if (lastIndx==-1) {
- System.out.println("RoccaProcess: Cannot determine lastIndx, raw data lifetime = " + prdb.getNaturalLifetimeMillis() + " ms");
int newTime;
if (prdb.getNaturalLifetimeMillis() > Integer.MAX_VALUE/2) {
newTime = Integer.MAX_VALUE;
} else {
newTime = prdb.getNaturalLifetimeMillis()*2;
}
+ newTime = Math.min(newTime, roccaControl.getMaxDataKeepTime());
+ System.out.println("RoccaProcess: Cannot determine lastIndx, raw data lifetime = " + prdb.getNaturalLifetimeMillis() + " ms");
prdb.setNaturalLifetimeMillis(newTime); // increase the lifetime to try and prevent this from happening again
return null;
}
From b5eb1b843cada41a83e38a639923a09fd711e0e7 Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Tue, 14 Jun 2022 17:34:07 +0100
Subject: [PATCH 24/37] Several small bug fixes to support annotating super
detectoins of super detections
---
.../overlaymark/ExtMouseAdapter.java | 3 ++-
.../overlaymark/OverlayMarker.java | 2 --
.../modifier/SuperDetSymbolWrapper.java | 3 ++-
src/PamguardMVC/PamDataUnit.java | 26 +++++++++++++++++++
.../handler/AnnotationChoiceHandler.java | 11 ++++++++
src/generalDatabase/PamTableItem.java | 6 ++++-
src/offlineProcessing/OfflineTask.java | 12 ++++++++-
7 files changed, 57 insertions(+), 6 deletions(-)
diff --git a/src/PamView/paneloverlay/overlaymark/ExtMouseAdapter.java b/src/PamView/paneloverlay/overlaymark/ExtMouseAdapter.java
index d06d0041..dcac5902 100644
--- a/src/PamView/paneloverlay/overlaymark/ExtMouseAdapter.java
+++ b/src/PamView/paneloverlay/overlaymark/ExtMouseAdapter.java
@@ -87,7 +87,8 @@ public class ExtMouseAdapter {
}
final public boolean mouseWheelMoved(MouseWheelEvent e) {
- return mouseWheelMoved(fxScroll(e));
+// return mouseWheelMoved(fxScroll(e));
+ return false;
}
// private MouseEvent swingMouse(javafx.scene.input.MouseEvent e) {
diff --git a/src/PamView/paneloverlay/overlaymark/OverlayMarker.java b/src/PamView/paneloverlay/overlaymark/OverlayMarker.java
index 3dc591f9..c6ad2ad6 100644
--- a/src/PamView/paneloverlay/overlaymark/OverlayMarker.java
+++ b/src/PamView/paneloverlay/overlaymark/OverlayMarker.java
@@ -610,8 +610,6 @@ abstract public class OverlayMarker extends ExtMouseAdapter implements MarkManag
}
}
-// Debug.out.printf("OverlayMarker: _ 2 In getSelectedMarkedDataUnits with %d available units\n", selectedData.size());
-
return selectedData;
}
diff --git a/src/PamView/symbol/modifier/SuperDetSymbolWrapper.java b/src/PamView/symbol/modifier/SuperDetSymbolWrapper.java
index b498bf69..e4bfda42 100644
--- a/src/PamView/symbol/modifier/SuperDetSymbolWrapper.java
+++ b/src/PamView/symbol/modifier/SuperDetSymbolWrapper.java
@@ -32,12 +32,13 @@ public class SuperDetSymbolWrapper extends SymbolModifier {
@Override
public SymbolData getSymbolData(GeneralProjector projector, PamDataUnit dataUnit) {
- PamDataUnit superDet = dataUnit.getSuperDetection(superDetDataBlock);
+ PamDataUnit superDet = dataUnit.getSuperDetection(superDetDataBlock, true);
if (superDet == null) {
return null;
}
return superDetModifier.getSymbolData(getSymbolChooser().getProjector(), superDet);
}
+
@Override
public String getToolTipText() {
diff --git a/src/PamguardMVC/PamDataUnit.java b/src/PamguardMVC/PamDataUnit.java
index 2a9994a6..829ec1ab 100644
--- a/src/PamguardMVC/PamDataUnit.java
+++ b/src/PamguardMVC/PamDataUnit.java
@@ -1292,6 +1292,32 @@ abstract public class PamDataUnit
return null;
}
+ /**
+ * find a super detection form the parent data block of the super detection.
+ * @param superDataBlock data block of super detection
+ * @param allowSuperSuper Allow iteration through mutilple super detection layers
+ * @return data unit from that block, or null.
+ */
+ public SuperDetection getSuperDetection(PamDataBlock superDataBlock, boolean allowSuperSuper) {
+ synchronized (superDetectionSyncronisation) {
+ if (superDetections == null) return null;
+ SuperDetection superDet;
+ for (int i = 0; i < superDetections.size(); i++) {
+ superDet = superDetections.get(i);
+ if (superDet.getParentDataBlock() == superDataBlock) {
+ return superDet;
+ }
+ if (allowSuperSuper) {
+ SuperDetection supersuper = superDet.getSuperDetection(superDataBlock, allowSuperSuper);
+ if (supersuper != null) {
+ return supersuper;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
public SuperDetection getSuperDetection(int ind) {
synchronized (superDetectionSyncronisation) {
if (superDetections == null || superDetections.size()<=ind) return null;
diff --git a/src/annotation/handler/AnnotationChoiceHandler.java b/src/annotation/handler/AnnotationChoiceHandler.java
index 929903e0..911cd359 100644
--- a/src/annotation/handler/AnnotationChoiceHandler.java
+++ b/src/annotation/handler/AnnotationChoiceHandler.java
@@ -146,6 +146,17 @@ public abstract class AnnotationChoiceHandler extends AnnotationHandler {
* @param annotationType
*/
public boolean updateAnnotation(PamDataUnit pamDataUnit, DataAnnotationType annotationType) {
+ /*
+ * need to check this is actually the right data unit, which matches the datablock of
+ * this annotatoin handler. Gets very confused when dealing with superdetections
+ */
+ if (pamDataUnit.getParentDataBlock() != this.getPamDataBlock()) {
+ pamDataUnit = pamDataUnit.getSuperDetection(getPamDataBlock(), true);
+ if (pamDataUnit == null) {
+ return false;
+ }
+ }
+
DataAnnotation existingAnnotation = pamDataUnit.findDataAnnotation(annotationType.getAnnotationClass(), annotationType.getAnnotationName());
boolean changed = false;
if (annotationType.canAutoAnnotate()) {
diff --git a/src/generalDatabase/PamTableItem.java b/src/generalDatabase/PamTableItem.java
index 27a04d0d..1b75fded 100644
--- a/src/generalDatabase/PamTableItem.java
+++ b/src/generalDatabase/PamTableItem.java
@@ -426,7 +426,11 @@ public class PamTableItem implements Cloneable {
return (Double) value;
}
-
+ /**
+ * Get a float value, being aware that some DBMS may have
+ * decided to store as a Double anyway. Return Float.NaN for null data
+ * @return float value or NaN
+ */
public float getFloatValue() {
if (value == null) {
return Float.NaN;
diff --git a/src/offlineProcessing/OfflineTask.java b/src/offlineProcessing/OfflineTask.java
index 0905a765..a5ca3ac1 100644
--- a/src/offlineProcessing/OfflineTask.java
+++ b/src/offlineProcessing/OfflineTask.java
@@ -4,6 +4,7 @@ import generalDatabase.DBControlUnit;
import generalDatabase.PamConnection;
import generalDatabase.SQLLogging;
import generalDatabase.SQLTypes;
+import generalDatabase.SuperDetLogging;
import generalDatabase.clauses.FixedClause;
import generalDatabase.clauses.FromClause;
import generalDatabase.clauses.PAMSelectClause;
@@ -354,6 +355,7 @@ public abstract class OfflineTask {
}
aBlock.clearAll();
+
SQLLogging logging = aBlock.getLogging();
if (logging == null) {
@@ -382,7 +384,15 @@ public abstract class OfflineTask {
System.out.println("Unknown data selection option in OfflineTask.deleteOldData: " + taskGroupParams.dataChoice);
return;
}
- logging.deleteData(clause);
+ while (logging != null) {
+ logging.deleteData(clause);
+ if (logging instanceof SuperDetLogging) {
+ logging = ((SuperDetLogging) logging).getSubLogging();
+ }
+ else {
+ break;
+ }
+ }
}
From be3dee2e3cfa54d56ddef6020451082ee914b8eb Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Tue, 14 Jun 2022 17:48:27 +0100
Subject: [PATCH 25/37] Functions to more easily put dialogs close to where
mouse is
---
src/PamView/dialog/PamDialog.java | 36 +++++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
diff --git a/src/PamView/dialog/PamDialog.java b/src/PamView/dialog/PamDialog.java
index 4a1b12e1..90d966af 100644
--- a/src/PamView/dialog/PamDialog.java
+++ b/src/PamView/dialog/PamDialog.java
@@ -3,10 +3,14 @@ package PamView.dialog;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dialog;
+import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
+import java.awt.MouseInfo;
+import java.awt.Point;
import java.awt.Rectangle;
+import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -225,6 +229,9 @@ abstract public class PamDialog extends JDialog {
synchronized (this) {
PamColors.getInstance().notifyContianer(this.getContentPane());
}
+ if (getOwner() == null) {
+ moveToMouseLocation();
+ }
}
try{
super.setVisible(visible);
@@ -235,6 +242,35 @@ abstract public class PamDialog extends JDialog {
}
}
+ /**
+ * put the dialog near the mouse location.
+ */
+ public void moveToMouseLocation() {
+ Point mouse = MouseInfo.getPointerInfo().getLocation();
+ moveToLocation(mouse);
+ }
+
+ public void moveToLocation(Point point) {
+ if (point == null) {
+ return;
+ }
+ // check we're not going too far off the screen.
+ Dimension sz = getPreferredSize();
+ Dimension screen = null;
+ if (getOwner() != null) {
+ screen = getOwner().getSize();
+ }
+ else {
+ screen = Toolkit.getDefaultToolkit().getScreenSize();
+ }
+ point.y = Math.min(point.y, screen.height-sz.height-10);
+ point.y = Math.max(point.y, 0);
+ point.x = Math.min(point.x, screen.width-sz.width-10);
+ point.x = Math.max(point.x, 0);
+
+ setLocation(point);
+ }
+
/**
* Reschedule closing of the window to happen
* on the AWT thread using SwingUtilities.invokeLater(...)
From 0c3cd2995b30fc1a20b6d51d378ff96e2f608af8 Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Fri, 17 Jun 2022 09:51:44 +0100
Subject: [PATCH 26/37] Global arguments to set params in acquisition and
database.
---
src/Acquisition/FolderInputSystem.java | 21 ++++
.../filedate/StandardFileDate.java | 21 ++++
src/generalDatabase/DBControl.java | 2 +
.../sqlite/SqliteDialogPanel.java | 60 +---------
src/generalDatabase/sqlite/SqliteSystem.java | 107 +++++++++++++++++-
src/group3dlocaliser/Group3DProcess.java | 2 +
.../grouper/DetectionGrouper.java | 10 +-
.../grouper/FirstGrouping.java | 10 ++
src/pamguard/Pamguard.java | 13 ++-
9 files changed, 183 insertions(+), 63 deletions(-)
diff --git a/src/Acquisition/FolderInputSystem.java b/src/Acquisition/FolderInputSystem.java
index c9f276cd..227ff2d1 100644
--- a/src/Acquisition/FolderInputSystem.java
+++ b/src/Acquisition/FolderInputSystem.java
@@ -27,6 +27,7 @@ import Acquisition.layoutFX.AcquisitionPaneFX;
import Acquisition.layoutFX.DAQSettingsPane;
import Acquisition.layoutFX.FolderInputPane;
import javafx.application.Platform;
+import pamguard.GlobalArguments;
import Acquisition.pamAudio.PamAudioSystem;
import PamController.PamControlledUnitSettings;
import PamController.PamController;
@@ -77,6 +78,8 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings{
protected long eta = -1;
private FolderInputParameters folderInputParameters;
+
+ public static final String GlobalWavFolderArg = "wavfilefolder";
/**
@@ -110,12 +113,30 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings{
if (folderInputParameters == null)
setFolderInputParameters(new FolderInputParameters(getSystemType()));
// PamSettingManager.getInstance().registerSettings(this); //calling super already registers this in the FileInputSystem constructor
+ checkComandLine();
makeSelFileList();
newFileTimer = new Timer(1000, new RestartTimer());
newFileTimer.setRepeats(false);
// timer = new Timer(1000, new TimerAction());
}
+ /**
+ * Check to see if acquisition source folder was set in the command line.
+ */
+ private void checkComandLine() {
+ String globalFolder = GlobalArguments.getParam(GlobalWavFolderArg);
+ if (globalFolder == null) {
+ return;
+ }
+ // see if it at least exists, though will we want to do this for Network folders ?
+ File aFile = new File(globalFolder);
+ if (aFile.exists() == false) {
+ System.err.println("Command line folder does not exist: " + globalFolder);
+ }
+ String[] selList = {globalFolder};
+ folderInputParameters.setSelectedFiles(selList);
+ }
+
/**
* Restarts after a file has ended when processing multiple files.
* 27 Jan 2011 - this now reschedules in the AWT thread
diff --git a/src/Acquisition/filedate/StandardFileDate.java b/src/Acquisition/filedate/StandardFileDate.java
index 778bfccd..8fa56de6 100644
--- a/src/Acquisition/filedate/StandardFileDate.java
+++ b/src/Acquisition/filedate/StandardFileDate.java
@@ -249,6 +249,18 @@ public class StandardFileDate implements FileDate, PamSettings {
String name = file.getName();
name = removeWildChars(name, forcedDateFormat);
String redFormat = forcedDateFormat.replace("#", "");
+ // see if it's only all milliseconds, i.e. format is only 'S's and > 12 of them
+ if (allSSSS(redFormat)) {
+ // try pulling a number from the name.
+ try {
+ long millis = Long.valueOf(name);
+ return millis;
+ }
+ catch (NumberFormatException e) {
+
+ }
+ }
+
SimpleDateFormat sdf = null;
try {
sdf = new SimpleDateFormat(redFormat);
@@ -271,6 +283,15 @@ public class StandardFileDate implements FileDate, PamSettings {
return d.getTime();
}
+ private boolean allSSSS(String redFormat) {
+ for(int i = 0; i < redFormat.length(); i++) {
+ if (redFormat.charAt(i) != 'S') {
+ return false;
+ }
+ }
+ return true;
+ }
+
private String removeWildChars(String name, String forcedDateFormat) {
// # is the wild field i s#
if (name == null || forcedDateFormat == null) {
diff --git a/src/generalDatabase/DBControl.java b/src/generalDatabase/DBControl.java
index d8ffd9c6..031d8232 100644
--- a/src/generalDatabase/DBControl.java
+++ b/src/generalDatabase/DBControl.java
@@ -91,6 +91,8 @@ PamSettingsSource {
private boolean fullTablesCheck = false;
static private String dbUnitType = "Pamguard Database";
+
+ static public final String GlobalDatabaseNameArg = "-databasefile";
private DBControl THIS;
diff --git a/src/generalDatabase/sqlite/SqliteDialogPanel.java b/src/generalDatabase/sqlite/SqliteDialogPanel.java
index 656cc9f9..b9e17a27 100644
--- a/src/generalDatabase/sqlite/SqliteDialogPanel.java
+++ b/src/generalDatabase/sqlite/SqliteDialogPanel.java
@@ -91,69 +91,15 @@ public class SqliteDialogPanel implements SystemDialogPanel {
String newDB = sqliteSystem.browseDatabases(parent);
if (newDB != null) {
-
- // see if this file exists in the list and if it does, remove it
- for (int i = 0; i < sqliteSystem.getRecentDatabases().size(); i++) {
- if (sqliteSystem.getRecentDatabases().get(i).toString().equalsIgnoreCase(newDB)) {
- sqliteSystem.getRecentDatabases().remove(i);
- }
- }
- // then insert the file at the top of the list.
- File newFile = new File(newDB);
- // if the file doesn't exit, consider creating it.
- if (newFile.exists() == false) {
- newFile = createNewDatabase(newDB);
- if (newFile == null) {
- System.out.println("Unable to create "+newFile);
- return;
- }
-
- }
-
- sqliteSystem.getRecentDatabases().add(0, newFile);
+ sqliteSystem.setDatabaseName(newDB);
+
setParams();
-
}
}
}
- public File createNewDatabase(String newDB) {
-
- File newFile = new File(newDB);
- newFile = PamFileFilter.checkFileEnd(newFile, ".sqlite3", true);
-
- int ans = JOptionPane.showConfirmDialog(parent, "Create blank database " + newFile.getAbsolutePath() + " ?", "Sqlite", JOptionPane.OK_CANCEL_OPTION);
- if (ans == JOptionPane.CANCEL_OPTION) {
- return null;
- }
- Connection connection = null;
-
- try {
- // create a database connection;
- // Sqlite will automatically create file if it does not exist;
- connection = DriverManager.getConnection("jdbc:sqlite:" + newFile);
-
- }
- catch(SQLException e)
- {
- System.err.println(e.getMessage());
- }
- finally
- {
- try
- {
- if(connection != null)
- connection.close();
- }
- catch(SQLException e)
- {
- // connection close failed.
- System.err.println(e);
- }
- }
- return newFile;
- }
+
}
diff --git a/src/generalDatabase/sqlite/SqliteSystem.java b/src/generalDatabase/sqlite/SqliteSystem.java
index 5b1926e0..2bb92d33 100644
--- a/src/generalDatabase/sqlite/SqliteSystem.java
+++ b/src/generalDatabase/sqlite/SqliteSystem.java
@@ -3,6 +3,7 @@ package generalDatabase.sqlite;
import generalDatabase.pamCursor.NonScrollablePamCursor;
import generalDatabase.pamCursor.PamCursor;
import javafx.stage.FileChooser;
+import pamguard.GlobalArguments;
import java.awt.Component;
import java.awt.Desktop;
@@ -10,10 +11,12 @@ import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.sql.Connection;
+import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
import org.sqlite.SQLiteConfig;
@@ -82,6 +85,53 @@ public class SqliteSystem extends DBSystem implements PamSettings {
if (sqliteParameters.getRecentDatabases() == null) {
sqliteParameters.setRecentDatabases(new ArrayList());
}
+ checkCommandLineOption();
+ }
+
+ /**
+ * Check to see if the database name was included as a command line option,
+ * in which case, put it at the top of the list. this is better than just using
+ * it,since it then gets stored within it's own settings.
+ */
+ private void checkCommandLineOption() {
+ // TODO Auto-generated method stub
+ /*
+ * If a database name was passed as a global argument, then use the passed name instead of
+ * the name in the list of recent databases.
+ */
+ String commandName = GlobalArguments.getParam(DBControl.GlobalDatabaseNameArg);
+ if (commandName == null) {
+ return;
+ }
+ setDatabaseName(commandName);
+ }
+
+ /**
+ * Set the database name, check it exists, check it's end
+ * and add to top of list of databases.
+ * @param databaseName
+ */
+ public void setDatabaseName(String databaseName) {
+ // see if this file exists in the list and if it does, remove it
+ for (int i = 0; i < getRecentDatabases().size(); i++) {
+ if (getRecentDatabases().get(i).toString().equalsIgnoreCase(databaseName)) {
+ getRecentDatabases().remove(i);
+ }
+ }
+ // then insert the file at the top of the list.
+ File newFile = new File(databaseName);
+ // if the file doesn't exit, consider creating it.
+ if (newFile.exists() == false) {
+ newFile = createNewDatabase(databaseName, null, true);
+ if (newFile == null) {
+ System.out.println("Unable to create "+newFile);
+ return;
+ }
+
+ }
+
+ getRecentDatabases().add(0, newFile);
+
}
@Override
@@ -111,6 +161,52 @@ public class SqliteSystem extends DBSystem implements PamSettings {
}
return null;
}
+
+ /**
+ * Create a new empty database file.
+ * @param newDB full path for database file (can be missing .sqlit3 if you like - this will get checked and added).
+ * @param parent window (for confirm dialog, can be null)
+ * @param askFirst show a confirm dialog before creating the database file.
+ * @return a path to the file, whether created or no.
+ */
+ public File createNewDatabase(String newDB, Component parent, boolean askFirst) {
+
+ File newFile = new File(newDB);
+ newFile = PamFileFilter.checkFileEnd(newFile, ".sqlite3", true);
+
+ if (askFirst) {
+ int ans = JOptionPane.showConfirmDialog(parent, "Create blank database " + newFile.getAbsolutePath() + " ?", "Sqlite", JOptionPane.OK_CANCEL_OPTION);
+ if (ans == JOptionPane.CANCEL_OPTION) {
+ return null;
+ }
+ }
+ Connection connection = null;
+
+ try {
+ // create a database connection;
+ // Sqlite will automatically create file if it does not exist;
+ connection = DriverManager.getConnection("jdbc:sqlite:" + newFile);
+
+ }
+ catch(SQLException e)
+ {
+ System.err.println(e.getMessage());
+ }
+ finally
+ {
+ try
+ {
+ if(connection != null)
+ connection.close();
+ }
+ catch(SQLException e)
+ {
+ // connection close failed.
+ System.err.println(e);
+ }
+ }
+ return newFile;
+ }
@Override
public boolean canCreate() {
@@ -208,6 +304,15 @@ public class SqliteSystem extends DBSystem implements PamSettings {
@Override
public String getDatabaseName() {
+ /*
+ * If a database name was passed as a global argument, then use the passed name instead of
+ * the name in the list of recent databases.
+ */
+ String commandName = GlobalArguments.getParam(DBControl.GlobalDatabaseNameArg);
+ if (commandName != null) {
+ return commandName;
+ }
+
if (getRecentDatabases() == null) return null;
if (getRecentDatabases().size() < 1) return null;
return getRecentDatabases().get(0).getAbsolutePath();
@@ -271,7 +376,7 @@ public class SqliteSystem extends DBSystem implements PamSettings {
public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
Object settings = pamControlledUnitSettings.getSettings();
- if (settings instanceof ArrayList) {
+ if (settings instanceof ArrayList) { // deal with old format which just stored a list.
sqliteParameters.getRecentDatabases().clear();
sqliteParameters.getRecentDatabases().addAll((ArrayList) settings);
}
diff --git a/src/group3dlocaliser/Group3DProcess.java b/src/group3dlocaliser/Group3DProcess.java
index 45d2f466..7822e346 100644
--- a/src/group3dlocaliser/Group3DProcess.java
+++ b/src/group3dlocaliser/Group3DProcess.java
@@ -193,6 +193,7 @@ public class Group3DProcess extends PamProcess implements DetectionGroupMonitor
// will have to make a data unit for each group now...
Group3DDataUnit[] group3dDataUnits = new Group3DDataUnit[nGroups];
+// System.out.println("Enter newGRoupedDataSet with groups: " + detectionGroupedSet.getNumGroups());
// if (detectionGroupedSet.hasUID(14045004731L)) {
// Debug.out.println(" found it");
// }
@@ -209,6 +210,7 @@ public class Group3DProcess extends PamProcess implements DetectionGroupMonitor
// localiserAlgorithm3D.process(detectionGroupedSet.getGroup(i));
abstractLocalisation = localiserAlgorithm3D.runModel(group3dDataUnits[i], null, false);
if (abstractLocalisation == null) {
+ System.out.println("Group 3D process null localisation from " + localiserAlgorithm3D.getName());
continue;
}
// log all outputs ..
diff --git a/src/group3dlocaliser/grouper/DetectionGrouper.java b/src/group3dlocaliser/grouper/DetectionGrouper.java
index 6ad9bf38..c5ce50aa 100644
--- a/src/group3dlocaliser/grouper/DetectionGrouper.java
+++ b/src/group3dlocaliser/grouper/DetectionGrouper.java
@@ -160,9 +160,15 @@ public class DetectionGrouper {
if (motherGroup.getTotalChannelMap() == 0) {
return;
}
-// if (maybeCloseMotherGroup(0, sampleNumber - (long) (sampleRate / 2))) {
+// motherGroup.
+// int lastGroup = motherGroup.getLastChannelGroup();
+ long buffer = (long) this.maxInterGroupSample;
+// if (shouldCloseMotherGroup(lastGroup, sampleNumber, buffer)) {
+ if (sampleNumber > motherGroup.getVeryLastSample() + buffer + sampleRate) {
+ closeMotherGroup();
+// if (maybeCloseMotherGroup(motherGroup.getLastChannelGroup(), sampleNumber - (long) (sampleRate / 2))) {
// System.out.println("Mother group closed on timer");
-// }
+ }
}
private synchronized boolean maybeCloseMotherGroup(int iChanGroup, long currentSample) {
diff --git a/src/group3dlocaliser/grouper/FirstGrouping.java b/src/group3dlocaliser/grouper/FirstGrouping.java
index 6cdcd03a..b17be86e 100644
--- a/src/group3dlocaliser/grouper/FirstGrouping.java
+++ b/src/group3dlocaliser/grouper/FirstGrouping.java
@@ -24,6 +24,8 @@ public class FirstGrouping {
private long veryLastSample;
private int[] groupCount;
+
+ private int lastChannelGroup;
public FirstGrouping(int nChannelGroups, int channelGroup, PamDataUnit pamDataUnit) {
this.nChannelGroups = nChannelGroups;
@@ -44,6 +46,7 @@ public class FirstGrouping {
lastSamples[channelGroup] += pamDataUnit.getSampleDuration();
}
veryLastSample = Math.max(veryLastSample, lastSamples[channelGroup]);
+ lastChannelGroup = channelGroup;
}
// /**
@@ -92,4 +95,11 @@ public class FirstGrouping {
return dataUnits;
}
+ /**
+ * @return the lastChannelGroup
+ */
+ public int getLastChannelGroup() {
+ return lastChannelGroup;
+ }
+
}
diff --git a/src/pamguard/Pamguard.java b/src/pamguard/Pamguard.java
index 3c63090e..0e19e4e3 100644
--- a/src/pamguard/Pamguard.java
+++ b/src/pamguard/Pamguard.java
@@ -23,6 +23,7 @@ package pamguard;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
+import Acquisition.FolderInputSystem;
import PamController.PamController;
import PamController.PamGUIManager;
import PamController.PamSettingManager;
@@ -41,6 +42,8 @@ import PamView.dialog.warn.WarnOnce;
import PamguardMVC.debug.Debug;
import binaryFileStorage.BinaryStore;
import dataPlotsFX.JamieDev;
+import generalDatabase.DBControl;
+
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
@@ -216,11 +219,15 @@ public class Pamguard {
}
else if (anArg.equalsIgnoreCase(BinaryStore.GlobalFolderArg)) {
// output folder for binary files.
- GlobalArguments.setParam(anArg, args[iArg++]);
+ GlobalArguments.setParam(BinaryStore.GlobalFolderArg, args[iArg++]);
}
- else if (anArg.equalsIgnoreCase("-databasefile")) {
+ else if (anArg.equalsIgnoreCase(DBControl.GlobalDatabaseNameArg)) {
// database file name
- GlobalArguments.setParam(anArg, args[iArg++]);
+ GlobalArguments.setParam(DBControl.GlobalDatabaseNameArg, args[iArg++]);
+ }
+ else if (anArg.equalsIgnoreCase(FolderInputSystem.GlobalWavFolderArg)) {
+ // source folder for wav files (or other supported sound files)
+ GlobalArguments.setParam(FolderInputSystem.GlobalWavFolderArg, args[iArg++]);
}
else if (anArg.equalsIgnoreCase("-help")) {
System.out.println("--PamGuard Help");
From a7b2e7522e0f8e191063332083905413d28b45b6 Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Fri, 17 Jun 2022 09:55:18 +0100
Subject: [PATCH 27/37] Global arguments to set params in acquisition and
database. (#37)
---
src/Acquisition/FolderInputSystem.java | 21 ++++
.../filedate/StandardFileDate.java | 21 ++++
src/generalDatabase/DBControl.java | 2 +
.../sqlite/SqliteDialogPanel.java | 60 +---------
src/generalDatabase/sqlite/SqliteSystem.java | 107 +++++++++++++++++-
src/group3dlocaliser/Group3DProcess.java | 2 +
.../grouper/DetectionGrouper.java | 10 +-
.../grouper/FirstGrouping.java | 10 ++
src/pamguard/Pamguard.java | 13 ++-
9 files changed, 183 insertions(+), 63 deletions(-)
diff --git a/src/Acquisition/FolderInputSystem.java b/src/Acquisition/FolderInputSystem.java
index c9f276cd..227ff2d1 100644
--- a/src/Acquisition/FolderInputSystem.java
+++ b/src/Acquisition/FolderInputSystem.java
@@ -27,6 +27,7 @@ import Acquisition.layoutFX.AcquisitionPaneFX;
import Acquisition.layoutFX.DAQSettingsPane;
import Acquisition.layoutFX.FolderInputPane;
import javafx.application.Platform;
+import pamguard.GlobalArguments;
import Acquisition.pamAudio.PamAudioSystem;
import PamController.PamControlledUnitSettings;
import PamController.PamController;
@@ -77,6 +78,8 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings{
protected long eta = -1;
private FolderInputParameters folderInputParameters;
+
+ public static final String GlobalWavFolderArg = "wavfilefolder";
/**
@@ -110,12 +113,30 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings{
if (folderInputParameters == null)
setFolderInputParameters(new FolderInputParameters(getSystemType()));
// PamSettingManager.getInstance().registerSettings(this); //calling super already registers this in the FileInputSystem constructor
+ checkComandLine();
makeSelFileList();
newFileTimer = new Timer(1000, new RestartTimer());
newFileTimer.setRepeats(false);
// timer = new Timer(1000, new TimerAction());
}
+ /**
+ * Check to see if acquisition source folder was set in the command line.
+ */
+ private void checkComandLine() {
+ String globalFolder = GlobalArguments.getParam(GlobalWavFolderArg);
+ if (globalFolder == null) {
+ return;
+ }
+ // see if it at least exists, though will we want to do this for Network folders ?
+ File aFile = new File(globalFolder);
+ if (aFile.exists() == false) {
+ System.err.println("Command line folder does not exist: " + globalFolder);
+ }
+ String[] selList = {globalFolder};
+ folderInputParameters.setSelectedFiles(selList);
+ }
+
/**
* Restarts after a file has ended when processing multiple files.
* 27 Jan 2011 - this now reschedules in the AWT thread
diff --git a/src/Acquisition/filedate/StandardFileDate.java b/src/Acquisition/filedate/StandardFileDate.java
index 778bfccd..8fa56de6 100644
--- a/src/Acquisition/filedate/StandardFileDate.java
+++ b/src/Acquisition/filedate/StandardFileDate.java
@@ -249,6 +249,18 @@ public class StandardFileDate implements FileDate, PamSettings {
String name = file.getName();
name = removeWildChars(name, forcedDateFormat);
String redFormat = forcedDateFormat.replace("#", "");
+ // see if it's only all milliseconds, i.e. format is only 'S's and > 12 of them
+ if (allSSSS(redFormat)) {
+ // try pulling a number from the name.
+ try {
+ long millis = Long.valueOf(name);
+ return millis;
+ }
+ catch (NumberFormatException e) {
+
+ }
+ }
+
SimpleDateFormat sdf = null;
try {
sdf = new SimpleDateFormat(redFormat);
@@ -271,6 +283,15 @@ public class StandardFileDate implements FileDate, PamSettings {
return d.getTime();
}
+ private boolean allSSSS(String redFormat) {
+ for(int i = 0; i < redFormat.length(); i++) {
+ if (redFormat.charAt(i) != 'S') {
+ return false;
+ }
+ }
+ return true;
+ }
+
private String removeWildChars(String name, String forcedDateFormat) {
// # is the wild field i s#
if (name == null || forcedDateFormat == null) {
diff --git a/src/generalDatabase/DBControl.java b/src/generalDatabase/DBControl.java
index d8ffd9c6..031d8232 100644
--- a/src/generalDatabase/DBControl.java
+++ b/src/generalDatabase/DBControl.java
@@ -91,6 +91,8 @@ PamSettingsSource {
private boolean fullTablesCheck = false;
static private String dbUnitType = "Pamguard Database";
+
+ static public final String GlobalDatabaseNameArg = "-databasefile";
private DBControl THIS;
diff --git a/src/generalDatabase/sqlite/SqliteDialogPanel.java b/src/generalDatabase/sqlite/SqliteDialogPanel.java
index 656cc9f9..b9e17a27 100644
--- a/src/generalDatabase/sqlite/SqliteDialogPanel.java
+++ b/src/generalDatabase/sqlite/SqliteDialogPanel.java
@@ -91,69 +91,15 @@ public class SqliteDialogPanel implements SystemDialogPanel {
String newDB = sqliteSystem.browseDatabases(parent);
if (newDB != null) {
-
- // see if this file exists in the list and if it does, remove it
- for (int i = 0; i < sqliteSystem.getRecentDatabases().size(); i++) {
- if (sqliteSystem.getRecentDatabases().get(i).toString().equalsIgnoreCase(newDB)) {
- sqliteSystem.getRecentDatabases().remove(i);
- }
- }
- // then insert the file at the top of the list.
- File newFile = new File(newDB);
- // if the file doesn't exit, consider creating it.
- if (newFile.exists() == false) {
- newFile = createNewDatabase(newDB);
- if (newFile == null) {
- System.out.println("Unable to create "+newFile);
- return;
- }
-
- }
-
- sqliteSystem.getRecentDatabases().add(0, newFile);
+ sqliteSystem.setDatabaseName(newDB);
+
setParams();
-
}
}
}
- public File createNewDatabase(String newDB) {
-
- File newFile = new File(newDB);
- newFile = PamFileFilter.checkFileEnd(newFile, ".sqlite3", true);
-
- int ans = JOptionPane.showConfirmDialog(parent, "Create blank database " + newFile.getAbsolutePath() + " ?", "Sqlite", JOptionPane.OK_CANCEL_OPTION);
- if (ans == JOptionPane.CANCEL_OPTION) {
- return null;
- }
- Connection connection = null;
-
- try {
- // create a database connection;
- // Sqlite will automatically create file if it does not exist;
- connection = DriverManager.getConnection("jdbc:sqlite:" + newFile);
-
- }
- catch(SQLException e)
- {
- System.err.println(e.getMessage());
- }
- finally
- {
- try
- {
- if(connection != null)
- connection.close();
- }
- catch(SQLException e)
- {
- // connection close failed.
- System.err.println(e);
- }
- }
- return newFile;
- }
+
}
diff --git a/src/generalDatabase/sqlite/SqliteSystem.java b/src/generalDatabase/sqlite/SqliteSystem.java
index 5b1926e0..2bb92d33 100644
--- a/src/generalDatabase/sqlite/SqliteSystem.java
+++ b/src/generalDatabase/sqlite/SqliteSystem.java
@@ -3,6 +3,7 @@ package generalDatabase.sqlite;
import generalDatabase.pamCursor.NonScrollablePamCursor;
import generalDatabase.pamCursor.PamCursor;
import javafx.stage.FileChooser;
+import pamguard.GlobalArguments;
import java.awt.Component;
import java.awt.Desktop;
@@ -10,10 +11,12 @@ import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.sql.Connection;
+import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
import org.sqlite.SQLiteConfig;
@@ -82,6 +85,53 @@ public class SqliteSystem extends DBSystem implements PamSettings {
if (sqliteParameters.getRecentDatabases() == null) {
sqliteParameters.setRecentDatabases(new ArrayList());
}
+ checkCommandLineOption();
+ }
+
+ /**
+ * Check to see if the database name was included as a command line option,
+ * in which case, put it at the top of the list. this is better than just using
+ * it,since it then gets stored within it's own settings.
+ */
+ private void checkCommandLineOption() {
+ // TODO Auto-generated method stub
+ /*
+ * If a database name was passed as a global argument, then use the passed name instead of
+ * the name in the list of recent databases.
+ */
+ String commandName = GlobalArguments.getParam(DBControl.GlobalDatabaseNameArg);
+ if (commandName == null) {
+ return;
+ }
+ setDatabaseName(commandName);
+ }
+
+ /**
+ * Set the database name, check it exists, check it's end
+ * and add to top of list of databases.
+ * @param databaseName
+ */
+ public void setDatabaseName(String databaseName) {
+ // see if this file exists in the list and if it does, remove it
+ for (int i = 0; i < getRecentDatabases().size(); i++) {
+ if (getRecentDatabases().get(i).toString().equalsIgnoreCase(databaseName)) {
+ getRecentDatabases().remove(i);
+ }
+ }
+ // then insert the file at the top of the list.
+ File newFile = new File(databaseName);
+ // if the file doesn't exit, consider creating it.
+ if (newFile.exists() == false) {
+ newFile = createNewDatabase(databaseName, null, true);
+ if (newFile == null) {
+ System.out.println("Unable to create "+newFile);
+ return;
+ }
+
+ }
+
+ getRecentDatabases().add(0, newFile);
+
}
@Override
@@ -111,6 +161,52 @@ public class SqliteSystem extends DBSystem implements PamSettings {
}
return null;
}
+
+ /**
+ * Create a new empty database file.
+ * @param newDB full path for database file (can be missing .sqlit3 if you like - this will get checked and added).
+ * @param parent window (for confirm dialog, can be null)
+ * @param askFirst show a confirm dialog before creating the database file.
+ * @return a path to the file, whether created or no.
+ */
+ public File createNewDatabase(String newDB, Component parent, boolean askFirst) {
+
+ File newFile = new File(newDB);
+ newFile = PamFileFilter.checkFileEnd(newFile, ".sqlite3", true);
+
+ if (askFirst) {
+ int ans = JOptionPane.showConfirmDialog(parent, "Create blank database " + newFile.getAbsolutePath() + " ?", "Sqlite", JOptionPane.OK_CANCEL_OPTION);
+ if (ans == JOptionPane.CANCEL_OPTION) {
+ return null;
+ }
+ }
+ Connection connection = null;
+
+ try {
+ // create a database connection;
+ // Sqlite will automatically create file if it does not exist;
+ connection = DriverManager.getConnection("jdbc:sqlite:" + newFile);
+
+ }
+ catch(SQLException e)
+ {
+ System.err.println(e.getMessage());
+ }
+ finally
+ {
+ try
+ {
+ if(connection != null)
+ connection.close();
+ }
+ catch(SQLException e)
+ {
+ // connection close failed.
+ System.err.println(e);
+ }
+ }
+ return newFile;
+ }
@Override
public boolean canCreate() {
@@ -208,6 +304,15 @@ public class SqliteSystem extends DBSystem implements PamSettings {
@Override
public String getDatabaseName() {
+ /*
+ * If a database name was passed as a global argument, then use the passed name instead of
+ * the name in the list of recent databases.
+ */
+ String commandName = GlobalArguments.getParam(DBControl.GlobalDatabaseNameArg);
+ if (commandName != null) {
+ return commandName;
+ }
+
if (getRecentDatabases() == null) return null;
if (getRecentDatabases().size() < 1) return null;
return getRecentDatabases().get(0).getAbsolutePath();
@@ -271,7 +376,7 @@ public class SqliteSystem extends DBSystem implements PamSettings {
public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
Object settings = pamControlledUnitSettings.getSettings();
- if (settings instanceof ArrayList) {
+ if (settings instanceof ArrayList) { // deal with old format which just stored a list.
sqliteParameters.getRecentDatabases().clear();
sqliteParameters.getRecentDatabases().addAll((ArrayList) settings);
}
diff --git a/src/group3dlocaliser/Group3DProcess.java b/src/group3dlocaliser/Group3DProcess.java
index 45d2f466..7822e346 100644
--- a/src/group3dlocaliser/Group3DProcess.java
+++ b/src/group3dlocaliser/Group3DProcess.java
@@ -193,6 +193,7 @@ public class Group3DProcess extends PamProcess implements DetectionGroupMonitor
// will have to make a data unit for each group now...
Group3DDataUnit[] group3dDataUnits = new Group3DDataUnit[nGroups];
+// System.out.println("Enter newGRoupedDataSet with groups: " + detectionGroupedSet.getNumGroups());
// if (detectionGroupedSet.hasUID(14045004731L)) {
// Debug.out.println(" found it");
// }
@@ -209,6 +210,7 @@ public class Group3DProcess extends PamProcess implements DetectionGroupMonitor
// localiserAlgorithm3D.process(detectionGroupedSet.getGroup(i));
abstractLocalisation = localiserAlgorithm3D.runModel(group3dDataUnits[i], null, false);
if (abstractLocalisation == null) {
+ System.out.println("Group 3D process null localisation from " + localiserAlgorithm3D.getName());
continue;
}
// log all outputs ..
diff --git a/src/group3dlocaliser/grouper/DetectionGrouper.java b/src/group3dlocaliser/grouper/DetectionGrouper.java
index 6ad9bf38..c5ce50aa 100644
--- a/src/group3dlocaliser/grouper/DetectionGrouper.java
+++ b/src/group3dlocaliser/grouper/DetectionGrouper.java
@@ -160,9 +160,15 @@ public class DetectionGrouper {
if (motherGroup.getTotalChannelMap() == 0) {
return;
}
-// if (maybeCloseMotherGroup(0, sampleNumber - (long) (sampleRate / 2))) {
+// motherGroup.
+// int lastGroup = motherGroup.getLastChannelGroup();
+ long buffer = (long) this.maxInterGroupSample;
+// if (shouldCloseMotherGroup(lastGroup, sampleNumber, buffer)) {
+ if (sampleNumber > motherGroup.getVeryLastSample() + buffer + sampleRate) {
+ closeMotherGroup();
+// if (maybeCloseMotherGroup(motherGroup.getLastChannelGroup(), sampleNumber - (long) (sampleRate / 2))) {
// System.out.println("Mother group closed on timer");
-// }
+ }
}
private synchronized boolean maybeCloseMotherGroup(int iChanGroup, long currentSample) {
diff --git a/src/group3dlocaliser/grouper/FirstGrouping.java b/src/group3dlocaliser/grouper/FirstGrouping.java
index 6cdcd03a..b17be86e 100644
--- a/src/group3dlocaliser/grouper/FirstGrouping.java
+++ b/src/group3dlocaliser/grouper/FirstGrouping.java
@@ -24,6 +24,8 @@ public class FirstGrouping {
private long veryLastSample;
private int[] groupCount;
+
+ private int lastChannelGroup;
public FirstGrouping(int nChannelGroups, int channelGroup, PamDataUnit pamDataUnit) {
this.nChannelGroups = nChannelGroups;
@@ -44,6 +46,7 @@ public class FirstGrouping {
lastSamples[channelGroup] += pamDataUnit.getSampleDuration();
}
veryLastSample = Math.max(veryLastSample, lastSamples[channelGroup]);
+ lastChannelGroup = channelGroup;
}
// /**
@@ -92,4 +95,11 @@ public class FirstGrouping {
return dataUnits;
}
+ /**
+ * @return the lastChannelGroup
+ */
+ public int getLastChannelGroup() {
+ return lastChannelGroup;
+ }
+
}
diff --git a/src/pamguard/Pamguard.java b/src/pamguard/Pamguard.java
index 3c63090e..0e19e4e3 100644
--- a/src/pamguard/Pamguard.java
+++ b/src/pamguard/Pamguard.java
@@ -23,6 +23,7 @@ package pamguard;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
+import Acquisition.FolderInputSystem;
import PamController.PamController;
import PamController.PamGUIManager;
import PamController.PamSettingManager;
@@ -41,6 +42,8 @@ import PamView.dialog.warn.WarnOnce;
import PamguardMVC.debug.Debug;
import binaryFileStorage.BinaryStore;
import dataPlotsFX.JamieDev;
+import generalDatabase.DBControl;
+
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
@@ -216,11 +219,15 @@ public class Pamguard {
}
else if (anArg.equalsIgnoreCase(BinaryStore.GlobalFolderArg)) {
// output folder for binary files.
- GlobalArguments.setParam(anArg, args[iArg++]);
+ GlobalArguments.setParam(BinaryStore.GlobalFolderArg, args[iArg++]);
}
- else if (anArg.equalsIgnoreCase("-databasefile")) {
+ else if (anArg.equalsIgnoreCase(DBControl.GlobalDatabaseNameArg)) {
// database file name
- GlobalArguments.setParam(anArg, args[iArg++]);
+ GlobalArguments.setParam(DBControl.GlobalDatabaseNameArg, args[iArg++]);
+ }
+ else if (anArg.equalsIgnoreCase(FolderInputSystem.GlobalWavFolderArg)) {
+ // source folder for wav files (or other supported sound files)
+ GlobalArguments.setParam(FolderInputSystem.GlobalWavFolderArg, args[iArg++]);
}
else if (anArg.equalsIgnoreCase("-help")) {
System.out.println("--PamGuard Help");
From 68d28152219681e8a42673408d71d654732b61a2 Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Fri, 17 Jun 2022 10:04:57 +0100
Subject: [PATCH 28/37] Add maven build configuration
---
buildconfigurations/Build PAMGuard DG.launch | 21 ++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 buildconfigurations/Build PAMGuard DG.launch
diff --git a/buildconfigurations/Build PAMGuard DG.launch b/buildconfigurations/Build PAMGuard DG.launch
new file mode 100644
index 00000000..21d3145c
--- /dev/null
+++ b/buildconfigurations/Build PAMGuard DG.launch
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
From df5b3b4dfe7659cd0f741c4f4a0261f00fc9190c Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Fri, 17 Jun 2022 14:25:31 +0100
Subject: [PATCH 29/37] Fix bug in CTD dataselector panel.
---
.../layout/dataselector/CTDataSelectPanel.java | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/clickTrainDetector/layout/dataselector/CTDataSelectPanel.java b/src/clickTrainDetector/layout/dataselector/CTDataSelectPanel.java
index 925741fe..10bc4ca0 100644
--- a/src/clickTrainDetector/layout/dataselector/CTDataSelectPanel.java
+++ b/src/clickTrainDetector/layout/dataselector/CTDataSelectPanel.java
@@ -3,6 +3,7 @@ package clickTrainDetector.layout.dataselector;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
+import java.util.ArrayList;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
@@ -15,6 +16,7 @@ import PamView.dialog.PamDialog;
import PamView.dialog.PamDialogPanel;
import PamView.dialog.PamGridBagContraints;
import PamguardMVC.dataSelector.DataSelectParams;
+import clickTrainDetector.classification.CTClassifier;
import clickTrainDetector.classification.CTClassifierManager;
import clickTrainDetector.dataselector.CTDataSelector;
import clickTrainDetector.dataselector.CTSelectParams;
@@ -287,9 +289,11 @@ public class CTDataSelectPanel implements PamDialogPanel {
// System.out.println("No. count: " + count);
currentParams.classifier = new int[count];
+ ArrayList classifiers = ctDataSelector.getClickControl().getClassifierManager().getCurrentClassifiers();
+ int used = 0;
for (int i=0; i
Date: Fri, 17 Jun 2022 15:04:24 +0100
Subject: [PATCH 30/37] Extra options for creating data selectors
Extra options so dataselectors can be kept simple and not include all
possible options for super detections as well as their own - more use
when selecting data for a superdetection !
---
src/PamguardMVC/PamDataBlock.java | 22 ++
src/PamguardMVC/RawDataTransforms.java | 261 ++++++++++--------
.../dataSelector/DataSelectorCreator.java | 27 +-
3 files changed, 193 insertions(+), 117 deletions(-)
diff --git a/src/PamguardMVC/PamDataBlock.java b/src/PamguardMVC/PamDataBlock.java
index 4db0263c..20d6aedb 100644
--- a/src/PamguardMVC/PamDataBlock.java
+++ b/src/PamguardMVC/PamDataBlock.java
@@ -3705,6 +3705,28 @@ public class PamDataBlock extends PamObservable {
return blockDataSelector;
}
+ /**
+ * Convenience method to save programmer from having to call into the creator
+ * all the time.
+ *
+ * @param selectorName
+ * @param allowScores
+ * @param selectorType Type of selector, generally a ModuleType name, e.g. Map,
+ * so that options can be tailored to specific needs
+ * @param includeAnnotations include options from any annotators of this data stream
+ * @param includeSuperDetections include any possible super detection data selectors.
+ * @return null or a DataSelector
+ */
+ public DataSelector getDataSelector(String selectorName, boolean allowScores, String selectorType,
+ boolean includeAnnotations, boolean includeSuperDetections) {
+ DataSelector blockDataSelector = null;
+ DataSelectorCreator dsc = getDataSelectCreator();
+ if (dsc != null) {
+ blockDataSelector = dsc.getDataSelector(selectorName, allowScores, selectorType, includeAnnotations, includeSuperDetections);
+ }
+ return blockDataSelector;
+ }
+
/**
* Get any information from the data block about cross referencing in database
* tables.
diff --git a/src/PamguardMVC/RawDataTransforms.java b/src/PamguardMVC/RawDataTransforms.java
index c0684730..81d8e3fe 100644
--- a/src/PamguardMVC/RawDataTransforms.java
+++ b/src/PamguardMVC/RawDataTransforms.java
@@ -99,11 +99,26 @@ public class RawDataTransforms {
*/
private int shortestFFTLength;
+ private Object synchObject;
-
- public RawDataTransforms(@SuppressWarnings("rawtypes") PamDataUnit rawDataHolder) {
+ /**
+ * Create a RawDataTransforms with a specified synchronisation object. This is mostly the data unit,
+ * but in some circumstances may need to be a different object to avoid thread lock.
+ * @param rawDataHolder
+ * @param synchObject
+ */
+ public RawDataTransforms(@SuppressWarnings("rawtypes") PamDataUnit rawDataHolder, Object synchObject) {
this.rawData=(RawDataHolder) rawDataHolder;
this.dataUnit = rawDataHolder;
+ this.synchObject = synchObject;
+ }
+
+ /**
+ * Create raw data transforms using the rawDatAholder for synchronisation.
+ * @param rawDataHolder
+ */
+ public RawDataTransforms(@SuppressWarnings("rawtypes") PamDataUnit rawDataHolder) {
+ this(rawDataHolder, rawDataHolder);
}
@@ -118,7 +133,7 @@ public class RawDataTransforms {
return powerSpectra;
}
-
+
/**
* Get the shortest FFT length for the number of samples.
* The is the
@@ -143,23 +158,25 @@ public class RawDataTransforms {
* @param fftLength
* @return Power spectrum
*/
- public synchronized double[] getPowerSpectrum(int channel, int minBin, int maxBin, int fftLength) {
- if (minBin==0 && maxBin>=this.getWaveData(0).length-1) {
- return getPowerSpectrum(channel, fftLength);
- }
- if (fftLength == 0) {
- fftLength = getCurrentSpectrumLength();
+ public double[] getPowerSpectrum(int channel, int minBin, int maxBin, int fftLength) {
+ synchronized (synchObject) {
+ if (minBin==0 && maxBin>=this.getWaveData(0).length-1) {
+ return getPowerSpectrum(channel, fftLength);
+ }
+ if (fftLength == 0) {
+ fftLength = getCurrentSpectrumLength();
+ }
+
+ double[] waveformTrim = new double[maxBin-minBin];
+
+ //System.out.println("minBin: " + minBin + " maxBin: " + maxBin + " raw waveform: " + this.getWaveData(channel).length);
+
+ System.arraycopy(this.getWaveData(channel), minBin, waveformTrim, 0, Math.min(this.getWaveData(channel).length-minBin-1, waveformTrim.length));
+
+ ComplexArray cData = getComplexSpectrumHann(waveformTrim, fftLength);
+
+ return cData.magsq();
}
-
- double[] waveformTrim = new double[maxBin-minBin];
-
- //System.out.println("minBin: " + minBin + " maxBin: " + maxBin + " raw waveform: " + this.getWaveData(channel).length);
-
- System.arraycopy(this.getWaveData(channel), minBin, waveformTrim, 0, Math.min(this.getWaveData(channel).length-minBin-1, waveformTrim.length));
-
- ComplexArray cData = getComplexSpectrumHann(waveformTrim, fftLength);
-
- return cData.magsq();
}
/**
@@ -170,29 +187,31 @@ public class RawDataTransforms {
* @param fftLength
* @return Power spectrum
*/
- public synchronized double[] getPowerSpectrum(int channel, int fftLength) {
- if (powerSpectra == null) {
- powerSpectra = new double[PamUtils.getNumChannels(dataUnit.getChannelBitmap())][];
- }
- if (fftLength == 0) {
- fftLength = getCurrentSpectrumLength();
- }
-
- if (powerSpectra[channel] == null
- || powerSpectra[channel].length != fftLength / 2) {
- ComplexArray cData = getComplexSpectrumHann(channel, fftLength);
- currentSpecLen = fftLength;
- powerSpectra[channel] = cData.magsq();
- if (powerSpectra==null){
- System.err.println("DLDetection: could not calculate power spectra");
- return null;
-
+ public double[] getPowerSpectrum(int channel, int fftLength) {
+ synchronized (synchObject) {
+ if (powerSpectra == null) {
+ powerSpectra = new double[PamUtils.getNumChannels(dataUnit.getChannelBitmap())][];
}
- if (powerSpectra[channel].length != fftLength/2) {
- powerSpectra[channel] = Arrays.copyOf(powerSpectra[channel], fftLength/2);
+ if (fftLength == 0) {
+ fftLength = getCurrentSpectrumLength();
}
+
+ if (powerSpectra[channel] == null
+ || powerSpectra[channel].length != fftLength / 2) {
+ ComplexArray cData = getComplexSpectrumHann(channel, fftLength);
+ currentSpecLen = fftLength;
+ powerSpectra[channel] = cData.magsq();
+ if (powerSpectra==null){
+ System.err.println("DLDetection: could not calculate power spectra");
+ return null;
+
+ }
+ if (powerSpectra[channel].length != fftLength/2) {
+ powerSpectra[channel] = Arrays.copyOf(powerSpectra[channel], fftLength/2);
+ }
+ }
+ return powerSpectra[channel];
}
- return powerSpectra[channel];
}
@@ -202,25 +221,27 @@ public class RawDataTransforms {
* @param fftLength
* @return Sum of power spectra
*/
- public synchronized double[] getTotalPowerSpectrum(int fftLength) {
- if (fftLength == 0) {
- fftLength = getCurrentSpectrumLength();
- }
- if (fftLength == 0) {
- fftLength = PamUtils.getMinFftLength(getSampleDuration());
- }
- double[] ps;
- if (totalPowerSpectrum == null
- || totalPowerSpectrum.length != fftLength / 2) {
- totalPowerSpectrum = new double[fftLength / 2];
- for (int c = 0; c < PamUtils.getNumChannels(this.dataUnit.getChannelBitmap()); c++) {
- ps = getPowerSpectrum(c, fftLength);
- for (int i = 0; i < fftLength / 2; i++) {
- totalPowerSpectrum[i] += ps[i];
+ public double[] getTotalPowerSpectrum(int fftLength) {
+ synchronized (synchObject) {
+ if (fftLength == 0) {
+ fftLength = getCurrentSpectrumLength();
+ }
+ if (fftLength == 0) {
+ fftLength = PamUtils.getMinFftLength(getSampleDuration());
+ }
+ double[] ps;
+ if (totalPowerSpectrum == null
+ || totalPowerSpectrum.length != fftLength / 2) {
+ totalPowerSpectrum = new double[fftLength / 2];
+ for (int c = 0; c < PamUtils.getNumChannels(this.dataUnit.getChannelBitmap()); c++) {
+ ps = getPowerSpectrum(c, fftLength);
+ for (int i = 0; i < fftLength / 2; i++) {
+ totalPowerSpectrum[i] += ps[i];
+ }
}
}
+ return totalPowerSpectrum;
}
- return totalPowerSpectrum;
}
@@ -235,15 +256,17 @@ public class RawDataTransforms {
* @param fftLength - the FFT length to use.
* @return the complex spectrum - the comnplex spectrum of the wave data from the specified channel.
*/
- public synchronized ComplexArray getComplexSpectrumHann(int channel, int fftLength) {
- complexSpectrum = new ComplexArray[PamUtils.getNumChannels(dataUnit.getChannelBitmap())];
- if (complexSpectrum[channel] == null
- || complexSpectrum.length != fftLength / 2) {
+ public ComplexArray getComplexSpectrumHann(int channel, int fftLength) {
+ synchronized (synchObject) {
+ complexSpectrum = new ComplexArray[PamUtils.getNumChannels(dataUnit.getChannelBitmap())];
+ if (complexSpectrum[channel] == null
+ || complexSpectrum.length != fftLength / 2) {
- complexSpectrum[channel] = getComplexSpectrumHann(rawData.getWaveData()[channel], fftLength);
- currentSpecLen = fftLength;
+ complexSpectrum[channel] = getComplexSpectrumHann(rawData.getWaveData()[channel], fftLength);
+ currentSpecLen = fftLength;
+ }
+ return complexSpectrum[channel];
}
- return complexSpectrum[channel];
}
@@ -300,8 +323,8 @@ public class RawDataTransforms {
public ClipSpectrogram getSpectrogram(int fftSize, int fftHop) {
return getSpectrogram( fftSize, fftHop, 1);
}
-
-
+
+
/**
* Get a spectrogram image of the wave clip. The clip is null until called. It is recalculated if the
* FFT length and/or hop size are different.
@@ -371,29 +394,31 @@ public class RawDataTransforms {
* @param fftLength
* @return the complex spectrum
*/
- public synchronized ComplexArray getComplexSpectrum(int channel, int fftLength) {
- double[] paddedRawData;
- double[] rawData;
- int i, mn;
+ public ComplexArray getComplexSpectrum(int channel, int fftLength) {
+ synchronized (synchObject) {
+ double[] paddedRawData;
+ double[] rawData;
+ int i, mn;
- if (complexSpectrum == null) {
- complexSpectrum = new ComplexArray[getNChan()];
- }
- if (complexSpectrum[channel] == null
- || complexSpectrum.length != fftLength / 2) {
- paddedRawData = new double[fftLength];
- rawData = getWaveData(channel);
- //double[] rotData = getRotationCorrection(channel);
- mn = Math.min(fftLength, getSampleDuration().intValue());
- for (i = 0; i < mn; i++) {
- paddedRawData[i] = rawData[i];//-rotData[i];
+ if (complexSpectrum == null) {
+ complexSpectrum = new ComplexArray[getNChan()];
}
- for (i = mn; i < fftLength; i++) {
- paddedRawData[i] = 0;
+ if (complexSpectrum[channel] == null
+ || complexSpectrum.length != fftLength / 2) {
+ paddedRawData = new double[fftLength];
+ rawData = getWaveData(channel);
+ //double[] rotData = getRotationCorrection(channel);
+ mn = Math.min(fftLength, getSampleDuration().intValue());
+ for (i = 0; i < mn; i++) {
+ paddedRawData[i] = rawData[i];//-rotData[i];
+ }
+ for (i = mn; i < fftLength; i++) {
+ paddedRawData[i] = 0;
+ }
+ complexSpectrum[channel] = fastFFT.rfft(paddedRawData, fftLength);
}
- complexSpectrum[channel] = fastFFT.rfft(paddedRawData, fftLength);
+ return complexSpectrum[channel];
}
- return complexSpectrum[channel];
}
@@ -402,14 +427,16 @@ public class RawDataTransforms {
* @param iChan channel index
* @return analytic waveform
*/
- public synchronized double[] getAnalyticWaveform(int iChan) {
- if (analyticWaveform == null) {
- analyticWaveform = new double[getNChan()][];
+ public double[] getAnalyticWaveform(int iChan) {
+ synchronized (synchObject) {
+ if (analyticWaveform == null) {
+ analyticWaveform = new double[getNChan()][];
+ }
+ // if (analyticWaveform[iChan] == null) {
+ analyticWaveform[iChan] = hilbert.getHilbert(getWaveData(iChan));
+ // }
+ return analyticWaveform[iChan];
}
- // if (analyticWaveform[iChan] == null) {
- analyticWaveform[iChan] = hilbert.getHilbert(getWaveData(iChan));
- // }
- return analyticWaveform[iChan];
}
/**
@@ -421,12 +448,14 @@ public class RawDataTransforms {
* @param fftFilterParams fft filter parameters.
* @return analystic waveform.
*/
- public synchronized double[] getAnalyticWaveform(int iChan, boolean filtered, FFTFilterParams fftFilterParams) {
- if (filtered == false || fftFilterParams == null) {
- return getAnalyticWaveform(iChan);
- }
- else {
- return getFilteredAnalyticWaveform(fftFilterParams, iChan);
+ public double[] getAnalyticWaveform(int iChan, boolean filtered, FFTFilterParams fftFilterParams) {
+ synchronized (synchObject) {
+ if (filtered == false || fftFilterParams == null) {
+ return getAnalyticWaveform(iChan);
+ }
+ else {
+ return getFilteredAnalyticWaveform(fftFilterParams, iChan);
+ }
}
}
@@ -437,15 +466,17 @@ public class RawDataTransforms {
* @param iChan channel number
* @return envelope of the filtered data.
*/
- public synchronized double[] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams, int iChan) {
- if (analyticWaveform == null) {
- analyticWaveform = new double[getNChan()][];
+ public double[] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams, int iChan) {
+ synchronized (synchObject) {
+ if (analyticWaveform == null) {
+ analyticWaveform = new double[getNChan()][];
+ }
+ // if (analyticWaveform[iChan] == null) {
+ analyticWaveform[iChan] = hilbert.
+ getHilbert(getFilteredWaveData(fftFilterParams, iChan));
+ // }
+ return analyticWaveform[iChan];
}
- // if (analyticWaveform[iChan] == null) {
- analyticWaveform[iChan] = hilbert.
- getHilbert(getFilteredWaveData(fftFilterParams, iChan));
- // }
- return analyticWaveform[iChan];
}
/**
@@ -478,9 +509,11 @@ public class RawDataTransforms {
* @param channelIndex channel index
* @return filtered waveform data
*/
- public synchronized double[] getFilteredWaveData(FFTFilterParams filterParams, int channelIndex) {
- filteredWaveData = getFilteredWaveData(filterParams);
- return filteredWaveData[channelIndex];
+ public double[] getFilteredWaveData(FFTFilterParams filterParams, int channelIndex) {
+ synchronized (synchObject) {
+ filteredWaveData = getFilteredWaveData(filterParams);
+ return filteredWaveData[channelIndex];
+ }
}
/**
@@ -489,12 +522,14 @@ public class RawDataTransforms {
* @param filterParams filter parameters
* @return array of filtered data
*/
- public synchronized double[][] getFilteredWaveData(FFTFilterParams filterParams) {
- //System.out.println("Make filterred wave data!: " + (filterParams != oldFFTFilterParams));
- if (filteredWaveData == null || filterParams != oldFFTFilterParams) {
- filteredWaveData = makeFilteredWaveData(filterParams);
+ public double[][] getFilteredWaveData(FFTFilterParams filterParams) {
+ synchronized (synchObject) {
+ //System.out.println("Make filterred wave data!: " + (filterParams != oldFFTFilterParams));
+ if (filteredWaveData == null || filterParams != oldFFTFilterParams) {
+ filteredWaveData = makeFilteredWaveData(filterParams);
+ }
+ return filteredWaveData;
}
- return filteredWaveData;
}
private double[][] makeFilteredWaveData(FFTFilterParams filterParams) {
@@ -574,7 +609,7 @@ public class RawDataTransforms {
public double[] getWaveData(int channel) {
return this.rawData.getWaveData()[channel];
}
-
+
/**
* Get the wave data for the given channel in int16 format.
* @param channel channel index
diff --git a/src/PamguardMVC/dataSelector/DataSelectorCreator.java b/src/PamguardMVC/dataSelector/DataSelectorCreator.java
index ffc458eb..77e199b5 100644
--- a/src/PamguardMVC/dataSelector/DataSelectorCreator.java
+++ b/src/PamguardMVC/dataSelector/DataSelectorCreator.java
@@ -62,19 +62,38 @@ public abstract class DataSelectorCreator implements PamSettings {
}
/**
- * Get a data selector of a given name.
+ * Get a data selector of a given name including all possible options for super detections and annotations.
* @param selectorName
* @param allowScores
- * @return
+ * @return data selector for given name.
*/
public synchronized DataSelector getDataSelector(String selectorName, boolean allowScores, String selectorType) {
+ return getDataSelector(selectorName, allowScores, selectorType, true, true);
+ }
+
+ /**
+ *
+ * Get a data selector of a given name with optional inclusion of options for annotations and super detections
+ * @param selectorName data selector name
+ * @param allowScores allow scores
+ * @param selectorType
+ * @param includeAnnotations include options from any annotators of this data stream
+ * @param includeSuperDetections include any possible super detection data selectors.
+ * @return data selector for given name with appropriate options.
+ */
+ public synchronized DataSelector getDataSelector(String selectorName, boolean allowScores, String selectorType,
+ boolean includeAnnotations, boolean includeSuperDetections) {
DataSelector ds = findDataSelector(selectorName);
if (ds == null) {
ds = createDataSelector(selectorName, allowScores, selectorType);
- ds = addAnnotationOptions(ds, selectorName, allowScores, selectorType);
+ if (includeAnnotations) {
+ ds = addAnnotationOptions(ds, selectorName, allowScores, selectorType);
+ }
- ds = addSuperDetectionOptions(ds, selectorName, allowScores, selectorType);
+ if (includeSuperDetections) {
+ ds = addSuperDetectionOptions(ds, selectorName, allowScores, selectorType);
+ }
// and get it's params from the centralised list.
DataSelectParams params = dataSelectorSettings.getParams(selectorName);
From c5c0f9bb44ea1c71c23830e31a60488e527bfe6b Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Fri, 17 Jun 2022 17:02:41 +0100
Subject: [PATCH 31/37] Bug fixes for data selectors (#38)
* Global arguments to set params in acquisition and database.
* Fix bug in CTD dataselector panel.
* Extra options for creating data selectors
Extra options so dataselectors can be kept simple and not include all
possible options for super detections as well as their own - more use
when selecting data for a superdetection !
---
src/PamguardMVC/PamDataBlock.java | 22 ++
src/PamguardMVC/RawDataTransforms.java | 261 ++++++++++--------
.../dataSelector/DataSelectorCreator.java | 27 +-
.../dataselector/CTDataSelectPanel.java | 6 +-
4 files changed, 198 insertions(+), 118 deletions(-)
diff --git a/src/PamguardMVC/PamDataBlock.java b/src/PamguardMVC/PamDataBlock.java
index 4db0263c..20d6aedb 100644
--- a/src/PamguardMVC/PamDataBlock.java
+++ b/src/PamguardMVC/PamDataBlock.java
@@ -3705,6 +3705,28 @@ public class PamDataBlock extends PamObservable {
return blockDataSelector;
}
+ /**
+ * Convenience method to save programmer from having to call into the creator
+ * all the time.
+ *
+ * @param selectorName
+ * @param allowScores
+ * @param selectorType Type of selector, generally a ModuleType name, e.g. Map,
+ * so that options can be tailored to specific needs
+ * @param includeAnnotations include options from any annotators of this data stream
+ * @param includeSuperDetections include any possible super detection data selectors.
+ * @return null or a DataSelector
+ */
+ public DataSelector getDataSelector(String selectorName, boolean allowScores, String selectorType,
+ boolean includeAnnotations, boolean includeSuperDetections) {
+ DataSelector blockDataSelector = null;
+ DataSelectorCreator dsc = getDataSelectCreator();
+ if (dsc != null) {
+ blockDataSelector = dsc.getDataSelector(selectorName, allowScores, selectorType, includeAnnotations, includeSuperDetections);
+ }
+ return blockDataSelector;
+ }
+
/**
* Get any information from the data block about cross referencing in database
* tables.
diff --git a/src/PamguardMVC/RawDataTransforms.java b/src/PamguardMVC/RawDataTransforms.java
index c0684730..81d8e3fe 100644
--- a/src/PamguardMVC/RawDataTransforms.java
+++ b/src/PamguardMVC/RawDataTransforms.java
@@ -99,11 +99,26 @@ public class RawDataTransforms {
*/
private int shortestFFTLength;
+ private Object synchObject;
-
- public RawDataTransforms(@SuppressWarnings("rawtypes") PamDataUnit rawDataHolder) {
+ /**
+ * Create a RawDataTransforms with a specified synchronisation object. This is mostly the data unit,
+ * but in some circumstances may need to be a different object to avoid thread lock.
+ * @param rawDataHolder
+ * @param synchObject
+ */
+ public RawDataTransforms(@SuppressWarnings("rawtypes") PamDataUnit rawDataHolder, Object synchObject) {
this.rawData=(RawDataHolder) rawDataHolder;
this.dataUnit = rawDataHolder;
+ this.synchObject = synchObject;
+ }
+
+ /**
+ * Create raw data transforms using the rawDatAholder for synchronisation.
+ * @param rawDataHolder
+ */
+ public RawDataTransforms(@SuppressWarnings("rawtypes") PamDataUnit rawDataHolder) {
+ this(rawDataHolder, rawDataHolder);
}
@@ -118,7 +133,7 @@ public class RawDataTransforms {
return powerSpectra;
}
-
+
/**
* Get the shortest FFT length for the number of samples.
* The is the
@@ -143,23 +158,25 @@ public class RawDataTransforms {
* @param fftLength
* @return Power spectrum
*/
- public synchronized double[] getPowerSpectrum(int channel, int minBin, int maxBin, int fftLength) {
- if (minBin==0 && maxBin>=this.getWaveData(0).length-1) {
- return getPowerSpectrum(channel, fftLength);
- }
- if (fftLength == 0) {
- fftLength = getCurrentSpectrumLength();
+ public double[] getPowerSpectrum(int channel, int minBin, int maxBin, int fftLength) {
+ synchronized (synchObject) {
+ if (minBin==0 && maxBin>=this.getWaveData(0).length-1) {
+ return getPowerSpectrum(channel, fftLength);
+ }
+ if (fftLength == 0) {
+ fftLength = getCurrentSpectrumLength();
+ }
+
+ double[] waveformTrim = new double[maxBin-minBin];
+
+ //System.out.println("minBin: " + minBin + " maxBin: " + maxBin + " raw waveform: " + this.getWaveData(channel).length);
+
+ System.arraycopy(this.getWaveData(channel), minBin, waveformTrim, 0, Math.min(this.getWaveData(channel).length-minBin-1, waveformTrim.length));
+
+ ComplexArray cData = getComplexSpectrumHann(waveformTrim, fftLength);
+
+ return cData.magsq();
}
-
- double[] waveformTrim = new double[maxBin-minBin];
-
- //System.out.println("minBin: " + minBin + " maxBin: " + maxBin + " raw waveform: " + this.getWaveData(channel).length);
-
- System.arraycopy(this.getWaveData(channel), minBin, waveformTrim, 0, Math.min(this.getWaveData(channel).length-minBin-1, waveformTrim.length));
-
- ComplexArray cData = getComplexSpectrumHann(waveformTrim, fftLength);
-
- return cData.magsq();
}
/**
@@ -170,29 +187,31 @@ public class RawDataTransforms {
* @param fftLength
* @return Power spectrum
*/
- public synchronized double[] getPowerSpectrum(int channel, int fftLength) {
- if (powerSpectra == null) {
- powerSpectra = new double[PamUtils.getNumChannels(dataUnit.getChannelBitmap())][];
- }
- if (fftLength == 0) {
- fftLength = getCurrentSpectrumLength();
- }
-
- if (powerSpectra[channel] == null
- || powerSpectra[channel].length != fftLength / 2) {
- ComplexArray cData = getComplexSpectrumHann(channel, fftLength);
- currentSpecLen = fftLength;
- powerSpectra[channel] = cData.magsq();
- if (powerSpectra==null){
- System.err.println("DLDetection: could not calculate power spectra");
- return null;
-
+ public double[] getPowerSpectrum(int channel, int fftLength) {
+ synchronized (synchObject) {
+ if (powerSpectra == null) {
+ powerSpectra = new double[PamUtils.getNumChannels(dataUnit.getChannelBitmap())][];
}
- if (powerSpectra[channel].length != fftLength/2) {
- powerSpectra[channel] = Arrays.copyOf(powerSpectra[channel], fftLength/2);
+ if (fftLength == 0) {
+ fftLength = getCurrentSpectrumLength();
}
+
+ if (powerSpectra[channel] == null
+ || powerSpectra[channel].length != fftLength / 2) {
+ ComplexArray cData = getComplexSpectrumHann(channel, fftLength);
+ currentSpecLen = fftLength;
+ powerSpectra[channel] = cData.magsq();
+ if (powerSpectra==null){
+ System.err.println("DLDetection: could not calculate power spectra");
+ return null;
+
+ }
+ if (powerSpectra[channel].length != fftLength/2) {
+ powerSpectra[channel] = Arrays.copyOf(powerSpectra[channel], fftLength/2);
+ }
+ }
+ return powerSpectra[channel];
}
- return powerSpectra[channel];
}
@@ -202,25 +221,27 @@ public class RawDataTransforms {
* @param fftLength
* @return Sum of power spectra
*/
- public synchronized double[] getTotalPowerSpectrum(int fftLength) {
- if (fftLength == 0) {
- fftLength = getCurrentSpectrumLength();
- }
- if (fftLength == 0) {
- fftLength = PamUtils.getMinFftLength(getSampleDuration());
- }
- double[] ps;
- if (totalPowerSpectrum == null
- || totalPowerSpectrum.length != fftLength / 2) {
- totalPowerSpectrum = new double[fftLength / 2];
- for (int c = 0; c < PamUtils.getNumChannels(this.dataUnit.getChannelBitmap()); c++) {
- ps = getPowerSpectrum(c, fftLength);
- for (int i = 0; i < fftLength / 2; i++) {
- totalPowerSpectrum[i] += ps[i];
+ public double[] getTotalPowerSpectrum(int fftLength) {
+ synchronized (synchObject) {
+ if (fftLength == 0) {
+ fftLength = getCurrentSpectrumLength();
+ }
+ if (fftLength == 0) {
+ fftLength = PamUtils.getMinFftLength(getSampleDuration());
+ }
+ double[] ps;
+ if (totalPowerSpectrum == null
+ || totalPowerSpectrum.length != fftLength / 2) {
+ totalPowerSpectrum = new double[fftLength / 2];
+ for (int c = 0; c < PamUtils.getNumChannels(this.dataUnit.getChannelBitmap()); c++) {
+ ps = getPowerSpectrum(c, fftLength);
+ for (int i = 0; i < fftLength / 2; i++) {
+ totalPowerSpectrum[i] += ps[i];
+ }
}
}
+ return totalPowerSpectrum;
}
- return totalPowerSpectrum;
}
@@ -235,15 +256,17 @@ public class RawDataTransforms {
* @param fftLength - the FFT length to use.
* @return the complex spectrum - the comnplex spectrum of the wave data from the specified channel.
*/
- public synchronized ComplexArray getComplexSpectrumHann(int channel, int fftLength) {
- complexSpectrum = new ComplexArray[PamUtils.getNumChannels(dataUnit.getChannelBitmap())];
- if (complexSpectrum[channel] == null
- || complexSpectrum.length != fftLength / 2) {
+ public ComplexArray getComplexSpectrumHann(int channel, int fftLength) {
+ synchronized (synchObject) {
+ complexSpectrum = new ComplexArray[PamUtils.getNumChannels(dataUnit.getChannelBitmap())];
+ if (complexSpectrum[channel] == null
+ || complexSpectrum.length != fftLength / 2) {
- complexSpectrum[channel] = getComplexSpectrumHann(rawData.getWaveData()[channel], fftLength);
- currentSpecLen = fftLength;
+ complexSpectrum[channel] = getComplexSpectrumHann(rawData.getWaveData()[channel], fftLength);
+ currentSpecLen = fftLength;
+ }
+ return complexSpectrum[channel];
}
- return complexSpectrum[channel];
}
@@ -300,8 +323,8 @@ public class RawDataTransforms {
public ClipSpectrogram getSpectrogram(int fftSize, int fftHop) {
return getSpectrogram( fftSize, fftHop, 1);
}
-
-
+
+
/**
* Get a spectrogram image of the wave clip. The clip is null until called. It is recalculated if the
* FFT length and/or hop size are different.
@@ -371,29 +394,31 @@ public class RawDataTransforms {
* @param fftLength
* @return the complex spectrum
*/
- public synchronized ComplexArray getComplexSpectrum(int channel, int fftLength) {
- double[] paddedRawData;
- double[] rawData;
- int i, mn;
+ public ComplexArray getComplexSpectrum(int channel, int fftLength) {
+ synchronized (synchObject) {
+ double[] paddedRawData;
+ double[] rawData;
+ int i, mn;
- if (complexSpectrum == null) {
- complexSpectrum = new ComplexArray[getNChan()];
- }
- if (complexSpectrum[channel] == null
- || complexSpectrum.length != fftLength / 2) {
- paddedRawData = new double[fftLength];
- rawData = getWaveData(channel);
- //double[] rotData = getRotationCorrection(channel);
- mn = Math.min(fftLength, getSampleDuration().intValue());
- for (i = 0; i < mn; i++) {
- paddedRawData[i] = rawData[i];//-rotData[i];
+ if (complexSpectrum == null) {
+ complexSpectrum = new ComplexArray[getNChan()];
}
- for (i = mn; i < fftLength; i++) {
- paddedRawData[i] = 0;
+ if (complexSpectrum[channel] == null
+ || complexSpectrum.length != fftLength / 2) {
+ paddedRawData = new double[fftLength];
+ rawData = getWaveData(channel);
+ //double[] rotData = getRotationCorrection(channel);
+ mn = Math.min(fftLength, getSampleDuration().intValue());
+ for (i = 0; i < mn; i++) {
+ paddedRawData[i] = rawData[i];//-rotData[i];
+ }
+ for (i = mn; i < fftLength; i++) {
+ paddedRawData[i] = 0;
+ }
+ complexSpectrum[channel] = fastFFT.rfft(paddedRawData, fftLength);
}
- complexSpectrum[channel] = fastFFT.rfft(paddedRawData, fftLength);
+ return complexSpectrum[channel];
}
- return complexSpectrum[channel];
}
@@ -402,14 +427,16 @@ public class RawDataTransforms {
* @param iChan channel index
* @return analytic waveform
*/
- public synchronized double[] getAnalyticWaveform(int iChan) {
- if (analyticWaveform == null) {
- analyticWaveform = new double[getNChan()][];
+ public double[] getAnalyticWaveform(int iChan) {
+ synchronized (synchObject) {
+ if (analyticWaveform == null) {
+ analyticWaveform = new double[getNChan()][];
+ }
+ // if (analyticWaveform[iChan] == null) {
+ analyticWaveform[iChan] = hilbert.getHilbert(getWaveData(iChan));
+ // }
+ return analyticWaveform[iChan];
}
- // if (analyticWaveform[iChan] == null) {
- analyticWaveform[iChan] = hilbert.getHilbert(getWaveData(iChan));
- // }
- return analyticWaveform[iChan];
}
/**
@@ -421,12 +448,14 @@ public class RawDataTransforms {
* @param fftFilterParams fft filter parameters.
* @return analystic waveform.
*/
- public synchronized double[] getAnalyticWaveform(int iChan, boolean filtered, FFTFilterParams fftFilterParams) {
- if (filtered == false || fftFilterParams == null) {
- return getAnalyticWaveform(iChan);
- }
- else {
- return getFilteredAnalyticWaveform(fftFilterParams, iChan);
+ public double[] getAnalyticWaveform(int iChan, boolean filtered, FFTFilterParams fftFilterParams) {
+ synchronized (synchObject) {
+ if (filtered == false || fftFilterParams == null) {
+ return getAnalyticWaveform(iChan);
+ }
+ else {
+ return getFilteredAnalyticWaveform(fftFilterParams, iChan);
+ }
}
}
@@ -437,15 +466,17 @@ public class RawDataTransforms {
* @param iChan channel number
* @return envelope of the filtered data.
*/
- public synchronized double[] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams, int iChan) {
- if (analyticWaveform == null) {
- analyticWaveform = new double[getNChan()][];
+ public double[] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams, int iChan) {
+ synchronized (synchObject) {
+ if (analyticWaveform == null) {
+ analyticWaveform = new double[getNChan()][];
+ }
+ // if (analyticWaveform[iChan] == null) {
+ analyticWaveform[iChan] = hilbert.
+ getHilbert(getFilteredWaveData(fftFilterParams, iChan));
+ // }
+ return analyticWaveform[iChan];
}
- // if (analyticWaveform[iChan] == null) {
- analyticWaveform[iChan] = hilbert.
- getHilbert(getFilteredWaveData(fftFilterParams, iChan));
- // }
- return analyticWaveform[iChan];
}
/**
@@ -478,9 +509,11 @@ public class RawDataTransforms {
* @param channelIndex channel index
* @return filtered waveform data
*/
- public synchronized double[] getFilteredWaveData(FFTFilterParams filterParams, int channelIndex) {
- filteredWaveData = getFilteredWaveData(filterParams);
- return filteredWaveData[channelIndex];
+ public double[] getFilteredWaveData(FFTFilterParams filterParams, int channelIndex) {
+ synchronized (synchObject) {
+ filteredWaveData = getFilteredWaveData(filterParams);
+ return filteredWaveData[channelIndex];
+ }
}
/**
@@ -489,12 +522,14 @@ public class RawDataTransforms {
* @param filterParams filter parameters
* @return array of filtered data
*/
- public synchronized double[][] getFilteredWaveData(FFTFilterParams filterParams) {
- //System.out.println("Make filterred wave data!: " + (filterParams != oldFFTFilterParams));
- if (filteredWaveData == null || filterParams != oldFFTFilterParams) {
- filteredWaveData = makeFilteredWaveData(filterParams);
+ public double[][] getFilteredWaveData(FFTFilterParams filterParams) {
+ synchronized (synchObject) {
+ //System.out.println("Make filterred wave data!: " + (filterParams != oldFFTFilterParams));
+ if (filteredWaveData == null || filterParams != oldFFTFilterParams) {
+ filteredWaveData = makeFilteredWaveData(filterParams);
+ }
+ return filteredWaveData;
}
- return filteredWaveData;
}
private double[][] makeFilteredWaveData(FFTFilterParams filterParams) {
@@ -574,7 +609,7 @@ public class RawDataTransforms {
public double[] getWaveData(int channel) {
return this.rawData.getWaveData()[channel];
}
-
+
/**
* Get the wave data for the given channel in int16 format.
* @param channel channel index
diff --git a/src/PamguardMVC/dataSelector/DataSelectorCreator.java b/src/PamguardMVC/dataSelector/DataSelectorCreator.java
index ffc458eb..77e199b5 100644
--- a/src/PamguardMVC/dataSelector/DataSelectorCreator.java
+++ b/src/PamguardMVC/dataSelector/DataSelectorCreator.java
@@ -62,19 +62,38 @@ public abstract class DataSelectorCreator implements PamSettings {
}
/**
- * Get a data selector of a given name.
+ * Get a data selector of a given name including all possible options for super detections and annotations.
* @param selectorName
* @param allowScores
- * @return
+ * @return data selector for given name.
*/
public synchronized DataSelector getDataSelector(String selectorName, boolean allowScores, String selectorType) {
+ return getDataSelector(selectorName, allowScores, selectorType, true, true);
+ }
+
+ /**
+ *
+ * Get a data selector of a given name with optional inclusion of options for annotations and super detections
+ * @param selectorName data selector name
+ * @param allowScores allow scores
+ * @param selectorType
+ * @param includeAnnotations include options from any annotators of this data stream
+ * @param includeSuperDetections include any possible super detection data selectors.
+ * @return data selector for given name with appropriate options.
+ */
+ public synchronized DataSelector getDataSelector(String selectorName, boolean allowScores, String selectorType,
+ boolean includeAnnotations, boolean includeSuperDetections) {
DataSelector ds = findDataSelector(selectorName);
if (ds == null) {
ds = createDataSelector(selectorName, allowScores, selectorType);
- ds = addAnnotationOptions(ds, selectorName, allowScores, selectorType);
+ if (includeAnnotations) {
+ ds = addAnnotationOptions(ds, selectorName, allowScores, selectorType);
+ }
- ds = addSuperDetectionOptions(ds, selectorName, allowScores, selectorType);
+ if (includeSuperDetections) {
+ ds = addSuperDetectionOptions(ds, selectorName, allowScores, selectorType);
+ }
// and get it's params from the centralised list.
DataSelectParams params = dataSelectorSettings.getParams(selectorName);
diff --git a/src/clickTrainDetector/layout/dataselector/CTDataSelectPanel.java b/src/clickTrainDetector/layout/dataselector/CTDataSelectPanel.java
index 925741fe..10bc4ca0 100644
--- a/src/clickTrainDetector/layout/dataselector/CTDataSelectPanel.java
+++ b/src/clickTrainDetector/layout/dataselector/CTDataSelectPanel.java
@@ -3,6 +3,7 @@ package clickTrainDetector.layout.dataselector;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
+import java.util.ArrayList;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
@@ -15,6 +16,7 @@ import PamView.dialog.PamDialog;
import PamView.dialog.PamDialogPanel;
import PamView.dialog.PamGridBagContraints;
import PamguardMVC.dataSelector.DataSelectParams;
+import clickTrainDetector.classification.CTClassifier;
import clickTrainDetector.classification.CTClassifierManager;
import clickTrainDetector.dataselector.CTDataSelector;
import clickTrainDetector.dataselector.CTSelectParams;
@@ -287,9 +289,11 @@ public class CTDataSelectPanel implements PamDialogPanel {
// System.out.println("No. count: " + count);
currentParams.classifier = new int[count];
+ ArrayList classifiers = ctDataSelector.getClickControl().getClassifierManager().getCurrentClassifiers();
+ int used = 0;
for (int i=0; i
Date: Mon, 20 Jun 2022 16:56:43 +0100
Subject: [PATCH 32/37] Move symbols dialogs close to where mouse is.
---
src/PamView/dialog/PamDialog.java | 11 +++++++++--
.../paneloverlay/OverlayCheckboxMenuSelect.java | 3 +++
.../layout/dataselector/CTDataSelectPanel.java | 5 ++++-
3 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/src/PamView/dialog/PamDialog.java b/src/PamView/dialog/PamDialog.java
index 90d966af..ad20c635 100644
--- a/src/PamView/dialog/PamDialog.java
+++ b/src/PamView/dialog/PamDialog.java
@@ -257,15 +257,22 @@ abstract public class PamDialog extends JDialog {
// check we're not going too far off the screen.
Dimension sz = getPreferredSize();
Dimension screen = null;
+ int w, h;
if (getOwner() != null) {
+ Window owner = getOwner();
+ Rectangle bounds = owner.getBounds();
+ w = bounds.x+bounds.width;
+ h = bounds.y+bounds.height;
screen = getOwner().getSize();
}
else {
screen = Toolkit.getDefaultToolkit().getScreenSize();
+ w = screen.width;
+ h = screen.height;
}
- point.y = Math.min(point.y, screen.height-sz.height-10);
+ point.y = Math.min(point.y, h-sz.height-10);
point.y = Math.max(point.y, 0);
- point.x = Math.min(point.x, screen.width-sz.width-10);
+ point.x = Math.min(point.x, w-sz.width-10);
point.x = Math.max(point.x, 0);
setLocation(point);
diff --git a/src/PamView/paneloverlay/OverlayCheckboxMenuSelect.java b/src/PamView/paneloverlay/OverlayCheckboxMenuSelect.java
index 20dfe5e1..fc743661 100644
--- a/src/PamView/paneloverlay/OverlayCheckboxMenuSelect.java
+++ b/src/PamView/paneloverlay/OverlayCheckboxMenuSelect.java
@@ -48,6 +48,9 @@ public class OverlayCheckboxMenuSelect implements ActionListener {
return;
}
DataSelectDialog dataSelectDialog = new DataSelectDialog(javaFrame, dataBlock, dataSelector, symbolChooser);
+ if (javaFrame == null) {
+ dataSelectDialog.moveToMouseLocation();
+ }
boolean ok = dataSelectDialog.showDialog();
if (ok) {
menuItem.setSelected(true);
diff --git a/src/clickTrainDetector/layout/dataselector/CTDataSelectPanel.java b/src/clickTrainDetector/layout/dataselector/CTDataSelectPanel.java
index 925741fe..9241ef56 100644
--- a/src/clickTrainDetector/layout/dataselector/CTDataSelectPanel.java
+++ b/src/clickTrainDetector/layout/dataselector/CTDataSelectPanel.java
@@ -3,6 +3,7 @@ package clickTrainDetector.layout.dataselector;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
+import java.util.ArrayList;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
@@ -15,6 +16,7 @@ import PamView.dialog.PamDialog;
import PamView.dialog.PamDialogPanel;
import PamView.dialog.PamGridBagContraints;
import PamguardMVC.dataSelector.DataSelectParams;
+import clickTrainDetector.classification.CTClassifier;
import clickTrainDetector.classification.CTClassifierManager;
import clickTrainDetector.dataselector.CTDataSelector;
import clickTrainDetector.dataselector.CTSelectParams;
@@ -289,7 +291,8 @@ public class CTDataSelectPanel implements PamDialogPanel {
currentParams.classifier = new int[count];
for (int i=0; i currentClassifiers = ctDataSelector.getClickControl().getClassifierManager().getCurrentClassifiers();
+ currentParams.classifier[i] = currentClassifiers.get(i).getSpeciesID();
}
}
From 87376a70ec876c1299700334128a2c0c4fa65874 Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Thu, 23 Jun 2022 15:55:05 +0100
Subject: [PATCH 33/37] Fix null pointer exception while marking
---
.../overlaymark/MarkOverlayDraw.java | 100 ++++++++++--------
.../paneloverlay/overlaymark/OverlayMark.java | 3 +
2 files changed, 57 insertions(+), 46 deletions(-)
diff --git a/src/PamView/paneloverlay/overlaymark/MarkOverlayDraw.java b/src/PamView/paneloverlay/overlaymark/MarkOverlayDraw.java
index 20598c41..1a7d6f76 100644
--- a/src/PamView/paneloverlay/overlaymark/MarkOverlayDraw.java
+++ b/src/PamView/paneloverlay/overlaymark/MarkOverlayDraw.java
@@ -143,52 +143,60 @@ public class MarkOverlayDraw extends PanelOverlayDraw {
* To allow for things like the rotated map which no longer show rectangles as
* rectangles, we now need to draw rectangles are irregular polygons too !
*/
- int[] x = new int[4];
- int[] y = new int[4];
- PamCoordinate m0 = mark.getCoordinate(0);
- PamCoordinate m1 = mark.getCoordinate(1);
- Point p;
- p = generalProjector.getCoord3d(m0.getCoordinate(0), m0.getCoordinate(1), 0).getXYPoint();
- x[0] = p.x;
- y[0] = p.y;
- p = generalProjector.getCoord3d(m0.getCoordinate(0), m1.getCoordinate(1), 0).getXYPoint();
- x[1] = p.x;
- y[1] = p.y;
- p = generalProjector.getCoord3d(m1.getCoordinate(0), m1.getCoordinate(1), 0).getXYPoint();
- x[2] = p.x;
- y[2] = p.y;
- p = generalProjector.getCoord3d(m1.getCoordinate(0), m0.getCoordinate(1), 0).getXYPoint();
- x[3] = p.x;
- y[3] = p.y;
- Polygon pgon = new Polygon(x, y, 4);
- Color fillCol = getFillCol();
- if (fillCol != null) {
- g2d.setColor(getFillCol());
- g2d.fillPolygon(pgon);
+ try {
+ int[] x = new int[4];
+ int[] y = new int[4];
+ PamCoordinate m0 = mark.getCoordinate(0);
+ PamCoordinate m1 = mark.getCoordinate(1);
+ if (m0 == null || m1 == null) {
+ return null;
+ }
+ Point p;
+ p = generalProjector.getCoord3d(m0.getCoordinate(0), m0.getCoordinate(1), 0).getXYPoint();
+ x[0] = p.x;
+ y[0] = p.y;
+ p = generalProjector.getCoord3d(m0.getCoordinate(0), m1.getCoordinate(1), 0).getXYPoint();
+ x[1] = p.x;
+ y[1] = p.y;
+ p = generalProjector.getCoord3d(m1.getCoordinate(0), m1.getCoordinate(1), 0).getXYPoint();
+ x[2] = p.x;
+ y[2] = p.y;
+ p = generalProjector.getCoord3d(m1.getCoordinate(0), m0.getCoordinate(1), 0).getXYPoint();
+ x[3] = p.x;
+ y[3] = p.y;
+ Polygon pgon = new Polygon(x, y, 4);
+ Color fillCol = getFillCol();
+ if (fillCol != null) {
+ g2d.setColor(getFillCol());
+ g2d.fillPolygon(pgon);
+ }
+ return pgon;
}
- return pgon;
-
-//
-// Point p0 = generalProjector.getCoord3d(m0).getXYPoint();
-// Point p1 = generalProjector.getCoord3d(m1).getXYPoint();
-// g2d.setColor(getLineCol());
-// g2d.setStroke(getLineStroke());
-// g2d.drawLine(p0.x, p0.y, p1.x, p0.y);
-// g2d.drawLine(p1.x, p0.y, p1.x, p1.y);
-// g2d.drawLine(p1.x, p1.y, p0.x, p1.y);
-// g2d.drawLine(p0.x, p1.y, p0.x, p0.y);
-// int x = Math.min(p0.x, p1.x);
-// int y = Math.min(p0.y, p1.y);
-// int w = Math.abs(p0.x - p1.x);
-// int h = Math.abs(p0.y - p1.y);
-//
-// Color fillCol = getFillCol();
-// if (fillCol != null) {
-// g2d.setColor(getFillCol());
-// g2d.fillRect(x, y, w, h);
-// }
-// Rectangle r = new Rectangle(x, y, w, h);
-// return r;
+ catch (NullPointerException e) {
+ return null;
+ }
+
+ //
+ // Point p0 = generalProjector.getCoord3d(m0).getXYPoint();
+ // Point p1 = generalProjector.getCoord3d(m1).getXYPoint();
+ // g2d.setColor(getLineCol());
+ // g2d.setStroke(getLineStroke());
+ // g2d.drawLine(p0.x, p0.y, p1.x, p0.y);
+ // g2d.drawLine(p1.x, p0.y, p1.x, p1.y);
+ // g2d.drawLine(p1.x, p1.y, p0.x, p1.y);
+ // g2d.drawLine(p0.x, p1.y, p0.x, p0.y);
+ // int x = Math.min(p0.x, p1.x);
+ // int y = Math.min(p0.y, p1.y);
+ // int w = Math.abs(p0.x - p1.x);
+ // int h = Math.abs(p0.y - p1.y);
+ //
+ // Color fillCol = getFillCol();
+ // if (fillCol != null) {
+ // g2d.setColor(getFillCol());
+ // g2d.fillRect(x, y, w, h);
+ // }
+ // Rectangle r = new Rectangle(x, y, w, h);
+ // return r;
}
@Override
@@ -223,7 +231,7 @@ public class MarkOverlayDraw extends PanelOverlayDraw {
public Stroke getLineStroke() {
return plainStroke ;
}
-
+
public Stroke getFinalLineStroke() {
return dashed;
}
diff --git a/src/PamView/paneloverlay/overlaymark/OverlayMark.java b/src/PamView/paneloverlay/overlaymark/OverlayMark.java
index 00238a6c..2cadab21 100644
--- a/src/PamView/paneloverlay/overlaymark/OverlayMark.java
+++ b/src/PamView/paneloverlay/overlaymark/OverlayMark.java
@@ -232,6 +232,9 @@ public class OverlayMark {
}
PamCoordinate c0 = projector.getCoord3d(coordinates.get(0));
PamCoordinate c1 = projector.getCoord3d(coordinates.get(1));
+ if (c0 == null || c1 == null) {
+ return null;
+ }
double x = Math.min(c0.getCoordinate(0), c1.getCoordinate(0));
double y = Math.min(c0.getCoordinate(1), c1.getCoordinate(1));
double w = Math.abs(c0.getCoordinate(0) - c1.getCoordinate(0));
From 7d0df4ca2d254016b45ccfef354903d89cbcb87f Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Thu, 23 Jun 2022 16:30:17 +0100
Subject: [PATCH 34/37] Update MarkOverlayDraw.java
fix null pointer crash
---
src/PamView/paneloverlay/overlaymark/MarkOverlayDraw.java | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/PamView/paneloverlay/overlaymark/MarkOverlayDraw.java b/src/PamView/paneloverlay/overlaymark/MarkOverlayDraw.java
index 1a7d6f76..530b6a97 100644
--- a/src/PamView/paneloverlay/overlaymark/MarkOverlayDraw.java
+++ b/src/PamView/paneloverlay/overlaymark/MarkOverlayDraw.java
@@ -76,6 +76,9 @@ public class MarkOverlayDraw extends PanelOverlayDraw {
hoverData.setTransformShape(t);
generalProjector.addHoverData(t, pamDataUnit);
}
+ if (drawnShape == null) {
+ return null;
+ }
return drawnShape.getBounds();
}
From 6ffc807803cdef663021351765f16203351ae39d Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Fri, 24 Jun 2022 11:28:48 +0100
Subject: [PATCH 35/37] Improve scroller logging
Additional options to only log outer scroller (data load) movement, not the very fine stuff.
---
src/effortmonitor/EffortControl.java | 82 +++++++++++++++-
src/effortmonitor/EffortDataUnit.java | 10 ++
src/effortmonitor/EffortParams.java | 5 +
src/effortmonitor/swing/EffortDialog.java | 18 ++++
src/effortmonitor/swing/EffortSidePanel.java | 99 ++++++++++++++++++++
src/pamScrollSystem/PamScrollerData.java | 2 +-
6 files changed, 213 insertions(+), 3 deletions(-)
create mode 100644 src/effortmonitor/swing/EffortSidePanel.java
diff --git a/src/effortmonitor/EffortControl.java b/src/effortmonitor/EffortControl.java
index 318a6bab..a15b1cf2 100644
--- a/src/effortmonitor/EffortControl.java
+++ b/src/effortmonitor/EffortControl.java
@@ -5,6 +5,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.Vector;
import javax.swing.JCheckBoxMenuItem;
@@ -18,14 +19,18 @@ import PamController.PamController;
import PamController.PamSettingManager;
import PamController.PamSettings;
import PamUtils.PamCalendar;
+import PamView.PamSidePanel;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamProcess;
import PamguardMVC.debug.Debug;
import effortmonitor.swing.EffortDataMapGraph;
import effortmonitor.swing.EffortDialog;
import effortmonitor.swing.EffortDisplayProvider;
+import effortmonitor.swing.EffortSidePanel;
import pamScrollSystem.AbstractPamScroller;
import pamScrollSystem.AbstractScrollManager;
+import pamScrollSystem.PamScroller;
+import pamScrollSystem.PamScrollerData;
import userDisplay.UserDisplayControl;
public class EffortControl extends PamControlledUnit implements PamSettings{
@@ -42,6 +47,10 @@ public class EffortControl extends PamControlledUnit implements PamSettings{
private EffortDataMapGraph dataMapGraph;
+ private HashMap lastOuterStarts = new HashMap<>();
+
+ private EffortSidePanel effortSidePanel;
+
public EffortControl(String unitName) {
super("unitType", unitName);
EffortProcess effortProc = new EffortProcess();
@@ -50,12 +59,22 @@ public class EffortControl extends PamControlledUnit implements PamSettings{
effortProc.addOutputDataBlock(effortDataBlock);
effortDataBlock.SetLogging(new EffortLogging(this, effortDataBlock));
dataMapGraph = new EffortDataMapGraph(this);
+
+// PamScroller
UserDisplayControl.addUserDisplayProvider(new EffortDisplayProvider(this));
PamSettingManager.getInstance().registerSettings(this);
}
+ @Override
+ public PamSidePanel getSidePanel() {
+ if (effortSidePanel == null) {
+ effortSidePanel = new EffortSidePanel(this);
+ }
+ return effortSidePanel;
+ }
+
@Override
public void notifyModelChanged(int changeType) {
super.notifyModelChanged(changeType);
@@ -65,6 +84,10 @@ public class EffortControl extends PamControlledUnit implements PamSettings{
break;
case PamController.NEW_SCROLL_TIME:
updateScrollerInfo();
+ break;
+ case PamController.DATA_LOAD_COMPLETE:
+ updateScrollerInfo();
+ break;
}
}
@@ -102,7 +125,25 @@ public class EffortControl extends PamControlledUnit implements PamSettings{
*/
return;
}
+
+ boolean newOuter = isNewOuter(scroller);
+ if (effortParams.outserScrollOnly) {
+ if (newOuter) {
+ logOuterScroll(scroller);
+ }
+ }
+ else {
+ logInnerScroll(scroller);
+ }
+ }
+
+ private void logOuterScroll(AbstractPamScroller scroller) {
+ EffortDataUnit effortData = new EffortDataUnit(scroller, effortParams.getObserver(), effortParams.getObjective());
+ effortData.setOuterLimits();
+ effortDataBlock.addPamData(effortData);
+ }
+ private void logInnerScroll(AbstractPamScroller scroller) {
// checkObserverName();
EffortDataUnit effortData = effortDataBlock.findActiveUnit(scroller);
@@ -129,6 +170,38 @@ public class EffortControl extends PamControlledUnit implements PamSettings{
}
}
+ /**
+ * Has the outer scroll moved.
+ * @param scroller
+ * @return true if the outer has moved.
+ */
+ private boolean isNewOuter(AbstractPamScroller scroller) {
+ PamScrollerData lastData = lastOuterStarts.get(scroller);
+ PamScrollerData nowVal = scroller.getScrollerData();
+ if (nowVal == null) {
+ return false; // shouldn't happen !
+ }
+ boolean changed = isChanged(lastData, nowVal);
+ if (changed) {
+ lastOuterStarts.put(scroller, nowVal.clone());
+ }
+ return changed;
+ }
+
+ private boolean isChanged(PamScrollerData lastData, PamScrollerData nowVal) {
+ if (lastData == null || nowVal == null) {
+ return true;
+ }
+ if (lastData.getMinimumMillis() != nowVal.getMinimumMillis()) {
+ return true;
+ }
+ if (lastData.getMaximumMillis() != nowVal.getMaximumMillis()) {
+ return true;
+ }
+
+ return false;
+ }
+
/**
* Quick and dirty to get observer name.
*/
@@ -203,9 +276,11 @@ public class EffortControl extends PamControlledUnit implements PamSettings{
existingUnit.setObserver(newParams.getObserver());
existingUnit.setObjective(newParams.getObjective());
}
- return true;
}
- return false;
+ if (effortSidePanel != null) {
+ effortSidePanel.updateSettings();
+ }
+ return newParams!=null;
}
public void goToTime(AbstractPamScroller scroller, long timeInMilliseconds) {
@@ -235,6 +310,9 @@ public class EffortControl extends PamControlledUnit implements PamSettings{
@Override
public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
effortParams = ((EffortParams) pamControlledUnitSettings.getSettings());
+ if (effortSidePanel != null) {
+ effortSidePanel.updateSettings();
+ }
return true;
}
diff --git a/src/effortmonitor/EffortDataUnit.java b/src/effortmonitor/EffortDataUnit.java
index d4e802c8..99c8eb7f 100644
--- a/src/effortmonitor/EffortDataUnit.java
+++ b/src/effortmonitor/EffortDataUnit.java
@@ -42,6 +42,7 @@ public class EffortDataUnit extends PamDataUnit {
getBasicData().setEndTime(scroller.getValueMillis()+scroller.getVisibleAmount());
}
+
/**
* Constructor to use when reloading from database.
* @param databaseIndex
@@ -210,4 +211,13 @@ public class EffortDataUnit extends PamDataUnit {
return runMode;
}
+
+ /**
+ * Set the limits as the outer limits of the scroller.
+ */
+ public void setOuterLimits() {
+ setTimeMilliseconds(scroller.getMinimumMillis());
+ getBasicData().setEndTime(scroller.getMaximumMillis());
+ }
+
}
diff --git a/src/effortmonitor/EffortParams.java b/src/effortmonitor/EffortParams.java
index beb35249..fcd5bcb5 100644
--- a/src/effortmonitor/EffortParams.java
+++ b/src/effortmonitor/EffortParams.java
@@ -16,6 +16,11 @@ public class EffortParams implements Cloneable, Serializable, ManagedParameters
public transient boolean isSet;
+ /**
+ * Only log outer scroll events when paging forwards, not every little movement.
+ */
+ public boolean outserScrollOnly = false;
+
private static final int MAX_OBSERVERS = 10;
private static final int MAX_OBJECTIVES = 10;
diff --git a/src/effortmonitor/swing/EffortDialog.java b/src/effortmonitor/swing/EffortDialog.java
index 3c8b6cdf..4f4d8b7f 100644
--- a/src/effortmonitor/swing/EffortDialog.java
+++ b/src/effortmonitor/swing/EffortDialog.java
@@ -8,9 +8,11 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
+import javax.swing.ButtonGroup;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
+import javax.swing.JRadioButton;
import javax.swing.border.TitledBorder;
import PamView.DBTextArea;
@@ -29,6 +31,7 @@ public class EffortDialog extends PamDialog {
private JComboBox observer;
private JComboBox oldObjectives;
private DBTextArea objective;
+ private JRadioButton outerOnly, allActions;
private EffortDialog(Window parentFrame, EffortControl effortControl) {
super(parentFrame, effortControl.getUnitName(), false);
@@ -40,6 +43,18 @@ public class EffortDialog extends PamDialog {
mainPanel.add(new JLabel("Observer name or initials"), c);
c.gridx++;
mainPanel.add(observer = new JComboBox(), c);
+ outerOnly = new JRadioButton("Log uter scroll only");
+ allActions = new JRadioButton("Log all scroll actions");
+ ButtonGroup bg = new ButtonGroup();
+ bg.add(allActions);
+ bg.add(outerOnly);
+ c.gridx = 0;
+ c.gridy++;
+ c.gridwidth = 1;
+ mainPanel.add(allActions, c);
+ c.gridx+=c.gridwidth;
+ mainPanel.add(outerOnly, c);
+
c.gridx = 0;
c.gridy++;
c.gridwidth = 2;
@@ -80,6 +95,8 @@ public class EffortDialog extends PamDialog {
for (String obs : oldObs) {
observer.addItem(obs);
}
+ allActions.setSelected(effortParams.outserScrollOnly == false);
+ outerOnly.setSelected(effortParams.outserScrollOnly);
oldObjectives.removeAllItems();
oldObjectives.addItem("");
for (String obj : effortParams.getRecentObjectives()) {
@@ -100,6 +117,7 @@ public class EffortDialog extends PamDialog {
if (obs == null || obs.length() == 0) {
return showWarning("You must give your name or initials to contine");
}
+ effortParams.outserScrollOnly = outerOnly.isSelected();
effortParams.setObserver(obs);
effortParams.setObjective(objective.getText());
return true;
diff --git a/src/effortmonitor/swing/EffortSidePanel.java b/src/effortmonitor/swing/EffortSidePanel.java
new file mode 100644
index 00000000..d10ab983
--- /dev/null
+++ b/src/effortmonitor/swing/EffortSidePanel.java
@@ -0,0 +1,99 @@
+package effortmonitor.swing;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JTextField;
+import javax.swing.border.TitledBorder;
+
+import PamView.PamSidePanel;
+import PamView.component.PamSettingsIconButton;
+import PamView.dialog.PamCheckBox;
+import PamView.dialog.PamGridBagContraints;
+import PamView.dialog.PamLabel;
+import PamView.dialog.PamTextField;
+import PamView.panel.PamPanel;
+import effortmonitor.EffortControl;
+import effortmonitor.EffortObserver;
+import effortmonitor.EffortParams;
+
+public class EffortSidePanel implements PamSidePanel, EffortObserver {
+
+ private PamPanel mainPanel;
+
+ private PamTextField person;
+
+ private PamCheckBox logging;
+
+ private PamSettingsIconButton settingsButton;
+
+ private EffortControl effortControl;
+
+ public EffortSidePanel(EffortControl effortControl) {
+ this.effortControl = effortControl;
+
+ mainPanel = new PamPanel(new GridBagLayout());
+ mainPanel.setBorder(new TitledBorder(effortControl.getUnitName()));
+ GridBagConstraints c = new PamGridBagContraints();
+ mainPanel.add(new PamLabel("Person ", JLabel.RIGHT), c);
+ c.gridx++;
+ mainPanel.add(person = new PamTextField(6), c);
+ person.setEditable(false);
+ c.gridx = 0;
+ c.gridy++;
+ c.gridwidth = 1;
+ mainPanel.add(logging = new PamCheckBox("Log effort"), c);
+ c.gridx += c.gridwidth;
+ mainPanel.add(settingsButton = new PamSettingsIconButton(), c);
+ settingsButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ settings();
+ }
+ });
+ effortControl.addObserver(this);
+ logging.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ loggingButton();
+ }
+ });
+
+ updateSettings();
+ }
+
+ protected void loggingButton() {
+ effortControl.setOnEffort(logging.isSelected());
+ }
+
+ protected void settings() {
+ effortControl.showSettingsDialog(effortControl.getGuiFrame(), null);
+ }
+
+ public void updateSettings() {
+ EffortParams params = effortControl.getEffortParams();
+ person.setText(params.getObserver());
+ logging.setSelected(params.isSet);
+ }
+
+ @Override
+ public JComponent getPanel() {
+ return mainPanel;
+ }
+
+ @Override
+ public void rename(String newName) {
+ mainPanel.setBorder(new TitledBorder(newName));
+ }
+
+ @Override
+ public void statusChange() {
+ updateSettings();
+ }
+
+}
diff --git a/src/pamScrollSystem/PamScrollerData.java b/src/pamScrollSystem/PamScrollerData.java
index 133dde58..11cc7265 100644
--- a/src/pamScrollSystem/PamScrollerData.java
+++ b/src/pamScrollSystem/PamScrollerData.java
@@ -58,7 +58,7 @@ public class PamScrollerData implements Serializable, Cloneable {
@Override
- protected PamScrollerData clone() {
+ public PamScrollerData clone() {
try {
return (PamScrollerData) super.clone();
} catch (CloneNotSupportedException e) {
From e176899a59f8f5ed3d3a29482a60445b4c02a0b0 Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Fri, 24 Jun 2022 12:29:38 +0100
Subject: [PATCH 36/37] Add fin whale simulator and ROCCA bug
Add 20Hz simulator and another go at ROCCA memory leak
---
dependency-reduced-pom.xml | 2 +-
pom.xml | 2 +-
src/PamController/PamguardVersionInfo.java | 4 ++--
src/rocca/RoccaSidePanel.java | 7 +++++--
src/simulatedAcquisition/SimProcess.java | 2 +-
src/simulatedAcquisition/sounds/SimSignals.java | 3 +++
6 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml
index 7ee84c51..5c0901f5 100644
--- a/dependency-reduced-pom.xml
+++ b/dependency-reduced-pom.xml
@@ -4,7 +4,7 @@
org.pamguard
Pamguard
Pamguard Java12+
- 2.02.04
+ 2.02.04a
Pamguard for Java 12+, using Maven to control dependcies
www.pamguard.org
diff --git a/pom.xml b/pom.xml
index cfccc70f..8a92ccc5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
org.pamguard
Pamguard
- 2.02.04
+ 2.02.04a
Pamguard Java12+
Pamguard for Java 12+, using Maven to control dependcies
www.pamguard.org
diff --git a/src/PamController/PamguardVersionInfo.java b/src/PamController/PamguardVersionInfo.java
index 2c91e596..7864fce0 100644
--- a/src/PamController/PamguardVersionInfo.java
+++ b/src/PamController/PamguardVersionInfo.java
@@ -31,12 +31,12 @@ public class PamguardVersionInfo {
* Version number, major version.minorversion.sub-release.
* Note: can't go higher than sub-release 'f'
*/
- static public final String version = "2.02.04";
+ static public final String version = "2.02.04a";
/**
* Release date
*/
- static public final String date = "11 June 2022";
+ static public final String date = "23 June 2022";
// /**
// * Release type - Beta or Core
diff --git a/src/rocca/RoccaSidePanel.java b/src/rocca/RoccaSidePanel.java
index 281724cc..35a8fa55 100644
--- a/src/rocca/RoccaSidePanel.java
+++ b/src/rocca/RoccaSidePanel.java
@@ -115,8 +115,11 @@ public class RoccaSidePanel extends PamObserverAdapter implements PamSidePanel
(roccaControl.roccaProcess,
roccaControl.roccaParameters.getChannelMap());
- // this one probably OK to never delete ?
- rsdb.setNaturalLifetimeMillis(Integer.MAX_VALUE);
+ /*
+ * this one probably OK to never delete ? Nope lots of stuff goes in
+ * here, so it seems it will eventually bring the system down.
+ */
+ rsdb.setNaturalLifetimeMillis(roccaControl.getMaxDataKeepTime());
rdl = new RoccaDetectionLogger(this, rsdb);
rsdb.SetLogging(rdl);
diff --git a/src/simulatedAcquisition/SimProcess.java b/src/simulatedAcquisition/SimProcess.java
index 50f998d3..f8905170 100644
--- a/src/simulatedAcquisition/SimProcess.java
+++ b/src/simulatedAcquisition/SimProcess.java
@@ -304,7 +304,7 @@ public class SimProcess extends DaqSystem implements PamSettings {
/* simulate the noise, need to divide fs by 2 to only generate for 0 to Nyquist to get correct values out.
* that match the results of the noise band monitor modules.
*/
- double dbNse = simParameters.backgroundNoise + 10*Math.log10(getSampleRate()/2);
+ double dbNse = simParameters.backgroundNoise + 10*Math.log10(getSampleRate()/2.);
nse = daqControl.getDaqProcess().dbMicropascalToSignal(i, dbNse);
generateNoise(channelData, nse);
// generateNoiseQuickly(channelData, nse, i);
diff --git a/src/simulatedAcquisition/sounds/SimSignals.java b/src/simulatedAcquisition/sounds/SimSignals.java
index 96e0db19..63137a51 100644
--- a/src/simulatedAcquisition/sounds/SimSignals.java
+++ b/src/simulatedAcquisition/sounds/SimSignals.java
@@ -27,6 +27,9 @@ public class SimSignals {
simSignalList.add(new ClickSound("Click", 3000, 3000, 2e-3, WINDOWTYPE.DECAY));
simSignalList.add(new ClickSound("Chirp", 3000, 6000, 0.1, WINDOWTYPE.TAPER10));
simSignalList.add(new ClickSound("Chirp", 3000, 8000, 0.5, WINDOWTYPE.TAPER10));
+ simSignalList.add(new ClickSound("Dolphin Click", 60000, 60000, 20.e-6, WINDOWTYPE.DECAY));
+ simSignalList.add(new ClickSound("Fin 20Hz", 20, 20, 0.5, WINDOWTYPE.HANN));
+ simSignalList.add(new ClickSound("Fin 40Hz", 40, 40, 0.5, WINDOWTYPE.HANN));
// simSignalList.add(new LinearChirp(simProcess.getSampleRate(), 3000, 6000, 0.1));
// simSignalList.add(new LinearChirp(simProcess.getSampleRate(), 3000, 8000, .5));
simSignalList.add(new RandomWhistles());
From b916209f4fda92877a5f117356a02d756bc2ed5f Mon Sep 17 00:00:00 2001
From: Douglas Gillespie <50671166+douggillespie@users.noreply.github.com>
Date: Fri, 24 Jun 2022 15:53:48 +0100
Subject: [PATCH 37/37] Better GoTo options for click events and
groupdetections
In tables, can now scroll to 10 or 60s before the marked event, which is
often more useful than scrolling to the exact start of those events.
---
src/PamModel/PamModel.java | 2 +-
src/clickDetector/ClickBTDisplay.java | 6 +-
src/clickDetector/ClickControl.java | 5 +-
src/clickDetector/ClickDisplayManager.java | 5 +-
.../offlineFuncs/EventListDialog.java | 22 ++++-
.../DetectionGroupControl.java | 3 +-
.../dialogs/DetectionGroupTable.java | 91 +++++++++++--------
7 files changed, 81 insertions(+), 53 deletions(-)
diff --git a/src/PamModel/PamModel.java b/src/PamModel/PamModel.java
index f0849981..d14cbb02 100644
--- a/src/PamModel/PamModel.java
+++ b/src/PamModel/PamModel.java
@@ -451,7 +451,7 @@ final public class PamModel implements PamModelInterface, PamSettings {
mi = PamModuleInfo.registerControlledUnit(EffortControl.class.getName(), EffortControl.unitType);
mi.setToolTipText("Record observer monitoring effort");
mi.setModulesMenuGroup(utilitiesGroup);
- mi.setHidden(SMRUEnable.isEnable() == false);
+// mi.setHidden(SMRUEnable.isEnable() == false);
mi.setToolTipText("Enables an observer to enter their name and infomation about which displays are being monitored");
mi.setMaxNumber(1);
diff --git a/src/clickDetector/ClickBTDisplay.java b/src/clickDetector/ClickBTDisplay.java
index a8556bdd..07c208d0 100644
--- a/src/clickDetector/ClickBTDisplay.java
+++ b/src/clickDetector/ClickBTDisplay.java
@@ -3660,15 +3660,15 @@ public class ClickBTDisplay extends ClickDisplay implements PamObserver, PamSett
/**
* Scroll the display to a specific event.
* @param event event to scroll to
+ * @param beforeTime seconds before the event to scroll to.
*/
- public void gotoEvent(OfflineEventDataUnit event) {
- long evStart = event.getTimeMilliseconds();
+ public void gotoEvent(OfflineEventDataUnit event, int beforeTime) {
+ long evStart = event.getTimeMilliseconds() - beforeTime*1000;
if (evStart < hScrollBar.getMinimumMillis() || evStart > hScrollBar.getMaximumMillis()) {
long range = hScrollBar.getMaximumMillis() - hScrollBar.getMinimumMillis();
hScrollBar.setRangeMillis(evStart, evStart + range, true);
}
hScrollBar.setValueMillis(evStart);
-
}
int playbackStatus = PlaybackProgressMonitor.PLAY_END;
diff --git a/src/clickDetector/ClickControl.java b/src/clickDetector/ClickControl.java
index e5a783b5..e5b6fce9 100644
--- a/src/clickDetector/ClickControl.java
+++ b/src/clickDetector/ClickControl.java
@@ -1015,9 +1015,10 @@ public class ClickControl extends PamControlledUnit implements PamSettings {
/**
* Scrolls the display to a specific event.
* @param event event to scroll to
+ * @param beforeTime
*/
- public void gotoEvent(OfflineEventDataUnit event) {
- tabPanelControl.clickDisplayManager.gotoEvent(event);
+ public void gotoEvent(OfflineEventDataUnit event, int beforeTime) {
+ tabPanelControl.clickDisplayManager.gotoEvent(event, beforeTime);
}
/**
diff --git a/src/clickDetector/ClickDisplayManager.java b/src/clickDetector/ClickDisplayManager.java
index 23237197..f46aeca8 100644
--- a/src/clickDetector/ClickDisplayManager.java
+++ b/src/clickDetector/ClickDisplayManager.java
@@ -463,11 +463,12 @@ public class ClickDisplayManager implements PamSettings {
/**
* Scroll the time displays to a specific event.
* @param event
+ * @param beforeTime
*/
- public void gotoEvent(OfflineEventDataUnit event) {
+ public void gotoEvent(OfflineEventDataUnit event, int beforeTime) {
for (int i = 0; i < windowList.size(); i++) {
if (windowList.get(i).getClass() == ClickBTDisplay.class) {
- ((ClickBTDisplay)windowList.get(i)).gotoEvent(event);
+ ((ClickBTDisplay)windowList.get(i)).gotoEvent(event, beforeTime);
}
}
}
diff --git a/src/clickDetector/offlineFuncs/EventListDialog.java b/src/clickDetector/offlineFuncs/EventListDialog.java
index 75b5c405..b40d6eab 100644
--- a/src/clickDetector/offlineFuncs/EventListDialog.java
+++ b/src/clickDetector/offlineFuncs/EventListDialog.java
@@ -175,9 +175,19 @@ public class EventListDialog extends PamDialog {
JPopupMenu menu = new JPopupMenu();
JMenuItem menuItem;
int evNo = event.getDatabaseIndex();
- menuItem = new JMenuItem(String.format("Goto event %d ...", evNo));
- menuItem.addActionListener(new GotoEvent(event));
- menu.add(menuItem);
+ int[] beforeTimes = {0, 10, 60};
+ for (int i = 0; i < beforeTimes.length; i++) {
+ String title;
+ if (beforeTimes[i] == 0) {
+ title = String.format("Goto event %d ...", evNo);
+ }
+ else {
+ title = String.format("Goto %ds before event %d ...", beforeTimes[i], evNo);
+ }
+ menuItem = new JMenuItem(title);
+ menuItem.addActionListener(new GotoEvent(event, beforeTimes[i]));
+ menu.add(menuItem);
+ }
menuItem = new JMenuItem(String.format("Edit event %d ...", evNo));
menuItem.addActionListener(new EditEvent(event));
menu.add(menuItem);
@@ -219,14 +229,16 @@ public class EventListDialog extends PamDialog {
private class GotoEvent implements ActionListener {
private OfflineEventDataUnit event;
+ private int beforeTime;
- public GotoEvent(OfflineEventDataUnit event) {
+ public GotoEvent(OfflineEventDataUnit event, int beforeTime) {
this.event = event;
+ this.beforeTime = beforeTime;
}
@Override
public void actionPerformed(ActionEvent arg0) {
- clickControl.gotoEvent(event);
+ clickControl.gotoEvent(event, beforeTime);
}
}
diff --git a/src/detectiongrouplocaliser/DetectionGroupControl.java b/src/detectiongrouplocaliser/DetectionGroupControl.java
index e7aa5c3d..4361fb85 100644
--- a/src/detectiongrouplocaliser/DetectionGroupControl.java
+++ b/src/detectiongrouplocaliser/DetectionGroupControl.java
@@ -24,7 +24,8 @@ import detectiongrouplocaliser.dialogs.DisplayOptionsHandler;
import userDisplay.UserDisplayControl;
/**
- * Class for grouping any type of data together.
+ * Class for grouping any type of data together. Not really a localiser, but
+ * does include some localisation options.
* Will attempt to offer a variety of localisation options and will store data for each group
* in a pair of database tables.
* @author dg50
diff --git a/src/detectiongrouplocaliser/dialogs/DetectionGroupTable.java b/src/detectiongrouplocaliser/dialogs/DetectionGroupTable.java
index a111226b..a51709e8 100644
--- a/src/detectiongrouplocaliser/dialogs/DetectionGroupTable.java
+++ b/src/detectiongrouplocaliser/dialogs/DetectionGroupTable.java
@@ -56,23 +56,23 @@ import warnings.PamWarning;
public class DetectionGroupTable extends UserDisplayComponentAdapter implements DetectionGroupObserver {
private JPanel mainPanel;
-
+
private DetectionGroupProcess detectionGroupProcess;
-
+
private DetectionGroupDataBlock detectionGroupDataBlock;
-
+
private DetectionGroupControl detectionGroupControl;
-
+
private JTable table;
private TableModel tableModel;
private JScrollPane scrollPane;
-
+
private JPanel controlPanel;
-
+
private JRadioButton showAll, showCurrent;
-
+
private JButton checkIntegrity;
private boolean isViewer;
@@ -80,7 +80,7 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements
private DisplayOptionsHandler displayOptionsHandler;
private SwingTableColumnWidths widthManager;
-
+
public DetectionGroupTable(DetectionGroupProcess detectionGroupProcess) {
super();
this.detectionGroupProcess = detectionGroupProcess;
@@ -95,7 +95,7 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements
mainPanel.add(BorderLayout.CENTER, scrollPane);
detectionGroupControl.addGroupObserver(this);
table.addMouseListener(new TableMouseHandler());
-
+
if (isViewer) {
displayOptionsHandler = detectionGroupControl.getDisplayOptionsHandler();
controlPanel = new JPanel(new BorderLayout());
@@ -134,9 +134,9 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements
}
});
}
-
-
-// sortColumnWidths();
+
+
+ // sortColumnWidths();
}
@@ -144,7 +144,7 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements
public Component getComponent() {
return mainPanel;
}
-
+
/* (non-Javadoc)
* @see userDisplay.UserDisplayComponentAdapter#openComponent()
*/
@@ -195,7 +195,7 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements
showPopupMenu(e);
}
}
-
+
}
@Override
@@ -205,7 +205,7 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements
public void editSelectedEvent(MouseEvent e) {
// TODO Auto-generated method stub
-
+
}
@@ -234,26 +234,39 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements
menuItem = annotationHandler.createAnnotationEditMenu(dgdu);
menuItem.setIcon(menuIcon);
pMenu.add(menuItem);
-
- menuItem = new JMenuItem("Scroll to Group UID " + dgdu.getUID() + " at " + PamCalendar.formatDBDateTime(dgdu.getTimeMilliseconds()));
- menuItem.setIcon(menuIcon);
- menuItem.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- scrollToEvent(dgdu.getTimeMilliseconds());
+
+ int[] beforeTimesSecs = {0, 10, 60};
+ pMenu.addSeparator();
+ for (int i = 0; i < beforeTimesSecs.length; i++) {
+ int before = beforeTimesSecs[i];
+ String title;
+ if (before == 0) {
+ title = "Scroll to Group UID " + dgdu.getUID() + " at " + PamCalendar.formatDBDateTime(dgdu.getTimeMilliseconds());
}
- });
- pMenu.add(menuItem);
+ else {
+ title = String.format("Scroll to %ds before Group UID %d", before, dgdu.getUID());
+ }
+ menuItem = new JMenuItem(title);
+ // menuItem.setIcon(menuIcon);
+ menuItem.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ scrollToEvent(dgdu.getTimeMilliseconds()-before*1000);
+ }
+ });
+ pMenu.add(menuItem);
+ }
+
pMenu.show(e.getComponent(), e.getX(), e.getY());
}
protected void scrollToEvent(long timeMilliseconds) {
// start a it earlier.
timeMilliseconds -= 5000;
-// now WTF - how do I tell every scroller to go to this point in time ?
+ // now WTF - how do I tell every scroller to go to this point in time ?
AbstractScrollManager scrollManager = AbstractScrollManager.getScrollManager();
scrollManager.startDataAt(detectionGroupDataBlock, timeMilliseconds);
-
+
}
@@ -300,9 +313,9 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements
TableColumn tableCol = table.getColumnModel().getColumn(i);
tableCol.setPreferredWidth(tableModel.getRelativeWidth(i)*50);
}
-
+
}
-
+
private int getViewOption() {
if (!isViewer) {
return DisplayOptionsHandler.SHOW_ALL;
@@ -348,7 +361,7 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements
@Override
public int getRowCount() {
-// System.out.println("getRowCount()");
+ // System.out.println("getRowCount()");
if (getViewOption() == DisplayOptionsHandler.SHOW_ALL) {
firstRowToShow = 0;
return numRowsToShow = detectionGroupDataBlock.getUnitsCount();
@@ -396,9 +409,9 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements
return null;
}
case 2:
-// if (iRow == 0) {
-// System.out.println("getValueAt(0,0)");
-// }
+ // if (iRow == 0) {
+ // System.out.println("getValueAt(0,0)");
+ // }
return dgdu.getUID();
case 3:
return PamCalendar.formatDateTime(dgdu.getTimeMilliseconds());
@@ -416,16 +429,16 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements
if (annotation != null) {
return annotation.toString();
}
-
+
}
-
+
}
catch (Exception e) {
return null;
}
return null;
}
-
+
@Override
public Class> getColumnClass(int col) {
if (col == 0) {
@@ -433,7 +446,7 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements
}
return super.getColumnClass(col);
}
-
+
/* (non-Javadoc)
* @see javax.swing.table.AbstractTableModel#fireTableStructureChanged()
*/
@@ -486,7 +499,7 @@ public class DetectionGroupTable extends UserDisplayComponentAdapter implements
widthManager = new SwingTableColumnWidths(uniqueName, table);
super.setUniqueName(uniqueName);
}
-
-
-
+
+
+
}