63static char *option[N_OPTIONS] = {
74 "Usage: sddsshift [<inputfile>] [<outputfile>]\n"
75 " [-pipe=[input][,output]] -columns=<inputcol>[,...]\n"
76 " [-zero | -circular] [-shift=<points> | -match=<matchcol>]\n"
77 " [-majorOrder=row|column]\n\n"
78 "-columns Provide <inputcols>, i.e., the data columns to be shifted.\n"
79 " Wildcards accepted.\n"
80 "-shift Provide number of points to shift in rows.\n"
81 " (positive = later, negative = earlier).\n"
82 "-match Provide <matchcol>. <inputcol> is shifted to\n"
83 " minimize the least squares error relative to <matchcol>.\n"
84 "-zero Set exposed end-points to zero.\n"
85 "-circular Shift the data in a circular fashion.\n"
86 "-majorOrder Specify output file in row or column major order.\n\n"
87 "sddsshift shifts specified data columns by rows. A copy of <inputfile> is made with the\n"
88 "addition of new columns \"Shifted<inputcol>\". Exposed end-points\n"
89 "are set to zero if the zero option is provided or\n"
90 "the value of the first/last row in <inputcol> as appropriate.\n"
91 "A parameter \"<inputcol>Shift\" contains the number of rows shifted.\n";
94void shift(
double *inputcol,
double *outputcol, int64_t npoints,
long delay,
long zero,
long circular);
95double mse(
double *y1,
double *y2,
long npoints);
96double simplex_driver(
double *data,
long *invalid);
97long resolve_column_names(
SDDS_DATASET *SDDSin,
char ***column, int32_t *columns);
100double *input_col, *working, *match_col;
104int main(
int argc,
char *argv[]) {
107 char *input_col_name, *match_col_name, *inputfile, *outputfile;
108 long i, i_arg, delay, tmp_file_used;
109 unsigned long pipe_flags, major_order_flag;
110 char actual_name[256], actual_desc[256], delay_name[256];
111 double sim_delay, lower, upper, final_mse;
113 short column_major_order = -1;
114 char **input_col_names = NULL;
115 int32_t n_input_col_names = 0;
118 argc =
scanargs(&s_arg, argc, argv);
126 inputfile = outputfile = input_col_name = match_col_name = NULL;
130 input_col = match_col = output_col = working = NULL;
133 for (i_arg = 1; i_arg < argc; i_arg++) {
134 if (s_arg[i_arg].arg_type == OPTION) {
136 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
137 case CLO_MAJOR_ORDER:
138 major_order_flag = 0;
139 s_arg[i_arg].n_items--;
140 if (s_arg[i_arg].n_items > 0 &&
141 (!
scanItemList(&major_order_flag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
142 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
143 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL))) {
144 SDDS_Bomb(
"Invalid -majorOrder syntax/values");
146 if (major_order_flag & SDDS_COLUMN_MAJOR_ORDER) {
147 column_major_order = 1;
148 }
else if (major_order_flag & SDDS_ROW_MAJOR_ORDER) {
149 column_major_order = 0;
153 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipe_flags)) {
158 if (s_arg[i_arg].n_items < 2) {
161 if (n_input_col_names) {
162 SDDS_Bomb(
"Invalid syntax: specify -columns once only");
164 input_col_names =
tmalloc(
sizeof(*input_col_names) * (s_arg[i_arg].n_items - 1));
165 for (i = 1; i < s_arg[i_arg].n_items; i++) {
166 input_col_names[i - 1] = s_arg[i_arg].list[i];
168 n_input_col_names = s_arg[i_arg].n_items - 1;
171 if (s_arg[i_arg].n_items != 2) {
174 if (!
get_long(&delay, s_arg[i_arg].list[1])) {
175 SDDS_Bomb(
"Invalid delay value provided.");
179 if (s_arg[i_arg].n_items != 2) {
182 match_col_name = s_arg[i_arg].list[1];
191 fprintf(stderr,
"Error (%s): unknown switch: %s\n", argv[0], s_arg[i_arg].list[0]);
196 inputfile = s_arg[i_arg].list[0];
197 }
else if (!outputfile) {
198 outputfile = s_arg[i_arg].list[0];
205 processFilenames(
"sddsshift", &inputfile, &outputfile, pipe_flags, 1, &tmp_file_used);
207 if (zero && circular) {
208 SDDS_Bomb(
"The -zero and -circular options are mutually exclusive.");
211 if (n_input_col_names == 0) {
212 SDDS_Bomb(
"A shift column is not given!");
214 if (!match_col_name && !delay) {
215 SDDS_Bomb(
"Either match column or shift should be provided.");
217 if (match_col_name && delay) {
218 SDDS_Bomb(
"-match column option and -shift option are incompatible.");
226 if (!resolve_column_names(&SDDS_input, &input_col_names, &n_input_col_names)) {
235 SDDS_output.layout.data_mode.column_major = column_major_order != -1 ? column_major_order : SDDS_input.layout.data_mode.column_major;
237 for (i = 0; i < n_input_col_names; i++) {
238 snprintf(actual_name,
sizeof(actual_name),
"Shifted%s", input_col_names[i]);
239 snprintf(actual_desc,
sizeof(actual_desc),
"Shifted %s", input_col_names[i]);
240 snprintf(delay_name,
sizeof(delay_name),
"%sShift", input_col_names[i]);
263 for (i = 0; i < n_input_col_names; i++) {
264 snprintf(actual_name,
sizeof(actual_name),
"Shifted%s", input_col_names[i]);
265 snprintf(delay_name,
sizeof(delay_name),
"%sShift", input_col_names[i]);
271 output_col = calloc(npoints,
sizeof(*output_col));
276 if (match_col_name) {
281 working = calloc(npoints,
sizeof(*working));
285 lower = -((double)npoints - 1);
286 upper = (double)npoints - 1;
287 simplexMin(&final_mse, &sim_delay, NULL, &lower, &upper, NULL, 1, 1e-6, 1e-12, simplex_driver, NULL, 2 * npoints, 6, 12, 3, 1.0, 0);
288 delay = (long)sim_delay;
291 match_col = working = NULL;
294 shift(input_col, output_col, npoints, delay, zero, circular);
295 if (!
SDDS_SetParameters(&SDDS_output, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, delay_name, delay, NULL) ||
296 !
SDDS_SetColumn(&SDDS_output, SDDS_SET_BY_NAME, output_col, npoints, actual_name)) {
302 output_col = input_col = NULL;
318long resolve_column_names(
SDDS_DATASET *SDDSin,
char ***column, int32_t *columns) {
322 for (i = 0; i < *columns; i++) {
329 if (!*column || *columns == 0) {
336void shift(
double *inputcol,
double *outputcol, int64_t npoints,
long delay,
long zero,
long circular) {
340 short local_buffer = 0;
341 if (inputcol == outputcol) {
342 inputcol =
tmalloc(
sizeof(*inputcol) * npoints);
343 memcpy(inputcol, outputcol,
sizeof(*inputcol) * npoints);
346 for (i = 0; i < npoints; i++) {
347 j = (i - delay) % npoints;
351 outputcol[i] = inputcol[j];
359 for (i = 0; i < npoints - delay; i++) {
360 outputcol[i] = inputcol[i + delay];
362 for (i = npoints - delay; i < npoints; i++) {
363 outputcol[i] = zero ? 0 : inputcol[npoints - 1];
366 for (i = npoints - 1; i >= delay; i--) {
367 outputcol[i] = inputcol[i - delay];
369 for (i = 0; i < delay; i++) {
370 outputcol[i] = zero ? 0 : inputcol[0];
376double mse(
double *y1,
double *y2,
long npoints) {
380 for (i = 0; i < npoints; i++) {
381 error += (y1[i] - y2[i]) * (y1[i] - y2[i]);
383 return error / npoints;
386double simplex_driver(
double *data,
long *invalid) {
391 shift(input_col, working, npoints, delay, zero, circular);
392 return mse(match_col, working, npoints);
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)
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
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_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length)
Defines a data column within the SDDS dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_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.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
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.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
#define SDDS_DOUBLE
Identifier for the double data type.
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
int get_long(long *iptr, char *s)
Parses a long integer value from the given string.
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
void free_scanargs(SCANNED_ARG **scanned, int argc)
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.
long simplexMin(double *yReturn, double *xGuess, double *dxGuess, double *xLowerLimit, double *xUpperLimit, short *disable, long dimensions, double target, double tolerance, double(*func)(double *x, long *invalid), void(*report)(double ymin, double *xmin, long pass, long evals, long dims), long maxEvaluations, long maxPasses, long maxDivisions, double divisorFactor, double passRangeFactor, unsigned long flags)
Top-level convenience function for simplex-based minimization.