SLAC ESD Software Engineering Group
Stanford Linear Accelerator Center
AIDA

Aida Basic User Guide

SLAC Detailed
SLAC Computing
Software Home
Software Detailed
AIDA

This page describes how to use AIDA to program some simple data acquisitions from the B-factory accelerator databases and control systems in Java. The setup and examples are for the SLAC AFS Unix system, but can be generalized to Windows.

Contents: Setup for Development The AIDA API
See also: Aida javadoc, in particular the classes DaObject and DaReference (and DaReference's parent _DaReference) in aida.lib.da which form Aida's programming interface. One can also use Matlab.


This web page describes tutorially how to program an application in Java that uses Aida to do data acquisition. First is described the required setup for development, then what is required in the environment of an application using Aida, and finally the Application Programming Interface (API) of Aida. More systematic documentation can be found in the Aida Javadoc.

Setup for Development and Delivery of AIDA Applications

Setup files to create the appropriate environment for Aida have been written, so, the short version of setup is simply to run those. The long version below describes what is in those setup files.

The Short Version

Create the basic development environment. This puts AIDA things in the CLASSPATH.

> source /afs/slac/g/cd/soft/dev/script/ENVS.csh

Set up specific Aida environment variables, and say which Aida network (dev or prod) you want to join (like the distinction between MCCDEV and MCC. Basically, if you want real accelerator data, join the prod network).

> source $CD_SOFT/dev/script/aidaSetEnv.csh [{dev|prod}]

Run a program with:

> java ${AIDABCSTRING} -DAIDA_DATABASE_USERID=AIDA${AIDA_MODE} -DAIDA_NAMESERVER_IOR_URL=${AIDA_NAMESERVER_IOR_URL} yourprogram

Examples

See the alias 'aidatest', which is defined by ENVS.csh (see above). It does this java invocation line for you, in order to run Aida test suite programs in /afs/slac/g/cd/soft/ref/package/aida/test/java/. The *.java files named *Tests.java contain java examples of getting data with Aida; those named da*Test.java are wrappers for their respective tests. For instance, daApiTest.java wraps ApiTests.java, and in fact that test suite is a good place to start for examples.

The Long Version

This section describes the Aida runtime environment in detail:

CLASSPATH

The following jar files must be in the CLASSPATH:

JAR file Use in AIDA
/afs/slac/g/cd/soft/ref/package/aida/lib/aida.jar The AIDA client side, including AIDA's API
/afs/slac/g/cd/soft/ref/package/except/lib/except.jar Exception (error object) definitions
/afs/slac/g/cd/soft/ref/package/err/lib/err.jar Error Handling and Logging
/afs/slac/package/iona/orbacus/prod/JOB/lib/OB.jar Orbacus implementation of CORBA, on which Aida is founded
/afs/slac/package/iona/orbacus/prod/JOB/lib/OBUtil.jar CORBA utilities used by AIDA.
/afs/slac/package/iona/orbacus/prod/JOB/lib/OBEvent.jar The mechanism for passing exception objects around.

Marginally better performance can be achieved for ref/package/{aida,err,except} by using the .class files directly in the CLASSPATH, rather than the jars. those are available in the edu.stanford.slac. package subdirectories of those packages.

JAVAVER

Aida must be run in Java 1.4 or above, though as of this writing (Mar-2010) it has not been tested in Java 6. So, for instance:

> setenv JAVAVER 1.5

BOOTCLASSPATH

OB.jar must be in the bootclasspath of a JVM running an application program using Aida. That is, you must start a program using Aida with:

> java -Xbootclasspath/p:/afs/slac/package/iona/orbacus/prod/JOB/lib/OB.jar ...

Aida Network (DEV or PROD)

There are three networks of Aida servers, one "AIDADEV" (used for development of Aida itself), and one "AIDAPROD", for real accelerator data, and available for general physics at SLAC, and thirdly "AIDALCLS", which is a high availibility network serving the same data as AIDAPROD, but exclusively for LCLS operations and only available on LCLS CA production network. On SLAC "AFS" computers (tersk, linux desktops etc), an Aida client can connect to either AIDADEV or AIDAPROD network when it starts. It does this by talking first to the right Aida NameServer (the one for the AIDADEV network or the one for AIDAPROD), and secondly telling the server which names database it wants to use. These two items are specified at the runtime of an Aida client program, by setting two Java properties to values which specify dev or prod:

  1. AIDA_NAMESERVER_IOR_URL - the URL at which can be found the CORBA Interoperable Object Reference (IOR) of the Aida NameServer of the Aida network you want to use (dev or prod).
  2. AIDA_DATABASE_USERID - the Oracle userid of the Names database you want to use (dev or prod).

See /afs/slac/g/cd/soft/ref/package/aida/common/script/aidaSetEnv.csh for how the valid values of these two properties are derived, and how to use them in the "java" command that starts an Aida client program.


What can Aida Acquire?

Aida discovers how to acquire a given "name", such as "BPMS:PR02:8012//twiss" by looking in an Oracle database. The database tells it which Aida Data Provder (DP) server is responsible for the name, plus a number of other details such as "what to actually ask the server for". A full explanation of the database is given in the Aida Directory Service Database Guide (a Word document), in particular the Entity Relation Diagram of the Directory Service Schema (pdf).

aidalist

You can simply browse the names in the database using a script called "aidalist". First "source /afs/slac/g/cd/soft/dev/script/ENVS.csh" if you haven't already done so. Then you can use aidalist from the command line (or even within unix matlab).

aidalist takes one, or optionally two, arguments. The first is the "instance" (the part before the //, the second is the "attribute" (like the secondary, or channel name). Either may include the Oracle SQL wildcard character '%' (note '*' is not wildcard to SQL).
aidalist <instance-pattern> [<attribute-pattern>]
Some example queries:
> aidalist XCOR:PR10:9042     - Confirms XCOR:PR10:9042 is known
> aidalist XCOR:PR10:9% - All "9 something" XCOR in PR10
> aidalist XCOR:PR10:9042 X% - All X attributes of XCOR:PR10:9042
> aidalist XCOR:PR10:9042 % - All attributes of XCOR:PR10:9042
> aidalist XCOR% % - All XCOR with all their attributes
> aidalist XCOR:LI%:502 twiss - Which linac 502 units have twiss

The AIDA Application Programming Interface (API)

This section describes how to use the Aida API. Most API features are described by example, but clearly an example can't be given for all combinations. The examples described here are taken from the demo ApiTests.java, but many more examples can be found in the Aida test suite.

The ApiTests.java demo

The following explanation of the AIDA API, is based on the examples in $CD_SOFT/ref/package/test/java/ApiTests.java. Each example is implemented as a method of that class. Each can be run individually using the wrapper daApiTest.java:

Eg, to setup and run test 2, which gets an array value from the SLC db, do this:

> source /afs/slac/g/cd/soft/dev/script/ENVS.csh
> source $CD_SOFT/dev/script/aidaSetEnv.csh prod
> cmlog -u &

> aidatest daApiTest 2
Constructing Err facility. Init ORB.
Sun Dec 12 21:06:58 PST 2004: Making connection to Name Service
Sun Dec 12 21:06:59 PST 2004: Making connection to daServer
IMMS of XCOR:LI03:120
-5.0
5.0
0.0

Important Notes: You only have to source the scripts once (obviously). Note also that, in this mode of testing, each execution of daApiTest goes through the whole Aida initialization, which includes things like connecting to the error service, connecting to Oracle etc. All these need only be done once. To get an idea of how fast Aida is after a program has been initialized, run 2 or more tests in the same execution (aidatest daApiTest 1 2 3), or run the performance test suite.

An Aida Client Setup Requirements

This section outlines the required code inside an Aida client which is necessary prior to using the Aida API to get data.

Imports

Import the classes you'll be using; these are like include statements in c code. Aida's API is in the last two of these. Additionally, the general purpose return object which Aida defines to help it return structured data, called DaValue, extends java.util.Vector, so you'll want that to help you manipulate Vectors. You'll also need the Err package, since Aida uses it to communicate errors.

import java.util.*; // useful stuff: Vector, Enumeration etc
import edu.stanford.slac.err.*; // error handling
import edu.stanford.slac.aida.lib.da.*; // Basic API
import edu.stanford.slac.aida.lib.util.common.*; // DaValue

Error Handling

Error handling in Aida is done through the Err package, which uses cmlog to log messages. Err uses a static singleton programming pattern - basically, the first time you call its getInstance() method, you must supply a string being the label it will use when logging your messages in cmlog (in the "Sys" column of a cmlog browser). It will return an Err object to you, with which you can log messages.

Eg, from daApiTest.java;

public class daApiTest
{
static Err err_; // Error issuance singleton.
/**
*/
public static void main(String args[])
{
// Register with the Error Messaging Service
err_ = Err.getInstance("daApiTest");
...

Note that, in ApiTests.java, the messages written in the catch block are written with System.out. In a real application, one would use Err.log(), using the Err object returned from Err.getInstance().

Note also that the Aida API methods (DaObject get() etc) described below, all throw Java checked exceptions. That means, you have to put them in a try{} block - the compiler will complain if you don't. See ApiTests.Test01 for example.

The main AIDA Api Object "DaObject"

To talk to Aida you need DaObject object. This connects to the Aida DaServer, and its methods allow you to get data. Its constructor throws checked exceptions, so you have to create it in a try block. See the example in ApiTests.java, in its case the constructor for DaObject is in the constructor for ApiTests:

                private DaObject da;
try
{
da = new DaObject(args);
}
catch ( Exception e ) {...}

Methods of DaObject for getting data

DaObject is described in detail in its javadoc entry. Here I shall work up some examples starting from the most basic and progressively adding features. The try blocks are omitted for clarity in the following examples.

Get a simple atomic value

Atomic types (like Double, Int, and including String) are acquired using DaObject.get.

For example see ApiTests.Test01:

Double v = (Double)da.get("TEST//VAL", DaValue.Type.DOUBLE);

 

Get an array of atomic values

Arrays of atomic types (like Double[], Int[], and String[]) are acquired using DaObject.geta.

Note that you both use the "get an array" geta method, and use an array variant of the type specified (so to get an array of Double you use DOUBLEA not DOUBLE). This is because the type argument of get and geta methods in AIDA, is formally the type that is required, not what type the data actually is in the native database. It tells Aida, and the Data Provider involved, to attempt to acquire the value, and if necessary make a conversion to the type given. However, bare in mind that a Data Provider that makes very general types of acquisition, like the SLC DB data provider, will take your argument as a clue about how to acquire the data, so it's a good idea to use something sensible. Check in the relevant Data Provider's user guide, under the Methods section of the Attribute you're trying to acquire, to see which methods are supported for that Attribute.

For example see ApiTests.Test02:

Double[] v = (Double[])da.geta("XCOR:LI03:120//IMMS", DaValue.Type.DOUBLEA);
for (int i=0; i < v.length; i++)
System.out.println( v[i] );

 

Get an array of atomic values, with a parameter

Aida allows you to supply arguments to an acquisition, using the setParam method of DaObject (or DaReference). Functionally, each argument consists of argument name assigned to an argument value, but this can be expressed two ways, either a single string like "MODE=7", or two strings like "MODE","7". Note that the arguments are always given as strings, even when the argument value is numerical eg da.setParam("MODE=7").

For example see ApiTests.Test03:

Float[] twiss;
String query = "BPMS:PR02:8032//twiss";
da.setParam("MODE=7");
twiss = (Float[])da.geta(query, DaValue.Type.FLOATA);

Get a structured value (with parameters)

Aida can return structured data in a special Aida class object called DaValue which extends java.util.Vector. This uses DaObject's method getDaValue (also available in DaReference). Vector can hold heterogeneous elements, so the first can be a float, the second can be a String etc. getDaValue automatically packages up the data you asked for as a DaValue, and you can use the methods of Vector to extract your data. For instance, the Aida SLC History Data Provider can return history data as a DaValue, in which case its structure is a Vector of 3 Vectors; the values, the times, and a "repeat count" (always valued all 0s and not interesting but maintained for compatibility with data returned by the EPICS channel archiver).

The following example acquires history, using DaObject arguments to specify the time range, and then calling getDaValue. Then 3 ways of looking at the data returned are given as examples. The example below is a hybrid of ApiTests.Test04 and Test05 (Test05 in fact illustrates a more direct way of inspecting the contents of the returned Vectors using Enumeration).

String query = "XCOR:LI03:120//BACT.HIST";
da.setParam("STARTTIME", "07/30/2004 00:00:00");
da.setParam("ENDTIME", "07/31/2004 00:00:00");
DaValue v = da.getDaValue(query);

// returns a Vector of 3 Vectors. First just toString() it.
System.out.println( "Test unparameterized history \t=" + v.toString() );

// Extract the values sub-Vector "v[0]", and times sub-Vector "v[1]"
Vector valuesvec = (Vector)v.get(0);
Vector timesvec = (Vector)v.get(1);
System.out.println("history values vector "+ valuesvec.toString());
System.out.println("history times vector "+ timesvec.toString());
// Convert the subvectors to array of Doubles and array of Strings.
int N = valuesvec.size(); // Get values Vector's length
Double[] values = new Double[N]; // Allocate an array of Doubles.
values = (Double[])valuesvec.toArray(values); // Copy Vector into array.
String[] times = new String[N]; // Allocate an array of Strings.
times = (String[])timesvec.toArray(times); // Copy Vector into array.
for (int i = 0;i<N;i++)
{
System.out.println( "history values [" + i + "]=" + values[i] );
System.out.println( "history times [" + i + "]=" + times[i] );
}

da.reset(); // Reset the arguments on da

Note the use of da.reset(). This is used to clear the parameters assigned to a DaObject. So, for instance, if you want to acquire history of a number of devices for the same time period, set the parameters once, then make the acquisitions with the same DaObject before doing the DaObject.reset.

To Add

DaObject.getAny

DaReference

Compiling a DaReference

Creating a DaReference with a DaObject

taxonomy of DaReference get calls

Calling DaObject methods with a DaReference

taxonomy of DaObject get calls passing a DaReference


[SLAC ESD Software Engineering Group][ SLAC Home Page]

Author: Greg White, 19-Nov-2004
Modified by:

Valid XHTML 1.0!