Added Tethys output to DL module

This commit is contained in:
Douglas Gillespie 2024-04-30 17:01:37 +01:00
parent 76ee0aebf4
commit e9bf8dd602
15 changed files with 388 additions and 21 deletions

2
.gitignore vendored
View File

@ -109,3 +109,5 @@ settings.xml
.classpath
.classpath
.classpath
.classpath
.settings/org.eclipse.jdt.core.prefs

View File

@ -1456,13 +1456,14 @@ public class PamController implements PamControllerInterface, PamSettings {
for (int iU = 0; iU < pamControlledUnits.size(); iU++) {
pamControlledUnits.get(iU).pamHasStopped();
}
guiFrameManager.pamEnded();
long stopTime = PamCalendar.getTimeInMillis();
saveEndSettings(stopTime);
setPamStatus(PAM_IDLE);
guiFrameManager.pamEnded();
// no good having this here since it get's called at the end of every file.
// if (GlobalArguments.getParam(PamController.AUTOEXIT) != null) {
//// can exit here, since we've auto started, can auto exit.

View File

@ -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.10bd";
static public final String version = "2.02.11c";
/**
* Release date
*/
static public final String date = "23 April 2024";
static public final String date = "29 April 2024";
// /**
// * Release type - Beta or Core

View File

@ -472,7 +472,7 @@ final public class PamModel implements PamSettings {
mi.setModulesMenuGroup(utilitiesGroup);
mi.setMaxNumber(1);
//mi.addGUICompatabilityFlag(PamGUIManager.FX); //has FX enabled GUI.
mi.setHidden(SMRUEnable.isEnable() == false);
// mi.setHidden(SMRUEnable.isEnable() == false);
}
/*

View File

@ -189,11 +189,11 @@ public class OfflineDataLoading<T extends PamDataUnit> {
switch (offlineDataInfo.getInterrupt()) {
case OFFLINE_DATA_INTERRUPT:
// System.out.println("Request order cancelling");
int giveUp = 0;
if (orderData.cancelOrder()) {
while (orderData!=null || !orderData.isDone()) {
while ((orderData!=null || !orderData.isDone()) & giveUp++ < 300) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {

View File

@ -7,22 +7,19 @@ import java.io.Serializable;
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;
import PamController.PamControllerInterface;
import PamController.PamSettingManager;
import PamController.PamSettings;
import PamUtils.PamUtils;
import PamView.GroupedDataSource;
import PamView.GroupedSourceParameters;
import PamView.dialog.GroupedSourcePanel;
import PamguardMVC.PamDataBlock;
import PamguardMVC.ProcessAnnotation;
import RightWhaleEdgeDetector.graphics.RWEDataPlotProviderFX;
import dataPlotsFX.data.TDDataProviderRegisterFX;
/**
* Exact implementation of the 2003 Right Whale detector I developed when I was
@ -43,6 +40,7 @@ public class RWEControl extends PamControlledUnit implements PamSettings {
super("RW Edge Detector", unitName);
rweProcess = new RWEProcess(this);
addPamProcess(rweProcess);
PamSettingManager.getInstance().registerSettings(this);
}

View File

@ -12,6 +12,7 @@ import Localiser.algorithms.timeDelayLocalisers.bearingLoc.BearingLocaliser;
import Localiser.algorithms.timeDelayLocalisers.bearingLoc.BearingLocaliserSelector;
import annotation.calcs.snr.SNRAnnotationType;
import autecPhones.AutecGraphics;
import dataPlotsFX.data.TDDataProviderRegisterFX;
import fftManager.Complex;
import fftManager.FFTDataBlock;
import fftManager.FFTDataUnit;
@ -33,6 +34,7 @@ import PamguardMVC.PamDataUnit;
import PamguardMVC.PamObservable;
import PamguardMVC.PamProcess;
import PamguardMVC.debug.Debug;
import RightWhaleEdgeDetector.graphics.RWEDataPlotProviderFX;
import RightWhaleEdgeDetector.graphics.RWESymbolManager;
public class RWEProcess extends PamProcess {
@ -53,6 +55,7 @@ public class RWEProcess extends PamProcess {
*/
private boolean isPreSmoothed;
private KernelSmoothing kernelSmoothing;
private RWEDataPlotProviderFX fxPlotProvider;
public RWEProcess(RWEControl rweControl) {
super(rweControl, null);
@ -71,6 +74,9 @@ public class RWEProcess extends PamProcess {
rweDataBlock.setCanClipGenerate(true);
rweDataBlock.SetLogging(new RWESQLLogging(rweControl, rweDataBlock));
rweDataBlock.addDataAnnotationType(new SNRAnnotationType());
fxPlotProvider = new RWEDataPlotProviderFX(this, rweDataBlock);
TDDataProviderRegisterFX.getInstance().registerDataInfo(fxPlotProvider);
}
@Override

View File

@ -0,0 +1,25 @@
package RightWhaleEdgeDetector.graphics;
import RightWhaleEdgeDetector.RWEDataBlock;
import RightWhaleEdgeDetector.RWEProcess;
import dataPlotsFX.data.TDDataInfoFX;
import dataPlotsFX.data.TDDataProviderFX;
import dataPlotsFX.layout.TDGraphFX;
public class RWEDataPlotProviderFX extends TDDataProviderFX {
private RWEDataBlock rweDataBlock;
private RWEProcess rweProcess;
public RWEDataPlotProviderFX(RWEProcess rweProcess, RWEDataBlock rweDataBlock) {
super(rweDataBlock);
this.rweProcess = rweProcess;
this.rweDataBlock = rweDataBlock;
}
@Override
public TDDataInfoFX createDataInfo(TDGraphFX tdGraph) {
return new RWEDataPlotinfoFX(this, rweProcess, tdGraph, rweDataBlock);
}
}

View File

@ -0,0 +1,133 @@
package RightWhaleEdgeDetector.graphics;
import PamUtils.Coordinate3d;
import PamView.GeneralProjector.ParameterType;
import PamView.GeneralProjector.ParameterUnits;
import PamguardMVC.PamDataUnit;
import RightWhaleEdgeDetector.RWEDataBlock;
import RightWhaleEdgeDetector.RWEDataUnit;
import RightWhaleEdgeDetector.RWEProcess;
import RightWhaleEdgeDetector.RWESound;
import dataPlotsFX.TDSymbolChooserFX;
import dataPlotsFX.data.TDDataInfoFX;
import dataPlotsFX.data.TDScaleInfo;
import dataPlotsFX.layout.TDGraphFX;
import dataPlotsFX.projector.TDProjectorFX;
import fftManager.FFTDataBlock;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.shape.Polygon;
public class RWEDataPlotinfoFX extends TDDataInfoFX {
private RWEDataBlock rweDataBlock;
private TDScaleInfo bearingScaleInfo;
private TDScaleInfo frequencyInfo;
private RWEProcess rweProcess;
public RWEDataPlotinfoFX(RWEDataPlotProviderFX tdDataProvider, RWEProcess rweProcess, TDGraphFX tdGraph, RWEDataBlock rweDataBlock) {
super(tdDataProvider, tdGraph, rweDataBlock);
this.rweProcess = rweProcess;
this.rweDataBlock = rweDataBlock;
bearingScaleInfo = new TDScaleInfo(0,180, ParameterType.BEARING, ParameterUnits.DEGREES);
bearingScaleInfo.setReverseAxis(true); //set the axis to be reverse so 0 is at top of graph
frequencyInfo = new TDScaleInfo(0, 1, ParameterType.FREQUENCY, ParameterUnits.HZ);
this.getScaleInfos().add(bearingScaleInfo);
this.getScaleInfos().add(frequencyInfo);
//set correct frequency range based on nyquist.
frequencyInfo.setMaxVal(rweDataBlock.getSampleRate()/2.);
}
@Override
public Double getDataValue(PamDataUnit pamDataUnit) {
if (pamDataUnit.getLocalisation() == null) {
return null;
}
double[] angles = pamDataUnit.getLocalisation().getAngles();
if (angles != null && angles.length > 0) {
return Math.toDegrees(angles[0]);
}
return null;
}
@Override
public TDScaleInfo getScaleInfo() {
setNPlotPanes(frequencyInfo, this.getDataBlock(), false);
double min = Math.min(bearingScaleInfo.getMinVal(), bearingScaleInfo.getMaxVal());
double max = Math.max(bearingScaleInfo.getMinVal(), bearingScaleInfo.getMaxVal());
bearingScaleInfo.setMaxVal(max);
bearingScaleInfo.setMinVal(min);
return super.getScaleInfo();
}
@Override
public TDSymbolChooserFX getSymbolChooser() {
// TODO Auto-generated method stub
return null;
}
@Override
public Polygon drawDataUnit(int plotNumber, PamDataUnit pamDataUnit, GraphicsContext g, double scrollStart, TDProjectorFX tdProjector,int type) {
// if drawing FFT then need to use slight more complex drawing functions.
if (getScaleInfoIndex()==1) {
return drawRWContour(plotNumber, pamDataUnit, g, scrollStart, tdProjector, type);
}
else {
return super.drawDataUnit(plotNumber, pamDataUnit, g, scrollStart, tdProjector ,type);
}
// return null;
}
private Polygon drawRWContour(int plotNumber, PamDataUnit pamDataUnit, GraphicsContext g, double scrollStart,
TDProjectorFX tdProjector, int type) {
if (!shouldDraw(plotNumber, pamDataUnit)){
//System.out.println("Cannot plot whistle");
// iCol++;
return null;
}
RWEDataUnit rweDataUnit = (RWEDataUnit) pamDataUnit;
RWESound rweSound = rweDataUnit.rweSound;
int[] hf = rweSound.highFreq;
int[] lf = rweSound.lowFreq;
int[] pf = rweSound.peakFreq;
FFTDataBlock dataSource = (FFTDataBlock) rweProcess.getParentDataBlock();
if (dataSource == null) {
return null;
}
double fs = dataSource.getSampleRate();
int fftLen = dataSource.getFftLength();
int fftHop = dataSource.getFftHop();
// Polygon outer = new Poly
int nOut = hf.length*2;
double[] outsideX = new double[nOut];
double[] outsideY = new double[nOut];
for (int i = 0; i < hf.length; i++) {
long t = (long) (i*1000*fftHop/fs)+rweDataUnit.getTimeMilliseconds();
double f = lf[i]*fs/fftLen;
double tdPix = tdProjector.getTimePix(t-scrollStart);
double fPix = tdProjector.getYPix(f);
// Coordinate3d coord = tdProjector.getCoord3d(i, t, f);
outsideX[i] = tdPix;
outsideY[i] = fPix;
f = hf[i]*fs/fftLen;
// coord = tdProjector.getCoord3d(i, t, f);
fPix = tdProjector.getYPix(f);
outsideX[nOut-1-i] = tdPix;
outsideY[nOut-1-i] = fPix;
}
g.strokePolygon(outsideX, outsideY, nOut);
return null;
}
}

View File

@ -494,6 +494,39 @@ public class DLClassifyProcess extends PamInstantProcess {
}
/**
* Get the result with the highest score.
* @return model result with the highest score.
*/
public PredictionResult getBestModelResult(DLDetection dlDetection) {
ArrayList<PredictionResult> results = dlDetection.getModelResults();
if (results == null || results.size() == 0) {
return null;
}
/*
* probably need to improve this function to only look at results
* that are in a list of used results or something crazy ?
*/
// dlControl.getDLModel().;
PredictionResult bestResult = null;
float bestScore = 0;
for (PredictionResult pred : results) {
float[] scores = pred.getPrediction();
if (scores == null) {
continue;
}
for (int i = 0; i < scores.length; i++) {
if (scores[i] > bestScore) {
bestScore = scores[i];
bestResult = pred;
}
}
}
return bestResult;
}
/**
* Clear the data unit buffer.
*/
@ -596,4 +629,8 @@ public class DLClassifyProcess extends PamInstantProcess {
return this.dlControl.getDLParams();
}
public DLControl getDLControl() {
return dlControl;
}
}

View File

@ -134,7 +134,6 @@ public class DLDetection extends PamDataUnit implements PamDetection, RawDataHol
}
/**
* Get the wave data for a specified channel.
* @param channel

View File

@ -3,6 +3,11 @@ package rawDeepLearningClassifier.dlClassification;
import PamView.GroupedDataSource;
import PamView.GroupedSourceParameters;
import PamguardMVC.AcousticDataBlock;
import rawDeepLearningClassifier.tethys.DLSpeciesManager;
import rawDeepLearningClassifier.tethys.DLTethysDataProvider;
import tethys.TethysControl;
import tethys.pamdata.TethysDataProvider;
import tethys.species.DataBlockSpeciesManager;
/**
* Holds classified data units from deep learning model.
@ -13,6 +18,8 @@ import PamguardMVC.AcousticDataBlock;
public class DLDetectionDataBlock extends AcousticDataBlock<DLDetection> implements GroupedDataSource {
private DLClassifyProcess dlClassifyProcess;
private DLTethysDataProvider dlTethysDataProvider;
private DLSpeciesManager dlSpeciesManager;
public DLDetectionDataBlock(String dataName, DLClassifyProcess parentProcess, int channelMap) {
super(DLDetection.class, dataName, parentProcess, channelMap);
@ -24,5 +31,21 @@ public class DLDetectionDataBlock extends AcousticDataBlock<DLDetection> impleme
return dlClassifyProcess.getDLParams().groupedSourceParams;
}
@Override
public TethysDataProvider getTethysDataProvider(TethysControl tethysControl) {
if (dlTethysDataProvider == null) {
dlTethysDataProvider = new DLTethysDataProvider(tethysControl, this);
}
return dlTethysDataProvider;
}
@Override
public DataBlockSpeciesManager<DLDetection> getDatablockSpeciesManager() {
if (dlSpeciesManager == null) {
dlSpeciesManager = new DLSpeciesManager(dlClassifyProcess.getDLControl(), this);
}
return dlSpeciesManager;
}
}

View File

@ -0,0 +1,105 @@
package rawDeepLearningClassifier.tethys;
import java.util.ArrayList;
import PamUtils.PamArrayUtils;
import PamguardMVC.PamDataBlock;
import annotation.DataAnnotation;
import rawDeepLearningClassifier.DLControl;
import rawDeepLearningClassifier.dlClassification.DLClassName;
import rawDeepLearningClassifier.dlClassification.DLClassiferModel;
import rawDeepLearningClassifier.dlClassification.DLDetection;
import rawDeepLearningClassifier.dlClassification.PredictionResult;
import rawDeepLearningClassifier.logging.DLAnnotation;
import tethys.species.DataBlockSpeciesCodes;
import tethys.species.DataBlockSpeciesManager;
public class DLSpeciesManager extends DataBlockSpeciesManager<DLDetection> {
private DLControl dlControl;
private static final String unknown = "Unknown";
public DLSpeciesManager(DLControl dlControl, PamDataBlock<DLDetection> dataBlock) {
super(dataBlock);
this.dlControl = dlControl;
}
@Override
public DataBlockSpeciesCodes getSpeciesCodes() {
DLClassName[] classNames = getClassNames();
String[] classStrings = getClassStrings(classNames);
return new DataBlockSpeciesCodes(unknown, classStrings);
}
/**
* Get just the strings of the class names.
* @param classNames
* @return
*/
private String[] getClassStrings(DLClassName[] classNames) {
if (classNames == null) {
return null;
}
String[] classStrings = new String[classNames.length];
for (int i = 0; i < classStrings.length; i++) {
classStrings[i] = classNames[i].className;
}
return classStrings;
}
/**
* Get the list of class names, or make a single unknown category.
* @return
*/
private DLClassName[] getClassNames() {
DLClassiferModel currentModel = dlControl.getDLModel();
DLClassName[] classNames = null;
if (currentModel != null) {
classNames = currentModel.getClassNames();
}
if (classNames == null) {
classNames = new DLClassName[1];
classNames[0] = new DLClassName(unknown, (short) 0);
}
return classNames;
}
@Override
public String getSpeciesCode(DLDetection dlDetection) {
int nAnnot = dlDetection.getNumDataAnnotations();
if (nAnnot == 0) {
return unknown;
}
// DataAnnotation annot = dlDetection.getDataAnnotation(0);
// ArrayList<PredictionResult> results = null;
// if (annot instanceof DLAnnotation) {
// DLAnnotation dlAnnot = (DLAnnotation) annot;
// results = dlAnnot.getModelResults();
// }
PredictionResult result = dlControl.getDLClassifyProcess().getBestModelResult(dlDetection);
if (result == null) {
return unknown;
}
int resInd = 0;
float bestScore = 0;
float[] scores = result.getPrediction();
if (scores == null || scores.length == 0) {
return unknown;
}
for (int i = 0; i < scores.length; i++) {
if (scores[i] > bestScore) {
bestScore = scores[i];
resInd = i;
}
}
String[] names = getClassStrings(getClassNames());
if (resInd < names.length) {
return names[resInd];
}
return unknown;
}
}

