Work on the data selector for the deep learning module.

This commit is contained in:
Jamie Mac 2024-07-15 15:25:16 +01:00
parent d2ba95f500
commit edd9df426f
9 changed files with 238 additions and 52 deletions

View File

@ -101,7 +101,7 @@
<exclude>META-INF/*.SF</exclude> <!-- get rid of manifests from library jars - also done in orig ant build file --> <exclude>META-INF/*.SF</exclude> <!-- get rid of manifests from library jars - also done in orig ant build file -->
<exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude> <exclude>META-INF/*.RSA</exclude>
<exclude>test/resources/**</exclude> <exclude>test/resources/**</exclude><!-- get rid of deep learning moduels and wav files used for unit tests -->
</excludes> </excludes>
</filter> </filter>
</filters> </filters>

View File

@ -39,8 +39,16 @@ public class CompoundDialogPaneFX extends DynamicSettingsPane<Boolean> {
DataSelectorDialogPaneFX dsp = new DataSelectorDialogPaneFX(ds, panel, ind++); DataSelectorDialogPaneFX dsp = new DataSelectorDialogPaneFX(ds, panel, ind++);
selectorPanels.add(dsp); selectorPanels.add(dsp);
//need to add a listener for settings changes to these panes so it can be passed to this pane
dsp.addSettingsListener(()->{
//notify any listeners to this pane that the sub pane has changed.
notifySettingsListeners();
});
mainPanel.getChildren().add(dsp.getContentNode()); mainPanel.getChildren().add(dsp.getContentNode());
} }
} }

View File

@ -109,6 +109,12 @@ public class DataSelectorDialogPaneFX extends DynamicSettingsPane<Boolean> {
dsPane.getChildren().add(contentPane); dsPane.getChildren().add(contentPane);
//need to add a listener for settings changes to these panes so it can be passed to this pane
innerPanel.addSettingsListener(()->{
notifySettingsListeners();
});
orButton.setVisible(setIndex > 0); orButton.setVisible(setIndex > 0);
if (dataSelector instanceof CompoundDataSelector || setIndex < 0) { if (dataSelector instanceof CompoundDataSelector || setIndex < 0) {
buttonPane.setVisible(false); buttonPane.setVisible(false);

View File

@ -189,11 +189,6 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
dataSelectHolder.setPadding(new Insets(5,5,5,5)); dataSelectHolder.setPadding(new Insets(5,5,5,5));
dataSelectPane = createDataSelectPane(); dataSelectPane = createDataSelectPane();
dataSelectPane.addSettingsListener(()->{
//dynamic settings pane so have to repaint whenever a control is selected.
getParams();
clickPlotInfo.getTDGraph().repaint(0);
});
dataSelectPane.setParams(true); dataSelectPane.setParams(true);
@ -231,6 +226,12 @@ public class ClickControlPane2 extends PamBorderPane implements TDSettingsPane {
enablePane(); enablePane();
setFreqType(); setFreqType();
setParams(); setParams();
dataSelectPane.addSettingsListener(()->{
//dynamic settings pane so have to repaint whenever a control is selected.
getParams();
clickPlotInfo.getTDGraph().repaint(0);
});
this.setCenter(tabPane); this.setCenter(tabPane);

View File

@ -97,7 +97,7 @@ public class DLDataSelector extends AnnotationDataSelector<DLAnnotation> {
//set paramters for all data filters. //set paramters for all data filters.
for (int i=0; i<dlDataSelectParams.dataSelectorParams.length; i++) { for (int i=0; i<dlDataSelectParams.dataSelectorParams.length; i++) {
dataFilters.get(i).setParams((DLDataSelectorParams) dataSelectParams); dataFilters.get(i).setParams((DataSelectParams) dlDataSelectParams.dataSelectorParams[i]);
} }
} }
@ -117,7 +117,9 @@ public class DLDataSelector extends AnnotationDataSelector<DLAnnotation> {
} }
@Override @Override
public DataSelectParams getParams() { public DLDataSelectorParams getParams() {
//get the paramters from the pane.
for (int i=0; i<dlDataSelectParams.dataSelectorParams.length; i++) { for (int i=0; i<dlDataSelectParams.dataSelectorParams.length; i++) {
dlDataSelectParams.dataSelectorParams[i] = dataFilters.get(i).getParams(); dlDataSelectParams.dataSelectorParams[i] = dataFilters.get(i).getParams();
} }

View File

@ -7,6 +7,7 @@ import pamViewFX.fxSettingsPanes.DynamicSettingsPane;
import rawDeepLearningClassifier.DLControl; import rawDeepLearningClassifier.DLControl;
import rawDeepLearningClassifier.dlClassification.DLDetection; import rawDeepLearningClassifier.dlClassification.DLDetection;
import rawDeepLearningClassifier.dlClassification.PredictionResult; import rawDeepLearningClassifier.dlClassification.PredictionResult;
import rawDeepLearningClassifier.logging.DLAnnotation;
/** /**
* A data filter which filters data by the maximum prediction value * A data filter which filters data by the maximum prediction value
@ -24,7 +25,9 @@ public class DLPredictionFilter implements DLDataFilter {
/** /**
* The filter parameters * The filter parameters
*/ */
private DLPredictionFilterParams filterParams = new DLPredictionFilterParams(); private DLPredictionFilterParams filterParams = new DLPredictionFilterParams();
private DLPredictonPane dlPredictonPane;
public DLPredictionFilter(DLControl dlcontrol) { public DLPredictionFilter(DLControl dlcontrol) {
this.dlcontrol = dlcontrol; this.dlcontrol = dlcontrol;
@ -35,15 +38,18 @@ public class DLPredictionFilter implements DLDataFilter {
@Override @Override
public int scoreDLData(PamDataUnit dataUnit) { public int scoreDLData(PamDataUnit dataUnit) {
DLDetection dlDetection = (DLDetection) dataUnit;
DLAnnotation annotation = (DLAnnotation) dataUnit. findDataAnnotation(DLAnnotation.class) ;
if (annotation==null) return -1;
//iterate through all results and check that at least one class passes data selection. //iterate through all results and check that at least one class passes data selection.
float[] results; float[] results;
int maxClassIndex = -1; int maxClassIndex = -1;
int maxPred = -1; int maxPred = -1;
//get the maximum prediction index which passes the minimum threshold //get the maximum prediction index which passes the minimum threshold
for (PredictionResult modelResult: dlDetection.getModelResults()) { for (PredictionResult modelResult: annotation.getModelResults()) {
results = modelResult.getPrediction(); results = modelResult.getPrediction();
for (int j=0; j<results.length; j++) { for (int j=0; j<results.length; j++) {
if (filterParams.classSelect[j] && results[j]>filterParams.minClassPredicton[j]) { if (filterParams.classSelect[j] && results[j]>filterParams.minClassPredicton[j]) {
@ -84,11 +90,19 @@ public class DLPredictionFilter implements DLDataFilter {
@Override @Override
public DynamicSettingsPane<DataSelectParams> getSettingsPane() { public DynamicSettingsPane getSettingsPane() {
// TODO Auto-generated method stub if (dlPredictonPane ==null) {
return null; dlPredictonPane = new DLPredictonPane(this);
}
return dlPredictonPane;
} }
public DLControl getDLControl() {
return this.dlcontrol;
}
// /** // /**
// * Get the index of the highest prediciton value a list of results. // * Get the index of the highest prediciton value a list of results.
// * @param predictions - index of the highest prediction within a matrix of predicitons. // * @param predictions - index of the highest prediction within a matrix of predicitons.

View File

@ -5,7 +5,7 @@ import PamguardMVC.dataSelector.DataSelectParams;
/** /**
* Parameters for filtering by the minimum prediciton value. * Parameters for filtering by the minimum prediciton value.
*/ */
public class DLPredictionFilterParams extends DataSelectParams { public class DLPredictionFilterParams extends DataSelectParams implements Cloneable{
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -22,6 +22,7 @@ public class DLPredictionFilterParams extends DataSelectParams {
/** /**
* Clone the parameters. * Clone the parameters.
*/ */
@Override
public DLPredictionFilterParams clone() { public DLPredictionFilterParams clone() {
try { try {
return (DLPredictionFilterParams) super.clone(); return (DLPredictionFilterParams) super.clone();

View File

@ -1,63 +1,191 @@
package rawDeepLearningClassifier.dataSelector; package rawDeepLearningClassifier.dataSelector;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.control.CheckBox; import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.Priority;
import javafx.scene.text.TextAlignment;
import pamViewFX.PamGuiManagerFX;
import pamViewFX.fxGlyphs.PamGlyphDude;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamHBox; import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.PamSpinner; import pamViewFX.fxNodes.PamSpinner;
import pamViewFX.fxNodes.PamVBox; import pamViewFX.fxNodes.PamVBox;
import pamViewFX.fxNodes.sliders.PamSlider;
import pamViewFX.fxSettingsPanes.DynamicSettingsPane; import pamViewFX.fxSettingsPanes.DynamicSettingsPane;
import rawDeepLearningClassifier.dlClassification.DLClassName;
/** /**
* Settings pane for filtering deep learning results by class prediciton. * Settings pane for filtering deep learning results by class prediciton.
*/ */
public class DLPredictonPane extends DynamicSettingsPane<DLPredictionFilterParams>{ public class DLPredictonPane extends DynamicSettingsPane<DLPredictionFilterParams>{
private DLPredictionFilter predicitonFilter; private DLPredictionFilter predicitonFilter;
private PamVBox mainPane; private PamBorderPane mainPane;
private PamVBox contentPane;
private ClassDataSelector[] classPanes;
private ToggleButton toggelButton;
public DLPredictonPane(DLPredictionFilter predicitonFilter) { public DLPredictonPane(DLPredictionFilter predicitonFilter) {
super(null); super(null);
this.predicitonFilter=predicitonFilter; this.predicitonFilter=predicitonFilter;
createPane(); createPane();
} }
private void createPane() { private void createPane() {
mainPane = new PamVBox(); mainPane = new PamBorderPane();
mainPane.setSpacing(5);
PamBorderPane topPane = new PamBorderPane();
Label label = new Label("Select classes to show");
PamBorderPane.setAlignment(label, Pos.BOTTOM_LEFT);
// label.setTextAlignment(TextAlignment.LEFT);
label.setAlignment(Pos.BOTTOM_LEFT);
topPane.setLeft(label);
toggelButton = new ToggleButton();
toggelButton.setTooltip(new Tooltip("Lock sliders together so one slider changes all values"));
toggelButton.setGraphic(PamGlyphDude.createPamIcon("mdi2l-lock-open", PamGuiManagerFX.iconSize));
toggelButton.selectedProperty().addListener((onsVal, oldVal,newVal)->{
if (newVal) {
toggelButton.setGraphic(PamGlyphDude.createPamIcon("mdi2l-lock", PamGuiManagerFX.iconSize));
}
else {
toggelButton.setGraphic(PamGlyphDude.createPamIcon("mdi2l-lock-open", PamGuiManagerFX.iconSize));
}
});
toggelButton.setSelected(false);
topPane.setRight(toggelButton);
// topPane.setAlignment(Pos.CENTER_RIGHT);
contentPane = new PamVBox();
contentPane.setSpacing(5);
mainPane.setTop(topPane);
mainPane.setCenter(contentPane);
PamBorderPane.setMargin(topPane, new Insets(0,0,5.,0));
} }
class ClassDataSelector extends PamHBox { class ClassDataSelector extends PamHBox {
PamSpinner<Double> spinner; Slider slider;
CheckBox enable; CheckBox enable;
Label valueLabel;
ClassDataSelector(String classType, int index) { ClassDataSelector(String classType, int index) {
enable = new CheckBox(classType); enable = new CheckBox(classType);
spinner = new PamSpinner<Double>(0., 1., 0.7, 0.1); enable.setPrefWidth(80);
spinner.setEditable(true); enable.setTooltip(new Tooltip(classType));
enable.setOnAction((a)->{
//disable if the class is unticked.
slider.setDisable(!enable.isSelected());
valueLabel.setDisable(!enable.isSelected());
notifySettingsListeners();
});
this.getChildren().addAll(getChildrenUnmodifiable()); slider = new Slider();
slider.setShowTickMarks(true);
slider.setMinorTickCount(10);
slider.setShowTickLabels(false);
slider.setMajorTickUnit(0.5);
slider.valueProperty().addListener((obsval, oldval, newval)->{
valueLabel.setText(String.format("%.2f", newval));
//if the lock button has been sleected then change all the sliders
//so that they are the same value as this slide (unless the class is disabled)
if (toggelButton.isSelected()) {
for (int i=0; i<classPanes.length; i++) {
if (classPanes[i].enable.isSelected() && i!=index) {
classPanes[i].slider.setValue(newval.doubleValue());
}
};
}
notifySettingsListeners();
});
slider.setMin(0.);
slider.setMax(1.);
PamHBox.setHgrow(slider, Priority.ALWAYS);
valueLabel = new Label();
valueLabel.setMinWidth(30);
valueLabel.setText(String.format("%.2f", slider.getValue()));
this.getChildren().addAll(enable, slider, valueLabel);
} }
} }
@Override @Override
public DLPredictionFilterParams getParams(DLPredictionFilterParams currParams) { public DLPredictionFilterParams getParams(DLPredictionFilterParams currParams) {
// TODO Auto-generated method stub
for (int i=0; i<classPanes.length ; i++) {
currParams.classSelect[i] = classPanes[i].enable.isSelected();
currParams.minClassPredicton[i] = classPanes[i].slider.getValue();
}
return currParams; return currParams;
} }
@Override @Override
public void setParams(DLPredictionFilterParams input) { public void setParams(DLPredictionFilterParams input) {
//set the parameters. Note that class numbers should have been checked already.
setClassPane(input);
} }
private void setClassPane(DLPredictionFilterParams input) {
DLClassName[] classNames = predicitonFilter.getDLControl().getDLModel().getClassNames();
contentPane.getChildren().clear();
classPanes = new ClassDataSelector[input.classSelect.length];
ClassDataSelector classPane;
for (int i=0; i<input.classSelect.length ; i++) {
classPane = new ClassDataSelector(classNames[i].className, i);
classPanes[i] = classPane;
contentPane.getChildren().add(classPane);
classPane.enable.setSelected(input.classSelect[i]);
classPane.slider.setValue(input.minClassPredicton[i]);
if (i==input.classSelect.length-1) {
classPane.slider.setShowTickLabels(true);
}
}
}
// /**
// * Check the class numbers are correct
// * @param input
// */
// private void checkSpeciesClassNumbers(DLPredictionFilterParams input) {
// this.predicitonFilter.getSpeciesClassList();
//
// }
@Override @Override
public String getName() { public String getName() {
return "Deep learning prediciton filter"; return "Deep learning prediciton filter";
@ -71,7 +199,7 @@ public class DLPredictonPane extends DynamicSettingsPane<DLPredictionFilterParam
@Override @Override
public void paneInitialized() { public void paneInitialized() {
// TODO Auto-generated method stub // TODO Auto-generated method stub
} }
} }

View File

@ -1,28 +1,30 @@
package rawDeepLearningClassifier.dataSelector; package rawDeepLearningClassifier.dataSelector;
import javafx.scene.Node; import javafx.scene.Node;
import javafx.scene.control.CheckBox; import pamViewFX.fxNodes.PamBorderPane;
import javafx.scene.control.Label;
import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.PamSpinner;
import pamViewFX.fxNodes.PamVBox;
import pamViewFX.fxSettingsPanes.DynamicSettingsPane; import pamViewFX.fxSettingsPanes.DynamicSettingsPane;
/** /**
* JavaFX pane for the deep learning data selector. This simply selects the rype * JavaFX pane for the deep learning data selector. This simply selects the rype
* of filter to use and sets that as the controls. * of filter to use and sets that as the controls.
* <p>
* Note that at the moment this only implements one type of data filter and so
* essentially all controls etc. for changing filters are invisible to the user.
* *
* @author Jamie Macaulay * @author Jamie Macaulay
*/ */
public class DLSelectPaneFX extends DynamicSettingsPane<Boolean>{ public class DLSelectPaneFX extends DynamicSettingsPane<Boolean>{
private PamVBox mainPane; private PamBorderPane mainPane;
/** /**
* Refrence to the deep learning data selector. * Reference to the deep learning data selector.
*/ */
private DLDataSelector dlDataSelector; private DLDataSelector dlDataSelector;
/**
* The current index selected by the user - not in the params.
*/
private int currentIndex = 0; private int currentIndex = 0;
public DLSelectPaneFX(DLDataSelector dlDataSelector) { public DLSelectPaneFX(DLDataSelector dlDataSelector) {
@ -38,23 +40,47 @@ public class DLSelectPaneFX extends DynamicSettingsPane<Boolean>{
} }
private void createPane() { private void createPane() {
mainPane = new PamVBox(); mainPane = new PamBorderPane();
mainPane.setSpacing(5);
//need to add a settings listener to the filter panes to pass on any notification this settings listener.
for (int i=0; i<dlDataSelector.getDataSelectors().size(); i++) {
dlDataSelector.getDataSelectors().get(currentIndex).getSettingsPane().addSettingsListener(()->{
//notify any listeners to this pane that a filter pane has changed.
notifySettingsListeners();
});
}
} }
@Override @Override
public Boolean getParams(Boolean currParams) { public Boolean getParams(Boolean input) {
dlDataSelector.getDataSelectors().get(currentIndex).getSettingsPane().getParams(null); // System.out.println("Get params DL data selector!");
DLDataSelectorParams currParams = dlDataSelector.getParams();
//TODO - maybe should grab settings from all filters or just the selected one?
currParams.dataSelectorParams[currentIndex] = dlDataSelector.getDataSelectors().get(currentIndex).getSettingsPane().getParams(currParams.dataSelectorParams[currentIndex]);
return currParams; dlDataSelector.setParams(currParams);
return true;
} }
@Override @Override
public void setParams(Boolean input) { public void setParams(Boolean input) {
dlDataSelector.getDataSelectors().get(currentIndex).getSettingsPane().getParams(null); DLDataSelectorParams currParams = dlDataSelector.getParams();
this.currentIndex = currParams.dataSelectorIndex;
dlDataSelector.getDataSelectors().get(currentIndex).getSettingsPane().setParams(currParams.dataSelectorParams[currentIndex]);
setDataFilterPane(currentIndex);
}
private void setDataFilterPane(int index) {
DLDataFilter dlFilter = dlDataSelector.getDataSelectors().get(index);
mainPane.setCenter(dlFilter.getSettingsPane().getContentNode());
} }
@Override @Override
@ -64,7 +90,7 @@ public class DLSelectPaneFX extends DynamicSettingsPane<Boolean>{
@Override @Override
public Node getContentNode() { public Node getContentNode() {
return new Label("Hello DL data selector"); return mainPane;
} }
@Override @Override