diff --git a/.classpath b/.classpath index 26c568d7..a66e1b06 100644 --- a/.classpath +++ b/.classpath @@ -6,7 +6,7 @@ - + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs index 42ac2a1a..9ba4622d 100644 --- a/.settings/org.eclipse.jdt.core.prefs +++ b/.settings/org.eclipse.jdt.core.prefs @@ -1,4 +1,14 @@ eclipse.preferences.version=1 +org.eclipse.jdt.core.codeComplete.argumentPrefixes= +org.eclipse.jdt.core.codeComplete.argumentSuffixes= +org.eclipse.jdt.core.codeComplete.fieldPrefixes= +org.eclipse.jdt.core.codeComplete.fieldSuffixes= +org.eclipse.jdt.core.codeComplete.localPrefixes= +org.eclipse.jdt.core.codeComplete.localSuffixes= +org.eclipse.jdt.core.codeComplete.staticFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFieldSuffixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes= +org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes= org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate org.eclipse.jdt.core.compiler.codegen.targetPlatform=16 diff --git a/.settings/org.eclipse.jdt.ui.prefs b/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 00000000..86a7add8 --- /dev/null +++ b/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,5 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.ui.exception.name=e +org.eclipse.jdt.ui.gettersetter.use.is=true +org.eclipse.jdt.ui.keywordthis=false +org.eclipse.jdt.ui.overrideannotation=true diff --git a/pom.xml b/pom.xml index 9e390083..6cc34e86 100644 --- a/pom.xml +++ b/pom.xml @@ -1,10 +1,13 @@ - - 4.0.0 - org.pamguard - Pamguard - 2.02.12 - Pamguard - Pamguard using Maven to control dependencies + + + 4.0.0 + org.pamguard + Pamguard + 2.02.12 + Pamguard + Pamguard using Maven to control dependencies www.pamguard.org Sea Mammal Research Unit, University of St. Andrews diff --git a/src/tethys/TethysControl.java b/src/tethys/TethysControl.java index 45671af1..45523eb8 100644 --- a/src/tethys/TethysControl.java +++ b/src/tethys/TethysControl.java @@ -724,8 +724,16 @@ public class TethysControl extends PamControlledUnit implements PamSettings, Tet */ public void exportedDetections(PamDataBlock dataBlock) { countProjectDetections(); -// sendStateUpdate(new TethysState(StateType.NEWPAMGUARDSELECTION, Collection.Detections)); +// sendStateUpdate(new TethysState(StateType.DELETEDATA)); + sendStateUpdate(new TethysState(StateType.NEWPAMGUARDSELECTION, Collection.Detections)); } + + public void deletedDetections(PamDataBlock dataBlock) { + countProjectDetections(); +// sendStateUpdate(new TethysState(StateType.DELETEDATA)); + sendStateUpdate(new TethysState(StateType.NEWPAMGUARDSELECTION, Collection.Detections)); + } + /** * @return the calibrationHandler */ diff --git a/src/tethys/detection/DetectionsHandler.java b/src/tethys/detection/DetectionsHandler.java index 8a6f0b88..d6c8d06f 100644 --- a/src/tethys/detection/DetectionsHandler.java +++ b/src/tethys/detection/DetectionsHandler.java @@ -1,5 +1,6 @@ package tethys.detection; +import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -30,6 +31,8 @@ import nilus.AlgorithmType; import nilus.AlgorithmType.SupportSoftware; import nilus.Localize.Effort; import nilus.Localize.Effort.CoordinateReferenceSystem; +import nilus.Localize.Effort.ReferencedDocuments; +import nilus.Localize.Effort.ReferencedDocuments.Document; import nilus.Localize.Localizations; import nilus.DataSourceType; import nilus.Deployment; @@ -49,6 +52,7 @@ import tethys.dbxml.DBXMLConnect; import tethys.dbxml.TethysException; import tethys.deployment.DeploymentHandler; import tethys.localization.CoordinateName; +import tethys.localization.LocalizationHandler; import tethys.localization.LocalizationSubType; import tethys.localization.LocalizationType; import tethys.localization.PLocalization; @@ -411,6 +415,8 @@ public class DetectionsHandler extends CollectionHandler { DeploymentHandler depHandler = tethysControl.getDeploymentHandler(); ArrayList deployments = depHandler.getMatchedDeployments(); + LocalizationHandler localizationHandler = tethysControl.getLocalizationHandler(); + /* * The main documents for both dets and locs. */ @@ -444,7 +450,7 @@ public class DetectionsHandler extends CollectionHandler { exportObserver.update(prog); granularityHandler.prepare(deployment.getAudioStart()); - List detectionList; + List detectionList = null; // export everything in that deployment. // need to loop through all map points in this interval. @@ -467,19 +473,19 @@ public class DetectionsHandler extends CollectionHandler { // onEffortDetections. // } } - else { - onEffortDetections = null; - detectionList = null; - } +// else { +// onEffortDetections = null; +// detectionList = null; +// } if (localiseDocument == null && streamExportParams.exportLocalisations) { - localiseDocument = startLocalisationDocument(deployment, dataBlock, streamExportParams); + localiseDocument = startLocalisationDocument(deployment, detectionsDocument, dataBlock, streamExportParams); Effort eff = localiseDocument.getEffort(); localiseDocument.getEffort().setStart(TethysTimeFuncs.xmlGregCalFromMillis(deployment.getAudioStart())); localisations = localiseDocument.getLocalizations(); } - else { - localisations = null; - } +// else { +// localisations = null; +// } if (mapPoint.getEndTime() < deployment.getAudioStart()) { continue; @@ -495,17 +501,24 @@ public class DetectionsHandler extends CollectionHandler { /* * Here is where we need to handle the different granularities. */ - Detection dets[] = granularityHandler.addDataUnit(dataUnit); - if (dets != null) { - for (int dd = 0; dd < dets.length; dd++) { - exportCount++; - documentCount++; - if (streamExportParams.exportDetections) { + if (streamExportParams.exportDetections) { + Detection dets[] = granularityHandler.addDataUnit(dataUnit); + if (dets != null) { + for (int dd = 0; dd < dets.length; dd++) { + exportCount++; + documentCount++; detectionList.add(dets[dd]); } - if (streamExportParams.exportLocalisations) { - // convert the dets into localisations and add them. - } + } + } + /** + * Localisations don't do granularity, so do all. + */ + if (streamExportParams.exportLocalisations) { + // convert the dets into localisations and add them. + nilus.LocalizationType localization = localizationHandler.createLocalization(localiseDocument, dataBlock, dataUnit, streamExportParams); + if (localization != null) { + localisations.getLocalization().add(localization); } } @@ -606,9 +619,9 @@ public class DetectionsHandler extends CollectionHandler { } } - prog = new DetectionExportProgress(null, null,totalMapPoints, totalMapPoints, - lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_COMPLETE); - exportObserver.update(prog); +// prog = new DetectionExportProgress(null, null,totalMapPoints, totalMapPoints, +// lastUnitTime, totalCount, exportCount, skipCount, DetectionExportProgress.STATE_COMPLETE); +// exportObserver.update(prog); return DetectionExportProgress.STATE_COMPLETE; } @@ -671,7 +684,7 @@ public class DetectionsHandler extends CollectionHandler { return detections; } - private Localize startLocalisationDocument(PDeployment deployment, PamDataBlock dataBlock, + private Localize startLocalisationDocument(PDeployment deployment, Detections detectionsDocument, PamDataBlock dataBlock, StreamExportParams exportParams) { Localize localisations = new Localize(); try { @@ -680,8 +693,9 @@ public class DetectionsHandler extends CollectionHandler { e.printStackTrace(); return null; } - if (localisations.getEffort() == null) { - Effort eff = new Effort(); + Effort eff = localisations.getEffort(); + if (eff == null) { + eff = new Effort(); try { Helper.createRequiredElements(eff); } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) { @@ -690,6 +704,29 @@ public class DetectionsHandler extends CollectionHandler { } localisations.setEffort(eff); } + if (detectionsDocument != null) { + /* + * add the reference document information. + * Within PAMGuard, this will always be 1:1 with a Detections doc. + */ + + ReferencedDocuments refDocs = eff.getReferencedDocuments(); + if (refDocs == null) { + refDocs = new ReferencedDocuments(); + try { + Helper.createRequiredElements(refDocs); + } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) { + e.printStackTrace(); + } + eff.setReferencedDocuments(refDocs); + } + Document detectsDoc = new Document(); + detectsDoc.setId(detectionsDocument.getId()); + detectsDoc.setType(Collection.Detections.collectionName()); + detectsDoc.setIndex(BigInteger.ZERO); + eff.getReferencedDocuments().getDocument().add(detectsDoc); + } + TethysDataProvider dataProvider = dataBlock.getTethysDataProvider(tethysControl); String prefix = deployment.nilusObject.getId() + "_" + dataProvider.getDetectionsName(); diff --git a/src/tethys/localization/LocalizationHandler.java b/src/tethys/localization/LocalizationHandler.java index 87c5fe0a..c2893e9d 100644 --- a/src/tethys/localization/LocalizationHandler.java +++ b/src/tethys/localization/LocalizationHandler.java @@ -1,24 +1,40 @@ package tethys.localization; +import java.math.BigInteger; import java.util.ArrayList; +import PamDetection.AbstractLocalisation; +import PamDetection.LocContents; +import PamUtils.LatLong; +import PamUtils.PamUtils; import PamguardMVC.PamDataBlock; -import nilus.CylindricalCoordinateType; +import PamguardMVC.PamDataUnit; +import nilus.AngularCoordinateType; +import nilus.BearingType; +import nilus.CoordinateType; +import nilus.Helper; import nilus.LocalizationType; +import nilus.LocalizationType.References; +import nilus.LocalizationType.References.Reference; import nilus.Localize; +import nilus.SpeciesIDType import nilus.Localize.Effort.CoordinateReferenceSystem; import tethys.Collection; import tethys.CollectionHandler; import tethys.TethysControl; +import tethys.TethysTimeFuncs; import tethys.detection.StreamDetectionsSummary; import tethys.niluswraps.NilusDataWrapper; import tethys.niluswraps.PDeployment; +import tethys.output.StreamExportParams; +import tethys.pamdata.AutoTethysProvider; +import tethys.species.DataBlockSpeciesManager; +import tethys.species.SpeciesMapItem; public class LocalizationHandler extends CollectionHandler { public LocalizationHandler(TethysControl tethysControl) { super(tethysControl, Collection.Localizations); - // TODO Auto-generated constructor stub } // public LocalizationType getLoc() { @@ -71,6 +87,232 @@ public class LocalizationHandler extends CollectionHandler { @Override public String getHelpPoint() { + return null; + } + + /** + * Create a Localization element object to add to a Localizations document. + * @param localiseDocument + * @param dataBlock + * @param dataUnit + * @param streamExportParams + * @return + */ + public LocalizationType createLocalization(Localize localiseDocument, PamDataBlock dataBlock, PamDataUnit dataUnit, + StreamExportParams streamExportParams) { + /* + * Get the current type from the document. This should always exist, so + * just go for it, then switch on the value to make the localisation. + */ + CoordinateReferenceSystem coordSystem = localiseDocument.getEffort().getCoordinateReferenceSystem(); + String name = coordSystem.getName(); + CoordinateName coordName = CoordinateName.valueOf(name); + if (coordName == null) { + return null; + } + LocalizationType locEl = null; + switch (coordName) { + case Cartesian: + locEl = createCartesianLoc(localiseDocument, dataBlock, dataUnit, streamExportParams); + break; + case Cylindrical: + locEl = createCylindricalLoc(localiseDocument, dataBlock, dataUnit, streamExportParams); + break; + case PerpindicularRange: + locEl = createPerpRange(localiseDocument, dataBlock, dataUnit, streamExportParams); + break; + case Polar: + locEl = createPolarLoc(localiseDocument, dataBlock, dataUnit, streamExportParams); + break; + case Range: + locEl = createRangeLoc(localiseDocument, dataBlock, dataUnit, streamExportParams); + break; + case Spherical: + locEl = createSphericalLoc(localiseDocument, dataBlock, dataUnit, streamExportParams); + break; + case UTM: + break; + case WGS84: + locEl = createWGS84Loc(localiseDocument, dataBlock, dataUnit, streamExportParams); + break; + default: + break; + + } + return locEl; + } + + private LocalizationType makeBaseLoc(PamDataBlock dataBlock, PamDataUnit dataUnit) { + LocalizationType locType = new LocalizationType(); + try { + Helper.createRequiredElements(locType); + } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) { + e.printStackTrace(); + } + locType.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataUnit.getTimeMilliseconds())); + + DataBlockSpeciesManager spManager = dataBlock.getDatablockSpeciesManager(); + if (spManager != null) { + SpeciesMapItem speciesStuff = spManager.getSpeciesItem(dataUnit); + SpeciesIDType species = new SpeciesIDType(); + if (speciesStuff != null) { + species.setValue(BigInteger.valueOf(speciesStuff.getItisCode())); + locType.setSpeciesId(species); + } + } + + References references = locType.getReferences(); + if (references == null) { + references = new References(); + try { + Helper.createRequiredElements(references); + } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) { + e.printStackTrace(); + } + locType.setReferences(references); + } + Reference reference = new Reference(); + reference.setIndex(BigInteger.valueOf(dataUnit.getUID())); + reference.setEventRef("UID"); + locType.getReferences().getReference().add(reference); + + return locType; + } + + /** + * Get angle in degrees constrained to 0-360 + * @param radians + * @return + */ + private double constrainRadianAngle(double radians) { + double deg = Math.toDegrees(radians); + if (Math.abs(deg) > 3600) { + return 359.9; + } + deg = PamUtils.constrainedAngle(deg); + deg = AutoTethysProvider.roundDecimalPlaces(deg, 2); + return deg; + } + + private LocalizationType createWGS84Loc(Localize localiseDocument, PamDataBlock dataBlock, PamDataUnit dataUnit, + StreamExportParams streamExportParams) { + AbstractLocalisation loc = dataUnit.getLocalisation(); + if (loc == null) { + return null; + } + LatLong latlong = loc.getLatLong(0); + if (latlong == null) { + return null; + } + LocalizationType locType = makeBaseLoc(dataBlock, dataUnit); + CoordinateType coord = new CoordinateType(); + coord.setX(latlong.getLongitude()); + coord.setY(latlong.getLatitude()); + coord.setZ(latlong.getHeight()); + + locType.setCoordinate(coord); + + return locType; + } + + private LocalizationType createSphericalLoc(Localize localiseDocument, PamDataBlock dataBlock, PamDataUnit dataUnit, + StreamExportParams streamExportParams) { + // TODO Auto-generated method stub + return null; + } + + private LocalizationType createRangeLoc(Localize localiseDocument, PamDataBlock dataBlock, PamDataUnit dataUnit, + StreamExportParams streamExportParams) { + // TODO Auto-generated method stub + return null; + } + + private LocalizationType createBearingLoc(Localize localiseDocument, PamDataBlock dataBlock, PamDataUnit dataUnit, + StreamExportParams streamExportParams) { + AbstractLocalisation loc = dataUnit.getLocalisation(); + if (loc == null) { + return null; + } + LocalizationType locType = makeBaseLoc(dataBlock, dataUnit); + double[] angles = loc.getAngles(); + if (angles == null || angles.length == 0) { + return null; + } + BearingType angType = new BearingType(); + angType.setAngle1(constrainRadianAngle(angles[0])); + if (angles.length >= 2) { + angType.setAngle2(constrainRadianAngle(angles[1])); + } + locType.setBearing(angType); + + double[] angErr = loc.getAngleErrors(); + if (angErr != null && angErr.length >= 1) { + BearingType angErrType = new BearingType(); + angErrType.setAngle1(constrainRadianAngle(angErr[0])); + if (angErr.length >= 2) { + angErrType.setAngle2(constrainRadianAngle(angErr[1])); + } + locType.setBearingError(angErrType); + } + + return locType; + } + private LocalizationType createPolarLoc(Localize localiseDocument, PamDataBlock dataBlock, PamDataUnit dataUnit, + StreamExportParams streamExportParams) { + AbstractLocalisation loc = dataUnit.getLocalisation(); + if (loc == null) { + return null; + } + if (loc.hasLocContent(LocContents.HAS_RANGE) == false) { + + // do the more basic bearing type instead. + return createBearingLoc(localiseDocument, dataBlock, dataUnit, streamExportParams); + } + LocalizationType locType = makeBaseLoc(dataBlock, dataUnit); + double[] angles = loc.getAngles(); + if (angles == null || angles.length == 0) { + return null; + } + AngularCoordinateType angType = new AngularCoordinateType(); + angType.setAngle1(constrainRadianAngle(angles[0])); + if (angles.length >= 2) { + angType.setAngle2(constrainRadianAngle(angles[1])); + } + if (loc.hasLocContent(LocContents.HAS_RANGE)) { + angType.setDistanceM(loc.getRange(0)); + } + locType.setAngularCoordinate(angType); + + double[] angErr = loc.getAngleErrors(); + if (angErr != null && angErr.length >= 1) { + AngularCoordinateType angErrType = new AngularCoordinateType(); + angErrType.setAngle1(constrainRadianAngle(angErr[0])); + if (angErr.length >= 2) { + angErrType.setAngle2(constrainRadianAngle(angErr[1])); + } + if (loc.hasLocContent(LocContents.HAS_RANGEERROR)) { + angErrType.setDistanceM(loc.getRangeError(0)); + } + locType.setAngularCoordinateError(angErrType); + } + + return locType; + } + + private LocalizationType createPerpRange(Localize localiseDocument, PamDataBlock dataBlock, PamDataUnit dataUnit, + StreamExportParams streamExportParams) { + // TODO Auto-generated method stub + return null; + } + + private LocalizationType createCylindricalLoc(Localize localiseDocument, PamDataBlock dataBlock, + PamDataUnit dataUnit, StreamExportParams streamExportParams) { + // TODO Auto-generated method stub + return null; + } + + private LocalizationType createCartesianLoc(Localize localiseDocument, PamDataBlock dataBlock, PamDataUnit dataUnit, + StreamExportParams streamExportParams) { // TODO Auto-generated method stub return null; } diff --git a/src/tethys/pamdata/AutoTethysProvider.java b/src/tethys/pamdata/AutoTethysProvider.java index 2af977d9..0c5e02b9 100644 --- a/src/tethys/pamdata/AutoTethysProvider.java +++ b/src/tethys/pamdata/AutoTethysProvider.java @@ -102,22 +102,17 @@ abstract public class AutoTethysProvider implements TethysDataProvider { @Override public AlgorithmType getAlgorithm() { + /** + * Probably need to split this to provide detection algorithm parameters and + * localisation algorithm parameters, or pass in the document type as a function + * argument. + */ AlgorithmType algorithm = new AlgorithmType(); try { nilus.Helper.createRequiredElements(algorithm); - } catch (IllegalArgumentException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IllegalAccessException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (InstantiationException e) { - // TODO Auto-generated catch block + } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) { e.printStackTrace(); } - // algorithm.setMethod(this.getAlgorithmMethod()); - // algorithm.setSoftware("PAMGuard"); - // algorithm.setVersion(PamguardVersionInfo.version); nilus.AlgorithmType.Parameters algoParameters = this.getAlgorithmParameters(); if (algoParameters != null) { algorithm.setParameters(algoParameters); diff --git a/src/tethys/swing/DatablockDetectionsPanel.java b/src/tethys/swing/DatablockDetectionsPanel.java index 8b76920b..a5fa2b35 100644 --- a/src/tethys/swing/DatablockDetectionsPanel.java +++ b/src/tethys/swing/DatablockDetectionsPanel.java @@ -129,9 +129,13 @@ public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTa return mainPanel; } - @Override - public void selectDataBlock(PamDataBlock dataBlock) { - if (this.dataBlock == dataBlock) { + /** + * update table for this datablock + * @param dataBlock datablock + * @param always always update, even if datablock hasn't changed. + */ + public void selectDataBlock(PamDataBlock dataBlock, boolean always) { + if (this.dataBlock == dataBlock && !always) { return; // stops lots of requerying, which matters when database is large. } this.dataBlock = dataBlock; @@ -147,6 +151,11 @@ public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTa w.start(); } + @Override + public void selectDataBlock(PamDataBlock dataBlock) { + selectDataBlock(dataBlock, false); + } + @Override public void taskFinished(String result) { tableModel.fireTableDataChanged(); @@ -169,13 +178,19 @@ public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTa @Override public void updateState(TethysState tethysState) { +// boolean fullUpdate = needFullUpdate(tethysState); if (dataBlock != null) { PamDataBlock currBlock = dataBlock; selectDataBlock(null); - selectDataBlock(dataBlock); + selectDataBlock(currBlock); } } +// private boolean needFullUpdate(TethysState tethysState) { +// // TODO Auto-generated method stub +// return false; +// } + private class MouseActions extends MouseAdapter { @Override @@ -305,13 +320,13 @@ public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTa @Override public void taskFinished(Integer result) { - getTethysControl().exportedDetections(dataBlock); - selectDataBlock(dataBlock); // force table update. + getTethysControl().deletedDetections(dataBlock); + selectDataBlock(dataBlock, true); // force table update. } } - protected void deleteDocument(PDetections pDets) { + protected void deleteDocument(NilusDataWrapper pDets) { String msg = String.format("Are you sure you want to delete the Detections document %s ?", pDets.getDocumentId()); int ans = WarnOnce.showWarning(PamGui.findComponentWindow(mainPanel), "Delete Document", msg, WarnOnce.OK_CANCEL_OPTION); if (ans != WarnOnce.OK_OPTION) { @@ -322,8 +337,8 @@ public class DatablockDetectionsPanel extends TethysGUIPanel implements StreamTa } catch (TethysException e) { getTethysControl().showException(e); } - getTethysControl().exportedDetections(dataBlock); - selectDataBlock(dataBlock); // force table update. + getTethysControl().deletedDetections(dataBlock); + selectDataBlock(dataBlock, true); // force table update. } private void displayDocument(NilusDataWrapper pDets) { diff --git a/src/tethys/swing/export/ExportWorkerCard.java b/src/tethys/swing/export/ExportWorkerCard.java index 27475bad..0542a59d 100644 --- a/src/tethys/swing/export/ExportWorkerCard.java +++ b/src/tethys/swing/export/ExportWorkerCard.java @@ -18,6 +18,7 @@ import PamView.panel.PamNorthPanel; import PamguardMVC.PamDataBlock; import tethys.TethysControl; import tethys.TethysState; +import tethys.TethysState.StateType; import tethys.TethysStateObserver; import tethys.detection.DetectionExportObserver; import tethys.detection.DetectionExportProgress; @@ -164,6 +165,7 @@ public class ExportWorkerCard extends ExportWizardCard implements DetectionExpor progressText.setText("Export complete"); detectionsExportWizard.getCancelButton().setText("Close"); detectionsExportWizard.getPreviousButton().setEnabled(false); +// getTethysControl().sendStateUpdate(new TethysState(StateType.EXPORTRDATA)); break; case DetectionExportProgress.STATE_WRITING: progressText.setText("Writing to Tethys: " + progress.currentDetections.getId());