CMS 3D CMS Logo

RandomNumberGeneratorService.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     RandomEngine
00004 // Class  :     RandomNumberGeneratorService
00005 // 
00006 // Implementation:
00007 //     <Notes on implementation>
00008 //
00009 // Original Author:  Chris Jones, W. David Dagenhart
00010 //   Created:  Tue Mar  7 09:43:46 EST 2006 (originally in FWCore/Services)
00011 // $Id: RandomNumberGeneratorService.cc,v 1.20 2008/05/14 21:49:41 marafino Exp $
00012 //
00013 
00014 #include "IOMC/RandomEngine/src/RandomNumberGeneratorService.h"
00015 
00016 #include <iostream>
00017 #include <fstream>
00018 #include <limits>
00019 #include <unistd.h>
00020 
00021 #include "FWCore/Framework/interface/Event.h"
00022 #include "DataFormats/Provenance/interface/ModuleDescription.h"
00023 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00024 #include "SimDataFormats/RandomEngine/interface/RandomEngineState.h"
00025 #include "CLHEP/Random/JamesRandom.h"
00026 #include "CLHEP/Random/RanecuEngine.h"
00027 #include "CLHEP/Random/engineIDulong.h"
00028 #include "FWCore/Utilities/interface/EDMException.h"
00029 
00030 #include "FWCore/ServiceRegistry/interface/Service.h"
00031 #include "FWCore/MessageLogger/interface/JobReport.h"
00032 #include "IOMC/RandomEngine/src/TRandomAdaptor.h"
00033 
00034 using namespace edm::service;
00035 
00036 typedef std::vector<std::string> VString;
00037 typedef std::vector<uint32_t>    Vuint32;
00038 typedef edm::ParameterSet        PSet;
00039 
00040 static const std::string sourceLabel("@source");
00041 
00042 
00043 RandomNumberGeneratorService::RandomNumberGeneratorService(const ParameterSet& iPSet,
00044                                                            ActivityRegistry& iRegistry):
00045   // The default is an empty string which signals to the process that it should not
00046   // try to restore the random engines to the state stored in the input event.
00047   // Otherwise, the configuration file should set this to the module label used
00048   // in the previous process to store the random engine state
00049   restoreStateLabel_(iPSet.getUntrackedParameter<std::string>("restoreStateLabel", std::string())),
00050   saveFileName_(std::string()),
00051   saveFileNameRecorded_(false),
00052   restoreFileName_(std::string()),
00053   oldStyle_(false)
00054 {
00055 
00056   std::string labels;
00057   std::vector<uint32_t> seeds;
00058   PSet  empty_PSet;
00059   VString  empty_VString;
00060   Vuint32  empty_Vuint32;
00061 
00062   // Record the names of the files to use to store engine states at the end of
00063   // each event and to restore engine states at the beginning of a job.
00064   // A blank name means don't bother.
00065   saveFileName_    = iPSet.getUntrackedParameter<std::string>("saveFileName",   std::string());
00066   restoreFileName_ = iPSet.getUntrackedParameter<std::string>("restoreFileName",std::string());
00067 
00068 // The saveFileName and must correspond to a file name without any path specification.
00069 // Throw if that is not true.
00070   if(!saveFileName_.empty() && (saveFileName_.find("/") != std::string::npos)) {
00071     std::ostringstream sstr;
00072     sstr << "Configuration: The saveFileName parameter " << saveFileName_ << "\n" 
00073          << "must be a simple file name with no path specification.\n" ;
00074     edm::Exception except(edm::errors::Configuration, sstr.str());
00075     throw except;
00076   }     
00077 
00078 // Check if the configuration file is still expressed in the old style.
00079 // We do this by looking for a PSet named moduleSeeds.  That parameter is 
00080 // unique to an old style cfg file.
00081 
00082   VString pSets = iPSet.getParameterNamesForType<edm::ParameterSet>();
00083   for(VString::const_iterator it = pSets.begin(), itEnd = pSets.end(); it != itEnd; ++it) {
00084     if(*it == std::string("moduleSeeds")) oldStyle_ = true;
00085   }
00086 
00087 // If only the source needs a random engine, there won't be a PSet named moduleSeeds and
00088 // this test will fail.  To cover that case, look for a sourceSeed parameter as well.  
00089 
00090   if(iPSet.getUntrackedParameter<uint32_t>("sourceSeed",0) != 0) oldStyle_ = true;
00091       
00092   if(oldStyle_) {
00093     oldStyleConfig(iPSet);
00094   } else {
00095 
00096 // We have a new style configuration file. deal with it here.
00097 // Loop over parameters of type ParameterSet and look for things
00098 // that should not appear in new-style cfg files. If any are found,
00099 // it means the user has supplied a mixture of new- and old-style
00100 // configuration parameters that can't possibly work correctly.
00101 
00102     bool source;
00103     std::string engineName;
00104     uint32_t initialSeed;
00105     std::vector<uint32_t> initialSeedSet;
00106 
00107     std::string sourceEngine = iPSet.getUntrackedParameter<std::string>("sourceEngine",std::string(""));
00108     if(!sourceEngine.empty()) {
00109       throw edm::Exception(edm::errors::Configuration)
00110         << "sourceEngine is obsolete for new-style configuration files." 
00111         << "\nPlease switch to the newer cfg format for the RandomNumberGeneratorService." ;
00112     }
00113 
00114     uint32_t sourceSeed = iPSet.getUntrackedParameter<uint32_t>("sourceSeed",0);
00115     if(sourceSeed != 0) {
00116       throw edm::Exception(edm::errors::Configuration)
00117         << "sourceSeed is obsolete for new-style configuration files." 
00118         << "\nPlease switch to the newer cfg format for the RandomNumberGeneratorService." ;
00119     }
00120 
00121     std::vector<uint32_t> sourceSeedVector = iPSet.getUntrackedParameter<std::vector<uint32_t> >("sourceSeedVector",empty_Vuint32);
00122     if(!sourceSeedVector.empty()) {
00123       throw edm::Exception(edm::errors::Configuration)
00124         << "sourceSeedVector is obsolete for new-style configuration files." 
00125         << "\nPlease switch to the newer cfg format for the RandomNumberGeneratorService." ;
00126     }
00127 
00128     VString pSets = iPSet.getParameterNamesForType<edm::ParameterSet>();
00129     for(VString::const_iterator it = pSets.begin(), itEnd = pSets.end(); it != itEnd; ++it) {
00130       source = false;
00131       if(*it == std::string("moduleEngines")) {
00132         throw edm::Exception(edm::errors::Configuration)
00133           << "moduleEngines is obsolete for new-style configuration files." 
00134           << "\nPlease switch to the newer cfg format for the RandomNumberGeneratorService." ;
00135       }
00136   
00137       if(*it == std::string("moduleSeedVectors")) {
00138         throw edm::Exception(edm::errors::Configuration)
00139           << "moduleSeedVectors is obsolete for new-style configuration files." 
00140           << "\nPlease switch to the newer cfg format for the RandomNumberGeneratorService." ;
00141       }
00142   
00143   // Deal with a source engine here
00144       if(*it == std::string("theSource")) source = true;
00145   
00146       PSet secondary = iPSet.getParameter<edm::ParameterSet>(*it);
00147       engineName = secondary.getUntrackedParameter<std::string>("engineName",std::string("HepJamesRandom"));
00148       if(!isEngineNameValid(engineName)) {
00149         throw edm::Exception(edm::errors::Configuration)
00150           << "The specified Random Engine name, " << engineName
00151           << " does not correspond to a supported engine." ;
00152       }
00153   
00154   // For the RanecuEngine case, require a seed set containing exactly two seeds.
00155   
00156       if(engineName == std::string("RanecuEngine")) {
00157         if(secondary.exists("initialSeedSet")) {
00158           initialSeedSet = secondary.getUntrackedParameter<std::vector<uint32_t> >("initialSeedSet",empty_Vuint32);
00159           uint32_t nSeeds = initialSeedSet.size();
00160           uint32_t mSeeds = expectedSeedCount(engineName);
00161           if(nSeeds != mSeeds) {
00162             throw edm::Exception(edm::errors::Configuration)
00163               << "RanecuEngine requires 2 seeds and "
00164               << nSeeds << " seeds were\n"
00165               << "specified in the configuration file for "
00166               << "the module with label " << *it << "." ;
00167           }
00168           if(source) {
00169             seedMap_[sourceLabel] = initialSeedSet;
00170           } else {
00171             seedMap_[*it] = initialSeedSet;
00172           }
00173           CLHEP::HepRandomEngine* engine = new RanecuEngine();
00174           if(source) {
00175             engineMap_[sourceLabel] = engine;
00176           } else {
00177             engineMap_[*it] = engine;
00178           }
00179           if (initialSeedSet[0] > std::numeric_limits<uint32_t>::max() ||
00180               initialSeedSet[1] > std::numeric_limits<uint32_t>::max()) {  // They need to fit in a 32 bit integer
00181             throw edm::Exception(edm::errors::Configuration)
00182               << "The RanecuEngine seeds should be in the range 0 to " << std::numeric_limits<uint32_t>::max() << " .\n"
00183               << "The seeds passed to the RandomNumberGenerationService from the\n"
00184                  "configuration file were " << initialSeedSet[0] << " and " << initialSeedSet[1]
00185               << " (or one was negative\nor larger "
00186                  "than a 32 bit unsigned integer).\nThis was for "
00187               << "the module with label " << *it << ".";
00188           }
00189           long int seedL[2];
00190           seedL[0] = static_cast<long int>(initialSeedSet[0]);
00191           seedL[1] = static_cast<long int>(initialSeedSet[1]);
00192           engine->setSeeds(seedL,0);
00193         } else {
00194           throw edm::Exception(edm::errors::Configuration)
00195             << "No initialSeedSet was supplied for engine " << engineName
00196             << ". Aborting." ;
00197         }
00198   
00199   // For the other engines, require one seed each as follows:
00200   //   If a single seed is offered, accept it unconditionally.
00201   //   If a seed set is offered use the first element of the set unconditionally.
00202   //   If both are offered, preferentially use the first element of the set.
00203   
00204       } else {
00205         initialSeed = 0;
00206         if(secondary.exists("initialSeed"))  {
00207           initialSeed = secondary.getUntrackedParameter<uint32_t>("initialSeed",0);
00208         }
00209         if(secondary.exists("initialSeedSet"))  {
00210           initialSeedSet = secondary.getUntrackedParameter<std::vector<uint32_t> >("initialSeedSet",empty_Vuint32);
00211           initialSeed = initialSeedSet[0];
00212         }
00213         if(initialSeed == 0)  { 
00214           throw edm::Exception(edm::errors::Configuration)
00215             << "No initialSeed was supplied for engine " << engineName
00216             << ". Aborting." ;
00217         }
00218         seeds.clear();
00219         seeds.push_back(initialSeed);
00220         if(source) {
00221           seedMap_[sourceLabel] = seeds;
00222         } else {
00223           seedMap_[*it] = seeds;
00224         }
00225         if(engineName == "HepJamesRandom") {
00226           if (initialSeed > 900000000) {
00227             throw edm::Exception(edm::errors::Configuration)
00228               << "The HepJamesRandom engine seed should be in the range 0 to 900000000.\n"
00229               << "The seed passed to the RandomNumberGenerationService from the\n"
00230                  "configuration file was " << initialSeed
00231               << " or negative or larger\n"
00232                  "than a 32 bit unsigned integer.  This was for "
00233               << "the module with label " << *it << ".";
00234           }
00235           long int seedL = static_cast<long int>(initialSeed);
00236           CLHEP::HepRandomEngine* engine = new HepJamesRandom(seedL);
00237           if(source) {
00238             engineMap_[sourceLabel] = engine;
00239           } else {
00240             engineMap_[*it] = engine;
00241           }
00242         } else if(engineName == "TRandom3") {
00243           CLHEP::HepRandomEngine* engine = new TRandomAdaptor(initialSeed);
00244           if(source) {
00245             engineMap_[sourceLabel] = engine;
00246           } else {
00247             engineMap_[*it] = engine;
00248           }
00249         }
00250       }
00251     }
00252   }
00253 
00254   iRegistry.watchPostBeginJob(this,&RandomNumberGeneratorService::postBeginJob);
00255   iRegistry.watchPostEndJob(this,&RandomNumberGeneratorService::postEndJob);
00256 
00257   iRegistry.watchPreModuleConstruction(this,&RandomNumberGeneratorService::preModuleConstruction);
00258   iRegistry.watchPostModuleConstruction(this,&RandomNumberGeneratorService::postModuleConstruction);
00259 
00260   iRegistry.watchPreSourceConstruction(this,&RandomNumberGeneratorService::preSourceConstruction);
00261   iRegistry.watchPostSourceConstruction(this,&RandomNumberGeneratorService::postSourceConstruction);
00262 
00263   iRegistry.watchPreProcessEvent(this,&RandomNumberGeneratorService::preEventProcessing);
00264   iRegistry.watchPostProcessEvent(this,&RandomNumberGeneratorService::postEventProcessing);
00265    
00266   iRegistry.watchPreModule(this,&RandomNumberGeneratorService::preModule);
00267   iRegistry.watchPostModule(this,&RandomNumberGeneratorService::postModule);
00268 
00269   iRegistry.watchPreModuleBeginJob(this,&RandomNumberGeneratorService::preModuleBeginJob);
00270   iRegistry.watchPostModuleBeginJob(this,&RandomNumberGeneratorService::postModuleBeginJob);
00271 
00272   iRegistry.watchPreModuleEndJob(this,&RandomNumberGeneratorService::preModuleEndJob);
00273   iRegistry.watchPostModuleEndJob(this,&RandomNumberGeneratorService::postModuleEndJob);
00274 
00275   // the default for the stack is to point to the 'end' of our map which is used to define not set
00276   engineStack_.push_back(engineMap_.end());
00277   currentEngine_ = engineMap_.end();
00278 
00279   labelStack_.push_back(std::string());
00280   currentLabel_ = std::string();
00281 }
00282 
00283 RandomNumberGeneratorService::~RandomNumberGeneratorService()
00284 {
00285   // Delete the engines
00286   for (EngineMap::iterator iter = engineMap_.begin();
00287        iter != engineMap_.end();
00288        ++iter) {
00289     delete iter->second;
00290   }
00291 }
00292 
00293 CLHEP::HepRandomEngine& 
00294 RandomNumberGeneratorService::getEngine() const {
00295 
00296   if (currentEngine_ == engineMap_.end()) {
00297     if (currentLabel_ != std::string() ) {
00298       if ( currentLabel_ != sourceLabel) {
00299        if(oldStyle_) {
00300           throw edm::Exception(edm::errors::Configuration)
00301             << "The module with label \""
00302             << currentLabel_
00303             << "\" requested a random number engine from the \n"
00304                "RandomNumberGeneratorService, but that module was not configured\n"
00305                "for random numbers.  An engine is created only if a seed(s) is provided\n"
00306                "in the configuration file.  Please add the following line to the\n"
00307                "configuration file in the moduleSeeds PSet of the RandomNumberGeneratorService:\n"
00308                "        untracked uint32 " << currentLabel_ << " = <your random number seed>\n\n"
00309                "Adding the line above will not work if you have modified the default and\n"
00310                "selected a different type of random engine that requires two or more seeds.\n"
00311                "In that case, you will need to add the following line to the moduleSeedVectors\n"
00312                "PSet instead:\n"
00313                "        untracked vuint32 " << currentLabel_ 
00314                << " = { <your first random number seed>, <your second random number seed> ... }\n\n";
00315         } else {
00316           throw edm::Exception(edm::errors::Configuration)
00317             << "The module with label \""
00318             << currentLabel_
00319             << "\" requested a random number engine from the \n"
00320                "RandomNumberGeneratorService, but that module was not configured\n"
00321                "for random numbers.  An engine is created only if a seed(s) is provided\n"
00322                "in the configuration file.  Please add the following PSet to the\n"
00323                "configuration file for the RandomNumberGeneratorService:\n"
00324                "        PSet " << currentLabel_ << " = {\n"
00325                "                   untracked string engineName = <name of chosen engine>\n"
00326                "                   untracked uint32 initialSeed = <value of chosen seed>\n" 
00327                "                  }\n"
00328                "Adding the line above will not work if you have modified the default and\n"
00329                "selected a different type of random engine that requires two or more seeds.\n"
00330                "In that case, you will need to replace the line with initialSeed with\n"
00331                "                   untracked vuint32 initialSeedSet = { <your first random number seed>,"
00332                "<your second random number seed> ... }\n\n";
00333         }
00334       } else {
00335         if(oldStyle_) {
00336           throw edm::Exception(edm::errors::Configuration)
00337             << "The source requested a random number engine from the \n"
00338                "RandomNumberGeneratorService, but the source was not configured\n"
00339                "for random numbers.  An engine is created only if a seed(s) is provided\n"
00340                "in the configuration file.  Please add the following line to the\n"
00341                "configuration file in the RandomNumberGeneratorService block:\n"
00342                "        untracked uint32 sourceSeed = <your random number seed>\n\n"
00343                "Adding the line above will not work if you have modified the default and\n"
00344                "selected a different type of random engine that requires two or more seeds.\n"
00345                "In that case, you will need to add the following line instead:\n"
00346                "        untracked vuint32 sourceSeedVector = { <your first random number seed>, <your second random number seed> ... }\n\n";
00347         } else {
00348           throw edm::Exception(edm::errors::Configuration)
00349             << "The source requested a random number engine from the \n"
00350                "RandomNumberGeneratorService, but the source was not configured\n"
00351                "for random numbers.  An engine is created only if a seed(s) is provided\n"
00352                "in the configuration file.  Please add the following PSet to the\n"
00353                "configuration file in the RandomNumberGeneratorService block:\n"
00354                "        PSet theSource  = {\n"
00355                "                   untracked string engineName = <name of chosen engine>\n"
00356                "                   untracked uint32 initialSeed = <value of chosen seed>\n" 
00357                "                  }\n"
00358                "Adding the line above will not work if you have modified the default and\n"
00359                "selected a different type of random engine that requires two or more seeds.\n"
00360                "In that case, you will need to add the following line instead:\n"
00361                "        untracked vuint32 sourceSeedVector = { <your first random number seed>, <your second random number seed> ... }\n\n";
00362         }
00363       }
00364     }
00365     else {
00366       throw edm::Exception(edm::errors::Unknown)
00367         << "Requested a random number engine from the RandomNumberGeneratorService\n"
00368            "when no module was active.  This is not supposed to be possible.\n"
00369            "Please rerun the job using a debugger to get a traceback to show\n"
00370            "what routines were called and then send information to the edm developers.";
00371     }
00372   }
00373   return *(currentEngine_->second); 
00374 }
00375 
00376 uint32_t
00377 RandomNumberGeneratorService::mySeed() const {
00378 
00379   std::map<std::string, std::vector<uint32_t> >::const_iterator iter;
00380   iter = seedMap_.find(currentLabel_);
00381 
00382   if (iter == seedMap_.end()) {
00383     if (currentLabel_ != std::string() ) {
00384       if ( currentLabel_ != sourceLabel) {
00385        if(oldStyle_) {
00386           throw edm::Exception(edm::errors::Configuration)
00387             << "The module with label \""
00388             << currentLabel_
00389             << "\" requested a random number engine from the \n"
00390                "RandomNumberGeneratorService, but that module was not configured\n"
00391                "for random numbers.  An engine is created only if a seed(s) is provided\n"
00392                "in the configuration file.  Please add the following line to the\n"
00393                "configuration file in the moduleSeeds PSet of the RandomNumberGeneratorService:\n"
00394                "        untracked uint32 " << currentLabel_ << " = <your random number seed>\n\n"
00395                "Adding the line above will not work if you have modified the default and\n"
00396                "selected a different type of random engine that requires two or more seeds.\n"
00397                "In that case, you will need to add the following line to the moduleSeedVectors\n"
00398                "PSet instead:\n"
00399                "        untracked vuint32 " << currentLabel_ 
00400                << " = { <your first random number seed>, <your second random number seed> ... }\n\n";
00401         } else {
00402           throw edm::Exception(edm::errors::Configuration)
00403             << "The module with label \""
00404             << currentLabel_
00405             << "\" requested a random number engine from the \n"
00406                "RandomNumberGeneratorService, but that module was not configured\n"
00407                "for random numbers.  An engine is created only if a seed(s) is provided\n"
00408                "in the configuration file.  Please add the following PSet to the\n"
00409                "configuration file for the RandomNumberGeneratorService:\n"
00410                "        PSet " << currentLabel_ << " = {\n"
00411                "                   untracked string engineName = <name of chosen engine>\n"
00412                "                   untracked uint32 initialSeed = <value of chosen seed>\n" 
00413                "                  }\n"
00414                "Adding the line above will not work if you have modified the default and\n"
00415                "selected a different type of random engine that requires two or more seeds.\n"
00416                "In that case, you will need to replace the line with initialSeed with\n"
00417                "                   untracked vuint32 initialSeedSet = { <your first random number seed>,"
00418                "<your second random number seed> ... }\n\n";
00419         }
00420       } else {
00421         if(oldStyle_) {
00422           throw edm::Exception(edm::errors::Configuration)
00423             << "The source requested a random number engine from the \n"
00424                "RandomNumberGeneratorService, but the source was not configured\n"
00425                "for random numbers.  An engine is created only if a seed(s) is provided\n"
00426                "in the configuration file.  Please add the following line to the\n"
00427                "configuration file in the RandomNumberGeneratorService block:\n"
00428                "        untracked uint32 sourceSeed = <your random number seed>\n\n"
00429                "Adding the line above will not work if you have modified the default and\n"
00430                "selected a different type of random engine that requires two or more seeds.\n"
00431                "In that case, you will need to add the following line instead:\n"
00432                "        untracked vuint32 sourceSeedVector = { <your first random number seed>, <your second random number seed> ... }\n\n";
00433         } else {
00434           throw edm::Exception(edm::errors::Configuration)
00435             << "The source requested a random number engine from the \n"
00436                "RandomNumberGeneratorService, but the source was not configured\n"
00437                "for random numbers.  An engine is created only if a seed(s) is provided\n"
00438                "in the configuration file.  Please add the following PSet to the\n"
00439                "configuration file in the RandomNumberGeneratorService block:\n"
00440                "        PSet theSource  = {\n"
00441                "                   untracked string engineName = <name of chosen engine>\n"
00442                "                   untracked uint32 initialSeed = <value of chosen seed>\n" 
00443                "                  }\n"
00444                "Adding the line above will not work if you have modified the default and\n"
00445                "selected a different type of random engine that requires two or more seeds.\n"
00446                "In that case, you will need to add the following line instead:\n"
00447                "        untracked vuint32 sourceSeedVector = { <your first random number seed>, <your second random number seed> ... }\n\n";
00448         }
00449       }
00450     } else {
00451       throw edm::Exception(edm::errors::Unknown)
00452         << "Requested a random number engine from the RandomNumberGeneratorService\n"
00453            "when no module was active.  This is not supposed to be possible.\n"
00454            "Please rerun the job using a debugger to get a traceback to show\n"
00455            "what routines were called and then send information to the edm developers.";
00456     }
00457   }
00458   return iter->second[0];
00459 }
00460 
00461 void 
00462 RandomNumberGeneratorService::preModuleConstruction(const ModuleDescription& iDesc)
00463 {
00464   push(iDesc.moduleLabel_);
00465 }
00466 
00467 void 
00468 RandomNumberGeneratorService::postModuleConstruction(const ModuleDescription&)
00469 {
00470   pop();
00471 }
00472 
00473 void 
00474 RandomNumberGeneratorService::preSourceConstruction(const ModuleDescription& iDesc)
00475 {
00476   push(sourceLabel);
00477 }
00478 
00479 void 
00480 RandomNumberGeneratorService::postSourceConstruction(const ModuleDescription&)
00481 {
00482   pop();
00483 }
00484 
00485 void 
00486 RandomNumberGeneratorService::postBeginJob()
00487 {
00488   //finished begin run so waiting for first event and the source will be the first one called
00489   push(sourceLabel);
00490 
00491   // If there is an engine state file, us it to restore all engines to that state.
00492   if(!restoreFileName_.empty()) restoreEngineState(restoreFileName_);
00493  
00494   // Here is the right place to record engine states if that has been requested
00495   if(!saveFileName_.empty())  {
00496     saveEngineState(saveFileName_);
00497     if(!saveFileNameRecorded_) {
00498       std::string fullName = constructSaveFileName();
00499       Service<JobReport> reportSvc;
00500       reportSvc->reportRandomStateFile(fullName);
00501       saveFileNameRecorded_ = true;
00502     }
00503   }
00504 }
00505 
00506 void 
00507 RandomNumberGeneratorService::postEndJob()
00508 {
00509   if (labelStack_.size() != 1) {
00510     pop();
00511   }
00512 }
00513 
00514 void 
00515 RandomNumberGeneratorService::preEventProcessing(const edm::EventID&, const edm::Timestamp&)
00516 {
00517   //finished with source and now waiting for a module
00518   pop();
00519 }
00520 
00521 void 
00522 RandomNumberGeneratorService::postEventProcessing(const Event&, const EventSetup&)
00523 {
00524   // Here is the right place to record engine states if that has been requested
00525   if(!saveFileName_.empty())  {
00526     saveEngineState(saveFileName_);
00527     if(!saveFileNameRecorded_) {
00528       std::string fullName = constructSaveFileName();
00529       Service<JobReport> reportSvc;
00530       reportSvc->reportRandomStateFile(fullName);
00531       saveFileNameRecorded_ = true;
00532     }
00533   }
00534   //finished processing the event so should start another one soon.  The first thing to be called will be the source
00535   push(sourceLabel);
00536 }
00537 
00538 void 
00539 RandomNumberGeneratorService::preModule(const ModuleDescription& iDesc)
00540 {
00541   push(iDesc.moduleLabel_);
00542 }
00543 
00544 void 
00545 RandomNumberGeneratorService::postModule(const ModuleDescription&)
00546 {
00547   pop();
00548 }
00549 
00550 void 
00551 RandomNumberGeneratorService::preModuleBeginJob(const ModuleDescription& iDesc)
00552 {
00553   push(iDesc.moduleLabel_);
00554 }
00555 
00556 void 
00557 RandomNumberGeneratorService::postModuleBeginJob(const ModuleDescription&)
00558 {
00559   pop();
00560 }
00561 
00562 void 
00563 RandomNumberGeneratorService::preModuleEndJob(const ModuleDescription& iDesc)
00564 {
00565   push(iDesc.moduleLabel_);
00566 }
00567 
00568 void 
00569 RandomNumberGeneratorService::postModuleEndJob(const ModuleDescription&)
00570 {
00571   pop();
00572 }
00573 
00574 const std::vector<std::string>& 
00575 RandomNumberGeneratorService::getCachedLabels() const {
00576 
00577   return cachedLabels_;
00578 }
00579 
00580 const std::vector<std::vector<uint32_t> >&
00581 RandomNumberGeneratorService::getCachedStates() const {
00582 
00583   return cachedStates_;
00584 }
00585 
00586 const std::vector<std::vector<uint32_t> >&
00587 RandomNumberGeneratorService::getCachedSeeds() const {
00588 
00589   return cachedSeeds_;
00590 }
00591 
00592 void
00593 RandomNumberGeneratorService::restoreState(const edm::Event& iEvent) {
00594 
00595   if ( restoreStateLabel_ == std::string()) return;
00596 
00597     Handle<std::vector<RandomEngineState> > states;
00598 
00599     iEvent.getByLabel(restoreStateLabel_, states);
00600     if(!states.isValid()) {
00601     throw edm::Exception(edm::errors::ProductNotFound)
00602       << "The RandomNumberGeneratorService is trying to restore\n"
00603       << "the state of the random engines by reading an object from\n"
00604       << "the event with label \"" << restoreStateLabel_ << "\".  It\n"
00605       << "fails to find one.  This is probably set to the wrong value\n"
00606       << "in the configuration file.  It must match the module label\n"
00607       << "of the RandomEngineStateProducer that created the object in\n"
00608       << "a previous process\n";   
00609   }
00610 
00611   // The service does not currently support restoring the state
00612   // of the source random engine.  Throw an exception if the user tries.
00613   // If we ever try to implement this, the main step is getting the functions
00614   // restoreState and snapShot called at the correct point(s) in time in the 
00615   // source.  And you also need a source that both reads an input file and
00616   // generates random numbers.  If those things are done, I think one could
00617   // simply delete the following error check and everything should
00618   // work.  The state of the source is already saved, the problem
00619   // involves restoring it.  Currently, the calls to snapShot and restoreState
00620   // are in the base class InputSource and also snapShot gets called at the
00621   // end of this function.  Alternatively, one could imagine separating the
00622   // parts of the source that generate random numbers and putting those
00623   // parts in normal modules.
00624   EngineMap::iterator sourceEngine = engineMap_.find(sourceLabel);
00625   if (sourceEngine != engineMap_.end()) {
00626     throw edm::Exception(edm::errors::UnimplementedFeature)
00627       << "The RandomNumberGeneratorService was instructed to restore\n"
00628       << "the state of the random engines and the source is\n"
00629       << "configured to generate random numbers.\n"
00630       << "Currently the RandomNumberGeneratorService is not\n"
00631       << "capable of restoring the random engine state of the\n"
00632       << "source.  This feature has not been implemented yet.\n"
00633       << "You need to remove the line in the configuration file\n"
00634       << "that gives the source a seed or stop trying to restore\n"
00635       << "the state of the random numbers (remove the line that sets\n"
00636       << "the \"restoreStateLabel\" in the configuration file).\n";
00637   }
00638 
00639   // Get the information out of the persistent object into
00640   // convenient vectors and convert to the type CLHEP requires.
00641   // There may be some issues here when we go to 64 bit machines.
00642 
00643   for (std::vector<RandomEngineState>::const_iterator iter = states->begin();
00644        iter != states->end();
00645        ++iter) {
00646     std::string engineLabel = iter->getLabel();
00647     std::vector<uint32_t> engineState = iter->getState();
00648     std::vector<unsigned long> engineStateL;
00649     for (std::vector<uint32_t>::const_iterator iVal = engineState.begin();
00650          iVal != engineState.end();
00651          ++iVal) {
00652       engineStateL.push_back(static_cast<unsigned long>(*iVal));
00653     }
00654 
00655     std::vector<uint32_t> engineSeeds = iter->getSeed();
00656     std::vector<long> engineSeedsL;
00657     for (std::vector<uint32_t>::const_iterator iVal = engineSeeds.begin();
00658          iVal != engineSeeds.end();
00659          ++iVal) {
00660       engineSeedsL.push_back(static_cast<long>(*iVal));
00661     }
00662 
00663     EngineMap::iterator engine = engineMap_.find(engineLabel);
00664 
00665     // Note: It is considered legal for the module label
00666     // to be in the event but not in the configuration file.
00667     // In this case we just ignore it and do nothing.
00668 
00669     // The converse is also legal.  If the module label is in the
00670     // configuration file and not in the event, this is legal.
00671     // Again we do nothing.
00672 
00673     // Now deal with the case where the module label appears both
00674     // in the input file and also in the configuration file.
00675 
00676     if (engine != engineMap_.end()) {
00677 
00678       seedMap_[engineLabel] = engineSeeds;
00679 
00680       // We need to handle each type of engine differently because each
00681       // has different requirements on the seed or seeds.
00682       if (engineStateL[0] == CLHEP::engineIDulong<CLHEP::HepJamesRandom>()) {
00683 
00684         checkEngineType(engine->second->name(), std::string("HepJamesRandom"), engineLabel);
00685 
00686         // These two lines actually restore the seed and engine state.
00687         engine->second->setSeed(engineSeedsL[0], 0);
00688         engine->second->get(engineStateL);
00689       }
00690       else if (engineStateL[0] == CLHEP::engineIDulong<CLHEP::RanecuEngine>()) {
00691 
00692         checkEngineType(engine->second->name(), std::string("RanecuEngine"), engineLabel);
00693 
00694         // This line actually restores the engine state.
00695         engine->second->get(engineStateL);
00696       }
00697 
00698       else if (engineStateL[0] == CLHEP::engineIDulong<TRandomAdaptor>()) {
00699 
00700         checkEngineType(engine->second->name(), std::string("TRandom3"), engineLabel);
00701 
00702         // This line actually restores the engine state.
00703         engine->second->setSeed(engineSeedsL[0], 0);
00704         engine->second->get(engineStateL);
00705       }
00706       // This should not be possible because this code should be able to restore
00707       // any kind of engine whose state can be saved.
00708       else {
00709         throw edm::Exception(edm::errors::Unknown)
00710           << "The RandomNumberGeneratorService is trying to restore the state\n"
00711              "of the random engines.  The state in the event indicates an engine\n"
00712              "of an unknown type.  This should not be possible unless you are\n"
00713              "running with an old code release on a new file that was created\n"
00714              "with a newer release which had new engine types added.  In this case\n"
00715              "the only solution is to use a newer release.  In any other case, notify\n"
00716              "the EDM developers because this should not be possible\n";
00717       }
00718     }
00719   }
00720   snapShot();
00721 }
00722 
00723 void
00724 RandomNumberGeneratorService::snapShot()
00725 {
00726   cachedLabels_.clear();
00727   cachedStates_.clear();
00728   cachedSeeds_.clear();
00729 
00730   // Loop over the engines and copy the engine state,
00731   // labels, and initial seeds into temporary cache
00732   // for later use by the RandomEngineStateProducer module
00733   for (EngineMap::const_iterator iter = engineMap_.begin();
00734        iter != engineMap_.end();
00735        ++iter) {
00736 
00737     cachedLabels_.push_back(iter->first);
00738 
00739     std::vector<unsigned long> stateL = iter->second->put();
00740     std::vector<uint32_t> state32;
00741     for (std::vector<unsigned long>::const_iterator vIter = stateL.begin();
00742          vIter != stateL.end();
00743          ++vIter) { 
00744       state32.push_back(static_cast<uint32_t>(*vIter));
00745     }
00746     cachedStates_.push_back(state32);
00747 
00748     cachedSeeds_.push_back(seedMap_[iter->first]);
00749   }
00750 }
00751 
00752 void
00753 RandomNumberGeneratorService::print() {
00754   std::cout << "\n\nRandomNumberGeneratorService dump\n\n";
00755 
00756   std::cout << "    Contents of seedMap\n";
00757   for (std::map<std::string, std::vector<uint32_t> >::const_iterator iter = seedMap_.begin();
00758        iter != seedMap_.end();
00759        ++iter) {
00760     std::cout << "        " << iter->first;
00761     std::vector<uint32_t> seeds = iter->second;
00762     for (std::vector<uint32_t>::const_iterator vIter = seeds.begin();
00763          vIter != seeds.end();
00764          ++vIter) {
00765       std::cout << "   "  << *vIter;
00766     }
00767     std::cout << "\n";
00768   }
00769   std::cout << "\n    Contents of engineMap\n";
00770   for (EngineMap::const_iterator iter = engineMap_.begin();
00771        iter != engineMap_.end();
00772        ++iter) {
00773     std::cout << "        " << iter->first
00774               << "   " << iter->second->name()
00775               << "   " << iter->second->getSeed()
00776               << "\n";
00777   }
00778   std::cout << "\n";
00779   std::cout << "    currentLabel_ = " << currentLabel_ << "\n";
00780   std::cout << "    labelStack_ size = " << labelStack_.size() << "\n";
00781   int i = 0;
00782   for (std::vector<std::string>::const_iterator iter = labelStack_.begin();
00783        iter != labelStack_.end();
00784        ++iter, ++i) {
00785     std::cout << "                 " << i << "  " << *iter << "\n";    
00786   }
00787   if (currentEngine_ == engineMap_.end()) {
00788     std::cout << "    currentEngine points to end\n";
00789   }
00790   else {
00791     std::cout << "    currentEngine_ = " << currentEngine_->first
00792               << "  " << currentEngine_->second->name()
00793               << "  " << currentEngine_->second->getSeed() << "\n";
00794   }
00795 
00796   std::cout << "    engineStack_ size = " << engineStack_.size() << "\n";
00797   i = 0;
00798   for (std::vector<EngineMap::const_iterator>::const_iterator iter = engineStack_.begin();
00799        iter != engineStack_.end();
00800        ++iter, ++i) {
00801     if (*iter == engineMap_.end()) {
00802       std::cout << "                 " << i << "  Points to end of engine map\n";    
00803     }
00804     else {
00805       std::cout << "                 " << i << "  " << (*iter)->first 
00806                 << "  " << (*iter)->second->name() << "  " << (*iter)->second->getSeed() << "\n";    
00807     }
00808   }
00809 
00810   std::cout << "    restoreStateLabel_ = " << restoreStateLabel_ << "\n";
00811 
00812   int size = getCachedLabels().size();
00813   std::cout << "    cachedLabels size = " << size << "\n";
00814   for (int i = 0; i < size; ++i) {
00815     std::cout << "      " << i << "  " << getCachedLabels()[i] << "\n";
00816   }
00817 
00818   size = getCachedStates().size();
00819   std::cout << "    cachedStates size = " << size << "\n";
00820   for (int i = 0; i < size; ++i) {
00821     std::vector<uint32_t> state = getCachedStates()[i];
00822     std::cout << "      " << i << " : ";
00823     int j = 0;
00824     for (std::vector<uint32_t>::const_iterator iter = state.begin();
00825          iter != state.end();
00826          ++iter, ++j) {
00827       if (j > 0 && (j % 10) == 0) {
00828         std::cout << "\n              ";
00829       }
00830       std::cout << "  " << *iter;
00831     }
00832     std::cout << "\n";
00833   }
00834 
00835   size = getCachedSeeds().size();
00836   std::cout << "    cachedSeeds size = " << size << "\n";
00837   for (int i = 0; i < size; ++i) {
00838     std::vector<uint32_t> seeds = getCachedSeeds()[i];
00839     std::cout << "      " << i << " : ";
00840     for (std::vector<uint32_t>::const_iterator iter = seeds.begin();
00841          iter != seeds.end();
00842          ++iter) {
00843       std::cout << "  " << *iter;
00844     }
00845     std::cout << "\n";
00846   }
00847 }
00848 
00849 void
00850 RandomNumberGeneratorService::push(const std::string& iLabel)
00851 {
00852   currentEngine_ = engineMap_.find(iLabel);
00853   engineStack_.push_back(currentEngine_);
00854   
00855   labelStack_.push_back(iLabel);
00856   currentLabel_ = iLabel;
00857 }
00858 
00859 void
00860 RandomNumberGeneratorService::pop()
00861 {
00862   engineStack_.pop_back();
00863   //NOTE: algorithm is such that we always have at least one item in the stacks
00864   currentEngine_ = engineStack_.back();
00865   labelStack_.pop_back();
00866   currentLabel_ = labelStack_.back();
00867 }
00868 
00869 void
00870 RandomNumberGeneratorService::checkEngineType(const std::string& typeFromConfig,
00871                                               const std::string& typeFromEvent,
00872                                               const std::string& engineLabel)
00873 {
00874   if (typeFromConfig != typeFromEvent) {
00875 
00876     if (engineLabel == sourceLabel) {
00877       throw edm::Exception(edm::errors::Configuration)
00878         << "The RandomNumberGeneratorService is trying to restore\n"
00879         << "the state of the random engine for the source.  An\n"
00880         << "error was detected because the type of the engine in the\n"
00881         << "input file and the configuration file do not match.\n"
00882         << "In the configuration file the type is \"" << typeFromConfig
00883         << "\".\nIn the input file the type is \"" << typeFromEvent << "\".  If\n"
00884         << "you are not generating any random numbers in the source, then\n"
00885         << "remove the line in the configuration file that gives the source\n"
00886         << "a seed and the error will go away.  Otherwise, you must give\n"
00887         << "the source the same engine type in the configuration file or\n"
00888         << "stop trying to restore the random engine state.\n";
00889     }
00890     else {
00891       throw edm::Exception(edm::errors::Configuration)
00892         << "The RandomNumberGeneratorService is trying to restore\n"
00893         << "the state of the random engine for the module \"" 
00894         << engineLabel << "\".  An\n"
00895         << "error was detected because the type of the engine in the\n"
00896         << "input file and the configuration file do not match.\n"
00897         << "In the configuration file the type is \"" << typeFromConfig
00898         << "\".\nIn the input file the type is \"" << typeFromEvent << "\".  If\n"
00899         << "you are not generating any random numbers in this module, then\n"
00900         << "remove the line in the configuration file that gives it\n"
00901         << "a seed and the error will go away.  Otherwise, you must give\n"
00902         << "this module the same engine type in the configuration file or\n"
00903         << "stop trying to restore the random engine state.\n";
00904     }
00905   }
00906 }
00907 
00908 void
00909 RandomNumberGeneratorService::dumpVector(const std::vector<uint32_t> &v)
00910 {
00911   if(v.empty()) return;
00912   size_t numItems = v.size();
00913   for( int i=0; i<(int)numItems; ++i)  {
00914     if( i != 0 && i%10 == 0 )  std::cerr << std::endl;
00915     std::cerr << std::setw(13) << v[i] ;
00916   }
00917     if(numItems%10 != 0)  std::cerr << std::endl;
00918 }
00919 
00920 void
00921 RandomNumberGeneratorService::stashVector(const std::vector<unsigned long> &v,
00922                                                 std::ostream &outFile)
00923 {
00924   if(v.empty()) return;
00925   size_t numItems = v.size();
00926   for( int i=0; i<(int)numItems; ++i)  {
00927     if( i != 0 && i%10 == 0 )  outFile << "\n" ;
00928     outFile << std::setw(13) << v[i] ;
00929   }
00930     if(numItems%10 != 0)  outFile << "\n" ;
00931 }
00932 
00933 std::vector<unsigned long>
00934 RandomNumberGeneratorService::restoreVector(std::istream &is, const int32_t numItems)
00935 {
00936   unsigned long value;
00937   std::vector<unsigned long> v;
00938   std::ostringstream sstr;
00939   int i = 0;
00940   is >> std::ws;
00941   while(i<numItems)  {
00942     if(!(is >> value)) {
00943       sstr << "Configuration: Unable to read the random engine state vector from file, "
00944            << restoreFileName_ << ".\n" 
00945            << "The file has probably been corrupted.\n" ;
00946       edm::Exception except(edm::errors::Configuration, sstr.str());
00947       throw except;
00948     } else {
00949       v.push_back(value);
00950       ++i;
00951     }
00952   }
00953   return v;
00954 }
00955 
00956 
00957 void RandomNumberGeneratorService::restoreEngineState(const std::string& fileName)
00958 {
00959 
00960 // Check that we do or do not want to restore state from a previously written state file
00961 
00962   std::ifstream inFile;
00963   std::ostringstream sstr;
00964   inFile.open(fileName.c_str(), std::ifstream::in);
00965   if(!inFile) {
00966     sstr << "Configuration: Unable to open the file, "
00967          << fileName << ", to restore the engine status.\n" ;
00968     edm::Exception except(edm::errors::Configuration, sstr.str());
00969     throw except;
00970   }
00971 
00972   std::string text;
00973   inFile >> text;
00974   if(text != std::string("<RandomEngineStates>")) {
00975     sstr << "Configuration: File, " << restoreFileName_ 
00976          << " is ill-structured or otherwise corrupted.\n"
00977          << "Cannot read the file header word.\n" ;
00978     edm::Exception except(edm::errors::Configuration, sstr.str());
00979     throw except;
00980   }
00981   while(processStanza(inFile)) { }
00982 }
00983 
00984 bool RandomNumberGeneratorService::processStanza(std::istream &is)
00985 {
00986   std::string leading, trailing;
00987   std::string moduleLabel;
00988   std::string engineName;
00989   long initialSeed;
00990   int stateVectorLength;
00991   std::vector<unsigned long> stateVector;
00992   std::ostringstream sstr;
00993 
00994   is >> leading;
00995   if(leading == std::string("</RandomEngineStates>")) return false;
00996   is >> moduleLabel >> trailing;
00997   if(leading != std::string("<ModuleLabel>") || trailing != std::string("</ModuleLabel>")) {
00998     sstr << "Configuration: File, " << restoreFileName_ 
00999          << ", is ill-structured or otherwise corrupted.\n" 
01000          << "Cannot read a module label.\n" ;
01001     edm::Exception except(edm::errors::Configuration, sstr.str());
01002     throw except;
01003   }
01004 
01005   is >> leading >> engineName >> trailing;
01006   if(leading != std::string("<EngineName>")  || trailing != std::string("</EngineName>")) {
01007     sstr << "Configuration: File, " << restoreFileName_ 
01008          << ", is ill-structured or otherwise corrupted.\n" 
01009          << "Cannot read an engine name.\n" ;
01010     edm::Exception except(edm::errors::Configuration, sstr.str());
01011     throw except;
01012   }
01013 
01014   is >> leading >> initialSeed >> trailing;
01015   if(leading != std::string("<InitialSeed>") || trailing != std::string("</InitialSeed>")) {
01016     sstr << "Configuration: File, " << restoreFileName_ 
01017          << ", is ill-structured or otherwise corrupted.\n" 
01018          << "Cannot read initial seed(s).\n" ;
01019     edm::Exception except(edm::errors::Configuration, sstr.str());
01020     throw except;
01021   }
01022 
01023   is >> leading >> stateVectorLength >> trailing;
01024   if(leading != std::string("<FullStateLength>") || trailing != std::string("</FullStateLength>")) {
01025     sstr << "Configuration: File, " << restoreFileName_ 
01026          << ", is ill-structured or otherwise corrupted.\n" 
01027          << "Cannot read the state vector length.\n" ;
01028     edm::Exception except(edm::errors::Configuration, sstr.str());
01029     throw except;
01030   }  
01031 
01032   is >> leading;
01033   if(leading != std::string("<FullState>")) {
01034     sstr << "Configuration: File, " << restoreFileName_ 
01035          << ", is ill-structured or otherwise corrupted.\n"
01036          << "Cannot read state vector header.\n" ;
01037     edm::Exception except(edm::errors::Configuration, sstr.str());
01038     throw except;
01039   }  
01040   stateVector = restoreVector(is, stateVectorLength);
01041   is >> trailing;
01042   if(trailing != std::string("</FullState>")) {
01043     sstr << "Configuration: File, " << restoreFileName_ 
01044          << ", is ill-structured or otherwise corrupted.\n"
01045          << "Cannot read state vector trailer.\n" ;
01046     edm::Exception except(edm::errors::Configuration, sstr.str());
01047     throw except;
01048   }  
01049  
01050 // We've recovered everything.  Now make sure it's all consistent
01051 // and, if so, overwrite the state.
01052 
01053   CLHEP::HepRandomEngine* engine;
01054   EngineMap::iterator iter = engineMap_.find(moduleLabel);
01055   if(iter == engineMap_.end()) {
01056     if(moduleLabel == sourceLabel) {
01057 
01058 //    Damned special case!
01059 //    For now, we have suppressed writing this stanza of the state save file
01060 //    so we should never get here.  If we do get here, yell and throw.
01061 
01062       sstr << "Configuration: sourceLabel @source is currently disallowed"
01063            << "\nbut appears in save file, " << saveFileName_ << "\n" ;
01064       edm::Exception except(edm::errors::Configuration, sstr.str());
01065       throw except;
01066     } else {
01067       sstr << "Configuration: The module label, " << moduleLabel 
01068            << ", found in the state save file does not match any label "
01069            << "in the configuration file.  There is a mismatch between "
01070            << "the configuration file and the state save file, "
01071            << saveFileName_ << "\n" ;
01072       edm::Exception except(edm::errors::Configuration, sstr.str());
01073       throw except;
01074     } 
01075   } else {
01076     engine = iter->second;
01077     if(engine->name() != engineName) {
01078       sstr << "Configuration: The engine name in the configuration file (" << engine->name() 
01079            << ")\ndoes not match the name (" << engineName << ") in the state save file,\n" 
01080            << saveFileName_ << ", for the module labelled " << moduleLabel << "\n" ;
01081       edm::Exception except(edm::errors::Configuration, sstr.str());
01082       throw except;
01083     }
01084     engine->setSeed(initialSeed,0);
01085     bool success = engine->get(stateVector);
01086     if(!success) {
01087       sstr << "Configuration: Setting the state of " << engine->name() << " failed.\n"
01088            << "Aborting.\n" ;
01089       edm::Exception except(edm::errors::Configuration, sstr.str());
01090       throw except;
01091     }
01092   }
01093   return true;
01094 }
01095 
01096 void RandomNumberGeneratorService::saveEngineState(const std::string& fileName)
01097 {
01098   std::ofstream outFile;
01099   outFile.open(fileName.c_str(), std::ofstream::out | std::ofstream::trunc);
01100   if(!outFile) {
01101     std::ostringstream sstr;
01102     sstr << "Configuration: Unable to open the file, "
01103          << fileName << ", to save the engine status.\n" ;
01104     edm::Exception except(edm::errors::Configuration, sstr.str());
01105     throw except;
01106   }
01107   outFile << "<RandomEngineStates>\n" ;
01108   for(EngineMap::const_iterator iter = engineMap_.begin(), iterEnd = engineMap_.end();
01109     iter != iterEnd;
01110     ++iter) {
01111     std::string moduleLabel = iter->first;
01112 //
01113 //  The service does not support restoring the state of the source engine. Until that
01114 //  is dealt with, there is no point in even saving the source engine state so, for
01115 //  the present, we skip it.
01116 //
01117     if(moduleLabel != sourceLabel) {
01118       std::string engineName = iter->second->name();
01119       long initialSeed = iter->second->getSeed();
01120       std::vector<unsigned long> stateVector = iter->second->put();
01121       int stateVectorLength = stateVector.size();
01122 
01123       outFile << "<ModuleLabel>\n" << moduleLabel << "\n</ModuleLabel>\n" ;
01124       outFile << "<EngineName>\n" << engineName << "\n</EngineName>\n" ;
01125       outFile << "<InitialSeed>\n" << initialSeed << "\n</InitialSeed>\n" ;
01126       outFile << "<FullStateLength>\n" << stateVectorLength << "\n</FullStateLength>\n" ;
01127       outFile << "<FullState>\n" ;
01128       stashVector(stateVector, outFile);
01129       outFile   << "</FullState>\n" ;
01130     }
01131   }
01132   outFile << "</RandomEngineStates>\n" ;
01133 }
01134 
01135 bool RandomNumberGeneratorService::isEngineNameValid(std::string const &name)
01136 {
01137   bool valid = false;
01138   if(name == std::string("HepJamesRandom")) valid = true;
01139   if(name == std::string("RanecuEngine"))   valid = true;
01140   if(name == std::string("TRandom3"))       valid = true;
01141   return valid;
01142 }
01143 
01144 int32_t RandomNumberGeneratorService::expectedSeedCount(std::string const &name)
01145 {
01146   int32_t count = 0;
01147   if(name == std::string("HepJamesRandom")) count = 1;
01148   if(name == std::string("RanecuEngine"))   count = 2;
01149   if(name == std::string("TRandom3"))       count = 1;
01150   return count;
01151 }
01152 std::string RandomNumberGeneratorService::constructSaveFileName()
01153 {
01154   std::string fullName;
01155   fullName.reserve(1000);
01156   fullName = getcwd(&fullName[0],1000); 
01157   fullName += "/" + saveFileName_;
01158   fullName.reserve();
01159   return fullName;
01160 }
01161 
01162 void
01163 RandomNumberGeneratorService::oldStyleConfig(const ParameterSet& iPSet)
01164 {
01165   std::string labels;
01166   std::vector<uint32_t> seeds;
01167   PSet  empty_PSet;
01168   VString  empty_VString;
01169   Vuint32  empty_Vuint32;
01170 
01171   std::string engineName;
01172 
01173   VString pSets = iPSet.getParameterNamesForType<edm::ParameterSet>();
01174   for(VString::const_iterator it = pSets.begin(), itEnd = pSets.end(); it != itEnd; ++it) {
01175     if(*it == std::string("theSource")) {
01176       throw edm::Exception(edm::errors::Configuration)
01177         << "PSet theSource is not recognized for old-style configuration files." 
01178         << "\nYou must be consistent in your use of new- or old-style cfg format"
01179         << "\nfor the RandomNumberGeneratorService." ;
01180     }
01181   }
01182 
01183   // If there is more than one seed required to initialize the engine type you want to use,
01184   // the vector form must be used.  Otherwise, either works.  The default engine only requires
01185   // one seed.  If both the vector seed and single seed commands appear in the configuration
01186   // file, then the vector form gets used and the other ignored.
01187 
01188   if(iPSet.exists("sourceSeedVector")) {
01189     seeds = iPSet.getUntrackedParameter<std::vector<uint32_t> >("sourceSeedVector");
01190   // If there is no vector look for a single seed
01191   } else if(iPSet.exists("sourceSeed")) {
01192       uint32_t seed = iPSet.getUntrackedParameter<uint32_t>("sourceSeed");
01193       seeds.push_back(seed);
01194   }
01195 
01196   // If you find seed(s) for the source, save it
01197   if (seeds.size() > 0) {
01198     seedMap_[sourceLabel] = seeds;
01199   }
01200 
01201   if(iPSet.exists("moduleSeedVectors")) {
01202     const edm::ParameterSet& moduleSeedVectors = iPSet.getParameter<edm::ParameterSet>("moduleSeedVectors");
01203     
01204     std::vector<std::string> names = moduleSeedVectors.getParameterNames();
01205     for(std::vector<std::string>::const_iterator itName = names.begin(), itNameEnd = names.end(); itName != itNameEnd; ++itName) {
01206 
01207       if(seedMap_.find(*itName) == seedMap_.end()) {
01208         if(moduleSeedVectors.exists(*itName)) {
01209           seeds = moduleSeedVectors.getUntrackedParameter<std::vector<uint32_t> >(*itName);
01210           if (seeds.size() > 0) {
01211             seedMap_[*itName] = seeds;
01212           }
01213         }
01214       }
01215     }
01216         // If there is something wrong, skip it. If this random engine or seed is actually needed
01217         // an exception will be thrown when the engine or seed is requested and not available
01218   }
01219     // It is OK if this is missing.
01220 
01221   if(iPSet.exists("moduleSeeds")) {
01222     const edm::ParameterSet& moduleSeeds = iPSet.getParameter<edm::ParameterSet>("moduleSeeds");
01223     
01224     std::vector<std::string> names = moduleSeeds.getParameterNames();
01225     for(std::vector<std::string>::const_iterator itName = names.begin(), itNameEnd = names.end();
01226                                                  itName != itNameEnd; ++itName) {
01227 
01228     // If we already have a seed vector for this label ignore this one
01229       if (seedMap_.find(*itName) == seedMap_.end()) {
01230 
01231         if(moduleSeeds.exists(*itName)) {
01232           uint32_t seed = moduleSeeds.getUntrackedParameter<uint32_t>(*itName);
01233           seeds.clear();
01234           seeds.push_back(seed);
01235           seedMap_[*itName] = seeds;
01236         }
01237         // If there is something wrong, skip it, if this random engine or seed is actually needed
01238         // an exception will be thrown when the engine or seed is requested and not available
01239       }
01240     }  
01241   }
01242 
01243     // It is OK if this is missing.
01244 
01245   // Loop over the engines where the seed(s) were specified and see
01246   // if the engine is also specified.  If not, default to HepJamesRandom.
01247   // Create the engines and fill the map.
01248 
01249   for (std::map<std::string, std::vector<uint32_t> >::iterator seedIter  = seedMap_.begin();
01250                                                                seedIter != seedMap_.end();
01251                                                              ++seedIter) {
01252 
01253     // Initialize with default engine
01254     std::string engineName = "HepJamesRandom";
01255 
01256     // Go see if this module name already appears in the engineMap_ as a consequence of
01257     // the new cfg format. Enter this engine only if it isn't already there.
01258     if(engineMap_.find(seedIter->first) == engineMap_.end()) {
01259  
01260       if (seedIter->first == sourceLabel) {
01261         if(iPSet.exists("sourceEngine")) {
01262           engineName = iPSet.getUntrackedParameter<std::string>("sourceEngine");
01263         }
01264       } else if(iPSet.exists("moduleEngines")) {
01265         const edm::ParameterSet& moduleEngines = iPSet.getParameter<edm::ParameterSet>("moduleEngines");
01266         if(moduleEngines.exists(seedIter->first)) {
01267           engineName = moduleEngines.getUntrackedParameter<std::string>(seedIter->first);
01268         }
01269       }
01270       // OK if none, use default
01271 
01272       std::string outputString = "the module with label \"";
01273       outputString += seedIter->first;
01274       outputString += "\"";
01275       if (seedIter->first == sourceLabel) outputString = "the source";
01276 
01277       if (engineName == "HepJamesRandom") {
01278 
01279         if (seedIter->second.size() != 1) {
01280           throw edm::Exception(edm::errors::Configuration)
01281             << "HepJamesRandom engine requires 1 seed and "
01282             << seedIter->second.size()
01283             << " seeds were\n"
01284             << "specified in the configuration file for "
01285             << outputString << ".";
01286         }
01287 
01288         if (seedIter->second[0] > 900000000) {
01289           throw edm::Exception(edm::errors::Configuration)
01290             << "The HepJamesRandom engine seed should be in the range 0 to 900000000.\n"
01291             << "The seed passed to the RandomNumberGenerationService from the\n"
01292                "configuration file was " << seedIter->second[0]
01293             << " or negative or larger\n"
01294                "than a 32 bit unsigned integer.  This was for "
01295             << outputString << ".";
01296         }
01297         long seedL = static_cast<long>(seedIter->second[0]);
01298         CLHEP::HepRandomEngine* engine = new CLHEP::HepJamesRandom(seedL);
01299         engineMap_[seedIter->first] = engine;
01300       } else if (engineName == "RanecuEngine") {
01301 
01302         if (seedIter->second.size() != 2) {
01303           throw edm::Exception(edm::errors::Configuration)
01304             << "RanecuEngine requires 2 seeds and "
01305             << seedIter->second.size()
01306             << " seeds were\n"
01307             << "specified in the configuration file for "
01308             << outputString << ".";
01309         }
01310 
01311         if (seedIter->second[0] > std::numeric_limits<uint32_t>::max() ||
01312             seedIter->second[1] > std::numeric_limits<uint32_t>::max()) {  // They need to fit in a 31 bit integer
01313           throw edm::Exception(edm::errors::Configuration)
01314             << "The RanecuEngine seeds should be in the range 0 to " << std::numeric_limits<uint32_t>::max() << ".\n"
01315             << "The seeds passed to the RandomNumberGenerationService from the\n"
01316                "configuration file were " << seedIter->second[0] << " and " << seedIter->second[1]
01317             << " (or one was negative\nor larger "
01318                "than a 32 bit unsigned integer).\nThis was for "
01319             << outputString << ".";
01320         }
01321         long seedL[2];
01322         seedL[0] = static_cast<long>(seedIter->second[0]);
01323         seedL[1] = static_cast<long>(seedIter->second[1]);
01324         CLHEP::HepRandomEngine* engine = new CLHEP::RanecuEngine();
01325         engine->setSeeds(seedL, 0);
01326         engineMap_[seedIter->first] = engine;
01327 
01328       } else if (engineName == "TRandom3") {
01329 
01330         if (seedIter->second.size() != 1) {
01331           throw edm::Exception(edm::errors::Configuration)
01332             << "TRandom3 engine requires 1 seed and "
01333             << seedIter->second.size()
01334             << " seeds were\n"
01335             << "specified in the configuration file for "
01336             << outputString << ".";
01337         }
01338         long seedL = static_cast<long>(seedIter->second[0]);
01339         CLHEP::HepRandomEngine* engine = new TRandomAdaptor(seedL);
01340         engineMap_[seedIter->first] = engine;
01341       } else {
01342         throw edm::Exception(edm::errors::Configuration)
01343           << "The configuration file requested the RandomNumberGeneratorService\n"
01344              "create an unknown random engine type named \""
01345           << engineName
01346           << "\"\nfor " << outputString
01347           << "\nCurrently the only valid types are HepJamesRandom, RanecuEngine and TRandom3";
01348       }
01349     }
01350   }
01351 }

Generated on Tue Jun 9 17:39:08 2009 for CMSSW by  doxygen 1.5.4