Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-06-01 07:06:42

0001 /**
0002  \file
0003  Implementation of class Smear::FormulaString.
0004  
0005  \author    Michael Savastio
0006  \date      2011-08-19
0007  \copyright 2011 Brookhaven National Lab
0008  */
0009 
0010 #include "eicsmear/smear/FormulaString.h"
0011 
0012 #include <algorithm>
0013 #include <iterator>
0014 #include <list>
0015 #include <map>
0016 #include <string>
0017 #include <vector>
0018 
0019 #include <TFormula.h>
0020 #include <TString.h>
0021 #include <TUUID.h>
0022 
0023 namespace {
0024 
0025 // Valid patterns for the names of smearing function variables.
0026 // These are replaced with "x", "y", "z", "t" when the functions are parsed.
0027 std::vector<std::string> functionPatterns;
0028 
0029 // Returns a reference to the function pattern vector, filling
0030 // it first if needed.
0031 const std::vector<std::string>& patterns() {
0032   if (functionPatterns.empty()) {
0033     const std::string array[6] = {"E", "P", "theta", "phi", "pT", "pZ"};
0034     functionPatterns.assign(array, array + 6);
0035   }  // if
0036   return functionPatterns;
0037 }
0038 
0039 // Variables recognised by ROOT::TFormula.
0040 // These replace the functionPatterns above so ROOT::TFormula can
0041 // understand the formula string.
0042 const std::string tformulaVariables[4] = {"x", "y", "z", "t"};
0043 
0044 // KinType keyed by corresponding string name.
0045 std::map<std::string, Smear::KinType> kinTypes;
0046 
0047 // Returns a reference to the KinType table, populating it first if needed.
0048 const std::map<std::string, Smear::KinType>& kinTypeTable() {
0049   if (kinTypes.empty()) {
0050     kinTypes.insert(std::make_pair("E", Smear::kE));
0051     kinTypes.insert(std::make_pair("P", Smear::kP));
0052     kinTypes.insert(std::make_pair("theta", Smear::kTheta));
0053     kinTypes.insert(std::make_pair("phi", Smear::kPhi));
0054     kinTypes.insert(std::make_pair("pT", Smear::kPt));
0055     kinTypes.insert(std::make_pair("pZ", Smear::kPz));
0056   }  // if
0057   return kinTypes;
0058 }
0059 
0060 }  // anonymous namespace
0061 
0062 namespace Smear {
0063 
0064 // This is basically a wrapper around ROOT::TFormula, with functionality
0065 // to parse functions containing "P", "theta" etc into "x, y, z, t"
0066 // as accepted by TFormula.
0067 
0068 FormulaString::~FormulaString() {
0069   if (mFormula) {
0070     delete mFormula;
0071     mFormula = NULL;
0072   }  // if
0073 }
0074 
0075 FormulaString::FormulaString()
0076 : mFormula(NULL) {
0077 }
0078 
0079 FormulaString::FormulaString(const std::string& formula)
0080 : mFormula(NULL)
0081 , mInput(formula) {
0082   std::string f = Parse(formula);
0083   mFormula = new TFormula(TUUID().AsString(), f.c_str());
0084 }
0085 
0086 double FormulaString::Eval(const std::vector<double>& args) const {
0087   if (args.size() != mVariables.size()) {
0088     std::cerr << "FormulaString::Eval() got " << args.size() <<
0089     " arguments, expected " << mVariables.size() << std::endl;
0090   }  // if
0091   // TFormula accepts up to four arguments.
0092   // Use default zeros for absent arguments.
0093   std::vector<double> a(args);
0094   a.resize(4, 0.);
0095   return mFormula->Eval(a.at(0), a.at(1), a.at(2), a.at(3));
0096 }
0097 
0098 std::vector<KinType> FormulaString::Variables() const {
0099   return mVariables;
0100 }
0101 
0102   /// TODO: kk Implicitly limits the number of variables in a formula to 4.
0103   /// TODO: kk Needs documentation and graceful handling.
0104 std::string FormulaString::Parse(const std::string& formula) {
0105   using std::string;
0106   using std::vector;
0107   mVariables.clear();
0108   // Get all the patterns that appear in the input string
0109   // We want to preserve the order in which the arguments appear
0110   // so store the position of each argument with its name.
0111   std::map<int, string> args;
0112   typedef vector<string>::const_iterator StrIter;
0113   for (StrIter i = patterns().begin(); i != patterns().end(); ++i) {
0114     size_t position = formula.find(*i);
0115     if (position != string::npos) {
0116       args.insert(std::make_pair(position, *i));
0117     }  // if
0118   }  // for
0119   // Substitute each pattern (E, P etc) with
0120   // variables recognised by ROOT::TFormula (x, y, z, t)
0121   // Also, accumulate the Smear::KinType corresponding to each pattern
0122   // in the vector function argument.
0123   std::list<string> substitutions(tformulaVariables,
0124                                   tformulaVariables + 4);
0125   TString s(formula);
0126   for (std::map<int, string>::const_iterator i = args.begin();
0127       i != args.end(); ++i) {
0128     s.ReplaceAll(i->second, substitutions.front());
0129     substitutions.pop_front();
0130     mVariables.push_back(GetKinType(i->second));
0131   }  // for
0132   return string(s.Data());
0133 }
0134 
0135 std::string FormulaString::GetString() const {
0136   std::string str;
0137   if (mFormula) {
0138     str = mFormula->GetTitle();
0139   }  // if
0140   return str;
0141 }
0142 
0143 std::string FormulaString::GetInputString() const {
0144   return mInput;
0145 }
0146 
0147 KinType FormulaString::GetKinType(const std::string& name) {
0148   KinType type(kInvalidKinType);
0149   if (kinTypeTable().find(name) != kinTypeTable().end()) {
0150     type = kinTypes[name];
0151   }  // if
0152   return type;
0153 }
0154 
0155 std::string FormulaString::GetKinName(KinType type) {
0156   std::string name;
0157   std::map<std::string, KinType>::const_iterator i;
0158   for (i = kinTypeTable().begin(); i != kinTypeTable().end(); ++i) {
0159     if (i->second == type) {
0160       name = i->first;
0161     }  // if
0162   }  // for
0163   return name;
0164 }
0165 
0166 }  // namespace Smear