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

Detailed Description

Performs FFT (Fast Fourier Transform) on SDDS-formatted data files.

This program processes SDDS data files, performing Fast Fourier Transforms (FFT) with extensive options for data manipulation, including normalization, windowing, PSD computation, and inverse transformations. It supports both complex and real input data and allows flexible output formats based on user-defined parameters.

Usage

sddsfft [<inputfile>] [<outputfile>]
[-pipe=[input][,output]]
[-columns=<indep-variable>[,<depen-quantity>[,...]]]
[-complexInput[=unfolded|folded]]
[-exclude=<depen-quantity>[,...]]
[-window[={hanning|welch|parzen|hamming|flattop|gaussian|none}[,correct]]]
[-sampleInterval=<number>]
[-normalize]
[-fullOutput[=unfolded|folded],unwrapLimit=<value>]
[-psdOutput[=plain][,{integrated|rintegrated[=<cutoff>]}]]
[-inverse]
[-padwithzeroes[=exponent] | -truncate]
[-suppressaverage]
[-noWarnings]
[-majorOrder=row|column]

Options

Required Description
-columns Specify the independent variable and dependent quantities for FFT analysis.
Optional Description
-pipe Utilize the standard SDDS Toolkit pipe option for input and/or output.
-complexInput Specify complex input column handling.
-exclude List of wildcard patterns to exclude specific quantities from analysis.
-window Apply a windowing function before analysis.
-sampleInterval Define the interval for sampling input data points.
-normalize Normalize output to have a peak magnitude of 1.
-fullOutput Output the real and imaginary parts of the FFT.
-psdOutput Output Power Spectral Density (PSD) in various formats.
-inverse Perform an inverse Fourier transform.
-padwithzeroes Pad data with zeroes for FFT optimization.
-truncate Truncate data to nearest product of small primes for efficiency.
-suppressaverage Remove average value from data before FFT.
-noWarnings Suppress warning messages.
-majorOrder Specify row or column major order for output.

Incompatibilities

  • -truncate is incompatible with:
    • -padwithzeroes
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
  • C. Saunders
  • R. Soliday
  • L. Emery

Definition in file sddsfft.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

int64_t greatestProductOfSmallPrimes (int64_t rows)
 
long process_data (SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, double *tdata, int64_t rows, int64_t rowsToUse, char *depenQuantity, char *depenQuantity2, unsigned long flags, long windowType, int64_t sampleInterval, long correctWindowEffects, long inverse, double rintegCutOffFreq, double unwrapLimit)
 
long create_fft_frequency_column (SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, char *timeName, char *freqUnits, long inverse)
 
long create_fft_columns (SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, char *origName, char *indepName, char *freqUnits, long full_output, unsigned long psd_output, long complexInput, long inverse, long unwrap_phase)
 
long create_fft_parameters (SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, char *indepName, char *freqUnits)
 
char * makeFrequencyUnits (SDDS_DATASET *SDDSin, char *indepName)
 
long expandComplexColumnPairNames (SDDS_DATASET *SDDSin, char **name, char ***realName, char ***imagName, long names, char **excludeName, long excludeNames, long typeMode, long typeValue)
 
int main (int argc, char **argv)
 
void moveToStringArrayComplex (char ***targetReal, char ***targetImag, long *targets, char **sourceReal, char **sourceImag, long sources)
 

Function Documentation

◆ create_fft_columns()

long create_fft_columns ( SDDS_DATASET * SDDSout,
SDDS_DATASET * SDDSin,
char * origName,
char * indepName,
char * freqUnits,
long full_output,
unsigned long psd_output,
long complexInput,
long inverse,
long unwrap_phase )

Definition at line 939 of file sddsfft.c.

