SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
agilentArb2sdds.c
Go to the documentation of this file.
1/**
2 * @file agilentArb2sdds.c
3 * @brief Converts Agilent Arbitrary Waveform files to SDDS format.
4 *
5 * @details
6 * This program reads Agilent Arbitrary Waveform files and converts them into
7 * SDDS (Self Describing Data Set) format. It supports various output options
8 * such as ASCII or binary formats, inclusion of an index column, and output
9 * precision (float or double).
10 *
11 * @section Usage
12 * ```
13 * agilentArb2sdds [<inputFile>] [<outputFile>]
14 * [-pipe[=in][,out]]
15 * [-ascii | -binary]
16 * [-withIndex]
17 * [-float | -double]
18 * [-dumpHeader]
19 * ```
20 *
21 * @section Options
22 * | Optional | Description |
23 * |----------|-------------------------------------------------------------------|
24 * | `-pipe` | Enable pipe mode with optional input and output pipes. |
25 * | `-ascii` | Request SDDS ASCII output. Default unless `-binary` is specified. |
26 * | `-binary`| Request SDDS binary output. |
27 * | `-withIndex`| Add an Index column to the output. |
28 * | `-float` | Output data in float format. Default is double precision. |
29 * | `-double`| Output data in double format. |
30 * | `-dumpHeader`| Output SDDS header information. |
31 *
32 * @subsection Incompatibilities
33 * - `-ascii` is incompatible with `-binary`.
34 * - `-float` is incompatible with `-double`.
35 *
36 * @copyright
37 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
38 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
39 *
40 * @license
41 * This file is distributed under the terms of the Software License Agreement
42 * found in the file LICENSE included with this distribution.
43 *
44 * @author
45 * R. Soliday
46 */
47
48#include <mdb.h>
49#include <SDDS.h>
50#include <scan.h>
51#if defined(_WIN32)
52# include <io.h>
53# include <fcntl.h>
54#endif
55
56/* Enumeration for option types */
57enum option_type {
58 SET_ASCII,
59 SET_BINARY,
60 SET_PIPE,
61 SET_WITHINDEX,
62 SET_FLOAT,
63 SET_DOUBLE,
64 N_OPTIONS
65};
66
67char *option[N_OPTIONS] = {
68 "ascii",
69 "binary",
70 "pipe",
71 "withindex",
72 "float",
73 "double"
74};
75
76char *USAGE =
77 "Usage: agilentArb2sdds [<inputFile>] [<outputFile>]\n"
78 " [-pipe[=in][,out]]\n"
79 " [-ascii | -binary]\n"
80 " [-withIndex]\n"
81 " [-float | -double]\n"
82 " [-dumpHeader]\n"
83 "Options:\n"
84 " -pipe[=in][,out] Enable pipe mode with optional input and output pipes.\n"
85 " -ascii Request SDDS ASCII output. Default is binary.\n"
86 " -binary Request SDDS BINARY output.\n"
87 " -withIndex Add an Index column to the output.\n"
88 " -float Output data in float format. Default is double.\n"
89 " -double Output data in double format.\n"
90 " -dumpHeader \n\n"
91 "Converts Agilent Arbitrary Waveform files to SDDS.\n"
92 "Program by Robert Soliday. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
93
94#define MAX_NUM_POINTS 100001
95
96int main(int argc, char *argv[]) {
97 SCANNED_ARG *scanned;
98 long iArg;
99 int ascii = 0, withIndex = 0, floatValues = 0;
100 unsigned long pipeFlags = 0;
101 char *input = NULL, *output = NULL;
102 FILE *fd;
103 SDDS_DATASET SDDSout;
104
105 long points;
106 short waveform[2 * MAX_NUM_POINTS];
107 char *pChar;
108 char buf;
109 int i;
110 double *IwaveIn;
111 double *QwaveIn;
112 int32_t *index = NULL;
113
115 argc = scanargs(&scanned, argc, argv);
116 if (argc < 2) {
117 fprintf(stderr, "%s", USAGE);
118 return EXIT_FAILURE;
119 }
120
121 for (iArg = 1; iArg < argc; iArg++) {
122 if (scanned[iArg].arg_type == OPTION) {
123 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
124 case SET_ASCII:
125 ascii = 1;
126 break;
127 case SET_BINARY:
128 ascii = 0;
129 break;
130 case SET_WITHINDEX:
131 withIndex = 1;
132 break;
133 case SET_FLOAT:
134 floatValues = 1;
135 break;
136 case SET_DOUBLE:
137 floatValues = 0;
138 break;
139 case SET_PIPE:
140 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags)) {
141 fprintf(stderr, "Error: Invalid -pipe syntax.\n");
142 fprintf(stderr, "%s", USAGE);
143 return EXIT_FAILURE;
144 }
145 break;
146 default:
147 fprintf(stderr, "Error: Invalid option '%s'.\n", scanned[iArg].list[0]);
148 fprintf(stderr, "%s", USAGE);
149 return EXIT_FAILURE;
150 }
151 } else {
152 if (!input)
153 input = scanned[iArg].list[0];
154 else if (!output)
155 output = scanned[iArg].list[0];
156 else {
157 fprintf(stderr, "Error: Too many filenames provided.\n");
158 fprintf(stderr, "%s", USAGE);
159 return EXIT_FAILURE;
160 }
161 }
162 }
163
164 processFilenames("agilentArb2sdds", &input, &output, pipeFlags, 0, NULL);
165
166 if (input) {
167 if (!fexists(input)) {
168 fprintf(stderr, "Error: Input file '%s' not found.\n", input);
169 return EXIT_FAILURE;
170 }
171 if (!(fd = fopen(input, "rb"))) {
172 fprintf(stderr, "Error: Unable to open input file '%s'.\n", input);
173 return EXIT_FAILURE;
174 }
175 } else {
176#if defined(_WIN32)
177 if (_setmode(_fileno(stdin), _O_BINARY) == -1) {
178 fprintf(stderr, "Error: Unable to set stdin to binary mode.\n");
179 return EXIT_FAILURE;
180 }
181#endif
182 fd = stdin;
183 }
184
185 points = fread((void *)waveform, sizeof(short), MAX_NUM_POINTS * 2, fd);
186 if (points == MAX_NUM_POINTS * 2) {
187 fprintf(stderr, "Error: Number of points in the waveform exceeds the maximum (%d).\n", MAX_NUM_POINTS);
188 return EXIT_FAILURE;
189 }
190 fclose(fd);
191
193 pChar = (char *)&waveform[0];
194 for (i = 0; i < points; i++) {
195 buf = *pChar;
196 *pChar = *(pChar + 1);
197 *(pChar + 1) = buf;
198 pChar += 2;
199 }
200 }
201
202 points = points / 2;
203 IwaveIn = malloc(sizeof(double) * points);
204 QwaveIn = malloc(sizeof(double) * points);
205 if (!IwaveIn || !QwaveIn) {
206 fprintf(stderr, "Error: Memory allocation failed for waveform data.\n");
207 return EXIT_FAILURE;
208 }
209
210 for (i = 0; i < points; i++) {
211 IwaveIn[i] = waveform[2 * i] / 32767.0;
212 QwaveIn[i] = waveform[2 * i + 1] / 32767.0;
213 }
214
215 if (withIndex) {
216 index = malloc(sizeof(int32_t) * points);
217 if (!index) {
218 fprintf(stderr, "Error: Memory allocation failed for index data.\n");
219 return EXIT_FAILURE;
220 }
221 for (i = 0; i < points; i++) {
222 index[i] = i;
223 }
224 }
225
226 if (!SDDS_InitializeOutput(&SDDSout, ascii ? SDDS_ASCII : SDDS_BINARY, 1, NULL, NULL, output)) {
227 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
228 return EXIT_FAILURE;
229 }
230
231 if (withIndex) {
232 if (!SDDS_DefineSimpleColumn(&SDDSout, "Index", NULL, SDDS_LONG)) {
233 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
234 return EXIT_FAILURE;
235 }
236 }
237
238 if (!SDDS_DefineSimpleColumn(&SDDSout, "I", NULL, floatValues ? SDDS_FLOAT : SDDS_DOUBLE)) {
239 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
240 return EXIT_FAILURE;
241 }
242
243 if (!SDDS_DefineSimpleColumn(&SDDSout, "Q", NULL, floatValues ? SDDS_FLOAT : SDDS_DOUBLE)) {
244 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
245 return EXIT_FAILURE;
246 }
247
248 if (!SDDS_WriteLayout(&SDDSout)) {
249 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
250 return EXIT_FAILURE;
251 }
252
253 if (!SDDS_StartTable(&SDDSout, points)) {
254 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
255 return EXIT_FAILURE;
256 }
257
258 if (withIndex) {
259 if (!SDDS_SetColumnFromLongs(&SDDSout, SDDS_SET_BY_NAME, index, points, "Index")) {
260 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
261 return EXIT_FAILURE;
262 }
263 }
264
265 if (!SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, IwaveIn, points, "I")) {
266 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
267 return EXIT_FAILURE;
268 }
269
270 if (!SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_NAME, QwaveIn, points, "Q")) {
271 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
272 return EXIT_FAILURE;
273 }
274
275 if (!SDDS_WriteTable(&SDDSout)) {
276 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
277 return EXIT_FAILURE;
278 }
279
280 if (!SDDS_Terminate(&SDDSout)) {
281 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
282 return EXIT_FAILURE;
283 }
284
285 if (withIndex)
286 free(index);
287 free_scanargs(&scanned, argc);
288 free(IwaveIn);
289 free(QwaveIn);
290
291 return EXIT_SUCCESS;
292}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_SetColumnFromDoubles(SDDS_DATASET *SDDS_dataset, int32_t mode, double *data, int64_t rows,...)
Sets the values for a single data column using double-precision floating-point numbers.
int32_t SDDS_SetColumnFromLongs(SDDS_DATASET *SDDS_dataset, int32_t mode, int32_t *data, int64_t rows,...)
Sets the values for a single data column using long integer numbers.
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_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
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_IsBigEndianMachine()
Determines whether the current machine uses big-endian byte ordering.
#define SDDS_FLOAT
Identifier for the float data type.
Definition SDDStypes.h:43
#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
long fexists(const char *filename)
Checks if a file exists.
Definition fexists.c:27
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
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584