View File

@ -0,0 +1,38 @@
package rawDeepLearningClassifier.tethys;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
import nilus.Detection;
import nilus.Detection.Parameters;
import rawDeepLearningClassifier.dlClassification.DLDetection;
import tethys.TethysControl;
import tethys.output.StreamExportParams;
import tethys.output.TethysExportParams;
import tethys.pamdata.AutoTethysProvider;
public class DLTethysDataProvider extends AutoTethysProvider {
public DLTethysDataProvider(TethysControl tethysControl, PamDataBlock pamDataBlock) {
super(tethysControl, pamDataBlock);
// TODO Auto-generated constructor stub
}
@Override
public Detection createDetection(PamDataUnit dataUnit, TethysExportParams tethysExportParams,
StreamExportParams streamExportParams) {
Detection detection = super.createDetection(dataUnit, tethysExportParams, streamExportParams);
if (detection == null) {
return null;
}
DLDetection dlDetection = (DLDetection) dataUnit;
// result =
String annotSummary = dlDetection.getAnnotationsSummaryString();
if (annotSummary != null) {
Parameters parameters = detection.getParameters();
addUserDefined(parameters, "Annotation", annotSummary);
}
return detection;
}
}

View File

@ -197,15 +197,15 @@ public class DBXMLConnect {
marshal.marshal(nilusObject, tempFile.toString());
// above lines have made a file. Are now going to gzip it before sending to Tethys
File zipFile = null;
try {
zipFile = zipOutputFile(tempFile);
}
catch (FileNotFoundException e1){
System.out.println(e1.getMessage());
}
catch (IOException e2) {
System.out.println(e2.getMessage());
}
// try {
// zipFile = zipOutputFile(tempFile);
// }
// catch (FileNotFoundException e1){
// System.out.println(e1.getMessage());
// }
// catch (IOException e2) {
// System.out.println(e2.getMessage());
// }
String finalName;
if (zipFile == null) {
finalName = bodgeName;