SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddsfdfilter.c File Reference

Detailed Description

SDDS-format frequency-domain filter program.

This program applies various frequency-domain filters to SDDS-formatted data files. It supports multiple filtering options, including high-pass, low-pass, notch, bandpass, threshold, and file-based filters. Users can specify input and output files or use pipes for data processing.

Usage

sddsfdfilter [<inputfile>] [<outputfile>]
[-pipe=[input][,output]]
[-columns=<indep-variable>[,<depen-quantity>[,...]]]
[-exclude=<depen-quantity>[,...]]
[-clipFrequencies=[high=<number>][,low=<number>]]
[-threshold=level=<value>[,fractional][,start=<freq>][,end=<freq>]]
[-highpass=start=<freq>,end=<freq>]
[-lowpass=start=<freq>,end=<freq>]
[-notch=center=<center>,flatWidth=<value>,fullWidth=<value>]
[-bandpass=center=<center>,flatWidth=<value>,fullWidth=<value>]
[-filterFile=filename=<filename>,frequency=<columnName>{,real=<cName>,imaginary=<cName>|magnitude=<cName>}]
[-cascade]
[-newColumns]
[-differenceColumns]
[-majorOrder=row|column]

Options

Required Description
-columns Specifies columns to filter.
Optional Description
-pipe Specifies input and/or output via pipes.
-exclude Specifies columns to exclude from filtering.
-clipFrequencies Clips frequencies outside the specified range.
-threshold Filters based on a threshold with optional range.
-highpass Applies a high-pass filter with a specified frequency range.
-lowpass Applies a low-pass filter with a specified frequency range.
-notch Applies a notch filter with specified characteristics.
-bandpass Applies a band-pass filter with specified characteristics.
-filterFile Specifies a filter based on external file data.
-cascade Specifies cascaded filter stages.
-newColumns Creates new columns for filtered data.
-differenceColumns Creates columns for differences between original and filtered data.
-majorOrder Specifies major order as either row or column.

Incompatibilities

  • -cascade must not precede filter definitions.
  • Only one of the following may be specified for -filterFile:
    • magnitude=<columnName>
    • Both real=<columnName> and imaginary=<columnName>
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Authors
M. Borland, R. Soliday, Xuesong Jiao, L. Emery, H. Shang

Definition in file sddsfdfilter.c.

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

Go to the source code of this file.

Functions

long applyFilters (double *outputData, double *inputData, double *timeData, int64_t rows, FILTER_STAGE *filterStage, long filterStages)
 
long applyFilterStage (double *outputRI, double *inputRI, int64_t frequencies, double dfrequency, FILTER_STAGE *filterStage)
 
void addClipFilterOutput (double *outputRI, double *inputRI, int64_t frequencies, double dfrequency, CLIP_FILTER *filter)
 
void addThresholdFilterOutput (double *outputRI, double *inputRI, int64_t frequencies, double dfrequency, THRESHOLD_FILTER *filter)
 
void addHighPassFilterOutput (double *outputRI, double *inputRI, int64_t frequencies, double dfrequency, HILO_FILTER *filter)
 
void addLowPassFilterOutput (double *outputRI, double *inputRI, int64_t frequencies, double dfrequency, HILO_FILTER *filter)
 
void addNotchFilterOutput (double *outputRI, double *inputRI, int64_t frequencies, double dfrequency, NHBP_FILTER *filter)
 
void addBandPassFilterOutput (double *outputRI, double *inputRI, int64_t frequencies, double dfrequency, NHBP_FILTER *filter)
 
void addFileFilterOutput (double *outputRI, double *inputRI, int64_t frequencies, double dfrequency, FILE_FILTER *filter)
 
int64_t computeIndex (double value, double dfrequency, int64_t frequencies)
 
void addFilter (FILTER_STAGE *filterStage, long optionCode, SCANNED_ARG *scanned)
 
int main (int argc, char **argv)
 

Function Documentation

◆ addBandPassFilterOutput()

void addBandPassFilterOutput ( double * outputRI,
double * inputRI,
int64_t frequencies,
double dfrequency,
NHBP_FILTER * filter )

Definition at line 648 of file sddsfdfilter.c.

