DelphinID almost there.

This commit is contained in:
Jamie Mac 2024-05-07 16:15:29 +01:00
parent c1f4ba9e37
commit 67b6d5e690
13 changed files with 191 additions and 59 deletions

View File

@ -101,6 +101,8 @@ public class DLPredictionPane extends PamBorderPane implements TDSettingsPane {
if (dlPredictionPlotInfoFX.getDlControl().getDLModel()!=null) {
//populate the prediction pane.
DLClassName[] classNames = dlPredictionPlotInfoFX.getDlControl().getDLModel().getClassNames();
// System.out.println("MAKE MY CLASS NAMES: " + dlPredictionPlotInfoFX.getDlControl().getDLModel().getClassNames());
layoutColourPanes(classNames);
}

View File

@ -94,7 +94,7 @@ public class DLPredictionPlotInfoFX extends GenericLinePlotInfo {
if (getDlControl().getDLModel()!=null) {
DLClassName[] classNames = getDlControl().getDLModel().getClassNames();
// System.out.println("Class names are: !!! " + (classNames == null ? "null" : classNames.length));
System.out.println("Class names are: !!! " + (classNames == null ? "null" : classNames.length));
if (classNames!=null) {
@ -105,8 +105,8 @@ public class DLPredictionPlotInfoFX extends GenericLinePlotInfo {
dlPredParams.lineInfos[i] = new LineInfo(true, Color.rgb(0, 0, 255%(i*30 + 50)));
}
}
}
getGraphSettingsPane().setParams();
}
}

View File

