Documentation:Reference:tdi misc help - MdsWiki
Navigation
Personal tools

From MdsWiki

Jump to: navigation, search

TDI VMS Help:

$ HELP/LIBRARY=MDS$ROOT:[SYSHLP]MDSPLUS.HLB TDISHR

C-like syntax case insensitive special functions for working with MDSplus objects ?can be invoked by putting call and args into an expression node in a tree, and then the actual TDI (compiled?) is found by looking in the sharable library pointed to by (TCL or MDS$TCL) SET LIBRARY ... or something like that

Variables

Local variables are to be used to optimize code by not recalculating and for writing repeated or more complicated expressions. They should not be used to carry information across trees because access is then order dependent.

>>>>>>>>>WARNING, they have side effects!!!

You may store any MDSplus data type in a variable and then reference it as you need it in other expressions.

>>>>>>>>>WARNING, the order of operations may not be clear (to you or the compiler), so be careful about assigning data to a variable and using the variable in the same expression.

COMMA, VECTOR, and statements are left to right but argments of functions may be used in any order.

There are two forms of variables: private and public. The usual, private variables are seen only by your current FUN. Whereas, public variables can be seen by all programs. Anywhere a VAR like _X can be used, you may use PRIVATE _X or PUBLIC _X to distinguish the one you want. Otherwise on reading, _X looks for PRIVATE _X first and then PUBLIC _X. On writing, _X will be stored in the private list unless it was a modify operation like _X++ or _X+=6.

>>>>>>>>>WARNING, always use PUBLIC for public variables to help you analyze the code later.

All user variables should begin with an underscore (_); system variables will begin with a dollar sign ($). Names beginning with alphabetics look like tree members.

The length must be less than 200.

Upper and lower cases are not distinct, thus _a and _A are the same.

Literals

Literals are constants written as text. Letters used to designate data type and base may be upper or lower case.

Integers must begin with a number.

Prefixes designate base and are 0B for binary, 0O for octal, 0X for hexadecimal, and none for decimal. [PR: look like SUFFIXES to me...] Suffixes designated data type: BU for byte_unsigned, WU for word_unsigned, LU for long_unsigned, QU for quadword_unsigned, OU for octaword_unsigned, B for byte, W for word, L for long, Q for quadword, and O for octaword. No suffix is type L. You may use UB instead of BU for byte_unsigned and SB or BS instead of B for byte. After 0X use SB for signed bytes because the B looks like a digit. Floating point numbers must have a decimal point or an exponent with following optionally signed digit or digits and at least one digit. The exponent designator is E or F for standard precision, D for double, G for wide-exponent double, and H for quad-precision.

Without an exponent, standard precision is assumed.

Complex numbers must be formed with the function CMPLX(real,imag). WARNING, you may specify D_COMPLEX and others but the precision of the arguments is determined by each exponent letter.

