Tethys updates

And get rid of some other files that had got into the repo by accident
This commit is contained in:
Douglas Gillespie 2024-08-23 14:58:32 +01:00
parent 34ba7ebceb
commit 51aa658514
16 changed files with 421 additions and 5179 deletions

View File

@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<a:clrMap xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" bg1="lt1" tx1="dk1" bg2="lt2" tx2="dk2" accent1="accent1" accent2="accent2" accent3="accent3" accent4="accent4" accent5="accent5" accent6="accent6" hlink="hlink" folHlink="folHlink"/>

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +0,0 @@
To build an executable jar file from the PAMGuard source using Eclipse, you need to use this build configuration
'Build PAMGuard.launch'
You cannot simply export the project as a runnable jar file, or you will not get the required Maven dependencies.
To use this with Eclipse, from your workspace, select File, then import, then in the list of things to be imported select
Run/Debug Launch Configurations, hit Next
Then in the Import Launch Configurations panel, browse to this folder. Select the folder (not a specific file)
then in the left panel, select the folder, then in the right panel the configuration you wish to import
(i.e. Build PAMGuard.launch) and hit Finish
Then go to 'Run Configurations' and find the launch in the 'Maven Builds' section. You'll probably have to change the
Base directory at the top of the panel to select the right project within your workspace.
Once that's done, you can Run the configuration. It will take a while to get all the Maven dependencies and will output
a runnable jar file into the 'targets' folder in your workspace.
The name and version number of the created files are taken from the POM.xml file, so edit that if you want a different name.
For unknown reasons, it makes three files. They are all the same, you can delete the ones starting with 'original-' and
ending with '-shared'

View File

