SDDSlib
Loading...
Searching...
No Matches
sdds2agilentArb.c
Go to the documentation of this file.
1/**
2 * @file sdds2agilentArb.c
3 * @brief Converts SDDS files to Agilent Arbitrary Waveform files.
4 *
5 * This program reads an SDDS file, extracts the "I" and "Q" floating-point
6 * columns, scales the data, and writes the results to an output file in a
7 * binary format compatible with Agilent arbitrary waveform generators.
8 *
9 * ## Features:
10 * - Supports input and output via pipes.
11 * - Automatically scales the waveform data to fit the [-32767, 32767] range.
12 * - Handles little-endian to big-endian conversion if needed.
13 *
14 * ## Usage:
15 * sdds2agilentArb [<inputFile>] [<outputFile>] [-pipe[=in][,out]]
16 *
17 * ## Example:
18 * sdds2agilentArb input.sdds output.wfm
19 *
20 * ## Options:
21 * - `-pipe`: Use pipes for input/output.
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 R. Soliday
32 */
33
34#include "SDDS.h"
35#include "mdb.h"
36#include "scan.h"
37#if defined(_WIN32)
38# include <io.h>
39# include <fcntl.h>
40#endif
41
42/* Enumeration for option types */
43enum option_type {
44 SET_PIPE,
45 N_OPTIONS
46};
47
48char *option[N_OPTIONS] =
49 {
50 "pipe"
51 };
52
53char *usage =
54 "sdds2agilentArb [<inputFile>] [<outputFile>] [-pipe[=in][,out]]\n\n"
55 "Converts SDDS to Agilent Arbitrary Waveform files.\n"
56 "Program by Robert Soliday. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
57
58int main(int argc, char *argv[]) {
59 SCANNED_ARG *scanned;
60 long i_arg;
61 unsigned long pipe_flags = 0;
62 char *input = NULL, *output = NULL;
63 FILE *fd;
64 SDDS_DATASET sdds_dataset;
65
66 long points;
67 double *i_wave;
68 double *q_wave;
69 double max_amp = 0;
70 double min_amp = 0;
71 int i;
72 double scale;
73 short *waveform = NULL;
74 char buf;
75 char *p_char;
76
78 argc = scanargs(&scanned, argc, argv);
79 if (argc < 2) {
80 fprintf(stderr, "%s", usage);
81 return 1;
82 }
83 for (i_arg = 1; i_arg < argc; i_arg++) {
84 if (scanned[i_arg].arg_type == OPTION) {
85 switch (match_string(scanned[i_arg].list[0], option, N_OPTIONS, 0)) {
86 case SET_PIPE:
87 if (!processPipeOption(scanned[i_arg].list + 1,
88 scanned[i_arg].n_items - 1, &pipe_flags)) {
89 fprintf(stderr, "invalid -pipe syntax\n");
90 return 1;
91 }
92 break;
93 default:
94 fprintf(stderr, "invalid option seen\n");
95 fprintf(stderr, "%s", usage);
96 return 1;
97 }
98 } else {
99 if (!input)
100 input = scanned[i_arg].list[0];
101 else if (!output)
102 output = scanned[i_arg].list[0];
103 else {
104 fprintf(stderr, "too many filenames\n");
105 fprintf(stderr, "%s", usage);
106 return 1;
107 }
108 }
109 }
110 processFilenames("sdds2agilentArb", &input, &output, pipe_flags, 0, NULL);
111
112 if (!SDDS_InitializeInput(&sdds_dataset, input)) {
113 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
114 }
115 if ((SDDS_CheckColumn(&sdds_dataset, "I", NULL, SDDS_ANY_FLOATING_TYPE,
116 NULL)) != SDDS_CHECK_OKAY) {
117 fprintf(stderr, "error: Floating type column named I does not exist\n");
118 return 1;
119 }
120 if ((SDDS_CheckColumn(&sdds_dataset, "Q", NULL, SDDS_ANY_FLOATING_TYPE,
121 NULL)) != SDDS_CHECK_OKAY) {
122 fprintf(stderr, "error: Floating type column named Q does not exist\n");
123 return 1;
124 }
125
126 if (SDDS_ReadTable(&sdds_dataset) != 1) {
127 fprintf(stderr, "error: No data found in SDDS file\n");
128 return 1;
129 }
130 points = SDDS_RowCount(&sdds_dataset);
131
132 i_wave = SDDS_GetColumnInDoubles(&sdds_dataset, "I");
133 q_wave = SDDS_GetColumnInDoubles(&sdds_dataset, "Q");
134 if (!SDDS_Terminate(&sdds_dataset)) {
135 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
136 exit(1);
137 }
138
139 max_amp = i_wave[0];
140 min_amp = i_wave[0];
141 for (i = 0; i < points; i++) {
142 if (max_amp < i_wave[i])
143 max_amp = i_wave[i];
144 else if (min_amp > i_wave[i])
145 min_amp = i_wave[i];
146 if (max_amp < q_wave[i])
147 max_amp = q_wave[i];
148 else if (min_amp > q_wave[i])
149 min_amp = q_wave[i];
150 }
151 max_amp = fabs(max_amp);
152 min_amp = fabs(min_amp);
153 if (min_amp > max_amp)
154 max_amp = min_amp;
155
156 scale = 32767 / max_amp;
157 waveform = malloc(sizeof(short) * points * 2);
158 for (i = 0; i < points; i++) {
159 waveform[2 * i] = (short)floor(i_wave[i] * scale + 0.5);
160 waveform[2 * i + 1] = (short)floor(q_wave[i] * scale + 0.5);
161 }
162 free(i_wave);
163 free(q_wave);
164
166 p_char = (char *)&waveform[0];
167 for (i = 0; i < 2 * points; i++) {
168 buf = *p_char;
169 *p_char = *(p_char + 1);
170 *(p_char + 1) = buf;
171 p_char += 2;
172 }
173 }
174
175 if (!output) {
176#if defined(_WIN32)
177 if (_setmode(_fileno(stdout), _O_BINARY) == -1) {
178 fprintf(stderr, "error: unable to set stdout to binary mode\n");
179 exit(1);
180 }
181#endif
182 fd = stdout;
183 } else {
184 fd = fopen(output, "wb");
185 }
186 if (fd == NULL) {
187 fprintf(stderr, "unable to open output file for writing\n");
188 exit(1);
189 }
190 fwrite((void *)waveform, sizeof(short), points * 2, fd);
191 fclose(fd);
192 if (waveform)
193 free(waveform);
194 free_scanargs(&scanned, argc);
195
196 return 0;
197}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
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_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.
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_ANY_FLOATING_TYPE
Special identifier used by SDDS_Check*() routines to accept any floating-point type.
Definition SDDStypes.h:165
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