Extra options for creating data selectors

Extra options so dataselectors can be kept simple and not include all
possible options for super detections as well as their own - more use
when selecting data for a superdetection !
This commit is contained in:
Douglas Gillespie 2022-06-17 15:04:24 +01:00
parent df5b3b4dfe
commit a26bb670d2
3 changed files with 193 additions and 117 deletions

View File

@ -3705,6 +3705,28 @@ public class PamDataBlock<Tunit extends PamDataUnit> extends PamObservable {
return blockDataSelector;
}
/**
* Convenience method to save programmer from having to call into the creator
* all the time.
*
* @param selectorName
* @param allowScores
* @param selectorType Type of selector, generally a ModuleType name, e.g. Map,
* so that options can be tailored to specific needs
* @param includeAnnotations include options from any annotators of this data stream
* @param includeSuperDetections include any possible super detection data selectors.
* @return null or a DataSelector
*/
public DataSelector getDataSelector(String selectorName, boolean allowScores, String selectorType,
boolean includeAnnotations, boolean includeSuperDetections) {
DataSelector blockDataSelector = null;
DataSelectorCreator dsc = getDataSelectCreator();
if (dsc != null) {
blockDataSelector = dsc.getDataSelector(selectorName, allowScores, selectorType, includeAnnotations, includeSuperDetections);
}
return blockDataSelector;
}
/**
* Get any information from the data block about cross referencing in database
* tables.

View File

@ -99,11 +99,26 @@ public class RawDataTransforms {
*/
private int shortestFFTLength;
private Object synchObject;
public RawDataTransforms(@SuppressWarnings("rawtypes") PamDataUnit rawDataHolder) {
/**
* Create a RawDataTransforms with a specified synchronisation object. This is mostly the data unit,
* but in some circumstances may need to be a different object to avoid thread lock.
* @param rawDataHolder
* @param synchObject
*/
public RawDataTransforms(@SuppressWarnings("rawtypes") PamDataUnit rawDataHolder, Object synchObject) {
this.rawData=(RawDataHolder) rawDataHolder;
this.dataUnit = rawDataHolder;
this.synchObject = synchObject;
}
/**
* Create raw data transforms using the rawDatAholder for synchronisation.
* @param rawDataHolder
*/
public RawDataTransforms(@SuppressWarnings("rawtypes") PamDataUnit rawDataHolder) {
this(rawDataHolder, rawDataHolder);
}
@ -118,7 +133,7 @@ public class RawDataTransforms {
return powerSpectra;
}
/**
* Get the shortest FFT length for the number of samples.
* The is the
@ -143,23 +158,25 @@ public class RawDataTransforms {
* @param fftLength
* @return Power spectrum
*/
public synchronized double[] getPowerSpectrum(int channel, int minBin, int maxBin, int fftLength) {
if (minBin==0 && maxBin>=this.getWaveData(0).length-1) {
return getPowerSpectrum(channel, fftLength);
}
if (fftLength == 0) {
fftLength = getCurrentSpectrumLength();
public double[] getPowerSpectrum(int channel, int minBin, int maxBin, int fftLength) {
synchronized (synchObject) {
if (minBin==0 && maxBin>=this.getWaveData(0).length-1) {
return getPowerSpectrum(channel, fftLength);
}
if (fftLength == 0) {
fftLength = getCurrentSpectrumLength();
}
double[] waveformTrim = new double[maxBin-minBin];
//System.out.println("minBin: " + minBin + " maxBin: " + maxBin + " raw waveform: " + this.getWaveData(channel).length);
System.arraycopy(this.getWaveData(channel), minBin, waveformTrim, 0, Math.min(this.getWaveData(channel).length-minBin-1, waveformTrim.length));
ComplexArray cData = getComplexSpectrumHann(waveformTrim, fftLength);
return cData.magsq();
}
double[] waveformTrim = new double[maxBin-minBin];
//System.out.println("minBin: " + minBin + " maxBin: " + maxBin + " raw waveform: " + this.getWaveData(channel).length);
System.arraycopy(this.getWaveData(channel), minBin, waveformTrim, 0, Math.min(this.getWaveData(channel).length-minBin-1, waveformTrim.length));
ComplexArray cData = getComplexSpectrumHann(waveformTrim, fftLength);
return cData.magsq();
}
/**
@ -170,29 +187,31 @@ public class RawDataTransforms {
* @param fftLength
* @return Power spectrum
*/
public synchronized double[] getPowerSpectrum(int channel, int fftLength) {
if (powerSpectra == null) {
powerSpectra = new double[PamUtils.getNumChannels(dataUnit.getChannelBitmap())][];
}
if (fftLength == 0) {
fftLength = getCurrentSpectrumLength();
}
if (powerSpectra[channel] == null
|| powerSpectra[channel].length != fftLength / 2) {
ComplexArray cData = getComplexSpectrumHann(channel, fftLength);
currentSpecLen = fftLength;
powerSpectra[channel] = cData.magsq();
if (powerSpectra==null){
System.err.println("DLDetection: could not calculate power spectra");
return null;
public double[] getPowerSpectrum(int channel, int fftLength) {
synchronized (synchObject) {
if (powerSpectra == null) {
powerSpectra = new double[PamUtils.getNumChannels(dataUnit.getChannelBitmap())][];
}
if (powerSpectra[channel].length != fftLength/2) {
powerSpectra[channel] = Arrays.copyOf(powerSpectra[channel], fftLength/2);
if (fftLength == 0) {
fftLength = getCurrentSpectrumLength();
}
if (powerSpectra[channel] == null
|| powerSpectra[channel].length != fftLength / 2) {
ComplexArray cData = getComplexSpectrumHann(channel, fftLength);
currentSpecLen = fftLength;
powerSpectra[channel] = cData.magsq();
if (powerSpectra==null){
System.err.println("DLDetection: could not calculate power spectra");
return null;
}
if (powerSpectra[channel].length != fftLength/2) {
powerSpectra[channel] = Arrays.copyOf(powerSpectra[channel], fftLength/2);
}
}
return powerSpectra[channel];
}
return powerSpectra[channel];
}
@ -202,25 +221,27 @@ public class RawDataTransforms {
* @param fftLength
* @return Sum of power spectra
*/
public synchronized double[] getTotalPowerSpectrum(int fftLength) {
if (fftLength == 0) {
fftLength = getCurrentSpectrumLength();
}
if (fftLength == 0) {
fftLength = PamUtils.getMinFftLength(getSampleDuration());
}
double[] ps;
if (totalPowerSpectrum == null
|| totalPowerSpectrum.length != fftLength / 2) {
totalPowerSpectrum = new double[fftLength / 2];
for (int c = 0; c < PamUtils.getNumChannels(this.dataUnit.getChannelBitmap()); c++) {
ps = getPowerSpectrum(c, fftLength);
for (int i = 0; i < fftLength / 2; i++) {
totalPowerSpectrum[i] += ps[i];
public double[] getTotalPowerSpectrum(int fftLength) {
synchronized (synchObject) {
if (fftLength == 0) {
fftLength = getCurrentSpectrumLength();
}
if (fftLength == 0) {
fftLength = PamUtils.getMinFftLength(getSampleDuration());
}
double[] ps;
if (totalPowerSpectrum == null
|| totalPowerSpectrum.length != fftLength / 2) {
totalPowerSpectrum = new double[fftLength / 2];
for (int c = 0; c < PamUtils.getNumChannels(this.dataUnit.getChannelBitmap()); c++) {
ps = getPowerSpectrum(c, fftLength);
for (int i = 0; i < fftLength / 2; i++) {
totalPowerSpectrum[i] += ps[i];
}
}
}
return totalPowerSpectrum;
}
return totalPowerSpectrum;
}
@ -235,15 +256,17 @@ public class RawDataTransforms {
* @param fftLength - the FFT length to use.
* @return the complex spectrum - the comnplex spectrum of the wave data from the specified channel.
*/
public synchronized ComplexArray getComplexSpectrumHann(int channel, int fftLength) {
complexSpectrum = new ComplexArray[PamUtils.getNumChannels(dataUnit.getChannelBitmap())];
if (complexSpectrum[channel] == null
|| complexSpectrum.length != fftLength / 2) {
public ComplexArray getComplexSpectrumHann(int channel, int fftLength) {
synchronized (synchObject) {
complexSpectrum = new ComplexArray[PamUtils.getNumChannels(dataUnit.getChannelBitmap())];
if (complexSpectrum[channel] == null
|| complexSpectrum.length != fftLength / 2) {
complexSpectrum[channel] = getComplexSpectrumHann(rawData.getWaveData()[channel], fftLength);
currentSpecLen = fftLength;
complexSpectrum[channel] = getComplexSpectrumHann(rawData.getWaveData()[channel], fftLength);
currentSpecLen = fftLength;
}
return complexSpectrum[channel];
}
return complexSpectrum[channel];
}
@ -300,8 +323,8 @@ public class RawDataTransforms {
public ClipSpectrogram getSpectrogram(int fftSize, int fftHop) {
return getSpectrogram( fftSize, fftHop, 1);
}
/**
* Get a spectrogram image of the wave clip. The clip is null until called. It is recalculated if the
* FFT length and/or hop size are different.
@ -371,29 +394,31 @@ public class RawDataTransforms {
* @param fftLength
* @return the complex spectrum
*/
public synchronized ComplexArray getComplexSpectrum(int channel, int fftLength) {
double[] paddedRawData;
double[] rawData;
int i, mn;
public ComplexArray getComplexSpectrum(int channel, int fftLength) {
synchronized (synchObject) {
double[] paddedRawData;
double[] rawData;
int i, mn;
if (complexSpectrum == null) {
complexSpectrum = new ComplexArray[getNChan()];
}
if (complexSpectrum[channel] == null
|| complexSpectrum.length != fftLength / 2) {
paddedRawData = new double[fftLength];
rawData = getWaveData(channel);
//double[] rotData = getRotationCorrection(channel);
mn = Math.min(fftLength, getSampleDuration().intValue());
for (i = 0; i < mn; i++) {
paddedRawData[i] = rawData[i];//-rotData[i];
if (complexSpectrum == null) {
complexSpectrum = new ComplexArray[getNChan()];
}
for (i = mn; i < fftLength; i++) {
paddedRawData[i] = 0;
if (complexSpectrum[channel] == null
|| complexSpectrum.length != fftLength / 2) {
paddedRawData = new double[fftLength];
rawData = getWaveData(channel);
//double[] rotData = getRotationCorrection(channel);
mn = Math.min(fftLength, getSampleDuration().intValue());
for (i = 0; i < mn; i++) {
paddedRawData[i] = rawData[i];//-rotData[i];
}
for (i = mn; i < fftLength; i++) {
paddedRawData[i] = 0;
}
complexSpectrum[channel] = fastFFT.rfft(paddedRawData, fftLength);
}
complexSpectrum[channel] = fastFFT.rfft(paddedRawData, fftLength);
return complexSpectrum[channel];
}
return complexSpectrum[channel];
}
@ -402,14 +427,16 @@ public class RawDataTransforms {
* @param iChan channel index
* @return analytic waveform
*/
public synchronized double[] getAnalyticWaveform(int iChan) {
if (analyticWaveform == null) {
analyticWaveform = new double[getNChan()][];
public double[] getAnalyticWaveform(int iChan) {
synchronized (synchObject) {
if (analyticWaveform == null) {
analyticWaveform = new double[getNChan()][];
}
// if (analyticWaveform[iChan] == null) {
analyticWaveform[iChan] = hilbert.getHilbert(getWaveData(iChan));
// }
return analyticWaveform[iChan];
}
// if (analyticWaveform[iChan] == null) {
analyticWaveform[iChan] = hilbert.getHilbert(getWaveData(iChan));
// }
return analyticWaveform[iChan];
}
/**
@ -421,12 +448,14 @@ public class RawDataTransforms {
* @param fftFilterParams fft filter parameters.
* @return analystic waveform.
*/
public synchronized double[] getAnalyticWaveform(int iChan, boolean filtered, FFTFilterParams fftFilterParams) {
if (filtered == false || fftFilterParams == null) {
return getAnalyticWaveform(iChan);
}
else {
return getFilteredAnalyticWaveform(fftFilterParams, iChan);
public double[] getAnalyticWaveform(int iChan, boolean filtered, FFTFilterParams fftFilterParams) {
synchronized (synchObject) {
if (filtered == false || fftFilterParams == null) {
return getAnalyticWaveform(iChan);
}
else {
return getFilteredAnalyticWaveform(fftFilterParams, iChan);
}
}
}
@ -437,15 +466,17 @@ public class RawDataTransforms {
* @param iChan channel number
* @return envelope of the filtered data.
*/
public synchronized double[] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams, int iChan) {
if (analyticWaveform == null) {
analyticWaveform = new double[getNChan()][];
public double[] getFilteredAnalyticWaveform(FFTFilterParams fftFilterParams, int iChan) {
synchronized (synchObject) {
if (analyticWaveform == null) {
analyticWaveform = new double[getNChan()][];
}
// if (analyticWaveform[iChan] == null) {
analyticWaveform[iChan] = hilbert.
getHilbert(getFilteredWaveData(fftFilterParams, iChan));
// }
return analyticWaveform[iChan];
}
// if (analyticWaveform[iChan] == null) {
analyticWaveform[iChan] = hilbert.
getHilbert(getFilteredWaveData(fftFilterParams, iChan));
// }
return analyticWaveform[iChan];
}
/**
@ -478,9 +509,11 @@ public class RawDataTransforms {
* @param channelIndex channel index
* @return filtered waveform data
*/
public synchronized double[] getFilteredWaveData(FFTFilterParams filterParams, int channelIndex) {
filteredWaveData = getFilteredWaveData(filterParams);
return filteredWaveData[channelIndex];
public double[] getFilteredWaveData(FFTFilterParams filterParams, int channelIndex) {
synchronized (synchObject) {
filteredWaveData = getFilteredWaveData(filterParams);
return filteredWaveData[channelIndex];
}
}
/**
@ -489,12 +522,14 @@ public class RawDataTransforms {
* @param filterParams filter parameters
* @return array of filtered data
*/
public synchronized double[][] getFilteredWaveData(FFTFilterParams filterParams) {
//System.out.println("Make filterred wave data!: " + (filterParams != oldFFTFilterParams));
if (filteredWaveData == null || filterParams != oldFFTFilterParams) {
filteredWaveData = makeFilteredWaveData(filterParams);
public double[][] getFilteredWaveData(FFTFilterParams filterParams) {
synchronized (synchObject) {
//System.out.println("Make filterred wave data!: " + (filterParams != oldFFTFilterParams));
if (filteredWaveData == null || filterParams != oldFFTFilterParams) {
filteredWaveData = makeFilteredWaveData(filterParams);
}
return filteredWaveData;
}
return filteredWaveData;
}
private double[][] makeFilteredWaveData(FFTFilterParams filterParams) {
@ -574,7 +609,7 @@ public class RawDataTransforms {
public double[] getWaveData(int channel) {
return this.rawData.getWaveData()[channel];
}
/**
* Get the wave data for the given channel in int16 format.
* @param channel channel index

View File

@ -62,19 +62,38 @@ public abstract class DataSelectorCreator implements PamSettings {
}
/**
* Get a data selector of a given name.
* Get a data selector of a given name including all possible options for super detections and annotations.
* @param selectorName
* @param allowScores
* @return
* @return data selector for given name.
*/
public synchronized DataSelector getDataSelector(String selectorName, boolean allowScores, String selectorType) {
return getDataSelector(selectorName, allowScores, selectorType, true, true);
}
/**
*
* Get a data selector of a given name with optional inclusion of options for annotations and super detections
* @param selectorName data selector name
* @param allowScores allow scores
* @param selectorType
* @param includeAnnotations include options from any annotators of this data stream
* @param includeSuperDetections include any possible super detection data selectors.
* @return data selector for given name with appropriate options.
*/
public synchronized DataSelector getDataSelector(String selectorName, boolean allowScores, String selectorType,
boolean includeAnnotations, boolean includeSuperDetections) {
DataSelector ds = findDataSelector(selectorName);
if (ds == null) {
ds = createDataSelector(selectorName, allowScores, selectorType);
ds = addAnnotationOptions(ds, selectorName, allowScores, selectorType);
if (includeAnnotations) {
ds = addAnnotationOptions(ds, selectorName, allowScores, selectorType);
}
ds = addSuperDetectionOptions(ds, selectorName, allowScores, selectorType);
if (includeSuperDetections) {
ds = addSuperDetectionOptions(ds, selectorName, allowScores, selectorType);
}
// and get it's params from the centralised list.
DataSelectParams params = dataSelectorSettings.getParams(selectorName);