Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DFDCPseudo_factory.cc
Go to the documentation of this file.
1 //********************************************************
2 // DFDCPseudo_factory.cc - factory producing first-order
3 // reconstructed points for the FDC
4 // Author: Craig Bookwalter (craigb at jlab.org)
5 // Date: March 2006
6 // UVX cathode-wire matching revised by Simon Taylor, Aug 2006
7 //********************************************************
8 
9 #include "DFDCPseudo_factory.h"
10 #include "HDGEOMETRY/DGeometry.h"
11 #include "DFDCGeometry.h"
13 #include <TROOT.h>
14 #include <FDC/DFDCCathodeDigiHit.h>
15 
16 #define HALF_CELL 0.5
17 #define MAX_DEFLECTION 0.15
18 #define X0 0
19 #define QA 1
20 #define K2 2
21 #define ITER_MAX 100
22 #define TOLX 1e-4
23 #define TOLF 1e-4
24 #define A_OVER_H 0.4
25 #define ONE_OVER_H 2.0
26 #define ALPHA 1e-4 // rate parameter for Newton step backtracking algorithm
27 #define W_EFF 30.2e-9 // GeV
28 #define GAS_GAIN 8e4
29 #define ELECTRON_CHARGE 1.6022e-4 // fC
30 
31 
32 ///
33 /// DFDCAnode_gLayer_cmp():
34 /// non-member function passed to std::sort() to sort DFDCHit pointers
35 /// for the anode wires by their gLayer attributes.
36 ///
37 bool DFDCAnode_gLayer_cmp(const DFDCHit* a, const DFDCHit* b) {
38  return a->gLayer < b->gLayer;
39 }
40 
41 bool static fdcxhit_cmp(const DFDCHit *a, const DFDCHit *b){
42  if (a->element != b->element) return (a->element < b->element);
43  return (a->t < b->t);
44 }
45 
46 
47 bool DFDCPseudo_cmp(const DFDCPseudo* a, const DFDCPseudo *b){
48  if (a->wire->wire == b->wire->wire && a->wire->layer==b->wire->layer){
49  return a->time<b->time;
50  }
51  if (a->wire->layer!=b->wire->layer) return a->wire->layer<b->wire->layer;
52 
53  return a->wire->wire<b->wire->wire;
54 }
55 
56 
57 
58 
59 ///
60 /// DFDCPseudo_factory::DFDCPseudo_factory():
61 /// default constructor -- initializes log file
62 ///
64  //_log = new JStreamLog(std::cout, "FDC PSEUDO >>");
65  //*_log << "File initialized." << endMsg;
66 }
67 
68 ///
69 /// DFDCPseudo_factory::~DFDCPseudo_factory():
70 /// default destructor -- closes log file
71 ///
73  if (fdcwires.size()){
74  for (unsigned int i=0;i<fdcwires.size();i++){
75  for (unsigned int j=0;j<fdcwires[i].size();j++){
76  delete fdcwires[i][j];
77  }
78  }
79  }
80  if (fdccathodes.size()){
81  for (unsigned int i=0;i<fdccathodes.size();i++){
82  for (unsigned int j=0;j<fdccathodes[i].size();j++){
83  delete fdccathodes[i][j];
84  }
85  }
86  }
87  //delete _log;
88 }
89 
90 //------------------
91 // init
92 //------------------
94 {
95  RIN_FIDUCIAL = 1.5;
96  ROUT_FIDUCIAL=48.0;
100  CHARGE_THRESHOLD=0.3;
101  DELTA_X_CUT=0.5;
102 
105 
106  gPARMS->SetDefaultParameter("FDC:ROUT_FIDUCIAL",ROUT_FIDUCIAL, "Outer fiducial radius of FDC in cm");
107  gPARMS->SetDefaultParameter("FDC:RIN_FIDUCIAL",RIN_FIDUCIAL, "Inner fiducial radius of FDC in cm");
108  gPARMS->SetDefaultParameter("FDC:MAX_ALLOWED_FDC_HITS",MAX_ALLOWED_FDC_HITS, "Max. number of FDC hits (includes both cathode strips and wires hits) to allow before considering event too busy to attempt FDC tracking");
109  gPARMS->SetDefaultParameter("FDC:STRIP_ANODE_TIME_CUT",STRIP_ANODE_TIME_CUT, "maximum time difference between strips and wires (in ns)");
110  gPARMS->SetDefaultParameter("FDC:CHARGE_THRESHOLD",CHARGE_THRESHOLD,"Minimum average charge on both cathode planes (in pC)");
111  gPARMS->SetDefaultParameter("FDC:DELTA_X_CUT",DELTA_X_CUT,"Maximum distance between reconstructed wire position and wire position");
112 
113  DEBUG_HISTS = false;
114  gPARMS->SetDefaultParameter("FDC:DEBUG_HISTS",DEBUG_HISTS);
115 
116 
117  return NOERROR;
118 }
119 
120 
121 //------------------
122 // brun
123 //------------------
124 jerror_t DFDCPseudo_factory::brun(JEventLoop *loop, int32_t runnumber)
125 {
126  // Get pointer to DGeometry object
127  DApplication* dapp=dynamic_cast<DApplication*>(eventLoop->GetJApplication());
128  const DGeometry *dgeom = dapp->GetDGeometry(runnumber);
129 
130  USE_FDC=true;
131  if (!dgeom->GetFDCWires(fdcwires)){
132  _DBG_<< "FDC geometry not available!" <<endl;
133  USE_FDC=false;
134  }
135  if (!dgeom->GetFDCCathodes(fdccathodes)){
136  _DBG_<< "FDC geometry not available!" <<endl;
137  USE_FDC=false;
138  }
139  if (USE_FDC){
140  // Get package offsets
141  vector<double>offsets;
142  dgeom->Get("//posXYZ[@volume='forwardDC_package_1']/@X_Y_Z",offsets);
143  dX[0]=offsets[0];
144  dY[0]=offsets[1];
145  dgeom->Get("//posXYZ[@volume='forwardDC_package_2']/@X_Y_Z",offsets);
146  dX[1]=offsets[0];
147  dY[1]=offsets[1];
148  dgeom->Get("//posXYZ[@volume='forwardDC_package_3']/@X_Y_Z",offsets);
149  dX[2]=offsets[0];
150  dY[2]=offsets[1];
151  dgeom->Get("//posXYZ[@volume='forwardDC_package_4']/@X_Y_Z",offsets);
152  dX[3]=offsets[0];
153  dY[3]=offsets[1];
154  }
155 
156  // Get offsets tweaking nominal geometry from calibration database
157  JCalibration * jcalib = dapp->GetJCalibration(runnumber);
158  vector<map<string,double> >vals;
159  if (jcalib->Get("FDC/cell_offsets",vals)==false){
160  for(unsigned int i=0; i<vals.size(); i++){
161  map<string,double> &row = vals[i];
162 
163  // Get the offsets from the calibration database
164  xshifts.push_back(row["xshift"]);
165  yshifts.push_back(row["yshift"]);
166  }
167  }
168  // Get FDC resolution parameters from database
169  map<string, double> fdcparms;
170  FDC_RES_PAR1=0.;
171  FDC_RES_PAR2=0.;
172  jcalib->Get("FDC/fdc_resolution_parms",fdcparms);
173  FDC_RES_PAR1=fdcparms["res_par1"];
174  FDC_RES_PAR2=fdcparms["res_par2"];
175 
176  if(DEBUG_HISTS){
177  dapp->Lock();
178 
179  // Histograms may already exist. (Another thread may have created them)
180  // Try and get pointers to the existing ones.
181  v_vs_u=(TH2F*)gROOT->FindObject("v_vs_u");
182  if (!v_vs_u) v_vs_u=new TH2F("v_vs_u","v vs u",192,0.5,192.5,192,0.5,192.5);
183 
184  qv_vs_qu= (TH2F*) gROOT->FindObject("qv_vs_qu");
185  if (!qv_vs_qu) qv_vs_qu=new TH2F("qv_vs_qu","Anode charge from each cathode",100,0,20000,100,0,20000);
186 
187  tv_vs_tu= (TH2F*) gROOT->FindObject("tv_vs_tu");
188  if (!tv_vs_tu) tv_vs_tu=new TH2F("tv_vs_tu","t(v) vs t(u)",100,-100,250,100,-100,250);
189 
190  dtv_vs_dtu= (TH2F*) gROOT->FindObject("dtv_vs_dtu");
191  if (!dtv_vs_dtu) dtv_vs_dtu=new TH2F("dtv_vs_dtu","t(wire)-t(v) vs t(wire)-t(u)",200,-100,100,200,-100,100);
192 
193  u_wire_dt_vs_wire=(TH2F *) gROOT->FindObject("u_wire_dt_vs_wire");
194  if (!u_wire_dt_vs_wire) u_wire_dt_vs_wire=new TH2F("u_wire_dt_vs_wire","wire/u cathode time difference vs wire number",
195  96,0.5,96.5,100,-500,500);
196  v_wire_dt_vs_wire=(TH2F *) gROOT->FindObject("v_wire_dt_vs_wire");
197  if (!v_wire_dt_vs_wire) v_wire_dt_vs_wire=new TH2F("v_wire_dt_vs_wire","wire/v cathode time difference vs wire number",
198  96,0.5,96.5,100,-500,500);
199  uv_dt_vs_u=(TH2F *) gROOT->FindObject("uv_dt_vs_u");
200  if (!uv_dt_vs_u) uv_dt_vs_u=new TH2F("uv_dt_vs_u","uv time difference vs u",
201  192,0.5,192.5,100,-50,50);
202  uv_dt_vs_v=(TH2F *) gROOT->FindObject("uv_dt_vs_v");
203  if (!uv_dt_vs_v) uv_dt_vs_v=new TH2F("uv_dt_vs_v","uv time difference vs v",
204  192,0.5,192.5,100,-50,50);
205 
206  ut_vs_u=(TH2F *) gROOT->FindObject("ut_vs_u");
207  if (!ut_vs_u) ut_vs_u=new TH2F("ut_vs_u","u time vs u",
208  192,0.5,192.5,100,0,1000);
209  vt_vs_v=(TH2F *) gROOT->FindObject("vt_vs_v");
210  if (!vt_vs_v) vt_vs_v=new TH2F("vt_vs_v","v time vs v",
211  192,0.5,192.5,100,0,1000);
212 
213  dx_vs_dE=(TH2F*)gROOT->FindObject("dx_vs_dE");
214  if (!dx_vs_dE) dx_vs_dE=new TH2F("dx_vs_dE","dx vs dE",100,0,25.0,
215  100,-0.2,0.2);
216 
217  u_cl_size=(TH1F*)gROOT->FindObject("u_cl_size");
218  if (!u_cl_size) u_cl_size=new TH1F("u_cl_size","u_cl_size",20,.5,20.5);
219  v_cl_size=(TH1F*)gROOT->FindObject("v_cl_size");
220  if (!v_cl_size) v_cl_size=new TH1F("v_cl_size","v_cl_size",20,.5,20.5);
221 
222  u_cl_n=(TH1F*)gROOT->FindObject("u_cl_n");
223  if (!u_cl_n) u_cl_n=new TH1F("u_cl_n","u_cl_n",20,.5,20.5);
224  v_cl_n=(TH1F*)gROOT->FindObject("v_cl_n");
225  if (!v_cl_n) v_cl_n=new TH1F("v_cl_n","v_cl_n",20,.5,20.5);
226 
227  x_dist_2=(TH1F*)gROOT->FindObject("x_dist_2");
228  if (!x_dist_2) x_dist_2=new TH1F("x_dist_2","x_dist_2",400,-2,2);
229 
230  x_dist_3=(TH1F*)gROOT->FindObject("x_dist_3");
231  if (!x_dist_3) x_dist_3=new TH1F("x_dist_3","x_dist_3",400,-2,2);
232 
233  x_dist_23=(TH1F*)gROOT->FindObject("x_dist_23");
234  if (!x_dist_23) x_dist_23=new TH1F("x_dist_23","x_dist_23",400,-2,2);
235 
236  x_dist_33=(TH1F*)gROOT->FindObject("x_dist_33");
237  if (!x_dist_33) x_dist_33=new TH1F("x_dist_33","x_dist_33",400,-2,2);
238 
239  d_uv=(TH1F*)gROOT->FindObject("d_uv");
240  if (!d_uv) d_uv=new TH1F("d_uv","d_uv",100,0,50);
241 
242 
243  for (unsigned int i=0;i<24;i++){
244  char hname[80];
245  sprintf(hname,"Hxy%d",i);
246  Hxy[i]=(TH2F *) gROOT->FindObject(hname);
247  if (!Hxy[i]){
248  Hxy[i]=new TH2F(hname,hname,4000,-50,50,200,-50,50);
249  }
250  }
251 
252  dapp->Unlock();
253  }
254 
255  return NOERROR;
256 }
257 
259  if (fdcwires.size()){
260  for (unsigned int i=0;i<fdcwires.size();i++){
261  for (unsigned int j=0;j<fdcwires[i].size();j++){
262  delete fdcwires[i][j];
263  }
264  }
265  }
266  fdcwires.clear();
267  if (fdccathodes.size()){
268  for (unsigned int i=0;i<fdccathodes.size();i++){
269  for (unsigned int j=0;j<fdccathodes[i].size();j++){
270  delete fdccathodes[i][j];
271  }
272  }
273  }
274  fdccathodes.clear();
275 
276 
277  return NOERROR;
278 }
279 ///
280 /// DFDCPseudo_factory::evnt():
281 /// this is the place that anode hits and DFDCCathodeClusters are organized into pseudopoints.
282 ///
283 jerror_t DFDCPseudo_factory::evnt(JEventLoop* eventLoop, uint64_t eventNo) {
284  if (!USE_FDC) return NOERROR;
285 
286  // Get all FDC hits (anode and cathode)
287  vector<const DFDCHit*> fdcHits;
288  eventLoop->Get(fdcHits);
289  if (fdcHits.size()==0) return NOERROR;
290 
291  // For events with a very large number of hits, assume
292  // we can't reconstruct them so bail early
293  // Feb. 8, 2008 D.L. (updated to config param. Nov. 18, 2010 D.L.)
294  if(fdcHits.size()>MAX_ALLOWED_FDC_HITS){
295  _DBG_<<"Too many hits in FDC ("<<fdcHits.size()<<", max="<<MAX_ALLOWED_FDC_HITS<<")! Pseudopoint reconstruction in FDC bypassed for event "<<eventLoop->GetJEvent().GetEventNumber()<<endl;
296  return NOERROR;
297  }
298 
299  // Get cathode clusters
300  vector<const DFDCCathodeCluster*> cathClus;
301  eventLoop->Get(cathClus);
302  if (cathClus.size()==0) return NOERROR;
303 
304  // Sift through hits and select out anode hits.
305  vector<const DFDCHit*> xHits;
306  for (unsigned int i=0; i < fdcHits.size(); i++)
307  if (fdcHits[i]->type == 0)
308  xHits.push_back(fdcHits[i]);
309  // Make sure the wires are also in order of ascending z position
310  std::sort(xHits.begin(), xHits.end(), DFDCAnode_gLayer_cmp);
311 
312  // Sift through clusters and put U and V clusters into respective vectors.
313  vector<const DFDCCathodeCluster*> uClus;
314  vector<const DFDCCathodeCluster*> vClus;
315  for (unsigned int i=0; i < cathClus.size(); i++) {
316  if (cathClus[i]->plane == 1)
317  vClus.push_back(cathClus[i]);
318  else
319  uClus.push_back(cathClus[i]);
320  }
321 
322  // If this is simulated data then we want to match up the truth hit
323  // with this "real" hit. Ideally, this would be done at the
324  // DFDCHit object level, but the organization of the data in HDDM
325  // makes that difficult. Here we have the full wire definition so
326  // we make the connection here.
327  vector<const DMCTrackHit*> mctrackhits;
328  eventLoop->Get(mctrackhits);
329 
330  vector<const DFDCCathodeCluster*>::iterator uIt = uClus.begin();
331  vector<const DFDCCathodeCluster*>::iterator vIt = vClus.begin();
332  vector<const DFDCHit*>::iterator xIt = xHits.begin();
333 
334  // For each layer, get its sets of V, X, and U hits, and then pass them to the geometrical
335  // organization routine, DFDCPseudo_factory::makePseudo()
336  vector<const DFDCCathodeCluster*> oneLayerU;
337  vector<const DFDCCathodeCluster*> oneLayerV;
338  vector<const DFDCHit*> oneLayerX;
339  for (int iLayer=1; iLayer <= 24; iLayer++) {
340  for (; ((uIt != uClus.end() && (*uIt)->gLayer == iLayer)); uIt++)
341  oneLayerU.push_back(*uIt);
342  for (; ((vIt != vClus.end() && (*vIt)->gLayer == iLayer)); vIt++)
343  oneLayerV.push_back(*vIt);
344  for (; ((xIt != xHits.end() && (*xIt)->gLayer == iLayer)); xIt++)
345  oneLayerX.push_back(*xIt);
346  if (oneLayerU.size()>0 && oneLayerV.size()>0 && oneLayerX.size()>0)
347  makePseudo(oneLayerX, oneLayerU, oneLayerV,iLayer, mctrackhits);
348  oneLayerU.clear();
349  oneLayerV.clear();
350  oneLayerX.clear();
351  }
352  // Make sure the data are both time- and z-ordered
353  std::sort(_data.begin(),_data.end(),DFDCPseudo_cmp);
354 
355  return NOERROR;
356 }
357 
358 ///
359 /// DFDCPseudo_factory::makePseudo():
360 /// performs UV+X matching to create pseudopoints
361 ///
362 void DFDCPseudo_factory::makePseudo(vector<const DFDCHit*>& x,
363  vector<const DFDCCathodeCluster*>& u,
364  vector<const DFDCCathodeCluster*>& v,
365  int layer,
366  vector<const DMCTrackHit*> &mctrackhits)
367 {
368  vector<const DFDCHit*>::iterator xIt;
369  vector<centroid_t>upeaks;
370  vector<centroid_t>vpeaks;
371 
372  sort(x.begin(), x.end(), fdcxhit_cmp);
373 
374  //printf("---------u clusters --------\n");
375  // Loop over all U and V clusters looking for peaks
376  for (unsigned int i=0;i<u.size();i++){
377  //printf("Cluster %d\n",i);
378  if (DEBUG_HISTS) u_cl_size->Fill(u[i]->members.size());
379  if (u[i]->members.size()>2){
380  for (vector<const DFDCHit*>::const_iterator strip=u[i]->members.begin()+1;strip+1!=u[i]->members.end();strip++){
381  //printf(" %d %f %f\n",(*strip)->element,(*strip)->pulse_height,(*strip)->t);
382  if (FindCentroid(u[i]->members,strip,upeaks)==NOERROR){
383  // Some values needed for cathode alignment
384  unsigned int index=2*((*strip)->gLayer-1)+(1-(*strip)->plane/2);
385  DMatrix3x1 XTemp,NTemp,NTempRaw,indexTemp;
386  XTemp(0) = fdccathodes[index][(*(strip-1))->element-1]->u;
387  XTemp(1) = fdccathodes[index][(*(strip))->element-1]->u;
388  XTemp(2) = fdccathodes[index][(*(strip+1))->element-1]->u;
389  NTemp(0) = double ((*(strip-1))->pulse_height);
390  NTemp(1) = double ((*(strip))->pulse_height);
391  NTemp(2) = double ((*(strip+1))->pulse_height);
392  NTempRaw(0) = double ((*(strip-1))->pulse_height_raw);
393  NTempRaw(1) = double ((*(strip))->pulse_height_raw);
394  NTempRaw(2) = double ((*(strip+1))->pulse_height_raw);
395  indexTemp(0) = (*(strip-1))->element;
396  indexTemp(1) = (*(strip))->element;
397  indexTemp(2) = (*(strip+1))->element;
398  upeaks[upeaks.size()-1].cluster=i;
399  upeaks[upeaks.size()-1].X = XTemp;
400  upeaks[upeaks.size()-1].N = NTemp;
401  upeaks[upeaks.size()-1].NRaw = NTempRaw;
402  upeaks[upeaks.size()-1].index = indexTemp;
403  }
404  else if (u[i]->members.size()==3){
405  if (ThreeStripCluster(u[i]->members,strip,upeaks)==NOERROR){
406  upeaks[upeaks.size()-1].cluster=i;
407  }
408  }
409  }
410  }
411  else if (u[i]->members.size()==2){
412  for (vector<const DFDCHit*>::const_iterator strip=u[i]->members.begin();strip+1!=u[i]->members.end();strip++){
413  if (TwoStripCluster(u[i]->members,strip,upeaks)==NOERROR){
414  upeaks[upeaks.size()-1].cluster=i;
415  }
416  }
417  }
418  }
419  // printf("---------v cluster --------\n");
420  for (unsigned int i=0;i<v.size();i++){
421  //printf("Cluster %d\n",i);
422  if (DEBUG_HISTS) v_cl_size->Fill(v[i]->members.size());
423  if (v[i]->members.size()>2){
424  for (vector<const DFDCHit*>::const_iterator strip=v[i]->members.begin()+1;strip+1!=v[i]->members.end();strip++){
425  //printf(" %d %f %f\n",(*strip)->element,(*strip)->pulse_height,(*strip)->t);
426  if (FindCentroid(v[i]->members,strip,vpeaks)==NOERROR){
427  // Some values needed for cathode alignment
428  unsigned int index=2*((*strip)->gLayer-1)+(1-(*strip)->plane/2);
429  DMatrix3x1 XTemp,NTemp,NTempRaw,indexTemp;
430  XTemp(0) = fdccathodes[index][(*(strip-1))->element-1]->u;
431  XTemp(1) = fdccathodes[index][(*(strip))->element-1]->u;
432  XTemp(2) = fdccathodes[index][(*(strip+1))->element-1]->u;
433  NTemp(0) = double ((*(strip-1))->pulse_height);
434  NTemp(1) = double ((*(strip))->pulse_height);
435  NTemp(2) = double ((*(strip+1))->pulse_height);
436  NTempRaw(0) = double ((*(strip-1))->pulse_height_raw);
437  NTempRaw(1) = double ((*(strip))->pulse_height_raw);
438  NTempRaw(2) = double ((*(strip+1))->pulse_height_raw);
439  indexTemp(0) = (*(strip-1))->element;
440  indexTemp(1) = (*(strip))->element;
441  indexTemp(2) = (*(strip+1))->element;
442  vpeaks[vpeaks.size()-1].cluster=i;
443  vpeaks[vpeaks.size()-1].X = XTemp;
444  vpeaks[vpeaks.size()-1].N = NTemp;
445  vpeaks[vpeaks.size()-1].NRaw = NTempRaw;
446  vpeaks[vpeaks.size()-1].index = indexTemp;
447  }
448  else if (v[i]->members.size()==3){
449  if (ThreeStripCluster(v[i]->members,strip,vpeaks)==NOERROR){
450  vpeaks[vpeaks.size()-1].cluster=i;
451  }
452  }
453  }
454  }
455  else if (v[i]->members.size()==2){
456  for (vector<const DFDCHit*>::const_iterator strip=v[i]->members.begin();strip+1!=v[i]->members.end();strip++){
457  if (TwoStripCluster(v[i]->members,strip,vpeaks)==NOERROR){
458  vpeaks[vpeaks.size()-1].cluster=i;
459  }
460  }
461  }
462  }
463  if (upeaks.size()*vpeaks.size()>0){
464  // Rotation angles for strips
465  unsigned int ilay=layer-1;
466  unsigned int ind=2*ilay;
467  float phi_u=fdccathodes[ind][0]->angle;
468  float phi_v=fdccathodes[ind+1][0]->angle;
469 
470  //Loop over all u and v centroids looking for matches with wires
471  for (unsigned int i=0;i<upeaks.size();i++){
472  for (unsigned int j=0;j<vpeaks.size();j++){
473  // In the layer local coordinate system, wires are quantized
474  // in the x-direction and y is along the wire.
475  double x_from_strips=DFDCGeometry::getXLocalStrips(upeaks[i].pos,phi_u,
476  vpeaks[j].pos,phi_v);
477  double y_from_strips=DFDCGeometry::getYLocalStrips(upeaks[i].pos,phi_u,
478  vpeaks[j].pos,phi_v);
479  int old_wire_num=-1;
480  for(xIt=x.begin();xIt!=x.end();xIt++){
481  if ((*xIt)->element<=WIRES_PER_PLANE && (*xIt)->element>0){
482  const DFDCWire *wire=fdcwires[layer-1][(*xIt)->element-1];
483  double x_from_wire=wire->u;
484 
485  //printf("xs %f xw %f\n",x_from_strips,x_from_wire);
486 
487  // Test radial value for checking whether or not the hit is within
488  // the fiducial region of the detector
489  double r2test=x_from_wire*x_from_wire+y_from_strips*y_from_strips;
490  double delta_x=x_from_wire-x_from_strips;
491 
492  if (DEBUG_HISTS){
493  if (upeaks[i].numstrips == 3 && vpeaks[j].numstrips == 3) x_dist_3->Fill(delta_x);
494  if (upeaks[i].numstrips == 2 && vpeaks[j].numstrips == 2) x_dist_2->Fill(delta_x);
495  if (upeaks[i].numstrips == 2 && vpeaks[j].numstrips == 3) x_dist_23->Fill(delta_x);
496  else if (upeaks[i].numstrips == 3 && vpeaks[j].numstrips == 2) x_dist_23->Fill(delta_x);
497 
498  if (upeaks[i].numstrips == 3 && vpeaks[j].numstrips == 10) x_dist_33->Fill(delta_x);
499  else if (upeaks[i].numstrips == 10 && vpeaks[j].numstrips == 3) x_dist_33->Fill(delta_x);
500  }
501 
502  // Match between this wire and cathodes below, skip all other hits
503  if (old_wire_num==(*xIt)->element) continue;
504 
505  if (fabs(delta_x)<DELTA_X_CUT && r2test<r2_out
506  && r2test>r2_in){
507  double dt1 = (*xIt)->t - upeaks[i].t;
508  double dt2 = (*xIt)->t - vpeaks[j].t;
509 
510  //printf("dt1 %f dt2 %f\n",dt1,dt2);
511 
512  if (DEBUG_HISTS){
513  //if (layer==1){
514  dtv_vs_dtu->Fill(dt1,dt2);
515  tv_vs_tu->Fill(upeaks[i].t, vpeaks[j].t);
516  u_wire_dt_vs_wire->Fill((*xIt)->element,(*xIt)->t-upeaks[i].t);
517  v_wire_dt_vs_wire->Fill((*xIt)->element,(*xIt)->t-vpeaks[j].t);
518 
519 
520 
521  int uid=u[upeaks[i].cluster]->members[1]->element;
522  int vid=v[vpeaks[j].cluster]->members[1]->element;
523 
524  const DFDCCathodeDigiHit *vdigihit;
525  v[vpeaks[j].cluster]->members[1]->GetSingle(vdigihit);
526  const DFDCCathodeDigiHit *udigihit;
527  u[upeaks[i].cluster]->members[1]->GetSingle(udigihit);
528  if (vdigihit!=NULL && udigihit!=NULL){
529  int dt=int(udigihit->pulse_time)-int(vdigihit->pulse_time);
530  // printf("%d %d\n",udigihit->pulse_time,vdigihit->pulse_time);
531  uv_dt_vs_u->Fill(uid,dt);
532  uv_dt_vs_v->Fill(vid,dt);
533  v_vs_u->Fill(uid,vid);
534  ut_vs_u->Fill(uid,udigihit->pulse_time);
535  vt_vs_v->Fill(vid,udigihit->pulse_time);
536  }
537  // Hxy->Fill(x_from_strips,y_from_strips);
538  //}
539  }
540 
541  if (DEBUG_HISTS){
542  d_uv->Fill(sqrt(dt1*dt1+dt2*dt2));
543  }
544 
545  if (sqrt(dt1*dt1+dt2*dt2)>STRIP_ANODE_TIME_CUT) continue;
546 
547  // Temporary cut until TDC timing is worked out
548  //if (fabs(vpeaks[j].t-upeaks[i].t)>STRIP_ANODE_TIME_CUT) continue;
549 
550  if (DEBUG_HISTS){
551  // number of clusters of each type
552  u_cl_n->Fill(upeaks[i].numstrips);
553  v_cl_n->Fill(vpeaks[j].numstrips);
554  }
555 
556  // Charge and energy loss
557  double q_cathodes=0.5*(upeaks[i].q+vpeaks[j].q);
558  double charge_to_energy=W_EFF/(GAS_GAIN*ELECTRON_CHARGE);
559  double dE=charge_to_energy*q_cathodes;
560  double q_from_pulse_height=5.0e-4*(upeaks[i].q_from_pulse_height
561  +vpeaks[j].q_from_pulse_height);
562  if (q_from_pulse_height<CHARGE_THRESHOLD) continue;
563  double dE_amp=charge_to_energy*q_from_pulse_height;
564 
565  if (DEBUG_HISTS){
566  qv_vs_qu->Fill(upeaks[i].q,vpeaks[j].q);
567  }
568 
569  // Match between this wire and cathodes, used to skip all other hits above
570  old_wire_num=(*xIt)->element;
571 
572  int status=upeaks[i].numstrips+vpeaks[j].numstrips;
573  //double xres=WIRE_SPACING/2./sqrt(12.);
574 
575  DFDCPseudo* newPseu = new DFDCPseudo;
576  newPseu->phi_u=phi_u;
577  newPseu->phi_v=phi_v;
578  newPseu->u = upeaks[i].pos;
579  newPseu->v = vpeaks[j].pos;
580  newPseu->t_u = upeaks[i].t;
581  newPseu->t_v = vpeaks[j].t;
582  newPseu->cluster_u = upeaks[i];
583  newPseu->cluster_v = vpeaks[j];
584  newPseu->w = x_from_wire+xshifts[ilay];
585  newPseu->dw = 0.; // place holder
586  newPseu->w_c = x_from_strips+xshifts[ilay];
587  newPseu->s = y_from_strips+yshifts[ilay];
588  newPseu->ds = FDC_RES_PAR1/q_from_pulse_height+FDC_RES_PAR2;
589  //newPseu->ds=0.011/q_from_pulse_height+5e-3+2.14e-10*pow(q_from_pulse_height,6);
590  newPseu->wire = wire;
591  newPseu->time = (*xIt)->t;
592  //newPseu->time=0.5*(upeaks[i].t+vpeaks[j].t);
593  newPseu->status = status;
594  newPseu->itrack = (*xIt)->itrack;
595 
596  newPseu->AddAssociatedObject(v[vpeaks[j].cluster]);
597  newPseu->AddAssociatedObject(u[upeaks[i].cluster]);
598 
599  newPseu->dE = dE;
600  newPseu->dE_amp = dE_amp;
601  newPseu->q = q_from_pulse_height;
602 
603  // It can occur (although rarely) that newPseu->wire is NULL
604  // which causes us to crash below. In these cases, we can't really
605  // make a psuedo point so we delete the current object
606  // and just go on to the next one.
607  if(newPseu->wire==NULL){
608  _DBG_<<"newPseu->wire=NULL! This shouldn't happen. Complain to staylor@jlab.org"<<endl;
609  delete newPseu;
610  continue;
611  }
612  double sinangle=newPseu->wire->udir(0);
613  double cosangle=newPseu->wire->udir(1);
614  unsigned int pack_id=(layer-1)/6;
615  newPseu->s+=dY[pack_id]*cosangle+dX[pack_id]*sinangle;
616 
617  newPseu->xy.Set((newPseu->w)*cosangle+(newPseu->s)*sinangle,
618  -(newPseu->w)*sinangle+(newPseu->s)*cosangle);
619 
620  double sigx2=HALF_CELL*HALF_CELL/3.;
621  double sigy2=MAX_DEFLECTION*MAX_DEFLECTION/3.;
622  newPseu->covxx=sigx2*cosangle*cosangle+sigy2*sinangle*sinangle;
623  newPseu->covyy=sigx2*sinangle*sinangle+sigy2*cosangle*cosangle;
624  newPseu->covxy=(sigy2-sigx2)*sinangle*cosangle;
625 
626  // Try matching truth hit with this "real" hit.
627  const DMCTrackHit *mctrackhit = DTrackHitSelectorTHROWN::GetMCTrackHit(newPseu->wire, DRIFT_SPEED*newPseu->time, mctrackhits);
628  if(mctrackhit)newPseu->AddAssociatedObject(mctrackhit);
629 
630  _data.push_back(newPseu);
631 
632  if (DEBUG_HISTS){
633  Hxy[ilay]->Fill(newPseu->w_c,newPseu->s);
634  if (ilay==6) dx_vs_dE->Fill(q_from_pulse_height,0.2588*delta_x);
635  }
636 
637  } // match in x
638  } else _DBG_ << "Bad wire " << (*xIt)->element <<endl;
639  } // xIt loop
640  } // vpeaks loop
641  } // upeaks loop
642  } // if we have peaks in both u and v views
643 
644 }
645 
646 //
647 /// DFDCPseudo_factory::CalcMeanTime()
648 /// Calculate the mean and rms of the times of the hits passed in "H".
649 /// The contents of H should be pointers to a single cluster in a
650 /// cathode plane.
651 // 1/2/2008 D.L.
652 void DFDCPseudo_factory::CalcMeanTime(const vector<const DFDCHit*>& H, double &t, double &t_rms)
653 {
654  // Calculate mean
655  t=0.0;
656  for(unsigned int i=0; i<H.size(); i++)t+=H[i]->t;
657  if(H.size()>0)t/=(double)H.size();
658 
659  // Calculate RMS
660  t_rms=0.0;
661  for(unsigned int i=0; i<H.size(); i++)t_rms+=pow((double)(H[i]->t-t),2.0);
662  if(H.size()>0)t_rms = sqrt(t_rms/(double)H.size());
663 }
664 
665 // Find the mean time and rms for a group of 3 hits with a maximum in the
666 // center hit
667 void DFDCPseudo_factory::CalcMeanTime(vector<const DFDCHit *>::const_iterator peak, double &t, double &t_rms)
668 {
669  // Calculate mean
670  t=0.0;
671  for (vector<const DFDCHit*>::const_iterator j=peak-1;j<=peak+1;j++){
672  t+=(*j)->t;
673  }
674  t/=3.;
675 
676  // Calculate RMS
677  t_rms=0.0;
678  for (vector<const DFDCHit*>::const_iterator j=peak-1;j<=peak+1;j++){
679  t_rms+=((*j)->t-t)*((*j)->t-t);
680  }
681  t_rms=sqrt(t_rms/3.);
682 }
683 
684 
685 //
686 /// DFDCPseudo_factory::FindCentroid()
687 /// Uses the Newton-Raphson method for solving the set of non-linear
688 /// equations describing the charge distribution over 3 strips for the peak
689 /// position x0, the anode charge qa, and the "width" parameter k2.
690 /// See Numerical Recipes in C p.379-383.
691 /// Updates list of centroids.
692 ///
693 jerror_t DFDCPseudo_factory::FindCentroid(const vector<const DFDCHit*>& H,
694  vector<const DFDCHit *>::const_iterator peak,
695  vector<centroid_t>&centroids){
697  double err_diff1=0.,err_diff2=0.;
698 
699  // Fill in time info in temp 1/2/2008 D.L.
700  //CalcMeanTime(H, temp.t, temp.t_rms);
701 
702  // Some code for checking for significance of fluctuations.
703  // Currently disabled.
704  //double dq1=(*(peak-1))->dq;
705  //double dq2=(*peak)->dq;
706  //double dq3=(*(peak+1))->dq;
707  //err_diff1=sqrt(dq1*dq1+dq2*dq2);
708  //err_diff2=sqrt(dq2*dq2+dq3*dq3);
709  if ((*peak)->pulse_height<MIDDLE_STRIP_THRESHOLD) {
710  return VALUE_OUT_OF_RANGE;
711  }
712 
713  // Check for a peak in three adjacent strips
714  if ((*peak)->pulse_height-(*(peak-1))->pulse_height > err_diff1
715  && (*peak)->pulse_height-(*(peak+1))->pulse_height > err_diff2){
716  // Define some matrices for use in the Newton-Raphson iteration
717  DMatrix3x3 J; //Jacobean matrix
718  DMatrix3x1 F,N,X,par,newpar,f;
719  int i=0;
720  double sum=0.;
721 
722  // Initialize the matrices to some suitable starting values
723  unsigned int index=2*((*peak)->gLayer-1)+(1-(*peak)->plane/2);
724  par(K2)=1.;
725  for (vector<const DFDCHit*>::const_iterator j=peak-1;j<=peak+1;j++){
726  X(i)=fdccathodes[index][(*j)->element-1]->u;
727  N(i)=double((*j)->pulse_height);
728  sum+=N(i);
729  i++;
730  }
731  par(X0)=X(1);
732  par(QA)=2.*sum;
733  newpar=par;
734 
735  // Newton-Raphson procedure
736  double errf=0.,errx=0;
737  for (int iter=1;iter<=ITER_MAX;iter++){
738  errf=0.;
739  errx=0.;
740 
741  // Compute Jacobian matrix: J_ij = dF_i/dx_j.
742  for (i=0;i<3;i++){
743  double dx=(par(X0)-X(i))*ONE_OVER_H;
744  double argp=par(K2)*(dx+A_OVER_H);
745  double argm=par(K2)*(dx-A_OVER_H);
746  double tanh_p=tanh(argp);
747  double tanh_m=tanh(argm);
748  double tanh2_p=tanh_p*tanh_p;
749  double tanh2_m=tanh_m*tanh_m;
750  double q_over_4=0.25*par(QA);
751 
752  f(i)=tanh_p-tanh_m;
753  J(i,QA)=-0.25*f(i);
754  J(i,K2)=-q_over_4*(argp/par(K2)*(1.-tanh2_p)
755  -argm/par(K2)*(1.-tanh2_m));
756  J(i,X0)=-q_over_4*par(K2)*(tanh2_m-tanh2_p);
757  F(i)=N(i)-q_over_4*f(i);
758  double new_errf=fabs(F(i));
759  if (new_errf>errf) errf=new_errf;
760  }
761  // Check for convergence
762  if (errf<TOLF){
763  temp.pos=par(X0);
764  temp.q_from_pulse_height=par(QA);
765  temp.numstrips=3;
766  temp.t=(*peak)->t;
767  temp.t_rms=0.;
768 
769  // Find estimate for anode charge
770  sum=0;
771  double sum_f=f(0)+f(1)+f(2);
772  for (vector<const DFDCHit*>::const_iterator j=peak-1;j<=peak+1;j++){
773  sum+=double((*j)->q);
774  }
775  temp.q=4.*sum/sum_f;
776 
777  //CalcMeanTime(peak,temp.t,temp.t_rms);
778  centroids.push_back(temp);
779 
780  return NOERROR;
781  }
782 
783  // Find the new set of parameters
784  FindNewParmVec(N,X,F,J,par,newpar);
785 
786  //Check for convergence
787  for (i=0;i<3;i++){
788  double new_err=fabs(par(i)-newpar(i));
789  if (new_err>errx) errx=new_err;
790  }
791  if (errx<TOLX){
792  temp.pos=par(X0);
793  temp.numstrips=3;
794  temp.q_from_pulse_height=par(QA);
795  temp.t=(*peak)->t;
796  temp.t_rms=0.;
797 
798  // Find estimate for anode charge
799  sum=0;
800  double sum_f=f(0)+f(1)+f(2);
801  for (vector<const DFDCHit*>::const_iterator j=peak-1;j<=peak+1;j++){
802  sum+=double((*j)->q);
803  }
804  temp.q=4.*sum/sum_f;
805 
806  //CalcMeanTime(peak,temp.t,temp.t_rms);
807  centroids.push_back(temp);
808 
809  return NOERROR;
810  }
811  par=newpar;
812  } // iterations
813  }
814  return INFINITE_RECURSION; // error placeholder
815 }
816 
817 
818 ///
819 /// DFDCPseudo_factory::FindNewParmVec()
820 /// Routine used by FindCentroid to backtrack along the direction
821 /// of the Newton step if the step is too large in order to avoid conditions
822 /// where the iteration procedure starts to diverge.
823 /// The procedure uses a scalar quantity f= 1/2 F.F for this purpose.
824 /// Algorithm described in Numerical Recipes in C, pp. 383-389.
825 ///
826 
828  const DMatrix3x1 &X,
829  const DMatrix3x1 &F,
830  const DMatrix3x3 &J,
831  const DMatrix3x1 &par,
832  DMatrix3x1 &newpar){
833  // Invert the J matrix
834  DMatrix3x3 InvJ=J.Invert();
835 
836  // Find the full Newton step
837  DMatrix3x1 fullstep=(-1.)*(InvJ*F);
838 
839  // find the rate of decrease for the Newton-Raphson step
840  double slope=(-1.0)*F.Mag2(); //dot product
841 
842  // This should be a negative number...
843  if (slope>=0){
844  return VALUE_OUT_OF_RANGE;
845  }
846 
847  double lambda=1.0; // Start out with full Newton step
848  double lambda_temp,lambda2=lambda;
849  DMatrix3x1 newF;
850  double f2=0.,newf;
851 
852  // Compute starting values for f=1/2 F.F
853  double f=-0.5*slope;
854 
855  for (;;){
856  newpar=par+lambda*fullstep;
857 
858  // Compute the value of the vector F and f=1/2 F.F with the current step
859  for (int i=0;i<3;i++){
860  double dx=(newpar(X0)-X(i))*ONE_OVER_H;
861  double argp=newpar(K2)*(dx+A_OVER_H);
862  double argm=newpar(K2)*(dx-A_OVER_H);
863  newF(i)=N(i)-0.25*newpar(QA)*(tanh(argp)-tanh(argm));
864  }
865  newf=0.5*newF.Mag2(); // dot product
866 
867  if (lambda<0.1) { // make sure the step is not too small
868  newpar=par;
869  return NOERROR;
870  } // Check if we have sufficient function decrease
871  else if (newf<=f+ALPHA*lambda*slope){
872  return NOERROR;
873  }
874  else{
875  // g(lambda)=f(par+lambda*fullstep)
876  if (lambda==1.0){//first attempt: quadratic approximation for g(lambda)
877  lambda_temp=-0.5*slope/(newf-f-slope);
878  }
879  else{ // cubic approximation for g(lambda)
880  double temp1=newf-f-lambda*slope;
881  double temp2=f2-f-lambda2*slope;
882  double one_over_lambda2_sq=1./(lambda2*lambda2);
883  double one_over_lambda_sq=1./(lambda*lambda);
884  double one_over_lambda_diff=1./(lambda-lambda2);
885  double a=(temp1*one_over_lambda_sq-temp2*one_over_lambda2_sq)*one_over_lambda_diff;
886  double b=(-lambda2*temp1*one_over_lambda_sq+lambda*temp2*one_over_lambda2_sq)
887  *one_over_lambda_diff;
888  if (a==0.0) lambda_temp=-0.5*slope/b;
889  else{
890  double disc=b*b-3.0*a*slope;
891  if (disc<0.0) lambda_temp=0.5*lambda;
892  else if (b<=0.0) lambda_temp=(-b+sqrt(disc))/(3.*a);
893  else lambda_temp=-slope/(b+sqrt(disc));
894  }
895  // ensure that we are headed in the right direction...
896  if (lambda_temp>0.5*lambda) lambda_temp=0.5*lambda;
897  }
898  }
899  lambda2=lambda;
900  f2=newf;
901  // Make sure that new version of lambda is not too small
902  lambda=(lambda_temp>0.1*lambda ? lambda_temp : 0.1*lambda);
903  }
904 }
905 
906 
907 //
908 /// DFDCPseudo_factory::TwoStripCluster()
909 /// Almost 10% of all clusters have only two strips
910 /// But FindCentroid does not work
911 /// Attempt to recover them with simple center-of-gravity
912 /// Updates list of centroids.
913 ///
914 jerror_t DFDCPseudo_factory::TwoStripCluster(const vector<const DFDCHit*>& H,
915  vector<const DFDCHit *>::const_iterator peak,
916  vector<centroid_t>&centroids){
918 
919  if ((*peak)->pulse_height<MIDDLE_STRIP_THRESHOLD && (*(peak+1))->pulse_height<MIDDLE_STRIP_THRESHOLD) {
920  return VALUE_OUT_OF_RANGE;
921  }
922 
923  unsigned int index1=2*((*peak)->gLayer-1)+(1-(*peak)->plane/2);
924  unsigned int index2=2*((*(peak+1))->gLayer-1)+(1-(*(peak+1))->plane/2);
925 
926  // this should never happen
927  if (index1 != index2) return VALUE_OUT_OF_RANGE;
928 
929  double pos1=fdccathodes[index1][(*peak)->element-1]->u;
930  double pos2=fdccathodes[index2][(*(peak+1))->element-1]->u;
931 
932  double amp1=double((*peak)->pulse_height);
933  double amp2=double((*(peak+1))->pulse_height);
934  double sum=amp1+amp2;
935 
936  double t1=double((*peak)->t);
937  double t2=double((*(peak+1))->t);
938 
939  // weighted sum
940  temp.pos=(pos1*amp1+pos2*amp2)/sum;
941 
942  //correct for 'missing' signals on the other side
943  //largest amp on the left: -
944  //largest amp on the right: +
945  double pos_corr = 0.05;
946  (amp2 > amp1) ? temp.pos+=pos_corr : temp.pos-=pos_corr;
947 
948  (amp2 > amp1) ? temp.q_from_pulse_height=amp2 : temp.q_from_pulse_height=amp1;
949  temp.q=sum;
950  temp.numstrips=2;
951 
952  // time from greater amplitude
953  (amp2 > amp1) ? temp.t=t2 : temp.t=t1;
954  temp.t_rms=0.;
955 
956  //CalcMeanTime(peak,temp.t,temp.t_rms);
957  centroids.push_back(temp);
958 
959  return NOERROR;
960 }
961 
962 //
963 /// DFDCPseudo_factory::ThreeStripCluster()
964 /// But FindCentroid does not work for Clusters without peak
965 /// Attempt to recover them with simple center-of-gravity
966 /// Updates list of centroids.
967 ///
968 jerror_t DFDCPseudo_factory::ThreeStripCluster(const vector<const DFDCHit*>& H,
969  vector<const DFDCHit *>::const_iterator peak,
970  vector<centroid_t>&centroids){
972 
973  if ((*(peak-1))->pulse_height<MIDDLE_STRIP_THRESHOLD &&
974  (*peak)->pulse_height<MIDDLE_STRIP_THRESHOLD &&
975  (*(peak+1))->pulse_height<MIDDLE_STRIP_THRESHOLD) {
976  return VALUE_OUT_OF_RANGE;
977  }
978 
979  double sum=0;
980  double wsum=0;
981  double t=0;
982  double o_amp=0;
983  int i_corr=-2;
984  double q_from_pulse_height = 0;
985  for (vector<const DFDCHit*>::const_iterator j=peak-1;j<=peak+1;j++){
986  unsigned int index=2*((*j)->gLayer-1)+(1-(*j)->plane/2);
987 
988  double pos=fdccathodes[index][(*j)->element-1]->u;
989  double amp=double((*j)->pulse_height);
990 
991  sum+=amp;
992  wsum+=amp*pos;
993 
994  // time, pulseheight and correction from largest amplitude
995  if (amp > o_amp){
996  t=double((*j)->t);
997  o_amp = amp;
998  q_from_pulse_height=amp;
999  i_corr++;
1000  }
1001  }
1002 
1003  //correct for 'missing' signals on the other side
1004  //largest amp on the left: -
1005  //largest amp on the right: +
1006  //minimum in the centre: 0
1007  double pos_corr = 0.1;
1008 
1009  // weighted sum
1010  temp.pos=wsum/sum + i_corr*pos_corr;
1011 
1012  temp.q=sum;
1013  temp.q_from_pulse_height = q_from_pulse_height;
1014  temp.numstrips=10;
1015  temp.t=t;
1016  temp.t_rms=0.;
1017 
1018  //CalcMeanTime(peak,temp.t,temp.t_rms);
1019  centroids.push_back(temp);
1020 
1021  return NOERROR;
1022 }
1023 
#define F(x, y, z)
vector< double > yshifts
unsigned int MAX_ALLOWED_FDC_HITS
DVector2 xy
rough x,y coordinates in lab coordinate system
Definition: DFDCPseudo.h:100
DApplication * dapp
DFDCPseudo_factory()
DFDCPseudo_factory::DFDCPseudo_factory(): default constructor – initializes log file.
DMatrix3x3 Invert() const
Definition: DMatrix3x3.h:90
static bool fdcxhit_cmp(const DFDCHit *a, const DFDCHit *b)
double q
&lt; energy deposition, from pulse height
Definition: DFDCPseudo.h:98
#define A_OVER_H
#define X0
double covxx
Definition: DFDCPseudo.h:95
Int_t layer
#define MAX_DEFLECTION
#define TOLX
int status
status word for pseudopoint
Definition: DFDCPseudo.h:94
#define QA
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
void makePseudo(vector< const DFDCHit * > &x, vector< const DFDCCathodeCluster * > &u, vector< const DFDCCathodeCluster * > &v, int layer, vector< const DMCTrackHit * > &mctrackhits)
DFDCPseudo_factory::makePseudo(): performs UV+X matching to create pseudopoints.
double t_v
time of the two cathode clusters
Definition: DFDCPseudo.h:86
sprintf(text,"Post KinFit Cut")
#define ONE_OVER_H
bool Get(string xpath, string &sval) const
Definition: DGeometry.h:50
#define WIRES_PER_PLANE
Definition: DFDCGeometry.h:23
int gLayer
Definition: DFDCHit.h:28
const DFDCWire * wire
DFDCWire for this wire.
Definition: DFDCPseudo.h:92
#define ELECTRON_CHARGE
int offsets(TString dir)
double q_from_pulse_height
Definition: DFDCPseudo.h:25
class DFDCPseudo: definition for a reconstructed point in the FDC
Definition: DFDCPseudo.h:74
jerror_t brun(JEventLoop *loop, int32_t runnumber)
static char index(char c)
Definition: base64.cpp:115
static const DMCTrackHit * GetMCTrackHit(const DCoordinateSystem *wire, double rdrift, vector< const DMCTrackHit * > &mctrackhits, int trackno_filter=-1)
#define X(str)
Definition: hddm-c.cpp:83
jerror_t FindCentroid(const vector< const DFDCHit * > &H, vector< const DFDCHit * >::const_iterator peak, vector< centroid_t > &centroids)
DFDCPseudo_factory::FindCentroid() Calculates the centroids of groups of three adjacent strips contai...
double ds
local coordinate of pseudopoint in the direction along the wire and its uncertainty ...
Definition: DFDCPseudo.h:91
#define TOLF
int layer
1-24
Definition: DFDCWire.h:16
double phi_v
rotation angles for cathode planes
Definition: DFDCPseudo.h:87
TF1 * f
Definition: FitGains.C:21
double w_c
Definition: DFDCPseudo.h:90
double t_u
Definition: DFDCPseudo.h:86
~DFDCPseudo_factory()
DFDCPseudo_factory::~DFDCPseudo_factory(): default destructor – closes log file.
double u
Definition: DFDCPseudo.h:85
bool DFDCPseudo_cmp(const DFDCPseudo *a, const DFDCPseudo *b)
double pos
Definition: DFDCPseudo.h:23
jerror_t init(void)
DFDCPseudo_factory::evnt(): this is the place that anode hits and DFDCCathodeClusters are organized i...
int itrack
Definition: DFDCPseudo.h:99
#define H(x, y, z)
#define GAS_GAIN
centroid_t cluster_v
Cathode cluster centroids, Useful for gain/strip pitch calibration.
Definition: DFDCPseudo.h:88
double q
Definition: DFDCPseudo.h:24
double dE
energy deposition, from integral
Definition: DFDCPseudo.h:96
jerror_t ThreeStripCluster(const vector< const DFDCHit * > &H, vector< const DFDCHit * >::const_iterator peak, vector< centroid_t > &centroids)
DFDCPseudo_factory::ThreeStripCluster() Calculates the center-of-gravity of Three adjacent strips...
TLatex * t1
DGeometry * GetDGeometry(unsigned int run_number)
bool DFDCAnode_gLayer_cmp(const DFDCHit *a, const DFDCHit *b)
DFDCAnode_gLayer_cmp(): non-member function passed to std::sort() to sort DFDCHit pointers for the an...
static float getYLocalStrips(float u, float v)
DFDCGeometry::getYLocalStrips() Compute the y-coordinate in the layer coordinate system from the stri...
Definition: DFDCGeometry.h:111
#define _DBG_
Definition: HDEVIO.h:12
double covxy
Definition: DFDCPseudo.h:95
double s
&lt; wire position computed from cathode data, assuming the avalanche occurs at the wire ...
Definition: DFDCPseudo.h:91
#define K2
double t_rms
Definition: DFDCPseudo.h:28
vector< vector< DFDCCathode * > > fdccathodes
double Mag2() const
Definition: DMatrix3x1.h:57
int element
Definition: DFDCHit.h:25
int numstrips
Definition: DFDCPseudo.h:26
double covyy
Covariance terms for (x,y)
Definition: DFDCPseudo.h:95
double dE_amp
Definition: DFDCPseudo.h:97
double w
Definition: DFDCPseudo.h:89
double time
time corresponding to this pseudopoint.
Definition: DFDCPseudo.h:93
double t
Definition: DFDCPseudo.h:27
jerror_t FindNewParmVec(const DMatrix3x1 &N, const DMatrix3x1 &X, const DMatrix3x1 &F, const DMatrix3x3 &J, const DMatrix3x1 &par, DMatrix3x1 &newpar)
DFDCPseudo_factory::FindNewParmVec() Routine used by FindCentroid to backtrack along the direction of...
uint32_t pulse_time
identified pulse time as returned by FPGA algorithm
double sqrt(double)
centroid_t cluster_u
Definition: DFDCPseudo.h:88
#define ITER_MAX
float t
Definition: DFDCHit.h:32
jerror_t TwoStripCluster(const vector< const DFDCHit * > &H, vector< const DFDCHit * >::const_iterator peak, vector< centroid_t > &centroids)
DFDCPseudo_factory::TwoStripCluster() Calculates the center-of-gravity of two adjacent strips...
void CalcMeanTime(const vector< const DFDCHit * > &H, double &t, double &t_rms)
DFDCPseudo_factory::CalcMeanTime() Calculates mean and RMS time for a cluster of cathode hits...
bool GetFDCCathodes(vector< vector< DFDCCathode * > > &fdccathodes) const
Definition: DGeometry.cc:978
#define DRIFT_SPEED
Definition: DFDCGeometry.h:17
#define W_EFF
TF1 * f2
Definition: FitGains.C:28
float u
Definition: DFDCWire.h:18
int wire
1-N
Definition: DFDCWire.h:17
bool GetFDCWires(vector< vector< DFDCWire * > > &fdcwires) const
Definition: DGeometry.cc:1078
double phi_u
Definition: DFDCPseudo.h:87
jerror_t evnt(JEventLoop *eventLoop, uint64_t eventNo)
DFDCPseudo_factory::evnt(): this is the place that anode hits and DFDCCathodeClusters are organized i...
vector< double > xshifts
double dw
local coordinate of pseudopoint in the direction perpendicular to the wires and its uncertainty ...
Definition: DFDCPseudo.h:89
static float getXLocalStrips(float u, float v)
DFDCGeometry::getXLocalStrips() Compute the x-coordinate in the layer coordinate system from the stri...
Definition: DFDCGeometry.h:93
vector< vector< DFDCWire * > > fdcwires
double v
centroid positions in the two cathode views
Definition: DFDCPseudo.h:85
TH2F * temp
union @6::@8 u
#define ALPHA
#define HALF_CELL
class DFDCHit: definition for a basic FDC hit data type.
Definition: DFDCHit.h:20