@ -14,6 +14,7 @@ public class RWTethysDataProvider extends AutoTethysProvider {
public RWTethysDataProvider(TethysControl tethysControl, PamDataBlock pamDataBlock) { public RWTethysDataProvider(TethysControl tethysControl, PamDataBlock pamDataBlock) {
super(tethysControl, pamDataBlock); super(tethysControl, pamDataBlock);
setAddFrequencyInfo(true);
} }
@Override @Override

View File

@ -15,8 +15,8 @@ public class ClickBlockSpeciesManager extends DataBlockSpeciesManager<ClickDetec
public ClickBlockSpeciesManager(ClickControl clickControl, ClickDataBlock clickDataBlock) { public ClickBlockSpeciesManager(ClickControl clickControl, ClickDataBlock clickDataBlock) {
super(clickDataBlock); super(clickDataBlock);
this.clickControl = clickControl; this.clickControl = clickControl;
setDefaultDefaultSpecies(new SpeciesMapItem(ITISTypes.OTHER, "Unknown", "Unknown")); setDefaultDefaultSpecies(new SpeciesMapItem(ITISTypes.CETACEAN, "Click", "Click"));
setDefaultSpeciesCode("Unknown"); setDefaultSpeciesCode("Click");
} }
@Override @Override

View File

@ -12,25 +12,25 @@ import PamDetection.LocContents;
import PamUtils.LatLong; import PamUtils.LatLong;
import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit; import PamguardMVC.PamDataUnit;
import nilus.AngularCoordinateType; import nilus.Helper;
import nilus.LocalizationType; import nilus.LocalizationType;
import nilus.Localize; import nilus.Localize;
import nilus.WGS84CoordinateType; import nilus.WGS84CoordinateType;
import nilus.LocalizationType.Angular;
import nilus.LocalizationType.Parameters; import nilus.LocalizationType.Parameters;
import nilus.LocalizationType.WGS84; import nilus.LocalizationType.WGS84;
import nilus.LocalizationType.Parameters.TargetMotionAnalysis; import nilus.LocalizationType.Parameters.TargetMotionAnalysis;
import nilus.Localize.Effort; import nilus.Localize.Effort;
import nilus.Localize.Effort.CoordinateReferenceSystem; import nilus.Localize.Effort.CoordinateReferenceSystem;
import nilus.Localize.Effort.CoordinateReferenceSystem.ReferenceFrame;
import pamMaths.PamVector; import pamMaths.PamVector;
import targetMotionOld.TargetMotionLocaliser; import targetMotionOld.TargetMotionLocaliser;
import tethys.TethysTimeFuncs; import tethys.TethysTimeFuncs;
import tethys.localization.Anchor;
import tethys.localization.CoordinateName; import tethys.localization.CoordinateName;
import tethys.localization.LocalizationBuilder; import tethys.localization.LocalizationBuilder;
import tethys.localization.LocalizationCreator; import tethys.localization.LocalizationCreator;
import tethys.localization.LocalizationSubTypes; import tethys.localization.LocalizationSubTypes;
import tethys.localization.LocalizationTypes; import tethys.localization.LocalizationTypes;
import tethys.localization.ReferenceFrame;
import tethys.localization.TimeReference; import tethys.localization.TimeReference;
import tethys.pamdata.AutoTethysProvider; import tethys.pamdata.AutoTethysProvider;
@ -38,7 +38,7 @@ public class TMALocalizationCreator implements LocalizationCreator {
int maxDimension = 2; int maxDimension = 2;
public TMALocalizationCreator(TargetMotionLocaliser targetMotionLocaliser) { public TMALocalizationCreator(TargetMotionLocaliser targetMotionLocaliser) {
// TODO Auto-generated constructor stub // TODO Auto-generated constructor stub
} }
@ -53,12 +53,36 @@ public class TMALocalizationCreator implements LocalizationCreator {
locTypes.add(LocalizationTypes.Point.toString()); locTypes.add(LocalizationTypes.Point.toString());
locTypes.add(LocalizationTypes.PerpendicularRange.toString()); locTypes.add(LocalizationTypes.PerpendicularRange.toString());
/**
* Currently, TMA is only outputing as WGS84. Future release will have
* options to put out local xyz coordinates instead, in which case this
* will be Engineering and the referenceFrame will become instrument.
*/
CoordinateReferenceSystem coordRefs = locEffort.getCoordinateReferenceSystem(); CoordinateReferenceSystem coordRefs = locEffort.getCoordinateReferenceSystem();
coordRefs.setName(CoordinateName.WGS84.toString()); coordRefs.setName(CoordinateName.WGS84.toString());
coordRefs.setSubtype(LocalizationSubTypes.Geographic.toString()); coordRefs.setSubtype(LocalizationSubTypes.Geographic.toString());
ReferenceFrame refFrame = localizationBuilder.getDefaultReferenceFrame(CoordinateName.WGS84, LocalizationSubTypes.Geographic);
if (refFrame != null) {
coordRefs.setReferenceFrame(refFrame);
}
// /**
// * TMA is always references to the earth.
// */
// ReferenceFrame refFrame = coordRefs.getReferenceFrame();
// if (refFrame == null) {
// refFrame = new ReferenceFrame();
// try {
// Helper.createRequiredElements(refFrame);
// } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) {
// e.printStackTrace();
// }
// coordRefs.setReferenceFrame(refFrame);
// }
// refFrame.setAnchor(Anchor.WGS84.toString());
locEffort.setDimension(2); locEffort.setDimension(2);
return true; return true;
} }
@ -115,19 +139,19 @@ public class TMALocalizationCreator implements LocalizationCreator {
* Needs a bit of work to get errors in correct direction (needs import * Needs a bit of work to get errors in correct direction (needs import
* of track data for this value ?) and conversion to latlong units. * of track data for this value ?) and conversion to latlong units.
*/ */
// if (errorVec != null && errorVec.length >= 2) { // if (errorVec != null && errorVec.length >= 2) {
// wgsErr = new WGS84CoordinateType(); // wgsErr = new WGS84CoordinateType();
// wgsErr.setLongitude(errorVec[0]); // wgsErr.setLongitude(errorVec[0]);
// wgsErr.setLatitude(errorVec[1]); // wgsErr.setLatitude(errorVec[1]);
// if (hasDepth && errorVec.length >= 3) { // if (hasDepth && errorVec.length >= 3) {
// wgsErr.setElevationM(errorVec[2]); // wgsErr.setElevationM(errorVec[2]);
// } // }
// wgs84.setCoordinateError(wgsErr); // wgs84.setCoordinateError(wgsErr);
// } // }
loc.setWGS84(wgs84); loc.setWGS84(wgs84);
// set the TMA information // set the TMA information
Parameters params = loc.getParameters(); Parameters params = loc.getParameters();
if (params == null) { if (params == null) {
@ -142,31 +166,31 @@ public class TMALocalizationCreator implements LocalizationCreator {
if (timeAbeam != null) { if (timeAbeam != null) {
loc.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(timeAbeam)); loc.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(timeAbeam));
} }
// now also output a perpendicular distance. // now also output a perpendicular distance.
Double perp = groupLocResult.getPerpendicularDistance(); Double perp = groupLocResult.getPerpendicularDistance();
if (perp != null) { if (perp != null) {
loc.setPerpendicularRangeM(AutoTethysProvider.roundDecimalPlaces(perp, 2)); loc.setPerpendicularRangeM(AutoTethysProvider.roundDecimalPlaces(perp, 2));
} }
// con only output one type.
// if (perp != null) {
// AngularCoordinateType acType = new AngularCoordinateType();
// acType.setAngle1(90);
// acType.setDistanceM(AutoTethysProvider.roundDecimalPlaces(perp,1));
// Angular angular = new Angular();
// angular.setCoordinate(acType);
// if (errors != null) {
// AngularCoordinateType angErr = new AngularCoordinateType();
// angErr.setDistanceM(errors.norm());
// angular.setCoordinateError(angErr);
// }
// loc.setAngular(angular);
// }
// con only output one type.
// if (perp != null) {
// AngularCoordinateType acType = new AngularCoordinateType();
// acType.setAngle1(90);
// acType.setDistanceM(AutoTethysProvider.roundDecimalPlaces(perp,1));
// Angular angular = new Angular();
// angular.setCoordinate(acType);
// if (errors != null) {
// AngularCoordinateType angErr = new AngularCoordinateType();
// angErr.setDistanceM(errors.norm());
// angular.setCoordinateError(angErr);
// }
// loc.setAngular(angular);
// }
return loc; return loc;
} }

View File

@ -87,6 +87,7 @@ import tethys.dbxml.TethysException;
import tethys.deployment.swing.DeploymentWizard; import tethys.deployment.swing.DeploymentWizard;
import tethys.deployment.swing.EffortProblemDialog; import tethys.deployment.swing.EffortProblemDialog;
import tethys.deployment.swing.RecordingGapDialog; import tethys.deployment.swing.RecordingGapDialog;
import tethys.localization.TethysLatLong;
import tethys.niluswraps.PDeployment; import tethys.niluswraps.PDeployment;
import tethys.output.TethysExportParams; import tethys.output.TethysExportParams;
import tethys.pamdata.AutoTethysProvider; import tethys.pamdata.AutoTethysProvider;
@ -909,8 +910,8 @@ public class DeploymentHandler extends CollectionHandler implements TethysStateO
GpsData gpsData = gpsDataUnit.getGpsData(); GpsData gpsData = gpsDataUnit.getGpsData();
Point gpsPoint = new Point(); Point gpsPoint = new Point();
gpsPoint.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(gpsDataUnit.getTimeMilliseconds())); gpsPoint.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(gpsDataUnit.getTimeMilliseconds()));
gpsPoint.setLatitude(gpsData.getLatitude()); gpsPoint.setLatitude(TethysLatLong.formatLatitude(gpsData.getLatitude()));
gpsPoint.setLongitude(PamUtils.constrainedAngle(gpsData.getLongitude())); gpsPoint.setLongitude(TethysLatLong.formatLongitude(gpsData.getLongitude()));
CourseOverGroundDegN cog = gpsPoint.getCourseOverGroundDegN(); CourseOverGroundDegN cog = gpsPoint.getCourseOverGroundDegN();
if (cog == null) { if (cog == null) {
cog = new CourseOverGroundDegN(); cog = new CourseOverGroundDegN();
@ -1080,8 +1081,8 @@ public class DeploymentHandler extends CollectionHandler implements TethysStateO
double recLat = deploymentData.getRecoveryDetails().getLatitude(); double recLat = deploymentData.getRecoveryDetails().getLatitude();
double recLong = deploymentData.getRecoveryDetails().getLongitude(); double recLong = deploymentData.getRecoveryDetails().getLongitude();
if (recLat != 0 & recLong != 0.) { if (recLat != 0 & recLong != 0.) {
deployment.getRecoveryDetails().setLatitude(recLat); deployment.getRecoveryDetails().setLatitude(TethysLatLong.formatLatitude(recLat));
deployment.getRecoveryDetails().setLongitude(PamUtils.constrainedAngle(recLong)); deployment.getRecoveryDetails().setLongitude(TethysLatLong.formatLongitude(recLong));
} }
} }