@ -197,7 +197,7 @@ public class DLClassifyProcess extends PamInstantProcess {
if (pamRawData instanceof SegmenterDetectionGroup) {
if (classificationBuffer.size()>=1) {
System.out.println("RUN THE MODEL FOR WHISTLES: ");
// System.out.println("RUN THE MODEL FOR WHISTLES: ");
runDetectionGroupModel();
classificationBuffer.clear();
}
@ -232,14 +232,15 @@ public class DLClassifyProcess extends PamInstantProcess {
/**
* Run a model for which the input is a detection group.
*/
private void runDetectionGroupModel() {
private synchronized void runDetectionGroupModel() {
if (classificationBuffer.size()<=0) return;
ArrayList<PamDataUnit> classificationBufferTemp = (ArrayList<PamDataUnit>) classificationBuffer.clone();
ArrayList<? extends PredictionResult> modelResults = this.dlControl.getDLModel().runModel(classificationBufferTemp);
for (int i=0; i<classificationBufferTemp.size(); i++) {
if (modelResults.get(i)!=null) {
if (modelResults!=null && modelResults.get(i)!=null) {
DLDataUnit dlDataUnit = predictionToDataUnit(classificationBuffer.get(i), modelResults.get(i));
this.dlModelResultDataBlock.addPamData(dlDataUnit); //here
}

View File

@ -106,7 +106,7 @@ public abstract class StandardClassifierModel implements DLClassiferModel, PamSe
@Override
public void prepModel() {
// System.out.println("STANDARD CLASSIFIER MODEL PREP MODEL! !!!");
System.out.println("STANDARD CLASSIFIER MODEL PREP MODEL! !!!: " + getDLParams().modelPath);
// StandardModelParams oldParams = getDLParams().clone();
getDLWorker().prepModel(getDLParams(), dlControl);
@ -115,6 +115,7 @@ public abstract class StandardClassifierModel implements DLClassiferModel, PamSe
if (getDLWorker().isModelNull()) {
dlClassifierWarning.setWarningMessage("There is no loaded " + getName() + " classifier model. " + getName() + " disabled.");
WarningSystem.getWarningSystem().addWarning(dlClassifierWarning);
return;
}
@ -187,7 +188,7 @@ public abstract class StandardClassifierModel implements DLClassiferModel, PamSe
public DLStatus setModel(URI uri) {
//will change the params if we do not clone.
StandardModelParams.setModel(uri, this.getDLParams());
this.prepModel();
this.getDLWorker().prepModel(getDLParams(), dlControl);
return getModelStatus();
}

View File

@ -199,8 +199,7 @@ public class ArchiveModelWorker extends GenericModelWorker {
* @throws IOException
*/
public ArchiveModel loadModel(String currentPath2) throws MalformedModelException, IOException {
System.out.println("HELLO MODEL: " +currentPath2 );
return new SimpleArchiveModel(new File(currentPath2));
}

View File

@ -8,6 +8,7 @@ import org.jamdev.jdl4pam.transforms.DLTransformsFactory;
import org.jamdev.jdl4pam.transforms.DLTransfromParams;
import PamController.PamControlledUnitSettings;
import PamController.PamSettingManager;
import rawDeepLearningClassifier.DLControl;
import rawDeepLearningClassifier.dlClassification.DLClassiferModel;
import rawDeepLearningClassifier.dlClassification.StandardClassifierModel;
@ -37,6 +38,9 @@ public class DelphinIDClassifier extends StandardClassifierModel {
public DelphinIDClassifier(DLControl dlControl) {
super(dlControl);
//load the previous settings
PamSettingManager.getInstance().registerSettings(this);
}
@Override
@ -105,10 +109,11 @@ public class DelphinIDClassifier extends StandardClassifierModel {
@Override
public boolean restoreSettings(PamControlledUnitSettings pamControlledUnitSettings) {
DelphinIDParams newParameters = (DelphinIDParams) pamControlledUnitSettings.getSettings();
if (newParameters!=null) {
delphinIDParams = (DelphinIDParams) newParameters.clone();
//System.out.println("SoundSpot have been restored. : " + soundSpotParmas.classNames);
// System.out.println("DELPHINID have been restored. : " + delphinIDParams.modelPath);
if (delphinIDParams.dlTransfromParams!=null) {
delphinIDParams.dlTransfroms = DLTransformsFactory.makeDLTransforms((ArrayList<DLTransfromParams>) delphinIDParams.dlTransfromParams);
}

View File

@ -2,6 +2,7 @@ package rawDeepLearningClassifier.dlClassification.delphinID;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import org.jamdev.jdl4pam.transforms.DLTransform;
@ -9,18 +10,23 @@ import org.jamdev.jdl4pam.transforms.DLTransfromParams;
import org.jamdev.jdl4pam.transforms.FreqTransform;
import org.jamdev.jdl4pam.transforms.DLTransform.DLTransformType;
import org.jamdev.jdl4pam.transforms.jsonfile.DLTransformsParser;
import org.jamdev.jdl4pam.utils.DLMatFile;
import org.jamdev.jdl4pam.utils.DLUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import PamUtils.PamArrayUtils;
import PamguardMVC.PamDataUnit;
import ai.djl.Model;
import rawDeepLearningClassifier.DLControl;
import rawDeepLearningClassifier.dlClassification.animalSpot.StandardModelParams;
import rawDeepLearningClassifier.dlClassification.archiveModel.ArchiveModelWorker;
import rawDeepLearningClassifier.dlClassification.delphinID.Whistles2Image.Whistle2ImageParams;
import rawDeepLearningClassifier.segmenter.GroupedRawData;
import rawDeepLearningClassifier.segmenter.SegmenterDetectionGroup;
import us.hebi.matlab.mat.format.Mat5;
import us.hebi.matlab.mat.types.MatFile;
import us.hebi.matlab.mat.types.Matrix;
import us.hebi.matlab.mat.types.Struct;
/**
*
@ -86,11 +92,50 @@ public class DelphinIDWorker extends ArchiveModelWorker {
return whistle2ImageParmas;
}
}
//something has gone wrong if we get here.
return null;
}
private Struct imageStruct;
int count = 0;
/**
* Tets by exporting results to a .mat file.
* @param data
* @param aSegment
*/
private void addIMage2MatFile(double[][] data, SegmenterDetectionGroup aSegment) {
long dataStartMillis = 1340212413000L;
if (imageStruct==null) {
imageStruct = Mat5.newStruct(100,1);
}
Matrix image = DLMatFile.array2Matrix(data);
imageStruct.set("image", count, image);
imageStruct.set("startmillis", count, Mat5.newScalar(aSegment.getSegmentStartMillis()));
imageStruct.set("startseconds", count, Mat5.newScalar((aSegment.getSegmentStartMillis()-dataStartMillis)/1000.));
count++;
System.out.println("SAVED " +count + " TO MAT FILE");
if (count==10) {
//create MatFile for saving the image data to.
MatFile matFile = Mat5.newMatFile();
matFile.addArray("whistle_images", imageStruct);
//the path to the model
String matImageSave = "C:/Users/Jamie Macaulay/MATLAB Drive/MATLAB/PAMGUARD/deep_learning/delphinID/whistleimages_pg.mat";
try {
Mat5.writeToFile(matFile,matImageSave);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
@ -110,7 +155,7 @@ public class DelphinIDWorker extends ArchiveModelWorker {
double[][] transformedData2; //spectrogram data
for (int j=0; j<numChunks; j++) {
System.out.println("Number of whisltes to process: " + whistleGroups.get(j).getSubDetectionsCount() + " " + whistleGroups.get(j).getSegmentStartMillis());
// System.out.println("Number of whistle to process: " + whistleGroups.get(j).getStartSecond() + "s " + whistleGroups.get(j).getSubDetectionsCount() + " " + whistleGroups.get(j).getSegmentStartMillis());
//create the first transform and set then whistle data. Note that the absolute time limits are
//contained within the SegmenterDetectionGroup unit.
Whistles2Image whistles2Image = new Whistles2Image(whistleGroups.get(j), whistleImageParams);
@ -126,6 +171,14 @@ public class DelphinIDWorker extends ArchiveModelWorker {
transformedData2 = ((FreqTransform) transform).getSpecTransfrom().getTransformedData();
transformedDataStack[j] = DLUtils.toFloatArray(transformedData2);
// //TEMP
// try {
// addIMage2MatFile(transformedData2, whistleGroups.get(j));
// }
// catch (Exception e) {
// e.printStackTrace();
// }
}

View File

@ -118,16 +118,19 @@ public class Whistles2Image extends FreqTransform {
// }
//
// }
// System.out.println("Whistle group: " + segStart);
for (int i=0; i<whistleGroup.getSubDetectionsCount(); i++) {
whistleContour = (AbstractWhistleDataUnit) whistleGroup.getSubDetection(i);
// System.out.println("Whistle start time: " + (segStart - whistleContour.getTimeMilliseconds())/1000. + " end: " + (segStart - whistleContour.getTimeMilliseconds() + whistleContour.getDurationInMilliseconds())/1000.);
// System.out.println("Whistle start time: " + (whistleContour.getTimeMilliseconds()-segStart)/1000. + " end: " +
// (whistleContour.getTimeMilliseconds() - (segStart + whistleContour.getDurationInMilliseconds()))/1000.
// + " millis: " + whistleContour.getTimeMilliseconds() + " first slice: " + whistleContour.getTimesInSeconds()[0]);
double[][] contourD = new double[whistleContour.getSliceCount()][2];
for (int j=0; j<whistleContour.getSliceCount(); j++) {
contourD[j][0] = (whistleContour.getTimeMilliseconds()-segStart)/1000. + whistleContour.getTimesInSeconds()[j];
contourD[j][0] = (whistleContour.getTimeMilliseconds()-segStart)/1000. + (whistleContour.getTimesInSeconds()[j]-whistleContour.getTimesInSeconds()[0]);
contourD[j][1] = whistleContour.getFreqsHz()[j];
}
contours.add(contourD);
@ -189,7 +192,7 @@ public class Whistles2Image extends FreqTransform {
x = ((points.get(j)[i][0]-xlims[0])/(xlims[1]-xlims[0]))*size[0];
y = ((points.get(j)[i][1]-ylims[0])/(ylims[1]-ylims[0]))*size[1];
//System.out.println("Fill oval: x" + x + " y: " + y + " time: " + points.get(j)[i][0]);
// System.out.println("Fill oval: x " + x + " y: " + y + " time: " + points.get(j)[i][0]);
Graphics2D g2 = (Graphics2D) canvas.getGraphics();

View File

@ -33,7 +33,7 @@ public class GenericModelWorker extends DLModelWorker<StandardPrediction> {
@Override
public float[] runModel(float[][][] transformedDataStack) {
System.out.println("RUN GENERIC MODEL: " + transformedDataStack.length + " " + transformedDataStack[0].length + " " + transformedDataStack[0][0].length);
// System.out.println("RUN GENERIC MODEL: " + transformedDataStack.length + " " + transformedDataStack[0].length + " " + transformedDataStack[0][0].length);
// System.out.println("RUN GENERIC MODEL: " + transformedDataStack[0][0][0]);
float[] results;
if (freqTransform)
@ -48,8 +48,8 @@ public class GenericModelWorker extends DLModelWorker<StandardPrediction> {
//System.out.println("RUN GENERIC MODEL WAVE: " + waveStack.length + " " + waveStack[0].length + " " + waveStack[0][0]);
results = getModel().runModel(waveStack);
}
System.out.println("GENERIC MODEL RESULTS: " + (results== null ? null : results.length));
PamArrayUtils.printArray(results);
// System.out.println("GENERIC MODEL RESULTS: " + (results== null ? null : results.length));
// PamArrayUtils.printArray(results);
return results;
}

View File

@ -21,6 +21,8 @@ public class SegmenterDetectionGroup extends GroupDetection<PamDataUnit> {
*/
private long segMillis;
private double timeS;
/**
* Constructor for a group of detections within a detection. Note that some
* longer detections (e.g. whistles) may have sections outside the segment.
@ -33,7 +35,7 @@ public class SegmenterDetectionGroup extends GroupDetection<PamDataUnit> {
public SegmenterDetectionGroup(long timeMilliseconds, int channelBitmap, long startSample, double duration) {
super(timeMilliseconds, channelBitmap, startSample, (long) duration);
this.setDurationInMilliseconds(duration);
this.segMillis =timeMilliseconds;
this.segMillis = timeMilliseconds;
this.segDuration = duration;
}
@ -56,5 +58,13 @@ public class SegmenterDetectionGroup extends GroupDetection<PamDataUnit> {
return (long) (segMillis+segDuration);
}
public void setStartSecond(double timeS) {
this.timeS = timeS;
}
public double getStartSecond() {
return timeS;
}
}

View File

@ -71,7 +71,11 @@ public class SegmenterProcess extends PamProcess {
/**
* The current segmenter detection group.
*/
private SegmenterDetectionGroup[] segmenterDetectionGroup = null;
private SegmenterDetectionGroup[] segmenterDetectionGroup = null;
private long segmentStart=-1;
private long segmenterEnd=-1;
public SegmenterProcess(DLControl pamControlledUnit, PamDataBlock parentDataBlock) {
@ -219,9 +223,10 @@ public class SegmenterProcess extends PamProcess {
*/
public void newData(PamDataUnit pamRawData) {
// System.out.println("New data for segmenter: " + pamRawData);
if (!dlControl.getDLParams().useDataSelector || dlControl.getDataSelector().scoreData(pamRawData)>0) {
//System.out.println("New data for segmenter: " + pamRawData);
if (pamRawData instanceof RawDataUnit) {
newRawDataUnit(pamRawData);
}
@ -243,7 +248,7 @@ public class SegmenterProcess extends PamProcess {
* A new detection data unit i.e. this is only if we have detection data which is being grouped into segments.
* @param dataUnit - the whistle data unit.
*/
private void newWhistleData(PamDataUnit dataUnit) {
private synchronized void newWhistleData(PamDataUnit dataUnit) {
ConnectedRegionDataUnit whistle = (ConnectedRegionDataUnit) dataUnit;
@ -256,11 +261,16 @@ public class SegmenterProcess extends PamProcess {
int index = -1;
for (int i=0; i<chanGroups.length; i++) {
if (dlControl.getDLParams().groupedSourceParams.getGroupChannels(chanGroups[i])==dataUnit.getChannelBitmap())
index=i;
if (dlControl.getDLParams().groupedSourceParams.getGroupChannels(chanGroups[i])==dataUnit.getChannelBitmap()) {
index=i;
break;
}
}
//System.out.println("Whiste data: " + dataUnit + " " + chanGroups.length + " " + index + " " + dataUnit.getChannelBitmap());
//FIXME - TWEMP
index =0;
// System.out.println("Whistle data: " + ((dataUnit.getTimeMilliseconds()-firstClockUpdate)/1000.) + "s " + chanGroups.length + " " + index + " " + dataUnit.getChannelBitmap());
// PamArrayUtils.printArray(chanGroups);
if (index<0) {
@ -272,33 +282,63 @@ public class SegmenterProcess extends PamProcess {
//System.out.println("Whiste not in segment");
//iterate until we find the correct time for this detection. This keeps the segments consist no matter
//the data units. What we do not want is the first data unit defining the start of the first segment.
long segmentStart = firstClockUpdate;
long segmenterEnd = (long) (segmentStart + getSegmentLenMillis());
while(!detectionInSegment(dataUnit, segmentStart, segmenterEnd)) {
segmentStart = segmenterEnd;
if (segmentStart <0) {
segmentStart= firstClockUpdate;
segmenterEnd = (long) (segmentStart + getSegmentLenMillis());
}
long startSample = this.absMillisecondsToSamples(segmenterEnd);
//now we need to create a new data unit.
if (segmenterDetectionGroup[index]!=null) {
System.out.println("SAVE WHISTLE SEGMENT!: " + segmenterDetectionGroup[index]);
//save the data unit
this.segmenterGroupDataBlock.addPamData(segmenterDetectionGroup[index]);
while(!detectionInSegment(dataUnit, segmentStart, segmenterEnd)) {
nextGroupSegment( index);
}
//TODO There is no good way to get the start sample?
segmenterDetectionGroup[index] = new SegmenterDetectionGroup(segmentStart, chanGroups[index], startSample, getSegmentLenMillis());
}
//System.out.println("Add whistle to existing segment");
segmenterDetectionGroup[index].addSubDetection(whistle);
// System.out.println("Segment sub detection count: " + segmenterDetectionGroup[index].getSubDetectionsCount());
}
/**
* Iterate to the next group segment
* @param index - the group index;
*/
private void nextGroupSegment(int index) {
// System.out.println("----------------------------------");
segmentStart = (long) (segmentStart+ getSegmentHopMillis());
segmenterEnd = (long) (segmentStart + getSegmentLenMillis());
int[] chanGroups = dlControl.getDLParams().groupedSourceParams.getChannelGroups();
long startSample = this.absMillisecondsToSamples(segmentStart);
//now we need to create a new data unit.
SegmenterDetectionGroup aSegment = new SegmenterDetectionGroup(segmentStart, chanGroups[index], startSample, getSegmentLenMillis());
aSegment.setStartSecond((segmentStart-firstClockUpdate)/1000.);
//save the last segment
if (segmenterDetectionGroup[index]!=null) {
//add any data units from the previous segment (because segments may overlap);
int count =0;
for (int i=0; i<segmenterDetectionGroup[index].getSubDetectionsCount() ; i++) {
if (detectionInSegment(segmenterDetectionGroup[index].getSubDetection(i), aSegment)){
aSegment.addSubDetection(segmenterDetectionGroup[index].getSubDetection(i));
count++;
}
}
// System.out.println("SAVE WHISTLE SEGMENT!: " + ((segmenterDetectionGroup[index].getSegmentStartMillis()-firstClockUpdate)/1000.) + "s" + " " + " no. whsitles: " + segmenterDetectionGroup[index].getSubDetectionsCount() + " " + segmenterDetectionGroup[index].getSegmentStartMillis() + " " + segmenterDetectionGroup[index]);
//save the data unit to the data block
if (segmenterDetectionGroup[index].getSubDetectionsCount()>0) {
this.segmenterGroupDataBlock.addPamData(segmenterDetectionGroup[index]);
}
}
segmenterDetectionGroup[index] = aSegment;
// System.out.println("NEW SEGMENT START!: " + (segmentStart-firstClockUpdate)/1000. + "s" + " " + segmenterDetectionGroup[index].getSegmentStartMillis()+ " " +segmenterDetectionGroup[index]);
}
private boolean detectionInSegment(PamDataUnit dataUnit, SegmenterDetectionGroup segmenterDetectionGroup2) {
return detectionInSegment(dataUnit, segmenterDetectionGroup2.getSegmentStartMillis(),
(long) (segmenterDetectionGroup2.getSegmentStartMillis()+segmenterDetectionGroup2.getSegmentDuration()));
@ -308,11 +348,11 @@ public class SegmenterProcess extends PamProcess {
private boolean detectionInSegment(PamDataUnit dataUnit, long segStart, long segEnd) {
//TODO - this is going to fail for very small segments.
long whistleStart = dataUnit.getTimeMilliseconds();
long whistleEnd = dataUnit.getDurationInMilliseconds().longValue();
long whistleEnd = whistleStart + dataUnit.getDurationInMilliseconds().longValue();
if ((whistleStart>=segStart && whistleStart<segEnd) || ((whistleEnd>=segStart && whistleEnd<segEnd))){
//some part of the whistle is in the segment.
System.out.println("Whsitle in segment: " + whistleStart + " " + whistleEnd);
// System.out.println("Whsitle in segment: " + whistleStart + " " + whistleEnd);
return true;
}
return false;
@ -323,6 +363,12 @@ public class SegmenterProcess extends PamProcess {
return millis;
}
private double getSegmentHopMillis() {
double millis = (dlControl.getDLParams().sampleHop/this.getSampleRate())*1000.;
return millis;
}
int count=0;
public void masterClockUpdate(long milliSeconds, long sampleNumber) {
@ -331,23 +377,13 @@ public class SegmenterProcess extends PamProcess {
firstClockUpdate = milliSeconds;
}
//want to make sure that a segment isn't saved if we suddenly lose
//want to make sure that a segment is saved if we suddenly lose
// a steady stream of data units. This ensure that the segments are saved properly
//after the master clock has gone past the end of the current segment.
if (segmenterDetectionGroup!=null && count%20==0) {
for (int i=0; i<segmenterDetectionGroup.length; i++) {
if (segmenterDetectionGroup[i]!=null && segmenterDetectionGroup[i].getSegmentEndMillis()<milliSeconds) {
//add the segment to the datablock
this.segmenterGroupDataBlock.addPamData(segmenterDetectionGroup[i]);
//create a new segment
SegmenterDetectionGroup aSegmenterDetectionGroup =
new SegmenterDetectionGroup(segmenterDetectionGroup[i].getSegmentEndMillis(),
segmenterDetectionGroup[i].getChannelBitmap(),
this.absMillisecondsToSamples(segmenterDetectionGroup[i].getSegmentEndMillis()),
getSegmentLenMillis());
segmenterDetectionGroup[i] = aSegmenterDetectionGroup;
nextGroupSegment(i);
}
}
}

View File

@ -9,7 +9,11 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import org.jamdev.jdl4pam.transforms.DLTransform;
import org.jamdev.jdl4pam.transforms.FreqTransform;
import org.jamdev.jdl4pam.transforms.DLTransform.DLTransformType;
import org.jamdev.jdl4pam.utils.DLMatFile;
import org.jamdev.jdl4pam.utils.DLUtils;
import org.junit.jupiter.api.Test;
import rawDeepLearningClassifier.dlClassification.delphinID.Whistles2Image;
@ -68,6 +72,24 @@ public class DelphinIDTest {
}
}
ArrayList<DLTransform> transforms = new ArrayList<DLTransform>();
transforms.add(new FreqTransform(DLTransformType.SPECRESIZE, new Number[] {Integer.valueOf(64), Integer.valueOf(48)}));
//
// //set the spec transform
// ((FreqTransform) transforms.get(0)).setSpecTransfrom(whistles2Image.getSpecTransfrom());
//
// //process all the transforms.
// DLTransform transform = modelTransforms.get(0);
// for (int i =0; i<modelTransforms.size(); i++) {
// transform = modelTransforms.get(i).transformData(transform);
// }
//
// transformedData2 = ((FreqTransform) transform).getSpecTransfrom().getTransformedData();
// transformedDataStack[j] = DLUtils.toFloatArray(transformedData2);
//
//now save this image to a MATFILE
// Create MAT file with a scalar in a nested struct
MatFile matFileWrite = Mat5.newMatFile()