00001 #ifndef ConfigurableAnalysis_CachingVariable_H
00002 #define ConfigurableAnalysis_CachingVariable_H
00003
00004 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00005 #include "FWCore/Services/interface/UpdaterService.h"
00006 #include "FWCore/ServiceRegistry/interface/Service.h"
00007 #include "FWCore/Framework/interface/Event.h"
00008 #include "DataFormats/Common/interface/Handle.h"
00009 #include "PhysicsTools/Utilities/interface/StringObjectFunction.h"
00010 #include "PhysicsTools/Utilities/interface/StringCutObjectSelector.h"
00011 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00012
00013 #include "PhysicsTools/UtilAlgos/interface/InputTagDistributor.h"
00014
00015 namespace edm {
00016 class EventSetup;
00017 }
00018 #include <vector>
00019 #include "TString.h"
00020
00021 class Description {
00022 public:
00023 Description(){}
00024 Description(std::vector<std::string> & d) : d_(d){}
00025 std::string text() const {
00026 std::string text;
00027 for (uint i=0;i!=d_.size();++i)
00028 text+=d_[i]+"\n";
00029 return text;
00030 }
00031 const std::vector<std::string> lines(){return d_;}
00032 void addLine(const std::string & l){d_.push_back(l);}
00033 private :
00034 std::vector<std::string> d_;
00035 };
00036
00037 class VariableComputer;
00038
00039 class CachingVariable {
00040 public:
00041
00042 typedef double valueType;
00043 typedef std::pair<bool, valueType> evalType;
00044 typedef std::map<std::string, const CachingVariable*> vMap;
00045 struct CachingVariableFactoryArg {
00046 CachingVariableFactoryArg( const CachingVariableFactoryArg & copy) : n(copy.n),m(copy.m),iConfig(copy.iConfig){}
00047 CachingVariableFactoryArg(std::string & N,CachingVariable::vMap & M,edm::ParameterSet & P) : n(N),m(M),iConfig(P){}
00048 std::string & n;
00049 CachingVariable::vMap & m;
00050 edm::ParameterSet & iConfig;
00051 };
00052
00053 CachingVariable(std::string m, std::string n, const edm::ParameterSet & iConfig) :
00054 cache_(std::make_pair(false,0)),method_(m),
00055 name_(n),conf_(iConfig) {}
00056
00057 virtual ~CachingVariable() {}
00058
00059
00060 bool compute(const edm::Event & iEvent) const { return baseEval(iEvent).first; }
00061
00062
00063 valueType operator()(const edm::Event & iEvent) const { return baseEval(iEvent).second; }
00064
00065 const std::string & name() const {return name_;}
00066 const std::string & method() const { return method_;}
00067 const Description & description()const { return d_;}
00068 void addDescriptionLine(const std::string & s){ d_.addLine(s);}
00069 const std::string & holderName() const { return holderName_;}
00070 void setHolder(std::string hn) const { holderName_=hn;}
00071
00072 void print() const {
00073 edm::LogVerbatim("CachingVariable")<<name()
00074 <<"\n"<<description().text();
00075 }
00076 protected:
00077
00078 mutable evalType cache_;
00079
00080 std::string method_;
00081 std::string name_;
00082 mutable std::string holderName_;
00083 void setCache(valueType & v) const {
00084 edm::Service<UpdaterService>()->checkOnce(name_+":"+holderName_);
00085 cache_.first=true; cache_.second = v;}
00086 void setNotCompute() const {
00087 edm::Service<UpdaterService>()->checkOnce(name_+":"+holderName_);
00088 cache_.first=false; cache_.second = 0;}
00089 evalType & baseEval(const edm::Event & iEvent) const {
00090 if (edm::Service<UpdaterService>()->checkOnce(name_+":"+holderName_)){
00091 LogDebug("CachingVariable")<<name_+":"+holderName_<<" is checking once";
00092 cache_=eval(iEvent);
00093 }
00094 return cache_;
00095 }
00096
00097 virtual evalType eval(const edm::Event & iEvent) const {return std::make_pair(false,0);};
00098
00099 Description d_;
00100 edm::ParameterSet conf_;
00101 friend class VariableComputer;
00102 };
00103
00104
00105 class ComputedVariable;
00106 class VariableComputer{
00107 public:
00108 VariableComputer(CachingVariable::CachingVariableFactoryArg arg);
00109 virtual ~VariableComputer(){}
00110
00111 virtual void compute(const edm::Event & iEvent) const = 0;
00112 const std::string & name() const { return name_;}
00113 void declare(std::string var);
00114 void assign(std::string var, double & value) const;
00115 void doesNotCompute() const;
00116 void doesNotCompute(std::string var) const;
00117
00118 protected:
00119 CachingVariable::CachingVariableFactoryArg & arg_;
00120 std::string name_;
00121 std::string method_;
00122 mutable std::map<std::string ,const ComputedVariable *> iCompute_;
00123 std::string separator_;
00124 };
00125
00126
00127 #include "FWCore/PluginManager/interface/PluginFactory.h"
00128 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00129
00130 typedef edmplugin::PluginFactory< CachingVariable* (CachingVariable::CachingVariableFactoryArg) > CachingVariableFactory;
00131 typedef edmplugin::PluginFactory< VariableComputer* (CachingVariable::CachingVariableFactoryArg) > VariableComputerFactory;
00132
00133 class ComputedVariable : public CachingVariable {
00134 public:
00135 ComputedVariable(CachingVariableFactoryArg arg );
00136 ComputedVariable(const std::string & M, std::string & N, edm::ParameterSet & P, const VariableComputer * c) :
00137 CachingVariable(M,N,P), myComputer(c){}
00138 virtual ~ComputedVariable(){};
00139
00140 virtual evalType eval(const edm::Event & iEvent) const {
00141 if (edm::Service<UpdaterService>()->checkOnce(myComputer->name()+":"+holderName_))
00142 myComputer->compute(iEvent);
00143 return cache_;
00144 }
00145 private:
00146 const VariableComputer * myComputer;
00147 };
00148
00149 class VariableComputerTest : public VariableComputer {
00150 public:
00151 VariableComputerTest(CachingVariable::CachingVariableFactoryArg arg) ;
00152 ~VariableComputerTest(){};
00153
00154 void compute(const edm::Event & iEvent) const;
00155 };
00156
00157 class Splitter : public CachingVariable {
00158 public:
00159 Splitter(std::string method, std::string n, const edm::ParameterSet & iConfig) :
00160 CachingVariable(method,n,iConfig) {}
00161
00162
00163 virtual CachingVariable::evalType eval(const edm::Event & iEvent) const =0;
00164
00165 uint maxIndex() const { return maxSlots()-1;}
00166
00167
00168 virtual uint maxSlots() const { return labels_.size();}
00169
00170 const std::string shortLabel(uint i) const{
00171 if (i>=short_labels_.size()){
00172 edm::LogError("Splitter")<<"trying to access slots short_label at index: "<<i<<"while of size: "<<short_labels_.size()<<"\n"<<conf_.dump();
00173 return short_labels_.back(); }
00174 else return short_labels_[i];}
00175
00176 const std::string & label(uint i) const{
00177 if (i>=labels_.size()){
00178 edm::LogError("Splitter")<<"trying to access slots label at index: "<<i<<"while of size: "<<labels_.size()<<"\n"<<conf_.dump();
00179 return labels_.back(); }
00180 else return labels_[i];}
00181
00182 protected:
00183 std::vector<std::string> labels_;
00184 std::vector<std::string> short_labels_;
00185 };
00186
00187
00188 class VarSplitter : public Splitter{
00189 public:
00190 VarSplitter(CachingVariableFactoryArg arg ) :
00191 Splitter("VarSplitter",arg.n,arg.iConfig) {
00192 var_=arg.iConfig.getParameter<std::string>("var");
00193 useUnderFlow_=arg.iConfig.getParameter<bool>("useUnderFlow");
00194 useOverFlow_=arg.iConfig.getParameter<bool>("useOverFlow");
00195 slots_=arg.iConfig.getParameter<std::vector<double> >("slots");
00196 if (useUnderFlow_){
00197 labels_.push_back("underflow");
00198 short_labels_.push_back("_"+arg.n+"_underflow");}
00199 std::vector<std::string> confLabels;
00200 if (arg.iConfig.exists("labels")){
00201 confLabels=arg.iConfig.getParameter<std::vector<std::string> >("labels");
00202 }
00203 else{
00204 std::string labelFormat = arg.iConfig.getParameter<std::string>("labelsFormat");
00205 for (uint is=0;is!=slots_.size()-1;++is){
00206 std::string l(Form(labelFormat.c_str(),slots_[is],slots_[is+1]));
00207 confLabels.push_back(l);
00208 }
00209 }
00210 for (uint i=0;i!=confLabels.size();++i){
00211 labels_.push_back(confLabels[i]);
00212 std::stringstream ss;
00213 ss<<"_"<<arg.n<<"_"<<i;
00214 short_labels_.push_back(ss.str());
00215 }
00216 if (useOverFlow_)
00217 { labels_.push_back("overFlow");
00218 short_labels_.push_back("_"+arg.n+"_overFlow");}
00219
00220
00221 if (labels_.size()!=maxSlots())
00222 edm::LogError("Splitter")<<"splitter with name: "<<name()<<" has inconsistent configuration\n"<<conf_.dump();
00223
00224 arg.m[arg.n]=this;
00225 }
00226
00227 CachingVariable::evalType eval(const edm::Event & iEvent) const;
00228
00229
00230 uint maxSlots() const{
00231 uint s=slots_.size()-1;
00232 if (useUnderFlow_) s++;
00233 if (useOverFlow_) s++;
00234 return s;}
00235
00236 protected:
00237 std::string var_;
00238 bool useUnderFlow_;
00239 bool useOverFlow_;
00240 std::vector<double> slots_;
00241 };
00242
00243 template <typename Object> class sortByStringFunction {
00244 public:
00245 sortByStringFunction(StringObjectFunction<Object> * f) : f_(f){}
00246 ~sortByStringFunction(){}
00247
00248 bool operator() (const Object * o1, const Object * o2) {
00249 return (*f_)(*o1) > (*f_)(*o2);
00250 }
00251 private:
00252 StringObjectFunction<Object> * f_;
00253 };
00254
00255 template <typename Object, const char * label>
00256 class ExpressionVariable : public CachingVariable {
00257 public:
00258 ExpressionVariable(CachingVariableFactoryArg arg) :
00259 CachingVariable(std::string(label)+"ExpressionVariable",arg.n,arg.iConfig) , f_(0), forder_(0) {
00260 src_=edm::Service<InputTagDistributorService>()->retrieve("src",arg.iConfig);
00261
00262 if (arg.iConfig.exists("expr") && arg.iConfig.exists("index")){
00263 std::string expr=arg.iConfig.getParameter<std::string>("expr");
00264 index_=arg.iConfig.getParameter<uint>("index");
00265 f_ = new StringObjectFunction<Object>(expr);
00266 addDescriptionLine("calculating: "+expr);
00267 std::stringstream ss;
00268 ss<<"on object at index: "<<index_<<" of: "<<src_;
00269
00270 if (arg.iConfig.exists("order")){
00271 std::string order=arg.iConfig.getParameter<std::string>("order");
00272 forder_ = new StringObjectFunction<Object>(order);
00273 ss<<" after sorting according to: "<<order;
00274 }else forder_ =0;
00275
00276 if (arg.iConfig.exists("selection")){
00277 std::string selection=arg.iConfig.getParameter<std::string>("selection");
00278 selector_ = new StringCutObjectSelector<Object>(selection);
00279 ss<<" and selecting only: "<<selection;
00280 }else selector_=0;
00281
00282
00283
00284 addDescriptionLine(ss.str()); ss.str("");
00285 arg.m[arg.n] = this;
00286 }
00287 else{
00288
00289 std::map<std::string, edm::Entry> indexEntry;
00290 if (arg.n.find("_N")!=std::string::npos){
00291
00292 std::vector<uint> indexes = arg.iConfig.getParameter<std::vector<uint> >("indexes");
00293 for (uint iI=0;iI!=indexes.size();++iI){
00294 edm::ParameterSet toUse = arg.iConfig;
00295 edm::Entry e("uint",indexes[iI],true);
00296 std::stringstream ss;
00297
00298 ss<<indexes[iI]+1;
00299 indexEntry.insert(std::make_pair(ss.str(),e));
00300 }
00301 }
00302
00303 std::map< std::string, edm::Entry> varEntry;
00304 if (arg.n.find("_V")!=std::string::npos){
00305
00306 std::vector<std::string> vars = arg.iConfig.getParameter<std::vector<std::string> >("vars");
00307 for (uint v=0;v!=vars.size();++v){
00308 uint sep=vars[v].find(":");
00309 std::string name=vars[v].substr(0,sep);
00310 std::string expr=vars[v].substr(sep+1);
00311
00312 edm::Entry e("string",expr,true);
00313 varEntry.insert(std::make_pair(name,e));
00314 }
00315 }
00316
00317 std::string radical = arg.n;
00318
00319 if (!varEntry.empty())
00320 radical = radical.substr(0,radical.size()-2);
00321
00322 if (!indexEntry.empty())
00323 radical = radical.substr(0,radical.size()-2);
00324
00325 if(varEntry.empty()){
00326
00327 for(std::map< std::string, edm::Entry>::iterator iIt=indexEntry.begin();iIt!=indexEntry.end();++iIt){
00328 edm::ParameterSet toUse = arg.iConfig;
00329 toUse.insert(true,"index",iIt->second);
00330 std::string newVname = radical+iIt->first;
00331
00332
00333 new ExpressionVariable(CachingVariable::CachingVariableFactoryArg(newVname,arg.m,toUse));
00334 }
00335 }else{
00336 for (std::map< std::string, edm::Entry>::iterator vIt=varEntry.begin();vIt!=varEntry.end();++vIt){
00337 if (indexEntry.empty()){
00338 edm::ParameterSet toUse = arg.iConfig;
00339 toUse.insert(true,"expr",vIt->second);
00340 std::string newVname = radical+vIt->first;
00341
00342
00343 new ExpressionVariable(CachingVariable::CachingVariableFactoryArg(newVname,arg.m,toUse));
00344 }else{
00345 for(std::map< std::string, edm::Entry>::iterator iIt=indexEntry.begin();iIt!=indexEntry.end();++iIt){
00346 edm::ParameterSet toUse = arg.iConfig;
00347 toUse.insert(true,"expr",vIt->second);
00348 toUse.insert(true,"index",iIt->second);
00349 std::string newVname = radical+iIt->first+vIt->first;
00350
00351
00352 new ExpressionVariable(CachingVariable::CachingVariableFactoryArg(newVname,arg.m,toUse));
00353 }}
00354 }
00355 }
00356
00357
00358
00359
00360 }
00361 }
00362 ~ExpressionVariable(){
00363 if (f_) delete f_;
00364 if (forder_) delete forder_;
00365 if (selector_) delete selector_;
00366 }
00367
00368 CachingVariable::evalType eval(const edm::Event & iEvent) const {
00369 if (!f_) {
00370 edm::LogError(method())<<" no parser attached.";
00371 return std::make_pair(false,0);
00372 }
00373 edm::Handle<edm::View<Object> > oH;
00374 iEvent.getByLabel(src_,oH);
00375 if (index_>=oH->size()){
00376 LogDebug(method())<<"fail to get object at index: "<<index_<<" in collection: "<<src_;
00377 return std::make_pair(false,0);
00378 }
00379
00380
00381 if (selector_ || forder_){
00382 std::vector<const Object*> copyToSort(0);
00383 copyToSort.reserve(oH->size());
00384 for (uint i=0;i!=oH->size();++i){
00385 if (selector_ && !((*selector_)((*oH)[i]))) continue;
00386 copyToSort.push_back(&(*oH)[i]);
00387 }
00388 if (index_ >= copyToSort.size()) return std::make_pair(false,0);
00389 if (forder_) std::sort(copyToSort.begin(), copyToSort.end(), sortByStringFunction<Object>(forder_));
00390
00391 const Object * o = copyToSort[index_];
00392 return std::make_pair(true,(*f_)(*o));
00393 }
00394 else{
00395 const Object & o = (*oH)[index_];
00396 return std::make_pair(true,(*f_)(o));
00397 }
00398 }
00399
00400 private:
00401 edm::InputTag src_;
00402 uint index_;
00403 StringObjectFunction<Object> * f_;
00404 StringObjectFunction<Object> * forder_;
00405 StringCutObjectSelector<Object> * selector_;
00406 };
00407
00408
00409 template< typename LHS,const char * lLHS, typename RHS,const char * lRHS, typename Calculator>
00410 class TwoObjectVariable : public CachingVariable {
00411 public:
00412 TwoObjectVariable(CachingVariableFactoryArg arg) :
00413 CachingVariable(Calculator::calculationType()+std::string(lLHS)+std::string(lRHS),arg.n,arg.iConfig),
00414 srcLhs_(edm::Service<InputTagDistributorService>()->retrieve("srcLhs",arg.iConfig)),
00415 indexLhs_(arg.iConfig.getParameter<uint>("indexLhs")),
00416 srcRhs_(edm::Service<InputTagDistributorService>()->retrieve("srcRhs",arg.iConfig)),
00417 indexRhs_(arg.iConfig.getParameter<uint>("indexRhs"))
00418 {
00419 std::stringstream ss;
00420 addDescriptionLine(Calculator::description());
00421 ss<<"with Obj1 at index: "<<indexLhs_<<" of: "<<srcLhs_;
00422 addDescriptionLine(ss.str()); ss.str("");
00423 ss<<"with Obj2 at index: "<<indexRhs_<<" of: "<<srcRhs_;
00424 addDescriptionLine(ss.str()); ss.str("");
00425 arg.m[arg.n]=this;
00426 }
00427
00428 class getObject{
00429 public:
00430 getObject() : test(false),lhs(0),rhs(0){}
00431 bool test;
00432 const LHS * lhs;
00433 const RHS * rhs;
00434 };
00435 getObject objects(const edm::Event & iEvent) const {
00436 getObject failed;
00437 edm::Handle<std::vector<LHS> > lhsH;
00438 iEvent.getByLabel(srcLhs_, lhsH);
00439 if (lhsH.failedToGet()){
00440 LogDebug("TwoObjectVariable")<<name()<<" could not get a collection with label: "<<srcLhs_;
00441 return failed;}
00442 if (indexLhs_>=lhsH->size()){
00443 LogDebug("TwoObjectVariable")<<name()<<" tries to access index: "<<indexLhs_<<" of: "<<srcLhs_<<" with: "<<lhsH->size()<<" entries.";
00444 return failed;}
00445 const LHS & lhs = (*lhsH)[indexLhs_];
00446
00447 edm::Handle<std::vector<RHS> > rhsH;
00448 iEvent.getByLabel(srcRhs_, rhsH);
00449 if (rhsH.failedToGet()){
00450 LogDebug("TwoObjectVariable")<<name()<<" could not get a collection with label: "<<srcLhs_;
00451 return failed;}
00452
00453 if (indexRhs_>=rhsH->size()){
00454 LogDebug("TwoObjectVariable")<<name()<<" tries to access index: "<<indexRhs_<<" of: "<<srcRhs_<<" with: "<<rhsH->size()<<" entries.";
00455 return failed;}
00456 const RHS & rhs = (*rhsH)[indexRhs_];
00457
00458 failed.test=true;
00459 failed.lhs=&lhs;
00460 failed.rhs=&rhs;
00461 return failed;
00462 }
00463
00464
00465 virtual CachingVariable::valueType calculate(getObject & o) const {
00466 Calculator calc;
00467 return calc(*o.lhs,*o.rhs);
00468 }
00469 CachingVariable::evalType eval(const edm::Event & iEvent) const {
00470 getObject o=objects(iEvent);
00471 if (!o.test) return std::make_pair(false,0);
00472 return std::make_pair(true,calculate(o));
00473 }
00474 private:
00475 edm::InputTag srcLhs_;
00476 uint indexLhs_;
00477 edm::InputTag srcRhs_;
00478 uint indexRhs_;
00479 };
00480
00481
00482 class VariablePower : public CachingVariable {
00483 public:
00484 VariablePower(CachingVariableFactoryArg arg) :
00485 CachingVariable("Power",arg.n,arg.iConfig){
00486 power_=arg.iConfig.getParameter<double>("power");
00487 var_=arg.iConfig.getParameter<std::string>("var");
00488 std::stringstream ss("Calculare X^Y, with X=");
00489 ss<<var_<<" and Y="<<power_;
00490 addDescriptionLine(ss.str());
00491 arg.m[arg.n]=this;
00492 }
00493 ~VariablePower(){}
00494
00495
00496 CachingVariable::evalType eval(const edm::Event & iEvent) const;
00497
00498 private:
00499 double power_;
00500 std::string var_;
00501 };
00502
00503
00504 template <typename TYPE>
00505 class SimpleValueVariable : public CachingVariable {
00506 public:
00507 SimpleValueVariable(CachingVariableFactoryArg arg) :
00508 CachingVariable("SimpleValueVariable",arg.n,arg.iConfig),
00509 src_(edm::Service<InputTagDistributorService>()->retrieve("src",arg.iConfig)) { arg.m[arg.n]=this;}
00510 CachingVariable::evalType eval(const edm::Event & iEvent) const{
00511 edm::Handle<TYPE> value;
00512 try{ iEvent.getByLabel(src_,value); }
00513 catch(...){ return std::make_pair(false,0); }
00514 if (value.failedToGet() || !value.isValid()) return std::make_pair(false,0);
00515 else return std::make_pair(true, *value);
00516 }
00517 private:
00518 edm::InputTag src_;
00519 };
00520
00521 template <typename TYPE>
00522 class SimpleValueVectorVariable : public CachingVariable {
00523 public:
00524 SimpleValueVectorVariable(CachingVariableFactoryArg arg) :
00525 CachingVariable("SimpleValueVectorVariable",arg.n,arg.iConfig),
00526 src_(edm::Service<InputTagDistributorService>()->retrieve("src",arg.iConfig)),
00527 index_(arg.iConfig.getParameter<uint>("index")) { arg.m[arg.n]=this;}
00528 CachingVariable::evalType eval(const edm::Event & iEvent) const{
00529 edm::Handle<std::vector<TYPE> > values;
00530 try { iEvent.getByLabel(src_,values);}
00531 catch(...){ return std::make_pair(false,0); }
00532 if (values.failedToGet() || !values.isValid()) return std::make_pair(false,0);
00533 else if (index_>=values->size()) return std::make_pair(false,0);
00534 else return std::make_pair(true, (*values)[index_]);
00535 }
00536
00537 private:
00538 edm::InputTag src_;
00539 uint index_;
00540 };
00541
00542
00543
00544
00545
00546
00547
00548 #endif