Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DEventProcessor_bcal_calib.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DEventProcessor_bcal_calib.cc
4 //
5 
7 using namespace jana;
8 
9 #include <TROOT.h>
10 #include <TCanvas.h>
11 #include <TPolyLine.h>
12 #include <DANA/DApplication.h>
13 
14 #define MAX_STEPS 1000
15 
16 // Routine used to create our DEventProcessor
17 #include <JANA/JApplication.h>
18 extern "C"{
19 void InitPlugin(JApplication *app){
20  InitJANAPlugin(app);
21  app->AddProcessor(new DEventProcessor_bcal_calib());
22 }
23 } // "C"
24 
25 
26 bool cdc_hit_cmp(const DCDCTrackHit *a,const DCDCTrackHit *b){
27 
28  return(a->wire->origin.Y()>b->wire->origin.Y());
29 }
30 
31 // Locate a position in vector xx given x
32 unsigned int DEventProcessor_bcal_calib::locate(vector<double>&xx,double x){
33  int ju,jm,jl;
34  int ascnd;
35 
36  int n=xx.size();
37 
38  jl=-1;
39  ju=n;
40  ascnd=(xx[n-1]>=xx[0]);
41  while(ju-jl>1){
42  jm=(ju+jl)>>1;
43  if ( (x>=xx[jm])==ascnd)
44  jl=jm;
45  else
46  ju=jm;
47  }
48  if (x==xx[0]) return 0;
49  else if (x==xx[n-1]) return n-2;
50  return jl;
51 }
52 
53 
54 // Convert time to distance for the cdc
56  double d=0.;
57  if (t>0){
58  unsigned int index=0;
59  index=locate(cdc_drift_table,t);
60  double dt=cdc_drift_table[index+1]-cdc_drift_table[index];
61  double frac=(t-cdc_drift_table[index])/dt;
62  d=0.01*(double(index)+frac);
63  }
64  return d;
65 }
66 
67 
68 //------------------
69 // DEventProcessor_bcal_calib (Constructor)
70 //------------------
72 {
73 
74 }
75 
76 //------------------
77 // ~DEventProcessor_bcal_calib (Destructor)
78 //------------------
80 {
81 
82 }
83 
84 //------------------
85 // init
86 //------------------
88 {
89  mT0=0.;
90 
91  DEBUG_HISTS=false;
92  gPARMS->SetDefaultParameter("BCAL_CALIB:DEBUG_HISTS",DEBUG_HISTS);
93 
94  DEBUG_PLOT_LINES=false;
95  gPARMS->SetDefaultParameter("BCAL_CALIB:DEBUG_PLOT_LINES",DEBUG_PLOT_LINES);
96 
97  if (DEBUG_HISTS){
98 
99  Hcdc_prob = (TH1F*)gROOT->FindObject("Hcdc_prob");
100  if (!Hcdc_prob){
101  Hcdc_prob=new TH1F("Hcdc_prob","Confidence level for time-based fit",100,0.0,1.);
102  }
103  Hcdcmatch = (TH1F*)gROOT->FindObject("Hcdcmatch");
104  if (!Hcdcmatch){
105  Hcdcmatch=new TH1F("Hcdcmatch","CDC hit matching distance",1000,0.0,50.);
106  }
107  Hcdcmatch_stereo = (TH1F*)gROOT->FindObject("Hcdcmatch_stereo");
108  if (!Hcdcmatch_stereo){
109  Hcdcmatch_stereo=new TH1F("Hcdcmatch_stereo","CDC stereo hit matching distance",1000,0.0,50.);
110  }
111 
112  Hbcalmatchxy=(TH2F*)gROOT->FindObject("Hbcalmatchxy");
113  if (!Hbcalmatchxy){
114  Hbcalmatchxy=new TH2F("Hbcalmatchxy","BCAL #deltay vs #deltax",400,-50.,50.,
115  400,-50.,50.);
116  }
117  }
118 
119  return NOERROR;
120 }
121 
122 //------------------
123 // brun
124 //------------------
125 jerror_t DEventProcessor_bcal_calib::brun(JEventLoop *loop, int32_t runnumber)
126 {
127  DApplication* dapp=dynamic_cast<DApplication*>(loop->GetJApplication());
128 
129  JCalibration *jcalib = dapp->GetJCalibration((loop->GetJEvent()).GetRunNumber());
130  typedef map<string,double>::iterator iter_double;
131  vector< map<string, double> > tvals;
132  if (jcalib->Get("CDC/cdc_drift_table", tvals)==false){
133  for(unsigned int i=0; i<tvals.size(); i++){
134  map<string, double> &row = tvals[i];
135  iter_double iter = row.find("t");
136  cdc_drift_table.push_back(1000.*iter->second);
137  }
138  }
139  else{
140  jerr << " CDC time-to-distance table not available... bailing..." << endl;
141  exit(0);
142  }
143 
144  map<string, double> cdc_res_parms;
145  jcalib->Get("CDC/cdc_resolution_parms", cdc_res_parms);
146  CDC_RES_PAR1 = cdc_res_parms["res_par1"];
147  CDC_RES_PAR2 = cdc_res_parms["res_par2"];
148 
149  return NOERROR;
150 }
151 
152 //------------------
153 // erun
154 //------------------
156 {
157 
158 
159  return NOERROR;
160 }
161 
162 //------------------
163 // fini
164 //------------------
166 {
167 
168  return NOERROR;
169 }
170 
171 //------------------
172 // evnt
173 //------------------
174 jerror_t DEventProcessor_bcal_calib::evnt(JEventLoop *loop, uint64_t eventnumber){
175 
176  // Get BCAL showers
177  vector<const DBCALShower*>bcalshowers;
178  loop->Get(bcalshowers);
179 
180  // Get CDC hits
181  vector<const DCDCTrackHit*>cdcs;
182  loop->Get(cdcs);
183 
184  // Associate axial hits and stereo hits into segments and link the segments
185  // together to form track candidates. Fit the candidates first using the
186  // wire positions only, then using the drift times.
187  if (cdcs.size()>10){
188  vector<const DCDCTrackHit*>axialhits;
189  vector<const DCDCTrackHit*>stereohits;
190  for (unsigned int i=0;i<cdcs.size();i++){
191  int ring=cdcs[i]->wire->ring;
192  if (ring<=4) axialhits.push_back(cdcs[i]);
193  else if (ring<=12) stereohits.push_back(cdcs[i]);
194  else if (ring<=16) axialhits.push_back(cdcs[i]);
195  else if (ring<=24) stereohits.push_back(cdcs[i]);
196  else axialhits.push_back(cdcs[i]);
197  }
198 
199  // Here we group axial hits into segments
200  vector<cdc_segment_t>axial_segments;
201  vector<bool>used_axial(axialhits.size());
202  FindSegments(axialhits,axial_segments,used_axial);
203 
204  if (axial_segments.size()>0 && stereohits.size()>0){
205  // Here we link axial segments into tracks and associate stereo hits
206  // with each track
207  vector<cdc_track_t>tracks;
208  LinkSegments(axial_segments,used_axial,axialhits,stereohits,tracks);
209 
210  for (unsigned int i=0;i<tracks.size();i++){
211  // Add lists of stereo and axial hits associated with this track
212  // and sort
213  vector<const DCDCTrackHit *>hits=tracks[i].axial_hits;
214  hits.insert(hits.end(),tracks[i].stereo_hits.begin(),tracks[i].stereo_hits.end());
215  sort(hits.begin(),hits.end(),cdc_hit_cmp);
216 
217  DMatrix4x1 S;
218  // Use earliest cdc time to estimate t0
219  double minT=1e6;
220  for (unsigned int j=0;j<hits.size();j++){
221  double L=(hits[0]->wire->origin-hits[j]->wire->origin).Perp();
222  double t_test=hits[j]->tdrift-L/29.98;
223  if (t_test<minT) minT=t_test;
224  }
225  mT0=minT;
226 
227  // Initial guess for state vector
228  if (GuessForStateVector(tracks[i],S)==NOERROR){
229  // Run the Kalman Filter algorithm
230  if (DoFilter(S,hits)==NOERROR){
231  MatchToBCAL(bcalshowers,S);
232  }
233  }
234  }
235  }
236  }
237 
238  return NOERROR;
239 }
240 
241 // Steering routine for the kalman filter
242 jerror_t
244  vector<const DCDCTrackHit *>&hits){
245  unsigned int numhits=hits.size();
246  unsigned int maxindex=numhits-1;
247 
248  // deque to store reference trajectory
249  deque<trajectory_t>trajectory;
250 
251  // State vector to store "best" values
252  DMatrix4x1 Sbest;
253 
254  // Covariance matrix
255  DMatrix4x4 C0,C,Cbest;
256  C0(state_x,state_x)=C0(state_y,state_y)=1.0;
257  C0(state_tx,state_tx)=C0(state_ty,state_ty)=0.01;
258 
259  double chi2=1e16,chi2_old=1e16;
260  unsigned int ndof=0,ndof_old=0;
261  unsigned int iter=0;
262 
263  // Perform a wire-based pass
264  for(iter=0;iter<20;iter++){
265  chi2_old=chi2;
266  ndof_old=ndof;
267 
268  trajectory.clear();
269  if (SetReferenceTrajectory(mOuterZ,S,trajectory,
270  hits[maxindex])!=NOERROR) break;
271 
272  C=C0;
273  if (KalmanFilter(S,C,hits,trajectory,chi2,ndof)!=NOERROR)
274  break;
275  //printf(">>>>>>chi2 %f ndof %d\n",chi2,ndof);
276 
277  if (fabs(chi2_old-chi2)<0.1
278  || TMath::Prob(chi2,ndof)<TMath::Prob(chi2_old,ndof_old)) break;
279 
280  // Save the current state and covariance matrixes
281  Cbest=C;
282  Sbest=S;
283  }
284  if (iter>0){
285  double prob=TMath::Prob(chi2_old,ndof_old);
286  //printf(">>>>>>> cdc prob %f\n",prob);
287  //Sbest.Print();
288 
289  if (DEBUG_HISTS){
290  // Lock mutex
291  pthread_mutex_lock(&mutex);
292 
293  Hcdc_prob->Fill(prob);
294 
295  // Unlock mutex
296  pthread_mutex_unlock(&mutex);
297  }
298 
299  if (prob>0.01){
300  // Save the best version of the state vector
301  S=Sbest;
302 
303  // Optionally superimpose results of line fit onto event viewer
304  if (DEBUG_PLOT_LINES){
305  PlotLines(trajectory);
306  }
307 
308  return NOERROR;
309  }
310  }
311 
312  return VALUE_OUT_OF_RANGE;
313 }
314 
315 // Find segments in cdc axial layers
316 jerror_t
317 DEventProcessor_bcal_calib::FindSegments(vector<const DCDCTrackHit*>&hits,
318  vector<cdc_segment_t>&segments,
319  vector<bool>&used_in_segment){
320  if (hits.size()==0) return RESOURCE_UNAVAILABLE;
321 
322  // Group adjacent hits into pairs
323  vector<pair<unsigned int,unsigned int> > pairs;
324  for (unsigned int i=0;i<hits.size()-1;i++){
325  for (unsigned int j=i+1;j<hits.size();j++){
326  int r1=hits[i]->wire->ring;
327  int r2=hits[j]->wire->ring;
328  int s1=hits[i]->wire->straw;
329  int s2=hits[j]->wire->straw;
330  double d=(hits[i]->wire->origin-hits[j]->wire->origin).Perp();
331 
332  if (DEBUG_HISTS){
333  pthread_mutex_lock(&mutex);
334  Hcdcmatch->Fill(d);
335  pthread_mutex_unlock(&mutex);
336  }
337 
338  if ((abs(r1-r2)<=2 && d<CDC_MATCH_RADIUS)
339  || (abs(r1-r2)==0 && abs(s1-s2)==1)){
340  pair <unsigned int,unsigned int> mypair(i,j);
341  pairs.push_back(mypair);
342  }
343  }
344  }
345  // Link pairs of hits together into segments
346  for (unsigned int i=0;i<pairs.size();i++){
347  if (used_in_segment[pairs[i].first]==false
348  && used_in_segment[pairs[i].second]==false){
349  vector<const DCDCTrackHit *>neighbors;
350  unsigned int old=i;
351  unsigned int old_first=pairs[old].first;
352  unsigned int old_second=pairs[old].second;
353  used_in_segment[old_first]=true;
354  used_in_segment[old_second]=true;
355  neighbors.push_back(hits[old_first]);
356  neighbors.push_back(hits[old_second]);
357  for (unsigned int j=i+1;j<pairs.size();j++){
358  unsigned int first=pairs[j].first;
359  unsigned int second=pairs[j].second;
360  old_first=pairs[old].first;
361  old_second=pairs[old].second;
362  if ((used_in_segment[old_first] || used_in_segment[old_second])
363  && (first==old_first || first==old_second || second==old_second
364  || second==old_first)){
365  if (used_in_segment[first]==false){
366  used_in_segment[first]=true;
367  neighbors.push_back(hits[first]);
368  }
369  if (used_in_segment[second]==false){
370  used_in_segment[second]=true;
371  neighbors.push_back(hits[second]);
372  }
373  if (used_in_segment[old_first]==false){
374  used_in_segment[old_first]=true;
375  neighbors.push_back(hits[old_first]);
376  }
377  if (used_in_segment[old_second]==false){
378  used_in_segment[old_second]=true;
379  neighbors.push_back(hits[old_second]);
380  }
381  }
382  old=j;
383  }
384 
385  cdc_segment_t mysegment;
386  sort(neighbors.begin(),neighbors.end(),cdc_hit_cmp);
387  mysegment.dir=neighbors[neighbors.size()-1]->wire->origin
388  -neighbors[0]->wire->origin;
389  mysegment.dir.SetMag(1.);
390  mysegment.hits=neighbors;
391  mysegment.matched=false;
392  segments.push_back(mysegment);
393  }
394 
395  }
396 
397  return NOERROR;
398 }
399 
400 // Perform the Kalman Filter for the current set of cdc hits
401 jerror_t
403  vector<const DCDCTrackHit *>&hits,
404  deque<trajectory_t>&trajectory,
405  double &chi2,unsigned int &ndof,
406  bool timebased){
407  DMatrix1x4 H; // Track projection matrix
408  DMatrix4x1 H_T; // Transpose of track projection matrix
409  DMatrix4x1 K; // Kalman gain matrix
410  DMatrix4x4 I; // identity matrix
411  DMatrix4x4 J; // Jacobian matrix
412  DMatrix4x1 S0; // State vector from reference trajectory
413  double V=1.2*(0.78*0.78/12.); // sigma=cell_size/sqrt(12.)*scale_factor
414 
415  //Initialize chi2 and ndof
416  chi2=0.;
417  ndof=0;
418 
419  double doca2=0.;
420 
421  // CDC index and wire position variables
422  unsigned int cdc_index=hits.size()-1;
423  bool more_hits=true;
424  const DCDCWire *wire=hits[cdc_index]->wire;
425  DVector3 origin=wire->origin;
426  double z0=origin.z();
427  DVector3 wdir=wire->udir;
428  double vz=wdir.z();
429 
430  // Wire offsets
431  DVector3 wirepos=origin+((trajectory[0].z-z0)/vz)*wdir;
432 
433  /// compute initial doca^2 to first wire
434  double dx=S(state_x)-wirepos.X();
435  double dy=S(state_y)-wirepos.Y();
436  double old_doca2=dx*dx+dy*dy;
437 
438  // Loop over all steps in the trajectory
439  S0=trajectory[0].S;
440  J=trajectory[0].J;
441  trajectory[0].Skk=S;
442  trajectory[0].Ckk=C;
443  for (unsigned int k=1;k<trajectory.size();k++){
444  if (C(0,0)<=0. || C(1,1)<=0. || C(2,2)<=0. || C(3,3)<=0.)
445  return UNRECOVERABLE_ERROR;
446 
447  // Propagate the state and covariance matrix forward in z
448  S=trajectory[k].S+J*(S-S0);
449  C=J*C*J.Transpose();
450 
451  // Save the current state and covariance matrix
452  trajectory[k].Skk=S;
453  trajectory[k].Ckk=C;
454 
455  // Save S and J for the next step
456  S0=trajectory[k].S;
457  J=trajectory[k].J;
458 
459  // Position along wire
460  wirepos=origin+((trajectory[k].z-z0)/wdir.z())*wdir;
461 
462  // New doca^2
463  dx=S(state_x)-wirepos.X();
464  dy=S(state_y)-wirepos.Y();
465  doca2=dx*dx+dy*dy;
466 
467  if (doca2>old_doca2 && more_hits){
468  // zero-position and direction of line describing particle trajectory
469  double tx=S(state_tx),ty=S(state_ty);
470  DVector3 pos0(S(state_x),S(state_y),trajectory[k].z);
471  DVector3 tdir(tx,ty,1.);
472  tdir.SetMag(1.);
473 
474  // Find the true doca to the wire
475  DVector3 diff=pos0-origin;
476  double dx0=diff.x(),dy0=diff.y();
477  double wdir_dot_diff=diff.Dot(wdir);
478  double tdir_dot_diff=diff.Dot(tdir);
479  double tdir_dot_wdir=tdir.Dot(wdir);
480  double D=1.-tdir_dot_wdir*tdir_dot_wdir;
481  double N=tdir_dot_wdir*wdir_dot_diff-tdir_dot_diff;
482  double N1=wdir_dot_diff-tdir_dot_wdir*tdir_dot_diff;
483  double scale=1./D;
484  double s=scale*N;
485  double t=scale*N1;
486  diff+=s*tdir-t*wdir;
487  double d=diff.Mag();
488 
489  // The next measurement: use half the radius of the straw
490  double dmeas=0.39;
491 
492  // residual
493  double res=dmeas-d;
494 
495  // Track projection
496  double one_over_d=1./d;
497  double diffx=diff.x(),diffy=diff.y(),diffz=diff.z();
498 
499  H(state_x)=H_T(state_x)=diffx*one_over_d;
500  H(state_y)=H_T(state_y)=diffy*one_over_d;
501 
502  double wx=wdir.x(),wy=wdir.y();
503 
504  double dN1dtx=2.*tx*wdir_dot_diff-wx*tdir_dot_diff-tdir_dot_wdir*dx0;
505  double dDdtx=2.*tx-2.*tdir_dot_wdir*wx;
506  double dtdtx=scale*(dN1dtx-t*dDdtx);
507 
508  double dN1dty=2.*ty*wdir_dot_diff-wy*tdir_dot_diff-tdir_dot_wdir*dy0;
509  double dDdty=2.*ty-2.*tdir_dot_wdir*wy;
510  double dtdty=scale*(dN1dty-t*dDdty);
511 
512  double dNdtx=wx*wdir_dot_diff-dx0;
513  double dsdtx=scale*(dNdtx-s*dDdtx);
514 
515  double dNdty=wy*wdir_dot_diff-dy0;
516  double dsdty=scale*(dNdty-s*dDdty);
517 
518  H(state_tx)=H_T(state_tx)
519  =one_over_d*(diffx*(s+tx*dsdtx-wx*dtdtx)+diffy*(ty*dsdtx-wy*dtdtx)
520  +diffz*(dsdtx-dtdtx));
521  H(state_ty)=H_T(state_ty)
522  =one_over_d*(diffx*(tx*dsdty-wx*dtdty)+diffy*(s+ty*dsdty-wy*dtdty)
523  +diffz*(dsdty-dtdty));
524 
525  // inverse of variance including prediction
526  double InvV=1./(V+H*C*H_T);
527 
528  // Compute Kalman gain matrix
529  K=InvV*(C*H_T);
530 
531  // Update state vector covariance matrix
532  DMatrix4x4 Ctest=C-K*(H*C);
533 
534  //C.Print();
535  //K.Print();
536  //Ctest.Print();
537 
538  // Check that Ctest is positive definite
539  if (Ctest(0,0)>0.0 && Ctest(1,1)>0.0 && Ctest(2,2)>0.0 && Ctest(3,3)>0.0)
540  {
541  C=Ctest;
542 
543  // Update the state vector
544  //S=S+res*K;
545  S+=res*K;
546 
547  // Compute new residual
548  d=FindDoca(trajectory[k].z,S,wdir,origin);
549  res=dmeas-d;
550 
551  // Update chi2 for this segment
552  double Vtemp=V-H*C*H_T;
553  chi2+=res*res/Vtemp;
554  ndof++;
555 
556  //printf("res %f V %f chi2 %f\n",res,Vtemp,res*res/Vtemp);
557  }
558  else{
559  // _DBG_ << "Bad C!" << endl;
560  return VALUE_OUT_OF_RANGE;
561  }
562 
563  // move to next cdc hit
564  if (cdc_index>0){
565  cdc_index--;
566 
567  //New wire position
568  wire=hits[cdc_index]->wire;
569  origin=wire->origin;
570  vz=wire->udir.z();
571  wdir=wire->udir;
572 
573  wirepos=origin+((trajectory[k].z-z0)/vz)*wdir;
574 
575  // New doca^2
576  dx=S(state_x)-wirepos.x();
577  dy=S(state_y)-wirepos.y();
578  doca2=dx*dx+dy*dy;
579 
580  }
581  else more_hits=false;
582  }
583 
584  old_doca2=doca2;
585  }
586 
587  ndof-=4;
588 
589  return NOERROR;
590 }
591 
592 //Reference trajectory for the track for cdc tracks
594 ::SetReferenceTrajectory(double z,DMatrix4x1 &S,deque<trajectory_t>&trajectory,
595  const DCDCTrackHit *last_cdc){
596  DMatrix4x4 J(1.,0.,1.,0., 0.,1.,0.,1., 0.,0.,1.,0., 0.,0.,0.,1.);
597 
598  double ds=1.0;
599  double dz=(S(state_ty)>0.?-1.:1.)*ds/sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
600  double t=0.;
602 
603  //y-position after which we cut off the loop
604  double min_y=last_cdc->wire->origin.y()-5.;
605  unsigned int numsteps=0;
606  do{
607  double newz=z+dz;
608  temp.Skk=Zero4x1;
609  temp.Ckk=Zero4x4;
610  temp.h_id=0;
611  temp.z=newz;
612  temp.J=J;
613  temp.J(state_x,state_tx)=-dz;
614  temp.J(state_y,state_ty)=-dz;
615  // Flight time: assume particle is moving at the speed of light
616  temp.t=(t+=ds/29.98);
617  //propagate the state to the next z position
618  temp.S(state_x)=S(state_x)+S(state_tx)*dz;
619  temp.S(state_y)=S(state_y)+S(state_ty)*dz;
620  temp.S(state_tx)=S(state_tx);
621  temp.S(state_ty)=S(state_ty);
622  S=temp.S;
623  trajectory.push_front(temp);
624 
625  z=newz;
626  numsteps++;
627  }while (S(state_y)>min_y && numsteps<MAX_STEPS);
628 
629  if (trajectory.size()<2) return UNRECOVERABLE_ERROR;
630 
631  //if (true)
632  if (false)
633  {
634  printf("Trajectory:\n");
635  for (unsigned int i=0;i<trajectory.size();i++){
636  printf(" x %f y %f z %f\n",trajectory[i].S(state_x),
637  trajectory[i].S(state_y),trajectory[i].z);
638  }
639  }
640 
641  return NOERROR;
642 }
643 
644 // Link axial segments together to form track candidates and match to stereo
645 // hits
646 jerror_t
647 DEventProcessor_bcal_calib::LinkSegments(vector<cdc_segment_t>&axial_segments,
648  vector<bool>&used_axial,
649  vector<const DCDCTrackHit *>&axial_hits,
650  vector<const DCDCTrackHit *>&stereo_hits,
651  vector<cdc_track_t>&LinkedSegments){
652 
653  unsigned int num_axial=axial_segments.size();
654  for (unsigned int i=0;i<num_axial-1;i++){
655  if (axial_segments[i].matched==false){
656  cdc_track_t mytrack;
657  mytrack.axial_hits=axial_segments[i].hits;
658 
659  DVector3 pos0=axial_segments[i].hits[0]->wire->origin;
660  DVector3 vhat=axial_segments[i].dir;
661 
662  for (unsigned int j=i+1;j<num_axial;j++){
663  if (axial_segments[j].matched==false){
664  DVector3 pos1=axial_segments[j].hits[0]->wire->origin;
665  DVector3 dir1=axial_segments[j].hits[0]->wire->udir;
666  DVector3 diff=pos1-pos0;
667  double s=diff.Dot(vhat);
668  double d=(diff-s*vhat).Mag();
669 
670  if (DEBUG_HISTS){
671  pthread_mutex_lock(&mutex);
672  Hcdcmatch_stereo->Fill(d);
673  pthread_mutex_unlock(&mutex);
674  }
675 
676  if (d<CDC_MATCH_RADIUS){
677  axial_segments[j].matched=true;
678  mytrack.axial_hits.insert(mytrack.axial_hits.end(),
679  axial_segments[j].hits.begin(),
680  axial_segments[j].hits.end());
681  sort(mytrack.axial_hits.begin(),mytrack.axial_hits.end(),
682  cdc_hit_cmp);
683 
684  vhat=mytrack.axial_hits[mytrack.axial_hits.size()-1]->wire->origin
685  -mytrack.axial_hits[0]->wire->origin;
686  vhat.SetMag(1.);
687  }
688  }
689  }
690  // Position of the first axial wire in the track
691  pos0=mytrack.axial_hits[0]->wire->origin;
692 
693  // Grab axial hits not associated with segments
694  bool got_match=false;
695  for (unsigned int j=0;j<axial_hits.size();j++){
696  if (used_axial[j]==false){
697  if (MatchCDCHit(vhat,pos0,axial_hits[j])){
698  used_axial[j]=true;
699  mytrack.axial_hits.push_back(axial_hits[j]);
700  got_match=true;
701  }
702  }
703  }
704  // Resort if we added axial hits and recompute direction vector
705  if (got_match){
706  sort(mytrack.axial_hits.begin(),mytrack.axial_hits.end(),cdc_hit_cmp);
707 
708  vhat=mytrack.axial_hits[mytrack.axial_hits.size()-1]->wire->origin
709  -mytrack.axial_hits[0]->wire->origin;
710  vhat.SetMag(1.);
711  }
712 
713  // Now try to associate stereo hits with this track
714  vector<unsigned int>used_stereo(stereo_hits.size());
715  for (unsigned int j=0;j<stereo_hits.size();j++){
716  if (used_stereo[j]==false){
717  if (MatchCDCHit(vhat,pos0,stereo_hits[j])){
718  used_stereo[j]=true;
719  mytrack.stereo_hits.push_back(stereo_hits[j]);
720  }
721  }
722  }
723  size_t num_stereo=mytrack.stereo_hits.size();
724  size_t num_axial=mytrack.axial_hits.size();
725  if (num_stereo>0 && num_stereo+num_axial>4){
726  mytrack.dir=vhat;
727  LinkedSegments.push_back(mytrack);
728  }
729  }
730  }
731 
732  return NOERROR;
733 }
734 
735 // Match a CDC hit with a line starting at pos0 going in the vhat direction
737  const DVector3 &pos0,
738  const DCDCTrackHit *hit){
739  DVector3 pos1=hit->wire->origin;
740  DVector3 uhat=hit->wire->udir;
741  DVector3 diff=pos1-pos0;
742  double vhat_dot_uhat=vhat.Dot(uhat);
743  double scale=1./(1.-vhat_dot_uhat*vhat_dot_uhat);
744  double s=scale*(vhat_dot_uhat*diff.Dot(vhat)-diff.Dot(uhat));
745  double t=scale*(diff.Dot(vhat)-vhat_dot_uhat*diff.Dot(uhat));
746  double d=(diff+s*uhat-t*vhat).Mag();
747 
748  if (d<CDC_MATCH_RADIUS) return true;
749 
750  return false;
751 }
752 
753 
754 // Compute initial guess for state vector (x,y,tx,ty) for a track in the CDC
755 // by fitting a line to the intersections between the line in the xy plane and
756 // the stereo wires.
757 jerror_t
759  DMatrix4x1 &S){
760  // Parameters for line in x-y plane
761  double vx=track.dir.x();
762  double vy=track.dir.y();
763  DVector3 pos0=track.axial_hits[0]->wire->origin;
764  double xa=pos0.x();
765  double ya=pos0.y();
766 
767  double sumv=0,sumx=0,sumy=0,sumz=0,sumxx=0,sumyy=0,sumxz=0,sumyz=0;
768  for (unsigned int i=0;i<track.stereo_hits.size();i++){
769  // Intersection of line in xy-plane with this stereo straw
770  DVector3 origin_s=track.stereo_hits[i]->wire->origin;
771  DVector3 dir_s=track.stereo_hits[i]->wire->udir;
772  double ux_s=dir_s.x();
773  double uy_s=dir_s.y();
774  double dx=xa-origin_s.x();
775  double dy=ya-origin_s.y();
776  double s=(dx*vy-dy*vx)/(ux_s*vy-uy_s*vx);
777  DVector3 pos1=origin_s+s*dir_s;
778  double x=pos1.x(),y=pos1.y(),z=pos1.z();
779 
780  if (z>17.0 && z<167.0){ // Check for CDC dimensions
781  sumv+=1.;
782  sumx+=x;
783  sumxx+=x*x;
784  sumy+=y;
785  sumyy+=y*y;
786  sumz+=z;
787  sumxz+=x*z;
788  sumyz+=y*z;
789  }
790  }
791  double xdenom=sumv*sumxz-sumx*sumz;
792  if (fabs(xdenom)<EPS) return VALUE_OUT_OF_RANGE;
793 
794  double ydenom=sumv*sumyz-sumy*sumz;
795  if (fabs(ydenom)<EPS) return VALUE_OUT_OF_RANGE;
796 
797  double xtemp=sumv*sumxx-sumx*sumx;
798  double xslope=xtemp/xdenom;
799  double ytemp=sumv*sumyy-sumy*sumy;
800  double yslope=ytemp/ydenom;
801 
802  // double z0x=(sumxx*sumz-sumx*sumxz)/xtemp;
803  double z0y=(sumyy*sumz-sumy*sumyz)/ytemp;
804 
805  // Increment just beyond point largest in y
806  double delta_z=(yslope>0)?0.5:-0.5;
807 
808  //Starting z position
809  mOuterZ=z0y+ya/yslope+delta_z;
810 
811  S(state_x)=xa+xslope*delta_z;
812  S(state_y)=ya+yslope*delta_z;
813  S(state_tx)=xslope;
814  S(state_ty)=yslope;
815 
816  return NOERROR;
817 }
818 
819 // Compute distance of closest approach between two lines
821  const DVector3 &wdir,
822  const DVector3 &origin){
823  DVector3 pos(S(state_x),S(state_y),z);
824  DVector3 diff=pos-origin;
825 
826  DVector3 uhat(S(state_tx),S(state_ty),1.);
827  uhat.SetMag(1.);
828  DVector3 vhat=wdir;
829  // vhat.SetMag(1.);
830 
831  double vhat_dot_diff=diff.Dot(vhat);
832  double uhat_dot_diff=diff.Dot(uhat);
833  double uhat_dot_vhat=uhat.Dot(vhat);
834  double D=1.-uhat_dot_vhat*uhat_dot_vhat;
835  double N=uhat_dot_vhat*vhat_dot_diff-uhat_dot_diff;
836  double N1=vhat_dot_diff-uhat_dot_vhat*uhat_dot_diff;
837  double scale=1./D;
838  double s=scale*N;
839  double t=scale*N1;
840 
841  diff+=s*uhat-t*vhat;
842  return diff.Mag();
843 }
844 
845 // If the event viewer is available, grab parts of the hdview2 display and
846 // overlay the results of the line fit on the tracking views.
847 void DEventProcessor_bcal_calib::PlotLines(deque<trajectory_t>&traj){
848  unsigned int last_index=traj.size()-1;
849 
850  TCanvas *c1=dynamic_cast<TCanvas *>(gROOT->FindObject("endviewA Canvas"));
851  if (c1!=NULL){
852  c1->cd();
853  TPolyLine *line=new TPolyLine();
854 
855  line->SetLineColor(1);
856  line->SetLineWidth(1);
857 
858  line->SetNextPoint(traj[last_index].S(state_x),traj[last_index].S(state_y));
859  line->SetNextPoint(traj[0].S(state_x),traj[0].S(state_y));
860  line->Draw();
861 
862  c1->Update();
863 
864  delete line;
865  }
866 
867  c1=dynamic_cast<TCanvas *>(gROOT->FindObject("endviewA Large Canvas"));
868  if (c1!=NULL){
869  c1->cd();
870  TPolyLine *line=new TPolyLine();
871 
872  line->SetLineColor(1);
873  line->SetLineWidth(1);
874 
875  line->SetNextPoint(traj[last_index].S(state_x),traj[last_index].S(state_y));
876  line->SetNextPoint(traj[0].S(state_x),traj[0].S(state_y));
877  line->Draw();
878 
879  c1->Update();
880 
881  delete line;
882  }
883 
884  c1=dynamic_cast<TCanvas *>(gROOT->FindObject("sideviewA Canvas"));
885  if (c1!=NULL){
886  c1->cd();
887  TPolyLine *line=new TPolyLine();
888 
889  line->SetLineColor(1);
890  line->SetLineWidth(1);
891 
892  line->SetNextPoint(traj[last_index].z,traj[last_index].S(state_x));
893  line->SetNextPoint(traj[0].z,traj[0].S(state_x));
894  line->Draw();
895 
896  c1->Update();
897 
898  delete line;
899  }
900 
901  c1=dynamic_cast<TCanvas *>(gROOT->FindObject("sideviewB Canvas"));
902  if (c1!=NULL){
903  c1->cd();
904  TPolyLine *line=new TPolyLine();
905 
906  line->SetLineColor(1);
907  line->SetLineWidth(1);
908 
909  line->SetNextPoint(traj[last_index].z,traj[last_index].S(state_y));
910  line->SetNextPoint(traj[0].z,traj[0].S(state_y));
911  line->Draw();
912 
913  c1->Update();
914  delete line;
915  }
916  // end of drawing code
917 
918 }
919 
920 
921 // Match tracks in the cdc to the BCAL
922 bool DEventProcessor_bcal_calib::MatchToBCAL(vector<const DBCALShower *>&bcalshowers,
923  DMatrix4x1 &S){
924 
925  double denom=sqrt(S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
926  double ux=S(state_tx)/denom;
927  double uy=S(state_ty)/denom;
928  double x0=S(state_x);
929  double y0=S(state_y);
930 
931  // Keep list of matches
932  vector<bcal_match_t>matching_bcals;
933 
934  for (unsigned int i=0;i<bcalshowers.size();i++){
935  double x=bcalshowers[i]->x,y=bcalshowers[i]->y;
936  double s=(x-x0)*ux+(y-y0)*uy;
937  double x1=x0+s*ux;
938  double y1=y0+s*uy;
939  double dx=x1-x;
940  double dy=y1-y;
941 
942  if (DEBUG_HISTS){
943  // Lock mutex
944  pthread_mutex_lock(&mutex);
945 
946  Hbcalmatchxy->Fill(dx,dy);
947 
948  // Unlock mutex
949  pthread_mutex_unlock(&mutex);
950  }
951 
952  if (fabs(dx)<2.0 && fabs(dy)<1.0){
954  temp.dir.SetXYZ(ux,uy,1.);
955  temp.dir.SetMag(1.);
956  temp.match=bcalshowers[i];
957  matching_bcals.push_back(temp);
958  }
959  }
960  if (matching_bcals.size()>0){
961  for (unsigned int i=0;i<matching_bcals.size();i++){
962  //matching_bcals[i].dir.Print();
963  }
964 
965  return true;
966  }
967  return false;
968 }
Definition: track.h:16
bool MatchCDCHit(const DVector3 &vhat, const DVector3 &pos0, const DCDCTrackHit *hit)
DApplication * dapp
bool cdc_hit_cmp(const DCDCTrackHit *a, const DCDCTrackHit *b)
jerror_t brun(jana::JEventLoop *eventLoop, int32_t runnumber)
Called everytime a new run number is detected.
const DBCALShower * match
const DCDCWire * wire
Definition: DCDCTrackHit.h:37
TVector3 DVector3
Definition: DVector3.h:14
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
#define EPS
bool MatchToBCAL(vector< const DBCALShower * > &bcalshowers, DMatrix4x1 &S)
#define C0
Definition: src/md5.cpp:24
#define y
unsigned int locate(vector< double > &xx, double x)
void PlotLines(deque< trajectory_t > &traj)
jerror_t KalmanFilter(DMatrix4x1 &S, DMatrix4x4 &C, vector< const DCDCTrackHit * > &hits, deque< trajectory_t > &trajectory, double &chi2, unsigned int &ndof, bool timebased=false)
DMatrix4x4 Transpose()
Definition: DMatrix4x4.h:174
static char index(char c)
Definition: base64.cpp:115
jerror_t SetReferenceTrajectory(double z, DMatrix4x1 &S, deque< trajectory_t > &trajectory, const DCDCTrackHit *last_cdc)
static void locate(const double *xx, int n, double x, int *j)
jerror_t init(void)
Called once at program start.
Double_t c1[2][NMODULES]
Definition: tw_corr.C:68
jerror_t fini(void)
Called after last event of last event source has been processed.
jerror_t GuessForStateVector(const cdc_track_t &track, DMatrix4x1 &S)
#define H(x, y, z)
vector< const DCDCTrackHit * > stereo_hits
vector< const DCDCTrackHit * > hits
TLatex tx
#define MAX_STEPS
InitPlugin_t InitPlugin
double FindDoca(double z, const DMatrix4x1 &S, const DVector3 &vhat, const DVector3 &origin)
vector< double > cdc_drift_table
jerror_t LinkSegments(vector< cdc_segment_t > &axial_segments, vector< bool > &used_axial, vector< const DCDCTrackHit * > &axial_hits, vector< const DCDCTrackHit * > &stereo_hits, vector< cdc_track_t > &LinkedSegments)
vector< const DCDCTrackHit * > axial_hits
double sqrt(double)
#define S(str)
Definition: hddm-c.cpp:84
jerror_t DoFilter(DMatrix4x1 &S, vector< const DCDCTrackHit * > &hits)
jerror_t evnt(jana::JEventLoop *eventLoop, uint64_t eventnumber)
Called every event.
jerror_t erun(void)
Called everytime run number changes, provided brun has been called.
jerror_t FindSegments(vector< const DCDCTrackHit * > &hits, vector< cdc_segment_t > &segments, vector< bool > &used_hits)
printf("string=%s", string)
TH2F * temp
#define CDC_MATCH_RADIUS
#define I(x, y, z)