SDDSlib
Loading...
Searching...
No Matches
sddsrespmatrixderivative.c
Go to the documentation of this file.
1/**
2 * @file sddsrespmatrixderivative.c
3 * @brief Calculates the response matrix derivative with respect to correctors or BPMs.
4 *
5 * This program reads an input response matrix file and computes its derivative
6 * with respect to either correctors or Beam Position Monitors (BPMs). It supports
7 * modes for correctors ("cor"), BPMs ("bpm"), and quadrupoles ("quad"). Additional
8 * rows can be added before or after the main data to accommodate specific requirements.
9 *
10 * @copyright
11 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
12 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
13 *
14 * @license
15 * This file is distributed under the terms of the Software License Agreement
16 * found in the file LICENSE included with this distribution.
17 *
18 * @author R. Soliday
19 */
20
21
22#include "mdb.h"
23#include "scan.h"
24#include "match_string.h"
25#include "matlib.h"
26#include "SDDS.h"
27
28/* Enumeration for option types */
29enum option_type {
30 CLO_VERBOSE,
31 CLO_PIPE,
32 CLO_MODE,
33 CLO_ADDROWSBEFORE,
34 CLO_ADDROWSAFTER,
35 N_OPTIONS
36};
37
38char *commandline_option[N_OPTIONS] = {
39 "verbose",
40 "pipe",
41 "mode",
42 "addRowsBefore",
43 "addRowsAfter",
44};
45
46static char *USAGE =
47 "Usage: sddsrespmatrixderivative <inputfile> <outputfile> [OPTIONS]\n\n"
48 "Options:\n"
49 " -pipe=[input][,output] Read input from and/or write output to a pipe.\n"
50 " -mode=<string> Specify the mode of derivative:\n"
51 " \"cor\" - derivative with respect to correctors\n"
52 " \"bpm\" - derivative with respect to BPMs\n"
53 " \"quad\" - add rows related to quad constraints\n"
54 " -addRowsBefore=<number> Number of zero rows to add before the meaningful rows of output.\n"
55 " Default is 0.\n"
56 " If mode=quad, it specifies the column number where the diagonal output starts.\n"
57 " -addRowsAfter=<number> Number of zero rows to add after the meaningful rows of output.\n"
58 " Default is 0.\n"
59 " If mode=quad, it specifies the number of rows of diagonal output.\n"
60 " -verbose Print incidental information to stderr.\n";
61
62char **TokenizeString(char *source, long n_items);
63char *JoinStrings(char **source, long n_items, long buflen_increment);
64int MakeDerivative(char *mode, int addRowsBefore, int addRowsAfter, int addColumnsBefore, MATRIX *B, MATRIX *A);
65int MakeRootnameColumn(char *mode, long inputDoubleColumns, int64_t inputRows, long addRowsBefore, long addRowsAfter,
66 char **inputDoubleColumnName, char **stringData, char **rootnameData);
67
68int main(int argc, char **argv) {
69 SCANNED_ARG *s_arg;
70 SDDS_DATASET inputPage, outputPage;
71
72 char *inputfile, *outputfile;
73 char **inputColumnName, **inputStringColumnName, **inputDoubleColumnName;
74 char **outputStringColumnName, **outputDoubleColumnName;
75 int64_t inputRows, outputRows;
76 long inputDoubleColumns, inputStringColumns;
77 long outputDoubleColumns, outputStringColumns;
78 char **inputParameterName;
79 int32_t inputParameters, inputColumns;
80 char *inputDescription, *inputContents;
81 long i, i_arg, col;
82#define BUFFER_SIZE_INCREMENT 16384
83 MATRIX *R, *Rderiv;
84 long OldStringColumnsDefined;
85 long verbose;
86 long ascii;
87 unsigned long pipeFlags;
88 long tmpfile_used, noWarnings;
89 long ipage, columnType;
90 long addRowsBefore, addRowsAfter, addColumnsBefore;
91 char *mode;
92 char **stringData = NULL;
93 char **rootnameData = NULL;
94
95 inputColumnName = outputStringColumnName = outputDoubleColumnName = inputParameterName = NULL;
96 outputRows = outputDoubleColumns = outputStringColumns = OldStringColumnsDefined = 0;
97
99
100 argc = scanargs(&s_arg, argc, argv);
101 if (argc == 1)
102 bomb(NULL, USAGE);
103
104 inputfile = outputfile = NULL;
105 verbose = 0;
106 ascii = 0;
107 pipeFlags = 0;
108 tmpfile_used = 0;
109 noWarnings = 0;
110 mode = NULL;
111 int modeDefined = 0;
112 addRowsBefore = 0;
113 addRowsAfter = 0;
114
115 for (i_arg = 1; i_arg < argc; i_arg++) {
116 if (s_arg[i_arg].arg_type == OPTION) {
117 delete_chars(s_arg[i_arg].list[0], "_");
118 switch (match_string(s_arg[i_arg].list[0], commandline_option, N_OPTIONS, UNIQUE_MATCH)) {
119 case CLO_VERBOSE:
120 verbose = 1;
121 break;
122 case CLO_PIPE:
123 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
124 SDDS_Bomb("Invalid -pipe syntax");
125 break;
126 case CLO_MODE:
127 modeDefined = 1;
128 if (!(mode = s_arg[i_arg].list[1]))
129 SDDS_Bomb("No mode string provided");
130 break;
131 case CLO_ADDROWSBEFORE:
132 if (!(sscanf(s_arg[i_arg].list[1], "%ld", &addRowsBefore)) || (addRowsBefore < 0))
133 SDDS_Bomb("Invalid value for addRowsBefore: must be a non-negative number");
134 break;
135 case CLO_ADDROWSAFTER:
136 if (!(sscanf(s_arg[i_arg].list[1], "%ld", &addRowsAfter)) || (addRowsAfter < 0))
137 SDDS_Bomb("Invalid value for addRowsAfter: must be a non-negative number");
138 break;
139 default:
140 bomb("Unrecognized option provided", USAGE);
141 }
142 } else {
143 if (!inputfile)
144 inputfile = s_arg[i_arg].list[0];
145 else if (!outputfile)
146 outputfile = s_arg[i_arg].list[0];
147 else
148 bomb("Too many filenames provided", USAGE);
149 }
150 }
151
152 if (modeDefined) {
153 if (strcmp(mode, "cor") && strcmp(mode, "bpm") && strcmp(mode, "quad")) {
154 bomb("Invalid mode parameter", "Mode must be 'cor', 'bpm', or 'quad'");
155 }
156 } else {
157 bomb("Mode parameter is not defined.", "Mode must be 'cor', 'bpm', or 'quad'");
158 }
159
160 processFilenames("sddsrespmatrixderivative", &inputfile, &outputfile, pipeFlags, noWarnings, &tmpfile_used);
161
162 if (!SDDS_InitializeInput(&inputPage, inputfile) ||
163 !(inputColumnName = (char **)SDDS_GetColumnNames(&inputPage, &inputColumns)) ||
164 !(inputParameterName = (char **)SDDS_GetParameterNames(&inputPage, &inputParameters)) ||
165 !SDDS_GetDescription(&inputPage, &inputDescription, &inputContents)) {
166 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
167 exit(EXIT_FAILURE);
168 }
169
170 inputDoubleColumns = 0;
171 inputStringColumns = 0;
172 inputDoubleColumnName = (char **)malloc(inputColumns * sizeof(char *));
173 inputStringColumnName = (char **)malloc(inputColumns * sizeof(char *));
174 inputRows = 0;
175
176 if (strcmp(mode, "quad") == 0) {
177 addColumnsBefore = addRowsBefore;
178 addRowsBefore = 0;
179 } else {
180 addColumnsBefore = 0;
181 }
182
183 /* Read data */
184 while (0 < (ipage = SDDS_ReadTable(&inputPage))) {
185 if (ipage == 1) {
186 if (!SDDS_SetColumnFlags(&inputPage, 0))
187 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
188
189 /* Count the string and numerical columns in the input file */
190 for (i = 0; i < inputColumns; i++) {
191 if (SDDS_NUMERIC_TYPE(columnType = SDDS_GetColumnType(&inputPage, i))) {
192 inputDoubleColumnName[inputDoubleColumns] = inputColumnName[i];
193 inputDoubleColumns++;
194 } else if (columnType == SDDS_STRING) {
195 inputStringColumnName[inputStringColumns] = inputColumnName[i];
196 inputStringColumns++;
197 }
198 }
199
200 if (!(inputRows = SDDS_CountRowsOfInterest(&inputPage)))
201 SDDS_Bomb("No rows in dataset.");
202 } else {
203 SDDS_Bomb("Dataset must be one-page.");
204 }
205
206 if (inputDoubleColumns == 0)
207 SDDS_Bomb("No numerical columns in file.");
208
209 if ((ipage == 1) && verbose) {
210 fprintf(stderr, "Number of numerical columns: %ld.\n", inputDoubleColumns);
211 fprintf(stderr, "Number of string columns: %ld.\n", inputStringColumns);
212 fprintf(stderr, "Number of rows: %" PRId64 ".\n", inputRows);
213 }
214
215 /* Work on data */
216 if (inputDoubleColumns) {
217 m_alloc(&R, inputDoubleColumns, inputRows);
218 outputRows = inputDoubleColumns * inputRows + addRowsBefore + addRowsAfter;
219
220 if (strcmp(mode, "cor") == 0) {
221 m_alloc(&Rderiv, inputDoubleColumns, outputRows);
222 } else if (strcmp(mode, "bpm") == 0) {
223 m_alloc(&Rderiv, inputRows, outputRows);
224 } else {
225 outputRows = addRowsAfter;
226 m_alloc(&Rderiv, inputDoubleColumns, outputRows);
227 }
228
229 for (col = 0; col < inputDoubleColumns; col++) {
230 if (!(R->a[col] = (double *)SDDS_GetColumnInDoubles(&inputPage, inputDoubleColumnName[col]))) {
231 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
232 }
233 }
234
235 /* Read stringData only in non-quad mode */
236 if (strcmp(mode, "quad") != 0) {
237 if (!(stringData = SDDS_GetColumn(&inputPage, "BPMName"))) {
238 SDDS_SetError("Unable to read specified column: BPMName.");
239 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
240 return EXIT_FAILURE;
241 }
242 }
243 }
244
245 if ((ipage == 1) && verbose) {
246 fprintf(stderr, "Starting MakeDerivative...\n");
247 }
248
249 MakeDerivative(mode, addRowsBefore, addRowsAfter, addColumnsBefore, Rderiv, R);
250
251 rootnameData = (char **)malloc(outputRows * sizeof(char *));
252 if ((ipage == 1) && verbose) {
253 fprintf(stderr, "Starting MakeRootnameColumn...\n");
254 }
255
256 MakeRootnameColumn(mode, inputDoubleColumns, inputRows, addRowsBefore, addRowsAfter,
257 inputDoubleColumnName, stringData, rootnameData);
258
259 /* Define output page */
260 if ((ipage == 1) && verbose) {
261 fprintf(stderr, "Starting output...\n");
262 }
263
264 if (ipage == 1) {
265 if (strcmp(mode, "cor") == 0) {
266 outputDoubleColumns = inputDoubleColumns;
267 outputDoubleColumnName = inputDoubleColumnName;
268 } else if (strcmp(mode, "bpm") == 0) {
269 outputDoubleColumns = inputRows;
270 outputDoubleColumnName = stringData;
271 } else {
272 outputDoubleColumns = inputDoubleColumns;
273 outputDoubleColumnName = inputDoubleColumnName;
274 }
275
276 if (!SDDS_InitializeOutput(&outputPage, ascii ? SDDS_ASCII : SDDS_BINARY, 1, NULL, NULL, outputfile))
277 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
278
279 /* Define string columns */
280 outputStringColumns = 1;
281 outputStringColumnName = (char **)malloc(sizeof(char *));
282 outputStringColumnName[0] = "Rootname";
283 if (SDDS_DefineColumn(&outputPage, outputStringColumnName[0], NULL, NULL, NULL, NULL, SDDS_STRING, 0) < 0)
284 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
285
286 /* Define double columns */
287 for (i = 0; i < outputDoubleColumns; i++) {
288 if (SDDS_DefineColumn(&outputPage, outputDoubleColumnName[i], NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0) < 0)
289 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
290 }
291
292 /* Write layout */
293 switch (SDDS_CheckParameter(&outputPage, "InputFile", NULL, SDDS_STRING, NULL)) {
294 case SDDS_CHECK_NONEXISTENT:
295 if (SDDS_DefineParameter(&outputPage, "InputFile", NULL, NULL, "Original matrix file", NULL, SDDS_STRING, NULL) < 0)
296 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
297 break;
298 default:
299 break;
300 }
301
302 if (!SDDS_WriteLayout(&outputPage))
303 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
304 }
305
306 if (!SDDS_StartTable(&outputPage, outputRows))
307 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
308
309 if (ipage == 1) {
310 if (!SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, "InputFile", inputfile ? inputfile : "pipe", NULL))
311 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
312 }
313
314 /* Assign data to output table part of data set */
315
316 /* Assign string column data */
317 if (!SDDS_SetColumn(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, rootnameData, outputRows, outputStringColumnName[0]))
318 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
319
320 /* Assign double column data */
321 for (i = 0; i < outputDoubleColumns; i++) {
322 if (!SDDS_SetColumn(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, Rderiv->a[i], outputRows, outputDoubleColumnName[i]))
323 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
324 }
325 }
326
327 if (!SDDS_WriteTable(&outputPage))
328 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
329
330 if (outputDoubleColumns) {
331 m_free(&R);
332 m_free(&Rderiv);
333 free(rootnameData);
334 }
335
336 if (!SDDS_Terminate(&inputPage) || !SDDS_Terminate(&outputPage))
337 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
338
339 if (tmpfile_used && !replaceFileAndBackUp(inputfile, outputfile))
340 exit(EXIT_FAILURE);
341
342 return EXIT_SUCCESS;
343}
344
345/**********************************************************************************************************/
346
347int MakeRootnameColumn(char *mode, long inputDoubleColumns, int64_t inputRows, long addRowsBefore, long addRowsAfter,
348 char **inputDoubleColumnName, char **stringData, char **rootnameData) {
349 int64_t i, j, n;
350
351 n = 0;
352 for (i = 0; i < addRowsBefore; i++) {
353 rootnameData[n] = (char *)malloc(sizeof(char) * 1);
354 rootnameData[n][0] = '\0'; // Initialize to empty string
355 n++;
356 }
357
358 if (strcmp(mode, "quad") == 0) {
359 for (i = 0; i < addRowsAfter; i++) {
360 if (addRowsAfter > inputDoubleColumns) {
361 SDDS_SetError("Number of addRowsAfter is greater than number of input columns in quad mode.");
362 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
363 return EXIT_FAILURE;
364 }
365 rootnameData[n] = (char *)malloc(sizeof(char) * (strlen(inputDoubleColumnName[i]) + 1));
366 strcpy(rootnameData[n], inputDoubleColumnName[i]);
367 n++;
368 }
369 } else {
370 for (i = 0; i < inputRows; i++) {
371 for (j = 0; j < inputDoubleColumns; j++) {
372 size_t len = strlen(inputDoubleColumnName[j]) + strlen(stringData[i]) + 1;
373 rootnameData[n] = (char *)malloc(sizeof(char) * (len + 1));
374 strcpy(rootnameData[n], inputDoubleColumnName[j]);
375 strcat(rootnameData[n], stringData[i]);
376 n++;
377 }
378 }
379 /* Only in non-quad mode, add additional rows after */
380 for (i = 0; i < addRowsAfter; i++) {
381 rootnameData[n] = (char *)malloc(sizeof(char) * 1);
382 rootnameData[n][0] = '\0'; // Initialize to empty string
383 n++;
384 }
385 }
386
387 return EXIT_SUCCESS;
388}
389
390/**********************************************************************************************************/
391
392int MakeDerivative(char *mode, int addRowsBefore, int addRowsAfter, int addColumnsBefore, MATRIX *B, MATRIX *A) {
393 register long i, j;
394 long Ncols, Nrows;
395
396 Ncols = A->n;
397 Nrows = A->m;
398
399 /* Initialize matrix B to zero */
400 for (i = 0; i < B->n; i++) {
401 for (j = 0; j < B->m; j++) {
402 B->a[i][j] = 0.0;
403 }
404 }
405
406 if (strcmp(mode, "cor") == 0) {
407 for (i = 0; i < Ncols; i++) {
408 for (j = 0; j < Nrows; j++) {
409 B->a[i][i + j * Ncols + addRowsBefore] = A->a[i][j];
410 }
411 }
412 } else if (strcmp(mode, "bpm") == 0) {
413 for (i = 0; i < Nrows; i++) {
414 for (j = 0; j < Ncols; j++) {
415 B->a[i][i * Ncols + j + addRowsBefore] = A->a[j][i];
416 }
417 }
418 } else { /* mode == "quad" */
419 for (i = 0; i < addRowsAfter; i++) {
420 B->a[i + addColumnsBefore][i] = 1.0;
421 }
422 }
423
424 return EXIT_SUCCESS;
425}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
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.
void * SDDS_GetColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves a copy of the data for a specified column, including only rows marked as "of interest".
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
int32_t SDDS_SetColumnFlags(SDDS_DATASET *SDDS_dataset, int32_t column_flag_value)
Sets the acceptance flags for all columns in the current data table of a data set.
int32_t SDDS_GetDescription(SDDS_DATASET *SDDS_dataset, char **text, char **contents)
Retrieves the text and contents descriptions from an SDDS dataset.
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_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_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.
Definition SDDS_utils.c:379
char ** SDDS_GetParameterNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all parameters in the SDDS dataset.
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_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_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
Definition SDDStypes.h:138
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
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.
long replaceFileAndBackUp(char *file, char *replacement)
Replaces a file with a replacement file and creates a backup of the original.
Definition replacefile.c:75
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