Documentation:Reference:C2 - MdsWiki
Navigation
Personal tools

From MdsWiki

Jump to: navigation, search

Calling MDSplus from C Programs: More Examples

burruss@fusion.gat.com Updated 2003-02-27

Introduction

This document continues where Calling MDSplus from C Programs left off by adding new examples of calling MDSplus from C.

3D Signal Example

The following source code was compiled on Linux. It demonstrates one way to handle 3D data in C.

Here's the Makefile:

CC = cc
INCL = -I/usr/local/mdsplus/include
FLAGS = $(INCL) -L/usr/local/mdsplus/lib \
 -lMdsLib_client -g

all: example

example: mdsplus_examples.c
	$(CC) $(FLAGS) mdsplus_examples.c -o mdsplus_examples

clean:
	rm -f *~ core a.out mdsplus_examples *.o

Here's the header file (named mdsplus_examples.h):

 #ifndef MDSPLUS_EXAMPLES_H
 #define MDSPLUS_EXAMPLES_H
 
 #include <mdslib.h>
 #include <string.h>
 
 #include <errno.h>
 
 #define STATUS_OK(status) (((status) & 1) == 1)
 
 typedef struct {
 
   char *   name;
 
   float *  data;
   int      data_rank;
   int      data_len;
   char *   data_units;
 
   float *  dim0;
   int      dim0_rank;
   int      dim0_len;
   char *   dim0_units;
 
   float *  dim1;
   int      dim1_rank;
   int      dim1_len;
   char *   dim1_units;
 
 } signal;
 
 static int null         = 0;
 static int dtype_long   = DTYPE_LONG;
 static int dtype_float  = DTYPE_FLOAT;
 static int dtype_string = DTYPE_CSTRING;
 
 void       signal_units(const char *, char **);
 int        signal_rank(const char *);
 int        signal_length(const char *);
 signal *   get_signal(const char *);
 void       free_signal(signal *);
 
 #endif
 

