Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DEventProcessor_dc_alignment.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: DEventProcessor_dc_alignment.cc
4 // Created: Thu Oct 18 17:15:41 EDT 2012
5 // Creator: staylor (on Linux ifarm1102 2.6.18-274.3.1.el5 x86_64)
6 //
7 
9 using namespace jana;
10 
11 #include <TROOT.h>
12 #include <TCanvas.h>
13 #include <TPolyLine.h>
14 
15 #define MAX_STEPS 1000
16 
17 // Routine used to create our DEventProcessor
18 #include <JANA/JApplication.h>
19 extern "C"{
20 void InitPlugin(JApplication *app){
21  InitJANAPlugin(app);
22  app->AddProcessor(new DEventProcessor_dc_alignment());
23 }
24 } // "C"
25 
26 
27 bool cdc_hit_cmp(const DCDCTrackHit *a,const DCDCTrackHit *b){
28 
29  return(a->wire->origin.Y()>b->wire->origin.Y());
30 }
31 
32 bool fdc_pseudo_cmp(const DFDCPseudo *a,const DFDCPseudo *b){
33  return (a->wire->origin.z()<b->wire->origin.z());
34 }
35 
36 
37 bool bcal_cmp(const bcal_match_t &a,const bcal_match_t &b){
38  return (a.match->y>b.match->y);
39 }
40 
41 // Locate a position in vector xx given x
42 unsigned int DEventProcessor_dc_alignment::locate(vector<double>&xx,double x){
43  int n=xx.size();
44  if (x==xx[0]) return 0;
45  else if (x==xx[n-1]) return n-2;
46 
47  int jl=-1;
48  int ju=n;
49  int ascnd=(xx[n-1]>=xx[0]);
50  while(ju-jl>1){
51  int jm=(ju+jl)>>1;
52  if ( (x>=xx[jm])==ascnd)
53  jl=jm;
54  else
55  ju=jm;
56  }
57  return jl;
58 }
59 
60 
61 // Convert time to distance for the cdc
63  double delta,double t){
64  double d=0.;
65  if (t>0){
66  double f_0=0.;
67  double f_delta=0.;
68 
69  if (dphi*delta>0){
70  double a1=long_drift_func[0][0];
71  double a2=long_drift_func[0][1];
72  double b1=long_drift_func[1][0];
73  double b2=long_drift_func[1][1];
74  double c1=long_drift_func[2][0];
75  double c2=long_drift_func[2][1];
76  double c3=long_drift_func[2][2];
77 
78  // use "long side" functional form
79  double my_t=0.001*t;
80  double sqrt_t=sqrt(my_t);
81  double t3=my_t*my_t*my_t;
82  double delta_mag=fabs(delta);
83  f_delta=(a1+a2*delta_mag)*sqrt_t+(b1+b2*delta_mag)*my_t
84  +(c1+c2*delta_mag+c3*delta*delta)*t3;
85  f_0=a1*sqrt_t+b1*my_t+c1*t3;
86  }
87  else{
88  double my_t=0.001*t;
89  double sqrt_t=sqrt(my_t);
90  double delta_mag=fabs(delta);
91 
92  // use "short side" functional form
93  double a1=short_drift_func[0][0];
94  double a2=short_drift_func[0][1];
95  double a3=short_drift_func[0][2];
96  double b1=short_drift_func[1][0];
97  double b2=short_drift_func[1][1];
98  double b3=short_drift_func[1][2];
99 
100  double delta_sq=delta*delta;
101  f_delta= (a1+a2*delta_mag+a3*delta_sq)*sqrt_t
102  +(b1+b2*delta_mag+b3*delta_sq)*my_t;
103  f_0=a1*sqrt_t+b1*my_t;
104  }
105 
106  unsigned int max_index=cdc_drift_table.size()-1;
107  if (t>cdc_drift_table[max_index]){
108  //_DBG_ << "t: " << t <<" d " << f_delta <<endl;
109  d=f_delta;
110 
111  return d;
112  }
113 
114  // Drift time is within range of table -- interpolate...
115  unsigned int index=0;
116  index=locate(cdc_drift_table,t);
117  double dt=cdc_drift_table[index+1]-cdc_drift_table[index];
118  double frac=(t-cdc_drift_table[index])/dt;
119  double d_0=0.01*(double(index)+frac);
120 
121  double P=0.;
122  double tcut=250.0; // ns
123  if (t<tcut) {
124  P=(tcut-t)/tcut;
125  }
126  d=f_delta*(d_0/f_0*P+1.-P);
127  }
128  return d;
129 }
130 
131 
132 // Interpolate on a table to convert time to distance for the fdc
134  double d=0.;
135  if (t>fdc_drift_table[fdc_drift_table.size()-1]) return 0.5;
136  if (t>0){
137  unsigned int index=0;
138  index=locate(fdc_drift_table,t);
139  double dt=fdc_drift_table[index+1]-fdc_drift_table[index];
140  double frac=(t-fdc_drift_table[index])/dt;
141  d=0.01*(double(index)+frac);
142  }
143  return d;
144 }
145 
146 
147 
148 //------------------
149 // DEventProcessor_dc_alignment (Constructor)
150 //------------------
152 {
153  fdc_ptr = &fdc;
154  fdc_c_ptr= &fdc_c;
155  cdc_ptr = &cdc;
156 
157  pthread_mutex_init(&mutex, NULL);
158 
159 }
160 
161 //------------------
162 // ~DEventProcessor_dc_alignment (Destructor)
163 //------------------
165 {
166 
167 }
168 
169 //------------------
170 // init
171 //------------------
173 {
174  myevt=0;
175  one_over_zrange=1./150.;
176 
177  printf("Initializing..........\n");
178 
179  RUN_BENCHMARK=false;
180  gPARMS->SetDefaultParameter("DCALIGN:RUN_BENCHMARK",RUN_BENCHMARK);
181  USE_BCAL=false;
182  gPARMS->SetDefaultParameter("DCALIGN:USE_BCAL", USE_BCAL);
183  USE_FCAL=false;
184  gPARMS->SetDefaultParameter("DCALIGN:USE_FCAL", USE_FCAL);
185  COSMICS=false;
186  gPARMS->SetDefaultParameter("DCALIGN:COSMICS", COSMICS);
187  USE_DRIFT_TIMES=false;
188  gPARMS->SetDefaultParameter("DCALIGN:USE_DRIFT_TIMES",USE_DRIFT_TIMES);
189  READ_CDC_FILE=false;
190  gPARMS->SetDefaultParameter("DCALIGN:READ_CDC_FILE",READ_CDC_FILE);
191  READ_ANODE_FILE=false;
192  gPARMS->SetDefaultParameter("DCALIGN:READ_ANODE_FILE",READ_ANODE_FILE);
193  READ_CATHODE_FILE=false;
194  gPARMS->SetDefaultParameter("DCALIGN:READ_CATHODE_FILE",READ_CATHODE_FILE);
195  ALIGN_WIRE_PLANES=true;
196  gPARMS->SetDefaultParameter("DCALIGN:ALIGN_WIRE_PLANES",ALIGN_WIRE_PLANES);
197  FILL_TREE=false;
198  gPARMS->SetDefaultParameter("DCALIGN:FILL_TREE",FILL_TREE);
199  MIN_PSEUDOS=12;
200  gPARMS->SetDefaultParameter("DCALIGN:MIN_PSEUDOS",MIN_PSEUDOS);
201  MIN_INTERSECTIONS=10;
202  gPARMS->SetDefaultParameter("DCALIGN:MIN_INTERSECTIONS",MIN_INTERSECTIONS);
203 
204  fdc_alignments.resize(24);
205  for (unsigned int i=0;i<24;i++){
206  fdc_alignments[i].A=DMatrix2x1();
207  if (RUN_BENCHMARK==false){
208  fdc_alignments[i].E=DMatrix2x2(0.000001,0.,0.,0.0001);
209  }
210  else{
211  fdc_alignments[i].E=DMatrix2x2();
212  }
213  }
214  fdc_cathode_alignments.resize(24);
215  for (unsigned int i=0;i<24;i++){
216  double var=0.0001;
217  double var_phi=0.000001;
218  if (RUN_BENCHMARK==false){
219  fdc_cathode_alignments[i].E=DMatrix4x4(var_phi,0.,0.,0., 0.,var,0.,0.,
220  0.,0.,var_phi,0., 0.,0.,0.,var);
221  }
222  else{
223  fdc_cathode_alignments[i].E=DMatrix4x4();
224  }
225  fdc_cathode_alignments[i].A=DMatrix4x1();
226  }
227 
228  if (READ_ANODE_FILE){
229  ifstream fdcfile("fdc_alignment.dat");
230  // Skip first line, used to identify columns in file
231  //char sdummy[40];
232  // fdcfile.getline(sdummy,40);
233  // loop over remaining entries
234  for (unsigned int i=0;i<24;i++){
235  double du,dphi,dz;
236 
237  fdcfile >> dphi;
238  fdcfile >> du;
239  fdcfile >> dz;
240 
241  fdc_alignments[i].A(kU)=du;
242  fdc_alignments[i].A(kPhiU)=dphi;
243  }
244  fdcfile.close();
245  }
246 
247  if (READ_CATHODE_FILE){
248  ifstream fdcfile("fdc_cathode_alignment.dat");
249  // Skip first line, used to identify columns in file
250  //char sdummy[40];
251  // fdcfile.getline(sdummy,40);
252  // loop over remaining entries
253  for (unsigned int i=0;i<24;i++){
254  double du,dphiu,dv,dphiv;
255 
256  fdcfile >> dphiu;
257  fdcfile >> du;
258  fdcfile >> dphiv;
259  fdcfile >> dv;
260 
261  fdc_cathode_alignments[i].A(kU)=du;
262  fdc_cathode_alignments[i].A(kPhiU)=dphiu;
263  fdc_cathode_alignments[i].A(kV)=dv;
264  fdc_cathode_alignments[i].A(kPhiV)=dphiv;
265 
266  }
267  fdcfile.close();
268  }
269 
270  fdc_drift_parms(0)=0.;
271  fdc_drift_parms(1)=0.;
272  fdc_drift_parms(2)=0.03;
273 
274  unsigned int numstraws[28]={42,42,54,54,66,66,80,80,93,93,106,106,123,123,
275  135,135,146,146,158,158,170,170,182,182,197,197,
276  209,209};
277  for (unsigned int i=0;i<28;i++){
278  vector<cdc_align_t>tempvec;
279  for (unsigned int j=0;j<numstraws[i];j++){
281  temp.A=DMatrix4x1(0.,0.,0.,0.);
282  double var=0.01;
283  if (RUN_BENCHMARK==false){
284  temp.E=DMatrix4x4(var,0.,0.,0., 0.,var,0.,0., 0.,0.,var,0., 0.,0.,0.,var);
285  }
286  else {
287  temp.E=DMatrix4x4();
288  }
289  tempvec.push_back(temp);
290  }
291  cdc_alignments.push_back(tempvec);
292  }
293 
294  if (READ_CDC_FILE){
295  ifstream cdcfile("cdc_alignment.dat");
296  for (unsigned int ring=0;ring<cdc_alignments.size();ring++){
297  for (unsigned int straw=0;straw<cdc_alignments[ring].size();
298  straw++){
299  double dxu,dyu,dxd,dyd;
300 
301  cdcfile >> dxu;
302  cdcfile >> dyu;
303  cdcfile >> dxd;
304  cdcfile >> dyd;
305 
306  cdc_alignments[ring][straw].A(k_dXu)=dxu;
307  cdc_alignments[ring][straw].A(k_dYu)=dyu;
308  cdc_alignments[ring][straw].A(k_dXd)=dxd;
309  cdc_alignments[ring][straw].A(k_dYd)=dyd;
310 
311  double var=0.0001;
312  cdc_alignments[ring][straw].E=DMatrix4x4(var,0.,0.,0., 0.,var,0.,0., 0.,0.,var,0., 0.,0.,0.,var);
313  }
314  }
315  cdcfile.close();
316  }
317 
318 
319 
320  if (FILL_TREE){
321  // Create Tree
322  fdctree = new TTree("fdc","FDC alignments");
323  fdcbranch = fdctree->Branch("T","FDC_branch",&fdc_ptr);
324 
325  // Create Tree
326  fdcCtree = new TTree("fdc_c","FDC alignments");
327  fdcCbranch = fdcCtree->Branch("T","FDC_c_branch",&fdc_c_ptr);
328 
329  // Create Tree
330  cdctree = new TTree("cdc","CDC alignments");
331  cdcbranch = cdctree->Branch("T","CDC_branch",&cdc_ptr);
332  }
333 
334  return NOERROR;
335 }
336 
337 //------------------
338 // brun
339 //------------------
340 jerror_t DEventProcessor_dc_alignment::brun(JEventLoop *loop, int32_t runnumber)
341 {
342  DApplication* dapp=dynamic_cast<DApplication*>(loop->GetJApplication());
343  dgeom = dapp->GetDGeometry(runnumber);
344  //dgeom->GetFDCWires(fdcwires);
345 
346  // Get the position of the CDC downstream endplate from DGeometry
347  double endplate_dz,endplate_rmin,endplate_rmax;
348  dgeom->GetCDCEndplate(endplate_z,endplate_dz,endplate_rmin,endplate_rmax);
349  endplate_z+=0.5*endplate_dz;
350 
351 
352  JCalibration *jcalib = dapp->GetJCalibration((loop->GetJEvent()).GetRunNumber());
353  vector< map<string, double> > tvals;
354  cdc_drift_table.clear();
355  if (jcalib->Get("CDC/cdc_drift_table::NoBField", tvals)==false){
356  for(unsigned int i=0; i<tvals.size(); i++){
357  map<string, double> &row = tvals[i];
358  cdc_drift_table.push_back(1000.*row["t"]);
359  }
360  }
361  else{
362  jerr << " CDC time-to-distance table not available... bailing..." << endl;
363  exit(0);
364  }
365 
366  unsigned int numstraws[28]={42,42,54,54,66,66,80,80,93,93,106,106,123,123,
367  135,135,146,146,158,158,170,170,182,182,197,197,
368  209,209};
369 
370  map<string, double> cdc_res_parms;
371  jcalib->Get("CDC/cdc_resolution_parms", cdc_res_parms);
372  CDC_RES_PAR1 = cdc_res_parms["res_par1"];
373  CDC_RES_PAR2 = cdc_res_parms["res_par2"];
374 
375  fdc_drift_table.clear();
376  if (jcalib->Get("FDC/fdc_drift_table", tvals)==false){
377  for(unsigned int i=0; i<tvals.size(); i++){
378  map<string, double> &row = tvals[i];
379  fdc_drift_table.push_back(1000.*row["t"]);
380  }
381  }
382  else{
383  jerr << " FDC time-to-distance table not available... bailing..." << endl;
384  exit(0);
385  }
386 
387  // Get offsets tweaking nominal geometry from calibration database
388  vector<map<string,double> >vals;
389  vector<cdc_offset_t>tempvec;
390 
391  if (jcalib->Get("CDC/wire_alignment",vals)==false){
392  unsigned int straw_count=0,ring_count=0;
393  for(unsigned int i=0; i<vals.size(); i++){
394  map<string,double> &row = vals[i];
395 
396  // put the vector of offsets for the current ring into the offsets vector
397  if (straw_count==numstraws[ring_count]){
398  straw_count=0;
399  ring_count++;
400 
401  cdc_offsets.push_back(tempvec);
402 
403  tempvec.clear();
404  }
405 
406  // Get the offsets from the calibration database
408  temp.dx_u=row["dxu"];
409  //temp.dx_u=0.;
410 
411  temp.dy_u=row["dyu"];
412  //temp.dy_u=0.;
413 
414  temp.dx_d=row["dxd"];
415  //temp.dx_d=0.;
416 
417  temp.dy_d=row["dyd"];
418  //temp.dy_d=0.;
419 
420  tempvec.push_back(temp);
421 
422  straw_count++;
423  }
424  cdc_offsets.push_back(tempvec);
425  }
426  else{
427  jerr<< "CDC wire alignment table not available... bailing... " <<endl;
428  exit(0);
429  }
430 
431  // Get the straw sag parameters from the database
432  max_sag.clear();
433  sag_phi_offset.clear();
434  unsigned int straw_count=0,ring_count=0;
435  if (jcalib->Get("CDC/sag_parameters", tvals)==false){
436  vector<double>temp,temp2;
437  for(unsigned int i=0; i<tvals.size(); i++){
438  map<string, double> &row = tvals[i];
439 
440  temp.push_back(row["offset"]);
441  temp2.push_back(row["phi"]);
442 
443  straw_count++;
444  if (straw_count==numstraws[ring_count]){
445  max_sag.push_back(temp);
446  sag_phi_offset.push_back(temp2);
447  temp.clear();
448  temp2.clear();
449  straw_count=0;
450  ring_count++;
451  }
452  }
453  }
454 
455  if (jcalib->Get("CDC/drift_parameters::NoBField", tvals)==false){
456  map<string, double> &row = tvals[0]; //long drift side
457  long_drift_func[0][0]=row["a1"];
458  long_drift_func[0][1]=row["a2"];
459  long_drift_func[0][2]=row["a3"];
460  long_drift_func[1][0]=row["b1"];
461  long_drift_func[1][1]=row["b2"];
462  long_drift_func[1][2]=row["b3"];
463  long_drift_func[2][0]=row["c1"];
464  long_drift_func[2][1]=row["c2"];
465  long_drift_func[2][2]=row["c3"];
466 
467  row = tvals[1]; // short drift side
468  short_drift_func[0][0]=row["a1"];
469  short_drift_func[0][1]=row["a2"];
470  short_drift_func[0][2]=row["a3"];
471  short_drift_func[1][0]=row["b1"];
472  short_drift_func[1][1]=row["b2"];
473  short_drift_func[1][2]=row["b3"];
474  short_drift_func[2][0]=row["c1"];
475  short_drift_func[2][1]=row["c2"];
476  short_drift_func[2][2]=row["c3"];
477  }
478 
479  japp->RootWriteLock(); //ACQUIRE ROOT LOCK
480 
481  for (int i=0;i<28;i++){
482  char title[40];
483  sprintf(title,"cdc_residual_ring%d",i+1);
484  Hcdc_ring_res[i]=(TH2F*)gROOT->FindObject(title);
485  if (!Hcdc_ring_res[i]){
486  Hcdc_ring_res[i]=new TH2F(title,title,numstraws[i],0.5,numstraws[i]+0.5,
487  100,-1,1);
488  }
489  }
490  for (int i=0;i<28;i++){
491  char title[40];
492  sprintf(title,"cdc_drift_time_ring%d",i+1);
493  Hcdc_ring_time[i]=(TH2F*)gROOT->FindObject(title);
494  if (!Hcdc_ring_time[i]){
495  Hcdc_ring_time[i]=new TH2F(title,title,numstraws[i],0.5,numstraws[i]+0.5,
496  900,-100,800);
497  }
498  }
499 
500  Hprob = (TH1F*)gROOT->FindObject("Hprob");
501  if (!Hprob){
502  Hprob=new TH1F("Hprob","Confidence level for final fit",100,0.0,1.);
503  }
504  Hpseudo_prob = (TH1F*)gROOT->FindObject("Hpseudo_prob");
505  if (!Hpseudo_prob){
506  Hpseudo_prob=new TH1F("Hpseudo_prob","Confidence level for final fit",100,0.0,1.);
507  }
508 
509  Hcdc_prob = (TH1F*)gROOT->FindObject("Hcdc_prob");
510  if (!Hcdc_prob){
511  Hcdc_prob=new TH1F("Hcdc_prob","Confidence level for time-based fit",100,0.0,1.);
512  }
513  Hcdc_prelimprob = (TH1F*)gROOT->FindObject("Hcdc_prelimprob");
514  if (!Hcdc_prelimprob){
515  Hcdc_prelimprob=new TH1F("Hcdc_prelimprob","Confidence level for prelimary fit",100,0.0,1.);
516  }
517  Hintersection_match = (TH1F*)gROOT->FindObject("Hintersection_match");
518  if (!Hintersection_match){
519  Hintersection_match=new TH1F("Hintersection_match","Intersection matching distance",100,0.0,25.);
520  }
521  Hintersection_link_match = (TH1F*)gROOT->FindObject("Hintersection_link_match");
522  if (!Hintersection_link_match){
523  Hintersection_link_match=new TH1F("Hintersection_link_match","Segment matching distance",100,0.0,25.);
524  }
525 
526  Hcdcmatch = (TH1F*)gROOT->FindObject("Hcdcmatch");
527  if (!Hcdcmatch){
528  Hcdcmatch=new TH1F("Hcdcmatch","CDC hit matching distance",1000,0.0,50.);
529  }
530  Hcdcmatch_stereo = (TH1F*)gROOT->FindObject("Hcdcmatch_stereo");
531  if (!Hcdcmatch_stereo){
532  Hcdcmatch_stereo=new TH1F("Hcdcmatch_stereo","CDC stereo hit matching distance",1000,0.0,50.);
533  }
534 
535  Hmatch = (TH1F*)gROOT->FindObject("Hmatch");
536  if (!Hmatch){
537  Hmatch=new TH1F("Hmatch","Segment matching distance",100,0.0,25.);
538  }
539  Hlink_match = (TH1F*)gROOT->FindObject("Hlink_match");
540  if (!Hlink_match){
541  Hlink_match=new TH1F("link_match","Segment matching distance",100,0.0,25.);
542  }
543 
544 
545  Hbeta = (TH1F*)gROOT->FindObject("Hbeta");
546  if (!Hbeta){
547  Hbeta=new TH1F("Hbeta","Estimate for #beta",100,0.0,1.5);
548  Hbeta->SetXTitle("#beta");
549  }
550 
551  Hztarg = (TH1F*)gROOT->FindObject("Hztarg");
552  if (!Hztarg){
553  Hztarg=new TH1F("Hztarg","Estimate for target z",1200,-300.0,300.0);
554  }
555  Hures_vs_layer=(TH2F*)gROOT->FindObject("Hures_vs_layer");
556  if (!Hures_vs_layer){
557  Hures_vs_layer=new TH2F("Hures_vs_layer","Cathode u-view residuals",
558  24,0.5,24.5,200,-0.5,0.5);
559  }
560  Hres_vs_layer=(TH2F*)gROOT->FindObject("Hres_vs_layer");
561  if (!Hres_vs_layer){
562  Hres_vs_layer=new TH2F("Hres_vs_layer","wire-based residuals",
563  24,0.5,24.5,200,-0.5,0.5);
564  }
565  Hvres_vs_layer=(TH2F*)gROOT->FindObject("Hvres_vs_layer");
566  if (!Hvres_vs_layer){
567  Hvres_vs_layer=new TH2F("Hvres_vs_layer","Cathode v-view residuals",
568  24,0.5,24.5,200,-0.5,0.5);
569  }
570  Hcdc_time_vs_d=(TH2F*)gROOT->FindObject("Hcdc_time_vs_d");
571  if (!Hcdc_time_vs_d){
572  Hcdc_time_vs_d=new TH2F("Hcdc_time_vs_d",
573  "cdc drift time vs doca",120,0,1.2,600,-20,1180);
574  }
575  Hcdcdrift_time=(TH2F*)gROOT->FindObject("Hcdcdrift_time");
576  if (!Hcdcdrift_time){
577  Hcdcdrift_time=new TH2F("Hcdcdrift_time",
578  "cdc doca vs drift time",1201,-21,1181,100,0,1);
579  }
580  Hcdcres_vs_drift_time=(TH2F*)gROOT->FindObject("Hcdcres_vs_drift_time");
581  if (!Hcdcres_vs_drift_time){
582  Hcdcres_vs_drift_time=new TH2F("Hcdcres_vs_drift_time","cdc Residual vs drift time",600,-20,1180,500,-1.,1.);
583  }
584  Hcdcres_vs_d=(TH2F*)gROOT->FindObject("Hcdcres_vs_d");
585  if (!Hcdcres_vs_d){
586  Hcdcres_vs_d=new TH2F("Hcdcres_vs_d","cdc Residual vs distance to wire",600,0,1.2,500,-1.,1.);
587  }
588 
589  Hdrift_time=(TH2F*)gROOT->FindObject("Hdrift_time");
590  if (!Hdrift_time){
591  Hdrift_time=new TH2F("Hdrift_time",
592  "doca vs drift time",201,-21,381,100,0,1);
593  }
594  Hres_vs_drift_time=(TH2F*)gROOT->FindObject("Hres_vs_drift_time");
595  if (!Hres_vs_drift_time){
596  Hres_vs_drift_time=new TH2F("Hres_vs_drift_time","Residual vs drift time",320,-20,300,1000,-1,1);
597  }
598  Hdv_vs_dE=(TH2F*)gROOT->FindObject("Hdv_vs_dE");
599  if (!Hdv_vs_dE){
600  Hdv_vs_dE=new TH2F("Hdv_vs_dE","dv vs energy dep",100,0,20e-6,200,-1,1);
601  }
602 
603  Hbcalmatch=(TH2F*)gROOT->FindObject("Hbcalmatch");
604  if (!Hbcalmatch){
605  Hbcalmatch=new TH2F("Hbcalmatch","BCAL #deltar vs #deltaz",100,-50.,50.,
606  100,0.,10.);
607  }
608  Hbcalmatchxy=(TH2F*)gROOT->FindObject("Hbcalmatchxy");
609  if (!Hbcalmatchxy){
610  Hbcalmatchxy=new TH2F("Hbcalmatchxy","BCAL #deltay vs #deltax",400,-50.,50.,
611  400,-50.,50.);
612  }
613  Hfcalmatch=(TH1F*)gROOT->FindObject("Hfcalmatch");
614  if (!Hfcalmatch){
615  Hfcalmatch=new TH1F("Hfcalmatch","FCAL #deltar",400,0.,50.);
616  }
617 
618 
619 
620  japp->RootUnLock(); //RELEASE ROOT LOCK
621 
622  return NOERROR;
623 }
624 
625 //------------------
626 // erun
627 //------------------
629 {
630 
631 
632  return NOERROR;
633 }
634 
635 //------------------
636 // fini
637 //------------------
639 {
640  // Get pointer to TrackFinder object
641  vector<const DTrackFinder *> finders;
642  loop->Get(finders);
643 
644  if(finders.size()<1){
645  _DBG_<<"Unable to get a DTrackFinder object!"<<endl;
646  return RESOURCE_UNAVAILABLE;
647  }
648 
649  // Drop the const qualifier from the DTrackFinder pointer
650  auto finder = const_cast<DTrackFinder*>(finders[0]);
651 
652 
653  printf("Events processed = %d\n",myevt);
654 
655  if (RUN_BENCHMARK==false){
656 
657  for (unsigned int ring=0;ring<cdc_alignments.size();ring++){
658  for (unsigned int straw=0;straw<cdc_alignments[ring].size();
659  straw++){
660  if (fabs(cdc_alignments[ring][straw].A(k_dXu))>0.19)
661  cout << cdc_alignments[ring][straw].A(k_dXu) << " "
662  << sqrt(cdc_alignments[ring][straw].E(k_dXu,k_dXu)) << endl;
663  }
664  }
665 
666  ofstream cdcfile("cdc_alignment.dat");
667  //cdcfile << "Ring straw dXu dYu dXd dYd" << endl;
668  for (unsigned int ring=0;ring<cdc_alignments.size();ring++){
669  for (unsigned int straw=0;straw<cdc_alignments[ring].size();
670  straw++){
671  // cdcfile << ring+1 << " " << straw+1 << " "
672  cdcfile << cdc_alignments[ring][straw].A(k_dXu) << " "
673  << cdc_alignments[ring][straw].A(k_dYu) << " "
674  << cdc_alignments[ring][straw].A(k_dXd) << " "
675  << cdc_alignments[ring][straw].A(k_dYd) << endl;
676  }
677  }
678  cdcfile.close();
679 
680  ofstream cdcfile2("cdc_alignment_update.dat");
681  //cdcfile << "Ring straw dXu dYu dXd dYd" << endl;
682  for (unsigned int ring=0;ring<cdc_alignments.size();ring++){
683  for (unsigned int straw=0;straw<cdc_alignments[ring].size();
684  straw++){
685  // cdcfile << ring+1 << " " << straw+1 << " "
686  cdcfile2 << (cdc_alignments[ring][straw].A(k_dXu)+cdc_offsets[ring][straw].dx_u) << " "
687  << (cdc_alignments[ring][straw].A(k_dYu)+cdc_offsets[ring][straw].dy_u) << " "
688  << (cdc_alignments[ring][straw].A(k_dXd)+cdc_offsets[ring][straw].dx_d) << " "
689  << (cdc_alignments[ring][straw].A(k_dYd)+cdc_offsets[ring][straw].dy_d) << endl;
690  }
691  }
692  cdcfile2.close();
693 
694 
695 
696 
697  if (ALIGN_WIRE_PLANES){
698  ofstream fdcfile("fdc_alignment.dat");
699  //fdcfile << "dPhi dU sig(dU)" <<endl;
700  for (unsigned int layer=0;layer<24;layer++){
701  double du=fdc_alignments[layer].A(kU);
702  double dphi=fdc_alignments[layer].A(kPhiU);
703 
704  fdcfile << dphi <<" " <<" " << du << " " << "0." << endl;
705  }
706  fdcfile.close();
707  }
708  else{
709  ofstream fdcfile("fdc_cathode_alignment.dat");
710  for (unsigned int layer=0;layer<24;layer++){
711  fdcfile << fdc_cathode_alignments[layer].A(kPhiU)
712  << " " << fdc_cathode_alignments[layer].A(kU)
713  << " " << fdc_cathode_alignments[layer].A(kPhiV)
714  << " " << fdc_cathode_alignments[layer].A(kV) << endl;
715  }
716  fdcfile.close();
717  }
718  }
719 
720  return NOERROR;
721 }
722 
723 //------------------
724 // evnt
725 //------------------
726 jerror_t DEventProcessor_dc_alignment::evnt(JEventLoop *loop, uint64_t eventnumber){
727  myevt++;
728 
729  // Reset the track finder
730  finder->Reset();
731 
732  // Get BCAL showers, FCAL showers and FDC space points
733  vector<const DFCALShower*>fcalshowers;
734  if (USE_FCAL) loop->Get(fcalshowers);
735  vector<const DBCALShower*>bcalshowers;
736  if (USE_BCAL)loop->Get(bcalshowers);
737 
738  vector<const DFDCPseudo*>pseudos;
739  loop->Get(pseudos);
740  vector<const DCDCTrackHit*>cdcs;
741  //if (COSMICS)
742  loop->Get(cdcs);
743 
744  if (cdcs.size()>20 /* && cdcs.size()<60*/){
745  // Add the hits to the finder helper class, link axial hits into segments
746  // then link axial hits and stereo hits together to form track candidates
747  for (size_t i=0;i<cdcs.size();i++) finder->AddHit(cdcs[i]);
748  finder->FindAxialSegments();
749  finder->LinkCDCSegments();
750 
751  // Get the list of linked segments and fit the hits to lines
752  const vector<DTrackFinder::cdc_track_t>tracks=finder->GetCDCTracks();
753  for (unsigned int i=0;i<tracks.size();i++){
754  // Add lists of stereo and axial hits associated with this track
755  // and sort
756  vector<const DCDCTrackHit *>hits=tracks[i].axial_hits;
757  hits.insert(hits.end(),tracks[i].stereo_hits.begin(),tracks[i].stereo_hits.end());
758  sort(hits.begin(),hits.end(),cdc_hit_cmp);
759 
760  // Use earliest cdc time to estimate t0
761  double t0=1e6;
762  for (unsigned int j=0;j<hits.size();j++){
763  double L=(hits[0]->wire->origin-hits[j]->wire->origin).Perp();
764  double t_test=hits[j]->tdrift-L/29.98;
765  if (t_test<t0) t0=t_test;
766  }
767 
768  // Initial guess for state vector
769  DMatrix4x1 S(tracks[i].S);
770 
771  // Run the Kalman Filter algorithm
772  DoFilter(t0,tracks[i].z,S,hits);
773  }
774  }
775 
776  //-------------------------------------------------------------------------
777  // FDC alignment
778  //-------------------------------------------------------------------------
779  if (pseudos.size()>MIN_PSEUDOS
780  //&&((fcalshowers.size()>0&&fcalshowers.size()<3)
781  // || (bcalshowers.size()>0&&bcalshowers.size()<3))
782  ){
783  // Add hits to the track finder helper class, link hits into segments
784  // then link segments together to form track candidates
785  for (size_t i=0;i<pseudos.size();i++) finder->AddHit(pseudos[i]);
786  finder->FindFDCSegments();
787  finder->LinkFDCSegments();
788 
789  // Get the list of linked segments
790  const vector<DTrackFinder::fdc_segment_t>tracks=finder->GetFDCTracks();
791 
792  // Loop over linked segments
793  for (unsigned int k=0;k<tracks.size();k++){
794  vector<const DFDCPseudo *>hits=tracks[k].hits;
795 
796  if (hits.size()>MIN_PSEUDOS){
797  sort(hits.begin(),hits.end(),fdc_pseudo_cmp);
798 
799  // Initial guess for state vector
800  DMatrix4x1 S(tracks[k].S);
801 
802  // Move x and y to just before the first hit
803  double my_z=hits[0]->wire->origin.z()-1.;
804  S(state_x)+=my_z*S(state_tx);
805  S(state_y)+=my_z*S(state_ty);
806 
807  // Use earliest fdc time to estimate t0
808  double t0=1e6;
809  double dsdz=sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
810  for (unsigned int m=0;m<hits.size();m++){
811  if (hits[m]->time<t0){
812  double L=(hits[m]->wire->origin.z()-my_z)*dsdz;
813  t0=hits[m]->time-L/29.98; // assume moving at speed of light
814  }
815  }
816 
817  // Run the Kalman Filter algorithm
818  if (ALIGN_WIRE_PLANES) DoFilterAnodePlanes(t0,my_z,S,hits);
819  else DoFilterCathodePlanes(t0,my_z,S,hits);
820  }
821  } //loop over tracks
822  } // minimimum number of pseudopoints?
823 
824  return NOERROR;
825 }
826 
827 // Steering routine for the kalman filter
828 jerror_t
830  vector<const DCDCTrackHit *>&hits){
831  unsigned int numhits=hits.size();
832  unsigned int maxindex=numhits-1;
833 
834  int NEVENTS=100000;
835  double anneal_factor=pow(1e4,(double(NEVENTS-myevt))/(NEVENTS-1.));
836  if (myevt>NEVENTS) anneal_factor=1.;
837  anneal_factor=1.;
838  if (RUN_BENCHMARK) anneal_factor=1.;
839 
840  // deques to store reference trajectories
841  deque<trajectory_t>trajectory;
842  deque<trajectory_t>best_traj;
843 
844  // State vector to store "best" values
845  DMatrix4x1 Sbest;
846 
847  // Covariance matrix
848  DMatrix4x4 C0,C,Cbest;
849  C0(state_x,state_x)=C0(state_y,state_y)=1.0;
850  C0(state_tx,state_tx)=C0(state_ty,state_ty)=0.01;
851 
852  vector<cdc_update_t>updates(hits.size());
853  vector<cdc_update_t>best_updates;
854  double chi2=1e16,chi2_old=1e16;
855  unsigned int ndof=0,ndof_old=0;
856  unsigned int iter=0;
857 
858  //printf("wirebased-----------\n");
859 
860  // Perform a wire-based pass
861  for(iter=0;iter<20;iter++){
862  chi2_old=chi2;
863  ndof_old=ndof;
864 
865  trajectory.clear();
866  if (SetReferenceTrajectory(t0,OuterZ,S,trajectory,
867  hits[maxindex])!=NOERROR) break;
868 
869  C=C0;
870  if (KalmanFilter(anneal_factor,S,C,hits,trajectory,updates,chi2,ndof)!=NOERROR)
871  break;
872 
873  //printf(">>>>>>chi2 %f ndof %d\n",chi2,ndof);
874 
875  if (fabs(chi2_old-chi2)<0.1 || chi2>chi2_old) break;
876 
877  // Save the current state and covariance matrixes
878  Cbest=C;
879  Sbest=S;
880  best_updates.assign(updates.begin(),updates.end());
881  best_traj.assign(trajectory.begin(),trajectory.end());
882 
883  // run the smoother (opposite direction to filter)
884  //Smooth(S,C,trajectory,updates);
885  }
886  if (iter>0){
887  double prelimprob=TMath::Prob(chi2_old,ndof_old);
888  Hcdc_prelimprob->Fill(prelimprob);
889 
890  if (prelimprob>0.0001){
891 
892  // Perform a time-based pass
893  S=Sbest;
894  chi2=1e16;
895 
896  //printf("Timebased-----------\n");
897  //if (false)
898  for (iter=0;iter<20;iter++){
899  chi2_old=chi2;
900  ndof_old=ndof;
901 
902  trajectory.clear();
903  if (SetReferenceTrajectory(t0,OuterZ,S,trajectory,hits[maxindex])
904  ==NOERROR){
905  C=C0;
906  KalmanFilter(anneal_factor,S,C,hits,trajectory,updates,chi2,ndof,true);
907 
908  //printf(">>>>>>chi2 %f ndof %d\n",chi2,ndof);
909  if (fabs(chi2-chi2_old)<0.1
910  || TMath::Prob(chi2,ndof)<TMath::Prob(chi2_old,ndof_old)) break;
911 
912  Sbest=S;
913  Cbest=C;
914  best_updates.assign(updates.begin(),updates.end());
915  best_traj.assign(trajectory.begin(),trajectory.end());
916  }
917  else break;
918  }
919  if (iter>0){
920  double prob=TMath::Prob(chi2_old,ndof_old);
921  Hcdc_prob->Fill(prob);
922 
923  PlotLines(trajectory);
924 
925  if (prob>1e-3)
926  {
927  // run the smoother (opposite direction to filter)
928  vector<cdc_update_t>smoothed_updates(updates.size());
929  for (unsigned int k=0;k<smoothed_updates.size();k++){
930  smoothed_updates[k].used_in_fit=false;
931  }
932  Smooth(Sbest,Cbest,best_traj,hits,best_updates,smoothed_updates);
933 
934  for (unsigned int k=0;k<smoothed_updates.size();k++){
935  if (smoothed_updates[k].used_in_fit==true){
936  double tdrift=smoothed_updates[k].drift_time;
937  double d=smoothed_updates[k].doca;
938  double res=smoothed_updates[k].res;
939  int ring_id=smoothed_updates[k].ring_id;
940  int straw_id=smoothed_updates[k].straw_id;
941  Hcdcres_vs_drift_time->Fill(tdrift,res);
942  Hcdcres_vs_d->Fill(d,res);
943  Hcdcdrift_time->Fill(tdrift,d);
944  Hcdc_time_vs_d->Fill(d,tdrift);
945  Hcdc_ring_res[ring_id]->Fill(straw_id+1,res);
946  Hcdc_ring_time[ring_id]->Fill(straw_id+1,tdrift);
947  }
948  }
949 
950  if (prob>0.001 && RUN_BENCHMARK==false){
951  FindOffsets(hits,smoothed_updates);
952 
953  if (FILL_TREE){
954  for (unsigned int ring=0;ring<cdc_alignments.size();ring++){
955  for (unsigned int straw=0;straw<cdc_alignments[ring].size();
956  straw++){
957  // Set up to fill tree
958  cdc.dXu=cdc_alignments[ring][straw].A(k_dXu);
959  cdc.dYu=cdc_alignments[ring][straw].A(k_dYu);
960  cdc.dXd=cdc_alignments[ring][straw].A(k_dXd);
961  cdc.dYd=cdc_alignments[ring][straw].A(k_dYd);
962  cdc.straw=straw+1;
963  cdc.ring=ring+1;
964  cdc.N=myevt;
965 
966 
967  // Although we are only filling objects local to this plugin, TTree::Fill() periodically writes to file: Global ROOT lock
968  japp->RootWriteLock(); //ACQUIRE ROOT LOCK
969 
970  cdctree->Fill();
971 
972  japp->RootUnLock(); //RELEASE ROOT LOCK
973 
974  }
975  }
976  }
977  }
978 
979  } // check on final fit CL
980  } // at least one time-based fit worked?
981  } // check on preliminary fit CL
982  } // at least one iteration worked?
983 
984  return NOERROR;
985 }
986 
987 
988 // Steering routine for the kalman filter
989 jerror_t
991  DMatrix4x1 &S,
992  vector<const DFDCPseudo *>&hits){
993  unsigned int num_hits=hits.size();
994  vector<update_t>updates(num_hits);
995  vector<update_t>best_updates;
996  vector<update_t>smoothed_updates(num_hits);
997 
998  int NEVENTS=100000;
999  double anneal_factor=pow(1e3,(double(NEVENTS-myevt))/(NEVENTS-1.));
1000  if (myevt>NEVENTS) anneal_factor=1.;
1001  //anneal_factor=10.;
1002  if (RUN_BENCHMARK) anneal_factor=1.;
1003  //anneal_factor=1e3;
1004 
1005  // Best guess for state vector at the beginning of the trajectory
1006  DMatrix4x1 Sbest;
1007 
1008  // Use the result from the initial line fit to form a reference trajectory
1009  // for the track.
1010  deque<trajectory_t>trajectory;
1011  deque<trajectory_t>best_traj;
1012 
1013  // Intial guess for covariance matrix
1014  DMatrix4x4 C,C0,Cbest;
1015  C0(state_x,state_x)=C0(state_y,state_y)=1.;
1016  C0(state_tx,state_tx)=C0(state_ty,state_ty)=0.01;
1017 
1018  // Chi-squared and degrees of freedom
1019  double chi2=1e16,chi2_old=1e16;
1020  unsigned int ndof=0,ndof_old=0;
1021  unsigned iter=0;
1022  for(;;){
1023  iter++;
1024  chi2_old=chi2;
1025  ndof_old=ndof;
1026 
1027  trajectory.clear();
1028  if (SetReferenceTrajectory(t0,start_z,S,trajectory,hits)!=NOERROR) break;
1029  C=C0;
1030  if (KalmanFilter(anneal_factor,S,C,hits,trajectory,updates,chi2,ndof)
1031  !=NOERROR) break;
1032 
1033  //printf("== event %d == iter %d =====chi2 %f ndof %d \n",myevt,iter,chi2,ndof);
1034  if (chi2>chi2_old || fabs(chi2_old-chi2)<0.1 || iter==ITER_MAX) break;
1035 
1036  // Save the current state and covariance matrixes
1037  Cbest=C;
1038  Sbest=S;
1039  best_updates.assign(updates.begin(),updates.end());
1040  best_traj.assign(trajectory.begin(),trajectory.end());
1041  // run the smoother (opposite direction to filter)
1042  //Smooth(S,C,trajectory,hits,updates,smoothed_updates);
1043  }
1044 
1045  if (iter>1){
1046  double prob=TMath::Prob(chi2_old,ndof_old);
1047  Hpseudo_prob->Fill(prob);
1048 
1049  // printf("prob %f\n",prob);
1050 
1051  PlotLines(trajectory);
1052 
1053  if (prob>0.00001)
1054  {
1055  // run the smoother (opposite direction to filter)
1056  Smooth(Sbest,Cbest,best_traj,hits,best_updates,smoothed_updates);
1057 
1058  //Hbeta->Fill(mBeta);
1059  for (unsigned int i=0;i<smoothed_updates.size();i++){
1060  unsigned int layer=hits[i]->wire->layer;
1061 
1062  Hures_vs_layer->Fill(layer,smoothed_updates[i].res(0));
1063  Hvres_vs_layer->Fill(layer,smoothed_updates[i].res(1));
1064  Hdv_vs_dE->Fill(hits[i]->dE,smoothed_updates[i].res(1));
1065 
1066  Hdrift_time->Fill(smoothed_updates[i].drift_time,
1067  smoothed_updates[i].doca);
1068  }
1069 
1070  if (prob>0.001 && RUN_BENCHMARK==false){
1071  FindOffsets(hits,smoothed_updates);
1072 
1073  if (FILL_TREE){
1074  for (unsigned int layer=0;layer<24;layer++){
1075  fdc_c.dPhiU=fdc_cathode_alignments[layer].A(kPhiU);
1076  fdc_c.dU=fdc_cathode_alignments[layer].A(kU);
1077  fdc_c.dPhiV=fdc_cathode_alignments[layer].A(kPhiV);
1078  fdc_c.dV=fdc_cathode_alignments[layer].A(kV);
1079 
1080  fdc_c.layer=layer+1;
1081  fdc_c.N=myevt;
1082 
1083  // Although we are only filling objects local to this plugin, TTree::Fill() periodically writes to file: Global ROOT lock
1084  japp->RootWriteLock(); //ACQUIRE ROOT LOCK
1085 
1086  fdcCtree->Fill();
1087 
1088  japp->RootUnLock(); //RELEASE ROOT LOCK
1089  }
1090  }
1091  }
1092  return NOERROR;
1093  }
1094  }
1095 
1096 
1097  return VALUE_OUT_OF_RANGE;
1098 }
1099 
1100 // Steering routine for the kalman filter
1101 jerror_t
1103  DMatrix4x1 &S,
1104  vector<const DFDCPseudo *>&hits){
1105  unsigned int num_hits=hits.size();
1106  vector<wire_update_t>updates(num_hits);
1107  vector<wire_update_t>best_updates;
1108  vector<wire_update_t>smoothed_updates(num_hits);
1109 
1110  int NEVENTS=75000;
1111  double anneal_factor=1.;
1112  if (USE_DRIFT_TIMES){
1113  anneal_factor=pow(1000.,(double(NEVENTS-myevt))/(NEVENTS-1.));
1114  if (myevt>NEVENTS) anneal_factor=1.;
1115  }
1116  if (RUN_BENCHMARK) anneal_factor=1.;
1117  //anneal_factor=1e3;
1118 
1119  // Best guess for state vector at "vertex"
1120  DMatrix4x1 Sbest;
1121 
1122  // Use the result from the initial line fit to form a reference trajectory
1123  // for the track.
1124  deque<trajectory_t>trajectory;
1125  deque<trajectory_t>best_traj;
1126 
1127  // Intial guess for covariance matrix
1128  DMatrix4x4 C,C0,Cbest;
1129  C0(state_x,state_x)=C0(state_y,state_y)=1.;
1130  C0(state_tx,state_tx)=C0(state_ty,state_ty)=0.001;
1131 
1132  // Chi-squared and degrees of freedom
1133  double chi2=1e16,chi2_old=1e16;
1134  unsigned int ndof=0,ndof_old=0;
1135  unsigned iter=0;
1136  for(;;){
1137  iter++;
1138  chi2_old=chi2;
1139  ndof_old=ndof;
1140 
1141  trajectory.clear();
1142  if (SetReferenceTrajectory(t0,start_z,S,trajectory,hits)!=NOERROR) break;
1143  C=C0;
1144  if (KalmanFilter(anneal_factor,S,C,hits,trajectory,updates,chi2,ndof)
1145  !=NOERROR) break;
1146 
1147  //printf("== event %d == iter %d =====chi2 %f ndof %d \n",myevt,iter,chi2,ndof);
1148  if (chi2>chi2_old || iter==ITER_MAX) break;
1149 
1150  // Save the current state and covariance matrixes
1151  Cbest=C;
1152  Sbest=S;
1153  best_updates.assign(updates.begin(),updates.end());
1154  best_traj.assign(trajectory.begin(),trajectory.end());
1155  // run the smoother (opposite direction to filter)
1156  //Smooth(S,C,trajectory,hits,updates,smoothed_updates);
1157  }
1158 
1159  if (iter>1){
1160  double prob=TMath::Prob(chi2_old,ndof_old);
1161  Hprob->Fill(prob);
1162 
1163  PlotLines(trajectory);
1164 
1165  if (prob>0.001)
1166  {
1167  // run the smoother (opposite direction to filter)
1168  Smooth(Sbest,Cbest,best_traj,hits,best_updates,smoothed_updates);
1169 
1170  //Hbeta->Fill(mBeta);
1171  for (unsigned int i=0;i<smoothed_updates.size();i++){
1172  unsigned int layer=hits[i]->wire->layer;
1173 
1174  Hres_vs_layer->Fill(layer,smoothed_updates[i].ures);
1175  if (prob>0.1/*&&layer==smoothed_updates.size()/2*/){
1176  Hdrift_time->Fill(smoothed_updates[i].drift_time,
1177  smoothed_updates[i].doca);
1178  Hres_vs_drift_time->Fill(smoothed_updates[i].drift_time,
1179  smoothed_updates[i].ures);
1180 
1181  }
1182 
1183  }
1184 
1185  if (RUN_BENCHMARK==false){
1186  FindOffsets(hits,smoothed_updates);
1187 
1188  if (FILL_TREE){
1189  for (unsigned int layer=0;layer<24;layer++){
1190  fdc.dPhi=fdc_alignments[layer].A(kPhiU);
1191  fdc.dX=fdc_alignments[layer].A(kU);
1192 
1193  fdc.layer=layer+1;
1194  fdc.N=myevt;
1195 
1196  // Although we are only filling objects local to this plugin, TTree::Fill() periodically writes to file: Global ROOT lock
1197  japp->RootWriteLock(); //ACQUIRE ROOT LOCK
1198 
1199  fdctree->Fill();
1200 
1201  japp->RootUnLock(); //RELEASE ROOT LOCK
1202  }
1203  }
1204  }
1205  return NOERROR;
1206 
1207  }
1208  }
1209 
1210 
1211  return VALUE_OUT_OF_RANGE;
1212 }
1213 
1214 
1215 // Kalman smoother
1217  deque<trajectory_t>&trajectory,
1218  vector<const DFDCPseudo *>&hits,
1219  vector<update_t>updates,
1220  vector<update_t>&smoothed_updates
1221  ){
1222  DMatrix4x1 S;
1223  DMatrix4x4 C,dC;
1224  DMatrix4x4 JT,A;
1225  DMatrix2x1 Mdiff;
1226 
1227  unsigned int max=trajectory.size()-1;
1228  S=(trajectory[max].Skk);
1229  C=(trajectory[max].Ckk);
1230  JT=(trajectory[max].J.Transpose());
1231  //Ss=S;
1232  //Cs=C;
1233  for (unsigned int m=max-1;m>0;m--){
1234  if (trajectory[m].h_id==0){
1235  A=trajectory[m].Ckk*JT*C.Invert();
1236  Ss=trajectory[m].Skk+A*(Ss-S);
1237  Cs=trajectory[m].Ckk+A*(Cs-C)*A.Transpose();
1238  }
1239  else if (trajectory[m].h_id>0){
1240  unsigned int first_id=trajectory[m].h_id-1;
1241  for (int k=trajectory[m].num_hits-1;k>=0;k--){
1242  unsigned int id=first_id+k;
1243  A=updates[id].C*JT*C.Invert();
1244  dC=A*(Cs-C)*A.Transpose();
1245  Ss=updates[id].S+A*(Ss-S);
1246  Cs=updates[id].C+dC;
1247 
1248  // Nominal rotation of wire planes
1249  double cosa=hits[id]->wire->udir.y();
1250  double sina=hits[id]->wire->udir.x();
1251 
1252  // State vector
1253  double x=Ss(state_x);
1254  double y=Ss(state_y);
1255  double tx=Ss(state_tx);
1256  double ty=Ss(state_ty);
1257 
1258  // Get the aligment parameters for this layer
1259  unsigned int layer=hits[id]->wire->layer-1;
1260  DMatrix4x1 A=fdc_cathode_alignments[layer].A;
1261  DMatrix2x1 Aw=fdc_alignments[layer].A;
1262  double delta_u=Aw(kU);
1263  double sindphi=sin(Aw(kPhiU));
1264  double cosdphi=cos(Aw(kPhiU));
1265 
1266  // Components of rotation matrix for converting global to local coords.
1267  double cospsi=cosa*cosdphi+sina*sindphi;
1268  double sinpsi=sina*cosdphi-cosa*sindphi;
1269 
1270  // x,y and tx,ty in local coordinate system
1271  // To transform from (x,y) to (u,v), need to do a rotation:
1272  // u = x*cosa-y*sina
1273  // v = y*cosa+x*sina
1274  double upred_wire_plane=x*cospsi-y*sinpsi;
1275  double vpred_wire_plane=x*sinpsi+y*cospsi;
1276  double tu=tx*cospsi-ty*sinpsi;
1277  double tv=tx*sinpsi+ty*cospsi;
1278 
1279  // Variables for angle of incidence with respect to the z-direction in
1280  // the u-z plane
1281  double alpha=atan(tu);
1282  double cosalpha=cos(alpha);
1283  double sinalpha=sin(alpha);
1284 
1285  // Doca from wire
1286  double uwire=hits[id]->wire->u+delta_u;
1287  double d=(upred_wire_plane-uwire)*cosalpha;
1288 
1289  // Predicted avalanche position along the wire
1290  double vpred=vpred_wire_plane-tv*sinalpha*d;
1291 
1292  // predicted positions in two cathode planes' coordinate systems
1293  double phi_u=hits[id]->phi_u+A(kPhiU);
1294  double phi_v=hits[id]->phi_v+A(kPhiV);
1295  double cosphi_u=cos(phi_u);
1296  double sinphi_u=sin(phi_u);
1297  double cosphi_v=cos(phi_v);
1298  double sinphi_v=sin(phi_v);
1299  double vv=-vpred*sinphi_v+uwire*cosphi_v+A(kV);
1300  double vu=-vpred*sinphi_u+uwire*cosphi_u+A(kU);
1301 
1302  // Difference between measurements and predictions
1303  Mdiff(0)=hits[id]->u-vu;
1304  Mdiff(1)=hits[id]->v-vv;
1305 
1306  smoothed_updates[id].res=Mdiff;
1307  smoothed_updates[id].doca=fabs(d);
1308 
1309  smoothed_updates[id].drift=updates[id].drift;
1310  smoothed_updates[id].drift_time=updates[id].drift_time;
1311  smoothed_updates[id].S=Ss;
1312  smoothed_updates[id].C=Cs;
1313  smoothed_updates[id].V=updates[id].V-updates[id].H*dC*updates[id].H_T;
1314  }
1315  }
1316  S=trajectory[m].Skk;
1317  C=trajectory[m].Ckk;
1318  JT=trajectory[m].J.Transpose();
1319  }
1320 
1321  A=trajectory[0].Ckk*JT*C.Invert();
1322  Ss=trajectory[0].Skk+A*(Ss-S);
1323  Cs=trajectory[0].Ckk+A*(Cs-C)*A.Transpose();
1324 
1325  return NOERROR;
1326 }
1327 
1328 
1329 // Kalman smoother
1331  deque<trajectory_t>&trajectory,
1332  vector<const DFDCPseudo *>&hits,
1333  vector<wire_update_t>updates,
1334  vector<wire_update_t>&smoothed_updates
1335  ){
1336  DMatrix4x1 S;
1337  DMatrix4x4 C,dC;
1338  DMatrix4x4 JT,A;
1339 
1340  unsigned int max=trajectory.size()-1;
1341  S=(trajectory[max].Skk);
1342  C=(trajectory[max].Ckk);
1343  JT=(trajectory[max].J.Transpose());
1344  //Ss=S;
1345  //Cs=C;
1346  for (unsigned int m=max-1;m>0;m--){
1347  if (trajectory[m].h_id==0){
1348  A=trajectory[m].Ckk*JT*C.Invert();
1349  Ss=trajectory[m].Skk+A*(Ss-S);
1350  Cs=trajectory[m].Ckk+A*(Cs-C)*A.Transpose();
1351  }
1352  else if (trajectory[m].h_id>0){
1353  unsigned int first_id=trajectory[m].h_id-1;
1354  for (int k=trajectory[m].num_hits-1;k>=0;k--){
1355  unsigned int id=first_id+k;
1356  A=updates[id].C*JT*C.Invert();
1357  dC=A*(Cs-C)*A.Transpose();
1358  Ss=updates[id].S+A*(Ss-S);
1359  Cs=updates[id].C+dC;
1360 
1361  // Nominal rotation of wire planes
1362  double cosa=hits[id]->wire->udir.y();
1363  double sina=hits[id]->wire->udir.x();
1364 
1365  // State vector
1366  double x=Ss(state_x);
1367  double y=Ss(state_y);
1368  double tx=Ss(state_tx);
1369  double ty=Ss(state_ty);
1370 
1371  // Get the aligment vector and error matrix for this layer
1372  unsigned int layer=hits[id]->wire->layer-1;
1373  DMatrix2x2 E=fdc_alignments[layer].E;
1374  DMatrix2x1 A=fdc_alignments[layer].A;
1375  double delta_u=A(kU);
1376  double sindphi=sin(A(kPhiU));
1377  double cosdphi=cos(A(kPhiU));
1378 
1379  // Components of rotation matrix for converting global to local coords.
1380  double cospsi=cosa*cosdphi+sina*sindphi;
1381  double sinpsi=sina*cosdphi-cosa*sindphi;
1382 
1383  // x,y and tx,ty in local coordinate system
1384  // To transform from (x,y) to (u,v), need to do a rotation:
1385  // u = x*cosa-y*sina
1386  // v = y*cosa+x*sina
1387  // (without alignment offsets)
1388  double upred=x*cospsi-y*sinpsi;
1389  double tu=tx*cospsi-ty*sinpsi;
1390 
1391  // Variables for angle of incidence with respect to the z-direction in
1392  // the u-z plane
1393  double alpha=atan(tu);
1394  double cosalpha=cos(alpha);
1395 
1396  // Smoothed residuals
1397  double uwire=hits[id]->wire->u+delta_u;
1398  double d=(upred-uwire)*cosalpha;
1399  smoothed_updates[id].ures=(d>0?1.:-1.)*updates[id].drift-d;
1400  smoothed_updates[id].doca=fabs(d);
1401 
1402  smoothed_updates[id].drift=updates[id].drift;
1403  smoothed_updates[id].drift_time=updates[id].drift_time;
1404  smoothed_updates[id].S=Ss;
1405  smoothed_updates[id].C=Cs;
1406  smoothed_updates[id].R=updates[id].R-updates[id].H*dC*updates[id].H_T;
1407  }
1408  }
1409  S=trajectory[m].Skk;
1410  C=trajectory[m].Ckk;
1411  JT=trajectory[m].J.Transpose();
1412  }
1413 
1414  A=trajectory[0].Ckk*JT*C.Invert();
1415  Ss=trajectory[0].Skk+A*(Ss-S);
1416  Cs=trajectory[0].Ckk+A*(Cs-C)*A.Transpose();
1417 
1418  return NOERROR;
1419 }
1420 
1421 // Kalman smoother
1422 jerror_t
1424  deque<trajectory_t>&trajectory,
1425  vector<const DCDCTrackHit *>&hits,
1426  vector<cdc_update_t>&updates,
1427  vector<cdc_update_t>&smoothed_updates
1428  ){
1429  DMatrix4x1 S;
1430  DMatrix4x4 C,dC;
1431  DMatrix4x4 JT,A;
1432 
1433  unsigned int max=trajectory.size()-1;
1434  S=(trajectory[max].Skk);
1435  C=(trajectory[max].Ckk);
1436  JT=(trajectory[max].J.Transpose());
1437  //Ss=S;
1438  //Cs=C;
1439  //printf("--------\n");
1440  for (unsigned int m=max-1;m>0;m--){
1441  if (trajectory[m].h_id==0){
1442  A=trajectory[m].Ckk*JT*C.Invert();
1443  Ss=trajectory[m].Skk+A*(Ss-S);
1444  Cs=trajectory[m].Ckk+A*(Cs-C)*A.Transpose();
1445  }
1446  else{
1447  unsigned int id=trajectory[m].h_id-1;
1448  smoothed_updates[id].used_in_fit=false;
1449  //printf("%d:%d used ? %d\n",m,id,updates[id].used_in_fit);
1450  if (updates[id].used_in_fit){
1451  smoothed_updates[id].used_in_fit=true;
1452 
1453  A=updates[id].C*JT*C.Invert();
1454  dC=A*(Cs-C)*A.Transpose();
1455  Ss=updates[id].S+A*(Ss-S);
1456  Cs=updates[id].C+dC;
1457 
1458  // CDC index and wire position variables
1459  const DCDCWire *wire=hits[id]->wire;
1460  DVector3 origin=wire->origin;
1461  DVector3 wdir=wire->udir;
1462 
1463  unsigned int ring=hits[id]->wire->ring-1;
1464  unsigned int straw=hits[id]->wire->straw-1;
1465  UpdateWireOriginAndDir(ring,straw,origin,wdir);
1466 
1467  // doca using smoothed state vector
1468  double d=finder->FindDoca(trajectory[m].z,Ss,wdir,origin);
1469  smoothed_updates[id].ring_id=ring;
1470  smoothed_updates[id].straw_id=straw;
1471  smoothed_updates[id].doca=d;
1472  smoothed_updates[id].res=updates[id].drift-d;
1473  smoothed_updates[id].drift=updates[id].drift;
1474  smoothed_updates[id].drift_time=updates[id].drift_time;
1475  smoothed_updates[id].S=Ss;
1476  smoothed_updates[id].C=Cs;
1477  smoothed_updates[id].V=updates[id].V-updates[id].H*dC*updates[id].H_T;
1478  smoothed_updates[id].z=updates[id].z;
1479 
1480  // Reset h_id for this position along the reference trajectory
1481  trajectory[m].h_id=0;
1482  }
1483  else{
1484  A=trajectory[m].Ckk*JT*C.Invert();
1485  Ss=trajectory[m].Skk+A*(Ss-S);
1486  Cs=trajectory[m].Ckk+A*(Cs-C)*A.Transpose();
1487  }
1488  }
1489 
1490  S=trajectory[m].Skk;
1491  C=trajectory[m].Ckk;
1492  JT=trajectory[m].J.Transpose();
1493  }
1494 
1495  A=trajectory[0].Ckk*JT*C.Invert();
1496  Ss=trajectory[0].Skk+A*(Ss-S);
1497  Cs=trajectory[0].Ckk+A*(Cs-C)*A.Transpose();
1498 
1499  return NOERROR;
1500 }
1501 
1502 // Perform the Kalman Filter for the current set of cdc hits
1503 jerror_t
1505  DMatrix4x1 &S,DMatrix4x4 &C,
1506  vector<const DCDCTrackHit *>&hits,
1507  deque<trajectory_t>&trajectory,
1508  vector<cdc_update_t>&updates,
1509  double &chi2,unsigned int &ndof,
1510  bool timebased){
1511  DMatrix1x4 H; // Track projection matrix
1512  DMatrix4x1 H_T; // Transpose of track projection matrix
1513  DMatrix4x1 K; // Kalman gain matrix
1514  DMatrix4x4 I; // identity matrix
1515  DMatrix4x4 J; // Jacobian matrix
1516  DMatrix4x1 S0; // State vector from reference trajectory
1517  double V=1.15*(0.78*0.78/12.); // sigma=cell_size/sqrt(12.)*scale_factor
1518 
1519  for (unsigned int i=0;i<updates.size();i++){
1520  updates[i].used_in_fit=false;
1521  }
1522 
1523  //Initialize chi2 and ndof
1524  chi2=0.;
1525  ndof=0;
1526 
1527  double doca2=0.;
1528  const double d_EPS=1e-8;
1529 
1530  // CDC index and wire position variables
1531  unsigned int cdc_index=hits.size()-1;
1532  bool more_hits=true;
1533  const DCDCWire *wire=hits[cdc_index]->wire;
1534  DVector3 origin=wire->origin;
1535  double z0=origin.z();
1536  double vz=wire->udir.z();
1537  DVector3 wdir=(1./vz)*wire->udir;
1538 
1539  // Wire offsets
1540  unsigned int ring=wire->ring-1;
1541  unsigned int straw=wire->straw-1;
1542  UpdateWireOriginAndDir(ring,straw,origin,wdir);
1543 
1544  DVector3 wirepos=origin+(trajectory[0].z-z0)*wdir;
1545 
1546  /// compute initial doca^2 to first wire
1547  double dx=S(state_x)-wirepos.X();
1548  double dy=S(state_y)-wirepos.Y();
1549  double old_doca2=dx*dx+dy*dy;
1550 
1551  // Loop over all steps in the trajectory
1552  S0=trajectory[0].S;
1553  J=trajectory[0].J;
1554  trajectory[0].Skk=S;
1555  trajectory[0].Ckk=C;
1556  for (unsigned int k=1;k<trajectory.size();k++){
1557  if (C(0,0)<=0. || C(1,1)<=0. || C(2,2)<=0. || C(3,3)<=0.)
1558  return UNRECOVERABLE_ERROR;
1559 
1560  // Propagate the state and covariance matrix forward in z
1561  S=trajectory[k].S+J*(S-S0);
1562  C=J*C*J.Transpose();
1563 
1564  // Save the current state and covariance matrix
1565  trajectory[k].Skk=S;
1566  trajectory[k].Ckk=C;
1567 
1568  // Save S and J for the next step
1569  S0=trajectory[k].S;
1570  J=trajectory[k].J;
1571 
1572  // Position along wire
1573  wirepos=origin+(trajectory[k].z-z0)*wdir;
1574 
1575  // New doca^2
1576  dx=S(state_x)-wirepos.X();
1577  dy=S(state_y)-wirepos.Y();
1578  doca2=dx*dx+dy*dy;
1579 
1580  if (doca2>old_doca2 && more_hits){
1581 
1582  // zero-position and direction of line describing particle trajectory
1583  double tx=S(state_tx),ty=S(state_ty);
1584  DVector3 pos0(S(state_x),S(state_y),trajectory[k].z);
1585  DVector3 tdir(tx,ty,1.);
1586 
1587  // Find the true doca to the wire
1588  DVector3 diff=pos0-origin;
1589  double dx0=diff.x(),dy0=diff.y();
1590  double wdir_dot_diff=diff.Dot(wdir);
1591  double tdir_dot_diff=diff.Dot(tdir);
1592  double tdir_dot_wdir=tdir.Dot(wdir);
1593  double tdir2=tdir.Mag2();
1594  double wdir2=wdir.Mag2();
1595  double D=tdir2*wdir2-tdir_dot_wdir*tdir_dot_wdir;
1596  double N=tdir_dot_wdir*wdir_dot_diff-wdir2*tdir_dot_diff;
1597  double N1=tdir2*wdir_dot_diff-tdir_dot_wdir*tdir_dot_diff;
1598  double scale=1./D;
1599  double s=scale*N;
1600  double t=scale*N1;
1601  diff+=s*tdir-t*wdir;
1602  double d=diff.Mag()+d_EPS; // prevent division by zero
1603 
1604  // The next measurement and its variance
1605  double tdrift=hits[cdc_index]->tdrift-trajectory[k].t;
1606  double dmeas=0.39;
1607  if (timebased){
1608  double drift_var=cdc_variance(tdrift);
1609  V=anneal_factor*drift_var;
1610 
1611  double phi_d=diff.Phi();
1612  double dphi=phi_d-origin.Phi();
1613  while (dphi>M_PI) dphi-=2*M_PI;
1614  while (dphi<-M_PI) dphi+=2*M_PI;
1615 
1616  int ring_index=hits[cdc_index]->wire->ring-1;
1617  int straw_index=hits[cdc_index]->wire->straw-1;
1618  double dz=t*wdir.z();
1619  double delta=max_sag[ring_index][straw_index]*(1.-dz*dz/5625.)
1620  *sin(phi_d+sag_phi_offset[ring_index][straw_index]);
1621  dmeas=cdc_drift_distance(dphi,delta,tdrift);
1622 
1623  //printf("t %f d %f %f V %f\n",hits[cdc_index]->tdrift,dmeas,d,V);
1624  }
1625 
1626  // residual
1627  double res=dmeas-d;
1628 
1629  // Track projection
1630  double one_over_d=1./d;
1631  double diffx=diff.x(),diffy=diff.y(),diffz=diff.z();
1632  double wx=wdir.x(),wy=wdir.y();
1633 
1634  double dN1dtx=2.*tx*wdir_dot_diff-wx*tdir_dot_diff-tdir_dot_wdir*dx0;
1635  double dDdtx=2.*tx*wdir2-2.*tdir_dot_wdir*wx;
1636  double dtdtx=scale*(dN1dtx-t*dDdtx);
1637 
1638  double dN1dty=2.*ty*wdir_dot_diff-wy*tdir_dot_diff-tdir_dot_wdir*dy0;
1639  double dDdty=2.*ty*wdir2-2.*tdir_dot_wdir*wy;
1640  double dtdty=scale*(dN1dty-t*dDdty);
1641 
1642  double dNdtx=wx*wdir_dot_diff-wdir2*dx0;
1643  double dsdtx=scale*(dNdtx-s*dDdtx);
1644 
1645  double dNdty=wy*wdir_dot_diff-wdir2*dy0;
1646  double dsdty=scale*(dNdty-s*dDdty);
1647 
1648  H(state_tx)=H_T(state_tx)
1649  =one_over_d*(diffx*(s+tx*dsdtx-wx*dtdtx)+diffy*(ty*dsdtx-wy*dtdtx)
1650  +diffz*(dsdtx-dtdtx));
1651  H(state_ty)=H_T(state_ty)
1652  =one_over_d*(diffx*(tx*dsdty-wx*dtdty)+diffy*(s+ty*dsdty-wy*dtdty)
1653  +diffz*(dsdty-dtdty));
1654 
1655  double dsdx=scale*(tdir_dot_wdir*wx-wdir2*tx);
1656  double dtdx=scale*(tdir2*wx-tdir_dot_wdir*tx);
1657  double dsdy=scale*(tdir_dot_wdir*wy-wdir2*ty);
1658  double dtdy=scale*(tdir2*wy-tdir_dot_wdir*ty);
1659 
1660  H(state_x)=H_T(state_x)
1661  =one_over_d*(diffx*(1.+dsdx*tx-dtdx*wx)+diffy*(dsdx*ty-dtdx*wy)
1662  +diffz*(dsdx-dtdx));
1663  H(state_y)=H_T(state_y)
1664  =one_over_d*(diffx*(dsdy*tx-dtdy*wx)+diffy*(1.+dsdy*ty-dtdy*wy)
1665  +diffz*(dsdy-dtdy));
1666 
1667  // Matrices to rotate alignment error matrix into measurement space
1668  DMatrix1x4 G;
1669  DMatrix4x1 G_T;
1670  ComputeGMatrices(s,t,scale,tx,ty,tdir2,one_over_d,wx,wy,wdir2,tdir_dot_wdir,
1671  tdir_dot_diff,wdir_dot_diff,dx0,dy0,diffx,diffy,diffz,
1672  G,G_T);
1673 
1674  // inverse of variance including prediction
1675  DMatrix4x4 E=cdc_alignments[ring][straw].E;
1676  double Vtemp=V+G*E*G_T;
1677  double InvV=1./(Vtemp+H*C*H_T);
1678 
1679  // Compute Kalman gain matrix
1680  K=InvV*(C*H_T);
1681 
1682  // Update state vector covariance matrix
1683  DMatrix4x4 Ctest=C-K*(H*C);
1684 
1685  //C.Print();
1686  //K.Print();
1687  //Ctest.Print();
1688 
1689  // Check that Ctest is positive definite
1690  if (Ctest(0,0)>0.0 && Ctest(1,1)>0.0 && Ctest(2,2)>0.0 && Ctest(3,3)>0.0)
1691  {
1692  C=Ctest;
1693 
1694  // Update the state vector
1695  //S=S+res*K;
1696  S+=res*K;
1697 
1698  // Compute new residual
1699  d=finder->FindDoca(trajectory[k].z,S,wdir,origin);
1700  res=dmeas-d;
1701 
1702  // Update chi2 for this segment
1703  Vtemp-=H*C*H_T;
1704  chi2+=res*res/Vtemp;
1705  ndof++;
1706  }
1707  else{
1708  // _DBG_ << "Bad C!" << endl;
1709  return VALUE_OUT_OF_RANGE;
1710  }
1711 
1712  updates[cdc_index].S=S;
1713  updates[cdc_index].C=C;
1714  updates[cdc_index].drift=dmeas;
1715  updates[cdc_index].drift_time=tdrift;
1716  updates[cdc_index].doca=d;
1717  updates[cdc_index].res=res;
1718  updates[cdc_index].V=Vtemp;
1719  updates[cdc_index].H_T=H_T;
1720  updates[cdc_index].H=H;
1721  updates[cdc_index].z=trajectory[k].z;
1722  updates[cdc_index].used_in_fit=true;
1723 
1724  trajectory[k].h_id=cdc_index+1;
1725 
1726  // move to next cdc hit
1727  if (cdc_index>0){
1728  cdc_index--;
1729 
1730  //New wire position
1731  wire=hits[cdc_index]->wire;
1732  origin=wire->origin;
1733  vz=wire->udir.z();
1734  wdir=(1./vz)*wire->udir;
1735 
1736  ring=hits[cdc_index]->wire->ring-1;
1737  straw=hits[cdc_index]->wire->straw-1;
1738  UpdateWireOriginAndDir(ring,straw,origin,wdir);
1739 
1740  wirepos=origin+((trajectory[k].z-z0))*wdir;
1741 
1742  // New doca^2
1743  dx=S(state_x)-wirepos.x();
1744  dy=S(state_y)-wirepos.y();
1745  doca2=dx*dx+dy*dy;
1746 
1747  }
1748  else more_hits=false;
1749  }
1750 
1751  old_doca2=doca2;
1752  }
1753 
1754  ndof-=4;
1755 
1756  return NOERROR;
1757 }
1758 
1759 // Perform Kalman Filter for the current trajectory
1760 jerror_t
1762  DMatrix4x1 &S,DMatrix4x4 &C,
1763  vector<const DFDCPseudo *>&hits,
1764  deque<trajectory_t>&trajectory,
1765  vector<update_t>&updates,
1766  double &chi2,unsigned int &ndof){
1767  DMatrix2x4 H; // Track projection matrix
1768  DMatrix4x2 H_T; // Transpose of track projection matrix
1769  DMatrix4x2 K; // Kalman gain matrix
1770  DMatrix2x2 V(0.0008*anneal_factor,0.,0.,0.0008*anneal_factor); // Measurement variance
1771  DMatrix2x2 Vtemp,InvV;
1772  DMatrix2x1 Mdiff;
1773  DMatrix4x4 I; // identity matrix
1774  DMatrix4x4 J; // Jacobian matrix
1775  DMatrix4x1 S0; // State vector from reference trajectory
1776 
1777  //Initialize chi2 and ndof
1778  chi2=0.;
1779  ndof=0;
1780 
1781  // Loop over all steps in the trajectory
1782  S0=trajectory[0].S;
1783  J=trajectory[0].J;
1784  trajectory[0].Skk=S;
1785  trajectory[0].Ckk=C;
1786  for (unsigned int k=1;k<trajectory.size();k++){
1787  if (C(0,0)<=0. || C(1,1)<=0. || C(2,2)<=0. || C(3,3)<=0.)
1788  return UNRECOVERABLE_ERROR;
1789 
1790  // Propagate the state and covariance matrix forward in z
1791  S=trajectory[k].S+J*(S-S0);
1792  C=J*C*J.Transpose();
1793 
1794  // Save the current state and covariance matrix
1795  trajectory[k].Skk=S;
1796  trajectory[k].Ckk=C;
1797 
1798  // Save S and J for the next step
1799  S0=trajectory[k].S;
1800  J=trajectory[k].J;
1801 
1802  // Correct S and C for the hit
1803  if (trajectory[k].h_id>0){
1804  unsigned int id=trajectory[k].h_id-1;
1805 
1806  double cosa=hits[id]->wire->udir.y();
1807  double sina=hits[id]->wire->udir.x();
1808 
1809  // State vector
1810  double x=S(state_x);
1811  double y=S(state_y);
1812  double tx=S(state_tx);
1813  double ty=S(state_ty);
1814  if (std::isnan(x) || std::isnan(y)) return UNRECOVERABLE_ERROR;
1815 
1816  // Get the alignment vector and error matrix for this layer
1817  unsigned int layer=hits[id]->wire->layer-1;
1818  DMatrix2x1 Aw=fdc_alignments[layer].A;
1819  double delta_u=Aw(kU);
1820  double sindphi=sin(Aw(kPhiU));
1821  double cosdphi=cos(Aw(kPhiU));
1822 
1823  // Components of rotation matrix for converting global to local coords.
1824  double cospsi=cosa*cosdphi+sina*sindphi;
1825  double sinpsi=sina*cosdphi-cosa*sindphi;
1826 
1827  // x,y and tx,ty in local coordinate system
1828  // To transform from (x,y) to (u,v), need to do a rotation:
1829  // u = x*cosa-y*sina
1830  // v = y*cosa+x*sina
1831  // (without alignment offsets)
1832  double vpred_wire_plane=y*cospsi+x*sinpsi;
1833  double upred_wire_plane=x*cospsi-y*sinpsi;
1834  double tu=tx*cospsi-ty*sinpsi;
1835  double tv=tx*sinpsi+ty*cospsi;
1836 
1837  // Variables for angle of incidence with respect to the z-direction in
1838  // the u-z plane
1839  double alpha=atan(tu);
1840  double cosalpha=cos(alpha);
1841  double cos2_alpha=cosalpha*cosalpha;
1842  double sinalpha=sin(alpha);
1843  double sin2_alpha=sinalpha*sinalpha;
1844 
1845  // Alignment parameters for cathode planes
1846  DMatrix4x4 E=fdc_cathode_alignments[layer].E;
1847  DMatrix4x1 A=fdc_cathode_alignments[layer].A;
1848 
1849  // Difference between measurement and projection
1850  for (int m=trajectory[k].num_hits-1;m>=0;m--){
1851  unsigned int my_id=id+m;
1852  double uwire=hits[my_id]->wire->u+delta_u;
1853  // (signed) distance of closest approach to wire
1854  double doca=(upred_wire_plane-uwire)*cosalpha;
1855 
1856  // Predicted avalanche position along the wire
1857  double vpred=vpred_wire_plane-tv*sinalpha*doca;
1858 
1859  // predicted positions in two cathode planes' coordinate systems
1860  double phi_u=hits[my_id]->phi_u+A(kPhiU);
1861  double phi_v=hits[my_id]->phi_v+A(kPhiV);
1862  double cosphi_u=cos(phi_u);
1863  double sinphi_u=sin(phi_u);
1864  double cosphi_v=cos(phi_v);
1865  double sinphi_v=sin(phi_v);
1866  double vv=-vpred*sinphi_v-uwire*cosphi_v+A(kV);
1867  double vu=-vpred*sinphi_u-uwire*cosphi_u+A(kU);
1868 
1869  // Difference between measurements and predictions
1870  Mdiff(0)=hits[my_id]->u-vu;
1871  Mdiff(1)=hits[my_id]->v-vv;
1872 
1873  // Start filling the update vector
1874  updates[my_id].drift_time=hits[my_id]->time-trajectory[k].t;
1875 
1876  // Matrix for transforming from state-vector space to measurement space
1877  double temp2=tv*sinalpha*cosalpha;
1878  double dvdy=cospsi+sinpsi*temp2;
1879  double dvdx=sinpsi-cospsi*temp2;
1880 
1881  H_T(state_x,0)=-dvdx*sinphi_u;
1882  H_T(state_y,0)=-dvdy*sinphi_u;
1883  H_T(state_x,1)=-dvdx*sinphi_v;
1884  H_T(state_y,1)=-dvdy*sinphi_v;
1885 
1886  double cos2_minus_sin2=cos2_alpha-sin2_alpha;
1887  double doca_cosalpha=doca*cosalpha;
1888  double dvdtx=-doca_cosalpha*(tu*sina+tv*cosa*cos2_minus_sin2);
1889  double dvdty=-doca_cosalpha*(tu*cosa-tv*sina*cos2_minus_sin2);
1890 
1891  H_T(state_tx,0)=-dvdtx*sinphi_u;
1892  H_T(state_ty,0)=-dvdty*sinphi_u;
1893  H_T(state_tx,1)=-dvdtx*sinphi_v;
1894  H_T(state_ty,1)=-dvdty*sinphi_v;
1895 
1896  // Matrix transpose H_T -> H
1897  H(0,state_x)=H_T(state_x,0);
1898  H(0,state_y)=H_T(state_y,0);
1899  H(0,state_tx)=H_T(state_tx,0);
1900  H(0,state_ty)=H_T(state_ty,0);
1901  H(1,state_x)=H_T(state_x,1);
1902  H(1,state_y)=H_T(state_y,1);
1903  H(1,state_tx)=H_T(state_tx,1);
1904  H(1,state_ty)=H_T(state_ty,1);
1905 
1906  updates[my_id].H=H;
1907  updates[my_id].H_T=H_T;
1908 
1909  // Matrices to rotate alignment error matrix into measurement space
1910  DMatrix2x4 G;
1911  DMatrix4x2 G_T;
1912 
1913  G_T(kU,0)=1.;
1914  G_T(kPhiU,0)=-vpred*cosphi_u-uwire*sinphi_u;
1915  G_T(kV,1)=1.;
1916  G_T(kPhiV,1)=-vpred*cosphi_v-uwire*sinphi_v;
1917 
1918  // G-matrix transpose
1919  G(0,kU)=G_T(kU,0);
1920  G(0,kPhiU)=G_T(kPhiU,0);
1921  G(1,kV)=G_T(kV,1);
1922  G(1,kPhiV)=G_T(kPhiV,1);
1923 
1924  Vtemp=V+G*E*G_T;
1925 
1926  // Variance for this hit
1927  InvV=(Vtemp+H*C*H_T).Invert();
1928 
1929  // Compute Kalman gain matrix
1930  K=(C*H_T)*InvV;
1931 
1932  // Update the state vector
1933  S+=K*Mdiff;
1934 
1935  // Update state vector covariance matrix
1936  C=C-K*(H*C);
1937 
1938  // Update the filtered measurement covariane matrix and put results in
1939  // update vector
1940  DMatrix2x2 RC=Vtemp-H*C*H_T;
1941  updates[my_id].res=Mdiff-H*K*Mdiff;
1942  updates[my_id].V=RC;
1943  updates[my_id].S=S;
1944  updates[my_id].C=C;
1945 
1946  chi2+=RC.Chi2(updates[my_id].res);
1947  ndof+=2;
1948  }
1949 
1950  }
1951 
1952  }
1953  // chi2*=anneal_factor;
1954  ndof-=4;
1955 
1956  return NOERROR;
1957 }
1958 
1959 
1960 
1961 // Perform Kalman Filter for the current trajectory
1962 jerror_t
1964  DMatrix4x1 &S,DMatrix4x4 &C,
1965  vector<const DFDCPseudo *>&hits,
1966  deque<trajectory_t>&trajectory,
1967  vector<wire_update_t>&updates,
1968  double &chi2,unsigned int &ndof){
1969  DMatrix1x4 H; // Track projection matrix
1970  DMatrix4x1 H_T; // Transpose of track projection matrix
1971  DMatrix4x1 K; // Kalman gain matrix
1972  double V=0.020833; // Measurement variance
1973  double Vtemp,Mdiff,InvV;
1974  DMatrix4x4 I; // identity matrix
1975  DMatrix4x4 J; // Jacobian matrix
1976  DMatrix4x1 S0; // State vector from reference trajectory
1977 
1978  //Initialize chi2 and ndof
1979  chi2=0.;
1980  ndof=0;
1981 
1982  // Loop over all steps in the trajectory
1983  S0=trajectory[0].S;
1984  J=trajectory[0].J;
1985  trajectory[0].Skk=S;
1986  trajectory[0].Ckk=C;
1987  for (unsigned int k=1;k<trajectory.size();k++){
1988  if (C(0,0)<=0. || C(1,1)<=0. || C(2,2)<=0. || C(3,3)<=0.)
1989  return UNRECOVERABLE_ERROR;
1990 
1991  // Propagate the state and covariance matrix forward in z
1992  S=trajectory[k].S+J*(S-S0);
1993  C=J*C*J.Transpose();
1994 
1995  // Save the current state and covariance matrix
1996  trajectory[k].Skk=S;
1997  trajectory[k].Ckk=C;
1998 
1999  // Save S and J for the next step
2000  S0=trajectory[k].S;
2001  J=trajectory[k].J;
2002 
2003  // Correct S and C for the hit
2004  if (trajectory[k].h_id>0){
2005  unsigned int id=trajectory[k].h_id-1;
2006 
2007  double cosa=hits[id]->wire->udir.y();
2008  double sina=hits[id]->wire->udir.x();
2009 
2010  // State vector
2011  double x=S(state_x);
2012  double y=S(state_y);
2013  double tx=S(state_tx);
2014  double ty=S(state_ty);
2015  if (std::isnan(x) || std::isnan(y)) return UNRECOVERABLE_ERROR;
2016 
2017  // Get the alignment vector and error matrix for this layer
2018  unsigned int layer=hits[id]->wire->layer-1;
2019  DMatrix2x2 E=fdc_alignments[layer].E;
2020  DMatrix2x1 A=fdc_alignments[layer].A;
2021  double delta_u=A(kU);
2022  double sindphi=sin(A(kPhiU));
2023  double cosdphi=cos(A(kPhiU));
2024 
2025  // Components of rotation matrix for converting global to local coords.
2026  double cospsi=cosa*cosdphi+sina*sindphi;
2027  double sinpsi=sina*cosdphi-cosa*sindphi;
2028 
2029  // x,y and tx,ty in local coordinate system
2030  // To transform from (x,y) to (u,v), need to do a rotation:
2031  // u = x*cosa-y*sina
2032  // v = y*cosa+x*sina
2033  // (without alignment offsets)
2034  double upred=x*cospsi-y*sinpsi;
2035  double tu=tx*cospsi-ty*sinpsi;
2036  double tv=tx*sinpsi+ty*cospsi;
2037 
2038  // Variables for angle of incidence with respect to the z-direction in
2039  // the u-z plane
2040  double alpha=atan(tu);
2041  double cosalpha=cos(alpha);
2042  double sinalpha=sin(alpha);
2043 
2044  // Difference between measurement and projection
2045  for (int m=trajectory[k].num_hits-1;m>=0;m--){
2046  unsigned int my_id=id+m;
2047  double uwire=hits[my_id]->wire->u+delta_u;
2048 
2049  // Find drift distance
2050  double drift_time=hits[my_id]->time-trajectory[k].t;
2051  updates[my_id].drift_time=drift_time;
2052  updates[my_id].t=trajectory[k].t;
2053 
2054  double du=upred-uwire;
2055  double d=du*cosalpha;
2056  double sign=(du>0)?1.:-1.;
2057 
2058  // Difference between measured and predicted vectors
2059  // assume the track passes through the center of the cell
2060  double drift=0.25;
2061  if (USE_DRIFT_TIMES){
2062  drift=0.;
2063  if (drift_time>0){
2064  drift=fdc_drift_distance(drift_time);
2065 
2066  //V=0.0004+0.020433*(anneal_factor/1000.);
2067  double sigma=0.0135-3.98e-4*drift_time+5.62e-6*drift_time*drift_time;
2068  V=anneal_factor*sigma*sigma;
2069  }
2070  }
2071  Mdiff=sign*drift-d;
2072  updates[my_id].drift=drift;
2073 
2074  // Matrix for transforming from state-vector space to measurement space
2075  double sinalpha_cosalpha=sinalpha*cosalpha;
2076  H_T(state_x)=cospsi*cosalpha;
2077  H_T(state_y)=-sinpsi*cosalpha;
2078 
2079  double temp=d*sinalpha_cosalpha;
2080  H_T(state_tx)=-temp*cospsi;
2081  H_T(state_ty)=+temp*sinpsi;
2082 
2083  // H-matrix transpose
2084  H(state_x)=H_T(state_x);
2085  H(state_y)=H_T(state_y);
2086 
2087  H(state_tx)=H_T(state_tx);
2088  H(state_ty)=H_T(state_ty);
2089 
2090  updates[my_id].H=H;
2091  updates[my_id].H_T=H_T;
2092 
2093  // Matrices to rotate alignment error matrix into measurement space
2094  DMatrix1x2 G;
2095  DMatrix2x1 G_T;
2096 
2097  G_T(kU)=-cosalpha;
2098  G_T(kPhiU)=cosalpha*(x*sinpsi+y*cospsi-tv*d);
2099 
2100  // G-matrix transpose
2101  G(kU)=G_T(kU);
2102  G(kPhiU)=G_T(kPhiU);
2103 
2104  Vtemp=V+G*E*G_T;
2105 
2106  // Variance for this hit
2107  InvV=1./(Vtemp+H*C*H_T);
2108 
2109  // Compute Kalman gain matrix
2110  K=InvV*(C*H_T);
2111 
2112  // Update the state vector
2113  S+=Mdiff*K;
2114  updates[my_id].S=S;
2115 
2116  // Update state vector covariance matrix
2117  C=C-K*(H*C);
2118  updates[my_id].C=C;
2119 
2120  // Update chi2 for this trajectory
2121  x=S(state_x);
2122  y=S(state_y);
2123  tx=S(state_tx);
2124  ty=S(state_ty);
2125  upred=x*cospsi-y*sinpsi;
2126  tu=tx*cospsi-ty*sinpsi;
2127 
2128  // Variables for angle of incidence with respect to the z-direction in
2129  // the u-z plane
2130  alpha=atan(tu);
2131  cosalpha=cos(alpha);
2132  du=upred-uwire;
2133  d=du*cosalpha;
2134  sinalpha=sin(alpha);
2135 
2136  sign=(du>0)?1.:-1.;
2137  Mdiff=sign*drift-d;
2138 
2139  double RC=Vtemp-H*C*H_T;
2140  updates[my_id].ures=Mdiff;
2141  updates[my_id].R=RC;
2142 
2143  chi2+=Mdiff*Mdiff/RC;
2144  ndof++;
2145  }
2146 
2147  }
2148 
2149  }
2150  // chi2*=anneal_factor;
2151  ndof-=4;
2152 
2153  return NOERROR;
2154 }
2155 
2156 //Reference trajectory for the track for cdc tracks
2159  deque<trajectory_t>&trajectory,
2160  const DCDCTrackHit *last_cdc){
2161  DMatrix4x4 J(1.,0.,1.,0., 0.,1.,0.,1., 0.,0.,1.,0., 0.,0.,0.,1.);
2162 
2163  double ds=1.0;
2164  double dz=(S(state_ty)>0.?-1.:1.)*ds/sqrt(1.+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty));
2165  double t=t0;
2166 
2167  //y-position after which we cut off the loop
2168  double min_y=last_cdc->wire->origin.y()-5.;
2169  unsigned int numsteps=0;
2170  do{
2171  z+=dz;
2172  J(state_x,state_tx)=-dz;
2173  J(state_y,state_ty)=-dz;
2174  // Flight time: assume particle is moving at the speed of light
2175  t+=ds/29.98;
2176  //propagate the state to the next z position
2177  S(state_x)+=S(state_tx)*dz;
2178  S(state_y)+=S(state_ty)*dz;
2179  trajectory.push_front(trajectory_t(z,t0,S,J,Zero4x1,Zero4x4));
2180 
2181  numsteps++;
2182  }while (S(state_y)>min_y && numsteps<MAX_STEPS);
2183 
2184  if (trajectory.size()<2) return UNRECOVERABLE_ERROR;
2185  if (false)
2186  {
2187  printf("Trajectory:\n");
2188  for (unsigned int i=0;i<trajectory.size();i++){
2189  printf(" x %f y %f z %f\n",trajectory[i].S(state_x),
2190  trajectory[i].S(state_y),trajectory[i].z);
2191  }
2192  }
2193 
2194 
2195 
2196 
2197  return NOERROR;
2198 }
2199 
2200 
2201 // Reference trajectory for the track
2204  deque<trajectory_t>&trajectory,
2205  vector<const DFDCPseudo *>&pseudos){
2206  // Jacobian matrix
2207  DMatrix4x4 J(1.,0.,1.,0., 0.,1.,0.,1., 0.,0.,1.,0., 0.,0.,0.,1.);
2208 
2209  double dz=1.1;
2210  double t=t0;
2211  trajectory.push_front(trajectory_t(z,t0,S,J,Zero4x1,Zero4x4));
2212 
2213  double zhit=z;
2214  double old_zhit=z;
2215  for (unsigned int i=0;i<pseudos.size();i++){
2216  zhit=pseudos[i]->wire->origin.z();
2217  dz=1.1;
2218 
2219  if (fabs(zhit-old_zhit)<EPS){
2220  trajectory[0].num_hits++;
2221  continue;
2222  }
2223  bool done=false;
2224  while (!done){
2225  double new_z=z+dz;
2226 
2227  if (new_z>zhit){
2228  dz=zhit-z;
2229  new_z=zhit;
2230  done=true;
2231  }
2232  J(state_x,state_tx)=-dz;
2233  J(state_y,state_ty)=-dz;
2234  // Flight time: assume particle is moving at the speed of light
2235  t+=dz*sqrt(1+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty))/29.98;
2236  //propagate the state to the next z position
2237  S(state_x)+=S(state_tx)*dz;
2238  S(state_y)+=S(state_ty)*dz;
2239 
2240  trajectory.push_front(trajectory_t(new_z,t,S,J,Zero4x1,Zero4x4));
2241  if (done){
2242  trajectory[0].h_id=i+1;
2243  trajectory[0].num_hits=1;
2244  }
2245 
2246  z=new_z;
2247  }
2248  old_zhit=zhit;
2249  }
2250  // One last step
2251  dz=1.1;
2252  J(state_x,state_tx)=-dz;
2253  J(state_y,state_ty)=-dz;
2254 
2255  // Flight time: assume particle is moving at the speed of light
2256  t+=dz*sqrt(1+S(state_tx)*S(state_tx)+S(state_ty)*S(state_ty))/29.98;
2257 
2258  //propagate the state to the next z position
2259  S(state_x)+=S(state_tx)*dz;
2260  S(state_y)+=S(state_ty)*dz;
2261  trajectory.push_front(trajectory_t(z+dz,t,S,J,Zero4x1,Zero4x4));
2262 
2263  if (false)
2264  {
2265  printf("Trajectory:\n");
2266  for (unsigned int i=0;i<trajectory.size();i++){
2267  printf(" x %f y %f z %f first hit %d num in layer %d\n",trajectory[i].S(state_x),
2268  trajectory[i].S(state_y),trajectory[i].z,trajectory[i].h_id,
2269  trajectory[i].num_hits);
2270  }
2271  }
2272 
2273  return NOERROR;
2274 }
2275 
2276 // Crude approximation for the variance in drift distance due to smearing
2278  if (t<0) t=0;
2279  else if (t>110.) t=110.;
2280  double sigma=0.01639/sqrt(t+1.)+5.405e-3+4.936e-4*exp(0.09654*(t-66.86));
2281  return sigma*sigma;
2282 }
2283 
2284 // convert time to distance for the fdc
2286  if (t<0.) return 0.;
2287  double d=0.0268*sqrt(t)/*-3.051e-4*/+7.438e-4*t;
2288  if (d>0.5) d=0.5;
2289  return d;
2290 }
2291 
2293  unsigned int straw,
2294  DVector3 &origin,
2295  DVector3 &wdir){
2296  double zscale=75.0/wdir.z();
2297  DVector3 upstream=origin-zscale*wdir;
2298  DVector3 downstream=origin+zscale*wdir;
2299  DVector3 du(cdc_alignments[ring][straw].A(k_dXu),
2300  cdc_alignments[ring][straw].A(k_dYu),0.);
2301  DVector3 dd(cdc_alignments[ring][straw].A(k_dXd),
2302  cdc_alignments[ring][straw].A(k_dYd),0.);
2303  upstream+=du;
2304  downstream+=dd;
2305 
2306  origin=0.5*(upstream+downstream);
2307  wdir=downstream-upstream;
2308  wdir.SetMag(1.);
2309 }
2310 
2311 
2312 
2313 jerror_t
2314 DEventProcessor_dc_alignment::FindOffsets(vector<const DCDCTrackHit*>&hits,
2315  vector<cdc_update_t>&updates){
2316  for (unsigned int i=0;i<updates.size();i++){
2317  if (updates[i].used_in_fit==true){
2318  // wire data
2319  const DCDCWire *wire=hits[i]->wire;
2320  DVector3 origin=wire->origin;
2321  DVector3 wdir=wire->udir;
2322 
2323  unsigned int ring=wire->ring-1;
2324  unsigned int straw=wire->straw-1;
2325  UpdateWireOriginAndDir(ring,straw,origin,wdir);
2326 
2327  // zero-position and direction of line describing particle trajectory
2328  double tx=updates[i].S(state_tx),ty=updates[i].S(state_ty);
2329  DVector3 pos0(updates[i].S(state_x),updates[i].S(state_y),updates[i].z);
2330  DVector3 diff=pos0-origin;
2331  double dx0=diff.x(),dy0=diff.y();
2332  DVector3 tdir(tx,ty,1.);
2333  double wdir_dot_diff=diff.Dot(wdir);
2334  double tdir_dot_diff=diff.Dot(tdir);
2335  double tdir_dot_wdir=tdir.Dot(wdir);
2336  double tdir2=tdir.Mag2();
2337  double wdir2=wdir.Mag2();
2338  double wx=wdir.x(),wy=wdir.y();
2339  double D=tdir2*wdir2-tdir_dot_wdir*tdir_dot_wdir;
2340  double N=tdir_dot_wdir*wdir_dot_diff-wdir2*tdir_dot_diff;
2341  double N1=tdir2*wdir_dot_diff-tdir_dot_wdir*tdir_dot_diff;
2342  double scale=1./D;
2343  double s=scale*N;
2344  double t=scale*N1;
2345  diff+=s*tdir-t*wdir;
2346  double diffx=diff.x(),diffy=diff.y(),diffz=diff.z();
2347  double one_over_d=1./diff.Mag();
2348 
2349  // Matrices to rotate alignment error matrix into measurement space
2350  DMatrix1x4 G;
2351  DMatrix4x1 G_T;
2352  ComputeGMatrices(s,t,scale,tx,ty,tdir2,one_over_d,wx,wy,wdir2,tdir_dot_wdir,
2353  tdir_dot_diff,wdir_dot_diff,dx0,dy0,diffx,diffy,diffz,
2354  G,G_T);
2355 
2356  // Offset error matrix
2357  DMatrix4x4 E=cdc_alignments[ring][straw].E;
2358 
2359  // Inverse error
2360  double InvV=1./updates[i].V;
2361 
2362  // update the alignment vector and covariance
2363  DMatrix4x1 Ka=InvV*(E*G_T);
2364  DMatrix4x1 dA=updates[i].res*Ka;
2365  DMatrix4x4 Etemp=E-Ka*G*E;
2366  //dA.Print();
2367  //Etemp.Print();
2368  if (Etemp(0,0)>0 && Etemp(1,1)>0 && Etemp(2,2)>0&&Etemp(3,3)>0.){
2369  //cdc_alignments[ring][straw].A.Print();
2370  //dA.Print();
2371  //Etemp.Print();
2372  DMatrix4x1 A=cdc_alignments[ring][straw].A+dA;
2373  // Restrict offsets to less than 2 mm
2374  if (fabs(A(k_dXu))<0.2 && fabs(A(k_dXd))<0.2 && fabs(A(k_dYu))<0.2
2375  && fabs(A(k_dYd))<0.2){
2376  cdc_alignments[ring][straw].E=Etemp;
2377  cdc_alignments[ring][straw].A=A;
2378  }
2379  }
2380  }
2381  }
2382 
2383  return NOERROR;
2384 }
2385 
2386 
2387 jerror_t
2388 DEventProcessor_dc_alignment::FindOffsets(vector<const DFDCPseudo *>&hits,
2389  vector<update_t>&smoothed_updates){
2390  DMatrix2x4 G;//matrix relating alignment vector to measurement coords
2391  DMatrix4x2 G_T; // .. and its transpose
2392 
2393  unsigned int num_hits=hits.size();
2394 
2395  for (unsigned int i=0;i<num_hits;i++){
2396  // Get the cathode planes aligment vector and error matrix for this layer
2397  unsigned int layer=hits[i]->wire->layer-1;
2398  DMatrix4x1 A=fdc_cathode_alignments[layer].A;
2399  DMatrix4x4 E=fdc_cathode_alignments[layer].E;
2400 
2401  // Rotation of wire planes
2402  double cosa=hits[i]->wire->udir.y();
2403  double sina=hits[i]->wire->udir.x();
2404 
2405  // State vector
2406  DMatrix4x1 S=smoothed_updates[i].S;
2407  double x=S(state_x);
2408  double y=S(state_y);
2409  double tx=S(state_tx);
2410  double ty=S(state_ty);
2411  if (std::isnan(x) || std::isnan(y)) return UNRECOVERABLE_ERROR;
2412 
2413  // Get the wire plane alignment vector and error matrix for this layer
2414  DMatrix2x1 Aw=fdc_alignments[layer].A;
2415  double delta_u=Aw(kU);
2416  double sindphi=sin(Aw(kPhiU));
2417  double cosdphi=cos(Aw(kPhiU));
2418 
2419  // Components of rotation matrix for converting global to local coords.
2420  double cospsi=cosa*cosdphi+sina*sindphi;
2421  double sinpsi=sina*cosdphi-cosa*sindphi;
2422 
2423  // x,y and tx,ty in local coordinate system
2424  // To transform from (x,y) to (u,v), need to do a rotation:
2425  // u = x*cosa-y*sina
2426  // v = y*cosa+x*sina
2427  // (without alignment offsets)
2428  double vpred_wire_plane=y*cospsi+x*sinpsi;
2429  double upred_wire_plane=x*cospsi-y*sinpsi;
2430  double tu=tx*cospsi-ty*sinpsi;
2431  double tv=tx*sinpsi+ty*cospsi;
2432  double alpha=atan(tu);
2433  double cosalpha=cos(alpha);
2434  double sinalpha=sin(alpha);
2435 
2436  // Wire position in wire-plane local coordinate system
2437  double uwire=hits[i]->wire->u+delta_u;
2438  // (signed) distance of closest approach to wire
2439  double doca=(upred_wire_plane-uwire)*cosalpha;
2440 
2441  // Predicted avalanche position along the wire
2442  double vpred=vpred_wire_plane-tv*sinalpha*doca;
2443 
2444  // Matrices to rotate alignment error matrix into measurement space
2445  DMatrix2x4 G;
2446  DMatrix4x2 G_T;
2447 
2448  double phi_u=hits[i]->phi_u+A(kPhiU);
2449  double phi_v=hits[i]->phi_v+A(kPhiV);
2450 
2451  G_T(kU,0)=1.;
2452  G_T(kPhiU,0)=-vpred*cos(phi_u)-uwire*sin(phi_u);
2453  G_T(kV,1)=1.;
2454  G_T(kPhiV,1)=-vpred*cos(phi_v)-uwire*sin(phi_v);
2455 
2456  // update the alignment vector and covariance
2457  DMatrix4x2 Ka=(E*G_T)*smoothed_updates[i].V.Invert();
2458  DMatrix4x1 dA=Ka*smoothed_updates[i].res;
2459  DMatrix4x4 Etemp=E-Ka*G*E;
2460  if (Etemp(0,0)>0 && Etemp(1,1)>0 && Etemp(2,2)>0 && Etemp(3,3)>0){
2461  fdc_cathode_alignments[layer].E=Etemp;
2462  fdc_cathode_alignments[layer].A=A+dA;
2463  }
2464  else {
2465  /*
2466  printf("-------t= %f\n",smoothed_updates[i].drift_time);
2467  E.Print();
2468  Etemp.Print();
2469  */
2470  }
2471  }
2472 
2473  return NOERROR;
2474 }
2475 
2476 jerror_t
2477 DEventProcessor_dc_alignment::FindOffsets(vector<const DFDCPseudo *>&hits,
2478  vector<wire_update_t>&smoothed_updates){
2479  DMatrix1x2 G;//matrix relating alignment vector to measurement coords
2480  DMatrix2x1 G_T; // .. and its transpose
2481 
2482  unsigned int num_hits=hits.size();
2483 
2484 
2485  for (unsigned int i=0;i<num_hits;i++){
2486  double x=smoothed_updates[i].S(state_x);
2487  double y=smoothed_updates[i].S(state_y);
2488  double tx=smoothed_updates[i].S(state_tx);
2489  double ty=smoothed_updates[i].S(state_ty);
2490 
2491  double cosa=hits[i]->wire->udir.y();
2492  double sina=hits[i]->wire->udir.x();
2493 
2494  // Get the aligment vector and error matrix for this layer
2495  unsigned int layer=hits[i]->wire->layer-1;
2496  DMatrix2x1 A=fdc_alignments[layer].A;
2497  DMatrix2x2 E=fdc_alignments[layer].E;
2498  double delta_u=A(kU);
2499  double sindphi=sin(A(kPhiU));
2500  double cosdphi=cos(A(kPhiU));
2501 
2502  // Components of rotation matrix for converting global to local coords.
2503  double cospsi=cosa*cosdphi+sina*sindphi;
2504  double sinpsi=sina*cosdphi-cosa*sindphi;
2505 
2506  // x,y and tx,ty in local coordinate system
2507  // To transform from (x,y) to (u,v), need to do a rotation:
2508  // u = x*cosa-y*sina
2509  // v = y*cosa+x*sina
2510  // (without alignment offsets)
2511  double uwire=hits[i]->wire->u+delta_u;
2512  double upred=x*cospsi-y*sinpsi;
2513  double tu=tx*cospsi-ty*sinpsi;
2514  double tv=tx*sinpsi+ty*cospsi;
2515  double du=upred-uwire;
2516 
2517  // Variables for angle of incidence with respect to the z-direction in
2518  // the u-z plane
2519  double alpha=atan(tu);
2520  double cosalpha=cos(alpha);
2521 
2522  // Transform from alignment vector coords to measurement coords
2523  G_T(kU)=-cosalpha;
2524 
2525  double d=du*cosalpha;
2526  G_T(kPhiU)=cosalpha*(x*sinpsi+y*cospsi-tv*d);
2527 
2528  // G-matrix transpose
2529  G(kU)=G_T(kU);
2530  G(kPhiU)=G_T(kPhiU);
2531 
2532  // Inverse of error "matrix"
2533  double InvV=1./smoothed_updates[i].R;
2534 
2535  // update the alignment vector and covariance
2536  DMatrix2x1 Ka=InvV*(E*G_T);
2537  DMatrix2x1 dA=smoothed_updates[i].ures*Ka;
2538  DMatrix2x2 Etemp=E-Ka*G*E;
2539  if (Etemp(0,0)>0 && Etemp(1,1)>0){
2540  fdc_alignments[layer].E=Etemp;
2541  fdc_alignments[layer].A=A+dA;
2542  }
2543  else {
2544  /*
2545  printf("-------t= %f\n",smoothed_updates[i].drift_time);
2546  E.Print();
2547  Etemp.Print();
2548  */
2549  }
2550  }
2551 
2552  return NOERROR;
2553 }
2554 
2555 // Compute matrices for rotating the aligment error matrix into the measurement
2556 // space
2557 void
2558 DEventProcessor_dc_alignment::ComputeGMatrices(double s,double t,double scale,
2559  double tx,double ty,double tdir2,
2560  double one_over_d,
2561  double wx,double wy,double wdir2,
2562  double tdir_dot_wdir,
2563  double tdir_dot_diff,
2564  double wdir_dot_diff,
2565  double dx0,double dy0,
2566  double diffx,double diffy,
2567  double diffz,
2568  DMatrix1x4 &G,DMatrix4x1 &G_T){
2569  double dsdDx=scale*(tdir_dot_wdir*wx-wdir2*tx);
2570  double dsdDy=scale*(tdir_dot_wdir*wy-wdir2*ty);
2571 
2572  double dNdvx=tx*wdir_dot_diff+tdir_dot_wdir*dx0-2.*wx*tdir_dot_diff;
2573  double dDdvx=2.*wx*tdir2-2.*tdir_dot_wdir*tx;
2574  double dsdvx=scale*(dNdvx-s*dDdvx);
2575 
2576  double dNdvy=ty*wdir_dot_diff+tdir_dot_wdir*dy0-2.*wy*tdir_dot_diff;
2577  double dDdvy=2.*wy*tdir2-2.*tdir_dot_wdir*ty;;
2578  double dsdvy=scale*(dNdvy-s*dDdvy);
2579 
2580  double dsddxu=-0.5*dsdDx-one_over_zrange*dsdvx;
2581  double dsddxd=-0.5*dsdDx+one_over_zrange*dsdvx;
2582  double dsddyu=-0.5*dsdDy-one_over_zrange*dsdvy;
2583  double dsddyd=-0.5*dsdDy+one_over_zrange*dsdvy;
2584 
2585  double dtdDx=scale*(tdir2*wx-tdir_dot_wdir*tx);
2586  double dtdDy=scale*(tdir2*wy-tdir_dot_wdir*ty);
2587 
2588  double dN1dvx=tdir2*dx0-tdir_dot_diff*tx;
2589  double dtdvx=scale*(dN1dvx-t*dDdvx);
2590 
2591  double dN1dvy=tdir2*dy0-tdir_dot_diff*ty;
2592  double dtdvy=scale*(dN1dvy-t*dDdvy);
2593 
2594  double dtddxu=-0.5*dtdDx-one_over_zrange*dtdvx;
2595  double dtddxd=-0.5*dtdDx+one_over_zrange*dtdvx;
2596  double dtddyu=-0.5*dtdDy-one_over_zrange*dtdvy;
2597  double dtddyd=-0.5*dtdDy+one_over_zrange*dtdvy;
2598 
2599  double t_over_zrange=one_over_zrange*t;
2600  G(k_dXu)=one_over_d*(diffx*(-0.5+tx*dsddxu+t_over_zrange-wx*dtddxu)
2601  +diffy*(ty*dsddxu-wy*dtddxu)+diffz*(dsddxu-dtddxu));
2602  G(k_dXd)=one_over_d*(diffx*(-0.5+tx*dsddxd-t_over_zrange-wx*dtddxd)
2603  +diffy*(ty*dsddxd-wy*dtddxd)+diffz*(dsddxd-dtddxd));
2604  G(k_dYu)=one_over_d*(diffx*(tx*dsddyu-wx*dtddyu)+diffz*(dsddyu-dtddyu)
2605  +diffy*(-0.5+ty*dsddyu+t_over_zrange-wy*dtddyu));
2606  G(k_dYd)=one_over_d*(diffx*(tx*dsddyd-wx*dtddyd)+diffz*(dsddyd-dtddyd)
2607  +diffy*(-0.5+ty*dsddyd-t_over_zrange-wy*dtddyd));
2608  G_T(k_dXu)=G(k_dXu);
2609  G_T(k_dXd)=G(k_dXd);
2610  G_T(k_dYu)=G(k_dYu);
2611  G_T(k_dYd)=G(k_dYd);
2612 }
2613 
2614 // If the event viewer is available, grab parts of the hdview2 display and
2615 // overlay the results of the line fit on the tracking views.
2616 void DEventProcessor_dc_alignment::PlotLines(deque<trajectory_t>&traj){
2617  unsigned int last_index=traj.size()-1;
2618 
2619  TCanvas *c1=dynamic_cast<TCanvas *>(gROOT->FindObject("endviewA Canvas"));
2620  if (c1!=NULL){
2621  c1->cd();
2622  TPolyLine *line=new TPolyLine();
2623 
2624  line->SetLineColor(1);
2625  line->SetLineWidth(1);
2626 
2627  line->SetNextPoint(traj[last_index].S(state_x),traj[last_index].S(state_y));
2628  line->SetNextPoint(traj[0].S(state_x),traj[0].S(state_y));
2629  line->Draw();
2630 
2631  c1->Update();
2632 
2633  delete line;
2634  }
2635 
2636  c1=dynamic_cast<TCanvas *>(gROOT->FindObject("endviewA Large Canvas"));
2637  if (c1!=NULL){
2638  c1->cd();
2639  TPolyLine *line=new TPolyLine();
2640 
2641  line->SetLineColor(1);
2642  line->SetLineWidth(1);
2643 
2644  line->SetNextPoint(traj[last_index].S(state_x),traj[last_index].S(state_y));
2645  line->SetNextPoint(traj[0].S(state_x),traj[0].S(state_y));
2646  line->Draw();
2647 
2648  c1->Update();
2649 
2650  delete line;
2651  }
2652 
2653  c1=dynamic_cast<TCanvas *>(gROOT->FindObject("sideviewA Canvas"));
2654  if (c1!=NULL){
2655  c1->cd();
2656  TPolyLine *line=new TPolyLine();
2657 
2658  line->SetLineColor(1);
2659  line->SetLineWidth(1);
2660 
2661  line->SetNextPoint(traj[last_index].z,traj[last_index].S(state_x));
2662  line->SetNextPoint(traj[0].z,traj[0].S(state_x));
2663  line->Draw();
2664 
2665  c1->Update();
2666 
2667  delete line;
2668  }
2669 
2670  c1=dynamic_cast<TCanvas *>(gROOT->FindObject("sideviewB Canvas"));
2671  if (c1!=NULL){
2672  c1->cd();
2673  TPolyLine *line=new TPolyLine();
2674 
2675  line->SetLineColor(1);
2676  line->SetLineWidth(1);
2677 
2678  line->SetNextPoint(traj[last_index].z,traj[last_index].S(state_y));
2679  line->SetNextPoint(traj[0].z,traj[0].S(state_y));
2680  line->Draw();
2681 
2682  c1->Update();
2683  delete line;
2684  }
2685  // end of drawing code
2686 
2687 }
void PlotLines(deque< trajectory_t > &traj)
DApplication * dapp
jerror_t DoFilterAnodePlanes(double t0, double start_z, DMatrix4x1 &S, vector< const DFDCPseudo * > &fdchits)
bool cdc_hit_cmp(const DCDCTrackHit *a, const DCDCTrackHit *b)
const DBCALShower * match
double cdc_drift_distance(double dphi, double delta, double t)
const DCDCWire * wire
Definition: DCDCTrackHit.h:37
Int_t layer
double short_drift_func[3][3]
TVector3 DVector3
Definition: DVector3.h:14
jerror_t init(void)
Called once at program start.
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
#define EPS
sprintf(text,"Post KinFit Cut")
#define C0
Definition: src/md5.cpp:24
#define y
const DFDCWire * wire
DFDCWire for this wire.
Definition: DFDCPseudo.h:92
jerror_t brun(jana::JEventLoop *eventLoop, int32_t runnumber)
Called everytime a new run number is detected.
jerror_t DoFilterCathodePlanes(double t0, double start_z, DMatrix4x1 &S, vector< const DFDCPseudo * > &fdchits)
#define MAX_STEPS
class DFDCPseudo: definition for a reconstructed point in the FDC
Definition: DFDCPseudo.h:74
DMatrix4x4 Transpose()
Definition: DMatrix4x4.h:174
static char index(char c)
Definition: base64.cpp:115
static void locate(const double *xx, int n, double x, int *j)
Double_t c1[2][NMODULES]
Definition: tw_corr.C:68
void ComputeGMatrices(double s, double t, double scale, double tx, double ty, double tdir2, double one_over_d, double wx, double wy, double wdir2, double tdir_dot_wdir, double tdir_dot_diff, double wdir_dot_diff, double dx0, double dy0, double diffx, double diffy, double diffz, DMatrix1x4 &G, DMatrix4x1 &G_T)
JApplication * japp
Double_t c2[2][NMODULES]
Definition: tw_corr.C:69
double long_drift_func[3][3]
TEllipse * e
const double alpha
#define H(x, y, z)
double cdc_variance(double x)
TLatex tx
InitPlugin_t InitPlugin
int straw
Definition: DCDCWire.h:81
bool bcal_cmp(const bcal_match_t &a, const bcal_match_t &b)
vector< double > cdc_drift_table
DMatrix4x4 Invert()
Definition: DMatrix4x4.h:161
jerror_t SetReferenceTrajectory(double t0, double z, DMatrix4x1 &S, deque< trajectory_t > &trajectory, vector< const DFDCPseudo * > &hits)
DGeometry * GetDGeometry(unsigned int run_number)
#define _DBG_
Definition: HDEVIO.h:12
jerror_t fini(void)
Called after last event of last event source has been processed.
Double_t sigma[NCHANNELS]
Definition: st_tw_resols.C:37
jerror_t erun(void)
Called everytime run number changes, provided brun has been called.
double sqrt(double)
double sin(double)
#define S(str)
Definition: hddm-c.cpp:84
#define ITER_MAX
jerror_t evnt(jana::JEventLoop *eventLoop, uint64_t eventnumber)
Called every event.
jerror_t DoFilter(double t0, double z, DMatrix4x1 &S, vector< const DCDCTrackHit * > &hits)
jerror_t FindOffsets(vector< const DFDCPseudo * > &hits, vector< update_t > &smoothed_updates)
int ring
Definition: DCDCWire.h:80
unsigned int locate(vector< double > &xx, double x)
jerror_t Smooth(DMatrix4x1 &Ss, DMatrix4x4 &Cs, deque< trajectory_t > &trajectory, vector< const DFDCPseudo * > &hits, vector< update_t >updates, vector< update_t > &smoothed_updates)
bool GetCDCEndplate(double &z, double &dz, double &rmin, double &rmax) const
Definition: DGeometry.cc:1497
TCanvas * c3
printf("string=%s", string)
void UpdateWireOriginAndDir(unsigned int ring, unsigned int straw, DVector3 &origin, DVector3 &wdir)
TH2F * temp
jerror_t KalmanFilter(double anneal_factor, DMatrix4x1 &S, DMatrix4x4 &C, vector< const DFDCPseudo * > &hits, deque< trajectory_t > &trajectory, vector< update_t > &updates, double &chi2, unsigned int &ndof)
#define I(x, y, z)
#define G(x, y, z)
bool fdc_pseudo_cmp(const DFDCPseudo *a, const DFDCPseudo *b)