// class MacroCellData
// M. Pallavicini - created 20-11-2001
// Description of the data gathered by the MacroCell during the whole event
//
#include <math.h>
#include "MacroCellData.hh"
#include "MacroCell.hh"
#include "FrontEndChip.hh"
#include "MacroCellHit.hh"
#include "EEvent.hh"
#include "Photomultiplier.hh"
ClassImp(MacroCellData)
//______________________________________________________________________________
MacroCellData::MacroCellData( MacroCell* p ) : pCell(p) {
// ctor
fGtuStart = 999999;
fGtuEnd = 0;
fGtuTrigger = 999999;
SetEmpty();
}
//______________________________________________________________________________
MacroCellData::~MacroCellData() {
// dtor
map<Int_t, map<Int_t,ChipGtuData*>* >::const_iterator it3;
for(it3=fChipData2.begin(); it3 != fChipData2.end(); it3++) {
map<Int_t,ChipGtuData*>* mm = it3->second;
map<Int_t,ChipGtuData*>::const_iterator it4;
for(it4=mm->begin(); it4!=mm->end(); it4++) {
ChipGtuData* d=it4->second;
if (d) delete d;
}
if ( mm ) {
mm->clear();
delete mm;
}
}
fChipData2.clear();
map<Int_t, vector<ChipGtuData*>* >::const_iterator it;
for(it=fChipData.begin(); it != fChipData.end(); it++) {
vector<ChipGtuData*>* hits = it->second;
if ( hits ) {
/* for(size_t j=0; j < hits->size(); j++) {
ChipGtuData* d = (*hits)[j];
if (d)
delete d;
}*/
hits->clear();
delete hits;
}
}
fChipData.clear();
map<Int_t, vector<MacroCellHit*>* >::const_iterator it2;
for(it2=fData.begin(); it2 != fData.end(); it2++) {
vector<MacroCellHit*>* hits = it2->second;
if ( hits ) {
for(size_t j=0;j<hits->size(); j++) {
MacroCellHit* h = (*hits)[j];
if (h)
delete h;
}
hits->clear();
delete hits;
}
}
fData.clear();
}
//______________________________________________________________________________
void MacroCellData::BuildGtu( Int_t gtu_num ) {
// perform the single GTU analysis
// look for X & Y logic for the whole macrocell
// compute the number of hits and the time recorded for each pixels
// including ghosts
// data is saved into a map
Int_t total_counts = 0;
Double_t trigger_time = HUGE;
fData[gtu_num] = new vector<MacroCellHit*>;
Bool_t active = kFALSE;
// get the list of ChipGtuData associated to this GTU
vector<ChipGtuData*> *v = fChipData[gtu_num];
if ( v == NULL ) {
return;
}
// flags for ghost calculation
vector<Int_t> ColumnFlags;
vector<Int_t> RowFlags;
ColumnFlags.clear();
RowFlags.clear();
// loop on all objects
vector<ChipGtuData*>::const_iterator it = v->begin();
for( ; it != v->end(); it++) {
ChipGtuData *chdat = *it;
if ( chdat ) {
Int_t x;
Int_t y;
Double_t t;
Int_t nch = chdat->FrontEnd()->Channels();
if ( chdat->GetXYLogic(x,y,t) ) {
active = kTRUE;
total_counts += chdat->FastOrHits(); // counts after gate opened
for(Int_t i=0; i<nch; i++) {
if ( chdat->CheckCounter(i) ) {
//FIXME ChkCntr is kTRUE also if counts == threshold
//FIXME Hitsa with counts == threshod are also saved
Int_t mx, my;
chdat->FrontEnd()->GetPixelCellRowCol( i, mx, my );
if ( t < trigger_time ) {
trigger_time = t; // time at which the logic fired
}
// add this hit to the list
ChannelUniqueId uid = chdat->FrontEnd()->UniqueChanId(i);
fData[gtu_num]->push_back(new MacroCellHit(mx,my,total_counts,gtu_num,uid));
ColumnFlags.push_back(my);
RowFlags.push_back(mx);
}
}
}
}
}
// if there was activity in this gtu, increment the counter
if ( active ) {
if ( gtu_num < GtuStart() ) fGtuStart = gtu_num;
if ( gtu_num > GtuEnd() ) fGtuEnd = gtu_num;
fNumActiveGtus ++;
}
// add ghost hits
for(UInt_t i=0; i<RowFlags.size(); i++) {
Int_t mx = RowFlags[i];
for(UInt_t j=0; j<ColumnFlags.size(); j++) {
Int_t my = ColumnFlags[j];
Int_t uid = Cell()->GetUniqueIdRowCol(mx,my);
// add hit (avoid duplication with check i != j because the hit was already added before)
if ( uid && i!=j ) {
fData[gtu_num]->push_back(new MacroCellHit(mx,my,total_counts,gtu_num,uid));
}
}
}
// all "hits" (real and ghosts) have the same number of counts
// the macrocell has just one counter and keep track of every X Y
// logic fired during the GTU
// I assume here that when more than one XY pair is active, the
// macrocell will have no memory of the time in which they occurred
// and will just associate the total number of hits to all combinations
// of x and y
for(UInt_t i=0; i<fData[gtu_num]->size(); i++) {
// set number of counts to the same value for all Macrocellhits
(*fData[gtu_num])[i]->SetHits( total_counts );
// FIXME: debug code
/*cout << "Hit " << i << ":"
<< (*fData[gtu_num])[i]->Row() << " "
<< (*fData[gtu_num])[i]->Col() << " "
<< (*fData[gtu_num])[i]->Gtu() << " "
<< (*fData[gtu_num])[i]->Hits()<< " "
<< (*fData[gtu_num])[i]->UniqueId()<< " " << endl;
*/
}
}
//______________________________________________________________________________
void MacroCellData::Add( Int_t gtu_num, ChipGtuData* pData) {
// add data from a chip; just stored into a map
// a second map is also filled for triggering purposes
// fill first map only if pData->IsEmpty() is kFALSE, which
// means at least one channel had at lest 5 hits
if ( !pData->IsEmpty() ) {
if ( !fChipData[gtu_num] )
fChipData[gtu_num] = new vector<ChipGtuData*>;
fChipData[gtu_num]->push_back( pData );
}
// fill second map every time
Int_t id = pData->FrontEnd()->Id();
if ( !fChipData2[id] )
fChipData2[id] = new map<Int_t,ChipGtuData*>;
(*fChipData2[id])[gtu_num] = pData;
SetEmpty( kFALSE );
}
//______________________________________________________________________________
string& MacroCellData::Dump() {
//
// dump macrocell data onto a string
//
char line[500];
sprintf(line,"MacroCell %dn",Cell()->Id());
text_dump.append(line);
sprintf(line,"Number of active GTUs = %dn",GtuEnd()-GtuStart());
text_dump.append(line);
for(UInt_t i=0; i < fData.size(); i++ ) {
vector<MacroCellHit*>& v = *(fData[i]);
if ( &v ) {
sprintf(line,"GTU = %dn",i);
text_dump.append(line);
for( UInt_t j=0; j < v.size(); j++ ) {
MacroCellHit *hit = v[j];
if ( hit ) {
sprintf(line,"HIT %02d X=%02d Y=%02d Hits=%02d n",
j,hit->Row(),hit->Col(), hit->Hits() );
text_dump.append(line);
}
}
}
}
return text_dump;
}
//______________________________________________________________________________
Bool_t MacroCellData::CheckContiguity(Int_t gtu1, Int_t gtu2 ) {
// trigger function
// returns kTRUE if gtu1 has at least one MacroCellHit
// that is contiguous (in space) with one MacroCellHit of gtu2
vector<MacroCellHit*>* hits1 = fData[gtu1];
vector<MacroCellHit*>* hits2 = fData[gtu2];
if ( !hits1 || !hits2 )
return kFALSE;
for(unsigned i1=0; i1 < hits1->size(); i1++) {
MacroCellHit* hit1 = (*hits1)[i1];
if ( hit1) {
for(unsigned i2=0; i2 < hits2->size(); i2++) {
MacroCellHit* hit2 = (*hits2)[i2];
if ( hit2) {
if ( (*hit1)%(*hit2) ) { // % operator for MacroCellHit
return kTRUE;
}
}
}
}
}
return kFALSE;
}
//______________________________________________________________________________
void MacroCellData::SimulateTrigger() {
// simulate trigger using all engines associated to the macrocell
// clear trigger word in all engines
TriggerEngine::ResetTriggerWord();
// get iterator over existing engines
map<ETriggerTypeIdentifier,TriggerEngine*>::const_iterator it = Cell()->GetEngines().begin();
// iterate and simulate trigger
for( ; it != Cell()->GetEngines().end(); it++ ) {
TriggerEngine *trg = it->second;
trg->Simulate( this );
if ( trg->HasTriggered() ) {
SetGtuTrigger( trg->GetGtuTrigger() );
}
}
}
//______________________________________________________________________________
Double_t MacroCellData::GtuTimeStart() {
// time in ns of the first edge of the first GTU for this event
// the time is measured from the Photons time
Double_t start = Cell()->GetGtuBegin();
start += GtuStart()*Cell()->GetGtuLength();
return start;
}
//______________________________________________________________________________
Double_t MacroCellData::GtuTimeEnd() {
// same for second edge of last GTU
Double_t end = Cell()->GetGtuBegin();
end += (GtuEnd()+1.)*Cell()->GetGtuLength();
return end;
}
//______________________________________________________________________________
Int_t MacroCellData::NumMacroCellHits() {
// compute the total number of hits and returns it
Int_t NumHits = 0;
for(Int_t iGtu = GtuStart(); iGtu < GtuEnd(); iGtu++) {
if ( Hits(iGtu) ) {
NumHits += Hits(iGtu)->size();
}
}
return NumHits;
}