Bug Summary

File:plugins/Analysis/dc_alignment/DEventProcessor_dc_alignment.cc
Location:line 835, column 10
Description:Value stored to 'anneal_factor' during its initialization is never read

Annotated Source Code

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
8#include "DEventProcessor_dc_alignment.h"
9using namespace jana;
10
11#include <TROOT.h>
12#include <TCanvas.h>
13#include <TPolyLine.h>
14
15#define MAX_STEPS1000 1000
16
17// Routine used to create our DEventProcessor
18#include <JANA/JApplication.h>
19extern "C"{
20void InitPlugin(JApplication *app){
21 InitJANAPlugin(app);
22 app->AddProcessor(new DEventProcessor_dc_alignment());
23}
24} // "C"
25
26
27bool cdc_hit_cmp(const DCDCTrackHit *a,const DCDCTrackHit *b){
28
29 return(a->wire->origin.Y()>b->wire->origin.Y());
30}
31
32bool fdc_pseudo_cmp(const DFDCPseudo *a,const DFDCPseudo *b){
33 return (a->wire->origin.z()<b->wire->origin.z());
34}
35
36
37bool 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
42unsigned 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
62double DEventProcessor_dc_alignment::cdc_drift_distance(double dphi,
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
133double DEventProcessor_dc_alignment::fdc_drift_distance(double t){
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//------------------
151DEventProcessor_dc_alignment::DEventProcessor_dc_alignment()
152{
153 fdc_ptr = &fdc;
154 fdc_c_ptr= &fdc_c;
155 cdc_ptr = &cdc;
156
157 pthread_mutex_init(&mutex, NULL__null);
158
159}
160
161//------------------
162// ~DEventProcessor_dc_alignment (Destructor)
163//------------------
164DEventProcessor_dc_alignment::~DEventProcessor_dc_alignment()
165{
166
167}
168
169//------------------
170// init
171//------------------
172jerror_t DEventProcessor_dc_alignment::init(void)
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++){
280 cdc_align_t temp;
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//------------------
340jerror_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
407 cdc_offset_t temp;
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 // Get pointer to TrackFinder object
623 vector<const DTrackFinder *> finders;
624 loop->Get(finders);
625
626 if(finders.size()<1){
627 _DBG_std::cerr<<"plugins/Analysis/dc_alignment/DEventProcessor_dc_alignment.cc"
<<":"<<627<<" "
<<"Unable to get a DTrackFinder object!"<<endl;
628 return RESOURCE_UNAVAILABLE;
629 }
630
631 // Drop the const qualifier from the DTrackFinder pointer
632 finder = const_cast<DTrackFinder*>(finders[0]);
633
634 return NOERROR;
635}
636
637//------------------
638// erun
639//------------------
640jerror_t DEventProcessor_dc_alignment::erun(void)
641{
642
643
644 return NOERROR;
645}
646
647//------------------
648// fini
649//------------------
650jerror_t DEventProcessor_dc_alignment::fini(void)
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//------------------
726jerror_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
828jerror_t
829DEventProcessor_dc_alignment::DoFilter(double t0,double OuterZ,DMatrix4x1 &S,
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.));
Value stored to 'anneal_factor' during its initialization is never read
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
989jerror_t
990DEventProcessor_dc_alignment::DoFilterCathodePlanes(double t0,double start_z,
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_MAX20) 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
1101jerror_t
1102DEventProcessor_dc_alignment::DoFilterAnodePlanes(double t0,double start_z,
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_MAX20) 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
1216jerror_t DEventProcessor_dc_alignment::Smooth(DMatrix4x1 &Ss,DMatrix4x4 &Cs,
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
1330jerror_t DEventProcessor_dc_alignment::Smooth(DMatrix4x1 &Ss,DMatrix4x4 &Cs,
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
1422jerror_t
1423DEventProcessor_dc_alignment::Smooth(DMatrix4x1 &Ss,DMatrix4x4 &Cs,
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
1503jerror_t
1504DEventProcessor_dc_alignment::KalmanFilter(double anneal_factor,
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_PI3.14159265358979323846) dphi-=2*M_PI3.14159265358979323846;
1614 while (dphi<-M_PI3.14159265358979323846) dphi+=2*M_PI3.14159265358979323846;
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
1760jerror_t
1761DEventProcessor_dc_alignment::KalmanFilter(double anneal_factor,
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
1962jerror_t
1963DEventProcessor_dc_alignment::KalmanFilter(double anneal_factor,
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
2157jerror_t DEventProcessor_dc_alignment
2158::SetReferenceTrajectory(double t0,double z,DMatrix4x1 &S,
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_STEPS1000);
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
2202jerror_t DEventProcessor_dc_alignment
2203::SetReferenceTrajectory(double t0,double z,DMatrix4x1 &S,
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)<EPS1e-3){
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
2277double DEventProcessor_dc_alignment::GetDriftVariance(double t){
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
2285double DEventProcessor_dc_alignment::GetDriftDistance(double t){
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
2292void DEventProcessor_dc_alignment::UpdateWireOriginAndDir(unsigned int ring,
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
2313jerror_t
2314DEventProcessor_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
2387jerror_t
2388DEventProcessor_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
2476jerror_t
2477DEventProcessor_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
2557void
2558DEventProcessor_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.
2616void 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__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__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__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__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}