From ee694146c3349b63efe44780e6359fabf30569ff Mon Sep 17 00:00:00 2001 From: Jamie Mac Date: Thu, 2 May 2024 16:00:21 +0100 Subject: [PATCH 1/3] More updates to get DelphinID working --- .../animalSpot/StandardModelPane.java | 7 +- .../archiveModel/ArchiveModelWorker.java | 7 +- .../delphinID/DelphinIDPane.java | 130 +++++++++++++++--- .../delphinID/DelphinIDParams.java | 6 + .../delphinID/DelphinIDWorker.java | 5 + .../delphinID/Whistles2Image.java | 15 +- .../segmenter/SegmenterProcess.java | 35 ++++- .../DelphinIDTest.java | 91 ++++++++++++ .../DelphinID/whistle_image_example.mat | Bin 0 -> 19051 bytes 9 files changed, 266 insertions(+), 30 deletions(-) create mode 100644 src/test/rawDeepLearningClassifier/DelphinIDTest.java create mode 100644 src/test/resources/rawDeepLearningClassifier/DelphinID/whistle_image_example.mat diff --git a/src/rawDeepLearningClassifier/dlClassification/animalSpot/StandardModelPane.java b/src/rawDeepLearningClassifier/dlClassification/animalSpot/StandardModelPane.java index 231a6d3e..7dda72ad 100644 --- a/src/rawDeepLearningClassifier/dlClassification/animalSpot/StandardModelPane.java +++ b/src/rawDeepLearningClassifier/dlClassification/animalSpot/StandardModelPane.java @@ -32,6 +32,7 @@ import pamViewFX.fxNodes.PamSpinner; import pamViewFX.fxNodes.PamVBox; import pamViewFX.validator.PamValidator; import rawDeepLearningClassifier.dlClassification.DLClassiferModel; +import rawDeepLearningClassifier.dlClassification.StandardClassifierModel; /** * Settings pane for SoundSpot @@ -163,7 +164,7 @@ public abstract class StandardModelPane extends SettingsPane { - +public class DelphinIDPane extends SettingsPane { + /** * The main pane. */ private Pane mainPane; - + /** * Reference to the delphinID classifier */ private DelphinIDClassifier delphinUIClassifier; + private PamSpinner detectionDensitySpinner; + + private Slider decisionSlider; + + private DelphinIDParams currentParams; + + private File currentSelectedFile; + public DelphinIDPane(DelphinIDClassifier delphinUIClassifier) { super(null); this.delphinUIClassifier = delphinUIClassifier; mainPane = createPane(); } - + private Pane createPane() { - //font to use for title labels. Font font= Font.font(null, FontWeight.BOLD, 11); - Node classifierIcon; - classifierIcon = delphinUIClassifier.getModelUI().getIcon(); - - + Label classifierIcon; + classifierIcon = new Label("DelphinID"); + PamGuiManagerFX.titleFont2style(classifierIcon); + //todo - will need to figure out colour of icon using CSS. + Node icon = PamGlyphDude.createPamIcon("mdi2r-rss", Color.BLACK, PamGuiManagerFX.iconSize); + icon.getStyleClass().add(getName()); + icon.setRotate(45); + classifierIcon.setGraphic(icon); + classifierIcon.setContentDisplay(ContentDisplay.RIGHT); + + + // String settings = currentParams.toString(); + // classifierIcon.setTooltip(new Tooltip(settings)); + PamVBox vBox = new PamVBox(); vBox.setSpacing(5.); - + + /**Classification thresholds etc to set.**/ + Label detectionDensity = new Label("Detection Density"); + detectionDensity.setFont(font); + String tooltip = "Set the minimum detection density to attempt to classify."; + detectionDensity.setTooltip(new Tooltip(tooltip)); + detectionDensitySpinner = new PamSpinner(0.0, 1.0, 0.3, 0.1); + detectionDensitySpinner.setPrefWidth(70); + detectionDensitySpinner.setEditable(true); + detectionDensitySpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL); + + PamHBox minDensityHolder = new PamHBox(); + minDensityHolder.setAlignment(Pos.CENTER_RIGHT); + minDensityHolder.setSpacing(5); + Label minDensity = new Label("Min. density"); + minDensityHolder.getChildren().addAll(minDensity, detectionDensitySpinner); + /**Classification thresholds etc to set.**/ Label classiferInfoLabel2 = new Label("Decision Threshold"); classiferInfoLabel2.setTooltip(new Tooltip("Set the minimum prediciton value for selected classes. If a prediction exceeds this value " + "a detection will be saved.")); classiferInfoLabel2.setFont(font); - - - vBox.getChildren().addAll(classifierIcon, classiferInfoLabel2); - + + decisionSlider = new Slider(); + decisionSlider.setMin(0); + decisionSlider.setMax(1); + decisionSlider.setMajorTickUnit(0.2); + decisionSlider.setMinorTickCount(10); + decisionSlider.valueProperty().addListener((obsVal, oldVal, newVal)->{ + classiferInfoLabel2.setText(String.format("Decision Threshold %.2f", newVal)); + }); + decisionSlider.setShowTickMarks(true); + decisionSlider.setShowTickLabels(true); + + vBox.getChildren().addAll(classifierIcon, detectionDensity, minDensityHolder, classiferInfoLabel2, decisionSlider); + return vBox; } @Override public DelphinIDParams getParams(DelphinIDParams currParams) { - // TODO Auto-generated method stub - return null; + currParams.threshold = decisionSlider.getValue(); + currParams.minDetectionDensity = detectionDensitySpinner.getValue(); + return currParams; } @Override public void setParams(DelphinIDParams input) { - // TODO Auto-generated method stub + this.currentParams = input; + decisionSlider.setValue(input.threshold); + detectionDensitySpinner.getValueFactory().setValue(input.minDetectionDensity); + + if (input.modelPath!=null) { + //this might + currentSelectedFile = new File(currentParams.modelPath); + + //this might change the paramsClone values if the model contains pamguard compatible metadata + newModelSelected(currentSelectedFile); + } } + private void newModelSelected(File currentSelectedFile2) { + if (currentParams!=null && currentParams.defaultSegmentLen != null) { + + //System.out.println("Defualt segment length: " + paramsClone.defaultSegmentLen); + + //cannot use because, if the parent datablock has changed, samplerate will be out of date. + // int defaultsamples = (int) this.soundSpotClassifier.millis2Samples(paramsClone.defaultSegmentLen); + + + // float sR = dlClassifierModel.getDLControl().getSettingsPane().getSelectedParentDataBlock().getSampleRate(); + + int defaultsamples = StandardModelPane.getDefaultSamples(delphinUIClassifier, currentParams); + + //work out the window length in samples + delphinUIClassifier.getDLControl().getSettingsPane().getSegmentLenSpinner().getValueFactory().setValue(defaultsamples); + // dlClassifierModel.getDLControl().getSettingsPane().getHopLenSpinner().getValueFactory().setValue((int) defaultsamples/2); + + delphinUIClassifier.getDLControl().getSettingsPane().getSegmentLenSpinner().setDisable(true); + } + else { + delphinUIClassifier.getDLControl().getSettingsPane().getSegmentLenSpinner().setDisable(false); + } + + } + + + @Override public String getName() { return "delphinIDParams"; @@ -82,7 +176,7 @@ public class DelphinIDPane extends SettingsPane { @Override public void paneInitialized() { // TODO Auto-generated method stub - + } } diff --git a/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDParams.java b/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDParams.java index 8cbe9398..e655270c 100644 --- a/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDParams.java +++ b/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDParams.java @@ -8,5 +8,11 @@ public class DelphinIDParams extends StandardModelParams { * */ private static final long serialVersionUID = 1L; + + /** + * The minimum detection density. + */ + public double minDetectionDensity = 0.3; + } diff --git a/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDWorker.java b/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDWorker.java index 547f8bc8..b3ef293d 100644 --- a/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDWorker.java +++ b/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDWorker.java @@ -48,6 +48,11 @@ public class DelphinIDWorker extends ArchiveModelWorker { System.err.println("Error: could not find whistle2image transform in DelphinID JSON file. Model will not work."); this.setModel(null); // set model to null to make sure nothing works and errors are thrown } + + dlParams.binaryClassification = new boolean[dlParams.classNames.length]; + for (int i=0; i points, double[] size, double[] xlims, double[] ylims, double markerSize) { + public static BufferedImage makeScatterImage(ArrayList points, double[] size, double[] xlims, double[] ylims, double markerSize) { BufferedImage canvas = new BufferedImage((int) size[0], (int) size[1], BufferedImage.TYPE_INT_RGB); @@ -187,9 +189,13 @@ 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(); - canvas.getGraphics().fillOval((int) (x+markerSize/2),(int) (y-markerSize/2), (int) markerSize,(int) markerSize); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + g2.fillOval((int) (x+markerSize/2),(int) (y-markerSize/2), (int) markerSize,(int) markerSize); } } @@ -206,6 +212,7 @@ public class Whistles2Image extends FreqTransform { public double[] size; } + diff --git a/src/rawDeepLearningClassifier/segmenter/SegmenterProcess.java b/src/rawDeepLearningClassifier/segmenter/SegmenterProcess.java index 134204ab..407d4d03 100644 --- a/src/rawDeepLearningClassifier/segmenter/SegmenterProcess.java +++ b/src/rawDeepLearningClassifier/segmenter/SegmenterProcess.java @@ -60,7 +60,17 @@ public class SegmenterProcess extends PamProcess { /** * Holds groups of data units which are within a defined segment. */ - private SegmenterGroupDataBlock segmenterGroupDataBlock; + private SegmenterGroupDataBlock segmenterGroupDataBlock; + + /** + * The first clock update - segments for detection groups (not raw sound data) are referenced from this. + */ + private long firstClockUpdate; + + /** + * The current segmenter detection group. + */ + private SegmenterDetectionGroup segmenterDetectionGroup = null; public SegmenterProcess(DLControl pamControlledUnit, PamDataBlock parentDataBlock) { @@ -111,7 +121,7 @@ public class SegmenterProcess extends PamProcess { */ @Override public ArrayList getCompatibleDataUnits(){ - return new ArrayList>(Arrays.asList(RawDataUnit.class, ClickDetection.class, ClipDataUnit.class)); + return new ArrayList>(Arrays.asList(RawDataUnit.class, ClickDetection.class, ClipDataUnit.class, ConnectedRegionDataUnit.class)); } @@ -177,6 +187,8 @@ public class SegmenterProcess extends PamProcess { if (rawDataBlock==null) return; setParentDataBlock(rawDataBlock); + + this.firstClockUpdate = -1; } @@ -232,10 +244,27 @@ public class SegmenterProcess extends PamProcess { //TODO //this contains no raw data so we are branching off on a completely different processing path here. - //Whislte data units are saved to a buffer and then fed to the deep learning algorohtm + //Whislte data units are saved to a buffer and then fed to the deep learning algorithms + + if (segmenterDetectionGroup==null) { + //iterate until we find the correct time + long segmentStart = firstClockUpdate; + while() { + + } + } } + + + public void masterClockUpdate(long milliSeconds, long sampleNumber) { + super.masterClockUpdate(milliSeconds, sampleNumber); + if (firstClockUpdate<0) { + firstClockUpdate = milliSeconds; + } + } + /** diff --git a/src/test/rawDeepLearningClassifier/DelphinIDTest.java b/src/test/rawDeepLearningClassifier/DelphinIDTest.java new file mode 100644 index 00000000..198c00ed --- /dev/null +++ b/src/test/rawDeepLearningClassifier/DelphinIDTest.java @@ -0,0 +1,91 @@ +package test.rawDeepLearningClassifier; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.awt.image.BufferedImage; +import java.awt.image.Raster; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; + +import org.jamdev.jdl4pam.utils.DLMatFile; +import org.junit.jupiter.api.Test; + +import rawDeepLearningClassifier.dlClassification.delphinID.Whistles2Image; +import us.hebi.matlab.mat.format.Mat5; +import us.hebi.matlab.mat.types.MatFile; +import us.hebi.matlab.mat.types.Matrix; + +public class DelphinIDTest { + + + @Test + public void whistle2ImageTest() { + + System.out.println("Whislte2Image test started"); + + /** + * Test whether the Whistles2Image transform works properly + */ + String relMatPath = "./src/test/resources/rawDeepLearningClassifier/DelphinID/whistle_image_example.mat"; + + Path path = Paths.get(relMatPath); + + // Create MAT file with a scalar in a nested struct + try { + MatFile matFile = Mat5.readFromFile(path.toString()); + Matrix array = matFile.getArray("tfvalues"); + + //the values for the whistle detector. + double[][] whistleValues = DLMatFile.matrix2array(array); + + //the image after compression + array = matFile.getArray("image1compressedgrayscale"); + double[][] compressedWhistleImage = DLMatFile.matrix2array(array); + + //the whistle2Image transform image + array = matFile.getArray("image1originalgrayscalenorm"); + double[][] whislteImage = DLMatFile.matrix2array(array); + + //now perform the image transform in Java + double[] freqLimits = new double[] {0., 20000.}; + double[] size = new double[] {680., 480.}; + + ArrayList whistleImageArr = new ArrayList(); + whistleImageArr.add(whistleValues); + + BufferedImage canvas = Whistles2Image.makeScatterImage(whistleImageArr, size, new double[]{48, 48. + 4.}, freqLimits, 5.); + + double[][] imaged = new double[(int) size[0]][(int) size[1]]; + + float[] color = new float[3]; + Raster raster = canvas.getData(); + for (int i=0; iR##d5jt~z-*3IgPhm|G7#aR^c$kr30_QV$g5rhcviwcW~3J5?1 z`2~d_|BoBN-;GdN?E>)k9Ps0l_RGS|jO^zVGc)1=CMs$M61}W|vyeLk<_eHRlG(1w z=Iuw{=ME-A-Ve>r4kc{AZ|<0#YfgLg;r?}MLLn5Mlb$r&j4qOh%m)*}wyxn&^)M%B z%IQ@F-uQqqf3nRxY$vGs*S?5ImRCSa(Za6Dq??O~%+lkM7dCsGu$`C?O@4~!Gz0`5E1O&3T4iLxwXStFk$>l> z3ZF@mk@0UQx@QyopzojB5Uy7GHIg)K7nVwP%die7ou&25e*1mW4A&%93Y+Q;Qi}H7 zOD-=@DI-#N1nPb!6*W`qCds&#;Fe*g)iAhs^_?|jNwgT-|G6C^!FlocwHASM1O#Nn zpYMH#Gjj0!fY@bTx4BW}H1T)Gu9Kc#cZ!SCDGyHV1M~`~JUHdSDGyHL!aRM8u^FR;WLKcWTo?kB&fA1HF(Tg z|Iz-MP1NQ5jp)n!Ne{H6A8%`<>kKMO7u;PW8txX1xbahI~J~!_B zL|rU-yx{pN-W!F--C$$8zeRM^XzVQ|50;{m>W_q6suEFA7~x|2O72V|@N?MUG+C;r=(on?*mH=IPKhz?0q zVdw3Yp(2gH$d3W30|23u>tC1VAJWPbGW;D{m0kFjg5j;zL~=$ZwFW z>PX2QZ_OMF(^&(Ik`t9WLw$ywb*bYi3BKhNF2jxb`8QE2hm6Mx!tb2GlyybwAwhV* zNa#C;`6z3$n+0TL_5{RcL;)yI)~Kh4ZY$j)VM8p$%IM388eRaW$j8n;6Ir%*^Jm>^b$Klm(Na9F2_wCn{s zlt@X6rAm7-C#bh}U1kFt9``Cmqyei}5pSM=*v8Zd{&$X=whVzi9rPH za%y5QhDnGG47+lp{c+0Lqe=dipGv-8iT*Y}SKPE+a)>fLWyN_Ft~9JW8R`a2kjs&s zxqY(PnbVx|ee5(DXo@@0IA;4_+(JQXWhBgfXO+OnYZ2!3&Vu;N4}z<-1fr@&YTg(9 z;J#&(U%XUugVY^oOOv2AF$i&}ifVdE;HucMZk4Ao%uYMKB68Z5uNMwpHFl$}DZ}P& z|FvOI;eeUheg1Lc6<*yNhh z2zW7fYwv=_F$f57J}QEy$Y8x-O>xl&gc7v;MBlUq`V>^+unU$ouFG1D8K8l$t$13O zT48%@SpxwUr77ac0jbA&h3hQZqjz;jYBm&+?KJ@>E=dCL8&py=DiC@pmE0MUoM57h z^k!#>A-AhCt|t5GM?#xcVVtLQR)<_a zCkpNUGFip|j@DeF^?(K+(6%w3vPVL*Y1;T-S_C;PZS+-BuvXo5SN$iM`Oo6dv|-!< zaNjVYkJ=qmS3n)Qdo?FGm0CJvPC&QQLCk?2SvOLM$7NLEmH;~A(I+~T22Jbv|7BWd z{5TUZ#w;^%j#*SU1iW3{S4V?oI9+$RbqX^abTpo_n}+0HxsHI9?u`u>XE2oMB?4hx z;(8BpMW(Td+$xfrOuxc3tHnI_Nus*aZ#wY4zsB(hFw_oS5yk;8_MbO3`BzC&52=G^ zL_+kwa=Hkm@>9@qF7tjRL*L5kQ|6#RA_HoS+~;#2jk|+(#Es}rDX{HQ6EfPW!SAaB z+%m;+1B;z=pRnx=)J-Xt+}{vX%tUqu`TaXQzyXr4M;s9R%K?}jwI_9ri+ZB*mjkV0 zrpj23Ixj!gBtZ3EfI9#P-zVFDsDL{piF~#RU+%O4gJO98AUflQ>g;2o$ zHDiJ~2LxX!TF?rryoFdT=|ip%?x}iFR4dV?O)%A9=i{|+;s7U*F}wQ`P1hirsk)rL zxa7YF_yKeyLPAi%e?nl#sU#LyMbPSfs2mQDq%LyOFb(8WMrW{`tfG!Q>>)L2pKgew znLSrY1+Q8`UjU=$ldy9uFVtco6%*wFEy8i}@v_F!7=PM^m)D^R< zX5=5*0S$K~J)kj=3;W`b0jOB(ZrIQhLRMGfgi8DR<*fmKFk4t~Yx~LQWnZ18;iOZL z9P|R9duFL-|4m_I@7M4^6F&_g2WU3hcpKz%%*C-%@^F4Y^1~@Uz2Artc2<%dR5*`#M1dC=FpgV8+>Di;+uQh02Xl zyD<*<3_o>nhJs0p-^!{EZ;FRoC-6|uT-XZst)J|8vNXG z{sj0Zfch^sMM5|$6l(grz7j-+kaE!ZT{0u7QB~i(7_|@=V7lc{@@1Aa#7jj=u31+H zaW%YB#croMSy;(=y&WYFOcA-0ei21K;vJ337{bg}??~!fJH_WATHEj|22Lta5fG;M zH7hx}gZTdn4q%7@a8DFfQE;bamcKz}OXFZHr5MY^5kbwvqdtdU_~+_V`BzU{!_GTU z^HmKvbGJ_@Fu=lv#1$ZPpo_>{HOJc zV(~T17tCs1tSY8rQ4tUz`vh}9@qiCi05GShiiY*4Nnh4_de$GDp0asXiX`>NrpZ>N zZqA<>IjwvOXj%1nr=rJV4z)#v`VI~kf{qlQ+GvP2{?hYsnI`ohX>S@MJx9_r z8`Q1%Wnn;~rzWAZPNfR=9Ru4bPv`g}?WQwv7Fbqkm1~lve^gHq1{hk7$CE)DEupxG z@P8lWS8ceE@Gt;BSeLaUNex_z9GV_bs><(ON;L@$+C7f!qXHD6QUL4{G7+%}_d1xm z4L?*XL&7UVcKrx`k(AO2JVbQYIdIDF94D>o8HoJGC;u}e;i)*PV+~-1n&AWT-G;$3IcCB9Pxom z7$8v=?>LQ(jR0ri6NZtzEH>mNs_4X zuW#Y1`dGQE%6GIN<5Ar!cZpz|#Ze?Y7^Kkpy7l~1?VwDA_+ z!!`im)8K~}lZWbmxzqS(xG$sjzBp(W>-eFP#)$xDptuVB($a&ijm@q$RZ^jmV%uNz6y&yg7=i%KL@24*O!f*Be!b@U73Ufz@n|c;N6_@YD{O zg72lT4>aVBV0iJ%n&62O6X5hpJ z?NR?@?&iCcwo3=Z0H3c_{q>fJ_3s74s?KWdBUse)z+&$8M&Db8iQ$O$_7%ix1LoTn z^z)psg9RD~R*I4HV}6D1y;vr?jeHZJ0%tRK{GL{h35xJt5@C^u88zX_JiyXy`k(kS zL;;YF&?(IH1QWD#dJ9z%oXv)~{+PW&@RmTyMXNIvj!ob@Zpw1rv+kK)z@cyHh+AkKB z3V}aUz}4OxC&5yH;v1m08Ho^1y%o&`Ta%^_wpQY=o&~29@|rVWpq6;nLFLFm{xXE; z7D|{kj5kqjODun?hMG zMOzTNrCcyt2S^&UMERHOKu_SsCeU!O1VSwbeG3T?Y0i8l`QhKLOn13|5)3um9O#aq z9(ud-GcK3L?Qa*A*C2exrOOD85^0Py4uwx{4(}PCV2Wnv%-gcj&`cVpivS^c4`C zD}j8=_Qr?UnyAVb$QYkC+LJYd9$#U`P@2+Ev8I1gPLbv^b;aix$|W*b=qRat7=1v= z9z`nqa12|cF)1+2v)oF1ryWghhyK=a7&1L|YtFqNa}KGE1U>2>Pt?Z9H-?_{mS~U? za0ai3Bm1qL%>V4_tkk*3;~H>i3)cmDYHE>u@qBZpBh?jM~pxs@(CvV#9d774^)*Vh0Bpe%ro z|8`slb8_bK2`?0I#!M?;zSe?kIx`(Z4AP3K^yk~%xU1ms5bLr&$649*;GXhJQPKVZXcO5 zFzUG7o(J>I_Ok&sm@p7Fhx;2pj^_h)Xts<~k8cZO^Gu9Q+e zp+nJG>S(iFk#f>=SFg$d*<85!Ge_ZMYOPRGxn^?8ovQdxm)!I1Ckk56f2thi5-ZR+ zJiPtsAV3qhf&tYTAsKU1z318e-Xa{_upjk(@z-X3S0Di1?7+TBQGK3?ucU}Kd~tE3 zdWan!)4&Xzz~he7JcPh`siQ0lNUEa+72PQxF@>w=dk~!cN*;6(Rh89i6Mo@VH#IhXWQ-r+pyF$f(HXN_dA*=(LM|3y3+)w4Wx>>Qv&NMVvEDH@ zWQfEoiUe+GT*3IPWEj{#aq5*J+5g3bbXut5i1e;4}LRK?{YafurK2Zu5D z#|OZ2q#57NB3syd5_Eu^56l>tvK}psXV+)@UTjba?_s`4ZzB=BOHw)4w0hmrmWm4x z4^T=J&sR*NY-k36WcjI|I{#_v{Z8oh39$;xO!ha~BVPE>^u{(F%}4`>g6-ZujyGO0(6beR!WgEH6`1~bMBrkTi&$@Mnbmv!=F4H|lq|CQb`dP+jOhl&2g_bKP(nq7OeM7vG==r#-@v>>9PrOSJEd><3f?)Drhu2qy8CQ4LMz7 zd&=1T#_c*#OjlF;9;P0ye$n3bMSPHG3D!Q-qPp(Jgd#TgD5$O1+~Vq=KH+V{xlkY< zexeh6otb4`p_3w(sMeBBi8wvil30&GA!37LuqJ|9Qghm&@mqI|*jSHU)R%~4VHNXk zkfIT(47B6egMs3)CoC-`4+Hg81avWz2iByeZ}ZB3`TFo~sBje# zue7xpyN1wR{RDjcWh$QU3cu2-UdaM<7?}V{qvYXrs;$wZt_0hmVClh(gg;Oa-Ph7J z;QJ{2_|%ItwXkf4*GNXK=ZXhU09KI*(k)Ov3^@35OnzElZn}ro6iH zJa3WlNXsi5xCRbviO4mJ>^C|UZrtW}=o@G7%#fK_FW$xGqxP}dc%UwqJIHKgrznWQ ze(PPM0xmviIG%O%gb*>owwz$UmK3@Ys~KXebxn)&-E~S1b~$etmsCVYSp>j{4s`o) zdyk!|YebOalR!%!yYh<5>sQr^c3_6pW_bwz+as038Fh<-tBqZ(SY`l=P4Ru)j4kr5 z0{4FX5r3}k;N4#ilj1KFs;vKEftR#FSpm_+Gof&O)aAd8N5Fvj>0Y=-OO2|^XK3 zVD<*2uuo!QKT9d>DRxr4W&3FMhMq!{V)Uy%Br|N49Z?)@%Mr9%Wi4Q}^?e-Ec=AYR z&cDqu=BnWa+_bwA1vb_+f!Xr(|e6bej#4?UV-!;4f_N{{~ zO028wdz~I(0@mUG88q_{dXirEG=X`&ytFFWomj1^iiEt%Q7J8%r%fIZwyrv=PPn6k zw?vgA*iZ%bgE)UL`SzXPx1N#soUIb#~i__*Bd=pehvbz9o=o0}pPF zo{peMxW16wTO?vug2X;FRwHY#w|?bx#~k5)Bv89ekrl$tAW#wm#U4Mg5??&AwiCP~ zA-8^Vilk&O(~Z{!M?=nR_%U9X!!6JZPT&4Ief#Tw$p_#E*^a@>1(e)}rD_U#~TYhk}tz=>i+te`V zmqVq@;&C}MAB{n)TxxSJe%be7cKpRf`>S)e{NBxwTMv^r!CES5NJ?Ya4_tSaKC`~{ zv6rjd@uYUMe{k?o+c?bc9hrnUuQqV%;><-l8RHI_rigU>8_OA2Odh=5PVlwTlDQQ^NsgaWW4jCUI;O5o#X+Q zCm)ug%BPdNHCk;fy`=ajBCDr=6=9+g{x??BYuH|2-iUn4y1FsY;%B3x@9iOP%f|?9 z@k3c-!@0b>eTMx|(S0e^z6o6PyD2*v!Thi!v6h1xTE0KEI~leOHw;iNdMIVGvh~gf z&UsOk(-qS=vI}k)ouy~|*TTKWzx$zH_6e}NOAS|3CzkeDJkWQR<0F|iQjf9>ldLI1 z#}{Fy$?^iR5GCIWyQR}uwu9?V+f_R~;sq21RD zN)l>pv4Uw9(QnQLDXrKE+679orE}+P3Wb~9bt#{HMAT%EX9uSu(k~uwBZ>JD@?h}H zAem1sWndk(H@K8e zyDM!uaxbHP=&S}Z+GRN1=q_JJV9!tRiIMMa8uP7HOoL)yw#!&An-0zKO;k*=@kRJI z?wFW0T-HN{=lJT#rP#C}#0DdGoQd|L&fS@Ip|3S2m&IJk)73o#b4iv@#!Nr`_)aUwHpRVZtnE6i*3H{Ea|$7_eOc^ z&llf%C|qw+3@t7$o-RHt<}-rV>_w#UiM)v0Vz}4q+{3=?_O8(5-bLl4+au<-_G9#u zCi_^%{`u*sB{#HA|C9*2X6i6qQung1q^_y1%gEW06zq>ZZ=5H4?W&9L6wVl~C@7f3 i#J Date: Fri, 3 May 2024 16:29:37 +0100 Subject: [PATCH 2/3] More work on delphinID classifier but not quite there yet. --- src/rawDeepLearningClassifier/DLControl.java | 1 + .../dlClassification/DLClassifyProcess.java | 184 +++++++++++------- .../StandardClassifierModel.java | 2 +- .../delphinID/DelphinIDClassifier.java | 2 +- .../delphinID/DelphinIDWorker.java | 5 +- .../genericModel/GenericDLClassifier.java | 2 +- .../genericModel/GenericModelWorker.java | 6 +- .../segmenter/SegmenterDetectionGroup.java | 6 +- .../segmenter/SegmenterGroupDataBlock.java | 2 + .../segmenter/SegmenterProcess.java | 118 +++++++++-- 10 files changed, 240 insertions(+), 88 deletions(-) diff --git a/src/rawDeepLearningClassifier/DLControl.java b/src/rawDeepLearningClassifier/DLControl.java index fda39d72..3b2ad27f 100644 --- a/src/rawDeepLearningClassifier/DLControl.java +++ b/src/rawDeepLearningClassifier/DLControl.java @@ -228,6 +228,7 @@ public class DLControl extends PamControlledUnit implements PamSettings { // classify the raw data segments. addPamProcess(dlClassifyProcess = new DLClassifyProcess(this, segmenterProcess.getSegmenterDataBlock())); + dlClassifyProcess.addMultiPlexDataBlock(segmenterProcess.getSegmenteGrouprDataBlock()); //manages the names assigned to different output classes. dlClassNameManager = new DLClassNameManager(this); diff --git a/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java b/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java index fe515cb1..bb0f8945 100644 --- a/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java +++ b/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java @@ -20,6 +20,7 @@ import rawDeepLearningClassifier.logging.DLAnnotation; import rawDeepLearningClassifier.logging.DLAnnotationType; import rawDeepLearningClassifier.segmenter.GroupedRawData; import rawDeepLearningClassifier.segmenter.SegmenterDataBlock; +import rawDeepLearningClassifier.segmenter.SegmenterDetectionGroup; /** * The deep learning classification process. This takes a segment of raw data from the segmenter. @@ -35,7 +36,7 @@ import rawDeepLearningClassifier.segmenter.SegmenterDataBlock; */ public class DLClassifyProcess extends PamInstantProcess { - + /** * Holds all model results but no other information */ @@ -64,15 +65,13 @@ public class DLClassifyProcess extends PamInstantProcess { /** * The DL buffer */ - private ArrayList classificationBuffer; - + private ArrayList classificationBuffer; /** * The DL annotation type. */ private DLAnnotationType dlAnnotationType; - /** * The last parent data for grouped data. This is used to ensure that DLDetections * correspond to the raw chunk of data from a parent detection e.g. a click detection. @@ -82,8 +81,8 @@ public class DLClassifyProcess extends PamInstantProcess { public DLClassifyProcess(DLControl dlControl, SegmenterDataBlock parentDataBlock) { super(dlControl); - - + + this.setParentDataBlock(parentDataBlock); // this.setParentDataBlock(parentDataBlock); @@ -117,7 +116,7 @@ public class DLClassifyProcess extends PamInstantProcess { overlayGraphics.setDetectionData(true); dlDetectionDataBlock.setOverlayDraw(overlayGraphics); - classificationBuffer = new ArrayList(); + classificationBuffer = new ArrayList(); //the process name. setProcessName("Deep Learning Classifier"); @@ -140,7 +139,7 @@ public class DLClassifyProcess extends PamInstantProcess { System.err.println("Raw Deep Learning Classifier: The grouped source parameters were null." + " A new instance has been created: Possible de-serialization error."); } - + //important for downstream processes such as the bearing localiser. dlModelResultDataBlock.setChannelMap(dlControl.getDLParams().groupedSourceParams.getChannelBitmap()); @@ -166,7 +165,7 @@ public class DLClassifyProcess extends PamInstantProcess { public void prepareProcess() { setupClassifierProcess(); } - + /** * called for every process once the system model has been created. @@ -194,36 +193,71 @@ public class DLClassifyProcess extends PamInstantProcess { */ @Override public void newData(PamObservable obs, PamDataUnit pamRawData) { +// System.out.println("NEW SEGMENTER DATA"); - //the raw data units should appear in sequential channel order - GroupedRawData rawDataUnit = (GroupedRawData) pamRawData; - - if (checkGroupData(rawDataUnit)) { - //check whether the classification buffer is full. If it is then run - if (isClassificationBufferFull(classificationBuffer, rawDataUnit)) { - - //first call run model to clear out the classification buffer if needs be - runModel(); + if (pamRawData instanceof SegmenterDetectionGroup) { + if (classificationBuffer.size()>=1) { + System.out.println("RUN THE MODEL FOR WHISTLES: "); + runDetectionGroupModel(); classificationBuffer.clear(); } - - classificationBuffer.add(rawDataUnit); + else { + classificationBuffer.add(pamRawData); + } } -// System.out.println("New raw data in: chan: " + PamUtils.getSingleChannel(pamRawData.getChannelBitmap()) + -// " Size: " + pamRawData.getSampleDuration() + " first sample: " + rawDataUnit.getRawData()[0][0] -// + "Parent UID: " + rawDataUnit.getParentDataUnit().getUID()); + + if (pamRawData instanceof GroupedRawData) { + //the raw data units should appear in sequential channel order + GroupedRawData rawDataUnit = (GroupedRawData) pamRawData; + + if (checkGroupData(rawDataUnit)) { + //check whether the classification buffer is full. If it is then run + if (isRawClassificationBufferFull(classificationBuffer, rawDataUnit)) { + + //first call run model to clear out the classification buffer if needs be + runRawModel(); + classificationBuffer.clear(); + } + + classificationBuffer.add(rawDataUnit); + + } + } + // System.out.println("New raw data in: chan: " + PamUtils.getSingleChannel(pamRawData.getChannelBitmap()) + + // " Size: " + pamRawData.getSampleDuration() + " first sample: " + rawDataUnit.getRawData()[0][0] + // + "Parent UID: " + rawDataUnit.getParentDataUnit().getUID()); } - + + + /** + * Run a model for which the input is a detection group. + */ + private void runDetectionGroupModel() { + if (classificationBuffer.size()<=0) return; + ArrayList classificationBufferTemp = (ArrayList) classificationBuffer.clone(); + + ArrayList modelResults = this.dlControl.getDLModel().runModel(classificationBufferTemp); + + for (int i=0; i classificationBufferTemp = (ArrayList) classificationBuffer.clone(); - ArrayList modelResults = this.dlControl.getDLModel().runModel(classificationBuffer); + ArrayList modelResults = this.dlControl.getDLModel().runModel(classificationBufferTemp); if (modelResults==null) { return; //there has been a problem @@ -235,18 +269,18 @@ public class DLClassifyProcess extends PamInstantProcess { // System.out.println("Compare Times: " + PamCalendar.formatDBDateTime(modelResults.get(i).getTimeMillis(), true) + // " " + PamCalendar.formatDBDateTime(classificationBufferTemp.get(i).getTimeMilliseconds(), true) + " " + // modelResults.get(i).getPrediction()[1]); - newModelResult(modelResults.get(i), classificationBufferTemp.get(i)); + newRawModelResult(modelResults.get(i), classificationBufferTemp.get(i)); } } } /** - * Check whether the buffer is full and the results should be passed to the classification model. + * Check whether the buffer is full and the results should be passed to the classification model if we are using GrpoupDataUnits * @param classificationBuffer2 - the classification buffer. * @param rawDataUnit - the next raw data unit to add to the buffer. * @return true if the buffer is full. */ - private boolean isClassificationBufferFull(ArrayList classificationBuffer2, GroupedRawData rawDataUnit) { + private boolean isRawClassificationBufferFull(ArrayList classificationBuffer2, GroupedRawData rawDataUnit) { if (classificationBuffer2.size()==0) return false; @@ -254,16 +288,16 @@ public class DLClassifyProcess extends PamInstantProcess { //1) It's over a max time //2) Contains different parent data units (if not from raw data). - GroupedRawData lastUnit = classificationBuffer2.get(classificationBuffer2.size()-1); + GroupedRawData lastUnit = (GroupedRawData) classificationBuffer2.get(classificationBuffer2.size()-1); if (!(lastUnit.getParentDataUnit() instanceof RawDataUnit) && lastUnit.getParentDataUnit()!=rawDataUnit.getParentDataUnit()) { //there is a new parent data unit. return true; } - //get the start time. Use min value instead of first data just in case units ar enot in order. + //get the start time. Use min value instead of first data just in case units are not in order. long min = Long.MAX_VALUE; - for (GroupedRawData groupedRawData: classificationBuffer2) { + for (PamDataUnit groupedRawData: classificationBuffer2) { if (groupedRawData.getTimeMilliseconds()0) { - //System.out.println("Save click annotation to " + lastParentDataUnit[i].getUID()); + //System.out.println("Save click annotation to " + lastParentDataUnit[i].getUID()); addDLAnnotation(dataUnit,groupDataBuffer[i],modelResultDataBuffer[i]); lastParentDataUnit[i]=null; clearBuffer(i); @@ -532,15 +573,22 @@ public class DLClassifyProcess extends PamInstantProcess { @Override public void pamStart() { - // TODO Auto-generated method stub - System.out.println("PREP MODEL:"); +// System.out.println("PREP MODEL:"); this.dlControl.getDLModel().prepModel(); } @Override public void pamStop() { - runModel(); //make sure to run the last data in the buffer. - + //make sure to run the last data in the buffer. + if (this.classificationBuffer.size()>0) { + if (classificationBuffer.get(0) instanceof GroupedRawData) { + runRawModel(); //raw data or raw data units + } + if (classificationBuffer.get(0) instanceof SegmenterDetectionGroup) { + runDetectionGroupModel(); //any other data units. + } + } + //21/11/2022 - it seems like this causes a memory leak when models are reopened and closed every file... //this.dlControl.getDLModel().closeModel(); } diff --git a/src/rawDeepLearningClassifier/dlClassification/StandardClassifierModel.java b/src/rawDeepLearningClassifier/dlClassification/StandardClassifierModel.java index 0fbce3de..b6138e44 100644 --- a/src/rawDeepLearningClassifier/dlClassification/StandardClassifierModel.java +++ b/src/rawDeepLearningClassifier/dlClassification/StandardClassifierModel.java @@ -271,7 +271,7 @@ public abstract class StandardClassifierModel implements DLClassiferModel, PamSe */ protected void newResult(StandardPrediction modelResult, PamDataUnit groupedRawData) { if (groupedRawData instanceof GroupedRawData) { - this.dlControl.getDLClassifyProcess().newModelResult(modelResult, (GroupedRawData) groupedRawData); + this.dlControl.getDLClassifyProcess().newRawModelResult(modelResult, (GroupedRawData) groupedRawData); } } // diff --git a/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDClassifier.java b/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDClassifier.java index b55c8655..0a7e2813 100644 --- a/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDClassifier.java +++ b/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDClassifier.java @@ -91,7 +91,7 @@ public class DelphinIDClassifier extends StandardClassifierModel { @Override public boolean isDecision(StandardPrediction modelResult, StandardModelParams modelParmas) { //TODO - //DelphinID uses a different decision making process to most of the standard classifiers which just pass a binary threhsoild. + //DelphinID uses a different decision making process to most of the standard classifiers which just pass a binary threshold. return false; } diff --git a/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDWorker.java b/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDWorker.java index b3ef293d..c411cce1 100644 --- a/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDWorker.java +++ b/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDWorker.java @@ -49,8 +49,8 @@ public class DelphinIDWorker extends ArchiveModelWorker { this.setModel(null); // set model to null to make sure nothing works and errors are thrown } - dlParams.binaryClassification = new boolean[dlParams.classNames.length]; - for (int i=0; i { @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) @@ -47,7 +48,8 @@ public class GenericModelWorker extends DLModelWorker { //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); + System.out.println("GENERIC MODEL RESULTS: " + (results== null ? null : results.length)); + PamArrayUtils.printArray(results); return results; } diff --git a/src/rawDeepLearningClassifier/segmenter/SegmenterDetectionGroup.java b/src/rawDeepLearningClassifier/segmenter/SegmenterDetectionGroup.java index 93bbb7e3..fe218fbf 100644 --- a/src/rawDeepLearningClassifier/segmenter/SegmenterDetectionGroup.java +++ b/src/rawDeepLearningClassifier/segmenter/SegmenterDetectionGroup.java @@ -28,7 +28,7 @@ public class SegmenterDetectionGroup extends GroupDetection { * @param timeMilliseconds - this is the start of the SEGMENT - Note that the * @param channelBitmap - channels of all detections * @param startSample - the stratSample of the SEGMENT. - * @param duration - the duration of the SEGMENT. + * @param duration - the duration of the SEGMENT in milliseconds. */ public SegmenterDetectionGroup(long timeMilliseconds, int channelBitmap, long startSample, double duration) { super(timeMilliseconds, channelBitmap, startSample, (long) duration); @@ -52,5 +52,9 @@ public class SegmenterDetectionGroup extends GroupDetection { return segDuration; } + public long getSegmentEndMillis() { + return (long) (segMillis+segDuration); + } + } diff --git a/src/rawDeepLearningClassifier/segmenter/SegmenterGroupDataBlock.java b/src/rawDeepLearningClassifier/segmenter/SegmenterGroupDataBlock.java index 3bda33fd..3a69c23a 100644 --- a/src/rawDeepLearningClassifier/segmenter/SegmenterGroupDataBlock.java +++ b/src/rawDeepLearningClassifier/segmenter/SegmenterGroupDataBlock.java @@ -12,6 +12,8 @@ public class SegmenterGroupDataBlock extends PamDataBlock=segStart && whistleStart=segStart && whistleEnd Date: Tue, 7 May 2024 16:15:29 +0100 Subject: [PATCH 3/3] DelphinID almost there. --- .../dataPlotFX/DLPredictionPane.java | 2 + .../dataPlotFX/DLPredictionPlotInfoFX.java | 4 +- .../dlClassification/DLClassifyProcess.java | 7 +- .../StandardClassifierModel.java | 5 +- .../archiveModel/ArchiveModelWorker.java | 3 +- .../delphinID/DelphinIDClassifier.java | 7 +- .../delphinID/DelphinIDWorker.java | 59 +++++++++- .../delphinID/Whistles2Image.java | 13 ++- .../genericModel/GenericModelWorker.java | 6 +- .../segmenter/SegmenterDetectionGroup.java | 12 +- .../segmenter/SegmenterProcess.java | 110 ++++++++++++------ .../DelphinIDTest.java | 22 ++++ .../DelphinID/whistle_image_example.mat | Bin 19051 -> 19612 bytes 13 files changed, 191 insertions(+), 59 deletions(-) diff --git a/src/rawDeepLearningClassifier/dataPlotFX/DLPredictionPane.java b/src/rawDeepLearningClassifier/dataPlotFX/DLPredictionPane.java index c603f08f..19147c81 100644 --- a/src/rawDeepLearningClassifier/dataPlotFX/DLPredictionPane.java +++ b/src/rawDeepLearningClassifier/dataPlotFX/DLPredictionPane.java @@ -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); } diff --git a/src/rawDeepLearningClassifier/dataPlotFX/DLPredictionPlotInfoFX.java b/src/rawDeepLearningClassifier/dataPlotFX/DLPredictionPlotInfoFX.java index 44fdca6f..36aed7ed 100644 --- a/src/rawDeepLearningClassifier/dataPlotFX/DLPredictionPlotInfoFX.java +++ b/src/rawDeepLearningClassifier/dataPlotFX/DLPredictionPlotInfoFX.java @@ -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(); } } diff --git a/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java b/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java index bb0f8945..03806aa3 100644 --- a/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java +++ b/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java @@ -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 classificationBufferTemp = (ArrayList) classificationBuffer.clone(); ArrayList modelResults = this.dlControl.getDLModel().runModel(classificationBufferTemp); for (int i=0; i) delphinIDParams.dlTransfromParams); } diff --git a/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDWorker.java b/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDWorker.java index c411cce1..a2fcc459 100644 --- a/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDWorker.java +++ b/src/rawDeepLearningClassifier/dlClassification/delphinID/DelphinIDWorker.java @@ -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 { @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 { //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; } diff --git a/src/rawDeepLearningClassifier/segmenter/SegmenterDetectionGroup.java b/src/rawDeepLearningClassifier/segmenter/SegmenterDetectionGroup.java index fe218fbf..9636a52b 100644 --- a/src/rawDeepLearningClassifier/segmenter/SegmenterDetectionGroup.java +++ b/src/rawDeepLearningClassifier/segmenter/SegmenterDetectionGroup.java @@ -21,6 +21,8 @@ public class SegmenterDetectionGroup extends GroupDetection { */ 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 { 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 { return (long) (segMillis+segDuration); } + public void setStartSecond(double timeS) { + this.timeS = timeS; + } + + public double getStartSecond() { + return timeS; + } + } diff --git a/src/rawDeepLearningClassifier/segmenter/SegmenterProcess.java b/src/rawDeepLearningClassifier/segmenter/SegmenterProcess.java index 3ae032a0..7012ac68 100644 --- a/src/rawDeepLearningClassifier/segmenter/SegmenterProcess.java +++ b/src/rawDeepLearningClassifier/segmenter/SegmenterProcess.java @@ -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; i0) { + 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=segStart && whistleEnd transforms = new ArrayList(); + 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; ilYI#tEk4rKt+OiIoZp<_d-;R>me)1{MlN21X_m1C=Kxuud%bQ?JRyz)&&g z&6$Io4F)_87b^n3JYsvdK==hm--Si4EUPcgyK_s>=c4GIzlWX+Iz@G#$Z+A>I_3J8 zPx*3N!cK2-i{2X>V=nuTN6*b%|6p9ZtW*_x1d~S+hOeYHz*KN|8Ikr>;SOnd06xjsC@Jlv|WqTu$#WpZ==Kf?D|We|7=}#Uw!58+BEhWsr0?? zv$JZabP06W_rF~A_n!g3@5f4??GX&~k43!y|6cN0&{n4HkIpCWx~raXsZ#XTqt7$m z<%u~-C0=}fo8hx&J%gO?hPHd`OXeRBQJ?8wduE~Ov^{@)L+|Eq-~QmYrNMcpTjw2{ z#cpo3lVAG$f9CJV?)swYfaRHC%TGyeIr9AX+f|?K_cG=^*)@IM^^o+)*>ds+E`C>h zx%1IFEB3aTi{I~l?^OHGwp`Kj^}{VZa%(sJ|9)@(x38>BQmJ~p8_)mUP{w%j=ewO} z_VmB6I=OTIj4U%|M&AuDzW-wbhx<8CUIqmohJ#jz_jB+uv#3m1#W2b6=J^_PrQ51@ s8?WX}ySTaZZ@Y@;Bq%y5ZUc_6h($ delta 46 zcmbO;lkxQw#tEk48KnxoiIoZpMhb=oR;K1whK34821X_m1C=Kxuud%bvw0!&Zw~-h CE)Qw|