SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
raw2sdds.c
Go to the documentation of this file.
1/**
2 * @file raw2sdds.c
3 * @brief Converts a binary raw data stream to SDDS format.
4 *
5 * @details
6 * This program reads a binary raw data file and converts it into the SDDS format, widely used for storing and sharing scientific data.
7 * Users can define the structure of the SDDS columns, specify the data size, and choose the major order for the output file.
8 *
9 * @section Usage
10 * ```
11 * raw2sdds <inputfile> <outputfile>
12 * -definition=<name>,<definition-entries>
13 * [-size=<horiz-pixels>,<vert-pixels>]
14 * [-majorOrder=row|column]
15 * ```
16 *
17 * @section Options
18 * | Required | Description |
19 * |---------------------------------------|---------------------------------------------------------------------------------------|
20 * | `-definition` | Defines the SDDS columns. Each definition entry must be in the form `<keyword>=<value>`. |
21 *
22 * | Optional | Description |
23 * |---------------------------------------|---------------------------------------------------------------------------------------|
24 * | `-size` | Specifies the horizontal and vertical size of the data in pixels. Defaults: 484x512. |
25 * | `-majorOrder` | Sets the major order for data storage. Defaults to `row`. |
26 *
27 * @subsection Incompatibilities
28 * - `-definition` requires the keyword `type=character`. Other data types are not yet supported.
29 *
30 * @copyright
31 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
32 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
33 *
34 * @license
35 * This file is distributed under the terms of the Software License Agreement
36 * found in the file LICENSE included with this distribution.
37 *
38 * @author
39 * M. Borland, C. Saunders, R. Soliday, H. Shang
40 */
41
42#include "mdb.h"
43#include "SDDS.h"
44#include "scan.h"
45#include "match_string.h"
46
47#define DEFAULT_HSIZE 484
48#define DEFAULT_VSIZE 512
49
50enum option_type {
51 SET_DEFINITION, /* Set the definition of SDDS columns */
52 SET_SIZE, /* Set the size of the data */
53 SET_MAJOR_ORDER, /* Set the major order (row or column) */
54 N_OPTIONS /* Number of options */
55};
56
57char *option[N_OPTIONS] = {
58 "definition",
59 "size",
60 "majorOrder"
61};
62
63char *USAGE =
64 "Usage: raw2sdds <inputfile> <outputfile>\n"
65 " -definition=<name>,<definition-entries>\n"
66 " [-size=<horiz-pixels>,<vert-pixels>] \n"
67 " [-majorOrder=row|column]\n"
68 "Options:\n"
69 " -definition=<name>,<definition-entries>\n"
70 " Defines the SDDS columns. Each definition entry should be in the form <keyword>=<value>.\n"
71 " Example: -definition=Data,type=character\n\n"
72 " -size=<horiz-pixels>,<vert-pixels>\n"
73 " Specifies the horizontal and vertical size of the data in pixels.\n"
74 " Defaults are 484 horizontally and 512 vertically if not specified.\n"
75 " Example: -size=800,600\n\n"
76 " -majorOrder=row|column\n"
77 " Sets the major order of the output file data. Choose 'row' for row-major order or 'column' for column-major order.\n"
78 " Defaults to row-major if not specified.\n"
79 " Example: -majorOrder=column\n\n"
80 "raw2sdds converts a binary data stream to SDDS format. The definition entries are of the form <keyword>=<value>,\n"
81 "where the keyword is any valid field name for an SDDS column.\n\n"
82 "Program by Michael Borland (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
83
84char *process_column_definition(char **argv, long argc);
85
86int main(int argc, char **argv) {
87 SDDS_TABLE SDDS_table;
88 SCANNED_ARG *scanned;
89 unsigned long majorOrderFlag;
90 long i_arg;
91 char *input, *output, *definition;
92 long hsize, vsize;
93 char *data, *data_name;
94 char ts1[100], ts2[100];
95 FILE *fpi;
96 short columnMajorOrder = 0;
97
98 argc = scanargs(&scanned, argc, argv);
99 if (argc < 3) {
100 fprintf(stderr, "%s", USAGE);
101 return EXIT_FAILURE;
102 }
103
104 input = output = data_name = NULL;
105 hsize = DEFAULT_HSIZE;
106 vsize = DEFAULT_VSIZE;
107 definition = NULL;
108
109 for (i_arg = 1; i_arg < argc; i_arg++) {
110 if (scanned[i_arg].arg_type == OPTION) {
111 /* Process options here */
112 switch (match_string(scanned[i_arg].list[0], option, N_OPTIONS, 0)) {
113 case SET_MAJOR_ORDER:
114 majorOrderFlag = 0;
115 scanned[i_arg].n_items--;
116 if (scanned[i_arg].n_items > 0 &&
117 (!scanItemList(&majorOrderFlag, scanned[i_arg].list + 1, &scanned[i_arg].n_items,
118 0, "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
119 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL))) {
120 fprintf(stderr, "Error: Invalid -majorOrder syntax or values.\n");
121 return EXIT_FAILURE;
122 }
123 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
124 columnMajorOrder = 1;
125 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
126 columnMajorOrder = 0;
127 break;
128
129 case SET_DEFINITION:
130 if (scanned[i_arg].n_items < 2) {
131 fprintf(stderr, "Error: -definition requires at least a name and one definition entry.\n");
132 fprintf(stderr, "%s", USAGE);
133 return EXIT_FAILURE;
134 }
135 data_name = scanned[i_arg].list[1];
136 definition = process_column_definition(scanned[i_arg].list + 1, scanned[i_arg].n_items - 1);
137 if (!definition) {
138 fprintf(stderr, "Error: Invalid column definition.\n");
139 return EXIT_FAILURE;
140 }
141 if (!strstr(definition, "type=character")) {
142 fprintf(stderr, "Error: Data type must be 'character' for now.\n");
143 return EXIT_FAILURE;
144 }
145 break;
146
147 case SET_SIZE:
148 if (scanned[i_arg].n_items != 3 ||
149 sscanf(scanned[i_arg].list[1], "%ld", &hsize) != 1 || hsize <= 0 ||
150 sscanf(scanned[i_arg].list[2], "%ld", &vsize) != 1 || vsize <= 0) {
151 fprintf(stderr, "Error: Invalid -size syntax.\n");
152 fprintf(stderr, "%s", USAGE);
153 return EXIT_FAILURE;
154 }
155 break;
156
157 default:
158 fprintf(stderr, "Error: Invalid option '%s'.\n", scanned[i_arg].list[0]);
159 fprintf(stderr, "%s", USAGE);
160 return EXIT_FAILURE;
161 }
162 } else {
163 if (!input)
164 input = scanned[i_arg].list[0];
165 else if (!output)
166 output = scanned[i_arg].list[0];
167 else {
168 fprintf(stderr, "Error: Too many filenames provided.\n");
169 fprintf(stderr, "%s", USAGE);
170 return EXIT_FAILURE;
171 }
172 }
173 }
174
175 if (!input) {
176 fprintf(stderr, "Error: Input file not specified.\n");
177 fprintf(stderr, "%s", USAGE);
178 return EXIT_FAILURE;
179 }
180
181 if (!output) {
182 fprintf(stderr, "Error: Output file not specified.\n");
183 fprintf(stderr, "%s", USAGE);
184 return EXIT_FAILURE;
185 }
186
187 if (!definition) {
188 fprintf(stderr, "Error: Column definition not specified.\n");
189 fprintf(stderr, "%s", USAGE);
190 return EXIT_FAILURE;
191 }
192
193 snprintf(ts1, sizeof(ts1), "%ld", hsize);
194 snprintf(ts2, sizeof(ts2), "%ld", vsize);
195
196 if (!SDDS_InitializeOutput(&SDDS_table, SDDS_BINARY, 0,
197 "Screen image from raw file", "screen image",
198 output) ||
199 SDDS_ProcessColumnString(&SDDS_table, definition, 0) < 0 ||
200 SDDS_DefineParameter(&SDDS_table, "NumberOfRows", NULL, NULL, "number of rows", NULL, SDDS_LONG, ts1) < 0 ||
201 SDDS_DefineParameter(&SDDS_table, "NumberOfColumns", NULL, NULL, "number of columns", NULL, SDDS_LONG, ts2) < 0) {
202 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
203 return EXIT_FAILURE;
204 }
205
206 SDDS_table.layout.data_mode.column_major = columnMajorOrder;
207
208 if (!SDDS_WriteLayout(&SDDS_table) || !SDDS_StartTable(&SDDS_table, hsize * vsize)) {
209 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
210 return EXIT_FAILURE;
211 }
212
213 data = tmalloc(sizeof(*data) * hsize * vsize);
214 fpi = fopen_e(input, "rb", 0);
215 if (fread(data, sizeof(*data), hsize * vsize, fpi) != (size_t)(hsize * vsize)) {
216 fclose(fpi);
217 fprintf(stderr, "Error: Unable to read all data from input file '%s'.\n", input);
218 return EXIT_FAILURE;
219 }
220 fclose(fpi);
221
222 if (!SDDS_SetColumn(&SDDS_table, SDDS_SET_BY_NAME, data, hsize * vsize, data_name) ||
223 !SDDS_WriteTable(&SDDS_table) ||
224 !SDDS_Terminate(&SDDS_table)) {
225 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
226 return EXIT_FAILURE;
227 }
228
229 free(data);
230 return EXIT_SUCCESS;
231}
232
233char *process_column_definition(char **argv, long argc) {
234 char buffer[SDDS_MAXLINE] = "&column name=";
235 char *ptr;
236 long i;
237
238 if (argc < 1)
239 return NULL;
240
241 strcat(buffer, argv[0]);
242 strcat(buffer, ", ");
243
244 for (i = 1; i < argc; i++) {
245 if (!strchr(argv[i], '=')) {
246 return NULL;
247 }
248 strcat(buffer, argv[i]);
249 strcat(buffer, ", ");
250 }
251
252 if (!strstr(buffer, "type=")) {
253 strcat(buffer, "type=character, ");
254 }
255
256 strcat(buffer, "&end");
257
258 cp_str(&ptr, buffer);
259 return ptr;
260}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
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_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_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_ProcessColumnString(SDDS_DATASET *SDDS_dataset, char *string, int32_t mode)
Process a column definition string.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
char * cp_str(char **s, char *t)
Copies a string, allocating memory for storage.
Definition cp_str.c:28
FILE * fopen_e(char *file, char *open_mode, long mode)
Opens a file with error checking, messages, and aborts.
Definition fopen_e.c:30
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 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.