939 {
940 char s[SDDS_MAXLINE];
941 char *origUnits, *origSymbol;
942 char *description, *name, *symbol, *units;
943 long index0, index1;
944 long offset = 0;
945
946 if (complexInput)
947 offset = 4;
948 if (SDDS_GetColumnInformation(SDDSin, "units", &origUnits, SDDS_GET_BY_NAME, origName) != SDDS_STRING ||
949 SDDS_GetColumnInformation(SDDSin, "symbol", &origSymbol, SDDS_GET_BY_NAME, origName) != SDDS_STRING)
950 return 0;
951 if (!inverse)
952 sprintf(s, "FFT%s", origName + offset);
953 else {
954 if (strncmp(origName, "FFT", 3) == 0)
955 offset = 3;
956 else if (strncmp(origName, "RealFFT", 7) == 0)
957 offset = 7;
958 else
959 offset = 0;
960 sprintf(s, "%s", origName + offset);
961 }
962 SDDS_CopyString(&name, s);
963 if (!origSymbol)
964 SDDS_CopyString(&origSymbol, origName + offset);
965 sprintf(s, "FFT %s", origSymbol);
966 SDDS_CopyString(&symbol, s);
967
968 sprintf(s, "Amplitude of FFT of %s", origSymbol);
969 SDDS_CopyString(&description, s);
970
971 if (SDDS_NumberOfErrors() || (index0 = SDDS_DefineColumn(SDDSout, name, symbol, origUnits, description, NULL, SDDS_DOUBLE, 0)) < 0)
972 return 0;
973 free(name);
974 free(symbol);
975 free(description);
976
977 if (fftOffset == -1)
978 fftOffset = 0;
979
980 if (psd_output & FL_PSDOUTPUT) {
981 if (origUnits && !SDDS_StringIsBlank(origUnits)) {
982 if (freqUnits && !SDDS_StringIsBlank(freqUnits)) {
983 sprintf(s, "(%s)$a2$n/(%s)", origUnits, freqUnits);
984 } else
985 sprintf(s, "(%s)$a2$n", origUnits);
986 SDDS_CopyString(&units, s);
987 } else
988 units = NULL;
989
990 sprintf(s, "PSD%s", origName + offset);
991 SDDS_CopyString(&name, s);
992
993 if (!origSymbol)
994 SDDS_CopyString(&origSymbol, origName + offset);
995 sprintf(s, "PSD %s", origSymbol);
996 SDDS_CopyString(&symbol, s);
997
998 sprintf(s, "PSD of %s", origSymbol);
999 SDDS_CopyString(&description, s);
1000
1001 if (SDDS_NumberOfErrors() || (index1 = SDDS_DefineColumn(SDDSout, name, symbol, units, description, NULL, SDDS_DOUBLE, 0)) < 0)
1002 return 0;
1003 psdOffset = index1 - index0;
1004 free(name);
1005 if (units)
1006 free(units);
1007 free(symbol);
1008 free(description);
1009 }
1010
1011 if (psd_output & (FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT)) {
1012 if (origUnits && !SDDS_StringIsBlank(origUnits)) {
1013 SDDS_CopyString(&units, origUnits);
1014 } else
1015 units = NULL;
1016
1017 sprintf(s, "SqrtIntegPSD%s", origName + offset);
1018 SDDS_CopyString(&name, s);
1019
1020 if (!origSymbol)
1021 SDDS_CopyString(&origSymbol, origName + offset);
1022 sprintf(s, "Sqrt Integ PSD %s", origSymbol);
1023 SDDS_CopyString(&symbol, s);
1024
1025 sprintf(s, "Sqrt Integ PSD of %s", origSymbol);
1026 SDDS_CopyString(&description, s);
1027
1028 if (SDDS_NumberOfErrors() || (index1 = SDDS_DefineColumn(SDDSout, name, symbol, units, description, NULL, SDDS_DOUBLE, 0)) < 0)
1029 return 0;
1030 psdIntOffset = index1 - index0;
1031
1032 sprintf(s, "IntegPSD%s", origName + offset);
1033 SDDS_CopyString(&name, s);
1034
1035 if (!origSymbol)
1036 SDDS_CopyString(&origSymbol, origName + offset);
1037 sprintf(s, "Integ PSD %s", origSymbol);
1038 SDDS_CopyString(&symbol, s);
1039
1040 sprintf(s, "Integ PSD of %s", origSymbol);
1041 SDDS_CopyString(&description, s);
1042
1043 if (origUnits && !SDDS_StringIsBlank(origUnits)) {
1044 sprintf(s, "%sPower", origUnits);
1045 SDDS_CopyString(&units, origUnits);
1046 } else
1047 units = NULL;
1048
1049 if (SDDS_NumberOfErrors() || (index1 = SDDS_DefineColumn(SDDSout, name, symbol, units, description, NULL, SDDS_DOUBLE, 0)) < 0)
1050 return 0;
1051 psdIntPowerOffset = index1 - index0;
1052 free(name);
1053 if (units)
1054 free(units);
1055 free(symbol);
1056 free(description);
1057 }
1058
1059 if (full_output) {
1060 if (!inverse)
1061 sprintf(s, "RealFFT%s", origName + offset);
1062 else
1063 sprintf(s, "Real%s", origName + offset);
1064 SDDS_CopyString(&name, s);
1065
1066 if (!origSymbol)
1067 SDDS_CopyString(&origSymbol, origName + offset);
1068 if (!inverse)
1069 sprintf(s, "Re[FFT %s]", origSymbol);
1070 else
1071 sprintf(s, "Re[%s]", origSymbol);
1072 SDDS_CopyString(&symbol, s);
1073
1074 if (!inverse)
1075 sprintf(s, "Real part of FFT of %s", origSymbol);
1076 else
1077 sprintf(s, "Real part of %s", origSymbol);
1078 SDDS_CopyString(&description, s);
1079
1080 if (SDDS_NumberOfErrors() || (index1 = SDDS_DefineColumn(SDDSout, name, symbol, origUnits, description, NULL, SDDS_DOUBLE, 0)) < 0)
1081 return 0;
1082 realOffset = index1 - index0;
1083 free(name);
1084 free(symbol);
1085 free(description);
1086
1087 if (!inverse)
1088 sprintf(s, "ImagFFT%s", origName + offset);
1089 else
1090 sprintf(s, "Imag%s", origName + offset);
1091 SDDS_CopyString(&name, s);
1092
1093 if (!origSymbol)
1094 SDDS_CopyString(&origSymbol, origName + offset);
1095 if (!inverse)
1096 sprintf(s, "Im[FFT %s]", origSymbol);
1097 else
1098 sprintf(s, "Im[%s]", origSymbol);
1099 SDDS_CopyString(&symbol, s);
1100
1101 if (!inverse)
1102 sprintf(s, "Imaginary part of FFT of %s", origSymbol);
1103 else
1104 sprintf(s, "Imaginary part of %s", origSymbol);
1105 SDDS_CopyString(&description, s);
1106
1107 if (SDDS_NumberOfErrors() || (index1 = SDDS_DefineColumn(SDDSout, name, symbol, origUnits, description, NULL, SDDS_DOUBLE, 0)) < 0)
1108 return 0;
1109 imagOffset = index1 - index0;
1110 free(name);
1111 free(symbol);
1112 free(description);
1113
1114 if (!inverse)
1115 sprintf(s, "ArgFFT%s", origName + offset);
1116 else
1117 sprintf(s, "Arg%s", origName + offset);
1118 SDDS_CopyString(&name, s);
1119
1120 if (!origSymbol)
1121 SDDS_CopyString(&origSymbol, origName + offset);
1122 if (!inverse)
1123 sprintf(s, "Arg[FFT %s]", origSymbol);
1124 else
1125 sprintf(s, "Arg[%s]", origSymbol);
1126 SDDS_CopyString(&symbol, s);
1127
1128 if (!inverse)
1129 sprintf(s, "Phase of FFT of %s", origSymbol);
1130 else
1131 sprintf(s, "Phase of %s", origSymbol);
1132 SDDS_CopyString(&description, s);
1133
1134 if (SDDS_NumberOfErrors() || (index1 = SDDS_DefineColumn(SDDSout, name, symbol, "degrees", description, NULL, SDDS_DOUBLE, 0)) < 0)
1135 return 0;
1136 argOffset = index1 - index0;
1137 free(name);
1138 free(symbol);
1139 free(description);
1140 if (unwrap_phase) {
1141 if (!inverse)
1142 sprintf(s, "UnwrapArgFFT%s", origName + offset);
1143 else
1144 sprintf(s, "UnwrapArg%s", origName + offset);
1145 SDDS_CopyString(&name, s);
1146
1147 if (!origSymbol)
1148 SDDS_CopyString(&origSymbol, origName + offset);
1149 if (!inverse)
1150 sprintf(s, "UnwrapArg[FFT %s]", origSymbol);
1151 else
1152 sprintf(s, "UnwrapArg[%s]", origSymbol);
1153 SDDS_CopyString(&symbol, s);
1154
1155 if (!inverse)
1156 sprintf(s, "Unwrapped Phase of FFT of %s", origSymbol);
1157 else
1158 sprintf(s, "Unwrapped Phase of %s", origSymbol);
1159 SDDS_CopyString(&description, s);
1160
1161 if (SDDS_NumberOfErrors() || (index1 = SDDS_DefineColumn(SDDSout, name, symbol, "degrees", description, NULL, SDDS_DOUBLE, 0)) < 0)
1162 return 0;
1163 unwrappedArgOffset = index1 - index0;
1164 free(name);
1165 free(symbol);
1166 free(description);
1167 }
1168 }
1169
1170 return 1;
1171}
int32_t SDDS_GetColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified column in the SDDS dataset.
Definition SDDS_info.c:41
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_NumberOfErrors()
Retrieves the number of errors recorded by SDDS library routines.
Definition SDDS_utils.c:304
int32_t SDDS_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:856
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37

◆ create_fft_frequency_column()

long create_fft_frequency_column ( SDDS_DATASET * SDDSout,
SDDS_DATASET * SDDSin,
char * timeName,
char * freqUnits,
long inverse )

Definition at line 907 of file sddsfft.c.

