public void fire() throws IllegalActionException {
super.fire();
startIndex.update();
endIndex.update();
if (input.hasToken(0)) {
ArrayToken inputArray = (ArrayToken)input.get(0);
Type inputElementType = inputArray.getElementType();
int inputSize = inputArray.length();
if (inputSize == 0) {
peakValues.send(0, inputArray);
peakIndices.send(0, inputArray);
return;
}
int start = ((IntToken)startIndex.getToken()).intValue();
int end = ((IntToken)endIndex.getToken()).intValue();
int maxPeaks = ((IntToken)maximumNumberOfPeaks.getToken()).intValue();
if (end >= inputSize) {
end = inputSize - 1;
}
if (start >= inputSize) {
start = inputSize - 1;
}
if (end < 0) {
end = 0;
}
if (start < 0) {
start = 0;
}
int increment = 1;
if (end < start) {
increment = -1;
}
boolean searchValley = false;
boolean searchPeak = true;
int localMaxIndex = start;
double localMax = ((DoubleToken)inputArray.getElement(start)).doubleValue();
double localMin = localMax;
double dipValue = ((DoubleToken)dip.getToken()).doubleValue();
double squelchValue = ((DoubleToken)squelch.getToken()).doubleValue();
double dipThreshold = dipValue;
double riseThreshold = dipValue;
String scaleValue = scale.stringValue();
int scaleIndicator = _ABSOLUTE;
if (!scaleValue.equals("absolute")) {
double maxValue = localMax;
for (int i = 0; i <= (inputSize - 1); i = i + increment) {
double indata = ((DoubleToken)inputArray.getElement(i)).doubleValue();
if (indata > maxValue) {
maxValue = indata;
}
}
if (scaleValue.equals("relative amplitude decibels")) {
scaleIndicator = _RELATIVE_DB;
dipThreshold = localMax * Math.pow(10.0, (-dipValue / 20));
riseThreshold = localMin * Math.pow(10.0, (dipValue / 20));
squelchValue = maxValue * Math.pow(10.0, (-squelchValue / 20));
} else if (scaleValue.equals("relative power decibels")) {
scaleIndicator = _RELATIVE_DB_POWER;
dipThreshold = localMax * Math.pow(10.0, (-dipValue / 10));
riseThreshold = localMin * Math.pow(10.0, (dipValue / 10));
squelchValue = maxValue * Math.pow(10.0, (-squelchValue / 10));
} else if (scaleValue.equals("relative linear")) {
scaleIndicator = _RELATIVE_LINEAR;
dipThreshold = localMax - dipValue;
riseThreshold = localMin + dipValue;
squelchValue = maxValue - squelchValue;
}
}
ArrayList resultIndices = new ArrayList();
ArrayList resultPeaks = new ArrayList();
for (int i = start; i <= end; i = i + increment) {
double indata = ((DoubleToken)inputArray.getElement(i)).doubleValue();
if (_debugging) {
_debug("-- Checking input with value " + indata+" at index "+i);
}
if (searchValley) {
if (indata < localMin) {
localMin = indata;
switch (scaleIndicator) {
case _RELATIVE_DB:
riseThreshold = localMin * Math.pow(10.0, (dipValue / 20));
break;
case _RELATIVE_DB_POWER:
riseThreshold = localMin * Math.pow(10.0, (dipValue / 10));
break;
case _RELATIVE_LINEAR:
riseThreshold = localMin + dipValue;
break;
}
}
if (_debugging) {
_debug("-- Looking for a value above " + riseThreshold);
}
if ((indata > riseThreshold) && (indata > squelchValue)) {
localMax = indata;
switch (scaleIndicator) {
case _RELATIVE_DB:
dipThreshold = localMax * Math.pow(10.0, (-dipValue / 20));
break;
case _RELATIVE_DB_POWER:
dipThreshold = localMax * Math.pow(10.0, (-dipValue / 10));
break;
case _RELATIVE_LINEAR:
dipThreshold = localMax - dipValue;
break;
}
localMaxIndex = i;
searchValley = false;
searchPeak = true;
}
} else if (searchPeak) {
if ((indata > localMax) && (indata > squelchValue)) {
localMax = indata;
switch (scaleIndicator) {
case _RELATIVE_DB:
dipThreshold = localMax * Math.pow(10.0, (-dipValue / 20));
break;
case _RELATIVE_DB_POWER:
dipThreshold = localMax * Math.pow(10.0, (-dipValue / 10));
break;
case _RELATIVE_LINEAR:
dipThreshold = localMax - dipValue;
break;
}
localMaxIndex = i;
}
if (_debugging) {
_debug("-- Looking for a value below " + dipThreshold);
}
if ((indata < dipThreshold) && (localMax > squelchValue)) {
if (_debugging) {
_debug("** Found a peak with value " + localMax+" at index "+localMaxIndex);
}
resultIndices.add(new IntToken(localMaxIndex));
resultPeaks.add(new DoubleToken(localMax));
if (resultPeaks.size() > maxPeaks) {
break;
}
localMin = indata;
switch (scaleIndicator) {
case _RELATIVE_DB:
riseThreshold = localMin * Math.pow(10.0, (dipValue / 20));
break;
case _RELATIVE_DB_POWER:
riseThreshold = localMin * Math.pow(10.0, (dipValue / 10));
break;
case _RELATIVE_LINEAR:
riseThreshold = localMin + dipValue;
break;
}
searchValley = true;
searchPeak = false;
}
}
}
if (resultPeaks.isEmpty()) {
resultPeaks.add(inputArray.getElement(start));
resultIndices.add(startIndex.getToken());
}
Token[] resultPeaksArray = (Token[])resultPeaks.toArray(new Token[resultPeaks.size()]);
Token[] resultIndicesArray = (Token[])resultIndices.toArray(new Token[resultIndices.size()]);
peakValues.send(0, new ArrayToken(inputElementType, resultPeaksArray));
peakIndices.send(0, new ArrayToken(BaseType.INT, resultIndicesArray));
}
}