648 {
649 int64_t i1, i2, i;
650 double fraction, dfraction;
651
652 i1 = computeIndex(filter->center - filter->fullwidth / 2, dfrequency, frequencies);
653 i2 = computeIndex(filter->center - filter->flatwidth / 2, dfrequency, frequencies);
654 dfraction = i1 == i2 ? 0 : 1.0 / (i2 - i1);
655 fraction = 0;
656 for (i = i1; i <= i2; i++) {
657 outputRI[2 * i] += inputRI[2 * i] * fraction;
658 outputRI[2 * i + 1] += inputRI[2 * i + 1] * fraction;
659 if ((fraction += dfraction) > 1)
660 fraction = 1;
661 }
662
663 i1 = computeIndex(filter->center + filter->flatwidth / 2, dfrequency, frequencies);
664 i2 = computeIndex(filter->center + filter->fullwidth / 2, dfrequency, frequencies);
665 dfraction = i1 == i2 ? 0 : 1.0 / (i2 - i1);
666 fraction = 1;
667 for (i = i1; i <= i2; i++) {
668 outputRI[2 * i] += inputRI[2 * i] * fraction;
669 outputRI[2 * i + 1] += inputRI[2 * i + 1] * fraction;
670 if ((fraction -= dfraction) < 0)
671 fraction = 0;
672 }
673
674 i1 = computeIndex(filter->center - filter->flatwidth / 2, dfrequency, frequencies);
675 i2 = computeIndex(filter->center + filter->flatwidth / 2, dfrequency, frequencies);
676 for (i = i1; i <= i2; i++) {
677 outputRI[2 * i] += inputRI[2 * i];
678 outputRI[2 * i + 1] += inputRI[2 * i + 1];
679 }
680}

◆ addClipFilterOutput()

void addClipFilterOutput ( double * outputRI,
double * inputRI,
int64_t frequencies,
double dfrequency,
CLIP_FILTER * filter )

Definition at line 521 of file sddsfdfilter.c.

521 {
522 int64_t i1, i2;
523
524 i1 = 0;
525 i2 = frequencies - 1;
526 if (filter->flags & FILT_HIGH_GIVEN)
527 if ((i2 = frequencies - filter->high) < 0)
528 i2 = 0;
529 if (filter->flags & FILT_LOW_GIVEN)
530 if ((i1 = filter->low) >= frequencies)
531 i1 = frequencies - 1;
532 for (; i1 <= i2; i1++) {
533 outputRI[2 * i1] += inputRI[2 * i1];
534 outputRI[2 * i1 + 1] += inputRI[2 * i1 + 1];
535 }
536}

◆ addFileFilterOutput()

void addFileFilterOutput ( double * outputRI,
double * inputRI,
int64_t frequencies,
double dfrequency,
FILE_FILTER * filter )

Definition at line 682 of file sddsfdfilter.c.

682 {
683 long code;
684 int64_t i;
685 double factor, ifactor, rfactor, rdata, idata, f;
686
687 if (!filter->freqData) {
688 SDDS_DATASET SDDSin;
689 long readCode = 0;
690
691 if (!SDDS_InitializeInput(&SDDSin, filter->file) || (readCode = SDDS_ReadPage(&SDDSin)) == 0)
692 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
693 if (readCode < 0) {
694 fprintf(stderr, "error: unable to read filter file %s (sddsfdfilter)\n", filter->file);
695 exit(EXIT_FAILURE);
696 }
697 if ((filter->points = SDDS_CountRowsOfInterest(&SDDSin)) <= 0) {
698 fprintf(stderr, "error: file %s has no data on first page (sddsfdfilter)\n", filter->file);
699 exit(EXIT_FAILURE);
700 }
701 if (!(filter->freqData = SDDS_GetColumnInDoubles(&SDDSin, filter->freqName)) ||
702 (filter->magName && !(filter->magData = SDDS_GetColumnInDoubles(&SDDSin, filter->magName))) ||
703 (filter->imagName && !(filter->imagData = SDDS_GetColumnInDoubles(&SDDSin, filter->imagName))) ||
704 (filter->realName && !(filter->realData = SDDS_GetColumnInDoubles(&SDDSin, filter->realName))) ||
705 !SDDS_Terminate(&SDDSin))
706 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
707 for (i = 1; i < filter->points; i++)
708 if (filter->freqData[i - 1] >= filter->freqData[i]) {
709 fprintf(stderr, "error: frequency data not monotonically increasing for %s (sddsfdfilter)\n", filter->file);
710 exit(EXIT_FAILURE);
711 }
712 }
713 for (i = 0; i < frequencies; i++) {
714 f = i * dfrequency;
715 if (filter->freqData[0] > f || filter->freqData[filter->points - 1] < f)
716 continue;
717 if (filter->magName) {
718 factor = interp(filter->magData, filter->freqData, filter->points, f, 0, 1, &code);
719 outputRI[2 * i] += factor * inputRI[2 * i];
720 outputRI[2 * i + 1] += factor * inputRI[2 * i + 1];
721 } else {
722 rfactor = interp(filter->realData, filter->freqData, filter->points, f, 0, 1, &code);
723 ifactor = interp(filter->imagData, filter->freqData, filter->points, f, 0, 1, &code);
724 rdata = inputRI[2 * i];
725 idata = inputRI[2 * i + 1];
726 outputRI[2 * i] += rdata * rfactor - idata * ifactor;
727 outputRI[2 * i + 1] += rdata * ifactor + idata * rfactor;
728 }
729 }
730}
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)
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
double interp(double *f, double *x, long n, double xo, long warnings, long order, long *returnCode)
Performs simple linear interpolation of data.
Definition interp.c:34

