More detection work

This commit is contained in:
Douglas Gillespie 2023-03-15 22:04:13 +00:00
parent 4876899b54
commit 27b8456c5a
8 changed files with 230 additions and 94 deletions

View File

@ -16,5 +16,10 @@ abstract public class MovingHydrophoneLocator extends SimpleHydrophoneLocator {
super(pamArray, streamer); super(pamArray, streamer);
} }
@Override
public boolean isChangeable() {
return true;
}
} }

View File

@ -464,7 +464,7 @@ final public class PamModel implements PamModelInterface, PamSettings {
mi = PamModuleInfo.registerControlledUnit(MetaDataContol.class.getName(), MetaDataContol.unitType); mi = PamModuleInfo.registerControlledUnit(MetaDataContol.class.getName(), MetaDataContol.unitType);
mi.setToolTipText("Deployment Meta Data"); mi.setToolTipText("Project Meta Data");
mi.setModulesMenuGroup(utilitiesGroup); mi.setModulesMenuGroup(utilitiesGroup);
mi.setMaxNumber(1); mi.setMaxNumber(1);

View File

@ -218,7 +218,7 @@ public class RWEBinaryDataSource extends BinaryDataSource {
binaryObjectData.getDataUnitBaseData().setSampleDuration(duration); binaryObjectData.getDataUnitBaseData().setSampleDuration(duration);
// rweDataUnit = new RWEDataUnit(aSound.timeMilliseconds, channelMap, // rweDataUnit = new RWEDataUnit(aSound.timeMilliseconds, channelMap,
// startSample, duration, aSound); // startSample, duration, aSound);
rweDataUnit = new RWEDataUnit(binaryObjectData.getDataUnitBaseData(), aSound); rweDataUnit = new RWEDataUnit(rweProcess, binaryObjectData.getDataUnitBaseData(), aSound);
rweDataUnit.setSequenceBitmap(sequenceMap); rweDataUnit.setSequenceBitmap(sequenceMap);
double f[] = new double[2]; double f[] = new double[2];
f[0] = aSound.minFreq * rweDataBlock.getSampleRate()/rweDataBlock.getFftLength(); f[0] = aSound.minFreq * rweDataBlock.getSampleRate()/rweDataBlock.getFftLength();

View File

@ -6,26 +6,31 @@ import whistlesAndMoans.AbstractWhistleDataUnit;
public class RWEDataUnit extends AbstractWhistleDataUnit { public class RWEDataUnit extends AbstractWhistleDataUnit {
public RWESound rweSound; public RWESound rweSound;
private RWEProcess rweProcess;
public RWEDataUnit(long timeMilliseconds, int channelBitmap, public RWEDataUnit(RWEProcess rweProcess, long timeMilliseconds, int channelBitmap,
long startSample, long duration, RWESound rweSound) { long startSample, long duration, RWESound rweSound) {
super(timeMilliseconds, channelBitmap, startSample, duration); super(timeMilliseconds, channelBitmap, startSample, duration);
this.rweSound = rweSound; this.rweSound = rweSound;
this.rweProcess = rweProcess;
// TODO Auto-generated constructor stub // TODO Auto-generated constructor stub
} }
public RWEDataUnit(DataUnitBaseData basicData, RWESound rweSound) { public RWEDataUnit(RWEProcess rweProcess, DataUnitBaseData basicData, RWESound rweSound) {
super(basicData); super(basicData);
this.rweSound = rweSound; this.rweSound = rweSound;
this.rweProcess = rweProcess;
} }
double[] freqsHz;
@Override @Override
public double[] getFreqsHz() { public double[] getFreqsHz() {
if (freqsHz == null) { double[] f = new double[rweSound.sliceCount];
freqsHz = new double[rweSound.sliceCount]; RWEDataBlock rweDataBlock = rweProcess.getRweDataBlock();
double binToHz = rweDataBlock.getSampleRate() / rweDataBlock.getFftLength();
for (int i = 0; i < f.length; i++) {
f[i] = (double) rweSound.peakFreq[i] * binToHz;
} }
return null; return f;
} }
@Override @Override
@ -35,9 +40,17 @@ public class RWEDataUnit extends AbstractWhistleDataUnit {
@Override @Override
public double[] getTimesInSeconds() { public double[] getTimesInSeconds() {
// TODO Auto-generated method stub if (rweSound == null) {
return null; return null;
} }
double[] t = new double[rweSound.sliceCount];
RWEDataBlock rweDataBlock = rweProcess.getRweDataBlock();
double binToT = rweDataBlock.getFftHop() / rweDataBlock.getSampleRate();
for (int i = 0; i < t.length; i++) {
t[i] = (double) rweSound.sliceList[i] * binToT;
}
return t;
}
@Override @Override
public String getSummaryString() { public String getSummaryString() {

View File

@ -42,6 +42,10 @@ public class RWEProcess extends PamProcess {
private FFTDataBlock sourceDataBlock; private FFTDataBlock sourceDataBlock;
private RWEDataBlock rweDataBlock; private RWEDataBlock rweDataBlock;
public RWEDataBlock getRweDataBlock() {
return rweDataBlock;
}
private Hashtable<Integer, BearingLocaliser> bearingLocalisers; private Hashtable<Integer, BearingLocaliser> bearingLocalisers;
private StandardSymbolManager symbolManager; private StandardSymbolManager symbolManager;
/** /**
@ -211,7 +215,7 @@ public class RWEProcess extends PamProcess {
// System.out.println(String.format("Detected sound type %d on channel %d", // System.out.println(String.format("Detected sound type %d on channel %d",
// soundType, this.iChannel)); // soundType, this.iChannel));
duration = sourceDataBlock.getFftHop() * aSound.duration; duration = sourceDataBlock.getFftHop() * aSound.duration;
rweDataUnit = new RWEDataUnit(aSound.timeMilliseconds, rweDataUnit = new RWEDataUnit(RWEProcess.this, aSound.timeMilliseconds,
1<<iChannel, fftDataUnit.getStartSample()-duration, duration, aSound); 1<<iChannel, fftDataUnit.getStartSample()-duration, duration, aSound);
rweDataUnit.sortOutputMaps(sourceDataBlock.getChannelMap(), sourceDataBlock.getSequenceMapObject(), 1<<iChannel); rweDataUnit.sortOutputMaps(sourceDataBlock.getChannelMap(), sourceDataBlock.getSequenceMapObject(), 1<<iChannel);
f[0] = aSound.minFreq * getSampleRate()/sourceDataBlock.getFftLength(); f[0] = aSound.minFreq * getSampleRate()/sourceDataBlock.getFftLength();

View File

@ -1,6 +1,5 @@
package tethys.deployment; package tethys.deployment;
import java.io.Serializable;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -16,23 +15,26 @@ import Acquisition.DaqStatusDataUnit;
import Acquisition.DaqSystem; import Acquisition.DaqSystem;
import Array.ArrayManager; import Array.ArrayManager;
import Array.Hydrophone; import Array.Hydrophone;
import Array.HydrophoneLocator;
import Array.PamArray; import Array.PamArray;
import Array.Streamer;
import Array.ThreadingHydrophoneLocator;
import PamController.PamControlledUnit; import PamController.PamControlledUnit;
import PamController.PamController; import PamController.PamController;
import PamUtils.PamCalendar;
import PamUtils.PamUtils;
import PamguardMVC.PamDataBlock; import PamguardMVC.PamDataBlock;
import metadata.MetaDataContol;
import metadata.deployment.DeploymentData;
import nilus.Audio; import nilus.Audio;
import nilus.ChannelInfo; import nilus.ChannelInfo;
import nilus.ChannelInfo.Sampling; import nilus.ChannelInfo.Sampling;
import nilus.ChannelInfo.Sampling.Regimen; import nilus.ChannelInfo.Sampling.Regimen;
import nilus.Deployment; import nilus.Deployment;
import nilus.Deployment.Instrument;
import nilus.Deployment.SamplingDetails; import nilus.Deployment.SamplingDetails;
import nilus.Deployment.Sensors; import nilus.Deployment.Sensors;
import nilus.DeploymentRecoveryDetails; import nilus.DeploymentRecoveryDetails;
import nilus.GeometryTypeM; import nilus.GeometryTypeM;
import nilus.Helper; import nilus.Helper;
import nilus.MarshalXML;
import pamMaths.PamVector; import pamMaths.PamVector;
import tethys.TethysLocationFuncs; import tethys.TethysLocationFuncs;
import tethys.TethysTimeFuncs; import tethys.TethysTimeFuncs;
@ -52,7 +54,7 @@ public class DeploymentHandler {
public DeploymentOverview createOverview() { public DeploymentOverview createOverview() {
// first find an acquisition module. // first find an acquisition module.
PamControlledUnit aModule = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null); PamControlledUnit aModule = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
if (aModule instanceof AcquisitionControl == false) { if (!(aModule instanceof AcquisitionControl)) {
// will return if it's null. Impossible for it to be the wrong type. // will return if it's null. Impossible for it to be the wrong type.
// but it's good practice to check anyway before casting. // but it's good practice to check anyway before casting.
return null; return null;
@ -192,7 +194,7 @@ public class DeploymentHandler {
// first find an acquisition module. // first find an acquisition module.
PamControlledUnit aModule = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null); PamControlledUnit aModule = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
if (aModule instanceof AcquisitionControl == false) { if (!(aModule instanceof AcquisitionControl)) {
// will return if it's null. Impossible for it to be the wrong type. // will return if it's null. Impossible for it to be the wrong type.
// but it's good practice to check anyway before casting. // but it's good practice to check anyway before casting.
return null; return null;
@ -289,6 +291,8 @@ public class DeploymentHandler {
TethysLocationFuncs.getTrackAndPositionData(deployment); TethysLocationFuncs.getTrackAndPositionData(deployment);
getProjectData(deployment);
getSamplingDetails(deployment); getSamplingDetails(deployment);
getSensorDetails(deployment); getSensorDetails(deployment);
@ -305,6 +309,58 @@ public class DeploymentHandler {
return deployment; return deployment;
} }
/**
* Add project Metadata to a Deploymnet document. This is currently being
* made available in the MetaDataControl module which should be added to PAMGuard
* as well as the Tethys output module.
* @param deployment
*/
private boolean getProjectData(Deployment deployment) {
PamControlledUnit aUnit = PamController.getInstance().findControlledUnit(MetaDataContol.class, null);
if (aUnit instanceof MetaDataContol == false) {
return false;
}
MetaDataContol metaControl = (MetaDataContol) aUnit;
DeploymentData deploymentData = metaControl.getDeploymentData();
deployment.setProject(deploymentData.getProject());
deployment.setDeploymentAlias(deploymentData.getDeploymentAlias());
deployment.setSite(deploymentData.getSite());
deployment.setCruise(deploymentData.getCruise());
deployment.setPlatform(deploymentData.getPlatform());
deployment.setRegion(deploymentData.getRegion());
Instrument instrument = new Instrument();
instrument.setType(deploymentData.getInstrumentType());
instrument.setInstrumentId(deploymentData.getInstrumentId());
// get the geometry type from the array manager.
String geomType = getGeometryType();
instrument.setGeometryType(geomType);
deployment.setInstrument(instrument);
return true;
}
/**
* Get a geometry type string for Tethys based on information in the array manager.
* @return
*/
private String getGeometryType() {
PamArray array = ArrayManager.getArrayManager().getCurrentArray();
int nStreamer = array.getStreamerCount();
for (int i = 0; i < nStreamer; i++) {
Streamer streamer = array.getStreamer(i);
HydrophoneLocator locator = streamer.getHydrophoneLocator();
if (locator == null) {
continue;
}
if (locator instanceof ThreadingHydrophoneLocator) {
return "cabled";
}
else {
return "rigid";
}
}
return "unknown";
}
private boolean getSensorDetails(Deployment deployment) { private boolean getSensorDetails(Deployment deployment) {
PamArray array = ArrayManager.getArrayManager().getCurrentArray(); PamArray array = ArrayManager.getArrayManager().getCurrentArray();
Sensors sensors = new Sensors(); Sensors sensors = new Sensors();
@ -385,7 +441,7 @@ public class DeploymentHandler {
channelInfo.setEnd(deployment.getRecoveryDetails().getAudioTimeStamp()); channelInfo.setEnd(deployment.getRecoveryDetails().getAudioTimeStamp());
BigIntegerConverter biCon = new BigIntegerConverter(); BigIntegerConverter biCon = new BigIntegerConverter();
BigInteger chanNum = BigInteger.valueOf((long) i); BigInteger chanNum = BigInteger.valueOf(i);
channelInfo.setChannelNumber(chanNum); channelInfo.setChannelNumber(chanNum);
if (hydroMap != null) { if (hydroMap != null) {
channelInfo.setSensorNumber(hydroMap[i]); channelInfo.setSensorNumber(hydroMap[i]);

View File

@ -13,9 +13,12 @@ import PamController.PamSettings;
import PamController.PamguardVersionInfo; import PamController.PamguardVersionInfo;
import PamController.settings.output.xml.PamguardXMLWriter; import PamController.settings.output.xml.PamguardXMLWriter;
import PamUtils.XMLUtils; import PamUtils.XMLUtils;
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.TFContourProvider;
import generalDatabase.DBSchemaWriter; import generalDatabase.DBSchemaWriter;
import generalDatabase.SQLLogging; import generalDatabase.SQLLogging;
import nilus.AlgorithmType; import nilus.AlgorithmType;
@ -27,6 +30,7 @@ import nilus.SpeciesIDType;
import tethys.TethysTimeFuncs; import tethys.TethysTimeFuncs;
import tethys.output.StreamExportParams; import tethys.output.StreamExportParams;
import tethys.output.TethysExportParams; import tethys.output.TethysExportParams;
import whistleClassifier.WhistleContour;
/** /**
* Automatically provides Tethys data based on the SQL database interface * Automatically provides Tethys data based on the SQL database interface
@ -182,9 +186,64 @@ public class AutoTethysProvider implements TethysDataProvider {
*/ */
detection.setChannel(BigInteger.valueOf(dataUnit.getChannelBitmap())); detection.setChannel(BigInteger.valueOf(dataUnit.getChannelBitmap()));
nilus.Detection.Parameters detParams = new nilus.Detection.Parameters();
detection.setParameters(detParams);
double[] freqs = dataUnit.getFrequency();
if (freqs != null) {
detParams.setMinFreqHz(freqs[0]);
detParams.setMaxFreqHz(freqs[1]);
}
double ampli = dataUnit.getAmplitudeDB();
detParams.setReceivedLevelDB(ampli);
// DataUnitBaseData basicData = dataUnit.getBasicData();
gotTonalContour(dataUnit, detParams);
return detection; return detection;
} }
/**
* Get tonal sounds contour. Sadly there are two slightly different interfaces in use
* in PAMGuard, so try them both.
* @param detParams
* @return true if a contour was added
*/
private boolean gotTonalContour(PamDataUnit dataUnit, nilus.Detection.Parameters detParams) {
if (dataUnit instanceof TFContourProvider) {
TFContourProvider tfcp = (TFContourProvider) dataUnit;
TFContourData cd = tfcp.getTFContourData();
if (cd != null) {
long[] tMillis = cd.getContourTimes();
double[] fHz = cd.getRidgeFrequency();
nilus.Detection.Parameters.Tonal tonal = new nilus.Detection.Parameters.Tonal();
List<Double> offsetS = tonal.getOffsetS();
List<Double> hz = tonal.getHz();
for (int i = 0; i < tMillis.length; i++) {
offsetS.add((double) (tMillis[i]-tMillis[0]) / 1000.);
hz.add(fHz[i]);
}
detParams.setTonal(tonal);
return true;
}
}
if (dataUnit instanceof WhistleContour) {
WhistleContour wc = (WhistleContour) dataUnit;
double[] t = wc.getTimesInSeconds();
double[] f = wc.getFreqsHz();
if (t != null && f != null) {
nilus.Detection.Parameters.Tonal tonal = new nilus.Detection.Parameters.Tonal();
List<Double> offsetS = tonal.getOffsetS();
List<Double> hz = tonal.getHz();
for (int i = 0; i < t.length; i++) {
offsetS.add(t[i]-t[0]);
hz.add(f[i]);
}
detParams.setTonal(tonal);
return true;
}
}
return false;
}
private SpeciesIDType getSpeciesIdType() { private SpeciesIDType getSpeciesIdType() {
SpeciesIDType species = new SpeciesIDType(); SpeciesIDType species = new SpeciesIDType();
// species.s // species.s

View File

@ -7,9 +7,8 @@ import PamguardMVC.DataUnitBaseData;
import PamguardMVC.PamDataUnit; import PamguardMVC.PamDataUnit;
import PamguardMVC.TFContourProvider;; import PamguardMVC.TFContourProvider;;
public abstract class AbstractWhistleDataUnit public abstract class AbstractWhistleDataUnit extends PamDataUnit<PamDataUnit, PamDataUnit>
extends PamDataUnit<PamDataUnit, PamDataUnit> implements WhistleContour, PamDetection {
implements WhistleContour, PamDetection{
public AbstractWhistleDataUnit(long timeMilliseconds, int channelBitmap, public AbstractWhistleDataUnit(long timeMilliseconds, int channelBitmap,
long startSample, long duration) { long startSample, long duration) {