SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddsunwrap.c
Go to the documentation of this file.
1/**
2 * @file sddsunwrap.c
3 * @brief Identifies and corrects phase discontinuities in datasets using the SDDS library.
4 *
5 * @details
6 * This program processes datasets to identify and correct phase discontinuities. It allows
7 * users to specify thresholds for detecting discontinuities and applies modular corrections.
8 * The input/output files must follow the SDDS format.
9 *
10 * @section Usage
11 * ```
12 * sddsunwrap [<input>] [<output>]
13 * [-pipe=[input][,output]]
14 * [-column=<list>]
15 * [-threshold=<value>]
16 * [-modulo=<value>]
17 * [-majorOrder=<row|column>]
18 * ```
19 *
20 * @section Options
21 * | Optional | Description |
22 * |---------------------------------------|---------------------------------------------------------------------------------------|
23 * | `-pipe` | Enables piping for input/output. |
24 * | `-column` | Specifies the columns to be unwrapped. Accepts a comma-separated list and wildcards. |
25 * | `-threshold` | Sets the discontinuity threshold (default: PI). |
26 * | `-modulo` | Sets the modulo value for unwrapping (default: 2*PI). |
27 * | `-majorOrder` | Specifies data order (row-major or column-major). |
28 *
29 * @subsection spec_req Specific Requirements
30 * - If `-column` is not specified, the program defaults to numeric columns.
31 *
32 * @copyright
33 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
34 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
35 *
36 * @license
37 * This file is distributed under the terms of the Software License Agreement
38 * found in the file LICENSE included with this distribution.
39 *
40 * @authors
41 * H. Shang, R. Soliday
42 */
43
44#include "mdb.h"
45#include "SDDS.h"
46#include "SDDSutils.h"
47#include "scan.h"
48#include <ctype.h>
49
50typedef enum {
51 OPTION_PIPE,
52 OPTION_COLUMN,
53 OPTION_THRESHOLD,
54 OPTION_MAJOR_ORDER,
55 OPTION_MODULO,
56 N_OPTIONS
57} OptionType;
58
59static char *USAGE = "\n"
60 "sddsunwrap [<input>] [<output>]\n"
61 " [-pipe=[input][,output]]\n"
62 " [-column=<list>]\n"
63 " [-threshold=<value>]\n"
64 " [-modulo=<value>]\n"
65 " [-majorOrder=<row|column>]\n"
66"Options:\n\
67 -pipe=[input][,output] Use pipes for input/output.\n\
68 -column=list Specify columns to be unwrapped, separated by commas.\n\
69 Accepts wildcards.\n\
70 -threshold=<value> Set the discontinuity threshold to identify a wrap.\n\
71 Default: PI.\n\
72 -modulo=<value> Set the value used to unwrap the data.\n\
73 Default: 2*PI.\n\
74 -majorOrder=<row|column> Specify the data order (row-major or column-major).\n\
75Description:\n\
76 sddsunwrap identifies discontinuities greater than the threshold in a set of data\n\
77 and adds the appropriate multiple of the modulo to the data set.\n\
78Program by Hairong Shang. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")";
79
80static char *option[N_OPTIONS] = {
81 "pipe",
82 "column",
83 "threshold",
84 "majorOrder",
85 "modulo",
86};
87
88int main(int argc, char **argv) {
89 double *x_data, *y_data, threshold, modulo = 0;
90 char *input = NULL, *output = NULL, **column_match = NULL, **column_name = NULL, **column;
91 long i, i_arg;
92 char output_column[256];
93
94 SDDS_DATASET sdds_in, sdds_out;
95 SCANNED_ARG *scanned;
96 unsigned long pipe_flags = 0, major_order_flag = 0;
97 int32_t column_type, columns0 = 0;
98 int64_t j, k, rows;
99 int32_t columns = 0, column_matches = 0;
100 short column_major_order = -1, phase = 1, threshold_provided = 0;
101
103
104 argc = scanargs(&scanned, argc, argv);
105 if (argc == 1)
106 bomb(NULL, USAGE);
107
108 input = output = NULL;
109 x_data = y_data = NULL;
110 column_name = NULL;
111
112 for (i_arg = 1; i_arg < argc; i_arg++) {
113 if (scanned[i_arg].arg_type == OPTION) {
114 /* process options here */
115 OptionType option_type =
116 (OptionType)match_string(scanned[i_arg].list[0], option,
117 N_OPTIONS, 0);
118 switch (option_type) {
119 case OPTION_MAJOR_ORDER:
120 major_order_flag = 0;
121 scanned[i_arg].n_items--;
122 if (scanned[i_arg].n_items > 0 && (!scanItemList(&major_order_flag, scanned[i_arg].list + 1,
123 &scanned[i_arg].n_items, 0, "row", -1,
124 NULL, 0, SDDS_ROW_MAJOR_ORDER, "column", -1,
125 NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
126 SDDS_Bomb("invalid -majorOrder syntax/values");
127 if (major_order_flag & SDDS_COLUMN_MAJOR_ORDER)
128 column_major_order = 1;
129 else if (major_order_flag & SDDS_ROW_MAJOR_ORDER)
130 column_major_order = 0;
131 break;
132 case OPTION_THRESHOLD:
133 if (scanned[i_arg].n_items != 2)
134 SDDS_Bomb("invalid -threshold syntax");
135 if (!get_double(&threshold, scanned[i_arg].list[1]))
136 SDDS_Bomb("invalid -threshold value given");
137 threshold_provided = 1;
138 break;
139 case OPTION_MODULO:
140 if (scanned[i_arg].n_items != 2)
141 SDDS_Bomb("invalid -modulo syntax");
142 if (!get_double(&modulo, scanned[i_arg].list[1]))
143 SDDS_Bomb("invalid -modulo value given");
144 break;
145 case OPTION_COLUMN:
146 if ((scanned[i_arg].n_items < 2))
147 SDDS_Bomb("invalid -column syntax");
148 column_matches = scanned[i_arg].n_items - 1;
149 column_match = tmalloc(sizeof(*column_match) * column_matches);
150 for (i = 0; i < column_matches; i++)
151 column_match[i] = scanned[i_arg].list[i + 1];
152 break;
153 case OPTION_PIPE:
154 if (!processPipeOption(scanned[i_arg].list + 1,
155 scanned[i_arg].n_items - 1,
156 &pipe_flags))
157 SDDS_Bomb("invalid -pipe syntax");
158 break;
159 default:
160 fprintf(stderr, "Unknown option %s provided\n",
161 scanned[i_arg].list[0]);
162 exit(1);
163 break;
164 }
165 } else {
166 if (!input)
167 input = scanned[i_arg].list[0];
168 else if (!output)
169 output = scanned[i_arg].list[0];
170 else
171 SDDS_Bomb("too many filenames");
172 }
173 }
174 processFilenames("sddsunwrap", &input, &output, pipe_flags, 0, NULL);
175 if (phase && !threshold_provided)
176 threshold = PI;
177
178 if (!modulo)
179 modulo = 2 * threshold;
180
181 if (!SDDS_InitializeInput(&sdds_in, input))
182 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
183 if (column_matches) {
184 column = getMatchingSDDSNames(&sdds_in, column_match, column_matches,
185 &columns, SDDS_MATCH_COLUMN);
186 } else {
187 column = tmalloc(sizeof(*column) * 1);
188 if (!(column_name = (char **)SDDS_GetColumnNames(&sdds_in, &columns0)))
189 SDDS_PrintErrors(stderr,
190 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
191 for (i = 0; i < columns0; i++) {
192 if (SDDS_NUMERIC_TYPE(column_type =
193 SDDS_GetColumnType(&sdds_in, i))) {
194 SDDS_CopyString(&column[0], column_name[i]);
195 break;
196 }
197 }
198 SDDS_FreeStringArray(column_name, columns0);
199 columns = 1;
200 }
201
202 if (!SDDS_InitializeCopy(&sdds_out, &sdds_in, output, "w"))
203 SDDS_PrintErrors(stderr,
204 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
205 if (column_major_order != -1)
206 sdds_out.layout.data_mode.column_major = column_major_order;
207 else
208 sdds_out.layout.data_mode.column_major = sdds_in.layout.data_mode.column_major;
209
210 for (i = 0; i < columns; i++) {
211 sprintf(output_column, "Unwrap%s", column[i]);
212 if (!SDDS_TransferColumnDefinition(&sdds_out, &sdds_in, column[i],
213 output_column))
214 SDDS_PrintErrors(stderr,
215 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
216 }
217 if (!SDDS_WriteLayout(&sdds_out))
218 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
219
220 while (SDDS_ReadPage(&sdds_in) > 0) {
221 if ((rows = SDDS_CountRowsOfInterest(&sdds_in)) <= 0)
222 continue;
223 if (!SDDS_StartPage(&sdds_out, rows) || !SDDS_CopyPage(&sdds_out, &sdds_in))
224 SDDS_PrintErrors(stderr,
225 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
226
227 y_data = tmalloc(sizeof(*y_data) * rows);
228 for (i = 0; i < columns; i++) {
229 sprintf(output_column, "Unwrap%s", column[i]);
230 if (!(x_data = SDDS_GetColumnInDoubles(&sdds_in, column[i])))
231 SDDS_PrintErrors(stderr,
232 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
233 k = 0;
234 for (j = 0; j < rows - 1; j++) {
235 y_data[j] = x_data[j] + modulo * k; /*add 2*Pi*k to input */
236 /* check if diff is greater than alpha */
237 if (fabs(x_data[j + 1] - x_data[j]) > fabs(threshold)) {
238 if (x_data[j + 1] < x_data[j])
239 k = k + 1; /* if the pahse jump is negative, increment k */
240 else
241 k = k - 1; /* if the phase jump is positive, decrement k */
242 }
243 }
244 y_data[rows - 1] = x_data[rows - 1] + modulo * k; /* add 2*pi*k to the last element of the input */
245
246 if (x_data)
247 free(x_data);
248 x_data = NULL;
249
250 if (!SDDS_SetColumnFromDoubles(&sdds_out, SDDS_BY_NAME, y_data,
251 rows, output_column))
252 SDDS_PrintErrors(stderr,
253 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
254 }
255 free(y_data);
256 y_data = NULL;
257 if (!SDDS_WritePage(&sdds_out))
258 SDDS_PrintErrors(stderr,
259 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
260 }
261 if (!SDDS_Terminate(&sdds_in) || !SDDS_Terminate(&sdds_out)) {
262 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
263 exit(1);
264 }
265 if (column_name) {
266 SDDS_FreeStringArray(column_name, columns0);
267 free(column_name);
268 }
269 SDDS_FreeStringArray(column, columns);
270 free(column);
271 if (column_match)
272 free(column_match);
273 free_scanargs(&scanned, argc);
274 return 0;
275}
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
Utility functions for SDDS dataset manipulation and string array operations.
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.