mirror of
https://github.com/PAMGuard/PAMGuard.git
synced 2025-02-16 17:22:46 +00:00
Merge branch 'main' into main
This commit is contained in:
commit
fbe39a7416
@ -2000,6 +2000,10 @@ public abstract class SQLLogging {
|
|||||||
}
|
}
|
||||||
PamSubtableData subtableData = new PamSubtableData();
|
PamSubtableData subtableData = new PamSubtableData();
|
||||||
long utc = SQLTypes.millisFromTimeStamp(subtableTableDef.getTimeStampItem().getValue());
|
long utc = SQLTypes.millisFromTimeStamp(subtableTableDef.getTimeStampItem().getValue());
|
||||||
|
if (utc % 1000 == 0) {
|
||||||
|
int millis = subtableTableDef.getTimeStampMillis().getIntegerValue();
|
||||||
|
utc += millis;
|
||||||
|
}
|
||||||
subtableData.setChildUTC(utc);
|
subtableData.setChildUTC(utc);
|
||||||
subtableData.setParentID(subtableTableDef.getParentID().getIntegerValue());
|
subtableData.setParentID(subtableTableDef.getParentID().getIntegerValue());
|
||||||
subtableData.setParentUID(subtableTableDef.getParentUID().getLongValue());
|
subtableData.setParentUID(subtableTableDef.getParentUID().getLongValue());
|
||||||
|
30
src/generalDatabase/UTCTimestamp.java
Normal file
30
src/generalDatabase/UTCTimestamp.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package generalDatabase;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override standard Timestamp class and stop it making UTC corrections as it writes to database
|
||||||
|
* @author dg50
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class UTCTimestamp extends Timestamp {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public UTCTimestamp(long time) {
|
||||||
|
super(time);
|
||||||
|
// TODO Auto-generated constructor stub
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTime() {
|
||||||
|
return super.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocalDateTime toLocalDateTime() {
|
||||||
|
return super.toLocalDateTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -44,6 +44,31 @@ public class SqliteSQLTypes extends SQLTypes {
|
|||||||
return super.systemSqlType(sqlType);
|
return super.systemSqlType(sqlType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getTimeStamp(Long timeMillis) {
|
||||||
|
/**
|
||||||
|
* This has just got nasty WRT time zones.
|
||||||
|
* When the TimeStamp is written to database it uses the default time zone correction, which of course
|
||||||
|
* I don't want since I only do UTC. I was therefore subtracting this off before creating the ts
|
||||||
|
* so that it all worked fine when it was added back on again.
|
||||||
|
* This was fine for many years until someone processed data from exactly when the clocks went
|
||||||
|
* forward in the spring. Because the data were just after the clocks going forward, it took off
|
||||||
|
* an hour, then failed to add it back on again since the time was now before daylight saving.
|
||||||
|
* Amazed this has never happened before. Well done G and E ! I can fix it by setting the
|
||||||
|
* default time zone to UTC when PAMGuard starts, but note that all future references to local time
|
||||||
|
* will then be UTC. If I try to change it temporarily it doesn't help since the Timestamp always
|
||||||
|
* goes to the default, so it needs to be on UTC at the moment data are written to the database, not
|
||||||
|
* just in this function.
|
||||||
|
*
|
||||||
|
* Seems that for SQLite we can get away with a string, for MySQL we need a TimeStamp object still
|
||||||
|
*/
|
||||||
|
// return timeMillis;
|
||||||
|
if (timeMillis == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return PamCalendar.formatDBDateTime(timeMillis, true);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String formatDBDateTimeQueryString(long timeMilliseconds) {
|
public String formatDBDateTimeQueryString(long timeMilliseconds) {
|
||||||
switch (dateClass) {
|
switch (dateClass) {
|
||||||
|
@ -2,12 +2,25 @@ package whistleClassifier;
|
|||||||
|
|
||||||
import PamguardMVC.PamDataBlock;
|
import PamguardMVC.PamDataBlock;
|
||||||
import PamguardMVC.PamProcess;
|
import PamguardMVC.PamProcess;
|
||||||
|
import PamguardMVC.dataSelector.DataSelectorCreator;
|
||||||
|
import whistleClassifier.dataselect.WslClsDataSelectCreator;
|
||||||
|
|
||||||
public class WhistleClasificationDataBlock extends PamDataBlock<WhistleClassificationDataUnit> {
|
public class WhistleClasificationDataBlock extends PamDataBlock<WhistleClassificationDataUnit> {
|
||||||
|
|
||||||
|
private WslClsDataSelectCreator dataSelectCreator;
|
||||||
|
private WhistleClassifierControl wslClassifierControl;
|
||||||
|
|
||||||
public WhistleClasificationDataBlock(PamProcess parentProcess, int channelMap) {
|
public WhistleClasificationDataBlock(WhistleClassifierControl wslClassifierControl, PamProcess parentProcess, int channelMap) {
|
||||||
super(WhistleClassificationDataUnit.class, "Whistle Classification", parentProcess, channelMap);
|
super(WhistleClassificationDataUnit.class, "Whistle Classification", parentProcess, channelMap);
|
||||||
|
this.wslClassifierControl = wslClassifierControl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataSelectorCreator getDataSelectCreator() {
|
||||||
|
if (dataSelectCreator == null) {
|
||||||
|
dataSelectCreator = new WslClsDataSelectCreator(wslClassifierControl, this);
|
||||||
|
}
|
||||||
|
return dataSelectCreator;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
package whistleClassifier;
|
package whistleClassifier;
|
||||||
|
|
||||||
|
import PamDetection.PamDetection;
|
||||||
import PamguardMVC.AcousticDataUnit;
|
import PamguardMVC.AcousticDataUnit;
|
||||||
import PamguardMVC.PamDataUnit;
|
import PamguardMVC.PamDataUnit;
|
||||||
|
|
||||||
public class WhistleClassificationDataUnit extends PamDataUnit<PamDataUnit,PamDataUnit> implements AcousticDataUnit {
|
public class WhistleClassificationDataUnit extends PamDataUnit<PamDataUnit,PamDataUnit> implements AcousticDataUnit, PamDetection {
|
||||||
|
|
||||||
private double[] speciesLogLikelihoods;
|
private double[] speciesLogLikelihoods;
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ public class WhistleClassifierProcess extends PamProcess {
|
|||||||
|
|
||||||
this.whistleClassifierControl = whistleClassifierControl;
|
this.whistleClassifierControl = whistleClassifierControl;
|
||||||
|
|
||||||
whistleClasificationDataBlock = new WhistleClasificationDataBlock(this, 3);
|
whistleClasificationDataBlock = new WhistleClasificationDataBlock(whistleClassifierControl, this, 3);
|
||||||
|
|
||||||
addOutputDataBlock(whistleClasificationDataBlock);
|
addOutputDataBlock(whistleClasificationDataBlock);
|
||||||
|
|
||||||
|
35
src/whistleClassifier/dataselect/SppClsSelectParams.java
Normal file
35
src/whistleClassifier/dataselect/SppClsSelectParams.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package whistleClassifier.dataselect;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data selector params for a single species.
|
||||||
|
* @author dg50
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SppClsSelectParams implements Serializable, Cloneable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public String name;
|
||||||
|
public boolean selected;
|
||||||
|
public double minScore;
|
||||||
|
|
||||||
|
public SppClsSelectParams(String name, boolean selected, double minScore) {
|
||||||
|
super();
|
||||||
|
this.name = name;
|
||||||
|
this.selected = selected;
|
||||||
|
this.minScore = minScore;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected SppClsSelectParams clone() {
|
||||||
|
try {
|
||||||
|
return (SppClsSelectParams) super.clone();
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package whistleClassifier.dataselect;
|
||||||
|
|
||||||
|
import PamguardMVC.PamDataBlock;
|
||||||
|
import PamguardMVC.dataSelector.DataSelectParams;
|
||||||
|
import PamguardMVC.dataSelector.DataSelector;
|
||||||
|
import PamguardMVC.dataSelector.DataSelectorCreator;
|
||||||
|
import whistleClassifier.WhistleClasificationDataBlock;
|
||||||
|
import whistleClassifier.WhistleClassifierControl;
|
||||||
|
|
||||||
|
public class WslClsDataSelectCreator extends DataSelectorCreator {
|
||||||
|
|
||||||
|
private WhistleClassifierControl wslClassifierControl;
|
||||||
|
private WhistleClasificationDataBlock wslClassifierDataBlock;
|
||||||
|
|
||||||
|
public WslClsDataSelectCreator(WhistleClassifierControl wslClassifierControl, WhistleClasificationDataBlock pamDataBlock) {
|
||||||
|
super(pamDataBlock);
|
||||||
|
this.wslClassifierControl = wslClassifierControl;
|
||||||
|
this.wslClassifierDataBlock = pamDataBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataSelector createDataSelector(String selectorName, boolean allowScores, String selectorType) {
|
||||||
|
return new WslClsDataSelector(wslClassifierControl, wslClassifierDataBlock, selectorName, allowScores);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DataSelectParams createNewParams(String name) {
|
||||||
|
return new WslClsSelectorParams();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
70
src/whistleClassifier/dataselect/WslClsDataSelector.java
Normal file
70
src/whistleClassifier/dataselect/WslClsDataSelector.java
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package whistleClassifier.dataselect;
|
||||||
|
|
||||||
|
import PamView.dialog.PamDialogPanel;
|
||||||
|
import PamguardMVC.PamDataBlock;
|
||||||
|
import PamguardMVC.PamDataUnit;
|
||||||
|
import PamguardMVC.dataSelector.DataSelectParams;
|
||||||
|
import PamguardMVC.dataSelector.DataSelector;
|
||||||
|
import pamViewFX.fxSettingsPanes.DynamicSettingsPane;
|
||||||
|
import whistleClassifier.WhistleClassificationDataUnit;
|
||||||
|
import whistleClassifier.WhistleClassifierControl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Species selector for whistle classifier. Currently only does yes / no, will
|
||||||
|
* maybe one day be extended to allow scores as well.
|
||||||
|
* @author dg50
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class WslClsDataSelector extends DataSelector {
|
||||||
|
|
||||||
|
private WhistleClassifierControl wslClassifierControl;
|
||||||
|
|
||||||
|
private WslClsSelectorParams wcsParams = new WslClsSelectorParams();
|
||||||
|
|
||||||
|
public WslClsDataSelector(WhistleClassifierControl wslClassifierControl, PamDataBlock pamDataBlock, String selectorName, boolean allowScores) {
|
||||||
|
super(pamDataBlock, selectorName, allowScores);
|
||||||
|
this.wslClassifierControl = wslClassifierControl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParams(DataSelectParams dataSelectParams) {
|
||||||
|
if (dataSelectParams instanceof WslClsSelectorParams) {
|
||||||
|
wcsParams = (WslClsSelectorParams) dataSelectParams;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WslClsSelectorParams getParams() {
|
||||||
|
return wcsParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PamDialogPanel getDialogPanel() {
|
||||||
|
return new WslClsDialogPanel(wslClassifierControl, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DynamicSettingsPane<Boolean> getDialogPaneFX() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double scoreData(PamDataUnit pamDataUnit) {
|
||||||
|
WhistleClassificationDataUnit wcdu = (WhistleClassificationDataUnit) pamDataUnit;
|
||||||
|
String species = wcdu.getSpecies();
|
||||||
|
// score = wcdu.get
|
||||||
|
SppClsSelectParams sppParams = wcsParams.getSppParams(species);
|
||||||
|
// if ()
|
||||||
|
// if (sppParams.selected == false) {
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
// if (isAllowScores()) {
|
||||||
|
// return sppP
|
||||||
|
// }
|
||||||
|
// wslClassifierControl.getWhistleClassificationParameters().
|
||||||
|
return sppParams.selected ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
132
src/whistleClassifier/dataselect/WslClsDialogPanel.java
Normal file
132
src/whistleClassifier/dataselect/WslClsDialogPanel.java
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
package whistleClassifier.dataselect;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.GridBagConstraints;
|
||||||
|
import java.awt.GridBagLayout;
|
||||||
|
|
||||||
|
import javax.swing.JCheckBox;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JTextField;
|
||||||
|
import javax.swing.border.TitledBorder;
|
||||||
|
|
||||||
|
import PamView.dialog.PamDialog;
|
||||||
|
import PamView.dialog.PamDialogPanel;
|
||||||
|
import PamView.dialog.PamGridBagContraints;
|
||||||
|
import PamguardMVC.dataSelector.DataSelectParams;
|
||||||
|
import whistleClassifier.FragmentClassifierParams;
|
||||||
|
import whistleClassifier.WhistleClassificationParameters;
|
||||||
|
import whistleClassifier.WhistleClassifierControl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dialog for whistle classifier data selector
|
||||||
|
* @author dg50
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class WslClsDialogPanel implements PamDialogPanel {
|
||||||
|
|
||||||
|
private WhistleClassifierControl wslClassifierControl;
|
||||||
|
private WslClsDataSelector wslClsDataSelector;
|
||||||
|
|
||||||
|
private JPanel mainPanel;
|
||||||
|
|
||||||
|
private JPanel sppPanel;
|
||||||
|
|
||||||
|
private JCheckBox[] speciesBoxes;
|
||||||
|
|
||||||
|
private JTextField[] speciesScores;
|
||||||
|
|
||||||
|
public WslClsDialogPanel(WhistleClassifierControl wslClassifierControl, WslClsDataSelector wslClsDataSelector) {
|
||||||
|
this.wslClassifierControl = wslClassifierControl;
|
||||||
|
this.wslClsDataSelector = wslClsDataSelector;
|
||||||
|
|
||||||
|
this.mainPanel = new JPanel(new BorderLayout());
|
||||||
|
mainPanel.setBorder(new TitledBorder("Select species"));
|
||||||
|
|
||||||
|
sppPanel = new JPanel(new GridBagLayout());
|
||||||
|
mainPanel.add(BorderLayout.CENTER, sppPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JComponent getDialogComponent() {
|
||||||
|
return mainPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParams() {
|
||||||
|
WhistleClassificationParameters wslParams = wslClassifierControl.getWhistleClassificationParameters();
|
||||||
|
WslClsSelectorParams selParams = wslClsDataSelector.getParams();
|
||||||
|
if (wslParams == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FragmentClassifierParams fragParams = wslParams.fragmentClassifierParams;
|
||||||
|
if (fragParams == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fillSppPanel(wslParams, selParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillSppPanel(WhistleClassificationParameters wslParams, WslClsSelectorParams selParams) {
|
||||||
|
boolean allowScores = wslClsDataSelector.isAllowScores();
|
||||||
|
sppPanel.removeAll();
|
||||||
|
String[] sppList = wslParams.fragmentClassifierParams.getSpeciesList();
|
||||||
|
if (sppList == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int nSpp = sppList.length;
|
||||||
|
speciesBoxes = new JCheckBox[nSpp];
|
||||||
|
speciesScores = new JTextField[nSpp];
|
||||||
|
GridBagConstraints c = new PamGridBagContraints();
|
||||||
|
sppPanel.add(new JLabel("Species", JLabel.CENTER), c);
|
||||||
|
if (allowScores) {
|
||||||
|
c.gridx++;
|
||||||
|
JLabel lab = new JLabel(" Min score ", JLabel.CENTER);
|
||||||
|
lab.setToolTipText("Minimum classification score (between 0 and 1)");
|
||||||
|
sppPanel.add(lab , c);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < nSpp; i++) {
|
||||||
|
speciesBoxes[i] = new JCheckBox(sppList[i]);
|
||||||
|
speciesScores[i] = new JTextField(3);
|
||||||
|
c.gridx = 0;
|
||||||
|
c.gridy++;
|
||||||
|
sppPanel.add(speciesBoxes[i], c);
|
||||||
|
if (allowScores) {
|
||||||
|
c.gridx++;
|
||||||
|
sppPanel.add(speciesScores[i], c);
|
||||||
|
}
|
||||||
|
SppClsSelectParams sppSel = selParams.getSppParams(sppList[i]);
|
||||||
|
speciesBoxes[i].setSelected(sppSel.selected);
|
||||||
|
speciesScores[i].setText(String.format("%3.2f", sppSel.minScore));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getParams() {
|
||||||
|
WslClsSelectorParams selParams = wslClsDataSelector.getParams();
|
||||||
|
boolean allowScores = wslClsDataSelector.isAllowScores();
|
||||||
|
if (speciesBoxes == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int nSpp = speciesBoxes.length;
|
||||||
|
for (int i = 0; i < nSpp; i++) {
|
||||||
|
String name = speciesBoxes[i].getText();
|
||||||
|
boolean sel = speciesBoxes[i].isSelected();
|
||||||
|
double score = 0;
|
||||||
|
if (allowScores) {
|
||||||
|
try {
|
||||||
|
score = Double.valueOf(speciesScores[i].getText());
|
||||||
|
}
|
||||||
|
catch (NumberFormatException e) {
|
||||||
|
score = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (score < 0 || score > 1) {
|
||||||
|
return PamDialog.showWarning(null, "Invalid score value for " + name, "Score values must be betwween 0 and 1");
|
||||||
|
}
|
||||||
|
selParams.setSppParams(name, new SppClsSelectParams(name, sel, score));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
46
src/whistleClassifier/dataselect/WslClsSelectorParams.java
Normal file
46
src/whistleClassifier/dataselect/WslClsSelectorParams.java
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package whistleClassifier.dataselect;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import PamguardMVC.dataSelector.DataSelectParams;
|
||||||
|
|
||||||
|
public class WslClsSelectorParams extends DataSelectParams implements Cloneable, Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private HashMap<String, SppClsSelectParams> sppParamsTable = new HashMap<>();
|
||||||
|
|
||||||
|
public WslClsSelectorParams() {
|
||||||
|
// TODO Auto-generated constructor stub
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WslClsSelectorParams clone() {
|
||||||
|
try {
|
||||||
|
return (WslClsSelectorParams) super.clone();
|
||||||
|
} catch (CloneNotSupportedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSppParams(String sppName, SppClsSelectParams params) {
|
||||||
|
if (sppParamsTable == null) {
|
||||||
|
sppParamsTable = new HashMap<String, SppClsSelectParams>();
|
||||||
|
}
|
||||||
|
sppParamsTable.put(sppName, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SppClsSelectParams getSppParams(String sppName) {
|
||||||
|
if (sppParamsTable == null) {
|
||||||
|
sppParamsTable = new HashMap<String, SppClsSelectParams>();
|
||||||
|
}
|
||||||
|
SppClsSelectParams sppParams = sppParamsTable.get(sppName);
|
||||||
|
if (sppParams == null) {
|
||||||
|
sppParams = new SppClsSelectParams(sppName, false, 0);
|
||||||
|
}
|
||||||
|
return sppParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user