◆ addFilter()

void addFilter ( FILTER_STAGE * filterStage,
long optionCode,
SCANNED_ARG * scanned )

Definition at line 743 of file sddsfdfilter.c.

743 {
744 THRESHOLD_FILTER *thresholdFilter;
745 HILO_FILTER *hiloFilter;
746 NHBP_FILTER *nhbpFilter;
747 FILE_FILTER *fileFilter;
748 CLIP_FILTER *clipFilter;
749 FILTER *filter;
750 long items, filters;
751 char **item;
752
753 if (!(filterStage->filter = SDDS_Realloc(filterStage->filter, sizeof(*filterStage->filter) * (filterStage->filters + 1))))
754 SDDS_Bomb("allocation failure adding filter slot");
755 filter = filterStage->filter;
756 filters = filterStage->filters;
757 filterStage->filters++;
758
759 items = scanned->n_items - 1;
760 item = scanned->list + 1;
761 switch (filter[filters].filterType = optionCode) {
762 case SET_THRESHOLD:
763 if (!(thresholdFilter = filter[filters].filter = calloc(1, sizeof(THRESHOLD_FILTER))))
764 SDDS_Bomb("allocation failure allocating threshold filter");
765 if (items < 1)
766 SDDS_Bomb("invalid -threshold syntax");
767 if (!scanItemList(&thresholdFilter->flags, item, &items, 0,
768 "level", SDDS_DOUBLE, &thresholdFilter->level, 1, FILT_LEVEL_GIVEN,
769 "fractional", -1, NULL, 0, FILT_FRACTHRES_GIVEN,
770 "start", SDDS_DOUBLE, &thresholdFilter->start, 1, FILT_START_GIVEN,
771 "end", SDDS_DOUBLE, &thresholdFilter->end, 1, FILT_END_GIVEN, NULL))
772 SDDS_Bomb("invalid -threshold syntax/values");
773 if (!(thresholdFilter->flags & FILT_LEVEL_GIVEN))
774 SDDS_Bomb("supply level=<value> qualifier for -threshold");
775 if ((thresholdFilter->flags & FILT_START_GIVEN && thresholdFilter->flags & FILT_END_GIVEN) && thresholdFilter->start > thresholdFilter->end)
776 SDDS_Bomb("start > end for -threshold filter");
777 break;
778 case SET_HIGHPASS:
779 case SET_LOWPASS:
780 if (!(hiloFilter = filter[filters].filter = calloc(1, sizeof(HILO_FILTER))))
781 SDDS_Bomb("allocation failure allocating low-pass or high-pass filter");
782 if (!scanItemList(&hiloFilter->flags, item, &items, 0,
783 "start", SDDS_DOUBLE, &hiloFilter->start, 1, FILT_START_GIVEN,
784 "end", SDDS_DOUBLE, &hiloFilter->end, 1, FILT_END_GIVEN, NULL))
785 SDDS_Bomb("invalid -highpass or -lowpass syntax");
786 if (!(hiloFilter->flags & FILT_START_GIVEN) || !(hiloFilter->flags & FILT_END_GIVEN))
787 SDDS_Bomb("supply start=<value> and end=<value> qualifiers with -highpass and -lowpass");
788 break;
789 case SET_NOTCH:
790 case SET_BANDPASS:
791 if (!(nhbpFilter = filter[filters].filter = calloc(1, sizeof(NHBP_FILTER))))
792 SDDS_Bomb("allocation failure allocating notch or bandpass filter");
793 if (!scanItemList(&nhbpFilter->flags, item, &items, 0,
794 "center", SDDS_DOUBLE, &nhbpFilter->center, 1, FILT_CENTER_GIVEN,
795 "fullwidth", SDDS_DOUBLE, &nhbpFilter->fullwidth, 1, FILT_FULLWIDTH_GIVEN,
796 "flatwidth", SDDS_DOUBLE, &nhbpFilter->flatwidth, 1, FILT_FLATWIDTH_GIVEN, NULL))
797 SDDS_Bomb("invalid -notch or -bandpass syntax");
798 if (!(nhbpFilter->flags & FILT_CENTER_GIVEN) || !(nhbpFilter->flags & FILT_FLATWIDTH_GIVEN))
799 SDDS_Bomb("supply center=<value> and flatWidth=<value> qualifiers with -notch and -bandpass");
800 if (!(nhbpFilter->flags & FILT_FULLWIDTH_GIVEN))
801 nhbpFilter->fullwidth = nhbpFilter->flatwidth;
802 if (nhbpFilter->fullwidth < nhbpFilter->flatwidth)
803 SDDS_Bomb("full width may not be less than flat width for notch/bandpass filter");
804 break;
805 case SET_FILTERFILE:
806 if (!(fileFilter = filter[filters].filter = calloc(1, sizeof(FILE_FILTER))))
807 SDDS_Bomb("allocation failure allocating file filter");
808 if (!scanItemList(&fileFilter->flags, item, &items, 0,
809 "filename", SDDS_STRING, &fileFilter->file, 1, FILT_FILENAME_GIVEN,
810 "frequency", SDDS_STRING, &fileFilter->freqName, 1, FILT_FREQNAME_GIVEN,
811 "real", SDDS_STRING, &fileFilter->realName, 1, FILT_REALNAME_GIVEN,
812 "imaginary", SDDS_STRING, &fileFilter->imagName, 1, FILT_IMAGNAME_GIVEN,
813 "magnitude", SDDS_STRING, &fileFilter->magName, 1, FILT_MAGNAME_GIVEN, NULL))
814 SDDS_Bomb("invalid -filterFile syntax");
815 if (!(fileFilter->flags & FILT_FILENAME_GIVEN))
816 SDDS_Bomb("supply filename=<string> with -filterFile");
817 if (!(fileFilter->flags & FILT_FREQNAME_GIVEN))
818 SDDS_Bomb("supply frequency=<columnName> with -filterFile");
819 if (!(fileFilter->flags & FILT_MAGNAME_GIVEN) && !(fileFilter->flags & FILT_REALNAME_GIVEN && fileFilter->flags & FILT_IMAGNAME_GIVEN))
820 SDDS_Bomb("supply either magnitude=<columnName>, or real=<columnName> and imag=<columnName>, with -filterFile");
821 if (fileFilter->flags & FILT_MAGNAME_GIVEN && (fileFilter->flags & FILT_REALNAME_GIVEN || fileFilter->flags & FILT_IMAGNAME_GIVEN))
822 SDDS_Bomb("magnitude=<columnName> is incompatible with real=<columnName> and imag=<columnName> for -filterFile");
823 fileFilter->freqData = NULL; /* Indicates no data present */
824 break;
825 case SET_CLIPFREQ:
826 if (!(clipFilter = filter[filters].filter = calloc(1, sizeof(CLIP_FILTER))))
827 SDDS_Bomb("allocation failure allocating clip filter");
828 if (!scanItemList(&clipFilter->flags, item, &items, 0,
829 "high", SDDS_LONG, &clipFilter->high, 1, FILT_HIGH_GIVEN,
830 "low", SDDS_LONG, &clipFilter->low, 1, FILT_LOW_GIVEN, NULL))
831 SDDS_Bomb("invalid -clipFrequencies syntax");
832 if (!(clipFilter->flags & FILT_HIGH_GIVEN) && !(clipFilter->flags & FILT_LOW_GIVEN))
833 SDDS_Bomb("supply at least one of high=<number> or low=<number> with -clipFrequencies");
834 break;
835 default:
836 SDDS_Bomb("invalid filter code---this shouldn't happen");
837 break;
838 }
839}
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#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
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.

