Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
JEventProcessor_FCAL_online.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: JEventProcessor_FCAL_online.cc
4 // Created: Fri Nov 9 11:58:09 EST 2012
5 // Creator: wolin (on Linux stan.jlab.org 2.6.32-279.11.1.el6.x86_64 x86_64)
6 //
7 
8 #include <stdint.h>
9 #include <vector>
10 #include <iostream>
12 #include <JANA/JApplication.h>
13 
14 #include "FCAL/DFCALHit.h"
15 #include "FCAL/DFCALDigiHit.h"
16 #include "FCAL/DFCALGeometry.h"
17 #include "FCAL/DFCALCluster.h"
18 #include "FCAL/DFCALShower.h"
19 #include "DAQ/Df250PulseIntegral.h"
20 #include "DAQ/Df250PulsePedestal.h"
21 #include "DAQ/Df250PulseData.h"
22 #include "units.h"
23 #include "DLorentzVector.h"
24 #include "DVector3.h"
25 #include "HDGEOMETRY/DGeometry.h"
26 #include "DANA/DApplication.h"
27 #include "DANA/DStatusBits.h"
28 #include "TRIGGER/DL1Trigger.h"
29 
30 #include <TDirectory.h>
31 #include <TH2F.h>
32 #include <TH1I.h>
33 #include <TH2I.h>
34 #include <TProfile.h>
35 #include <TProfile2D.h>
36 
37 using namespace std;
38 using namespace jana;
39 
40 
41 //----------------------------------------------------------------------------------
42 
43 
44 // Routine used to create our JEventProcessor
45 extern "C"{
46  void InitPlugin(JApplication *app){
47  InitJANAPlugin(app);
48  app->AddProcessor(new JEventProcessor_FCAL_online());
49  }
50 }
51 
52 
53 //----------------------------------------------------------------------------------
54 
55 
57 }
58 
59 
60 //----------------------------------------------------------------------------------
61 
62 
64 }
65 
66 
67 //----------------------------------------------------------------------------------
68 
70 
71  // create root folder for fcal and cd to it, store main dir
72  TDirectory *main = gDirectory;
73  gDirectory->mkdir("fcal")->cd();
74 
75  //
76  // these with "dig" use raw channel-level output of the FADC
77  //
78  fcal_num_events = new TH1D("fcal_num_events","FCAL number of events",1, 0.5, 1.5);
79 
80  m_digInt = new TH1I( "digHitE", "FCAL Raw Pulse Integral; Integral [2 V * 4 ns / 4096]; Pulses / ( 100 * 2 V * 4 ns / 4096 )", 300, 0, 30000 );
81  m_digCoarseT = new TH1I( "digCoarseTime", "FCAL Raw Pulse Coarse Time; Time [4 ns]; Pulses / 4 ns", 100, 0, 100 );
82 
83  m_digCoarseTChan = new TProfile( "digCoarseTChan", "FCAL Coarse Time vs. Channel; Channel Index; Average Time [4 ns]",
84  2800,-0.5, 2799.5 );
85  m_digPreciseT = new TH1I( "digPreciseT", "FCAL Raw Pulse Precise Time; Time [62.5 ps]; Pulses / 62.5 ps", 64, -0.5, 63.5 );
86  m_digPreciseTChan = new TProfile( "digPreciseTChan", "FCAL Precise Time vs. Channel; Channel Index; Average Time [62.5 ps]",
87  2800,-0.5, 2799.5 );
88  m_digT = new TH1I( "digT", "FCAL Pulse Time; t [62.5 ps]; Pulses / 625 ps", 500, 0, 5000 );
89  m_digT0 = new TH1I( "digT0", "FCAL Pulse Energy Weighted Average Time; t_{0} [62.5 ps]; Events / 625 ps", 500, 0, 5000 );
90  m_digTmT0 = new TH1I( "digTmT0", "FCAL Pulse Local Time; t - t_{0} [62.5 ps]; Pulses / 625 ps", 200, -1000, 1000 );
91  m_digTmT02D = new TH2F( "digTmT02D", "FCAL Pulse Local Time [62.5 ps]; column; row", 61, -1.5, 59.5, 61, -1.5, 59.5 );
92  m_digPed = new TH1I( "digPed", "FCAL Pedestal (All Channels); ADC Counts; Pules / 10 Counts", 100, 0, 1000 );
93  m_digPedChan = new TProfile( "digPedChan", "FCAL Pedestal vs. Channel; Channel Index; Average Pedestal [ADC Counts]", 2800,-0.5,2799.5 );
94  m_digPed2D = new TH2F( "digPed2D", "FCAL Pedestal [ADC Counts]; column; row", 61, -1.5, 59.5, 61, -1.5, 59.5 );
95  m_digPedSq2D = new TH2F( "digPedSq2D", "FCAL Pedestal^{2} [ADC Counts^{2}]; column; row", 61, -1.5, 59.5, 61, -1.5, 59.5 );
96  m_digQual = new TH1I( "digQual", "FCAL Hit Quality; Quality Factor Index; Number of Pulses", 16, -0.5, 15.5 );
97  m_digNUnder = new TH1I( "digNUnder", "FCAL Number of Underflows per Event; Number of Underflows; Events / 1",
98  100, -0.5, 99.5 );
99  m_digNOver = new TH1I( "digNOver", "FCAL Number of Overflows per Event; Number of Overflows; Events / 1",
100  100, -0.5, 99.5 );
101  m_digN = new TH1I( "digN", "FCAL Number of Raw Hits per Event; Number of Hits; Events / 5", 600, 0, 3000 );
102  m_digPeakV = new TH1I( "digPeakV", "FCAL Pulse Peak; Peak Sample [Volts]; Pulses / 10 mV", 210, 0, 2.1 );
103  m_digPeakV2D = new TProfile2D( "digPeakV2D", "FCAL Pulse Peak [Volts]; column; row", 61, -1.5, 59.5, 61, -1.5, 59.5 );
104  m_digOcc2D = new TH2F( "digOcc2D", "FCAL Pulse Occupancy; column; row", 61, -1.5, 59.5, 61, -1.5, 59.5 );
105  m_digIntVsPeak = new TH2I( "digIntVsPeak", "FCAL Pulse Integral vs. Peak Sample; Peak Sample [ADC Units]; Integral [ADC Units]", 200, 0, 4000, 200, 0, 40000 );
106  m_digIntToPeak = new TH1I( "digIntToPeak", "Pedestal Subtracted Integral to Peak Ratio (Peak > 200); Ratio; Pulses / 0.1", 200, 0, 20 );
107 
108  //
109  // these with "hit" are block level plots after calibration
110  //
111 
112  m_hitN = new TH1I( "hitN", "FCAL Number of Hits; Number of Hits; Events / 5 Hits", 600, 0, 3000 );
113  m_hitE = new TH1I( "hitE", "FCAL Hit Energy; Energy [MeV]; Hits / 100 MeV", 100, 0, 10000 );
114  m_hitETot = new TH1I( "hitETot", "FCAL Hit Total Energy; Energy [MeV]; Events / 100 MeV", 100, 0, 10000 );
115  m_hitT = new TH1I( "hitT", "FCAL Hit Time; t [ns]; Hits / 4 ns", 100, 0, 400 );
116  m_hitT0 = new TH1I( "hitT0", "FCAL Hit Energy Weighted Average Time; t_{0} [ns]; Events / 4 ns", 100, 0, 400 );
117  m_hitTmT0 = new TH1I( "hitTmT0", "FCAL Hit Local Time; t-t_{0} [ns]; Hits / 0.4 ns", 100, -20, 20 );
118  m_hitE2D = new TH2F( "hitE2D", "FCAL Hit Average Energy [MeV]; column; row", 61, -1.5, 59.5, 61, -1.5, 59.5 );
119  m_hitTmT02D = new TH2F( "hitTmT02D", "FCAL Hit Local Time [ns]; column; row", 61, -1.5, 59.5, 61, -1.5, 59.5 );
120  m_hitTmT0Sq2D = new TH2F( "hitTmT0Sq2D", "FCAL Hit Local Time^{2} [ns^{2}]; column; row", 61, -1.5, 59.5, 61, -1.5, 59.5 );
121  m_hitOcc2D = new TH2F( "hitOcc2D", "FCAL Hit Occupancy; column; row", 61, -1.5, 59.5, 61, -1.5, 59.5 );
122 
123  //
124  // these with "clus" are after clusterization
125  //
126 
127  m_clusN = new TH1I( "clusN", "FCAL Number of Clusters; Number of Clusters; Events", 40, -0.5, 39.5 );
128  m_clusE = new TH1I( "clusE", "FCAL Cluster Energy; Energy [MeV]; Clusters / 50 MeV", 100, 0, 15000 );
129  m_clusETot = new TH1I( "clusETot", "FCAL Cluster Total Energy; Energy [MeV]; Events / 100 MeV", 100, 0, 15000 );
130  m_clusT = new TH1I( "clusT", "FCAL Cluster Time; t [ns]; Clusters / 4 ns", 100, 0, 400 );
131  m_clusT0 = new TH1I( "clusT0", "FCAL Cluster Energy Weighted Average Time; t_{0} [ns]; Events / 4 ns]", 100, 0, 400 );
132  m_clusTmT0 = new TH1I( "clusTmT0", "FCAL Cluster Local Time; t - t_{0} [ns]; Clusters / 0.8 ns", 100, -40, 40 );
133  m_clusXYHigh = new TH2I( "clusXYHigh", "FCAL Cluster Positions (E > 200 MeV); x [cm]; y [cm]", 100, -150, 150, 100, -150, 150 );
134  m_clusXYLow = new TH2I( "clusXYLow", "FCAL Cluster Positions (E < 200 MeV); x [cm]; y [cm]", 100, -150, 150, 100, -150, 150 );
135  m_clusPhi = new TH1I( "clusPhi", "FCAL Cluster #phi; #phi [rad]; Clusters / 62.8 mrad", 100, -3.14, 3.14 );
136  m_clusPhi->SetMinimum( 0 );
137  m_clus2GMass = new TH1I( "clus2GMass", "FCAL 2 Cluster Invariant Mass E > 1 GeV; Invariant Mass [GeV]", 500, 0.0, 0.6 );
138 
139  //
140  // these with "show" are after energy dependent non-linear correction
141  //
142 
143  m_show2GMass = new TH1I( "show2GMass", "FCAL 2 Shower Invariant Mass E > 1 GeV; Invariant Mass [GeV]", 500, 0.0, 1.0 );
144  m_showZvsE = new TH2I( "showZvsE", "FCAL z_{shower} vs. E_{shower}; E_{shower} [GeV]; z_{shower} [cm]", 120, 0.0, 6.0, 120, 620, 680 );
145  m_showECorVsE = new TH2I( "showECorVsE", "FCAL E_{shower}/E_{cluster} vs. E_{shower}; E_{shower} [GeV]; E_{shower}/E_{cluster}", 200, 0.0, 6.0, 200, 0.0, 2.0 );
146  m_showTsMTcVsZ = new TH2I( "showTsMTcVsZ", "FCAL t_{shower} - t_{cluster} vs. z_{shower}; z_{shower} cm; t_{shower} - t_{cluster} [ns]", 120, 620, 680, 120, -6, 6 );
147 
148  // back to main dir
149  main->cd();
150 
151  return NOERROR;
152 }
153 
154 
155 //----------------------------------------------------------------------------------
156 
157 
158 jerror_t JEventProcessor_FCAL_online::brun(JEventLoop *eventLoop, int32_t runnumber) {
159  // This is called whenever the run number changes
160 
161  DGeometry *dgeom = NULL;
162  DApplication *dapp = dynamic_cast< DApplication* >( eventLoop->GetJApplication() );
163  if( dapp ) dgeom = dapp->GetDGeometry( runnumber );
164 
165  if( dgeom ){
166 
167  dgeom->GetTargetZ( m_targetZ );
168 
169  }
170  else{
171 
172  cerr << "No geometry accessbile to FCAL_online monitoring plugin." << endl;
173  return RESOURCE_UNAVAILABLE;
174  }
175 
176  return NOERROR;
177 }
178 
179 
180 //----------------------------------------------------------------------------------
181 
182 
183 jerror_t JEventProcessor_FCAL_online::evnt(JEventLoop *eventLoop, uint64_t eventnumber) {
184 
185  vector< const DFCALGeometry* > geomVec;
186  vector< const DFCALDigiHit* > digiHits;
187  vector< const DFCALHit* > hits;
188  vector< const DFCALCluster* > clusterVec;
189  vector< const DFCALShower* > showerVec;
190 
191  // First check that this is not a font panel trigger or no trigger
192  bool goodtrigger=1;
193 
194  const DL1Trigger *trig = NULL;
195  try {
196  eventLoop->GetSingle(trig);
197  } catch (...) {}
198  if (trig) {
199  if (trig->fp_trig_mask){
200  goodtrigger=0;
201  }
202  } else {
203  // HDDM files are from simulation, so keep them even though they have no trigger
204  bool locIsHDDMEvent = eventLoop->GetJEvent().GetStatusBit(kSTATUS_HDDM);
205  if (!locIsHDDMEvent) goodtrigger=0;
206  }
207 
208  if (!goodtrigger) {
209  return NOERROR;
210  }
211 
212 
213  eventLoop->Get( geomVec );
214  eventLoop->Get( digiHits );
215  eventLoop->Get( hits );
216  if( hits.size() <= 500 ){ // only form clusters and showers if there aren't too many hits
217  eventLoop->Get( clusterVec );
218  eventLoop->Get( showerVec );
219  }
220 
221  const DFCALGeometry& fcalGeom = *(geomVec[0]);
222 
223  //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
224 
225  //
226  // extract and fill histograms for raw block level
227  // hits -- this should be very fast
228  //
229 
230  // loop through the hits and find the integral-weighted
231  // average time for this event -- this is like a
232  // local t0 for the FCAL and will be useful
233  // for looking at timing variances as there is no
234  // absolute time in actual events
235 
236  double totIntegral = 0;
237  double intWeightTime = 0;
238 
239  // while doing this, we find the Df250PulseIntegral and Df250PulsePedestal
240  // objects (if any) associated with each hit and store them in a map.
241  // This is done here since it is outside of the ROOT lock. It turns out
242  // that the GetSingle calls use dynamic_cast and are therefore raher
243  // expensive causing significant performance degredation if done inside
244  // the lock. This will eventually be fixed in JANA, but for now we implement
245  // this caching solution to make multi-threading efficient. 3/4/2015 DL
246  map< const DFCALDigiHit*, pair<const Df250PulseIntegral*, const Df250PulsePedestal*> > pi_pp_cache;
247  map< const DFCALDigiHit*, const Df250PulseData* > pd_cache;
248 
249  for( vector< const DFCALDigiHit* >::const_iterator dHitItr = digiHits.begin();
250  dHitItr != digiHits.end(); ++dHitItr ){
251 
252  totIntegral += (**dHitItr).pulse_integral;
253  intWeightTime += (**dHitItr).pulse_integral * (**dHitItr).pulse_time;
254 
255  // fetch lower level FADC data
256  const Df250PulseIntegral* pulseInt = NULL;
257  const Df250PulsePedestal* pulsePed = NULL;
258  const Df250PulseData* pulseDat = NULL;
259 
260  const DFCALDigiHit& dHit = (**dHitItr);
261  dHit.GetSingle( pulseInt );
262  if( pulseInt ) pulseInt->GetSingle( pulsePed );
263  dHit.GetSingle( pulseDat );
264 
265  pi_pp_cache[&dHit] = pair<const Df250PulseIntegral*, const Df250PulsePedestal*>(pulseInt, pulsePed);
266  pd_cache[&dHit] = pulseDat;
267  }
268 
269  intWeightTime /= totIntegral;
270 
271  int nOverflow = 0;
272 
273  //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
274 
275  // first find and energy weighted average time
276  // for the hits in this event -- we'll use this
277  // as a t0 later
278 
279  double hitETot = 0;
280  double hitEwtT = 0;
281 
282  for( vector< const DFCALHit* >::const_iterator hit_itr = hits.begin();
283  hit_itr != hits.end(); ++hit_itr ){
284 
285  hitETot += (**hit_itr).E;
286  hitEwtT += (**hit_itr).E * (**hit_itr).t;
287  }
288 
289  hitEwtT /= hitETot;
290 
291  //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
292 
293  double clusETot = 0;
294  double clusEwtT = 0;
295 
296  for( vector< const DFCALCluster*>::const_iterator clusItr = clusterVec.begin();
297  clusItr != clusterVec.end(); ++clusItr ){
298 
299  clusETot += (**clusItr).getEnergy();
300  clusEwtT += (**clusItr).getEnergy() * (**clusItr).getTime();
301  }
302 
303  clusEwtT /= clusETot;
304 
305  //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
306 
307  // FILL HISTOGRAMS
308  // Since we are filling histograms local to this plugin, it will not interfere with other ROOT operations: can use plugin-wide ROOT fill lock
309  japp->RootFillLock(this); //ACQUIRE ROOT FILL LOCK
310 
311  if( digiHits.size() > 0 )
312  fcal_num_events->Fill(1);
313 
314  m_digT0->Fill( intWeightTime );
315  m_digN->Fill( digiHits.size() );
316 
317  //std::cout << "Number of blocks hit: " << digiHits.size() << endl;
318 
319 
320  for( vector< const DFCALDigiHit* >::const_iterator dHitItr = digiHits.begin();
321  dHitItr != digiHits.end(); ++dHitItr ){
322 
323  const DFCALDigiHit& dHit = (**dHitItr);
324 
325 
326  int chan = fcalGeom.channel( dHit.row, dHit.column );
327 
328  m_digOcc2D->Fill( dHit.column, dHit.row );
329 
330  // fetch lower level FADC data
331  pair<const Df250PulseIntegral*, const Df250PulsePedestal*> &pulseX = pi_pp_cache[&dHit];
332  const Df250PulseIntegral* pulseInt = pulseX.first;
333  const Df250PulsePedestal* pulsePed = pulseX.second;
334  const Df250PulseData* pulseDat = pd_cache[&dHit];
335 
336  // dHit.GetSingle( pulseInt );
337  // if( pulseInt ) pulseInt->GetSingle( pulsePed );
338 
339  if( pulseDat || (pulseInt && pulsePed) ){
340 
341  double pulse_peak, pulse_integral, pedestal, nsamples_integral, nsamples_pedestal;
342  if(pulseDat) {
343  // post-Fall 2016 firmware
344  pulse_peak = pulseDat->pulse_peak;
345  pulse_integral = pulseDat->integral;
346  pedestal = pulseDat->pedestal;
347  nsamples_integral = pulseDat->nsamples_integral;
348  nsamples_pedestal = pulseDat->nsamples_pedestal;
349  } else {
350  // pre-Fall 2016 firmware
351  pulse_peak = pulsePed->pulse_peak;
352  pulse_integral = pulseInt->integral;
353  pedestal = pulseInt->pedestal;
354  nsamples_integral = pulseInt->nsamples_integral;
355  nsamples_pedestal = 1;
356  }
357 
358  double peakV = pulse_peak * 2.0 / 4096;
359 
360  m_digPeakV->Fill( peakV );
361  m_digPeakV2D->Fill( dHit.column, dHit.row, peakV );
362 
363  // overflows should be tagged at a lower level this
364  // is an imperfect way of trying to detect them as
365  // "pulse_peak" is defined as the first sample for
366  // which the subsequent sample is a lower amplitude
367  if( pulse_peak == 4096 ) ++nOverflow;
368 
369  m_digIntVsPeak->Fill( pulse_peak, pulse_integral );
370 
371  double integral = (double)( pulse_integral -
372  ( pedestal *
373  nsamples_integral/nsamples_pedestal ) );
374  double peak = (double)( pulse_peak - pedestal/nsamples_pedestal );
375 
376  if( pulse_peak > 300 )
377  m_digIntToPeak->Fill( integral / peak );
378  }
379 
380  // pulse_time is a 15-bit int - the lower six bits are
381  // a precision time determined by a separate algorithm
382  // from the upper 9 bits: track each separately
383 
384  int coarseT = dHit.pulse_time >> 6;
385  int preciseT = dHit.pulse_time & 0x3F;
386 
387  m_digInt->Fill( dHit.pulse_integral );
388  m_digT->Fill( dHit.pulse_time );
389  if( digiHits.size() > 0 )
390  m_digTmT0->Fill( dHit.pulse_time - intWeightTime );
391  m_digTmT02D->Fill( dHit.column, dHit.row, dHit.pulse_time - intWeightTime );
392  m_digCoarseT->Fill( coarseT );
393  m_digCoarseTChan->Fill( chan, coarseT );
394  m_digPreciseT->Fill( preciseT );
395  m_digPreciseTChan->Fill( chan, preciseT );
396  m_digPed->Fill( dHit.pedestal );
397  m_digPedChan->Fill( chan, dHit.pedestal );
398  m_digPed2D->Fill( dHit.column, dHit.row, dHit.pedestal );
399  m_digPedSq2D->Fill( dHit.column, dHit.row, dHit.pedestal*dHit.pedestal );
400  m_digQual->Fill( dHit.QF );
401  }
402  m_digNOver->Fill( nOverflow );
403 
404 // japp->RootFillUnLock(this); //RELEASE ROOT FILL LOCK
405 
406  // end of raw hit filling
407 
408  //
409  // extract and fill histograms for calibrated block
410  // level hits -- this should also be fast
411  //
412 
413 
414  // now fill histograms
415 
416 // japp->RootFillLock(this); //ACQUIRE ROOT FILL LOCK
417 
418  m_hitETot->Fill( hitETot*k_to_MeV );
419  m_hitT0->Fill( hitEwtT );
420 
421  m_hitN->Fill( hits.size() );
422  for( vector< const DFCALHit* >::const_iterator hit_itr = hits.begin();
423  hit_itr != hits.end(); ++hit_itr ){
424 
425  const DFCALHit& hit = (**hit_itr);
426 
427  double locTime = ( hit.t - hitEwtT )*k_to_nsec;
428 
429  m_hitE->Fill( hit.E*k_to_MeV );
430  m_hitT->Fill( hit.t*k_to_nsec );
431 
432  if( hits.size() > 1 )
433  m_hitTmT0->Fill( locTime );
434 
435  if (fabs(locTime) < 20){
436  m_hitTmT02D->Fill( hit.column, hit.row, locTime );
437  m_hitTmT0Sq2D->Fill( hit.column, hit.row, locTime*locTime );
438  m_hitOcc2D->Fill( hit.column, hit.row );
439  }
440 
441  m_hitE2D->Fill( hit.column, hit.row, hit.E*k_to_MeV );
442  }
443 
444 // japp->RootFillUnLock(this); //RELEASE ROOT FILL LOCK
445 
446  // end calibrated block-level filling
447 
448  // for events with a lot of hits -- stop now
449  if( hits.size() > 500 ){
450  japp->RootFillUnLock(this); //RELEASE ROOT FILL LOCK
451  return NOERROR;
452  }
453 
454  //
455  // if there are a small number of hits go ahead
456  // and run the clusterizer and make a few plots
457  // utilizing the list of clusters and showers
458  //
459 
460 
461 
462 
463 // japp->RootFillLock(this); //ACQUIRE ROOT FILL LOCK
464 
465  m_clusN->Fill( clusterVec.size() );
466 
467  if( clusterVec.size() > 0 ){
468 
469  m_clusT0->Fill( clusEwtT );
470  m_clusETot->Fill( clusETot * k_to_MeV );
471  }
472 
473  for( vector< const DFCALCluster*>::const_iterator clusItr = clusterVec.begin();
474  clusItr != clusterVec.end(); ++clusItr ){
475 
476  const DFCALCluster& cluster = (**clusItr);
477 
478  double clusX = cluster.getCentroid().X();
479  double clusY = cluster.getCentroid().Y();
480 
481  double clusR = sqrt( clusX * clusX + clusY * clusY );
482 
483  DVector3 clus1Mom = cluster.getCentroid();
484  clus1Mom.SetMag( cluster.getEnergy() );
485 
486  m_clusPhi->Fill( clus1Mom.Phi() );
487  m_clusE->Fill( cluster.getEnergy() * k_to_MeV );
488  m_clusT->Fill( cluster.getTime() );
489 
490  if( clusterVec.size() > 1 )
491  m_clusTmT0->Fill( cluster.getTime() - clusEwtT );
492 
493  if( cluster.getEnergy() > 200*k_MeV ){
494 
495  m_clusXYHigh->Fill( cluster.getCentroid().X(),
496  cluster.getCentroid().Y() );
497  }
498  else{
499 
500  m_clusXYLow->Fill( cluster.getCentroid().X(),
501  cluster.getCentroid().Y() );
502  }
503 
504  if( ( cluster.getEnergy() < 1*k_GeV ) ||
505  ( clusR < 20*k_cm ) ||
506  ( cluster.GetNHits() < 2 )
507  ) continue;
508 
509  for( vector< const DFCALCluster*>::const_iterator clus2Itr = clusItr + 1;
510  clus2Itr != clusterVec.end(); ++clus2Itr ){
511 
512  const DFCALCluster& cluster2 = (**clus2Itr);
513 
514  double clus2X = cluster2.getCentroid().X();
515  double clus2Y = cluster2.getCentroid().Y();
516 
517  double clus2R = sqrt( clus2X * clus2X + clus2Y * clus2Y );
518 
519  // only make the 2-cluster invariant mass plot for
520  // cases where both clusters are greater than 200 MeV
521  // in energy
522 
523  if( ( cluster2.getEnergy() < 1*k_GeV ) ||
524  ( clus2R < 20*k_cm ) ||
525  ( cluster2.GetNHits() < 2 )
526  ) continue;
527 
528  if( fabs( cluster.getTime() - cluster2.getTime() ) > 10*k_nsec ) continue;
529 
530  DVector3 clus2Mom = cluster2.getCentroid();
531  clus2Mom.SetMag( cluster2.getEnergy() );
532 
533  DLorentzVector gam1( clus1Mom, clus1Mom.Mag() );
534  DLorentzVector gam2( clus2Mom, clus2Mom.Mag() );
535 
536  m_clus2GMass->Fill( ( gam1 + gam2 ).M() );
537  }
538  }
539 // japp->RootFillUnLock(this); //RELEASE ROOT FILL LOCK
540 
541  // end cluster lever filling
542 
543  // now do shower filling -- these are clusters that have
544  // had timing, position, and nonlinear energy corrections
545  // applied on a cluster level
546 
547 
548 // japp->RootFillLock(this); //ACQUIRE ROOT FILL LOCK
549 
550  for( vector< const DFCALShower* >::const_iterator showItr = showerVec.begin();
551  showItr != showerVec.end(); ++showItr ){
552 
553  const DFCALShower& show = (**showItr);
554 
555  const DFCALCluster* clus = NULL;
556  show.GetSingle( clus );
557  if( clus == NULL ) continue;
558 
559  DVector3 clusMom = clus->getCentroid();
560  clusMom.SetZ( clusMom.Z() - m_targetZ );
561  clusMom.SetMag( clus->getEnergy() );
562 
563  DVector3 showMom = show.getPosition();
564  showMom.SetZ( showMom.Z() - m_targetZ );
565  showMom.SetMag( show.getEnergy() );
566 
567  m_showZvsE->Fill( show.getEnergy(), show.getPosition().Z() );
568  m_showECorVsE->Fill( show.getEnergy(), show.getEnergy() / clus->getEnergy() );
569  m_showTsMTcVsZ->Fill( show.getPosition().Z(), show.getTime() - clus->getTime() );
570 
571  if( ( show.getEnergy() < 1*k_GeV ) ||
572  ( show.getPosition().Pt() < 20*k_cm ) ) continue;
573 
574  for( vector< const DFCALShower* >::const_iterator show2Itr = showItr + 1;
575  show2Itr != showerVec.end(); ++show2Itr ){
576 
577  const DFCALShower& show2 = (**show2Itr);
578 
579  // only make the 2-shower invariant mass plot for
580  // cases where both showers are greater than 200 MeV
581  // in energy
582 
583  if( ( show2.getEnergy() < 1*k_GeV ) ||
584  ( show2.getPosition().Pt() < 20*k_cm ) ) continue;
585 
586  DVector3 show2Mom = show2.getPosition();
587  show2Mom.SetZ( show2Mom.Z() - m_targetZ );
588  show2Mom.SetMag( show2.getEnergy() );
589 
590  DLorentzVector gam1( showMom, showMom.Mag() );
591  DLorentzVector gam2( show2Mom, show2Mom.Mag() );
592 
593  m_show2GMass->Fill( ( gam1 + gam2 ).M() );
594  }
595 
596 
597  }
598  japp->RootFillUnLock(this); //RELEASE ROOT FILL LOCK
599  return NOERROR;
600 }
601 
602 
603 //----------------------------------------------------------------------------------
604 
605 
607  // This is called whenever the run number changes, before it is
608  // changed to give you a chance to clean up before processing
609  // events from the next run number.
610  return NOERROR;
611 }
612 
613 
614 //----------------------------------------------------------------------------------
615 
616 
618  // Called before program exit after event processing is finished.
619  return NOERROR;
620 }
621 
622 
623 //----------------------------------------------------------------------------------
624 //----------------------------------------------------------------------------------
uint32_t QF
Quality Factor from FPGA algorithms.
Definition: DFCALDigiHit.h:23
DVector3 getCentroid() const
Definition: DFCALCluster.h:183
double getEnergy() const
Definition: DFCALShower.h:156
DApplication * dapp
const double k_MeV
Definition: units.h:44
TVector3 DVector3
Definition: DVector3.h:14
uint32_t fp_trig_mask
Definition: DL1Trigger.h:19
double getTime() const
Definition: DFCALShower.h:161
double getTime() const
Definition: DFCALCluster.h:165
uint32_t nsamples_integral
number of samples used in integral
TLorentzVector DLorentzVector
trig[33-1]
uint32_t pulse_time
identified pulse time as returned by FPGA algorithm
Definition: DFCALDigiHit.h:21
uint32_t pulse_peak
from Pulse Pedestal Data word
jerror_t init(void)
Called once at program start.
JApplication * japp
const double k_to_MeV
Definition: units.h:48
uint32_t pedestal
pedestal info used by FPGA (if any)
Definition: DFCALDigiHit.h:22
double getEnergy() const
Definition: DFCALCluster.h:155
jerror_t fini(void)
Called after last event of last event source has been processed.
const double k_cm
Definition: units.h:14
const double k_GeV
Definition: units.h:43
uint32_t integral
InitPlugin_t InitPlugin
uint32_t nsamples_integral
number of samples used in integral
uint32_t pedestal
jerror_t erun(void)
Called everytime run number changes, provided brun has been called.
int row
Definition: DFCALHit.h:23
uint32_t GetNHits(void) const
Definition: DFCALCluster.h:85
static evioFileChannel * chan
DGeometry * GetDGeometry(unsigned int run_number)
uint32_t pulse_integral
identified pulse integral as returned by FPGA algorithm
Definition: DFCALDigiHit.h:20
double sqrt(double)
int channel(int row, int column) const
uint32_t integral
from Pulse Integral Data word
uint32_t pedestal
from Pulse Integral Data word (future)
const double k_nsec
Definition: units.h:67
const double k_to_nsec
Definition: units.h:72
uint32_t pulse_peak
uint32_t nsamples_pedestal
number of samples used in pedestal
static TH1I * pedestal[nChan]
float E
Definition: DFCALHit.h:27
float t
Definition: DFCALHit.h:28
int column
Definition: DFCALHit.h:24
DVector3 getPosition() const
Definition: DFCALShower.h:151
bool GetTargetZ(double &z_target) const
z-location of center of target
Definition: DGeometry.cc:1933
int main(int argc, char *argv[])
Definition: gendoc.cc:6
jerror_t evnt(jana::JEventLoop *eventLoop, uint64_t eventnumber)
Called every event.
jerror_t brun(jana::JEventLoop *eventLoop, int32_t runnumber)
Called everytime a new run number is detected.