CTriggerServer.C
//-----------------------------------------------------------------------------
// $Header: /asis/offline/ceres/cool/project/RCS/CTriggerServer.C,v 3.0 1996/10/02 09:39:50 voigt Exp $
//
// COOL Program Library
// Copyright (C) CERES collaboration, 1996
//
// Implementation of class CTriggerServer.
//
//-----------------------------------------------------------------------------
#include <iostream.h>
#include <limits.h>
#include <stdlib.h>
#include "CTriggerServer.h"
unsigned hashString(const RWCString& str)
{
return str.hash();
}
CTriggerServer::CTriggerServer(const char* setupFile)
{
//
// Create and read setup
//
setup = new CTriggerSetup;
if (setupFile == 0) {
CString setupName = CString(C_DEFAULT_SETUP_PATH)+
CString(C_SETUPFILE_TRIGGER);
setup->read(setupName.data());
}
else
setup->read(setupFile);
trigPatt[trigFLT ] = new RWTValHashDictionary<RWCString, unsigned long>(hashString);
trigPatt[trigMAIN] = new RWTValHashDictionary<RWCString, unsigned long>(hashString);
readTriggerConfiguration(); // read trigger pattern (separate file)
//
// reset all warning flags
//
for (int i=0; i<100; i++)
warned[i] = False;
}
CTriggerServer::~CTriggerServer()
{
trigPatt[trigFLT ]->clear();
trigPatt[trigMAIN]->clear();
delete [] trigPatt;
for (int i=0; i<MaxHTDCChannels; i++) {
hTDC[i].clear();
}
delete hTDC;
delete setup;
}
CTriggerServer::CTriggerServer(const CTriggerServer &) // this should never be called
{
trigPatt[trigFLT ] = new RWTValHashDictionary<RWCString, unsigned long>(hashString);
trigPatt[trigMAIN] = new RWTValHashDictionary<RWCString, unsigned long>(hashString);
trigPatt[trigFLT ]->clear();
trigPatt[trigMAIN]->clear();
delete [] trigPatt;
}
CTriggerServer & CTriggerServer::operator = (const CTriggerServer &)
{
return *this;
}
CBoolean CTriggerServer::update(CEventServer& es)
{
unpackTriggerPattern(es);
if (!md.unpack(es)) return False; // unpack multiplicity detector
if (!unpackHTDC(es)) return False; // unpack historyTDC
return True;
}
void CTriggerServer::listSetup(ostream& ost) const
{
ost << "\nSetup listing of trigger server" << endl;
CString line('=', 46);
ost << line << endl;
setup->list(ost);
}
// ============================== multiplicity ==========================
float CTriggerServer::getMultiplicity()
{
return md.getMultiplicity(); // get mult from MD
}
// ========================= cleanup using HTDC =========================
CBoolean CTriggerServer::unpackHTDC(CEventServer& es)
{
int i;
for (i=0; i<MaxHTDCChannels; i++) { // remove old contents
hTDC[i].clear();
}
const CLabel *evt = es.getLabel(HTDC, Evt); // get pointer to current event
if (evt == 0) {
cerr << "CTriggerServer::unpackHTDC():\n";
cerr << "\tERROR\n";
cerr << "\tLabel HTDC not found. No further action.\n";
return False;
}
unsigned long *data = (unsigned long *) evt->getData(); // that's where the data starts
if (data == 0) {
cerr << "CTriggerServer::unpackHTDC():\n";
cerr << "\tERROR\n";
cerr << "\tData in label HTDC not found. No further action.\n";
return False;
}
int chan = 0;
int time = 0;
for (i=1; i<evt->getSize(); i++) { // skip the status word (word 0)
chan = int((data[i]>>17) & 0x0f); // get channel number
if (chan < MaxHTDCChannels) {
time = int((data[i]) & 0xffff); // time info
hTDC[chan].insert(time); // intrinsically convert to float
}
else {
if (chan >= 100 || (chan < 100 && !warned[chan])) {
cerr << "CTriggerServer::unpackHTDC():\n";
cerr << "\tWARNING\n";
cerr << "\tIllegal channel '" << chan << "' found. Further warnings will be supressed\n";
warned[chan] = True;
}
}
}
return True;
} // end CTriggerServer::unpackHTDC
int CTriggerServer::isBadN2Interaction(int tBC1, int tMB)
{
int BC1_min = setup->getLowerEdgeBC1Window();
int BC1_max = setup->getUpperEdgeBC1Window();
int min_bias_min = setup->getLowerEdgeMinBiasWindow();
int min_bias_max = setup->getUpperEdgeMinBiasWindow();
int N2_min = setup->getLowerEdgeN2Window();
int N2_max = setup->getUpperEdgeN2Window();
int t0DownStream = setup->getT0DownStream();
int t0BC1 = (BC1_max + BC1_min)/2;
int t0MinBias = (min_bias_max + min_bias_min)/2;
if (getNumberInWindow(htdcBC1, BC1_min, BC1_max) == 0)
return noBeamParticle;
if (getNumberInWindow(htdcN2, N2_min, N2_max) == 0)
return noN2Interaction;
if (getNumberInWindow(htdcMinBias, min_bias_min, min_bias_max) == 0)
return noMinBias;
if (getNumberInWindow(htdcBC1, t0BC1 - tBC1, t0BC1 + tBC1) > 1) {
timeOfSecondBeamParticle = getMinTime(htdcBC1, t0BC1 - tBC1, t0BC1 + tBC1);
return beamPileUp;
}
if (getNumberInWindow(htdcMinBias, t0MinBias - tMB, t0MinBias + tMB) > 1)
return minBiasPileUp;
if (getNumberInWindow(htdcDownStream, t0DownStream - tMB, t0DownStream + tMB) > 0)
return downstramInteractionPileUp;
return 0;
}
int CTriggerServer::getMinTime(int chan, int tlow, int tup)
{
//
// this function returns the smallest time difference between two hits in hTDC[chan],
// if they are within the given time window. If there is only one hit, time is set to 0.
//
CBoolean oneAdditionalHitFound = False;
if (hTDC[chan].length() < 2) return 0;
int i, j, time;
int minTime = INT_MAX;
for (i=0; i<hTDC[chan].length(); i++) {
if ( hTDC[chan](i) >= tlow && hTDC[chan](i) <= tup ) {
for (j=i+1; j<hTDC[chan].length(); j++) {
if ( hTDC[chan](j) >= tlow && hTDC[chan](j) <= tup ) {
time = abs(hTDC[chan](j) - hTDC[chan](i));
oneAdditionalHitFound = True;
if (time < minTime)
minTime = time;
}
}
}
}
if (oneAdditionalHitFound)
return minTime;
else
return 0;
}
int CTriggerServer::getNumberInWindow(int chan, int tlow, int tup)
{
int num=0;
for (int i=0; i<hTDC[chan].length(); i++) {
if ( hTDC[chan](i) >= tlow && hTDC[chan](i) <= tup )
num++;
}
return num;
}
int CTriggerServer::getBeamInWindow(int tlow, int tup)
{
return getNumberInWindow(htdcBC1, tlow, tup);
}
int CTriggerServer::getN2InWindow (int tlow, int tup) // get # of interactions from HTDC
{
return getNumberInWindow(htdcN2, tlow, tup);
}
// ======================= trigger pattern info =========================
//-----------------------------------------------------------------------------
// Construct Trigger
// Read trigger pattern from file
// Format of the (ascii) file must be:
// pattern-id bit name
// with
// pattern-id 1 or 2
// name up to 16 characters
// and bit [0-31]
// This is the easiest way to cope with some people changing
// the trigger pattern every day.
//
//-----------------------------------------------------------------------------
void CTriggerServer::readTriggerConfiguration()
{
CString filename = CString(C_DEFAULT_SETUP_PATH)+
CString(C_SETUPFILE_TRIGGERPATTERN);
ifstream ifs(filename); // open file
if (!ifs) {
cerr << "CTriggerServer::readTriggerConfiguration():\n";
cerr << "\tERROR\n";
cerr << "\tCan't open trigger pattern file '" << filename << "'.\n";
return;
}
//
// Read pattern
//
int npat, bit;
RWCString name;
while (ifs >> npat >> bit >> name, !ifs.eof() && ifs.good() ) {
trigPatt[npat-1]->insertKeyAndValue(name, (unsigned long)(1<<bit));
}
} // end CTriggerServer::readTriggerConfiguration
void CTriggerServer::unpackTriggerPattern(CEventServer& es)
{
const CLabel *evt = es.getLabel(EVNT, Evt); // get pointer to current event
if (evt == 0) { // not an event, return
triggerPattern[trigFLT ] = 0;
triggerPattern[trigMAIN] = 0;
return;
}
const CWord *data = evt->getData(); // that's where the data starts
triggerPattern[trigFLT ] = (int) data[TriggerWord1Position];
triggerPattern[trigMAIN] = (int) data[TriggerWord2Position];
} // end CTriggerServer::unpackTriggerPattern
void CTriggerServer::printTriggerPattern(ostream& os)
{
RWTValHashDictionaryIterator<RWCString, unsigned long> fltIter (*trigPatt[trigFLT ]);
RWTValHashDictionaryIterator<RWCString, unsigned long> mainIter(*trigPatt[trigMAIN]);
os << "trigger pattern: ";
while (mainIter()) {
if (mainIter.value() & triggerPattern[trigMAIN]) {
os << "/" << mainIter.key();
}
}
while (fltIter()) {
if (fltIter.value() & triggerPattern[trigFLT ]) {
os << "/" << fltIter.key();
}
}
os << endl;
} // end CTriggerServer::printTriggerPattern