SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
tdms2sdds.c File Reference

Detailed Description

Converts National Instruments' LabVIEW TDMS files to SDDS format.

This program reads National Instruments' LabVIEW TDMS (Technical Data Management Streaming) files and converts them into SDDS (Self Describing Data Sets) format. It supports customization of output, including ASCII or binary formats, segmentation, and other advanced features for better data management.

Usage

tdms2sdds <inputFile> [<outputFile>]
[-pipe=out]
[-ascii | -binary]
[-numOfSegments]
[-segment=<integer>]

Options

Optional Description
-pipe SDDS toolkit pipe option.
-ascii Requests SDDS ASCII output (default).
-binary Requests SDDS binary output.
-numOfSegments Prints the number of TDMS segments in the input file.
-segment Specifies a particular segment to convert.

Incompatibilities

  • Only one of the following may be specified:
    • -ascii
    • -binary
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
R. Soliday, M. Borland

Definition in file tdms2sdds.c.

#include "mdb.h"
#include "SDDS.h"
#include "scan.h"

Go to the source code of this file.

Functions

void TDMS_ReadLeadIn (FILE *fd, TDMS_SEGMENT *segment)
 
void TDMS_ReadMetaData (FILE *fd, TDMS_SEGMENT *segment)
 
void TDMS_ReadRawData (FILE *fd, TDMS_FILE *tdms, uint32_t n_segment, long filesize)
 
void TDMS_GetValue (FILE *fd, void **value, int32_t datatype)
 
int main (int argc, char **argv)
 

Function Documentation

◆ main()

int main ( int argc,
char ** argv )

Definition at line 200 of file tdms2sdds.c.

