Update: 6/7/99:
- bdl syntax documentation has been updated and separated out into a separate file.

Update: 2/24/99:
- ASCII Constants Access is now Implemented.  Changed supported types to require specific bit numbers for integer parameters (Int16 instead of short).  Old types are still supported, but will produce warning messages from the latest bdlCompiler.

 
Update: 2/1/99:
- Updated to account for many of the environment evolutions that have been going on since last summer.
 

CLEO III Constants Access

    Welcome to the world of CLEO III Constants!  These pages are intended to document the user interfaces for defining, creating and using constants.  Before launching into the details, it seems appropriate to describe exactly what "Constants" are in the context of the CLEO III software environment.

   A "constants object" is a collection of related parameters with a common index that are typically stored, retrieved and used together.  For example, the set of numbers needed to perform sparsification of the SVX data might be grouped together as a single "SVXSparsification" object.  More likely, there would be a set of parameters for each channel and a different set of parameters for each crate which might be thought of as "SVSparsificationChannel" (indexed by ChannelNumber) and "SVSparsificationCrate" objects (indexed by CrateNumber).  It is probably easiest to think of a constants object as a vector of records.  In this example, there would be a single "SVSparsificationChannel" object that contains a record for each channel.  A single record of this object would contain all of the parameters for a single channel.

   The constants database can contain multiple "versions" of the same constants object.  Each version would be "valid" for a specified run range and possibly for a specific purpose.  One version of "SVSparsificationChannel" constants might be the "DEFAULT" constants valid from run R1 to run R2 and a different version might be the "DEFAULT" constants from run R2 to run R3.  There could be other non-default versions of constants as well.  For a full description of versions in the CLEO III database, see the CLEO III DataBase Version Information page.

    In practice, a constants object is a "smart" vector that contains the actual data for a single version of a specific type of constants as well as some information about the version such as the valid start and stop runs, the version number and the text "tag" associated with the version.  The version information has the same structure or appearance for all constants objects, whereas the structure of the data records is unique for each type of constants.  There are several different user interfaces through which the constants can be accessed, depending on your choice of programming language.  The only access method that is currently supported is via C++.  Other languages will be supported as demand and time dictate.



OK...  I think I'm ready to get started..... where do I begin?

    Good question.  I'm glad you asked.  The first step is to name your constants and define the structure of a record using a very simple "Baker Definition Language" that I created specifically for this purpose.  The syntax of these files is described here.

   Now that you've defined your constants, it's time to learn how to create and use constants objects.



Direct C++ Constants Access

2/1/99:  In order to actually compile and link your job (a minor detail), you will need to do the following
For Online users, see the DAQIII Online Database Page.

2/23/99: For Offline constants use via Suez, the software is far from complete.  For now, users can read and write their constants via ASCII files.  I have written up a detailed description of how to use constants objects from ASCII files here.

- Include directives:  To use DBConstants<DBXyZz>, you need the following #include statements:
#include "DBConstants.hxx"
#include "DBXyZz.hh"

Notes for Offline users:  These header files will be found in
    /nfs/cleo3/Common/rel/development/include/ConstantsUtility/
    /nfs/cleo3/Common/rel/development/include/BDLclient/
    Include the necessary libraries, include directories and symbol definitions in your Makefile.  See
    /nfs/cleo3/Offline/rel/current/src/ConstantsDelivery/Makefile for an example.

4/22/98:  STL dependency removed:  If your machine does not support STL, include -DDONT_HAVE_STL in your compile command.  (Of course this should be taken care of in some global definition file that checks what platform/compiler you are using.)   The only other documented feature that has changed is an additional constructor that takes an array instead of a vector to create new constants.  Other changes affect the way that the DBConstants<T> class is storing data internally and some (so far undocumented) constructors for specifying select tags to use when synchronizing constants.  Also, all string variables have been replaced with char* to avoid problems with platforms that may not support strings.  For now, the DONT_HAVE_STL definition removes both STL and strings.  There are some functions that can take either string or char* inputs, but the string versions are excluded by #ifdef blocks when the  DONT_HAVE_STL flag is set.

The only access method currently supported is via C++.

The precompiler will create a header file that you must #include when you use a constants object.  The name of the header file and the name of the constants class are derived from the "Name: " line in your .bdl file.  If you name your constants XyZz, the generated class will be DBXyZz, and the header file will be named DBXyZz.hh.  The header file will be put into a directory in the Common area. The class DBXyZz is a very simple "record" that contains the information you specified in your .bdl file.  For example, if one of your data items was defined as "float myFloat", a DBXyZz object will have a float member data item named m_myFloat and will have member functions to set and retrieve the parameter value.  The functions will be:

inline const float& get_myFloat() const;                // implementation is: { return m_myFloat; }
inline void set_myFloat( const float& value );        // implementation is: { m_myFloat = value; }

