diff --git a/src/Acquisition/FileInputSystem.java b/src/Acquisition/FileInputSystem.java index 9b99ad3b..f3988d61 100644 --- a/src/Acquisition/FileInputSystem.java +++ b/src/Acquisition/FileInputSystem.java @@ -181,7 +181,6 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe this.acquisitionDialog = acquisitionDialog; - return getDialogPanel(); } @@ -198,7 +197,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe protected JPanel createDaqDialogPanel() { - JPanel p = new JPanel(); + PamPanel p = new PamPanel(); p.setBorder(new TitledBorder("Select sound file")); GridBagLayout layout = new GridBagLayout(); layout.columnWidths = new int[]{100, 100, 10}; @@ -253,6 +252,7 @@ public class FileInputSystem extends DaqSystem implements ActionListener, PamSe // constraints.gridwidth = 2; // addComponent(p, fileDateText = new JTextField(), constraints); // fileDateText.setEnabled(false); + return p; } diff --git a/src/Acquisition/FolderInputSystem.java b/src/Acquisition/FolderInputSystem.java index c8c2d872..fab8e961 100644 --- a/src/Acquisition/FolderInputSystem.java +++ b/src/Acquisition/FolderInputSystem.java @@ -32,6 +32,7 @@ import javafx.application.Platform; import pamguard.GlobalArguments; import Acquisition.pamAudio.PamAudioFileManager; import Acquisition.pamAudio.PamAudioFileFilter; +import Acquisition.pamAudio.PamAudioFileLoader; import Acquisition.pamAudio.PamAudioSystem; import PamController.DataInputStore; import PamController.InputStoreInfo; @@ -92,6 +93,12 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D * Text field for skipping initial few seconds of a file. */ 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 public boolean runFileAnalysis() { @@ -170,6 +177,8 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D } } + + @Override protected JPanel createDaqDialogPanel() { JPanel p = new JPanel(); @@ -228,6 +237,7 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D constraints.gridwidth = 2; constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.WEST; + addComponent(p, mergeFiles = new JCheckBox("Merge contiguous files"), constraints); if (PamController.getInstance().getRunMode() == PamController.RUN_PAMVIEW) { constraints.gridx+=2; @@ -236,18 +246,28 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D checkFiles.addActionListener(new CheckFiles()); } -// if (SMRUEnable.isEnable()) { + // if (SMRUEnable.isEnable()) { // no reason to hide this option from users. - constraints.gridy++; - constraints.gridx = 0; - constraints.gridwidth = 1; - addComponent(p, new JLabel("Skip initial :"), constraints); - constraints.gridx++; - addComponent(p, skipSecondsField = new JTextField(4), constraints); - constraints.gridx++; - addComponent(p, new JLabel("seconds"), constraints); - constraints.anchor = GridBagConstraints.EAST; -// } + constraints.gridy++; + constraints.gridx = 0; + constraints.gridwidth = 1; + addComponent(p, new JLabel("Skip initial :"), constraints); + constraints.gridx++; + addComponent(p, skipSecondsField = new JTextField(4), constraints); + constraints.gridx++; + addComponent(p, new JLabel("seconds"), constraints); + 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; } @@ -525,10 +545,14 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D List asList = allFiles; setSelectedFileTypes(acquisitionControl.soundFileTypes.getUsedTypes(allFiles)); + //set the date of the first file. 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 // and set these - File file = getCurrentFile(); if (file == null) return; AudioInputStream audioStream; @@ -558,7 +582,7 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D /****FX GUI stuff****/ if (folderInputPane!=null) { Platform.runLater(()->{ - folderInputPane.newFileList(fileListData); + folderInputPane.newFileList(fileListData); }); } } @@ -572,7 +596,38 @@ public class FolderInputSystem extends FileInputSystem implements PamSettings, D protected int fudgeNumChannels(int 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 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() { if (allFiles.size() > 0) { long fileTime = getFileStartTime(getCurrentFile()); diff --git a/src/Acquisition/layoutFX/FolderInputPane.java b/src/Acquisition/layoutFX/FolderInputPane.java index cf0b0e3e..48e7cb16 100644 --- a/src/Acquisition/layoutFX/FolderInputPane.java +++ b/src/Acquisition/layoutFX/FolderInputPane.java @@ -48,7 +48,7 @@ import pamViewFX.fxNodes.PamProgressBar; 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 * diff --git a/src/Acquisition/offlineFuncs/OfflineWavFileServer.java b/src/Acquisition/offlineFuncs/OfflineWavFileServer.java index b10b27dc..582c4bdc 100644 --- a/src/Acquisition/offlineFuncs/OfflineWavFileServer.java +++ b/src/Acquisition/offlineFuncs/OfflineWavFileServer.java @@ -178,7 +178,7 @@ public class OfflineWavFileServer extends OfflineFileServer { return false; } - PamAudioFileLoader audioFile = PamAudioFileManager.getInstance().getAudioLoader(mapPoint.getSoundFile()); + PamAudioFileLoader audioFile = PamAudioFileManager.getInstance().getAudioFileLoader(mapPoint.getSoundFile()); if (audioFile==null) { System.err.println("OfflineWavFileServer: could not find audio loader for mapped sound file: " + mapPoint.getSoundFile()); diff --git a/src/Acquisition/pamAudio/FlacAudioFile.java b/src/Acquisition/pamAudio/FlacAudioFile.java index 13d95b87..0330ef3d 100644 --- a/src/Acquisition/pamAudio/FlacAudioFile.java +++ b/src/Acquisition/pamAudio/FlacAudioFile.java @@ -233,4 +233,10 @@ public class FlacAudioFile implements PamAudioFileLoader { return (end.equals(".flac")); } + @Override + public PamAudioSettingsPane getSettingsPane() { + // TODO Auto-generated method stub + return null; + } + } diff --git a/src/Acquisition/pamAudio/PamAudioFileLoader.java b/src/Acquisition/pamAudio/PamAudioFileLoader.java index 90cc524d..077e1f6e 100644 --- a/src/Acquisition/pamAudio/PamAudioFileLoader.java +++ b/src/Acquisition/pamAudio/PamAudioFileLoader.java @@ -48,5 +48,11 @@ public interface PamAudioFileLoader { public boolean loadAudioData(OfflineFileServer offlineFileServer, PamDataBlock dataBlock, OfflineDataLoadInfo offlineDataLoadInfo, ViewLoadObserver loadObserver); + /** + * Get a settings pane for the audio loader + * @return settings pane for audio loader - can be null. + */ + public PamAudioSettingsPane getSettingsPane(); + } diff --git a/src/Acquisition/pamAudio/PamAudioFileManager.java b/src/Acquisition/pamAudio/PamAudioFileManager.java index bf13f904..3805e738 100644 --- a/src/Acquisition/pamAudio/PamAudioFileManager.java +++ b/src/Acquisition/pamAudio/PamAudioFileManager.java @@ -56,7 +56,7 @@ public class PamAudioFileManager { * @param soundFile - the sound file * @return the audio file loader. */ - public PamAudioFileLoader getAudioLoader(File soundFile) { + public PamAudioFileLoader getAudioFileLoader(File soundFile) { for (int i = 0; i < pamAudioFileTypes.size(); i++) { if (isExtension(soundFile, pamAudioFileTypes.get(i))) { return pamAudioFileTypes.get(i); @@ -169,6 +169,23 @@ public class PamAudioFileManager { public ArrayList getAudioFileLoaders() { 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 getAudioFileLoaders(ArrayList files) { + ArrayList audioLoaders = new ArrayList(); + PamAudioFileLoader loader; + for (int i=0; i worker; private volatile SudMapWorker sudMapWorker; + /** + * Settings pane to allow users to set some additional options. + */ + private SudAudioSettingsPane sudAudioSettingsPane; + public SudAudioFile() { super(); fileExtensions = new ArrayList(Arrays.asList(new String[] { ".sud" })); @@ -216,5 +222,13 @@ public class SudAudioFile extends WavAudioFile { } } + + @Override + public PamAudioSettingsPane getSettingsPane() { + if (sudAudioSettingsPane==null) { + sudAudioSettingsPane = new SudAudioSettingsPane(this); + } + return sudAudioSettingsPane; + } } \ No newline at end of file diff --git a/src/Acquisition/pamAudio/WavAudioFile.java b/src/Acquisition/pamAudio/WavAudioFile.java index e8789da0..7df37862 100644 --- a/src/Acquisition/pamAudio/WavAudioFile.java +++ b/src/Acquisition/pamAudio/WavAudioFile.java @@ -296,5 +296,11 @@ public class WavAudioFile implements PamAudioFileLoader { } } + @Override + public PamAudioSettingsPane getSettingsPane() { + // TODO Auto-generated method stub + return null; + } + } diff --git a/src/Acquisition/sud/SudAudioSettingsPane.java b/src/Acquisition/sud/SudAudioSettingsPane.java new file mode 100644 index 00000000..5d3e1e87 --- /dev/null +++ b/src/Acquisition/sud/SudAudioSettingsPane.java @@ -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")); + + } + +} diff --git a/src/PamUtils/PamArrayUtils.java b/src/PamUtils/PamArrayUtils.java index 37909be0..b6a4da62 100644 --- a/src/PamUtils/PamArrayUtils.java +++ b/src/PamUtils/PamArrayUtils.java @@ -564,6 +564,55 @@ public class PamArrayUtils { 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; imax) { + index[0]=i; + index[1]=j; + max=cur; + } + // count++; + } + } + return index; + } + /** * Get the minimum index of an array * @param arr - the array to find the position of the maximum value. diff --git a/src/pamViewFX/fxNodes/utilsFX/ColourArray.java b/src/pamViewFX/fxNodes/utilsFX/ColourArray.java index 536fa9d3..3d60628f 100644 --- a/src/pamViewFX/fxNodes/utilsFX/ColourArray.java +++ b/src/pamViewFX/fxNodes/utilsFX/ColourArray.java @@ -244,7 +244,6 @@ public class ColourArray implements Cloneable, Serializable{ colors[4]=Color.web("#0000ff"); colors[5]=Color.web("#ff00ff"); colors[6]=Color.web("#ff0000"); - return colors; case PATRIOTIC: colors=new Color[3]; @@ -254,22 +253,22 @@ public class ColourArray implements Cloneable, Serializable{ return colors; case MATLAB: colors=new Color[7]; - colors[0]= Color.color( 0, 0.4470, 0.7410); - colors[1]= Color.color(0.8500 , 0.3250 , 0.0980); - colors[2]= Color.color(0.9290 , 0.6940 , 0.1250); - colors[3]= Color.color( 0.4940 , 0.1840 , 0.5560); - colors[4]= Color.color(0.4660 , 0.6740 , 0.1880); - colors[5]= Color.color( 0.3010 , 0.7450 , 0.9330); - colors[6]= Color.color( 0.6350 , 0.0780 , 0.1840); + colors[0]= Color.color(0, 0.4470, 0.7410); + colors[1]= Color.color(0.8500, 0.3250, 0.0980); + colors[2]= Color.color(0.9290, 0.6940, 0.1250); + colors[3]= Color.color(0.4940, 0.1840, 0.5560); + colors[4]= Color.color(0.4660, 0.6740, 0.1880); + colors[5]= Color.color(0.3010, 0.7450, 0.9330); + colors[6]= Color.color(0.6350, 0.0780, 0.1840); return colors; case PARULA: colors=new Color[6]; - colors[0]= Color.color( 0.24220, 0.150400, 0.66030); - colors[1]= Color.color( 0.264700 ,0.403000 , 0.993500); - colors[2]= Color.color( 0.108500, 0.66690 , 0.873400); - colors[3]= Color.color( 0.280900 , 0.796400, 0.526600); - colors[4]= Color.color( 0.918400, 0.73080 , 0.18900); - colors[5]= Color.color( 0.9769 , 0.98390 ,0.0805000); + colors[0]= Color.color(0.24220, 0.150400, 0.66030); + colors[1]= Color.color(0.264700, 0.403000, 0.993500); + colors[2]= Color.color(0.108500, 0.66690, 0.873400); + colors[3]= Color.color(0.280900, 0.796400, 0.526600); + colors[4]= Color.color(0.918400, 0.73080, 0.18900); + colors[5]= Color.color(0.9769, 0.98390, 0.0805000); return colors; case INFERNO: return InfernoColorMap.getInfernoColourMap(); diff --git a/src/pamViewFX/fxNodes/utilsFX/PamUtilsFX.java b/src/pamViewFX/fxNodes/utilsFX/PamUtilsFX.java index a0d976b2..98efc95b 100644 --- a/src/pamViewFX/fxNodes/utilsFX/PamUtilsFX.java +++ b/src/pamViewFX/fxNodes/utilsFX/PamUtilsFX.java @@ -632,13 +632,37 @@ public class PamUtilsFX { * @param color - the color. * @return the color. */ - public static String toRGBCode( Color color ) - { - return String.format( "#%02X%02X%02X", - (int)( color.getRed() * 255 ), - (int)( color.getGreen() * 255 ), - (int)( color.getBlue() * 255 ) ); - } + public static String toRGBCode( Color color ){ + return String.format( "#%02X%02X%02X", + (int)( color.getRed() * 255 ), + (int)( color.getGreen() * 255 ), + (int)( color.getBlue() * 255 ) ); + } + + + /** + * 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); + } } diff --git a/src/rawDeepLearningClassifier/dataPlotFX/DLSymbolModifier.java b/src/rawDeepLearningClassifier/dataPlotFX/DLSymbolModifier.java index ce94692a..6e6bc752 100644 --- a/src/rawDeepLearningClassifier/dataPlotFX/DLSymbolModifier.java +++ b/src/rawDeepLearningClassifier/dataPlotFX/DLSymbolModifier.java @@ -2,6 +2,7 @@ package rawDeepLearningClassifier.dataPlotFX; import java.awt.Color; +import PamUtils.PamArrayUtils; import PamView.GeneralProjector; import PamView.PamSymbolType; 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. * @@ -94,7 +96,70 @@ public class DLSymbolModifier extends SymbolModifier { 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) { dlSymbolOptions.classIndex=0; diff --git a/src/rawDeepLearningClassifier/dataPlotFX/DLSymbolModifierParams.java b/src/rawDeepLearningClassifier/dataPlotFX/DLSymbolModifierParams.java index 718b6378..45e775a8 100644 --- a/src/rawDeepLearningClassifier/dataPlotFX/DLSymbolModifierParams.java +++ b/src/rawDeepLearningClassifier/dataPlotFX/DLSymbolModifierParams.java @@ -1,7 +1,10 @@ package rawDeepLearningClassifier.dataPlotFX; + import PamView.symbol.modifier.SymbolModifierParams; +import javafx.scene.paint.Color; import pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType; +import pamViewFX.fxNodes.utilsFX.PamUtilsFX; /** * Parameters for colouring symbols by deep learning probability. @@ -10,11 +13,28 @@ import pamViewFX.fxNodes.utilsFX.ColourArray.ColourArrayType; * */ 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. @@ -27,16 +47,72 @@ public class DLSymbolModifierParams extends SymbolModifierParams { */ 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. */ 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 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) { 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; initialised=true; } + + private void setSettingsPane() { + if (b1.isSelected()) { + holder.setCenter(probPane); + } + if (b2.isSelected()) { + holder.setCenter(classPane); + } + } + + + private Pane createClassPane() { + + classNameBox2 = new ComboBox(); + 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() { @@ -82,6 +211,8 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane { //change the colour of the colour range slider. notifySettingsListeners(); }); + classNameBox.setPrefWidth(CLASS_NAME_BOX_WIDTH); + colourBox = new ColorComboBox(ColorComboBox.COLOUR_ARRAY_BOX); colourBox.setPrefWidth(50); @@ -92,17 +223,10 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane { 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(); classHolder.setSpacing(5); 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(); colorHolder.setSpacing(5); @@ -112,7 +236,7 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane { holder.getChildren().addAll(classHolder, new Label("Probability"), colorHolder); - holder.getChildren().add(showOnlyBinary); +// holder.getChildren().add(showOnlyBinary); holder.setPadding(new Insets(5,0,5,0)); setParams = false; @@ -120,35 +244,68 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane { 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 ) { + + int index = classNameBox2.getSelectionModel().getSelectedIndex()>=0 ? classNameBox2.getSelectionModel().getSelectedIndex():0; - - //bit messy but works / - DLSymbolModifierParams symbolOptions = dlSymbolModifier.getSymbolModifierParams(); + symbolOptions.classColors[index] = PamUtilsFX.colorToInt(colourPicker.getValue()); + + symbolOptions.classIndex2 = classNameBox2.getSelectionModel().getSelectedIndex(); + + return symbolOptions; + } + + /** + * + * @param symbolOptions + * @return + */ + public DLSymbolModifierParams getPredictionColParams(DLSymbolModifierParams symbolOptions ) { - //need to chekc this here. - //checkClassNamesBox(symbolOptions); - - symbolOptions.clims=new double[] {colourRangeSlider.getLowValue(), colourRangeSlider.getHighValue()}; symbolOptions.colArray = ColourArray.getColorArrayType(this.colourBox.getSelectionModel().getSelectedItem()); 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(); dlSymbolModifier.checkColourArray(); - //System.out.println("Get params: " ); - return standardSymbolOptions; - } - private void checkClassNamesBox(DLSymbolModifierParams symbolOptions) { + + private int checkClassNamesBox(DLSymbolModifierParams symbolOptions, ComboBox classNameBox) { DLClassName[] classNames = dlSymbolModifier.getDLAnnotType().getDlControl().getDLModel().getClassNames(); @@ -167,8 +324,51 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane { 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); 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 @@ -180,24 +380,27 @@ public class DLSymbolOptionPane extends StandardSymbolModifierPane { setParams = true; -// StandardSymbolOptions standardSymbolOptions = (StandardSymbolOptions) getSymbolModifier().getSymbolChooser().getSymbolOptions(); - + //get the symbool options DLSymbolModifierParams symbolOptions = dlSymbolModifier.getSymbolModifierParams(); - //now set frequency parameters - colourRangeSlider.setLowValue(symbolOptions.clims[0]); - colourRangeSlider.setHighValue(symbolOptions.clims[1]); - colourRangeSlider.setColourArrayType( symbolOptions.colArray); - - //set the combo box class types. - checkClassNamesBox( symbolOptions); +// b1.setSelected(false); +// b2.setSelected(false); + if (symbolOptions.colTypeSelection == DLSymbolModifierParams.PREDICITON_COL) b1.setSelected(true); + if (symbolOptions.colTypeSelection == DLSymbolModifierParams.PREDICITON_COL) b2.setSelected(true); + setSettingsPane(); - //color box. - colourBox.setValue(symbolOptions.colArray); + symbolOptions.colTypeSelection = b1.isSelected() ? DLSymbolModifierParams.PREDICITON_COL : DLSymbolModifierParams.CLASS_COL; + + //set the parameters for colouring by prediction + setPredictionColParams(symbolOptions); + + //set the class colour parameters + setClassColParams(symbolOptions); //set the selected. showOnlyBinary.setSelected(symbolOptions.showOnlyBinary); + setParams = false; }