Working on new symbol options for deep learning and sud file options in SoundAcquisition GUI

This commit is contained in:
Jamie Mac 2024-07-08 16:26:51 +01:00
parent a0399fce84
commit 9628b69f3b
17 changed files with 665 additions and 83 deletions

View File

@ -180,7 +180,6 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
this.acquisitionDialog = acquisitionDialog; this.acquisitionDialog = acquisitionDialog;
return getDialogPanel(); return getDialogPanel();
} }
@ -197,7 +196,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
protected JPanel createDaqDialogPanel() { protected JPanel createDaqDialogPanel() {
JPanel p = new JPanel(); PamPanel p = new PamPanel();
p.setBorder(new TitledBorder("Select sound file")); p.setBorder(new TitledBorder("Select sound file"));
GridBagLayout layout = new GridBagLayout(); GridBagLayout layout = new GridBagLayout();
layout.columnWidths = new int[]{100, 100, 10}; layout.columnWidths = new int[]{100, 100, 10};
@ -252,6 +251,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe
// constraints.gridwidth = 2; // constraints.gridwidth = 2;
// addComponent(p, fileDateText = new JTextField(), constraints); // addComponent(p, fileDateText = new JTextField(), constraints);
// fileDateText.setEnabled(false); // fileDateText.setEnabled(false);
return p; return p;
} }

View File

