SDDSlib
Loading...
Searching...
No Matches
sddssmooth.c File Reference

SDDS-format smoothing program. More...

#include "mdb.h"
#include "SDDS.h"
#include "scan.h"
#include <ctype.h>

Go to the source code of this file.

Macros

#define FL_NEWCOLUMNS   0x0001UL
 
#define FL_DIFCOLUMNS   0x0002UL
 
#define DESPIKE_AVERAGEOF   0x0001U
 

Enumerations

enum  option_type {
  CLO_POINTS , CLO_PASSES , CLO_COLUMNS , CLO_PIPE ,
  CLO_NEWCOLUMNS , CLO_DIFFERENCECOLUMNS , CLO_DESPIKE , CLO_NOWARNINGS ,
  CLO_SAVITZKYGOLAY , CLO_MAJOR_ORDER , CLO_MEDIAN_FILTER , CLO_GAUSSIAN ,
  N_OPTIONS
}
 

Functions

long resolveColumnNames (SDDS_DATASET *SDDSin, char ***column, int32_t *columns)
 
void gaussianConvolution (double *data, int64_t rows, double sigma)
 
int main (int argc, char **argv)
 

Variables

char * option [N_OPTIONS]
 
static char * USAGE
 

Detailed Description

SDDS-format smoothing program.

This program smooths columns in SDDS-format data files using various smoothing techniques such as nearest-neighbor averaging, Gaussian convolution, median filtering, and Savitzky-Golay filtering. It can also perform despiking of data.

License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
M. Borland, C. Saunders, R. Soliday, H. Shang

Definition in file sddssmooth.c.

Macro Definition Documentation

◆ DESPIKE_AVERAGEOF

#define DESPIKE_AVERAGEOF   0x0001U

Definition at line 97 of file sddssmooth.c.

◆ FL_DIFCOLUMNS

#define FL_DIFCOLUMNS   0x0002UL

Definition at line 95 of file sddssmooth.c.

◆ FL_NEWCOLUMNS

#define FL_NEWCOLUMNS   0x0001UL

Definition at line 94 of file sddssmooth.c.

Enumeration Type Documentation

◆ option_type

enum option_type

Definition at line 27 of file sddssmooth.c.

27 {
28 CLO_POINTS,
29 CLO_PASSES,
30 CLO_COLUMNS,
31 CLO_PIPE,
32 CLO_NEWCOLUMNS,
33 CLO_DIFFERENCECOLUMNS,
34 CLO_DESPIKE,
35 CLO_NOWARNINGS,
36 CLO_SAVITZKYGOLAY,
37 CLO_MAJOR_ORDER,
38 CLO_MEDIAN_FILTER,
39 CLO_GAUSSIAN,
40 N_OPTIONS
41};

Function Documentation

◆ gaussianConvolution()

void gaussianConvolution ( double * data,
int64_t rows,
double sigma )

Definition at line 387 of file sddssmooth.c.

387 {
388 double *data1, *expFactor;
389 int64_t i, j, j1, j2, nsRows, nsPerSide;
390
391 nsPerSide = 6 * sigma;
392 nsRows = 2 * nsPerSide + 1;
393 expFactor = tmalloc(sizeof(*expFactor) * nsRows);
394 for (j = -nsPerSide; j <= nsPerSide; j++)
395 expFactor[j + nsPerSide] = exp(-sqr(j / sigma) / 2.0) / (sigma * sqrt(2 * PI));
396
397 data1 = calloc(rows, sizeof(*data1));
398 for (i = 0; i < rows; i++) {
399 j1 = i - nsPerSide;
400 j2 = i + nsPerSide;
401 if (j1 < 0)
402 j1 = 0;
403 if (j2 >= rows)
404 j2 = rows;
405 for (j = j1; j <= j2; j++)
406 data1[i] += data[j] * expFactor[j - i + nsPerSide];
407 }
408 memcpy(data, data1, sizeof(*data) * rows);
409 free(data1);
410}
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59