907 {
908 char s[SDDS_MAXLINE];
909 char *timeSymbol;
910 char *description;
911
912 if (SDDS_GetColumnInformation(SDDSin, "symbol", &timeSymbol, SDDS_GET_BY_NAME, timeName) != SDDS_STRING)
913 return 0;
914 if (!timeSymbol || SDDS_StringIsBlank(timeSymbol))
915 SDDS_CopyString(&timeSymbol, timeName);
916
917 sprintf(s, "Frequency for %s", timeSymbol);
918 SDDS_CopyString(&description, s);
919 if (!inverse) {
920 if (SDDS_DefineColumn(SDDSout, "f", NULL, freqUnits, description, NULL, SDDS_DOUBLE, 0) < 0) {
921 free(timeSymbol);
922 free(description);
923 return 0;
924 }
925 } else {
926 sprintf(s, "inverse for %s", timeSymbol);
927 SDDS_CopyString(&description, s);
928 if (SDDS_DefineColumn(SDDSout, "t", NULL, freqUnits, description, NULL, SDDS_DOUBLE, 0) < 0) {
929 free(timeSymbol);
930 free(description);
931 return 0;
932 }
933 }
934 free(timeSymbol);
935 free(description);
936 return 1;
937}

◆ expandComplexColumnPairNames()

long expandComplexColumnPairNames ( SDDS_DATASET * SDDSin,
char ** name,
char *** realName,
char *** imagName,
long names,
char ** excludeName,
long excludeNames,
long typeMode,
long typeValue )

Definition at line 1175 of file sddsfft.c.

1175 {
1176 long i, j, k, realNames, imagNames, names2;
1177 char **realName1, **imagName1, **realName2, **imagName2;
1178 char *realPattern, *imagPattern = NULL;
1179 long longest=0;
1180
1181 if (!names || !name)
1182 return 0;
1183 realName1 = imagName1 = realName2 = imagName2 = NULL;
1184 realNames = imagNames = names2 = 0;
1185 for (i = 0; i < names; i++) {
1186 if (strlen(name[i]) > longest)
1187 longest = strlen(name[i]);
1188 }
1189 longest += 10;
1190 if (!(realPattern = SDDS_Malloc(sizeof(*realPattern) * longest)) || !(imagPattern = SDDS_Malloc(sizeof(*imagPattern) * longest)))
1191 SDDS_Bomb("memory allocation failure");
1192
1193 for (i = 0; i < names; i++) {
1194 for (j = 0; j < 2; j++) {
1195 if (j == 0) {
1196 sprintf(realPattern, "Real%s", name[i]);
1197 sprintf(imagPattern, "Imag%s", name[i]);
1198 } else {
1199 sprintf(realPattern, "%sReal", name[i]);
1200 sprintf(imagPattern, "%sImag", name[i]);
1201 }
1202 switch (typeMode) {
1203 case FIND_ANY_TYPE:
1204 case FIND_NUMERIC_TYPE:
1205 case FIND_INTEGER_TYPE:
1206 case FIND_FLOATING_TYPE:
1207 realNames = SDDS_MatchColumns(SDDSin, &realName1, SDDS_MATCH_STRING, typeMode, realPattern, SDDS_0_PREVIOUS | SDDS_OR);
1208 imagNames = SDDS_MatchColumns(SDDSin, &imagName1, SDDS_MATCH_STRING, typeMode, imagPattern, SDDS_0_PREVIOUS | SDDS_OR);
1209 break;
1210 case FIND_SPECIFIED_TYPE:
1211 if (!SDDS_VALID_TYPE(typeValue))
1212 SDDS_Bomb("invalid type value in expandColumnPairNames");
1213 realNames = SDDS_MatchColumns(SDDSin, &realName1, SDDS_MATCH_STRING, typeMode, typeValue, realPattern, SDDS_0_PREVIOUS | SDDS_OR);
1214 imagNames = SDDS_MatchColumns(SDDSin, &imagName1, SDDS_MATCH_STRING, typeMode, typeValue, imagPattern, SDDS_0_PREVIOUS | SDDS_OR);
1215 break;
1216 default:
1217 SDDS_Bomb("invalid typeMode in expandColumnPairNames");
1218 exit(EXIT_FAILURE);
1219 break;
1220 }
1221 if (realNames == 0)
1222 continue;
1223 if (realNames == -1 || imagNames == -1) {
1224 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
1225 SDDS_Bomb("unable to perform column name match in expandColumnPairNames");
1226 }
1227 if (realNames != imagNames)
1228 SDDS_Bomb("found different number of real and imaginary columns");
1229 if (excludeNames) {
1230 for (j = 0; j < excludeNames; j++)
1231 for (k = 0; k < realNames; k++)
1232 if (wild_match(realName1[k], excludeName[j])) {
1233 free(realName1[k]);
1234 free(imagName1[k]);
1235 imagName1[k] = realName1[k] = NULL;
1236 }
1237 }
1238 moveToStringArrayComplex(&realName2, &imagName2, &names2, realName1, imagName1, realNames);
1239 free(realName1);
1240 free(imagName1);
1241 }
1242 }
1243 free(realPattern);
1244 free(imagPattern);
1245 if (names2 == 0)
1246 return 0;
1247 *realName = realName2;
1248 *imagName = imagName2;
1249 return names2;
1250}
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
void * SDDS_Malloc(size_t size)
Allocates memory of a specified size.
Definition SDDS_utils.c:639
int32_t SDDS_MatchColumns(SDDS_DATASET *SDDS_dataset, char ***nameReturn, int32_t matchMode, int32_t typeMode,...)
Matches and retrieves column names from an SDDS dataset based on specified criteria.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
#define SDDS_VALID_TYPE(type)
Validates whether the given type identifier is within the defined range of SDDS types.
Definition SDDStypes.h:149
int wild_match(char *string, char *template)
Determine whether one string is a wildcard match for another.
Definition wild_match.c:49

◆ greatestProductOfSmallPrimes()

int64_t greatestProductOfSmallPrimes ( int64_t rows)

Definition at line 277 of file SDDSutils.c.

279{
280 int64_t bestResult = 0, result, nPrimes;
281 static int64_t prime[MAXPRIMES] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
282 71, 73, 79, 83, 89, 97};
283
284 for (nPrimes = 1; nPrimes <= MAXPRIMES; nPrimes++) {
285 if ((result = greatestProductOfSmallPrimes1(rows, prime, nPrimes)) > bestResult &&
286 result <= rows)
287 bestResult = result;
288 }
289 if (bestResult == 0)
290 SDDS_Bomb("couldn't find acceptable number of rows for truncation/padding");
291 return bestResult;
292}

◆ main()

int main ( int argc,
char ** argv )

Definition at line 235 of file sddsfft.c.