View File

@ -620,7 +620,7 @@ public class DetectionsHandler extends CollectionHandler {
* Check the document name isn't already used and increment id as necessary. * Check the document name isn't already used and increment id as necessary.
*/ */
while (true) { while (true) {
fullId = String.format("%s_%d", prefix, uniqueDetectionsId++); fullId = String.format("%s_D_%d", prefix, uniqueDetectionsId++);
if (!tethysControl.getDbxmlQueries().documentExists(Collection.Detections.toString(), fullId)) { if (!tethysControl.getDbxmlQueries().documentExists(Collection.Detections.toString(), fullId)) {
break; break;
} }

View File

@ -0,0 +1,10 @@
package tethys.localization;
/**
* Anchors for localization effort coordinate system.
* @author dg50
*
*/
public enum Anchor {
UTMZone, WGS84, instrument;
}

View File

@ -3,6 +3,18 @@ package tethys.localization;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.List; import java.util.List;
import javax.xml.bind.JAXBException;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Element;
import Array.ArrayManager;
import Array.PamArray;
import Array.Streamer;
import Array.streamerOrigin.OriginSettings;
import Array.streamerOrigin.StaticOriginSettings;
import GPS.GpsData;
import GPS.GpsDataUnit;
import Localiser.LocalisationAlgorithm; import Localiser.LocalisationAlgorithm;
import Localiser.LocalisationAlgorithmInfo; import Localiser.LocalisationAlgorithmInfo;
import Localiser.detectionGroupLocaliser.GroupLocResult; import Localiser.detectionGroupLocaliser.GroupLocResult;
@ -14,6 +26,7 @@ import PamUtils.LatLong;
import PamUtils.PamUtils; import PamUtils.PamUtils;
import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit; import PamguardMVC.PamDataUnit;
import binaryFileStorage.DataUnitFileInformation;
import nilus.AlgorithmType; import nilus.AlgorithmType;
import nilus.AngularCoordinateType; import nilus.AngularCoordinateType;
import nilus.BearingType; import nilus.BearingType;
@ -31,10 +44,12 @@ import nilus.LocalizationType.Parameters;
import nilus.LocalizationType.References; import nilus.LocalizationType.References;
import nilus.LocalizationType.WGS84; import nilus.LocalizationType.WGS84;
import nilus.LocalizationType.Parameters.TargetMotionAnalysis; import nilus.LocalizationType.Parameters.TargetMotionAnalysis;
import nilus.LocalizationType.Parameters.UserDefined;
import nilus.LocalizationType.References.Reference; import nilus.LocalizationType.References.Reference;
import nilus.Localize.Effort; import nilus.Localize.Effort;
import nilus.Localize.Effort.CoordinateReferenceSystem; import nilus.Localize.Effort.CoordinateReferenceSystem;
import nilus.Localize.Effort.ReferencedDocuments; import nilus.Localize.Effort.ReferencedDocuments;
import nilus.Localize.Effort.CoordinateReferenceSystem.ReferenceFrame;
import nilus.Localize.Effort.ReferencedDocuments.Document; import nilus.Localize.Effort.ReferencedDocuments.Document;
import pamMaths.PamVector; import pamMaths.PamVector;
import tethys.Collection; import tethys.Collection;
@ -68,6 +83,8 @@ public class LocalizationBuilder {
private Localize currentDocument; private Localize currentDocument;
private LocalizationCreator localisationCreator; private LocalizationCreator localisationCreator;
private TethysDataProvider dataProvider; private TethysDataProvider dataProvider;
private Helper helper;
public LocalizationBuilder(TethysControl tethysControl, PDeployment deployment, Detections detectionsDocument, PamDataBlock dataBlock, public LocalizationBuilder(TethysControl tethysControl, PDeployment deployment, Detections detectionsDocument, PamDataBlock dataBlock,
StreamExportParams exportParams) { StreamExportParams exportParams) {
@ -76,6 +93,11 @@ public class LocalizationBuilder {
this.dataBlock = dataBlock; this.dataBlock = dataBlock;
this.streamExportParams = exportParams; this.streamExportParams = exportParams;
this.tethysControl = tethysControl; this.tethysControl = tethysControl;
try {
helper = new Helper();
} catch (JAXBException e) {
e.printStackTrace();
}
dataProvider = dataBlock.getTethysDataProvider(tethysControl); dataProvider = dataBlock.getTethysDataProvider(tethysControl);
localisationHandler = tethysControl.getLocalizationHandler(); localisationHandler = tethysControl.getLocalizationHandler();
localisationAlgorithm = dataBlock.getLocalisationAlgorithm(); localisationAlgorithm = dataBlock.getLocalisationAlgorithm();
@ -123,13 +145,13 @@ public class LocalizationBuilder {
} }
Document detectsDoc = new Document(); Document detectsDoc = new Document();
detectsDoc.setId(detectionsDocument.getId()); detectsDoc.setId(detectionsDocument.getId());
detectsDoc.setType(Collection.Localizations.collectionName()); detectsDoc.setType(Collection.Detections.collectionName());
detectsDoc.setIndex(BigInteger.ZERO); detectsDoc.setIndex(BigInteger.ZERO);
eff.getReferencedDocuments().getDocument().add(detectsDoc); eff.getReferencedDocuments().getDocument().add(detectsDoc);
} }
String prefix = deployment.nilusObject.getId() + "_" + dataProvider.getDetectionsName(); String prefix = deployment.nilusObject.getId() + "_" + dataProvider.getDetectionsName() + "_L";
String fullId = localisationHandler.getLocalisationdocId(prefix); String fullId = localisationHandler.getLocalisationdocId(prefix);
currentDocument.setId(fullId); currentDocument.setId(fullId);
// detections.setDescription(dataProvider.getDescription(deployment, tethysExportParams)); // detections.setDescription(dataProvider.getDescription(deployment, tethysExportParams));
@ -185,6 +207,54 @@ public class LocalizationBuilder {
return done; return done;
} }
/**
* Get a default reference frame for the header of a localization document. This is very dependent
* on the localization subtype. Also on whether the array is fixed or moving. It it's fixed, then
* we also need to add the instrument lat long.
* @param coordinateName
* @param subType
* @return
*/
public ReferenceFrame getDefaultReferenceFrame(CoordinateName coordinateName, LocalizationSubTypes subType) {
ReferenceFrame referenceFrame = new ReferenceFrame();
switch (subType) {
case Derived:
referenceFrame.setAnchor(Anchor.UTMZone.toString()); // i never use this on. If I do, this will need work !
break;
case Engineering:
referenceFrame.setAnchor(Anchor.instrument.toString());
break;
case Geographic:
referenceFrame.setAnchor(Anchor.WGS84.toString());
break;
default:
break;
}
/*
* And see if it's a fixed or moving array. Will just have to look at the
* first streamer here. Hard to copy with multiples !
*/
PamArray array = ArrayManager.getArrayManager().getCurrentArray();
Streamer streamer = array.getStreamer(0);
if (streamer != null) {
OriginSettings origin = streamer.getOriginSettings();
if (origin instanceof StaticOriginSettings) {
StaticOriginSettings staticOrigin = (StaticOriginSettings) origin;
GpsDataUnit ll = staticOrigin.getStaticPosition();
if (ll != null) {
GpsData pos = ll.getGpsData();
if (pos != null) {
referenceFrame.setLatitude(TethysLatLong.formatLatitude(pos.getLatitude()));
referenceFrame.setLongitude(TethysLatLong.formatLongitude(pos.getLongitude()));
referenceFrame.setDatum(String.format("Altitude %3.2fm", pos.getHeight()));
}
}
}
}
return referenceFrame;
}
public boolean sortStandardCoordinates(PamDataBlock dataBlock) { public boolean sortStandardCoordinates(PamDataBlock dataBlock) {
LocalisationInfo locInfo = dataBlock.getLocalisationContents(); LocalisationInfo locInfo = dataBlock.getLocalisationContents();
Effort locEffort = currentDocument.getEffort(); Effort locEffort = currentDocument.getEffort();
@ -202,6 +272,7 @@ public class LocalizationBuilder {
// List<String> locTypes = locEffort.getLocalizationType(); // List<String> locTypes = locEffort.getLocalizationType();
boolean ambiguity = locInfo.hasLocContent(LocContents.HAS_AMBIGUITY); boolean ambiguity = locInfo.hasLocContent(LocContents.HAS_AMBIGUITY);
CoordinateReferenceSystem coordRefs = locEffort.getCoordinateReferenceSystem(); CoordinateReferenceSystem coordRefs = locEffort.getCoordinateReferenceSystem();
ReferenceFrame referenceFrame = null;
List<String> locTypes = locEffort.getLocalizationType(); List<String> locTypes = locEffort.getLocalizationType();
if (locInfo.getLocContent() == 0) { if (locInfo.getLocContent() == 0) {
return false; return false;
@ -217,6 +288,7 @@ public class LocalizationBuilder {
else { else {
locEffort.setDimension(2); locEffort.setDimension(2);
} }
referenceFrame = getDefaultReferenceFrame(CoordinateName.WGS84, LocalizationSubTypes.Geographic);
// locEffort.set // locEffort.set
} }
else if (locInfo.hasLocContent(LocContents.HAS_XYZ)) { else if (locInfo.hasLocContent(LocContents.HAS_XYZ)) {
@ -224,12 +296,14 @@ public class LocalizationBuilder {
coordRefs.setSubtype(LocalizationSubTypes.Engineering.toString()); coordRefs.setSubtype(LocalizationSubTypes.Engineering.toString());
locTypes.add(LocalizationTypes.Point.toString()); locTypes.add(LocalizationTypes.Point.toString());
locEffort.setDimension(3); locEffort.setDimension(3);
referenceFrame = getDefaultReferenceFrame(CoordinateName.Cartesian, LocalizationSubTypes.Engineering);
} }
else if (locInfo.hasLocContent(LocContents.HAS_XY)) { else if (locInfo.hasLocContent(LocContents.HAS_XY)) {
coordRefs.setName(CoordinateName.Cartesian.toString()); coordRefs.setName(CoordinateName.Cartesian.toString());
coordRefs.setSubtype(LocalizationSubTypes.Engineering.toString()); coordRefs.setSubtype(LocalizationSubTypes.Engineering.toString());
locTypes.add(LocalizationTypes.Point.toString()); locTypes.add(LocalizationTypes.Point.toString());
locEffort.setDimension(2); locEffort.setDimension(2);
referenceFrame = getDefaultReferenceFrame(CoordinateName.Cartesian, LocalizationSubTypes.Engineering);
} }
else if (locInfo.hasLocContent(LocContents.HAS_BEARING)) { else if (locInfo.hasLocContent(LocContents.HAS_BEARING)) {
coordRefs.setName(CoordinateName.Polar.toString()); coordRefs.setName(CoordinateName.Polar.toString());
@ -241,10 +315,12 @@ public class LocalizationBuilder {
else { else {
locEffort.setDimension(2); locEffort.setDimension(2);
} }
referenceFrame = getDefaultReferenceFrame(CoordinateName.Polar, LocalizationSubTypes.Engineering);
} }
else { else {
return false; return false;
} }
coordRefs.setReferenceFrame(referenceFrame);
return true; return true;
} }
@ -329,21 +405,41 @@ public class LocalizationBuilder {
locType.setSpeciesId(species); locType.setSpeciesId(species);
} }
} }
References references = locType.getReferences(); /*
if (references == null) { * Add references back to PAMGuard data as for Detections.
references = new References(); * Same code as in Detections, but classes are different (though with the same fields).
try { */
Helper.createRequiredElements(references); Parameters params = getParameters(locType);
} catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) { String uid = BigInteger.valueOf(dataUnit.getUID()).toString();
e.printStackTrace(); Element el = addUserDefined(params,"PAMGuardUID", uid);
} DataUnitFileInformation fileInf = dataUnit.getDataUnitFileInformation();
locType.setReferences(references); if (fileInf != null) {
el.setAttribute("BinaryFile", fileInf.getShortFileName(2048));
el.setAttribute("FileIndex", Long.valueOf(fileInf.getIndexInFile()).toString());
} }
Reference reference = new Reference(); if (dataUnit.getDatabaseIndex() > 0) {
reference.setIndex(BigInteger.valueOf(dataUnit.getUID())); // only write the database index if it's > 0, i.e. is used.
reference.setEventRef("UID"); addUserDefined(params, "DatabaseId", String.format("%d", dataUnit.getDatabaseIndex()));
locType.getReferences().getReference().add(reference); }
/*
* Not needed. something to do with references to Detection docs.
*/
// 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; return locType;
} }
@ -405,11 +501,7 @@ public class LocalizationBuilder {
locType.setWGS84(wgs84); locType.setWGS84(wgs84);
// locType.setParameters(null); // locType.setParameters(null);
Parameters params = locType.getParameters(); Parameters params = getParameters(locType);
if (params == null) {
params = new Parameters();
locType.setParameters(params);
}
TargetMotionAnalysis tma = new TargetMotionAnalysis(); TargetMotionAnalysis tma = new TargetMotionAnalysis();
tma.setStart(TethysTimeFuncs.xmlGregCalFromMillis(dataUnit.getTimeMilliseconds())); tma.setStart(TethysTimeFuncs.xmlGregCalFromMillis(dataUnit.getTimeMilliseconds()));
tma.setEnd(TethysTimeFuncs.xmlGregCalFromMillis(dataUnit.getEndTimeInMilliseconds())); tma.setEnd(TethysTimeFuncs.xmlGregCalFromMillis(dataUnit.getEndTimeInMilliseconds()));
@ -442,6 +534,40 @@ public class LocalizationBuilder {
return locType; return locType;
} }
/**
* Convenience method to get the Parameters object for a localisation and
* to automatically create it if it doesn't exist.
* @param localization
* @return
*/
public Parameters getParameters(LocalizationType localization) {
Parameters params = localization.getParameters();
if (params == null) {
params = new Parameters();
localization.setParameters(params);
}
return params;
}
public Element addUserDefined(Parameters parameters, String parameterName, String parameterValue) {
UserDefined userDefined = parameters.getUserDefined();
if (userDefined == null) {
userDefined = new UserDefined();
parameters.setUserDefined(userDefined);
}
Element el = null;
try {
el = helper.AddAnyElement(userDefined.getAny(), parameterName, parameterValue);
} catch (JAXBException e) {
e.printStackTrace();
return null;
} catch (ParserConfigurationException e) {
e.printStackTrace();
return null;
}
return el;
}
public LocalizationType createSphericalLoc(PamDataUnit dataUnit) { public LocalizationType createSphericalLoc(PamDataUnit dataUnit) {
// TODO Auto-generated method stub // TODO Auto-generated method stub

View File

@ -2,17 +2,8 @@ package tethys.localization;
import java.util.ArrayList; import java.util.ArrayList;
import Localiser.detectionGroupLocaliser.GroupLocResult;
import Localiser.detectionGroupLocaliser.GroupLocalisation;
import PamDetection.AbstractLocalisation;
import PamDetection.LocContents;
import PamUtils.LatLong;
import PamUtils.PamUtils;
import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataBlock;
import nilus.Localize; import nilus.Localize;
import nilus.SpeciesIDType;
import pamMaths.PamVector;
import nilus.Localize.Effort.CoordinateReferenceSystem;
import tethys.Collection; import tethys.Collection;
import tethys.CollectionHandler; import tethys.CollectionHandler;
import tethys.TethysControl; import tethys.TethysControl;

View File

@ -0,0 +1,122 @@
package tethys.localization;
import PamUtils.PamUtils;
import tethys.pamdata.AutoTethysProvider;
/**
* Static formatting (rounding and range checking) functions for latlong values.
* @author dg50
*
*/
public class TethysLatLong {
/*
* A degree is 60 minutes and a minute is one mile = 1852m.
* Therefore one metre of latitude is 9e-6 degrees.
* One mm of latitude is therefore 9e-9 degrees.
* GPS Accuracy is generally <3m, so 6dp generally OK for track data. however,
* localisations around a small static array may want mm accuracy, so need 8dp.
* For a double precision number, resolution at 360 degrees is 14dp
*
*/
/**
* Number of decimal places for metre accuracy
*/
public static int metreDecimalPlaces = 6;
/**
* Number of decimal places for mm accuracy.
*/
public static int mmDecimalPlaces = 9;
/**
* Check range of a latitude value.
* This function does absolutely nothing, but is here for completeness.
* @param latitude
* @return
*/
public static Double formatLatitude(Double latitude) {
if (latitude == null) {
return null;
}
return latitude;
}
/**
* Check range and round a latitude value to a set number of decimal places.
* @param latitude
* @param decimalPlaces
* @return
*/
public static Double formatLatitude(Double latitude, int decimalPlaces) {
if (latitude == null) {
return null;
}
return AutoTethysProvider.roundDecimalPlaces(latitude, decimalPlaces);
}
/**
* format a latitude to metre accuracy
* @param latitude
* @return
*/
public static Double formatLatitude_m(Double latitude) {
return formatLatitude(latitude, metreDecimalPlaces);
}
/**
* format a latitude to mm accuracy
* @param latitude
* @return
*/
public static Double formatLatitude_mm(Double latitude) {
return formatLatitude(latitude, mmDecimalPlaces);
}
/**
* Check range of a longitude value which must be between 0 and 360.
* This function does absolutely nothing, but is here for completeness.
* @param latitude
* @return
*/
public static Double formatLongitude(Double longitude) {
if (longitude == null) {
return null;
}
return PamUtils.constrainedAngle(longitude);
}
/**
* Check range and round a longitude value to a set number of decimal places.
* @param latitude
* @param decimalPlaces
* @return
*/
public static Double formatLongitude(Double longitude, int decimalPlaces) {
if (longitude == null) {
return null;
}
longitude = formatLongitude(longitude); // constrain first.
return AutoTethysProvider.roundDecimalPlaces(longitude, decimalPlaces);
}
/**
* format a longitude value to m accuracy.
* @param latitude
* @return
*/
public static Double formatLongitude_m(Double longitude) {
return formatLongitude(longitude, metreDecimalPlaces);
}
/**
* format a longitude value to mm accuracy.
* @param latitude
* @return
*/
public static Double formatLongitude_mm(Double longitude) {
return formatLongitude(longitude, mmDecimalPlaces);
}
}

View File

@ -1,32 +1,34 @@
package tethys.pamdata; package tethys.pamdata;
import java.io.StringReader;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.xml.bind.JAXBException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import Localiser.LocalisationAlgorithm; import Localiser.LocalisationAlgorithm;
import Localiser.LocalisationAlgorithmInfo; import Localiser.LocalisationAlgorithmInfo;
import PamController.PamControlledUnit; import PamController.PamControlledUnit;
import PamController.PamSettings; import PamController.PamSettings;
import PamController.PamguardVersionInfo;
import PamController.settings.output.xml.PamguardXMLWriter;
import PamDetection.LocalisationInfo; import PamDetection.LocalisationInfo;
import PamUtils.XMLUtils;
import PamguardMVC.DataAutomationInfo; import PamguardMVC.DataAutomationInfo;
import PamguardMVC.DataUnitBaseData;
import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit; import PamguardMVC.PamDataUnit;
import PamguardMVC.PamProcess; import PamguardMVC.PamProcess;
import PamguardMVC.TFContourData; import PamguardMVC.TFContourData;
import PamguardMVC.TFContourProvider; import PamguardMVC.TFContourProvider;
import binaryFileStorage.DataUnitFileInformation; import binaryFileStorage.DataUnitFileInformation;
import generalDatabase.DBSchemaWriter;
import generalDatabase.SQLLogging;
import nilus.AlgorithmType; import nilus.AlgorithmType;
import nilus.Deployment; import nilus.Deployment;
import nilus.DescriptionType; import nilus.DescriptionType;
@ -52,23 +54,11 @@ import tethys.species.SpeciesMapItem;
import tethys.swing.export.ExportWizardCard; import tethys.swing.export.ExportWizardCard;
import whistleClassifier.WhistleContour; import whistleClassifier.WhistleContour;
import javax.xml.bind.JAXBException;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.net.URISyntaxException;
/** /**
* Automatically provides Tethys data for a PAMGuard datablock. * Automatically provides Tethys data for a PAMGuard datablock.
* Does most of what needs to be done, though individual modules * Does most of what needs to be done, though individual modules
* will want to override this, call the base createDetection function and then add a * will want to override this, call the base createDetection function and then add a
* few more bespoke elements. * few more bespoke elements.
* @author dg50 * @author dg50
* *
*/ */
@ -79,6 +69,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
private PamControlledUnit pamControlledUnit; private PamControlledUnit pamControlledUnit;
private TethysControl tethysControl; private TethysControl tethysControl;
private Helper helper; private Helper helper;
private boolean addFrequencyInfo = false;
public AutoTethysProvider(TethysControl tethysControl, PamDataBlock pamDataBlock) { public AutoTethysProvider(TethysControl tethysControl, PamDataBlock pamDataBlock) {
this.tethysControl = tethysControl; this.tethysControl = tethysControl;
@ -91,7 +82,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
e.printStackTrace(); e.printStackTrace();
} }
} }
@Override @Override
public DescriptionType getDescription(Deployment deployment, TethysExportParams tethysExportParams) { public DescriptionType getDescription(Deployment deployment, TethysExportParams tethysExportParams) {
DescriptionType description = new DescriptionType(); DescriptionType description = new DescriptionType();
@ -106,9 +97,9 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
@Override @Override
public AlgorithmType getAlgorithm(Collection collection) { public AlgorithmType getAlgorithm(Collection collection) {
/** /**
* Probably need to split this to provide detection algorithm parameters and * Probably need to split this to provide detection algorithm parameters and
* localisation algorithm parameters, or pass in the document type as a function * localisation algorithm parameters, or pass in the document type as a function
* argument. * argument.
*/ */
AlgorithmType algorithm = new AlgorithmType(); AlgorithmType algorithm = new AlgorithmType();
try { try {
@ -116,7 +107,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
} catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) { } catch (IllegalArgumentException | IllegalAccessException | InstantiationException e) {
e.printStackTrace(); e.printStackTrace();
} }
// do the parameters as normal whether it's dets or locs. // do the parameters as normal whether it's dets or locs.
nilus.AlgorithmType.Parameters algoParameters = this.getAlgorithmParameters(); nilus.AlgorithmType.Parameters algoParameters = this.getAlgorithmParameters();
if (algoParameters != null) { if (algoParameters != null) {
algorithm.setParameters(algoParameters); algorithm.setParameters(algoParameters);
@ -125,7 +116,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
nilus.AlgorithmType.Parameters locParameters = this.getLocalisationParameters(); nilus.AlgorithmType.Parameters locParameters = this.getLocalisationParameters();
if (locParameters == null) { if (locParameters == null) {
/* /*
* It seems Tethys MUST have parameters, so make an empty one if needed. * It seems Tethys MUST have parameters, so make an empty one if needed.
*/ */
locParameters = new nilus.AlgorithmType.Parameters(); locParameters = new nilus.AlgorithmType.Parameters();
} }
@ -133,7 +124,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
algorithm.setParameters(locParameters); algorithm.setParameters(locParameters);
} }
else if (locParameters != null) { else if (locParameters != null) {
// merge the two sets, putting the localisation information first. // merge the two sets, putting the localisation information first.
List<Element> mainList = algoParameters.getAny(); List<Element> mainList = algoParameters.getAny();
List<Element> locList = locParameters.getAny(); List<Element> locList = locParameters.getAny();
if (mainList != null && locList != null) { if (mainList != null && locList != null) {
@ -150,7 +141,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
} }
/** /**
* Localisation parameters. Some localisers don't actually have any parameters, * Localisation parameters. Some localisers don't actually have any parameters,
* but Tethys requires a parameters element, so if there aren't any, set a dummy * but Tethys requires a parameters element, so if there aren't any, set a dummy
* @return * @return
*/ */
@ -181,13 +172,13 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
nilus.AlgorithmType.Parameters parameters = new nilus.AlgorithmType.Parameters(); nilus.AlgorithmType.Parameters parameters = new nilus.AlgorithmType.Parameters();
List<Element> paramList = parameters.getAny(); List<Element> paramList = parameters.getAny();
paramList.add(paramEl); paramList.add(paramEl);
return parameters; return parameters;
} }
@Override @Override
public nilus.AlgorithmType.Parameters getAlgorithmParameters() { public nilus.AlgorithmType.Parameters getAlgorithmParameters() {
if (pamControlledUnit instanceof PamSettings == false) { if (!(pamControlledUnit instanceof PamSettings)) {
return null; return null;
} }
PamSettings pamSettings = (PamSettings) pamControlledUnit; PamSettings pamSettings = (PamSettings) pamControlledUnit;
@ -211,7 +202,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
/** /**
* Not used. Was an attempt to automatically add name spaces to the PAMGuard settings * Not used. Was an attempt to automatically add name spaces to the PAMGuard settings
* XML I generate, but we found a better way. * XML I generate, but we found a better way.
* @param doc * @param doc
* @param settingsEl * @param settingsEl
* @param xmlNameSpace * @param xmlNameSpace
@ -270,7 +261,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
DOMSource source = new DOMSource(doc); DOMSource source = new DOMSource(doc);
// Result // Result
// Source text = new StreamSource(new File("input.xml")); // Source text = new StreamSource(new File("input.xml"));
DOMResult result = new DOMResult(); DOMResult result = new DOMResult();
transformer.transform(source, result); transformer.transform(source, result);
@ -294,8 +285,8 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
} }
/** /**
* Algorithm method. Default is the module name. Can change to a paper citation * Algorithm method. Default is the module name. Can change to a paper citation
* by overriding this * by overriding this
* @return * @return
*/ */
private String getAlgorithmMethod() { private String getAlgorithmMethod() {
@ -335,16 +326,21 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
} }
detection.setSpeciesId(species); detection.setSpeciesId(species);
/* /*
* NOTE: I use channel bitmaps throughout since detections are often made on multiple channels. * NOTE: I use channel bitmaps throughout since detections are often made on multiple channels.
*/ */
detection.setChannel(BigInteger.valueOf(dataUnit.getChannelBitmap())); detection.setChannel(BigInteger.valueOf(dataUnit.getChannelBitmap()));
nilus.Detection.Parameters detParams = new nilus.Detection.Parameters(); nilus.Detection.Parameters detParams = new nilus.Detection.Parameters();
detection.setParameters(detParams); detection.setParameters(detParams);
double[] freqs = dataUnit.getFrequency(); if (addFrequencyInfo) {
if (freqs != null && freqs[1] != 0) { /**
detParams.setMinFreqHz(freqs[0]); * Don't add by default.
detParams.setMaxFreqHz(freqs[1]); */
double[] freqs = dataUnit.getFrequency();
if (freqs != null && freqs[1] != 0) {
detParams.setMinFreqHz(freqs[0]);
detParams.setMaxFreqHz(freqs[1]);
}
} }
double ampli = dataUnit.getAmplitudeDB(); double ampli = dataUnit.getAmplitudeDB();
ampli = roundDecimalPlaces(ampli, 1); ampli = roundDecimalPlaces(ampli, 1);
@ -359,7 +355,8 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
el.setAttribute("BinaryFile", fileInf.getShortFileName(2048)); el.setAttribute("BinaryFile", fileInf.getShortFileName(2048));
el.setAttribute("FileIndex", Long.valueOf(fileInf.getIndexInFile()).toString()); el.setAttribute("FileIndex", Long.valueOf(fileInf.getIndexInFile()).toString());
} }
if (dataUnit.getDatabaseIndex() >= 0) { if (dataUnit.getDatabaseIndex() > 0) {
// only write the database index if it's > 0, i.e. is used.
addUserDefined(detParams, "DatabaseId", String.format("%d", dataUnit.getDatabaseIndex())); addUserDefined(detParams, "DatabaseId", String.format("%d", dataUnit.getDatabaseIndex()));
} }
@ -387,7 +384,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
/** /**
* Get tonal sounds contour. Sadly there are two slightly different interfaces in use * Get tonal sounds contour. Sadly there are two slightly different interfaces in use
* in PAMGuard, so try them both. * in PAMGuard, so try them both.
* @param detParams * @param detParams
* @return true if a contour was added * @return true if a contour was added
*/ */
@ -402,7 +399,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
List<Double> offsetS = tonal.getOffsetS(); List<Double> offsetS = tonal.getOffsetS();
List<Double> hz = tonal.getHz(); List<Double> hz = tonal.getHz();
for (int i = 0; i < tMillis.length; i++) { for (int i = 0; i < tMillis.length; i++) {
offsetS.add(roundSignificantFigures((double) (tMillis[i]-tMillis[0]) / 1000., 4)); offsetS.add(roundSignificantFigures((tMillis[i]-tMillis[0]) / 1000., 4));
hz.add(roundSignificantFigures(fHz[i], 4)); hz.add(roundSignificantFigures(fHz[i], 4));
} }
detParams.setTonal(tonal); detParams.setTonal(tonal);
@ -485,7 +482,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
kind.setCall(mapItem.getCallType()); kind.setCall(mapItem.getCallType());
effortKinds.add(kind); effortKinds.add(kind);
} }
@ -495,7 +492,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
public String getDetectionsMethod() { public String getDetectionsMethod() {
/* /*
* could really do with knowing what type of detector we're dealing with, i.e. if it's * could really do with knowing what type of detector we're dealing with, i.e. if it's
* automatic or manual. For most blocks this is fixed, though some may have a mixture of both ! * automatic or manual. For most blocks this is fixed, though some may have a mixture of both !
*/ */
DataAutomationInfo dataAutomation = pamDataBlock.getDataAutomationInfo(); DataAutomationInfo dataAutomation = pamDataBlock.getDataAutomationInfo();
String method; String method;
@ -524,7 +521,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
String blockName = pamDataBlock.getDataName(); String blockName = pamDataBlock.getDataName();
String documentName; String documentName;
/** /**
* If the datablock name is the same as the unit name, no need to repeat onesself. * If the datablock name is the same as the unit name, no need to repeat onesself.
*/ */
if (pcuName.equals(blockName)) { if (pcuName.equals(blockName)) {
documentName = new String(pcuName); // copy it, since we're about to modify it! documentName = new String(pcuName); // copy it, since we're about to modify it!
@ -539,7 +536,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
public static double roundDecimalPlaces(double value, int decPlaces) { public static double roundDecimalPlaces(double value, int decPlaces) {
double scale = Math.pow(10, decPlaces); double scale = Math.pow(10, decPlaces);
long longVal = Math.round(value*scale); long longVal = Math.round(value*scale);
return (double) longVal/scale; return longVal/scale;
} }
public static double roundSignificantFigures(double value, int sigFigs) { public static double roundSignificantFigures(double value, int sigFigs) {
@ -551,7 +548,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
double scale = sigFigs-Math.floor(Math.log10(value)); double scale = sigFigs-Math.floor(Math.log10(value));
scale = Math.pow(10, scale); scale = Math.pow(10, scale);
long longVal = Math.round(value*scale); long longVal = Math.round(value*scale);
return sign*(double) longVal/scale; return sign*longVal/scale;
} }
@Override @Override
@ -571,7 +568,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
return true; return true;
} }
@Override @Override
public boolean canExportLocalisations(GranularityEnumType granularityType) { public boolean canExportLocalisations(GranularityEnumType granularityType) {
LocalisationInfo locCont = pamDataBlock.getLocalisationContents(); LocalisationInfo locCont = pamDataBlock.getLocalisationContents();
@ -582,7 +579,7 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
} }
/** /**
* Granularity is OK for export. * Granularity is OK for export.
* @param granularityType * @param granularityType
* @return * @return
*/ */
@ -607,7 +604,21 @@ abstract public class AutoTethysProvider implements TethysDataProvider {
protected PamDataBlock getPamDataBlock() { protected PamDataBlock getPamDataBlock() {
return pamDataBlock; return pamDataBlock;
} }
/**
* @return the addFrequencyInfo
*/
public boolean isAddFrequencyInfo() {
return addFrequencyInfo;
}
/**
* @param addFrequencyInfo the addFrequencyInfo to set
*/
public void setAddFrequencyInfo(boolean addFrequencyInfo) {
this.addFrequencyInfo = addFrequencyInfo;
}
} }

View File

@ -7,8 +7,14 @@ package tethys.species;
*/ */
public class ITISTypes { public class ITISTypes {
/*
* A few that get used in defaults copied from itis.gov for convenience.
*/
public static final int OTHER = -10; public static final int OTHER = -10;
public static final int ANTHROPOGENIC = 1758; public static final int ANTHROPOGENIC = 1758;
public static final int CETACEAN = 180403;
public static final int ODONTOCETE = 180404;
public static final int MYSTICETE = 552298;
public static final String getName(int code) { public static final String getName(int code) {
switch (code) { switch (code) {

View File

@ -8,6 +8,7 @@ public class WhistleMoanTethysProvider extends AutoTethysProvider {
public WhistleMoanTethysProvider(TethysControl tethysControl, PamDataBlock pamDataBlock) { public WhistleMoanTethysProvider(TethysControl tethysControl, PamDataBlock pamDataBlock) {
super(tethysControl, pamDataBlock); super(tethysControl, pamDataBlock);
setAddFrequencyInfo(true);
} }
} }