Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
JEventProcessor_FDCProjectionResiduals.cc
Go to the documentation of this file.
1 // $Id$
2 //
3 // File: JEventProcessor_FDCProjectionResiduals.cc
4 // Created: Wed Oct 26 14:07:16 EDT 2016
5 // Creator: mstaib (on Linux ifarm1401 2.6.32-431.el6.x86_64 x86_64)
6 //
7 
12 #include "HistogramTools.h"
13 
14 using namespace jana;
15 
16 
17 // Routine used to create our JEventProcessor
18 #include <JANA/JApplication.h>
19 #include <JANA/JFactory.h>
20 extern "C"{
21 void InitPlugin(JApplication *app){
22  InitJANAPlugin(app);
23  app->AddProcessor(new JEventProcessor_FDCProjectionResiduals());
24 }
25 } // "C"
26 
27 
28 //------------------
29 // JEventProcessor_FDCProjectionResiduals (Constructor)
30 //------------------
32 {
33 
34 }
35 
36 //------------------
37 // ~JEventProcessor_FDCProjectionResiduals (Destructor)
38 //------------------
40 {
41 
42 }
43 
44 //------------------
45 // init
46 //------------------
48 {
49  // This is called once at program startup.
50 
51  return NOERROR;
52 }
53 
54 //------------------
55 // brun
56 //------------------
57 jerror_t JEventProcessor_FDCProjectionResiduals::brun(JEventLoop *eventLoop, int32_t runnumber)
58 {
59  // This is called whenever the run number changes
60  // This is called whenever the run number changes
61  DApplication* dapp=dynamic_cast<DApplication*>(eventLoop->GetJApplication());
62  dIsNoFieldFlag = (dynamic_cast<const DMagneticFieldMapNoField*>(dapp->GetBfield(runnumber)) != NULL);
63  JCalibration *jcalib = dapp->GetJCalibration(runnumber);
64  dgeom = dapp->GetDGeometry(runnumber);
65  //bfield = dapp->GetBfield();
66 
67  //Get Target Center Z, length
68  dgeom->GetTargetZ(dTargetCenterZ);
69  dgeom->GetTargetLength(dTargetLength);
70 
71  // Get the position of the CDC downstream endplate from DGeometry
72  //double endplate_z,endplate_dz,endplate_rmin,endplate_rmax;
73  dgeom->GetCDCEndplate(endplate_z,endplate_dz,endplate_rmin,endplate_rmax);
74  dgeom->GetCDCWires(cdcwires);
75  unsigned int numstraws[28]={42,42,54,54,66,66,80,80,93,93,106,106,123,123,
76  135,135,146,146,158,158,170,170,182,182,197,197,
77  209,209};
78 
79  // Get the straw sag parameters from the database
80  vector< map<string, double> > tvals;
81  max_sag.clear();
82  sag_phi_offset.clear();
83  unsigned int straw_count=0,ring_count=0;
84  if (jcalib->Get("CDC/sag_parameters", tvals)==false){
85  vector<double>temp,temp2;
86  for(unsigned int i=0; i<tvals.size(); i++){
87  map<string, double> &row = tvals[i];
88 
89  temp.push_back(row["offset"]);
90  temp2.push_back(row["phi"]);
91 
92  straw_count++;
93  if (straw_count==numstraws[ring_count]){
94  max_sag.push_back(temp);
95  sag_phi_offset.push_back(temp2);
96  temp.clear();
97  temp2.clear();
98  straw_count=0;
99  ring_count++;
100  }
101  }
102  }
103 
104  typedef map<string,double>::iterator iter_double;
105  if (dIsNoFieldFlag){
106  if (jcalib->Get("CDC/cdc_drift_table::NoBField", tvals)==false){
107  for(unsigned int i=0; i<tvals.size(); i++){
108  map<string, double> &row = tvals[i];
109  iter_double iter = row.find("t");
110  cdc_drift_table.push_back(1000.*iter->second);
111  }
112  }
113 
114  if (jcalib->Get("CDC/drift_parameters::NoBField", tvals)==false){
115  map<string, double> &row = tvals[0]; //long drift side
116  long_drift_func[0][0]=row["a1"];
117  long_drift_func[0][1]=row["a2"];
118  long_drift_func[0][2]=row["a3"];
119  long_drift_func[1][0]=row["b1"];
120  long_drift_func[1][1]=row["b2"];
121  long_drift_func[1][2]=row["b3"];
122  long_drift_func[2][0]=row["c1"];
123  long_drift_func[2][1]=row["c2"];
124  long_drift_func[2][2]=row["c3"];
125 
126  row = tvals[1]; // short drift side
127  short_drift_func[0][0]=row["a1"];
128  short_drift_func[0][1]=row["a2"];
129  short_drift_func[0][2]=row["a3"];
130  short_drift_func[1][0]=row["b1"];
131  short_drift_func[1][1]=row["b2"];
132  short_drift_func[1][2]=row["b3"];
133  short_drift_func[2][0]=row["c1"];
134  short_drift_func[2][1]=row["c2"];
135  short_drift_func[2][2]=row["c3"];
136  }
137  }
138  else{
139  if (jcalib->Get("CDC/cdc_drift_table", tvals)==false){
140  for(unsigned int i=0; i<tvals.size(); i++){
141  map<string, double> &row = tvals[i];
142  iter_double iter = row.find("t");
143  cdc_drift_table.push_back(1000.*iter->second);
144  }
145  }
146 
147  if (jcalib->Get("CDC/drift_parameters", tvals)==false){
148  map<string, double> &row = tvals[0]; //long drift side
149  long_drift_func[0][0]=row["a1"];
150  long_drift_func[0][1]=row["a2"];
151  long_drift_func[0][2]=row["a3"];
152  long_drift_func[1][0]=row["b1"];
153  long_drift_func[1][1]=row["b2"];
154  long_drift_func[1][2]=row["b3"];
155  long_drift_func[2][0]=row["c1"];
156  long_drift_func[2][1]=row["c2"];
157  long_drift_func[2][2]=row["c3"];
158 
159  row = tvals[1]; // short drift side
160  short_drift_func[0][0]=row["a1"];
161  short_drift_func[0][1]=row["a2"];
162  short_drift_func[0][2]=row["a3"];
163  short_drift_func[1][0]=row["b1"];
164  short_drift_func[1][1]=row["b2"];
165  short_drift_func[1][2]=row["b3"];
166  short_drift_func[2][0]=row["c1"];
167  short_drift_func[2][1]=row["c2"];
168  short_drift_func[2][2]=row["c3"];
169  }
170  }
171 
172 
173  MAX_DRIFT_TIME = 1000.0; //ns: from TRKFIND:MAX_DRIFT_TIME in DTrackCandidate_factory_CDC
174  PLANE_TO_SKIP = 0;
175  //Make sure it gets initialize first, in case we want to change it:
176  vector<const DTrackCandidate*> locTrackCandidates;
177  eventLoop->Get(locTrackCandidates,"StraightLine");
178  gPARMS->GetParameter("TRKFIT:PLANE_TO_SKIP", PLANE_TO_SKIP);
179 
180  return NOERROR;
181 }
182 
183 //------------------
184 // evnt
185 //------------------
186 jerror_t JEventProcessor_FDCProjectionResiduals::evnt(JEventLoop *loop, uint64_t eventnumber)
187 {
188  vector<const DTrackFitter *> fitters;
189  loop->Get(fitters);
190 
191  if(fitters.size()<1){
192  _DBG_<<"Unable to get a DTrackFinder object!"<<endl;
193  return RESOURCE_UNAVAILABLE;
194  }
195  const DTrackFitter *fitter = fitters[0];
196 
197  vector <const DCDCHit *> cdcHitVector;
198  loop->Get(cdcHitVector);
199 
200  vector <const DChargedTrack *> chargedTrackVector;
201  loop->Get(chargedTrackVector);
202 
203  unsigned int numstraws[28]={42,42,54,54,66,66,80,80,93,93,106,106,123,123,
204  135,135,146,146,158,158,170,170,182,182,197,197,
205  209,209};
206 
207  for (unsigned int iTrack = 0; iTrack < chargedTrackVector.size(); iTrack++){
208 
209  const DChargedTrackHypothesis* bestHypothesis = chargedTrackVector[iTrack]->Get_BestTrackingFOM();
210 
211 
212  // Cut very loosely on the track quality
213  auto thisTimeBasedTrack = bestHypothesis->Get_TrackTimeBased();
214 
215  double t0 = thisTimeBasedTrack->t0();
216 
217  Fill1DHistogram("FDCProjectionResiduals", "", "Tracking FOM", thisTimeBasedTrack->FOM, "TrackingFOM", 200, 0.0, 1.0);
218  if (thisTimeBasedTrack->FOM < 0.0027 || thisTimeBasedTrack->Ndof < 4) continue;
219 
220  // Loop through the pulls to try to check on the FDC calibtrations
221  vector<DTrackFitter::pull_t> pulls = thisTimeBasedTrack->pulls;
222  for (size_t iPull = 0; iPull < pulls.size(); iPull++){
223  if ( pulls[iPull].fdc_hit != nullptr){
224  if (PLANE_TO_SKIP == 0 || PLANE_TO_SKIP == pulls[iPull].fdc_hit->wire->layer){
225  double DOCA = pulls[iPull].d;
226  double residual = pulls[iPull].resi;
227  double cathode_resi = pulls[iPull].resic;
228  double tdrift = pulls[iPull].tdrift;
229  Fill2DHistogram("FDCProjectionResiduals", "FDCReco","Distance Vs Time",
230  tdrift, DOCA,
231  "Distance Vs. Time; Time [ns]; Distance [cm]",
232  300, 0.0, 300., 100, 0.0, 0.5);
233  Fill2DHistogram("FDCProjectionResiduals", "FDCReco","Residual Vs Time",
234  tdrift, residual,
235  "Residual Vs. Time; Time [ns]; Residual [cm]",
236  200, 0.0, 200., 160, -0.2, 0.2);
237  Fill1DHistogram("FDCProjectionResiduals", "FDCReco","Cathode Residuals",
238  cathode_resi, "Cathode Residual; Residual [cm];", 160,-0.2, 0.2);
239 
240  }
241  }
242  }
243 
244  vector<DTrackFitter::Extrapolation_t>extrapolations=thisTimeBasedTrack->extrapolations.at(SYS_CDC);
245  if (extrapolations.size()>0){
246  for (auto ringPtr=cdcwires.begin(); ringPtr < cdcwires.end(); ringPtr++){
247  vector< DCDCWire * > wireByNumber = (*ringPtr);
248  for (auto wirePtr = wireByNumber.begin(); wirePtr < wireByNumber.end(); wirePtr++)
249  {
250  DCDCWire * wire = *wirePtr;
251  //double wireLength = wire->L;
252  //double distanceToWire = thisTimeBasedTrack->rt->DistToRT(wire, &wireLength);
253  DVector3 POCAOnTrack(0.0, 0.0, 0.0), POCAOnWire(0.0, 0.0, 0.0);
254  double zVertex = thisTimeBasedTrack->position().Z();
255  double distanceToBeamline = thisTimeBasedTrack->position().Perp();
256  double distanceToWire;
257  if (dIsNoFieldFlag) distanceToWire = GetDOCA(wire->origin, wire->udir, thisTimeBasedTrack->position(), thisTimeBasedTrack->momentum(), POCAOnTrack, POCAOnWire);
258  else {
259  distanceToWire=fitter->DistToWire(wire,extrapolations,
260  &POCAOnTrack,NULL,&POCAOnWire);
261  }
262  double zPOCA = POCAOnTrack.Z();
263  DVector3 LOCA = POCAOnTrack - POCAOnWire;
264  if(distanceToWire > 1.2 || distanceToBeamline > 1.0 || zPOCA < zVertex || POCAOnWire.Z() > endplate_z) continue;
265  jout << " Dist = " << distanceToWire << " POCAOnTrack POCAOnWire Manual Distance = " << LOCA.Mag() << endl;
266  POCAOnTrack.Print();
267  POCAOnWire.Print();
268 
269  double delta = 0.0, dz = 0.0;
270  if(!Expect_Hit(thisTimeBasedTrack, wire, distanceToWire, delta, dz, fitter))
271  continue;
272  // Check for a CDC Hit on this wire
273  for (auto cdcHit = cdcHitVector.begin(); cdcHit != cdcHitVector.end(); cdcHit++){
274  const DCDCHit *thisHit = (*cdcHit);
275  if (thisHit->ring == wire->ring && thisHit->straw == wire->straw){
276  // We found the hit on the wire and have all of the information we need.
277  // Get the corrected drift time
278  //DReferenceTrajectory::swim_step_t* swimstep = thisTimeBasedTrack->rt->FindClosestSwimStep(wire);
279  double tdrift = thisHit->t - t0;
280  double measurement = CDCDriftDistance(delta, tdrift);
281  double signedResidual = measurement - (POCAOnTrack.Phi() - POCAOnWire.Phi())*POCAOnTrack.Perp();
282  double residual = measurement - distanceToWire;
283  //jout << "evnt" << eventnumber << " ring " << wire->ring << " straw " << wire->straw << " t " << thisHit->t << " t0 " << t0 << " measurement " << measurement << " residual " << residual << endl;
284  char name[200];
285  char title[200];
286  sprintf(name,"Ring %i Residual Vs. Straw Number", thisHit->ring);
287  sprintf(title,"Ring %i Residual Vs. Straw Number; Straw Number; Residual [cm]", thisHit->ring);
288  Fill2DHistogram("FDCProjectionResiduals","ResidualVsStrawNumber",name,
289  thisHit->straw, residual,
290  title,
291  numstraws[thisHit->ring-1], 0.5, numstraws[thisHit->ring-1] + 0.5, 1000, -0.5, 0.5);
292  sprintf(name,"Ring %i rPhi Residual Vs. phi", thisHit->ring);
293  sprintf(title,"Ring %i #Deltar#phi Vs. #phi; Straw Number; Residual [cm]", thisHit->ring);
294  Fill2DHistogram("FDCProjectionResiduals","ResidualVsPhi",name,
295  thisTimeBasedTrack->momentum().Phi(), signedResidual,
296  title,
297  numstraws[thisHit->ring-1], -3.14, 3.14, 1000, -0.5, 0.5);
298  if (thisHit->ring == 1){
299  sprintf(name,"Ring %i Straw %i Distance Vs. Time", thisHit->ring, thisHit->straw);
300  sprintf(title,"Ring %i Straw %i Distance Vs. Time ; Time [ns]; Distance [cm]", thisHit->ring, thisHit->straw);
301  Fill2DHistogram("FDCProjectionResiduals","DistanceVsTimeRing1",name,
302  tdrift, distanceToWire,
303  title,
304  500, -50.0, 1000, 120, 0.0, 1.2);
305  }
306  }
307  }
308  }
309  }
310  }
311  }
312  return NOERROR;
313 }
314 
315 //------------------
316 // erun
317 //------------------
319 {
320  // This is called whenever the run number changes, before it is
321  // changed to give you a chance to clean up before processing
322  // events from the next run number.
323  return NOERROR;
324 }
325 
326 //------------------
327 // fini
328 //------------------
330 {
331  // Called before program exit after event processing is finished.
332  return NOERROR;
333 }
334 
335 // Convert time to distance for the cdc
337  double d=0.;
338 
339  if (t>0){
340  double f_0=0.;
341  double f_delta=0.;
342 
343  if (delta > 0){
344  double a1=long_drift_func[0][0];
345  double a2=long_drift_func[0][1];
346  double b1=long_drift_func[1][0];
347  double b2=long_drift_func[1][1];
348  double c1=long_drift_func[2][0];
349  double c2=long_drift_func[2][1];
350  double c3=long_drift_func[2][2];
351 
352  // use "long side" functional form
353  double my_t=0.001*t;
354  double sqrt_t=sqrt(my_t);
355  double t3=my_t*my_t*my_t;
356  double delta_mag=fabs(delta);
357  f_delta=(a1+a2*delta_mag)*sqrt_t+(b1+b2*delta_mag)*my_t
358  +(c1+c2*delta_mag+c3*delta*delta)*t3;
359  f_0=a1*sqrt_t+b1*my_t+c1*t3;
360  }
361  else{
362  double my_t=0.001*t;
363  double sqrt_t=sqrt(my_t);
364  double delta_mag=fabs(delta);
365 
366  // use "short side" functional form
367  double a1=short_drift_func[0][0];
368  double a2=short_drift_func[0][1];
369  double a3=short_drift_func[0][2];
370  double b1=short_drift_func[1][0];
371  double b2=short_drift_func[1][1];
372  double b3=short_drift_func[1][2];
373 
374  double delta_sq=delta*delta;
375  f_delta= (a1+a2*delta_mag+a3*delta_sq)*sqrt_t
376  +(b1+b2*delta_mag+b3*delta_sq)*my_t;
377  f_0=a1*sqrt_t+b1*my_t;
378  }
379 
380  unsigned int max_index=cdc_drift_table.size()-1;
381  if (t>cdc_drift_table[max_index]){
382  //_DBG_ << "t: " << t <<" d " << f_delta <<endl;
383  d=f_delta;
384  //cout << "t = " << t << " > " << cdc_drift_table[max_index] << " d = " << f_delta << endl;
385  return d;
386  }
387 
388  // Drift time is within range of table -- interpolate...
389  unsigned int index=0;
390  index=Locate(cdc_drift_table,t);
391  double dt=cdc_drift_table[index+1]-cdc_drift_table[index];
392  double frac=(t-cdc_drift_table[index])/dt;
393  double d_0=0.01*(double(index)+frac);
394 
395  double P=0.;
396  double tcut=250.0; // ns
397  if (t<tcut) {
398  P=(tcut-t)/tcut;
399  }
400  d=f_delta*(d_0/f_0*P+1.-P);
401  }
402  return d;
403 }
404 
405 bool JEventProcessor_FDCProjectionResiduals::Expect_Hit(const DTrackTimeBased* thisTimeBasedTrack, DCDCWire* wire, double distanceToWire, double& delta, double& dz, const DTrackFitter *fitter)
406 {
407  delta = 0.0;
408  dz = 0.0;
409  if (distanceToWire >= 1.2 )
410  return false;
411 
412  // Loose cut before delta information
413  // Need to get phi_doca for each of the wires that pass this cut
414  vector<DTrackFitter::Extrapolation_t>extrapolations=thisTimeBasedTrack->extrapolations.at(SYS_CDC);
415  if (extrapolations.size()==0) return false;
416 
417  // Form the vector between the wire and the DOCA point
418  DVector3 pos;
419  fitter->DistToWire(wire,extrapolations,&pos);
420  DVector3 DOCA = (-1) * ((wire->origin - pos) - (wire->origin - pos).Dot(wire->udir) * wire->udir);
421 
422  double docaphi = DOCA.Phi();
423  dz = (pos - wire->origin).Z();
424  //cout << "distanceToWire = " << distanceToWire << " DOCA = " << DOCA.Mag() << endl;
425  // Get delta at this location for this straw
426  int ring_index = wire->ring - 1;
427  int straw_index = wire->straw - 1;
428  delta = max_sag[ring_index][straw_index] * ( 1. - (dz*dz/5625.)) * TMath::Cos(docaphi + sag_phi_offset[ring_index][straw_index]);
429 
430  return (distanceToWire < (0.78 + delta) && fabs(dz) < 65.0);
431 }
432 
433 // Locate a position in vector xx given x
434 unsigned int JEventProcessor_FDCProjectionResiduals::Locate(vector<double>&xx,
435  double x){
436  int n=xx.size();
437  if (x==xx[0]) return 0;
438  else if (x==xx[n-1]) return n-2;
439 
440  int jl=-1;
441  int ju=n;
442  int ascnd=(xx[n-1]>=xx[0]);
443  while(ju-jl>1){
444  int jm=(ju+jl)>>1;
445  if ( (x>=xx[jm])==ascnd)
446  jl=jm;
447  else
448  ju=jm;
449  }
450  return jl;
451 }
452 
453 double JEventProcessor_FDCProjectionResiduals::GetDOCA(DVector3 wirePosition, DVector3 wireDirection, DVector3 trackPosition, DVector3 trackMomentum, DVector3 &POCAOnTrack, DVector3 &POCAOnWire){
454  // Get the vector pointing from the wire to the doca point
455  Float_t a = trackMomentum.Dot(trackMomentum);
456  Float_t b = trackMomentum.Dot(wireDirection);
457  Float_t c = wireDirection.Dot(wireDirection);
458  DVector3 w0 = trackPosition - wirePosition;
459  Float_t d = trackMomentum.Dot(w0);
460  Float_t e = wireDirection.Dot(w0);
461  Float_t sc = ((b*e - c*d)/(a*c-b*b));
462  Float_t tc = ((a*e - b*d)/(a*c-b*b));
463  //if (sc < 0) continue; // Track must come from location away from origin
464  POCAOnTrack = trackPosition + sc * trackMomentum;
465  POCAOnWire = wirePosition + tc * wireDirection;
466  DVector3 LOCA = w0 + sc*trackMomentum - tc*wireDirection;
467  return LOCA.Mag();
468 }
DApplication * dapp
double t0(void) const
Definition: DTrackingData.h:23
The DTrackFitter class is a base class for different charged track fitting algorithms. It does not actually fit the track itself, but provides the interface and some common support features most algorthims will need to implement.
Definition: DTrackFitter.h:61
unsigned int Locate(vector< double > &xx, double x)
double short_drift_func[3][3]
TVector3 DVector3
Definition: DVector3.h:14
Double_t x[NCHANNELS]
Definition: st_tw_resols.C:39
jerror_t erun(void)
Called everytime run number changes, provided brun has been called.
sprintf(text,"Post KinFit Cut")
#define c
DMagneticFieldMap * GetBfield(unsigned int run_number=1)
const DTrackTimeBased * Get_TrackTimeBased(void) const
jerror_t init(void)
Called once at program start.
static char index(char c)
Definition: base64.cpp:115
Definition: GlueX.h:17
Double_t c1[2][NMODULES]
Definition: tw_corr.C:68
Double_t c2[2][NMODULES]
Definition: tw_corr.C:69
double long_drift_func[3][3]
float t
Definition: DCDCHit.h:22
TEllipse * e
InitPlugin_t InitPlugin
int straw
Definition: DCDCWire.h:81
vector< double > cdc_drift_table
DGeometry * GetDGeometry(unsigned int run_number)
#define _DBG_
Definition: HDEVIO.h:12
int ring
Definition: DCDCHit.h:18
void Fill1DHistogram(const char *plugin, const char *directoryName, const char *name, const double value, const char *title, int nBins, double xmin, double xmax, bool print=false)
bool Expect_Hit(const DTrackTimeBased *thisTimeBasedTrack, DCDCWire *wire, double distanceToWire, double &delta, double &dz, const DTrackFitter *fitter)
void Fill2DHistogram(const char *plugin, const char *directoryName, const char *name, const double valueX, const double valueY, const char *title, int nBinsX, double xmin, double xmax, int nBinsY, double ymin, double ymax, bool print=false)
unsigned int Locate(vector< double > &xx, double x)
double sqrt(double)
jerror_t fini(void)
Called after last event of last event source has been processed.
const DTrackFitter * fitter
int ring
Definition: DCDCWire.h:80
double GetDOCA(DVector3, DVector3, DVector3, DVector3, DVector3 &, DVector3 &)
map< DetectorSystem_t, vector< DTrackFitter::Extrapolation_t > > extrapolations
jerror_t evnt(jana::JEventLoop *eventLoop, uint64_t eventnumber)
Called every event.
TCanvas * c3
TH2F * temp
bool GetTargetZ(double &z_target) const
z-location of center of target
Definition: DGeometry.cc:1933
int straw
Definition: DCDCHit.h:19
jerror_t brun(jana::JEventLoop *eventLoop, int32_t runnumber)
Called everytime a new run number is detected.
double DistToWire(const DCoordinateSystem *wire, const vector< Extrapolation_t > &extrapolations, DVector3 *pos=NULL, DVector3 *mom=NULL, DVector3 *position_along_wire=NULL) const