mirror of
https://github.com/PAMGuard/PAMGuard.git
synced 2024-11-21 22:52:22 +00:00
Rw improvement (#16)
* Update .project * RWE imporvement to peak detection and dealing with smoothing. * Make improvements to MARW edge detector so that it doesn't merge harmonics, by using a threshold down from the peak as well as up from the noise
This commit is contained in:
parent
591d3157b6
commit
e0c9abcc3d
@ -6,8 +6,9 @@
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="module" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
|
2
.project
2
.project
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>PamGuard Main</name>
|
||||
<name>PamGuard Main DG</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
|
@ -264,7 +264,8 @@ public class StandardFileDate implements FileDate, PamSettings {
|
||||
// System.out.println(d);
|
||||
} catch (ParseException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
// e.printStackTrace();
|
||||
System.out.println(e.getMessage());
|
||||
} //throws ParseException if no match
|
||||
setLastFormat(forcedDateFormat);
|
||||
return d.getTime();
|
||||
|
@ -10,6 +10,7 @@ import javax.swing.JMenuItem;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import KernelSmoothing.KernelSmoothingProcess;
|
||||
import PamController.PamControlledUnit;
|
||||
import PamController.PamControlledUnitSettings;
|
||||
import PamController.PamController;
|
||||
@ -20,6 +21,8 @@ import PamUtils.PamUtils;
|
||||
import PamView.GroupedDataSource;
|
||||
import PamView.GroupedSourceParameters;
|
||||
import PamView.dialog.GroupedSourcePanel;
|
||||
import PamguardMVC.PamDataBlock;
|
||||
import PamguardMVC.ProcessAnnotation;
|
||||
|
||||
/**
|
||||
* Exact implementation of the 2003 Right Whale detector I developed when I was
|
||||
@ -85,6 +88,19 @@ public class RWEControl extends PamControlledUnit implements PamSettings {
|
||||
rweProcess.setupProcesses();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the input process has implemented kernel smoothing.
|
||||
* @param inputBlock input data block (should be fft data).
|
||||
* @return true if kernel smoothing is in place.
|
||||
*/
|
||||
protected boolean hasKernelSmoothing(PamDataBlock inputBlock) {
|
||||
if (inputBlock == null) {
|
||||
return false;
|
||||
}
|
||||
ProcessAnnotation an = inputBlock.findAnnotation(KernelSmoothingProcess.processType, KernelSmoothingProcess.processName);
|
||||
return an != null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
|
@ -5,6 +5,7 @@ import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Window;
|
||||
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTabbedPane;
|
||||
@ -29,11 +30,15 @@ public class RWEDialog extends PamDialog {
|
||||
private static RWEDialog singleInstance;
|
||||
private SourcePanel sourcePanel;
|
||||
|
||||
private RWEControl rweControl;
|
||||
|
||||
private JTextField startFreq, endFreq, thresholdDB;
|
||||
private JTextField minSoundType;
|
||||
private JCheckBox downThreshold;
|
||||
|
||||
private RWEDialog(Window parentFrame) {
|
||||
private RWEDialog(RWEControl rweControl, Window parentFrame) {
|
||||
super(parentFrame, "Right Whale Edge Detector Settings", true);
|
||||
this.rweControl = rweControl;
|
||||
sourcePanel = new SourcePanel(this, "Source and Channels",
|
||||
FFTDataUnit.class, true, true);
|
||||
sourcePanel.setSourceToolTip("Data source should be the output of a Spectrogram Smmothing Kernel");
|
||||
@ -67,6 +72,11 @@ public class RWEDialog extends PamDialog {
|
||||
addComponent(det, thresholdDB = new JTextField(5), c);
|
||||
c.gridx++;
|
||||
addComponent(det, new JLabel(" dB", SwingConstants.RIGHT), c);
|
||||
c.gridy++;
|
||||
c.gridx = 0;
|
||||
addComponent(det, new JLabel("Appy down threshold ", SwingConstants.RIGHT), c);
|
||||
c.gridx++;
|
||||
addComponent(det, downThreshold = new JCheckBox(), c);
|
||||
|
||||
JPanel cl = new JPanel(new GridBagLayout());
|
||||
cl.setBorder(new TitledBorder("Detection"));
|
||||
@ -85,6 +95,7 @@ public class RWEDialog extends PamDialog {
|
||||
}
|
||||
txt += "</html>";
|
||||
minSoundType.setToolTipText(txt);
|
||||
downThreshold.setToolTipText("Applies threshold as dB down from the peak, as well as up from the noise floor");
|
||||
|
||||
pp.add(BorderLayout.NORTH, det);
|
||||
pp.add(BorderLayout.CENTER, cl);
|
||||
@ -96,8 +107,8 @@ public class RWEDialog extends PamDialog {
|
||||
}
|
||||
|
||||
public static RWEParameters showDialog(Window frame, RWEControl rweControl) {
|
||||
if (singleInstance == null || frame != singleInstance.getOwner()) {
|
||||
singleInstance = new RWEDialog(frame);
|
||||
if (singleInstance == null || frame != singleInstance.getOwner() || rweControl != singleInstance.rweControl) {
|
||||
singleInstance = new RWEDialog(rweControl, frame);
|
||||
}
|
||||
singleInstance.rweParameters = rweControl.rweParameters.clone();
|
||||
singleInstance.setParams();
|
||||
@ -113,6 +124,7 @@ public class RWEDialog extends PamDialog {
|
||||
endFreq.setText(String.format("%3.1f", rweParameters.endFreq));
|
||||
double thDB = 10. * Math.log10(rweParameters.threshold);
|
||||
thresholdDB.setText(String.format("%3.1f", thDB));
|
||||
downThreshold.setSelected(rweParameters.downThreshold);
|
||||
minSoundType.setText(String.format("%d", rweParameters.minSoundType));
|
||||
}
|
||||
|
||||
@ -120,6 +132,7 @@ public class RWEDialog extends PamDialog {
|
||||
public boolean getParams() {
|
||||
rweParameters.channelMap = sourcePanel.getChannelList();
|
||||
rweParameters.dataSourceName = sourcePanel.getSource().getDataName();
|
||||
rweParameters.downThreshold = downThreshold.isSelected();
|
||||
if (rweParameters.dataSourceName == null) {
|
||||
return showWarning("You must select a valid input data source");
|
||||
}
|
||||
@ -137,26 +150,13 @@ public class RWEDialog extends PamDialog {
|
||||
catch (NumberFormatException e) {
|
||||
return showWarning("Invalid detection or classification parameter");
|
||||
}
|
||||
boolean gok = checkInputProcessing();
|
||||
if (gok == false) {
|
||||
return showWarning("Right whale detector input must include Gaussian Kernel Smoothing as part of the FFT module, or a stand alone smoothing module");
|
||||
}
|
||||
// boolean gok = rweControl.hasKernelSmoothing(sourcePanel.getSource());
|
||||
// if (gok == false) {
|
||||
// return showWarning("Right whale detector input must include Gaussian Kernel Smoothing as part of the FFT module, or a stand alone smoothing module");
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that the input process has implemented kernel smoothing.
|
||||
* @return
|
||||
*/
|
||||
private boolean checkInputProcessing() {
|
||||
PamDataBlock db = sourcePanel.getSource();
|
||||
if (db == null) {
|
||||
return false;
|
||||
}
|
||||
ProcessAnnotation an = db.findAnnotation(KernelSmoothingProcess.processType, KernelSmoothingProcess.processName);
|
||||
return an != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelButtonPressed() {
|
||||
rweParameters = null;
|
||||
|
@ -27,6 +27,8 @@ public class RWEParameters implements Serializable, Cloneable, ManagedParameters
|
||||
|
||||
public int minSoundType = 5;
|
||||
|
||||
public boolean downThreshold = false;
|
||||
|
||||
@Override
|
||||
protected RWEParameters clone() {
|
||||
try {
|
||||
|
@ -16,6 +16,7 @@ import fftManager.Complex;
|
||||
import fftManager.FFTDataBlock;
|
||||
import fftManager.FFTDataUnit;
|
||||
import networkTransfer.receive.BuoyStatusDataUnit;
|
||||
import spectrogramNoiseReduction.kernelSmoothing.KernelSmoothing;
|
||||
import whistlesAndMoans.WhistleBearingInfo;
|
||||
import PamController.PamController;
|
||||
import PamDetection.AbstractLocalisation;
|
||||
@ -43,6 +44,11 @@ public class RWEProcess extends PamProcess {
|
||||
|
||||
private Hashtable<Integer, BearingLocaliser> bearingLocalisers;
|
||||
private StandardSymbolManager symbolManager;
|
||||
/**
|
||||
* Already has Kernel smoothing applied to input data.
|
||||
*/
|
||||
private boolean isPreSmoothed;
|
||||
private KernelSmoothing kernelSmoothing;
|
||||
|
||||
public RWEProcess(RWEControl rweControl) {
|
||||
super(rweControl, null);
|
||||
@ -96,6 +102,18 @@ public class RWEProcess extends PamProcess {
|
||||
if (sourceDataBlock == null) {
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* work out if the fft source has already run the Guassian smoothing or not
|
||||
*/
|
||||
isPreSmoothed = rweControl.hasKernelSmoothing(sourceDataBlock);
|
||||
if (isPreSmoothed) {
|
||||
kernelSmoothing = null;
|
||||
}
|
||||
else {
|
||||
kernelSmoothing = new KernelSmoothing();
|
||||
kernelSmoothing.initialise(sourceDataBlock.getChannelMap());
|
||||
}
|
||||
// sourceDataBlock.findAnnotation(null);
|
||||
// rweDataBlock.setChannelMap(rweControl.rweParameters.channelMap);
|
||||
rweDataBlock.sortOutputMaps(sourceDataBlock.getChannelMap(), sourceDataBlock.getSequenceMapObject(), rweControl.rweParameters.channelMap);
|
||||
if (db == null) {
|
||||
@ -135,6 +153,7 @@ public class RWEProcess extends PamProcess {
|
||||
private int numOT; // number of bins in last analysed slice over threshold
|
||||
private int minSoundType;
|
||||
private RWClassifier classifier = new RWStandardClassifier();
|
||||
|
||||
public RWEChannelProcess(RWEProcess rweProcess, int iChannel) {
|
||||
this.rweProcess = rweProcess;
|
||||
this.iChannel = iChannel;
|
||||
@ -160,6 +179,15 @@ public class RWEProcess extends PamProcess {
|
||||
|
||||
|
||||
public void newData(FFTDataUnit fftDataUnit) {
|
||||
if (!isPreSmoothed) {
|
||||
FFTDataUnit newFFTUnit = new FFTDataUnit(fftDataUnit.getTimeMilliseconds(), fftDataUnit.getChannelBitmap(),
|
||||
fftDataUnit.getStartSample(), fftDataUnit.getSampleDuration(), null, fftDataUnit.getFftSlice());
|
||||
newFFTUnit.setSequenceBitmap(fftDataUnit.getSequenceBitmapObject());
|
||||
newFFTUnit.setFftData(fftDataUnit.getFftData().clone());
|
||||
kernelSmoothing.runNoiseReduction(newFFTUnit);
|
||||
fftDataUnit = newFFTUnit;
|
||||
}
|
||||
|
||||
RWEDetectionPeak[] newPeaks = findPeaks(fftDataUnit.getFftData());
|
||||
RWESound[] newSounds = findSounds(fftDataUnit.getTimeMilliseconds(), newPeaks);
|
||||
if (newSounds == null) {
|
||||
@ -197,6 +225,7 @@ public class RWEProcess extends PamProcess {
|
||||
RWEDetectionPeak[] detectedPeaks = null;
|
||||
int nPeaks = 0;
|
||||
int nOver = 0;
|
||||
double onDown = rweControl.rweParameters.downThreshold ? 1 : 0;
|
||||
for (int i = searchBin1; i <= searchBin2; i++) {
|
||||
magData[i] = complexArray.magsq(i);
|
||||
}
|
||||
@ -239,7 +268,8 @@ public class RWEProcess extends PamProcess {
|
||||
// do nothing it it's still off !
|
||||
}
|
||||
else {
|
||||
if (oTh[i]) { // continue peak
|
||||
// if downThreshold == false then onDown is 0, so second threshold is always on since magData always > 0
|
||||
if (oTh[i] && magData[i] > newPeak.maxAmp*onDown/threshold) { // continue peak
|
||||
newPeak.bin2 = i;
|
||||
if (magData[i] > newPeak.maxAmp) {
|
||||
newPeak.maxAmp = magData[i];
|
||||
@ -258,6 +288,16 @@ public class RWEProcess extends PamProcess {
|
||||
detectedPeaks[nPeaks++] = newPeak;
|
||||
newPeak = new RWEDetectionPeak(0);
|
||||
peakOn = false;
|
||||
// now trim off the start of the peak if it's too wide.
|
||||
if (onDown > 0) {
|
||||
for (int ip = newPeak.bin1; ip < newPeak.peakBin; ip++) {
|
||||
if (magData[ip] < newPeak.maxAmp/threshold) {
|
||||
newPeak.bin1 = ip+1;
|
||||
newPeak.signal -= magData[ip];
|
||||
newPeak.noise -= backgroundData[ip];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ public class BinaryStorageDialogPanel {
|
||||
JPanel qb = new JPanel(new BorderLayout());
|
||||
qb.add(BorderLayout.WEST, q);
|
||||
qb.setBorder(new TitledBorder("Options"));
|
||||
qb.setVisible(PamController.getInstance().getRunMode() != PamController.RUN_PAMVIEW);
|
||||
// qb.setVisible(PamController.getInstance().getRunMode() != PamController.RUN_PAMVIEW);
|
||||
|
||||
p.add(BorderLayout.CENTER, qb);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user