BLEvaluator.hh

Go to the documentation of this file.
00001 //      BLEvaluator.hh
00002 
00003 #ifndef BLEVALUATOR_HH
00004 #define BLEVALUATOR_HH
00005 
00006 #include <assert.h>
00007 #include <stdio.h>
00008 #include <math.h>
00009 #include <string.h>
00010 #include <ctype.h>
00011 #include "CLHEP/Evaluator/Evaluator.h"
00012 //@#include <gsl/gsl_sys.h>
00013 
00014 #include "G4Track.hh"
00015 #include "G4RunManager.hh"
00016 #include "G4Event.hh"
00017 
00018 #include "BLCoordinates.hh"
00019 #include "BLGlobalField.hh"
00020 
00021 /** class BLEvaluator implements an expression evaluator.
00022  *
00023  *      Uses HepTool::Evaluator, but fixes up a few minor bugs:
00024  *              automatically calls setStdMath()
00025  *              adds floor(x) and ceil(x)
00026  *              fixes unary +/- by enclosing them in parens
00027  **/
00028 class BLEvaluator : public HepTool::Evaluator {
00029 public:
00030         /// Constructor
00031         BLEvaluator() : HepTool::Evaluator() {
00032                 setSystemOfUnits(1.e+3, 1./1.60217733e-25, 1.e+9,
00033                                 1./1.60217733e-10, 1.0, 1.0, 1.0);
00034                 setStdMath();
00035                 setFunction("floor",floor);
00036                 setFunction("ceil",ceil);
00037         }
00038 
00039         /// evaluate() will evaluate the expression.
00040         /// returns NAN if the expression is not valid (use either isOK() or
00041         /// std::isnan(double) or gsl_isnan(double) to check).
00042         double evaluate(const char *expression) {
00043                 char s[1024];
00044                 // put parens around unary - and unary +, omit whitespace
00045                 int j=0;
00046                 char prev=' ';
00047                 for(int i=0; expression[i]!='\0'; ++i) {
00048                         char c = expression[i];
00049                         if(isspace(c)) continue;
00050                         if(c == '-' || c == '+') {
00051                                 if(isopchar(prev) && isidchar(expression[i+1])) {
00052                                         s[j++] = '(';
00053                                         s[j++] = c;
00054                                         ++i;
00055                                         while(isidchar(expression[i]))
00056                                                 s[j++] = expression[i++];
00057                                         c = ')';
00058                                         --i;
00059                                 }
00060                         }
00061                         prev = s[j++] = c;
00062                 }
00063                 assert((unsigned)j < sizeof(s)-1);
00064                 s[j] = '\0';
00065 
00066                 // if empty or all whitespace, force invalid
00067                 if(j == 0) strcpy(s,"x+-*/y");
00068 
00069                 double v = HepTool::Evaluator::evaluate(s);
00070                 if(status() != OK) v = std::numeric_limits<double>::quiet_NaN();
00071                 return v;
00072         }
00073 
00074         /// isOK() returns true if the previous call to expression succeeded.
00075         bool isOK() { return status() == OK; }
00076 
00077         /// setTrackVariables() devines variables in the evaluator
00078         /// corresponding to the usual track variables. These can then
00079         /// be used in expressions.
00080         void setTrackVariables(const G4Track *track, BLCoordinateType coordType,
00081                                         G4String suffix="", bool fields=false) {
00082                 G4RunManager* runmgr = G4RunManager::GetRunManager();
00083                 const G4Event* event = runmgr->GetCurrentEvent();
00084                 int evId = event->GetEventID();
00085                 G4ThreeVector position = track->GetPosition();
00086                 G4double time = track->GetGlobalTime();
00087                 G4ThreeVector momentum = track->GetMomentum();
00088 
00089                 // get B and E fields
00090                 G4ThreeVector B, E;
00091                 if(fields) {
00092                         G4double point[4], field[6];
00093                         point[0] = position[0];
00094                         point[1] = position[1];
00095                         point[2] = position[2];
00096                         point[3] = time;
00097                         BLGlobalField::getObject()->GetFieldValue(point,field);
00098                         B = G4ThreeVector(field[0],field[1],field[2]);
00099                         E = G4ThreeVector(field[3],field[4],field[5]);
00100                 }
00101 
00102                 // transform to desired coordinates, if available
00103                 BLCoordinates *c = (BLCoordinates *)track->GetUserInformation();
00104                 if(c && c->isValid()) {
00105                         c->getCoords(coordType,position);
00106                         momentum = c->getRotation() * momentum;
00107                         B = c->getRotation() * B;
00108                         E = c->getRotation() * E;
00109                 }
00110                 setVariable((G4String("x")+suffix).c_str(), position[0]/mm);
00111                 setVariable((G4String("y")+suffix).c_str(), position[1]/mm);
00112                 setVariable((G4String("z")+suffix).c_str(), position[2]/mm);
00113                 setVariable((G4String("Px")+suffix).c_str(), momentum[0]/MeV);
00114                 setVariable((G4String("Py")+suffix).c_str(), momentum[1]/MeV);
00115                 setVariable((G4String("Pz")+suffix).c_str(), momentum[2]/MeV);
00116                 setVariable((G4String("t")+suffix).c_str(), time/ns);
00117                 setVariable((G4String("PDGid")+suffix).c_str(), track->GetDefinition()->GetPDGEncoding());
00118                 setVariable((G4String("EvNum")+suffix).c_str(), evId);
00119                 setVariable((G4String("TrkId")+suffix).c_str(), 
00120                                 BLManager::getObject()->
00121                                     getExternalTrackID(track));
00122                 setVariable((G4String("Parent")+suffix).c_str(),
00123                                 BLManager::getObject()->
00124                                     getExternalParentID(track));
00125                 setVariable((G4String("wt")+suffix).c_str(),track->GetWeight());
00126                 if(fields) {
00127                         setVariable((G4String("Bx")+suffix).c_str(),B[0]/tesla);
00128                         setVariable((G4String("By")+suffix).c_str(),B[1]/tesla);
00129                         setVariable((G4String("Bz")+suffix).c_str(),B[2]/tesla);
00130                         setVariable((G4String("Ex")+suffix).c_str(),
00131                                                         E[0]/(megavolt/meter));
00132                         setVariable((G4String("Ey")+suffix).c_str(),
00133                                                         E[1]/(megavolt/meter));
00134                         setVariable((G4String("Ez")+suffix).c_str(),
00135                                                         E[2]/(megavolt/meter));
00136                 }
00137         }
00138 
00139         /// isidchar() returns true if the char is valid for an identifier.
00140         bool isidchar(char c) { return isalnum(c) || c == '_'; }
00141 
00142         /// isopchar() returns true if the character is an operator.
00143         bool isopchar(char c) { return c=='+' || c=='-' || c=='*' || c=='/' ||
00144                                         c=='^' || c=='<' || c=='>' || c=='!' ||
00145                                         c=='|' || c=='&' || c=='='; }
00146 };
00147 
00148 #endif // BLEVALUATOR_HH
g4beamline