SDDSlib
Loading...
Searching...
No Matches
tek2sdds.c
1/*************************************************************************\
2 * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * This file is distributed subject to a Software License Agreement found
7 * in the file LICENSE that is included with this distribution.
8\*************************************************************************/
9
10/* program: tek2sdds.c
11 * purpose: converts a waveform from a Tektronix scope to
12 * SDDS format
13 *
14 * M. Borland, 1994
15 $Log: not supported by cvs2svn $
16 Revision 1.5 2001/01/23 19:14:59 soliday
17 Standardized usage message.
18
19 Revision 1.4 1999/05/25 19:18:07 soliday
20 Removed compiler warning on linux.
21
22 Revision 1.3 1999/01/06 19:55:01 borland
23 Fixed the version number in the usage message.
24
25 * Revision 1.2 1995/09/06 14:57:27 saunders
26 * First test release of SDDS1.5
27 *
28 */
29#include "mdb.h"
30#include "SDDS.h"
31#include "scan.h"
32#include "match_string.h"
33
34#define SET_SIGNAL_NAME 0
35#define SET_DESCRIPTION 1
36#define SET_MPL_LABELS 2
37#define SET_MAJOR_ORDER 3
38#define N_OPTIONS 4
39
40static char *option[N_OPTIONS] = {
41 "signalname",
42 "description",
43 "mpllabels",
44 "majorOrder",
45};
46
47char *USAGE = "tek2sdds <inputfile> <outputfile>\n\
48 -signalname=<name>\n\
49 [-description=<text>,<contents>]\n\
50 [-mpllabels=<title>,<topline>] [-majorOrder=row|column] \n\n\
51This program converts Tektronix ASCII format waveforms to SDDS format.\n\n\
52Program by Michael Borland (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
53
54typedef struct
55{
56 char *TEK_name, *SDDS_name, *value_string;
57 long type;
59
60#define TEK_PARAMETERS 23
61TEK_PARAMETER TEK_parameter[TEK_PARAMETERS] = {
62 {"ACSTATE", "ACStart", NULL, SDDS_STRING},
63 {"NR.PT", "Points", NULL, SDDS_LONG},
64 {"WFID", "WaveformID", NULL, SDDS_STRING},
65 {"XMULT", "XMultiplier", NULL, SDDS_DOUBLE},
66 {"LABEL", "TekLabel", NULL, SDDS_STRING},
67 {"TIME", "TimeStamp", NULL, SDDS_STRING},
68 {"DATE", "DateStamp", NULL, SDDS_STRING},
69 {"TSTIME", "TSTime", NULL, SDDS_DOUBLE},
70 {"XINCR", "XIncrement", NULL, SDDS_DOUBLE},
71 {"XZERO", "XZero", NULL, SDDS_DOUBLE},
72 {"XUNIT", "XUnits", NULL, SDDS_STRING},
73 {"YUNIT", "YUnits", NULL, SDDS_STRING},
74 {"YZERO", "YZero", NULL, SDDS_DOUBLE},
75 {"YMULT", "YMultiplier", NULL, SDDS_DOUBLE},
76 {"ENCDG", "Encoding", NULL, SDDS_STRING},
77 {"BYT/NR", "TEKBytesPerNumber", NULL, SDDS_LONG},
78 {"BYT.OR", "TEKByteOrder", NULL, SDDS_STRING},
79 {NULL, NULL, NULL, 0},
80};
81
82char *TEK_PreambleString = "WFMPRE ";
83char *TEK_DataMarker = "CURVE ";
84char *TEK_PointsName = "NR.PT";
85char *TEK_XIncrementName = "XINCR";
86char *TEK_XZeroName = "XZERO";
87char *TEK_XUnitsName = "XUNIT";
88char *TEK_YUnitsName = "YUNIT";
89char *TEK_YZeroName = "YZERO";
90char *TEK_YMultiplierName = "YMULT";
91char *TEK_EncodingName = "ENCDG";
92char *TEK_BytesPerNumberName = "BYT/NR";
93char *TEK_ByteOrderName = "BYT.OR";
94
95#define BUFSIZE 256
96
97long GetNextItem(char *buffer, long bufsize, FILE *fpi);
98
99int main(int argc, char **argv) {
100 SDDS_TABLE SDDS_table;
101 SCANNED_ARG *scanned;
102 long i, i_arg, index, points, bytes_per_number;
103 //long lsb_first;
104 char *input, *output, buffer[BUFSIZE];
105 char *signal_name, *ptr, *parameter_name;
106 char *mpl_title, *mpl_topline, *descrip_text, *descrip_contents;
107 FILE *fpi;
108 long code, binary;
109 double xIncrement, xZero, yMultiplier, yZero;
110 char *xUnits, *yUnits;
111 double *time, *data;
112 short columnMajorOrder = 0;
113 unsigned long majorOrderFlag;
114
115 xUnits = yUnits = NULL;
116
117 argc = scanargs(&scanned, argc, argv);
118 if (argc < 3)
119 bomb(NULL, USAGE);
120
121 input = output = signal_name = NULL;
122 mpl_title = mpl_topline = descrip_text = descrip_contents = NULL;
123 binary = 0;
124
125 for (i_arg = 1; i_arg < argc; i_arg++) {
126 if (scanned[i_arg].arg_type == OPTION) {
127 delete_chars(scanned[i_arg].list[0], "_");
128 /* process options here */
129 switch (match_string(scanned[i_arg].list[0], option, N_OPTIONS, 0)) {
130 case SET_MAJOR_ORDER:
131 majorOrderFlag = 0;
132 scanned[i_arg].n_items--;
133 if (scanned[i_arg].n_items > 0 &&
134 (!scanItemList(&majorOrderFlag, scanned[i_arg].list + 1, &scanned[i_arg].n_items, 0,
135 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
136 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
137 SDDS_Bomb("invalid -majorOrder syntax/values");
138 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
139 columnMajorOrder = 1;
140 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
141 columnMajorOrder = 0;
142 break;
143 case SET_SIGNAL_NAME:
144 if (scanned[i_arg].n_items != 2)
145 bomb("invalid -signal_name syntax", USAGE);
146 signal_name = scanned[i_arg].list[1];
147 break;
148 case SET_DESCRIPTION:
149 if (scanned[i_arg].n_items != 3)
150 bomb("invalid -description syntax", USAGE);
151 descrip_text = scanned[i_arg].list[1];
152 descrip_contents = scanned[i_arg].list[2];
153 break;
154 case SET_MPL_LABELS:
155 if (scanned[i_arg].n_items != 3)
156 bomb("invalid -mpl_labels syntax", USAGE);
157 mpl_title = scanned[i_arg].list[1];
158 mpl_topline = scanned[i_arg].list[2];
159 break;
160 default:
161 bomb("invalid option seen", USAGE);
162 break;
163 }
164 } else {
165 if (!input)
166 input = scanned[i_arg].list[0];
167 else if (!output)
168 output = scanned[i_arg].list[0];
169 else
170 bomb("too many filenames", USAGE);
171 }
172 }
173 if (!input)
174 SDDS_Bomb("input file not seen");
175 if (!output)
176 SDDS_Bomb("output file not seen");
177 if (!signal_name)
178 signal_name = "V";
179
180 fpi = fopen_e(input, "r", 0);
181 if (fread(buffer, 1, strlen(TEK_PreambleString), fpi) != strlen(TEK_PreambleString) ||
182 strncmp(TEK_PreambleString, buffer, strlen(TEK_PreambleString)) != 0)
183 SDDS_Bomb("file does not appear to be in Tektronix format");
184
185 parameter_name = buffer;
186 while ((code = GetNextItem(buffer, BUFSIZE, fpi)) < 3) {
187 if (!(ptr = strchr(buffer, ':')))
188 SDDS_Bomb("error parsing input file--missing colon on parameter tag");
189 *ptr++ = 0;
190 if (strcmp(TEK_DataMarker, parameter_name) == 0)
191 break;
192 index = 0;
193 while (TEK_parameter[index].TEK_name) {
194 if (strcmp(TEK_parameter[index].TEK_name, parameter_name) == 0)
195 break;
196 index++;
197 }
198 if (!TEK_parameter[index].TEK_name) {
199 fprintf(stderr, "warning: parameter %s is not recognized\n", parameter_name);
200 continue;
201 }
202 if (TEK_parameter[index].value_string) {
203 fprintf(stderr, "error: duplicate entries for parameter %s\n", parameter_name);
204 exit(1);
205 }
207 SDDS_CopyString(&TEK_parameter[index].value_string, ptr);
208 if (code == 2 || code == 3)
209 break;
210 }
211 if (code != 2)
212 SDDS_Bomb("unexpected end of file");
213
214 if (fread(buffer, 1, strlen(TEK_DataMarker), fpi) != strlen(TEK_DataMarker) ||
215 strncmp(TEK_DataMarker, buffer, strlen(TEK_DataMarker)) != 0)
216 SDDS_Bomb("CURVE item missing or not in right place");
217
218 if (!SDDS_InitializeOutput(&SDDS_table, SDDS_BINARY, 0, descrip_text, descrip_contents, output))
219 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
220 SDDS_table.layout.data_mode.column_major = columnMajorOrder;
221
222 index = 0;
223 while (TEK_parameter[index].TEK_name) {
224 if (!TEK_parameter[index].value_string) {
225 index++;
226 continue;
227 }
228 if (strcmp(TEK_parameter[index].TEK_name, TEK_XIncrementName) == 0) {
229 if (sscanf(TEK_parameter[index].value_string, "%lf", &xIncrement) != 1)
230 SDDS_Bomb("unable to scan value for x increment");
231 } else if (strcmp(TEK_parameter[index].TEK_name, TEK_XZeroName) == 0) {
232 if (sscanf(TEK_parameter[index].value_string, "%lf", &xZero) != 1)
233 SDDS_Bomb("unable to scan value for x zero");
234 } else if (strcmp(TEK_parameter[index].TEK_name, TEK_YZeroName) == 0) {
235 if (sscanf(TEK_parameter[index].value_string, "%lf", &yZero) != 1)
236 SDDS_Bomb("unable to scan value for y zero");
237 } else if (strcmp(TEK_parameter[index].TEK_name, TEK_YMultiplierName) == 0) {
238 if (sscanf(TEK_parameter[index].value_string, "%lf", &yMultiplier) != 1)
239 SDDS_Bomb("unable to scan value for y multiplier");
240 } else if (strcmp(TEK_parameter[index].TEK_name, TEK_XUnitsName) == 0) {
241 xUnits = TEK_parameter[index].value_string;
242 str_tolower(xUnits);
243 } else if (strcmp(TEK_parameter[index].TEK_name, TEK_YUnitsName) == 0) {
244 yUnits = TEK_parameter[index].value_string;
245 str_tolower(yUnits);
246 } else if (strcmp(TEK_parameter[index].TEK_name, TEK_PointsName) == 0) {
247 if (sscanf(TEK_parameter[index].value_string, "%ld", &points) != 1)
248 SDDS_Bomb("unable to scan value for number of points");
249 } else if (strcmp(TEK_parameter[index].TEK_name, TEK_EncodingName) == 0) {
250 if (strcmp(TEK_parameter[index].value_string, "ASCII") == 0)
251 binary = 0;
252 else if (strcmp(TEK_parameter[index].value_string, "BINARY") == 0)
253 binary = 1;
254 else
255 SDDS_Bomb("data encoding is neither ASCII nor BINARY");
256 } else if (strcmp(TEK_parameter[index].TEK_name, TEK_BytesPerNumberName) == 0) {
257 if (sscanf(TEK_parameter[index].value_string, "%ld", &bytes_per_number) != 1)
258 SDDS_Bomb("unable to scan value bytes per number");
259 } else if (strcmp(TEK_parameter[index].TEK_name, TEK_ByteOrderName) == 0) {
260 //lsb_first = 1;
261 if (strcmp(TEK_parameter[index].value_string, "LSB") != 0) {
262 //lsb_first = 0;
263 }
264 }
265 if (SDDS_DefineParameter(&SDDS_table, TEK_parameter[index].SDDS_name, NULL, NULL, TEK_parameter[index].TEK_name,
266 NULL, TEK_parameter[index].type, TEK_parameter[index].value_string) < 0)
267 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
268 index++;
269 }
270
271 if (mpl_title &&
272 (SDDS_DefineParameter(&SDDS_table, "mplTitle", NULL, NULL, NULL, NULL, SDDS_STRING, mpl_title) < 0 ||
273 SDDS_DefineParameter(&SDDS_table, "mplTopline", NULL, NULL, NULL, NULL, SDDS_STRING, mpl_topline) < 0))
274 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
275
276 if (SDDS_DefineColumn(&SDDS_table, "t", NULL, xUnits, NULL, NULL, SDDS_DOUBLE, 0) < 0 ||
277 SDDS_DefineColumn(&SDDS_table, signal_name, NULL, yUnits, NULL, NULL, SDDS_DOUBLE, 0) < 0 ||
278 !SDDS_WriteLayout(&SDDS_table) || !SDDS_StartTable(&SDDS_table, points))
279 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
280
281 data = tmalloc(sizeof(*data) * points);
282 time = tmalloc(sizeof(*time) * points);
283 if (!binary) {
284 for (i = 0; i < points; i++) {
285
286 if (!(code = GetNextItem(buffer, BUFSIZE, fpi)))
287 SDDS_Bomb("insufficient data in input file");
288 if (code == 4) {
289 points = i;
290 break;
291 }
292 time[i] = xZero + i * xIncrement;
293 if (sscanf(buffer, "%lf", data + i) != 1)
294 SDDS_Bomb("invalid data in input file");
295 data[i] = yZero + data[i] * yMultiplier;
296 }
297 } else {
298 short sdata;
299 fread(buffer, sizeof(char), 4, fpi);
300 for (i = 0; i < points; i++) {
301 if (fread(&sdata, sizeof(sdata), 1, fpi) != 1) {
302 fprintf(stderr, "file ends unexpectedly\n");
303 points = i;
304 break;
305 }
306 time[i] = xZero + i * xIncrement;
307 data[i] = sdata;
308 data[i] = yZero + data[i] * yMultiplier;
309 }
310 }
311
312 if (!SDDS_SetColumn(&SDDS_table, SDDS_SET_BY_NAME, time, points, "t") ||
313 !SDDS_SetColumn(&SDDS_table, SDDS_SET_BY_NAME, data, points, signal_name) ||
314 !SDDS_WriteTable(&SDDS_table) ||
315 !SDDS_Terminate(&SDDS_table))
316 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
317 return (0);
318}
319
320long GetNextItem(char *buffer, long bufsize, FILE *fpi) {
321 long i;
322 char c;
323
324 i = c = 0;
325 while (i < bufsize && (c = getc(fpi)) != EOF) {
326 if (c == ',' || c == ';' || c == '%')
327 break;
328 buffer[i++] = c;
329 }
330 if (c == EOF && i == 0)
331 return 0;
332 buffer[i] = 0;
333 if (c == ',')
334 return 1;
335 if (c == ';')
336 return 2;
337 if (c == EOF)
338 return 3;
339 fprintf(stderr, "warning: invalid data seen--ignoring\n");
340 return 4;
341}
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_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.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
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
void SDDS_RemovePadding(char *s)
Removes leading and trailing whitespace from a string.
#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
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
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.
char * str_tolower(char *s)
Convert a string to lower case.
Definition str_tolower.c:27