Here's the source file (named mdsplus_examples.c):

 #include "mdsplus_examples.h"
 
 void signal_units(const char *signal, char **p_units)
 {
   /* local vars */
   char buf[1024];
   int len;
   int desc  = descr(&dtype_long, &len, &null);
   int status;
 
   /* build string */
   status = snprintf(buf,sizeof(buf),"LEN(UNITS(%s))",signal);
   if ( status == -1 ) {
     fprintf(stderr,"Error in signal_units: %s\n",strerror(errno));
     return;
   }
 
   /* use MdsValue to get the length of the units string */
   status = MdsValue(buf, &desc, &null, 0);
   if ( !STATUS_OK(status) ) {
     fprintf(stderr,"Unable to get length of units of %s.\n",signal);
     return;
   }
 
   /* if string length is zero, just return */
   if (len == 0) return;
 
   /* leave room for null terminator */
   ++len;
 
   /* allocate memory for the units string */
   *p_units = (char *)malloc(len*sizeof(char));
   if ( !(*p_units) ) {
     fprintf(stderr,"Error allocating memory for units string of %s.\n",
 	    signal);
     return;
   }
 
   /* make a descriptor for the string */
   desc = descr(&dtype_string, *p_units, &null, &len);
 
   /* build a string to get the units string */
   status = snprintf(buf,sizeof(buf),"UNITS(%s)",signal);
   if ( status == -1 ) {
     /* TO DO: should we free the descr and *p_units before returning? */
     /* What does the calling function expect in the event of an error? */
     fprintf(stderr,"Error in signal_units %s\n",strerror(errno));
     return;
   }
 
   /* Use MdsValue to get the units string */
   status = MdsValue(buf, &desc, &null, 0);
   if ( !STATUS_OK(status) ) {
     /* TO DO: should we free the descr and *p_units before returning? */
     fprintf(stderr,"Unable to get units of %s.\n",signal);
     fprintf(stderr,"Error code = %i\n",status);
     return;
   }
 
   /* null-terminate the string */
   (*p_units)[len-1] = '\0';
 
   return;
 }
 
 int signal_rank(const char *signal)
 {
   /* local vars */
   char buf[1024];
   int rank;
   int desc = descr(&dtype_long, &rank, &null);
   int status;
 
   /* put RANK() TDI function around signal name */
   status = snprintf(buf,sizeof(buf),"RANK(%s)",signal);
   if ( status == -1 ) {
     fprintf(stderr,"Error in signal_rank: %s\n",strerror(errno));
     return -1;
   }
 
   /* use MdsValue to get the signal rank */
   status = MdsValue(buf, &desc, &null, 0);
   if ( !STATUS_OK(status) ) {
     fprintf(stderr,"Unable to get rank of %s.\n",signal);
     return -1;
   }
 
   /* return signal rank */
   return rank;
 }
 
 int signal_length(const char *signal)
 {
   /* local vars */
   char buf[1024];
   int size;
   int desc = descr(&dtype_long, &size, &null);
   int status;
 
   /* put SIZE() TDI function around signal name */
   status = snprintf(buf,sizeof(buf),"SIZE(%s)",signal);
   if ( status == -1 ) {
     fprintf(stderr,"Error in signal_length: %s\n",strerror(errno));
     return -1;
   }
 
   /* use MdsValue to get the signal length */
   status = MdsValue(buf, &desc, &null, 0);
   if ( !STATUS_OK(status) ) {
     fprintf(stderr,"Unable to get length of %s.\n",signal);
     return -1;
   }
 
   /* return signal length */
   return size;
 
 }
 
 signal *get_signal(const char *name)
 {
   int len, sigdesc, status;
   signal *sig;
   char buf[1024];
 
   /* Try to allocate memory for signal */
   sig = (signal *)malloc(sizeof(signal));
   if ( !sig ) {
     fprintf(stderr,"Error allocating memory for signal %s\n",name);
     return sig;
   }
 
   /* Initialize pointers */
   sig->data       = NULL;
   sig->name       = NULL;
   sig->data_units = NULL;
   sig->dim0       = NULL;
   sig->dim0_units = NULL;
   sig->dim1       = NULL;
   sig->dim1_units = NULL;
 
   /* Try to allocate memory for signal name */
   sig->name = malloc((strlen(name)+1)*sizeof(char));
   if ( !sig->name ) {
     fprintf(stderr,"Error allocating memory for signal name %s\n",name);
     return sig;
   }
   snprintf(sig->name,strlen(name)+1,"%s",name);
 
   /*
    * Get dependent data
    */
 
   /* Try to get rank of signal */
   sig->data_rank = signal_rank(name);
   if ( sig->data_rank < 0 ) {
     fprintf(stderr,"%s does not appear to be a valid signal.\n",name);
     fprintf(stderr,"Remember to quote backslash characters.\n");
     return sig;
   }
 
   /* Try to get length of signal dependent dimension */
   sig->data_len = signal_length(name);
   if ( sig->data_len < 0 ) {
     fprintf(stderr,"%s had a problem with the signal length.\n",name);
     return sig;
   }
 
   /* Try to allocate memory for dependent dim of signal */
   sig->data = malloc(sig->data_len*sizeof(float));
   if ( !sig->data ) {
     fprintf(stderr,"Error allocating memory for %s data\n",name);
     return sig;
   }
 
   /* Create a descriptor for this signal */
   sigdesc = descr(&dtype_float, sig->data, &sig->data_len, &null);
 
   /* Retrieve signal */
   status = MdsValue((char *)name, &sigdesc, &null, &len );
   if ( !STATUS_OK(status) ) {
     fprintf(stderr,"Error retrieving data for %s\n",name);
     return sig;
   }
 
   /* Try to get signal units */
   signal_units(name,&sig->data_units);
 
   /* If there are no more dimensions, return now */
   if ( sig->data_rank == 0 ) return sig;
 
 
   /*
    * Get dim0
    */
 
   /* Get rank of dim0 */
   snprintf(buf,sizeof(buf),"RANK(DIM_OF(%s,0))",name);
   sig->dim0_rank = signal_rank(buf);
   if ( sig->dim0_rank < 0 ) {
     fprintf(stderr,"%s had a problem with dim0 rank\n",name);
     return sig;
   }
 
   /* Get length of dim0 */
   snprintf(buf,sizeof(buf),"DIM_OF(%s,0)",name);
   sig->dim0_len = signal_length(buf);
   if ( sig->dim0_len < 0 ) {
     fprintf(stderr,"%s had a problem with dim0 length\n",name);
     return sig;
   }
 
   /* Try to allocate memory for dim0 */
   sig->dim0 = malloc(sig->dim0_len*sizeof(float));
   if ( !sig->dim0 ) {
     fprintf(stderr,"Error allocating memory for %s dim0\n",name);
     return sig;
   }
 
   /* Create a descriptor for dim0 */
   sigdesc = descr(&dtype_float, sig->dim0, &sig->dim0_len, &null);
 
   /* Retrieve dim0 */
   status = MdsValue(buf, &sigdesc, &null, &len );
   if ( !STATUS_OK(status) ) {
     fprintf(stderr,"Error retrieving dim0 for %s\n",name);
     return sig;
   }
 
   /* Try to get dim0 units */
   signal_units(buf, &sig->dim0_units);
 
   /* If there are no more dims, return now */
   if ( sig->data_rank == 1 ) return;
 
 
   /*
    * Get dim1
    */
 
   /* Get rank of dim1 */
   snprintf(buf,sizeof(buf),"RANK(DIM_OF(%s,1))",name);
   sig->dim1_rank = signal_rank(buf);
   if ( !STATUS_OK(status) ) {
     fprintf(stderr,"Error retrieving dim1 for %s\n",name);
     return sig;
   }
 
   /* Get length of dim1 */
   snprintf(buf,sizeof(buf),"DIM_OF(%s,1)",name);
   sig->dim1_len = signal_length(buf);
   if ( sig->dim1_len < 0 ) {
     fprintf(stderr,"%s had a problem with dim1 length\n",name);
     return sig;
   }
 
   /* Try to allocate memory for dim1 */
   sig->dim1 = malloc(sig->dim1_len*sizeof(float));
   if ( !sig->dim1 ) {
     fprintf(stderr,"Error allocating memory for %s dim1\n",name);
     return sig;
   }
 
   /* Create a descriptor for dim1 */
   sigdesc = descr(&dtype_float, sig->dim1, &sig->dim1_len, &null);
 
   /* Retrieve dim1 */
   status = MdsValue(buf, &sigdesc, &null, &len );
   if ( !STATUS_OK(status) ) {
     fprintf(stderr,"Error retrieving dim1 for %s\n",name);
     return sig;
   }
 
   /* Try to get units */
   signal_units(buf, &sig->dim1_units);
 
   return sig;
 
 }
 
 void free_signal(signal *signal)
 {
   if ( !signal ) {
     fprintf(stderr,"WARNING: tried to free invalid signal %x.\n",signal);
     return;
   }
 
   if ( signal->data ) free( (void *)signal->data );
   if ( signal->data_units ) free( (void *)signal->data_units );
   if ( signal->name ) free( (void *)signal->name );
   if ( signal->dim0 ) free( (void *)signal->dim0 );
   if ( signal->dim0_units ) free( (void *)signal->dim0_units );
   if ( signal->dim1 ) free( (void *)signal->dim1 );
   if ( signal->dim1_units ) free( (void *)signal->dim1_units );
 
   free( (void *)signal );
 
 }
 
 void print_signal_info(signal *signal)
 {
 
   int i;
 
   if ( !signal ) {
     printf("Empty signal\n");
     return;
   }
 
   if ( signal->name ) {
     printf("Name        = %s\n",signal->name);
   } else {
     printf("Unnamed signal\n");
   }
 
   printf("Data Rank   = %i\n",signal->data_rank);
   printf("Data Length = %i\n",signal->data_len);
 
   if ( signal->data_units ) {
     printf("Data Units  = %s\n",signal->data_units);
   } else {
     printf("Empty units\n");
   }
 
   if ( signal->data ) {
     printf("Data[0:5]   = ");
     for ( i=0 ; i<5 && i<signal->data_len ; i++ )
       printf("%f ",signal->data[i]);
     printf("\n");
   } else {
     printf("Empty data\n");
   }
 
   if ( signal->dim0 ) {
     printf("Dim0 Rank   = %i\n",signal->dim0_rank);
     printf("Dim0 Length = %i\n",signal->dim0_len);
     if ( signal->dim0_units ) {
       printf("Dim0 Units  = %s\n",signal->dim0_units);
     } else {
       printf("Empty dim0 units\n");
     }
     printf("Dim0[0:5]   = ");
     for ( i=0 ; i<5 && i<signal->dim0_len ; i++ )
       printf("%f ",signal->dim0[i]);
     printf("\n");
   } else {
     printf("Empty dim0\n");
   }
 
   if ( signal->dim1 ) {
     printf("Dim1 Rank   = %i\n",signal->dim1_rank);
     printf("Dim1 Length = %i\n",signal->dim1_len);
     if ( signal->dim1_units ) {
       printf("Dim1 Units  = %s\n",signal->dim1_units);
     } else {
       printf("Empty dim1 units\n");
     }
     printf("Dim1[0:5]   = ");
     for ( i=0 ; i<5 && i<signal->dim1_len ; i++ )
       printf("%f ",signal->dim1[i]);
     printf("\n");
   } else {
     printf("Empty dim1\n");
   }
 
 }
 
 int main(int argc, char *argv[])
 {
   signal * sig;
   signal * sig2;
   int status;
   int shot = 111203;
 
   /* connect to MDSplus server */
   printf("Connecting to MyServer.\n");
   status = MdsConnect("myserver");
   if ( !STATUS_OK(status) ) {
     fprintf(stderr,"Error connecting to MyServer.\n");
     return 1;
   }
 
   /* open the tree */
   printf("Opening EFIT01 tree.\n");
   status = MdsOpen("EFIT01", &shot);
   if ( !STATUS_OK(status) ) {
     fprintf(stderr,"Error opening EFIT01 tree for shot %i.\n",shot);
     return 1;
   }
 
   sig = get_signal("\\AMINOR");
   print_signal_info(sig);
   free_signal(sig);
 
   /* open the tree */
   printf("Opening ELECTRONS tree.\n");
   status = MdsOpen("ELECTRONS", &shot);
   if ( !STATUS_OK(status) ) {
     fprintf(stderr,"Error opening ELECTRONS tree for shot %i.\n",shot);
     return 1;
   }
 
   sig2 = get_signal("\\TSTE_CORE");
   print_signal_info(sig2);
   free_signal(sig2);
 
   return 0;
 }
 
 

