EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EicTrackingDigiHitProducer.h
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file EicTrackingDigiHitProducer.h
1 //
2 // AYK (ayk@bnl.gov), 2013/06/12
3 //
4 // Tracking digi hit producer class;
5 //
6 
7 #include <TRandom.h>
8 #include <TMath.h>
9 
10 #include <EicDigiHitProducer.h>
11 #include <EicDigiParData.h>
12 #include <EicTrackingDigiHit.h>
13 
14 #define RADIANS(x) ((x)*TMath::Pi()/180.0)
15 
16 #ifndef _EIC_TRACKING_DIGI_HIT_PRODUCER_
17 #define _EIC_TRACKING_DIGI_HIT_PRODUCER_
18 
19 class KfMatrix;
20 class SensitiveVolume;
21 class EicRunDigi;
22 
24 {
26  friend class EicHtcTask;
27  friend class KalmanNodeWrapper;
28 
29  public:
30  EicKfNodeTemplate(TGeoMatrix *node2sv = 0): mNodeToSensitiveVolume(node2sv) {};
32 
33  // These are either hints or exclusions based on which main code should decide
34  // on basic compatibility and guess to choose either {XY} or {r,phi} generic scheme;
35  //virtual bool FavorCylindricalThreeDee() const { return false; };
36  virtual bool CylindricalThreeDeeOnly() const { return false; };
37  virtual bool CartesianThreeDeeOnly() const { return false; };
38 
39  // No default calls here;
40  virtual void FillGranularityArray(bool useCartesian, double spGranularity, double aGranularity,
41  double gra[]) const = 0;
42  //virtual void FillSmearingArray(double spSmearing, double aSmearing, double sme[]) const = 0;
43  virtual double GetSmearingValue(double spSmearing, const EicTrackingDigiHit *hit,
44  unsigned iq) const = 0;
45  virtual void FillMinMaxArrays(bool useCartesian, const std::set<double> &xMin,
46  const std::set<double> &xMax,
47  const std::set<double> &yMin, const std::set<double> &yMax,
48  const std::set<double> &rMin, const std::set<double> &rMax,
49  double min[], double max[]) const = 0;
50 
51  virtual unsigned GetMdim() const = 0;
52  virtual double GetSigma(unsigned iq) const = 0;
53  virtual double GetPitch(unsigned iq) const = 0;
54  virtual double GetPixelCenterOffset(unsigned iq) const = 0;
55 
56  virtual KfMatrix *GetMeasurementNoise(const EicTrackingDigiHit *hit) const = 0;
57 
58  // Well, 0.0 is equivalent to "don't know"; fine as default;
59  virtual double GetSpatialSigma() const { return 0.0; };
60  virtual double GetAngularSigma() const { return 0.0; };
61 
62  //virtual unsigned CalculateSmearing(double smearing) const {
63  //assert(0);
64  //};
65 
66  bool IsCompatible(const EicKfNodeTemplate *sample) {
67  // Dimensions should match; otherwise nothing to talk about;
68  if (GetMdim() != sample->GetMdim()) return false;
69 
70  if (CylindricalThreeDeeOnly() && sample->CartesianThreeDeeOnly()) return false;
71  if (CartesianThreeDeeOnly() && sample->CylindricalThreeDeeOnly()) return false;
72 
73  // FIXME: eventually check orientation of cartesian-only and origin match of
74  // cylindrical-only templates;
75 
76  return true;
77  };
78 
80  EicTrackingDigiHit *hit, double zRef,
81  KfMatrix *A, KfMatrix *b);
82 
83  // These two calls default to linear templates and can be overriden by {r,phi} ones;
84  virtual TVector3 TemplateToThreeDee(const double tmplCoord[]) const {
85  TVector3 vv(0.0, 0.0, 0.0);
86 
87  for(unsigned xy=0; xy<GetMdim(); xy++)
88  vv[xy] = tmplCoord[xy];
89 
90  return vv;
91  };
92  virtual void ThreeDeeToTemplate(const TVector3 &crs, double tmplCoord[]) const {
93  for(unsigned xy=0; xy<GetMdim(); xy++)
94  tmplCoord[xy] = crs[xy];
95  };
96  virtual void CartesianToCylindrical(const TVector3 &crs, double tmplCoord[]) const {
97  assert(0);
98  };
99 
100  protected:
101  double GetSmearedValue(double value, unsigned iq, EicDigiHitProducer::SmearingModel smearing_model) {
102  if (iq >= GetMdim()) return value;
103 
104  switch (smearing_model) {
106  return value + (GetSigma(iq) ? gRandom->Gaus(0.0, GetSigma(iq)) : 0.0);
108  if (!GetPitch(iq)) return value;
109 
110  return GetPitch(iq) * rint((value - GetPixelCenterOffset(iq))/GetPitch(iq)) +
112  default:
113  assert(0); return 0.0;
114  } //switch
115  };
116 
117  // These two mathods are template-specific;
118  virtual void SmearLocalCoord(TVector3 &local, EicDigiHitProducer::SmearingModel smearing_model) = 0;
119  virtual void PackSmearedHit(TClonesArray *arr,
120  const TString &detName,
121  const EicMoCaPoint *point, unsigned kfNodeID,
122  TVector3 &global,
123  TVector3 &local) = 0;
124 
125  // This one is sort of universal;
126  void StoreDigiHit(TClonesArray *arr,
127  const TString &detName,
128  const EicMoCaPoint *point, unsigned kfNodeID,
129  TVector3 &global,
130  TVector3 &local, EicDigiHitProducer::SmearingModel smearing_model) {
131  SmearLocalCoord(local, smearing_model);
132 
133  PackSmearedHit(arr, detName, point, kfNodeID, global, local);
134  };
135 
136  private:
137  TGeoMatrix *mNodeToSensitiveVolume; // transformation from KF node to the sensitive volume
138 
139  ClassDef(EicKfNodeTemplate,2)
140 };
141 
142 // ---------------------------------------------------------------------------------------
143 
145 {
146  public:
147  EicKfNodeTemplate1D(TGeoMatrix *transformation = 0): EicKfNodeTemplate(transformation),
148  mSigma(0.0), mPitch(0.0), mPixelCenterOffset(0.0) {};
150 
151  void SetSigma(double sigma) { mSigma = sigma; };
152  void SetPitch(double pitch) { mPitch = pitch; mSigma = pitch/sqrt(12.); };
153 
154  unsigned GetMdim() const { return 1; };
155  double GetSigma(unsigned iq) const { return (iq == 0 ? mSigma : 0.0); };
156  double GetPitch(unsigned iq) const { return (iq == 0 ? mPitch : 0.0); };
157  double GetPixelCenterOffset(unsigned iq) const {
158  return (iq == 0 ? mPixelCenterOffset : 0.0);
159  };
160 
161  // This call is the same for all 1D templates;
162  void PackSmearedHit(TClonesArray *arr,
163  const TString &detName,
164  const EicMoCaPoint *point, unsigned kfNodeID,
165  TVector3 &global,
166  TVector3 &local) {
167  assert(0);
168  new((*arr)[arr->GetEntriesFast()])
169  EicTrackingDigiHit1D(detName, point, kfNodeID, global, local, mSigma);
170  };
171 
173 
174  protected:
175  Double_t mSigma; // gaussian sigma in all cases
176 
177  private:
178  Double_t mPitch; // 1D pitch in case of 'Quantize' digitization
179  // Unbiased quantization will be done with this overall offset of pixel grid;
180  Double_t mPixelCenterOffset; // any pixel center offset
181 
182  ClassDef(EicKfNodeTemplate1D,6)
183 };
184 
185 // THINK: does nothing; yet want to have a separate class, "symmetric" to the
186 // Radial and Asimuthal ones;
188 {
189  public:
190  EicKfNodeTemplateLinear1D(TGeoMatrix *transformation = 0):
191  EicKfNodeTemplate1D(transformation) {};
193 
194  void FillGranularityArray(bool useCartesian, double spGranularity,
195  double aGranularity, double gra[]) const {
196  gra[0] = spGranularity;
197  };
198  //void FillSmearingArray(double spSmearing, double aSmearing, double sme[]) const {
199  // sme[0] = spSmearing;
200  //};
201  double GetSmearingValue(double spSmearing, const EicTrackingDigiHit *hit, unsigned iq) const {
202  return (iq ? 0.0 : spSmearing);
203  };
204  void FillMinMaxArrays(bool useCartesian, const std::set<double> &xMin, const std::set<double> &xMax,
205  const std::set<double> &yMin, const std::set<double> &yMax,
206  const std::set<double> &rMin, const std::set<double> &rMax,
207  double min[], double max[]) const {
208  min[0] = *xMin.begin();
209  max[0] = *xMax.rbegin();
210  };
211 
212  void SmearLocalCoord(TVector3 &local, EicDigiHitProducer::SmearingModel smearing_model) {
213  assert(0);
214 
215  local.SetX(GetSmearedValue(local[0], 0, smearing_model));
216  };
217 
218  double GetSpatialSigma() const { return mSigma; };
219  bool CartesianThreeDeeOnly() const { return true; };
220 
221  ClassDef(EicKfNodeTemplateLinear1D,1)
222 };
223 
225 {
226  public:
227  EicKfNodeTemplateRadial1D(TGeoMatrix *transformation = 0):
228  EicKfNodeTemplate1D(transformation) {};
230 
231  double GetSpatialSigma() const { return mSigma; };
232  bool CylindricalThreeDeeOnly() const { return true; };
233 
234  void FillGranularityArray(bool useCartesian, double spGranularity,
235  double aGranularity, double gra[]) const {
236  gra[0] = spGranularity;
237  };
238  //void FillSmearingArray(double spSmearing, double aSmearing, double sme[]) const {
239  //sme[0] = spSmearing;
240  //};
241  double GetSmearingValue(double spSmearing, const EicTrackingDigiHit *hit, unsigned iq) const {
242  return (iq ? 0.0 : spSmearing);
243  };
244  void FillMinMaxArrays(bool useCartesian, const std::set<double> &xMin, const std::set<double> &xMax,
245  const std::set<double> &yMin, const std::set<double> &yMax,
246  const std::set<double> &rMin, const std::set<double> &rMax,
247  double min[], double max[]) const {
248  min[0] = 0.0;
249  max[0] = *rMax.rbegin();
250  };
251 
252  void SmearLocalCoord(TVector3 &local, EicDigiHitProducer::SmearingModel smearing_model) {
253  assert(0);
254  };
255 
256  void CartesianToCylindrical(const TVector3 &crs, double tmplCoord[]) const {
257  ThreeDeeToTemplate(crs, tmplCoord);
258  };
259  TVector3 TemplateToThreeDee(const double tmplCoord[]) const {
260  TVector3 vv(0.0, 0.0, 0.0);
261 
262  // NB: 'phi' can be any (?) -> take 0.0;
263  double r = tmplCoord[0], phi = 0.0;
264  vv[0] = r*cos(phi); vv[1] = r*sin(phi);
265 
266  return vv;
267  };
268  void ThreeDeeToTemplate(const TVector3 &crs, double tmplCoord[]) const {
269  double x = crs[0], y = crs[1];
270  tmplCoord[0] = sqrt(x*x+y*y);
271  };
272 
273  ClassDef(EicKfNodeTemplateRadial1D,1)
274 };
275 
277 {
278  public:
279  EicKfNodeTemplateAsimuthal1D(TGeoMatrix *transformation = 0):
280  EicKfNodeTemplate1D(transformation) {};
282 
283  double GetAngularSigma() const { return mSigma; };
284  bool CylindricalThreeDeeOnly() const { return true; };
285 
286  void FillGranularityArray(bool useCartesian, double spGranularity,
287  double aGranularity, double gra[]) const {
288  gra[0] = aGranularity;
289  };
290  //void FillSmearingArray(double spSmearing, double aSmearing, double sme[]) const {
291  //sme[0] = aSmearing;
292  //};
293  // Don't know what to do with this value, sorry;
294  double GetSmearingValue(double spSmearing, const EicTrackingDigiHit *hit, unsigned iq) const {
295  return 0.0;
296  };
297  void FillMinMaxArrays(bool useCartesian, const std::set<double> &xMin, const std::set<double> &xMax,
298  const std::set<double> &yMin, const std::set<double> &yMax,
299  const std::set<double> &rMin, const std::set<double> &rMax,
300  double min[], double max[]) const {
301  min[0] = -TMath::Pi();
302  max[0] = TMath::Pi();
303  };
304  TVector3 TemplateToThreeDee(const double tmplCoord[]) const {
305  TVector3 vv(0.0, 0.0, 0.0);
306 
307  // NB: 'r' can be any (?) -> take 1.0;
308  double r = 1.0, phi = tmplCoord[0];
309  vv[0] = r*cos(phi); vv[1] = r*sin(phi);
310 
311  return vv;
312  };
313  void CartesianToCylindrical(const TVector3 &crs, double tmplCoord[]) const {
314  ThreeDeeToTemplate(crs, tmplCoord);
315  };
316  void ThreeDeeToTemplate(const TVector3 &crs, double tmplCoord[]) const {
317  double x = crs[0], y = crs[1];
318  tmplCoord[0] = atan2(y, x);
319  };
320 
321  void SmearLocalCoord(TVector3 &local, EicDigiHitProducer::SmearingModel smearing_model) {
322  assert(0);
323  };
324 
325  ClassDef(EicKfNodeTemplateAsimuthal1D,1)
326 };
327 
328 // ---------------------------------------------------------------------------------------
329 
331 {
333 
334  public:
335  EicKfNodeTemplateOrth2D(TGeoMatrix *transformation = 0, bool xy_mode = true):
336  EicKfNodeTemplate(transformation), mXYmode(xy_mode) {
337  mSigma[0] = mSigma[1] = mPitch[0] = mPitch[1] = 0.0;
339  };
341 
342  unsigned GetMdim() const { return 2; };
343  double GetSigma(unsigned iq) const { return (iq <= 1 ? mSigma[iq] : 0.0); };
344  double GetPitch(unsigned iq) const { return (iq <= 1 ? mPitch[iq] : 0.0); };
345  double GetPixelCenterOffset(unsigned iq) const {
346  return (iq <= 1 ? mPixelCenterOffset[iq] : 0.0);
347  };
348 
349  // THINK: so it is the same for EicKfNodeTemplateCartesian2D & EicKfNodeTemplateCylindrical2D?;
350  void FillGranularityArray(bool useCartesian, double spGranularity,
351  double aGranularity, double gra[]) const {
352  gra[0] = spGranularity;
353  gra[1] = useCartesian ? spGranularity : aGranularity;
354  };
355  void FillMinMaxArrays(bool useCartesian, const std::set<double> &xMin, const std::set<double> &xMax,
356  const std::set<double> &yMin, const std::set<double> &yMax,
357  const std::set<double> &rMin, const std::set<double> &rMax,
358  double min[], double max[]) const {
359  if (useCartesian) {
360  // Well, I guess can do by hand?;
361  min[0] = *xMin.begin();
362  max[0] = *xMax.rbegin();
363  min[1] = *yMin.begin();
364  max[1] = *yMax.rbegin();
365  } else {
366  min[0] = 2.0;
367  max[0] = *rMax.rbegin();
368  // Should work for stere skewed option as well, right?;
369  min[1] = -TMath::Pi();
370  max[1] = TMath::Pi();
371  } //if
372  };
373 
374  // This call is the same for all 2D templates;
375  void PackSmearedHit(TClonesArray *arr,
376  const TString &detName,
377  const EicMoCaPoint *point, unsigned kfNodeID,
378  TVector3 &global,
379  TVector3 &local) {
380  new((*arr)[arr->GetEntriesFast()])
381  EicTrackingDigiHitOrth2D(detName, point, kfNodeID, global, local, mXYmode, mSigma);
382  };
383 
385 
386  void CartesianToCylindrical(const TVector3 &crs, double tmplCoord[]) const {
387  double x = crs[0], y = crs[1], r = sqrt(x*x+y*y);
388  double phi = atan2(y, x);
389 
390  tmplCoord[0] = r;
391  tmplCoord[1] = phi;
392  };
393 
394  bool mXYmode;
395 
396  protected:
397  // Well, do not see any good reason to introduce true correlations; if such
398  // a detector ever becomes needed, just create a separate class;
399  Double_t mSigma[2]; // gaussian sigma in all cases
400  Double_t mPixelCenterOffset[2];
401 
402  private:
403  void SetSigma(double sigmaX, double sigmaY) {
404  mSigma[0] = sigmaX; mSigma[1] = sigmaY;
405  };
406  void SetPitch(double pitchX, double pitchY) {
407  mPitch[0] = pitchX; mPitch[1] = pitchY;
408 
409  for(unsigned xy=0; xy<2; xy++)
410  mSigma[xy] = mPitch[xy]/sqrt(12.);
411  };
412 
413  Double_t mPitch[2]; // 2D pitch in case of 'Quantize' digitization
414 
416 };
417 
418 // THINK: does nothing; yet want to have a separate class, "symmetric" to the
419 // Cylindrical one;
421 {
422  public:
423  // NB: typically use XY-based mode (true); the other option iz TZ-mode (false);
424  EicKfNodeTemplateCartesian2D(TGeoMatrix *transformation = 0, bool xy_mode = true):
425  EicKfNodeTemplateOrth2D(transformation, xy_mode) {};
427 
428  void SmearLocalCoord(TVector3 &local, EicDigiHitProducer::SmearingModel smearing_model) {
429  if (mXYmode) {
430  // In this case smear XY-coordinates;
431  local.SetX(GetSmearedValue(local[0], 0, smearing_model));
432  local.SetY(GetSmearedValue(local[1], 1, smearing_model));
433  } else {
434  // FIXME: for now do not want these extra complications;
435  assert(smearing_model == EicDigiHitProducer::Smear);
436 
437  // In this case smear RZ-coordinates;
438  {
439  // NB: should be in sync with EicPlanarRecoHit::EicPlanarRecoHit();
440  TVector3 uu = TVector3(local.Y(),-local.X(),0).Unit();
441  double smeared_value = GetSmearedValue(0.0, 0, smearing_model);
442 
443  local += smeared_value * uu;
444  }
445  local.SetZ(GetSmearedValue(local[2], 1, smearing_model));
446  } //if
447  };
448 
449  double GetSmearingValue(double spSmearing, const EicTrackingDigiHit *hit, unsigned iq) const {
450  return (iq <= 1 ? spSmearing : 0.0);
451  };
452  double GetSpatialSigma() const {
453  return mSigma[0] < mSigma[1] ? mSigma[0] : mSigma[1];
454  };
455 
457 };
458 
460 {
461  public:
462  EicKfNodeTemplateCylindrical2D(TGeoMatrix *transformation = 0):
463  EicKfNodeTemplateOrth2D(transformation), mStereoSkewRadius(0.0) {};
465 
466  double GetSpatialSigma() const { return mSigma[0]; };
467  double GetAngularSigma() const { return mSigma[1]; };
468 
469  double GetSmearingValue(double spSmearing, const EicTrackingDigiHit *hit, unsigned iq) const {
470  switch (iq) {
471  case 0:
472  return spSmearing;
473  case 1:
474  {
475  double r = hit->_GetCoord(0); assert(r);
476  return spSmearing/r;
477  }
478  default:
479  return 0.0;
480  } //switch
481  };
482  TVector3 TemplateToThreeDee(const double tmplCoord[]) const {
483  TVector3 vv(0.0, 0.0, 0.0);
484 
485  double r = tmplCoord[0], phi = tmplCoord[1];
486  if (mStereoSkewRadius) {
487  // FIXME: do a proper check here; this regularization is really crap;
488  //assert(mStereoSkewRadius < r);
490 
491  // NB: mStereoSkewRadius sign will be automatically taken into account here;
492  if (mStereoSkewRadius <= r) phi -= asin(mStereoSkewRadius/r);
493  } //if
494  vv[0] = r*cos(phi); vv[1] = r*sin(phi);
495 
496  return vv;
497  };
498  void ThreeDeeToTemplate(const TVector3 &crs, double tmplCoord[]) const {
499  CartesianToCylindrical(crs, tmplCoord);
500 
501  // If stereo skew is defined, modify asimuthal angle (which is tmplCoord[1]);
502  if (mStereoSkewRadius) {
503  // FIXME: do a proper check here;
504  double r = tmplCoord[0]; assert(mStereoSkewRadius < r);
505 
506  // NB: mStereoSkewRadius sign will be automatically taken into account here;
507  tmplCoord[1] += asin(mStereoSkewRadius/r);
508  } //if
509  };
510 
511  void SmearLocalCoord(TVector3 &local, EicDigiHitProducer::SmearingModel smearing_model) {
512  assert(0);
513  };
514 #if _OFF_
515  void StoreDigiHit(TClonesArray *arr,
516  const TString &detName,
517  const EicMoCaPoint *point, unsigned kfNodeID,
518  TVector3 &global,
519  TVector3 &local, EicDigiHitProducer::SmearingModel smearing_model) {
520  assert(0);
521  };
522 #endif
524  // FIXME: may later want to use for other templates as well;
525  void SetPixelCenterOffsets(double offsetR, double offsetA = 0.0) {
526  mPixelCenterOffset[0] = offsetR;
527  mPixelCenterOffset[1] = offsetA;
528  };
529 
530  private:
531  double mStereoSkewRadius;
532 
534 };
535 
536 // ---------------------------------------------------------------------------------------
537 
539 {
541 
542  public:
543  EicKfNodeTemplateOrth3D(TGeoMatrix *transformation = 0): EicKfNodeTemplate(transformation) {
544  mSigma[0] = mSigma[1] = mSigma[2] = 0.0;
545  };
547 
548  unsigned GetMdim() const { return 3; };
549  double GetSigma(unsigned iq) const { return (iq <= 2 ? mSigma[iq] : 0.0); };
550  double GetPitch(unsigned iq) const { assert(0); return 0.0; };
551  double GetPixelCenterOffset(unsigned iq) const { assert(0); return 0.0; };
552 
553  void FillGranularityArray(bool useCartesian, double spGranularity,
554  double aGranularity, double gra[]) const {
555  assert(0);
556  };
557  double GetSmearingValue(double spSmearing, const EicTrackingDigiHit *hit, unsigned iq) const {
558  assert(0); return 0.0;
559  };
560  void FillMinMaxArrays(bool useCartesian, const std::set<double> &xMin, const std::set<double> &xMax,
561  const std::set<double> &yMin, const std::set<double> &yMax,
562  const std::set<double> &rMin, const std::set<double> &rMax,
563  double min[], double max[]) const {
564  assert(0);
565  };
566  //void FillSmearingArray(double spSmearing, double aSmearing, double sme[]) const {
567  //assert(0);
568  //};
569 
570  void SmearLocalCoord(TVector3 &local, EicDigiHitProducer::SmearingModel smearing_model) {
571  assert(0);
572  };
573  void PackSmearedHit(TClonesArray *arr,
574  const TString &detName,
575  const EicMoCaPoint *point, unsigned kfNodeID,
576  TVector3 &global,
577  TVector3 &local) {
578  assert(0);
579  };
580 #if _OLD_
581  int PackSmearedHit(TClonesArray *arr, const TString &detName,
582  const EicMoCaPoint *point, unsigned kfNodeID,
583  double localCoord[], double localDirection[], TVector3 &global) {
584  assert(0);
585  // It has never been checked this stuff works after Nov'2015 changes;
586 
587  // And diagonal cov.matrix, please;
588  double localCov[3][3];
589  memset(localCov, 0x00, sizeof(localCov));
590  for(int iq=0; iq<3; iq++)
591  localCov[iq][iq] = mSigma[iq] * mSigma[iq];
592 
593  TVector3 vCoord = TVector3(localCoord);
594  new((*arr)[arr->GetEntriesFast()])
595  //EicTrackingDigiHit3D(detName, point, global, localCoord, localCov);
596  EicTrackingDigiHit3D(detName, point, global, vCoord, localCov);
597  };
598 #endif
599 
601 
602  private:
603  void SetSigma(double sigmaX, double sigmaY, double sigmaZ) {
604  mSigma[0] = sigmaX; mSigma[1] = sigmaY; mSigma[2] = sigmaZ;
605  };
606 
607  // Well, do not see any good reason to introduce true correlations; if such
608  // a detector ever becomes needed, just create a separate class;
609  Double_t mSigma[3]; // gaussian sigma in volume local coordinate system
610 
612 };
613 
614 // ---------------------------------------------------------------------------------------
615 
616 #if _LATER_
617 class EicKfNodeTemplateAxial3D: public EicKfNodeTemplate
618 {
619  friend class EicTrackingDigiHitProducer;
620 
621  public:
622  EicKfNodeTemplateAxial3D(TGeoMatrix *transformation = 0): EicKfNodeTemplate(transformation) {
623  mSigmaL = mSigmaT = 0.0;
624  };
625  ~EicKfNodeTemplateAxial3D() {};
626 
627  unsigned GetMdim() const { return 3; };
628  // This call is sort of fake here;
629  double GetSigma(unsigned iq) const {
630  switch (iq) {
631  case 0:;
632  case 1:
633  return mSigmaT;
634  case 2:
635  return mSigmaL;
636  default:
637  return 0.0;
638  } //switch
639  };
640  double GetPitch(unsigned iq) const { assert(0); };
641  double GetPixelCenterOffset(unsigned iq) const { assert(0); };
642  int PackSmearedHit(TClonesArray *arr, const TString &detName,
643  const EicMoCaPoint *point, unsigned kfNodeID,
644  TVector3 &local, double localDirection[], TVector3 &global) {
645  assert(0);
646  };
647  //void FillSmearingArray(double spSmearing, double aSmearing, double sme[]) const {
648  //assert(0);
649  //};
650 
651  void FillGranularityArray(bool useCartesian, double spGranularity,
652  double aGranularity, double gra[]) const {
653  assert(0);
654  };
655  double GetSmearingValue(double spSmearing, const EicTrackingDigiHit *hit, unsigned iq) const {
656  assert(0); return 0.0;
657  };
658  void FillMinMaxArrays(bool useCartesian, const std::set<double> &xMin, const std::set<double> &xMax,
659  const std::set<double> &yMin, const std::set<double> &yMax,
660  const std::set<double> &rMin, const std::set<double> &rMax,
661  double min[], double max[]) const {
662  assert(0);
663  };
664 
665  int StoreDigiHit(TClonesArray *arr, EicDigiHitProducer::SmearingModel originalSmearingModel,
666  EicDigiHitProducer::SmearingModel effectiveSmearingModel,
667  const TString &detName,
668  const EicMoCaPoint *point, unsigned kfNodeID,
669  TVector3 &local, double localDirection[], TVector3 &global) {
670  ConvertLocalCoordInPlace(localCoord);
671 
672  //
673  // FIXME: "sigma != 0" case?;
674  //
675 
676  // This part is a bit nasty; may want to write a more generic call; basically all I need
677  // is to calculate 3D rotation which moves local Z axis to localDirection[] (or vice versa?);
678  TVector3 zLocal(0.0, 0.0, 1.0), zAxis(localDirection[0], localDirection[1], localDirection[2]);
679  TVector3 xAxis = (zLocal.Cross(zAxis)).Unit(), yAxis = zAxis.Cross(xAxis);
680 
681  double data[3][3] = {{xAxis.X(), yAxis.X(), zAxis.X()},
682  {xAxis.Y(), yAxis.Y(), zAxis.Y()},
683  {xAxis.Z(), yAxis.Z(), zAxis.Z()}};
684  TGeoRotation grr;
685  grr.SetMatrix((double*)data);
686 
687  // Ok, now ehen rotation matrix is calculated, need to move localCoord[] into the rotated
688  // system (where it is easy to smear it);
689  double rotatedCoord[3];
690  grr.MasterToLocal(localCoord, rotatedCoord);
691 #if 0
692  printf("loc(xx): %f %f %f\n", localCoord [0], localCoord [1], localCoord [2]);
693  printf("rot(xx): %f %f %f\n", rotatedCoord[0], rotatedCoord[1], rotatedCoord[2]);
694  {
695  double bff[3];
696  grr.MasterToLocalVect(localDirection, bff);
697  printf("loc(nn): %f %f %f\n", localDirection [0], localDirection [1], localDirection [2]);
698  printf("rot(nn): %f %f %f\n\n", bff[0], bff[1], bff[2]);
699  }
700 #endif
701 
702  // In rotated coordinate system cov.matrix is trivially diagonal (do not care about
703  // arbitrary phi rotation around Z axis);
704  double qsigma[3] = {mSigmaT, mSigmaT, mSigmaL};
705 
706  // If no action was requested (like in case of real hit import),
707  // do not touch "original" local[] at all (so no smearing);
708  if (effectiveSmearingModel != EicDigiHitProducer::NoAction) {
709  // This is just a dummy call for now;
710  for(int iq=0; iq<3; iq++)
711  rotatedCoord[iq] += gRandom->Gaus(0.0, qsigma[iq]);
712  } //if
713 
714  // Move back; localCoord[] is now smeared properly;
715  grr.LocalToMaster(rotatedCoord, localCoord);
716 
717  // Now need to calculate cov.matrix; just fill out diagonal elements and then move
718  // back from rotated to local system;
719  double rotatedCov[3][3], localCov[3][3];
720  memset(rotatedCov, 0x00, sizeof(rotatedCov));
721  for(int iq=0; iq<3; iq++)
722  rotatedCov[iq][iq] = qsigma[iq] * qsigma[iq];
723 
724  memset(localCov, 0x00, sizeof(localCov));
725  // FIXME: not too much efficient;
726  for(unsigned ip=0; ip<3; ip++)
727  for(unsigned ir=0; ir<3; ir++)
728  for(unsigned is=0; is<3; is++)
729  for(unsigned iq=0; iq<3; iq++)
730  //localCov[ip][iq] += data[ir][ip] * rotatedCov[ir][is] * data[is][iq];
731  localCov[ip][iq] += data[ip][ir] * rotatedCov[ir][is] * data[iq][is];
732 
733  new((*arr)[arr->GetEntriesFast()])
734  EicTrackingDigiHit3D(detName, point, global, localCoord, localCov);
735 
736  return 0;
737  };
738 
740 
741  TVector3 TemplateToThreeDee( const double tmplCoord[]) const { assert(0); };
742  void ThreeDeeToTemplate(const TVector3 &crs, double tmplCoord[]) const { assert(0); };
743 
744  private:
745  void SetSigma(double sigmaL, double sigmaT) {
746  mSigmaL = sigmaL; mSigmaT = sigmaT;
747  };
748 
749  // Well, do not see any good reason to introduce true correlations; if such
750  // a detector ever becomes needed, just create a separate class;
751  Double_t mSigmaL; // gaussian sigma along track direction
752  Double_t mSigmaT; // gaussian sigma in "both" transverse directions
753 
754  ClassDef(EicKfNodeTemplateAxial3D,1)
755 };
756 #endif
757 // ---------------------------------------------------------------------------------------
758 
760 {
761  friend class EicHtcTask;
762 
763  public:
764  EicTrackingDigiHitProducer()/*: mHitImportMode(false), mForceRealHitSmearing(false)*/ {};
765  EicTrackingDigiHitProducer(const char *name,
766  SmearingModel smearingModel = EicDigiHitProducer::Smear);
768 
769  // Want just to allocate mDigiHitArray of proper type objects;
771 
772  void DefineKfNodeTemplate1D(double angle, double sigmaOrPitch) {
773  TGeoMatrix *mtx = 0;
774 
775  if (angle) {
776  mtx = new TGeoRotation();
777  mtx->RotateZ(angle);
778  } //if
779 
781 
782  DefineKfNodeTemplateCore1D(node, sigmaOrPitch);
783  };
784 
785  void DefineKfNodeTemplateX(double sigmaOrPitch) {
786  DefineKfNodeTemplate1D( 0.0, sigmaOrPitch);
787  };
788  void DefineKfNodeTemplateY(double sigmaOrPitch) {
789  DefineKfNodeTemplate1D(90.0, sigmaOrPitch);
790  };
791  void DefineKfNodeTemplateR(double sigmaOrPitch) {
793 
794  DefineKfNodeTemplateCore1D(node, sigmaOrPitch);
795  };
796  void DefineKfNodeTemplateA(double sigmaOrPitch) {
798 
799  DefineKfNodeTemplateCore1D(node, RADIANS(sigmaOrPitch));
800  };
801 
802  void DefineKfNodeTemplateXY(double sigmaOrPitchX, double sigmaOrPitchY) {
804 
805  DefineKfNodeTemplateCore2D(node, sigmaOrPitchX, sigmaOrPitchY);
806  };
807  void DefineKfNodeTemplateTZ(double sigmaOrPitchX, double sigmaOrPitchY) {
809 
810  DefineKfNodeTemplateCore2D(node, sigmaOrPitchX, sigmaOrPitchY);
811  };
813  double sigmaOrPitchA) {
815 
816  DefineKfNodeTemplateCore2D(node, sigmaOrPitchR, RADIANS(sigmaOrPitchA));
817 
818  return node;
819  };
820 
821  void DefineKfNodeTemplateOrth3D(double sigmaX, double sigmaY, double sigmaZ) {
823 
824  //assert(mOriginalSmearingModel == EicDigiHitProducer::Smear);
826  node->SetSigma(sigmaX, sigmaY, sigmaZ);
827 
828  mKfNodeTemplates.push_back(node);
829  AssignDigiHitClassName("EicTrackingDigiHit3D");
830  };
831 #if _LATER_
832  void DefineKfNodeTemplateAxial3D(double sigmaL, double sigmaT) {
833  EicKfNodeTemplateAxial3D *node = new EicKfNodeTemplateAxial3D();
834 
835  assert(mOriginalSmearingModel == EicDigiHitProducer::Smear);
836  //mOriginalSmearingModel == EicDigiHitProducer::Smear ?
837  node->SetSigma(sigmaL, sigmaT);// : node->SetPitch(sigmaOrPitchX, sigmaOrPitchY);
838 
839  mKfNodeTemplates.push_back(node);
840  AssignDigiHitClassName("EicTrackingDigiHit3D");
841  };
842 #endif
843 
844  // Tracking-specific generic (ideal) call; NB: TPC will handle hits totally
845  // differently; also at some point will have to implement hit overlap and
846  // things like this;
847  int HandleHit(const EicMoCaPoint *point);
848 
849  //void ForceRealHitSmearing() {
850  //mForceRealHitSmearing = true;
851  // mEffectiveSmearingModel = mOriginalSmearingModel;
852  //};
853 
854  protected:
855 
856  void AssignDigiHitClassName(const char *name) {
857  // Protected method -> assume 0 pointer can not happen;
858  if (!mDigiHitClassName.IsNull() && !mDigiHitClassName.EqualTo(name))
859  fLogger->Fatal(MESSAGE_ORIGIN, "\033[5m\033[31m attempt to define two different output"
860  " hit classes (%s & %s)! Not suported yet ... \033[0m",
861  mDigiHitClassName.Data(), name);
862 
864  };
865 
866  private:
867  TString mDigiHitClassName; // either EicTrackingDigiHit1D or EicTrackingDigiHitOrth2D
868 
869  // Move to EicDigiHitProducer and merge with Calorimeter codes later;
870  virtual EicDigiParData *getEicDigiParDataPtr() { return 0; };
871  virtual void Finish();
872 
873  // Covariance matrix will be calculated differently (sqrt(12) involved in case of
874  // 'Quantize' mode);
875  //SmearingModel mOriginalSmearingModel; // the mode given in constructor arguments
876  SmearingModel mSmearingModel;// the effective smearing mode (NoAction if import hits)
877 
878  //EicRunDigi *mDigiRun; //! transient pointer to EicRunDigi instance
879  //Bool_t mHitImportMode; // 'true' if real hit import is requested
880  public:
881  std::vector<EicKfNodeTemplate*> mKfNodeTemplates;
882  private:
883  //Bool_t mForceRealHitSmearing; // may want to force real hit smearing a-la MC mode
884 
885  void DefineKfNodeTemplateCore1D(EicKfNodeTemplate1D *node, double sigmaOrPitch) {
887  node->SetSigma(sigmaOrPitch) : node->SetPitch(sigmaOrPitch);
888 
889  mKfNodeTemplates.push_back(node);
890  AssignDigiHitClassName("EicTrackingDigiHit1D");
891  };
893  double sigmaOrPitch1, double sigmaOrPitch2) {
895  node->SetSigma(sigmaOrPitch1, sigmaOrPitch2) : node->SetPitch(sigmaOrPitch1, sigmaOrPitch2);
896 
897  mKfNodeTemplates.push_back(node);
898  AssignDigiHitClassName("EicTrackingDigiHitOrth2D");
899  };
900 
902 };
903 
904 #endif