// class MacroCell
// M. Pallavicini - created 20-5-01
//
#include <iostream>
#include <math.h>
#include "euso.hh"
#include "MacroCell.hh"
#include "FrontEndChip.hh"
#include "Config.hh"
#include "ChipGtuData.hh"
#include "MacroCellData.hh"
#include "Photomultiplier.hh"
#include "MacroCellGeometry.hh"
ClassImp(MacroCell)
Int_t MacroCell::gCellCounter = 1;
map<ETriggerTypeIdentifier,TriggerEngine*> *MacroCell::fEngines=0;
//______________________________________________________________________________
MacroCell::MacroCell(Int_t rows, Int_t columns) :
EsafConfigurable(), fRows(rows), fCols(columns) {
//
// Constructor (needs number of rows and columns)
//
fCellId = gCellCounter++;
if ( GetRows()<=0 || GetColumns()<=0) {
Msg(EsafMsg::Warning) << "Error building macrocell "
<< fCellId << MsgDispatch;
Msg(EsafMsg::Warning) << "Invalid Rows or Columns (" << rows << " "
<< columns << ")" << MsgDispatch;
}
fGtuLength = Conf()->GetNum("MacroCell.fGtuTimeLength");
fLogicEnabled = Conf()->GetBool("MacroCell.fLogicEnabled");
// trigger parameters and algorythms
fTriggerThreshold = (Int_t)Conf()->GetNum("MacroCell.fTriggerThreshold");
fTriggerType = (ETriggerTypeIdentifier)Conf()->GetNum("MacroCell.fTriggerType");
if ( !fEngines )
fEngines = &(TriggerEngine::GetEngines( fTriggerType ) );
// reset arrays and maps
fPmts.clear();
fECs.clear();
fECRowColMap.clear();
}
//______________________________________________________________________________
MacroCell::~MacroCell() {
//
// Destructor does nothing
//
}
//______________________________________________________________________________
Double_t MacroCell::FirstHitTime() {
//
// Compute the time of the first hit in the macrocell
//
Double_t start_event = HUGE;
for(size_t i=0; i < fECs.size(); i++) {
if ( fECs[i] ) {
Double_t t = fECs[i]->FrontEnd()->FirstHitTime();
if ( t < start_event )
start_event = t;
}
}
return start_event;
}
//______________________________________________________________________________
Double_t MacroCell::LastHitTime() {
//
// Compute the time of the last hit in the macrocell
//
Double_t end_event = -HUGE;
for(size_t i=0; i < fECs.size(); i++) {
if ( fECs[i] ) {
Double_t t = fECs[i]->FrontEnd()->LastHitTime();
if ( t > end_event )
end_event = t;
}
}
return end_event;
}
//______________________________________________________________________________
FrontEndChip* MacroCell::FrontEnd(Int_t r, Int_t c) {
//
// Returns a pointer to the front end chip in row r and column c returns
// NULL if it is not a valid position even if r,c are valid, return value
// may be NULL with non-squared macrocells
//
if ( IsValid(r,c) ) {
if ( fECRowColMap[RowColId(r,c)] ) {
return fECRowColMap[RowColId(r,c)]->FrontEnd();
}
}
return (FrontEndChip*)NULL;
}
//______________________________________________________________________________
Bool_t MacroCell::Add(ElementaryCell* ec, Int_t row, Int_t col) {
//
// Add an elementary cell to this macrocell in position i and j
// returns true if ok, false on error
//
if ( !IsValid(row,col) ) {
Msg(EsafMsg::Panic) << "Wrong row/col Row "<<row<< " " << GetRows()
<< " Col:" << col << " " << GetColumns() << MsgDispatch;
}
if ( !ec )
Msg(EsafMsg::Panic) << "Invalid EC pointer in MacroCell::Add" << MsgDispatch;
if ( FrontEnd(row,col) )
Msg(EsafMsg::Panic) << "MacroCell::Add() Row,Col already associated" << MsgDispatch;
if (!ec->FrontEnd())
Msg(EsafMsg::Panic) << "Null Front End pointer in MacroCell::Add" << MsgDispatch;
// associate all channels to the right row and column
fECs.push_back( ec );
for(Int_t i=0; i < ec->FrontEnd()->NumSide(); i++) {
int r = row+i;
for(Int_t j=0; j < ec->FrontEnd()->NumSide(); j++) {
int c = col+j;
SetECRowCol(ec,row,col);
pair<int,int> p(r,c);
fUidRowCol[p]=ec->FrontEnd()->UniqueChanId( ec->FrontEnd()->ChanRowCol(i,j) );
fRowColUid[ec->FrontEnd()->UniqueChanId( ec->FrontEnd()->ChanRowCol(i,j) )] = p;
}
}
ec->FrontEnd()->SetCellRowColOffset( row, col );
// get pmt pointers
for(Int_t i=1; i <= ec->GetNumPmts(); i++) {
fPmts.push_back( ec->GetPmt( i ) );
}
// compute new geometry area covered by this macrocell
Geometry()->Compute();
return kTRUE;
}
//______________________________________________________________________________
Bool_t MacroCell::CheckPmtState() const {
//
// Check if all pmts of this macrocell are ready
// (user must have called Simulate for each of them)
//
for( size_t i=0; i < fPmts.size(); i++) {
Photomultiplier* pPmt = fPmts[i];
if ( pPmt ) {
if ( pPmt->Status() == kPmtFilling )
pPmt->Simulate();
} else {
Msg(EsafMsg::Panic) << "NULL Pmt pointer in CheckPmtState()" << MsgDispatch;
}
}
return kTRUE;
}
//______________________________________________________________________________
Bool_t MacroCell::IsEmpty() const {
// returns true if there were not hits in the macrocell or if there is low
// signal (threshold set by EusoElectronics)
if (fLowSignalThreshold <= 0) {
for( size_t i=0; i < fPmts.size(); i++) {
Photomultiplier* pPmt = fPmts[i];
if ( pPmt ) {
if ( !pPmt->IsEmpty() )
return kFALSE;
} else {
Msg(EsafMsg::Panic) << "NULL Pmt pointer in CheckPmtState()" << MsgDispatch;
}
}
return kTRUE;
} else { //if ( fLowSignalThreshold > 0 ) {
Int_t numSignals(0);
for( size_t i=0; i < fPmts.size(); i++) {
Photomultiplier* pPmt = fPmts[i];
if ( pPmt ) {
for ( Int_t ch=0; ch < pPmt->NumChan(); ch++ ) {
vector<PmtSignal*>* sigs = &(pPmt->Signals(ch));
if ( sigs ) {
for(UInt_t iSig=0; iSig < sigs->size(); iSig++) {
PmtSignal *s = (*sigs)[iSig];
if ( s ) {
numSignals++;
}
}
}
}
}
}
return ( numSignals <= fLowSignalThreshold );
}
/*
else {
FatalError("Wrong LowSignalThreshold Assignment");
return kFALSE;
}
*/
}
//______________________________________________________________________________
void MacroCell::Reset() {
// reset data and get ready for next event
// reset all front end chips and all pmts in this macrocell
for(size_t iEC=0; iEC < fECs.size(); iEC++) {
ElementaryCell *pEC = fECs[iEC];
if ( pEC )
pEC->FrontEnd()->Reset();
}
for( size_t iPm=0; iPm < fPmts.size(); iPm++ ) {
Photomultiplier* pPmt = fPmts[iPm];
if ( pPmt )
pPmt->Reset();
}
}