Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DBCALUnifiedHit_factory.cc
Go to the documentation of this file.
1 #include <vector>
2 using namespace std;
3 
4 #include <JANA/JApplication.h>
5 using namespace jana;
6 
8 
9 #include "units.h"
10 
11 //----------------
12 // init
13 //----------------
15 {
16 
17  if (enable_debug_output) {
18  bcal_points_tree = new TTree("bcal_points_tree","");
19  bcal_points_tree->Branch("E",&E_tree,"E/F");
20  bcal_points_tree->Branch("t_tdc",&t_tdc_tree,"t_tdc/F");
21  bcal_points_tree->Branch("t_adc",&t_adc_tree,"t_adc/F");
22  bcal_points_tree->Branch("t_tdc_corrected",&t_tdc_corrected_tree,"t_tdc_corrected/F");
23  bcal_points_tree->Branch("t_adc_corrected",&t_adc_corrected_tree,"t_adc_corrected/F");
24  bcal_points_tree->Branch("layer",&layer_tree,"layer/I");
25  bcal_points_tree->Branch("end",&end_tree,"end/O");
26  }
27 
28  USE_TDC = false;
29  if (gPARMS){
30  gPARMS->SetDefaultParameter("BCAL:USE_TDC", USE_TDC, "Set to 1 to use TDC times");
31  }
32 
33  static pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER;
34  static bool printMessage = true;
35  pthread_mutex_lock(&print_mutex);
36  if (printMessage){
37  if (USE_TDC){
38  jout << "DBCALUnifiedHit_factory: Using TDC times when available." << endl;
39  }
40  else{
41  jout << "DBCALUnifiedHit_factory: Using ADC times only." << endl;
42  }
43  }
44  printMessage = false;
45  pthread_mutex_unlock(&print_mutex);
46 
47  return NOERROR;
48 }
49 
50 jerror_t DBCALUnifiedHit_factory::brun(jana::JEventLoop *eventLoop, int32_t runnumber) {
51 
52  // load BCAL geometry
53  vector<const DBCALGeometry *> BCALGeomVec;
54  eventLoop->Get(BCALGeomVec);
55  if(BCALGeomVec.size() == 0)
56  throw JException("Could not load DBCALGeometry object!");
57  dBCALGeom = BCALGeomVec[0];
58 
59  //get timewalk corrections from CCDB
60  JCalibration *jcalib = eventLoop->GetJCalibration();
61  //these tables hold: module layer sector end c0 c1 c2 c3 threshold
62  vector<vector<float> > tdc_timewalk_table;
63 
64  // jcalib->Get("BCAL/timewalk_tdc",tdc_timewalk_table);
65  if(jcalib->Get("BCAL/timewalk_tdc_c4",tdc_timewalk_table)) {
66  jerr << "Error loading BCAL/timewalk_tdc !" << endl;
67  } else {
68  for (vector<vector<float> >::const_iterator iter = tdc_timewalk_table.begin();
69  iter != tdc_timewalk_table.end();
70  ++iter) {
71  //if (iter->size() != 8) {
72  // cout << "DBCALUnifiedHit_factory: Wrong number of values in timewalk_tdc table (should be 8)" << endl;
73  if (iter->size() != 9) {
74  cout << "DBCALUnifiedHit_factory: Wrong number of values in timewalk_tdc table (should be 9)" << endl;
75  continue;
76  }
77  //be really careful about float->int conversions
78  int module = (int)((*iter)[0]+0.5);
79  int layer = (int)((*iter)[1]+0.5);
80  int sector = (int)((*iter)[2]+0.5);
81  int endi = (int)((*iter)[3]+0.5);
83  float c0 = (*iter)[4];
84  float c1 = (*iter)[5];
85  float c2 = (*iter)[6];
86  float c3 = (*iter)[7];
87  float thresh = (*iter)[8];
88  int cellId = dBCALGeom->cellId(module, layer, sector);
89  readout_channel channel(cellId,end);
90  tdc_timewalk_map_c4[channel] = timewalk_coefficients_c4(c0,c1,c2,c3,thresh);
91  //tdc_timewalk_map[channel] = timewalk_coefficients(c0,c1,c2,a_thresh);
92  }
93 
94  for (int module=1; module<=dBCALGeom->GetBCAL_Nmodules(); module++) {
95  //shouldn't be hardcoded
96  for (int sector=1; sector<=4; sector++) {
97  for (int layer=1; layer<=dBCALGeom->GetBCAL_NInnerLayers(); layer++) {
98  int id = dBCALGeom->cellId(module, layer, sector);
99  //if (tdc_timewalk_map.count(readout_channel(id,dBCALGeom->kUpstream)) != 1) {
100  if (tdc_timewalk_map_c4.count(readout_channel(id,dBCALGeom->kUpstream)) != 1) {
101  cout << "DBCALUnifiedHit_factory: Channel missing in timewalk_tdc_table: "
102  << endl << " module " << module << " layer " << layer << " sector " << sector << " upstream" << endl;
103  }
104  //if (tdc_timewalk_map.count(readout_channel(id,dBCALGeom->kDownstream)) != 1) {
105  if (tdc_timewalk_map_c4.count(readout_channel(id,dBCALGeom->kDownstream)) != 1) {
106  cout << "DBCALUnifiedHit_factory: Channel missing in timewalk_tdc_table: "
107  << endl << " module " << module << " layer " << layer << " sector " << sector << " downstream" << endl;
108  }
109  }
110  }
111  }
112  }
113 
114  return NOERROR;
115 }
116 
117 //----------------
118 // evnt
119 //----------------
120 jerror_t DBCALUnifiedHit_factory::evnt(JEventLoop *loop, uint64_t eventnumber) {
121  vector<const DBCALHit*> hits;
122  vector<const DBCALTDCHit*> tdc_hits;
123  loop->Get(hits);
124  loop->Get(tdc_hits);
125  if (hits.size() + tdc_hits.size() <= 0) return NOERROR;
126  if (VERBOSE>=3) jout << eventnumber << " " << hits.size() << " ADC hits, " << tdc_hits.size() << " TDC hits" << endl;
127 
128  // first arrange the list of hits so they are grouped by cell
129  map<readout_channel, cellHits> cellHitMap;
130  for( vector<const DBCALHit*>::const_iterator hitPtr = hits.begin();
131  hitPtr != hits.end();
132  ++hitPtr ){
133 
134  const DBCALHit& hit = (**hitPtr);
135 
136  int id = dBCALGeom->cellId( hit.module, hit.layer, hit.sector );
137  readout_channel chan(id, hit.end);
138 
139  //this will create cellHitMap[chan] if it doesn't already exist
140  cellHitMap[chan].hits.push_back(*hitPtr);
141  }
142 
143  //add TDC hits to the same structure
144  for(vector<const DBCALTDCHit*>::const_iterator hitPtr = tdc_hits.begin();
145  hitPtr != tdc_hits.end();
146  ++hitPtr ){
147 
148  const DBCALTDCHit& hit = (**hitPtr);
149 
150  int id = dBCALGeom->cellId (hit.module, hit.layer, hit.sector );
151  readout_channel chan(id, hit.end);
152 
153  if( cellHitMap.find(chan) == cellHitMap.end() ){
154  cellHitMap[chan] = cellHits();
155  }
156 
157  cellHitMap[chan].tdc_hits.push_back(*hitPtr);
158  }
159 
160  // now go through this list cell by cell and creat a UnifiedHit if appropriate
161  for(map<readout_channel,cellHits>::const_iterator mapItr = cellHitMap.begin();
162  mapItr != cellHitMap.end();
163  ++mapItr) {
164 
165  readout_channel chan = mapItr->first;
166  int cellId = chan.cellId;
167  int module = dBCALGeom->module(cellId);
168  int layer = dBCALGeom->layer(cellId);
169  int sector = dBCALGeom->sector(cellId);
170 
171  const vector<const DBCALHit*> &hits = mapItr->second.hits;
172  const vector<const DBCALTDCHit*> &tdc_hits = mapItr->second.tdc_hits;
173 
174  //if we have no ADC hits in the cell, there is nothing to do with the TDC hits either
175  if (hits.size()==0) {
176  if (VERBOSE>=1) {
177  if (tdc_hits.size()!=0) {
178  static uint64_t Nwarnings = 0;
179  if(++Nwarnings <= 10) cout << "DBCALUnifiedHit_factory (event " << eventnumber << "): TDC hits without ADC hits" << endl;
180  if( Nwarnings == 10) cout << "DBCALUnifiedHit_factory: LAST WARNING (others will be suppressed)" <<endl;
181  }
182  }
183  continue;
184  }
185 
186  // Find the index of the earliest ADC hit.
187  unsigned int firstIndex = 0;
188  for(unsigned int i=1; i<hits.size(); i++){
189  if (hits[i]->t < hits[firstIndex]->t) firstIndex = i;
190  if (VERBOSE>=4 && hits.size()>=2) {
191  printf("DBCALUnifiedHit_factory event %5llu (%2i,%i,%i,%i) peak %4i, ADC %i %6.1f\n",
192  (unsigned long long int)eventnumber, module, layer, sector, chan.end, hits[i]->pulse_peak, i, hits[i]->t);
193  }
194  }
195 
196  const DBCALHit* hit=hits[firstIndex];
197  float pulse_peak, E, t, t_ADC, t_TDC=0; //these are values that will be assigned to the DBCALUnifiedHit
198  pulse_peak = hit->pulse_peak;
199  E = hit->E;
200  t_ADC = hit->t;
201 
202  // Loop through the TDC hits, apply timewalk correction and find the TDC time closest to the ADC time
203  int goodTDCindex=-1;
204  //timewalk_coefficients tdc_coeff = tdc_timewalk_map[chan];
205  timewalk_coefficients_c4 tdc_coeff;
206  bool good_timewalk_params = false;
207  if( tdc_timewalk_map_c4.find(chan) != tdc_timewalk_map_c4.end() ) {
208  // really we should probably print out some more errors here, if we can't find the timewalk correction factor
209  // but since we complain enough above, it is probably fine...
210  tdc_coeff = tdc_timewalk_map_c4[chan];
211  good_timewalk_params = true;
212  }
213  float t_diff=100000;
214  bool haveTDChit = false;
215  for (unsigned int i=0; i<tdc_hits.size(); i++) {
216  haveTDChit = true;
217  const DBCALTDCHit* tdc_hit=tdc_hits[i];
218  float tdc_hit_t = tdc_hit->t;
219 
220  if(good_timewalk_params) {
221  //tdc_hit_t -= tdc_coeff.c0 + tdc_coeff.c1/pow(pulse_peak/tdc_coeff.a_thresh, tdc_coeff.c2);
222  float shifted_peak = pulse_peak+tdc_coeff.c2; // only apply formula if time is above TDC zero
223  if (shifted_peak>0) tdc_hit_t -= tdc_coeff.c0 + tdc_coeff.c1*pow(shifted_peak,tdc_coeff.c3);
224  if (VERBOSE>=4) printf("tamewalk %f -> %f: (%f,%f,%f,%f)\n",tdc_hit->t,tdc_hit_t,tdc_coeff.c0,tdc_coeff.c1,tdc_coeff.c2,tdc_coeff.c3);
225  }
226 
227  float tdc_adc_diff = tdc_hit_t - t_ADC;
228  if (fabs(tdc_adc_diff) < fabs(t_diff)) {
229  goodTDCindex=i;
230  t_diff=tdc_adc_diff;
231  t_TDC=tdc_hit_t;
232  }
233  if (VERBOSE>=4 || (VERBOSE>=3&&tdc_hits.size()>1)) {
234  printf("DBCALUnifiedHit_factory event %5llu (%2i,%i,%i,%i) peak %4.0f, ADC 0 %6.1f, TDC %i %6.1f diff %6.1f best %2i %6.1f\n",
235  (unsigned long long int)eventnumber, module, layer, sector, chan.end, pulse_peak, t_ADC, i, tdc_hit_t, tdc_adc_diff, goodTDCindex, t_diff);
236  }
237  }
238  if (VERBOSE>=4 && !haveTDChit) {
239  // printf("DBCALUnifiedHit_factory event %5llu (%2i,%i,%i,%i) peak %4.0f, ADC 0 %6.1f, TDC diff best %2i %6.1f\n",
240  // (unsigned long long int)eventnumber, module, layer, sector, chan.end, pulse_peak, hit->t, goodTDCindex, t_diff);
241  printf("DBCALUnifiedHit_factory event %5llu (%2i,%i,%i,%i) peak %4.0f, ADC 0 %6.1f\n",
242  (unsigned long long int)eventnumber, module, layer, sector, chan.end, pulse_peak, hit->t);
243  }
244  // Decide whether to use TDC time
245  if (pulse_peak>tdc_coeff.thresh && USE_TDC==1 && goodTDCindex>=0 && fabs(t_diff)<2 && good_timewalk_params) {
246  t = t_TDC;
247  } else {
248  t = t_ADC;
249  }
250 
251  // Create the DBCALUnifiedHit
252  DBCALUnifiedHit *uhit = new DBCALUnifiedHit;
253  uhit->E = E;
254  uhit->t = t;
255  uhit->t_ADC = t_ADC;
256  uhit->t_TDC = t_TDC;
257  uhit->has_TDC_hit = haveTDChit;
258  uhit->cellId = cellId;
259  uhit->module = module;
260  uhit->layer = layer;
261  uhit->sector = sector;
262  uhit->end = chan.end;
263 
264  uhit->AddAssociatedObject(hit);
265  if (goodTDCindex>=0) uhit->AddAssociatedObject(tdc_hits[goodTDCindex]);
266 
267  _data.push_back(uhit);
268  } // end loop over cells
269 
270  return NOERROR;
271 }
float E
Definition: DBCALHit.h:30
Double_t c0[2][NMODULES]
Definition: tw_corr.C:67
float t_TDC
Time of TDC hit that is closes t to the ADC time.
Int_t layer
int module
Definition: DBCALHit.h:25
int layer
Definition: DBCALHit.h:26
Double_t c1[2][NMODULES]
Definition: tw_corr.C:68
DBCALGeometry::End end
Definition: DBCALHit.h:28
Double_t c2[2][NMODULES]
Definition: tw_corr.C:69
bool has_TDC_hit
Flag if the Unified Time is the TDC time.
const bool VERBOSE
static evioFileChannel * chan
float t_ADC
Time from fADC.
DBCALGeometry::End end
float t
Definition: DBCALHit.h:31
int sector
Definition: DBCALHit.h:27
int cellId
Definition: DBCALHit.h:34
jerror_t brun(jana::JEventLoop *eventLoop, int32_t runnumber)
Called everytime a new run number is detected.
int pulse_peak
Definition: DBCALHit.h:29
DBCALGeometry::End end
Definition: DBCALTDCHit.h:25
TCanvas * c3
printf("string=%s", string)
jerror_t evnt(JEventLoop *loop, uint64_t eventnumber)
float t
Unified time, obtained from ADC and/or TDC and used for further analysis.