Compiled by Jack Cranshaw
Last updated 11/19/2002
Online Calibrations :
Online calibration data will be collected, analyzed, and written to
the database with consumers. For any consumers requiring online histogramming,
these should use the consumer
monitoring framework developed by Hans Wenzel and Kaori Maeshima.
The file I/O (tape, disk, data stream, EDM2, ...) is provided as modules
inside AC++ where it is up to the user to include and specify the appropriate
parameters. The online display tools and Root
I/O are provided by the consumer framework. The interface to the database
is provided by the Calibration database API and the CalibrationManager
AC++ module. Calibration data can be taken in one of two modes: X-mode
(data collected in the crate) or D-mode (accumulate D-banks like normal
data). The method for making X-mode consumers is described at the indicated
link.
General Aspects of D-mode Calibration Data:
When calibration data is collected in D-mode, it involves:
Understanding the Template:
The template class comes in several flavors/versions which are kept
in the CalibConsumer package.
The template contains the talk-to parameters. User specific code then gets called based on those parameters.
Defining User Classes:
The class GenericDMode3.hh is not modified
by the user, but the user must know what is expected in order to include
them in the user class. Methods which are required by the template are
marked as Required.
1. (Required) The user class must provide at least three typedef's.
2. The user can define a transient class for collecting
data from the event which will be used in the
calculation, for example:
struct Avg
{
int noent;
double sum;
double sum2;
Avg():noent(0),sum(0.0),sum2(0.0) {}
};
This struct contains the information needed to calculate
a mean and sigma. There will be one struct
per channel, so a mapping of channel to struct must
be provided. One of the simplest ways to do this
is with an STL map, for example:
std::map<MapClass::CalibKey,Avg> Avgmap;
3. (Required) The user
class must provide a method bookHistos() where the Root objects to be
presented for display are declared and put in a
TList. The method should return the pointer to the
list. For example:
TList* bookHistos()
{
// Declare histograms
_testhist1 = TH1F("testhist1","totevents
RAW",2,0,2);
_testhist2 = TH1F("testhist2","totevents
FILTERED",2,0,2);
// add histograms to
list
TList* lista = new TList();
lista->Add(&_testhist1);
lista->Add(&_testhist2);
return lista;
}
All the Root manipulations are handled by the base class of the template.
4. (Required) The user
class must provide an initialize method where histograms are reset and
any
containers or maps are cleared.
5. (Required) The user
class must provide an accumulate method. This method is called by the
template once for every channel for every event
and fills the map of structs. For example:
void LEDCalib2::accumulate(const EventRecord::ConstIterator
p_bank)
{
ConstHandle<StorableBank> temp(p_bank);
string name = temp->bank_name();
cout << "Processing bank "
<< name << endl;
if(name == "CEMD") {
ConstHandle<EventClass>
e(p_bank);
for (EventClass::ConstGrandBankIter
iter(e) ;
iter.is_valid()
;
++iter)
{
double sumenergy
= e->get_energy(iter);
double sum2energy
= sumenergy*sumenergy;
// Decode
channel, and re-encode using EventClass parent
//
because bank does not give access to channel
MapClass::EventKey
ek = _m.makeEventKey(e->get_we(iter),e->get_phi(iter),
e->get_eta(iter),e->get_pmt(iter));
MapClass::CalibKey
key = _m.EventKeyToCalibKey(ek);
_calibdata[key].sum
+= sumenergy;
_calibdata[key].sum2
+= sum2energy;
_calibdata[key].noent++;
}
}
if(name == "LEDD") {
ConstHandle<EventClass2>
g(p_bank);
for (EventClass2::ConstGrandBankIter
iter(g) ;
iter.is_valid() ;
++iter)
{
< Analysis code for LEDD>
}
}
}
All the EventClass's must obviously be StorableBank's.
The accumulate method for
GenericDMode3 uses a pointer to an EventClass as
an argument rather than a pointer
to a record in the EventClass. This allows the user
class to handle any differences in EventClass
iterators while the template need only loop over
the designated banks in the event and call the
accumulate method for the banks indicated by the
user class.
6. At the end of the run the template begins the
writing to the database. First it callse the calculate
method of the user class which should contain any
universal manipulations of the raw data to turn
it into calibration data. It then calls the convert,
valid, badchan methods based on the talk-to parameter
DBStatusList and the values RAW, GOOD, BAD for the
respective methods.
7. (Required)
"RAW" data is written by the convert method in the user class.
For example:
std::auto_ptr<LEDCalib::CalibClass> LEDCalib::convert()
{
int thresh=0;
std::auto_ptr<CalibClass> c(new
CalibClass);
Avgmap::const_iterator it = _calibdata.begin();
while (it != _calibdata.end() )
{
double n
= it->second.noent;
double s
= it->second.sum;
double s2
= it->second.sum2;
double response
= s/n;
double sigma
= sqrt(s2/n-response*response);
if (n>=thresh)
{
c->push_back(CalibClass::value_type(it->first,n,response,sigma,0.0,0.0));
_testhist1.Fill(1.);
}
++it;
}
return c;
}
This example shows how this method writes the results
of the calculation into an instance of the
CalibClass.
8. (Required) Another
write to the database is done using the validate method in the user class
to
filter out badly calibrated channels. The results
are written to the database and labelled "GOOD".
A simple example would look like the example in
6. but with a minimum number of entries required
per channel, i.e. thresh=10.
9. (Required) Another
write to the database is done using the badchan method in the user class
to
filter out badly calibrated channels. The results
are written to the database and labelled "BAD". This
method is separate from the validate method because
"BAD" does not always mean not "GOOD".
A simple example would look like the example in
6. but with a maximum sigma allowed,
i.e. sigma < 10 counts.
10. The user class is used with the template in an AC++ program like the following.
add(new GenericDMode<LEDCalib>("DCalibModule", "DCalib for a consumer program" ));
Multiple instances for multiple user classes can
be declared in one executable.