◆ addHighPassFilterOutput()

void addHighPassFilterOutput ( double * outputRI,
double * inputRI,
int64_t frequencies,
double dfrequency,
HILO_FILTER * filter )

Definition at line 571 of file sddsfdfilter.c.

571 {
572 int64_t i, i1, i2;
573 double fraction, dfraction;
574
575 i1 = computeIndex(filter->start, dfrequency, frequencies);
576 i2 = computeIndex(filter->end, dfrequency, frequencies);
577
578 dfraction = i1 == i2 ? 0 : 1.0 / (i2 - i1);
579 fraction = 0;
580 for (i = i1; i <= i2; i++) {
581 outputRI[2 * i] += inputRI[2 * i] * fraction;
582 outputRI[2 * i + 1] += inputRI[2 * i + 1] * fraction;
583 if ((fraction += dfraction) > 1)
584 fraction = 1;
585 }
586 for (; i < frequencies; i++) {
587 outputRI[2 * i] += inputRI[2 * i];
588 outputRI[2 * i + 1] += inputRI[2 * i + 1];
589 }
590}

◆ addLowPassFilterOutput()

void addLowPassFilterOutput ( double * outputRI,
double * inputRI,
int64_t frequencies,
double dfrequency,
HILO_FILTER * filter )

Definition at line 592 of file sddsfdfilter.c.

