Documentation:Tutorial:APIs:IDL - MdsWiki
Navigation
Personal tools

From MdsWiki

Jump to: navigation, search

Reading and writing data in MDSplus trees in IDL

So far, you have seen of jScope can be connected to a mdsip server for accessing data. In this case data is accessed only for display, but in a more general situation you may wish to access MDSplus data for running some kind of analysis program, possibly with a graphical interface for data display. MDSplus allows data access from two tools for interactive data analysis: IDL and Matlab. We shall see that the two interfaces are quite similar, both requiring as first step the connection to a mdsip data server.

Currently, there is a slight difference between the way data is accessed via IDL and Matlab: while in IDL it is possible to read also local data (i.e. not connecting to a mdsip server, but directly using the data access routines of MDSplus), in Matlab it is only possible to access MDSplus data via a mdsip server.

Let's start with IDL, making local data access to the sample MDSplus tree used in the previous section.
Once MDSplus has been installed, all you need to make it work under IDL is to make sure that the IDL_PATH environment variable includes also the directory containing the MDSPlus interfaces for IDL (on Unix, usually /usr/local/mdsplus/idl).

Once IDL has been started, it is possible to evaluate TDI expressions using function mdsvalue, as in the following example:

IDL> a = mdsvalue('2+3')
IDL> print,a
5

function mdsvalue accepts a string argument which represents the expression to be evaluated, and returns the result of such evaluation.
We already know that data references are always seen as expressions, so this mechanism is valid also for data access. However, the following statement (recall that :SIGNAL1 is the name of a node of my_tree containing a signal):

IDL> a = mdsvalue(':SIGNAL1')

will generate an error message. In fact, before accessing data in a MDSplus tree, we need to open the tree first. The correct sequence is (in the example we are working with the experiment model, labelled by shot number -1):

IDL> mdsopen, 'my_tree', -1
IDL> a = mdsvalue(':SIGNAL1')

At this point the IDL variable a contains the result of the evaluation of the expression :SIGNAL1. Being such expression composed of a reference to a node of my_tree, the result of its evaluation is the content of the node (an array in our example). More generally, the result of the evaluation of a TDI expression may be a scalar, and array (both integer or float) or a text string.

Recalling the structure of my_tree, node :SIGNAL has been designed to containing a Signal data type, i.e. a MDSplus data type defining values for both X and Y axis. However, the result of its evaluation is a single array (of Y values), stored then in IDL variable a. This means that there is still information to be retrieved from node :SIGNAL1, i.e. the values of the X axis (usually representing the times associated with the samples of the signal). To retrieve this information, we need to evaluate another TDI expression, as shown in the complete example below:

IDL> mdsopen, 'my_tree', -1
IDL> y = mdsvalue(':SIGNAL1')
IDL> x = mdsvalue('DIM_OF(:SIGNAL1)')

The TDI operator DIM_OF returns in fact the values of the X axis of the argument, assumed to be a signal.

We can also write into MDSPlus trees from IDL, using procedure mdsput, as in the following example in which we write an array into node :NUM1.

IDL> mdsopen, 'my_tree', -1
IDL> mdsput, ':NODE1', '[1,2,3,4,5]'

The first argument of procedure mdsput is the name of the node, expressed as a string. You can use both path names and (more likely) tag names.
The second argument is a string representing the TDI expression to be stored. Recall that, while reading data expressions are evaluated (i.e. the returned values are always numbers or text strings), when writing data into trees, the expression is only compiled, i.e. transformed into the corresponding MDSplus data type prior to be stored. This difference may seem subtle, but it important and worth to be understood. Consider the following code snippet:

IDL> mdsput,':NUM1', '2*:NUM2'
IDL> mdsput,':NUM2', '1'
IDL> a = mdsvalue(':NUM1')
IDL> print,a
2
IDL> mdsput,':NUM2', '100'
IDL> a = mdsvalue(':NUM1')
IDL> print,a
200

Why we retrieve two different values from node :NUM1? The reason is that node :NUM1 contains a TDI expression. Such expression is evaluated when calling mdsvalue, yielding two different results as the value of node :NUM2 is changed between the two data accesses.

Be aware of the usage defined for the node into which we write data. The MDSplus data access layer performs in fact some checks on the kind of data being inserted in the MDSplus tree. Try for example to write a string in node :NUM1 (whose usage has been declared as numeric) and you will see something like this:

IDL> mdsput,':NUM2', ' "This is a string" '
% MDSPUT: %TREE-E-TreeINVDTPUSG, Attempt to store datatype which conflicts with the designated usage of this node

At this point we may think to have in hand all the tools required for making MDSplus data computation and visualization in IDL, but this is not true in practice. In fact, when we perform some kind of computations, we store results in some IDL variables, so we need a mechanism for transferring the content of IDL variables into a MDSPlus tree.
The following example stores a floating point array into IDL variable a and then stores such array in tree node :NUM1

IDL> a = sin(findgen(100)/30.)
IDL> mdsput,':NUM1', '$1', a

The mechanism is almost the same of the previous examples, but in this case the TDI expression is composed of symbol $1, meaning that it will be replaced by the contents of the first argument after the TDI expression in the mdsput argument list.
This mechanism is of course more general, and you can define an arbitrary TDI expression containing symbols $1, $2, ...$n, followed by n arguments whose content will replace those symbols in the expression which will be written into the MDSplus tree.
It is often convenient to store the results of a computation in a Signal structure, so that the same node contains both Y and X information and can be displayed, for example, by jScope without the need of a separate definition of the X axis. Suppose we have the Y and X values in IDL variables y and x, respectively. The following command stores X and Y information into node :SIGNAL1:

IDL> mdsput,':SIGNAL1', 'BUILD_SIGNAL($1,,$2)',y,x

Recall that the TDI operator BUILD_SIGNAL defines a Signal MDSplus data structure, taking the Y and X axis as first and third arguments, respectively.

Finally, the currently open MDSplus tree can be closed with the command:

IDL> mdsclose

Now we are really able to perform data analysis in MDSplus, so let's take a step further, and move to the management of remote MDSplus trees.
Remote data access, both for reading and writing, is the most likely scenario in practice. In fact, even if you are working in your lab, accessing data of your experiment, such data will be likely stored in a machine different from the machine on which you are performing tour computation. In this case, unless you are using a distributed file system (so that you see remote data as local), you need to connect to the mdsip server exporting MDSplus data before working on it.

Working with remote MDSplus trees is as simple as working with local trees. In fact all you need is to call once the procedure mdsconnect, '<IP of the node running mdsip>:<port>'.
For example, if your mdsip server runs on node at IP 150.178.3.101 using port 8000, before any other data access operation (opening trees, reading and writing data), you need to give the following command:

IDL> mdsconnect,'150.178.3.101:8000'

You can also connect to a different mdsip server within the same IDL session by calling mdsdisconnect, and mdsconnect again.