Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DFCALCluster_factory.cc
Go to the documentation of this file.
1 // $Id: DFCALShower_factory.cc 2001 2006-11-28 11:09:47Z mikornic $
2 //
3 // File: DFCALShower_factory.cc
4 // Created: Tue Nov 28 11:57:50 EST 2006
5 // Creator: remitche (on Linux mantrid00 2.4.20-18.8smp i686)
6 //
7 
8 #include <iostream>
9 #include <fstream>
10 #include <math.h>
11 #include <DVector3.h>
12 using namespace std;
13 
14 #include <JANA/JEvent.h>
15 using namespace jana;
16 
17 #include "FCAL/DFCALCluster.h"
19 #include "FCAL/DFCALHit.h"
20 #include "FCAL/DFCALGeometry.h"
21 #include "HDGEOMETRY/DGeometry.h"
22 
23 
24 // Used to sort hits by Energy
25 bool FCALHitsSort_C(const DFCALHit* const &thit1, const DFCALHit* const &thit2) {
26  return thit1->E>thit2->E;
27 }
28 
29 const DFCALHit *GetDFCALHitFromClusterHit(const DFCALCluster::DFCALClusterHit_t &theClusterHit, const vector<const DFCALHit*> &fcalhits) {
30  for( vector<const DFCALHit*>::const_iterator fcalhits_itr = fcalhits.begin();
31  fcalhits_itr != fcalhits.end(); fcalhits_itr++) {
32  if(theClusterHit.id == (*fcalhits_itr)->id)
33  return *fcalhits_itr;
34  }
35 
36  return NULL;
37 }
38 
39 //----------------
40 // Constructor
41 //----------------
43 {
44  // Set defaults
45  MIN_CLUSTER_BLOCK_COUNT = 2;
46  MIN_CLUSTER_SEED_ENERGY = 0.035; // GeV
47  TIME_CUT = 15.0 ; //ns
48  MAX_HITS_FOR_CLUSTERING = 250;
49 
50  gPARMS->SetDefaultParameter("FCAL:MIN_CLUSTER_BLOCK_COUNT", MIN_CLUSTER_BLOCK_COUNT);
51  gPARMS->SetDefaultParameter("FCAL:MIN_CLUSTER_SEED_ENERGY", MIN_CLUSTER_SEED_ENERGY);
52  gPARMS->SetDefaultParameter("FCAL:MAX_HITS_FOR_CLUSTERING", MAX_HITS_FOR_CLUSTERING);
53  gPARMS->SetDefaultParameter("FCAL:TIME_CUT",TIME_CUT,"time cut for associating FCAL hits together into a cluster");
54 
55 }
56 
57 //------------------
58 // brun
59 //------------------
60 jerror_t DFCALCluster_factory::brun(JEventLoop *eventLoop, int32_t runnumber)
61 {
62  double targetZ;
63  double fcalFrontFaceZ;
64 
65  DGeometry *dgeom = NULL;
66  DApplication *dapp = dynamic_cast< DApplication* >( eventLoop->GetJApplication() );
67  if( dapp ) dgeom = dapp->GetDGeometry( runnumber );
68 
69  if( dgeom ){
70 
71  dgeom->GetTargetZ( targetZ );
72  dgeom->GetFCALZ( fcalFrontFaceZ );
73  }
74  else{
75 
76  cerr << "No geometry accessbile." << endl;
77  return RESOURCE_UNAVAILABLE;
78  }
79 
80  fcalFaceZ_TargetIsZeq0 = fcalFrontFaceZ - targetZ;
81 
82  return NOERROR;
83 }
84 
85 //------------------
86 // evnt
87 // Implementation of UConn LGD clusterizer (M. Kornicer)
88 //------------------
89 jerror_t DFCALCluster_factory::evnt(JEventLoop *eventLoop, uint64_t eventnumber)
90 {
91 
92  vector<const DFCALHit*> fcalhits;
93  eventLoop->Get(fcalhits);
94 
95  // LED events will have hits in nearly every channel. Do NOT
96  // try clusterizing if more than 250 hits in FCAL
97  if(fcalhits.size() > MAX_HITS_FOR_CLUSTERING) return NOERROR;
98 
99  vector<const DFCALGeometry*> geomVec;
100  eventLoop->Get(geomVec);
101  const DFCALGeometry& fcalGeom = *(geomVec[0]);
102 
103  // Sort hits by energy
104  sort(fcalhits.begin(), fcalhits.end(), FCALHitsSort_C);
105 
106  // fill user's hit list
107  int nhits = 0;
108  DFCALCluster::userhits_t* hits =
110 
111  // Fill the structure that used to be used by clusterizers in Radphi
112  for (vector<const DFCALHit*>::const_iterator hit = fcalhits.begin();
113  hit != fcalhits.end(); hit++ ) {
114  if ( (**hit).E < 1e-6 ) continue;
115  hits->hit[nhits].id = (**hit).id;
116  hits->hit[nhits].ch = fcalGeom.channel( (**hit).row, (**hit).column );
117  hits->hit[nhits].x = (**hit).x;
118  hits->hit[nhits].y = (**hit).y;
119  hits->hit[nhits].E = (**hit).E;
120  hits->hit[nhits].t = (**hit).t;
121  hits->hit[nhits].intOverPeak = (**hit).intOverPeak;
122  nhits++;
123 
124  if (nhits >= (int) FCAL_USER_HITS_MAX) {
125  cout << "ERROR: FCALCluster_factory: number of hits "
126  << nhits << " larger than " << FCAL_USER_HITS_MAX << endl;
127  break;
128  }
129 
130  }
131  hits->nhits = nhits;
132 
133  int hitUsed[nhits];
134  for ( int i = 0; i < nhits; i++ ) {
135  hitUsed[i] = 0;
136  }
137 
138  const unsigned int max = 999;
139  DFCALCluster* clusterList[max];
140  unsigned int clusterCount = 0;
141  int iter;
142  for ( iter=0; iter < 99; iter++ ) {
143 
144  // 1. At beginning of iteration, recompute info for all clusters.
145  // If something changed, return all hits to the pool and repeat.
146 
147  bool something_changed = false;
148  for ( unsigned int c = 0; c < clusterCount; c++ ) {
149  //cout << " --------- Update iteration " << iter << endl;
150  something_changed |= clusterList[c]->update( hits, fcalFaceZ_TargetIsZeq0 );
151  }
152  if (something_changed) {
153  for ( unsigned int c = 0; c < clusterCount; c++ ) {
154  clusterList[c]->resetClusterHits();
155  }
156  // reset hits in factory also:
157  for ( int h = 0; h < nhits; h++ ) hitUsed[h] = 0;
158  }
159  else if (iter > 0) {
160  break;
161  }
162 
163  // 2. Look for blocks with energy large enough to require formation
164  // of a new cluster, and assign them as cluster seeds.
165 
166  for ( int ih = 0; ih < hits->nhits; ih++ ) {
167  double energy = hits->hit[ih].E;
168  //cout << "hit: " << ih << " E: " << energy << endl;
169  if (energy < MIN_CLUSTER_SEED_ENERGY)
170  break;
171  double totalAllowed = 0;
172  for ( unsigned int c = 0; c < clusterCount; c++ ) {
173  totalAllowed += clusterList[c]->getEallowed(ih);
174  //cout << " totalAlowed from clust " << c << " is " << totalAllowed << endl;
175 
176  }
177  if (energy > totalAllowed) {
178  clusterList[clusterCount] = new DFCALCluster( hits->nhits );
179  hitUsed[ih] = -1;
180  clusterList[clusterCount]->addHit(ih,1.);
181  clusterList[clusterCount]->update( hits, fcalFaceZ_TargetIsZeq0 );
182  ++clusterCount;
183  }
184  else if (iter > 0) {
185  for ( unsigned int c = 0; c < clusterCount; c++ ) {
186  int nh_clust = clusterList[c]->getHits();
187  //cout << " Nhits " << nh_clust << " from clust " << c << " ? " << endl;
188  if ( nh_clust )
189  continue;
190  totalAllowed -= clusterList[c]->getEallowed(ih);
191  //cout << " else totalAlowed from " << c << " E: " << totalAllowed << endl;
192  if (energy > totalAllowed) {
193  if ( clusterList[c]->getHits() == 0 ) {
194  hitUsed[ih] = -1;
195  }
196  else {
197  ++hitUsed[ih];
198  }
199  clusterList[c]->addHit(ih,1.);
200  break;
201  }
202  }
203  }
204  }
205 
206 
207  // 3. Share all non-seed blocks among seeded clusters, where
208  // any cluster shares a block if it expects at least 1 KeV in it.
209 
210  for ( int ih = 0; ih < hits->nhits; ih++ ) {
211  if ( hitUsed[ih] < 0) // cannot share seed
212  continue;
213  double totalExpected = 0;
214  //cout << " Share hit: " << ih << " E: " << hits->hit[ih].E
215  // << " ch: " << hits->hit[ih].ch << " t: " << hits->hit[ih].t
216  // << endl;
217  for ( unsigned int c = 0; c < clusterCount; c++ ) {
218  if (clusterList[c]->getHits() > 0) {
219  totalExpected += clusterList[c]->getEexpected(ih);
220  }
221  }
222  //cout << " totExpected " << totalExpected ;
223  for ( unsigned int c = 0; c < clusterCount; c++ ) {
224  if (clusterList[c]->getHits() > 0) {
225  double expected = clusterList[c]->getEexpected(ih);
226  //cout << " expected " << expected ;
227  if (expected > 1e-6
228  && fabs(clusterList[c]->getTimeMaxE()
229  -hits->hit[ih].t)<TIME_CUT ) {
230  clusterList[c]->addHit(ih,expected/totalExpected);
231  ++hitUsed[ih];
232  }
233  }
234  }
235  }
236  }
237 
238  for ( unsigned int c = 0; c < clusterCount; c++) {
239  unsigned int blockCount = clusterList[c]->getHits();
240  //cout << " Blocks " << blockCount << endl;
241  if (blockCount < MIN_CLUSTER_BLOCK_COUNT) {
242  delete clusterList[c];
243  continue;
244  }
245  else {
246 
247  clusterList[c]->saveHits( hits );
248 
249  // save associated FCAL hit information
250  const vector<DFCALCluster::DFCALClusterHit_t> &clusterHits = clusterList[c]->GetHits();
251  for(size_t loc_i = 0; loc_i < clusterHits.size(); loc_i++) {
252  const DFCALHit *clusterHit = GetDFCALHitFromClusterHit(clusterHits[loc_i], fcalhits);
253  if( clusterHit != NULL )
254  clusterList[c]->AddAssociatedObject( clusterHit );
255  }
256 
257  _data.push_back( clusterList[c] );
258  }
259  }
260 
261 
262  if (hits) {
263  free(hits);
264  hits=0;
265  }
266 
267  return NOERROR;
268 
269 }
270 
DApplication * dapp
const vector< DFCALClusterHit_t > GetHits() const
Definition: DFCALCluster.h:84
#define c
#define FCAL_USER_HITS_MAX
Definition: DFCALCluster.h:19
jerror_t evnt(JEventLoop *eventLoop, uint64_t eventnumber)
bool GetFCALZ(double &z_fcal) const
z-location of front face of CCAL in cm
Definition: DGeometry.cc:1718
double getEallowed(const int ihit) const
Definition: DFCALCluster.h:146
TEllipse * e
jerror_t brun(JEventLoop *eventLoop, int32_t runnumber)
DGeometry * GetDGeometry(unsigned int run_number)
void saveHits(const userhits_t *const hit)
Definition: DFCALCluster.cc:57
bool update(const userhits_t *const hitList, double fcalFaceZ)
int addHit(const int ihit, const double frac)
Definition: DFCALCluster.cc:86
int channel(int row, int column) const
int getHits() const
Definition: DFCALCluster.h:218
bool FCALHitsSort_C(const DFCALHit *const &thit1, const DFCALHit *const &thit2)
const DFCALHit * GetDFCALHitFromClusterHit(const DFCALCluster::DFCALClusterHit_t &theClusterHit, const vector< const DFCALHit * > &fcalhits)
float E
Definition: DFCALHit.h:27
void resetClusterHits()
bool GetTargetZ(double &z_target) const
z-location of center of target
Definition: DGeometry.cc:1933
double getEexpected(const int ihit) const
Definition: DFCALCluster.h:138