QwAnalysis
QwPartialTrack.cc
Go to the documentation of this file.
1 #include "QwPartialTrack.h"
3 
4 // ROOT headers
5 #include "TRandom.h"
6 
7 // Qweak headers
8 #include "QwLog.h"
9 #include "QwUnits.h"
10 #include "QwVertex.h"
11 
12 /**
13  * Default constructor
14  */
16 {
17  // Initialize
18  Initialize();
19 }
20 
21 /**
22  * Constructor with position and direction vectors
23  * @param position Position of the partial track
24  * @param direction Direction of the partial track
25  */
26 QwPartialTrack::QwPartialTrack(const TVector3& position, const TVector3& direction)
27 {
28  // Initialize
29  Initialize();
30 
31  // Calculate slopes
32  fSlopeX = direction.X() / direction.Z();
33  fSlopeY = direction.Y() / direction.Z();
34 
35  // Calculate offset
36  fOffsetX = position.X() - fSlopeX * position.Z();
37  fOffsetY = position.Y() - fSlopeY * position.Z();
38 }
39 
40 /**
41  * Copy constructor by reference
42  */
44 : VQwTrackingElement(that)
45 {
46  // Initialize
47  Initialize();
48 
49  // Assignment
50  *this = that;
51 }
52 
53 /**
54  * Copy constructor with pointer
55  */
57 : VQwTrackingElement(*that)
58 {
59  // Initialize
60  Initialize();
61 
62  // Null pointer
63  if (that == 0) return;
64 
65  // Assignment
66  *this = *that;
67 }
68 
69 /**
70  * Destructor
71  */
73 {
74  // Clear the partial track
75  Clear();
76 
77  /* for (int i = 0; i < kNumDirections; i++){
78  if(fTreeLine[i])
79  delete fTreeLine[i];
80  }
81  */
82  // nothing
83 }
84 
85 /**
86  * Assignment operator
87  */
89 {
90  if (this == &that) return *this;
91 
93 
94  fAlone = that.fAlone;
95 
96  fOffsetX = that.fOffsetX;
97  fOffsetY = that.fOffsetY;
98  fSlopeX = that.fSlopeX;
99  fSlopeY = that.fSlopeY;
100 
101  fChi = that.fChi;
103 
104  for (size_t i = 0; i < 4; ++i)
105  for (size_t j = 0; j < 4; ++j)
106  fCov[i][j] = that.fCov[i][j];
107 
108  // this is a pointer
109  for (size_t i = 0; i < kNumDirections; ++i){
110  TResidual[i]=that.TResidual[i];
111  }
112 
113  for (size_t i=0;i< 12;++i)
114  fSignedResidual[i]=that.fSignedResidual[i];
115 
116  fIsUsed = that.fIsUsed;
117  fIsVoid = that.fIsVoid;
118  fIsGood = that.fIsGood;
119 
120  fNumMiss = that.fNumMiss;
121  fNumHits = that.fNumHits;
122 
123  for (size_t i = 0; i < 3; ++i) {
124  pR2hit[i] = that.pR2hit[i];
125  uvR2hit[i] = that.uvR2hit[i];
126  pR3hit[i] = that.pR3hit[i];
127 
128  uvR3hit[i] = that.uvR3hit[i];
129  }
130 
131  // Copy tree lines
132  ClearTreeLines();
134 
135  return *this;
136 }
137 
138 
139 /**
140  * Perform object initialization
141  */
143 {
144  // Initialize the member fields
145  fOffsetX = 0.0; fOffsetY = 0.0;
146  fSlopeX = 0.0; fSlopeY = 0.0;
147  fIsVoid = false; fIsUsed = false; fIsGood = false;
148 
149  // Initialize pointers
150  for (int i = 0; i < kNumDirections; ++i){
151  TResidual[i]=0.0;
152  }
153 
154  for(int i=0; i< 12;++i)
155  fSignedResidual[i]=-10;
156 
157  //Only 2 Plane 0 treelines
158  fAlone=0;
159 }
160 
161 
162 /**
163  * Determine the chi^2 for a partial track, weighted by the number of hits
164  *
165  * @return Weighted chi^2
166  */
168 {
169  // Determine the weight if there are enough hits
170  if (fNumHits >= fNumMiss) {
171  // NOTE Added +1 to get this to work if fNumHits == fNumMiss (wdc)
172  double weight = (double) (fNumHits + fNumMiss + 1)
173  / (fNumHits - fNumMiss + 1);
174  return weight * weight * fChi;
175  // TODO Why is the weight squared here, but not in the weighted chi^2 for treelines?
176 
177  } else {
178 
179  QwDebug << "miss = " << fNumMiss << ", hit = " << fNumHits << QwLog::endl;
180  return 100.0; // This is bad...
181  }
182 }
183 
184 
185 /**
186  * Calculate the average residual of this partial track over all treelines
187  */
189 {
190  int numTreeLines = 0;
191  double sumResiduals = 0.0;
192  for (Int_t i = 0; i < GetNumberOfTreeLines(); i++) {
193  const QwTreeLine* treeline = GetTreeLine(i);
194  if (treeline->IsUsed()) {
195  numTreeLines++;
196  sumResiduals += treeline->GetAverageResidual();
197  }
198  } // end of loop over treelines
199  fAverageResidual = sumResiduals / numTreeLines;
200  return fAverageResidual;
201 }
202 
203 
204 // Clear the local TClonesArrays
205 void QwPartialTrack::Clear(Option_t *option)
206 {
207  ClearTreeLines(option);
208 }
209 
210 // Delete the static TClonesArrays
211 void QwPartialTrack::Reset(Option_t *option)
212 {
213  ResetTreeLines(option);
214 }
215 
216 // Create a new QwTreeLine
218 {
219  QwTreeLine* treeline = new QwTreeLine();
220  AddTreeLine(treeline);
221  return treeline;
222 }
223 
224 // Add an existing QwTreeLine
226 {
227  fQwTreeLines.push_back(new QwTreeLine(treeline));
228  ++fNQwTreeLines;
229 }
230 
231 // Add a linked list of QwTreeLine's
233 {
234  for (const QwTreeLine *treeline = treelinelist;
235  treeline; treeline = treeline->next){
236  if (treeline->IsValid()){
237  AddTreeLine(treeline);
238  }
239  }
240 }
241 
242 // Add a list of tree lines
243 void QwPartialTrack::AddTreeLineList(const std::vector<QwTreeLine*> &treelinelist)
244 {
245  for (std::vector<QwTreeLine*>::const_iterator treeline = treelinelist.begin();
246  treeline != treelinelist.end(); treeline++)
247  AddTreeLine(*treeline);
248 }
249 
250 // Clear the local TClonesArray of tree lines
251 void QwPartialTrack::ClearTreeLines(Option_t *option)
252 {
253  for (size_t i = 0; i < fQwTreeLines.size(); i++) {
254  QwTreeLine* tl = fQwTreeLines.at(i);
255  delete tl;
256  }
257  fQwTreeLines.clear();
258  fNQwTreeLines = 0;
259 }
260 
261 // Delete the static TClonesArray of tree lines
262 void QwPartialTrack::ResetTreeLines(Option_t *option)
263 {
264  ClearTreeLines();
265 }
266 
267 // Print the tree lines
268 void QwPartialTrack::PrintTreeLines(Option_t *option) const
269 {
270  for (std::vector<QwTreeLine*>::const_iterator treeline = fQwTreeLines.begin();
271  treeline != fQwTreeLines.end(); treeline++) {
272  std::cout << **treeline << std::endl;
273  QwTreeLine* tl = (*treeline)->next;
274  while (tl) {
275  std::cout << *tl << std::endl;
276  tl = tl->next;
277  }
278  }
279 }
280 
281 
282 /**
283  * Print some debugging information
284  */
285 void QwPartialTrack::Print(const Option_t* options) const
286 {
287  if (!this) return;
288  QwVerbose << *this << QwLog::endl;
289 }
290 
291 /**
292  * Print some debugging information for valid partial tracks
293  */
295 {
296  if (!this) return;
297  if (this->IsValid()) QwVerbose << *this << QwLog::endl;
298 }
299 
300 /**
301  * Output stream operator overloading
302  */
303 std::ostream& operator<< (std::ostream& stream, const QwPartialTrack& pt)
304 {
305  stream << "pt: ";
306  if (pt.GetRegion() != kRegionIDNull)
307  stream << "(" << pt.GetRegion() << "/" << "?UD"[pt.GetPackage()] << "); ";
308  stream << "x,y(z=0) = (" << pt.fOffsetX/Qw::cm << " cm, " << pt.fOffsetY/Qw::cm << " cm), ";
309  stream << "d(x,y)/dz = (" << pt.fSlopeX << ", " << pt.fSlopeY << ")";
310 
311  double x=pt.fOffsetX/Qw::cm-663*pt.fSlopeX;
312  double y=pt.fOffsetY/Qw::cm-663*pt.fSlopeY;
313  stream << " downstream target: " << x << ", " << y;
314  if (pt.fChi > 0.0) { // parttrack has been fitted
315  stream << ", chi = " << pt.fChi;
316  }
317  if (pt.fAverageResidual > 0.0) {
318  stream << ", res = " << pt.fAverageResidual;
319  }
320  if (pt.IsVoid()) stream << " (void)";
321  return stream;
322 }
323 
324 
325 /**
326  * Determines the position of the track at the given z position
327  */
328 const TVector3 QwPartialTrack::GetPosition(const double z) const
329 {
330  TVector3 position;
331  position.SetX(fOffsetX + fSlopeX * z);
332  position.SetY(fOffsetY + fSlopeY * z);
333  position.SetZ(z);
334  return position;
335 }
336 
337 /**
338  * Determines the direction of the track at the given z position
339  */
341 {
342  TVector3 direction;
343  double kz = sqrt(fSlopeX * fSlopeX + fSlopeY * fSlopeY + 1);
344  direction.SetX(fSlopeX / kz);
345  direction.SetY(fSlopeY / kz);
346  direction.SetZ(1 / kz);
347  return direction;
348 }
349 
350 /**
351  * Smear the position of the partial track
352  * @param sigma_x Standard deviation in x
353  * @param sigma_y Standard deviation in y
354  */
355 QwPartialTrack& QwPartialTrack::SmearPosition(double sigma_x, double sigma_y)
356 {
357  fOffsetX = gRandom->Gaus(fOffsetX, sigma_x);
358  fOffsetY = gRandom->Gaus(fOffsetY, sigma_y);
359  return *this;
360 }
361 
362 /**
363  * Smear the theta angle of the partial track
364  * @param sigma Standard deviation in theta
365  */
367 {
368  double theta = GetMomentumDirectionTheta();
369  double phi = GetMomentumDirectionPhi();
370  theta = gRandom->Gaus(theta, sigma);
371  fSlopeX = sin(theta) * cos(phi);
372  fSlopeY = sin(theta) * sin(phi);
373  return *this;
374 }
375 
376 /**
377  * Smear the phi angle of the partial track
378  * @param sigma Standard deviation in phi
379  */
381 {
382  double theta = GetMomentumDirectionTheta();
383  double phi = GetMomentumDirectionPhi();
384  phi = gRandom->Gaus(phi, sigma);
385  fSlopeX = sin(theta) * cos(phi);
386  fSlopeY = sin(theta) * sin(phi);
387  return *this;
388 }
389 
390 
391 /**
392  * This method checks determines the intersection of the partial track
393  * with a planar detector.
394  */
396 {
397  QwVertex* vertex = 0;
398  if (detector->GetDetectorPitch() != 0) {
399  // Get intersection with z-plane
400  double z = detector->GetZPosition();
401  TVector3 position = GetPosition(z);
402  // Check acceptance with active width
403  if (fabs(position.X() - detector->GetPosition().X()) < detector->GetActiveWidthX()/2
404  && fabs(position.Y() - detector->GetPosition().Y()) < detector->GetActiveWidthY()/2) {
405  vertex = new QwVertex(position);
406  } else {
407  QwMessage << "No support for intersections of partial tracks "
408  << "with tilted detectors yet..." << QwLog::endl;
409  }
410  }
411  return vertex;
412 }
413 
414 
415 /**
416  * This method checks determines the intersection of the partial track
417  * with the target.
418  *
419  * \note At this point the target defined at one z value only. A more careful
420  * determination of the primary vertex will be implemented using the general
421  * QwVertex class, e.g. QwVertex* primary_vertex = QwVertex (partial_track, beam)
422  */
424 {
425  // TODO target should be put in in the geometry file
426  TVector3 primary = GetPosition(0.0);
427  QwVerbose << "Target vertex at : (" << primary.X() << "," << primary.Y() << "," << primary.Z() << ")" << QwLog::endl;
428  return 0;
429 }
430 
431 /**
432  * This method checks whether the region 3 partial track has an intersection
433  * with the trigger scintillators in a detector package.
434  *
435  * The trigger scintillators are assumed to be the only (or at least the first)
436  * detectors in region 3.
437  */
439 {
440  // Get the trigger scintillator detectors in this package
441  QwGeometry trigscint(geometry.in(kRegionIDTrig).in(GetPackage()));
442 
443  // Find the first hit
444  for (size_t i = 0; i < trigscint.size(); i++) {
445  const QwVertex* vertex = DeterminePositionInDetector(trigscint.at(i));
446  if (vertex) return vertex;
447  }
448  return 0;
449 }
450 
451 /**
452  * This method checks whether the region 3 partial track has an intersection
453  * with the trigger scintillators in a detector package.
454  *
455  * The cerenkov bars are assumed to be the only (or at least the first)
456  * detectors in region 3.
457  */
459 {
460  // Get the Cherenkov detectors in this package
461  QwGeometry cerenkov(geometry.in(kRegionIDCer).in(GetPackage()));
462 
463  // Find the first hit
464  for (size_t i = 0; i < cerenkov.size(); i++) {
465  const QwVertex* vertex = DeterminePositionInDetector(cerenkov.at(i));
466  if (vertex) return vertex;
467  }
468  return 0;
469 }
470 
471 /**
472  * This method checks whether the region 2 partial track has an intersection
473  * with the horizontal drift chambers in a detector package.
474  *
475  * The drift chambers are assumed to be the only (or at least the first)
476  * detectors in region 2.
477  */
479 {
480  // Get the HDC detectors in this package
481  QwGeometry hdc(geometry.in(kRegionID2).in(GetPackage()));
482  // Find the first hit
483  for (size_t i = 0; i < hdc.size(); i++) {
484  const QwVertex* vertex = DeterminePositionInDetector(hdc.at(i));
485  if (vertex) return vertex;
486  }
487  return 0;
488 }
489 
490 /**
491  * This method rotate track geometry information to the right postion
492  * according to the octant number. Remember the initial position is at
493  * octant 3.
494  */
495 
497  //pick two points
498  double z1=0,z2=-250;
499  double x1=0,y1=0,x2=0,y2=0;
500  double x3=0,y3=0,x4=0,y4=0;
501  double PI=3.1415926;
502  x1=fOffsetX+fSlopeX*z1;
503  y1=fOffsetY+fSlopeY*z1;
504  x2=fOffsetX+fSlopeX*z2;
505  y2=fOffsetY+fSlopeY*z2;
506  int oct=GetOctant();
507  double rotate=oct==8? 135: (3-oct)*45;
508  double Cos=cos(rotate*PI/180);
509  double Sin=sin(rotate*PI/180);
510  x3=Cos*x1+Sin*y1;
511  y3=-Sin*x1+Cos*y1;
512  x4=Cos*x2+Sin*y2;
513  y4=-Sin*x2+Cos*y2;
514 
515  fOffsetX=x3;
516  fOffsetY=y3;
517 
518  fSlopeX=(x4-x3)/(z2-z1);
519  fSlopeY=(y4-y3)/(z2-z1);
520 
521 }
523 
524  double z1=476.7,z2=500.0;
525  double x1=0,y1=0,x2=0,y2=0;
526  double pitch=0,yaw=0,roll=0;
527  double rotatorZpos = 476.7;
528 
529  x1=fOffsetX+fSlopeX*z1;
530  y1=fOffsetY+fSlopeY*z1;
531  x2=fOffsetX+fSlopeX*z2;
532  y2=fOffsetY+fSlopeY*z2;
533 
534  z1 = z1 - rotatorZpos;
535  z2 = z2 - rotatorZpos;
536 
537  TVector3 v1(x1,y1,z1);
538  TVector3 v2(x2,y2,z2);
539 
540  TVector3 xaxis(1,0,0); //x-axis of rotator
541  TVector3 yaxis(0,1,0); //y-axis of rotator
542  TVector3 zaxis(0,0,1); //z-axis of rotator
543 
544  pitch = detector->GetRotatorPitch();
545  yaw = detector->GetRotatorYaw();
546  roll = detector->GetRotatorRoll();
547 
548  v1.Rotate(pitch,xaxis);
549  v2.Rotate(pitch,xaxis);
550  yaxis.Rotate(pitch,xaxis); //rotating y-axis for yaw next
551  zaxis.Rotate(pitch,xaxis); //rotating z-axis for roll later
552 
553  v1.Rotate(yaw,yaxis);
554  v2.Rotate(yaw,yaxis);
555  zaxis.Rotate(yaw,yaxis); //rotating z-axis for roll next
556 
557  v1.Rotate(roll,zaxis);
558  v2.Rotate(roll,zaxis);
559 
560  v1.SetZ( v1.Z() + rotatorZpos );
561  v2.SetZ( v2.Z() + rotatorZpos );
562 
563  fSlopeX = (v2.X()-v1.X())/(v2.Z()-v1.Z());
564  fSlopeY = (v2.Y()-v1.Y())/(v2.Z()-v1.Z());
565 
566  fOffsetX = v1.X()-v1.Z()*fSlopeX;
567  fOffsetY = v1.Y()-v1.Z()*fSlopeY;
568 
569 
570 }
#define QwMessage
Predefined log drain for regular messages.
Definition: QwLog.h:50
QwPartialTrack & SmearAngleTheta(const double sigma)
Smear the theta angle.
QwPartialTrack & SmearPosition(const double sigma_x, const double sigma_y)
Smear the position.
QwPartialTrack & SmearAnglePhi(const double sigma)
Smear the phi angle.
std::ostream & operator<<(std::ostream &out, const QwColor &color)
Output stream operator which uses the enum-to-escape-code mapping.
Definition: QwColor.h:153
Int_t GetNumberOfTreeLines() const
Get the number of tree lines.
const QwVertex * DeterminePositionInHDC(const QwGeometry &geometry)
Determine position in first horizontal drift chamber.
Double_t fOffsetX
x coordinate (at MAGNET_CENTER)
const QwGeometry in(const EQwRegionID &r) const
Get detectors in given region.
Definition: QwGeometry.h:92
Contains vertex information.
Definition: QwVertex.h:23
QwPartialTrack & operator=(const QwPartialTrack &that)
Assignment operator.
bool IsVoid() const
Double_t fSlopeY
y slope
double fAverageResidual
number of Plane 0 Treelines
double GetActiveWidthY() const
double GetAverageResidual() const
Get the average residuals.
Definition: QwTreeLine.h:163
int GetOctant() const
Get the octant number.
#define QwVerbose
Predefined log drain for verbose messages.
Definition: QwLog.h:55
Double_t GetMomentumDirectionTheta() const
Return the theta angle.
Double_t fChi
combined chi square
Int_t fNQwTreeLines
Number of tree lines in this partial track.
bool IsUsed() const
Is this tree line used?
Definition: QwTreeLine.h:96
const TVector3 GetPosition(const double z) const
Return the vertex at position z.
Definition of the partial track class.
QwTreeLine * CreateNewTreeLine()
Create a new tree line.
void AddTreeLine(const QwTreeLine *treeline)
Add an existing tree line as a copy.
double GetRotatorYaw() const
EQwRegionID GetRegion() const
Get the region.
double pR2hit[3]
x-y-z position at R2
double GetDetectorPitch() const
VQwTrackingElement & operator=(const VQwTrackingElement &that)
Assignment operator.
#define QwDebug
Predefined log drain for debugging output.
Definition: QwLog.h:60
void RotateCoordinates()
Rotate coordinates to right octant.
A logfile class, based on an identical class in the Hermes analyzer.
const TVector3 GetMomentumDirection() const
Return the direction.
const TVector3 GetPosition() const
const QwTreeLine * GetTreeLine(const int tl) const
Get the specified tree line.
void Reset(Option_t *option="")
const QwVertex * DeterminePositionInTarget(const QwGeometry &geometry)
Determine vertex in the target.
const QwVertex * DeterminePositionInCerenkovBars(const QwGeometry &geometry)
Determine intersection with cerenkov bars.
double CalculateAverageResidual()
Double_t fCov[4][4]
covariance matrix
double uvR3hit[3]
direction at R3
double GetRotatorRoll() const
Double_t fSlopeX
x slope
Bool_t fIsVoid
marked as being void
Double_t TResidual[kNumDirections]
void Clear(Option_t *option="")
One-dimensional (u, v, or x) track stubs and associated hits.
Definition: QwTreeLine.h:51
static std::ostream & endl(std::ostream &)
End of the line.
Definition: QwLog.cc:299
double GetRotatorPitch() const
double uvR2hit[3]
direction at R2
void RotateRotator(const QwDetectorInfo *geometry)
ClassImp(QwF1TDC)
void ResetTreeLines(Option_t *option="")
Reset the list of tree lines.
Collection of QwDetectorInfo pointers that specifies an experimental geometry.
Definition: QwGeometry.h:27
double pR3hit[3]
x-y-z position at R3
const QwVertex * DeterminePositionInDetector(const QwDetectorInfo *geometry)
Determine vertex in detector.
QwTreeLine * next
Definition: QwTreeLine.h:231
QwPartialTrack()
Default constructor.
Double_t fOffsetY
y coordinate (at MAGNET_CENTER)
Double_t fSignedResidual[12]
void PrintTreeLines(Option_t *option="") const
Print the list of tree lines.
Double_t GetMomentumDirectionPhi() const
Return the phi angle.
const QwVertex * DeterminePositionInTriggerScintillators(const QwGeometry &geometry)
Determine intersection with trigger scintillators.
void Initialize()
Initialization.
Bool_t fIsUsed
used (part of a track)
double GetChiWeight() const
double GetZPosition() const
std::vector< QwTreeLine * > fQwTreeLines
List of tree lines in this partial track.
virtual ~QwPartialTrack()
Destructor.
void AddTreeLineList(const QwTreeLine *treelinelist)
Add a linked list of existing tree lines as a copy.
bool IsValid() const
Int_t fNumMiss
missing hits
Contains the straight part of a track in one region only.
void ClearTreeLines(Option_t *option="")
Clear the list of tree lines.
Int_t fNumHits
used hits
EQwDetectorPackage GetPackage() const
Get the package.
static const double cm
Length units: base unit is mm.
Definition: QwUnits.h:61
double GetActiveWidthX() const
Virtual base class for all tracking elements.
void Print(const Option_t *options=0) const