592 {
593 int64_t i, i1, i2;
594 double fraction, dfraction;
595
596 i1 = computeIndex(filter->start, dfrequency, frequencies);
597 i2 = computeIndex(filter->end, dfrequency, frequencies);
598
599 dfraction = i1 == i2 ? 0 : 1.0 / (i2 - i1);
600 fraction = 1;
601 for (i = i1; i <= i2; i++) {
602 outputRI[2 * i] += inputRI[2 * i] * fraction;
603 outputRI[2 * i + 1] += inputRI[2 * i + 1] * fraction;
604 if ((fraction -= dfraction) < 0)
605 fraction = 0;
606 }
607 for (i = 0; i < i1; i++) {
608 outputRI[2 * i] += inputRI[2 * i];
609 outputRI[2 * i + 1] += inputRI[2 * i + 1];
610 }
611}

◆ addNotchFilterOutput()

void addNotchFilterOutput ( double * outputRI,
double * inputRI,
int64_t frequencies,
double dfrequency,
NHBP_FILTER * filter )

Definition at line 613 of file sddsfdfilter.c.

613 {
614 int64_t i1, i2, i;
615 double fraction, dfraction;
616
617 i1 = computeIndex(filter->center - filter->fullwidth / 2, dfrequency, frequencies);
618 i2 = computeIndex(filter->center - filter->flatwidth / 2, dfrequency, frequencies);
619 for (i = 0; i < i1; i++) {
620 outputRI[2 * i] += inputRI[2 * i];
621 outputRI[2 * i + 1] += inputRI[2 * i + 1];
622 }
623 dfraction = i1 == i2 ? 0 : 1.0 / (i2 - i1);
624 fraction = 1;
625 for (i = i1; i <= i2; i++) {
626 outputRI[2 * i] += inputRI[2 * i] * fraction;
627 outputRI[2 * i + 1] += inputRI[2 * i + 1] * fraction;
628 if ((fraction -= dfraction) < 0)
629 fraction = 0;
630 }
631
632 i1 = computeIndex(filter->center + filter->flatwidth / 2, dfrequency, frequencies);
633 i2 = computeIndex(filter->center + filter->fullwidth / 2, dfrequency, frequencies);
634 for (i = i2; i < frequencies; i++) {
635 outputRI[2 * i] += inputRI[2 * i];
636 outputRI[2 * i + 1] += inputRI[2 * i + 1];
637 }
638 dfraction = i1 == i2 ? 0 : 1.0 / (i2 - i1);
639 fraction = 0;
640 for (i = i1; i <= i2; i++) {
641 outputRI[2 * i] += inputRI[2 * i] * fraction;
642 outputRI[2 * i + 1] += inputRI[2 * i + 1] * fraction;
643 if ((fraction += dfraction) > 1)
644 fraction = 1;
645 }
646}

◆ addThresholdFilterOutput()

void addThresholdFilterOutput ( double * outputRI,
double * inputRI,
int64_t frequencies,
double dfrequency,
THRESHOLD_FILTER * filter )

Definition at line 538 of file sddsfdfilter.c.

538 {
539 int64_t i, i1, i2;
540 double level2, level2q, level2o;
541 double max2, mag2;
542
543 i1 = 0;
544 if (filter->flags & FILT_START_GIVEN)
545 i1 = computeIndex(filter->start, dfrequency, frequencies);
546 i2 = frequencies - 1;
547 if (filter->flags & FILT_END_GIVEN)
548 i2 = computeIndex(filter->end, dfrequency, frequencies);
549
550 if (filter->flags & FILT_FRACTHRES_GIVEN) {
551 max2 = -DBL_MAX;
552 for (i = i1; i <= i2; i++)
553 if ((mag2 = inputRI[2 * i] * inputRI[2 * i] + inputRI[2 * i + 1] * inputRI[2 * i + 1]) > max2)
554 max2 = mag2;
555 level2o = max2 * sqr(filter->level);
556 } else
557 level2o = sqr(filter->level);
558 level2q = level2o / 4;
559
560 for (i = i1; i <= i2; i++) {
561 level2 = level2q; /* only half the amplitude is in positive frequencies */
562 if (i == 0 || i == frequencies - 1)
563 level2 = level2o;
564 if ((inputRI[2 * i] * inputRI[2 * i] + inputRI[2 * i + 1] * inputRI[2 * i + 1]) >= level2) {
565 outputRI[2 * i] += inputRI[2 * i];
566 outputRI[2 * i + 1] += inputRI[2 * i + 1];
567 }
568 }
569}

◆ applyFilters()

long applyFilters ( double * outputData,
double * inputData,
double * timeData,
int64_t rows,
FILTER_STAGE * filterStage,
long filterStages )

Definition at line 439 of file sddsfdfilter.c.