In addition, a DBXyZz object will have setIndex and getIndex functions to set/retrieve the index value, which is the first parameter defined in your .bdl file.  Although your index field will have get_ and set_ functions that use the name you provided, the setIndex and getIndex functions allow access to the index in the same manner for all records.  The functions are decalred as:

inline const int getIndex() const;
inline void setIndex( const int index );

The class DBXyZz will implement the standard copy constructor and assignment operators.

If you look at the actual header file, you may note that there are a few other methods declared, but DO NOT even think about using them.  They are features that are used only by the DBConstants<T> class.  I will hide these functions when I get a chance.  As far as you should be concerned, DBXyZz is a very simple class that is just a repository for the parametrs you declared in your .bdl file.

By itself, DBXyZz isn't very useful, but it can be used to instantiate templated DBConstants<T> objects.  A DBConstants<T> is essentially a smart vector that knows how to read and write your constants from/to the database (as of Feb, 99, also to/from ASCII files).  The standard usage of DBConstants is illustrated by the following code segments.

// Starting out, perhaps at job initialization: declare your constants object

   DBConstants<DBXyZz> myFavoriteConstantsObject;

// check if constants are loaded:
   if ( myFavoriteConstantsObject.isValid() ) { ...  // will return false here because you haven't loaded any constants yet!

// Different methods of "filling" your object:

// default synchronization to "DEFAULT" constants, time:
   myFavoriteConstantsObject.synchronize();

// Or you can pass an explicit DBVersion::Select object to
   DBVersion::Select myPersonalVersionSelect;   // Set this up however you want and then
   myFavoriteConstantsObject.synchronize(myPersonalVersionSelect);

// Or use the DBVersion::Select passed to you by the Global Slow Control process
   myFavoriteConstantsObject.synchronize(GSC_Passed_VersionSelect);

There are a few other synchronization options that I will document soon...

Once you have synchronized, you can use your constants just like a const vector<T>.  Specifically, DBConstants<T> has the following utility and accessor functions:

   const int size() const;          // returns the number of constants records just like .size() for a standard STL vector

   const T& operator[]( const int i ) const;   // standard dereferencing but note that it only returns a CONSTANT object! 0 <= i < size()

   const T& get_index( const int index ) const;  // returns the record with an index that matches the specified value

So you would use your constants object as follows:

   if myFavoriteConstantsObject.isValid() {

      for ( int channel = 0; channel < myFavoriteConstantsObject.size(); channel++ ) {

         const float aParameter = myFavoriteConstantsObject[channel].get_myFloat();   // use as you would any "const float"

      }

// or perhaps to consider only channel # n:
     const float FloatValueForChannel_n = myFavoriteConstantsObject.getIndex(n).get_myFloat();
// or if you know that channel #n is also the nth entry in the constants vector, you can get the desired value more efficiently with
     const float FloatValueForChannel_n = myFavoriteConstantsObject[n-1].get_myFloat();
   }
 

Note that the getIndex(i) method is nowhere near as fast as standard dereferencing.  If you want fast random access to your constants, you will have to know which record number you want and use [].

But what if I want to CREATE or CHANGE constants?

Good question.  Once you instantiate a constants object, there is no way to change the value of any of its parameters except by using the "synchronize" or readFromFile methods, and those will just retrieve constants from the DataBase or ASCII file.  If you are doing calibrations, you will need a method to create and change constants.  This is accomplished by creating a DBConstants object using a special constructor that takes as input a vector<T>.  The following example illustrates a simple case:

4/22/98:  Alternate form available using DBXyZz* array instead of vector.

   vector<DBXyZz> newConstantsVector;
// or
   DBXyZz* newConstantsArray = new DBXyZz[maxRecords];

   DBXyZz TempObject;
   for ( int i = 0; i < maxRecords; i++ ) {

// calculate the right constants for this record...
// this might include obtaining it from an existing
// constants object ( i.e. x = myFavoriteConstantsObject[i].get_myFloat(); )
      TempObject.setIndex(i);
      TempObject.set_myFloat(x);

      newConstantsVector.push_back(TempObject);
// or
      newConstantsArray[i] = TempObject;
   }

// Now pass the vector you have created to the constructor of a new DBConstants object:
   DBConstants<DBXyZz> newConstantsObject(newConstantsVector);
// or, without STL, use the constructor that takes an array, but you must also pass the length of the array:
    DBConstants<DBXyZz> newConstantsObject(newConstantsArray, maxRecords);

// You will also need to set up version description information for your new constants,
// but I haven't fully implemented all of that yet.  For now, just to get started, you can
// ignore version information.

// Once the constants are completely set up, simply invoke the write() method:

   newConstantsObject.write();  // writes to database

// or
    newConstantsObject.writeToFile("/home/myname/mysubdirectory/myASCIIFile");  // writes to file

That's all!  Your constants will be inserted into the database as a new version. For now, each newly inserted version becomes the default version and when you retrieve constants, you will always get the most recently inserted version.  We are working to fully implement version selection, but it certainly isn't done yet.   I will add more information to this page as I can.

This isn't done yet...  I'm working on it.

Rich Baker