The BaBar Calibration System
Lawrence Berkeley Lab
In this document we describe the BaBar calibration system. This system is based on a proposal presented in 19961. This system has been adopted for electronics calibration by the BaBar online group. A recent offline reconstruction workshop has also given provisional endorsement of this system for performing datastream calibrations in Prompt Reconstruction.
The BaBar calibration system provides for many of the technical aspects of dealing with these environments. This minimizes the amount of expert knowledge necessary for subsystem developers to create calibration applications. It also presents a uniform interface to calibration users across all subsystems, and allows code reuse between subsystems.
The BaBar calibration system is not a framework like dataflow, OEP, or the offline reconstruction and analysis frameworks. It is instead a toolkit which provides developers with standard interfaces and implementations. It contains tested code which can be used to reduce the developer coding burden. This toolkit takes the form of a set of C++ classes which work together to provide the needed functionality.
This document will be kept current as the packages develop. The most recent version can always be found at http://online04.lbl.gov/~brownd/docs/BabarCalibrationSystem.ps. The reader is assumed to be familiar with the BaBar online and offline systems, and to have a basic understanding of C++ and OO software. This document is targeted mainly for developers of online or datastream calibrations, but calibration data consumers may also find it useful.
2) Design Overview
The BaBar calibration system design is based on a particular definition of calibration. We define calibration to be the characterization of the response of the detector and/or detector electronics to known stimuli. The purpose of calibration is to record those responses, in order to provide a better understanding of the physics significance of the event data, and to allow optimization of the detector for taking subsequent event data.
In calibration, the detector response is observed through the same electronics used for physics data. The stimulus may be artificial (such as charge injection) or natural (a track). Response characterization takes the form of determining the parameters of a function family (defined apriori) which best describe the response in terms of the known stimulus. Note that, by this definition, alignment is not a calibration, since that characterizes the position of the active elements of the detector, not the direct electronic response. Similairly, measurements made using anciliary hardware readout independently of the detector electronics (magnet current, ambient pressure, beam orbit monitors, etc.) are not calibrations. A characterizable detector response depedence on those measurements however would be a legitimate calibration.
The end result of a calibration may be simply the function parameters. It may also be an optimal value of a the function ordinate given the measured response. For instance, the result of a threshold calibration might be the threshold value which maximized the signal/noise, whose value as a function of threshold was parameterized in calibration.
In order to fully characterize a systems response, many different calibration measurements are required. For example, to characterize a typical ADC channel both itsgain and pedestal must be measured. Different measurements made on the same channel are referred to as calibration types. The term channel can refer to any unit of the electronic readout hierarchy below the readout module (ROM), such as front end channels, chips, sections, or modules2 . Subsystems must design their own calibration types specific to their needs, using the base classes and templates provided by the core software.
The BaBar calibration system divides the process of performing a calibration into well-defined steps. To allow an accurate response characterization, the stimuli must be repeated to average out statistical fluctuations. This loop over stimuli is refered to as pulsing. For each stimulus in the pulsing loop, the measured response is used to update the state of some object recording the response for the entire loop. This process is refered to as accumulation. Once sufficient stimuli have been accumulated, this object is processed to extract the parmeters. This is refered to as fitting. Final parameters can be either verified (compared against a reference, and judged compatible or incompatible), or validated (judged accurate or inaccurate). Once validated, parameters can be stored in the calibration database. These different phases of performaning a calibration are described in detail in the rest of this document.
An important concern which shaped this design was assuring data safety and quality. Calibration data is crucial to the interpretation of the event data and is irreplaceable if damaged or destroyed. This concern is especially prominent when using Objectivity, whose native API provides read-write-modify access to all users. This opens the possibility for inadvertent modification or destruction of calibration data by user code. To guard against data damage, users interact with the calibration system only through transient copies of persistent objects.
The calibration system also provides safeguards on the quality of the stored data. This is provided by using gatekeeper objects which test the structure and content of all calibration data before allowing it to be persistently stored. Together these strategies provide users with full read and write access to the calibration database without risking data quality or integrity.
Calibration data are stored according to the time-interval structure defined by the Conditions Database. This defines a time validity range for all constants, with the most-recently stored set generally assigned an open-ended range (valid until time +inifinty). Providing alternative versions of data for the same time period is supporte by the conditions database. Details of the conditions database are described in a separate document3 .
3) Calibration Packages
The calibration code is divided into several packages which follow the general guidelines for online, offline, and common packages4. BbrCalib is a common package which implements the user interface with the calibration database. It also contains most of the base classes used throughout the calibration system. Only the non-objectivity part of this package is used in dataflow. CalOnline is another common package which defines the interface for accumulating calibration data. These classes can be used in any only environment (dataflow, OEP, or PR). CalOdf is an online-only package which contains general calibration code specific to the dataflow. CalOffline is a new offline-only package which contains tools for offline manipulation and visualization of calibration data. BdbBrowser is a recently-released package with a GUI for browsing calibration data. This browser will be described in a separate note.
Subsystems are expected to manage at least four packages for calibration-related software. The XxxCond package should define the persistent classes used in calibration. Here, Xxx stands for the three letter acronym of a subsystem. This is an offline-only package. The DrcCond package, an example of this package for the DIRC system, is described in appendix E.
Subsystem classes for accumulating and fitting electronics calibration should be kept in the XxxOnline package. This is a common package, as accumulation and fitting should be transportable between dataflow and OEP.
Subsystem classes for datastream calibrations may be kept in the XxxOep package. This is also an appropriate package to contain TCÆdigi format conversion code. The DrcOep package is an example, and is described in appendix E.
XxxEnv packages already exist for all subsystems, but dont yet use calibration classes. As these packages define the reconstruction interface to the conditions database, they should provide appropriate proxies for calibration persistent data. Other kinds of conditions database classes (IE geometry and alignment) can also have proxies in these packages.
4) The BbrCalib package
The architecture of the calibration system is defined by the classes in the BbrCalib package. This package also contains several fully-implemented generic subclasses which can be used as-is for simple calibration types (pedestals, gains, etc.). The generic classes also provide examples for subsystem-specific calibration subclasses. BbrCalib also holds the CalBase class, a base class which defines the validation, verification, and storage user interface. The following sections describe these classes. More detailed information can be obtained from the source files (*.hh, *.ddl, *.cc).
4.1) BbrCalib base classes
The base classes described below define the behavior of the Babar calibration system through their interface. Most are abstract base classes, and need to be subclassed to provide useful implementations. A UML diagram of the BbrCalib base classes is provided in figure 1.
Figure 1: BbrCalib base classes
CalChan is the base class for accumulating and storing calibration constants for a single channel. It is the central class in the calibration system, being referenced by nearly every other class, and used in all phases of the calibration process in all the online environments. The base class is simple, but CalChan subclasses may be quite complex. CalChan is not a persistent capable class. Instead, it is stored persistently through inclusion in a persistent class.
The CalChan base class contains a channel ID which uniquely defines the channel. The interpretation of a channel ID is context-dependent. When accessed during verification or validation, or when stored in Objectivity, channel ID generally refers to a valid dataflow detector tag. When used within the dataflow system, the ID generally refers to the detector address. The only exceptions to these interpretations of the CalChan channelID are when indirection is used to compress redundant data. Indirections are discussed in detail in section 4.4.
The CalChan base class also provides a channel flag, which is used to summarize the status, condition, and properties of its data. The flag is divided into private fields, whose allowed values are predefined and whose setting is controlled, and public fields, which can be separately defined for each calibration type. The CalChan flag fields are described in detail in appendix A.
Because of Objectivity restrictions when storing collections of objects, and because of dataflow transmission restrictions, CalChan and its daughters can only contain fixed-length collections of fundamental data types (IE it cannot contain pointers, strings, lists, etc.). To insure platform independence and compatibility with Objectivity, the fundamental types used in CalChan and its daughters must be defined using the typedefs found in the file BaBar/BaBarODMBTypes.h. A further restriction applies to any CalChan class intended to be transmitted by dataflow that all the fundamental types used have the same byte structure. Since the base class contains 4-byte integers, this restricts data storage in all dataflow-based CalChan subclasses to 4-byte representation (essentially long and float).
CalChan also provides a virtual interface used in many parts of the calibration system. For instance, each CalChan subclass is required to provide its name (virtual const char* channelName()=0;). In addition to the explicity required pure virtual functions, CalChan subclasses are implicitly required to provide functional default constructors, copy constructors, and equivalence operators. Absence of these will cause template instantiation failure in user code. In addition to the default constructor, it is recommended that all CalChan subclasses provide a constructor which takes as input the channelID, and which initializes all specific data members to default values.
The channel a CalChan object represents is not necessarily a single electronics channel. For instance, a threshold value common to all channels in a chip can be described by a single CalChan object. A CalChan is intrinsically capable of being associated with any of the dataflow detector levels (module, section, chip, or channel). Association of a single CalChan object to arbitrary collections of electronics channels can be via an indirection. In all cases, the significance of what level or collection a CalChan object represents is not stored in the CalChan itself, but is provided by the calibration type (see section 4.1.4). Thus the same CalChan subclass may be used to represent channels in one type and chips in another.
CalChan subclasses are intended to be simple classes providing only basic data storage and access. Thus a single CalChan subclass can be used to store the constants from different calibration types if their data format (float, int, etc.) are identical. As with the channelID, the interpretation of CalChan data fields is provided by the calibration type. Thus the same CalChan subclass may be used in one calibration type to represent ADC values and in another TDC values.
Information common to a collection of CalChan objects is stored in a CalHeader object. CalHeader is a fully implemented class at base. If additional common information is needed to interpret a CalChan collection, CalHeader should be subclasses and that information should be stored in the CalHeader subclass. This guarantees that the information will not be lost in processing, transporting or storing the collection.
The CalHeader base class stores the number of pulses processed to create the data. It also defines a flag which describes the general condition and status of the collection. For instance, banks used as a standard against which to compare new data during verification or validation can be identified by having the reference bit set in their CalHeader flag. Flag selection will also be used to create a functional subset of the calibration database for efficient export to remote sites based on the nature of the intended remote usage, though this feature is not yet implemented. A full description of the CalHeader flags is given in appendix B.
This abstract base class defines the CalChan collection class which can be stored in the database. CalBank is a persistent-capable class, so all its subclasses can be persistently stored. Storing channels as collections is necessary since Objectivity overhead (16 bytes/object plus access time) precludes storing channels as individual objects. Since most use cases involve manipulating channel collections, this should not be a problem.
CalBank and its subclasses are not intended to be used directly by end users, as this could put persistent data in jeopardy. Consequently, the interface functions to this class are extremely sparse to discourage its use. End users wishing to access calibration data should use one of the CalBase subclasses defined below, or a dedicated offline proxy.
CalBank subclasses are associated with specific CalChan and CalHeader subclasses, but not with specific calibration types. Consequently, the same CalBank subclass can be used to store calibration constants for several calibration types in different subsystems. As with CalChan, generic CalBank subclasses should be used whenever possible to reduce the proliferation of classes.
CalBank subclasses own their CalChan data through the persistent variable-length array class ooVArray. Because the ooVArray template does not support polymorphism, it cannot be declared in the CalBank base class. Instead, CalBank subclasses must each declare an ooVArray for the specific CalChan subclass used by the type. This is demonstrated in the generic CalBank classes described in section 4.2. The CalBank base class contains an ooVArray of CalHistory objects to record the history of how the object was generated.
In general, several CalBank objects are needed to define the constants for all channels in a subsystem (IE the subsystems channels are divided among several CalBank objects). The division of channels into banks is defined per subsystem by the CalSysDfn object described below. Assignment of channels to banks cannot be arbitrary, as the ability to download calibration data back into dataflow currently requires that channels belonging to a ROM not be split between objects. In general, collecting all the channels in a ROM into a single CalBank is optimal, though load balancing in the SVT requires collections at the section level. The possibility of collecting channels from several EMC ROMs into a single object for efficiency reasons is still open.
CalType is an abstract base class that uniquely defines a calibration type. This class performs a number of functions, namely:
Much of this functionality is fully implemented in the base class, so calibration developers need only implement a few virtual functions. End users need never be aware of the existence of CalType objects, as they function automatically behind the calibration public interface. A detailed description of the CalType functions is given in appendix D.
Unlike CalChan and CalBank, there are no generic CalType classes: each calibration type must have its own unique CalType subclass. Calibration types which describe essentially the same information obtained via different mechanisms (EG ECAL gain measured via source or pulser) can and should share the same CalChan, CalHeader, and CalBank classes, but must have different CalType subclasses (though they could inherit from a common base class). Unlike CalBanks, a single CalType object describes all channels in a subsystem.
CalType is a persistent capable class. The base class data members describe the basic parameters of the type and the structure of the data storage for the type (which CalBank class, CalChan class, the number of objects for this type, etc.). Subclass data members are intended to store the values for cuts used in the channel content and CalType content tests. CalTypes are expected to be updated much less frequently than CalBank objects, as they describe detector configuration, not detector data. CalType owns a CalHistory object, in order to record its creation.
One of the jobs of a CalType object is to allow safe storage of new calibration data, presented in the form of a CalBase object. Consequently, a CalType object must be present in the database before data of its calibration type can be stored. Before copying the CalBase content into a persistent CalBank object, the CalType validates both its structure and content (validation can also be performed as a separate step before storing data). The structure test insures that the data are consistent with the calibration type (correct CalChan and CalHeader subclass), and that the channel IDs correspond exactly to those of the specified CalBank object. This test is implemented in the base class, guaranteeing that all stored calibration data are structurally correct.
Another CalType job is to verify data. Verification differs from validation in that it tests whether new data are consistent with old, whereas validation makes the stronger test of whether new data are fit to replace old. Verification will be used to make factory-mode running of BaBar more efficient, by avoiding the costly overhead of database storage and dataflow download of new calibration constants when the old ones are still adequate. The CalType verification interface is very similair to the validation interface, having a mandatory structure test with a user-defined content test. The verification structure test is identical to the validation test. The content check for verification is however separate from validation, and may or may not use the same algorithms and/or cut values.
The responsibility for defining both validation and verification content checks for every calibration type lies with the subsystem developer. A fully-implemented template function for the content checks are provided by the CalType base class. This template compares each channel with the most recent data for that channel taken from the reference calibration of this type. The general channel status flag for this channel can also be considered when making this comparison, to allow known bad channels to be skipped. The CalBase is considered to have been validated/verified if the number of channels failing this comparison test is less than a value defined per-object by the CalType object (this threshold is a base class data member). To account for drastic changes in calibration constants which may occur for instance when hardware is exchanged, the content test may be overridden via an optional argument.
During the validation content check, the CalType object is allowed to change the channel data. This might be necessary for instance if the data are sufficiently corrupt that they pose a danger to dependent downstream code. In this case, a reasonable strategy would be to replace the corrupt data with valid data for the offending channel from the reference set. The CalChan flags should always be set according to the original data. The verification content check is not allowed to change the channel data.
CalTypes do not directly own the data used to check the CalBase structure. Instead, they reference it through a CalSysDfn object. All CalType objects in a given subsystem share the same, unique CalSysDfn object, as the channel and object IDs must be the same for all types. Because this structure is not allowed to evolve, only a single CalSysDfn object for each subsystem is stored in the calibration database. The association of the CalSysDfn object with new CalType objects is made transparently in the CalType base class constructor.
CalTypes are also responsible for storing new CalType objects of their calibration type. Before being stored, the content of each new CalType object must be validated by the most recent CalType object in the database. The responsibility for defining the CalType validation algorithm lies with the subsystem developers.
Storing the first CalType object for a given calibration type uses a bootstrap procedure which requires explicit authorization. Once defined, types cannot be removed from the database, so this procedure should not be abused. Under normal operating conditions new calibration types will be needed only rarely.
The very first CalType object stored in a subsystem database must have the class name XxxStatusType. This type is intended to serve as the hot channel list for the subsystem. XxxStatusType may use any CalChan subclass for its storage, though a minimal CalStatusChan is provided. Only the XxxStatusType is allowed to create the persistent CalSysDfn object for the subsystem, to which every subsequent CalType object will refer in making its content tests. Thus XxxStatusType needs a special constructor for this purpose.
Because CalType objects internally record the conditions under which calibration constants were stored, it is not allowed to store a CalType object for a time in the past. Every new CalType object is therefore stored with the current time, defining the tests which will be performed on new calibration data of its type.
CalSysDfn is an abstract base class which defines the valid set of channel and object IDs for a subsystem. CalSysDfn is a persistent capable class which is stored outside the normal time interval structure of the Conditions Database, as, unlike other conditions information, it is not allowed to evolve with time. If the dataflow structure of a system changes it will be necessary to create a new database to store new data. No code will necessarily need modification to make this change. The need to have different databases for different system configurations is already foreseen in the general structure of the conditions database.
CalSysDfn must be subclassed for each subsystem. Thus every XxxCond package must define a XxxSysDfn class. CalSysDfn is flexible enough that the same class can be used to define test beams, test stands, and the IR2 configurations. Different configurations will require different objects of this class, and hence different databases.
The information content of a CalSysDfn object is somewhat redundant with that of the odf persistent map5 . To avoid storing redundant persistent information, it may be desirable for subsystems to implement their CalSysDfn object using persistent map objects. This may not permit the most efficient implementation of the CalSysDfn functions.
Exactly one XxxSysDfn object is stored in each subsystem database upon the storage of its first XxxStatusType object. New CalType objects are set to reference this same object during their construction. This implies that XxxStatusType must be the first object stored in a new calibration database, as a kind of bootstrap.
CalSysDfn uses the dataflow detector tag class odfdTag to validate channel structure. To be valid, the channel IDs of the CalChans must correspond to a valid detector tag for that subsystem.
The CalHistory class is used to record changes made on calibration data. When modifications are made to calibration data a CalHistory object is automatically created. During a CalHistory object's creation, it logs information regarding the change to the calibration data and information about the user who initiated the change. By keeping collections of CalHistory objects, a journal is produced that accurately tracks all modifications to calibration data. This journal can be used both to keep track of interactive operations when examining and manipulating data inside transient objects, and for recording the set of manipulations used to create persistent data.
In the CalHistory class, five data fields are used to register the necessary information concerning alterations to calibration data. These fields are:
Figure 2: BbrCalib generic classes
CalStatusChan is the simplest possible implementation of a CalChan in that it has no data members besides those defined by the base class. This class is intended to represent the general status for a channel, and can be used for the required XxxStatusType calibration type. Private and public fields of the normal CalChan flag operate exactly the same for this class as for any other, except that they are interpreted as the general condition of the channel, not just how it performed in a single calibration type.
CalStatusBank is a generic implementation of a CalBank using CalStatusChan. This class is the OO database equivalent of the hot channel list. It uses the base CalHeader class. This same class can be used by all subsystems to store the data of their XxxStatusType calibration type.
The responsibility for defining how the flag information from various calibration types are combined to produce the CalStatusChan general flag lies with the subsystem developer. The code for performing the merger should be part of the XxxStatusType class. Since this type will be used throughout the online and offline, it probably should be updated only rarely, in order to provide stability for users.
Two very similar generic CalChan subclasses (CalMSChan and CalMSNChan) are implemented for storing simple calibration data. These classes store a mean value and RMS as floats. CalMS[N]Chan objects can be used to represent any value whose sampling obeys Gaussian statistics: pedestals and gains are obvious examples. The only difference between these classes is in how they handle sample counting: CalMSChan assumes an external counter has kept track of the number of samples used to compute the value and RMS, while CalMSNChan stores the number of samples itself. CalMSChan is only appropriate when exactly the same number of samples will be used to compute values for all the channels in a CalBank, in which case the number of samples should be stored by the CalHeader object. CalMSNChan should be used whenever the number of samples may vary by channel. CalMSNChan is thus more general, while CalMSChan is more efficient in using storage space. Example use cases of CalMS[N]Chan classes are given in section 6.
As with CalStatusChan, generic CalMS[N]Bank subclasses are also provided for CalMS[N]Chan CalChan subclasses. These can be used with any appropriate calibration type in any subsystem.
4.3)CalBase and subclasses
CalBase is an abstract base class which defines the calibration user interface for verification, validation, data manipulation. It also implements store and retrieve functions which allow users to move data in and out of the calibration database. A list of CalBase functions can be found in Appendix C. A diagram of CalBase and related classes is shown in figure 3.
A CalBase object is a transient proxy to a CalBank. Data stored in the conditions database in the form of a CalBank can be loaded into a CalBase, where it can be manipulated and viewed. Conversely, data in a CalBase object can be stored in the database as a CalBank object, subject to passing the validation checks. This avoids users ever having to code directly to CalBank, which could compromise persistent data. CalBase objects can be used anywhere in user code where generic access to calibration data suffices. Offline applications which require read access to specific calibration data should probably implement a dedicated proxy to their CalBank data instead of using a CalBase subclass.
CalBase also defines the calibration interface between Dataflow and OEP. Data generated in Dataflow in the form of a CalTC must be converted into a CalBase object in order to be manipulated and/or stored in the database during OEP processing. The Dataflow calibration classes are described in section 5.3.
Each CalBase object contains a collection of CalHistory objects that summarizes the modifications that have been performed on its data. All CalBase operations that alter calibration data automatically add a CalHistory object that describes the action, creating a log of how the data was created. Additional CalHistory objects can be entered by the user as desired. Because the CalBase collection of CalHistory objects is stored when the CalBase is stored, a complete record of how calibration data was generated or modified will always be available.
BbrCalib contains three concrete implementations of CalBase. CalList is a CalBase subclass which has a polymorphic storage of the CalChan and CalHeader objects it contains. CalList uses the Rogue Wave pointer sorted vector template to store an ordered (by channelID) list of CalChan pointers. This class adds no new functions on top of the CalBase interface. Its use is appropriate where generic access to channel data is sufficient. For instance, CalList is used inside the CalType base class to access status information.
CalChanList is a templated CalBase subclass which provides a type-safe interface to channel and header data in addition to the polymorphic CalBase interface. This class is appropriate for use when the type of calibration data being used is known at compile time. CalChanList is also used as the underlying storage in the CalListCollection described below.
CalIndirectList class is a CalBase subclass specialized for use with indirect calibration types. Indirect calibration types are described more fully in section 4.4.3.
A subclass of CalBase which uses distributed object technology (IE CORBA) to store its data is forseen. This class will be used in the multi-processor Prompt Reconstruction environment. Details on this class will be given in a later note.
4.3.1) CalMapBrowser and associated CalBase constructors
A common use case in calibration involves creating a CalBase object with a complete set of channels whose channelIDs correspond to some fixed segment (say a ROM) of the hardware. For instance, this need arises in initializing storage for accumulation or fitting. The channelID spaces relevant for calibration are most fully defined by the map classes in the MapDetector package6 . To avoid reproducing the same code in another form, these classes are also used to define channel space in calibration. In order to decouple the specific implementation of these maps from the calibration code, an interface class CalMapBrowser is used.
The CalMapBrowser class defines an abstract interface for accessing a channelID space map of any kind. It functions as an iterater whose next function returns sequentially all the individual channelIDs of the objects between two layers of the dataflow system. For instance, a particular CalMapBrowser may be instantiated to browse over channels (lower level) specific to a particular ROM (upper level). Calling reset on a CalMapBrowser object returns it to the state it had on construction, allowing it to be reused.
Both CalList and CalChanList have constructors which take a CalMapBrowser object as input, and use it to create a collection whose CalChan members have the channelID numbers specified by the browser. These constructors also take as argument an example CalChan object, whose Chan subclass specific state (IE everything outside the channelID and the status flag) is copied into every channel in the collection.
CalSimpleMapBrowser is a trivial implementation of CalMapBrowser provided for test purposes. It works only in detector tag space, and assumes a compact, uniform channelID space. This class actually contains its map in specific data members whose value are defined on construction. Implementations of CalMapBrowser based on the MapDetector classes will be provided in a future release of the calibration code.
4.4) CalIndirect classes
In some calibrations, the underlying electronics may force the results to take on a limited range of discrete values. A hypothetical example of this would be a calibration whose result represents the setting of a small-range (say 4-bit) DAC. Similarly, a-priori conditions (such as geometry) may cause some calibrations to produce results which are equivalent across large collections of channels. In both these cases, the groupings of channels which give equal or equivalent results probably do not fall naturally into the dataflow hierarchy (IE, not all channels in a chip have the same values). In several known cases in BaBar, storing this redundant data for every channel results in a significant, unnecessary burden on the conditions database.
The CalIndirect classes were designed to avoid storing redundant channel data. The idea is to provide a layer of indirection which allows an arbitrary subset of channels within a system to point to the same CalChan data object. This indirection is supported by special subclasses of CalChan, CalHeader, CalType, and CalBase, as described below. A UML diagram of these classes is shown in figure 3.
Figure 3: CalBase classes
CalIndirectChan is a fully-implemented subclass of CalChan which defines the indirection layer of an indirect calibration type. CalIndirectChan has a single integer specific data member (called data index) whose value specifies the channelID of another CalChan (of unspecified subclass). The value of the data index has no relation with the channelID of the CalIndirectChan.
CalIndirectHeader is a subclass of CalHeader specialized for use with a collection of CalIndirectChans. CalIndirectHeader has a specific data member which records the maximum index value of the collection to which it is associated.
CalIndirectList is a subclass of CalChanList specialized for dealing with indirect calibration types. CalIndirectList is templated on the subclass of CalChan which stores the real calibration data. In addition, CalIndirectList contains a distinct CalChanList fully templated on CalIndirectChan and CalIndirectHeader. CalIndirectList satisfies the CalBase interface using its CalChanList base class. The channelIDs of the CalIndirectChans have valid detector tag values, as with normal calibration types. The channelIDs of the templated CalChanList CalChans must equal their index position in that list, and thus do not correspond to valid detector tags. The value of the CalIndirectChans data index correspond to a valid index in this data layer list. Thus a CalIndirectList connects a detector tag channelID with the data contents of the data layer CalChan. CalIndirectList also provides access to the indirection layer CalIndirectHeader.
CalIndirectList inherits its CalBase interface implementation from CalChanList, which provides direct access to the data layer via their index (= channelID). In addition, CalIndirectList provides two other interfaces to channel data. The first provides access to the CalIndirectChans indirection layer via their index and channelID. The second navigates the indirection to return the value of the data layer CalChan given the index or channelID of the CalIndirectChan. This latter interface allows one to hide the indirection from user code.
CalIndirectList overwrites the CalBase store and fetch functions to deal with both the indirect and the data layer through a single function. Invoking these functions with normal objectID value arguments acts on the indirect layer, storing or retrieving the CalIndirectChan list. Invoking these functions with a special value (-1) of objectID acts on the data layer. This interface defines the design that an indirect type uses the same data layer with all the calibration objects controlled by the type. CalIndirectList also overwrites the verify and validate functions to behave the same way as store and fetch.
CalIndirectType is the CalType subclass associated with indirect calibration types. CalIndirectType is an abstract class, and must be subclassed for every unique indirect calibration type. To correctly store and use an indirect calibration, its type must inherit from CalIndirectType. CalIndirectType inherits most of its functionality from CalType. It adds to CalType data members which record the CalChan and CalHeader subclass names of the data layer of the indirection.
A single CalIndirectType class manages the verification, validation, and storage of both the indirection and the data layers of a CalIndirectList. As in the CalIndirectList store and fetch interface, these layers are distinguished by the value of the objectID argument, with normal values indicating the indirection layer and a special value (-1) indicating the data layer.
To handle their overloaded meaning, CalIndirectType overwrites the CalType store,validate, and verify functions. When the objectID value indicates that the input CalBase represents the indirection layer, these functions simply call down to the CalType base functions. When the objectID indicates that the input CalBase represents the data layer, the normal structure check that the channelID values correspond to valid detector tags is bypassed, and instead the channelIDs are required to equal their index value in the CalBase collection. In both cases content check functions are also invoked.
The content check for the indirection layer of a CalIndirectType is fully specified in the base class. This simply confirms that the index values specified in the CalIndirectChans correspond to valid values in the associated data layer. Implicitly, this requires that the data layer be stored before any of the indirect layer objects. The content check for the data layer is the responsibility of the specific subclass implementation. This content check should verify that the dimension of the data layer is sufficient to satisfy all the CalIndirectChans in all objects of the indirection layer, in addition to an appropriate test of the data value contents.
In order to transport calibration accumulation and fitting code between Dataflow and Oep, a generic way of handling CalChan collections (CalTCs and CalBase subclasses) is needed. This is provided by the CalCollection class. CalCollection is an abstract base class which defines an interface for accessing channel data by index. In addition, the channelIndex function finds the CalChan in the collection whose channelID matches the input value. This function is implemented in the base class using a binary tree search. Specific CalCollection subclasses may wish to override this with a hash table or similar faster algorithm if the structure of their collection is known a-priori.
CalCollection is a wrapper class which does not own its data, but knows how to access the data in the class that it wraps. CalListCollection is a CalCollection subclass built around a CalChanList. A concrete implementation of CalCollection around a CalTC is provided in the CalOnline package. Use cases for CalCollection objects are described in section 5.4.
5) The CalOnline package
The general classes associated with the accumulation are kept in the CalOnline package. This is a common online/offline package, so the code within it can run both in dataflow, OEP, or PR. CalOnline contains the calibration-specific tagged container class CalTC, which interfaces calibration with the dataflow system. It also contains the interface class CalProcessor which allows a portable (IE between dataflow and the UNIX environments) implementation of accumulation. This interface is described in section 5.4.
The accumulation classes in CalOnline can be broken down into two categories, according to two virtual base classes: CalAddChan and CalFit. A UML diagram of these classes, their subclasses and their related classes are shown in figures 4 and 5 respectively. These classes are described in the following two subsections.
Figure 4: CalAddChan and related classes
5.1) CalAddChan classes
CalAddChan is an abstract CalChan subclass which adds special functions associated with accumulation. These functions allow the CalAddChan object state to be updated for new data presented on each pulse, or to prepare it for a new sequence of pulses.
The primary CalAddChan accumulation function is increment, which passes pulse data to the object. This function takes as input an object of class AbsArg7, which functions as a type-safe void *. With this prototype, increment can be implemented in the CalAddChan subclasses to take whatever type (IE float, int, or more complicated structures) is appropriate for that subclass. The cast from an AbsArg to the correct type is done via the AbsArgCast function, which insures type safety at run time. For instance, if one tries to cast an AbsArg representing a float to an int, the result will be a null pointer, whereas casting it to a float gives a pointer to a float. AbsArg is a very lightweight class which does not appreciably impact the performance of the increment method.
As with all CalChan subclasses, CalAddChan subclasses are required to have only simple (fixed size) data members, to allow them to be stored in the database. Storing a bank of CalAddChans may be useful during commissioning and debugging. During factory-mode running the CalAddChans will probably not be stored, but instead the CalChan output to the fit of the CalAddChan will be stored.
The CalOnline package contains four fully implemented CalAddChan subclasses. These are intended to be used directly by the subsystems, as well as serving as examples for subsystem specific accumulation implementations. These four classes cover many of the accumulation use cases described by the subsystems in their responses to the calibration survey.
The simplest CalAddChan is the CalEffChan, which is intended for measuring hit efficiency. This class increments a counter every time increment is called, regardless of the value of the AbsArg. A similar CalAddChan subclass is CalSS2Chan, which keeps a running sum, sum of squares, and counter. CalSS2Chan can use either int or float AbsArg inputs. Processing these channels into useful quantities (like efficiencies or means and sigmas) is done by the CalFit objects described in the next section.
A more complicated CalAddChan is CalHistChan. This base class defines an interface for interpreting channel data as a histogram. In CalHist, the input argument passed to the increment function is a float, which is used to increment an appropriate bin. The CalHist base class stores all information necessary to interpret the histogram (bin range and size, etc) and provides the usual set of histogram access functions (bin contents and center position by index, etc). It does not however define the type or storage of the bin contents. A particular CalHist subclass CalIntHistChan defines bin storage as 32-bit integers, with appropriate definition of the access functions. An implementation which allows weighted histograms is possible under the CalHist interface, but not yet implemented.
Because CalChan data members must be fixed-size, CalIntHistChan cannot be fully implemented for an arbitrary number of bins. Instead it must be subclassed to provide bin contents storage as a fixed size array. The class CalIntHist50Chan is provided as a 50 bin example of a fully implemented CalHistChan subclass.
In order to inspect CalHistChan contents, a translation to a viewable histogram form is needed. This is provided by the CalHistBook class described in section 6, which translates CalHistChans into Heptuple histograms.
Another CalAddChan subclass implemented in CalOnline is CalScatChan. This class stores a true scatterplot of points defined by the CalScatPoint class, which stores x,y, and dy as floats. The CalScatChan implementation of increment requires the AbsArg to be of type CalScatPoint, and simply copies this into the CalScatChans local store. As with CalHistChan, an arbitrary number of points cannot be stored in CalScatChan, hence it must be subclassed to provide fixed-size storage. The CalScat10Chan class is provided as a 10-point example.
CalScatChan is intended to be used in nested cycle calibrations, where the result of each low-level cycle is entered as a point in a scatter plot. A simple example is provided in the CalOnline test program TestCalFit.
Figure 5: CalFit and related classes
5.2) CalFit classes
CalFit is a templated abstract base class from which all calibration fits inherit. The term fit refers to the final processing of a CalAddChan after its been incremented for the last time. CalFit processing does not change the internal state of the CalAddChan, but instead produces a new CalChan object to store the processing result. Storing the processing result as a separate object guarantees that the intermediate calibration results (the CalAddChan objects) can be brought up through dataflow in the same state as when they were processed, to allow debugging of the CalFit object offline.
The CalFit base class defines the function fitChannel, which takes an input CalAddChan and sets the state of an output CalChan whose subclass is specified by the CalFit template argument. The output channel object is provided by the caller. To be used online (IE in the ROM), the fitChannel function must be implemented as a deterministic and fail proof algorithm, as its call will not be protected by timeout checks to catch infinite loops or exception handling to catch arithmetic exceptions. The output of the fitChannel function is a FitStatus flag, whose value can signal any irregular conditions which arise during the fit. This return value should also be encoded into the fitStatus field of the output CalChan object, allowing tests on the fit status to be deferred to verification or validation if desired.
The CalOnline package contains three fully implemented CalFit subclasses. These are provided both as examples for developing subsystem-specific CalFits, as well as for direct use in simple calibrations. CalSS2MSNFit has a trivial fitChannel function which converts a CalSS2Chan (which stores Sx, Sx2 , and S1) to a CalMSNChan (which stores mean, sigma, and N). The fit in this case consists only of simple arithmetic operations;
A more sophisticated example is provided by CalHistLineFit and CalScatLineFit classes. These perform a closed-form least squares linear fit to a CalHistChan or a CalScatChan, respectively. The minimization engine used for this fit is an object of class CalLeastSquares, an independent class which performs a closed-form minimization of any function when supplied with residuals and derivatives. CalLeastSquares provides a full-featured and general interface to allow it to be used by other CalFit subclasses which need minimization engines. Since the algorithm used is closed form and all risky operations (such as matrix inversion) are internally tested, it satisfies the CalFit online use requirements.
Figure 6: CalTC and releated classes
5.3) Dataflow-specific CalOnline classes
CalOnline contains several classes designed for use inside dataflow, but which are also used in OEP when converting from CalTCs to CalLists (analogously to the TC to Digi conversion done by subsystems in OEP). Calibration classes which are used only in dataflow are contained in the CalOdf package. A UML diagram of the dataflow-specific CalOnline classes is shown in figure 6.
The main dataflow-specific class in CalOnline is CalTC, which is the tagged container subclass specific to calibration. CalTC defines a CalChan collection like CalBase, but uses a special kind of memory management in order to facilitate dataflow transmission. CalTC inherits most of its functionality from its templated base class odfFlatTC, which implements channel storage using a self relative pointer. CalTC is not a base class, and needs only the specification of its template argument CalChan subclass to be fully functional. In addition to the channel storage, CalTC owns a CalHeader. Unlike CalBase, no subclassing of CalHeader is allowed inside a CalTC.
Like CalChanList, CalTC has a constructor which takes as input a CalMapBrowser and an example CalChan. This constructor functions analogously to the CalChanList constructor, building storage and setting channelIDs on all the channels specified by the browser. An implementation of CalMapBrowser around the dataflow map class odfMap will be provided in a future release of the CalOdf package.
CalTC has a special constructor which allows reconstitution of a CalTC object after transmission through dataflow. Reconstitution is a delicate process due to the need to rebuild the virtual table in the constituent CalChan objects, and should not be invoked directly by users. Instead, reconstitution takes place automatically upon instantiation and use of a CalTCIterator. The CalTC reconstitution constructor takes as input an object of CalTCBase, a class with no public constructors and no useful functions which should never be referenced directly by users.
CalTCIterator is a tagged container iterate specialized to work on a CalTC. It inherits most of its functionality from its base class odfFlatTCIterator, but adds the special functionality necessary to reconstitute the underlying CalTC when necessary. Given the indexed channel access provided by CalTC, there are very few reasons for users to ever need a CalTCIterator.
Figure 7: CalProcessor and related classes
5.4) Calibration portability classes
The calibration system has been designed to operate within all three of the online environments, namely dataflow, OEP, and Prompt Reconstruction. However, these environments present substantially different methods and classes for accessing the different transitions and the data associated with them. Because of this, the direct interface to most calibration classes has been left very general. In particular, none of the accumulation classes mentioned above provides functions for looping over channels or data accumulation cycles. Implicitly, their interface assumes those loops will be implemented in user code, independently for dataflow, OEP, and PR.
CalOnline includes a number of classes which provide a more general interface that implements some of these loops, and can be transported freely between the online environments. These classes do not provide any new functionality, but rather are wrapper classes, with subclasses built around the specific collection and accumulation classes already described. They provide access to the specific functions of those specialized classes through a standardized interface. A UML diagram of these classes is shown in figure 7, and they are described in detail below.
Calibration system users are not required use these wrapper classes to implement their calibration accumulation. Doing so may however reduce their coding burden and result in simpler, more easily maintained code. Using these classes will also insure that their code can be moved between dataflow and OEP with relatively little work. These wrapper classes however may not provide the most efficient implementation for all types of calibration, and users are advised to judge for themselves the costs and benefits.
It is foreseen to build code generators around the CalOnline wrapper classes which will allow automatic incorporation of user calibration code in any of the online environments without any additional coding. However, these code generators do not currently exist, and subsystem developers should not assume their existence any time soon.
The CalProcessor class encapsulates all the calibration accumulation functionality in a single object. It hides the complexity of the calibration process behind three simple functions: initialize, accumulate, and finalize. By simplifying and standardizing the calibration interface, CalProcessor simplifies the transportation of calibration code between the different online environments. CalProcessor relies heavily on the interfaces and functionality of other calibration classes to perform its job.
CalProcessor is a concrete class which implements the loops over channelIDs that are implicit in the fit and collection classes described above. It is a doubly-templated class, requiring as template arguments the CalAddChan subclass to be used during accumulation and the CalChan subclass which is the output of the fit.
The CalProcessor constructor requires CalCollection objects for both the accumulation and fit result, and a CalFit object capable of transforming the input CalChan subclass to the output. These objects are used directly by CalProcessor (IE they are not copied), but are owned outside it. It is therefore important not to alter the objects provided to the CalProcessor constructor, or to delete them or allow them to fall out of the CalProcessor object scope. The same warning applies to the CalCollection classes used by CalProcessor regarding the CalTC or CalChanList objects which they wrap.
The CalProcessor initialize function resets the state of all the CalAddChans in its input CalCollection. By default this is done by calling the CalAddChan reset function of those channels. If the optional example argument is provided, initialization is performed by equivalencing all the input channels to that example.
The CalProcessor finalize function loops over the accumulated CalAddChans and runs the CalFit fitChannel function on them. The output channel is the CalChan in the output CalCollection at the same index value as the input collection index. For this reason, the input and output CalCollection objects must have the same set of channelIDs. One way of guaranteeing this is to construct the CalCollection underlying object using the same CalMapBrowser.
The CalProcessor accumulate function must be called by the user for each step in the accumulation loop. This function takes as input an object of class CalIterator, which is described below. CalProcessor implements the accumulate function by looping over the input data specified by the CalIterator object, and calling the increment function of the corresponding CalAddChan for each element returned by CalIterator.
CalIterator is an abstract class which defines an interface for looping over channel-structured data and sequentially processing data from every channel into an AbsArg. CalIterator is used by CalProcessor as a standard way of accessing arbitrary data serving as input to calibration accumulation. To use CalProcessor to perform a particular kind of calibration accumulation, an appropriate subclass of CalIterator must be written. For instance, a CalIterator subclass designed to loop over the channels in the input container returned by a L1 accept of a given subsystem would be a natural way of implementing accumulation in the ROM.
The CalIterator interface is mostly defined by the next function, which returns an AbsArg for every channel in the collection it is iterating over. The next function also updates the value of the channelID argument (supplied by reference) to the value corresponding to the channel used to create the AbsArg. As with most other parts of the calibration system, the channelID return value must correspond to a valid detector address (in dataflow) or detector tag (in OEP or offline). The end function signals the last channel in the channel-structured data when it returns true. The CalIterator reset function should be implemented to return the iterator to its initial state.
Besides simply iterating over the collection, CalIterator must process the data it finds for each channel into the form expected by a particular CalAddChan. This processing function may be as simple as wrapping an AbsArg around a native data member in the channel-structured data, or it may involve calling elaborate mathematical transform functions. It is very likely that several CalIterator subclasses will be needed to loop over the same channel-structured data class when used to accumulate different calibration types. An example CalIterator implementation for raw data in the DIRC is described in appendix E.
CalCollectionIterator is a subclass of CalIterator intended for use in nested calibration cycles. It is a templated concrete class. Its constructor requires a CalCollection object and a CalChanArg object (described below), both templated on the same CalChan subclass as CalCollectionIterator itself. CalCollectionIterator implements the CalIterator functionality by simply looping over the index values of its underlying CalCollection. Its next function returns the AbsArg value returned by its CalChanArg when applied to the current CalChan object. It updates the input channelID to have the same value as the current CalChans channelID.
5.4.4) CalChanArg and CalMSNChanArg
CalChanArg is a templated abstract base class intended for use in nested calibration cycles. It defines the interface for a factory object which translates a (const) input CalChan object into an AbsArg value suitable for using in the increment method of an (unspecified) CalAddChan.
CalMSNChanArg is a fully implemented subclass of CalChanArg templated on CalMSNChan provided in CalOnline as an example. It combines the CalMSNChan mean and error together with a floating point value supplied on construction to build a CalScatPoint. The floating value is used as the CalScatPoint x value, while the mean and error are used as y and dy. The CalScatPoint owned by CalMSNChanArg is returned in the form of an AbsArg by the channelArg function. This class is used in one of the test programs described below.
5.5) CalOnline test classes and programs
The CalOnline package includes several classes designed for testing and developing CalAddChan and CalFit subclasses. The first of these is a virtual base class CalInput, which simulates the generation of raw calibration data. CalInput defines the pure virtual function fire, which returns an AbsArg containing randomly-generated data of a type defined by its subclass. The returned AbsArg can in turn be used to increment a CalAddChan.
CalGauInput, CalPointInput, and CalHistInput are three fully implemented CalInput subclasses found in CalOnline. CalGauInput returns a random floating point value distributed according to a Gaussian whose parameters are specified at construction. CalPointInput returns a random CalScatPoint object whose x value is distributed uniformly over a range specified at construction, and whose y value is smeared around the value of an arbitrary function evaluated at the random x value. This function is specified by the user at construction. The y smearing uses a Gaussian distribution independent of x whose sigma is specified at construction, which value is returned as the CalScatPoint dy value. CalHistInput returns a random floating point value whose distribution is specified by a CalHistChan object provided at construction.
The program TestCalTC tests construction, transmission and reconstitution of a CalTC. It also makes use of CalProcessor and CalTCCollection. The program TestCalFit directly tests all the CalFit subclasses described above, using an appropriate CalInput object to increment the CalAddChan.
TestCalFit also provides a simple example of nested calibration using CalProcessor. The test consists of two loops, an inner loop representing L1 accepts (pulses) and an outer loop (minor cycle) over DAC settings. The inner loop accumulates CalSS2Chans using a CalGauInput whose value depends on the DAC value specified by the outer loop step. Each time the inner loop completes, the CalSS2Chans are fit to produce CalMSNChans. The outer loop step combines these with the DAC value to create a CalMSNArg which is used to increment a CalScat10Chan. On completion of the outer loop, the CalScat10Chans are fit, producing a CalLineChan.
The CalOffline package contains a number of classes which can convert between calibration objects such as CalBase or CalHistChan to hbook ntuples and histograms (respectively).
A) CalChan flag fields
The CalChan flag is divided into private and public fields. The private fields can only assume predefined values, as they are intended to have a universal meaning across calibration types and subsystems. The public fields can be defined for each calibration type, and are intended to describe the results of the verification tests. Flag fields should be defined so that a null value means the channel is normal.
The value of the public flag may be accessed as an integer via the CalChan publicFlag method. It may be set using the setPublicFlag (sets value to input) or addPublicFlag (performs binary OR of the existing field with the input).
The private flag fields are defined in the following list. They can only be set by using the CalChan functions. In general, this should be done only during validation. The values listed below may not be changed, but new values can be added. The enums and bit fields for these are defined in BbrCalib/CalFlags.hh.
B) CalHeader flag fields
As with CalChan, the CalHeader flag fields are divided into public and private. The private fields of the CalHeader flag describe general attributes of the bank which owns it, while the public field can be defined as desired for different calibration types. A future release of the calibration system will allow searching the database for objects whose CalHeader flags satisfy an input (bit mask) condition.
The private CalHeader fields are defined in the following list. Most of these fields should be set prior to storing a CalBase object. The enums and bit fields for these are defined in BbrCalib/CalFlags.hh.
C) CalBase functions
The CalBase function set is listed below. Those functions not yet implemented are marked with a . Garden variety inspector and modifier functions are not listed here: people interested in seeing all the functions should look at BbrCalib/CalBase.hh.
Constructors. These are only public through the fully implemented classes CalList, CalChanList, and CalIndirectList.
D) CalType functions
The CalType class performs many functions, some of which are listed below. These functions are described only to give an understanding of the internal mechanisms involved, as the CalType interface should never be used directly. Only the validate functions are described: exactly analogous verify functions also exist, with nearly identical implementations. In addition to the functions described below, CalType has normal accessor functions which provide the names of the CalBank, CalChan, and CalHeader subclasses used for its data. CalType also has functions which return the name and unit name for each data field of the CalChan subclass it uses.
E) DIRC examples
The DrcCond package provides an example of subsystem specific CalSysDfn and CalType subclasses. Currently this package fully implements three calibration types relevant for the DIRC which use generic CalChan and CalBank subclasses. It also contains a few simple test programs which allow DIRC calibration data to be generated (with random values), stored, and retrieved.
The DrcSysDfn class is a subclass of CalSysDfn which fully describes the dataflow tag space for the DIRC. Because the DIRC has a simple and uniform dataflow hierarchy, this class contains only a few native data members, which it uses to implement the CalSysDfn virtual functions. By default the main constructor for this class builds the IR2 configuration. The constructor parameter defaults can be overwritten to describe a simpler configuration (IE a test stand). DrcSysDfn divides up the calibration objects according to ROMs, and defines the calibration object IDs to be the same as the module field values in the detector tag.
The DrcStatusType class defines the DIRC status calibration type (general channel status type). This uses the generic CalStatusBank class to store its types data. This class has data members which define bit masks which, when applied to the public CalChan fields, define the private field Quality and Condition values. Eventually this class will contain code to merge the status flags from different DIRC calibration types to define the general channel status.
The DrcPedType class defines the calibration type for the DIRC ADC readout pedestals. It uses the generic CalMSBank to store its types data, assuming the pedestals can be measured as a simple mean of the response to null stimulus. DrcPedType data members define the cuts which are used in the verifyChannel function to define good channel data (min/max pedestal value, maximum difference/significance from the reference value). This class uses the DrcFlags.hh file, which defines a bit in the public CalChan flag field for each of the different data tests it performs during channel verification. DrcPedType also has several bit masks data members, which when applied to the public flag field define the channel Quality and whether it passes verification (the return value of the verifyChannel function).
A similar class DrcT0Type defines the calibration type for DIRC TDC readout time offsets. It uses the generic CalMSNBank to store its types data. The additional data word in CalMSNChan (number of samples) versus CalMSChan is necessary since time offsets will be measured using the light flasher system, which randomly illuminates each phototube (channel), giving each a different number of samples. Data members in DrcT0Type define cuts on the channel data and masks for defining the flags similarly to DrcPedType.
There are three test programs in the DrcCond package which fully exercise the system. StoreDrcTypes creates persistent objects for the three calibration types mentioned above. This program must be run first. StoreDrcData creates CalBase objects for the three calibration types listed above, and stores them. A complete set of calibration data objects (12 objects of roughly 10K channels) is created for each type, with random values in place of measurements. The StoreDrcType and StoreDrcData programs may be run repeatedly. The FetchDrcData program retrieves data from the database and prints it to the screen. These programs obey the Objectivity linking rules described in appendix H.
DrcTDCOutputIterator is an example of a CalIterator subclass for looping over raw data. It is built around the DrcTDCOutputTC class, the tagged container which stores the TDC results of feature extraction in the DIRC. These classes can be found in the DrcOnline package.
The DrcOep package currently contains a single test program TestDrcT0Calib. This program simulates DIRC front-end data with random T0 offsets and realistic TDC resolution using classes from the DrcOnline package. The simulation produces a DrcTDCOutputTC object, as described above. A DrcTDCOutputIterator is constructed around this, which is then used to accumulate data in a CalProcessor object built using CalSS2Chan and CalMSNChan CalCollection (CalChanList) objects. After accumulating statistics, the CalProcessor finalizes the data, and the CalChanList objects are validated and stored in the database. This executable obeys the Objectivity linking rules described in appendix H.
F) Protection against inadvertent persistent object creation.
Objectivity implements persistent storage of objects by overwriting the new operator on persistent-capable classes. Thus any persistent-capable class with public constructors can be directly persistently stored by any user with Unix file system write access to the database and federated database, who successfully starts and commits his transaction. The calibration system does not try to prevent users from directly creating new persistent objects (for instance by making constructors private), as this was deemed too restrictive. For instance, private constructors would prevent users from creating transient objects of persistent-capable classes. Instead, persistent calibration objects created by direct calls to new are sterile (cannot be retrieved from the database) as they have no connections to the time interval search index. Thus the worst effect of users directly storing objects will be to add dead space to the database. The only useful way to store calibration data is through the system described in this document, which implements strict form and content tests before allowing objects to be stored.
G) Calibration proxies
To protect offline users from potentially damaging persistent data, subsystem developers need to provide transient proxy classes to serve calibration data to their users. The exact form of these proxies is subsystem and calibration-type dependent: for instance, it might be useful offline to combine data from several calibration types into a single transient object, in order to use the information more efficiently. Examples of offline calibration proxies are currently being prepared for the EMC and DIRC subsystems.
H) Linking Objectivity executables
Objectivity supports polymorphic references and handles to persistent data. This feature is used extensively in the calibration system. While very useful, this feature can cause puzzling run-time errors if special care is not taken at link time. The problem comes because, in retrieving objects, Objectivity does NOT call constructors. Thus, if a retrieved persistent object is referenced polymorphically, the loader may see no reference to the actual subclass of the object, and therefore omit the subclasses specific functions and vtable from the executable. The symptom for this is a segment violation during the call to a virtual function of a persistent object.
The way to insure against this problem is to make sure that, somewhere in your executable, an object of every persistent class you plan to use is created, and that a virtual function of that class is called. The object need not be created persistently or even on the heap, stack invocation works fine. This will guarantee that the loader sees references to the class vtable and loads it. Calibration system users should be aware that fetching data through the CalBase interface uses CalBank, CalType, and CalSysDfn objects polymorpically. Consequently all user applications MUST somewhere explicitly reference the specific subclasses of these classes as described above. Examples of this procedure can be found in the DrcCond and DrcOep packages.
1 David Brown, BaBar Calibration Object Proposal
2 See The Dataflow platform guide
5 Defined in the MapDetector package
6 Coordinated by Roly Martin of Imperial College
7 Written by Ed Frank (U. Penn) originally for use within the ProxyDict package