◆ main()

int main ( int argc,
char ** argv )

Definition at line 99 of file sddssmooth.c.

99 {
100 int iArg;
101 char **inputColumn, **outputColumn, **difColumn;
102 int32_t columns;
103 long despike, median, smooth;
104 int32_t despikeNeighbors, despikePasses, despikeAverageOf;
105 char *input, *output;
106 long i, readCode;
107 int64_t j, rows;
108 int32_t smoothPoints, smoothPasses;
109 long noWarnings, medianWindowSize = 3;
110 unsigned long pipeFlags, flags, despikeFlags, majorOrderFlag, dummyFlags;
111 SCANNED_ARG *scanned;
112 SDDS_DATASET SDDSin, SDDSout;
113 double *data, despikeThreshold;
114 int32_t SGLeft, SGRight, SGOrder, SGDerivOrder;
115 short columnMajorOrder = -1;
116 double gaussianSigma = 0;
117
119 argc = scanargs(&scanned, argc, argv);
120 if (argc < 3 || argc > (3 + N_OPTIONS))
121 bomb(NULL, USAGE);
122
123 output = input = NULL;
124 inputColumn = outputColumn = NULL;
125 columns = 0;
126 pipeFlags = 0;
127 smoothPoints = 3;
128 smoothPasses = 1;
129 flags = 0;
130 despike = 0;
131 median = 0;
132 smooth = 0;
133 noWarnings = 0;
134 SGOrder = -1;
135 SGDerivOrder = 0;
136
137 for (iArg = 1; iArg < argc; iArg++) {
138 if (scanned[iArg].arg_type == OPTION) {
139 /* process options here */
140 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
141 case CLO_PASSES:
142 smooth = 1;
143 if (scanned[iArg].n_items != 2 ||
144 sscanf(scanned[iArg].list[1], "%" SCNd32, &smoothPasses) != 1 ||
145 smoothPasses < 0)
146 SDDS_Bomb("invalid -passes syntax/value");
147 break;
148 case CLO_GAUSSIAN:
149 gaussianSigma = 0;
150 if (scanned[iArg].n_items != 2 ||
151 sscanf(scanned[iArg].list[1], "%lf", &gaussianSigma) != 1 ||
152 gaussianSigma <= 0)
153 SDDS_Bomb("invalid -gaussian syntax/value");
154 break;
155 case CLO_POINTS:
156 if (scanned[iArg].n_items != 2 ||
157 sscanf(scanned[iArg].list[1], "%" SCNd32, &smoothPoints) != 1 ||
158 smoothPoints < 1 ||
159 smoothPoints % 2 == 0)
160 SDDS_Bomb("invalid -points syntax/value");
161 break;
162 case CLO_COLUMNS:
163 if (scanned[iArg].n_items < 2)
164 SDDS_Bomb("invalid -columns syntax");
165 inputColumn = tmalloc(sizeof(*inputColumn) * (columns = scanned[iArg].n_items - 1));
166 for (i = 0; i < columns; i++)
167 inputColumn[i] = scanned[iArg].list[i + 1];
168 break;
169 case CLO_PIPE:
170 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
171 SDDS_Bomb("invalid -pipe syntax");
172 break;
173 case CLO_NEWCOLUMNS:
174 flags |= FL_NEWCOLUMNS;
175 break;
176 case CLO_DIFFERENCECOLUMNS:
177 flags |= FL_DIFCOLUMNS;
178 break;
179 case CLO_DESPIKE:
180 scanned[iArg].n_items--;
181 despikeNeighbors = 4;
182 despikePasses = 1;
183 despikeThreshold = 0;
184 despikeAverageOf = 2;
185 if (scanned[iArg].n_items > 0 &&
186 (!scanItemList(&despikeFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
187 "neighbors", SDDS_LONG, &despikeNeighbors, 1, 0,
188 "passes", SDDS_LONG, &despikePasses, 1, 0,
189 "averageof", SDDS_LONG, &despikeAverageOf, 1, DESPIKE_AVERAGEOF,
190 "threshold", SDDS_DOUBLE, &despikeThreshold, 1, 0, NULL) ||
191 despikeNeighbors < 2 || despikePasses < 1 || despikeAverageOf < 2 || despikeThreshold < 0)) {
192 fprintf(stderr, "sddssmooth: Invalid -despike syntax/values: neighbors=%" PRId32 ", passes=%" PRId32 ", averageOf=%" PRId32 ", threshold=%e\n", despikeNeighbors, despikePasses, despikeAverageOf, despikeThreshold);
193 exit(EXIT_FAILURE);
194 }
195 if (!(despikeFlags & DESPIKE_AVERAGEOF))
196 despikeAverageOf = despikeNeighbors;
197 if (despikeAverageOf > despikeNeighbors)
198 SDDS_Bomb("invalid -despike syntax/values: averageOf>neighbors");
199 despike = 1;
200 break;
201 case CLO_MEDIAN_FILTER:
202 scanned[iArg].n_items--;
203 medianWindowSize = 0;
204 if (scanned[iArg].n_items > 0 &&
205 (!scanItemList(&dummyFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
206 "windowSize", SDDS_LONG, &medianWindowSize, 1, 0, NULL) ||
207 medianWindowSize <= 0)) {
208 fprintf(stderr, "sddssmooth: Invalid -medianFilter syntax/values: windowSize=%ld\n", medianWindowSize);
209 exit(EXIT_FAILURE);
210 }
211 median = 1;
212 break;
213 case CLO_NOWARNINGS:
214 noWarnings = 1;
215 break;
216 case CLO_SAVITZKYGOLAY:
217 if ((scanned[iArg].n_items != 4 && scanned[iArg].n_items != 5) ||
218 sscanf(scanned[iArg].list[1], "%" SCNd32, &SGLeft) != 1 ||
219 sscanf(scanned[iArg].list[2], "%" SCNd32, &SGRight) != 1 ||
220 sscanf(scanned[iArg].list[3], "%" SCNd32, &SGOrder) != 1 ||
221 (scanned[iArg].n_items == 5 && sscanf(scanned[iArg].list[4], "%" SCNd32, &SGDerivOrder) != 1) ||
222 SGLeft < 0 ||
223 SGRight < 0 ||
224 (SGLeft + SGRight) < SGOrder ||
225 SGOrder < 0 ||
226 SGDerivOrder < 0)
227 SDDS_Bomb("invalid -SavitzkyGolay syntax/values");
228 break;
229 case CLO_MAJOR_ORDER:
230 majorOrderFlag = 0;
231 scanned[iArg].n_items--;
232 if (scanned[iArg].n_items > 0 &&
233 (!scanItemList(&majorOrderFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
234 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
235 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
236 SDDS_Bomb("invalid -majorOrder syntax/values");
237 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
238 columnMajorOrder = 1;
239 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
240 columnMajorOrder = 0;
241 break;
242 default:
243 fprintf(stderr, "error: unknown/ambiguous option: %s\n", scanned[iArg].list[0]);
244 exit(EXIT_FAILURE);
245 break;
246 }
247 } else {
248 if (!input)
249 input = scanned[iArg].list[0];
250 else if (!output)
251 output = scanned[iArg].list[0];
252 else
253 SDDS_Bomb("too many filenames seen");
254 }
255 }
256
257 processFilenames("sddssmooth", &input, &output, pipeFlags, 0, NULL);
258 /*do not change the previous setting; before it does smooth by default before adding median */
259 if (!median)
260 smooth = 1;
261
262 if (!despike && !smoothPasses && !median && !noWarnings)
263 fprintf(stderr, "warning: smoothing parameters won't result in any change in data (sddssmooth)\n");
264
265 if (!columns)
266 SDDS_Bomb("supply the names of columns to smooth with the -columns option");
267
268 if (!SDDS_InitializeInput(&SDDSin, input))
269 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
270
271 if (!resolveColumnNames(&SDDSin, &inputColumn, &columns))
272 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
273 if (!columns)
274 SDDS_Bomb("no columns selected for smoothing");
275
276 if (!SDDS_InitializeCopy(&SDDSout, &SDDSin, output, "w"))
277 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
278
279 outputColumn = tmalloc(sizeof(*outputColumn) * columns);
280
281 if (flags & FL_NEWCOLUMNS) {
282 for (i = 0; i < columns; i++) {
283 if (SGDerivOrder <= 0) {
284 outputColumn[i] = tmalloc(sizeof(**outputColumn) * (strlen(inputColumn[i]) + 1 + strlen("Smoothed")));
285 sprintf(outputColumn[i], "%sSmoothed", inputColumn[i]);
286 } else {
287 outputColumn[i] = tmalloc(sizeof(**outputColumn) * (strlen(inputColumn[i]) + 1 + strlen("SmoothedDeriv")) + 5);
288 sprintf(outputColumn[i], "%sSmoothedDeriv%" PRId32, inputColumn[i], SGDerivOrder);
289 }
290 if (!SDDS_TransferColumnDefinition(&SDDSout, &SDDSin, inputColumn[i], outputColumn[i]))
291 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
292 }
293 } else
294 for (i = 0; i < columns; i++)
295 outputColumn[i] = inputColumn[i];
296
297 difColumn = NULL;
298 if (flags & FL_DIFCOLUMNS) {
299 difColumn = tmalloc(sizeof(*difColumn) * columns);
300 for (i = 0; i < columns; i++) {
301 difColumn[i] = tmalloc(sizeof(**difColumn) * (strlen(inputColumn[i]) + 1 + strlen("Unsmooth")));
302 sprintf(difColumn[i], "%sUnsmooth", inputColumn[i]);
303 if (!SDDS_TransferColumnDefinition(&SDDSout, &SDDSin, inputColumn[i], difColumn[i]))
304 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
305 }
306 }
307
308 if ((SDDS_GetParameterIndex(&SDDSout, "SmoothPoints") < 0 &&
309 SDDS_DefineParameter1(&SDDSout, "SmoothPoints", NULL, NULL, NULL, NULL, SDDS_LONG, &smoothPoints) < 0) ||
310 (SDDS_GetParameterIndex(&SDDSout, "SmoothPasses") < 0 &&
311 SDDS_DefineParameter1(&SDDSout, "SmoothPasses", NULL, NULL, NULL, NULL, SDDS_LONG, &smoothPasses) < 0))
312 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
313 if (columnMajorOrder != -1)
314 SDDSout.layout.data_mode.column_major = columnMajorOrder;
315 else
316 SDDSout.layout.data_mode.column_major = SDDSin.layout.data_mode.column_major;
317
318 if (!SDDS_WriteLayout(&SDDSout))
319 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
320
321 while ((readCode = SDDS_ReadPage(&SDDSin)) > 0) {
322 if (!SDDS_CopyPage(&SDDSout, &SDDSin))
323 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
324 if ((rows = SDDS_CountRowsOfInterest(&SDDSin))) {
325 for (i = 0; i < columns; i++) {
326 if (!(data = SDDS_GetColumnInDoubles(&SDDSin, inputColumn[i])))
327 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
328 if (despike)
329 despikeData(data, rows, despikeNeighbors, despikePasses, despikeAverageOf, despikeThreshold, 0);
330 if (gaussianSigma > 0)
331 gaussianConvolution(data, rows, gaussianSigma);
332 if (median) {
333 double *mData = NULL;
334 mData = malloc(sizeof(*mData) * rows);
335 median_filter(data, mData, rows, medianWindowSize);
336 memcpy(data, mData, sizeof(*mData) * rows);
337 free(mData);
338 }
339 if (SGOrder >= 0) {
340 long pass = 0;
341 for (pass = 0; pass < smoothPasses; pass++)
342 SavitzkyGolaySmooth(data, rows, SGOrder, SGLeft, SGRight, SGDerivOrder);
343 } else if (smooth && smoothPasses)
344 smoothData(data, rows, smoothPoints, smoothPasses);
345
346 if (!SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, data, rows, outputColumn[i]))
347 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
348 if (flags & FL_DIFCOLUMNS) {
349 double *data0;
350 if (!(data0 = SDDS_GetColumnInDoubles(&SDDSin, inputColumn[i])))
351 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
352 for (j = 0; j < rows; j++)
353 data0[j] -= data[j];
354 if (!SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, data0, rows, difColumn[i]))
355 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
356 free(data0);
357 }
358 free(data);
359 }
360 }
361 if (!SDDS_WritePage(&SDDSout))
362 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
363 }
364 if (!SDDS_Terminate(&SDDSin) || !SDDS_Terminate(&SDDSout)) {
365 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
366 exit(EXIT_FAILURE);
367 }
368 return EXIT_SUCCESS;
369}
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
Definition SDDS_copy.c:40
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:578
int32_t SDDS_SetColumnFromDoubles(SDDS_DATASET *SDDS_dataset, int32_t mode, double *data, int64_t rows,...)
Sets the values for a single data column using double-precision floating-point numbers.
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
double * SDDS_GetColumnInDoubles(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of doubles, considering only rows mark...
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_DefineParameter1(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, void *fixed_value)
Defines a data parameter with a fixed numerical value.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_TransferColumnDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers a column definition from a source dataset to a target dataset.
int32_t SDDS_GetParameterIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named parameter in the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
void median_filter(double *x, double *m, long n, long W)
Applies a median filter to an input signal.
long SavitzkyGolaySmooth(double *data, long rows, long order, long nLeft, long nRight, long derivativeOrder)
Applies Savitzky-Golay smoothing or differentiation to a data array.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.
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

◆ resolveColumnNames()

long resolveColumnNames ( SDDS_DATASET * SDDSin,
char *** column,
int32_t * columns )

Definition at line 371 of file sddssmooth.c.

371 {
372 long i;
373
374 SDDS_SetColumnFlags(SDDSin, 0);
375 for (i = 0; i < *columns; i++) {
376 if (!SDDS_SetColumnsOfInterest(SDDSin, SDDS_MATCH_STRING, (*column)[i], SDDS_OR))
377 return 0;
378 }
379 free(*column);
380 if (!(*column = SDDS_GetColumnNames(SDDSin, columns)) || *columns == 0) {
381 SDDS_SetError("no columns found");
382 return 0;
383 }
384 return 1;
385}
int32_t SDDS_SetColumnsOfInterest(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
Sets the acceptance flags for columns based on specified naming criteria.
int32_t SDDS_SetColumnFlags(SDDS_DATASET *SDDS_dataset, int32_t column_flag_value)
Sets the acceptance flags for all columns in the current data table of a data set.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:379
char ** SDDS_GetColumnNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all columns in the SDDS dataset.

Variable Documentation

◆ option

char* option[N_OPTIONS]
Initial value:
= {
"points",
"passes",
"columns",
"pipe",
"newcolumns",
"differencecolumns",
"despike",
"nowarnings",
"savitzkygolay",
"majorOrder",
"medianFilter",
"gaussian"
}

Definition at line 43 of file sddssmooth.c.

43 {
44 "points",
45 "passes",
46 "columns",
47 "pipe",
48 "newcolumns",
49 "differencecolumns",
50 "despike",
51 "nowarnings",
52 "savitzkygolay",
53 "majorOrder",
54 "medianFilter",
55 "gaussian"
56};

◆ USAGE

char* USAGE
static

Definition at line 58 of file sddssmooth.c.