200 {
201 FILE *fd;
202 char *input = NULL, *output = NULL;
203 SDDS_DATASET SDDSout;
204 SCANNED_ARG *scanned;
205 long iArg;
206 long ascii = 0;
207 unsigned long pipeFlags = 0;
208 int i = 0, n, found, ii, jj, kk, segment = 0, querySegments = 0;
209 long double timeValue;
210 short timeDefined = 0;
211 char buffer[1024];
212
213 TDMS_FILE tdms;
214 uint64_t rows = 0, j = 0, k;
215
217 argc = scanargs(&scanned, argc, argv);
218 if (argc < 2) {
219 fprintf(stderr, "%s", USAGE);
220 return (EXIT_FAILURE);
221 }
222
223 for (iArg = 1; iArg < argc; iArg++) {
224 if (scanned[iArg].arg_type == OPTION) {
225 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
226 case SET_ASCII:
227 ascii = 1;
228 break;
229 case SET_BINARY:
230 ascii = 0;
231 break;
232 case SET_SEGMENT:
233 if (scanned[iArg].n_items < 2) {
234 fprintf(stderr, "Error (%s): invalid -segment syntax\n", argv[0]);
235 return (EXIT_FAILURE);
236 }
237 if (sscanf(scanned[iArg].list[1], "%d", &segment) != 1 || segment <= 0) {
238 fprintf(stderr, "Error (%s): invalid -segment syntax or value\n", argv[0]);
239 return (EXIT_FAILURE);
240 }
241 break;
242 case SET_NUMOFSEGMENTS:
243 querySegments = 1;
244 break;
245 case SET_PIPE:
246 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags)) {
247 fprintf(stderr, "invalid -pipe syntax\n");
248 return (EXIT_FAILURE);
249 }
250 break;
251 default:
252 fprintf(stderr, "invalid option seen\n");
253 fprintf(stderr, "%s", USAGE);
254 return (EXIT_FAILURE);
255 }
256 } else {
257 if (!input)
258 input = scanned[iArg].list[0];
259 else if (!output)
260 output = scanned[iArg].list[0];
261 else {
262 fprintf(stderr, "too many filenames\n");
263 fprintf(stderr, "%s", USAGE);
264 return (EXIT_FAILURE);
265 }
266 }
267 }
268 if (!querySegments) {
269 processFilenames("tdms2sdds", &input, &output, pipeFlags, 0, NULL);
270 }
271
272 if (input) {
273 if (!fexists(input)) {
274 fprintf(stderr, "input file not found\n");
275 return (EXIT_FAILURE);
276 }
277 if (!(fd = fopen(input, "rb"))) {
278 fprintf(stderr, "problem opening input file\n");
279 return (EXIT_FAILURE);
280 }
281 } else {
282 fprintf(stderr, "tdms2sdds cannot -pipe=in tdms files\n");
283 return (EXIT_FAILURE);
284 }
285
286 fseek(fd, 0L, SEEK_END);
287 tdms.filesize = ftell(fd);
288 fseek(fd, 0L, SEEK_SET);
289
290 tdms.n_segments = 0;
291 while (ftell(fd) < tdms.filesize) {
292 tdms.n_segments++;
293 if (tdms.n_segments == 1) {
294 tdms.segment = malloc(sizeof(TDMS_SEGMENT));
295 } else {
296 tdms.segment = realloc(tdms.segment, sizeof(TDMS_SEGMENT) * tdms.n_segments);
297 }
298 /* Read Lead In */
299 TDMS_ReadLeadIn(fd, &(tdms.segment[tdms.n_segments - 1]));
300 if (tdms.segment[tdms.n_segments - 1].lead_in.toc & kTocBigEndian) {
302 fprintf(stderr, "tdms2sdds does not yet support reading from non-native endian TDMS files.\n");
303 return (EXIT_FAILURE);
304 }
305 } else {
307 fprintf(stderr, "tdms2sdds does not yet support reading from non-native endian TDMS files.\n");
308 return (EXIT_FAILURE);
309 }
310 }
311 /* Read Meta Data */
312 if (tdms.segment[tdms.n_segments - 1].lead_in.toc & kTocMetaData) {
313 TDMS_ReadMetaData(fd, &(tdms.segment[tdms.n_segments - 1]));
314 }
315 /* Read Raw Data */
316 if (tdms.segment[tdms.n_segments - 1].lead_in.toc & kTocRawData) {
317 TDMS_ReadRawData(fd, &tdms, tdms.n_segments - 1, tdms.filesize);
318 }
319 }
320 fclose(fd);
321
322 if (querySegments) {
323 fprintf(stdout, "Number of segments: %u\n", tdms.n_segments);
324 return (EXIT_SUCCESS);
325 }
326 if (!SDDS_InitializeOutput(&SDDSout, ascii ? SDDS_ASCII : SDDS_BINARY, 1, NULL, NULL, output)) {
327 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
328 return (EXIT_FAILURE);
329 }
330 if (input) {
331 if (SDDS_DefineParameter(&SDDSout, "TDMSfile", NULL, NULL, NULL, NULL, SDDS_STRING, input) == -1) {
332 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
333 return (EXIT_FAILURE);
334 }
335 }
336 if (segment > tdms.n_segments) {
337 fprintf(stderr, "tdms2sdds: Error: segment selected does not exist\n");
338 return (EXIT_FAILURE);
339 } else {
340 segment--;
341 }
342 for (i = 0; i < tdms.n_segments; i++) {
343 if ((segment != -1) && (segment != i)) {
344 continue;
345 }
346 for (j = 0; j < tdms.segment[i].raw_data.n_channels; j++) {
347 if (j == 0) {
348 rows = tdms.segment[i].raw_data.channel[j].n_values;
349 } else {
350 if (rows != tdms.segment[i].raw_data.channel[j].n_values) {
351 fprintf(stderr, "tdms2sdds: Error: channels in the same TDMS segment have different lengths which is not allowed in SDDS\n");
352 return (EXIT_FAILURE);
353 }
354 }
355 }
356 k = 0;
357 for (j = 0; j < tdms.segment[i].meta_data.n_objects; j++) {
358 found = 0;
359 for (n = 0; n < tdms.segment[i].meta_data.object[j].n_properties; n++) {
360 if (strcmp(tdms.segment[i].meta_data.object[j].property[n].name, "NI_ChannelName") == 0) {
361 found = 1;
362 strcpy(buffer, tdms.segment[i].meta_data.object[j].property[n].value);
363 break;
364 }
365 }
366 if (!found) {
367 strcpy(buffer, tdms.segment[i].meta_data.object[j].path);
368 }
369 if (!edit_string(buffer, "1Z/%g/ /_/%ga/a_a%g/\'//%g/(/[/%g/)/]/%g/=/_eq_/")) {
370 fprintf(stderr, "tdms2sdds: Error: problem editing column label\n");
371 return (EXIT_FAILURE);
372 }
373 /* Check for channel name that starts with a number and prepend a semicolon */
374 if (!(isalpha(*buffer) || strchr(".:", *buffer))) {
375 if (!edit_string(buffer, "i/:/")) {
376 fprintf(stderr, "tdms2sdds: Error: problem editing column label\n");
377 return (EXIT_FAILURE);
378 }
379 }
380 strcpy(tdms.segment[i].meta_data.object[j].path, buffer);
381 if (tdms.segment[i].meta_data.object[j].raw_data_index != 0xFFFFFFFF) {
382 tdms.segment[i].raw_data.channel[k].name = tdms.segment[i].meta_data.object[j].path;
383 tdms.segment[i].raw_data.channel[k].datatype = tdms.segment[i].meta_data.object[j].raw_data_datatype;
384 }
385 if (((segment == -1) && (i == 0)) || (segment != -1)) {
386 if (tdms.segment[i].meta_data.object[j].raw_data_index != 0xFFFFFFFF) {
387 if (timeDefined == 0) {
388 if (tdms.segment[i].xpart.samples > 0) {
389 if (tdms.segment[i].xpart.name == NULL) {
390 tdms.segment[i].xpart.name = malloc(5);
391 sprintf(tdms.segment[i].xpart.name, "Time");
392 }
393 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].xpart.name, tdms.segment[i].xpart.unit, SDDS_DOUBLE)) {
394 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
395 return (EXIT_FAILURE);
396 }
397 timeDefined = 1;
398 }
399 }
400 if ((tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeBoolean) ||
401 (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeU8) ||
402 (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeU16)) {
403 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].meta_data.object[j].path, NULL, SDDS_USHORT)) {
404 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
405 return (EXIT_FAILURE);
406 }
407 } else if ((tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeI8) ||
408 (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeI16)) {
409 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].meta_data.object[j].path, NULL, SDDS_SHORT)) {
410 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
411 return (EXIT_FAILURE);
412 }
413 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeI32) {
414 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].meta_data.object[j].path, NULL, SDDS_LONG)) {
415 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
416 return (EXIT_FAILURE);
417 }
418 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeU32) {
419 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].meta_data.object[j].path, NULL, SDDS_ULONG)) {
420 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
421 return (EXIT_FAILURE);
422 }
423 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeI64) {
424 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].meta_data.object[j].path, NULL, SDDS_LONG64)) {
425 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
426 return (EXIT_FAILURE);
427 }
428 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeU64) {
429 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].meta_data.object[j].path, NULL, SDDS_ULONG64)) {
430 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
431 return (EXIT_FAILURE);
432 }
433 } else if ((tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeSingleFloat) ||
434 (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeSingleFloatWithUnit)) {
435 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].meta_data.object[j].path, NULL, SDDS_FLOAT)) {
436 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
437 return (EXIT_FAILURE);
438 }
439 } else if ((tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeDoubleFloat) ||
440 (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeDoubleFloatWithUnit) ||
441 (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeTimeStamp)) {
442 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].meta_data.object[j].path, NULL, SDDS_DOUBLE)) {
443 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
444 return (EXIT_FAILURE);
445 }
446 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeString) {
447 fprintf(stderr, "tdms2sdds: string type channels are not yet supported in tdms2sdds\n");
448 return (EXIT_FAILURE);
449 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeVoid) {
450 fprintf(stderr, "tdms2sdds: void type channels are not yet supported in tdms2sdds\n");
451 return (EXIT_FAILURE);
452 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeExtendedFloat) {
453 fprintf(stderr, "tdms2sdds: extended float type channels are not yet supported in tdms2sdds\n");
454 return (EXIT_FAILURE);
455 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeExtendedFloatWithUnit) {
456 fprintf(stderr, "tdms2sdds: extended float with unit type channels are not yet supported in tdms2sdds\n");
457 return (EXIT_FAILURE);
458 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeDAQmxRawData) {
459 fprintf(stderr, "tdms2sdds: DAQmx raw data channels are not yet supported in tdms2sdds\n");
460 return (EXIT_FAILURE);
461 } else {
462 fprintf(stderr, "tdms2sdds: unknown data type\n");
463 return (EXIT_FAILURE);
464 }
465 }
466 for (n = 0; n < tdms.segment[i].meta_data.object[j].n_properties; n++) {
467 if (strcmp(tdms.segment[i].meta_data.object[j].property[n].name, "name") == 0) {
468 continue;
469 }
470 strcpy(buffer, tdms.segment[i].meta_data.object[j].property[n].name);
471 if (!edit_string(buffer, "%g/ /_/%g/\'//%g/(/[/%g/)/]/%g/=/_eq_/")) {
472 fprintf(stderr, "tdms2sdds: Error: problem editing column label\n");
473 return (EXIT_FAILURE);
474 }
475 /* Check for channel name that starts with a number and prepend a semicolon */
476 if (!(isalpha(*buffer) || strchr(".:", *buffer))) {
477 if (!edit_string(buffer, "i/:/")) {
478 fprintf(stderr, "tdms2sdds: Error: problem editing column label\n");
479 return (EXIT_FAILURE);
480 }
481 }
482 strcpy(tdms.segment[i].meta_data.object[j].property[n].name, buffer);
483
484 /* Check if additional channels have the same property names. Only include the first */
485 if (SDDS_GetParameterIndex(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name) != -1) {
487 continue;
488 }
489 if ((tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeBoolean) ||
490 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeU8) ||
491 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeU16)) {
492 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_USHORT)) {
493 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
494 return (EXIT_FAILURE);
495 }
496 } else if ((tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeI8) ||
497 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeI16)) {
498 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_SHORT)) {
499 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
500 return (EXIT_FAILURE);
501 }
502 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeI32) {
503 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_LONG)) {
504 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
505 return (EXIT_FAILURE);
506 }
507 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeU32) {
508 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_ULONG)) {
509 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
510 return (EXIT_FAILURE);
511 }
512 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeI64) {
513 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_LONG64)) {
514 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
515 return (EXIT_FAILURE);
516 }
517 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeU64) {
518 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_ULONG64)) {
519 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
520 return (EXIT_FAILURE);
521 }
522 } else if ((tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeSingleFloat) ||
523 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeSingleFloatWithUnit)) {
524 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_FLOAT)) {
525 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
526 return (EXIT_FAILURE);
527 }
528 } else if ((tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeDoubleFloat) ||
529 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeDoubleFloatWithUnit) ||
530 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeTimeStamp)) {
531 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_DOUBLE)) {
532 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
533 return (EXIT_FAILURE);
534 }
535 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeString) {
536 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_STRING)) {
537 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
538 return (EXIT_FAILURE);
539 }
540 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeVoid) {
541 fprintf(stderr, "tdms2sdds: void type parameters are not yet supported in tdms2sdds\n");
542 return (EXIT_FAILURE);
543 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeExtendedFloat) {
544 fprintf(stderr, "tdms2sdds: extended float type parameters are not yet supported in tdms2sdds\n");
545 return (EXIT_FAILURE);
546 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeExtendedFloatWithUnit) {
547 fprintf(stderr, "tdms2sdds: extended float with unit type parameters are not yet supported in tdms2sdds\n");
548 return (EXIT_FAILURE);
549 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeDAQmxRawData) {
550 fprintf(stderr, "tdms2sdds: DAQmx raw data parameters are not yet supported in tdms2sdds\n");
551 return (EXIT_FAILURE);
552 } else {
553 fprintf(stderr, "tdms2sdds: unknown data type\n");
554 return (EXIT_FAILURE);
555 }
556 }
557 }
558 if (tdms.segment[i].meta_data.object[j].raw_data_index != 0xFFFFFFFF) {
559 k++;
560 }
561 }
562 if (((segment == -1) && (i == 0)) || (segment != -1)) {
563 if (!SDDS_WriteLayout(&SDDSout)) {
564 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
565 return (EXIT_FAILURE);
566 }
567 }
568 if (!SDDS_StartTable(&SDDSout, rows)) {
569 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
570 return (EXIT_FAILURE);
571 }
572
573 if ((tdms.segment[i].xpart.name != NULL) &&
574 (tdms.segment[i].xpart.samples > 0) &&
575 (tdms.segment[i].raw_data.n_channels > 0)) {
576 timeValue = tdms.segment[i].xpart.start_time + tdms.segment[i].xpart.start_offset;
577 for (j = 0; j < rows; j++) {
578 if (!SDDS_SetRowValues(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, j, tdms.segment[i].xpart.name, (double)timeValue, NULL)) {
579 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
580 return (EXIT_FAILURE);
581 }
582 timeValue += tdms.segment[i].xpart.increment;
583 }
584 }
585 for (j = 0; j < tdms.segment[i].raw_data.n_channels; j++) {
586 if ((tdms.segment[i].raw_data.channel[j].datatype == tdsTypeI16) ||
587 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeU16) ||
588 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeI32) ||
589 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeU32) ||
590 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeI64) ||
591 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeU64) ||
592 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeSingleFloat) ||
593 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeSingleFloatWithUnit) ||
594 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeDoubleFloat) ||
595 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeDoubleFloatWithUnit) ||
596 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeTimeStamp)) {
597 if (!SDDS_SetColumn(&SDDSout, SDDS_SET_BY_NAME, tdms.segment[i].raw_data.channel[j].values,
598 tdms.segment[i].raw_data.channel[j].n_values, tdms.segment[i].raw_data.channel[j].name)) {
599 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
600 return (EXIT_FAILURE);
601 }
602 } else if ((tdms.segment[i].raw_data.channel[j].datatype == tdsTypeBoolean) ||
603 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeI8)) {
604 for (k = 0; k < rows; k++) {
605 if (!SDDS_SetRowValues(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, k,
606 tdms.segment[i].raw_data.channel[j].name,
607 (int16_t)(((int8_t *)(tdms.segment[i].raw_data.channel[j].values))[k]), NULL)) {
608 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
609 return (EXIT_FAILURE);
610 }
611 }
612 } else if (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeU8) {
613 for (k = 0; k < rows; k++) {
614 if (!SDDS_SetRowValues(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, k,
615 tdms.segment[i].raw_data.channel[j].name,
616 (uint16_t)(((uint8_t *)(tdms.segment[i].raw_data.channel[j].values))[k]), NULL)) {
617 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
618 return (EXIT_FAILURE);
619 }
620 }
621 } else if (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeString) {
622 fprintf(stderr, "tdms2sdds: string type channels are not yet supported in tdms2sdds\n");
623 return (EXIT_FAILURE);
624 } else if (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeVoid) {
625 fprintf(stderr, "tdms2sdds: void type channels are not yet supported in tdms2sdds\n");
626 return (EXIT_FAILURE);
627 } else if (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeExtendedFloat) {
628 fprintf(stderr, "tdms2sdds: extended float type channels are not yet supported in tdms2sdds\n");
629 return (EXIT_FAILURE);
630 } else if (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeExtendedFloatWithUnit) {
631 fprintf(stderr, "tdms2sdds: extended float with unit type channels are not yet supported in tdms2sdds\n");
632 return (EXIT_FAILURE);
633 } else if (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeDAQmxRawData) {
634 fprintf(stderr, "tdms2sdds: DAQmx raw data channels are not yet supported in tdms2sdds\n");
635 return (EXIT_FAILURE);
636 } else {
637 fprintf(stderr, "tdms2sdds: unknown data type\n");
638 return (EXIT_FAILURE);
639 }
640 }
641
642 for (j = 0; j < tdms.segment[i].meta_data.n_objects; j++) {
643 for (n = 0; n < tdms.segment[i].meta_data.object[j].n_properties; n++) {
644 /* Do not write parameter if it wasn't defined in the first segment */
645 if (SDDS_GetParameterIndex(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name) == -1) {
647 continue;
648 }
649 if ((tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeI16) ||
650 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeU16) ||
651 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeI32) ||
652 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeU32) ||
653 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeI64) ||
654 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeU64) ||
655 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeSingleFloat) ||
656 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeSingleFloatWithUnit) ||
657 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeDoubleFloat) ||
658 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeDoubleFloatWithUnit) ||
659 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeTimeStamp)) {
660 if (!SDDS_SetParameters(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE,
661 tdms.segment[i].meta_data.object[j].property[n].name,
662 tdms.segment[i].meta_data.object[j].property[n].value, NULL)) {
663 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
664 return (EXIT_FAILURE);
665 }
666 } else if ((tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeBoolean) ||
667 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeI8)) {
668 if (!SDDS_SetParameters(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE,
669 tdms.segment[i].meta_data.object[j].property[n].name,
670 (int16_t)(*(int8_t *)(tdms.segment[i].meta_data.object[j].property[n].value)), NULL)) {
671 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
672 return (EXIT_FAILURE);
673 }
674 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeU8) {
675 if (!SDDS_SetParameters(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE,
676 tdms.segment[i].meta_data.object[j].property[n].name,
677 (uint16_t)(*(uint8_t *)(tdms.segment[i].meta_data.object[j].property[n].value)), NULL)) {
678 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
679 return (EXIT_FAILURE);
680 }
681 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeString) {
682 if (!SDDS_SetParameters(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE,
683 tdms.segment[i].meta_data.object[j].property[n].name,
684 tdms.segment[i].meta_data.object[j].property[n].value, NULL)) {
685 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
686 return (EXIT_FAILURE);
687 }
688 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeVoid) {
689 fprintf(stderr, "tdms2sdds: void type parameters are not yet supported in tdms2sdds\n");
690 return (EXIT_FAILURE);
691 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeExtendedFloat) {
692 fprintf(stderr, "tdms2sdds: extended float type parameters are not yet supported in tdms2sdds\n");
693 return (EXIT_FAILURE);
694 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeExtendedFloatWithUnit) {
695 fprintf(stderr, "tdms2sdds: extended float with unit type parameters are not yet supported in tdms2sdds\n");
696 return (EXIT_FAILURE);
697 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeDAQmxRawData) {
698 fprintf(stderr, "tdms2sdds: DAQmx raw data parameters are not yet supported in tdms2sdds\n");
699 return (EXIT_FAILURE);
700 } else {
701 fprintf(stderr, "tdms2sdds: unknown data type\n");
702 return (EXIT_FAILURE);
703 }
704 }
705 }
706 if (!SDDS_WriteTable(&SDDSout)) {
707 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
708 return (EXIT_FAILURE);
709 }
710 }
711 if (!SDDS_Terminate(&SDDSout)) {
712 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
713 return (EXIT_FAILURE);
714 }
715
716 if (tdms.n_segments > 0) {
717 for (i = 0; i < tdms.n_segments; i++) {
718 if (tdms.segment[i].raw_data.n_channels > 0) {
719 for (j = 0; j < tdms.segment[i].raw_data.n_channels; j++) {
720 if (tdms.segment[i].raw_data.channel[j].n_values > 0) {
721 free(tdms.segment[i].raw_data.channel[j].values);
722 }
723 }
724 free(tdms.segment[i].raw_data.channel);
725 }
726 if (tdms.segment[i].meta_data.n_objects > 0) {
727 for (j = 0; j < tdms.segment[i].meta_data.n_objects; j++) {
728 if (tdms.segment[i].meta_data.object[j].path) {
729 free(tdms.segment[i].meta_data.object[j].path);
730 }
731 if (tdms.segment[i].meta_data.object[j].n_properties > 0) {
732 for (k = 0; k < tdms.segment[i].meta_data.object[j].n_properties; k++) {
733 if (tdms.segment[i].meta_data.object[j].property[k].name) {
734 for (ii = i + 1; ii < tdms.n_segments; ii++) {
735 for (jj = 0; jj < tdms.segment[ii].meta_data.n_objects; jj++) {
736 for (kk = 0; kk < tdms.segment[ii].meta_data.object[jj].n_properties; kk++) {
737 if (tdms.segment[i].meta_data.object[j].property[k].name == tdms.segment[ii].meta_data.object[jj].property[kk].name) {
738 tdms.segment[ii].meta_data.object[jj].property[kk].name = NULL;
739 tdms.segment[ii].meta_data.object[jj].property[kk].value = NULL;
740 }
741 }
742 }
743 }
744 free(tdms.segment[i].meta_data.object[j].property[k].name);
745 tdms.segment[i].meta_data.object[j].property[k].name = NULL;
746 }
747 if (tdms.segment[i].meta_data.object[j].property[k].value) {
748 free(tdms.segment[i].meta_data.object[j].property[k].value);
749 tdms.segment[i].meta_data.object[j].property[k].value = NULL;
750 }
751 }
752 free(tdms.segment[i].meta_data.object[j].property);
753 }
754 }
755 free(tdms.segment[i].meta_data.object);
756 }
757 }
758 free(tdms.segment);
759 }
760
761 free_scanargs(&scanned, argc);
762
763 return (EXIT_SUCCESS);
764}
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
int32_t SDDS_SetParameters(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
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_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_DefineSimpleParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data parameter 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.
int32_t SDDS_GetParameterIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named parameter 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
void SDDS_ClearErrors()
Clears all recorded error messages from the SDDS error stack.
Definition SDDS_utils.c:318
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.
long edit_string(char *text, char *edit)
Edits the provided text based on the specified edit commands.
Definition edit_string.c:75
#define SDDS_ULONG
Identifier for the unsigned 32-bit integer data type.
Definition SDDStypes.h:67
#define SDDS_FLOAT
Identifier for the float data type.
Definition SDDStypes.h:43
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_ULONG64
Identifier for the unsigned 64-bit integer data type.
Definition SDDStypes.h:55
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_SHORT
Identifier for the signed short integer data type.
Definition SDDStypes.h:73
#define SDDS_USHORT
Identifier for the unsigned short integer data type.
Definition SDDStypes.h:79
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
Definition SDDStypes.h:49
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

◆ TDMS_GetValue()

void TDMS_GetValue ( FILE * fd,
void ** value,
int32_t datatype )

Definition at line 1134 of file tdms2sdds.c.

1134 {
1135 uint64_t uLLong;
1136 int64_t LLong;
1137
1138 if (datatype == tdsTypeI8) {
1139 *value = malloc(sizeof(int8_t));
1140 fread(((int8_t *)(*value)), 1, 1, fd);
1141 } else if (datatype == tdsTypeU8) {
1142 *value = malloc(sizeof(uint8_t));
1143 fread(((uint8_t *)(*value)), 1, 1, fd);
1144 } else if (datatype == tdsTypeI16) {
1145 *value = malloc(sizeof(int16_t));
1146 fread(((int16_t *)(*value)), 1, 2, fd);
1147 } else if (datatype == tdsTypeU16) {
1148 *value = malloc(sizeof(uint16_t));
1149 fread(((uint16_t *)(*value)), 1, 2, fd);
1150 } else if (datatype == tdsTypeI32) {
1151 *value = malloc(sizeof(int32_t));
1152 fread(((int32_t *)(*value)), 1, 4, fd);
1153 } else if (datatype == tdsTypeU32) {
1154 *value = malloc(sizeof(uint32_t));
1155 fread(((uint32_t *)(*value)), 1, 4, fd);
1156 } else if (datatype == tdsTypeI64) {
1157 *value = malloc(sizeof(int64_t));
1158 fread(((int64_t *)(*value)), 1, 8, fd);
1159 } else if (datatype == tdsTypeU64) {
1160 *value = malloc(sizeof(uint64_t));
1161 fread(((uint64_t *)(*value)), 1, 8, fd);
1162 } else if ((datatype == tdsTypeSingleFloat) || (datatype == tdsTypeSingleFloatWithUnit)) {
1163 *value = malloc(sizeof(float));
1164 fread(((float *)(*value)), 1, 4, fd);
1165 } else if ((datatype == tdsTypeDoubleFloat) || (datatype == tdsTypeDoubleFloatWithUnit)) {
1166 *value = malloc(sizeof(double));
1167 fread(((double *)(*value)), 1, 8, fd);
1168 } else if (datatype == tdsTypeBoolean) {
1169 *value = malloc(sizeof(int8_t));
1170 fread(((int8_t *)(*value)), 1, 1, fd);
1171 } else if (datatype == tdsTypeTimeStamp) {
1172 *value = malloc(sizeof(double));
1173 fread(&uLLong, 1, 8, fd);
1174 fread(&LLong, 1, 8, fd);
1175 /*LLong = LLong - 2082844791LL; */ /* Subtract seconds between 1904 and 1970 */
1176 *((double *)(*value)) = LLong + (uLLong * 5.42101086242752217e-20);
1177 } else if (datatype == tdsTypeVoid) {
1178 fprintf(stderr, "tdms2sdds: datatype Void is not yet supported in tdms2sdds\n");
1179 exit(EXIT_FAILURE);
1180 } else if (datatype == tdsTypeExtendedFloat) {
1181 fprintf(stderr, "tdms2sdds: datatype ExtendedFloat is not yet supported in tdms2sdds\n");
1182 exit(EXIT_FAILURE);
1183 } else if (datatype == tdsTypeExtendedFloatWithUnit) {
1184 fprintf(stderr, "tdms2sdds: datatype ExtendedFloatWithUnit is not yet supported in tdms2sdds\n");
1185 exit(EXIT_FAILURE);
1186 } else if (datatype == tdsTypeDAQmxRawData) {
1187 fprintf(stderr, "tdms2sdds: datatype DAQmxRawData is not yet supported in tdms2sdds\n");
1188 exit(EXIT_FAILURE);
1189 } else {
1190 fprintf(stderr, "tdms2sdds: unknown data type\n");
1191 exit(EXIT_FAILURE);
1192 }
1193}

◆ TDMS_ReadLeadIn()

void TDMS_ReadLeadIn ( FILE * fd,
TDMS_SEGMENT * segment )

Definition at line 766 of file tdms2sdds.c.

766 {
767 char buffer[50];
768
769 fread(buffer, 1, 4, fd);
770 buffer[4] = '\0';
771 if (strcmp(buffer, "TDSm") != 0) {
772 fprintf(stderr, "tdms2sdds: Error: File does not start with TDSm\n");
773 exit(EXIT_FAILURE);
774 }
775 fread(&(segment->lead_in.toc), 1, 4, fd); /* TOC */
776 fread(&(segment->lead_in.version), 1, 4, fd); /* Version */
777 if (segment->lead_in.version == 4712) {
778 fprintf(stderr, "tdms2sdds: Error: TDMS version 1.0 files unsupported\n");
779 exit(EXIT_FAILURE);
780 }
781 if (segment->lead_in.version != 4713) {
782 fprintf(stderr, "tdms2sdds: Error: Unknown TDMS version\n");
783 exit(EXIT_FAILURE);
784 }
785 fread(&(segment->lead_in.next_segment_offset), 1, 8, fd); /* Next segment offset */
786 fread(&(segment->lead_in.raw_data_offset), 1, 8, fd); /* Raw data offset */
787}

◆ TDMS_ReadMetaData()

void TDMS_ReadMetaData ( FILE * fd,
TDMS_SEGMENT * segment )

Definition at line 789 of file tdms2sdds.c.

789 {
790 uint32_t uLong, i, j;
791
792 segment->xpart.name = NULL;
793 segment->xpart.unit = NULL;
794 segment->xpart.start_time = 0;
795 segment->xpart.start_offset = 0;
796 segment->xpart.increment = 0;
797 segment->xpart.samples = 0;
798 segment->xpart.time_pref = NULL;
799 segment->xpart.range = 0;
800
801 fread(&(segment->meta_data.n_objects), 1, 4, fd);
802
803 segment->meta_data.object = malloc(sizeof(TDMS_META_DATA_OBJECT) * segment->meta_data.n_objects);
804 for (i = 0; i < segment->meta_data.n_objects; i++) {
805 fread(&uLong, 1, 4, fd);
806 segment->meta_data.object[i].path = malloc(sizeof(char) * (uLong + 1));
807 fread(segment->meta_data.object[i].path, 1, uLong, fd);
808 segment->meta_data.object[i].path[uLong] = '\0';
809 fread(&(segment->meta_data.object[i].raw_data_index), 1, 4, fd);
810 if ((segment->meta_data.object[i].raw_data_index != 0xFFFFFFFF) && (segment->meta_data.object[i].raw_data_index != 0x00000000)) {
811 fread(&(segment->meta_data.object[i].raw_data_datatype), 1, 4, fd);
812 fread(&(segment->meta_data.object[i].raw_data_dimensions), 1, 4, fd);
813 fread(&(segment->meta_data.object[i].raw_data_count), 1, 8, fd);
814 if (segment->meta_data.object[i].raw_data_datatype == tdsTypeString) {
815 fread(&(segment->meta_data.object[i].raw_data_total_size), 1, 8, fd);
816 }
817 }
818 fread(&(segment->meta_data.object[i].n_properties), 1, 4, fd);
819 segment->meta_data.object[i].property = malloc(sizeof(TDMS_META_DATA_OBJECT_PROPERTY) * segment->meta_data.object[i].n_properties);
820 for (j = 0; j < segment->meta_data.object[i].n_properties; j++) {
821 fread(&uLong, 1, 4, fd);
822 segment->meta_data.object[i].property[j].name = malloc(sizeof(char) * (uLong + 1));
823 fread(segment->meta_data.object[i].property[j].name, 1, uLong, fd);
824 segment->meta_data.object[i].property[j].name[uLong] = '\0';
825 fread(&(segment->meta_data.object[i].property[j].datatype), 1, 4, fd);
826 if (segment->meta_data.object[i].property[j].datatype == tdsTypeString) {
827 fread(&uLong, 1, 4, fd);
828 segment->meta_data.object[i].property[j].value = malloc(sizeof(char) * (uLong + 1));
829 fread(segment->meta_data.object[i].property[j].value, 1, uLong, fd);
830 ((char *)(segment->meta_data.object[i].property[j].value))[uLong] = '\0';
831 } else {
832 TDMS_GetValue(fd, &(segment->meta_data.object[i].property[j].value), segment->meta_data.object[i].property[j].datatype);
833 }
834 /* check for waveform channel properties */
835 if (strcmp(segment->meta_data.object[i].property[j].name, "wf_xname") == 0) {
836 segment->xpart.name = segment->meta_data.object[i].property[j].value;
837 }
838 if (strcmp(segment->meta_data.object[i].property[j].name, "wf_xunit_string") == 0) {
839 segment->xpart.unit = segment->meta_data.object[i].property[j].value;
840 }
841 if (strcmp(segment->meta_data.object[i].property[j].name, "wf_start_time") == 0) {
842 segment->xpart.start_time = *(double *)(segment->meta_data.object[i].property[j].value);
843 }
844 if (strcmp(segment->meta_data.object[i].property[j].name, "wf_start_offset") == 0) {
845 segment->xpart.start_offset = *(double *)(segment->meta_data.object[i].property[j].value);
846 }
847 if (strcmp(segment->meta_data.object[i].property[j].name, "wf_increment") == 0) {
848 segment->xpart.increment = *(double *)(segment->meta_data.object[i].property[j].value);
849 }
850 if (strcmp(segment->meta_data.object[i].property[j].name, "wf_samples") == 0) {
851 segment->xpart.samples = *(int32_t *)(segment->meta_data.object[i].property[j].value);
852 }
853 if (strcmp(segment->meta_data.object[i].property[j].name, "wf_time_pref") == 0) {
854 segment->xpart.time_pref = segment->meta_data.object[i].property[j].value;
855 }
856 }
857 }
858}

◆ TDMS_ReadRawData()

void TDMS_ReadRawData ( FILE * fd,
TDMS_FILE * tdms,
uint32_t n_segment,
long filesize )

Definition at line 860 of file tdms2sdds.c.

860 {
861 uint32_t i, j, k, n, p, a;
862 uint32_t channel_size;
863 uint32_t chunk_size = 0;
864 uint32_t total_chunks;
865 uint32_t n_chunks;
866 uint32_t chunk;
867 int64_t LLong;
868 uint64_t uLLong;
869 int prevFound = 0;
870 TDMS_SEGMENT *segment = &((*tdms).segment[n_segment]);
871
872 segment->raw_data.n_channels = 0;
873 for (i = 0; i < segment->meta_data.n_objects; i++) {
874 if (segment->meta_data.object[i].raw_data_index != 0xFFFFFFFF) {
875 if (segment->meta_data.object[i].raw_data_index == 0x00000000) {
876 /* An object with this name already exists in the previous segment.
877 Copy over meta data */
878 prevFound = 0;
879 a = 0;
880 while (prevFound == 0) {
881 a++;
882 if (a > n_segment) {
883 fprintf(stderr, "tdms2sdds: Error: unable to find %s in a previous segment.\n", segment->meta_data.object[i].path);
884 exit(EXIT_FAILURE);
885 }
886 for (n = 0; n < (*tdms).segment[n_segment - a].meta_data.n_objects; n++) {
887 if (strcmp((*tdms).segment[n_segment - a].meta_data.object[n].path, segment->meta_data.object[i].path) == 0) {
888 prevFound = 1;
889 segment->meta_data.object[i].raw_data_datatype = (*tdms).segment[n_segment - a].meta_data.object[n].raw_data_datatype;
890 segment->meta_data.object[i].raw_data_dimensions = (*tdms).segment[n_segment - a].meta_data.object[n].raw_data_dimensions;
891 segment->meta_data.object[i].raw_data_count = (*tdms).segment[n_segment - a].meta_data.object[n].raw_data_count;
892 if (segment->meta_data.object[i].raw_data_datatype == tdsTypeString) {
893 segment->meta_data.object[i].raw_data_total_size = (*tdms).segment[n_segment - a].meta_data.object[n].raw_data_total_size;
894 }
895
896 /* Copy over previous properties excluding any that were overwritten */
897 /* There will be errors if new properties are inserted after the first segment in the TDMS file */
898 for (j = 0; j < (*tdms).segment[n_segment - a].meta_data.object[n].n_properties; j++) {
899 for (k = 0; k < segment->meta_data.object[i].n_properties; k++) {
900 if (strcmp((*tdms).segment[n_segment - a].meta_data.object[n].property[j].name, segment->meta_data.object[i].property[k].name) == 0) {
901 break;
902 }
903 }
904 p = segment->meta_data.object[i].n_properties;
905 segment->meta_data.object[i].n_properties++;
906 segment->meta_data.object[i].property = realloc(segment->meta_data.object[i].property, sizeof(TDMS_META_DATA_OBJECT_PROPERTY) * segment->meta_data.object[i].n_properties);
907 segment->meta_data.object[i].property[p].name = (*tdms).segment[n_segment - a].meta_data.object[n].property[j].name;
908 segment->meta_data.object[i].property[p].datatype = (*tdms).segment[n_segment - a].meta_data.object[n].property[j].datatype;
909 segment->meta_data.object[i].property[p].value = (*tdms).segment[n_segment - a].meta_data.object[n].property[j].value;
910 /* check for waveform channel properties */
911 if (strcmp(segment->meta_data.object[i].property[p].name, "wf_xname") == 0) {
912 segment->xpart.name = segment->meta_data.object[i].property[p].value;
913 }
914 if (strcmp(segment->meta_data.object[i].property[p].name, "wf_xunit_string") == 0) {
915 segment->xpart.unit = segment->meta_data.object[i].property[p].value;
916 }
917 if (strcmp(segment->meta_data.object[i].property[p].name, "wf_start_time") == 0) {
918 segment->xpart.start_time = *(double *)(segment->meta_data.object[i].property[p].value);
919 }
920 if (strcmp(segment->meta_data.object[i].property[p].name, "wf_start_offset") == 0) {
921 segment->xpart.start_offset = *(double *)(segment->meta_data.object[i].property[p].value);
922 segment->xpart.start_offset += (*tdms).segment[n_segment - a].xpart.range;
923 /*put code here */
924 }
925 if (strcmp(segment->meta_data.object[i].property[p].name, "wf_increment") == 0) {
926 segment->xpart.increment = *(double *)(segment->meta_data.object[i].property[p].value);
927 }
928 if (strcmp(segment->meta_data.object[i].property[p].name, "wf_samples") == 0) {
929 segment->xpart.samples = *(int32_t *)(segment->meta_data.object[i].property[p].value);
930 }
931 if (strcmp(segment->meta_data.object[i].property[p].name, "wf_time_pref") == 0) {
932 segment->xpart.time_pref = segment->meta_data.object[i].property[p].value;
933 }
934 }
935 }
936 }
937 }
938 }
939
940 segment->raw_data.n_channels++;
941 if (segment->meta_data.object[i].raw_data_dimensions != 1) {
942 fprintf(stderr, "tdms2sdds: Error: raw data dimension is %d and should have been 1.\n", segment->meta_data.object[i].raw_data_dimensions);
943 exit(EXIT_FAILURE);
944 }
945 if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeI8) ||
946 (segment->meta_data.object[i].raw_data_datatype == tdsTypeU8) ||
947 (segment->meta_data.object[i].raw_data_datatype == tdsTypeBoolean)) {
948 channel_size = 1 * segment->meta_data.object[i].raw_data_dimensions * segment->meta_data.object[i].raw_data_count;
949 } else if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeI16) ||
950 (segment->meta_data.object[i].raw_data_datatype == tdsTypeU16)) {
951 channel_size = 2 * segment->meta_data.object[i].raw_data_dimensions * segment->meta_data.object[i].raw_data_count;
952 } else if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeI32) ||
953 (segment->meta_data.object[i].raw_data_datatype == tdsTypeU32) ||
954 (segment->meta_data.object[i].raw_data_datatype == tdsTypeSingleFloat) ||
955 (segment->meta_data.object[i].raw_data_datatype == tdsTypeSingleFloatWithUnit)) {
956 channel_size = 4 * segment->meta_data.object[i].raw_data_dimensions * segment->meta_data.object[i].raw_data_count;
957 } else if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeI64) ||
958 (segment->meta_data.object[i].raw_data_datatype == tdsTypeU64) ||
959 (segment->meta_data.object[i].raw_data_datatype == tdsTypeDoubleFloat) ||
960 (segment->meta_data.object[i].raw_data_datatype == tdsTypeDoubleFloatWithUnit)) {
961 channel_size = 8 * segment->meta_data.object[i].raw_data_dimensions * segment->meta_data.object[i].raw_data_count;
962 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeTimeStamp) {
963 channel_size = 16 * segment->meta_data.object[i].raw_data_dimensions * segment->meta_data.object[i].raw_data_count;
964 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeString) {
965 fprintf(stderr, "tdms2sdds: string type channels are not yet supported in tdms2sdds\n");
966 exit(EXIT_FAILURE);
967 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeVoid) {
968 fprintf(stderr, "tdms2sdds: void type channels are not yet supported in tdms2sdds\n");
969 exit(EXIT_FAILURE);
970 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeExtendedFloat) {
971 fprintf(stderr, "tdms2sdds: extended float type channels are not yet supported in tdms2sdds\n");
972 exit(EXIT_FAILURE);
973 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeExtendedFloatWithUnit) {
974 fprintf(stderr, "tdms2sdds: extended float type with unit channels are not yet supported in tdms2sdds\n");
975 exit(EXIT_FAILURE);
976 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeDAQmxRawData) {
977 fprintf(stderr, "tdms2sdds: extended DAQmx raw data channels are not yet supported in tdms2sdds\n");
978 exit(EXIT_FAILURE);
979 } else {
980 fprintf(stderr, "tdms2sdds: unknown data type\n");
981 exit(EXIT_FAILURE);
982 }
983 chunk_size += channel_size;
984 }
985 }
986
987 if (segment->lead_in.next_segment_offset == -1) {
988 if (filesize == -1) {
989 fprintf(stderr, "tdms2sdds: Error: cannot calculate file size because you are using stdin\n");
990 exit(EXIT_FAILURE);
991 }
992 segment->lead_in.next_segment_offset = filesize;
993 }
994 total_chunks = segment->lead_in.next_segment_offset - segment->lead_in.raw_data_offset;
995 n_chunks = total_chunks / chunk_size;
996
997 segment->raw_data.channel = malloc(sizeof(TDMS_RAW_DATA_CHANNEL) * segment->raw_data.n_channels);
998
999 if (segment->lead_in.toc & kTocInterleavedData) {
1000 fprintf(stderr, "tdms2sdds does not yet support interleaved data\n");
1001 exit(EXIT_FAILURE);
1002 } else {
1003 j = 0;
1004 for (i = 0; i < segment->meta_data.n_objects; i++) {
1005 if (segment->meta_data.object[i].raw_data_index != 0xFFFFFFFF) {
1006 segment->xpart.range = segment->xpart.increment * segment->meta_data.object[i].raw_data_count * n_chunks;
1007
1008 if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeI8) ||
1009 (segment->meta_data.object[i].raw_data_datatype == tdsTypeU8) ||
1010 (segment->meta_data.object[i].raw_data_datatype == tdsTypeBoolean)) {
1011 segment->raw_data.channel[j].values = malloc(1 * segment->meta_data.object[i].raw_data_count * n_chunks);
1012 } else if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeI16) ||
1013 (segment->meta_data.object[i].raw_data_datatype == tdsTypeU16)) {
1014 segment->raw_data.channel[j].values = malloc(2 * segment->meta_data.object[i].raw_data_count * n_chunks);
1015 } else if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeI32) ||
1016 (segment->meta_data.object[i].raw_data_datatype == tdsTypeU32) ||
1017 (segment->meta_data.object[i].raw_data_datatype == tdsTypeSingleFloat) ||
1018 (segment->meta_data.object[i].raw_data_datatype == tdsTypeSingleFloatWithUnit)) {
1019 segment->raw_data.channel[j].values = malloc(4 * segment->meta_data.object[i].raw_data_count * n_chunks);
1020 } else if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeI64) ||
1021 (segment->meta_data.object[i].raw_data_datatype == tdsTypeU64) ||
1022 (segment->meta_data.object[i].raw_data_datatype == tdsTypeDoubleFloat) ||
1023 (segment->meta_data.object[i].raw_data_datatype == tdsTypeDoubleFloatWithUnit)) {
1024 segment->raw_data.channel[j].values = malloc(8 * segment->meta_data.object[i].raw_data_count * n_chunks);
1025 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeTimeStamp) {
1026 /* This is converted into a double value */
1027 segment->raw_data.channel[j].values = malloc(8 * segment->meta_data.object[i].raw_data_count * n_chunks);
1028 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeString) {
1029 fprintf(stderr, "tdms2sdds: string type channels are not yet supported in tdms2sdds\n");
1030 exit(EXIT_FAILURE);
1031 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeVoid) {
1032 fprintf(stderr, "tdms2sdds: void type channels are not yet supported in tdms2sdds\n");
1033 exit(EXIT_FAILURE);
1034 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeExtendedFloat) {
1035 fprintf(stderr, "tdms2sdds: extended float type channels are not yet supported in tdms2sdds\n");
1036 exit(EXIT_FAILURE);
1037 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeExtendedFloatWithUnit) {
1038 fprintf(stderr, "tdms2sdds: extended float type with unit channels are not yet supported in tdms2sdds\n");
1039 exit(EXIT_FAILURE);
1040 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeDAQmxRawData) {
1041 fprintf(stderr, "tdms2sdds: extended DAQmx raw data channels are not yet supported in tdms2sdds\n");
1042 exit(EXIT_FAILURE);
1043 } else {
1044 fprintf(stderr, "tdms2sdds: unknown data type\n");
1045 exit(EXIT_FAILURE);
1046 }
1047 segment->raw_data.channel[j].n_values = segment->meta_data.object[i].raw_data_count * n_chunks;
1048 j++;
1049 }
1050 }
1051 for (chunk = 0; chunk < n_chunks; chunk++) {
1052 j = 0;
1053 for (i = 0; i < segment->meta_data.n_objects; i++) {
1054 if (segment->meta_data.object[i].raw_data_index != 0xFFFFFFFF) {
1055 if (segment->meta_data.object[i].raw_data_datatype == tdsTypeBoolean) {
1056 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1057 fread(&(((int8_t *)(segment->raw_data.channel[j].values))[k]), 1, 1, fd);
1058 }
1059 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeI8) {
1060 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1061 fread(&(((int8_t *)(segment->raw_data.channel[j].values))[k]), 1, 1, fd);
1062 }
1063 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeU8) {
1064 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1065 fread(&(((uint8_t *)(segment->raw_data.channel[j].values))[k]), 1, 1, fd);
1066 }
1067 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeI16) {
1068 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1069 fread(&(((int16_t *)(segment->raw_data.channel[j].values))[k]), 1, 2, fd);
1070 }
1071 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeU16) {
1072 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1073 fread(&(((uint16_t *)(segment->raw_data.channel[j].values))[k]), 1, 2, fd);
1074 }
1075 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeI32) {
1076 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1077 fread(&(((int32_t *)(segment->raw_data.channel[j].values))[k]), 1, 4, fd);
1078 }
1079 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeU32) {
1080 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1081 fread(&(((uint32_t *)(segment->raw_data.channel[j].values))[k]), 1, 4, fd);
1082 }
1083 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeI64) {
1084 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1085 fread(&(((int64_t *)(segment->raw_data.channel[j].values))[k]), 1, 8, fd);
1086 }
1087 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeU64) {
1088 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1089 fread(&(((uint64_t *)(segment->raw_data.channel[j].values))[k]), 1, 8, fd);
1090 }
1091 } else if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeSingleFloat) ||
1092 (segment->meta_data.object[i].raw_data_datatype == tdsTypeSingleFloatWithUnit)) {
1093 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1094 fread(&(((float *)(segment->raw_data.channel[j].values))[k]), 1, 4, fd);
1095 }
1096 } else if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeDoubleFloat) ||
1097 (segment->meta_data.object[i].raw_data_datatype == tdsTypeDoubleFloatWithUnit)) {
1098 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1099 fread(&(((double *)(segment->raw_data.channel[j].values))[k]), 1, 8, fd);
1100 }
1101 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeTimeStamp) {
1102 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1103 fread(&uLLong, 1, 8, fd);
1104 fread(&LLong, 1, 8, fd);
1105 /*LLong = LLong - 2082844791LL; */ /* Subtract seconds between 1904 and 1970 */
1106 segment->raw_data.channel[j].values[k] = LLong + (uLLong * 5.42101086242752217e-20);
1107 }
1108 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeString) {
1109 fprintf(stderr, "tdms2sdds: string type channels are not yet supported in tdms2sdds\n");
1110 exit(EXIT_FAILURE);
1111 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeVoid) {
1112 fprintf(stderr, "tdms2sdds: void type channels are not yet supported in tdms2sdds\n");
1113 exit(EXIT_FAILURE);
1114 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeExtendedFloat) {
1115 fprintf(stderr, "tdms2sdds: extended float type channels are not yet supported in tdms2sdds\n");
1116 exit(EXIT_FAILURE);
1117 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeExtendedFloatWithUnit) {
1118 fprintf(stderr, "tdms2sdds: extended float with unit type channels are not yet supported in tdms2sdds\n");
1119 exit(EXIT_FAILURE);
1120 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeDAQmxRawData) {
1121 fprintf(stderr, "tdms2sdds: DAQmx raw data channels are not yet supported in tdms2sdds\n");
1122 exit(EXIT_FAILURE);
1123 } else {
1124 fprintf(stderr, "tdms2sdds: unknown data type\n");
1125 exit(EXIT_FAILURE);
1126 }
1127 j++;
1128 }
1129 }
1130 }
1131 }
1132}