This commit is contained in:
kbolaughlin 2023-03-15 15:05:57 -07:00
commit d96ace1ca2
8 changed files with 230 additions and 94 deletions

View File

@ -16,5 +16,10 @@ abstract public class MovingHydrophoneLocator extends SimpleHydrophoneLocator {
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.setToolTipText("Deployment Meta Data");
mi.setToolTipText("Project Meta Data");
mi.setModulesMenuGroup(utilitiesGroup);
mi.setMaxNumber(1);

View File

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

View File

@ -6,26 +6,31 @@ import whistlesAndMoans.AbstractWhistleDataUnit;
public class RWEDataUnit extends AbstractWhistleDataUnit {
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) {
super(timeMilliseconds, channelBitmap, startSample, duration);
this.rweSound = rweSound;
this.rweProcess = rweProcess;
// TODO Auto-generated constructor stub
}
public RWEDataUnit(DataUnitBaseData basicData, RWESound rweSound) {
public RWEDataUnit(RWEProcess rweProcess, DataUnitBaseData basicData, RWESound rweSound) {
super(basicData);
this.rweSound = rweSound;
this.rweProcess = rweProcess;
}
double[] freqsHz;
@Override
public double[] getFreqsHz() {
if (freqsHz == null) {
freqsHz = new double[rweSound.sliceCount];
double[] f = 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
@ -35,8 +40,16 @@ public class RWEDataUnit extends AbstractWhistleDataUnit {
@Override
public double[] getTimesInSeconds() {
// TODO Auto-generated method stub
return null;
if (rweSound == 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

View File

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

View File

@ -1,6 +1,5 @@
package tethys.deployment;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
@ -16,29 +15,32 @@ import Acquisition.DaqStatusDataUnit;
import Acquisition.DaqSystem;
import Array.ArrayManager;
import Array.Hydrophone;
import Array.HydrophoneLocator;
import Array.PamArray;
import Array.Streamer;
import Array.ThreadingHydrophoneLocator;
import PamController.PamControlledUnit;
import PamController.PamController;
import PamUtils.PamCalendar;
import PamUtils.PamUtils;
import PamguardMVC.PamDataBlock;
import metadata.MetaDataContol;
import metadata.deployment.DeploymentData;
import nilus.Audio;
import nilus.ChannelInfo;
import nilus.ChannelInfo.Sampling;
import nilus.ChannelInfo.Sampling.Regimen;
import nilus.Deployment;
import nilus.Deployment.Instrument;
import nilus.Deployment.SamplingDetails;
import nilus.Deployment.Sensors;
import nilus.DeploymentRecoveryDetails;
import nilus.GeometryTypeM;
import nilus.Helper;
import nilus.MarshalXML;
import pamMaths.PamVector;
import tethys.TethysLocationFuncs;
import tethys.TethysTimeFuncs;
/**
* Functions to gather data for the deployment document from all around PAMGuard.
* Functions to gather data for the deployment document from all around PAMGuard.
* @author dg50
*
*/
@ -46,42 +48,42 @@ public class DeploymentHandler {
/**
* Get an overview of all the deployments.
* Get an overview of all the deployments.
* @return
*/
public DeploymentOverview createOverview() {
// first find an acquisition module.
// first find an acquisition module.
PamControlledUnit aModule = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
if (aModule instanceof AcquisitionControl == false) {
// will return if it's null. Impossible for it to be the wrong type.
// but it's good practice to check anyway before casting.
if (!(aModule instanceof AcquisitionControl)) {
// will return if it's null. Impossible for it to be the wrong type.
// but it's good practice to check anyway before casting.
return null;
}
// cast it to the right type.
// cast it to the right type.
AcquisitionControl daqControl = (AcquisitionControl) aModule;
AcquisitionParameters daqParams = daqControl.getAcquisitionParameters();
/**
* The daqParams class has most of what we need about the set up in terms of sample rate,
* number of channels, instrument type, ADC input range (part of calibration), etc.
* It also has a hydrophone list, which maps the input channel numbers to the hydrophon numbers.
* The daqParams class has most of what we need about the set up in terms of sample rate,
* number of channels, instrument type, ADC input range (part of calibration), etc.
* It also has a hydrophone list, which maps the input channel numbers to the hydrophon numbers.
* Realistically, this list is always 0,1,2,etc or it goes horribly wrong !
*/
// so write functions here to get information from the daqParams.
// so write functions here to get information from the daqParams.
// System.out.printf("Sample regime: %s input with rate %3.1fHz, %d channels, gain %3.1fdB, ADCp-p %3.1fV\n", daqParams.getDaqSystemType(),
// daqParams.getSampleRate(), daqParams.getNChannels(), daqParams.preamplifier.getGain(), daqParams.voltsPeak2Peak);
/**
* then there is the actual sampling. This is a bit harder to find. I thought it would be in the data map
* but the datamap is a simple count of what's in the databasase which is not quite what we want.
* we're going to have to query the database to get more detailed informatoin I think.
* I'll do that here for now, but we may want to move this when we better organise the code.
* but the datamap is a simple count of what's in the databasase which is not quite what we want.
* we're going to have to query the database to get more detailed informatoin I think.
* I'll do that here for now, but we may want to move this when we better organise the code.
* It also seems that there are 'bad' dates in the database when it starts new files, which are the date
* data were analysed at. So we really need to check the start and stop records only.
* data were analysed at. So we really need to check the start and stop records only.
*/
PamDataBlock<DaqStatusDataUnit> daqInfoDataBlock = daqControl.getAcquisitionProcess().getDaqStatusDataBlock();
// just load everything. Probably OK for the acqusition, but will bring down
// just load everything. Probably OK for the acqusition, but will bring down
daqInfoDataBlock.loadViewerData(0, Long.MAX_VALUE, null);
ArrayList<DaqStatusDataUnit> allStatusData = daqInfoDataBlock.getDataCopy();
ArrayList<RecordingPeriod> tempPeriods = null;
if (allStatusData == null || allStatusData.size() == 0) {
@ -95,7 +97,7 @@ public class DeploymentHandler {
System.out.println("Data appear to have no logged recording periods available either from the database or the raw recordings.");
}
int nPeriods = tempPeriods.size();
// now go through those and merge into longer periods where there is no gap between files.
// now go through those and merge into longer periods where there is no gap between files.
ListIterator<RecordingPeriod> iterator = tempPeriods.listIterator();
RecordingPeriod prevPeriod = null;
while (iterator.hasNext()) {
@ -108,7 +110,7 @@ public class DeploymentHandler {
long gap = nextPeriod.getRecordStart() - prevPeriod.getRecordStop();
long prevDur = prevPeriod.getRecordStop()-prevPeriod.getRecordStart();
if (gap < 3 || gap < prevDur/50) {
// ignoring up to 3s gap or a sample error < 2%.Dunno if this is sensible or not.
// ignoring up to 3s gap or a sample error < 2%.Dunno if this is sensible or not.
prevPeriod.setRecordStop(nextPeriod.getRecordStop());
iterator.remove();
nextPeriod = prevPeriod;
@ -121,16 +123,16 @@ public class DeploymentHandler {
DeploymentOverview deploymentOverview = new DeploymentOverview(false, tempPeriods);
return deploymentOverview;
// find the number of times it started and stopped ....
// System.out.printf("Input map of sound data indicates data from %s to %s with %d starts and %d stops over %d files\n",
// System.out.printf("Input map of sound data indicates data from %s to %s with %d starts and %d stops over %d files\n",
// PamCalendar.formatDateTime(dataStart), PamCalendar.formatDateTime(dataEnd), nStart, nStop, nFile+1);
// now work out where there are genuine gaps and make up a revised list of recording periods.
// now work out where there are genuine gaps and make up a revised list of recording periods.
}
/**
* Work out whether or not the data are evenly duty cycled by testing the
* distributions of on and off times.
* Work out whether or not the data are evenly duty cycled by testing the
* distributions of on and off times.
* @param tempPeriods
* @return
*/
@ -187,38 +189,38 @@ public class DeploymentHandler {
//in each channel
public ArrayList<DeploymentRecoveryPair> getDeployments() {
DeploymentOverview recordingOverview = createOverview();
// first find an acquisition module.
// first find an acquisition module.
PamControlledUnit aModule = PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
if (aModule instanceof AcquisitionControl == false) {
// will return if it's null. Impossible for it to be the wrong type.
// but it's good practice to check anyway before casting.
if (!(aModule instanceof AcquisitionControl)) {
// will return if it's null. Impossible for it to be the wrong type.
// but it's good practice to check anyway before casting.
return null;
}
// cast it to the right type.
// cast it to the right type.
AcquisitionControl daqControl = (AcquisitionControl) aModule;
AcquisitionParameters daqParams = daqControl.getAcquisitionParameters();
/**
* The daqParams class has most of what we need about the set up in terms of sample rate,
* number of channels, instrument type, ADC input range (part of calibration), etc.
* It also has a hydrophone list, which maps the input channel numbers to the hydrophon numbers.
* The daqParams class has most of what we need about the set up in terms of sample rate,
* number of channels, instrument type, ADC input range (part of calibration), etc.
* It also has a hydrophone list, which maps the input channel numbers to the hydrophon numbers.
* Realistically, this list is always 0,1,2,etc or it goes horribly wrong !
*/
// so write functions here to get information from the daqParams.
// so write functions here to get information from the daqParams.
// System.out.printf("Sample regime: %s input with rate %3.1fHz, %d channels, gain %3.1fdB, ADCp-p %3.1fV\n", daqParams.getDaqSystemType(),
// daqParams.getSampleRate(), daqParams.getNChannels(), daqParams.preamplifier.getGain(), daqParams.voltsPeak2Peak);
/**
* then there is the actual sampling. This is a bit harder to find. I thought it would be in the data map
* but the datamap is a simple count of what's in the databasase which is not quite what we want.
* we're going to have to query the database to get more detailed informatoin I think.
* I'll do that here for now, but we may want to move this when we better organise the code.
* but the datamap is a simple count of what's in the databasase which is not quite what we want.
* we're going to have to query the database to get more detailed informatoin I think.
* I'll do that here for now, but we may want to move this when we better organise the code.
* It also seems that there are 'bad' dates in the database when it starts new files, which are the date
* data were analysed at. So we really need to check the start and stop records only.
* data were analysed at. So we really need to check the start and stop records only.
*/
PamDataBlock<DaqStatusDataUnit> daqInfoDataBlock = daqControl.getAcquisitionProcess().getDaqStatusDataBlock();
// just load everything. Probably OK for the acqusition, but will bring down
// just load everything. Probably OK for the acqusition, but will bring down
daqInfoDataBlock.loadViewerData(0, Long.MAX_VALUE, null);
ArrayList<DaqStatusDataUnit> allStatusData = daqInfoDataBlock.getDataCopy();
long dataStart = Long.MAX_VALUE;
@ -241,24 +243,24 @@ public class DeploymentHandler {
break;
}
}
// System.out.printf("Input map of sound data indicates data from %s to %s with %d starts and %d stops over %d files\n",
// System.out.printf("Input map of sound data indicates data from %s to %s with %d starts and %d stops over %d files\n",
// PamCalendar.formatDateTime(dataStart), PamCalendar.formatDateTime(dataEnd), nStart, nStop, nFile+1);
}
// // and we find the datamap within that ...
// OfflineDataMap daqMap = daqInfoDataBlock.getOfflineDataMap(DBControlUnit.findDatabaseControl());
// if (daqMap != null) {
// // iterate through it.
// // iterate through it.
// long dataStart = daqMap.getFirstDataTime();
// long dataEnd = daqMap.getLastDataTime();
// List<OfflineDataMapPoint> mapPoints = daqMap.getMapPoints();
// System.out.printf("Input map of sound data indicates data from %s to %s with %d individual files\n",
// System.out.printf("Input map of sound data indicates data from %s to %s with %d individual files\n",
// PamCalendar.formatDateTime(dataStart), PamCalendar.formatDateTime(dataEnd), mapPoints.size());
// /*
// * clearly in the first database I've been looking at of Tinas data, this is NOT getting sensible start and
// * end times. Print them out to see what's going on.
// * end times. Print them out to see what's going on.
// */
//// for ()
// }
@ -267,18 +269,18 @@ public class DeploymentHandler {
DeploymentRecoveryDetails recovery = new DeploymentRecoveryDetails();
pair.deploymentDetails = deployment;
pair.recoveryDetails = recovery;
deployment.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataStart));
deployment.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataStart));
recovery.setTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataEnd));
recovery.setAudioTimeStamp(TethysTimeFuncs.xmlGregCalFromMillis(dataEnd));
ArrayList<DeploymentRecoveryPair> drPairs = new ArrayList<>();
drPairs.add(pair);
return drPairs;
}
public Deployment createDeploymentDocument(int i, DeploymentRecoveryPair drd) {
Deployment deployment = new Deployment();
String id = String.format("%d", i);
@ -286,25 +288,79 @@ public class DeploymentHandler {
deployment.setDeploymentId(i);
deployment.setDeploymentDetails(drd.deploymentDetails);
deployment.setRecoveryDetails(drd.recoveryDetails);
TethysLocationFuncs.getTrackAndPositionData(deployment);
getProjectData(deployment);
getSamplingDetails(deployment);
getSensorDetails(deployment);
/**
* Stuff that may need to be put into the UI:
* Audio: can easily get current loc of raw and binary data, but may need to override these. I think
* this may be for the export UI ?
* Tracks: trackline information. General problem in PAMGUard.
* Audio: can easily get current loc of raw and binary data, but may need to override these. I think
* this may be for the export UI ?
* Tracks: trackline information. General problem in PAMGUard.
*/
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) {
PamArray array = ArrayManager.getArrayManager().getCurrentArray();
Sensors sensors = new Sensors();
@ -322,7 +378,7 @@ public class DeploymentHandler {
PamVector hydLocs = array.getAbsHydrophoneVector(iPhone, timeMillis);
Audio audio = new Audio();
audio.setNumber(BigInteger.valueOf(iPhone));
audio.setSensorId(String.format("Hydrophone %d", iPhone)); // shold replace with serial number if it exists.
audio.setSensorId(String.format("Hydrophone %d", iPhone)); // shold replace with serial number if it exists.
GeometryTypeM geom = new GeometryTypeM();
geom.setXM(hydLocs.getCoordinate(0));
geom.setYM(hydLocs.getCoordinate(1));
@ -342,7 +398,7 @@ public class DeploymentHandler {
// e.printStackTrace();
// }
/**
* Need to be able to add the values from hydLocs to the geometry object, but can't.
* Need to be able to add the values from hydLocs to the geometry object, but can't.
*/
audioList.add(audio);
iPhone++;
@ -354,18 +410,18 @@ public class DeploymentHandler {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
deployment.setSensors(sensors);
deployment.setSensors(sensors);
return true;
}
/**
* Fill in the sampling details in a Deployment document.
* Fill in the sampling details in a Deployment document.
* @param deployment
*/
private boolean getSamplingDetails(Deployment deployment) {
SamplingDetails samplingDetails = new SamplingDetails();
// this is basically going to be a list of almost identical channel information
// currently just for the first acquisition. May extend to more.
// currently just for the first acquisition. May extend to more.
AcquisitionControl daq = (AcquisitionControl) PamController.getInstance().findControlledUnit(AcquisitionControl.class, null);
if (daq == null) {
return false;
@ -377,15 +433,15 @@ public class DeploymentHandler {
int[] hydroMap = daqParams.getHydrophoneList();
int[] inputMap = daqParams.getHardwareChannelList();
double vp2p = daqParams.getVoltsPeak2Peak();
List<ChannelInfo> channelInfos = samplingDetails.getChannel();
for (int i = 0; i < nChan; i++) {
ChannelInfo channelInfo = new ChannelInfo();
channelInfo.setStart(deployment.getDeploymentDetails().getAudioTimeStamp());
channelInfo.setEnd(deployment.getRecoveryDetails().getAudioTimeStamp());
BigIntegerConverter biCon = new BigIntegerConverter();
BigInteger chanNum = BigInteger.valueOf((long) i);
BigInteger chanNum = BigInteger.valueOf(i);
channelInfo.setChannelNumber(chanNum);
if (hydroMap != null) {
channelInfo.setSensorNumber(hydroMap[i]);
@ -402,7 +458,7 @@ public class DeploymentHandler {
nilus.ChannelInfo.Gain.Regimen aGain = new nilus.ChannelInfo.Gain.Regimen();
aGain.setGainDB(daqParams.getPreamplifier().getGain());
channelInfo.setGain(gain);
Sampling sampling = new Sampling();
List<Regimen> regimens = sampling.getRegimen();
Sampling.Regimen regimen = new Sampling.Regimen();
@ -412,14 +468,14 @@ public class DeploymentHandler {
regimen.setSampleBits(system.getSampleBits());
}
regimens.add(regimen);
channelInfo.setSampling(sampling);
channelInfos.add(channelInfo);
/**
* Need something about duty cycling. this is probably something that will have to be added
* earlier to a wrapper around the Deployment class.
* Need something about duty cycling. this is probably something that will have to be added
* earlier to a wrapper around the Deployment class.
*/
}
deployment.setSamplingDetails(samplingDetails);

View File

@ -13,9 +13,12 @@ import PamController.PamSettings;
import PamController.PamguardVersionInfo;
import PamController.settings.output.xml.PamguardXMLWriter;
import PamUtils.XMLUtils;
import PamguardMVC.DataUnitBaseData;
import PamguardMVC.PamDataBlock;
import PamguardMVC.PamDataUnit;
import PamguardMVC.PamProcess;
import PamguardMVC.TFContourData;
import PamguardMVC.TFContourProvider;
import generalDatabase.DBSchemaWriter;
import generalDatabase.SQLLogging;
import nilus.AlgorithmType;
@ -27,6 +30,7 @@ import nilus.SpeciesIDType;
import tethys.TethysTimeFuncs;
import tethys.output.StreamExportParams;
import tethys.output.TethysExportParams;
import whistleClassifier.WhistleContour;
/**
* 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()));
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;
}
/**
* 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() {
SpeciesIDType species = new SpeciesIDType();
// species.s

View File

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