12 #include "TVirtualFFT.h" 24 using PeakTuple = std::tuple<size_t, size_t, size_t>;
27 void triangleSmooth(
const std::vector<float>&, std::vector<float>&,
size_t = 0)
const override;
30 size_t = 0)
const override;
31 void medianSmooth(
const std::vector<float>&, std::vector<float>&,
size_t = 3)
const override;
32 void medianSmooth(
const std::vector<double>&, std::vector<double>&,
size_t = 3)
const override;
43 void firstDerivative(
const std::vector<float>&, std::vector<float>&)
const override;
44 void firstDerivative(
const std::vector<double>&, std::vector<double>&)
const override;
49 size_t)
const override;
54 size_t)
const override;
55 void getFFTPower(
const std::vector<float>& inputVec,
56 std::vector<float>& outputPowerVec)
const override;
57 void getFFTPower(
const std::vector<double>& inputVec,
58 std::vector<double>& outputPowerVec)
const override;
102 template <
typename T>
103 void triangleSmooth(
const std::vector<T>&, std::vector<T>&,
size_t = 0)
const;
104 template <
typename T>
105 void medianSmooth(
const std::vector<T>&, std::vector<T>&,
size_t = 3)
const;
106 template <
typename T>
108 template <
typename T>
110 template <
typename T>
117 template <
typename T>
126 template <
typename T>
151 std::vector<double>& smoothVec,
152 size_t lowestBin)
const 154 triangleSmooth<double>(inputVec, smoothVec, lowestBin);
160 std::vector<float>& smoothVec,
161 size_t lowestBin)
const 163 triangleSmooth<float>(inputVec, smoothVec, lowestBin);
168 template <
typename T>
170 std::vector<T>& smoothVec,
171 size_t lowestBin)
const 173 if (inputVec.size() != smoothVec.size()) smoothVec.resize(inputVec.size());
176 if (inputVec.size() > 4) {
177 std::copy(inputVec.begin(), inputVec.begin() + 2 + lowestBin, smoothVec.begin());
178 std::copy(inputVec.end() - 2, inputVec.end(), smoothVec.end() - 2);
184 while (curInItr++ != stopInItr) {
186 T newVal = (*(curInItr - 2) + 2. * *(curInItr - 1) + 3. * *curInItr + 2. * *(curInItr + 1) +
194 std::copy(inputVec.begin(), inputVec.end(), smoothVec.begin());
200 std::vector<float>& smoothVec,
203 medianSmooth<float>(inputVec, smoothVec, nBins);
209 std::vector<double>& smoothVec,
212 medianSmooth<double>(inputVec, smoothVec, nBins);
217 template <
typename T>
219 std::vector<T>& smoothVec,
223 if (nBins % 2 == 0) nBins++;
226 if (inputVec.size() != smoothVec.size()) smoothVec.resize(inputVec.size());
229 typename std::vector<T> medianVec(nBins);
233 std::advance(stopItr, inputVec.size() - nBins);
235 size_t medianBin = nBins / 2;
236 size_t smoothBin = medianBin;
239 std::copy(startItr, startItr + medianBin, smoothVec.begin());
241 while (std::distance(startItr, stopItr) > 0) {
242 std::copy(startItr, startItr + nBins, medianVec.begin());
243 std::sort(medianVec.begin(), medianVec.end());
245 T medianVal = medianVec[medianBin];
247 smoothVec[smoothBin++] = medianVal;
253 std::copy(startItr + medianBin, inputVec.end(), smoothVec.begin() + smoothBin);
264 getTruncatedMeanRMS<double>(waveform,
mean, rmsFull, rmsTrunc, nTrunc);
273 getTruncatedMeanRMS<float>(waveform,
mean, rmsFull, rmsTrunc, nTrunc);
276 template <
typename T>
287 std::map<int, int> frequencyMap;
291 for (
const auto& val : waveform) {
292 int intVal = std::round(4. * val);
294 frequencyMap[intVal]++;
296 if (frequencyMap.at(intVal) > mpCount) {
297 mpCount = frequencyMap.at(intVal);
305 int binRange = std::min(16,
int(frequencyMap.size() / 2 + 1));
307 for (
int idx = -binRange; idx <= binRange; idx++) {
310 if (neighborItr != frequencyMap.end() && 5 * neighborItr->second > mpCount) {
311 meanSum += neighborItr->first * neighborItr->second;
312 meanCnt += neighborItr->second;
316 mean = 0.25 * T(meanSum) / T(meanCnt);
319 typename std::vector<T> locWaveform = waveform;
321 std::transform(locWaveform.begin(),
324 std::bind(std::minus<T>(), std::placeholders::_1, mean));
327 std::sort(locWaveform.begin(), locWaveform.end(), [](
const auto&
left,
const auto&
right) {
328 return std::fabs(
left) < std::fabs(
right);
332 rmsFull = std::inner_product(locWaveform.begin(), locWaveform.end(), locWaveform.begin(), 0.);
333 rmsFull = std::sqrt(std::max(T(0.), rmsFull / T(locWaveform.size())));
336 rmsTrunc = std::inner_product(
337 locWaveform.begin(), locWaveform.begin() + meanCnt, locWaveform.begin(), 0.);
338 rmsTrunc = std::sqrt(std::max(T(0.), rmsTrunc / T(meanCnt)));
345 std::vector<double>& derivVec)
const 347 firstDerivative<double>(inputVec, derivVec);
353 std::vector<float>& derivVec)
const 355 firstDerivative<float>(inputVec, derivVec);
360 template <
typename T>
362 std::vector<T>& derivVec)
const 364 derivVec.resize(inputVec.size(), 0.);
366 for (
size_t idx = 1; idx < derivVec.size() - 1; idx++)
367 derivVec.at(idx) = 0.5 * (inputVec.at(idx + 1) - inputVec.at(idx - 1));
376 size_t firstTick)
const 378 findPeaks<double>(startItr, stopItr, peakTupleVec, threshold, firstTick);
387 size_t firstTick)
const 389 findPeaks<float>(startItr, stopItr, peakTupleVec, threshold, firstTick);
394 template <
typename T>
399 size_t firstTick)
const 402 if (std::distance(startItr, stopItr) > 4) {
405 std::max_element(startItr, stopItr, [](
float left,
float right) {
406 return std::fabs(left) < std::fabs(right);
410 if (std::fabs(*firstItr) > threshold) {
422 while (tempItr != stopItr) {
423 if (*++tempItr < -threshold) {
424 if (*tempItr < *secondItr) secondItr = tempItr;
426 else if (secondItr != firstItr)
434 while (tempItr != startItr) {
435 if (*--tempItr > threshold) {
436 if (*tempItr > *secondItr) secondItr = tempItr;
438 else if (secondItr != firstItr)
442 std::swap(firstItr, secondItr);
446 if (firstItr != secondItr) {
449 std::distance(startItr, firstItr) + std::distance(firstItr, secondItr) / 2;
452 while (firstItr != startItr)
453 if (*--firstItr < 0.)
break;
454 while (secondItr != stopItr)
455 if (*++secondItr > 0.)
break;
457 size_t firstBin = std::distance(startItr, firstItr);
458 size_t lastBin = std::distance(startItr, secondItr);
461 findPeaks(startItr, firstItr, peakTupleVec, threshold, firstTick);
464 peakTupleVec.push_back(
465 PeakTuple(firstBin + firstTick, peakBin + firstTick, lastBin + firstTick));
472 firstTick + std::distance(startItr, secondItr));
481 std::vector<float>& outputPowerVec)
const 483 std::vector<double> inputDoubleVec(inputVec.size());
484 std::vector<double> outputDoubleVec(inputVec.size() / 2);
486 std::copy(inputVec.begin(), inputVec.end(), inputDoubleVec.begin());
490 if (outputDoubleVec.size() != outputPowerVec.size())
491 outputPowerVec.resize(outputDoubleVec.size());
493 std::copy(outputDoubleVec.begin(), outputDoubleVec.end(), outputPowerVec.begin());
499 std::vector<double>& outputPowerVec)
const 502 int fftDataSize = inputVec.size();
504 TVirtualFFT* fftr2c = TVirtualFFT::FFT(1, &fftDataSize,
"R2C");
506 fftr2c->SetPoints(inputVec.data());
510 size_t halfFFTDataSize(fftDataSize / 2 + 1);
512 std::vector<double> realVals(halfFFTDataSize);
513 std::vector<double> imaginaryVals(halfFFTDataSize);
515 fftr2c->GetPointsComplex(realVals.data(), imaginaryVals.data());
517 if (outputPowerVec.size() != halfFFTDataSize) outputPowerVec.resize(halfFFTDataSize, 0.);
519 std::transform(realVals.begin(),
520 realVals.begin() + halfFFTDataSize,
521 imaginaryVals.begin(),
522 outputPowerVec.begin(),
523 [](
const double& real,
const double& imaginary) {
524 return std::sqrt(real * real + imaginary * imaginary);
531 int structuringElement,
538 getErosionDilationAverageDifference<short>(waveform,
550 int structuringElement,
557 getErosionDilationAverageDifference<float>(waveform,
569 int structuringElement,
576 getErosionDilationAverageDifference<double>(waveform,
587 template <
typename T>
589 int structuringElement,
597 int halfWindowSize(structuringElement / 2);
602 std::minmax_element(inputWaveform.begin(), inputWaveform.begin() + halfWindowSize);
608 erosionVec.resize(inputWaveform.size());
609 dilationVec.resize(inputWaveform.size());
610 averageVec.resize(inputWaveform.size());
611 differenceVec.resize(inputWaveform.size());
620 inputItr != inputWaveform.end();
627 if (std::distance(inputItr, inputWaveform.end()) > halfWindowSize) {
628 if (std::distance(minElementItr, inputItr) >= halfWindowSize)
630 std::min_element(inputItr - halfWindowSize + 1, inputItr + halfWindowSize + 1);
631 else if (*(inputItr + halfWindowSize) < *minElementItr)
632 minElementItr = inputItr + halfWindowSize;
634 if (std::distance(maxElementItr, inputItr) >= halfWindowSize)
636 std::max_element(inputItr - halfWindowSize + 1, inputItr + halfWindowSize + 1);
637 else if (*(inputItr + halfWindowSize) > *maxElementItr)
638 maxElementItr = inputItr + halfWindowSize;
642 *minItr++ = *minElementItr;
643 *maxItr++ = *maxElementItr;
644 *aveItr++ = 0.5 * (*maxElementItr + *minElementItr);
645 *difItr++ = *maxElementItr - *minElementItr;
647 if (!histogramMap.empty()) {
648 int curBin = std::distance(inputWaveform.begin(), inputItr);
650 histogramMap.at(
WAVEFORM)->Fill(curBin, *inputItr);
651 histogramMap.at(
EROSION)->Fill(curBin, *minElementItr);
652 histogramMap.at(
DILATION)->Fill(curBin, *maxElementItr);
653 histogramMap.at(
AVERAGE)->Fill(curBin, 0.5 * (*maxElementItr + *minElementItr));
654 histogramMap.at(
DIFFERENCE)->Fill(curBin, *maxElementItr - *minElementItr);
663 int structuringElement,
668 getOpeningAndClosing<short>(
669 erosionVec, dilationVec, structuringElement, histogramMap, openingVec, closingVec);
676 int structuringElement,
681 getOpeningAndClosing<float>(
682 erosionVec, dilationVec, structuringElement, histogramMap, openingVec, closingVec);
689 int structuringElement,
694 getOpeningAndClosing<double>(
695 erosionVec, dilationVec, structuringElement, histogramMap, openingVec, closingVec);
700 template <
typename T>
703 int structuringElement,
709 int halfWindowSize(structuringElement / 2);
713 std::max_element(erosionVec.begin(), erosionVec.begin() + halfWindowSize);
716 openingVec.resize(erosionVec.size());
722 inputItr != erosionVec.end();
729 if (std::distance(inputItr, erosionVec.end()) > halfWindowSize) {
730 if (std::distance(maxElementItr, inputItr) >= halfWindowSize)
732 std::max_element(inputItr - halfWindowSize + 1, inputItr + halfWindowSize + 1);
733 else if (*(inputItr + halfWindowSize) > *maxElementItr)
734 maxElementItr = inputItr + halfWindowSize;
738 *maxItr++ = *maxElementItr;
740 if (!histogramMap.empty()) {
741 int curBin = std::distance(erosionVec.begin(), inputItr);
743 histogramMap.at(
OPENING)->Fill(curBin, *maxElementItr);
749 std::min_element(dilationVec.begin(), dilationVec.begin() + halfWindowSize);
752 closingVec.resize(dilationVec.size());
758 inputItr != dilationVec.end();
765 if (std::distance(inputItr, dilationVec.end()) > halfWindowSize) {
766 if (std::distance(minElementItr, inputItr) >= halfWindowSize)
768 std::min_element(inputItr - halfWindowSize + 1, inputItr + halfWindowSize + 1);
769 else if (*(inputItr + halfWindowSize) < *minElementItr)
770 minElementItr = inputItr + halfWindowSize;
774 *minItr++ = *minElementItr;
776 if (!histogramMap.empty()) {
777 int curBin = std::distance(dilationVec.begin(), inputItr);
779 histogramMap.at(
CLOSING)->Fill(curBin, *minElementItr);
780 histogramMap.at(
DOPENCLOSING)->Fill(curBin, *minElementItr - openingVec.at(curBin));
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
double mean(const std::vector< short > &wf, size_t start, size_t nsample)