SDDSlib
Loading...
Searching...
No Matches
sddsunwrap.c
Go to the documentation of this file.
1/**
2 * @file sddsunwrap.c
3 * @brief Program to unwrap data by identifying and correcting phase discontinuities.
4 *
5 * This program processes a dataset to identify discontinuities larger than a specified
6 * threshold and applies the appropriate multiple of a modulo value to remove these discontinuities.
7 * It is designed to handle Self Describing Data Set (SDDS) files, providing options for
8 * input/output redirection, column selection, and order specification.
9 *
10 * @details
11 * The program supports the following options:
12 * - `-pipe=[input][,output]`: Use pipes for input/output.
13 * - `-column=list`: Specify columns to unwrap, separated by commas (supports wildcards).
14 * - `-threshold=<value>`: Set the discontinuity threshold (default: PI).
15 * - `-modulo=<value>`: Set the modulo value for unwrapping (default: 2*PI).
16 * - `-majorOrder=<row|column>`: Specify the data order (row-major or column-major).
17 *
18 * Example usage:
19 * @code
20 * sddsunwrap input.sdds output.sdds -column=Phase -threshold=3.14 -modulo=6.28
21 * @endcode
22 *
23 * @copyright
24 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
25 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
26 *
27 * @license
28 * This file is distributed under the terms of the Software License Agreement
29 * found in the file LICENSE included with this distribution.
30 *
31 * @author H. Shang, R. Soliday
32 */
33
34#include "mdb.h"
35#include "SDDS.h"
36#include "SDDSutils.h"
37#include "scan.h"
38#include <ctype.h>
39
40typedef enum {
41 OPTION_PIPE,
42 OPTION_COLUMN,
43 OPTION_THRESHOLD,
44 OPTION_MAJOR_ORDER,
45 OPTION_MODULO,
46 N_OPTIONS
48
49static char *USAGE = "Usage: sddsunwrap [<input>] [<output>]\n\
50Options:\n\
51 -pipe=[input][,output] Use pipes for input/output.\n\
52 -column=list Specify columns to be unwrapped, separated by commas.\n\
53 Accepts wildcards.\n\
54 -threshold=<value> Set the discontinuity threshold to identify a wrap.\n\
55 Default: PI.\n\
56 -modulo=<value> Set the value used to unwrap the data.\n\
57 Default: 2*PI.\n\
58 -majorOrder=<row|column> Specify the data order (row-major or column-major).\n\
59Description:\n\
60 sddsunwrap identifies discontinuities greater than the threshold in a set of data\n\
61 and adds the appropriate multiple of the modulo to the data set.\n\
62Program by Hairong Shang. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")";
63
64static char *option[N_OPTIONS] = {
65 "pipe",
66 "column",
67 "threshold",
68 "majorOrder",
69 "modulo",
70};
71
72int main(int argc, char **argv) {
73 double *x_data, *y_data, threshold, modulo = 0;
74 char *input = NULL, *output = NULL, **column_match = NULL, **column_name = NULL, **column;
75 long i, i_arg;
76 char output_column[256];
77
78 SDDS_DATASET sdds_in, sdds_out;
79 SCANNED_ARG *scanned;
80 unsigned long pipe_flags = 0, major_order_flag = 0;
81 int32_t column_type, columns0 = 0;
82 int64_t j, k, rows;
83 int32_t columns = 0, column_matches = 0;
84 short column_major_order = -1, phase = 1, threshold_provided = 0;
85
87
88 argc = scanargs(&scanned, argc, argv);
89 if (argc == 1)
90 bomb(NULL, USAGE);
91
92 input = output = NULL;
93 x_data = y_data = NULL;
94 column_name = NULL;
95
96 for (i_arg = 1; i_arg < argc; i_arg++) {
97 if (scanned[i_arg].arg_type == OPTION) {
98 /* process options here */
99 OptionType option_type =
100 (OptionType)match_string(scanned[i_arg].list[0], option,
101 N_OPTIONS, 0);
102 switch (option_type) {
103 case OPTION_MAJOR_ORDER:
104 major_order_flag = 0;
105 scanned[i_arg].n_items--;
106 if (scanned[i_arg].n_items > 0 && (!scanItemList(&major_order_flag, scanned[i_arg].list + 1,
107 &scanned[i_arg].n_items, 0, "row", -1,
108 NULL, 0, SDDS_ROW_MAJOR_ORDER, "column", -1,
109 NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
110 SDDS_Bomb("invalid -majorOrder syntax/values");
111 if (major_order_flag & SDDS_COLUMN_MAJOR_ORDER)
112 column_major_order = 1;
113 else if (major_order_flag & SDDS_ROW_MAJOR_ORDER)
114 column_major_order = 0;
115 break;
116 case OPTION_THRESHOLD:
117 if (scanned[i_arg].n_items != 2)
118 SDDS_Bomb("invalid -threshold syntax");
119 if (!get_double(&threshold, scanned[i_arg].list[1]))
120 SDDS_Bomb("invalid -threshold value given");
121 threshold_provided = 1;
122 break;
123 case OPTION_MODULO:
124 if (scanned[i_arg].n_items != 2)
125 SDDS_Bomb("invalid -modulo syntax");
126 if (!get_double(&modulo, scanned[i_arg].list[1]))
127 SDDS_Bomb("invalid -modulo value given");
128 break;
129 case OPTION_COLUMN:
130 if ((scanned[i_arg].n_items < 2))
131 SDDS_Bomb("invalid -column syntax");
132 column_matches = scanned[i_arg].n_items - 1;
133 column_match = tmalloc(sizeof(*column_match) * column_matches);
134 for (i = 0; i < column_matches; i++)
135 column_match[i] = scanned[i_arg].list[i + 1];
136 break;
137 case OPTION_PIPE:
138 if (!processPipeOption(scanned[i_arg].list + 1,
139 scanned[i_arg].n_items - 1,
140 &pipe_flags))
141 SDDS_Bomb("invalid -pipe syntax");
142 break;
143 default:
144 fprintf(stderr, "Unknown option %s provided\n",
145 scanned[i_arg].list[0]);
146 exit(1);
147 break;
148 }
149 } else {
150 if (!input)
151 input = scanned[i_arg].list[0];
152 else if (!output)
153 output = scanned[i_arg].list[0];
154 else
155 SDDS_Bomb("too many filenames");
156 }
157 }
158 processFilenames("sddsunwrap", &input, &output, pipe_flags, 0, NULL);
159 if (phase && !threshold_provided)
160 threshold = PI;
161
162 if (!modulo)
163 modulo = 2 * threshold;
164
165 if (!SDDS_InitializeInput(&sdds_in, input))
166 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
167 if (column_matches) {
168 column = getMatchingSDDSNames(&sdds_in, column_match, column_matches,
169 &columns, SDDS_MATCH_COLUMN);
170 } else {
171 column = tmalloc(sizeof(*column) * 1);
172 if (!(column_name = (char **)SDDS_GetColumnNames(&sdds_in, &columns0)))
173 SDDS_PrintErrors(stderr,
174 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
175 for (i = 0; i < columns0; i++) {
176 if (SDDS_NUMERIC_TYPE(column_type =
177 SDDS_GetColumnType(&sdds_in, i))) {
178 SDDS_CopyString(&column[0], column_name[i]);
179 break;
180 }
181 }
182 SDDS_FreeStringArray(column_name, columns0);
183 columns = 1;
184 }
185
186 if (!SDDS_InitializeCopy(&sdds_out, &sdds_in, output, "w"))
187 SDDS_PrintErrors(stderr,
188 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
189 if (column_major_order != -1)
190 sdds_out.layout.data_mode.column_major = column_major_order;
191 else
192 sdds_out.layout.data_mode.column_major = sdds_in.layout.data_mode.column_major;
193
194 for (i = 0; i < columns; i++) {
195 sprintf(output_column, "Unwrap%s", column[i]);
196 if (!SDDS_TransferColumnDefinition(&sdds_out, &sdds_in, column[i],
197 output_column))
198 SDDS_PrintErrors(stderr,
199 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
200 }
201 if (!SDDS_WriteLayout(&sdds_out))
202 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
203
204 while (SDDS_ReadPage(&sdds_in) > 0) {
205 if ((rows = SDDS_CountRowsOfInterest(&sdds_in)) <= 0)
206 continue;
207 if (!SDDS_StartPage(&sdds_out, rows) || !SDDS_CopyPage(&sdds_out, &sdds_in))
208 SDDS_PrintErrors(stderr,
209 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
210
211 y_data = tmalloc(sizeof(*y_data) * rows);
212 for (i = 0; i < columns; i++) {
213 sprintf(output_column, "Unwrap%s", column[i]);
214 if (!(x_data = SDDS_GetColumnInDoubles(&sdds_in, column[i])))
215 SDDS_PrintErrors(stderr,
216 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
217 k = 0;
218 for (j = 0; j < rows - 1; j++) {
219 y_data[j] = x_data[j] + modulo * k; /*add 2*Pi*k to input */
220 /* check if diff is greater than alpha */
221 if (fabs(x_data[j + 1] - x_data[j]) > fabs(threshold)) {
222 if (x_data[j + 1] < x_data[j])
223 k = k + 1; /* if the pahse jump is negative, increment k */
224 else
225 k = k - 1; /* if the phase jump is positive, decrement k */
226 }
227 }
228 y_data[rows - 1] = x_data[rows - 1] + modulo * k; /* add 2*pi*k to the last element of the input */
229
230 if (x_data)
231 free(x_data);
232 x_data = NULL;
233
234 if (!SDDS_SetColumnFromDoubles(&sdds_out, SDDS_BY_NAME, y_data,
235 rows, output_column))
236 SDDS_PrintErrors(stderr,
237 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
238 }
239 free(y_data);
240 y_data = NULL;
241 if (!SDDS_WritePage(&sdds_out))
242 SDDS_PrintErrors(stderr,
243 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
244 }
245 if (!SDDS_Terminate(&sdds_in) || !SDDS_Terminate(&sdds_out)) {
246 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
247 exit(1);
248 }
249 if (column_name) {
250 SDDS_FreeStringArray(column_name, columns0);
251 free(column_name);
252 }
253 SDDS_FreeStringArray(column, columns);
254 free(column);
255 if (column_match)
256 free(column_match);
257 free_scanargs(&scanned, argc);
258 return 0;
259}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
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_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_SetColumnFromDoubles(SDDS_DATASET *SDDS_dataset, int32_t mode, double *data, int64_t rows,...)
Sets the values for a single data column using double-precision floating-point numbers.
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
double * SDDS_GetColumnInDoubles(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of doubles, considering only rows mark...
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_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_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.
char ** SDDS_GetColumnNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all columns in the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
int32_t SDDS_GetColumnType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a column in the SDDS dataset by its index.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
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_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
Definition SDDStypes.h:138
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
int get_double(double *dptr, char *s)
Parses a double value from the given string.
Definition data_scan.c:40
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
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584
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.
OptionType
Enumeration for command-line options.