157 {
158 SCANNED_ARG *s_arg;
160 char *inputfile, *outputfile, *xcolName, **ycolName, **ycolMatch;
161 long columnsupplied, totalFilterCount, totalStages, tmpfileUsed;
162 int64_t npoints;
163 int32_t yColumns, ycolMatches;
164 long i, j, i_arg, filterNum, stageNum, currentFilter, currentStage, filterType, error;
165 unsigned long pipeFlags, majorOrderFlag;
166 char outColName[256], outColDesc[256];
167 double *xcol, *ycol;
168 short columnMajorOrder = -1;
169
174
176 argc =
scanargs(&s_arg, argc, argv);
177 if (argc < 2)
179
180
181 tmpfileUsed = 0;
182 pipeFlags = 0;
183 verbose = 0;
184 columnsupplied = 0;
185 inputfile = outputfile = xcolName = NULL;
186 ycolName = ycolMatch = NULL;
187 yColumns = ycolMatches = 0;
188
189
190 totalFilterCount = 0;
191 filterNum = 0;
192 stageNum = 0;
193
194
195 stage = (
STAGE *)malloc(
sizeof(*stage));
196 stage[0].filter = (void *)malloc(sizeof(*stage[0].filter));
197 stage[0].type = (long *)malloc(sizeof(*stage[0].type));
198
199 for (i_arg = 1; i_arg < argc; i_arg++) {
200 if (s_arg[i_arg].arg_type == OPTION) {
202 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
203 case CLO_MAJOR_ORDER:
204 majorOrderFlag = 0;
205 s_arg[i_arg].n_items--;
206 if (s_arg[i_arg].n_items > 0 && (!
scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
"row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
"column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
207 SDDS_Bomb(
"invalid -majorOrder syntax/values");
208 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
209 columnMajorOrder = 1;
210 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
211 columnMajorOrder = 0;
212 break;
213 case CLO_LOWPASS:
214 if (s_arg[i_arg].n_items < 2)
216 LHptr = (
LOWHIGH *)malloc(
sizeof(*LHptr));
217 if (!
get_double(&(LHptr->gain), s_arg[i_arg].list[1]))
218 SDDS_Bomb(
"Invalid -lowpass value provided.");
219 if (s_arg[i_arg].n_items > 2 && !
get_double(&(LHptr->cutoff), s_arg[i_arg].list[2]))
220 SDDS_Bomb(
"Invalid -lowpass value provided.");
221 stage[stageNum].filter[filterNum] = LHptr;
222 stage[stageNum].type[filterNum] = CLO_LOWPASS;
223 stage[stageNum].numFilters = ++filterNum;
224 totalFilterCount++;
225
226 stage[stageNum].filter = (void *)realloc(stage[stageNum].filter, sizeof(*stage[stageNum].filter) * (filterNum + 1));
227 stage[stageNum].type = (long *)realloc(stage[stageNum].type, sizeof(*stage[stageNum].type) * (filterNum + 1));
228 break;
229 case CLO_HIGHPASS:
230 if (s_arg[i_arg].n_items < 2)
232 LHptr = (
LOWHIGH *)malloc(
sizeof(*LHptr));
233 if (!
get_double(&(LHptr->gain), s_arg[i_arg].list[1]))
234 SDDS_Bomb(
"Invalid -highpass value provided.");
235 if (s_arg[i_arg].n_items > 2 && !
get_double(&(LHptr->cutoff), s_arg[i_arg].list[2]))
236 SDDS_Bomb(
"Invalid -highpass value provided.");
237 stage[stageNum].filter[filterNum] = LHptr;
238 stage[stageNum].type[filterNum] = CLO_HIGHPASS;
239 stage[stageNum].numFilters = ++filterNum;
240 totalFilterCount++;
241
242 stage[stageNum].filter = (void *)realloc(stage[stageNum].filter, sizeof(*stage[stageNum].filter) * (filterNum + 1));
243 stage[stageNum].type = (long *)realloc(stage[stageNum].type, sizeof(*stage[stageNum].type) * (filterNum + 1));
244 break;
245 case CLO_PROPORTIONAL:
246 if (s_arg[i_arg].n_items != 2)
247 SDDS_Bomb(
"Invalid -proportional option.");
248 Gptr = (
GAIN *)malloc(
sizeof(*Gptr));
249 if (!
get_double(&(Gptr->gain), s_arg[i_arg].list[1]))
250 SDDS_Bomb(
"Invalid -proportional value provided.");
251 stage[stageNum].filter[filterNum] = Gptr;
252 stage[stageNum].type[filterNum] = CLO_PROPORTIONAL;
253 stage[stageNum].numFilters = ++filterNum;
254 totalFilterCount++;
255
256 stage[stageNum].filter = (void *)realloc(stage[stageNum].filter, sizeof(*stage[stageNum].filter) * (filterNum + 1));
257 stage[stageNum].type = (long *)realloc(stage[stageNum].type, sizeof(*stage[stageNum].type) * (filterNum + 1));
258 break;
259 case CLO_ANALOGFILTER:
260 if (s_arg[i_arg].n_items < 2)
261 SDDS_Bomb(
"Invalid -analogfilter option.");
262 ADptr = (
ANADIG *)malloc(
sizeof(*ADptr));
263 ADptr->ACcoeff = ADptr->BDcoeff = NULL;
264 if (strcasecmp(s_arg[i_arg].list[1], "C") == 0 || strcasecmp(s_arg[i_arg].list[1], "D") == 0) {
265 processFilterParams(s_arg[i_arg].list, s_arg[i_arg].n_items, "C", "D", ADptr);
266 } else {
267 if (s_arg[i_arg].n_items != 4)
268 SDDS_Bomb(
"Invalid -analogfilter option for providing coefficient file and coefficient column names.");
269 processFilterParamsFromFile(s_arg[i_arg].list[1], s_arg[i_arg].list[2], s_arg[i_arg].list[3], ADptr);
270 }
271 stage[stageNum].filter[filterNum] = ADptr;
272 stage[stageNum].type[filterNum] = CLO_ANALOGFILTER;
273 stage[stageNum].numFilters = ++filterNum;
274 totalFilterCount++;
275
276 stage[stageNum].filter = (void *)realloc(stage[stageNum].filter, sizeof(*stage[stageNum].filter) * (filterNum + 1));
277 stage[stageNum].type = (long *)realloc(stage[stageNum].type, sizeof(*stage[stageNum].type) * (filterNum + 1));
278 break;
279 case CLO_DIGITALFILTER:
280 if (s_arg[i_arg].n_items < 2)
281 SDDS_Bomb(
"Invalid -digitalfilter option.");
282 ADptr = (
ANADIG *)malloc(
sizeof(*ADptr));
283 ADptr->ACcoeff = ADptr->BDcoeff = NULL;
284 if (strcasecmp(s_arg[i_arg].list[1], "A") == 0 || strcasecmp(s_arg[i_arg].list[1], "B") == 0) {
285 processFilterParams(s_arg[i_arg].list, s_arg[i_arg].n_items, "A", "B", ADptr);
286 } else {
287 if (s_arg[i_arg].n_items != 4)
288 SDDS_Bomb(
"Invalid -digitalfilter option for providing coefficient file and coefficient column names.");
289 processFilterParamsFromFile(s_arg[i_arg].list[1], s_arg[i_arg].list[2], s_arg[i_arg].list[3], ADptr);
290 }
291 stage[stageNum].filter[filterNum] = ADptr;
292 stage[stageNum].type[filterNum] = CLO_DIGITALFILTER;
293 stage[stageNum].numFilters = ++filterNum;
294 totalFilterCount++;
295
296 stage[stageNum].filter = (void *)realloc(stage[stageNum].filter, sizeof(*stage[stageNum].filter) * (filterNum + 1));
297 stage[stageNum].type = (long *)realloc(stage[stageNum].type, sizeof(*stage[stageNum].type) * (filterNum + 1));
298 break;
299 case CLO_CASCADE:
300 stageNum++;
301
302 stage = (
STAGE *)realloc(stage,
sizeof(*stage) * (stageNum + 1));
303 stage[stageNum].filter = (void *)malloc(sizeof(*stage[stageNum].filter));
304 stage[stageNum].type = (long *)malloc(sizeof(*stage[stageNum].type));
305 filterNum = 0;
306 stage[stageNum].numFilters = filterNum;
307 break;
308 case CLO_COLUMN:
309 if (s_arg[i_arg].n_items < 3)
311 xcolName = s_arg[i_arg].list[1];
312 ycolMatches = s_arg[i_arg].n_items - 2;
313 ycolMatch = malloc(sizeof(*ycolMatch) * ycolMatches);
314 for (i = 2; i < s_arg[i_arg].n_items; i++)
315 ycolMatch[i - 2] = s_arg[i_arg].list[i];
316 columnsupplied = 1;
317 break;
318 case CLO_PIPE:
319 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
321 break;
322 case CLO_VERBOSE:
323 verbose = 1;
324 break;
325 default:
326 fprintf(stderr, "Error (%s): unknown switch: %s\n", argv[0], s_arg[i_arg].list[0]);
327 exit(EXIT_FAILURE);
328 break;
329 }
330 } else {
331 if (inputfile == NULL)
332 inputfile = s_arg[i_arg].list[0];
333 else if (outputfile == NULL)
334 outputfile = s_arg[i_arg].list[0];
335 else
337 }
338 }
339
340 processFilenames(
"sddsdigfilter", &inputfile, &outputfile, pipeFlags, 1, &tmpfileUsed);
341
342 if (totalFilterCount == 0 || columnsupplied == 0) {
343 fprintf(stderr, "no filter or no columns supplied.\n");
344 exit(EXIT_FAILURE);
345 }
346 totalStages = stageNum + 1;
349 if (
SDDS_CheckColumn(&SDDS_input, xcolName, NULL, 0, stderr) != SDDS_CHECK_OKAY) {
350 fprintf(stderr, "xColumn %s does not exist.\n", xcolName);
351 exit(EXIT_FAILURE);
352 }
353 ycolName =
getMatchingSDDSNames(&SDDS_input, ycolMatch, ycolMatches, &yColumns, SDDS_MATCH_COLUMN);
354 for (i = 0; i < yColumns; i++) {
355 if (
SDDS_CheckColumn(&SDDS_input, ycolName[i], NULL, 0, stderr) != SDDS_CHECK_OKAY) {
356 fprintf(stderr, "yColumn %s does not exist.\n", ycolName[i]);
357 exit(EXIT_FAILURE);
358 }
359 }
362 if (columnMajorOrder != -1)
363 SDDS_output.layout.data_mode.column_major = columnMajorOrder;
364 else
365 SDDS_output.layout.data_mode.column_major = SDDS_input.layout.data_mode.column_major;
366 for (i = 0; i < yColumns; i++) {
367 sprintf(outColName, "DigFiltered%s", ycolName[i]);
368 sprintf(outColDesc, "Digital Filtered %s", ycolName[i]);
371 }
374
380 if (npoints) {
381
384 for (i = 0; i < yColumns; i++) {
385 sprintf(outColName, "DigFiltered%s", ycolName[i]);
388
389 for (currentStage = 0; currentStage < totalStages; currentStage++) {
390 if (verbose == 1) {
391 fprintf(stdout, "STAGE %ld\n", currentStage);
392 }
393
394 stage[currentStage].time = xcol;
395
396 if (currentStage == 0) {
397 stage[currentStage].input = ycol;
398 } else {
399 stage[currentStage].input = stage[currentStage - 1].output;
400 }
401
402 stage[currentStage].output = (double *)calloc(npoints, sizeof(*stage[currentStage].output));
403
404 for (currentFilter = 0; currentFilter < stage[currentStage].numFilters; currentFilter++) {
405 if (verbose == 1) {
406 fprintf(stdout, "filter %ld\n", currentFilter);
407 }
408
409 filterType = stage[currentStage].type[currentFilter];
410 error = (*filter_funct[filterType])(&(stage[currentStage]), currentFilter, npoints);
411 if (error != 0) {
412 fprintf(stderr, "nyquist violation.\n");
413 exit(EXIT_FAILURE);
414 }
415
416 }
417
418 }
419
420
423
424 free(ycol);
425 for (currentStage = 0; currentStage < totalStages; currentStage++)
426 free(stage[currentStage].output);
427 }
428 free(xcol);
429 }
432 }
435 for (i = 0; i < totalStages; i++) {
436 for (j = 0; j < stage[i].numFilters; j++) {
437 switch (stage[i].type[j]) {
438 case CLO_ANALOGFILTER:
439 case CLO_DIGITALFILTER:
440 free(((
ANADIG *)(stage[i].filter[j]))->ACcoeff);
441 free(((
ANADIG *)(stage[i].filter[j]))->BDcoeff);
442 free((
ANADIG *)(stage[i].filter[j]));
443 break;
444 case CLO_PROPORTIONAL:
445 free((
GAIN *)(stage[i].filter[j]));
446 break;
447 case CLO_HIGHPASS:
448 case CLO_LOWPASS:
449 free((
LOWHIGH *)(stage[i].filter[j]));
450 break;
451 }
452 }
453 free(stage[i].filter);
454 free(stage[i].type);
455 }
456 free(stage);
458 free(ycolName);
459 free(ycolMatch);
461 return (EXIT_SUCCESS);
462
463}
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
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.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length)
Defines a data column within the SDDS dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_FreeStringArray(char **string, int64_t strings)
Frees an array of strings by deallocating each individual string.
char ** getMatchingSDDSNames(SDDS_DATASET *dataset, char **matchName, int32_t matches, int32_t *names, short type)
Retrieves an array of matching SDDS entity names based on specified criteria.
int32_t SDDS_CheckColumn(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a column exists in the SDDS dataset with the specified name, units, and type.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
#define SDDS_DOUBLE
Identifier for the double data type.
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
int get_double(double *dptr, char *s)
Parses a double value from the given string.
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
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.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
void free_scanargs(SCANNED_ARG **scanned, int argc)
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.