SDDSlib
Loading...
Searching...
No Matches
smooth.c
Go to the documentation of this file.
1/**
2 * @file smooth.c
3 * @brief Functions for smoothing data and removing spikes from data arrays.
4 *
5 * This file provides two main functions:
6 * - smoothData(): Smooths a data set using a simple moving average over a defined number of points and passes.
7 * - despikeData(): Attempts to remove spike values from a data set by comparing each point to its neighbors and replacing it if it exceeds a defined threshold.
8 *
9 * @copyright
10 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
11 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
12 *
13 * @license
14 * This file is distributed under the terms of the Software License Agreement
15 * found in the file LICENSE included with this distribution.
16 *
17 * @author M. Borland, R. Soliday, H. Shang
18 */
19
20#include "mdb.h"
21
22/**
23 * @brief Smooth a data array using a moving average.
24 *
25 * This function applies a moving average smoothing operation to an array of data
26 * points a specified number of times. It uses a window defined by smoothPoints,
27 * averaging over this number of points and performing the operation for smoothPasses
28 * iterations.
29 *
30 * @param data Pointer to the array of data to be smoothed.
31 * @param rows The number of data points.
32 * @param smoothPoints The number of points to include in the smoothing window.
33 * @param smoothPasses The number of smoothing passes to perform.
34 */
35void smoothData(double *data, long rows, long smoothPoints, long smoothPasses) {
36 long lower, upper, row, pass, smoothPoints2, terms;
37 double sum;
38 static double *smoothedData = NULL;
39
40 smoothedData = trealloc(smoothedData, rows * sizeof(*smoothedData));
41
42 smoothPoints2 = smoothPoints / 2;
43
44 for (pass = 0; pass < smoothPasses; pass++) {
45 for (row = sum = 0; row < smoothPoints2; row++)
46 sum += data[row];
47
48 terms = row;
49 lower = -smoothPoints2;
50 upper = smoothPoints2;
51 for (row = 0; row < rows; row++, lower++, upper++) {
52 if (upper < rows) {
53 sum += data[upper];
54 terms += 1;
55 }
56 smoothedData[row] = sum / terms;
57 if (lower >= 0) {
58 sum -= data[lower];
59 terms -= 1;
60 }
61 }
62
63 for (row = 0; row < rows; row++)
64 data[row] = smoothedData[row];
65 }
66}
67
68/**
69 * @brief Remove spikes from a data array by comparing each point to its neighbors.
70 *
71 * This function identifies and replaces "spikes" in a data array. A spike is defined
72 * as a value that differs significantly from its neighboring values. The function
73 * compares each point to its neighbors over multiple passes and replaces values
74 * exceeding a given threshold with an average of their neighbors. The process can
75 * be halted if too many spikes are found (based on countLimit).
76 *
77 * @param data Pointer to the data array.
78 * @param rows The number of data points.
79 * @param neighbors The number of neighboring points to consider around each point.
80 * @param passes The maximum number of passes to attempt when removing spikes.
81 * @param averageOf The number of points to average when replacing a spiked value.
82 * @param threshold The threshold for determining if a value is a spike.
83 * @param countLimit The maximum number of spikes allowed before the process stops.
84 * @return The number of spikes removed on the final pass.
85 */
86long despikeData(double *data, long rows, long neighbors, long passes, long averageOf,
87 double threshold, long countLimit) {
88 long i0, i1, i2, i, j, i1a, i2a;
89 int64_t imin, imax;
90 double *deltaSum, sum, *tempdata;
91 long despikeCount;
92
93 neighbors = 2 * ((neighbors + 1) / 2);
94 if (!(tempdata = (double *)malloc(sizeof(*tempdata) * rows)) ||
95 !(deltaSum = (double *)malloc(sizeof(*deltaSum) * (neighbors + 1))))
96 bomb("despikeData: memory allocation failure", NULL);
97 memcpy(tempdata, data, sizeof(*data) * rows);
98 despikeCount = 0;
99 while (passes-- > 0) {
100 despikeCount = 0;
101 for (i0 = 0; i0 < rows; i0 += neighbors / 2) {
102 i1 = i0 - neighbors / 2;
103 i2 = i0 + neighbors / 2;
104 if (i1 < 0)
105 i1 = 0;
106 if (i2 >= rows)
107 i2 = rows - 1;
108 if (i2 - i1 == 0)
109 continue;
110 for (i = i1; i <= i2; i++) {
111 deltaSum[i - i1] = 0;
112 for (j = i1; j <= i2; j++)
113 deltaSum[i - i1] += fabs(tempdata[i] - tempdata[j]);
114 }
115 if (index_min_max(&imin, &imax, deltaSum, i2 - i1 + 1)) {
116 if ((imax += i1) < 0 || imax > rows) {
117 fprintf(stderr, "Error: index out of range in despikeData (sddssmooth)\n");
118 fprintf(stderr, " imax = %" PRId64 ", rows=%ld, i1=%ld, i2=%ld, neighbors=%ld\n",
119 imax - 1, rows, i1, i2, neighbors);
120 exit(1);
121 }
122 if (threshold == 0 || threshold * neighbors < deltaSum[imax - i1]) {
123 if ((i1a = imax - averageOf / 2) < 0)
124 i1a = 0;
125 if ((i2a = imax + averageOf / 2) >= rows)
126 i2a = rows - 1;
127 for (sum = 0, i = i1a; i <= i2a; i++) {
128 if (i != imax)
129 sum += tempdata[i];
130 }
131 despikeCount++;
132 tempdata[imax] = sum / (i2a - i1a);
133 }
134 }
135 }
136 if (!despikeCount || (countLimit > 0 && despikeCount > countLimit))
137 break;
138 }
139 if (countLimit <= 0 || despikeCount < countLimit)
140 for (i = 0; i < rows; i++)
141 data[i] = tempdata[i];
142 else
143 despikeCount = 0;
144 free(tempdata);
145 free(deltaSum);
146 return despikeCount;
147}
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
Definition array.c:181
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
int index_min_max(int64_t *imin, int64_t *imax, double *list, int64_t n)
Finds the indices of the minimum and maximum values in a list of doubles.
Definition findMinMax.c:116
void smoothData(double *data, long rows, long smoothPoints, long smoothPasses)
Smooth a data array using a moving average.
Definition smooth.c:35
long despikeData(double *data, long rows, long neighbors, long passes, long averageOf, double threshold, long countLimit)
Remove spikes from a data array by comparing each point to its neighbors.
Definition smooth.c:86