diff --git a/.classpath b/.classpath index b2a2497b..fe69133f 100644 --- a/.classpath +++ b/.classpath @@ -1,7 +1,14 @@ - + + + + + + + + @@ -10,11 +17,5 @@ - - - - - - diff --git a/src/Acquisition/layoutFX/AcquisitionPaneFX.java b/src/Acquisition/layoutFX/AcquisitionPaneFX.java index b97cb08f..7f866f7c 100644 --- a/src/Acquisition/layoutFX/AcquisitionPaneFX.java +++ b/src/Acquisition/layoutFX/AcquisitionPaneFX.java @@ -26,6 +26,7 @@ import pamViewFX.fxNodes.PamHBox; import pamViewFX.fxNodes.PamTextField; import pamViewFX.fxNodes.PamVBox; import pamViewFX.fxNodes.flipPane.FlipPane; +import pamViewFX.fxNodes.flipPane.PamFlipPane; import Acquisition.AcquisitionControl; import Acquisition.AcquisitionParameters; import Acquisition.ChannelListPanel; @@ -153,7 +154,7 @@ public class AcquisitionPaneFX extends SettingsPane{ //create the flip pane. flipPane=new FlipPane(); flipPane.setFlipDirection(Orientation.HORIZONTAL); - flipPane.setFlipTime(250); //default is 700ms- way too high + flipPane.setFlipTime(PamFlipPane.FLIP_TIME); //default is 700ms- way too high //flipPane.prefWidthProperty().bind(mainPane.widthProperty()); if (aquisitionControl.isViewer()){ diff --git a/src/PamController/FlipSettingsPane.java b/src/PamController/FlipSettingsPane.java new file mode 100644 index 00000000..9184837c --- /dev/null +++ b/src/PamController/FlipSettingsPane.java @@ -0,0 +1,136 @@ +package PamController; + +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.scene.layout.Priority; +import javafx.scene.paint.Color; +import pamViewFX.PamGuiManagerFX; +import pamViewFX.fxGlyphs.PamGlyphDude; +import pamViewFX.fxNodes.PamBorderPane; +import pamViewFX.fxNodes.PamButton; +import pamViewFX.fxNodes.PamHBox; +import pamViewFX.fxNodes.flipPane.FlipPane; + + +/** + * A pane which can flip to show another pane (referred to as the advanced settings pane). + * @author Jamie Macaulay + * + * @param + */ +public abstract class FlipSettingsPane extends SettingsPane { + + /** + * The holder pane. + */ + private FlipPane flipPane; + + /** + * The label at the top of the advanced pane. + */ + private Label advLabel; + + /** + * The advanced pane. + */ + private PamBorderPane advPane; + + /** + * The button which flips back to the front pane. + */ + private PamButton backButton; + + public FlipSettingsPane(Object ownerWindow) { + super(ownerWindow); + + flipPane = new FlipPane(); + flipPane.setFlipTime(200); + + this.advPane = createAdvSettingsPane() ; + + flipPane.getBack().getChildren().add(advPane); + + + } + + @Override + public Node getContentNode() { + flipPane.getFront().getChildren().clear(); + flipPane.getFront().getChildren().add(getFrontContentNode()); + return flipPane; + } + + /** + * Flip the pane to show the advanced settings pane. + */ + public void flipToBack() { + flipPane.flipToBack(); + } + /** + * Flip the pane to show the primary pane. + */ + public void flipToFront() { + flipPane.flipToBack(); + } + + + /** + * Set the contents of the advanced pane. + * @param contentNode - the content to set. + */ + public void setAdvPaneContents(Node contentNode) { + this.advPane.setCenter(contentNode); + } + + + /** + * Get the content node for the flip pane. + * @return + */ + public abstract Pane getFrontContentNode(); + + + /** + * Create the advanced settings pane which can be accessed by DAQ panes if needed. + */ + private PamBorderPane createAdvSettingsPane() { + + backButton = new PamButton(); + backButton.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-left", Color.WHITE, PamGuiManagerFX.iconSize)); + + backButton.setOnAction((action)->{ + flipPane.flipToFront(); + }); + + PamBorderPane advPane = new PamBorderPane(); + //advPane.setPadding(new Insets(5,5,5,5)); + + PamHBox buttonHolder = new PamHBox(); + + buttonHolder.setBackground(null); + //buttonHolder.setStyle("-fx-background-color: red;"); + buttonHolder.setAlignment(Pos.CENTER_LEFT); + buttonHolder.getChildren().addAll(backButton, advLabel = new Label("Adv. Settings")); + advLabel.setAlignment(Pos.CENTER); + advLabel.setMaxWidth(Double.MAX_VALUE); //need to make sure label is in center. + PamGuiManagerFX.titleFont2style(advLabel); + + advLabel.setAlignment(Pos.CENTER); + HBox.setHgrow(advLabel, Priority.ALWAYS); + + advPane.setTop(buttonHolder); + + return advPane; + + } + + public PamBorderPane getAdvPane() { + return advPane; + } + + + +} diff --git a/src/PamController/PamControlledUnitGUI.java b/src/PamController/PamControlledUnitGUI.java index 11168da9..02b5379e 100644 --- a/src/PamController/PamControlledUnitGUI.java +++ b/src/PamController/PamControlledUnitGUI.java @@ -17,7 +17,7 @@ public abstract class PamControlledUnitGUI { public abstract int getGUIFlag(); /** - * Allows the GUI to be notified of changes, e.g. in the PAMControlle.r + * Allows the GUI to be notified of changes, e.g. in the PAMController * @param flag - the change flag. */ public void notifyGUIChange(int flag) { diff --git a/src/PamController/SettingsPane.java b/src/PamController/SettingsPane.java index 6a02eab3..511f6d8b 100644 --- a/src/PamController/SettingsPane.java +++ b/src/PamController/SettingsPane.java @@ -40,7 +40,7 @@ public abstract class SettingsPane { public abstract String getName(); /** - * Get node for GUI chnage of settings. + * Get node for GUI change of settings. */ public abstract Node getContentNode(); diff --git a/src/PamUtils/TxtFileUtils.java b/src/PamUtils/TxtFileUtils.java index f2190a38..58d8c72b 100644 --- a/src/PamUtils/TxtFileUtils.java +++ b/src/PamUtils/TxtFileUtils.java @@ -6,6 +6,7 @@ import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; +import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Collection; @@ -62,7 +63,7 @@ public class TxtFileUtils { boolean isNaN=false; for (String line : lines) { - System.out.println(line); + //System.out.println(line); String[] recordsOnLine = line.split(delimeter); @@ -82,11 +83,15 @@ public class TxtFileUtils { // //This was causing isses with some numbers with e-06...dunno why so switched to parse double // String input = new String(recordsOnLine[i].toCharArray()); -// //System.out.println(input); +// System.out.println("|" + recordsOnLine[i] + "|"); // dat = nF.parse(input).doubleValue(); - - dat = Double.parseDouble(recordsOnLine[i]); + //5/08/2022 - there was a bug here where there is some sort of invisible character that does not appear on the + //print screen - the only way you can tell is the char array is greater than the number of digits - removed all non numeric + //characters. + String number = new String(recordsOnLine[i].strip().replaceAll("[^\\d.]", "")); + dat = Double.valueOf(number); + //dat = DecimalFormat.getNumberInstance().parse(new String(recordsOnLine[i].strip().toCharArray())).doubleValue(); } catch (Exception e){ e.printStackTrace(); diff --git a/src/PamguardMVC/RawDataTransforms.java b/src/PamguardMVC/RawDataTransforms.java index 81d8e3fe..6008aa5f 100644 --- a/src/PamguardMVC/RawDataTransforms.java +++ b/src/PamguardMVC/RawDataTransforms.java @@ -99,6 +99,7 @@ public class RawDataTransforms { */ private int shortestFFTLength; + private Object synchObject; /** @@ -187,31 +188,29 @@ public class RawDataTransforms { * @param fftLength * @return Power spectrum */ - public double[] getPowerSpectrum(int channel, int fftLength) { - synchronized (synchObject) { - if (powerSpectra == null) { - powerSpectra = new double[PamUtils.getNumChannels(dataUnit.getChannelBitmap())][]; - } - if (fftLength == 0) { - fftLength = getCurrentSpectrumLength(); - } - - if (powerSpectra[channel] == null - || powerSpectra[channel].length != fftLength / 2) { - ComplexArray cData = getComplexSpectrumHann(channel, fftLength); - currentSpecLen = fftLength; - powerSpectra[channel] = cData.magsq(); - if (powerSpectra==null){ - System.err.println("DLDetection: could not calculate power spectra"); - return null; - - } - if (powerSpectra[channel].length != fftLength/2) { - powerSpectra[channel] = Arrays.copyOf(powerSpectra[channel], fftLength/2); - } - } - return powerSpectra[channel]; + public synchronized double[] getPowerSpectrum(int channel, int fftLength) { + if (powerSpectra == null) { + powerSpectra = new double[PamUtils.getNumChannels(dataUnit.getChannelBitmap())][]; } + if (fftLength == 0) { + fftLength = getCurrentSpectrumLength(); + } + + if (powerSpectra[channel] == null + || powerSpectra[channel].length != fftLength / 2) { + ComplexArray cData = getComplexSpectrumHann(channel, fftLength); + currentSpecLen = fftLength; + powerSpectra[channel] = cData.magsq(); + if (powerSpectra==null){ + System.err.println("DLDetection: could not calculate power spectra"); + return null; + + } + if (powerSpectra[channel].length != fftLength/2) { + powerSpectra[channel] = Arrays.copyOf(powerSpectra[channel], fftLength/2); + } + } + return powerSpectra[channel]; } @@ -221,27 +220,25 @@ public class RawDataTransforms { * @param fftLength * @return Sum of power spectra */ - public double[] getTotalPowerSpectrum(int fftLength) { - synchronized (synchObject) { - if (fftLength == 0) { - fftLength = getCurrentSpectrumLength(); - } - if (fftLength == 0) { - fftLength = PamUtils.getMinFftLength(getSampleDuration()); - } - double[] ps; - if (totalPowerSpectrum == null - || totalPowerSpectrum.length != fftLength / 2) { - totalPowerSpectrum = new double[fftLength / 2]; - for (int c = 0; c < PamUtils.getNumChannels(this.dataUnit.getChannelBitmap()); c++) { - ps = getPowerSpectrum(c, fftLength); - for (int i = 0; i < fftLength / 2; i++) { - totalPowerSpectrum[i] += ps[i]; - } + public synchronized double[] getTotalPowerSpectrum(int fftLength) { + if (fftLength == 0) { + fftLength = getCurrentSpectrumLength(); + } + if (fftLength == 0) { + fftLength = PamUtils.getMinFftLength(getSampleDuration()); + } + double[] ps; + if (totalPowerSpectrum == null + || totalPowerSpectrum.length != fftLength / 2) { + totalPowerSpectrum = new double[fftLength / 2]; + for (int c = 0; c < PamUtils.getNumChannels(this.dataUnit.getChannelBitmap()); c++) { + ps = getPowerSpectrum(c, fftLength); + for (int i = 0; i < fftLength / 2; i++) { + totalPowerSpectrum[i] += ps[i]; } } - return totalPowerSpectrum; } + return totalPowerSpectrum; } @@ -256,17 +253,15 @@ public class RawDataTransforms { * @param fftLength - the FFT length to use. * @return the complex spectrum - the comnplex spectrum of the wave data from the specified channel. */ - public ComplexArray getComplexSpectrumHann(int channel, int fftLength) { - synchronized (synchObject) { - complexSpectrum = new ComplexArray[PamUtils.getNumChannels(dataUnit.getChannelBitmap())]; - if (complexSpectrum[channel] == null - || complexSpectrum.length != fftLength / 2) { + public synchronized ComplexArray getComplexSpectrumHann(int channel, int fftLength) { + complexSpectrum = new ComplexArray[PamUtils.getNumChannels(dataUnit.getChannelBitmap())]; + if (complexSpectrum[channel] == null + || complexSpectrum.length != fftLength / 2) { - complexSpectrum[channel] = getComplexSpectrumHann(rawData.getWaveData()[channel], fftLength); - currentSpecLen = fftLength; - } - return complexSpectrum[channel]; + complexSpectrum[channel] = getComplexSpectrumHann(rawData.getWaveData()[channel], fftLength); + currentSpecLen = fftLength; } + return complexSpectrum[channel]; } @@ -394,31 +389,29 @@ public class RawDataTransforms { * @param fftLength * @return the complex spectrum */ - public ComplexArray getComplexSpectrum(int channel, int fftLength) { - synchronized (synchObject) { - double[] paddedRawData; - double[] rawData; - int i, mn; + public synchronized ComplexArray getComplexSpectrum(int channel, int fftLength) { + double[] paddedRawData; + double[] rawData; + int i, mn; - if (complexSpectrum == null) { - complexSpectrum = new ComplexArray[getNChan()]; - } - if (complexSpectrum[channel] == null - || complexSpectrum.length != fftLength / 2) { - paddedRawData = new double[fftLength]; - rawData = getWaveData(channel); - //double[] rotData = getRotationCorrection(channel); - mn = Math.min(fftLength, getSampleDuration().intValue()); - for (i = 0; i < mn; i++) { - paddedRawData[i] = rawData[i];//-rotData[i]; - } - for (i = mn; i < fftLength; i++) { - paddedRawData[i] = 0; - } - complexSpectrum[channel] = fastFFT.rfft(paddedRawData, fftLength); - } - return complexSpectrum[channel]; + if (complexSpectrum == null) { + complexSpectrum = new ComplexArray[getNChan()]; } + if (complexSpectrum[channel] == null + || complexSpectrum.length != fftLength / 2) { + paddedRawData = new double[fftLength]; + rawData = getWaveData(channel); + //double[] rotData = getRotationCorrection(channel); + mn = Math.min(fftLength, getSampleDuration().intValue()); + for (i = 0; i < mn; i++) { + paddedRawData[i] = rawData[i];//-rotData[i]; + } + for (i = mn; i < fftLength; i++) { + paddedRawData[i] = 0; + } + complexSpectrum[channel] = fastFFT.rfft(paddedRawData, fftLength); + } + return complexSpectrum[channel]; } @@ -427,16 +420,14 @@ public class RawDataTransforms { * @param iChan channel index * @return analytic waveform */ - public double[] getAnalyticWaveform(int iChan) { - synchronized (synchObject) { - if (analyticWaveform == null) { - analyticWaveform = new double[getNChan()][]; - } - // if (analyticWaveform[iChan] == null) { - analyticWaveform[iChan] = hilbert.getHilbert(getWaveData(iChan)); - // } - return analyticWaveform[iChan]; + public synchronized double[] getAnalyticWaveform(int iChan) { + if (analyticWaveform == null) { + analyticWaveform = new double[getNChan()][]; } + // if (analyticWaveform[iChan] == null) { + analyticWaveform[iChan] = hilbert.getHilbert(getWaveData(iChan)); + // } + return analyticWaveform[iChan]; } /** @@ -448,14 +439,12 @@ public class RawDataTransforms { * @param fftFilterParams fft filter parameters. * @return analystic waveform. */ - public double[] getAnalyticWaveform(int iChan, boolean filtered, FFTFilterParams fftFilterParams) { - synchronized (synchObject) { - if (filtered == false || fftFilterParams == null) { - return getAnalyticWaveform(iChan); - } - else { - return getFilteredAnalyticWaveform(fftFilterParams, iChan); - } + public synchronized double[] getAnalyticWaveform(int iChan, boolean filtered, FFTFilterParams fftFilterParams) { + if (filtered == false || fftFilterParams == null) { + return getAnalyticWaveform(iChan); + } + else { + return getFilteredAnalyticWaveform(fftFilterParams, iChan); } } @@ -466,6 +455,7 @@ public class RawDataTransforms { * @param iChan channel number * @return envelope of the filtered data. */ + public double[] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams, int iChan) { synchronized (synchObject) { if (analyticWaveform == null) { @@ -509,6 +499,7 @@ public class RawDataTransforms { * @param channelIndex channel index * @return filtered waveform data */ + public double[] getFilteredWaveData(FFTFilterParams filterParams, int channelIndex) { synchronized (synchObject) { filteredWaveData = getFilteredWaveData(filterParams); @@ -522,6 +513,7 @@ public class RawDataTransforms { * @param filterParams filter parameters * @return array of filtered data */ + public double[][] getFilteredWaveData(FFTFilterParams filterParams) { synchronized (synchObject) { //System.out.println("Make filterred wave data!: " + (filterParams != oldFFTFilterParams)); diff --git a/src/Resources/css/pamCSS.css b/src/Resources/css/pamCSS.css index 0f8a0b11..b2b2d58d 100644 --- a/src/Resources/css/pamCSS.css +++ b/src/Resources/css/pamCSS.css @@ -638,4 +638,24 @@ #module-pane .ikonli-font-icon { -fx-icon-color: black; +} + +/******************************************************************************* + * * + * Custom slider for volume controls * + * * + ******************************************************************************/ +#thickslider .track { + -fx-pref-height:14; + -fx-background-radius: 8; +} + +#thickslider:vertical .track { + -fx-pref-width:12; + -fx-background-radius: 8; +} + +#thickslider .thumb { + -fx-pref-height: 14; + -fx-pref-width: 14; } \ No newline at end of file diff --git a/src/Resources/exampleSounds/Humpback_whale.wav b/src/Resources/exampleSounds/Humpback_whale.wav new file mode 100644 index 00000000..555232ce Binary files /dev/null and b/src/Resources/exampleSounds/Humpback_whale.wav differ diff --git a/src/Resources/exampleSounds/Minke_whale.wav b/src/Resources/exampleSounds/Minke_whale.wav new file mode 100644 index 00000000..2711bffc Binary files /dev/null and b/src/Resources/exampleSounds/Minke_whale.wav differ diff --git a/src/clickDetector/ClickClassifiers/basicSweep/SweepClassifier.java b/src/clickDetector/ClickClassifiers/basicSweep/SweepClassifier.java index 52c55e5e..d257e900 100644 --- a/src/clickDetector/ClickClassifiers/basicSweep/SweepClassifier.java +++ b/src/clickDetector/ClickClassifiers/basicSweep/SweepClassifier.java @@ -24,6 +24,7 @@ import clickDetector.ClickClassifiers.ClickIdentifier; import clickDetector.ClickClassifiers.ClickTypeCommonParams; import clickDetector.ClickClassifiers.basic.BasicClickIdentifier; import clickDetector.layoutFX.clickClassifiers.ClassifyPaneFX; +import clickDetector.layoutFX.clickClassifiers.SweepClassifierPaneFX; /** * An improvements on the BasicClickIdentifier based on work by @@ -44,6 +45,9 @@ public class SweepClassifier implements ClickIdentifier , PamSettings { private SweepClassifierPanel dialogPanel; + private SweepClassifierPaneFX fxPane; + + private SweepClassifierWorker sweepClassifierWorker; protected SweepClassifierParameters sweepClassifierParameters = new SweepClassifierParameters(); @@ -408,8 +412,8 @@ public class SweepClassifier implements ClickIdentifier , PamSettings { @Override public ClassifyPaneFX getClassifierPane() { - // TODO Auto-generated method stub - return null; + if (fxPane==null) fxPane = new SweepClassifierPaneFX(this, clickControl); + return fxPane; } @Override diff --git a/src/clickDetector/layoutFX/ClickDelayPane.java b/src/clickDetector/layoutFX/ClickDelayPane.java index f6df0a13..0af91475 100644 --- a/src/clickDetector/layoutFX/ClickDelayPane.java +++ b/src/clickDetector/layoutFX/ClickDelayPane.java @@ -194,8 +194,8 @@ public class ClickDelayPane extends SettingsPane { public ClickParameters getParams(ClickParameters clickParameters) { if (clickParameters==null) return null; - if (delayParams[0] == null) { - return null; + if (delayParams==null || delayParams[0] == null) { + return clickParameters; } clickParameters.setDelayMeasurementParams(0, delayParams[0]); for (int i = 1; i < typesList.length; i++) { diff --git a/src/clickDetector/layoutFX/ClickSettingsPane.java b/src/clickDetector/layoutFX/ClickSettingsPane.java index db6b3867..f50da155 100644 --- a/src/clickDetector/layoutFX/ClickSettingsPane.java +++ b/src/clickDetector/layoutFX/ClickSettingsPane.java @@ -6,6 +6,7 @@ import java.text.ParseException; import clickDetector.ClickControl; import clickDetector.ClickParameters; import clickDetector.layoutFX.clickClassifiers.ClickClassifyPaneFX; +import javafx.geometry.Orientation; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.CheckBox; @@ -13,6 +14,7 @@ import javafx.scene.control.Label; import javafx.scene.control.Spinner; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; +import javafx.scene.layout.GridPane; import javafx.scene.layout.Pane; import javafx.scene.layout.Priority; import javafx.scene.paint.Color; @@ -41,6 +43,8 @@ import pamViewFX.fxNodes.utilityPanes.GroupedSourcePaneFX; * @author Jamie Macaulay */ public class ClickSettingsPane extends SettingsPane{ + + public static double PREF_SPINNER_WIDTH = 100; /** * Group source pane for the click settings pane. @@ -158,7 +162,7 @@ public class ClickSettingsPane extends SettingsPane{ /** * The default pane width */ - public static double paneWidth=1050; + public static double paneWidth=500; /** * The default pane height. @@ -180,22 +184,17 @@ public class ClickSettingsPane extends SettingsPane{ pamTabbedPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE); //create a combined detection and length pane - PamHBox detectionPane=new PamHBox(); + PamVBox detectionPane=new PamVBox(); detectionPane.setSpacing(20); detectionPane.getChildren().add(createClickDetectionPane()); - //create a dividing line. - Line line=new Line(0,20,0,0); - line.startYProperty().bind(sourcePane.layoutYProperty().add(20)); - line.endYProperty().bind(detectionPane.heightProperty().subtract(20)); - line.setStroke(Color.WHITE); - line.setStrokeWidth(2); - PamHBox lineHolder=new PamHBox(); - lineHolder.getChildren().add(line); - lineHolder.setAlignment(Pos.CENTER); - detectionPane.getChildren().add(lineHolder); - PamVBox holder=new PamVBox(); + + + PamHBox holder=new PamHBox(); + holder.setSpacing(20); holder.getChildren().addAll(createClickLengthPane(), createClickTriggerPane()); detectionPane.getChildren().add(holder); + + detectionPane.getChildren().add(createTriggerGraph()); //add everything to tabs. pamTabbedPane.getTabs().add(new Tab("Click Detection", detectionPane)); @@ -211,11 +210,11 @@ public class ClickSettingsPane extends SettingsPane{ //pre filter pane. - preFilter=new FilterPaneFX(); + preFilter=new FilterPaneFX(Orientation.VERTICAL); pamTabbedPane.getTabs().add(new Tab("Pre Filter", preFilter.getContentNode())); //trigger pane - triggerFilter=new FilterPaneFX(); + triggerFilter=new FilterPaneFX(Orientation.VERTICAL); pamTabbedPane.getTabs().add(new Tab("Trigger Filter", triggerFilter.getContentNode())); //echo detection pane. @@ -268,12 +267,16 @@ public class ClickSettingsPane extends SettingsPane{ //channels, groups and trigger are all in one pane to make it easy not to make mistakes sourcePane=createClickSourcePane(); //create the source pane. - + + + GridPane.setColumnSpan(sourcePane.getDataBlockBox(), 4); //now create trigger pane. The trigger pane is added to the source pane. Label triggerLabel = new Label("Trigger Channels"); PamGuiManagerFX.titleFont2style(triggerLabel); sourcePane.getSourcePane().add(triggerLabel,1,2); - sourcePane.getSourcePane().add(triggerChannels=new Pane(),1,3); + + triggerChannels=new Pane(); + sourcePane.getSourcePane().add(triggerChannels,1,3); createTriggerChannels(); //sourcePane.getSourcePane().add(createClickTriggerPane(), 2, 3); @@ -282,6 +285,7 @@ public class ClickSettingsPane extends SettingsPane{ // pamTabbedPane.getTabs().add(new Tab("Click Echoes", createEchoPane())); // pamTabbedPane.getTabs().add(new Tab("Click Delays", createDelayPane())); + sourcePane.setPrefWidth(paneWidth); return sourcePane; } @@ -299,33 +303,41 @@ public class ClickSettingsPane extends SettingsPane{ lengthPane.setVgap(5); lengthPane.setHgap(5); - lengthPane.add(new Label("Min click separation"),0,0); + lengthPane.add(new Label("Min separation"),0,0); minClickSep=new PamSpinner(0, 10000000, 100, 20); minClickSep.setEditable(true); minClickSep.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL); + minClickSep.setPrefWidth(PREF_SPINNER_WIDTH); + lengthPane.add(minClickSep,1,0); lengthPane.add(new Label("samples"),2,0); - lengthPane.add(new Label("Max click length"),0,1); + lengthPane.add(new Label("Max length"),0,1); maxClickLength=new PamSpinner(0, 10000000, 100, 20); maxClickLength.setEditable(true); maxClickLength.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL); + maxClickLength.setPrefWidth(PREF_SPINNER_WIDTH); + lengthPane.add(maxClickLength,1,1); lengthPane.add(new Label("samples"),2,1); - lengthPane.add(new Label("pre samples"),0,2); + lengthPane.add(new Label("Pre samples"),0,2); preSampleSpinner=new PamSpinner(0, 10000000, 100, 20); preSampleSpinner.setEditable(true); preSampleSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL); + preSampleSpinner.setPrefWidth(PREF_SPINNER_WIDTH); + lengthPane.add(preSampleSpinner,1,2); lengthPane.add(new Label("samples"),2,2); - lengthPane.add(new Label("pre samples"),0,3); + lengthPane.add(new Label("Post samples"),0,3); postSampleSpinner=new PamSpinner(0, 10000000, 100, 20); postSampleSpinner.setEditable(true); postSampleSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL); + postSampleSpinner.setPrefWidth(PREF_SPINNER_WIDTH); + lengthPane.add(postSampleSpinner,1,3); lengthPane.add(new Label("samples"),2,3); @@ -398,6 +410,7 @@ public class ClickSettingsPane extends SettingsPane{ }); triggerBox.add(threshold,1,0); triggerBox.add(new Label("dB"),2,0); + threshold.setPrefWidth(PREF_SPINNER_WIDTH); triggerBox.add(new Label("Long Filter"),0,1); longFilter=new PamSpinner(0.0000001, 0.1, 0.000001, 0.000001); @@ -410,6 +423,7 @@ public class ClickSettingsPane extends SettingsPane{ clickTriggerGraph.updateWaveformGraph(this.clickParameters); }); triggerBox.add(longFilter,1,1); + longFilter.setPrefWidth(PREF_SPINNER_WIDTH); triggerBox.add(new Label("Long Filter 2"),0,2); longFilter2=new PamSpinner(0.0000001, 0.1, 0.000001, 0.000001); @@ -419,6 +433,7 @@ public class ClickSettingsPane extends SettingsPane{ longFilter2.getValueFactory().valueProperty().addListener((obs, before, after)->{ clickParameters.longFilter2=after; }); + longFilter2.setPrefWidth(PREF_SPINNER_WIDTH); triggerBox.add(longFilter2,1,2); triggerBox.add(new Label("Short Filter"),0,3); @@ -431,25 +446,33 @@ public class ClickSettingsPane extends SettingsPane{ clickTriggerGraph.setShortFilter(clickParameters.shortFilter); clickTriggerGraph.updateWaveformGraph(this.clickParameters); }); + shortFilter.setPrefWidth(PREF_SPINNER_WIDTH); triggerBox.add(shortFilter,1,3); triggerPane.add(triggerBox,0,1); - //trigger graph - Label graphLabel = new Label("Filter Graph"); - PamGuiManagerFX.titleFont2style(graphLabel); - triggerPane.add(graphLabel,0,2); - - clickTriggerGraph=new ClickTriggerGraph(); - PamGridPane.setHgrow(clickTriggerGraph, Priority.ALWAYS); - PamGridPane.setVgrow(clickTriggerGraph, Priority.ALWAYS); - triggerPane.add(clickTriggerGraph,0,3); - //triggerPane.setGridLinesVisible(true); return triggerPane; } + + private Pane createTriggerGraph() { + //trigger graph + Label graphLabel = new Label("Filter Graph"); + PamGuiManagerFX.titleFont2style(graphLabel); + + clickTriggerGraph=new ClickTriggerGraph(); + PamGridPane.setHgrow(clickTriggerGraph, Priority.ALWAYS); + PamGridPane.setVgrow(clickTriggerGraph, Priority.ALWAYS); + + PamVBox triggerGraph = new PamVBox(); + triggerGraph.setSpacing(5); + triggerGraph.getChildren().addAll(graphLabel, clickTriggerGraph); + + return triggerGraph; + + } /** * Unselect all trigger channels diff --git a/src/clickDetector/layoutFX/ClickTriggerGraph.java b/src/clickDetector/layoutFX/ClickTriggerGraph.java index 63123637..f1e0b5ed 100644 --- a/src/clickDetector/layoutFX/ClickTriggerGraph.java +++ b/src/clickDetector/layoutFX/ClickTriggerGraph.java @@ -19,6 +19,9 @@ import simulatedAcquisition.sounds.SimSignal; public class ClickTriggerGraph extends PamBorderPane { public final static int PORPOISE_CLICK=0; + + public final static int SPERM_WHALE=1; + private int currentClick=PORPOISE_CLICK; @@ -44,11 +47,15 @@ public class ClickTriggerGraph extends PamBorderPane { private LineChart plotChart; private int freq2; + + private double[] waveform; public ClickTriggerGraph(){ this.setCenter(createWaveformGraph()); - this.setPrefWidth(500); + this.setPrefWidth(400); //FIXME - seems to a resize bug in high DPI displays. Seems fixed in 8u60. + this.waveform=generateClickWaveform(currentClick, noise); + } /** @@ -67,7 +74,6 @@ public class ClickTriggerGraph extends PamBorderPane { Series noiseLevelSeries = new Series(); - double[] waveform=generateClickWaveform(currentClick, noise); double[] signalLevel=calcFilter(waveform, shortFilter); double[] noiseLevel=calcFilter(waveform, longFilter); @@ -111,6 +117,10 @@ public class ClickTriggerGraph extends PamBorderPane { clickSound=new ClickSound("Porpoise", freq=140000, freq2=140000, length=0.00015, WINDOWTYPE.HANN); sR=500000; break; + case SPERM_WHALE: + clickSound=(new ClickSound("Beaked Whale", 30000, 60000, length = 0.3e-3, WINDOWTYPE.HANN)); + sR=192000; + break; default: clickSound=new ClickSound("Porpoise", freq=140000, freq2=140000, length=0.00015, WINDOWTYPE.HANN); sR=500000; diff --git a/src/clickDetector/layoutFX/clickClassifiers/BasicIdentifierPaneFX.java b/src/clickDetector/layoutFX/clickClassifiers/BasicIdentifierPaneFX.java index f04b1f5e..e652a9f1 100644 --- a/src/clickDetector/layoutFX/clickClassifiers/BasicIdentifierPaneFX.java +++ b/src/clickDetector/layoutFX/clickClassifiers/BasicIdentifierPaneFX.java @@ -1,17 +1,15 @@ package clickDetector.layoutFX.clickClassifiers; import pamViewFX.fxNodes.PamBorderPane; -import pamViewFX.fxNodes.hidingPane.HidingPane; +import pamViewFX.fxNodes.flipPane.PamFlipPane; import pamViewFX.fxNodes.table.TableSettingsPane; import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import javafx.geometry.Side; import javafx.scene.Node; import javafx.scene.control.Button; import javafx.scene.control.Dialog; import javafx.scene.control.TableColumn; import javafx.scene.control.cell.CheckBoxTableCell; -import javafx.scene.paint.Color; import clickDetector.BasicClickIdParameters; import clickDetector.ClickControl; import clickDetector.ClickTypeParams; @@ -40,10 +38,10 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { */ private TableSettingsPane settingsPane; - /** - * Hiding pane which slides out to allow users to change click type settings. - */ - protected HidingPane hidingPane; +// /** +// * Hiding pane which slides out to allow users to change click type settings. +// */ +// protected HidingPane hidingPane; /** * Holds click classifier controls inside hiding pane. @@ -62,10 +60,10 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { */ protected PamBorderPane mainHolderPane; - /** - * The width of the hiding pane - */ - private double hidingPaneWidth=900; +// /** +// * The width of the hiding pane +// */ +// private double hidingPaneWidth=900; /** * Cloned copy of BasicClickIdParameters. @@ -73,10 +71,12 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { private BasicClickIdParameters basicClickIdParameters; private PamBorderPane mainPane; + + private PamFlipPane flipPane; /** * Create a BasicClickIdParameters pane which allows users to add multiple basic click identifiers to the PAMGuard click classifier. - * @param basicClickIdentifier - the ClickIdentifier. + * @param basicClickIdentifier - the ClickIdentifier. ob * @param clickControl -a reference to the ClickControl the classifier is associated with. */ public BasicIdentifierPaneFX(ClickIdentifier basicClickIdentifier, @@ -84,9 +84,17 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { this.basicClickIdentifier= basicClickIdentifier; this.clickControl=clickControl; mainPane= new PamBorderPane(); - mainPane.setCenter(createSettingsPane()); + + flipPane = new PamFlipPane(); + flipPane.getFrontPane().setCenter(createSettingsPane()); + flipPane.getBackPane().setCenter(clickTypeHolder); + + mainPane.setCenter(flipPane); + } + + /** * Create the controls for the basic click identifier pane. * @return node with all controls for basic click classifier. @@ -97,21 +105,23 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { mainHolderPane.setCenter(settingsPane=new ClickClassifierTable(clickClassifiers)); clickTypeHolder=new PamBorderPane(); - clickTypeHolder.setPrefWidth(hidingPaneWidth); + //clickTypeHolder.setPrefWidth(hidingPaneWidth); return mainHolderPane; } - /** - * Added purely so can be override and hiding pane set in different location if required - */ - public void createHidingPane(){ - hidingPane=new HidingPane(Side.RIGHT, clickTypeHolder, mainPane, false); - //hidingPane.showHidePane(false); - mainHolderPane.setRight(hidingPane); - hidingPane.showHidePane(false); - } +// /** +// * Added purely so can be override and hiding pane set in different location if required +// */ +// public void createHidingPane(){ +// hidingPane=new HidingPane(Side.RIGHT, clickTypeHolder, mainPane, false); +// //hidingPane.showHidePane(false); +// mainHolderPane.setRight(hidingPane); +// hidingPane.showHidePane(false); +// } + + @Override public Node getNode() { @@ -192,14 +202,14 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { public Dialog createSettingsDialog(ClickTypeProperty data) { //we do not use dialogs here- sliding pane instead. setClassifierPane(data); - showHidingPane(true); + showFlipPane(true); return null; } @Override public void editData(ClickTypeProperty data){ setClassifierPane(data); - showHidingPane(true); + showFlipPane(true); } @Override @@ -210,16 +220,31 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { } +// /** +// * Show the hiding pane which contains classifier settings +// * NOTE: needed to add this to stop a stack overflow error in BasicClickIdentifier 06/09/2016 +// * @param show - true to show pane. +// */ +// public void showHidingPane(boolean show){ +// if (hidingPane==null){ +// this.createHidingPane(); +// } +// hidingPane.showHidePane(true); +// } + /** - * Show the hiding pane which contains classifier settings + * Show the flip pane. * NOTE: needed to add this to stop a stack overflow error in BasicClickIdentifier 06/09/2016 * @param show - true to show pane. */ - public void showHidingPane(boolean show){ - if (hidingPane==null){ - this.createHidingPane(); + public void showFlipPane(boolean show){ + if (show) { + //System.out.println("Show flip pane: " + show); + flipPane.flipToBack(); + } + else { + flipPane.flipToFront(); } - hidingPane.showHidePane(true); } /** @@ -243,7 +268,9 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { //now need to make sure on closing the pane that settings are saved. Need to //remove the old click type from the list and add new one in the same position. - getHidingPaneCloseButton().setOnAction((action)->{ + getFlipPaneCloseButton().setOnAction((action)->{ + //System.out.println("CLOSE FLIP PANE"); + showFlipPane(false); //this should update the click type property in the observable list thus changing the table clickTypePane.getParams(clickTypeProperty); }); @@ -253,20 +280,20 @@ public class BasicIdentifierPaneFX implements ClassifyPaneFX { * Get the button which closes the hiding pane. * @return button which closes the hiding pane. */ - public Button getHidingPaneCloseButton() { - return getClickTypeHidingPane().getHideButton(); + public Button getFlipPaneCloseButton() { + return flipPane.getBackButton(); } - /** - * Get the hiding pane which holds settings for different click types. - * @return the HidingPane for click classifiers. - */ - public HidingPane getClickTypeHidingPane() { - if (hidingPane==null) { - this.createHidingPane(); - } - return hidingPane; - } +// /** +// * Get the hiding pane which holds settings for different click types. +// * @return the HidingPane for click classifiers. +// */ +// public HidingPane getClickTypeHidingPane() { +// if (hidingPane==null) { +// this.createHidingPane(); +// } +// return hidingPane; +// } /** * Get the pane which holds the ClickTypePaneFX. diff --git a/src/clickDetector/layoutFX/clickClassifiers/ClickClassifyPaneFX.java b/src/clickDetector/layoutFX/clickClassifiers/ClickClassifyPaneFX.java index 9f9606d9..aedca842 100644 --- a/src/clickDetector/layoutFX/clickClassifiers/ClickClassifyPaneFX.java +++ b/src/clickDetector/layoutFX/clickClassifiers/ClickClassifyPaneFX.java @@ -4,6 +4,7 @@ import org.controlsfx.glyphfont.Glyph; import clickDetector.ClickControl; import clickDetector.ClickParameters; +import clickDetector.ClickClassifiers.ClickClassifierManager; import clickDetector.ClickClassifiers.ClickIdentifier; import javafx.geometry.Insets; import javafx.geometry.Pos; @@ -41,6 +42,7 @@ public class ClickClassifyPaneFX extends PamStackPane { */ private ClickControl clickControl; + private CheckBox runOnlineCheckBox; private CheckBox discardClicksCheckBox; @@ -160,7 +162,11 @@ public class ClickClassifyPaneFX extends PamStackPane { //set parameters - listener will do everything else. currentClickIdentifier=clickControl.getClassifierManager(). getClassifier(clickParameters.clickClassifierType); - System.out.println("ClickClassifyPaneFX:setParams(): " +classifierComboBox.getSelectionModel().getSelectedIndex()); + if (clickParameters.clickClassifierType == ClickClassifierManager.CLASSIFY_BASIC) { + + } + + //System.out.println("ClickClassifyPaneFX:setParams(): " +classifierComboBox.getSelectionModel().getSelectedIndex()); classifierComboBox.getSelectionModel().select(clickParameters.clickClassifierType); //set classifier parameters if (currentClickIdentifier!=null && currentClickIdentifier.getClassifierPane()!=null) { @@ -171,7 +177,7 @@ public class ClickClassifyPaneFX extends PamStackPane { public ClickParameters getParams(ClickParameters clickParameters){ //set all parameters in classifier. - System.out.println("ClickClassifyPaneFX:getParams(): " +classifierComboBox.getSelectionModel().getSelectedIndex()); + //System.out.println("ClickClassifyPaneFX:getParams(): " +classifierComboBox.getSelectionModel().getSelectedIndex()); clickParameters.clickClassifierType=classifierComboBox.getSelectionModel().getSelectedIndex(); if (currentClickIdentifier != null && currentClickIdentifier.getClassifierPane() != null) { diff --git a/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierPaneFX.java b/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierPaneFX.java index 834f045e..44544234 100644 --- a/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierPaneFX.java +++ b/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierPaneFX.java @@ -1,7 +1,6 @@ package clickDetector.layoutFX.clickClassifiers; -import pamViewFX.fxNodes.PamScrollPane; import clickDetector.ClickControl; import clickDetector.ClickClassifiers.basicSweep.SweepClassifier; import clickDetector.ClickClassifiers.basicSweep.SweepClassifierParameters; @@ -9,17 +8,18 @@ import clickDetector.ClickClassifiers.basicSweep.SweepClassifierSet; /** * Slightly different pane for the sweep classifier. + * * @author Jamie Macaulay */ public class SweepClassifierPaneFX extends BasicIdentifierPaneFX { /** - * Reference to the sweep classifier + * Reference to the sweep classifier. */ SweepClassifier sweepClickClassifier; /** - * Reference to the sweep classifier params + * Reference to the sweep classifier params. */ private SweepClassifierParameters sweepIdParameters; @@ -39,11 +39,12 @@ public class SweepClassifierPaneFX extends BasicIdentifierPaneFX { public void setClassifierPane(ClickTypeProperty clickTypeProperty){ SweepClassifierSetPaneFX sweepPane=new SweepClassifierSetPaneFX(sweepClickClassifier); sweepPane.setParams(clickTypeProperty); - super.getClickTypeHolder().setCenter(new PamScrollPane(sweepPane.getContentNode())); + super.getClickTypeHolder().setCenter(sweepPane.getContentNode()); //now need to make sure on closing the pane that settings are saved. Need to //remove the old click type from the list and add new one in the same position. - getHidingPaneCloseButton().setOnAction((action)->{ + getFlipPaneCloseButton().setOnAction((action)->{ + showFlipPane(false); sweepPane.getParams(clickTypeProperty); }); } diff --git a/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierSetPaneFX.java b/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierSetPaneFX.java index 88e0199b..8120c7ed 100644 --- a/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierSetPaneFX.java +++ b/src/clickDetector/layoutFX/clickClassifiers/SweepClassifierSetPaneFX.java @@ -15,21 +15,22 @@ import javafx.scene.control.Label; import javafx.scene.control.Spinner; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; +import javafx.scene.control.TabPane.TabClosingPolicy; import javafx.scene.control.TextField; import javafx.scene.control.Tooltip; import javafx.scene.layout.Priority; import javafx.scene.text.Font; -import pamViewFX.PamGuiManagerFX; import pamViewFX.fxNodes.PamBorderPane; import pamViewFX.fxNodes.PamGridPane; import pamViewFX.fxNodes.PamHBox; import pamViewFX.fxNodes.PamSpinner; -import pamViewFX.fxNodes.PamTitledPane; import pamViewFX.fxNodes.PamVBox; import pamViewFX.fxNodes.pamDialogFX.PamDialogFX; import pamViewFX.fxNodes.picker.SymbolPicker; import pamViewFX.fxNodes.utilityPanes.FreqBandPane; +import pamViewFX.fxNodes.utilityPanes.PamToggleSwitch; import pamViewFX.fxNodes.utilityPanes.SimpleFilterPaneFX; +import pamViewFX.PamGuiManagerFX; import PamController.SettingsPane; import clickDetector.ClickClassifiers.basicSweep.CodeHost; @@ -38,6 +39,7 @@ import clickDetector.ClickClassifiers.basicSweep.SweepClassifierSet; /** * Pane which contains controls to change a SweepClassifierSet. + * * @author Jamie Macaulay * */ @@ -110,14 +112,15 @@ public class SweepClassifierSetPaneFX extends SettingsPane { private Node createSweepPane(){ PamVBox holder=new PamVBox(); - holder.setSpacing(10); - holder.setPadding(new Insets(10,5,5,40)); + holder.setSpacing(15); + holder.setPadding(new Insets(10,0,0,0)); optionBox=new OptionsBox(); /*********Waveform Tab************/ Tab waveformTab=new Tab("Waveform"); PamVBox waveformHolder=new PamVBox(5); + waveformHolder.setPadding(new Insets(10,0,0,0)); clickLength=new ClickLengthBox(); filterBox=new FilterBox(); @@ -134,11 +137,13 @@ public class SweepClassifierSetPaneFX extends SettingsPane { energyBox=new EnergyBandBox(); freqBox=new FrequencySearchBlock(); spectrumHolder.getChildren().addAll(energyBox, freqBox); + spectrumHolder.setPadding(new Insets(10,0,0,0)); spectrumTab.setContent(spectrumHolder); - + /**********Main Layout**************/ TabPane tabPane= new TabPane(); + tabPane.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE); tabPane.getTabs().addAll(waveformTab, spectrumTab); holder.getChildren().add(optionBox); @@ -153,12 +158,12 @@ public class SweepClassifierSetPaneFX extends SettingsPane { * @author Jamie Macaulay * */ - private abstract class SweepBox extends PamTitledPane { + private abstract class SweepBox extends PamBorderPane { /** * Check box to enable pane */ - private CheckBox enableBox; + private PamToggleSwitch enableBox; /** * Border pane to hold content @@ -167,40 +172,52 @@ public class SweepClassifierSetPaneFX extends SettingsPane { private Font disableFont; + + private Label label; SweepBox(String borderTitle, Boolean enableButton) { - + //create holder pnae borderPane=new PamBorderPane(); - - + this.setCenter(borderPane); + + PamHBox hBox = new PamHBox(); + hBox.setSpacing(5); + + if (borderTitle != null) { - //Label label=new Label(borderTitle); - PamGuiManagerFX.titleFont2style(this); - //borderPane.setTop(label); - this.setText(borderTitle); + label=new Label(borderTitle); + + PamGuiManagerFX.titleFont2style(label); + + hBox.getChildren().add(label); } - if (enableButton) { - enableBox = new CheckBox("Enable"); - PamVBox vBox=new PamVBox(); - vBox.setPadding(new Insets(0,20,0,0)); - vBox.setAlignment(Pos.CENTER); - vBox.getChildren().add(enableBox); + + if (enableButton.booleanValue() == true) { + + enableBox = new PamToggleSwitch(""); + //vBox.setPadding(new Insets(0,20,0,0)); enableBox.setTooltip(new Tooltip("Enable " + borderTitle + " measurements")); - - enableBox.setOnAction((action)->{ + + enableBox.selectedProperty().addListener((obsVal, oldVal, newVal)->{ disbleControls(!enableBox.isSelected()); - - /**FIXME- this does not seem to work. If titlepane collapsed auto returns to white**/ -// if (enableBox.isSelected()) this.setTextFill(Color.WHITE); -// else this.setTextFill(Color.GRAY); }); - - - borderPane.setLeft(vBox); + + hBox.getChildren().add(0,enableBox); + + // setOnAction((action)->{ + // disbleControls(!enableBox.isSelected()); + // + // /**FIXME- this does not seem to work. If titlepane collapsed auto returns to white**/ + // if (enableBox.isSelected()) this.setTextFill(Color.WHITE); + // else this.setTextFill(Color.GRAY); + // }); + //this.setDisable(!enableBox.isSelected()); } - this.setContent(borderPane); + + this.setTop(hBox); + /**Don't like this in old swing version*/ //tP.setCenter( description = new Label("", JLabel.CENTER)); //this.setTop(tP); @@ -211,7 +228,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane { * @param desc - a description of the control */ protected void setDescription(String desc) { - this.setTooltip(new Tooltip(desc)); + label.setTooltip(new Tooltip(desc)); } // private void showTopStrip() { @@ -326,7 +343,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane { nameField=new TextField(); nameField.setPrefColumnCount(10); - pamGridPane.add(nameField, 1, 0); + pamGridPane.add(nameField, 0, 0); PamGridPane.setColumnSpan(nameField, 2); @@ -334,17 +351,17 @@ public class SweepClassifierSetPaneFX extends SettingsPane { codeSpinner=new PamSpinner (0, 500, 0, 1); codeSpinner.setEditable(true); - codeSpinner.setPrefWidth(150); + //codeSpinner.setPrefWidth(150); codeSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL); - pamGridPane.add(codeSpinner, 4, 0); + pamGridPane.add(codeSpinner, 1, 0); // pamGridPane.add(new Label("Symbol"), 0,1); //create colour picker to allow users to change symbol colour. symbolPicker=new SymbolPicker(); - pamGridPane.add(symbolPicker, 6, 0); + pamGridPane.add(symbolPicker, 2, 0); - pamGridPane.add(new Label("Symbol"), 5,0); + pamGridPane.add(new Label("Symbol"), 3,0); // //create a button to allow users to change symbol shape. // symbolColour=new ColorPicker(); @@ -372,7 +389,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane { clickLengthSpinner=new PamSpinner(4,102400,128,32); clickLengthSpinner.setEditable(true); - clickLengthSpinner.setPrefWidth(150); + //clickLengthSpinner.setPrefWidth(150); clickLengthSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL); clickCenterBox.getChildren().add(clickLengthSpinner); @@ -380,7 +397,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane { clickCenterBox.getChildren().add(lengthMS=new Label("()")); clickCenterBox.getChildren().add(new Label("around click center.")); clickCenterBox.setAlignment(Pos.CENTER_LEFT); - PamGridPane.setColumnSpan(clickCenterBox, 7); + PamGridPane.setColumnSpan(clickCenterBox, 4); PamGridPane.setHgrow(clickCenterBox, Priority.ALWAYS); pamGridPane.add(clickCenterBox, 0,2); @@ -494,7 +511,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane { protected void setParams() { //set sample rate. simpleFilterPane.setSampleRate(sweepClassifier.getClickDetector().getSampleRate()); - simpleFilterPane.setParams(sweepClassifierSet.fftFilterParams); + if (sweepClassifierSet.fftFilterParams!=null) simpleFilterPane.setParams(sweepClassifierSet.fftFilterParams); } @@ -558,7 +575,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane { // gridPane.add(new Label("Smoothing"),0,0); smoothing=new PamSpinner(3,101,5,2); smoothing.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL); - smoothing.setPrefWidth(100); + //smoothing.setPrefWidth(100); // gridPane.add(smoothing,1,0); // gridPane.add(new Label("bins (must be odd)"),2,0); @@ -566,7 +583,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane { // gridPane.add(new Label("Threshold"),3,0); threshold=new PamSpinner(1., 300., 6.,1.); threshold.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL); - threshold.setPrefWidth(100); + //threshold.setPrefWidth(100); // gridPane.add(threshold,4,0); // gridPane.add(new Label("dB"),5,0); @@ -583,12 +600,12 @@ public class SweepClassifierSetPaneFX extends SettingsPane { minLengthms=new PamSpinner(0.00, 1.00, 0.03,0.01); minLengthms.setEditable(true); minLengthms.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL); - minLengthms.setPrefWidth(130); + //minLengthms.setPrefWidth(130); maxLengthms=new PamSpinner(0.00, 1.00, 0.22,0.01); maxLengthms.setEditable(true); maxLengthms.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL); - maxLengthms.setPrefWidth(130); + //maxLengthms.setPrefWidth(130); PamHBox clickLengthHolder2=new PamHBox(); @@ -752,9 +769,9 @@ public class SweepClassifierSetPaneFX extends SettingsPane { */ private class FrequencySearchBlock extends SweepBox { - private CheckBox peakFreqCheckBox; - private CheckBox peakWidthCheckBox; - private CheckBox meanFreqCheckBox; + private PamToggleSwitch peakFreqCheckBox; + private PamToggleSwitch peakWidthCheckBox; + private PamToggleSwitch meanFreqCheckBox; /** @@ -767,7 +784,7 @@ public class SweepClassifierSetPaneFX extends SettingsPane { private FreqBandPane meanFreq; FrequencySearchBlock() { - super("Peak and Mean Frequency", false); + super("Peak and Mean Frequency", true); this.getHolderPane().setCenter(createFreqSearchPane()); } @@ -796,8 +813,8 @@ public class SweepClassifierSetPaneFX extends SettingsPane { //peak frequency - peakFreqCheckBox=new CheckBox("Enable"); - peakFreqCheckBox.setOnAction((action)->{ + peakFreqCheckBox=new PamToggleSwitch(""); + peakFreqCheckBox.selectedProperty().addListener((obsVal, oldVal, newVal)->{ peakFreqPane.setDisableFreqPane(!peakWidthCheckBox.isSelected()); }); @@ -811,8 +828,8 @@ public class SweepClassifierSetPaneFX extends SettingsPane { //peak width - peakWidthCheckBox=new CheckBox("Enable"); - peakWidthCheckBox.setOnAction((action)->{ + peakWidthCheckBox=new PamToggleSwitch(""); + peakWidthCheckBox.selectedProperty().addListener((obsVal, oldVal, newVal)->{ //peakWidthPane.setDisable(!peakWidthCheckBox.isSelected()); peakWidthPane.setDisableFreqPane(!peakWidthCheckBox.isSelected()); threshold.setDisable(!peakWidthCheckBox.isSelected()); @@ -838,8 +855,8 @@ public class SweepClassifierSetPaneFX extends SettingsPane { //mean frequency - meanFreqCheckBox=new CheckBox("Enable"); - meanFreqCheckBox.setOnAction((action)->{ + meanFreqCheckBox=new PamToggleSwitch(""); + meanFreqCheckBox.selectedProperty().addListener((obsVal, oldVal, newVal)->{ meanFreq.setDisableFreqPane(!peakWidthCheckBox.isSelected()); }); diff --git a/src/clickTrainDetector/IDIInfo.java b/src/clickTrainDetector/IDIInfo.java index fa050111..da59ebd2 100644 --- a/src/clickTrainDetector/IDIInfo.java +++ b/src/clickTrainDetector/IDIInfo.java @@ -5,6 +5,7 @@ import java.util.List; import PamUtils.PamArrayUtils; import PamguardMVC.PamDataUnit; +import PamguardMVC.debug.Debug; /** * Holds some basic IDI info on the click train. @@ -47,7 +48,7 @@ public class IDIInfo { lastNumber = dataUnits.size(); if (dataUnits.size()<3) { - System.out.println("CTDataUnit: Cannot calculate IDIInfo for less than three data units"); + Debug.out.println("CTDataUnit: Cannot calculate IDIInfo for less than three data units"); return; } diff --git a/src/clickTrainDetector/classification/SimpleCTClassification.java b/src/clickTrainDetector/classification/SimpleCTClassification.java index 4a079670..ba7db1d8 100644 --- a/src/clickTrainDetector/classification/SimpleCTClassification.java +++ b/src/clickTrainDetector/classification/SimpleCTClassification.java @@ -31,7 +31,6 @@ public class SimpleCTClassification implements CTClassification { @Override public String getSummaryString() { - // TODO Auto-generated method stub return "SimpleClssf: SpeciesID: " + speciesID + " ClassifierType: " + classifierType; } diff --git a/src/clickTrainDetector/classification/bearingClassifier/BearingClassifier.java b/src/clickTrainDetector/classification/bearingClassifier/BearingClassifier.java index 615581b9..0507f367 100644 --- a/src/clickTrainDetector/classification/bearingClassifier/BearingClassifier.java +++ b/src/clickTrainDetector/classification/bearingClassifier/BearingClassifier.java @@ -1,8 +1,8 @@ package clickTrainDetector.classification.bearingClassifier; -import org.renjin.gcc.runtime.Debug; import PamUtils.PamArrayUtils; +import PamguardMVC.debug.Debug; import clickTrainDetector.CTDataUnit; import clickTrainDetector.ClickTrainControl; import clickTrainDetector.classification.CTClassification; @@ -95,7 +95,7 @@ public class BearingClassifier implements CTClassifier { if (nullcount>clickTrain.getSubDetectionsCount()-4) { //less than three data units with loc results - Debug.println("The bearing classifier has a null count: "); + Debug.out.println("The bearing classifier has a null count: "); return new BearingClassification(CTClassifier.NOSPECIES, Double.NaN, Double.NaN, Double.NaN); } @@ -111,7 +111,7 @@ public class BearingClassifier implements CTClassifier { double medianBearingD = PamArrayUtils.median(bearingDiff); double stdBearingD = PamArrayUtils.std(bearingDiff); - Debug.println("Bearing classifier: No. Detections: " + clickTrain.getSubDetectionsCount() + " medianBearing: " + medianBearingD); + Debug.out.println("Bearing classifier: No. Detections: " + clickTrain.getSubDetectionsCount() + " medianBearing: " + medianBearingD); int speciesID = CTClassifier.NOSPECIES; boolean passed= true; @@ -120,31 +120,31 @@ public class BearingClassifier implements CTClassifier { //is the minimum and maximum bearing in range... if ((min>=bearingClssfrParams.bearingLimMin && min<=bearingClssfrParams.bearingLimMax) || (max>=bearingClssfrParams.bearingLimMin && max<=bearingClssfrParams.bearingLimMax)) { - Debug.println("Passed on min max bearing"); + Debug.out.println("Passed on min max bearing"); } else passed =false; //mean bearing derivative if (bearingClssfrParams.useMean && meanBearingD>=bearingClssfrParams.minMeanBearingD && meanBearingD<=bearingClssfrParams.maxMeanBearingD) { - Debug.println("Passed on mean bearing"); + Debug.out.println("Passed on mean bearing"); } else if (bearingClssfrParams.useMean) passed=false; //median bearing derivative - Debug.println("Median Bearing: " + Math.toDegrees(medianBearingD) + + Debug.out.println("Median Bearing: " + Math.toDegrees(medianBearingD) + " minlim: " + Math.toDegrees(bearingClssfrParams.minMedianBearingD)+ " maxlim: " + Math.toDegrees(bearingClssfrParams.maxMedianBearingD)); if (bearingClssfrParams.useMedian && medianBearingD>=bearingClssfrParams.minMedianBearingD && medianBearingD<=bearingClssfrParams.maxMedianBearingD) { - Debug.println("Passed on median bearing"); + Debug.out.println("Passed on median bearing"); } else if (bearingClssfrParams.useMedian) passed = false; //standard deviation derivative if (bearingClssfrParams.useStD && stdBearingD>=bearingClssfrParams.minStdBearingD && stdBearingD<=bearingClssfrParams.maxStdBearingD) { - Debug.println("Passed on std bearing"); + Debug.out.println("Passed on std bearing"); } else if (bearingClssfrParams.useStD) passed= false; @@ -152,7 +152,7 @@ public class BearingClassifier implements CTClassifier { speciesID = this.bearingClssfrParams.speciesFlag; } - Debug.println("SPECIESID!! " + speciesID); + Debug.out.println("SPECIESID!! " + speciesID); return new BearingClassification(speciesID, meanBearingD, medianBearingD, stdBearingD); diff --git a/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTGarbageBot.java b/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTGarbageBot.java index 483b43a4..7758997f 100644 --- a/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTGarbageBot.java +++ b/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTGarbageBot.java @@ -70,11 +70,13 @@ public class MHTGarbageBot { double maxICI = mhtKernel.getMHTParams().maxCoast * mhtKernel.getMHTChi2Provider().getChi2Params().maxICI; //check the current set of click train possible ICI's - + + //Debug.out.println("MHTGARBAGEBOT: maxICI " + maxICI + " " + iciPrev); + //we have reached the hard limit. Save click trains, wipe the detector and start again. if (mhtKernel.getKCount()>mhtKernel.getMHTParams().nPruneBackStart && (iciPrev>maxICI || mhtKernel.getKCount()>DETECTION_HARD_LIMIT)) { -// Debug.out.println("MHTGarbageBot: KERNEL HARD LIMIT"); + //Debug.out.println("MHTGARBAGEBOT: KERNEL HARD LIMIT"); //check whether the next click has a gap so big that all click trains should be restarted //grab tracks mhtKernel.confirmRemainingTracks(); diff --git a/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTKernel.java b/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTKernel.java index 03a90f75..fe4a5ab9 100644 --- a/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTKernel.java +++ b/src/clickTrainDetector/clickTrainAlgorithms/mht/MHTKernel.java @@ -158,10 +158,10 @@ public class MHTKernel { if (verbosity>0) { Debug.out.println("Possiblity matrix size is " + possibleTracks.size() + " x " + kcount ); } - // for (int i=0; i { testBranch = newPossibleTracks.get(j); testBitSet=testBranch.trackBitSet.get(0, kcount-(pruneback)); + //now test whether the current and test branch are the same. if (testBitSet.equals(currentBitSet)) { indexConfirm[j]=true; @@ -423,6 +424,7 @@ public class MHTKernel { indexRemove[j]=true; } } + } //long time2a=System.currentTimeMillis(); @@ -437,9 +439,11 @@ public class MHTKernel { if (nCoasts>=this.mHTParams.maxCoast || confirmAll || currentBranch.flag==TrackBitSet.JUNK_TRACK) { //the branch needs to be confirmed. - // System.out.println(i + " DONE: "+ String.format("%.3f ", possibleTracks.get(i).chi2Track.getChi2())+ - // " " + String.format("%d ", possibleTracks.get(i).chi2Track.getNCoasts()) - // + MHTKernel.bitSetString(possibleTracks.get(i).trackBitSet, kcount)); +// System.out.println(i + " DONE: " + (nCoasts >= this.mHTParams.maxCoast) + " " + confirmAll + " " +// + (currentBranch.flag == TrackBitSet.JUNK_TRACK) + " " +// + String.format("%.3f ", currentBranch.chi2Track.getChi2()) + " " +// + String.format("%d ", currentBranch.chi2Track.getNCoasts()) +// + MHTKernel.bitSetString(currentBranch.trackBitSet, kcount)); /** * 27/02/2020 @@ -460,7 +464,7 @@ public class MHTKernel { //add confirmed track confirmedTracks.add(currentBranch); - + //// //if a branch is confirmed then all the tracks which include it's clicks must also be removed. //// //test the testBranch against all other branches. TODO - Is this the most efficient code -could add if statements to above loop? for (int j=0; j { indexRemove[j]=true; } } + } else { //save as an active track. @@ -678,7 +683,7 @@ public class MHTKernel { /** * * Set a new reference index and junk all data before that index. This can be - * useful for long data sets to save memory once all click trains in preceeding + * useful for long data sets to save memory once all click trains in preceding * data units have been detecteded. Note that the function deletes the currently * confirmed tracks. These should be extracted beforehand; * diff --git a/src/clickTrainDetector/clickTrainAlgorithms/mht/StandardMHTChi2.java b/src/clickTrainDetector/clickTrainAlgorithms/mht/StandardMHTChi2.java index ee8ec6ca..1a8d67e7 100644 --- a/src/clickTrainDetector/clickTrainAlgorithms/mht/StandardMHTChi2.java +++ b/src/clickTrainDetector/clickTrainAlgorithms/mht/StandardMHTChi2.java @@ -5,6 +5,7 @@ import java.util.BitSet; import PamUtils.PamArrayUtils; import PamguardMVC.PamDataUnit; +import PamguardMVC.debug.Debug; import clickTrainDetector.clickTrainAlgorithms.CTAlgorithmInfo; import clickTrainDetector.clickTrainAlgorithms.mht.electricalNoiseFilter.ElectricalNoiseFilter; import clickTrainDetector.clickTrainAlgorithms.mht.electricalNoiseFilter.SimpleElectricalNoiseFilter; @@ -225,16 +226,17 @@ public class StandardMHTChi2 implements MHTChi2, Cloneable { getIDIManager().setForceCalc(true); this.lastIDIData = getIDIManager().getIDIStruct(bitSet); - //System.out.println("Time diff: " + lastIDIData.timeDiff + " " + lastIDIData.medianIDI); nCoasts=(int) Math.floor(lastIDIData.timeDiff/Math.abs(lastIDIData.medianIDI)); } else if (bitcount==1) { //this stops a single units being stuck in the back of the probability matrix. - nCoasts = (int) Math.floor((newdataUnit.getTimeMilliseconds()/1000. - -getIDIManager().getLastTime(bitSet)/this.getChi2Params().maxICI)); + nCoasts = (int) Math.floor(((newdataUnit.getTimeMilliseconds()-getIDIManager().getFirstDataUnit().getTimeMilliseconds())/1000. + -getIDIManager().getLastTime(bitSet))/this.getChi2Params().maxICI); } + + //System.out.println("nCoasts: " + nCoasts); return nCoasts; } @@ -332,6 +334,8 @@ public class StandardMHTChi2 implements MHTChi2, Cloneable { double totalTracktime = PamArrayUtils.sum(lastIDIData.idiSeries); + //System.out.println("Total track time: " + totalTracktime); + /** * Add a nudge towards longer tracks (remember to cast to double when dividing). Note that * kcount coefficient is meaningless because all tracks are multiplied by it and x^2 is only used @@ -341,7 +345,7 @@ public class StandardMHTChi2 implements MHTChi2, Cloneable { //19/03/2020 - fixed a bug; Was multiplying instead of dividing - as such long tracks were being //discriminated against causing fragmentation...ooops chi2=chi2/Math.pow(totalTracktime/getIDIManager().getTotalTime(),getChi2Params().longTrackExponent); - + //chi2=chi2/Math.pow(bitSet.cardinality(),getChi2Params().longTrackExponent); } @@ -374,6 +378,8 @@ public class StandardMHTChi2 implements MHTChi2, Cloneable { //All done. Set the values. //set the chi2 values. //long time3=System.nanoTime(); + //Debug.out.println("Track chi2: " + chi2 + " " + bitcount ); + return chi2; } diff --git a/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/AmplitudeChi2.java b/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/AmplitudeChi2.java index cff7d705..43fbb67a 100644 --- a/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/AmplitudeChi2.java +++ b/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/AmplitudeChi2.java @@ -2,6 +2,9 @@ package clickTrainDetector.clickTrainAlgorithms.mht.mhtvar; import PamguardMVC.PamDataUnit; +import clickTrainDetector.clickTrainAlgorithms.mht.StandardMHTChi2Params; +import clickTrainDetector.layout.mht.AmplitudeMHTVarPane; +import clickTrainDetector.layout.mht.MHTVarSettingsPane; /** * Chi^2 value for dB amplitude of tracks. Measures the chnage in track delta between @@ -13,9 +16,14 @@ import PamguardMVC.PamDataUnit; @SuppressWarnings("rawtypes") public class AmplitudeChi2 extends SimpleChi2VarDelta { + private double lastDiff; + + private AmplitudeChi2Params amplitudeParams; + + public AmplitudeChi2() { super(); - super.setSimpleChiVarParams(defaultSettings()); + super.setSimpleChiVarParams(amplitudeParams = (AmplitudeChi2Params) defaultSettings()); } /** @@ -23,7 +31,7 @@ public class AmplitudeChi2 extends SimpleChi2VarDelta { * @return */ private SimpleChi2VarParams defaultSettings() { - SimpleChi2VarParams simpleChiVarParams = new SimpleChi2VarParams(getName(), getUnits()); + AmplitudeChi2Params simpleChiVarParams = new AmplitudeChi2Params(getName(), getUnits()); //simpleChiVarParams.errLimits=new double[] {Double.MIN_VALUE, 100}; simpleChiVarParams.error=30; simpleChiVarParams.minError=1; @@ -36,13 +44,15 @@ public class AmplitudeChi2 extends SimpleChi2VarDelta { return "Amplitude"; } + @Override public double getDiffValue(PamDataUnit pamDataUnit0, PamDataUnit pamDataUnit1) { //System.out.println("DB: " + pamDataUnit0.getAmplitudeDB()); //made this abs so it can deal with increasing then decreasing click trains. i.e. //the click trian is not penalised if it gradually increasing then starts to gradually decrease //in amplitude. - return Math.abs(pamDataUnit0.getAmplitudeDB()-pamDataUnit1.getAmplitudeDB()); + this.lastDiff = Math.abs(pamDataUnit0.getAmplitudeDB()-pamDataUnit1.getAmplitudeDB()); + return lastDiff; } @Override @@ -50,6 +60,28 @@ public class AmplitudeChi2 extends SimpleChi2VarDelta { //just a simple static error coefficient. return super.getError(); } + + @Override + public double calcDeltaChi2(double lastDelta, double newDelta, double timeDiff) { + + double chi2 = super.calcDeltaChi2(lastDelta, newDelta, timeDiff); + + /** + * There was a problem here with using the delta instead of the absolute difference between amplitudes. + * When using the delta there could be a slow change of amplitude gradient which could lead to giant + * changes in absolute amplitude. By ensuring this is the absolute + * value between bearings (lastdiff) then the bearingJump threshold works as it should. + */ + + //System.out.println("Amplitude: " + amplitudeParams.ampJumpEnable + " " + lastDiff + " " + amplitudeParams.maxAmpJump); + + if (lastDiff>amplitudeParams.maxAmpJump && amplitudeParams.ampJumpEnable ) { + chi2=chi2+StandardMHTChi2Params.JUNK_TRACK_PENALTY; + } + + + return chi2; + } @Override @@ -57,6 +89,27 @@ public class AmplitudeChi2 extends SimpleChi2VarDelta { return "dB"; } + @Override + public void setSimpleChiVarParams(SimpleChi2VarParams params) { + if (params==null) amplitudeParams = new AmplitudeChi2Params(getName(), getUnits()); //backwards compatibility + else this.amplitudeParams = (AmplitudeChi2Params) params; ; + + super.setSimpleChiVarParams(params); + //save a reference to params so we don;t have to keep casting. + } + + @Override + public void setSettingsObject(Object object) { + this.setSimpleChiVarParams((AmplitudeChi2Params) object); + } + + @Override + public MHTVarSettingsPane getSettingsPane() { + if (this.settingsPane==null) this.settingsPane= new AmplitudeMHTVarPane(getSimpleChiVarParams(), new ResultConverter()); + settingsPane.setParams(getSimpleChiVarParams()); + return settingsPane; + } + } diff --git a/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/AmplitudeChi2Params.java b/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/AmplitudeChi2Params.java new file mode 100644 index 00000000..20fa3e3a --- /dev/null +++ b/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/AmplitudeChi2Params.java @@ -0,0 +1,46 @@ +package clickTrainDetector.clickTrainAlgorithms.mht.mhtvar; + +import PamModel.parametermanager.ManagedParameters; + +public class AmplitudeChi2Params extends SimpleChi2VarParams implements ManagedParameters { + + + + public AmplitudeChi2Params(String name, String unitString, double error, double minError, double errorScaleValue) { + super(name, unitString, error, minError, errorScaleValue); + // TODO Auto-generated constructor stub + } + public AmplitudeChi2Params(String name, String unitString, double error, double minError) { + super(name, unitString, error, minError); + // TODO Auto-generated constructor stub + } + public AmplitudeChi2Params(String name, String unitString) { + super(name, unitString); + // TODO Auto-generated constructor stub + } + public AmplitudeChi2Params(String name) { + super(name); + } + + public AmplitudeChi2Params(SimpleChi2VarParams params) { + this(params.name, params.getUnits(), params.error, params.minError, params.errorScaleValue); + } + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** + * Whether the bearing jump is used. + */ + public boolean ampJumpEnable = true; + + /** + * The maximum allowed bearing bearing jump in a click train in RADIANS + */ + public double maxAmpJump = 10; //dB + + + +} \ No newline at end of file diff --git a/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/BearingChi2Delta.java b/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/BearingChi2Delta.java index 703257fa..49e571b8 100644 --- a/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/BearingChi2Delta.java +++ b/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/BearingChi2Delta.java @@ -141,7 +141,7 @@ public class BearingChi2Delta extends SimpleChi2VarDelta { if (delta>bearingParams.maxBearingJump) { //System.out.println("Hello!!!! Reverse Bearing"); - chi2=chi2*StandardMHTChi2Params.JUNK_TRACK_PENALTY; + chi2=chi2+StandardMHTChi2Params.JUNK_TRACK_PENALTY; } } diff --git a/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/IDIManager.java b/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/IDIManager.java index d6691247..f698e603 100644 --- a/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/IDIManager.java +++ b/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/IDIManager.java @@ -536,6 +536,10 @@ public class IDIManager { return (this.lastDetection.getTimeMilliseconds()- this.firstDetection.getTimeMilliseconds())/1000.; } + public PamDataUnit getFirstDataUnit() { + return this.firstDetection; + } + diff --git a/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/LengthChi2.java b/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/LengthChi2.java index 4ae8f6f1..96dd3515 100644 --- a/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/LengthChi2.java +++ b/src/clickTrainDetector/clickTrainAlgorithms/mht/mhtvar/LengthChi2.java @@ -16,7 +16,6 @@ public class LengthChi2 extends SimpleChi2Var { @Override public String getName() { - // TODO Auto-generated method stub return "Click Length"; } @@ -44,7 +43,7 @@ public class LengthChi2 extends SimpleChi2Var { //simpleChiVarParams.errLimits=new double[] {Double.MIN_VALUE, 100}; simpleChiVarParams.error=0.2; simpleChiVarParams.minError=0.002; - simpleChiVarParams.errorScaleValue = SimpleChi2VarParams.SCALE_FACTOR_ICI; + simpleChiVarParams.errorScaleValue = SimpleChi2VarParams.SCALE_FACTOR_ICI*10; return simpleChiVarParams; } diff --git a/src/clickTrainDetector/layout/dataselector/CTDataSelectPanel.java b/src/clickTrainDetector/layout/dataselector/CTDataSelectPanel.java index 5800d6f6..183f2772 100644 --- a/src/clickTrainDetector/layout/dataselector/CTDataSelectPanel.java +++ b/src/clickTrainDetector/layout/dataselector/CTDataSelectPanel.java @@ -288,7 +288,7 @@ public class CTDataSelectPanel implements PamDialogPanel { } // System.out.println("No. count: " + count); - currentParams.classifier = new int[count]; + currentParams.classifier = new int[count]; ArrayList classifiers = ctDataSelector.getClickControl().getClassifierManager().getCurrentClassifiers(); int used = 0; for (int i=0; i { /** * Default divisor of error for min error. */ - private static final Double ERROR_DIVISOR = 10000.0; + private static final Double ERROR_DIVISOR = 100.0; /** * The main pane. diff --git a/src/clickTrainDetector/layout/mht/AmplitudeChi2AdvPane.java b/src/clickTrainDetector/layout/mht/AmplitudeChi2AdvPane.java new file mode 100644 index 00000000..b4631820 --- /dev/null +++ b/src/clickTrainDetector/layout/mht/AmplitudeChi2AdvPane.java @@ -0,0 +1,97 @@ +package clickTrainDetector.layout.mht; + +import org.controlsfx.control.ToggleSwitch; + +import clickTrainDetector.clickTrainAlgorithms.mht.mhtvar.AmplitudeChi2Params; +import clickTrainDetector.clickTrainAlgorithms.mht.mhtvar.IDIChi2Params; +import clickTrainDetector.clickTrainAlgorithms.mht.mhtvar.ResultConverter; +import clickTrainDetector.clickTrainAlgorithms.mht.mhtvar.SimpleChi2VarParams; +import javafx.scene.control.Label; +import javafx.scene.control.Spinner; +import javafx.scene.control.Tooltip; +import javafx.scene.layout.GridPane; +import pamViewFX.fxNodes.PamSpinner; + +public class AmplitudeChi2AdvPane extends AdvMHTVarPane { + + private PamSpinner ampJumpSpinner; + private ToggleSwitch ampEnaleSwitch; + + + public AmplitudeChi2AdvPane(SimpleChi2VarParams simpleChi2Var2, ResultConverter resultConverter) { + super(simpleChi2Var2, resultConverter); + } + + + @Override + protected GridPane createAdvPane() { + + GridPane gridPane = (GridPane) super.createAdvPane(); + + int gridY=3; + + gridPane.add(ampEnaleSwitch = new ToggleSwitch("Max jump"), 0, gridY); + ampEnaleSwitch.selectedProperty().addListener((obsVal, newVal, oldVal)->{ + ampJumpSpinner.setDisable(!ampEnaleSwitch.isSelected()); + }); + ampJumpSpinner = new PamSpinner(0.,Double.MAX_VALUE,0.,1.0); + ampJumpSpinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL); + ampJumpSpinner.setPrefWidth(90); + ampJumpSpinner.valueProperty().addListener((obs,oldVal,newVal)->{ + notifySettingsListeners(); + }); + gridPane.add(ampJumpSpinner, 1, gridY); + gridPane.add(new Label("dB"), 2, gridY); + ampJumpSpinner.setEditable(true); + + //create tool tip + Tooltip errorCoeffTip = new Tooltip( + "The minimum Amplitude defines the maximum decibel jump between two detection allowed in a click train" + + "If an IDI below this minimum occurs in a click train it will incur" + + "a large chi^2 penalty and so the click train is unlikely to be kept" + + "in the hypothesis mix."); + errorCoeffTip.setWrapText(true); + errorCoeffTip.setPrefWidth(200); + ampEnaleSwitch.setTooltip(errorCoeffTip); + ampJumpSpinner.setTooltip(errorCoeffTip); + + ampJumpSpinner.setDisable(!ampEnaleSwitch.isSelected()); + + + return gridPane; + } + + + @Override + public AmplitudeChi2Params getParams(SimpleChi2VarParams currParams) { + + System.out.println("Get params: AMPLITUDE"); + + AmplitudeChi2Params newParams = new AmplitudeChi2Params(super.getParams(currParams)); + + newParams.maxAmpJump = ampJumpSpinner.getValue(); + newParams.ampJumpEnable = ampEnaleSwitch.isSelected(); + + return newParams; + } + + + @Override + public void setParams(SimpleChi2VarParams currParams) { + + AmplitudeChi2Params newParams; + if (currParams instanceof AmplitudeChi2Params) { + newParams = (AmplitudeChi2Params) currParams; + } + else { + newParams = new AmplitudeChi2Params(currParams); + } + + super.setParams(newParams); + + ampJumpSpinner.setDisable(!ampEnaleSwitch.isSelected()); + ampJumpSpinner.getValueFactory().setValue(newParams.maxAmpJump); + ampEnaleSwitch.setSelected(newParams.ampJumpEnable); + } + +} diff --git a/src/clickTrainDetector/layout/mht/AmplitudeMHTVarPane.java b/src/clickTrainDetector/layout/mht/AmplitudeMHTVarPane.java new file mode 100644 index 00000000..0c314755 --- /dev/null +++ b/src/clickTrainDetector/layout/mht/AmplitudeMHTVarPane.java @@ -0,0 +1,22 @@ +package clickTrainDetector.layout.mht; + +import clickTrainDetector.clickTrainAlgorithms.mht.mhtvar.ResultConverter; +import clickTrainDetector.clickTrainAlgorithms.mht.mhtvar.SimpleChi2VarParams; + +public class AmplitudeMHTVarPane extends SimpleMHTVarPane { + + public AmplitudeMHTVarPane(SimpleChi2VarParams simpleChi2Var, ResultConverter resultsConverter) { + super(simpleChi2Var, resultsConverter); + // TODO Auto-generated constructor stub + } + + /** + * Create the advanced settings pane. + * @return the advanced settings pane. + */ + @Override + public AdvMHTVarPane createAdvMHTVarPane(SimpleChi2VarParams simpleChi2VarParams, ResultConverter resultConverter) { + return new AmplitudeChi2AdvPane(simpleChi2VarParams, resultConverter); + } + +} diff --git a/src/clickTrainDetector/layout/mht/BearingMHTVarPane.java b/src/clickTrainDetector/layout/mht/BearingMHTVarPane.java index 7039f3cb..cb3036a0 100644 --- a/src/clickTrainDetector/layout/mht/BearingMHTVarPane.java +++ b/src/clickTrainDetector/layout/mht/BearingMHTVarPane.java @@ -8,7 +8,6 @@ public class BearingMHTVarPane extends SimpleMHTVarPane { public BearingMHTVarPane(SimpleChi2VarParams simpleChi2Var, ResultConverter resultsConverter) { super(simpleChi2Var, resultsConverter); - // TODO Auto-generated constructor stub } /** diff --git a/src/clickTrainDetector/layout/mht/CorrelationAdvMHTPane.java b/src/clickTrainDetector/layout/mht/CorrelationAdvMHTPane.java index 9b4e6166..5238b24d 100644 --- a/src/clickTrainDetector/layout/mht/CorrelationAdvMHTPane.java +++ b/src/clickTrainDetector/layout/mht/CorrelationAdvMHTPane.java @@ -86,11 +86,11 @@ public class CorrelationAdvMHTPane extends AdvMHTVarPane { CorrelationChi2Params newParams = new CorrelationChi2Params(super.getParams(currParams)); - System.out.println("GETPARAMS:fftFilterParams_OLD HIGHPASS: " + newParams.fftFilterParams.highPassFreq); + //System.out.println("GETPARAMS:fftFilterParams_OLD HIGHPASS: " + newParams.fftFilterParams.highPassFreq); newParams.fftFilterParams=filterPane.getParams(newParams.fftFilterParams); - System.out.println("GETPARAMS:fftFilterParams_NEW HIGHPASS: " + newParams.fftFilterParams.highPassFreq); + //System.out.println("GETPARAMS:fftFilterParams_NEW HIGHPASS: " + newParams.fftFilterParams.highPassFreq); newParams.useFilter=this.useFilterBox.isSelected(); diff --git a/src/clickTrainDetector/layout/mht/ICIChi2AdvPane.java b/src/clickTrainDetector/layout/mht/ICIChi2AdvPane.java index 53327efc..9af6bca4 100644 --- a/src/clickTrainDetector/layout/mht/ICIChi2AdvPane.java +++ b/src/clickTrainDetector/layout/mht/ICIChi2AdvPane.java @@ -42,7 +42,8 @@ public class ICIChi2AdvPane extends AdvMHTVarPane { }); gridPane.add(minICISpinner, 1, gridY); gridPane.add(new Label("ms"), 2, gridY); - + minICISpinner.setEditable(true); + //create tool tip Tooltip errorCoeffTip = new Tooltip( "The minimum IDI defines a minimum IDI allowed in a click train \n" + "If an IDI below this minimum occurs in a click train it will incur\n" diff --git a/src/clickTrainDetector/logging/ClickTrainDetLogging.java b/src/clickTrainDetector/logging/ClickTrainDetLogging.java index f4081e49..4ebe115d 100644 --- a/src/clickTrainDetector/logging/ClickTrainDetLogging.java +++ b/src/clickTrainDetector/logging/ClickTrainDetLogging.java @@ -98,7 +98,7 @@ public class ClickTrainDetLogging extends SuperDetLogging { //average spectrum tableDef.addTableItem(avrg_Spectrum_max = new PamTableItem("avrg_spectrum_max", Types.DOUBLE)); tableDef.addTableItem(avrg_Spectrum = new PamTableItem("avrg_spectrum", Types.CHAR, 8*DEFAULT_SPECTRUM_LEN)); - tableDef.addTableItem(classifiers = new PamTableItem("classifiers", Types.CHAR, 4096)); + tableDef.addTableItem(classifiers = new PamTableItem("classifiers", Types.CHAR, 8128)); //a species flag, this is entirely for user convenience and is NOT read back - the species flag //is read from the JSON strings when reloading the data unit. If they end being different something has gone @@ -279,7 +279,9 @@ public class ClickTrainDetLogging extends SuperDetLogging { //set the classifications. String classifiersData = classifiers.getStringValue(); - + + //FIXME + //System.out.println(classifiersData); if (classifiersData!=null && classifiersData.length()>0) { String[] classifiersDatas = classifiersData.split(JSON_DELIMITER); diff --git a/src/clickTrainDetector/offline/CTProcessDialog.java b/src/clickTrainDetector/offline/CTProcessDialog.java index 0f8e07cf..39cecd03 100644 --- a/src/clickTrainDetector/offline/CTProcessDialog.java +++ b/src/clickTrainDetector/offline/CTProcessDialog.java @@ -44,7 +44,7 @@ public class CTProcessDialog extends OLProcessDialog { getTaskCheckBoxs()[i].setEnabled(aTask.canRun() && nr); //added extra but here so that only one tasks can be run at a time- may change - System.out.println("A task can run: !!" + aTask.canRun() + " " + aTask.getDataBlock()); + //System.out.println("A task can run: !!" + aTask.canRun() + " " + aTask.getDataBlock()); //if more tasks are added to the click train detector. if (aTask.canRun() == false || (aTask!=task && task!=null)) { getTaskCheckBoxs()[i].setSelected(false); diff --git a/src/dataModelFX/structures/PamExtensionStructure.java b/src/dataModelFX/structures/PamExtensionStructure.java index 25a1a5e7..8bc428d9 100644 --- a/src/dataModelFX/structures/PamExtensionStructure.java +++ b/src/dataModelFX/structures/PamExtensionStructure.java @@ -14,7 +14,8 @@ import pamViewFX.fxNodes.connectionPane.StandardConnectionNode; import pamViewFX.fxNodes.connectionPane.structures.ExtensionSocketStructure; /** - * PAM extension structure + * PAM extension structure. The extension structure allows one parent to be split into multiple + * children primarily a way to neaten up a data model display. * * @author Jamie Macaulay * @@ -22,10 +23,11 @@ import pamViewFX.fxNodes.connectionPane.structures.ExtensionSocketStructure; public class PamExtensionStructure extends ExtensionSocketStructure implements PAMConnectionNode { private PamStructureParams groupStructureParams; - - + + public PamExtensionStructure(ConnectionPane connectionPane) { super(connectionPane); + groupStructureParams = new PamStructureParams(this); final ContextMenu contextMenu = new ContextMenu(); @@ -34,13 +36,18 @@ public class PamExtensionStructure extends ExtensionSocketStructure implements P paste.setOnAction((action)->{ removeStructure(); }); - - this.getConnectionNodeBody().setOnMousePressed((event)->{ + + + //this is a bit of a hack. We can't add this to the main connection body because + //it is already used for dragging. So instead at to the circle within the connection group. The event is registered + //by both the group and the circle. + circle.setOnMousePressed((event)->{ if (event.isSecondaryButtonDown()) { contextMenu.show(this.getConnectionNodeBody(), event.getScreenX(), event.getScreenY()); } }); + } diff --git a/src/matchedTemplateClassifer/ImportTemplateCSV.java b/src/matchedTemplateClassifer/ImportTemplateCSV.java index c3c1be20..0713f026 100644 --- a/src/matchedTemplateClassifer/ImportTemplateCSV.java +++ b/src/matchedTemplateClassifer/ImportTemplateCSV.java @@ -41,6 +41,7 @@ public class ImportTemplateCSV implements TemplateImport { //the first row is the waveform double[] waveform = new double[data.get(0).size()]; for (int i=0; i { */ PamControlledUnit parentControl = getTaskControlledUnit(); if (parentControl == null) { - System.out.printf("Offline task %d with datablock %s is not associated with a PAMGuard module\n", getName(), parentDataBlock); + System.out.printf("Offline task %s with datablock %s is not associated with a PAMGuard module\n", getName(), parentDataBlock==null ? "null": parentDataBlock.getDataName()); } else { OfflineTaskManager.getManager().registerTask(this); diff --git a/src/offlineProcessing/logging/TaskLogging.java b/src/offlineProcessing/logging/TaskLogging.java index 1193e05f..f98c667c 100644 --- a/src/offlineProcessing/logging/TaskLogging.java +++ b/src/offlineProcessing/logging/TaskLogging.java @@ -187,11 +187,16 @@ public class TaskLogging { String modType = moduleType.getDeblankedStringValue(); String modName = moduleName.getDeblankedStringValue(); String tskName = taskName.getDeblankedStringValue(); - long dStart = SQLTypes.millisFromTimeStamp(dataStart.getValue()); - long dEnd = SQLTypes.millisFromTimeStamp(dataEnd.getValue()); - long procEnd = SQLTypes.millisFromTimeStamp(runEnd.getValue()); + + Long dEnd = null, dStart = null, procEnd = null; + dStart = SQLTypes.millisFromTimeStamp(dataStart.getValue()); + dEnd = SQLTypes.millisFromTimeStamp(dataEnd.getValue()); + procEnd = SQLTypes.millisFromTimeStamp(runEnd.getValue()); + if (dStart==null && dEnd==null && procEnd==null) return null; + String compStatus = completionCode.getDeblankedStringValue(); TaskStatus status = null; + if (compStatus==null) return null; try { status = TaskStatus.valueOf(TaskStatus.class, compStatus); } @@ -199,8 +204,13 @@ public class TaskLogging { System.out.printf("Uknown completion code \"%s\" for task %s ended at %s\n", compStatus, tskName, PamCalendar.formatDateTime(dEnd)); } String taskNote = note.getDeblankedStringValue(); - OldTaskData monData = new OldTaskData(status, dStart, dEnd, utc, procEnd, taskNote); - return monData; + if (dStart!=null && dEnd!=null && procEnd!=null) { + OldTaskData monData = new OldTaskData(status, dStart, dEnd, utc, procEnd, taskNote); + return monData; + } + else { + return null; + } } /** diff --git a/src/pamViewFX/PamGuiFX.java b/src/pamViewFX/PamGuiFX.java index 23f0f2ba..f6e87e84 100644 --- a/src/pamViewFX/PamGuiFX.java +++ b/src/pamViewFX/PamGuiFX.java @@ -48,6 +48,11 @@ public class PamGuiFX extends StackPane implements PamViewInterface { */ private PamTabPane mainTabPane; + /** + * The preferred width of the side pane. + */ + public static final double SIDE_PANE_PREF_WIDTH = 250; + // /** // * Icon for menu // */ @@ -157,7 +162,9 @@ public class PamGuiFX extends StackPane implements PamViewInterface { /**create right hiding pane**/ sidePaneContent=new PamVBox(); - sidePaneContent.setPrefWidth(250); + sidePaneContent.setPrefWidth(SIDE_PANE_PREF_WIDTH); + sidePaneContent.setPadding(new Insets(25,5,5,5)); //give quite abit of spacing at the top so that there is room for close button + sidePaneContent.setMinWidth(0); hidingSidePane=new HidingPane(Side.RIGHT, sidePaneContent, this, false); hidingSidePane.showHidePane(false); @@ -176,7 +183,7 @@ public class PamGuiFX extends StackPane implements PamViewInterface { // showButton.prefWidthProperty().addListener((listener)->{ // mainTabPane.layout(); //Don't need this // }); - + hidingSidePane.getTimeLineShow().setOnFinished((value)->{ showButtonRight.setPrefWidth(1); showButtonRight.setVisible(false); @@ -187,6 +194,7 @@ public class PamGuiFX extends StackPane implements PamViewInterface { showButtonRight.setPrefWidth(40); showButtonRight.setVisible(true); hidingSidePane.getHideButton().setVisible(false); + //sidePaneContent.setVisible(false); layout.layout(); }); diff --git a/src/pamViewFX/fxNodes/PamHBox.java b/src/pamViewFX/fxNodes/PamHBox.java index 27517bf0..ed7839c1 100644 --- a/src/pamViewFX/fxNodes/PamHBox.java +++ b/src/pamViewFX/fxNodes/PamHBox.java @@ -24,4 +24,5 @@ public class PamHBox extends HBox { // TODO Auto-generated constructor stub } + } diff --git a/src/pamViewFX/fxNodes/PamSpinner.java b/src/pamViewFX/fxNodes/PamSpinner.java index 4b293e44..bf0b1c6c 100644 --- a/src/pamViewFX/fxNodes/PamSpinner.java +++ b/src/pamViewFX/fxNodes/PamSpinner.java @@ -13,41 +13,55 @@ import javafx.util.StringConverter; */ public class PamSpinner extends Spinner{ + + /** + * Default widths are way off in JavaFX for spinners. + */ +// private static final double PAMSPINNER_PREF_WIDTH = USE_COMPUTED_SIZE; + private static final double PAMSPINNER_PREF_WIDTH = 100; + public PamSpinner() { super(); + this.setPrefWidth(PAMSPINNER_PREF_WIDTH); // TODO Auto-generated constructor stub } public PamSpinner(double min, double max, double initialValue, double amountToStepBy) { super(min, max, initialValue, amountToStepBy); + this.setPrefWidth(PAMSPINNER_PREF_WIDTH); addDefocusConverter(); } public PamSpinner(double min, double max, double initialValue) { super(min, max, initialValue); + this.setPrefWidth(PAMSPINNER_PREF_WIDTH); addDefocusConverter(); } public PamSpinner(int min, int max, int initialValue, int amountToStepBy) { super(min, max, initialValue, amountToStepBy); + this.setPrefWidth(PAMSPINNER_PREF_WIDTH); addDefocusConverter(); } public PamSpinner(int min, int max, int initialValue) { super(min, max, initialValue); + this.setPrefWidth(PAMSPINNER_PREF_WIDTH); addDefocusConverter(); } public PamSpinner(ObservableList arg0) { super(arg0); + this.setPrefWidth(PAMSPINNER_PREF_WIDTH); addDefocusConverter(); } public PamSpinner(SpinnerValueFactory arg0) { super(arg0); addDefocusConverter(); + this.setPrefWidth(PAMSPINNER_PREF_WIDTH); } /** diff --git a/src/pamViewFX/fxNodes/connectionPane/structures/ExtensionSocketStructure.java b/src/pamViewFX/fxNodes/connectionPane/structures/ExtensionSocketStructure.java index 519ec75d..269a6df0 100644 --- a/src/pamViewFX/fxNodes/connectionPane/structures/ExtensionSocketStructure.java +++ b/src/pamViewFX/fxNodes/connectionPane/structures/ExtensionSocketStructure.java @@ -34,6 +34,8 @@ public class ExtensionSocketStructure extends StandardConnectionNode implements * The colour of the extension socket body */ private static Color bodyColour = Color.DODGERBLUE; + + protected Shape circle; /** * Extension structure construction. @@ -69,7 +71,7 @@ public class ExtensionSocketStructure extends StandardConnectionNode implements @Override public ConnectionNodeBody createNodeBody() { - Circle circle = new Circle(DEFAULT_BODY_WIDTH/2,DEFAULT_BODY_WIDTH/2, DEFAULT_BODY_WIDTH/2); + circle = new Circle(DEFAULT_BODY_WIDTH/2,DEFAULT_BODY_WIDTH/2, DEFAULT_BODY_WIDTH/2); circle.setFill(bodyColour); ConnectionNodeBody connectionNodeBody = new ConnectionNodeBody(this); @@ -79,7 +81,6 @@ public class ExtensionSocketStructure extends StandardConnectionNode implements connectionNodeBody.getChildren().add(circle); - connectionNodeBody.setPrefHeight(DEFAULT_BODY_WIDTH); connectionNodeBody.setPrefWidth(DEFAULT_BODY_WIDTH); diff --git a/src/pamViewFX/fxNodes/flipPane/PamFlipPane.java b/src/pamViewFX/fxNodes/flipPane/PamFlipPane.java new file mode 100644 index 00000000..1f0a4ca8 --- /dev/null +++ b/src/pamViewFX/fxNodes/flipPane/PamFlipPane.java @@ -0,0 +1,132 @@ +package pamViewFX.fxNodes.flipPane; + +import javafx.geometry.Insets; +import javafx.geometry.Orientation; +import javafx.geometry.Pos; +import javafx.scene.control.Label; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.paint.Color; +import pamViewFX.PamGuiManagerFX; +import pamViewFX.fxGlyphs.PamGlyphDude; +import pamViewFX.fxNodes.PamBorderPane; +import pamViewFX.fxNodes.PamButton; +import pamViewFX.fxNodes.PamHBox; + +/** + * Flip pane which has is supposed to be used for advanced settings. The front + * of the pane is to be used for standard settings and the pane can then flip to + * the back to show advanced settings. A back button is included in the back + * pane which can be used to flip the pane back to the standard settings. The + * front pane needs a control that calls flipPane.toBack() to show the advanced + * pane. + * + * @author Jamie Macaulay + * + */ +public class PamFlipPane extends FlipPane { + + public static final double FLIP_TIME =250; //milliseconds - the default is 700ms whihc is way too long. + + private PamBorderPane advPane; + + private PamBorderPane frontPane; + + private Label advLabel; + + private PamButton backButton; + + + public PamFlipPane() { + super(); + this.advPane = createAdvSettingsPane(); + this.getFront().getChildren().add(frontPane = new PamBorderPane()); + this.getBack().getChildren().add(advPane); + this.setFlipTime(FLIP_TIME); + + } + + public PamFlipPane(Orientation FLIP_DIRECTION) { + super(FLIP_DIRECTION); + this.advPane = createAdvSettingsPane(); + this.getFront().getChildren().add(frontPane = new PamBorderPane()); + this.getBack().getChildren().add(advPane); + this.setFlipTime(FLIP_TIME); + } + + /** + * Get the front pane. + * @return the front pane. + */ + public PamBorderPane getFrontPane() { + return frontPane; + } + + /** + * Get the back pane. + * @return the back pane. + */ + public PamBorderPane getBackPane() { + return advPane; + } + + /** + * Convenience duplicate of getBackPane(). + * @return the back pane. + */ + public PamBorderPane getAdvPane() { + return advPane; + } + + + /** + * Create the advanced settings pane which can be accessed by DAQ panes if needed. + */ + private PamBorderPane createAdvSettingsPane() { + + backButton = new PamButton(); + backButton.setGraphic(PamGlyphDude.createPamIcon("mdi2c-chevron-left", Color.WHITE, PamGuiManagerFX.iconSize)); + + backButton.setOnAction((action)->{ + // System.out.println("FLIP BACK TO FRONT"); + this.flipToFront(); + }); + + //backButton.setPrefWidth(150); + + PamBorderPane advPane = new PamBorderPane(); + advPane.setPadding(new Insets(5,5,5,5)); + + PamHBox buttonHolder = new PamHBox(); + + buttonHolder.setBackground(null); + //buttonHolder.setStyle("-fx-background-color: red;"); + buttonHolder.setAlignment(Pos.CENTER_LEFT); + buttonHolder.getChildren().addAll(backButton, advLabel = new Label("Adv. Settings")); + advLabel.setAlignment(Pos.CENTER); + advLabel.setMaxWidth(Double.MAX_VALUE); //need to make sure label is in center. + PamGuiManagerFX.titleFont2style(advLabel); + + advLabel.setAlignment(Pos.CENTER); + HBox.setHgrow(advLabel, Priority.ALWAYS); + + advPane.setTop(buttonHolder); + + return advPane; + + } + + + public Label getAdvLabel() { + return advLabel; + } + + public void setAdvLabel(Label advLabel) { + this.advLabel = advLabel; + } + + public PamButton getBackButton() { + return backButton; + } + +} diff --git a/src/pamViewFX/fxNodes/sliders/skin/PamSliderSkin.java b/src/pamViewFX/fxNodes/sliders/skin/PamSliderSkin.java index f008b044..37028cd9 100644 --- a/src/pamViewFX/fxNodes/sliders/skin/PamSliderSkin.java +++ b/src/pamViewFX/fxNodes/sliders/skin/PamSliderSkin.java @@ -1,46 +1,93 @@ package pamViewFX.fxNodes.sliders.skin; +import javafx.geometry.Orientation; import javafx.scene.Node; import javafx.scene.control.Slider; import javafx.scene.control.skin.SliderSkin; +import javafx.scene.layout.Pane; +import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import pamViewFX.fxNodes.utilsFX.PamUtilsFX; //import com.sun.javafx.scene.control.skin.SliderSkin; public class PamSliderSkin extends SliderSkin { - + /** * Reference to the slider track. */ - private Node track; - - private Slider slider; + private Pane track; + + private Slider slider; + + private StackPane topBar; + + private Pane thumb; public PamSliderSkin(Slider slider) { super(slider); this.slider=slider; - track = slider.lookup(".track"); - setTrackColor(Color.RED); + track = (Pane) slider.lookup(".track"); + thumb = (Pane) slider.lookup(".thumb"); + initTopBar(); + setTrackColor(Color.RED); } - + + + /** + * Create the top bar. + */ + public void initTopBar(){ + topBar=new StackPane(); + //TODO-need to sort for horizontal + if (slider.getOrientation()==Orientation.VERTICAL){ + topBar.layoutXProperty().bind(track.layoutXProperty()); + } + else { + topBar.layoutYProperty().bind(track.layoutYProperty()); + } + // topBar.setStyle("-fx-background-color: red;"); + //topBar.setSty + getChildren().add(topBar); + thumb.toFront(); + } + + @Override protected void layoutChildren(final double x, final double y, final double w, final double h) { super.layoutChildren(x, y, w, h); + double rangeStart; + if (track==null) return; + //now resize the top bar. + if (slider.getOrientation()==Orientation.VERTICAL){ + rangeStart=thumb.getLayoutY()+thumb.getHeight(); + topBar.layoutYProperty().setValue(0); + topBar.resize(track.getWidth(), rangeStart+1); + } + else { + rangeStart=thumb.getLayoutX()+thumb.getWidth(); + topBar.layoutXProperty().setValue(0); + topBar.resize(rangeStart+1, track.getHeight()); + } }; - + public void setTrackColor(Color trackCol){ - track = slider.lookup(".track"); -// int r = (int) (trackCol.getRed() * 255); -// int g = (int) (trackCol.getGreen() * 255); -// int b = (int) (trackCol.getBlue() * 255); -// String str = String.format("#%02X%02X%02X;", r, g, b); - //28/03/2017 - had to change to css as adding to a scroll pane seemed ot override background. - track.setStyle("-fx-background-color: " + PamUtilsFX.color2Hex(trackCol)); + track = (Pane) slider.lookup(".track"); + thumb = (Pane) slider.lookup(".thumb"); + + // int r = (int) (trackCol.getRed() * 255); + // int g = (int) (trackCol.getGreen() * 255); + // int b = (int) (trackCol.getBlue() * 255); + // String str = String.format("#%02X%02X%02X;", r, g, b); + //28/03/2017 - had to change to css as adding to a scroll pane seemed ot override background. + + if (topBar!=null) topBar.setStyle("-fx-background-color: " + PamUtilsFX.color2Hex(trackCol) + "; -fx-background-radius: " + 6 + "; -fx-border-radius: " + + 6 + " ; -fx-border-color: none;"); + //((Region) track).setBackground(new Background(new BackgroundFill(Color.RED, new CornerRadii(2), Insets.EMPTY))); } diff --git a/src/pamViewFX/fxNodes/utilityPanes/FilterPaneFX.java b/src/pamViewFX/fxNodes/utilityPanes/FilterPaneFX.java index ef9e42bb..c758442f 100644 --- a/src/pamViewFX/fxNodes/utilityPanes/FilterPaneFX.java +++ b/src/pamViewFX/fxNodes/utilityPanes/FilterPaneFX.java @@ -15,6 +15,7 @@ import pamViewFX.fxNodes.pamDialogFX.PamDialogFX; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.geometry.Insets; +import javafx.geometry.Orientation; import javafx.geometry.Side; import javafx.scene.Node; import javafx.scene.chart.NumberAxis; @@ -35,10 +36,10 @@ import PamController.SettingsPane; public class FilterPaneFX extends SettingsPane { - + private String[] filterNames = { "None", "IIR Butterworth", "IIR Chebyshev", "FIR Filter (Window Method)", "Arbitrary FIR Filter"}; - + /** * Combo box for selecting filter types. */ @@ -53,12 +54,12 @@ public class FilterPaneFX extends SettingsPane { * Text field for lower frequency */ private PamSpinner lowPass; - + /** * Spinner to allow user to change filter order. */ private PamSpinner filterOrder; - + /** * Spinner to allow user to change filter order. */ @@ -81,7 +82,7 @@ public class FilterPaneFX extends SettingsPane { private PamRadioButton logScale; private PamRadioButton linScale; - + /** * Some default frequency values for the high and low pass frequency spinner. */ @@ -106,12 +107,12 @@ public class FilterPaneFX extends SettingsPane { * Plot pane for the graph axis. */ private PamLineChart plotLogChart; - + /** * Line chart without logarithmic frequency axis. */ private PamLineChart plotLinChart; - + /** * Log axis for log chart */ @@ -126,15 +127,28 @@ public class FilterPaneFX extends SettingsPane { * Ripple label */ private Label rippleLabel; - - private PamBorderPane mainPane = new PamBorderPane(); - public FilterPaneFX () { - super(null); - mainPane.setLeft(createFilterPane()); - mainPane.setCenter(createBodeGraph()); - } + private PamBorderPane mainPane = new PamBorderPane(); + public FilterPaneFX () { + this(Orientation.HORIZONTAL); + } + + + public FilterPaneFX (Orientation orientaiton) { + super(null); + if (orientaiton == Orientation.HORIZONTAL) { + mainPane.setLeft(createFilterPane()); + mainPane.setCenter(createBodeGraph()); + } + else { + mainPane.setTop(createFilterPane()); + mainPane.setBottom(createBodeGraph()); + } + } + + + /** * Create the filter pane. This contains controls to change filter types and shows a graph of the current filter. * @return pane with controls to change filter params. @@ -142,14 +156,14 @@ public class FilterPaneFX extends SettingsPane { public Node createFilterPane(){ controlPane=new PamVBox(); controlPane.setSpacing(5); - + //label title Label title=new Label("Filter type"); PamGuiManagerFX.titleFont2style(title); -// title.setFont(PamGuiManagerFX.titleFontSize2); + // title.setFont(PamGuiManagerFX.titleFontSize2); controlPane.getChildren().add(title); - + //create combo box filterTypes=new PamComboBox(); for (int i=0; i { updateBodeGraph(); enableControls(); }); - filterTypes.setMaxWidth(Double.MAX_VALUE); + filterTypes.setMaxWidth(Double.MAX_VALUE); HBox.setHgrow(filterTypes, Priority.ALWAYS); controlPane.getChildren().add(filterTypes); - + //Radio buttons and frequency response Label freqResponse=new Label("Frequency Response"); -// freqResponse.setFont(PamGuiManagerFX.titleFontSize2); + // freqResponse.setFont(PamGuiManagerFX.titleFontSize2); PamGuiManagerFX.titleFont2style(freqResponse); controlPane.getChildren().add(freqResponse); - + //radio buttons final ToggleGroup group = new ToggleGroup(); -// group.selectedToggleProperty().addListener((obs, old_val, new_val)-> { -// if (group.getSelectedToggle() != null) { -// -// } -// }); + // group.selectedToggleProperty().addListener((obs, old_val, new_val)-> { + // if (group.getSelectedToggle() != null) { + // + // } + // }); PamVBox radioButtonBox=new PamVBox(); radioButtonBox.setSpacing(3); @@ -198,7 +212,7 @@ public class FilterPaneFX extends SettingsPane { updateBodeGraph(); }); radioButtonBox.getChildren().add(bandPassrb); - + bandStoprb = new PamRadioButton("Band Stop"); bandStoprb.setToggleGroup(group); bandStoprb.setOnAction((action)->{ @@ -207,7 +221,7 @@ public class FilterPaneFX extends SettingsPane { updateBodeGraph(); }); radioButtonBox.getChildren().add(bandStoprb); - + lowPassrb = new PamRadioButton("Low Pass"); lowPassrb.setToggleGroup(group); lowPassrb.setOnAction((action)->{ @@ -216,17 +230,17 @@ public class FilterPaneFX extends SettingsPane { updateBodeGraph(); }); radioButtonBox.getChildren().add(lowPassrb); - + //create frequency text boxes PamGridPane gridPaneFreq=new PamGridPane(); gridPaneFreq.setHgap(5); gridPaneFreq.setVgap(5); - + //lost of filter order sizes- anyone using >500 will be crazy anyway -// ObservableList freqList=FXCollections.observableArrayList(); -// for (int i=0; i freqList=FXCollections.observableArrayList(); + // for (int i=0; i(10.,500000.,2000.,2000.); highCut.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_HORIZONTAL); @@ -256,21 +270,21 @@ public class FilterPaneFX extends SettingsPane { gridPaneFreq.add(new Label("Low Pass"), 0, 1); gridPaneFreq.add(lowPass, 1, 1); gridPaneFreq.add(new Label("Hz"), 2, 1); - + PamHBox filterSettings=new PamHBox(); //holds radio buttons and frquency text fields. filterSettings.getChildren().addAll(radioButtonBox, gridPaneFreq); filterSettings.setSpacing(15); controlPane.getChildren().add(filterSettings); - - + + //next create filter order settings Label filterOrderLabel=new Label("Filter Order"); PamGuiManagerFX.titleFont2style(filterOrderLabel); -// filterOrderLabel.setFont(PamGuiManagerFX.titleFontSize2); + // filterOrderLabel.setFont(PamGuiManagerFX.titleFontSize2); controlPane.getChildren().add(filterOrderLabel); - + PamGridPane gridPaneOrder=new PamGridPane(); gridPaneOrder.setHgap(5); gridPaneOrder.setVgap(5); @@ -296,14 +310,14 @@ public class FilterPaneFX extends SettingsPane { }); gridPaneOrder.add(rippleLabel=new Label("Pass Band Ripple"), 0,1); gridPaneOrder.add( ripple, 1,1); - + controlPane.getChildren().add(gridPaneOrder); - + // TODO Auto-generated method stub return controlPane; } - + /** * Set correct filter type from filter type combo box selection. */ @@ -363,17 +377,17 @@ public class FilterPaneFX extends SettingsPane { filterParams.filterBand == FilterBand.BANDSTOP || filterParams.filterBand == FilterBand.LOWPASS) { if (filterParams.lowPassFreq > niquist) { - PamController.getInstance(); + PamController.getInstance(); PamDialogFX.showWarning(PamController.getMainStage(), "Filter Settings", "The low pass cut off frequency is too high"); - return null; + return null; } } if (filterParams.filterBand == FilterBand.BANDPASS || filterParams.filterBand == FilterBand.BANDSTOP || filterParams.filterBand == FilterBand.HIGHPASS) { if (filterParams.highPassFreq > niquist) { - PamDialogFX.showWarning(PamController.getMainStage(),"Filter Settings", "The high pass cut off frequency is too high"); - return null; + PamDialogFX.showWarning(PamController.getMainStage(),"Filter Settings", "The high pass cut off frequency is too high"); + return null; } } @@ -385,19 +399,19 @@ public class FilterPaneFX extends SettingsPane { return filterParams; } - + public void setSampleRate(float sampleRate) { this.sampleRate = sampleRate; filterMethod = FilterMethod.createFilterMethod(sampleRate, filterParams); } - - + + public Node createBodeGraph(){ - + pamBorderPane=new PamBorderPane(); //pamBorderPane.setPadding(new Insets(0, 0, 0, 10)); pamBorderPane.setPrefWidth(500); - + final ToggleGroup group = new ToggleGroup(); logScale = new PamRadioButton("Log Scale"); logScale.setOnAction((action)->{ @@ -409,22 +423,22 @@ public class FilterPaneFX extends SettingsPane { linScale.setOnAction((action)->{ setGraphLogAxis(!linScale.isSelected()); }); - + final PamHBox scalePane=new PamHBox(); scalePane.setPadding(new Insets(5)); scalePane.setSpacing(5); scalePane.getChildren().addAll(linScale, logScale); - + plotLogChart=createBodeChart(logarithmAxis=new LogarithmicAxis(10,50000)); plotLinChart=createBodeChart(new NumberAxis(0, 50000, 10000)); - + pamBorderPane.setTop(scalePane); pamBorderPane.setCenter(plotLogChart); return pamBorderPane; - + } - + /** * Convenience function to stop code repitition. Creates a line chart fro pane with specified x axis. * @param xAxis - x axis @@ -434,13 +448,13 @@ public class FilterPaneFX extends SettingsPane { PamLineChart plotChart=new PamLineChart(xAxis, new NumberAxis()); plotChart.setLegendVisible(false); plotChart.setCreateSymbols(false); - + plotChart.getXAxis().setLabel("Frequency (Hz)"); plotChart.getYAxis().setLabel("dB"); plotChart.getYAxis().setAutoRanging(false); plotChart.getXAxis().setSide(Side.TOP); - + /** * HACK. Make sure the graph updates once the axis has a width. */ @@ -459,7 +473,7 @@ public class FilterPaneFX extends SettingsPane { }); return plotChart; } - + @Override public Node getContentNode() { return mainPane; @@ -471,7 +485,7 @@ public class FilterPaneFX extends SettingsPane { setSettings(); } - + /** * Set controls to input params. */ @@ -516,19 +530,19 @@ public class FilterPaneFX extends SettingsPane { } -// highCut.setText(String.format("%1.1f", filterParams.highPassFreq)); + // highCut.setText(String.format("%1.1f", filterParams.highPassFreq)); highCut.getValueFactory().setValue(Double.valueOf(Float.valueOf(filterParams.highPassFreq).doubleValue())); -// lowCut.setText(String.format("%1.1f", filterParams.lowPassFreq)); + // lowCut.setText(String.format("%1.1f", filterParams.lowPassFreq)); lowPass.getValueFactory().setValue(Double.valueOf(Float.valueOf(filterParams.lowPassFreq).doubleValue())); filterOrder.getValueFactory().setValue(filterParams.filterOrder); setRippleParam(); - + logScale.setSelected(filterParams.scaleType == FilterParams.SCALE_LOG); linScale.setSelected(filterParams.scaleType == FilterParams.SCALE_LIN); - + filterMethod = FilterMethod.createFilterMethod(sampleRate, filterParams); - + //update control disable status enableControls(); //update graph @@ -536,7 +550,7 @@ public class FilterPaneFX extends SettingsPane { setXAxisRange(10, sampleRate/2.); } - + void setRippleParam() { int filtType = filterTypes.getSelectionModel().getSelectedIndex(); switch(filtType) { @@ -549,7 +563,7 @@ public class FilterPaneFX extends SettingsPane { break; } } - + private void enableControls() { int filterType = filterTypes.getSelectionModel().getSelectedIndex(); boolean haveFilter = filterType > 0; @@ -573,15 +587,15 @@ public class FilterPaneFX extends SettingsPane { break; } boolean isArb = filterType == 4; -// normalPanel.setVisible(isArb == false); -// arbPanel.setVisible(isArb); + // normalPanel.setVisible(isArb == false); + // arbPanel.setVisible(isArb); } @Override public String getName() { return "Filter Pane"; } - + /** * A VBox which holds all the main controls for the pane but not the graph. Can be used to add in custom controls such * as a source level pane. @@ -590,15 +604,15 @@ public class FilterPaneFX extends SettingsPane { public PamVBox getControlPane() { return controlPane; } - - + + /************Bode Graph************/ - + private int yScaleIndex = 0; - + private double[] yScales = {-90, -60, -30}; - + /** * Set the graph axis to a log or linear scale. * @param log - true to set chart with frequency log scale. @@ -614,7 +628,7 @@ public class FilterPaneFX extends SettingsPane { //setYAxisRange(yScales[0],10); updateBodeGraph(); } - + /** * Update the bode graph */ @@ -629,7 +643,7 @@ public class FilterPaneFX extends SettingsPane { plotLinChart.getData().add(createFilterPoints((ValueAxis) plotLinChart.getXAxis())); } } - + /** * Set y axis of graphs */ @@ -639,7 +653,7 @@ public class FilterPaneFX extends SettingsPane { ((NumberAxis) plotLinChart.getXAxis()).setLowerBound(0); ((NumberAxis) plotLinChart.getXAxis()).setUpperBound(max); } - + //Set x axis of graphs. private void setYAxisRange(double min, double max){ //System.out.println("Set y axis range: min "+min+" max "+max); @@ -647,13 +661,13 @@ public class FilterPaneFX extends SettingsPane { ((NumberAxis) plotLinChart.getYAxis()).setUpperBound(max); plotLinChart.getYAxis().requestLayout(); plotLinChart.getYAxis().requestAxisLayout(); - + ((NumberAxis) plotLogChart.getYAxis()).setLowerBound(min); ((NumberAxis) plotLogChart.getYAxis()).setUpperBound(max); plotLogChart.getYAxis().requestLayout(); plotLogChart.getYAxis().requestAxisLayout(); } - + /** * Get the scale type from the graph. * @return @@ -666,7 +680,7 @@ public class FilterPaneFX extends SettingsPane { return FilterParams.SCALE_LIN; } } - + /** * Create a data series for a filter. The function bases the data points on the pixel length of the chart frequency axis. This * is important because a log scale is used which would mess up if a data point was created at regular frequency, rather than pixel @@ -675,17 +689,17 @@ public class FilterPaneFX extends SettingsPane { * @return a data series to add to the line chart */ private Series createFilterPoints(ValueAxis axis){ - + Series series = new Series(); /* * It's on a log scale, so set up enough points to fill the plot on * a log scale */ //total number of pixels on axis -// double pixels=Math.abs(axis.getDisplayPosition(axis.getLowerBound())-axis.getDisplayPosition(axis.getUpperBound())); + // double pixels=Math.abs(axis.getDisplayPosition(axis.getLowerBound())-axis.getDisplayPosition(axis.getUpperBound())); double pixels=axis.getWidth(); int nPoints = (int) Math.max(pixels, 1024); - + //System.out.println("Update bode graph WIDTH: "+ pixels+ " height: " +this.plotLogChart.getYAxis().getHeight()+ this.plotLogChart.getWidth()); double xScale = pixels / (double) nPoints; @@ -693,7 +707,7 @@ public class FilterPaneFX extends SettingsPane { double[] freqPoints = new double[nPoints]; double[] gainPoints = new double[nPoints]; double[] phasePoints = new double[nPoints]; - + int i=0; while (i < freqPoints.length) { freqPoints[i] = axis.getValueForDisplay(i*xScale).doubleValue(); @@ -702,17 +716,17 @@ public class FilterPaneFX extends SettingsPane { / filterMethod.getFilterGainConstant(); phasePoints[i] = filterMethod.getFilterPhase( freqPoints[i] / sampleRate * 2 * Math.PI); -// System.out.println("freqPoints[i]: "+freqPoints[i] +" gainPoints[i] "+gainPoints[i]+ -// " nPoints: "+nPoints+" xScale "+xScale+ " sampleRate: "+sampleRate + " pixels "+pixels); + // System.out.println("freqPoints[i]: "+freqPoints[i] +" gainPoints[i] "+gainPoints[i]+ + // " nPoints: "+nPoints+" xScale "+xScale+ " sampleRate: "+sampleRate + " pixels "+pixels); series.getData().add(new Data(freqPoints[i], 20. * Math.log10(gainPoints[i]))); i++; } - + return series; - + } - + private void checkYScale() { double yScale = 0; if (plotLogChart.getYAxis() == null) return; diff --git a/src/pamViewFX/fxNodes/utilityPanes/FreqBandPane.java b/src/pamViewFX/fxNodes/utilityPanes/FreqBandPane.java index 058699d1..590dda3b 100644 --- a/src/pamViewFX/fxNodes/utilityPanes/FreqBandPane.java +++ b/src/pamViewFX/fxNodes/utilityPanes/FreqBandPane.java @@ -72,7 +72,7 @@ public class FreqBandPane extends PamGridPane { if (after>sampleRate/2.) highPassFreq.getValueFactory().setValue(sampleRate/2.); }); highPassFreq.setEditable(true); - highPassFreq.setPrefWidth(140); + //highPassFreq.setPrefWidth(140); //highCut.setPrefColumnCount(6); if (orientation==Orientation.VERTICAL){ @@ -94,7 +94,7 @@ public class FreqBandPane extends PamGridPane { }); lowPassFreq.setEditable(true); - lowPassFreq.setPrefWidth(140); + //lowPassFreq.setPrefWidth(140); if (orientation==Orientation.VERTICAL){ diff --git a/src/pamViewFX/fxNodes/utilityPanes/SimpleFilterPaneFX.java b/src/pamViewFX/fxNodes/utilityPanes/SimpleFilterPaneFX.java index cf3c1f52..fd7e288f 100644 --- a/src/pamViewFX/fxNodes/utilityPanes/SimpleFilterPaneFX.java +++ b/src/pamViewFX/fxNodes/utilityPanes/SimpleFilterPaneFX.java @@ -183,6 +183,7 @@ public class SimpleFilterPaneFX extends DynamicSettingsPane{ @Override public FFTFilterParams getParams(FFTFilterParams fftFilterParams) { + if (fftFilterParams==null) fftFilterParams=new FFTFilterParams(); fftFilterParams.filterBand = getBand(); try { //if (fftFilterParams.filterBand != FilterBand.HIGHPASS) { diff --git a/src/rawDeepLearningClassifier/dataPlotFX/DLPredictionPane.java b/src/rawDeepLearningClassifier/dataPlotFX/DLPredictionPane.java index f2b68a02..41d26118 100644 --- a/src/rawDeepLearningClassifier/dataPlotFX/DLPredictionPane.java +++ b/src/rawDeepLearningClassifier/dataPlotFX/DLPredictionPane.java @@ -110,6 +110,9 @@ public class DLPredictionPane extends PamBorderPane implements TDSettingsPane { private void layoutColourPanes(DLClassName[] classNames){ + if (classNames==null) return; + + //System.out.println("Class name map: " + dlPredictionPlotInfoFX.getDlControl().getDLParams().classNameMap); ArrayList colourPanes = new ArrayList(); diff --git a/src/rawDeepLearningClassifier/dataPlotFX/DLPredictionPlotInfoFX.java b/src/rawDeepLearningClassifier/dataPlotFX/DLPredictionPlotInfoFX.java index 61386c23..90672357 100644 --- a/src/rawDeepLearningClassifier/dataPlotFX/DLPredictionPlotInfoFX.java +++ b/src/rawDeepLearningClassifier/dataPlotFX/DLPredictionPlotInfoFX.java @@ -307,7 +307,13 @@ public class DLPredictionPlotInfoFX extends GenericLinePlotInfo { @Override public double[][] getDetData(PamDataUnit pamDataUnit) { double[] data = PamArrayUtils.float2Double(((DLDataUnit) pamDataUnit).getPredicitionResult().getPrediction()); - return new double[][] {data}; + + double[][] dataD = new double[data.length][]; + for (int i=0; i { defaultTogglePane = createTogglePane(); transfromPane = new DLImageTransformPane(); - mainPane.setPadding(new Insets(5,5,5,5)); + mainPane.setPadding(new Insets(2,2,2,2)); + mainPane.setPrefWidth(400); } diff --git a/src/rawDeepLearningClassifier/dlClassification/animalSpot/StandardModelPane.java b/src/rawDeepLearningClassifier/dlClassification/animalSpot/StandardModelPane.java index 57c7d13c..ce694ccf 100644 --- a/src/rawDeepLearningClassifier/dlClassification/animalSpot/StandardModelPane.java +++ b/src/rawDeepLearningClassifier/dlClassification/animalSpot/StandardModelPane.java @@ -18,10 +18,14 @@ import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.control.Label; +import javafx.scene.control.Labeled; import javafx.scene.control.ProgressIndicator; import javafx.scene.control.Spinner; import javafx.scene.control.Tooltip; import javafx.scene.control.Alert.AlertType; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.paint.Color; import javafx.scene.text.Font; import javafx.scene.text.FontWeight; import javafx.stage.FileChooser; @@ -34,6 +38,7 @@ import pamViewFX.fxNodes.PamGridPane; import pamViewFX.fxNodes.PamHBox; import pamViewFX.fxNodes.PamSpinner; import pamViewFX.fxNodes.PamVBox; +import pamViewFX.fxNodes.flipPane.FlipPane; import rawDeepLearningClassifier.dlClassification.DLClassiferModel; /** @@ -111,12 +116,14 @@ public abstract class StandardModelPane extends SettingsPane { ketosDLParams.binaryClassification[i] = true; //set default to true. } } - + + if (ketosParams.classNames!=null) { + ketosDLParams.classNames = dlControl.getClassNameManager().makeClassNames(ketosParams.classNames); + } // if (dlParams.classNames!=null) { // for (int i = 0; i{ + public static double MAX_WIDTH = 250; + /** * The source for the FFT data source. */ @@ -111,6 +114,10 @@ public class RawDLSettingsPane extends SettingsPane{ private Label infoLabel; + private Object flipPane; + + private PopupControl advLabel; + public RawDLSettingsPane(DLControl dlControl){ super(null); this.dlControl=dlControl; @@ -128,8 +135,10 @@ public class RawDLSettingsPane extends SettingsPane{ mainPane.setCenter(createDLPane()); mainPane.setPadding(new Insets(5,5,5,5)); mainPane.setMinHeight(400); - mainPane.setMaxWidth(250); - mainPane.setPrefWidth(250); + mainPane.setMaxWidth(MAX_WIDTH); + mainPane.setPrefWidth(MAX_WIDTH); + //this.getAdvPane().setMaxWidth(MAX_WIDTH); + //mainPane.getStylesheets().add(PamStylesManagerFX.getPamStylesManagerFX().getCurStyle().getDialogCSS()); @@ -253,7 +262,7 @@ public class RawDLSettingsPane extends SettingsPane{ return vBox; } - + /** * Create the data selector. @@ -483,7 +492,7 @@ public class RawDLSettingsPane extends SettingsPane{ @Override - public Node getContentNode() { + public Pane getContentNode() { return mainPane; } @@ -501,4 +510,6 @@ public class RawDLSettingsPane extends SettingsPane{ return sourcePane.getSource(); } + + } diff --git a/src/rawDeepLearningClassifier/layoutFX/dlTransfroms/DLTransformImage.java b/src/rawDeepLearningClassifier/layoutFX/dlTransfroms/DLTransformImage.java index 391bdeb7..d1051b9f 100644 --- a/src/rawDeepLearningClassifier/layoutFX/dlTransfroms/DLTransformImage.java +++ b/src/rawDeepLearningClassifier/layoutFX/dlTransfroms/DLTransformImage.java @@ -39,7 +39,6 @@ import rawDeepLearningClassifier.layoutFX.exampleSounds.ExampleSoundFactory.Exam */ public abstract class DLTransformImage extends PamBorderPane{ - /** * Plot pane. */ @@ -70,7 +69,6 @@ public abstract class DLTransformImage extends PamBorderPane{ */ private SpectrogramImage specImage = null; - /** * The current 1D transform data. */ @@ -97,7 +95,7 @@ public abstract class DLTransformImage extends PamBorderPane{ private RangeSlider timeSlider; /** - * tIME BINS. + * Time bins. */ private int[] timeBins = new int[2]; @@ -139,6 +137,7 @@ public abstract class DLTransformImage extends PamBorderPane{ plotPane.repaint(); }); transformschoiceBox.setConverter(new DLTransformConverter()); + transformschoiceBox.setPrefWidth(170); plotPane.getPlotCanvas().widthProperty().addListener((obsval, oldval, newval)->{ plotPane.repaint(); @@ -174,6 +173,7 @@ public abstract class DLTransformImage extends PamBorderPane{ updateExampleSound(newval); }); speciesChoiceBox.getSelectionModel().select(0); + speciesChoiceBox.setPrefWidth(170); PamHBox hBox = new PamHBox(); hBox.setAlignment(Pos.CENTER_RIGHT); diff --git a/src/rawDeepLearningClassifier/layoutFX/dlTransfroms/DataTransformPaneFactory.java b/src/rawDeepLearningClassifier/layoutFX/dlTransfroms/DataTransformPaneFactory.java index 6811d63f..c8010c09 100644 --- a/src/rawDeepLearningClassifier/layoutFX/dlTransfroms/DataTransformPaneFactory.java +++ b/src/rawDeepLearningClassifier/layoutFX/dlTransfroms/DataTransformPaneFactory.java @@ -77,7 +77,7 @@ public class DataTransformPaneFactory { ((SimpleTransformPane) settingsPane).setSpinnerMinMaxValues(1, -1000.0, 1000.0, 0.1); break; case SPECCROPINTERP: - settingsPane = new SimpleTransformPane((SimpleTransform) dlTransfrom, new String[]{"Min. Freq. ", "Max. Freq. ", " No. bins "}, new String[]{"Hz", "Hz", ""}, 2); + settingsPane = new SimpleTransformPane((SimpleTransform) dlTransfrom, new String[]{"Min. Freq. ", "Max. Freq. ", "No. bins "}, new String[]{"Hz", "Hz", ""}, 2); ((SimpleTransformPane) settingsPane).setSpinnerMinMaxValues(0, 0.0, 500000.0, 100.); //hmmmm would be nice to have the sample rate here... ((SimpleTransformPane) settingsPane).setSpinnerMinMaxValues(1, 0.0, 500000.0, 100.); ((SimpleTransformPane) settingsPane).setSpinnerMinMaxValues(2, 0, Integer.MAX_VALUE, 10); diff --git a/src/rawDeepLearningClassifier/layoutFX/dlTransfroms/FFTTransformPane.java b/src/rawDeepLearningClassifier/layoutFX/dlTransfroms/FFTTransformPane.java index 8f3eb2b6..3fb80d6e 100644 --- a/src/rawDeepLearningClassifier/layoutFX/dlTransfroms/FFTTransformPane.java +++ b/src/rawDeepLearningClassifier/layoutFX/dlTransfroms/FFTTransformPane.java @@ -25,6 +25,7 @@ public class FFTTransformPane extends SimpleTransformPane { //System.out.println("Create step list: " + createStepList().size()); PamSpinner spinner = new PamSpinner(createStepList()); spinner.getValueFactory().setConverter(new NumberConverter()); + spinner.setPrefWidth(PREF_SPINNER_WIDITH); return spinner; } else return super.createSpinner(i); diff --git a/src/rawDeepLearningClassifier/layoutFX/dlTransfroms/SimpleTransformPane.java b/src/rawDeepLearningClassifier/layoutFX/dlTransfroms/SimpleTransformPane.java index 762b73f7..2d987963 100644 --- a/src/rawDeepLearningClassifier/layoutFX/dlTransfroms/SimpleTransformPane.java +++ b/src/rawDeepLearningClassifier/layoutFX/dlTransfroms/SimpleTransformPane.java @@ -29,7 +29,7 @@ public class SimpleTransformPane extends DLTransformPane { /** * The default spinner width. */ - protected static int prefSpinnerWidth = 80; + protected static int PREF_SPINNER_WIDITH = 70; int nParamCol=10; @@ -80,7 +80,7 @@ public class SimpleTransformPane extends DLTransformPane { gridPane.setHgap(5); gridPane.setVgap(5); - gridPane.setPadding(new Insets(5,5.,5.,15)); + gridPane.setPadding(new Insets(2,2,2,2)); PamSpinner spinner; @@ -139,7 +139,9 @@ public class SimpleTransformPane extends DLTransformPane { * @return a new spinner */ protected PamSpinner createSpinner(int i) { - return new PamSpinner(0.0, Double.MAX_VALUE, 2, 0.01); + PamSpinner spnner = new PamSpinner(0.0, Double.MAX_VALUE, 2, 0.01); + spnner.setPrefWidth(PREF_SPINNER_WIDITH); + return spnner; } /** diff --git a/src/rawDeepLearningClassifier/layoutFX/exampleSounds/ExampleSoundFactory.java b/src/rawDeepLearningClassifier/layoutFX/exampleSounds/ExampleSoundFactory.java index 3de58be3..020339f5 100644 --- a/src/rawDeepLearningClassifier/layoutFX/exampleSounds/ExampleSoundFactory.java +++ b/src/rawDeepLearningClassifier/layoutFX/exampleSounds/ExampleSoundFactory.java @@ -15,9 +15,14 @@ public class ExampleSoundFactory { * */ public enum ExampleSoundType { + BAT_CALL("Bat Call (Myotis daubentonii)"), - RIGHT_WHALE("Southern Right Whale (Eubalaena australis)"); + RIGHT_WHALE("Southern Right Whale (Eubalaena australis)"), + + MINKE_WHALE("Minke Whale (Balaenoptera spp.)"), + + HUMPBACK_WHALE("Humpback whale (Megaptera novaeangliae) "); private final String text; @@ -56,6 +61,16 @@ public class ExampleSoundFactory { path = getClass().getResource("/Resources/exampleSounds/southern_right_whale_clip2.wav"); exampleSound = new SimpleExampleSound(path); break; + case MINKE_WHALE: + //file = new File("src/rawDeepLearningClassifier/layoutFX/exampleSounds/southern_right_whale_clip2.wav"); + path = getClass().getResource("/Resources/exampleSounds/Minke_whale.wav"); + exampleSound = new SimpleExampleSound(path); + break; + case HUMPBACK_WHALE: + //file = new File("src/rawDeepLearningClassifier/layoutFX/exampleSounds/southern_right_whale_clip2.wav"); + path = getClass().getResource("/Resources/exampleSounds/Humpback_whale.wav"); + exampleSound = new SimpleExampleSound(path); + break; default: break; } diff --git a/src/soundPlayback/PlaybackControl.java b/src/soundPlayback/PlaybackControl.java index 1af9673b..f341ec74 100644 --- a/src/soundPlayback/PlaybackControl.java +++ b/src/soundPlayback/PlaybackControl.java @@ -144,6 +144,7 @@ public class PlaybackControl extends PamControlledUnit implements PamSettings { playbackSystem = findPlaybackSystem(sourceDataBlock); playbackProcess.noteNewSettings(); playbackSidePanel.newSettings(); + if (playBackGUI!=null) playBackGUI.notifyGUIChange(PamController.CHANGED_PROCESS_SETTINGS); // if (this.getSidePanel() != null){ // this.getSidePanel().getPanel().setVisible(!isRealTimePlayback()); // } diff --git a/src/soundPlayback/fx/FilterSidePane.java b/src/soundPlayback/fx/FilterSidePane.java new file mode 100644 index 00000000..b0d21ce3 --- /dev/null +++ b/src/soundPlayback/fx/FilterSidePane.java @@ -0,0 +1,110 @@ +package soundPlayback.fx; + +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.control.Tooltip; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.scene.layout.Priority; +import pamViewFX.PamGuiManagerFX; +import pamViewFX.fxGlyphs.PamGlyphDude; +import pamViewFX.fxNodes.PamBorderPane; +import pamViewFX.fxNodes.PamButton; +import pamViewFX.fxNodes.PamHBox; +import soundPlayback.preprocess.PlaybackFilter; +import soundPlayback.preprocess.PreProcessFXPane; + +public class FilterSidePane implements PreProcessFXPane { + + + private Label label; + + + private FilterSlider filterSlider; + + + private PlaybackFilter playBackFilter; + + + private PamBorderPane mainPane; + + + private PamButton defaultGainButton; + + + public FilterSidePane(PlaybackFilter playBackFilter) { + + this.playBackFilter = playBackFilter; + + filterSlider = new FilterSlider(); + + filterSlider.getSlider().setTooltip(new Tooltip("High pass filter the data before playback")); + filterSlider.addChangeListener((oldval, newVal, obsVal)->{ + filterChanged(); + + }); + + + defaultGainButton = new PamButton("off"); + defaultGainButton.setGraphic(PamGlyphDude.createPamIcon("mdi2r-refresh", PamGuiManagerFX.iconSize-3)); + defaultGainButton.setPrefWidth(70); + defaultGainButton.setOnAction((action)->{ + filterSlider.setDataValue(filterSlider.getMinValue()); + }); + + label = new Label("Filter"); + //label.setGraphic(PamGlyphDude.createPamIcon("mdi2f-filter", PamGuiManagerFX.iconSize)); + + PamHBox hBox = new PamHBox(); + hBox.setAlignment(Pos.CENTER_LEFT); + hBox.setSpacing(5); + hBox.getChildren().addAll(PamGlyphDude.createPamIcon("mdi2f-filter", PamGuiManagerFX.iconSize), filterSlider); + filterSlider.setMaxWidth(Double.MAX_VALUE); + HBox.setHgrow(filterSlider, Priority.ALWAYS); + + this.mainPane = new PamBorderPane(); + this.mainPane.setCenter(hBox); + + } + + protected void filterChanged() { + playBackFilter.setValue(filterSlider.getDataValue()); + sayFilter(); + } + + @Override + public void update() { + filterSlider.setDataValue(playBackFilter.getValue()); + sayFilter(); + } + + private void sayFilter() { + //playGainSlider.setTextLabel(playbackGain.getTextValue()); + label.setText(playBackFilter.getTextValue()); + defaultGainButton.setDisable(false); + if (playBackFilter.getValue()==filterSlider.getMinValue()) { + defaultGainButton.setDisable(true); + } + } + + + + @Override + public Pane getPane() { + return mainPane; + } + + + @Override + public Label getLabel() { + return label; + } + + @Override + public Node getDefaultButton() { + return defaultGainButton; + } + + +} \ No newline at end of file diff --git a/src/soundPlayback/fx/FilterSlider.java b/src/soundPlayback/fx/FilterSlider.java new file mode 100644 index 00000000..8fe6ed03 --- /dev/null +++ b/src/soundPlayback/fx/FilterSlider.java @@ -0,0 +1,60 @@ +package soundPlayback.fx; + + +/** + * Slider for the high pass filter sound out process. + * @author Jamie Macaulay + * + */ +public class FilterSlider extends PlaySliderPane { + + private static final double MIN = 0.5e-3; + + private static final double MAX = 0.5; + + private static final double NSTEP = 100; + + + public FilterSlider() { + super(); + } + + + @Override + public double valueToPos(double filter) { + if (filter <= MIN) { + return 0; + } + else { + double grad = (Math.log(MAX)-Math.log(MIN))/NSTEP; + int pos = (int) Math.round((Math.log(filter/MIN))/grad); + return pos; + } + } + + @Override + public double posToValue(double pos) { + if (pos == 0) { + return 0; + } + else if (pos >= NSTEP) { + return MAX; + } + else { + double grad = (Math.log(MAX)-Math.log(MIN))/NSTEP; + return Math.exp(pos*grad)*MIN; + } + } + + @Override + public double getMinValue() { + return 0; + } + + @Override + public double getMaxValue() { + return 100; + } + + +} diff --git a/src/soundPlayback/fx/PlayBackGUI.java b/src/soundPlayback/fx/PlayBackGUI.java index 5137cff3..9c37518d 100644 --- a/src/soundPlayback/fx/PlayBackGUI.java +++ b/src/soundPlayback/fx/PlayBackGUI.java @@ -67,6 +67,17 @@ public class PlayBackGUI extends PamControlledGUIFX { } + /** + * Allows the GUI to be notified of changes, e.g. in the PAMController + * @param flag - the change flag. + */ + public void notifyGUIChange(int flag) { + for (Pane sidePane: sidePanes) { + ((PlayBackSidePane) sidePane).newSettings(); + } + } + + } diff --git a/src/soundPlayback/fx/PlayBackSidePane.java b/src/soundPlayback/fx/PlayBackSidePane.java index 707b5909..544daed0 100644 --- a/src/soundPlayback/fx/PlayBackSidePane.java +++ b/src/soundPlayback/fx/PlayBackSidePane.java @@ -1,11 +1,16 @@ package soundPlayback.fx; import java.util.ArrayList; - +import javafx.geometry.Insets; import javafx.geometry.Orientation; +import javafx.geometry.Pos; +import javafx.scene.Node; import javafx.scene.control.Label; import javafx.scene.layout.BorderPane; import javafx.scene.layout.Pane; +import pamViewFX.PamGuiFX; +import pamViewFX.PamGuiManagerFX; +import pamViewFX.fxGlyphs.PamGlyphDude; import pamViewFX.fxNodes.PamBorderPane; import pamViewFX.fxNodes.PamHBox; import pamViewFX.fxNodes.PamVBox; @@ -13,6 +18,7 @@ import pamViewFX.fxNodes.sliders.PamSlider; import soundPlayback.PlaybackControl; import soundPlayback.preprocess.PlaybackPreprocess; import soundPlayback.preprocess.PreProcessFXPane; +import soundPlayback.preprocess.PreprocessSwingComponent; /** * Th eplay back side pane. @@ -26,6 +32,11 @@ public class PlayBackSidePane extends BorderPane { */ private PlaybackControl playBackControl; + /** + * Label which shows which sound ouptut device is being used. + */ + private Label deviceLabel; + public PlayBackSidePane(PlaybackControl playBackControl) { this.playBackControl=playBackControl; this.setCenter(createSidePane()); @@ -39,29 +50,97 @@ public class PlayBackSidePane extends BorderPane { PamBorderPane borderPane = new PamBorderPane(); + borderPane.setPrefWidth(PamGuiFX.SIDE_PANE_PREF_WIDTH-10); + borderPane.setMaxWidth(Double.MAX_VALUE); + + + Label titlelabel = new Label("Playback"); + PamGuiManagerFX.titleFont2style(titlelabel); + // titlelabel.setGraphic(PamGlyphDude.createPamIcon("mdi2p-play", PamGuiManagerFX.iconSize)); + + borderPane.setTop(titlelabel); + PamHBox hBox = new PamHBox(); hBox.setSpacing(5); - - PamVBox vBox = new PamVBox(); - vBox.setSpacing(5); + hBox.getChildren().add(deviceLabel= new Label("")); borderPane.setCenter(hBox); - borderPane.setBottom(vBox); + + PamVBox vBox = new PamVBox(); + vBox.setSpacing(0); + vBox.setPadding(new Insets(5,0,0,0)); + ArrayList preProcesses = playBackControl.getPlaybackProcess().getPreProcesses(); PreProcessFXPane preProcessFXPane; for (int i=0; i{ +// defaultButton.setVisible(true); +// }); +// +// labelHBox.setOnMouseExited((e)->{ +// defaultButton.setVisible(false); +// }); +// +// preProcessFXPane.getPane().setOnMouseEntered((e)->{ +// defaultButton.setVisible(true); +// }); +// +// preProcessFXPane.getPane().setOnMouseExited((e)->{ +// defaultButton.setVisible(false); +// }); +// +// } } } + borderPane.setBottom(vBox); + return borderPane; } + + + public void newSettings() { + boolean isRT = playBackControl.isRealTimePlayback(); + ArrayList preProcesses = playBackControl.getPlaybackProcess().getPreProcesses(); + for (PlaybackPreprocess pp : preProcesses) { + PreProcessFXPane comp = pp.getSideParPane(); + if (comp != null) { + comp.update(); + } + } + this.setVisible(playBackControl.getPlaybackParameters().getSidebarShow() > 0); + // speedLabel.setVisible(!isRT); + // speedSlider.getSlider().setVisible(!isRT); + // PlaybackParameters params = playbackControl.getPlaybackParameters(); + // gainLabel.setText(String.format("Gain %d dB", params.playbackGain)); + // gainSlider.setGain(params.playbackGain); + // sayPlaySpeed(speedSlider.getSpeed()); + // speedSlider.setSpeed(params.getPlaybackSpeed()); + } + } diff --git a/src/soundPlayback/fx/PlayDecimatorSidePane.java b/src/soundPlayback/fx/PlayDecimatorSidePane.java new file mode 100644 index 00000000..eb83348c --- /dev/null +++ b/src/soundPlayback/fx/PlayDecimatorSidePane.java @@ -0,0 +1,106 @@ +package soundPlayback.fx; + +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.control.Labeled; +import javafx.scene.control.Tooltip; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.scene.layout.Priority; +import pamViewFX.PamGuiManagerFX; +import pamViewFX.fxGlyphs.PamGlyphDude; +import pamViewFX.fxNodes.PamBorderPane; +import pamViewFX.fxNodes.PamButton; +import pamViewFX.fxNodes.PamHBox; +import soundPlayback.preprocess.PlaybackDecimator; +import soundPlayback.preprocess.PlaybackGain; +import soundPlayback.preprocess.PreProcessFXPane; + +public class PlayDecimatorSidePane implements PreProcessFXPane { + + private static final double DEFAULT_PLAY_SPEED = 1; + + + private PlaybackDecimator playbackDecimator; + + + private PlaySpeedSlider playSpeedSlider; + + private PamBorderPane mainPane; + + + private Label label; + + + private PamButton defaultSpeedButton; + + public PlayDecimatorSidePane(PlaybackDecimator playbackDecimator) { + this.playbackDecimator = playbackDecimator; + playSpeedSlider = new PlaySpeedSlider(); + + playSpeedSlider.getSlider().setTooltip(new Tooltip("Adjust the output volume.
"+ + "N.B. You should also consider turning up the volume in the computers volume controls.")); + + playSpeedSlider.addChangeListener((oldval, newVal, obsVal)->{ + speedChanged(); + }); + + playSpeedSlider.getChildren().add(defaultSpeedButton = new PamButton("x 1")); + defaultSpeedButton.setGraphic(PamGlyphDude.createPamIcon("mdi2r-refresh", PamGuiManagerFX.iconSize-3)); + defaultSpeedButton.setPrefWidth(70); + defaultSpeedButton.setOnAction((action)->{ + playSpeedSlider.setDataValue(DEFAULT_PLAY_SPEED); + }); + + label = new Label("Speed"); + + PamHBox hBox = new PamHBox(); + hBox.setAlignment(Pos.CENTER_LEFT); + hBox.setSpacing(5); + hBox.getChildren().addAll(PamGlyphDude.createPamIcon("mdi2p-play", PamGuiManagerFX.iconSize), playSpeedSlider); + playSpeedSlider.setMaxWidth(Double.MAX_VALUE); + HBox.setHgrow(playSpeedSlider, Priority.ALWAYS); + + this.mainPane = new PamBorderPane(); + this.mainPane.setCenter(hBox); + } + + @Override + public void update() { + playSpeedSlider.setVisible(playbackDecimator.makeVisible()); + playSpeedSlider.setDataValue(playbackDecimator.getPlaySpeed()); + saySpeed(); + } + + private void saySpeed() { + //playSpeedSlider.setTextLabel("Speed " + playSpeedSlider.getRatioString()); + label.setText("Speed " + playSpeedSlider.getRatioString()); + + } + + protected void speedChanged() { + defaultSpeedButton.setDisable(false); + playbackDecimator.setPlaySpeed(playSpeedSlider.getDataValue()); + if (playSpeedSlider.getDataValue()== DEFAULT_PLAY_SPEED) { + defaultSpeedButton.setDisable(true); + } + saySpeed(); + } + + @Override + public Pane getPane() { + return mainPane; + } + + @Override + public Label getLabel() { + return label; + } + + @Override + public Node getDefaultButton() { + return defaultSpeedButton; + } + +} \ No newline at end of file diff --git a/src/soundPlayback/fx/PlayGainSidePane.java b/src/soundPlayback/fx/PlayGainSidePane.java index 2b1c3e35..9c70b3ee 100644 --- a/src/soundPlayback/fx/PlayGainSidePane.java +++ b/src/soundPlayback/fx/PlayGainSidePane.java @@ -1,51 +1,153 @@ package soundPlayback.fx; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; - +import javafx.geometry.Pos; +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.control.Tooltip; +import javafx.scene.layout.HBox; import javafx.scene.layout.Pane; +import javafx.scene.layout.Priority; +import javafx.scene.text.Text; +import pamViewFX.PamGuiManagerFX; +import pamViewFX.fxGlyphs.PamGlyphDude; +import pamViewFX.fxNodes.PamBorderPane; +import pamViewFX.fxNodes.PamButton; +import pamViewFX.fxNodes.PamHBox; import soundPlayback.preprocess.PlaybackGain; import soundPlayback.preprocess.PreProcessFXPane; -import soundPlayback.swing.BasicSidebarLayout; -import soundPlayback.fx.PlayGainSlider; public class PlayGainSidePane implements PreProcessFXPane { private PlaybackGain playbackGain; - - private BasicSidebarLayout basicSidebarLayout; - + + private PlayGainSlider playGainSlider; + private PamBorderPane mainPane; + + + private Label label; + + + private Text medVol; + + + private Text lowVol; + + + private Text highVol; + + + private PamButton defaultGainButton; + + + private Label iconLabel; + + + private static final double DEFAULT_GAIN = 0; + + +// private PamHBox labelHBox; + public PlayGainSidePane(PlaybackGain playbackGain) { this.playbackGain = playbackGain; playGainSlider = new PlayGainSlider(); - - basicSidebarLayout.setToolTipText("Adjust the output volume.
"+ - "N.B. You should also consider turning up the volume in the computers volume controls."); + + playGainSlider.getSlider().setTooltip(new Tooltip("Adjust the output volume.
"+ + "N.B. You should also consider turning up the volume in the computers volume controls.")); playGainSlider.addChangeListener((oldval, newVal, obsVal)->{ - gainChanged(); - }); + gainChanged(); + }); + + //create the label which also has a default button + + defaultGainButton = new PamButton("0 dB"); + defaultGainButton.setGraphic(PamGlyphDude.createPamIcon("mdi2r-refresh", PamGuiManagerFX.iconSize-3)); + defaultGainButton.setPrefWidth(70); + defaultGainButton.setOnAction((action)->{ + playGainSlider.setDataValue(0); + }); + + label = new Label("Gain"); + +// labelHBox = new PamHBox(); +// labelHBox.setAlignment(Pos.CENTER_LEFT); +// labelHBox.setSpacing(5); +// labelHBox.getChildren().addAll(label, defaultGainButton); + + lowVol = PamGlyphDude.createPamIcon("mdi2v-volume-low", PamGuiManagerFX.iconSize); + medVol = PamGlyphDude.createPamIcon("mdi2v-volume-medium", PamGuiManagerFX.iconSize); + highVol = PamGlyphDude.createPamIcon("mdi2v-volume-high", PamGuiManagerFX.iconSize); + + iconLabel = new Label(); + + this.mainPane = new PamBorderPane(); + + PamHBox hBox = new PamHBox(); + hBox.setAlignment(Pos.CENTER_LEFT); + hBox.setSpacing(5); + hBox.getChildren().addAll(iconLabel, playGainSlider); + playGainSlider.setMaxWidth(Double.MAX_VALUE); + HBox.setHgrow(playGainSlider, Priority.ALWAYS); + + this.mainPane.setCenter(hBox); + + setLabelVolGrpahic(); + + } + + private void setLabelVolGrpahic() { + //System.out.println("Playback gain: " + playbackGain.getGaindB()); + + if (playbackGain.getGaindB()=PlayGainSlider.MINGAIN+20 && playbackGain.getGaindB()=PlayGainSlider.MAXGAIN-20 && iconLabel.getGraphic()!=highVol) { + iconLabel.setGraphic(highVol); + } + + + } @Override public void update() { playGainSlider.setDataValue(playbackGain.getGaindB()); + setLabelVolGrpahic(); sayGain(); } - + private void sayGain() { - basicSidebarLayout.setTextLabel(playbackGain.getTextValue()); + //playGainSlider.setTextLabel(playbackGain.getTextValue()); + label.setText(playbackGain.getTextValue()); } - + private void gainChanged() { + defaultGainButton.setDisable(false); playbackGain.setGaindB(playGainSlider.getDataValue()); + setLabelVolGrpahic(); sayGain(); + if (playbackGain.getGaindB()==DEFAULT_GAIN) { + defaultGainButton.setDisable(true); + } + } @Override public Pane getPane() { - return null; + return mainPane; + } + + @Override + public Node getLabel() { + return label; + } + + @Override + public Node getDefaultButton() { + return defaultGainButton; } } diff --git a/src/soundPlayback/fx/PlayGainSlider.java b/src/soundPlayback/fx/PlayGainSlider.java index dde50ee8..258e48f6 100644 --- a/src/soundPlayback/fx/PlayGainSlider.java +++ b/src/soundPlayback/fx/PlayGainSlider.java @@ -7,9 +7,9 @@ package soundPlayback.fx; */ public class PlayGainSlider extends PlaySliderPane { - private static final int MINGAIN = -20; + static final int MINGAIN = -20; - private static final int MAXGAIN = 60; + static final int MAXGAIN = 60; public PlayGainSlider() { @@ -26,4 +26,5 @@ public class PlayGainSlider extends PlaySliderPane { return MAXGAIN; } + } \ No newline at end of file diff --git a/src/soundPlayback/fx/PlaySliderPane.java b/src/soundPlayback/fx/PlaySliderPane.java index 1475c026..b89dab22 100644 --- a/src/soundPlayback/fx/PlaySliderPane.java +++ b/src/soundPlayback/fx/PlaySliderPane.java @@ -1,31 +1,72 @@ package soundPlayback.fx; import javafx.beans.value.ChangeListener; +import javafx.geometry.Pos; +import javafx.scene.control.Label; +import javafx.scene.control.Slider; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.paint.Color; +import pamViewFX.fxNodes.PamHBox; import pamViewFX.fxNodes.sliders.PamSlider; /** - * Default slider pane. + * Default slider pane for the sound output sliders. + * * @author Jamie Macaulay * */ -public abstract class PlaySliderPane { +public abstract class PlaySliderPane extends PamHBox { + /** + * The slider to chnage the value of something. + */ private PamSlider slider; + + /** + * The label which shows a slider value + */ + private Label sliderLabel; public PlaySliderPane() { slider = new PamSlider(getMinValue(), getMaxValue(), getMinValue()); + //slider.setShowTickMarks(true); + slider.setMaxWidth(Double.POSITIVE_INFINITY); + //slider.setShowTickLabels(true); //setSliderSize(); + + sliderLabel = new Label(); + slider.setId("thickslider"); + + HBox.setHgrow(slider, Priority.ALWAYS); + + this.setAlignment(Pos.CENTER_LEFT); + this.setSpacing(5); + + slider.setTrackColor(Color.rgb(0,204,204)); + slider.setTrackColor(Color.DODGERBLUE); + //slider.setTrackColor(Color.GRAY); + + this.getChildren().addAll(slider,sliderLabel); } + /** + * get the minimum value of the slider + * @return the minimum value fo the slider. + */ public abstract double getMinValue(); + /** + * Get the maximum value of the slider. + * @return the maximum value of the slider. + */ public abstract double getMaxValue(); /** * @return the slider */ - public PamSlider getSlider() { + public Slider getSlider() { return slider; } @@ -34,7 +75,7 @@ public abstract class PlaySliderPane { * @return the real scaled value */ public double getDataValue() { - return slider.getValue(); + return posToValue(slider.getValue()); } /** @@ -42,7 +83,7 @@ public abstract class PlaySliderPane { * @param value the scaled value. */ public void setDataValue(double value) { - slider.setValue(value); + slider.setValue(valueToPos(value)); } /** @@ -53,4 +94,28 @@ public abstract class PlaySliderPane { slider.valueProperty().addListener(changeListener); } + + public void setTextLabel(String textValue) { + this.sliderLabel.setText(textValue); + } + + + /** + * Get the slider position from a value (usually value = out). + * @param value + * @return + */ + public double valueToPos(double value) { + return value; + } + + /** + * Get the value from a slider position (usually pos = out). + * @param pos - the position of the slider. + * @return - the corresponding value. + */ + public double posToValue(double pos) { + return pos; + } + } diff --git a/src/soundPlayback/fx/PlaySpeedSlider.java b/src/soundPlayback/fx/PlaySpeedSlider.java new file mode 100644 index 00000000..1b41bd94 --- /dev/null +++ b/src/soundPlayback/fx/PlaySpeedSlider.java @@ -0,0 +1,59 @@ +package soundPlayback.fx; + +import java.text.DecimalFormat; + + +public class PlaySpeedSlider extends PlaySliderPane { + + + private static final double MINSPEED = -6; + + private static final double MAXSPEED = 6; + + public PlaySpeedSlider() { + this.getSlider().setBlockIncrement(1); + } + + + public String getRatioString() { + return getRatioString(getDataValue()); + } + + public static String getRatioString(double speed) { + if (speed >= 1) { + DecimalFormat df = new DecimalFormat(" x #.##"); + return df.format(speed); + } + else if (speed <= 0) { + return "Err 0"; + } + else { + DecimalFormat df = new DecimalFormat(" \u00F7 #.##"); + return df.format(1./speed); + } + } + + + @Override + public double getMinValue() { + return MINSPEED; + } + + @Override + public double getMaxValue() { + return MAXSPEED; + } + + + @Override + public double valueToPos(double value) { + return super.valueToPos(Math.log(value)/Math.log(2.)); + } + + + @Override + public double posToValue(double pos) { + return Math.pow(2,super.posToValue(pos)); + } + +} diff --git a/src/soundPlayback/preprocess/PlaybackDecimator.java b/src/soundPlayback/preprocess/PlaybackDecimator.java index 98395373..a5d0cf47 100644 --- a/src/soundPlayback/preprocess/PlaybackDecimator.java +++ b/src/soundPlayback/preprocess/PlaybackDecimator.java @@ -11,6 +11,7 @@ import soundPlayback.PBSampleRateData; import soundPlayback.PlaybackControl; import soundPlayback.PlaybackParameters; import soundPlayback.PlaybackProcess; +import soundPlayback.fx.PlayDecimatorSidePane; import soundPlayback.swing.DecimatorSideBar; public class PlaybackDecimator implements PlaybackPreprocess { @@ -22,6 +23,8 @@ public class PlaybackDecimator implements PlaybackPreprocess { private PlaybackControl playbackControl; private DecimatorSideBar decimatorSideBar; + + private PlayDecimatorSidePane playDecimatorSidePane; public PlaybackDecimator(PlaybackControl playbackControl) { this.playbackControl = playbackControl; @@ -72,7 +75,9 @@ public class PlaybackDecimator implements PlaybackPreprocess { @Override public PreProcessFXPane getSideParPane() { - // TODO Auto-generated method stub - return null; + if (playDecimatorSidePane==null) { + playDecimatorSidePane = new PlayDecimatorSidePane(this); + } + return playDecimatorSidePane; } } diff --git a/src/soundPlayback/preprocess/PlaybackFilter.java b/src/soundPlayback/preprocess/PlaybackFilter.java index 07ff4214..e4a98d5a 100644 --- a/src/soundPlayback/preprocess/PlaybackFilter.java +++ b/src/soundPlayback/preprocess/PlaybackFilter.java @@ -12,6 +12,8 @@ import PamUtils.FrequencyFormat; import PamUtils.PamUtils; import soundPlayback.PlaybackControl; import soundPlayback.PlaybackParameters; +import soundPlayback.fx.FilterSidePane; +import soundPlayback.fx.PlayDecimatorSidePane; import soundPlayback.swing.PlayFilterSideBar; /** @@ -31,6 +33,8 @@ public class PlaybackFilter implements PlaybackPreprocess { private PlayFilterSideBar playFilterSideBar; + private FilterSidePane filterSidePane; + public PlaybackFilter(PlaybackControl playbackControl) { this.playbackControl = playbackControl; playFilterSideBar = new PlayFilterSideBar(this); @@ -70,6 +74,7 @@ public class PlaybackFilter implements PlaybackPreprocess { } public String getTextValue() { + //System.out.println("Playback control Sample rate: " + playbackControl.getSourceSampleRate() + " val: " + getValue()); double f = getValue() * playbackControl.getSourceSampleRate(); if (f == 0) { return "High pass filter off"; @@ -114,8 +119,10 @@ public class PlaybackFilter implements PlaybackPreprocess { @Override public PreProcessFXPane getSideParPane() { - // TODO Auto-generated method stub - return null; + if (filterSidePane==null) { + filterSidePane = new FilterSidePane(this); + } + return filterSidePane; } } diff --git a/src/soundPlayback/preprocess/PreProcessFXPane.java b/src/soundPlayback/preprocess/PreProcessFXPane.java index f0834b75..a50f0d00 100644 --- a/src/soundPlayback/preprocess/PreProcessFXPane.java +++ b/src/soundPlayback/preprocess/PreProcessFXPane.java @@ -1,5 +1,7 @@ package soundPlayback.preprocess; +import javafx.scene.Node; +import javafx.scene.control.Label; import javafx.scene.layout.Pane; /** @@ -21,4 +23,14 @@ public interface PreProcessFXPane { */ public void update(); + /** + * Pane which shows the name of the pre-process. + */ + public Node getLabel(); + + /** + * Pane which allows the user to switch to a default. + */ + public Node getDefaultButton(); + }