The basic idea with the above example is to define a signal structure for handling the different components of a signal. If we were using C++ we would take this one step further and turn that signal structure into a signal class with methods for working with the signal data.

Note that this code would not work with signals that had more than two independent dimensions. It also assumes that the data is floating point; this is almost always the case, but there are exceptions.

The above code produces this output:

myclient % ./mdsplus_examples
Connecting to MyServer.
Opening EFIT01 tree.
Name        = \AMINOR
Data Rank   = 1
Data Length = 258
Data Units  = m
Data[0:5]   = 0.666194 0.597840 0.595714 0.628156 0.627738
Dim0 Rank   = 0
Dim0 Length = 258
Dim0 Units  = ms
Dim0[0:5]   = 50.000000 75.000000 100.000000 125.000000 150.000000
Empty dim1
Opening ELECTRONS tree.
Name        = \TSTE_CORE
Data Rank   = 2
Data Length = 16306
Data Units  = eV
Data[0:5]   = 0.000000 0.000000 0.000000 0.000000 0.000000
Dim0 Rank   = 0
Dim0 Length = 526
Dim0 Units  = ms
Dim0[0:5]   = -49.794998 -37.276001 -24.795000 -12.495000 0.205000
Dim1 Rank   = 0
Dim1 Length = 31
Dim1 Units  = m
Dim1[0:5]   = 0.825000 0.813000 0.801000 0.789000 0.776000