package org.signalml.plugin.newstager.logic.helper;
public class NewStagerRangeGabor {
private static int DFBOUND = 3;
private static interface Predicate {
public boolean keepLooping(double v);
}
private static interface Step {
public double newValue(double v);
}
public static double HRangeGabor(int signalSize, double signalSampling,
double width, double frequency, double position, double amplitude,
double phase) {
if (width == signalSize) {
return amplitude;
} else if (width == 0) {
return 0.0d;
} else if (frequency == 0.0d) {
return 0.5d * amplitude;
} else {
return DoCompute(signalSize, signalSampling, width, frequency,
position, amplitude, phase);
}
}
protected static double DoCompute(int signalSize, double signalSampling,
double width, double frequency, double position, double amplitude,
double phase) {
final double p = position * signalSampling;
final double tb = 0.0d;
final double te = ((double) signalSize) * signalSampling - 1;
final double w = width * signalSampling;
final double f = Math.PI * frequency / (0.5d * signalSampling);
final double a = 0.5d * amplitude;
double tpp = Math.min(Math.max(Math.round(p), tb), te);
double hb = Coeff(a, tb - p, w, f, phase);
double he = Coeff(a, te - p, w, f, phase);
double hp = Coeff(a, tpp - p, w, f, phase);
double h1[] = ComputeRange(phase, p, w, f, a, tpp, hp, new Predicate() {
@Override
public boolean keepLooping(double v) {
return v > 0.0d;
}
}, new Step() {
@Override
public double newValue(double v) {
return v - 1;
}
});
double h2[] = ComputeRange(phase, p, w, f, a, tpp, hp, new Predicate() {
@Override
public boolean keepLooping(double v) {
return v < te;
}
}, new Step() {
@Override
public double newValue(double v) {
return v + 1;
}
});
return (Math.max(Math.max(hb, he), Math.max(h1[1], h2[1])) -
Math.min(Math.min(hb, he), Math.min(h1[0], h2[0])));
}
private static double[] ComputeRange(double phase, double p, double w,
double f, double a, double tp, double hn, Predicate loopCondition,
Step updater) {
double ho;
double hmin = hn;
double hmax = hn;
int signOld, sign = 0;
int dfps = 0;
while (loopCondition.keepLooping(tp) && dfps < DFBOUND) {
tp = updater.newValue(tp);
ho = hn;
hn = Coeff(a, tp - p, w, f, phase);
signOld = sign;
sign = (int) Math.signum(hn - ho);
if (sign != signOld) {
++dfps;
}
hmin = Math.min(hmin, hn);
hmax = Math.max(hmax, hn);
}
return new double[] { hmin, hmax };
}
private static double Coeff(double amplitude, double arg, double w,
double f, double phase) {
double v = arg / w;
return amplitude * Math.exp(-Math.PI * v * v)
* Math.cos(f * arg + phase);
}
}