Characters or text may be enclosed in single quotes (apostrophes) or double quotes. TDISHR uses the CC-style designation of control characters (\001 or \n), the quoting character (\' or \"), and the backslash (\\) itself.

Hexadecimal control characters (\x8c) must be used with care, because they stop on the first non-hexadecimal character. Octal controls are limited to three digits or the first non-octal one. Adjacent text strings (possibly with white space between) are concatenated. This allows breaking of strings across more than one line. Otherwise, two literals may not be adjacent--bad syntax.

Glossary

array... A collection of scalars in a multidimensional rectangle.
axis.... The independent variable.
bounds.. Array subscript limits, lower and upper.
byte.... Eight bits of information, one character, an integer.
C$LIBRARY A logical definition of a .TLB for #include files.
call.... To invoke a subroutine during program execution.
CC...... The C-language compiler.
class... The class of a block of memory, static, dynamic, array.
complex. Real and imaginary parts joined.
conforming The matching of shapes, a scalar matches any shape.
descrip. The header file defining VMS descriptor, dtype, class.
descriptor The description of the contents of a memory block.
dimension An independent axis of an array.
dtype... The kind of a block of memory.
dynamic. Data whose memory location is changable.
evaluate To remove references like NIDs, PATHs, and FUNCTIONs.
F90..... The proposed Fortran 90 standard.
float... A floating-point number, esp. a single-precision real.
function An opcode and arguments to determine a value.
include. A file .H for CC, .FOR for Fortran with definitions.
index... A subscript value.
integer. Whole numbers.
kind.... The data type of a block of memory.
length.. The number of bytes in an element.
logical. Variable with two states: true or false; low bit tested.
matrix.. A two-dimensional array, usually.
MDSplus. The programs and libraries for data taking and analysis.
MDSLIB.. Routines easily called from VAX Fortran or IDL, etc.
MDSSHR.. Routines common to several MDSplus libraries.
missing. An omitted argument.
multiplier Array subscript number of values, upper-lower+1.
NID..... A node identifier, a number used in references in trees.
node.... A element of a tree with data and/or links to nodes.
numeric. Integer, real, or complex number.
OPC$.... Operation codes for TDISHR functions.
opcode.. An operation code identifying the action to take.
param... An independent value with textual and validation info.
path.... The textual name of a tree element.
pointer. The address of a memory object.
precedence The order operations are done without parentheses.
rank.... Dimensionality of an array. A scalar is rank 0.
real... An approximate number with exponent and fraction.
record.. A class-R descriptor or a data block on disk.
ROPRAND. The floating point reserved operand, a bad number.
scalar.. A single value.
shape... The extent of all dimensions of an object.
signal.. Data, including the raw data, and independent axes.
signal_VMS To notify routines of some condition like an error.
signed.. Integer forms with positive and negative numbers.
size.... The number of elements of an array; sometimes bytes.
static.. Data with fixed memory location.
status.. An integer identifying severity and text of an error.
subscript The offset along a dimension of an array.
tdescrip The header file defining MDS descriptor, dtype, class.
TDISHR.. Tree Data Interface sharable library.
tree.... A linked collection of nodes.
units... The physical measure associated with a number.
unsigned Integer forms ranging from 0 to 2^(number of bits)-1.
vector.. A linearly ordered list of scalars. A rank-one array.
window.. The region of an axis that is viewed.
word.... Two bytes of information, an integer.
XD...... A class of descriptor for dynamic storage.

CC-use

The easiest calls are the MDSLIB routines.

To eliminate using the compiler you could write functions to be evaluated. This involves many descriptors and pointers, see OPC$.

Between the inefficiency of compilation and the difficulty of function coding is the method of direct calls to the TDISHR library. Like

       status = TDI$ADD(&first_dsc, &second_dsc, &output_dsc);

Other than special calls directly into TDISHR, you call routines by names like TDI$xxx, where xxx is the function to be performed. Each routine returns a VMS-type status code as its function value. The arguments are the addresses of descriptors of each input with the final argument being the one output descriptor.

Operations like + have special names like TDI$ADD, see Precedence.

Calls

As an example of TDISHR calls we will add 2 and a tree element.

       #include descrip
       int call_test(struct dsc$descriptor *out_dsc_ptr)
       {
           static int const two = 2;
           static struct dsc$descriptor two_dsc
= {0,DSC$K_DTYPE_L,DSC$K_CLASS_S,&two}; static $DESCRIPTOR(const elem_dsc, "\\TOP.XRAY.CHAN_1:GAIN"); int status;
status = TDI$ADD(&two_dsc, &elem_dsc, out_dsc_ptr); return status; }

This example would be easier to code in VAX Fortran.

MDSLIB

As an example of MDSLIB calls we will add 2 and a tree element. The experiment and shot are assumed identified elsewhere.

       #include descrip
       int call_test(struct dsc$descriptor *out_dsc_ptr)
      {
           static $DESCRIPTOR(const expression,
                     "2+\\TOP.XRAY.CHAN_01:GAIN");
           int status;
status = MDS$VALUE(&expression, out_dsc_ptr); return status; }

This example would be easier to code in VAX Fortran.

OPC$

The most difficult form of coding is to define all relationships with pointers in special (class-R) descriptors to other descriptors of VMS and MDSplus data. As an example, we will add 2 and a tree element. Use DCL to

       DEFINE C$LIBRARY MDS$ROOT:[SYSLIB]MDSDEF.TLB

before compiling with CC the following code excerpt:

       #include descrip
       #include tdescrip
       int opc_test(struct dsc$descriptor *out_dsc_ptr)
      {
           globalref unsigned short OPC$ADD;
           static int const two = 2;
           static struct dsc$descriptor const two_dsc
                   = {sizeof(two),DSC$K_DTYPE_L,DSC$K_CLASS_S,&two};
static $DESCRIPTOR(const elem_dsc, "\\TOP.XRAY.CHAN_1:GAIN"); static struct dsc$descriptor_r const add_dsc = {2,DSC$K_DTYPE_FUNCTION,DSC$K_CLASS_R,&OPC$ADD,2,0, &two_dsc,&elem_dsc}; int status;
status = TDI$EVALUATE(&add_dsc, out_dsc_ptr); return status; }

The included files define the descriptor structures, descrip from VAXCDEF and tdescrip from MDSDEF. The global reference is to TDISHR and the function number is used by EVALUATE to do the operation. The node's data is fetched and its data type, and possibly two's data type, are converted to match. The addition is done and the result is embedded in units and signal descriptions as needed. The result is then matched to the output descriptor's data class and type. The output descriptor must be class-XD if the result is more complicated than a standard scalar. The input arguments could be "static const" because they are read only.

Status

Each TDISHR routine returns a longword VMS-type status.
The lowest bit is set (status & 1) if the operation succeeded.
Otherwise, the error may be signaled by LIB$SIGNAL(status) or its text fetched by SYS$GETMSG(status, &length_ret, &text_dsc, 15, 0).

Fortran-use

The easiest calls are the MDSLIB routines.

To eliminate using the compiler you could write functions to be evaluated. This involves many descriptors and pointers, see OPC$.

Between the inefficiency of compilation and the difficulty of function coding is the method of direct calls to the TDISHR library.

      status = TDI$ADD(%DESCR(first), %DESCR(second), output_dsc)

Other than special calls directly into TDISHR, you call routines by names like TDI$xxx, where xxx is the function to be performed. Each routine returns a VMS-type status code as its function value. The arguments are the addresses of descriptors of each input with the final argument being the one output descriptor.

Operations like + have special names like TDI$ADD, see Precedence.
WARNING each TDI routine must be declared as an Integer*4.
WARNING (Today, Fortran include file tdescrip does not exist.)

Calls

As an example of TDISHR calls we will add 2 and a tree element.

       Integer function call_test(out_dsc)
       Include 'FORSYSDEF.TLB($DSCDEF)'
       Record /DSCDEF1/ out_dsc
       Integer two /2/
       Character*21 elem = '\TOP.XRAY.CHAN_1:GAIN'
call_test = TDI$ADD(%descr(two), %descr(elem), out_dsc); Return End

We could also have used

       TDI$ADD(%descr(2), '\TOP.XRAY.CHAN_1:GAIN', out_dsc)

MDSLIB

As an example of MDSLIB calls we will add 2 and a tree element. The experiment and shot are assumed identified elsewhere.

       Integer function mds_test(dataid)
       Integer dataid
mds_test = MDS$GET('2+\TOP.XRAY.CHAN_01:GAIN', dataid); Return End

OPC$

The most difficult form of coding is to define all relationships with pointers in special (class-R) descriptors to other descriptors of VMS and MDSplus data. As an example, we will add 2 and a tree element. As of this writing, there is no TDESCRIP definitions for Fortran use.

       Integer Function opc_test(out_dsc)
       Include 'FORSYSDEF.TLB($DSCDEF)'
       Include 'FORMDSDEF.TLB(tdescrip)'
       Record /DSCDEF1/ out_dsc
       External OPC$ADD
       Integer two = 2
       Character*21 elem = '\TOP.XRAY.CHAN_1:GAIN'
       Record /DSC$DESCRIPTOR_R2/ add_dsc
add_dsc.dsc$w_length = 2 add_dsc.dsc$b_dtype = DSC$K_DTYPE_FUNCTION add_dsc.dsc$b_class = DSC$K_CLASS_R add_dsc.dsc$a_pointer = %loc(OPC$ADD) add_dsc.dsc$b_ndesc = 2 add_dsc.dsc$a_dscptrs(1) = %loc(%descr(2)) add_dsc.dsc$a_dscptrs(2) = %loc(%descr(elem)) opc_test = TDI$EVALUATE(add_dsc, out_dsc); Return End

The included files define the descriptor structures. The external reference is satisfied by TDISHR and the function number is used by EVALUATE to do the operation. The node's data is fetched and its data type, and possibly two's data type, are converted to match. The addition is done and the result is embedded in units and signal descriptions as needed. The result is then matched to the output descriptor's data class and type. The output descriptor must be class-XD if the result is more complicated than a standard scalar.

There is no way in VAX Fortran to "Data" (initialize) a record.
This is better done in C, if it is done at all.

Status

Each TDISHR routine returns a longword VMS-type status. The lowest bit is set (status .AND. 1) if the operation succeeded. Otherwise, the error may be signaled by LIB$SIGNAL(%val(status)) or its text fetched by

      SYS$GETMSG(%val(status), length_ret, text_ret, %val(15), ).

Precedence

TDISHR supports many syntactical forms having different precedence.
Precedence determines the order operations are done when operators are on both sides of a resolved portion of an expression. Thus, precedence makes 2+3*4 have value 14 and not 20.

Operators with equal precedence are evaluated left to right (LR) or right to left (RL). You may use F90 (/ for [, /) for ], and /= for !=.

group function name symbol
(highest precedence)
-- grouping (none) (x)
LR postfix CALL(i,r,[x]...) i->r:type(x,...)
POST_DEC(v) v--
POST_INC(v) v++
SUBSCRIPT(x,y,...) x[y,...], x(/y,.../)
VECTOR(x,y,...) [x,y,...], (/x,y,.../)
RL unary INOT(x) ~x
NOT(x)  !x, NOT x
PRE_DEC(v) --v
PRE_INC(v) ++v
UNARY_MINUS(x) -x
UNARY_PLUS(x) +x
RL power POWER(x,y) x^y, x**y
LR multiply MULTIPLY(x,y) x*y
DIVIDE(x,y) x/y
MOD(x,y) x MOD y
LR addition ADD(x,y) x+y
SUBTRACT(x,y) x-y
LR shift SHIFT_LEFT(x,y) x<<y
SHIFT_RIGHT(x,y) x>>y
LR concatenate CONCAT(x,y) x//y
LR subset Hi - IS_IN(x,y) x IS_IN y
LR inequality GE(x,y) x>=y, x GE y
GT(x,y) x>y, x GT y
LE(x,y) x<=y, x LE y
LT(x,y) x<y x LT y
LR equality EQ(x,y) x==y, x EQ y
NE(x,y) x!=y, x<>y, x/=y, x NE y
LR bit-AND IAND(x,y) x&y (see IAND etc.)
LR bit-EOR (see IEOR etc.)
LR bit-OR IOR(x,y) y (see IOR etc.)
LR equivalence EQV(x,y) x EQV y
NEQV(x,y) x NEQV y
LR logical-OR OR(x,y) x && y, x OR y
OR_NOT(x,y) x OR_NOT y
NOR(x,y) x NOR y
NOR_NOT(x,y) x NOR_NOT y
LR logical-AND AND(x,y) x y, x AND y
AND_NOT(x,y) x AND_NOT y
NAND(x,y) x NAND y
NAND_NOT(x,y) x NAND_NOT y
RL promotion PROMOTE(x,y) x@y
RL conditional CONDITIONAL(y,z,x) x?y:z
RL range BUILD_RANGE(x,y,[z]) x..y, x..y..z, x:y
RL assignment EQUALS(v,x) v=x
EQUALS_FIRST(ADD(v,x)) v+=x, ... v MOD=x, ...
RL immediate does EVALUATE(x) x, (x)+y
LR comma COMMA(x,y,...) x,y,...
LR statement (none) x;
STATEMENT(s,...) {s ...}
BREAK() BREAK;
CASE(x,s,...) CASE(x)s
CONTINUE() CONTINUE;
DEFAULT(s,...) CASE DEFAULT s
DO(x,s,...) DO{s...}WHILE(x);
FOR([x],[y],[z],s,...) FOR(x;y;z)s
FUN(f,s,v...) FUN f(v,...)s
PRIVATE FUN f(v,...)s
PUBLIC FUN f(v,...)s
GOTO(x) GOTO x;
IF(x,s,se) IF(x)s
IF(x)s ELSE se
LABEL(v,s,...) LABEL v: s
RETURN([x]) RETURN(x);
SWITCH(x,s,...) SWITCH(x) s
WHERE(x,s,se) WHERE(x)s
WHERE(x)s ELSEWHERE se
WHILE(x,s,...) WHILE(x)s
does EVALUATE(s) s
(lowest precedence)
where x, y, or z are resolved expressions, f and v are variables, and s and se are statements. Think about "-2.^-3^4". (Answer: -2.417852E24.)

Signals

A signal is data with its source (RAW is usually an intermediate expression) and its DIMENSIONs. The dimensions are the independent axes of the dependent data. For example, a waveform is a function of time and the dimension is the time points at which the waveform was recorded. Often this axis is a simple expression that can be expressed as a SLOPE or RANGE.

In combining expressions with signals, generally a single signal will dominate. When more than one signal is combined, only one signal can be chosen. The signal selected will be the one with the smaller number of elements as this limits the size of the result.

Units

Units can be added to any data field by the WITH_UNITS descriptor.
Units are the "dimensions". (Be careful not to confuse this with the word for the independent axis.) Units are like meters and seconds.

Spell out units with lowercase or better yet use the abbreviation.
Proper names are spelled in lowercase or abbreviated in uppercase.

The basic unit names are:

       m       meter           kg      kilogram        s       second
       A       ampere          K       kelvin          mol     mole
       cd      candela

The supplementary unit names are:

       rad     radian          sr      steradian

Derived unit names are:

       Hz      hertz        	J    	joule        	N       newton
       Pa      pascal       	W   	 watt       	C       coulomb
       V       volt         	(Omega) ohm     	S       siemens
       F       farad        	Wb  	weber      	H       henry
       T       tesla        	lm   	lumen       	lx      lux
       Bq      becquerel	Gy   	gray

Use star (*) for multiplication.
Use caret (^) to mark powers.
Use positive powers and precede negative ones by a slash (/).

The use of nonstandard names, like sec for second, will inhibit the use of later (to be written) unit handling.
It is unlikely that Pa/torr will be recognized as unit-less, it will be hard enough to see that V*A is W.

Restrain the use of multipliers. If you do use them, then:

f for femto, p for pico, n for nano, u for micro, m for milli, k for kilo, M for mega, G for giga, and T for tera are OK. (Micro is a Greek mu but u is readable.)

>>>>>>>>>WARNING, use the preferred SI units:

Avoid cm for centimeter, use mm or m.
Avoid G or gauss, use T. (1T = 10000G, 1mT = 10G.)
Use of eV for electron volt may be necessary.
The abbreviation of millitorr is mtorr.

Conversions and simple arithmetic operations do not change the units.
For example, BYTE, ABS, and UNARY_MINUS keep the units.

The argument of mathematical operations like SIN(x) should not have units because the number must be dimensionless.
Degrees are not recognized--Use SIND(x).

The units of a result are defined for some binary operations:
Addition and subtraction retain the units of a single WITH_UNITS or if the units match. Otherwise, the result is an error and is given the units "?".

Multiplication and division try to combine units.
Problems exist with SQRT, POWER, and PRODUCT. PRODUCT may have an ill defined number of terms. (It depends on the MASK and the number of $ROPRANDs.)

TDI$_direct_calls

These routines directly enter TDISHR and have less error checking.
They do return a long status and must be declared as INTEGER*4 in Fortran programs.

Additional information available:

TDI$CONVERT(%descr(IN),%descr(OUT))
TDI$CVT_DX_DX(%descr(IN),%ref(DTYPE),%descr(XD))
TDI$FAULT_CLEAR([%ref(NEW)])
TDI$FAULT_HANDLER(%ref(SIG_ARGS),%ref(MECH_ARGS))
TDI$GET_DATA(%ref(OMITS),%descr(IN),%descr(XD))
TDI$GET_FLOAT(%descr(IN),%ref(OUT))
TDI$GET_LONG(%descr(IN),%ref(OUT))
TDI$GET_NID(%descr(IN),%ref(OUT))
TDI$$INTRINSIC(%val(OPCODE),%val(NARG),%ref(LIST),%descr(OUT))

Restrictions

Trouble words for tree node names without preceding . or : are the names of standard operations: NOT BREAK CONTINUE ELSE ELSEWHERE.

It is highly recommended that child or member nodes be marked.

Partial implementation:

No IO nor DECODE/ENCODE/STRING.
Statements not written: ON_ERROR WHERE.
Elementals: BITS NEAREST IS_IN.
F90: CSHIFT EOSHIFT PROJECT RANDOM_SEED
RESHAPE TRANSFER UNPACK
F90 system: DATE_AND_TIME SYSTEM_CLOCK.
Cross-element: CONVOLVE DERIVATIVE FFT INTEGRAL MEDIAN
RC_DROOP INTERSECT SMOOTH.
Matrix: INVERSE MATMUL SOLVE TRANSPOSE.
Interpolation: INTERPOL MAT_ROT MAT_ROT_INT REBIN.
No SUBSCRIPTS for variable store.
Axes are not propagated for most transforms.
No text to numerics, no Abs("123"). Numbers compiled OK.
Subscript should immediately follow name. Watch NOT[sub].
[non-VMS] generates VECTOR not APD.
APD is evaluated by VECTOR requiring DATA of objects.
No units for POWER SQRT and some transforms.
Quirk:
-128b is illegal because it is negative of "bad" 128b, etc.

APD: Array of Pointers to Descriptors

About TDISHR

Software version: 9-Oct-1991.
Help version: 9-Oct-1991.

The information in these texts is subject to change without notice and should not be construed as a commitment for development by the MDSplus development team.

The software described in these texts is furnished under a license and may be used or copied only under the terms of such license.

The Tree Data Interface shared library is mostly written by

Kenneth A. Klare
Group P-4, MS E554
Los Alamos National Laboratory

All rights reserved, 1989, 1990, 1991.