439 {
440 long stage;
441 int64_t frequencies, row;
442 double *realimagInput, *realimagOutput;
443 double length, dfrequency, factor;
444 realimagOutput = NULL;
445 if (!(realimagInput = (double *)malloc(sizeof(*realimagInput) * (rows + 2))) ||
446 !(realimagOutput = (double *)malloc(sizeof(*realimagOutput) * (rows + 2))))
447 SDDS_Bomb("allocation failure");
448
449 /* Input data is real and has "rows" rows */
450 /* Result is interleaved real and imaginary */
451 realFFT2(realimagInput, inputData, rows, 0);
452 frequencies = rows / 2 + 1;
453
454 /* Length is the assumed length of the periodic signal,
455 which is one interval longer than the actual data entered */
456 length = ((double)rows) * (timeData[rows - 1] - timeData[0]) / ((double)rows - 1.0);
457 dfrequency = factor = 1.0 / length;
458
459 for (stage = 0; stage < filterStages; stage++) {
460 if (!applyFilterStage(realimagOutput, realimagInput, frequencies, dfrequency, filterStage + stage))
461 return 0;
462 SWAP_PTR(realimagOutput, realimagInput);
463 }
464
465 /* Input is still interleaved real and imaginary. The flag
466 INVERSE_FFT ensures that the array is interpreted correctly. */
467 /* Output is interleaved real and imaginary */
468#if DEBUG
469 for (row = 0; row < rows; row++) {
470 fprintf(stdout, "Real: %f, Imag: %f\n", realimagInput[2 * row], realimagInput[2 * row + 1]);
471 }
472#endif
473 realFFT2(realimagOutput, realimagInput, rows, INVERSE_FFT);
474
475 for (row = 0; row < rows; row++)
476 outputData[row] = realimagOutput[row];
477
478 free(realimagOutput);
479 free(realimagInput);
480
481 return 1;
482}

◆ applyFilterStage()

long applyFilterStage ( double * outputRI,
double * inputRI,
int64_t frequencies,
double dfrequency,
FILTER_STAGE * filterStage )

Definition at line 484 of file sddsfdfilter.c.

484 {
485 int64_t i, ifilter;
486
487 for (i = 0; i < 2 * frequencies; i++)
488 outputRI[i] = 0;
489
490 for (ifilter = 0; ifilter < filterStage->filters; ifilter++) {
491 switch (filterStage->filter[ifilter].filterType) {
492 case SET_CLIPFREQ:
493 addClipFilterOutput(outputRI, inputRI, frequencies, dfrequency, filterStage->filter[ifilter].filter);
494 break;
495 case SET_THRESHOLD:
496 addThresholdFilterOutput(outputRI, inputRI, frequencies, dfrequency, filterStage->filter[ifilter].filter);
497 break;
498 case SET_HIGHPASS:
499 addHighPassFilterOutput(outputRI, inputRI, frequencies, dfrequency, filterStage->filter[ifilter].filter);
500 break;
501 case SET_LOWPASS:
502 addLowPassFilterOutput(outputRI, inputRI, frequencies, dfrequency, filterStage->filter[ifilter].filter);
503 break;
504 case SET_NOTCH:
505 addNotchFilterOutput(outputRI, inputRI, frequencies, dfrequency, filterStage->filter[ifilter].filter);
506 break;
507 case SET_BANDPASS:
508 addBandPassFilterOutput(outputRI, inputRI, frequencies, dfrequency, filterStage->filter[ifilter].filter);
509 break;
510 case SET_FILTERFILE:
511 addFileFilterOutput(outputRI, inputRI, frequencies, dfrequency, filterStage->filter[ifilter].filter);
512 break;
513 default:
514 SDDS_Bomb("unknown filter type in applyFilterStage--this shouldn't happen");
515 break;
516 }
517 }
518 return 1;
519}

◆ computeIndex()

int64_t computeIndex ( double value,
double dfrequency,
int64_t frequencies )

Definition at line 732 of file sddsfdfilter.c.

732 {
733 int64_t i1;
734
735 i1 = value / dfrequency + 0.5;
736 if (i1 < 0)
737 i1 = 0;
738 if (i1 > frequencies - 1)
739 i1 = frequencies - 1;
740 return i1;
741}

◆ main()

int main ( int argc,
char ** argv )

Definition at line 198 of file sddsfdfilter.c.

