diff --git a/src/export/swing/ExportProcessDialog.java b/src/export/swing/ExportProcessDialog.java index 7008b7f8..93184f13 100644 --- a/src/export/swing/ExportProcessDialog.java +++ b/src/export/swing/ExportProcessDialog.java @@ -76,7 +76,6 @@ public class ExportProcessDialog { public void createExportGroup() { - //clear current tasks. dlOfflineGroup.clearTasks(); @@ -88,7 +87,6 @@ public class ExportProcessDialog { dlOfflineGroup.addTask(new ExportTask(dataBlocks.get(i), exportManager)); } } - } ////---Swing stuff----/// should not be here but this is how PG works. @@ -388,7 +386,7 @@ public class ExportProcessDialog { /** - * Export taks group. + * Export task */ class ExportTaskGroup extends OfflineTaskGroup { diff --git a/src/rawDeepLearningClassifier/DLControl.java b/src/rawDeepLearningClassifier/DLControl.java index 4b7d3713..67126845 100644 --- a/src/rawDeepLearningClassifier/DLControl.java +++ b/src/rawDeepLearningClassifier/DLControl.java @@ -622,8 +622,9 @@ public class DLControl extends PamControlledUnit implements PamSettings { } /** - * Get the classifier chooser. - * @return the classifier chooser.Take it + * Get the classifier chooser. The classifier chooser chooses which classifier use + * based on a selected file or URL. + * @return the classifier chooser. */ public DLClassifierChooser getDlClassifierChooser() { return dlClassifierChooser; diff --git a/src/rawDeepLearningClassifier/dataPlotFX/DLSymbolOptionPane.java b/src/rawDeepLearningClassifier/dataPlotFX/DLSymbolOptionPane.java index 7023de9d..7e6370dc 100644 --- a/src/rawDeepLearningClassifier/dataPlotFX/DLSymbolOptionPane.java +++ b/src/rawDeepLearningClassifier/dataPlotFX/DLSymbolOptionPane.java @@ -361,7 +361,7 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane { classNameBox2.getSelectionModel().select(Math.max(symbolOptions.classIndex2, 0)); - int index = symbolOptions.classIndex2>=0? symbolOptions.classIndex2 : 0; + int index = symbolOptions.classIndex2>=0 ? symbolOptions.classIndex2 : 0; if (symbolOptions.classColors==null) { symbolOptions.setDefaultClassColors(nClass); diff --git a/src/rawDeepLearningClassifier/dataSelector/DLDataFilter.java b/src/rawDeepLearningClassifier/dataSelector/DLDataFilter.java new file mode 100644 index 00000000..f4527b5d --- /dev/null +++ b/src/rawDeepLearningClassifier/dataSelector/DLDataFilter.java @@ -0,0 +1,35 @@ +package rawDeepLearningClassifier.dataSelector; + +import PamguardMVC.PamDataUnit; +import PamguardMVC.dataSelector.DataSelectParams; + +/** + * Score a data unit with a deep learning annotation. Note that this could be an + * external data unit with an annotation e.g. a click, or deep learning + * detections generated by the deep learning module. + * + * @author Jamie Macaulay + */ +public interface DLDataFilter { + + /** + * Score a data unit with deep learning annotations + * @param dataUnit - the data unit to score + * @return 0 to reject and >0 to accept. + */ + public int scoreDLData(PamDataUnit dataUnit); + + /** + * Get parameters for the data filter. + * @return parameters for the data selectors. + */ + public DataSelectParams getParams(); + + /** + * Set the parameters for the data filter. + * @param params - the parameters to set. + */ + public void setParams(DataSelectParams params); + + +} diff --git a/src/rawDeepLearningClassifier/dataSelector/DLDataSelectCreator.java b/src/rawDeepLearningClassifier/dataSelector/DLDataSelectCreator.java new file mode 100644 index 00000000..a4cf341c --- /dev/null +++ b/src/rawDeepLearningClassifier/dataSelector/DLDataSelectCreator.java @@ -0,0 +1,34 @@ +package rawDeepLearningClassifier.dataSelector; + +import PamguardMVC.PamDataBlock; +import PamguardMVC.dataSelector.DataSelectParams; +import PamguardMVC.dataSelector.DataSelector; +import PamguardMVC.dataSelector.DataSelectorCreator; +import clickDetector.dataSelector.ClickDataSelector; +import rawDeepLearningClassifier.DLControl; + +/** + * Creates a data selector for the deep learning module. + * + * @author Jamie Macaulay + */ +public class DLDataSelectCreator extends DataSelectorCreator { + + private DLControl dlcontrol; + + public DLDataSelectCreator(DLControl dlcontrol, PamDataBlock pamDataBlock) { + super(pamDataBlock); + this.dlcontrol = dlcontrol; + } + + @Override + public DataSelectParams createNewParams(String name) { + return new DLDataSelectorParams(); + } + + @Override + public DataSelector createDataSelector(String selectorName, boolean allowScores, String selectorType) { + return new DLDataSelector(dlcontrol, this.getPamDataBlock(), selectorName, allowScores, selectorType); + } + +} diff --git a/src/rawDeepLearningClassifier/dataSelector/DLDataSelector.java b/src/rawDeepLearningClassifier/dataSelector/DLDataSelector.java new file mode 100644 index 00000000..4ca9913f --- /dev/null +++ b/src/rawDeepLearningClassifier/dataSelector/DLDataSelector.java @@ -0,0 +1,120 @@ +package rawDeepLearningClassifier.dataSelector; + +import java.util.ArrayList; +import java.util.List; + +import PamView.dialog.PamDialogPanel; +import PamguardMVC.PamDataBlock; +import PamguardMVC.PamDataUnit; +import PamguardMVC.dataSelector.DataSelectParams; +import PamguardMVC.dataSelector.DataSelector; +import pamViewFX.fxSettingsPanes.DynamicSettingsPane; +import rawDeepLearningClassifier.DLControl; + +/** + * Data selector of DL data units. Note that data selectors are really data + * unit specific and not annotation specific. + *

+ * The data selector can have different types of data selectors which can + * depend on the classifer used and user choice. + *

+ * Note that this is slightly different from DLPredicitoDecision + * as it deals with data units that may have a more than one prediction. + * i.e. + */ +public class DLDataSelector extends DataSelector { + + + /** + * Swing panel for the data selector. + */ + private DLSelectPanel dlSelectPanel; + + + /** + * FX panel for the data selector. + */ + private DLSelectPaneFX dlSelectPaneFX; + + /** + * Data filter for filtering. + */ + private List dataFilters = new ArrayList (); + + + private DLDataSelectorParams dlDataSelectParams; + + /** + * Constructor for the data selector. + * @param dlcontrol - reference to the DLControl. + * @param pamDataBlock - the data block. + * @param selectorName - the selector name. + * @param allowScores - allow all the scores. + * @param selectorType - the selector type. + */ + public DLDataSelector(DLControl dlcontrol, PamDataBlock pamDataBlock, String selectorName, boolean allowScores, String selectorType) { + super(pamDataBlock, selectorName, allowScores); + /****New data filters go here****/ + dataFilters.add(new DLPredictionFilter(dlcontrol)); + } + + @Override + public PamDialogPanel getDialogPanel() { + if (dlSelectPanel == null) { + dlSelectPanel = new DLSelectPanel(this); + } + return dlSelectPanel; + } + + @Override + public DynamicSettingsPane getDialogPaneFX() { + if (dlSelectPaneFX == null) { + dlSelectPaneFX = new DLSelectPaneFX(this); + } + return dlSelectPaneFX; + } + + @Override + public void setParams(DataSelectParams dataSelectParams) { + + if (dataSelectParams instanceof DLDataSelectorParams) { + dlDataSelectParams = (DLDataSelectorParams) dataSelectParams; + + checkDataFilterParamsSize(dlDataSelectParams); + + //set paramters for all data filters. + for (int i=0; i=0 ? 1 : 0; + } + +} diff --git a/src/rawDeepLearningClassifier/dataSelector/DLDataSelectorParams.java b/src/rawDeepLearningClassifier/dataSelector/DLDataSelectorParams.java new file mode 100644 index 00000000..ebbc48c1 --- /dev/null +++ b/src/rawDeepLearningClassifier/dataSelector/DLDataSelectorParams.java @@ -0,0 +1,22 @@ +package rawDeepLearningClassifier.dataSelector; + +import java.io.Serializable; + +import PamguardMVC.dataSelector.DataSelectParams; + +/** + * Paramters for the DL data seelctor + */ +public class DLDataSelectorParams extends DataSelectParams implements Serializable, Cloneable{ + + private static final long serialVersionUID = 1L; + + public int dataSelectorIndex = 0; + + /** + * List of data selector parameters for different deep learning selectors. + */ + public DataSelectParams[] dataSelectorParams; + + +} diff --git a/src/rawDeepLearningClassifier/dataSelector/DLPredictionFilter.java b/src/rawDeepLearningClassifier/dataSelector/DLPredictionFilter.java new file mode 100644 index 00000000..54d193b1 --- /dev/null +++ b/src/rawDeepLearningClassifier/dataSelector/DLPredictionFilter.java @@ -0,0 +1,107 @@ +package rawDeepLearningClassifier.dataSelector; + + +import PamguardMVC.PamDataUnit; +import PamguardMVC.dataSelector.DataSelectParams; +import rawDeepLearningClassifier.DLControl; +import rawDeepLearningClassifier.dlClassification.DLDetection; +import rawDeepLearningClassifier.dlClassification.PredictionResult; + +/** + * A data filter which filters data by the maximum prediction value + * for different classes. + * + * @author Jamie Macaulay + */ +public class DLPredictionFilter implements DLDataFilter { + + /** + * Reference to the DLControl + */ + private DLControl dlcontrol; + + /** + * The filter parameters + */ + private DLPredictionFilterParams filterParams = new DLPredictionFilterParams(); + + public DLPredictionFilter(DLControl dlcontrol) { + this.dlcontrol = dlcontrol; + checkParamsClass() ; + } + + + @Override + public int scoreDLData(PamDataUnit dataUnit) { + + DLDetection dlDetection = (DLDetection) dataUnit; + + //iterate through all results and check that at least one class passes data selection. + float[] results; + int maxClassIndex = -1; + int maxPred = -1; + + //get the maximum prediction index which passes the minimum threshold + for (PredictionResult modelResult: dlDetection.getModelResults()) { + results = modelResult.getPrediction(); + for (int j=0; jfilterParams.minClassPredicton[j]) { + if (results[j]> maxPred) maxClassIndex = j; + } + } + } + + return maxClassIndex; + } + + @Override + public DataSelectParams getParams() { + checkParamsClass() ; + return filterParams; + } + + @Override + public void setParams(DataSelectParams params) { + this.filterParams = ((DLPredictionFilterParams) params).clone(); + checkParamsClass(); + + } + + private void checkParamsClass() { + if (filterParams.classSelect==null || dlcontrol.getNumClasses()!=filterParams.classSelect.length) { + filterParams.classSelect = new boolean[dlcontrol.getNumClasses()]; + filterParams.minClassPredicton = new double[dlcontrol.getNumClasses()]; + + //set default so data selector does not always prevent all classes from showing. + for (int i=0; i predictions) { +// +// float[][] results = new float[predictions.size()][]; +// +// //A detection might have multiple prediction results, i.e. predictions are a matrix. Need +// //to iterate through all the predictions and then work out whihc is the maximum. That index is then then] +// //class colour. +// int i=0; +// for (PredictionResult modelResult: predictions) { +// results[i] = modelResult.getPrediction(); +// i++; +// } +// +// int[] indexBest = PamArrayUtils.maxPos(results); +// +// return indexBest; +// } + +} diff --git a/src/rawDeepLearningClassifier/dataSelector/DLPredictionFilterParams.java b/src/rawDeepLearningClassifier/dataSelector/DLPredictionFilterParams.java new file mode 100644 index 00000000..b4dda76c --- /dev/null +++ b/src/rawDeepLearningClassifier/dataSelector/DLPredictionFilterParams.java @@ -0,0 +1,35 @@ +package rawDeepLearningClassifier.dataSelector; + +import PamguardMVC.dataSelector.DataSelectParams; + +/** + * Parameters for filtering by the minimum prediciton value. + */ +public class DLPredictionFilterParams extends DataSelectParams { + + private static final long serialVersionUID = 1L; + + /** + * An array indicating which classes are to be used in data selection + */ + public boolean[] classSelect; + + /** + * The minimum class prediction. + */ + public double[] minClassPredicton; + + /** + * Clone the parameters. + */ + public DLPredictionFilterParams clone() { + try { + return (DLPredictionFilterParams) super.clone(); + } catch (CloneNotSupportedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } + +} diff --git a/src/rawDeepLearningClassifier/dataSelector/DLSelectPaneFX.java b/src/rawDeepLearningClassifier/dataSelector/DLSelectPaneFX.java new file mode 100644 index 00000000..b49f9f47 --- /dev/null +++ b/src/rawDeepLearningClassifier/dataSelector/DLSelectPaneFX.java @@ -0,0 +1,47 @@ +package rawDeepLearningClassifier.dataSelector; + +import javafx.scene.Node; +import javafx.scene.control.Label; +import pamViewFX.fxSettingsPanes.DynamicSettingsPane; + +/** + * JavaFX pane for the deep learning data selector. + * + * @author Jamie Macaulay + */ +public class DLSelectPaneFX extends DynamicSettingsPane{ + + public DLSelectPaneFX(Object ownerWindow) { + super(ownerWindow); + // TODO Auto-generated constructor stub + } + + @Override + public Boolean getParams(Boolean currParams) { + // TODO Auto-generated method stub + return currParams; + } + + @Override + public void setParams(Boolean input) { + // TODO Auto-generated method stub + + } + + @Override + public String getName() { + return "Deep Learning Data Selector:"; + } + + @Override + public Node getContentNode() { + return new Label("Hello data selector"); + } + + @Override + public void paneInitialized() { + // TODO Auto-generated method stub + + } + +} diff --git a/src/rawDeepLearningClassifier/dataSelector/DLSelectPanel.java b/src/rawDeepLearningClassifier/dataSelector/DLSelectPanel.java new file mode 100644 index 00000000..bf7f054c --- /dev/null +++ b/src/rawDeepLearningClassifier/dataSelector/DLSelectPanel.java @@ -0,0 +1,34 @@ +package rawDeepLearningClassifier.dataSelector; + +import javax.swing.JComponent; + +import PamView.dialog.PamDialogPanel; + +/** + * Swing panel for the deep learning data selector. + */ +public class DLSelectPanel implements PamDialogPanel { + + public DLSelectPanel(DLDataSelector dlDataSelector) { + // TODO Auto-generated constructor stub + } + + @Override + public JComponent getDialogComponent() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setParams() { + // TODO Auto-generated method stub + + } + + @Override + public boolean getParams() { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/src/rawDeepLearningClassifier/dlClassification/DLClassiferModel.java b/src/rawDeepLearningClassifier/dlClassification/DLClassiferModel.java index dd0e85b7..7575d80b 100644 --- a/src/rawDeepLearningClassifier/dlClassification/DLClassiferModel.java +++ b/src/rawDeepLearningClassifier/dlClassification/DLClassiferModel.java @@ -115,7 +115,7 @@ public interface DLClassiferModel { /** * Get the parameters which can be serialized from transforms. - * @param dlTransfroms- the dl transforms. + * @param dlTransfroms- the DL transforms. */ public static ArrayList getDLTransformParams(ArrayList dlTransfroms) { ArrayList dlTransformParams = new ArrayList(); diff --git a/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java b/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java index 4f487b5c..5efdee3e 100644 --- a/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java +++ b/src/rawDeepLearningClassifier/dlClassification/DLClassifyProcess.java @@ -415,7 +415,7 @@ public class DLClassifyProcess extends PamInstantProcess { else { /****Add annotation to existing data unit (e.g. click, clip or other RawDataHolder)****/ //Need to go by the parent data unit for merging data not the segments. Note that we may still add multiple - //predicitions to a single data unit depending on how many segments it contains. + //predictions to a single data unit depending on how many segments it contains. //System.out.println("New model data " + pamRawData.getParentDataUnit().getUID() + " " + groupDataBuffer[i].size() + " " + modelResultDataBuffer[i].size()); diff --git a/src/rawDeepLearningClassifier/dlClassification/DLDetectionDataBlock.java b/src/rawDeepLearningClassifier/dlClassification/DLDetectionDataBlock.java index 490925cf..97bfe6d5 100644 --- a/src/rawDeepLearningClassifier/dlClassification/DLDetectionDataBlock.java +++ b/src/rawDeepLearningClassifier/dlClassification/DLDetectionDataBlock.java @@ -3,7 +3,10 @@ package rawDeepLearningClassifier.dlClassification; import PamView.GroupedDataSource; import PamView.GroupedSourceParameters; import PamguardMVC.AcousticDataBlock; +import PamguardMVC.dataSelector.DataSelectorCreator; +import clickTrainDetector.dataselector.CTDataSelectCreator; import rawDeepLearningClassifier.DLControl; +import rawDeepLearningClassifier.dataSelector.DLDataSelectCreator; import rawDeepLearningClassifier.tethys.DLSpeciesManager; import rawDeepLearningClassifier.tethys.DLTethysDataProvider; import tethys.TethysControl; @@ -18,10 +21,30 @@ import tethys.species.DataBlockSpeciesManager; */ public class DLDetectionDataBlock extends AcousticDataBlock implements GroupedDataSource { + /** + * Reference to the deep learning classifier process. + */ private DLClassifyProcess dlClassifyProcess; + + /** + * Reference to the Tethys data provider for the deep learning module (provides standardised metadata). + */ private DLTethysDataProvider dlTethysDataProvider; + + /** + * A species manager for metadata. + */ private DLSpeciesManager dlSpeciesManager; + + /** + * Reference to the deep learning control. + */ private DLControl dlControl; + + /** + * Data selector for the deep learning detections. + */ + private DLDataSelectCreator dlDataSelectCreator; public DLDetectionDataBlock(String dataName, DLClassifyProcess parentProcess, int channelMap) { super(DLDetection.class, dataName, parentProcess, channelMap); @@ -49,6 +72,19 @@ public class DLDetectionDataBlock extends AcousticDataBlock impleme } return dlSpeciesManager; } + + + /* (non-Javadoc) + * @see PamguardMVC.PamDataBlock#getDataSelectCreator() + */ + @Override + public synchronized DataSelectorCreator getDataSelectCreator() { + if (dlDataSelectCreator == null) { + dlDataSelectCreator = new DLDataSelectCreator(dlControl, this); + } + return dlDataSelectCreator; + + } } diff --git a/src/rawDeepLearningClassifier/dlClassification/DLPredictionDecision.java b/src/rawDeepLearningClassifier/dlClassification/DLPredictionDecision.java new file mode 100644 index 00000000..1ba8555e --- /dev/null +++ b/src/rawDeepLearningClassifier/dlClassification/DLPredictionDecision.java @@ -0,0 +1,26 @@ +package rawDeepLearningClassifier.dlClassification; + +/** + * Decides whether a prediction has passed a threshold to be used to create a new + * data unit. + *

+ * Note that the majority of the time this will be a simple test of the value of + * predictions of a model but there will be cases when a classifier implements a + * more complex system. For example, a implementation could save a buffer of predictions + * so that previous predictions inform the latest prediction. Or results may include + * some sort of object detection components and frequency bounds etc could be used for + * classification. + * + * + */ +public interface DLPredictionDecision { + + /** + * Check whether a single prediction passes a binary classifier. Prediction which pass decision will be + * passed on to create new data units. + * @param result - the prediciton result to test. + * @return true if the result is passed. + */ + public boolean isBinaryResult(PredictionResult result); + +} diff --git a/src/rawDeepLearningClassifier/dlClassification/SimpleDLDecision.java b/src/rawDeepLearningClassifier/dlClassification/SimpleDLDecision.java new file mode 100644 index 00000000..248faf4f --- /dev/null +++ b/src/rawDeepLearningClassifier/dlClassification/SimpleDLDecision.java @@ -0,0 +1,49 @@ +package rawDeepLearningClassifier.dlClassification; + +import rawDeepLearningClassifier.dlClassification.animalSpot.StandardModelParams; + +/** + * Make a decision based on a simple binary threshold for a prediction. + */ +public class SimpleDLDecision implements DLPredictionDecision { + + /** + * Reference to the parameters. + */ + private StandardModelParams params; + + + @Override + public boolean isBinaryResult(PredictionResult modelResult) { + return isBinaryResult(modelResult, getParams()) ; + } + + + /** + * Check whether a model passes a binary test... + * @param modelResult - the model results + * @return the model results. + */ + private static boolean isBinaryResult(PredictionResult modelResult, StandardModelParams genericModelParams) { + for (int i=0; igenericModelParams.threshold && genericModelParams.binaryClassification[i]) { + // System.out.println("SoundSpotClassifier: prediciton: " + i + " passed threshold with val: " + modelResult.getPrediction()[i]); + return true; + } + } + return false; + } + + + public StandardModelParams getParams() { + return params; + } + + + public void setParams( StandardModelParams genericModelParams) { + this.params = genericModelParams; + } + +} diff --git a/src/rawDeepLearningClassifier/dlClassification/StandardClassifierModel.java b/src/rawDeepLearningClassifier/dlClassification/StandardClassifierModel.java index bc11e883..7d363263 100644 --- a/src/rawDeepLearningClassifier/dlClassification/StandardClassifierModel.java +++ b/src/rawDeepLearningClassifier/dlClassification/StandardClassifierModel.java @@ -44,6 +44,12 @@ public abstract class StandardClassifierModel implements DLClassiferModel, PamSe * in real time without slowing down the rest of PAMGaurd. */ private TaskThread workerThread; + + /** + * Makes a binary decision on whether a prediction result should go on + * to be part of a data unit. + */ + private SimpleDLDecision simpleDLDecision = new SimpleDLDecision(); public StandardClassifierModel(DLControl dlControl) { @@ -84,7 +90,7 @@ public abstract class StandardClassifierModel implements DLClassiferModel, PamSe for (int i =0; igenericModelParams.threshold && genericModelParams.binaryClassification[i]) { - // System.out.println("SoundSpotClassifier: prediciton: " + i + " passed threshold with val: " + modelResult.getPrediction()[i]); - return true; - } - } - return false; - } +// /** +// * Check whether a model passes a binary test... +// * @param modelResult - the model results +// * @return the model results. +// */ +// public static boolean isBinaryResult(StandardPrediction modelResult, StandardModelParams genericModelParams) { +// for (int i=0; igenericModelParams.threshold && genericModelParams.binaryClassification[i]) { +// // System.out.println("SoundSpotClassifier: prediciton: " + i + " passed threshold with val: " + modelResult.getPrediction()[i]); +// return true; +// } +// } +// return false; +// } @Override