SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddstranspose.c
Go to the documentation of this file.
1/**
2 * @file sddstranspose.c
3 * @brief Transposes numerical columns in an SDDS file.
4 *
5 * @details
6 * This program reads an SDDS file with one or more pages, identifies all numerical columns,
7 * and transposes them as though they were a matrix. If the file contains multiple pages,
8 * additional pages are transposed only if they have the same number of rows as the first page.
9 * String columns are converted to string parameters, and string parameters listed in the
10 * "OldStringColumnNames" parameter become string columns in the output. If any string
11 * columns exist, the data in the first string column is used as the names of the columns
12 * in the output file. If no string columns exist, column names are generated from command
13 * line options. The names of the input file columns are saved as a string column in the
14 * output file with a name specified via the command line or the default "OldColumnName".
15 *
16 * @section Usage
17 * ```
18 * sddstranspose [<inputfile>] [<outputfile>]
19 * [-pipe=[input][,output]]
20 * [-oldColumnNames=<string>]
21 * [-root=<string>]
22 * [-digits=<integer>]
23 * [-newColumnNames=<column>}]
24 * [-matchColumn=<string>[,<string>,...]]
25 * [-indexColumn]
26 * [-noOldColumnNames]
27 * [-symbol=<string>]
28 * [-ascii]
29 * [-verbose]
30 * [-majorOrder=row|column]
31 * ```
32 *
33 * @section Options
34 * | Optional | Description |
35 * |---------------------------------------|---------------------------------------------------------------------------------------|
36 * | `-pipe` | Reads input from and/or writes output to a pipe. |
37 * | `-oldColumnNames` | Specifies the name for the output file string column created for the input column names. |
38 * | `-root` | Uses the specified string to generate column names of the output file. |
39 * | `-digits` | Sets the minimum number of digits appended to column names. Default is 3. |
40 * | `-newColumnNames` | Uses the specified column as the source for new column names. |
41 * | `-matchColumn` | Only transposes columns matching the specified names. |
42 * | `-indexColumn` | Adds an index column to the output file. |
43 * | `-noOldColumnNames` | Does not create a column for old column names. |
44 * | `-symbol` | Specifies the symbol field for column definitions. |
45 * | `-ascii` | Outputs the file in ASCII format. Default is binary. |
46 * | `-verbose` | Prints incidental information to stderr. |
47 * | `-majorOrder` | Specifies the output file's major order (row-major or column-major). |
48 *
49 * @subsection Incompatibilities
50 * - `-root` is incompatible with:
51 * - `-newColumnNames`
52 *
53 * @copyright
54 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
55 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
56 *
57 * @license
58 * This file is distributed under the terms of the Software License Agreement
59 * found in the file LICENSE included with this distribution.
60 *
61 * @author
62 * M. Borland, C. Saunders, L. Emery, R. Soliday, H. Shang
63 */
64
65#include "mdb.h"
66#include "scan.h"
67#include "match_string.h"
68#include "matlib.h"
69#include "SDDS.h"
70#include "SDDSutils.h"
71
72/* Enumeration for option types */
73enum option_type {
74 CLO_VERBOSE,
75 CLO_COLUMNROOT,
76 CLO_SYMBOL,
77 CLO_ASCII,
78 CLO_PIPE,
79 CLO_OLDCOLUMNNAMES,
80 CLO_NEWCOLUMNNAMES,
81 CLO_DIGITS,
82 CLO_MATCH_COLUMN,
83 CLO_INDEX_COLUMN,
84 CLO_NO_OLDCOLUMNNAMES,
85 CLO_MAJOR_ORDER,
86 N_OPTIONS
87};
88
89char *commandline_option[N_OPTIONS] = {
90 "verbose",
91 "root",
92 "symbol",
93 "ascii",
94 "pipe",
95 "oldColumnNames",
96 "newColumnNames",
97 "digits",
98 "matchColumn",
99 "indexColumn",
100 "noOldColumnNames",
101 "majorOrder",
102};
103
104static char *OLD_STRING_COLUMN_NAMES = "OldStringColumnNames";
105
106static char *USAGE =
107 "sddstranspose [<inputfile>] [<outputfile>]\n"
108 " [-pipe=[input][,output]]\n"
109 " [-oldColumnNames=<string>] \n"
110 " [-root=<string>]\n"
111 " [-digits=<integer>]\n"
112 " [-newColumnNames=<column>}] \n"
113 " [-matchColumn=<string>[,<string>,...]]\n"
114 " [-indexColumn] \n"
115 " [-noOldColumnNames] \n"
116 " [-symbol=<string>] \n"
117 " [-ascii] \n"
118 " [-verbose] \n"
119 " [-majorOrder=row|column]\n"
120 "Options:\n"
121 " -pipe=[input][,output] Reads input from and/or writes output to a pipe.\n"
122 " -oldColumnNames=<string> Specifies the name for the output file string column created for the input file column names.\n"
123 " -root=<string> Uses the specified string to generate column names of the output file.\n"
124 " Default column names are the first string column in <inputfile>.\n"
125 " If no string column exists, column names are formed with the root \"Column\".\n"
126 " -digits=<integer> Sets the minimum number of digits appended to the root part of the column names.\n"
127 " Default is 3.\n"
128 " -newColumnNames=<column> Uses the specified column as the source for new column names.\n"
129 " -symbol=<string> Uses the specified string for the symbol field in all column definitions.\n"
130 " -ascii Outputs the file in ASCII format. Default is binary.\n"
131 " -matchColumn=<string>[,<string>,...] Only transposes the columns that match the specified names.\n"
132 " -indexColumn Adds an index column to the output file.\n"
133 " -noOldColumnNames Does not create a new column for old column names.\n"
134 " -majorOrder=row|column Specifies the output file's major order (row-major or column-major).\n"
135 " -verbose Prints incidental information to stderr.\n\n"
136 "Link date: " __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION "\n";
137
138char **TokenizeString(char *source, long n_items);
139char *JoinStrings(char **source, long n_items, long buflen_increment);
140
141int main(int argc, char **argv) {
142 SCANNED_ARG *s_arg;
143 SDDS_DATASET inputPage, outputPage;
144
145 char *inputfile, *outputfile;
146 char **inputColumnName, **inputStringColumnName, **inputDoubleColumnName;
147 char **outputStringColumnName, **outputDoubleColumnName, **matchColumn = NULL;
148 long inputDoubleColumns, inputStringColumns, indexColumn = 0, noOldColumnNamesColumn = 0;
149 int64_t inputRows;
150 int32_t matchColumns = 0;
151 long outputRows, outputDoubleColumns, outputStringColumns;
152 char **inputParameterName;
153 int32_t inputParameters;
154 int32_t inputColumns;
155 char *inputDescription, *inputContents;
156 char *outputDescription;
157 long i, i_arg, col;
158 char *buffer;
159 char **columnOfStrings;
160 long buffer_size;
161#define BUFFER_SIZE_INCREMENT 16384
162 MATRIX *R, *RInv;
163 long OldStringColumnsDefined;
164 char *inputStringRows, *outputStringRows;
165 char **stringArray, *stringParameter;
166 long token_length;
167 long verbose;
168 char format[32];
169 long digits;
170 char *Symbol, *Root;
171 void *parameterPointer;
172 long ascii;
173 unsigned long pipeFlags, majorOrderFlag;
174 long tmpfile_used, noWarnings;
175 long ipage = 0, columnType;
176 char *oldColumnNames, *newColumnNamesColumn;
177 short columnMajorOrder = -1;
178
179 inputColumnName = outputStringColumnName = outputDoubleColumnName = inputParameterName = NULL;
180 outputRows = outputDoubleColumns = outputStringColumns = OldStringColumnsDefined = 0;
181
183
184 argc = scanargs(&s_arg, argc, argv);
185 if (argc == 1)
186 bomb(NULL, USAGE);
187
188 inputfile = outputfile = NULL;
189 verbose = 0;
190 Symbol = Root = NULL;
191 ascii = 0;
192 digits = 3;
193 pipeFlags = 0;
194 tmpfile_used = 0;
195 noWarnings = 0;
196 oldColumnNames = NULL;
197 newColumnNamesColumn = NULL;
198
199 for (i_arg = 1; i_arg < argc; i_arg++) {
200 if (s_arg[i_arg].arg_type == OPTION) {
201 switch (match_string(s_arg[i_arg].list[0], commandline_option, N_OPTIONS, UNIQUE_MATCH)) {
202 case CLO_MAJOR_ORDER:
203 majorOrderFlag = 0;
204 s_arg[i_arg].n_items--;
205 if (s_arg[i_arg].n_items > 0 &&
206 (!scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
207 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
208 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
209 SDDS_Bomb("invalid -majorOrder syntax/values");
210 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
211 columnMajorOrder = 1;
212 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
213 columnMajorOrder = 0;
214 break;
215 case CLO_MATCH_COLUMN:
216 matchColumns = s_arg[i_arg].n_items - 1;
217 matchColumn = s_arg[i_arg].list + 1;
218 break;
219 case CLO_INDEX_COLUMN:
220 indexColumn = 1;
221 break;
222 case CLO_NO_OLDCOLUMNNAMES:
223 noOldColumnNamesColumn = 1;
224 break;
225 case CLO_VERBOSE:
226 verbose = 1;
227 break;
228 case CLO_ASCII:
229 ascii = 1;
230 break;
231 case CLO_DIGITS:
232 if (!(get_long(&digits, s_arg[i_arg].list[1])))
233 bomb("No integer provided for option -digits", USAGE);
234 break;
235 case CLO_COLUMNROOT:
236 if (!(Root = s_arg[i_arg].list[1]))
237 SDDS_Bomb("No root string provided with -root option");
238 break;
239 case CLO_SYMBOL:
240 if (!(Symbol = s_arg[i_arg].list[1]))
241 SDDS_Bomb("No symbol string provided with -symbol option");
242 break;
243 case CLO_PIPE:
244 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
245 SDDS_Bomb("Invalid -pipe syntax");
246 break;
247 case CLO_OLDCOLUMNNAMES:
248 if (!(oldColumnNames = s_arg[i_arg].list[1]))
249 SDDS_Bomb("No string provided for -oldColumnNames option");
250 break;
251 case CLO_NEWCOLUMNNAMES:
252 if (s_arg[i_arg].n_items != 2 || SDDS_StringIsBlank(newColumnNamesColumn = s_arg[i_arg].list[1]))
253 SDDS_Bomb("Invalid syntax or value for -newColumnNames option");
254 break;
255 default:
256 bomb("Unrecognized option provided", USAGE);
257 }
258 } else {
259 if (!inputfile)
260 inputfile = s_arg[i_arg].list[0];
261 else if (!outputfile)
262 outputfile = s_arg[i_arg].list[0];
263 else
264 bomb("Too many filenames provided", USAGE);
265 }
266 }
267
268 processFilenames("sddstranspose", &inputfile, &outputfile, pipeFlags, noWarnings, &tmpfile_used);
269 if (newColumnNamesColumn && Root)
270 SDDS_Bomb("-root and -newColumnNames options are incompatible");
271
272 if (!SDDS_InitializeInput(&inputPage, inputfile) ||
273 !(inputParameterName = (char **)SDDS_GetParameterNames(&inputPage, &inputParameters)) ||
274 !SDDS_GetDescription(&inputPage, &inputDescription, &inputContents))
275 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
276
277 if (matchColumns)
278 inputColumnName = getMatchingSDDSNames(&inputPage, matchColumn, matchColumns, &inputColumns, SDDS_MATCH_COLUMN);
279 else {
280 if (!(inputColumnName = (char **)SDDS_GetColumnNames(&inputPage, &inputColumns)))
281 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
282 }
283
284 inputDoubleColumns = 0;
285 inputStringColumns = 0;
286 inputDoubleColumnName = (char **)malloc(inputColumns * sizeof(char *));
287 inputStringColumnName = (char **)malloc(inputColumns * sizeof(char *));
288 inputRows = 0;
289
290 /***********
291 * Read data
292 ***********/
293 while (0 < SDDS_ReadTable(&inputPage)) {
294 ipage++;
295#if defined(DEBUG)
296 fprintf(stderr, "Working on page %ld\n", ipage);
297#endif
298 if (ipage == 1) {
299 if (!SDDS_SetColumnFlags(&inputPage, 0))
300 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
301
302 /* Count the string and numerical columns in the input file */
303 for (i = 0; i < inputColumns; i++) {
304 if (SDDS_NUMERIC_TYPE(columnType = SDDS_GetColumnType(&inputPage, i))) {
305 inputDoubleColumnName[inputDoubleColumns] = inputColumnName[i];
306 inputDoubleColumns++;
307 }
308 }
309 for (i = 0; i < inputPage.layout.n_columns; i++) {
310 if (inputPage.layout.column_definition[i].type == SDDS_STRING) {
311 inputStringColumnName[inputStringColumns] = inputPage.layout.column_definition[i].name;
312 inputStringColumns++;
313 }
314 }
315 if (!(inputRows = SDDS_CountRowsOfInterest(&inputPage)))
316 SDDS_Bomb("No rows in dataset.");
317 } else {
318 /* These statements are executed on subsequent pages */
319 if (inputRows != SDDS_CountRowsOfInterest(&inputPage)) {
320 SDDS_Bomb("Datasets have differing number of rows. Processing stopped before reaching end of input file.");
321 }
322 }
323
324 if (inputRows > INT32_MAX) {
325 SDDS_Bomb("Too many rows in dataset.");
326 }
327
328#if defined(DEBUG)
329 fprintf(stderr, "Row flags set\n");
330#endif
331 if (inputDoubleColumns == 0)
332 SDDS_Bomb("No numerical columns in file.");
333
334 if ((ipage == 1) && verbose) {
335 fprintf(stderr, "Number of numerical columns: %ld.\n", inputDoubleColumns);
336 fprintf(stderr, "Number of string columns: %ld.\n", inputStringColumns);
337 fprintf(stderr, "Number of rows: %" PRId64 ".\n", inputRows);
338 }
339
340 /****************
341 * Transpose data
342 ****************/
343 if (inputDoubleColumns) {
344 if (ipage == 1) {
345 m_alloc(&RInv, inputRows, inputDoubleColumns);
346 m_alloc(&R, inputDoubleColumns, inputRows);
347 }
348 for (col = 0; col < inputDoubleColumns; col++) {
349 if (!(R->a[col] = (double *)SDDS_GetColumnInDoubles(&inputPage, inputDoubleColumnName[col]))) {
350 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
351 }
352 }
353 if (verbose) {
354 m_show(R, "%9.6le ", "Transpose of input matrix:\n", stdout);
355 }
356 m_trans(RInv, R);
357 }
358
359 /***************************
360 * Determine existence of
361 * transposed string columns
362 ***************************/
363 if (ipage == 1) {
364 OldStringColumnsDefined = 0;
365 switch (SDDS_CheckParameter(&inputPage, OLD_STRING_COLUMN_NAMES, NULL, SDDS_STRING, NULL)) {
366 case SDDS_CHECK_OKAY:
367 OldStringColumnsDefined = 1;
368 break;
369 case SDDS_CHECK_NONEXISTENT:
370 break;
371 case SDDS_CHECK_WRONGTYPE:
372 case SDDS_CHECK_WRONGUNITS:
373 fprintf(stderr, "Error: Parameter OldStringColumns has incorrect type or units.\n");
374 exit(EXIT_FAILURE);
375 break;
376 }
377
378 if (OldStringColumnsDefined) {
379 /* Decompose OldStringColumns into names of string columns for the output file */
380 if (!SDDS_GetParameter(&inputPage, OLD_STRING_COLUMN_NAMES, &inputStringRows))
381 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
382
383 if (verbose) {
384 fprintf(stderr, "Parameter OldStringColumns: %s.\n", inputStringRows);
385 }
386
387 outputStringColumnName = (char **)malloc(sizeof(char *));
388 outputStringColumns = 0;
389 buffer_size = BUFFER_SIZE_INCREMENT;
390 buffer = (char *)malloc(sizeof(char) * buffer_size);
391 while (0 <= (token_length = SDDS_GetToken(inputStringRows, buffer, BUFFER_SIZE_INCREMENT))) {
392 if (!token_length)
393 SDDS_Bomb("A null string was detected in parameter OldStringColumns.");
394
395 if (!SDDS_CopyString(&outputStringColumnName[outputStringColumns], buffer))
396 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
397
398 if (verbose) {
399 fprintf(stderr, "Output string column: %s\n", outputStringColumnName[outputStringColumns]);
400 }
401 outputStringColumns++;
402 }
403 }
404 }
405
406 /*********************
407 * Define output page
408 *********************/
409 if (ipage == 1) {
410 outputRows = inputDoubleColumns;
411 outputDoubleColumns = inputRows;
412
413 if (inputDescription) {
414 outputDescription = (char *)malloc(sizeof(char) * (strlen("Transpose of ") + strlen(inputDescription) + 1));
415 strcpy(outputDescription, "Transpose of ");
416 strcat(outputDescription, inputDescription);
417 if (!SDDS_InitializeOutput(&outputPage, ascii ? SDDS_ASCII : SDDS_BINARY, 1, outputDescription, inputContents, outputfile))
418 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
419 free(outputDescription);
420 } else {
421 if (!SDDS_InitializeOutput(&outputPage, ascii ? SDDS_ASCII : SDDS_BINARY, 1, NULL, NULL, outputfile))
422 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
423 }
424
425 SDDS_DeferSavingLayout(&outputPage, 1);
426
427 if (columnMajorOrder != -1)
428 outputPage.layout.data_mode.column_major = columnMajorOrder;
429 else
430 outputPage.layout.data_mode.column_major = inputPage.layout.data_mode.column_major;
431
432 /***********************************
433 * Define names for numerical columns
434 ***********************************/
435 if (!Root && inputStringColumns) {
436 /* Use specified string column, or first string column encountered */
437 if (!newColumnNamesColumn)
438 /* First string column encountered */
439 outputDoubleColumnName = (char **)SDDS_GetColumn(&inputPage, inputStringColumnName[0]);
440 else {
441 /* Use specified string column */
442 if (SDDS_CheckColumn(&inputPage, newColumnNamesColumn, NULL, SDDS_STRING, stderr) != SDDS_CHECK_OKAY)
443 SDDS_Bomb("Column specified with -newColumnNames does not exist in input file.");
444 outputDoubleColumnName = (char **)SDDS_GetColumn(&inputPage, newColumnNamesColumn);
445 }
446
447 for (i = 1; i < inputRows; i++) {
448 if (match_string(outputDoubleColumnName[i - 1], outputDoubleColumnName + i, inputRows - i, EXACT_MATCH) >= 0) {
449 fprintf(stderr, "Error: Duplicate column name '%s' found in input file string column '%s'. Cannot be used as output column names.\n",
450 outputDoubleColumnName[i - 1], newColumnNamesColumn ? newColumnNamesColumn : inputStringColumnName[0]);
451 exit(EXIT_FAILURE);
452 }
453 }
454 } else {
455 /* Use command line options to generate column names in the output file */
456 outputDoubleColumnName = (char **)malloc(outputDoubleColumns * sizeof(char *));
457 digits = MAX(digits, (long)(log10(inputRows) + 1));
458 if (!Root) {
459 Root = (char *)malloc(sizeof(char) * (strlen("Column") + 1));
460 strcpy(Root, "Column");
461 }
462 if (outputDoubleColumns != 1) {
463 for (i = 0; i < outputDoubleColumns; i++) {
464 outputDoubleColumnName[i] = (char *)malloc(sizeof(char) * (strlen(Root) + digits + 1));
465 sprintf(format, "%s%%0%ldld", Root, digits);
466 sprintf(outputDoubleColumnName[i], format, i);
467 }
468 } else { /* Only one row to transpose */
469 outputDoubleColumnName[0] = (char *)malloc(sizeof(char) * (strlen(Root) + 1));
470 strcpy(outputDoubleColumnName[0], Root);
471 }
472 }
473
474 /*************************
475 * Define string columns
476 *************************/
477 if (OldStringColumnsDefined) {
478 if (!SDDS_DefineSimpleColumns(&outputPage, outputStringColumns, outputStringColumnName, NULL, SDDS_STRING))
479 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
480 } else {
481 /* By default, at least one string column should exist for old column names */
482 if (!noOldColumnNamesColumn) {
483 outputStringColumns = 1;
484 outputStringColumnName = (char **)malloc(sizeof(char *));
485 if (oldColumnNames) {
486 /* Command line option specification */
487 outputStringColumnName[0] = oldColumnNames;
488 } else {
489 outputStringColumnName[0] = (char *)malloc(sizeof(char) * (strlen("OldColumnNames") + 1));
490 strcpy(outputStringColumnName[0], "OldColumnNames");
491 }
492 if (0 > SDDS_DefineColumn(&outputPage, outputStringColumnName[0], NULL, NULL, NULL, NULL, SDDS_STRING, 0))
493 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
494 }
495 }
496
497 if (indexColumn && !SDDS_DefineSimpleColumn(&outputPage, "Index", NULL, SDDS_LONG))
498 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
499
500 /*************************
501 * Define numerical columns
502 *************************/
503 for (i = 0; i < outputDoubleColumns; i++) {
504 if (Symbol) {
505 if (0 > SDDS_DefineColumn(&outputPage, outputDoubleColumnName[i], Symbol, NULL, NULL, NULL, SDDS_DOUBLE, 0))
506 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
507 } else {
508 if (0 > SDDS_DefineColumn(&outputPage, outputDoubleColumnName[i], NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0))
509 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
510 }
511 }
512
513 /********************************
514 * Define string parameters
515 * i.e., transposed string columns
516 ********************************/
517 if (inputStringColumns > 1) {
518 if (0 > SDDS_DefineParameter(&outputPage, OLD_STRING_COLUMN_NAMES, NULL, NULL, "Transposed string columns", NULL, SDDS_STRING, NULL))
519 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
520 for (i = 0; i < inputStringColumns; i++) {
521 if (0 > SDDS_DefineParameter(&outputPage, inputStringColumnName[i], NULL, NULL, "Transposed string column data", NULL, SDDS_STRING, NULL))
522 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
523 }
524 }
525
526 /*************************
527 * Transfer other parameters
528 *************************/
529 if (inputParameters) {
530 for (i = 0; i < inputParameters; i++) {
531 if ((0 > match_string(inputParameterName[i], outputStringColumnName, outputStringColumns, 0) &&
532 strcasecmp(inputParameterName[i], OLD_STRING_COLUMN_NAMES))) {
533 if (0 > SDDS_TransferParameterDefinition(&outputPage, &inputPage, inputParameterName[i], NULL))
534 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
535 }
536 }
537 }
538
539 /***************
540 * Write layout
541 ***************/
542 SDDS_DeferSavingLayout(&outputPage, 0);
543
544 /* If InputFile is not already transferred to the output file, then create it */
545 switch (SDDS_CheckParameter(&outputPage, "InputFile", NULL, SDDS_STRING, NULL)) {
546 case SDDS_CHECK_NONEXISTENT:
547 if (0 > SDDS_DefineParameter(&outputPage, "InputFile", NULL, NULL, "Original matrix file", NULL, SDDS_STRING, NULL))
548 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
549 break;
550 default:
551 break;
552 }
553
554 if (!SDDS_WriteLayout(&outputPage))
555 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
556 }
557
558#if defined(DEBUG)
559 fprintf(stderr, "Table layout defined\n");
560#endif
561
562 if (!SDDS_StartTable(&outputPage, outputRows))
563 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
564 if (ipage == 1) {
565 if (!SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, "InputFile", inputfile ? inputfile : "pipe", NULL))
566 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
567 }
568
569 /***************************************
570 * Assign string columns from input
571 * to string parameters in output
572 ***************************************/
573 if (inputStringColumns > 1) {
574 for (i = 0; i < inputStringColumns; i++) {
575 columnOfStrings = (char **)SDDS_GetColumn(&inputPage, inputStringColumnName[i]);
576 stringParameter = JoinStrings(columnOfStrings, inputRows, BUFFER_SIZE_INCREMENT);
577 if (!SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, inputStringColumnName[i], stringParameter, NULL))
578 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
579 free(columnOfStrings);
580 free(stringParameter);
581 }
582 outputStringRows = JoinStrings(inputStringColumnName, inputStringColumns, BUFFER_SIZE_INCREMENT);
583 if (!SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, OLD_STRING_COLUMN_NAMES, outputStringRows, NULL))
584 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
585 }
586
587#if defined(DEBUG)
588 fprintf(stderr, "String parameters assigned\n");
589#endif
590
591 if (inputParameters) {
592 for (i = 0; i < inputParameters; i++) {
593 if ((0 > match_string(inputParameterName[i], outputStringColumnName, outputStringColumns, 0) &&
594 strcasecmp(inputParameterName[i], OLD_STRING_COLUMN_NAMES))) {
595 parameterPointer = (void *)SDDS_GetParameter(&inputPage, inputParameterName[i], NULL);
596 if (!SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, inputParameterName[i], parameterPointer, NULL))
597 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
598 free(parameterPointer);
599 }
600 }
601 }
602
603#if defined(DEBUG)
604 fprintf(stderr, "Input parameters assigned\n");
605#endif
606
607 /**********************************
608 * Assign data to output table part
609 * of data set
610 **********************************/
611 if (outputRows) {
612 /***************************
613 * Assign string column data
614 ***************************/
615 if (OldStringColumnsDefined) {
616 for (i = 0; i < outputStringColumns; i++) {
617 if (!SDDS_GetParameter(&inputPage, outputStringColumnName[i], &stringParameter))
618 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
619 stringArray = TokenizeString(stringParameter, outputRows);
620 if (!SDDS_SetColumn(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, stringArray, outputRows, outputStringColumnName[i]))
621 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
622 free(stringArray);
623 }
624 } else {
625 if (!noOldColumnNamesColumn &&
626 !SDDS_SetColumn(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, inputDoubleColumnName, outputRows, outputStringColumnName[0]))
627 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
628 }
629
630#if defined(DEBUG)
631 fprintf(stderr, "String data columns assigned\n");
632#endif
633
634 /***************************
635 * Assign numerical column data
636 ***************************/
637 for (i = 0; i < outputDoubleColumns; i++) /* i is the row index */
638 if (!SDDS_SetColumn(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, RInv->a[i], outputRows, outputDoubleColumnName[i]))
639 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
640
641 if (indexColumn) {
642 for (i = 0; i < outputRows; i++)
643 if (!SDDS_SetRowValues(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, i, "Index", i, NULL))
644 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
645 }
646
647#if defined(DEBUG)
648 fprintf(stderr, "Numerical data columns assigned\n");
649#endif
650 }
651
652#if defined(DEBUG)
653 fprintf(stderr, "Data assigned\n");
654#endif
655
656 if (!SDDS_WriteTable(&outputPage))
657 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
658
659#if defined(DEBUG)
660 fprintf(stderr, "Data written out\n");
661#endif
662 }
663
664 if (inputDoubleColumns) {
665 m_free(&RInv);
666 m_free(&R);
667 }
668 if (inputColumnName) {
669 SDDS_FreeStringArray(inputColumnName, inputColumns);
670 free(inputColumnName);
671 }
672 if (inputStringColumns)
673 free(inputStringColumnName);
674 if (inputDescription)
675 free(inputDescription);
676 if (inputParameterName) {
677 SDDS_FreeStringArray(inputParameterName, inputParameters);
678 free(inputParameterName);
679 }
680 if (outputDoubleColumns) {
681 SDDS_FreeStringArray(outputDoubleColumnName, outputDoubleColumns);
682 free(outputDoubleColumnName);
683 }
684
685 if (!SDDS_Terminate(&inputPage))
686 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
687 if (ipage > 0) {
688 if (!SDDS_Terminate(&outputPage))
689 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
690 }
691 if (tmpfile_used && !replaceFileAndBackUp(inputfile, outputfile))
692 exit(EXIT_FAILURE);
693
694 return EXIT_SUCCESS;
695}
696
697char **TokenizeString(char *source, long n_items) {
698 char *buffer;
699 long buflen;
700 char *ptr;
701 char **string_array;
702 long i;
703
704 if (!source)
705 return NULL;
706 ptr = source;
707 string_array = (char **)malloc(sizeof(char *) * n_items);
708 buflen = strlen(source) + 1;
709 buffer = (char *)malloc(sizeof(char) * buflen);
710 for (i = 0; i < n_items; i++) {
711 if (SDDS_GetToken(ptr, buffer, buflen) != -1)
712 SDDS_CopyString(&string_array[i], buffer);
713 else
714 SDDS_CopyString(&string_array[i], "");
715 }
716 free(buffer);
717 return string_array;
718}
719
720char *JoinStrings(char **source, long n_items, long buflen_increment) {
721 char *buffer;
722 char *ptr;
723 long buffer_size, bufferLeft, bufferUsed;
724 long i, slen;
725 char *sptr;
726
727 buffer_size = buflen_increment;
728 buffer = (char *)malloc(sizeof(char) * buffer_size);
729 buffer[0] = '\0';
730 ptr = buffer;
731 bufferLeft = buffer_size - 2;
732 bufferUsed = 0;
733 for (i = 0; i < n_items; i++) {
734 sptr = source[i];
735 slen = strlen(sptr);
736 while ((slen + 5) > bufferLeft) {
737 buffer = trealloc(buffer, sizeof(char) * (buffer_size += buflen_increment));
738 bufferLeft += buflen_increment;
739 ptr = buffer + bufferUsed;
740 }
741 if (i) {
742 slen++;
743 *ptr++ = ' ';
744 }
745 *ptr++ = '"';
746 while (*sptr)
747 *ptr++ = *sptr++;
748 *ptr++ = '"';
749 *ptr = '\0';
750 bufferLeft -= slen + 2;
751 bufferUsed += slen + 2;
752 }
753
754 return buffer;
755}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
void SDDS_DeferSavingLayout(SDDS_DATASET *SDDS_dataset, int32_t mode)
Definition SDDS_copy.c:603
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
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.
void * SDDS_GetParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name, void *memory)
Retrieves the value of a specified parameter from the current data table of a data set.
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_DefineSimpleColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data column within the SDDS dataset.
int32_t SDDS_DefineSimpleColumns(SDDS_DATASET *SDDS_dataset, int32_t number, char **name, char **unit, int32_t type)
Defines multiple simple data columns of the same data type within the SDDS 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.
int32_t SDDS_TransferParameterDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers a parameter 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_GetParameterNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all parameters in the SDDS 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.
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_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
int32_t SDDS_GetToken(char *s, char *buffer, int32_t buflen)
Extracts the next token from a string, handling quoted substrings and escape characters.
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.
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_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#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
Utility functions for SDDS dataset manipulation and string array operations.
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
Definition array.c:181
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
int get_long(long *iptr, char *s)
Parses a long integer value from the given string.
Definition data_scan.c:255
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
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.