TWiki
>
CMSPublic Web
>
SWGuide
>
WorkBook
>
WorkBookFWLiteExamples
(revision 43) (raw view)
Edit
Attach
PDF
---+!! 3.5.3 Examples of !FWLite macros ---++ Contents * [[#IntroDuction][3.5.3.1. Introduction]] * [[#SetUp][3.5.3.2. Setting up the environment]] * [[#ExampleOne][3.5.3.3. Example 1: Access to event information]] * [[#ExampleTwo][3.5.3.4. Example 2: Plotting histograms]] * [[#ExampleThree][3.5.3.5. Example 3: Using _python_ configuration]] * [[#ExampleFour][3.5.3.6. Example 4: Using event selectors]] * [[#ExampleFive][3.5.3.7. Example 5: Using !FWLite and full framework in parallel]] %BR% [[#ReviewStatus][Detailed Review status]] #IntorDuction ---++ 3.5.3.1. Introduction You should view !FWLite as a way to access bare ROOT input files of the !EDM, with the capability to read and recognise CMSSW [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/DataFormats/][DataFormats]] while the performance advantages of I/O and CPU consumption of the bare ROOT access are sustained. It should be emphasised that !FWLite is not an exclusive alternative to the use of the full framework. Rather we propose to use !FWLite and full framework in parallel depending on the requirements of your analysis. Many efforts have been made during the developments of !FWLite to achieve a user interface maximally facilitating the interchange of code between both paradigms. AT (Analysis Tools) strongly recommends *NOT to rely on _CINT_ within ROOT with interactive macros!* We recommend to use compiled code instead. On this page you will find examples of compiled !FWLite executables that can be used as starting points for your own analysis. The emphasise is to start from the simplest and most basic skeletons and to give examples how to increase the level of complexity step by step. Finally we will point you to a fully equipped example to do an analysis both with !FWLite and within the full !EDM framework using the same code. We will assume that you work on _lxplus_, but following the instructions given [[WorkBookFWLite][above]] you can run these examples on any other computer system that has !FWLite installed. #SetUp ---++ 3.5.3.2. Setting up of the environment First of all connect to _lxplus_ and go to some working directory. You can choose any directory, provided that you have enough space. You need some minimum of free disc space to do the exercises described here. We recommend you to use your _~/scratch0_ space. In case you don't have this (or do not even know what it is) check your quota typing =fs lq= and follow [[https://cmsdoc.cern.ch/comp/help/doc/disk_space.shtml][this link]]. If you don't have enough space, you may instead use the temporary space (_/tmp/your_user_name_), but be aware that this is lost once you log out from _lxplus_ (or app. within a day). We will expect in the following that you have such a _~/scratch0_ directory. <verbatim> ssh lxplus [ ... enter password ... ] cd scratch0/ </verbatim> Create a local release area and enter it, set up the environment (using the _cmsenv_ command) <PRE> cmsrel CMSSW_5_3_12 cd CMSSW_5_3_12/src cmsenv </PRE> %X% *Note:* Please for the time being use the set of tags as described [[https://twiki.cern.ch/twiki/bin/view/CMSPublic/SWGuidePATReleaseNotes41X#V08_06_01_12][here]] on top of the recommended release to be able to follow the examples given in the following Checkout the [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/CMS.PhysicsTools/FWLite/][FWLite]] package, which contains the examples that will be discussed in the following to be able to inspect them in your favourite editor. You can use the _addpkg_ command, which will automatically pick up the proper _cvs_ tag from the release. <PRE> git cms-addpkg PhysicsTools/FWLite </PRE> %X% *Note:* We are going to go through the exmaples in the !FWLite package. The _addpkg_ tool picks the right _cvs_ version of this package from the release and copies it to your local release area. %X% *Note:* Don't forget to recompile the package whenever you changed any of the executables. You have to _rehash_ the environment after *each compilation* to make sure that the cash of the shell prompt is refreshed. You can do this using the _cmsenv_ command or better the command _rehash_. %X% *Note:* In the current implementation all examples will require a _patTuple.root_ file unless stated otherwise. Have a look to [[WorkBookPATTupleCreationExercise]] to learn how to create such a PAT tuple. #ExampleOne ---++ 3.5.3.3. Example 1: Access to event information The first example shows how to access simple event information. We are going to show how to access the run-wise luminosity and peak luminosity from the _edm::Event_ content. To run the example type the following command in the _src_ directory of your local release area (as long as you don't change any code in the local release area you will not have to compile): <verbatim> FWLiteLumiAccess inputFiles=root://eoscms//eos/cms/store/relval/CMSSW_5_3_11_patch6/RelValTTbar/GEN-SIM-RECO/START53_LV3_Feb20-v1/00000/72E794B2-A29A-E311-A464-02163E009E91.root </verbatim> %X% *Note:* As you can see we made use of the command line argument _inputFiles_ as described on [[SWGuideCommandLineParsing]]. Here we make use of a RECO input file from which we want to read the !LumiBlock information. We will now explain how this executable was compiled: To compile an individual executable as part of a CMSSW package the only thing you have to do is to make it known to the _scram_ build mechanism via a corresponding line in a given _BuildFile.xml_. We followed the general convention to keep individual executable in a dedicated _bin_ directory of the package. There you can find the corresponding [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/FWLite/bin/BuildFile.xml?revision=1.4&view=markup][BuildFile.xml]] and within this file the following lines: %SYNTAX{ syntax="cpp"}% <use name="root"/> <use name="boost"/> <use name="rootcintex"/> <use name="FWCore/FWLite"/> <use name="DataFormats/FWLite"/> <use name="DataFormats/Luminosity"/> <use name="FWCore/PythonParameterSet"/> <use name="CommonTools/Utils"/> <use name="PhysicsTools/FWLite"/> <use name="PhysicsTools/Utilities"/> <use name="PhysicsTools/SelectorUtils"/> <environment> <bin file="FWLiteLumiAccess.cc"></bin> <bin file="FWLiteHistograms.cc"></bin> <bin file="FWLiteWithPythonConfig.cc"></bin> <bin file="FWLiteWithSelectorUtils.cc"></bin> </environment> %ENDSYNTAX% %X% *Note:* As you can see the _BuildFile.xml_ contains nothing more but compiler directives in _xml_ style. The first lines indicate the libraries that are used by the executables located in the directory followed by a list of _.cc_ files to be picked up for compilation. Each source will be compiled into an individual executable with the name of the file (omitting the _.cc_ ending). You can invoke the executable from the shell prompt after refreshing the cash after compilation (using _cmsenv_ or better _rehash_), as shown above. The important line for this example is: %SYNTAX{ syntax="cpp"}% <bin file="FWLiteLumiAccess.cc"></bin> %ENDSYNTAX% In the _FWLiteLumiAccess.cc_ file you can find a basic skeleton to write an !FWLite executable and to access some extra information from the _edm::Event_ content: %SYNTAX{ syntax="cpp"}% int main(int argc, char ** argv){ // load framework libraries gSystem->Load( "libFWCoreFWLite" ); AutoLibraryLoader::enable(); // initialize command line parser optutl::CommandLineParser parser ("Analyze FWLite Histograms"); // parse arguments parser.parseArguments (argc, argv); std::vector<std::string> inputFiles_ = parser.stringVector("inputFiles"); for(unsigned int iFile=0; iFile<inputFiles_.size(); ++iFile){ // open input file (can be located on castor) TFile* inFile = TFile::Open(inputFiles_[iFile].c_str()); if( inFile ){ fwlite::Event ev(inFile); fwlite::Handle<LumiSummary> summary; std::cout << "----------- Accessing by event ----------------" << std::endl; // get run and luminosity blocks from events as well as associated // products. (This works for both ChainEvent and MultiChainEvent.) for(ev.toBegin(); !ev.atEnd(); ++ev){ // get the Luminosity block ID from the event std::cout << " Luminosity ID " << ev.getLuminosityBlock().id() << std::endl; // get the Run ID from the event std::cout <<" Run ID " << ev.getRun().id()<< std::endl; // get the Run ID from the luminosity block you got from the event std::cout << "Run via lumi " << ev.getLuminosityBlock().getRun().id() << std::endl; // get the integrated luminosity (or any luminosity product) from // the event summary.getByLabel(ev.getLuminosityBlock(),"lumiProducer"); } //... } } return 0; } %ENDSYNTAX% %X% *Note:* Each C++ executable starts with a _main_ function. We allow arguments to be passed on the to executable. The next lines enable the ROOT !AutoLibraryLoader, which should be enabled for each !FWLite executable. Next we make use of command line parsing as described on [[SWGuideCommandLineParsing]]. The command line option that we read in is the option _inputFiles_. In the following the input files are looped and the event within each input file is accessed and looped. Within the event loop you can find the corresponding lines how to access luminosity and run information from the _edm::Event_ content. You can find the implementation of this executable in the [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/FWLite/bin/FWLiteLumiAccess.cc?revision=1.1&view=markup][FWLiteLumiAccess.cc]] file in the _bin_ directory of the package. #ExampleTwo ---++ 3.5.3.4. Example 2: Plotting histograms The second example shows how to book and fill histograms from objects collections in the event. To run the example type the following command in the _src_ directory of your local release area (again this is possible without compiling): <verbatim> FWLiteHistograms inputFiles=root://eoscms//eos/cms/store/relval/CMSSW_5_3_11_patch6/RelValTTbar/GEN-SIM-RECO/START53_LV3_Feb20-v1/00000/72E794B2-A29A-E311-A464-02163E009E91.root outputFile=analyzeFWLite.root maxEvents=-1 outputEvery=20 </verbatim> The corresponding line for compilation in the _BuildFile.xml_ is the following: %SYNTAX{ syntax="cpp"}% <bin file="FWLiteLumiHistograms.cc"></bin> %ENDSYNTAX% %X% *Note:* In this example more command line options are used: * _inputFiles_: to pass on a vector of input file paths. * _outputFile_: to pass an output file name. * _maxEvents_: to pass on the maximal number of events to loop. * _outputEvery_: to indicate after how many events a report should be sent to the prompt. You can find the read out of these options in the _main_ function of the _FWLiteHistograms.cc_ file: %SYNTAX{ syntax="cpp"}% // ... // initialize command line parser optutl::CommandLineParser parser ("Analyze FWLite Histograms"); // set defaults parser.integerValue ("maxEvents" ) = 1000; parser.integerValue ("outputEvery") = 10; parser.stringValue ("outputFile" ) = "analyzeFWLiteHistograms.root"; // parse arguments parser.parseArguments (argc, argv); int maxEvents_ = parser.integerValue("maxEvents"); unsigned int outputEvery_ = parser.integerValue("outputEvery"); std::string outputFile_ = parser.stringValue("outputFile"); std::vector<std::string> inputFiles_ = parser.stringVector("inputFiles"); // book a set of histograms fwlite::TFileService fs = fwlite::TFileService(outputFile_.c_str()); TFileDirectory dir = fs.mkdir("analyzeBasicPat"); TH1F* muonPt_ = dir.make<TH1F>("muonPt" , "pt" , 100, 0., 300.); TH1F* muonEta_ = dir.make<TH1F>("muonEta" , "eta" , 100, -3., 3.); TH1F* muonPhi_ = dir.make<TH1F>("muonPhi" , "phi" , 100, -5., 5.); TH1F* mumuMass_= dir.make<TH1F>("mumuMass", "mass", 90, 30., 120.); // ... %ENDSYNTAX% %X% *Note:* As you see we provide default values for the options _maxEvents_, _outputEvery_ and _outputFile_. In the following section a set of histograms are booked making use of the !TFileService, which takes automatic care of handling the individual file systems of the different input and output files. To learn more about the !TFileService have a look to [[SWGuideTFileService]]. In the event loop we do some gymnastics for the event report and to stop the loop after _maxEvents_ have been processed. We access the collection of _reco::Muon_'s, loop the muons and fill the histograms. %SYNTAX{ syntax="cpp"}% for(ev.toBegin(); !ev.atEnd(); ++ev, ++ievt){ edm::EventBase const & event = ev; // break loop if maximal number of events is reached if(maxEvents_>0 ? ievt+1>maxEvents_ : false) break; // simple event counter if(outputEvery_!=0 ? (ievt>0 && ievt%outputEvery_==0) : false) std::cout << " processing event: " << ievt << std::endl; // Handle to the muon collection edm::Handle<std::vector<Muon> > muons; event.getByLabel(std::string("muons"), muons); // loop muon collection and fill histograms for(std::vector<Muon>::const_iterator mu1=muons->begin(); mu1!=muons->end(); ++mu1){ muonPt_ ->Fill( mu1->pt () ); muonEta_->Fill( mu1->eta() ); muonPhi_->Fill( mu1->phi() ); if( mu1->pt()>20 && fabs(mu1->eta())<2.1 ){ for(std::vector<Muon>::const_iterator mu2=muons->begin(); mu2!=muons->end(); ++mu2){ if(mu2>mu1){ // prevent double conting if( mu1->charge()*mu2->charge()<0 ){ // check only muon pairs of unequal charge if( mu2->pt()>20 && fabs(mu2->eta())<2.1 ){ mumuMass_->Fill( (mu1->p4()+mu2->p4()).mass() ); } } } } } } //... %ENDSYNTAX% You can find the implementation of this executable in the [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/FWLite/bin/FWLiteHistograms.cc?revision=1.4&view=markup][FWLiteLumiHistograms.cc]] file in the _bin_ directory of the package. #ExampleThree ---++ 3.5.3.5. Example 3: Using _python_ configuration You can get the same results using the _python_ configuration you are used to from the full framework. It is much more powerful in passing on an arbitrary number of parameters and is not restricted to a single command line. In case you are not familiar with the _python_ configuration language used within CMS have a look to [[WorkBookConfigFileIntro]]. To run the example type the following command in the _src_ directory of your local release area: <verbatim> FWLiteWithPythonConfig PhysicsTools/FWLite/test/fwliteWithPythonConfig_cfg.py </verbatim> The corresponding line in the _BuildFile.xml_ is the following: %SYNTAX{ syntax="cpp"}% <bin file="FWLiteWithPythonConfig.cc"></bin> %ENDSYNTAX% %X% *Note:* For this examples we completely replaced the command line parsing by the _python_ configuration file mechanism. You can find the [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/FWLite/test/fwliteWithPythonConfig_cfg.py?revision=1.6&view=markup][fwliteWithPythonConfig_cfg.py]] configuration file in the _test_ directory of the package. It contains the following parameters: %SYNTAX{ syntax="python"}% import FWCore.ParameterSet.Config as cms process = cms.PSet() process.fwliteInput = cms.PSet( fileNames = cms.vstring('rfio:///castor/cern.ch/cms/store/relval/CMSSW_4_1_3/RelValTTbar/GEN-SIM-RECO/START311_V2-v1/0037/648B6AA5-C751-E011-8208-001A928116C6.root'), ## mandatory maxEvents = cms.int32(-1), ## optional outputEvery = cms.uint32(10), ## optional ) process.fwliteOutput = cms.PSet( fileName = cms.string('analyzeFWLiteHistograms.root'), ## mandatory ) process.muonAnalyzer = cms.PSet( ## input specific for this analyzer muons = cms.InputTag('muons') ) %ENDSYNTAX% You can find the readout of the configuration file in the _main_ function of the _FWLiteWithPythonConfig.cc_ file: %SYNTAX{ syntax="cpp"}% // ... // parse arguments if ( argc < 2 ) { std::cout << "Usage : " << argv[0] << " [parameters.py]" << std::endl; return 0; } if( !edm::readPSetsFrom(argv[1])->existsAs<edm::ParameterSet>("process") ){ std::cout << " ERROR: ParametersSet 'process' is missing in your configuration file" << std::endl; exit(0); } // get the python configuration const edm::ParameterSet& process = edm::readPSetsFrom(argv[1])->getParameter<edm::ParameterSet>("process"); fwlite::InputSource inputHandler_(process); fwlite::OutputFiles outputHandler_(process); // now get each parameter const edm::ParameterSet& ana = process.getParameter<edm::ParameterSet>("muonAnalyzer"); edm::InputTag muons_( ana.getParameter<edm::InputTag>("muons") ); // book a set of histograms fwlite::TFileService fs = fwlite::TFileService(outputHandler_.file().c_str()); TFileDirectory dir = fs.mkdir("analyzeBasicPat"); TH1F* muonPt_ = dir.make<TH1F>("muonPt" , "pt" , 100, 0., 300.); TH1F* muonEta_ = dir.make<TH1F>("muonEta" , "eta" , 100, -3., 3.); TH1F* muonPhi_ = dir.make<TH1F>("muonPhi" , "phi" , 100, -5., 5.); TH1F* mumuMass_= dir.make<TH1F>("mumuMass", "mass", 90, 30., 120.); // ... %ENDSYNTAX% %X% *Note:* The first part just hands over the single argument, the path to the configuration file. This path is passed on to the _PythonProcessDesc_ constructor from which the _edm::ParameterSet_ is derived. The parameters are then read out equivalent to the full framework case. In addition to the parameters in [[#ExampleThree][Example 3]] the collection label for the muon collection is also treated as a parameter. You can find the implementation of this executable in the [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/FWLite/bin/FWLiteWithPythonConfig.cc?revision=1.4&view=markup][FWLiteLumiWithPythonConfig.cc]] file in the _bin_ directory of the package. #ExampleFour ---++ 3.5.3.6. Example 4: Using event selectors In this example we will introduce you to some more advanced features of the [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/CMS.PhysicsTools/SelectorUtils/][SelectorUtils]] package. We will make use of an !EventSelector to apply event selections, rather than doing the selection in the main event loop. This will allow to keep track of the statistics of the event selection. More details about Selectors can be found on [[SWGuidePATSelectors]]. This particular example will create a simple W selector that will select events with muons with pt>20 !GeV, and MET>20 !GeV (using PAT the MET will per default be type1 and muon corrected calorimeter MET). To run the example type the following command in the _src_ directory of your local release area: <verbatim> FWLiteWithSelectorUtils PhysicsTools/FWLite/test/fwliteWithSelectorUtils_cfg.py processing event: 10 ... 0 : Muon Pt 22 1 : MET 86 </verbatim> The last lines correspond to the number of events that have passed the muon pt, and MET cut, respectively. This can be made as complicated as you wish and automatically keeps track of your cut flow. %X% *Note:* This example is an extension of [[#ExampleThree][Example 3]]. The configuration file has therefore been slightly modified: %SYNTAX{ syntax="python"}% import FWCore.ParameterSet.Config as cms process = cms.PSet() process.fwliteInput = cms.PSet( fileNames = cms.vstring('rfio:///castor/cern.ch/cms/store/relval/CMSSW_4_1_3/RelValTTbar/GEN-SIM-RECO/START311_V2-v1/0037/648B6AA5-C751-E011-8208-001A928116C6.root'), ## mandatory maxEvents = cms.int32(-1), ## optional outputEvery = cms.uint32(10), ## optional ) process.fwliteOutput = cms.PSet( fileName = cms.string('analyzeFWLiteHistograms.root'), ## mandatory ) process.selection = cms.PSet( muonSrc = cms.InputTag('muons'), metSrc = cms.InputTag('metJESCorAK5CaloJetMuons'), muonPtMin = cms.double(20.0), metMin = cms.double(20.0), #cutsToIgnore = cms.vstring('MET') ) %ENDSYNTAX% %X% *Note:* The additional _edm::ParameterSet_ _selection_ is passed on to the W boson selector in the implementation of the executable: %SYNTAX{ syntax="cpp"}% // get the python configuration const edm::ParameterSet& process = edm::readPSetsFrom(argv[1])->getParameter<edm::ParameterSet>("process"); fwlite::InputSource inputHandler_(process); fwlite::OutputFiles outputHandler_(process); // initialize the W selector edm::ParameterSet selection = process.getParameter<edm::ParameterSet>("selection"); WSelector wSelector( selection ); pat::strbitset wSelectorReturns = wSelector.getBitTemplate(); // book a set of histograms fwlite::TFileService fs = fwlite::TFileService(outputHandler_.file().c_str()); TFileDirectory theDir = fs.mkdir("analyzeBasicPat"); TH1F* muonPt_ = theDir.make<TH1F>("muonPt", "pt", 100, 0.,300.); TH1F* muonEta_ = theDir.make<TH1F>("muonEta","eta", 100, -3., 3.); TH1F* muonPhi_ = theDir.make<TH1F>("muonPhi","phi", 100, -5., 5.); %ENDSYNTAX% The definition of the Selector can be found as an own class in the [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/FWLite/interface/WSelector.h?revision=1.1&view=markup][WSelector.h]] file in the _interface_ directory of the package. The class is derived from the !EventSelector base class of the !SelectorUtils package: %SYNTAX{ syntax="cpp"}% class WSelector : public EventSelector { public: /// constructor WSelector(edm::ParameterSet const& params) : muonSrc_(params.getParameter<edm::InputTag>("muonSrc")), metSrc_ (params.getParameter<edm::InputTag>("metSrc")) { double muonPtMin = params.getParameter<double>("muonPtMin"); double metMin = params.getParameter<double>("metMin"); push_back("Muon Pt", muonPtMin ); push_back("MET" , metMin ); set("Muon Pt"); set("MET"); wMuon_ = 0; met_ = 0; if ( params.exists("cutsToIgnore") ){ setIgnoredCuts( params.getParameter<std::vector<std::string> >("cutsToIgnore") ); } retInternal_ = getBitTemplate(); } /// destructor virtual ~WSelector() {} /// return muon candidate of W boson pat::Muon const& wMuon() const { return *wMuon_;} /// return MET of W boson pat::MET const& met() const { return *met_; } /// here is where the selection occurs virtual bool operator()( edm::EventBase const & event, pat::strbitset & ret){ ret.set(false); // Handle to the muon collection edm::Handle<std::vector<pat::Muon> > muons; // Handle to the MET collection edm::Handle<std::vector<pat::MET> > met; // get the objects from the event bool gotMuons = event.getByLabel(muonSrc_, muons); bool gotMET = event.getByLabel(metSrc_, met ); // get the MET, require to be > minimum if( gotMET ){ met_ = &met->at(0); if( met_->pt() > cut("MET", double()) || ignoreCut("MET") ) passCut(ret, "MET"); } // get the highest pt muon, require to have pt > minimum if( gotMuons ){ if( !ignoreCut("Muon Pt") ){ if( muons->size() > 0 ){ wMuon_ = &muons->at(0); if( wMuon_->pt() > cut("Muon Pt", double()) || ignoreCut("Muon Pt") ) passCut(ret, "Muon Pt"); } } else{ passCut( ret, "Muon Pt"); } } setIgnored(ret); return (bool)ret; } protected: /// muon input edm::InputTag muonSrc_; /// met input edm::InputTag metSrc_; /// muon candidate from W boson pat::Muon const* wMuon_; /// MET from W boson pat::MET const* met_; }; %ENDSYNTAX% The selection is applied in the following lines in the _main_ function of the executable code in the _FWLiteWithSelectorUtils.cc_ file: %SYNTAX{ syntax="cpp"}% if ( wSelector(event, wSelectorReturns ) ) { pat::Muon const & wMuon = wSelector.wMuon(); muonPt_ ->Fill( wMuon.pt() ); muonEta_->Fill( wMuon.eta() ); muonPhi_->Fill( wMuon.phi() ); } %ENDSYNTAX% As a feature of the base class you can switch off all parts of the selection in our example by uncommenting the following line in the configuration file (indicating the corresponding selection step): %SYNTAX{ syntax="python"}% cutsToIgnore = cms.vstring('MET') # <<<----- Uncomment this line %ENDSYNTAX% This configuration parameter is picked up in these lines in the executable code: %SYNTAX{ syntax="cpp"}% if ( params.exists("cutsToIgnore") ) setIgnoredCuts( params.getParameter<std::vector<std::string> >("cutsToIgnore") ); %ENDSYNTAX% %X% *Note:* In general the Selector works with the old PAT feature of =strbitset=. You can operate it completely without this feature though, by changing the argument of the if statement in the _main_ function of the code from =if ( wSelector(event, wSelectorReturns ) )= to =if ( wSelector(event) )= and adding the following hook to the constructor of your selector: %SYNTAX{ syntax="cpp"}% retInternal_ = getBitTemplate(); %ENDSYNTAX% %X% *Note:* Recently the Selectors have been speeded up in CPU performance by introducing selection index cashing. By un/commenting the _.h_ files according to the following lines in the _FWLiteWithSelectorUtils.cc_ file: %SYNTAX{ syntax="cpp"}% //#include "PhysicsTools/FWLite/interface/WSelector.h" #include "PhysicsTools/FWLite/interface/WSelectorFast.h" %ENDSYNTAX% you can see the effect (don't forget to recompile and to refresh the cash of your shell). You can have a look into the [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/FWLite/interface/WSelectorFast.h?revision=1.1&view=markup][WSelectorFast.h]] file in the _interface_ directory of the package to check the differences to the common _WSelector.h_ file in the same directory. You can find the implementation of this executable in the [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/FWLite/bin/FWLiteWithSelectorUtils.cc?revision=1.2&view=markup][FWLiteLumiWithSelectorUtils.cc]] file in the _bin_ directory of the package. You can find a more elaborate example of a V+Jets selector on [[CMS.VplusJetsSelectors]]. #ExampleFive ---++ 3.5.3.7 Example 5:Using FWLite and full framework in parallel In this example we will show you how to write your analysis code that can be used both in !FWLite and full framework following only a few very simple rules. It makes use of the [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/UtilAlgos/interface/BasicAnalyzer.h?revision=1.2&view=markup][BasicAnalyzer]] class, a powerful tool of the [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/UtilAlgos/][UtilAlgos]] package. You can concentrate on the actual analysis code and with less than 10 lines will be able to transform it either into a !FWLite executable as described above or into a full framework !EDAnalyzer. For the 10 extra lines you gain that you don't have to care about the !FWLite event loop or any _python_ configuration parameter parsing any more in !FWLite case, which is taken care for you. You can combine this kind of programming style with any examples and !FWLite features shown on this page. *This is the way of doing an analysis as recommended by the AT (Analysis Tools) group*. The example given here is equivalent to [[#Exmplethree][Example 3]]. To run it type the following command in the _src_ directory of your local release area: <verbatim> FWLiteWithBasicAnalyzer PhysicsTools/FWLite/test/fwliteWithPythonConfig_cfg.py </verbatim> %X% *Note:* As you see it also makes use of the same configuration file as [[#ExampleThree][Example 3]]. The example though originates from the _PhysicsTools/UtilAlgos_ package. Having a look into the [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/UtilAlgos/bin/FWLiteWithBasicAnalyzer.cc?revision=1.2&view=markup&pathrev=V08-02-09-01][FWLiteWithBasicAnalyzer.cc]] file there, for the implementation of the executable you will recognise that it is significantly shorter: %SYNTAX{ syntax="cpp"}% int main(int argc, char* argv[]) { // load framework libraries gSystem->Load( "libFWCoreFWLite" ); AutoLibraryLoader::enable(); // only allow one argument for this simple example which should be the // the python cfg file if ( argc < 2 ) { std::cout << "Usage : " << argv[0] << " [parameters.py]" << std::endl; return 0; } if( !edm::readPSetsFrom(argv[1])->existsAs<edm::ParameterSet>("process") ){ std::cout << " ERROR: ParametersSet 'plot' is missing in your configuration file" << std::endl; exit(0); } WrappedFWLiteMuonAnalyzer ana(edm::readPSetsFrom(argv[1])->getParameter<edm::ParameterSet>("process"), std::string("muonAnalyzer"), std::string("analyzeBasicPat")); ana.beginJob(); ana.analyze(); ana.endJob(); return 0; } %ENDSYNTAX% %X% *Note:* What remains is the parameter check to read in the _python_ configuration file. The _edm::ParameterSet_ is handed over to the _WrappedFWLiteAnalyzer_ object, which is treated in maximal analogy to an !EDAnalyzer in the following. This object has been declared by a simmple template expansion in the first lines: %SYNTAX{ syntax="cpp"}% #include "PhysicsTools/FWLite/interface/BasicMuonAnalyzer.h" #include "PhysicsTools/UtilAlgos/interface/FWLiteAnalyzerWrapper.h" typedef fwlite::AnalyzerWrapper<BasicMuonAnalyzer> WrappedFWLiteMuonAnalyzer; %ENDSYNTAX% The _FWLiteAnalyzerWrapper.h_ is just a simple tool. You can use it as a black box if you like or have a short glimpse into the [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/UtilAlgos/interface/FWLiteAnalyzerWrapper.h?revision=1.6&view=markup][implementation]] in the _UtilAlgos_ package if you like. E.g. you will find back the event loop there that you know from [[#ExampleThree][Example 3]], which is already implemented there for you so that you don't have to programm it over and over again, for each new executable that you plan to write. The key element that drives the analysis is the [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/FWLite/interface/BasicMuonAnalyzer.h?revision=1.2&view=markup][BasicMuonAnalyzer]] class, which is defined in the _interface_ directory of the package: %SYNTAX{ syntax="cpp"}% class BasicMuonAnalyzer : public edm::BasicAnalyzer { public: /// default constructor BasicMuonAnalyzer(const edm::ParameterSet& cfg, TFileDirectory& fs); /// default destructor virtual ~BasicMuonAnalyzer(){}; /// everything that needs to be done before the event loop void beginJob(){}; /// everything that needs to be done after the event loop void endJob(){}; /// everything that needs to be done during the event loop void analyze(const edm::EventBase& event); private: /// input tag for mouns edm::InputTag muons_; /// histograms std::map<std::string, TH1*> hists_; }; %ENDSYNTAX% %X% *Note:* Those already familiar with the structure of !EDAnalyzer's will immediately recognise the similarities. The class derives from the _BasicAnalyzer_ class, which is an abstract base class. It has a _beginJob_, _endJob_ and an _analyze_ function in analogy to the !EDAnalyzer, which is a requirement of the base class. In addition we added a _std__map_ for histogramming and an input tag for a muon collection. You can find the implementation in the [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/FWLite/src/BasicMuonAnalyzer.cc?revision=1.3&view=markup][BasicMuonAnalyzer.cc]] file in the _src_ directory of the package: %SYNTAX{ syntax="cpp"}% /// default constructor BasicMuonAnalyzer::BasicMuonAnalyzer(const edm::ParameterSet& cfg, TFileDirectory& fs): edm::BasicAnalyzer::BasicAnalyzer(cfg, fs), muons_(cfg.getParameter<edm::InputTag>("muons")) { hists_["muonPt" ] = fs.make<TH1F>("muonPt" , "pt" , 100, 0., 300.); hists_["muonEta" ] = fs.make<TH1F>("muonEta" , "eta" , 100, -3., 3.); hists_["muonPhi" ] = fs.make<TH1F>("muonPhi" , "phi" , 100, -5., 5.); hists_["mumuMass"] = fs.make<TH1F>("mumuMass", "mass", 90, 30., 120.); } /// everything that needs to be done during the event loop void BasicMuonAnalyzer::analyze(const edm::EventBase& event) { // define what muon you are using; this is necessary as FWLite is not // capable of reading edm::Views using reco::Muon; // Handle to the muon collection edm::Handle<std::vector<Muon> > muons; event.getByLabel(muons_, muons); // loop muon collection and fill histograms for(std::vector<Muon>::const_iterator mu1=muons->begin(); mu1!=muons->end(); ++mu1){ hists_["muonPt" ]->Fill( mu1->pt () ); hists_["muonEta"]->Fill( mu1->eta() ); hists_["muonPhi"]->Fill( mu1->phi() ); if( mu1->pt()>20 && fabs(mu1->eta())<2.1 ){ for(std::vector<Muon>::const_iterator mu2=muons->begin(); mu2!=muons->end(); ++mu2){ if(mu2>mu1){ // prevent double conting if( mu1->charge()*mu2->charge()<0 ){ // check only muon pairs of unequal charge if( mu2->pt()>20 && fabs(mu2->eta())<2.1 ){ hists_["mumuMass"]->Fill( (mu1->p4()+mu2->p4()).mass() ); } } } } } } } %ENDSYNTAX% %X% *Note:* You find the histogram booking in the constructor and the analysis implementation in the _analyze_ function of the class. It is not the topic of this chapter but you can transform this very code into !EDAnalyzer by a few lines like this: %SYNTAX{ syntax="cpp"}% #include "PhysicsTools/PatExamples/interface/BasicMuonAnalyzer.h" #include "PhysicsTools/UtilAlgos/interface/EDAnalyzerWrapper.h" typedef edm::AnalyzerWrapper<BasicMuonAnalyzer> WrappedEDMuonAnalyzer; #include "FWCore/Framework/interface/MakerMacros.h" DEFINE_FWK_MODULE(WrappedEDMuonAnalyzer); %ENDSYNTAX% You can indeed find such an plugin definition at the end of the [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/UtilAlgos/plugins/modules.cc?revision=1.11&view=markup&pathrev=V08-02-09-01][modules.cc]] file in the _plugins_ directory of the _PhysicsTool/UtilAlgos_ package. Try to run the plugin: <PRE> addpkg PhysicsTools/UtilAlgos V08-02-09-01 scram b -j 4 cmsRun PhysicsTools/UtilAlgos/test/cmsswWithPythonConfig_cfg.py </PRE> You will get the exact same result as with the FWLite executable having used the exact same class _BasicMuonAnalyzer_. %X% *Note:* these lines imply that you have chaecked out the _PhysicsTools/UtilAlgos_ package with a tag larger or equa then _V08-02-09-01_ <!-- THIS EXAMPLE CURRENTLY IS NOT WORKING - IT TOOK IT OUT THEREFORE UNTIL WE HAVE A PROPER SET OF INPUT FILES AGAIN (RW). ---++ Example 4: Realistic Example With First Data (%GREEN%Updated to 38x!%ENDCOLOR%) This example will build upon the technology developed in the previous ones to create a full-functional analysis on first data and minbias MC. For further details on the events and event selections that follow, please see the following link: * https://twiki.cern.ch/twiki/bin/viewauth/CMS/Collisions2010Analysis It will first be necessary to create a new PAT-tuple of the 7 TeV JetMETTau Primary Dataset data: <verbatim> cmsRun PhysicsTools/PatExamples/test/patTuple_data_cfg.py </verbatim> We can then analyze the events using the analysis macro [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/PatExamples/bin/PatBasicFWLiteJetAnalyzer_Selector.cc?revision=1.7&view=markup][here]]. The configuration to run this example is found [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/PhysicsTools/PatExamples/bin/PatBasicFWLiteJetAnalyzer_Selector_cfg.py?revision=1.3&view=markup][here]]. We first need to get a good run/lumi list in the "JSON" format from the PVT group. <verbatim> wget https://cms-service-dqm.web.cern.ch/cms-service-dqm/CAF/certification/Collisions10/7TeV/DCSOnly/DCSTRONLY_132440-140388 </verbatim> You should have a JSON-formatted file containing the run/lumi pairs with the DCS bit "on" (i.e. stable beams, taking data). Then we need to look at an example of how to read in this format in FWLite. The full details are in SWGuideGoodRunJSON. <verbatim> PatBasicFWLiteJetAnalyzer_Selector PatBasicFWLiteJetAnalyzer_Selector_cfg.py </verbatim> This will perform a dijet selection on the events in question, and plot some jet ID variables. You should see this output: <verbatim> Hello from PatBasicFWLiteJetAnalyzer_Selector! Getting parameters Making RunLumiSelector setting up TFileService Setting up chain event Booking histograms Making functors Instantiated PFJetIDSelectionFunctor Instantiated PFJetIDSelectionFunctor About to begin looping Processing run 140124, lumi 511, event 451801229 Processing run 140124, lumi 511, event 452007006 Processing run 140124, lumi 511, event 452507663 Processing run 140124, lumi 511, event 451938065 Processing run 140124, lumi 511, event 452451106 Processing run 140124, lumi 511, event 452179692 Processing run 140124, lumi 512, event 453339053 Processing run 140124, lumi 512, event 452862359 Processing run 140124, lumi 512, event 453332856 Processing run 140124, lumi 512, event 452840754 Calo jet selection 0 : Calo Cuts 953 1 : Calo Kin Cuts 847 2 : Calo Delta Phi 720 3 : Calo Jet ID 712 4 : PF Cuts off 5 : PF Kin Cuts off 6 : PF Delta Phi off 7 : PF Jet ID off PF jet selection 0 : Calo Cuts off 1 : Calo Kin Cuts off 2 : Calo Delta Phi off 3 : Calo Jet ID off 4 : PF Cuts 953 5 : PF Kin Cuts 834 6 : PF Delta Phi 745 7 : PF Jet ID 742 </verbatim> There should be histograms in the file "jetPlots.root". *Congratulations! You're commissioning!* --> #AppenDix ---++ Appendix: Using DB Information in !FWLite In this appendix we explain how to access data base information in !FWLite: we will first need to create an FWLite-readable ROOT file that will "cache" the payloads from the Conditions Database (=CondDB=). As an example we choose B-Tag information. The first part will access the database, and dump the payloads to a ROOT file: <verbatim> cd RecoBTag/PerformanceDB/test cmsRun testFWLite_Writer_cfg.py </verbatim> It's obvious that for this operation you to be logged in to _lxplus_ or somewhere else with apropriate DB connection. You can find the _python_ configuration file that we used [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/RecoBTag/PerformanceDB/test/testFWLite_Writer_cfg.py?revision=1.2&view=markup][here]]. We will go through it step by step. The following lines connect to the database and accesses the appropriate payloads: %SYNTAX{ syntax="python"}% process.load("CondCore.DBCommon.CondDBCommon_cfi") process.load ("RecoBTag.PerformanceDB.PoolBTagPerformanceDB100426") process.load ("RecoBTag.PerformanceDB.BTagPerformanceDB100426") process.PoolDBESSource.connect = 'frontier://FrontierProd/CMS_COND_31X_PHYSICSTOOLS' %ENDSYNTAX% The specific records you want to cache will be specified with the "toGet" method: %SYNTAX{ syntax="python"}% process.PoolDBESSource.toGet = cms.VPSet( cms.PSet( record = cms.string('PerformanceWPRecord'), tag = cms.string('BTagPTRELSSVMwp_v1_offline'), label = cms.untracked.string('BTagPTRELSSVMwp_v1_offline') ), cms.PSet( record = cms.string('PerformancePayloadRecord'), tag = cms.string('BTagPTRELSSVMtable_v1_offline'), label = cms.untracked.string('BTagPTRELSSVMtable_v1_offline') )) %ENDSYNTAX% The actual module that dumps the payloads is specified here: %SYNTAX{ syntax="python"}% process.myrootwriter = cms.EDAnalyzer("BTagPerformaceRootProducerFromSQLITE", name = cms.string('PTRELSSVM'), index = cms.uint32(1001) ) %ENDSYNTAX% The root file containing the cached payloads will be accessed within FWLite as shown below: <verbatim> TestPerformanceFWLite_ES </verbatim> The source code of this file is located [[http://cmssw.cvs.cern.ch/cgi-bin/cmssw.cgi/CMSSW/RecoBTag/PerformanceDB/bin/TestPerformanceFWLite_ES.cc?revision=1.2&view=markup][here]]. To access the dumped DB information, the syntax is: %SYNTAX{ syntax="cpp"}% fwlite::ESHandle< PerformancePayload > plHandle; es.get(testRecID).get(plHandle,"PTRELSSVM"); fwlite::ESHandle< PerformanceWorkingPoint > wpHandle; es.get(testRecID).get(wpHandle,"PTRELSSVM"); if ( plHandle.isValid() && wpHandle.isValid() ) { BtagPerformance perf(*plHandle, *wpHandle); %ENDSYNTAX% From there you can access the payloads as you would in the full framework: %SYNTAX{ syntax="cpp"}% // check beff, berr for eta=.6, et=55; BinningPointByMap p; std::cout <<" test eta=0.6, et=55"<<std::endl; p.insert(BinningVariables::JetEta,0.6); p.insert(BinningVariables::JetEt,55); std::cout <<" nbeff/nberr ?"<<perf.isResultOk(PerformanceResult::BTAGNBEFF,p)<<"/"<<perf.isResultOk(PerformanceResult::BTAGNBERR,p)<<std::endl; std::cout <<" beff/berr ?"<<perf.isResultOk(PerformanceResult::BTAGBEFF,p)<<"/"<<perf.isResultOk(PerformanceResult::BTAGBERR,p)<<std::endl; std::cout <<" beff/berr ="<<perf.getResult(PerformanceResult::BTAGBEFF,p)<<"/"<<perf.getResult(PerformanceResult::BTAGBERR,p)<<std::endl; %ENDSYNTAX% #ReviewStatus ---++ Review status %TWISTY{mode="div" showlink="Show" hidelink="Hide" remember="on" showimgleft="%ICONURLPATH{toggleopen-small}%" hideimgleft="%ICONURLPATH{toggleclose-small}%"}% | *Reviewer/Editor and Date (copy from screen)* | *Comments* | | Main.RogerWolf - 09 Nov 2010 | Revision for Nov Tutorial | Responsible: Main.RogerWolf %ENDTWISTY%
Attachments
Attachments
Topic attachments
I
Attachment
History
Action
Size
Date
Who
Comment
css
tutorial.css
r1
manage
0.2 K
2010-12-18 - 23:03
RogerWolf
Edit
|
Attach
|
Watch
|
P
rint version
|
H
istory
:
r44
<
r43
<
r42
<
r41
<
r40
|
B
acklinks
|
V
iew topic
|
Raw edit
|
More topic actions...
Topic revision: r43 - 2014-06-25
-
FelixHoehle
Log In
CMSPublic
CMSPublic Web
CMSPrivate Web
Create New Topic
Index
Search
Changes
Notifications
Statistics
Preferences
Offline Workbook
Glossary/Index
Summary of Changes
Site Map
Print as PDF
For Contributors
User Support
Offline SW Guide
Reference Manual
Online WkBk
ESSENTIALS
Preface
0.1 Acknowledgements
0.2 Using the Workbook
0.3 Goals & Detector
1. Accounts & Registration
1.1 Introduction
1.2 Get an Account
1.3 Set Computing Env
1.4 CMS Computing
1.5 Resources/Help
1.6 First visit to CERN
2. Basics of Offline
2.1 Introduction
2.2 Computing Model
2.3 CMSSW Framework
3. Getting Started with Data Analysis
3.1 Overview
3.2 Which release
3.3 Exploring Data
-3.3.1 Copy and Merge Files
-3.3.2 EDM Tools
3.4 Fireworks Visualization
-3.4.1 User Guide
-3.4.2 Full Framework
-3.4.3 Geometry
-3.4.4 Particle Flow
-3.4.5 Projections
-3.4.6 Problems
-3.4.7 Archive
3.5 FW Lite
-3.5.1 Getting Started
-3.5.2 Event loop
-3.5.3 Examples
-3.5.4 FW Lite in Python
4. CMSSW in Data Analysis
4.1 Introduction
-4.1.1 More on CMSSW
-4.1.2 Write Analyzer
-4.1.3 Intro Config Files
-4.1.4 Config Editor
4.2 PAT
-4.2.1 PAT Data Formats
-4.2.2 PAT Workflow
-4.2.3 PAT Config
-4.2.4 PAT Tutorial
--4.2.4.1 PAT Docs
--4.2.4.2 Create PAT Tuple
--4.2.4.3 PAT Tuple on Grid
--4.2.4.4 Analyze PAT Cands
-4.2.5 PAT on Data
-4.2.6 PAT Glossary
4.3 Candidate Utilities
4.4 Gen Evts in AOD
4.5 MC Truth Matching
4.6 Access Trigger Info
4.7 MiniAOD Data-Tier
4.8 NanoAOD Analysis Documentation
5. Distributed Data Analysis
5.1 Chapter Overview -- Getting Started
5.2 Grid Computing Context
5.3 Analysis Workflow
5.4 Locating Data
5.5 Data Quality Monitorin
5.6 Analysis with CRAB
5.6.1 CRAB Tutorial
5.7 Data analysis with CMS Connect
5.8 Monitoring with CMS Dashboard
5.9 The Role of T2
5.10 Transfering Data
5.11 Data Organization Explained
5.12 Processing by Physics Groups
5.13 cmssh tutorial
5.14 Using Xrootd Service for Remote Data Accessing
Appendices
A.1 Remote Site Info
A.2 Troubleshooting
A.3 Linux Basics
A.4 ROOT Basics
A.5 SCRAM Intro
A.6 BuildFile Intro
A.7 C++ Basics
ADVANCED TOPICS
6. Event Gen & Sim
6.1 Gen-Sim-Dig Intro
6.2 Generation
6.3 Simulation&Digi.
6.4 Reconstruction
6.4 Fast Simulation
7. Physics Object Analysis Examples
7.1 Introduction
7.2 Track Analysis
7.3 Vertex Reconstruction
7.4 Electron Analysis
7.5 Photon Analysis
7.6 Jet Analysis
7.7 MET Analysis
7.8 Global Muon Reco
7.9 B Tagging
7.10 Tau PF Tagging
7.11 Particle Flow
8. Physics Group Analysis Examples
8.1 B Physics MiniAOD
8.2 Electroweak PAT
8.3 Exotica PAT
8.4 Higgs PAT
8.5 QCD PAT
8.6 Top PAT
8.7 CMS Data Analysis Schools
8.8 CMS Physics Object Schools
9. Advanced Tools & Tasks
9.1 Introduction
9.2 EDM Utilities
9.3 EDM Containers
9.4 Common Data Types
9.5 Write EDM Producer
9.6 Pick Events
10. Software Infrastructure
10.1 Install Software
10.2 Develop Software
10.3 Code Optimization
For Contributors
0.4 Contributors' Guide
Page Template
Review for Printing
To Do List
Public webs
Public webs
ABATBEA
ACPP
ADCgroup
AEGIS
AfricaMap
AgileInfrastructure
ALICE
AliceEbyE
AliceSPD
AliceSSD
AliceTOF
AliFemto
ALPHA
ArdaGrid
ASACUSA
AthenaFCalTBAna
Atlas
AtlasLBNL
AXIALPET
CAE
CALICE
CDS
CENF
CERNSearch
CLIC
Cloud
CloudServices
CMS
Controls
CTA
CvmFS
DB
DefaultWeb
DESgroup
DPHEP
DM-LHC
DSSGroup
EGEE
EgeePtf
ELFms
EMI
ETICS
FIOgroup
FlukaTeam
Frontier
Gaudi
GeneratorServices
GuidesInfo
HardwareLabs
HCC
HEPIX
ILCBDSColl
ILCTPC
IMWG
Inspire
IPv6
IT
ItCommTeam
ITCoord
ITdeptTechForum
ITDRP
ITGT
ITSDC
LAr
LCG
LCGAAWorkbook
Leade
LHCAccess
LHCAtHome
LHCb
LHCgas
LHCONE
LHCOPN
LinuxSupport
Main
Medipix
Messaging
MPGD
NA49
NA61
NA62
NTOF
Openlab
PDBService
Persistency
PESgroup
Plugins
PSAccess
PSBUpgrade
R2Eproject
RCTF
RD42
RFCond12
RFLowLevel
ROXIE
Sandbox
SocialActivities
SPI
SRMDev
SSM
Student
SuperComputing
Support
SwfCatalogue
TMVA
TOTEM
TWiki
UNOSAT
Virtualization
VOBox
WITCH
XTCA
Cern Search
TWiki Search
Google Search
CMSPublic
All webs
Copyright &© 2008-2021 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
or Ideas, requests, problems regarding TWiki? use
Discourse
or
Send feedback