@ -32,6 +32,7 @@ import javafx.application.Platform;
import pamguard.GlobalArguments; import pamguard.GlobalArguments;
import Acquisition.pamAudio.PamAudioFileManager; import Acquisition.pamAudio.PamAudioFileManager;
import Acquisition.pamAudio.PamAudioFileFilter; import Acquisition.pamAudio.PamAudioFileFilter;
import Acquisition.pamAudio.PamAudioFileLoader;
import Acquisition.pamAudio.PamAudioSystem; import Acquisition.pamAudio.PamAudioSystem;
import PamController.DataInputStore; import PamController.DataInputStore;
import PamController.InputStoreInfo; import PamController.InputStoreInfo;
@ -93,6 +94,12 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
*/ */
private JTextField skipSecondsField; private JTextField skipSecondsField;
/**
* Panel which shows bespoke settings for certain audio loaders. Contains nothing
* if the audio loader has no settings or no file is selected.
*/
protected PamPanel audioLoaderHolder;
@Override @Override
public boolean runFileAnalysis() { public boolean runFileAnalysis() {
currentFileStart = System.currentTimeMillis(); currentFileStart = System.currentTimeMillis();
@ -170,6 +177,8 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
} }
} }
@Override @Override
protected JPanel createDaqDialogPanel() { protected JPanel createDaqDialogPanel() {
JPanel p = new JPanel(); JPanel p = new JPanel();
@ -228,6 +237,7 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
constraints.gridwidth = 2; constraints.gridwidth = 2;
constraints.fill = GridBagConstraints.NONE; constraints.fill = GridBagConstraints.NONE;
constraints.anchor = GridBagConstraints.WEST; constraints.anchor = GridBagConstraints.WEST;
addComponent(p, mergeFiles = new JCheckBox("Merge contiguous files"), constraints); addComponent(p, mergeFiles = new JCheckBox("Merge contiguous files"), constraints);
if (PamController.getInstance().getRunMode() == PamController.RUN_PAMVIEW) { if (PamController.getInstance().getRunMode() == PamController.RUN_PAMVIEW) {
constraints.gridx+=2; constraints.gridx+=2;
@ -249,6 +259,16 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
constraints.anchor = GridBagConstraints.EAST; constraints.anchor = GridBagConstraints.EAST;
// } // }
//panel to show bespoke settings for certain audio loaders.
constraints.gridx = 0;
constraints.gridy++;
constraints.gridwidth = 3;
addComponent(p, audioLoaderHolder = new PamPanel(), constraints);
GridBagLayout layout2 = new GridBagLayout();
audioLoaderHolder.setLayout(layout2);
return p; return p;
} }
@ -525,10 +545,14 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
List<WavFileType> asList = allFiles; List<WavFileType> asList = allFiles;
setSelectedFileTypes(acquisitionControl.soundFileTypes.getUsedTypes(allFiles)); setSelectedFileTypes(acquisitionControl.soundFileTypes.getUsedTypes(allFiles));
//set the date of the first file.
setFileDateText(); setFileDateText();
//set any bespoke options for the files to be laoded.
setFileOptionPanel();
// also open up the first file and get the sample rate and number of channels from it // also open up the first file and get the sample rate and number of channels from it
// and set these // and set these
File file = getCurrentFile(); File file = getCurrentFile();
if (file == null) return; if (file == null) return;
AudioInputStream audioStream; AudioInputStream audioStream;
@ -573,6 +597,37 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D
return nChannels; return nChannels;
} }
/**
* Set bespoke options for certain file types.
*/
public void setFileOptionPanel() {
getDialogPanel(); // make sure panel is created
audioLoaderHolder.removeAll();
if (allFiles.size() > 0) {
//Get all the audio file laoders that will be used for this list of files. Usually
//just one but possible that there can be mixed files.
ArrayList<PamAudioFileLoader> loaders = PamAudioFileManager.getInstance().getAudioFileLoaders(allFiles);
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridx = 0;
constraints.gridy = 0;
for (PamAudioFileLoader loader : loaders) {
if (loader.getSettingsPane()!=null) {
// System.out.println("ADD AUDIO PANEL: " +loader.getSettingsPane().getAudioLoaderPanel());
//gridbag layout
addComponent(audioLoaderHolder, loader.getSettingsPane().getAudioLoaderPanel(), constraints);
constraints.gridy++;
}
}
}
}
/**
* Show the date of the first file in the dialog.
*/
public void setFileDateText() { public void setFileDateText() {
if (allFiles.size() > 0) { if (allFiles.size() > 0) {
long fileTime = getFileStartTime(getCurrentFile()); long fileTime = getFileStartTime(getCurrentFile());

View File

@ -48,7 +48,7 @@ import pamViewFX.fxNodes.PamProgressBar;
import pamViewFX.fxNodes.PamVBox; import pamViewFX.fxNodes.PamVBox;
/** /**
* Pane for the folder input of the sound acquisition. * JavaFX pane for the folder input of the sound acquisition.
* *
* @author Jamie Macaulay * @author Jamie Macaulay
* *

View File

@ -178,7 +178,7 @@ public class OfflineWavFileServer extends OfflineFileServer<FileDataMapPoint> {
return false; return false;
} }
PamAudioFileLoader audioFile = PamAudioFileManager.getInstance().getAudioLoader(mapPoint.getSoundFile()); PamAudioFileLoader audioFile = PamAudioFileManager.getInstance().getAudioFileLoader(mapPoint.getSoundFile());
if (audioFile==null) { if (audioFile==null) {
System.err.println("OfflineWavFileServer: could not find audio loader for mapped sound file: " + mapPoint.getSoundFile()); System.err.println("OfflineWavFileServer: could not find audio loader for mapped sound file: " + mapPoint.getSoundFile());

View File

@ -233,4 +233,10 @@ public class FlacAudioFile implements PamAudioFileLoader {
return (end.equals(".flac")); return (end.equals(".flac"));
} }
@Override
public PamAudioSettingsPane getSettingsPane() {
// TODO Auto-generated method stub
return null;
}
} }

View File

@ -48,5 +48,11 @@ public interface PamAudioFileLoader {
public boolean loadAudioData(OfflineFileServer offlineFileServer, PamDataBlock dataBlock, public boolean loadAudioData(OfflineFileServer offlineFileServer, PamDataBlock dataBlock,
OfflineDataLoadInfo offlineDataLoadInfo, ViewLoadObserver loadObserver); OfflineDataLoadInfo offlineDataLoadInfo, ViewLoadObserver loadObserver);
/**
* Get a settings pane for the audio loader
* @return settings pane for audio loader - can be null.
*/
public PamAudioSettingsPane getSettingsPane();
} }

View File

@ -56,7 +56,7 @@ public class PamAudioFileManager {
* @param soundFile - the sound file * @param soundFile - the sound file
* @return the audio file loader. * @return the audio file loader.
*/ */
public PamAudioFileLoader getAudioLoader(File soundFile) { public PamAudioFileLoader getAudioFileLoader(File soundFile) {
for (int i = 0; i < pamAudioFileTypes.size(); i++) { for (int i = 0; i < pamAudioFileTypes.size(); i++) {
if (isExtension(soundFile, pamAudioFileTypes.get(i))) { if (isExtension(soundFile, pamAudioFileTypes.get(i))) {
return pamAudioFileTypes.get(i); return pamAudioFileTypes.get(i);
@ -170,6 +170,23 @@ public class PamAudioFileManager {
return this.pamAudioFileTypes; return this.pamAudioFileTypes;
} }
/**
* Get the loaders which are needed to open a list of files
* @param files - the files to find audio loaders for.
* @return a list of the audio loaders required for the file list
*/
public ArrayList<PamAudioFileLoader> getAudioFileLoaders(ArrayList<? extends File> files) {
ArrayList<PamAudioFileLoader> audioLoaders = new ArrayList<PamAudioFileLoader>();
PamAudioFileLoader loader;
for (int i=0; i<files.size(); i++) {
loader = getAudioFileLoader(files.get(i));
if (!audioLoaders.contains(loader)) {
audioLoaders.add(loader);
}
}
return audioLoaders;
}
/** /**
* Get the default file loader for raw files. * Get the default file loader for raw files.
* @return the default file loader for raw files. * @return the default file loader for raw files.

View File

@ -0,0 +1,21 @@
package Acquisition.pamAudio;
import PamView.panel.PamPanel;
import javafx.scene.layout.Pane;
public interface PamAudioSettingsPane {
/**
* Get the JavaFX pane for loading audio.
* @return
*/
public Pane getAudioLoaderPane();
/**
* Get the swing audio loader pane.
* @return
*/
public PamPanel getAudioLoaderPanel();
}

View File

@ -12,6 +12,7 @@ import javax.swing.SwingUtilities;
import org.pamguard.x3.sud.ChunkHeader; import org.pamguard.x3.sud.ChunkHeader;
import org.pamguard.x3.sud.SudMapListener; import org.pamguard.x3.sud.SudMapListener;
import Acquisition.sud.SudAudioSettingsPane;
import PamController.PamController; import PamController.PamController;
import PamUtils.worker.PamWorkProgressMessage; import PamUtils.worker.PamWorkProgressMessage;
import PamUtils.worker.PamWorkWrapper; import PamUtils.worker.PamWorkWrapper;
@ -37,6 +38,11 @@ public class SudAudioFile extends WavAudioFile {
private volatile PamWorker<AudioInputStream> worker; private volatile PamWorker<AudioInputStream> worker;
private volatile SudMapWorker sudMapWorker; private volatile SudMapWorker sudMapWorker;
/**
* Settings pane to allow users to set some additional options.
*/
private SudAudioSettingsPane sudAudioSettingsPane;
public SudAudioFile() { public SudAudioFile() {
super(); super();
fileExtensions = new ArrayList<String>(Arrays.asList(new String[] { ".sud" })); fileExtensions = new ArrayList<String>(Arrays.asList(new String[] { ".sud" }));
@ -217,4 +223,12 @@ public class SudAudioFile extends WavAudioFile {
} }
@Override
public PamAudioSettingsPane getSettingsPane() {
if (sudAudioSettingsPane==null) {
sudAudioSettingsPane = new SudAudioSettingsPane(this);
}
return sudAudioSettingsPane;
}
} }

View File

@ -296,5 +296,11 @@ public class WavAudioFile implements PamAudioFileLoader {
} }
} }
@Override
public PamAudioSettingsPane getSettingsPane() {
// TODO Auto-generated method stub
return null;
}
} }

View File

@ -0,0 +1,41 @@
package Acquisition.sud;
import javax.swing.JLabel;
import Acquisition.pamAudio.PamAudioSettingsPane;
import Acquisition.pamAudio.SudAudioFile;
import PamView.panel.PamPanel;
import javafx.scene.layout.Pane;
public class SudAudioSettingsPane implements PamAudioSettingsPane {
private SudAudioFile sudAudioFile;
private PamPanel sudAudioPanel;
public SudAudioSettingsPane(SudAudioFile sudAudioFile) {
this.sudAudioFile=sudAudioFile;
}
@Override
public Pane getAudioLoaderPane() {
// TODO Auto-generated method stub
return null;
}
@Override
public PamPanel getAudioLoaderPanel() {
if (sudAudioPanel==null) {
createSudAudioPanel();
}
return sudAudioPanel;
}
private void createSudAudioPanel() {
sudAudioPanel = new PamPanel();
sudAudioPanel.add(new JLabel("Hello"));
}
}

View File

@ -564,6 +564,55 @@ public class PamArrayUtils {
return index; return index;
} }
/**
* Get the index of the maximum value in an array
* @param arr - the array to find the position of the maximum value.
* m value of.
* @return the index of the maximum value
*/
public static int maxPos(float[] arr) {
double max = Double.NEGATIVE_INFINITY;
int index = -1;
int count = 0;
for(float cur: arr) {
if (cur>max) {
index = count;
max=cur;
}
count++;
}
return index;
}
/**
* Get the index of the maximum value within a 2D matrix
* @param arr - the array to find the position of the maximum value.
* m value of.
* @return the index i and j of the maximum value
*/
public static int[] maxPos(float[][] arr) {
float max = Float.NEGATIVE_INFINITY;
int[] index = new int[] {-1,-1};
// int count = 0;
float cur;
for(int i=0; i<arr.length; i++) {
for(int j=0; j<arr.length; j++) {
cur = arr[i][j];
if (cur>max) {
index[0]=i;
index[1]=j;
max=cur;
}
// count++;
}
}
return index;
}
/** /**
* Get the minimum index of an array * Get the minimum index of an array
* @param arr - the array to find the position of the maximum value. * @param arr - the array to find the position of the maximum value.

View File

@ -244,7 +244,6 @@ public class ColourArray implements Cloneable, Serializable{
colors[4]=Color.web("#0000ff"); colors[4]=Color.web("#0000ff");
colors[5]=Color.web("#ff00ff"); colors[5]=Color.web("#ff00ff");
colors[6]=Color.web("#ff0000"); colors[6]=Color.web("#ff0000");
return colors; return colors;
case PATRIOTIC: case PATRIOTIC:
colors=new Color[3]; colors=new Color[3];

View File

@ -632,8 +632,7 @@ public class PamUtilsFX {
* @param color - the color. * @param color - the color.
* @return the color. * @return the color.
*/ */
public static String toRGBCode( Color color ) public static String toRGBCode( Color color ){
{
return String.format( "#%02X%02X%02X", return String.format( "#%02X%02X%02X",
(int)( color.getRed() * 255 ), (int)( color.getRed() * 255 ),
(int)( color.getGreen() * 255 ), (int)( color.getGreen() * 255 ),
@ -641,4 +640,29 @@ public class PamUtilsFX {
} }
/**
* Convert a colour to an int.
* @param c - the colour to change.
* @return the int representation of the colour
*/
public static int colorToInt(Color c) {
int r = (int) Math.round(c.getRed() * 255);
int g = (int) Math.round(c.getGreen() * 255);
int b = (int) Math.round(c.getBlue() * 255);
return (r << 16) | (g << 8) | b;
}
/**
* Convert an int encoded with a colour to a Color object.
* @param value - the int to convert to colour
* @return the Color object for the int
*/
public static Color intToColor(int value) {
int r = (value >>> 16) & 0xFF;
int g = (value >>> 8) & 0xFF;
int b = value & 0xFF;
return Color.rgb(r,g,b);
}
} }

View File

@ -2,6 +2,7 @@ package rawDeepLearningClassifier.dataPlotFX;
import java.awt.Color; import java.awt.Color;
import PamUtils.PamArrayUtils;
import PamView.GeneralProjector; import PamView.GeneralProjector;
import PamView.PamSymbolType; import PamView.PamSymbolType;
import PamView.symbol.PamSymbolChooser; import PamView.symbol.PamSymbolChooser;
@ -20,7 +21,8 @@ import rawDeepLearningClassifier.logging.DLAnnotationType;
/** /**
* The DL symbol modifier. Colours symbols by prediction. * The DL symbol modifier. Colours symbols by eother the vlaue of the prediction by a user selected class
* or by the class with the highest prediction value.
* *
* @author Jamie Macaulay. * @author Jamie Macaulay.
* *
@ -94,7 +96,70 @@ public class DLSymbolModifier extends SymbolModifier {
return null; return null;
} }
//System.out.println("Class index: " + dlSymbolOptions.classIndex);
//modify the default symbol
if (dlSymbolOptions.colTypeSelection == DLSymbolModifierParams.PREDICITON_COL) {
getSymbolDataPred(annotation);
}
else if (dlSymbolOptions.colTypeSelection == DLSymbolModifierParams.CLASS_COL) {
getSymbolDataClass(annotation);
}
return symbolData;
}
/**
* Get symbol data for colouring by the species class with the maximum prediction
* @param annotation - the annotation
* @return symbol data for colouring by class maximum.
*/
private SymbolData getSymbolDataClass(DLAnnotation annotation ) {
boolean passed = false;
int colIndex = -1;
float[][] results = new float[ annotation.getModelResults().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: annotation.getModelResults()) {
if (modelResult.isBinaryClassification()) passed = true;
results[i] = modelResult.getPrediction();
i++;
}
int[] indexBest = PamArrayUtils.maxPos(results);
if (passed || !dlSymbolOptions.showOnlyBinary) {
//work out the class colour...
javafx.scene.paint.Color color = PamUtilsFX.intToColor(dlSymbolOptions.classColors[indexBest[1]]);
Color colorAWT = PamUtilsFX.fxToAWTColor(color);
symbolData.setFillColor(colorAWT);
symbolData.setLineColor(colorAWT);
return symbolData;
}
else {
//has data but we have only show binary option selected.
return null;
}
}
/**
* Get symbol data for colouring by the prediction value for a selected species class.
* @param annotation - the annotation
* @return symbol data for colouring by prediction value for a selected species class.
*/
private SymbolData getSymbolDataPred(DLAnnotation annotation ) {
if (dlSymbolOptions.classIndex<0) { if (dlSymbolOptions.classIndex<0) {
dlSymbolOptions.classIndex=0; dlSymbolOptions.classIndex=0;

View File

@ -1,7 +1,10 @@
package rawDeepLearningClassifier.dataPlotFX; package rawDeepLearningClassifier.dataPlotFX;
import PamView.symbol.modifier.SymbolModifierParams; import PamView.symbol.modifier.SymbolModifierParams;
import javafx.scene.paint.Color;
import pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType; import pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType;
import pamViewFX.fxNodes.utilsFX.PamUtilsFX;
/** /**
* Parameters for colouring symbols by deep learning probability. * Parameters for colouring symbols by deep learning probability.
@ -11,10 +14,27 @@ import pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType;
*/ */
public class DLSymbolModifierParams extends SymbolModifierParams { public class DLSymbolModifierParams extends SymbolModifierParams {
public DLSymbolModifierParams() {
setDefaultClassColors(32);
}
/** /**
* *
*/ */
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 3L;
public static final int PREDICITON_COL = 0;
public static final int CLASS_COL = 1;
/**
* The way to colour the predictions.
*/
public int colTypeSelection = PREDICITON_COL;
/****Prediction colours****/
/** /**
* The colour limits. * The colour limits.
@ -27,16 +47,72 @@ public class DLSymbolModifierParams extends SymbolModifierParams {
*/ */
public int classIndex = 0; public int classIndex = 0;
/*******Class colours******/
/** /**
* Show only binary. * The current colours for each
*/ */
public boolean showOnlyBinary = false; public int[] classColors = new int[32];
/**
* The currently selected class for colour picker- just so the user sees the same selection.
*/
public int classIndex2 = 0;
/** /**
* The colour array to show. * The colour array to show.
*/ */
public ColourArrayType colArray = ColourArrayType.FIRE; public ColourArrayType colArray = ColourArrayType.FIRE;
/***************************/
/**
* Show only detections which have passed a decision threshold.
*/
public boolean showOnlyBinary = false;
/**
* Set the default colours.
* @param num - the number of colours to set.
*/
public void setDefaultClassColors(int num) {
if (classColors==null || classColors.length<num) {
classColors = new int[32];
}
//run through default colours
for (int i=0; i<classColors.length; i++) {
switch (i%8) {
case 0:
classColors[i]=PamUtilsFX.colorToInt(Color.RED);
break;
case 1:
classColors[i]=PamUtilsFX.colorToInt(Color.GREEN);
break;
case 2:
classColors[i]=PamUtilsFX.colorToInt(Color.BLUE);
break;
case 3:
classColors[i]=PamUtilsFX.colorToInt(Color.CYAN);
break;
case 4:
classColors[i]=PamUtilsFX.colorToInt(Color.MAGENTA);
break;
case 5:
classColors[i]=PamUtilsFX.colorToInt(Color.YELLOW);
break;
case 6:
classColors[i]=PamUtilsFX.colorToInt(Color.ORANGE);
break;
case 7:
classColors[i]=PamUtilsFX.colorToInt(Color.PURPLE);
break;
}
}
}
@Override @Override
protected DLSymbolModifierParams clone() { protected DLSymbolModifierParams clone() {

View File

@ -1,20 +1,29 @@
package rawDeepLearningClassifier.dataPlotFX; package rawDeepLearningClassifier.dataPlotFX;
import org.controlsfx.control.SegmentedButton;
import PamView.symbol.StandardSymbolOptions; import PamView.symbol.StandardSymbolOptions;
import PamView.symbol.modifier.SymbolModifier; import PamView.symbol.modifier.SymbolModifier;
import PamView.symbol.modifier.SymbolModifierParams;
import javafx.geometry.Insets; import javafx.geometry.Insets;
import javafx.geometry.Orientation; import javafx.geometry.Orientation;
import javafx.geometry.Pos; import javafx.geometry.Pos;
import javafx.scene.control.CheckBox; import javafx.scene.control.CheckBox;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.ComboBox; import javafx.scene.control.ComboBox;
import javafx.scene.control.Label; import javafx.scene.control.Label;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane; import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import pamViewFX.fxNodes.PamBorderPane;
import pamViewFX.fxNodes.PamHBox; import pamViewFX.fxNodes.PamHBox;
import pamViewFX.fxNodes.PamVBox; import pamViewFX.fxNodes.PamVBox;
import pamViewFX.fxNodes.comboBox.ColorComboBox; import pamViewFX.fxNodes.comboBox.ColorComboBox;
import pamViewFX.fxNodes.sliders.ColourRangeSlider; import pamViewFX.fxNodes.sliders.ColourRangeSlider;
import pamViewFX.fxNodes.utilsFX.ColourArray; import pamViewFX.fxNodes.utilsFX.ColourArray;
import pamViewFX.fxNodes.utilsFX.PamUtilsFX;
import pamViewFX.symbol.StandardSymbolModifierPane; import pamViewFX.symbol.StandardSymbolModifierPane;
import rawDeepLearningClassifier.dlClassification.DLClassName; import rawDeepLearningClassifier.dlClassification.DLClassName;
@ -25,6 +34,8 @@ import rawDeepLearningClassifier.dlClassification.DLClassName;
public class DLSymbolOptionPane extends StandardSymbolModifierPane { public class DLSymbolOptionPane extends StandardSymbolModifierPane {
private static final double CLASS_NAME_BOX_WIDTH = 130;
/** /**
* The colour range slider for colouring probabilities. * The colour range slider for colouring probabilities.
*/ */
@ -42,21 +53,139 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
/** /**
* Combo box which allows a user to select colour * Color picker which allows a user to select the gradient for colouring predictions
*/ */
private ColorComboBox colourBox; private ColorComboBox colourBox;
/**
* Color picker which allows a user to select colour for each class.
*/
private ColorPicker colourPicker;
private boolean initialised=true; private boolean initialised=true;
private DLSymbolModifier dlSymbolModifier; private DLSymbolModifier dlSymbolModifier;
private ComboBox<String> classNameBox2;
/**
* Pane which holds controls for changing the colour based on prediciton value
*/
private Pane probPane;
/**
* Pane which holds controls for changing the colour based on the highest prediction value
*/
private Pane classPane;
private PamBorderPane holder;
/**
* Button to select how to colour.
*/
private ToggleButton b1, b2;
public DLSymbolOptionPane(SymbolModifier symbolModifer) { public DLSymbolOptionPane(SymbolModifier symbolModifer) {
super(symbolModifer, Orientation.HORIZONTAL, true, 0); super(symbolModifer, Orientation.HORIZONTAL, true, 0);
this.setBottom(createProbPane());
probPane = createProbPane();
classPane = createClassPane();
classPane.setPadding(new Insets(0,0,5,0));
b1 = new ToggleButton("Prediction");
b1.setPrefWidth(80);
b1.setStyle("-fx-border-radius: 5 0 0 5; -fx-background-radius: 5 0 0 5;");
b2 = new ToggleButton("Class");
b2.setPrefWidth(80);
b1.setOnAction((a)->{
setSettingsPane();
//change the colour of the colour range slider.
notifySettingsListeners();
});
b2.setStyle("-fx-border-radius: 0 5 5 0; -fx-background-radius: 0 5 5 0;");
b2.setOnAction((a)->{
setSettingsPane();
//change the colour of the colour range slider.
notifySettingsListeners();
});
SegmentedButton segmentedButton = new SegmentedButton();
segmentedButton.getButtons().addAll(b1, b2);
segmentedButton.setPadding(new Insets(5,0,5,0));
BorderPane.setAlignment(segmentedButton, Pos.CENTER);
b1.setSelected(true);
showOnlyBinary = new CheckBox("Show only binary classificaiton");
showOnlyBinary.setOnAction((action)->{
getParams();
//change the colour of the colour range slider.
notifySettingsListeners();
});
showOnlyBinary.setTooltip(new Tooltip("Colour detections only if they passed decision threshold"));
holder = new PamBorderPane();
holder.setTop(segmentedButton);
holder.setCenter(probPane);
holder.setBottom(showOnlyBinary);
this.setBottom(holder);
this.dlSymbolModifier = (DLSymbolModifier) symbolModifer; this.dlSymbolModifier = (DLSymbolModifier) symbolModifer;
initialised=true; initialised=true;
} }
private void setSettingsPane() {
if (b1.isSelected()) {
holder.setCenter(probPane);
}
if (b2.isSelected()) {
holder.setCenter(classPane);
}
}
private Pane createClassPane() {
classNameBox2 = new ComboBox<String>();
classNameBox2.setOnAction((action)->{
getParams();
//change the colour of the colour range slider.
notifySettingsListeners();
});
classNameBox2.setMaxWidth(Double.MAX_VALUE);
classNameBox2.setOnAction((action)->{
colourPicker.setValue(PamUtilsFX.intToColor(dlSymbolModifier.getSymbolModifierParams().classColors[classNameBox2.getSelectionModel().getSelectedIndex()]));
});
classNameBox2.setPrefWidth(CLASS_NAME_BOX_WIDTH);
colourPicker = new ColorPicker();
colourPicker.setPrefWidth(60);
colourPicker.setOnAction((action)->{
getParams();
notifySettingsListeners();
});
HBox.setHgrow(classNameBox, Priority.ALWAYS);
PamHBox classHolder = new PamHBox();
classHolder.setSpacing(5);
classHolder.setAlignment(Pos.CENTER_LEFT);
classHolder.getChildren().addAll(classNameBox2, colourPicker);
return classHolder;
}
private Pane createProbPane() { private Pane createProbPane() {
PamVBox holder = new PamVBox(); PamVBox holder = new PamVBox();
@ -82,6 +211,8 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
//change the colour of the colour range slider. //change the colour of the colour range slider.
notifySettingsListeners(); notifySettingsListeners();
}); });
classNameBox.setPrefWidth(CLASS_NAME_BOX_WIDTH);
colourBox = new ColorComboBox(ColorComboBox.COLOUR_ARRAY_BOX); colourBox = new ColorComboBox(ColorComboBox.COLOUR_ARRAY_BOX);
colourBox.setPrefWidth(50); colourBox.setPrefWidth(50);
@ -92,17 +223,10 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
colourRangeSlider.setColourArrayType( dlSymbolModifier.getSymbolModifierParams().colArray); colourRangeSlider.setColourArrayType( dlSymbolModifier.getSymbolModifierParams().colArray);
}); });
showOnlyBinary = new CheckBox("Show only binary classificaiton");
showOnlyBinary.setOnAction((action)->{
getParams();
//change the colour of the colour range slider.
notifySettingsListeners();
});
PamHBox classHolder = new PamHBox(); PamHBox classHolder = new PamHBox();
classHolder.setSpacing(5); classHolder.setSpacing(5);
classHolder.setAlignment(Pos.CENTER_LEFT); classHolder.setAlignment(Pos.CENTER_LEFT);
classHolder.getChildren().addAll(new Label("Show Class"), classNameBox); classHolder.getChildren().addAll(new Label("Show class"), classNameBox);
PamHBox colorHolder = new PamHBox(); PamHBox colorHolder = new PamHBox();
colorHolder.setSpacing(5); colorHolder.setSpacing(5);
@ -112,7 +236,7 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
holder.getChildren().addAll(classHolder, new Label("Probability"), colorHolder); holder.getChildren().addAll(classHolder, new Label("Probability"), colorHolder);
holder.getChildren().add(showOnlyBinary); // holder.getChildren().add(showOnlyBinary);
holder.setPadding(new Insets(5,0,5,0)); holder.setPadding(new Insets(5,0,5,0));
setParams = false; setParams = false;
@ -120,17 +244,29 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
return holder; return holder;
} }
@Override
public StandardSymbolOptions getParams(){
StandardSymbolOptions standardSymbolOptions = super.getParams();
/**
* get parameters for colouring by class.
* @param symbolOptions - the symbol options.
* @return
*/
public DLSymbolModifierParams getClassColParams(DLSymbolModifierParams symbolOptions ) {
//bit messy but works / int index = classNameBox2.getSelectionModel().getSelectedIndex()>=0 ? classNameBox2.getSelectionModel().getSelectedIndex():0;
DLSymbolModifierParams symbolOptions = dlSymbolModifier.getSymbolModifierParams();
//need to chekc this here. symbolOptions.classColors[index] = PamUtilsFX.colorToInt(colourPicker.getValue());
//checkClassNamesBox(symbolOptions);
symbolOptions.classIndex2 = classNameBox2.getSelectionModel().getSelectedIndex();
return symbolOptions;
}
/**
*
* @param symbolOptions
* @return
*/
public DLSymbolModifierParams getPredictionColParams(DLSymbolModifierParams symbolOptions ) {
symbolOptions.clims=new double[] {colourRangeSlider.getLowValue(), colourRangeSlider.getHighValue()}; symbolOptions.clims=new double[] {colourRangeSlider.getLowValue(), colourRangeSlider.getHighValue()};
@ -138,17 +274,38 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
symbolOptions.classIndex = classNameBox.getSelectionModel().getSelectedIndex(); symbolOptions.classIndex = classNameBox.getSelectionModel().getSelectedIndex();
return symbolOptions;
}
@Override
public StandardSymbolOptions getParams(){
StandardSymbolOptions standardSymbolOptions = super.getParams();
//bit messy but works
DLSymbolModifierParams symbolOptions = dlSymbolModifier.getSymbolModifierParams();
//need to check this here.
//checkClassNamesBox(symbolOptions);
if (b1.isSelected()) symbolOptions.colTypeSelection = DLSymbolModifierParams.PREDICITON_COL;
if (b2.isSelected()) symbolOptions.colTypeSelection = DLSymbolModifierParams.CLASS_COL;
//get parameters for colouring
symbolOptions = getClassColParams(symbolOptions);
//get parameters for colouring by prediction value
symbolOptions = getPredictionColParams(symbolOptions) ;
symbolOptions.showOnlyBinary = showOnlyBinary.isSelected(); symbolOptions.showOnlyBinary = showOnlyBinary.isSelected();
dlSymbolModifier.checkColourArray(); dlSymbolModifier.checkColourArray();
//System.out.println("Get params: " );
return standardSymbolOptions; return standardSymbolOptions;
} }
private void checkClassNamesBox(DLSymbolModifierParams symbolOptions) {
private int checkClassNamesBox(DLSymbolModifierParams symbolOptions, ComboBox<String> classNameBox) {
DLClassName[] classNames = dlSymbolModifier.getDLAnnotType().getDlControl().getDLModel().getClassNames(); DLClassName[] classNames = dlSymbolModifier.getDLAnnotType().getDlControl().getDLModel().getClassNames();
@ -167,8 +324,51 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
classNameBox.getItems().add("Class: " + i); classNameBox.getItems().add("Class: " + i);
} }
} }
return nClass;
}
/**
* Set parameters for controls to change the colour gradient based on prediction.
* @param symbolOptions - the symbol options
*/
private void setPredictionColParams(DLSymbolModifierParams symbolOptions) {
//now set frequency parameters
colourRangeSlider.setLowValue(symbolOptions.clims[0]);
colourRangeSlider.setHighValue(symbolOptions.clims[1]);
colourRangeSlider.setColourArrayType( symbolOptions.colArray);
int nClass = checkClassNamesBox( symbolOptions, classNameBox);
symbolOptions.classIndex = Math.min(symbolOptions.classIndex, nClass-1); symbolOptions.classIndex = Math.min(symbolOptions.classIndex, nClass-1);
classNameBox.getSelectionModel().select(Math.max(symbolOptions.classIndex, 0)); classNameBox.getSelectionModel().select(Math.max(symbolOptions.classIndex, 0));
//color box.
colourBox.setValue(symbolOptions.colArray);
}
/**
* Set parameters for controls to change the colour gradient based on prediction.
* @param symbolOptions - the symbol options
*/
private void setClassColParams(DLSymbolModifierParams symbolOptions) {
int nClass = checkClassNamesBox( symbolOptions, classNameBox2);
symbolOptions.classIndex = Math.min(symbolOptions.classIndex, nClass-1);
classNameBox2.getSelectionModel().select(Math.max(symbolOptions.classIndex2, 0));
int index = symbolOptions.classIndex2>=0? symbolOptions.classIndex2 : 0;
if (symbolOptions.classColors==null) {
symbolOptions.setDefaultClassColors(nClass);
}
//set the correct colour
colourPicker.setValue(PamUtilsFX.intToColor(symbolOptions.classColors[index]));
} }
@Override @Override
@ -180,25 +380,28 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane {
setParams = true; setParams = true;
// StandardSymbolOptions standardSymbolOptions = (StandardSymbolOptions) getSymbolModifier().getSymbolChooser().getSymbolOptions(); //get the symbool options
DLSymbolModifierParams symbolOptions = dlSymbolModifier.getSymbolModifierParams(); DLSymbolModifierParams symbolOptions = dlSymbolModifier.getSymbolModifierParams();
//now set frequency parameters
colourRangeSlider.setLowValue(symbolOptions.clims[0]);
colourRangeSlider.setHighValue(symbolOptions.clims[1]);
colourRangeSlider.setColourArrayType( symbolOptions.colArray);
// b1.setSelected(false);
// b2.setSelected(false);
if (symbolOptions.colTypeSelection == DLSymbolModifierParams.PREDICITON_COL) b1.setSelected(true);
if (symbolOptions.colTypeSelection == DLSymbolModifierParams.PREDICITON_COL) b2.setSelected(true);
//set the combo box class types. setSettingsPane();
checkClassNamesBox( symbolOptions);
symbolOptions.colTypeSelection = b1.isSelected() ? DLSymbolModifierParams.PREDICITON_COL : DLSymbolModifierParams.CLASS_COL;
//color box. //set the parameters for colouring by prediction
colourBox.setValue(symbolOptions.colArray); setPredictionColParams(symbolOptions);
//set the class colour parameters
setClassColParams(symbolOptions);
//set the selected. //set the selected.
showOnlyBinary.setSelected(symbolOptions.showOnlyBinary); showOnlyBinary.setSelected(symbolOptions.showOnlyBinary);
setParams = false; setParams = false;
} }