235 {
236 int iArg;
237 char *freqUnits;
238 char *indepQuantity, **depenQuantity, **exclude, **realQuan = NULL, **imagQuan = NULL;
239 long depenQuantities, excludes;
240 char *input, *output;
241 long i, readCode, noWarnings, complexInput, inverse, spectrumFoldParExist = 0;
242 int64_t rows, rowsToUse, sampleInterval;
243 int32_t spectrumFolded = 0, page = 0;
244 unsigned long flags, pipeFlags, complexInputFlags = 0, fullOutputFlags = 0, majorOrderFlag;
245 long windowType = -1;
246 SCANNED_ARG *scanned;
247 SDDS_DATASET SDDSin, SDDSout;
248 double *tdata, rintegCutOffFreq, unwrapLimit = 0;
249 long padFactor, correctWindowEffects = 0;
250 short columnMajorOrder = -1;
251
253 argc = scanargs(&scanned, argc, argv);
254 if (argc < 3 || argc > (3 + N_OPTIONS)) {
255 fprintf(stderr, "%s%s", USAGE1, USAGE2);
256 exit(EXIT_FAILURE);
257 /* bomb(NULL, USAGE); */
258 }
259 rintegCutOffFreq = 0;
260 output = input = NULL;
261 flags = pipeFlags = excludes = complexInput = inverse = 0;
262 sampleInterval = 1;
263 indepQuantity = NULL;
264 depenQuantity = exclude = NULL;
265 depenQuantities = 0;
266 noWarnings = 0;
267 padFactor = 0;
268 for (iArg = 1; iArg < argc; iArg++) {
269 if (scanned[iArg].arg_type == OPTION) {
270 /* process options here */
271 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
272 case SET_NORMALIZE:
273 flags |= FL_NORMALIZE;
274 break;
275 case SET_WINDOW:
276 if (scanned[iArg].n_items != 1) {
277 if ((i = match_string(scanned[iArg].list[1], window_type, N_WINDOW_TYPES, 0)) < 0)
278 SDDS_Bomb("unknown window type");
279 windowType = i;
280 if (scanned[iArg].n_items > 2) {
281 if (strncmp(scanned[iArg].list[2], "correct", strlen(scanned[iArg].list[2])) == 0)
282 correctWindowEffects = 1;
283 else
284 SDDS_Bomb("invalid -window syntax");
285 }
286 } else
287 windowType = 0;
288 break;
289 case SET_PADWITHZEROES:
290 flags |= FL_PADWITHZEROES;
291 if (scanned[iArg].n_items != 1) {
292 if (scanned[iArg].n_items != 2 || sscanf(scanned[iArg].list[1], "%ld", &padFactor) != 1 || padFactor < 1)
293 SDDS_Bomb("invalid -padwithzeroes syntax");
294 }
295 break;
296 case SET_TRUNCATE:
297 flags |= FL_TRUNCATE;
298 break;
299 case SET_SUPPRESSAVERAGE:
300 flags |= FL_SUPPRESSAVERAGE;
301 break;
302 case SET_SAMPLEINTERVAL:
303 if (scanned[iArg].n_items != 2 || sscanf(scanned[iArg].list[1], "%" SCNd64, &sampleInterval) != 1 || sampleInterval <= 0)
304 SDDS_Bomb("invalid -sampleinterval syntax");
305 break;
306 case SET_COLUMNS:
307 if (indepQuantity)
308 SDDS_Bomb("only one -columns option may be given");
309 if (scanned[iArg].n_items < 2)
310 SDDS_Bomb("invalid -columns syntax");
311 indepQuantity = scanned[iArg].list[1];
312 if (scanned[iArg].n_items >= 2) {
313 depenQuantity = tmalloc(sizeof(*depenQuantity) * (depenQuantities = scanned[iArg].n_items - 2));
314 for (i = 0; i < depenQuantities; i++)
315 depenQuantity[i] = scanned[iArg].list[i + 2];
316 }
317 break;
318 case SET_FULLOUTPUT:
319 flags |= FL_FULLOUTPUT;
320 if (scanned[iArg].n_items >= 2) {
321 scanned[iArg].n_items--;
322 if (!scanItemList(&fullOutputFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0, "folded", -1, NULL, 0, FL_FULLOUTPUT_FOLDED, "unfolded", -1, NULL, 0, FL_FULLOUTPUT_UNFOLDED, "unwrapLimit", SDDS_DOUBLE, &unwrapLimit, 0, FL_UNWRAP_PHASE, NULL))
323 SDDS_Bomb("Invalid -fullOutput syntax");
324 scanned[iArg].n_items++;
325 if (fullOutputFlags & FL_FULLOUTPUT_UNFOLDED)
326 flags |= FL_FULLOUTPUT_UNFOLDED;
327 else
328 flags |= FL_FULLOUTPUT_FOLDED;
329 if (fullOutputFlags & FL_UNWRAP_PHASE)
330 flags |= FL_UNWRAP_PHASE;
331 }
332 break;
333 case SET_PIPE:
334 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
335 SDDS_Bomb("invalid -pipe syntax");
336 break;
337 case SET_PSDOUTPUT:
338 if (scanned[iArg].n_items -= 1) {
339 unsigned long tmpFlags;
340 if (strchr(scanned[iArg].list[1], '=') <= 0) {
341 if (!scanItemList(&tmpFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0, "integrated", -1, NULL, 0, FL_PSDINTEGOUTPUT, "rintegrated", -1, NULL, 0, FL_PSDRINTEGOUTPUT, "plain", -1, NULL, 0, FL_PSDOUTPUT, NULL))
342 SDDS_Bomb("invalid -psdOutput syntax");
343 } else {
344 if (!scanItemList(&tmpFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0, "integrated", -1, NULL, 0, FL_PSDINTEGOUTPUT, "rintegrated", SDDS_DOUBLE, &rintegCutOffFreq, 0, FL_PSDRINTEGOUTPUT, "plain", -1, NULL, 0, FL_PSDOUTPUT, NULL))
345 SDDS_Bomb("invalid -psdOutput syntax");
346 }
347 flags |= tmpFlags;
348 } else
349 flags |= FL_PSDOUTPUT;
350 if (flags & FL_PSDINTEGOUTPUT && flags & FL_PSDRINTEGOUTPUT)
351 SDDS_Bomb("invalid -psdOutput syntax: give only one of integrated or rintegrated");
352 break;
353 case SET_EXCLUDE:
354 if (scanned[iArg].n_items < 2)
355 SDDS_Bomb("invalid -exclude syntax");
356 moveToStringArray(&exclude, &excludes, scanned[iArg].list + 1, scanned[iArg].n_items - 1);
357 break;
358 case SET_NOWARNINGS:
359 noWarnings = 1;
360 break;
361 case SET_COMPLEXINPUT:
362 complexInput = 1;
363 if (scanned[iArg].n_items == 2) {
364 scanned[iArg].n_items--;
365 if (!scanItemList(&complexInputFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0, "folded", -1, NULL, 0, FL_COMPLEXINPUT_FOLDED, "unfolded", -1, NULL, 0, FL_COMPLEXINPUT_UNFOLDED, NULL))
366 SDDS_Bomb("Invalid -complexInput syntax");
367 scanned[iArg].n_items++;
368 }
369 break;
370 case SET_INVERSE:
371 inverse = 1;
372 break;
373 case SET_MAJOR_ORDER:
374 majorOrderFlag = 0;
375 scanned[iArg].n_items--;
376 if (scanned[iArg].n_items > 0 && (!scanItemList(&majorOrderFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0, "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER, "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
377 SDDS_Bomb("invalid -majorOrder syntax/values");
378 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
379 columnMajorOrder = 1;
380 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
381 columnMajorOrder = 0;
382 break;
383 default:
384 fprintf(stderr, "error: unknown/ambiguous option: %s\n", scanned[iArg].list[0]);
385 exit(EXIT_FAILURE);
386 break;
387 }
388 } else {
389 if (!input)
390 input = scanned[iArg].list[0];
391 else if (!output)
392 output = scanned[iArg].list[0];
393 else
394 SDDS_Bomb("too many filenames seen");
395 }
396 }
397 if (!complexInput) {
398 if (!noWarnings && inverse)
399 fprintf(stderr, "Warning: the inverse option is ignored since it only works with -complexInput.\n");
400 inverse = 0;
401 }
402 if (!noWarnings && inverse && flags & FL_FULLOUTPUT_FOLDED)
403 fprintf(stderr, "Warning: the -inverse -fullOutput=folded will be changed to -inverse -fullOutput=unfolded.\n");
404
405 processFilenames("sddsfft", &input, &output, pipeFlags, 0, NULL);
406
407 if (!indepQuantity)
408 SDDS_Bomb("Supply the independent quantity name with the -columns option.");
409
410 if (flags & FL_TRUNCATE && flags & FL_PADWITHZEROES)
411 SDDS_Bomb("Specify only one of -padwithzeroes and -truncate.");
412
413 if (!SDDS_InitializeInput(&SDDSin, input))
414 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
415
416 if (SDDS_CheckColumn(&SDDSin, indepQuantity, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OKAY)
417 exit(EXIT_FAILURE);
418
419 excludes = appendToStringArray(&exclude, excludes, indepQuantity);
420 if (!depenQuantities)
421 depenQuantities = appendToStringArray(&depenQuantity, depenQuantities, "*");
422
423 if (!complexInput) {
424 if ((depenQuantities = expandColumnPairNames(&SDDSin, &depenQuantity, NULL, depenQuantities, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
425 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
426 SDDS_Bomb("No quantities selected to FFT.");
427 }
428 } else {
429 if ((depenQuantities = expandComplexColumnPairNames(&SDDSin, depenQuantity, &realQuan, &imagQuan, depenQuantities, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
430 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
431 SDDS_Bomb("No quantities selected to FFT.");
432 }
433 }
434
435#if 0
436 fprintf(stderr, "%ld dependent quantities:\n", depenQuantities);
437 for (i = 0; i < depenQuantities; i++)
438 fprintf(stderr, " %s\n", depenQuantity[i]);
439#endif
440
441 if (!(freqUnits = makeFrequencyUnits(&SDDSin, indepQuantity)) ||
442 !SDDS_InitializeOutput(&SDDSout, SDDS_BINARY, 0, NULL, "sddsfft output", output) ||
443 !create_fft_frequency_column(&SDDSout, &SDDSin, indepQuantity, freqUnits, inverse) ||
444 SDDS_DefineParameter(&SDDSout, "fftFrequencies", NULL, NULL, NULL, NULL, SDDS_LONG, NULL) < 0 ||
445 SDDS_DefineParameter(&SDDSout, "fftFrequencySpacing", "$gD$rf", freqUnits, NULL, NULL, SDDS_DOUBLE, NULL) < 0)
446 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
447 if (columnMajorOrder != -1)
448 SDDSout.layout.data_mode.column_major = columnMajorOrder;
449 else
450 SDDSout.layout.data_mode.column_major = SDDSin.layout.data_mode.column_major;
451
452 if (flags & FL_FULLOUTPUT && SDDS_DefineParameter(&SDDSout, "SpectrumFolded", NULL, NULL, NULL, NULL, SDDS_LONG, NULL) < 0)
453 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
454 if (complexInput) {
455 if (!complexInputFlags) {
456 if (SDDS_CheckParameter(&SDDSin, "SpectrumFolded", NULL, SDDS_LONG, NULL) == SDDS_CHECK_OK)
457 spectrumFoldParExist = 1;
458 } else if (complexInputFlags & FL_COMPLEXINPUT_UNFOLDED)
459 flags |= FL_COMPLEXINPUT_UNFOLDED;
460 else
461 flags |= FL_COMPLEXINPUT_FOLDED;
462 }
463 for (i = 0; i < depenQuantities; i++) {
464 if (!complexInput)
465 create_fft_columns(&SDDSout, &SDDSin, depenQuantity[i], indepQuantity, freqUnits,
466 flags & FL_FULLOUTPUT,
467 flags & (FL_PSDOUTPUT + FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT),
468 0, inverse, flags & FL_UNWRAP_PHASE);
469 else
470 create_fft_columns(&SDDSout, &SDDSin, realQuan[i], indepQuantity, freqUnits,
471 flags & FL_FULLOUTPUT,
472 flags & (FL_PSDOUTPUT + FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT),
473 1, inverse, flags & FL_UNWRAP_PHASE);
474 }
475
476 if (!SDDS_TransferAllParameterDefinitions(&SDDSout, &SDDSin, SDDS_TRANSFER_KEEPOLD) ||
477 !SDDS_WriteLayout(&SDDSout))
478 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
479
480 while ((readCode = SDDS_ReadPage(&SDDSin)) > 0) {
481 page++;
482 if ((rows = SDDS_CountRowsOfInterest(&SDDSin)) < 0)
483 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
484 if (page == 1 && spectrumFoldParExist) {
485 if (!SDDS_GetParameterAsLong(&SDDSin, "SpectrumFolded", &spectrumFolded))
486 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
487 if (spectrumFolded)
488 flags |= FL_COMPLEXINPUT_FOLDED;
489 else
490 flags |= FL_COMPLEXINPUT_UNFOLDED;
491 }
492 if (rows) {
493 int64_t primeRows, pow2Rows;
494 rowsToUse = rows;
495 primeRows = greatestProductOfSmallPrimes(rows);
496 if (rows != primeRows || padFactor) {
497 if (flags & FL_PADWITHZEROES) {
498 pow2Rows = ipow(2., ((int64_t)(log((double)rows) / log(2.0F))) + (padFactor ? padFactor : 1.0));
499 if ((primeRows = greatestProductOfSmallPrimes(pow2Rows)) > rows)
500 rowsToUse = primeRows;
501 else
502 rowsToUse = pow2Rows;
503 } else if (flags & FL_TRUNCATE)
504 rowsToUse = greatestProductOfSmallPrimes(rows);
505 else if (largest_prime_factor(rows) > 1000 && !noWarnings)
506 fputs("Warning: number of points has large prime factors.\nThis could take a very long time.\nConsider using the -truncate option.\n", stderr);
507 }
508 if (!SDDS_StartPage(&SDDSout, 2 * rowsToUse + 2) || !SDDS_CopyParameters(&SDDSout, &SDDSin))
509 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
510 if (!(tdata = SDDS_GetColumnInDoubles(&SDDSin, indepQuantity)))
511 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
512 for (i = 0; i < depenQuantities; i++)
513 if (!process_data(&SDDSout, &SDDSin, tdata, rows, rowsToUse,
514 complexInput ? realQuan[i] : depenQuantity[i],
515 complexInput ? imagQuan[i] : NULL,
516 flags | (i == 0 ? FL_MAKEFREQDATA : 0),
517 windowType, sampleInterval, correctWindowEffects, inverse,
518 rintegCutOffFreq, unwrapLimit)) {
519 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
520 exit(EXIT_FAILURE);
521 }
522 free(tdata);
523 } else {
524 if (!SDDS_StartPage(&SDDSout, 0) || !SDDS_CopyParameters(&SDDSout, &SDDSin))
525 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
526 }
527 if (!SDDS_WritePage(&SDDSout))
528 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
529 }
530
531 if (!SDDS_Terminate(&SDDSin)) {
532 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
533 exit(EXIT_FAILURE);
534 }
535 if (!SDDS_Terminate(&SDDSout)) {
536 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
537 exit(EXIT_FAILURE);
538 }
539
540 return EXIT_SUCCESS;
541}
int32_t SDDS_CopyParameters(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:286
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t * SDDS_GetParameterAsLong(SDDS_DATASET *SDDS_dataset, char *parameter_name, int32_t *memory)
Retrieves the value of a specified parameter as a 32-bit integer from the current data table of a dat...
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_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
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_DefineParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, char *fixed_value)
Defines a data parameter with a fixed string value.
int32_t SDDS_TransferAllParameterDefinitions(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, uint32_t mode)
Transfers all parameter definitions 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
int32_t SDDS_CheckParameter(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a parameter exists in the SDDS dataset with the specified name, units, and type.
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#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
int64_t largest_prime_factor(int64_t number)
Find the largest prime factor of a number.
Definition factorize.c:83
double ipow(const double x, const int64_t p)
Compute x raised to the power p (x^p).
Definition ipow.c:33
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
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.

◆ makeFrequencyUnits()

char * makeFrequencyUnits ( SDDS_DATASET * SDDSin,
char * indepName )

Definition at line 235 of file SDDSutils.c.

235 {
236 char *timeUnits;
237 char *units;
238 long reciprocal = 0, end;
239
240 if (SDDS_GetColumnInformation(SDDSin, "units", &timeUnits, SDDS_GET_BY_NAME, indepName) != SDDS_STRING)
241 return 0;
242 if (timeUnits) {
243 while (1) {
244 end = strlen(timeUnits) - 1;
245 if (timeUnits[0] == '(' && timeUnits[end] == ')') {
246 timeUnits[end] = 0;
247 strslide(timeUnits, 1);
248 } else if (timeUnits[0] == '1' && timeUnits[1] == '/' && timeUnits[2] == '(' && timeUnits[end] == ')') {
249 timeUnits[end] = 0;
250 strslide(timeUnits, 3);
251 reciprocal = !reciprocal;
252 } else
253 break;
254 }
255 }
256 if (!timeUnits || SDDS_StringIsBlank(timeUnits)) {
257 units = tmalloc(sizeof(*units) * 1);
258 units[0] = 0;
259 return units;
260 }
261
262 if (reciprocal) {
263 if (!SDDS_CopyString(&units, timeUnits))
264 return NULL;
265 return units;
266 }
267
268 units = tmalloc(sizeof(*units) * (strlen(timeUnits) + 5));
269 if (strchr(timeUnits, ' '))
270 sprintf(units, "1/(%s)", timeUnits);
271 else
272 sprintf(units, "1/%s", timeUnits);
273 return units;
274}
char * strslide(char *s, long distance)
Slides character data within a string by a specified distance.
Definition strslide.c:32

◆ moveToStringArrayComplex()

void moveToStringArrayComplex ( char *** targetReal,
char *** targetImag,
long * targets,
char ** sourceReal,
char ** sourceImag,
long sources )

Definition at line 1252 of file sddsfft.c.

1252 {
1253 long i, j;
1254 if (!sources)
1255 return;
1256 if (!(*targetReal = SDDS_Realloc(*targetReal, sizeof(**targetReal) * (*targets + sources))) ||
1257 !(*targetImag = SDDS_Realloc(*targetImag, sizeof(**targetImag) * (*targets + sources))))
1258 SDDS_Bomb("memory allocation failure");
1259 for (i = 0; i < sources; i++) {
1260 if (sourceReal[i] == NULL || sourceImag[i] == NULL)
1261 continue;
1262 for (j = 0; j < *targets; j++)
1263 if (strcmp(sourceReal[i], (*targetReal)[j]) == 0)
1264 break;
1265 if (j == *targets) {
1266 (*targetReal)[j] = sourceReal[i];
1267 (*targetImag)[j] = sourceImag[i];
1268 *targets += 1;
1269 }
1270 }
1271}
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677

◆ process_data()

long process_data ( SDDS_DATASET * SDDSout,
SDDS_DATASET * SDDSin,
double * tdata,
int64_t rows,
int64_t rowsToUse,
char * depenQuantity,
char * depenQuantity2,
unsigned long flags,
long windowType,
int64_t sampleInterval,
long correctWindowEffects,
long inverse,
double rintegCutOffFreq,
double unwrapLimit )

Definition at line 545 of file sddsfft.c.

547 {
548 long offset, index, unfold = 0;
549 int64_t n_freq, i, fftrows = 0;
550 double r, r1, r2, length, factor, df, min, max, delta;
551 double *real, *imag, *magData, *arg = NULL, *real_imag, *data, *psd = NULL, *psdInteg = NULL, *psdIntegPower = NULL, *unwrapArg = NULL, phase_correction = 0;
552 double dtf_real, dtf_imag, t0;
553 char s[256];
554 double *fdata, *imagData = NULL;
555 double *tDataStore = NULL;
556 double windowCorrectionFactor = 0;
557
558 if (!(data = SDDS_GetColumnInDoubles(SDDSin, depenQuantity)))
559 return 0;
560 if (imagQuantity && !(imagData = SDDS_GetColumnInDoubles(SDDSin, imagQuantity)))
561 return 0;
562 if (flags & FL_SUPPRESSAVERAGE) {
563 compute_average(&r, data, rows);
564 for (i = 0; i < rows; i++)
565 data[i] -= r;
566 if (imagData) {
567 compute_average(&r, imagData, rows);
568 for (i = 0; i < rows; i++)
569 imagData[i] -= r;
570 }
571 }
572 if (rows < rowsToUse) {
573 /* pad with zeroes */
574 tDataStore = tmalloc(sizeof(*tDataStore) * rowsToUse);
575 memcpy((char *)tDataStore, (char *)tdata, rows * sizeof(*tdata));
576 if (!(data = SDDS_Realloc(data, sizeof(*data) * rowsToUse)))
577 SDDS_Bomb("memory allocation failure");
578 if (imagData && !(imagData = SDDS_Realloc(imagData, sizeof(*imagData) * rowsToUse)))
579 length = ((double)rows) * (tdata[rows - 1] - tdata[0]) / ((double)rows - 1.0);
580 else
581 length = tdata[rows - 1] - tdata[0];
582 for (i = rows; i < rowsToUse; i++) {
583 tDataStore[i] = tDataStore[i - 1] + length / ((double)rows - 1);
584 data[i] = 0;
585 }
586 if (imagData)
587 for (i = rows; i < rowsToUse; i++)
588 imagData[i] = 0;
589 tdata = tDataStore;
590 }
591 rows = rowsToUse; /* results in truncation if rows>rowsToUse */
592 windowCorrectionFactor = 0;
593 switch (windowType) {
594 case WINDOW_HANNING:
595 r = PIx2 / (rows - 1);
596 for (i = 0; i < rows; i++) {
597 factor = (1 - cos(i * r)) / 2;
598 data[i] *= factor;
599 windowCorrectionFactor += sqr(factor);
600 if (imagData)
601 imagData[i] *= factor;
602 }
603 break;
604 case WINDOW_HAMMING:
605 r = PIx2 / (rows - 1);
606 for (i = 0; i < rows; i++) {
607 factor = 0.54 - 0.46 * cos(i * r);
608 data[i] *= factor;
609 windowCorrectionFactor += sqr(factor);
610 if (imagData)
611 imagData[i] *= factor;
612 }
613 if (imagData)
614 for (i = 0; i < rows; i++)
615 imagData[i] *= (1 - cos(i * r)) / 2;
616 break;
617 case WINDOW_WELCH:
618 r1 = (rows - 1) / 2.0;
619 r2 = sqr((rows + 1) / 2.0);
620 for (i = 0; i < rows; i++) {
621 factor = 1 - sqr(i - r1) / r2;
622 data[i] *= factor;
623 windowCorrectionFactor += sqr(factor);
624 if (imagData)
625 imagData[i] *= factor;
626 }
627 break;
628 case WINDOW_PARZEN:
629 r = (rows - 1) / 2.0;
630 for (i = 0; i < rows; i++) {
631 factor = 1 - FABS((i - r) / r);
632 data[i] *= factor;
633 windowCorrectionFactor += sqr(factor);
634 if (imagData)
635 imagData[i] *= factor;
636 }
637 break;
638 case WINDOW_FLATTOP:
639 for (i = 0; i < rows; i++) {
640 r = i * PIx2 / (rows - 1);
641 factor = 1 - 1.93 * cos(r) + 1.29 * cos(2 * r) - 0.388 * cos(3 * r) + 0.032 * cos(4 * r);
642 data[i] *= factor;
643 windowCorrectionFactor += sqr(factor);
644 if (imagData)
645 imagData[i] *= factor;
646 }
647 break;
648 case WINDOW_GAUSSIAN:
649 for (i = 0; i < rows; i++) {
650 r = sqr((i - (rows - 1) / 2.) / (0.4 * (rows - 1) / 2.)) / 2;
651 factor = exp(-r);
652 data[i] *= factor;
653 windowCorrectionFactor += sqr(factor);
654 if (imagData)
655 imagData[i] *= factor;
656 }
657 break;
658 case WINDOW_NONE:
659 default:
660 windowCorrectionFactor = 1;
661 break;
662 }
663
664 if (correctWindowEffects) {
665 /* Add correction factor to make the integrated PSD come out right. */
666 windowCorrectionFactor = 1 / sqrt(windowCorrectionFactor / rows);
667 for (i = 0; i < rows; i++)
668 data[i] *= windowCorrectionFactor;
669 if (imagData)
670 imagData[i] *= windowCorrectionFactor;
671 }
672 if (imagData && flags & FL_COMPLEXINPUT_FOLDED) {
673 double min, max, max1;
674 data = SDDS_Realloc(data, sizeof(*data) * rows * 2);
675 imagData = SDDS_Realloc(imagData, sizeof(*data) * rows * 2);
676 find_min_max(&min, &max, data, rows);
677 if (fabs(min) > fabs(max))
678 max1 = fabs(min);
679 else
680 max1 = fabs(max);
681 find_min_max(&min, &max, imagData, rows);
682 if (fabs(min) > max1)
683 max1 = fabs(min);
684 if (fabs(max) > max1)
685 max1 = fabs(max);
686 if (fabs(imagData[rows - 1]) / max1 < 1.0e-15) {
687 fftrows = 2 * (rows - 1);
688 for (i = 1; i < rows - 1; i++) {
689 data[i] = data[i] / 2.0;
690 imagData[i] = imagData[i] / 2.0;
691 }
692 for (i = 1; i < rows - 1; i++) {
693 data[rows - 1 + i] = data[rows - 1 - i];
694 imagData[rows - 1 + i] = -imagData[rows - 1 - i];
695 }
696 length = (tdata[rows - 1] - tdata[0]) * 2.0;
697 } else {
698 fftrows = 2 * (rows - 1) + 1;
699 for (i = 1; i < rows; i++) {
700 data[i] = data[i] / 2.0;
701 imagData[i] = imagData[i] / 2.0;
702 }
703 for (i = 0; i < rows - 1; i++) {
704 data[rows + i] = data[rows - 1 - i];
705 imagData[rows + i] = -imagData[rows - 1 - i];
706 }
707 length = ((double)fftrows) * (tdata[rows - 1] - tdata[0]) / ((double)fftrows - 1.0) * 2;
708 }
709 } else {
710 fftrows = rows;
711 length = ((double)rows) * (tdata[rows - 1] - tdata[0]) / ((double)rows - 1.0);
712 }
713 /* compute FFT */
714
715 real_imag = tmalloc(sizeof(double) * (2 * fftrows + 2));
716 for (i = 0; i < fftrows; i++) {
717 real_imag[2 * i] = data[i];
718 if (imagData)
719 real_imag[2 * i + 1] = imagData[i];
720 else
721 real_imag[2 * i + 1] = 0;
722 }
723 if (!inverse) {
724 complexFFT(real_imag, fftrows, 0);
725 if (flags & FL_FULLOUTPUT_UNFOLDED) {
726 n_freq = fftrows;
727 unfold = 1;
728 } else if (flags & FL_FULLOUTPUT_FOLDED)
729 n_freq = fftrows / 2 + 1;
730 else if (!imagData)
731 n_freq = fftrows / 2 + 1;
732 else
733 n_freq = fftrows + 1;
734 } else {
735 complexFFT(real_imag, fftrows, INVERSE_FFT);
736 n_freq = fftrows;
737 }
738 /* calculate factor for converting k to f or omega */
739 /* length is assumed the length of period, not the total length of the data file */
740
741 /* length = ((double)rows)*(tdata[rows-1]-tdata[0])/((double)rows-1.0); */
742 t0 = tdata[0];
743 df = factor = 1.0 / length;
744
745 /* convert into amplitudes and frequencies, adding phase factor for t[0]!=0 */
746 real = tmalloc(sizeof(double) * n_freq);
747 imag = tmalloc(sizeof(double) * n_freq);
748 fdata = tmalloc(sizeof(double) * n_freq);
749 magData = tmalloc(sizeof(double) * n_freq);
750 if (flags & FL_PSDOUTPUT || flags & (FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT)) {
751 psd = tmalloc(sizeof(*psd) * n_freq);
752 if (flags & (FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT)) {
753 psdInteg = tmalloc(sizeof(*psdInteg) * n_freq);
754 psdIntegPower = tmalloc(sizeof(*psdIntegPower) * n_freq);
755 }
756 }
757
758 for (i = 0; i < n_freq; i++) {
759 fdata[i] = i * df;
760 dtf_real = cos(-2 * PI * fdata[i] * t0);
761 dtf_imag = sin(-2 * PI * fdata[i] * t0);
762 if (psd)
763 psd[i] = (sqr(real_imag[2 * i]) + sqr(real_imag[2 * i + 1])) / df;
764 if (!imagData && i != 0 && !(i == (n_freq - 1) && rows % 2 == 0)) {
765 /* This is not the DC or Nyquist term, so
766 multiply by 2 to account for amplitude in
767 negative frequencies
768 */
769 if (!unfold) {
770 real_imag[2 * i] *= 2;
771 real_imag[2 * i + 1] *= 2;
772 }
773 if (psd)
774 psd[i] *= 2; /* 2 really is what I want--not 4 */
775 }
776 real[i] = real_imag[2 * i] * dtf_real - real_imag[2 * i + 1] * dtf_imag;
777 imag[i] = real_imag[2 * i + 1] * dtf_real + real_imag[2 * i] * dtf_imag;
778 magData[i] = sqrt(sqr(real[i]) + sqr(imag[i]));
779 }
780
781 if (psdInteg) {
782 if (flags & FL_PSDINTEGOUTPUT) {
783 psdIntegPower[0] = 0;
784 for (i = 1; i < n_freq; i++)
785 psdIntegPower[i] = psdIntegPower[i - 1] + (psd[i - 1] + psd[i]) * df / 2.;
786 for (i = 0; i < n_freq; i++)
787 psdInteg[i] = sqrt(psdIntegPower[i]);
788 } else {
789 psdIntegPower[n_freq - 1] = 0;
790 for (i = n_freq - 2; i >= 0; i--) {
791 if (rintegCutOffFreq == 0 || fdata[i] <= rintegCutOffFreq)
792 psdIntegPower[i] = psdIntegPower[i + 1] + (psd[i + 1] + psd[i]) * df / 2.;
793 }
794 for (i = 0; i < n_freq; i++)
795 psdInteg[i] = sqrt(psdIntegPower[i]);
796 }
797 }
798
799 if (flags & FL_FULLOUTPUT) {
800 arg = tmalloc(sizeof(*arg) * n_freq);
801 for (i = 0; i < n_freq; i++) {
802 if (real[i] || imag[i])
803 arg[i] = 180.0 / PI * atan2(imag[i], real[i]);
804 else
805 arg[i] = 0;
806 }
807 }
808 if (flags & FL_UNWRAP_PHASE) {
809 find_min_max(&min, &max, magData, n_freq);
810 unwrapArg = tmalloc(sizeof(*unwrapArg) * n_freq);
811 phase_correction = 0;
812 for (i = 0; i < n_freq; i++) {
813 if (i && magData[i] / max > unwrapLimit) {
814 delta = arg[i] - arg[i - 1];
815 if (delta < -180.0)
816 phase_correction += 360.0;
817 else if (delta > 180.0)
818 phase_correction -= 360.0;
819 }
820 unwrapArg[i] = arg[i] + phase_correction;
821 }
822 }
823
824 if (flags & FL_NORMALIZE) {
825 factor = -DBL_MAX;
826 for (i = 0; i < n_freq; i++)
827 if (magData[i] > factor)
828 factor = magData[i];
829 if (factor != -DBL_MAX)
830 for (i = 0; i < n_freq; i++) {
831 real[i] /= factor;
832 imag[i] /= factor;
833 magData[i] /= factor;
834 }
835 }
836 if (!inverse)
837 sprintf(s, "FFT%s", depenQuantity + (imagData ? 4 : 0));
838 else {
839 if (strncmp(depenQuantity, "FFT", 3) == 0)
840 sprintf(s, "%s", depenQuantity + 3);
841 else if (strncmp(depenQuantity, "RealFFT", 7) == 0)
842 sprintf(s, "%s", depenQuantity + 7);
843 else
844 sprintf(s, "%s", depenQuantity);
845 }
846
847 if ((index = SDDS_GetColumnIndex(SDDSout, s)) < 0)
848 return 0;
849
850 if (flags & FL_SUPPRESSAVERAGE) {
851 n_freq -= 1;
852 offset = 1;
853 } else
854 offset = 0;
855
856 if ((flags & FL_MAKEFREQDATA &&
857 !SDDS_SetColumn(SDDSout, SDDS_SET_BY_INDEX, fdata + offset, n_freq, 0)) ||
858 !SDDS_SetColumn(SDDSout, SDDS_SET_BY_INDEX, magData + offset, n_freq, index + fftOffset) ||
859 (flags & FL_FULLOUTPUT &&
860 (!SDDS_SetColumn(SDDSout, SDDS_SET_BY_INDEX, real + offset, n_freq, index + realOffset) ||
861 !SDDS_SetColumn(SDDSout, SDDS_SET_BY_INDEX, imag + offset, n_freq, index + imagOffset) ||
862 !SDDS_SetColumn(SDDSout, SDDS_SET_BY_INDEX, arg + offset, n_freq, index + argOffset))) ||
863 (flags & FL_PSDOUTPUT &&
864 !SDDS_SetColumn(SDDSout, SDDS_SET_BY_INDEX, psd + offset, n_freq, index + psdOffset)) ||
865 (flags & (FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT) && (!SDDS_SetColumn(SDDSout, SDDS_SET_BY_INDEX, psdInteg + offset, n_freq, index + psdIntOffset) ||
866 !SDDS_SetColumn(SDDSout, SDDS_SET_BY_INDEX, psdIntegPower + offset, n_freq, index + psdIntPowerOffset))) ||
867 (flags & FL_UNWRAP_PHASE && !SDDS_SetColumn(SDDSout, SDDS_SET_BY_INDEX, unwrapArg + offset, n_freq, index + unwrappedArgOffset)))
868 return 0;
869 if (sampleInterval > 0) {
870 int32_t *sample_row_flag;
871 sample_row_flag = calloc(sizeof(*sample_row_flag), n_freq);
872 for (i = 0; i < n_freq; i += sampleInterval)
873 sample_row_flag[i] = 1;
874 if (!SDDS_AssertRowFlags(SDDSout, SDDS_FLAG_ARRAY, sample_row_flag, n_freq)) {
875 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
876 return 0;
877 }
878 free(sample_row_flag);
879 }
880 if (!SDDS_SetParameters(SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, "fftFrequencies", n_freq, "fftFrequencySpacing", df, NULL))
881 return 0;
882 if (flags & FL_FULLOUTPUT && !SDDS_SetParameters(SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, "SpectrumFolded", flags & FL_FULLOUTPUT_UNFOLDED ? 0 : 1, NULL))
883 return 0;
884 free(data);
885 free(magData);
886 if (imagData)
887 free(imagData);
888 if (tDataStore)
889 free(tDataStore);
890 if (arg)
891 free(arg);
892 free(real_imag);
893 free(real);
894 free(imag);
895 free(fdata);
896 if (psd)
897 free(psd);
898 if (psdInteg)
899 free(psdInteg);
900 if (psdIntegPower)
901 free(psdIntegPower);
902 if (unwrapArg)
903 free(unwrapArg);
904 return 1;
905}
int32_t SDDS_SetParameters(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
int32_t SDDS_SetColumn(SDDS_DATASET *SDDS_dataset, int32_t mode, void *data, int64_t rows,...)
Sets the values for one data column in the current data table of an SDDS dataset.
int32_t SDDS_AssertRowFlags(SDDS_DATASET *SDDS_dataset, uint32_t mode,...)
Sets acceptance flags for rows based on specified criteria.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
int find_min_max(double *min, double *max, double *list, int64_t n)
Finds the minimum and maximum values in a list of doubles.
Definition findMinMax.c:33
long compute_average(double *value, double *data, int64_t n)
Computes the average of an array of doubles.
Definition median.c:144