EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Device.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Device.cxx
1 
10 #include "eicsmear/smear/Device.h"
11 
12 #include <algorithm>
13 #include <functional>
14 #include <iterator>
15 #include <stdexcept>
16 #include <string>
17 #include <vector>
18 
19 #include <TUUID.h>
20 #include <TDatabasePDG.h>
21 
24 
25 using std::cout;
26 using std::cerr;
27 using std::endl;
28 
29 namespace Smear {
30 
31 
34  // - create a string that identifies the smeared observable (say, phi)
35  // - create a string ("phi"), translate it to a TF1 ("x")
36  // - relate the smeared value to the observable using GetX()
37  //But this TF1 is always identity, modulo range restrictions that cause obscure errors
38 bool Device::Init(const TString& kinematicFunction,
39  const TString& resolutionFunction, int genre) {
40  Accept.SetGenre(genre);
41  // Use FormulaString to parse the kinematic function,
42  // though we can't use a FormulaString for the kinematic
43  // function as we need TF1 functionality.
44  FormulaString f(kinematicFunction.Data());
45  // The expression has to have exactly one variable.
46  mSmeared = f.Variables().front();
47  // Use UUID for ROOT function name to avoid instances clashing
48  mKinematicFunction = new TF1(TUUID().AsString(),
49  f.GetString().c_str(), -1e15, 1.e16);
50  // Set the resolution function.
51  mFormula = new FormulaString(resolutionFunction.Data());
52  // cout << mFormula->GetString() << endl;
53  return mFormula && mKinematicFunction;
54 }
55 
56 Device::Device(KinType type, const TString& formula, EGenre genre)
57 : mSmeared(type)
58 , mKinematicFunction(NULL)
59 , mFormula(NULL) {
60  Accept.SetGenre(genre);
61  Init(FormulaString::GetKinName(type), formula, genre);
62 }
63 
64 Device::Device(const TString& variable, const TString& resolution,
65  EGenre genre)
66 : mSmeared(kInvalidKinType)
67 , mKinematicFunction(NULL)
68 , mFormula(NULL) {
69  Init(variable, resolution, genre);
70 }
71 
72 Device::Device(const Device& that)
73 : Smearer(that)
74 , mSmeared(that.mSmeared)
75 , mKinematicFunction(NULL)
76 , mFormula(NULL)
77 , mDimensions(that.mDimensions) {
78  if (that.mKinematicFunction) {
79  mKinematicFunction = static_cast<TF1*>(
80  that.mKinematicFunction->Clone(TUUID().AsString()));
81  } // if
82  if (that.mFormula) {
83  mFormula = static_cast<FormulaString*>(that.mFormula->Clone());
84  } // if
85 }
86 
88  if (mFormula) {
89  delete mFormula;
90  mFormula = NULL;
91  } // if
92  if (mKinematicFunction) {
93  delete mKinematicFunction;
94  mKinematicFunction = NULL;
95  } // if
96 }
97 
99  // Test for acceptance and do nothing if it fails.
100  if (!Accept.Is(prt)) {
101  return;
102  } // if
103  // Get each argument for the resolution function from the particle.
104  const std::vector<KinType> vars = mFormula->Variables();
105  std::vector<double> args;
106  for (unsigned i(0); i < vars.size(); ++i) {
107  args.push_back(GetVariable(prt, vars.at(i)));
108  } // for
109  // Evaluate the quantity to smear and the resolution, then throw
110  // a random smeared value.
111  double unsmeared = mKinematicFunction->Eval(GetVariable(prt, mSmeared));
112  double resolution = mFormula->Eval(args);
113  double smeared = mDistribution.Generate(unsmeared, resolution);
114  // mDistribution.Print();
115  if ( false && abs(prt.Id())==11){
116  // if ( mSmeared != kE ){std::cerr << " ====================== " << mSmeared << std::endl; throw(-1);}
117  std::cout << " ====================== mSmeared = " << mSmeared << std::endl;
118  // prt.Print();
119  std::cout << " orig eta = " << prt.GetEta()<< std::endl;
120  std::cout << "unsmeared " << unsmeared << std::endl;
121  std::cout << "resolution " << resolution << std::endl;
122  std::cout << "smeared " << smeared << std::endl;
123  std::cout << "mSmeared " << mSmeared << std::endl;
124  }
125  // mKinematicFunction->Print();
126  if ( mKinematicFunction->GetFormula()->GetExpFormula() != "x" ){
127  std::cerr << "Formula = " << mKinematicFunction->GetFormula()->GetExpFormula() << std::endl;
128  throw -1;
129  }
130  // if ( smeared < 0 || fabs(mKinematicFunction->GetX(smeared)-smeared)>1e-5 ) cout << mKinematicFunction->GetX(smeared) << " " << smeared << endl;
131  out.SetVariable(mKinematicFunction->GetX(smeared), mSmeared);
132  // Fix angles to the correct ranges.
133  if (kTheta == mSmeared) {
134  out.SetTheta ( FixTheta(out.GetTheta() ), false);
135  } else if (kPhi == mSmeared) {
136  out.SetPhi ( FixPhi(out.GetPhi() ), false);
137  } // else if
138  // Ensure E, p are positive definite
140  if ( std::isnan( GetVariable (out, mSmeared ) ) ) cout << "Problem. smeared is " << smeared << " but propagated nan in " << mSmeared<< endl;
141  // std::cout << "Bye Smear" << std::endl << std::endl;
142 }
143 
144 Device* Device::Clone(const char* ) const {
145  return new Device(*this);
146 }
147 
148 void Device::Print(Option_t* /* option */) const {
149  const std::string name = FormulaString::GetKinName(mSmeared);
150  std::cout << "Device smearing " << name << " with sigma(" << name <<
151  ") = " << mFormula->GetInputString() << std::endl;
152 }
153 
154 } // namespace Smear