SDDSlib
Loading...
Searching...
No Matches
sdds2mpl.c
Go to the documentation of this file.
1/**
2 * @file sdds2mpl.c
3 * @brief Converts SDDS data files into MPL format.
4 *
5 * This program reads data from SDDS (Self Describing Data Set) files and generates
6 * output files in MPL (MetaPost Language) format. It supports multiple options to
7 * configure input files, output formats, and page separation. The output includes
8 * parameters, columns, and arrays, which can be selectively extracted and labeled.
9 *
10 * ### Features:
11 * - Handles multiple input and output specifications.
12 * - Supports labeled parameters for detailed annotations.
13 * - Allows separation of data into multiple pages.
14 * - Provides command-line options for flexible data processing.
15 *
16 * ### Usage:
17 * ```
18 * sdds2mpl [-pipe[=input]] [<SDDSfilename>] [-rootname=<string>]
19 * -output={column|parameter},<x-name>,<y-name>[,{<sy-name>|<sx-name>,<sy-name>}]...
20 * [-labelParameters=<name>[=<format>]...] [-separatePages] [-announceOpenings]
21 * ```
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 M. Borland, C. Saunders, R. Soliday
32 */
33
34#include "mdb.h"
35#include "table.h"
36#include "scan.h"
37#include "SDDS.h"
38#include "SDDSaps.h"
39
40/* Enumeration for option types */
41enum option_type {
42 SET_ROOTNAME,
43 SET_OUTPUT,
44 SET_SEPARATE_PAGES,
45 SET_LABEL_PARAMETERS,
46 SET_ANNOUNCE_OPENINGS,
47 SET_PIPE,
48 N_OPTIONS
49};
50
51static char *option[N_OPTIONS] = {
52 "rootname",
53 "output",
54 "separatepages",
55 "labelparameters",
56 "announceopenings",
57 "pipe",
58};
59
60static const char *usage =
61 "sdds2mpl [-pipe[=input]] [<SDDSfilename>] [-rootname=<string>]\n"
62 "-output={column|parameter},<x-name>,<y-name>[,{<sy-name>|<sx-name>,<sy-name>}]...\n"
63 "[-labelParameters=<name>[=<format>]...] [-separatePages] [-announceOpenings]\n\n"
64 "Any number of -output specifications may be given.\n\n"
65 "sdds2mpl extracts data from an SDDS file into MPL-format files.\n"
66 "Program by Michael Borland. ("__DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
67
68int main(int argc, char **argv) {
69 SDDS_DATASET sdds_dataset;
70 LABEL_PARAMETER *label_parameter = NULL;
71 long label_parameters = 0;
72 COLUMN_DEFINITION **coldef;
73 PARAMETER_DEFINITION **pardef;
74 char *inputfile = NULL;
75 char *rootname = NULL;
76 char filename[200];
77 long outputs = 0;
78 OUTPUT_REQUEST **output = NULL;
79 long i, i_arg;
80 int64_t n_rows;
81 long page_number, separate_pages = 0;
82 long announce_openings = 0;
83 SCANNED_ARG *s_arg;
84 char *ptr;
85 void *data[4];
86 double param[4];
87 long data_present = 0;
88 unsigned long pipe_flags = 0;
89
90 argc = scanargs(&s_arg, argc, argv);
91 if (argc < 3) {
92 fputs(usage, stderr);
93 exit(EXIT_FAILURE);
94 }
95
96 for (i_arg = 1; i_arg < argc; i_arg++) {
97 if (s_arg[i_arg].arg_type == OPTION) {
98 delete_chars(s_arg[i_arg].list[0], "_");
99 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
100 case SET_ROOTNAME:
101 if (s_arg[i_arg].n_items != 2)
102 SDDS_Bomb("Invalid -rootname syntax");
103 rootname = s_arg[i_arg].list[1];
104 break;
105 case SET_OUTPUT:
106 if (s_arg[i_arg].n_items < 4 || s_arg[i_arg].n_items > 6)
107 SDDS_Bomb("Invalid -output syntax");
108 output = trealloc(output, sizeof(*output) * (outputs + 1));
109 if (!(output[outputs] = process_output_request(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, outputs ? output[outputs - 1] : NULL)))
110 SDDS_Bomb("Invalid -output syntax");
111 outputs++;
112 break;
113 case SET_SEPARATE_PAGES:
114 separate_pages = 1;
115 break;
116 case SET_LABEL_PARAMETERS:
117 if (s_arg[i_arg].n_items < 2)
118 SDDS_Bomb("Invalid -labelparameters syntax");
119 label_parameter = trealloc(label_parameter, sizeof(*label_parameter) * (label_parameters + s_arg[i_arg].n_items));
120 for (i = 1; i < s_arg[i_arg].n_items; i++)
121 scan_label_parameter(label_parameter + i - 1, s_arg[i_arg].list[i]);
122 label_parameters += s_arg[i_arg].n_items - 1;
123 break;
124 case SET_ANNOUNCE_OPENINGS:
125 announce_openings = 1;
126 break;
127 case SET_PIPE:
128 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipe_flags))
129 SDDS_Bomb("Invalid -pipe syntax");
130 break;
131 default:
132 SDDS_Bomb("Unknown switch");
133 break;
134 }
135 } else {
136 if (!inputfile)
137 inputfile = s_arg[i_arg].list[0];
138 else
139 SDDS_Bomb("Too many filenames");
140 }
141 }
142
143 if (!inputfile && !(pipe_flags & USE_STDIN))
144 SDDS_Bomb("No input source given");
145
146 if (!rootname) {
147 if (!inputfile)
148 SDDS_Bomb("You must give a rootname if you don't give an input filename");
149 SDDS_CopyString(&rootname, inputfile);
150 if ((ptr = strrchr(rootname, '.')))
151 *ptr = '\0';
152 }
153
154 if (outputs <= 0)
155 SDDS_Bomb("No output specifications given");
156
157 if (!SDDS_InitializeInput(&sdds_dataset, inputfile)) {
158 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
159 exit(EXIT_FAILURE);
160 }
161
162 for (i = 0; i < outputs; i++) {
163 if (!output[i]->parameter_output) {
164 if (SDDS_GetColumnIndex(&sdds_dataset, output[i]->item[0]) < 0 ||
165 SDDS_GetColumnIndex(&sdds_dataset, output[i]->item[1]) < 0 ||
166 (output[i]->item[2] && SDDS_GetColumnIndex(&sdds_dataset, output[i]->item[2]) < 0) ||
167 (output[i]->item[3] && SDDS_GetColumnIndex(&sdds_dataset, output[i]->item[3]) < 0)) {
168 fprintf(stderr, "Error: unrecognized column name given\n");
169 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
170 exit(EXIT_FAILURE);
171 }
172 } else {
173 if (SDDS_GetParameterIndex(&sdds_dataset, output[i]->item[0]) < 0 ||
174 SDDS_GetParameterIndex(&sdds_dataset, output[i]->item[1]) < 0 ||
175 (output[i]->item[2] && SDDS_GetParameterIndex(&sdds_dataset, output[i]->item[2]) < 0) ||
176 (output[i]->item[3] && SDDS_GetParameterIndex(&sdds_dataset, output[i]->item[3]) < 0)) {
177 fprintf(stderr, "Error: unrecognized parameter name given\n");
178 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
179 exit(EXIT_FAILURE);
180 }
181 }
182 }
183
184 while ((page_number = SDDS_ReadPage(&sdds_dataset)) > 0) {
185 data_present = 1;
186 if (!SDDS_SetRowFlags(&sdds_dataset, 1)) {
187 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
188 exit(EXIT_FAILURE);
189 }
190 if ((n_rows = SDDS_CountRowsOfInterest(&sdds_dataset)) <= 0) {
191 fprintf(stderr, "Warning: no rows selected for page %" PRId32 "\n", sdds_dataset.page_number);
193 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
194 }
195 for (i = 0; i < outputs; i++) {
196 if (!output[i]->fp) {
197 if (separate_pages && !output[i]->parameter_output)
198 snprintf(filename, sizeof(filename), "%s_%03ld_%s_%s.out", rootname, output[i]->counter++, output[i]->item[0], output[i]->item[1]);
199 else
200 snprintf(filename, sizeof(filename), "%s_%s_%s.out", rootname, output[i]->item[0], output[i]->item[1]);
201 set_up_output(filename, output[i], label_parameter, label_parameters, separate_pages, announce_openings, &sdds_dataset);
202 }
203 if (!output[i]->parameter_output) {
204 coldef = (COLUMN_DEFINITION **)output[i]->definitions;
205 data[2] = data[3] = NULL;
206 if (!(data[0] = SDDS_GetColumn(&sdds_dataset, output[i]->item[0])) ||
207 !(data[1] = SDDS_GetColumn(&sdds_dataset, output[i]->item[1])) ||
208 (output[i]->columns > 2 && !(data[2] = SDDS_GetColumn(&sdds_dataset, output[i]->item[2]))) ||
209 (output[i]->columns > 3 && !(data[3] = SDDS_GetColumn(&sdds_dataset, output[i]->item[3])))) {
210 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
211 exit(EXIT_FAILURE);
212 }
213 for (int64_t j = 0; j < n_rows; j++) {
214 for (long k = 0; k < output[i]->columns; k++) {
215 SDDS_PrintTypedValue((char *)data[k], j, coldef[k]->type, coldef[k]->format_string, output[i]->fp, 0);
216 if (k < output[i]->columns - 1)
217 fputc(' ', output[i]->fp);
218 }
219 fputc('\n', output[i]->fp);
220 }
221 output[i]->points += n_rows;
222 for (long k = 0; k < output[i]->columns; k++) {
223 free(data[k]);
224 }
225 } else {
226 pardef = (PARAMETER_DEFINITION **)output[i]->definitions;
227 for (long k = 0; k < output[i]->columns; k++) {
228 if (!SDDS_GetParameter(&sdds_dataset, output[i]->item[k], &param[k])) {
229 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
230 exit(EXIT_FAILURE);
231 }
232 }
233 output[i]->points += 1;
234 for (long k = 0; k < output[i]->columns; k++) {
235 SDDS_PrintTypedValue((char *)&param[k], 0, pardef[k]->type, pardef[k]->format_string, output[i]->fp, 0);
236 if (k < output[i]->columns - 1)
237 fputc(' ', output[i]->fp);
238 }
239 fputc('\n', output[i]->fp);
240 }
241 if (separate_pages && !output[i]->parameter_output) {
242 fclose(output[i]->fp);
243 output[i]->fp = NULL;
244 output[i]->points = 0;
245 }
246 }
247 }
248
249 if (page_number == 0) {
250 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
251 exit(EXIT_FAILURE);
252 }
253 if (page_number == -1 && !data_present) {
254 if (SDDS_NumberOfErrors()) {
255 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
256 exit(EXIT_FAILURE);
257 }
258 fprintf(stderr, "Error: input data file is empty\n");
259 exit(EXIT_FAILURE);
260 }
261
262 for (i = 0; i < outputs; i++) {
263 if (output[i]->fp)
264 fclose(output[i]->fp);
265 }
266
267 for (i = 0; i < outputs; i++) {
268 if (!separate_pages || output[i]->parameter_output) {
269 snprintf(filename, sizeof(filename), "%s_%s_%s.out", rootname, output[i]->item[0], output[i]->item[1]);
270 fixcount(filename, output[i]->points);
271 }
272 }
273 return 0;
274}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
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_SetRowFlags(SDDS_DATASET *SDDS_dataset, int32_t row_flag_value)
Sets the acceptance flags for all rows in the current data table of a data set.
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_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_GetParameterIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named parameter in the SDDS dataset.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column 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
int32_t SDDS_NumberOfErrors()
Retrieves the number of errors recorded by SDDS library routines.
Definition SDDS_utils.c:304
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
int32_t SDDS_PrintTypedValue(void *data, int64_t index, int32_t type, char *format, FILE *fp, uint32_t mode)
Prints a data value of a specified type using an optional printf format string.
Definition SDDS_utils.c:59
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
Definition array.c:181
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
int fixcount(char *filename, long n_points)
Updates the data point count in a specified file.
Definition fixcounts.c:33
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