198 {
199 int iArg;
200 char **outputColumn, **difColumn;
201 char *indepColumn, **depenColumn, **exclude;
202 long depenColumns, excludes;
203 char *input, *output;
204 long i, readCode, optionCode;
205 int64_t rows;
206 unsigned long flags, pipeFlags, majorOrderFlag;
207 SCANNED_ARG *scanned;
208 SDDS_DATASET SDDSin, SDDSout;
209 double *timeData, *inputData, *outputData;
210 FILTER_STAGE *filterStage;
211 long filterStages, totalFilters;
212 short columnMajorOrder = -1;
213
215 argc = scanargs(&scanned, argc, argv);
216 if (argc < 3 || argc > (3 + N_OPTIONS))
217 bomb(NULL, USAGE);
218
219 output = input = NULL;
220 flags = pipeFlags = 0;
221 indepColumn = NULL;
222 depenColumn = exclude = NULL;
223 depenColumns = excludes = 0;
224 if (!(filterStage = (FILTER_STAGE *)calloc(1, sizeof(*filterStage))))
225 SDDS_Bomb("allocation failure");
226
227 filterStage->filter = NULL;
228 filterStage->filters = 0;
229 filterStages = 1;
230 totalFilters = 0;
231
232 for (iArg = 1; iArg < argc; iArg++) {
233 if (scanned[iArg].arg_type == OPTION) {
234 /* Process options here */
235 switch (optionCode = match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
236 case SET_MAJOR_ORDER:
237 majorOrderFlag = 0;
238 scanned[iArg].n_items--;
239 if (scanned[iArg].n_items > 0 && (!scanItemList(&majorOrderFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
240 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
241 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
242 SDDS_Bomb("invalid -majorOrder syntax/values");
243 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
244 columnMajorOrder = 1;
245 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
246 columnMajorOrder = 0;
247 break;
248 case SET_PIPE:
249 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
250 SDDS_Bomb("invalid -pipe syntax");
251 break;
252 case SET_COLUMNS:
253 if (indepColumn)
254 SDDS_Bomb("only one -columns option may be given");
255 if (scanned[iArg].n_items < 2)
256 SDDS_Bomb("invalid -columns syntax");
257 indepColumn = scanned[iArg].list[1];
258 if (scanned[iArg].n_items >= 2) {
259 depenColumn = tmalloc(sizeof(*depenColumn) * (depenColumns = scanned[iArg].n_items - 2));
260 for (i = 0; i < depenColumns; i++)
261 depenColumn[i] = scanned[iArg].list[i + 2];
262 }
263 break;
264 case SET_THRESHOLD:
265 case SET_HIGHPASS:
266 case SET_LOWPASS:
267 case SET_NOTCH:
268 case SET_BANDPASS:
269 case SET_FILTERFILE:
270 case SET_CLIPFREQ:
271 addFilter(filterStage + filterStages - 1, optionCode, scanned + iArg);
272 totalFilters++;
273 break;
274 case SET_CASCADE:
275 if (filterStages == 0)
276 SDDS_Bomb("-cascade option precedes all filter definitions");
277 if (!(filterStage = SDDS_Realloc(filterStage, (filterStages + 1) * sizeof(*filterStage))))
278 SDDS_Bomb("allocation failure");
279 filterStage[filterStages].filter = NULL;
280 filterStage[filterStages].filters = 0;
281 filterStages++;
282 break;
283 case SET_NEWCOLUMNS:
284 flags |= FL_NEWCOLUMNS;
285 break;
286 case SET_DIFFERENCECOLUMNS:
287 flags |= FL_DIFCOLUMNS;
288 break;
289 case SET_EXCLUDE:
290 if (scanned[iArg].n_items < 2)
291 SDDS_Bomb("invalid -exclude syntax");
292 moveToStringArray(&exclude, &excludes, scanned[iArg].list + 1, scanned[iArg].n_items - 1);
293 break;
294 default:
295 fprintf(stderr, "error: unknown/ambiguous option: %s (%s)\n", scanned[iArg].list[0], argv[0]);
296 exit(EXIT_FAILURE);
297 break;
298 }
299 } else {
300 if (!input)
301 input = scanned[iArg].list[0];
302 else if (!output)
303 output = scanned[iArg].list[0];
304 else
305 SDDS_Bomb("too many filenames seen");
306 }
307 }
308
309 processFilenames("sddsfdfilter", &input, &output, pipeFlags, 0, NULL);
310
311 if (!totalFilters)
312 fputs("warning: no filters specified (sddsfdfilter)\n", stderr);
313
314 if (!indepColumn)
315 SDDS_Bomb("supply the independent column name with the -columns option");
316
317 if (!SDDS_InitializeInput(&SDDSin, input))
318 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
319
320 if (SDDS_CheckColumn(&SDDSin, indepColumn, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OKAY)
321 exit(EXIT_FAILURE);
322
323 excludes = appendToStringArray(&exclude, excludes, indepColumn);
324 if (!depenColumns)
325 depenColumns = appendToStringArray(&depenColumn, depenColumns, "*");
326
327 if ((depenColumns = expandColumnPairNames(&SDDSin, &depenColumn, NULL, depenColumns, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
328 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
329 SDDS_Bomb("No quantities selected to filter");
330 }
331
332 if (!SDDS_InitializeCopy(&SDDSout, &SDDSin, output, "w"))
333 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
334
335 if (columnMajorOrder != -1)
336 SDDSout.layout.data_mode.column_major = columnMajorOrder;
337 else
338 SDDSout.layout.data_mode.column_major = SDDSin.layout.data_mode.column_major;
339
340 if (flags & FL_NEWCOLUMNS) {
341 outputColumn = tmalloc(sizeof(*outputColumn) * depenColumns);
342 for (i = 0; i < depenColumns; i++) {
343 outputColumn[i] = tmalloc(sizeof(**outputColumn) * (strlen(depenColumn[i]) + 1 + strlen("Filtered")));
344 sprintf(outputColumn[i], "%sFiltered", depenColumn[i]);
345 if (!SDDS_TransferColumnDefinition(&SDDSout, &SDDSin, depenColumn[i], outputColumn[i]))
346 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
347 }
348 } else
349 outputColumn = depenColumn;
350
351 difColumn = NULL;
352 if (flags & FL_DIFCOLUMNS) {
353 difColumn = tmalloc(sizeof(*difColumn) * depenColumns);
354 for (i = 0; i < depenColumns; i++) {
355 difColumn[i] = tmalloc(sizeof(**difColumn) * (strlen(depenColumn[i]) + 1 + strlen("Difference")));
356 sprintf(difColumn[i], "%sDifference", depenColumn[i]);
357 if (!SDDS_TransferColumnDefinition(&SDDSout, &SDDSin, depenColumn[i], difColumn[i]))
358 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
359 }
360 }
361
362 if (!SDDS_WriteLayout(&SDDSout))
363 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
364
365 outputData = NULL;
366 while ((readCode = SDDS_ReadPage(&SDDSin)) > 0) {
367 if (!SDDS_CopyPage(&SDDSout, &SDDSin))
368 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
369 if ((rows = SDDS_CountRowsOfInterest(&SDDSin)) < 0)
370 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
371
372 if (rows) {
373 if (!(timeData = SDDS_GetColumnInDoubles(&SDDSin, indepColumn)))
374 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
375 if (!(outputData = SDDS_Realloc(outputData, sizeof(*outputData) * rows)))
376 SDDS_Bomb("allocation failure");
377 for (i = 0; i < depenColumns; i++) {
378 if (!(inputData = SDDS_GetColumnInDoubles(&SDDSin, depenColumn[i])))
379 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
380 if (!applyFilters(outputData, inputData, timeData, rows, filterStage, filterStages))
381 exit(EXIT_FAILURE);
382 if (!SDDS_SetColumnFromDoubles(&SDDSout, SDDS_BY_NAME, outputData, rows, outputColumn[i]))
383 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
384 if (flags & FL_DIFCOLUMNS) {
385 int64_t j;
386 for (j = 0; j < rows; j++)
387 outputData[j] = inputData[j] - outputData[j];
388 if (!SDDS_SetColumnFromDoubles(&SDDSout, SDDS_BY_NAME, outputData, rows, difColumn[i]))
389 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
390 }
391 free(inputData);
392 }
393 free(timeData);
394 }
395 if (!SDDS_WritePage(&SDDSout))
396 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
397 }
398
399 free(outputData);
400 for (i = 0; i < depenColumns; i++) {
401 free(depenColumn[i]);
402 if (flags & FL_NEWCOLUMNS)
403 free(outputColumn[i]);
404 if (flags & FL_DIFCOLUMNS)
405 free(difColumn[i]);
406 }
407 for (i = 0; i < excludes; i++)
408 free(exclude[i]);
409
410 free(indepColumn);
411 if (flags & FL_NEWCOLUMNS)
412 free(outputColumn);
413 free(depenColumn);
414 if (flags & FL_DIFCOLUMNS)
415 free(difColumn);
416 free(exclude);
417 for (i = 0; i < filterStages; i++) {
418 long j;
419 for (j = 0; j < filterStage[i].filters; j++) {
420 switch (filterStage[i].filter[j].filterType) {
421 case SET_FILTERFILE:
422 free(((FILE_FILTER *)(filterStage[i].filter[j].filter))->freqData);
423 free(((FILE_FILTER *)(filterStage[i].filter[j].filter))->magData);
424 free(((FILE_FILTER *)(filterStage[i].filter[j].filter))->imagData);
425 free(((FILE_FILTER *)(filterStage[i].filter[j].filter))->realData);
426 break;
427 default:
428 break;
429 }
430 }
431 }
432
433 if (!SDDS_Terminate(&SDDSout) || !SDDS_Terminate(&SDDSin))
434 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
435
436 return EXIT_SUCCESS;
437}
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.
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_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_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
#define SDDS_ANY_NUMERIC_TYPE
Special identifier used by SDDS_Check*() routines to accept any numeric type.
Definition SDDStypes.h:157
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
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.
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