FairRoot/PandaRoot
PndEmcMakeCluster.cxx
Go to the documentation of this file.
1 //---------------------------------------------------------------------
2 // File and Version Information:
3 // $Id: $
4 //
5 // Description:
6 // This object constructs a list of clusters from a list of digis.
7 // This module use a simple algorithm.
8 // Digis which are in a Cluster are add to this cluster.
9 // If a Digi is in more than one cluster, the clusters are merged.
10 // Digis are added to the cluster if they have an energy above
11 // _digiEnergyTreshold->value().
12 //
13 // Environment:
14 // Software developed for the PANDA Detector at GSI.
15 //
16 // Author List:
17 // Jan Zhong //------------------------------------------------------------------------
18 // Philipp Mahlberg //-------------added timebased reconstruction capabilities----------------
19 
20 #include "PndEmcMakeCluster.h"
21 
23 #include "PndEmcXClMoments.h"
24 #include "PndEmcStructure.h"
25 #include "PndEmcMapper.h"
26 #include "PndEmcGeoPar.h"
27 #include "PndEmcDigiPar.h"
28 #include "PndEmcRecoPar.h"
29 #include "PndEmcCluster.h"
30 #include "PndEmcDigi.h"
31 #include "PndMCTrack.h"
32 
33 #include "FairRootManager.h"
34 #include "FairRunAna.h"
35 #include "FairRuntimeDb.h"
36 
37 #include "TClonesArray.h"
38 #include "TROOT.h"
39 
40 
41 #include <iostream>
42 #include <exception>
43 
44 using std::cout;
45 using std::endl;
46 
48 
50 PndPersistencyTask("EmcClusteringTask", verbose),
51 fDigiArray(NULL), fHitArray(NULL), fMCTrackArray(NULL), fClusterArray(NULL), fWriteOutArray(NULL), fDigiFunctor(NULL), fClusterList(), fDigiEnergyTresholdBarrel(0), fDigiEnergyTresholdFWD(0), fDigiEnergyTresholdBWD(0), fDigiEnergyTresholdShashlyk(0), fClusterPosParam(), fMapVersion(0), fGeoPar(new PndEmcGeoPar()), fDigiPar(new PndEmcDigiPar()), fRecoPar(new PndEmcRecoPar()), fVerbose(verbose), fStoreClusters(storeclusters)
52 {
53  fClusterList.clear();
54  fClusterPosParam.clear();
55  SetPersistency(storeclusters);
56 }
57 
58 //--------------
59 // Destructor --
60 //--------------
62 {
63 }
64 
75 {
76 
77  // Get RootManager
78  FairRootManager* ioman = FairRootManager::Instance();
79  if ( ! ioman )
80  {
81  cout << "-E- PndEmcMakeCluster::Init: "
82  << "RootManager not instantiated!" << endl;
83  return kFATAL;
84  }
85 
86  // Get input array
87  fDigiArray = (TClonesArray*) ioman->GetObject("EmcDigi");
88  if ( ! fDigiArray ) {
89  fDigiArray = (TClonesArray*) ioman->GetObject("EmcDigiSorted");
90  if ( ! fDigiArray ) {
91  cout << "-W- PndEmcMakeCluster::Init: "
92  << "No PndEmcDigi array!" << endl;
93  return kERROR;
94  }
95  }
96 
97  // Get input array
98  fHitArray = (TClonesArray*) ioman->GetObject("EmcHit");
99  if ( ! fHitArray ) {
100  cout << "-W- PndEmcMakeCluster::Init: "
101  << "No PndEmcHit array! Needed for MC Truth" << endl;
102  }
103 
104  // Get input array
105  fMCTrackArray = (TClonesArray*) ioman->GetObject("MCTrack");
106  if ( ! fMCTrackArray ) {
107  cout << "-W- PndEmcMakeCluster::Init: "
108  << "No MCTrack array! Needed for MC Truth" << endl;
109  }
110 
111  // Create and register output array
112  fClusterArray = new TClonesArray("PndEmcCluster");
113  fWriteOutArray = new TClonesArray(fClusterArray->GetClass());
114 
115  ioman->Register("EmcCluster","Emc", fWriteOutArray, GetPersistency());
116 
117  if(FairRunAna::Instance()->IsTimeStamp()) {
118  // for subsequent methods we need the "event grouping" as given by the TS buffer --> fDigiArray becomes an output array.
119  fDigiArray = new TClonesArray(fDigiArray->GetClass()); //still needed to activate array
120  ioman->Register("EmcDigiClusterBase", "Emc", fDigiArray, fStoreClusterBase);
121  }
122  fDigiFunctor = new TimeGap();
123 
126 
131  fClusterActiveTime=fRecoPar->GetClusterActiveTime() * 1.0e9; //convert from seconds to nanoseconds
132 
133  cout<<"PndEmcMakeCluster::fDigiEnergyTresholdBarrel: "<<fDigiEnergyTresholdBarrel<<endl;
134  cout<<"PndEmcMakeCluster::fDigiEnergyTresholdFWD: "<<fDigiEnergyTresholdFWD<<endl;
135  cout<<"PndEmcMakeCluster::fDigiEnergyTresholdBWD: "<<fDigiEnergyTresholdBWD<<endl;
136  cout<<"PndEmcMakeCluster::fDigiEnergyTresholdShashlyk: "<<fDigiEnergyTresholdShashlyk<<endl;
137  cout<<"PndEmcMakeCluster::fClusterActiveTime in ns(!): "<<fClusterActiveTime<<endl;
138  cout<<"PndEmcMakeCluster::ClusterPosMethod(): " << fRecoPar->GetEmcClusterPosMethod() << std::endl;
139 
140  if (!strcmp(fRecoPar->GetEmcClusterPosMethod(),"lilo"))
141  {
142  cout<<"Lilo cluster position method"<<endl;
146  }
147 
148  cout << "-I- PndEmcMakeCluster: Intialization successfull" << endl;
149  return kSUCCESS;
150 }
151 
161 void PndEmcMakeCluster::Exec(Option_t*)
162 {
163 
164  if (fVerbose>2){
165  fTimer.Start();
166  }
167  // Reset output array
168  if ( ! fClusterArray ) Fatal("Exec", "No Cluster Array");
169 
170  fWriteOutArray->Delete();
171 
172 // std::cout << "------ Event " << FairRootManager::Instance()->GetEntryNr() << " ------" << std::endl;
173 
174  if(FairRunAna::Instance()->IsTimeStamp()) {
175  fDigiArray->Delete();
176  fDigiArray->AbsorbObjects(FairRootManager::Instance()->GetData("EmcDigiSorted", fDigiFunctor, fClusterActiveTime));
177  }
178 
179 
180  Int_t nDigis = fDigiArray->GetEntriesFast();
181  if (fVerbose>2){
182  cout<<"DigiList length "<<nDigis<<endl;
183  }
184 
185  //loop to build Cluster
186  for (Int_t iDigi=0; iDigi<nDigis; iDigi++)
187  {
188  PndEmcDigi* theDigi = (PndEmcDigi*) fDigiArray->At(iDigi);
189 // std::cout << std::endl << "DigiArray: " << iDigi << std::endl;
190 // theDigi->Print();
191 // std::cout << *theDigi->GetPointerToLinks() << std::endl;
192 // std::cout << std::endl;
193  Int_t module=theDigi->GetModule();
194 
195  // In the following lines there is separate threshold for forward endcap
196  // and the same for barrel and backward and shashlyk EMC, but for last 2 threshold probably should be different
197  if ((module==1||module==2)&&(theDigi->GetEnergy()< fDigiEnergyTresholdBarrel)) continue;
198  if ((module==3)&&(theDigi->GetEnergy()< fDigiEnergyTresholdFWD)) continue;
199  if ((module==4)&&(theDigi->GetEnergy()< fDigiEnergyTresholdBWD)) continue;
200  if ((module==5)&&(theDigi->GetEnergy()< fDigiEnergyTresholdShashlyk)) continue;
201 
202  bool isAdded = false;
203  Int_t clustmarker=0;
204  Int_t clustLength=fClusterArray->GetEntriesFast();
205 
206  for(Int_t i=0;i<clustLength;i++)
207  {
208  PndEmcCluster* cluster= (PndEmcCluster*) fClusterArray->At(i);
209  if(HasExpired(theDigi, cluster, i)) {
210  clustLength--;
211  i--;
212  continue;
213  } else {
214 // std::cout << "Clusterarray: " << i << std::endl;
215  }
216 
217  if(cluster->isInCluster(theDigi, fDigiArray))
218  {
219  if(!isAdded) {
220  clustmarker=i;
221  isAdded=true;
222  cluster->addDigi(fDigiArray, iDigi);
223  //cluster->AddLink(FairLink("EmcDigi", iDigi));
224  FairMultiLinkedData hitLinks = theDigi->GetLinksWithType(FairRootManager::Instance()->GetBranchId("EmcHit"));
225  for (Int_t j = 0; j < hitLinks.GetNLinks(); j++){
226  PndEmcHit* hit = (PndEmcHit*)FairRootManager::Instance()->GetCloneOfLinkData(hitLinks.GetLink(j));
227  //std::cout << "Hit: " << hit->GetDetectorID() << std::endl;
228  if(hit) {
229 // std::cout << "Cluster : " << clustmarker << " Hit to add: " << hitLinks.GetLink(j) << std::endl;
230  if (cluster->GetLinks().count(hitLinks.GetLink(j)) == 0){
232  cluster->AddLink(hitLinks.GetLink(j));
233 // std::cout << "Links in Cluster: " << *cluster->GetPointerToLinks() << std::endl;
234 // std::cout << "EnteringExiting for Hit: " << hitLinks.GetLink(j) << std::endl;
235 // std::cout << "TrackEntering: " << hit->GetTrackEntering() << std::endl;
236 // std::cout << "TrackExiting: " << hit->GetTrackExiting() << std::endl;
237 // std::cout << "Resulting Enter: " << cluster->GetTrackEntering() << std::endl;
238 // std::cout << "Resulting Exit: " << cluster->GetTrackExiting() << std::endl;
239  } else {
240  //std::cout << "Hit Already exists!" << std::endl;
241  }
242  delete(hit);
243 
244  } else {
245  std::cout << "-E in PndEmcMakeCluster::Exec FairLink " << hitLinks.GetLink(j) << "to EmcHit delivers null" << std::endl;
246  }
247  }
248  }
249  else
250  {
251  PndEmcCluster* clust_clustmarker=(PndEmcCluster*) fClusterArray->At(clustmarker);
252  PndEmcCluster* clust_i=(PndEmcCluster*) fClusterArray->At(i);
253  clust_clustmarker->addCluster(clust_i, fDigiArray);
254  fClusterArray->RemoveAt(i);
255  fClusterArray->Compress();
256  clustLength--;
257  i--;
258  }
259  }
260  }
261 
262  if (!isAdded)
263  {
264  PndEmcCluster* newcluster = new((*fClusterArray)[clustLength]) PndEmcCluster();
265  newcluster->addDigi(fDigiArray, iDigi);
266 
267  FairMultiLinkedData hitLinks = theDigi->GetLinksWithType(FairRootManager::Instance()->GetBranchId("EmcHit"));
268  //std::cout << "HitLinks isNotAdded: " << hitLinks << std::endl;
269  // theDigi->Print(); std::cout << std::endl;
270  for (Int_t i = 0; i < hitLinks.GetNLinks(); i++){
271  PndEmcHit* hit = (PndEmcHit*)FairRootManager::Instance()->GetCloneOfLinkData(hitLinks.GetLink(i));
272  if(hit) {
273 // std::cout << "NewCluster : " << clustLength << " Hit Added: " << hitLinks.GetLink(i) << std::endl;
274 // std::cout << "TrackEntering: " << hit->GetTrackEntering() << std::endl;
275 // std::cout << "TrackExiting: " << hit->GetTrackExiting() << std::endl;
276  newcluster->SetTrackEntering(hit->GetTrackEntering());
277  newcluster->SetTrackExiting(hit->GetTrackExiting());
278  newcluster->SetInsertHistory(kFALSE);
279  newcluster->AddLink(hitLinks.GetLink(i));
280 // std::cout << "Resulting Enter: " << newcluster->GetTrackEntering() << std::endl;
281 // std::cout << "Resulting Exit: " << newcluster->GetTrackExiting() << std::endl;
282 // std::cout << "Links in Cluster: " << *newcluster->GetPointerToLinks() << std::endl;
283  delete(hit);
284  } else {
285  std::cout << "-E in PndEmcMakeCluster::Exec FairLink " << hitLinks.GetLink(i) << "to EmcHit delivers null" << std::endl;
286  }
287  }
288  //newcluster->SetLink(FairLink("EmcDigi", iDigi));
289  }
290  }
291 // for (int k = 0; k < fClusterArray->GetEntriesFast(); k++){
292 // PndEmcCluster* myCluster = (PndEmcCluster*)fClusterArray->At(k);
293 // std::cout << k << " : Entering: " << myCluster->GetTrackEntering() << std::endl;
294 // std::cout << k << " : Exiting: " << myCluster->GetTrackExiting() << std::endl;
295 // }
296 // std::cout << std::endl;
297 
298  fWriteOutArray->AbsorbObjects(fClusterArray);
299 }
300 
301 
311 {
312  using namespace std;
313 
314  //cout << "\tfinalizing cluster: ";
315  //cout << "\tmaxTime: " << tmpclust->GetTimeStamp() << endl;
316  //cout << "\tcontains the following digis: " << endl;
317  //for(unsigned int i=0; i<tmpclust->DigiList().size(); ++i) {
318  //cout << "\t#:" << i << "\ttime: " << ((PndEmcDigi*) (fDigiArray->UncheckedAt(tmpclust->DigiList()[i])))->GetTimeStamp() << "\tenergy: " << ((PndEmcDigi*) (fDigiArray->UncheckedAt(tmpclust->DigiList()[i])))->GetEnergy() << "\tidx: " << ((PndEmcDigi*) (fDigiArray->UncheckedAt(tmpclust->DigiList()[i])))->GetDetectorId() << endl;
319  //}
320 
321  PndEmcClusterProperties clustProperties(*tmpclust, fDigiArray);
322 
323  tmpclust->SetEnergy(clustProperties.Energy());
324  tmpclust->SetTimeStamp(tmpclust->Maxima(fDigiArray)->GetTimeStamp());
325  TVector3 tmpbumppos = clustProperties.Where(fRecoPar->GetEmcClusterPosMethod(), fClusterPosParam);
326  tmpclust->SetPosition(tmpbumppos);
327  PndEmcXClMoments xClMoments(*tmpclust, fDigiArray);
328  tmpclust->SetZ20(xClMoments.AbsZernikeMoment(2, 0, 15));
329  tmpclust->SetZ53(xClMoments.AbsZernikeMoment(5, 3, 15));
330  tmpclust->SetLatMom(xClMoments.Lat());
331  tmpclust->SetLinks(tmpclust->GetTrackEntering());
332  // std::cout << "ClusterOutput: " << std::endl;
333  // tmpclust->Print();
334  //const std::vector<Int_t>& MCTruth = tmpclust->GetMcList();
335  //std::cout<<"The cluster #"<<i<<" produced by MC Track #";
336  //for(Int_t j=0;j<MCTruth.size();++j)
337  // cout<<MCTruth[j]<<' ';
338  //cout<<endl;
339 
340  //tmpclust->fMcList.clear();
341  //if(fHitArray && fMCTrackArray && !FairRunAna::Instance()->IsTimeStamp()){
342  // // BS: this is a first order approximation only !!!!
343 
344  // std::vector <Int_t> newlist;
345  // newlist.clear();
346  // for(Int_t j=0; j<tmpclust->fDigiList.size(); j++){
347  // PndEmcDigi*m;
348  // m=(PndEmcDigi*)fDigiArray->At(tmpclust->fDigiList[j]);
349 
350  // Int_t inx;
351  // inx=m->GetHitIndex();
352 
353  // if(inx>=0){
354  // if(fHitArray->At(inx) != 0 ){//add by hujf
355  // const std::vector <Int_t> &tmplist=((PndEmcHit*) fHitArray->At(inx))->GetMcList();
356 
357  // // I copy the complete list instead of only the highest energy particle
358  // // highest energy might be a problem for Hits which belong to two real clusters?
359  // for(Int_t k=0; k<tmplist.size(); k++){
360  // newlist.push_back(tmplist[k]);
361  // }
362  // }
363  // }
364  // // if( fMCTrackArray) checked above already
365  // cleansortmclist(newlist,fMCTrackArray);
366  // tmpclust->fMcList=newlist;
367  //}
368 }
369 
370 
377 {
378  Int_t nCluster = fWriteOutArray->GetEntriesFast();
379  for (Int_t i=0; i<nCluster; i++) {
381  }
382 
383  fEventCounter++;
384  if (fVerbose>0)
385  cout<<"PndEmcMakeCluster, event: "<<fEventCounter<<endl;
386 
387  if (fVerbose>2){
388  fTimer.Stop();
389  Double_t rtime = fTimer.RealTime();
390  Double_t ctime = fTimer.CpuTime();
391  fTimer.Reset();
392  cout << "PndEmcMakeCluster, Real time " << rtime << " s, CPU time " << ctime << " s" << endl;
393  }
394 }
395 
409 bool PndEmcMakeCluster::HasExpired(PndEmcDigi* latestDigi, PndEmcCluster* theCluster, Int_t clusterIdx)
410 {
411  if(!FairRunAna::Instance()->IsTimeStamp()) return false;
412 
413  if(latestDigi->GetTimeStamp() > theCluster->GetTimeStamp() + fClusterActiveTime) {
414  fWriteOutArray->AbsorbObjects(fClusterArray, clusterIdx, clusterIdx);
415  //cout << "cluster " << clusterIdx << "has been expired" << std::endl;
416  return true;
417  } else {
418  return false;
419  }
420 }
421 
422 
432 void PndEmcMakeCluster::cleansortmclist( std::vector <Int_t> &newlist,TClonesArray* mcTrackArray)
433 {
434  std::vector <Int_t> tmplist;
435  // Sort list...
436  std::sort( newlist.begin(), newlist.end());
437  // and copy every id only once (even though it might be in the list several times)
438  std::unique_copy( newlist.begin(), newlist.end(), std::back_inserter( tmplist ) );
439 
440  // Now check if mother or (grand)^x-mother are already in the list
441  // (which means i am a secondary)... if so, remove myself
442  for(Int_t j=tmplist.size()-1; j>=0; j--){
443  bool flag;
444  PndMCTrack *pt;
445  pt=((PndMCTrack*)mcTrackArray->At(tmplist[j]));
446  if(pt->GetMotherID()<0) continue;
447  flag=false;
448  while(!flag){
449  Int_t id;
450  id=pt->GetMotherID();
451  if(id<0) break;
452  pt=(PndMCTrack*)mcTrackArray->At(id);
453 
454  for(Int_t k=j-1; k>=0; k--){
455  if(tmplist[k]==id){
456  tmplist.erase(tmplist.begin()+j);
457  flag=true;
458  break;
459  }
460  }
461  }
462  }
463  newlist=tmplist;
464 }
465 
467 
468  // Get run and runtime database
469  FairRun* run = FairRun::Instance();
470  if ( ! run ) Fatal("SetParContainers", "No analysis run");
471 
472  FairRuntimeDb* db = run->GetRuntimeDb();
473  if ( ! db ) Fatal("SetParContainers", "No runtime database");
474 
475  // Get Emc geometry parameter container
476  fGeoPar = (PndEmcGeoPar*) db->getContainer("PndEmcGeoPar");
477 
478  // Get Emc digitisation parameter container
479  fDigiPar = (PndEmcDigiPar*) db->getContainer("PndEmcDigiPar");
480 
481  // Get Emc reconstruction parameter container
482  fRecoPar = (PndEmcRecoPar*) db->getContainer("PndEmcRecoPar");
483 }
484 
486 {
487  SetPersistency(val);
488  return;
489 }
490 
491 
void SetEnergy(Double_t en)
virtual void SetParContainers()
void SetStorageOfData(Bool_t val)
Method to specify whether clusters are stored or not.
int fVerbose
Definition: poormantracks.C:24
PndEmcDigiPar * fDigiPar
Double_t fDigiEnergyTresholdBWD
virtual void FinishClusters()
Calls FinishCluster() for each cluster.
bool isInCluster(PndEmcDigi *theDigi, const TClonesArray *digiArray)
Double_t fDigiEnergyTresholdShashlyk
Int_t run
Definition: autocutx.C:47
static Int_t fEventCounter
Double_t fClusterActiveTime
Defines how long clusters are kept open in timebased reconstruction.
virtual Double_t GetEnergy() const
Definition: PndEmcDigi.cxx:296
represents the reconstructed hit of one emc crystal
Definition: PndEmcDigi.h:40
Int_t i
Definition: run_full.C:25
PndEmcMakeCluster(Int_t verbose=0, Bool_t storeclusters=kTRUE)
FairMultiLinkedData GetTrackEntering() const
Definition: PndEmcHit.h:65
TClonesArray * fClusterArray
active clusters
Double_t val[nBoxes][nFEBox]
Definition: createCalib.C:11
virtual Double_t Lat() const
#define verbose
FairMultiLinkedData GetTrackExiting() const
Definition: PndEmcHit.h:66
void SetTrackExiting(const FairMultiLinkedData &tracks)
Double_t GetEnergyThresholdBarrel()
Definition: PndEmcRecoPar.h:15
TVector3 Where(TString method, std::vector< Double_t > params)
void SetPersistency(Bool_t val=kTRUE)
TClonesArray * fHitArray
PndEmcRecoPar * fRecoPar
virtual Double_t AbsZernikeMoment(int n, int m, Double_t R0=15) const
Double_t GetOffsetParmB()
Definition: PndEmcRecoPar.h:22
Double_t GetOffsetParmC()
Definition: PndEmcRecoPar.h:23
virtual void Exec(Option_t *opt)
Runs the task.
void AddTracksEnteringExiting(const FairMultiLinkedData &tracksEntering, const FairMultiLinkedData &tracksExiting)
Updates the links to entering and exiting tracks.
Short_t GetModule() const
Definition: PndEmcDigi.h:103
void InitEmcMapper()
void addCluster(PndEmcCluster *cluster, const TClonesArray *digiArray)
TString pt(TString pts, TString exts="px py pz")
Definition: invexp.C:133
TClonesArray * fDigiArray
void cleansortmclist(std::vector< Int_t > &newlist, TClonesArray *mcTrackArray)
Helper function, does not depend on class, identical to the one in PndEmcHitProducer.
Double_t fDigiEnergyTresholdFWD
Double_t GetClusterActiveTime()
Definition: PndEmcRecoPar.h:19
virtual const PndEmcDigi * Maxima(const TClonesArray *digiArray) const
Double_t
Double_t GetEnergyThresholdFWD()
Definition: PndEmcRecoPar.h:16
parameter set of Emc digitisation
Definition: PndEmcDigiPar.h:12
void FinishCluster(PndEmcCluster *tmpcluster)
Assign final parameters to cluster.
Double_t GetOffsetParmA()
Definition: PndEmcRecoPar.h:21
a cluster (group of neighboring crystals) of hit emc crystals
Definition: PndEmcCluster.h:29
Double_t ctime
Definition: hit_dirc.C:114
std::vector< PndEmcCluster * > fClusterList
Task to cluster PndEmcDigis.
void SetZ20(Double_t z20)
represents the deposited energy of one emc crystal from simulation
Definition: PndEmcHit.h:26
std::vector< Double_t > fClusterPosParam
virtual Double_t Energy() const
void SetZ53(Double_t z53)
int hit(Int_t nEvents=0, TString inFile="sim.root", TString parFile="par.root", TString inDigi="digi.root", TString outFile="hit.root", Int_t timeBased=0)
Definition: hit.C:1
virtual InitStatus Init()
Init Task.
ClassImp(PndAnaContFact)
Double_t fDigiEnergyTresholdBarrel
BinaryFunctor * fDigiFunctor
Double_t GetEnergyThresholdShashlyk()
Definition: PndEmcRecoPar.h:18
void SetPosition(TVector3 pos)
void SetTrackEntering(const FairMultiLinkedData &tracks)
PndEmcGeoPar * fGeoPar
Text_t * GetEmcClusterPosMethod()
Definition: PndEmcRecoPar.h:20
static PndEmcStructure * Instance()
Int_t GetMotherID() const
Definition: PndMCTrack.h:74
Double_t rtime
Definition: hit_dirc.C:113
bool HasExpired(PndEmcDigi *latestDigi, PndEmcCluster *theCluster, Int_t clusterIdx)
Finishes clusters in timebased analysis.
Double_t GetEnergyThresholdBWD()
Definition: PndEmcRecoPar.h:17
TClonesArray * fMCTrackArray
void SetLatMom(Double_t latMom)
TClonesArray * fWriteOutArray
expired clusters
FairMultiLinkedData GetTrackEntering() const
Parameter set for Emc Reco.
Definition: PndEmcRecoPar.h:12
virtual void addDigi(const TClonesArray *digiArray, Int_t iDigi)