-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Storing Generator Filter Information in NanoAOD #34169
Merged
Merged
Changes from 1 commit
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
1eb6263
Add nanoAOD flat table producers to store generator filter informatio…
mzarucki 68d7a15
Apply code format
mzarucki a4a7f44
Update nanoAOD lumi flat table producers to support processing concur…
mzarucki 7ea752f
Merge branch 'master' into nanoAOD_genFilterEff_120X
mzarucki 27fcb91
Add genFilterTable to the NanoGen sequence
mzarucki File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
#include "PhysicsTools/NanoAOD/plugins/LumiOutputBranches.h" | ||
|
||
#include <iostream> | ||
|
||
namespace { | ||
std::string makeBranchName(const std::string &baseName, const std::string &leafName) { | ||
return baseName.empty() ? leafName : (leafName.empty() ? baseName : baseName + "_" + leafName); | ||
} | ||
} // namespace | ||
|
||
void LumiOutputBranches::defineBranchesFromFirstEvent(const nanoaod::FlatTable &tab) { | ||
m_baseName = tab.name(); | ||
for (size_t i = 0; i < tab.nColumns(); i++) { | ||
const std::string &var = tab.columnName(i); | ||
switch (tab.columnType(i)) { | ||
case nanoaod::FlatTable::ColumnType::Float: | ||
m_floatBranches.emplace_back(var, tab.columnDoc(i), "F"); | ||
break; | ||
case nanoaod::FlatTable::ColumnType::Int: | ||
m_intBranches.emplace_back(var, tab.columnDoc(i), "I"); | ||
break; | ||
case nanoaod::FlatTable::ColumnType::UInt8: | ||
m_uint8Branches.emplace_back(var, tab.columnDoc(i), "b"); | ||
break; | ||
case nanoaod::FlatTable::ColumnType::Bool: | ||
m_uint8Branches.emplace_back(var, tab.columnDoc(i), "O"); | ||
break; | ||
default: | ||
throw cms::Exception("LogicError", "Unsupported type"); | ||
} | ||
} | ||
} | ||
|
||
void LumiOutputBranches::branch(TTree &tree) { | ||
if (!m_singleton) { | ||
if (m_extension == IsExtension) { | ||
m_counterBranch = tree.FindBranch(("n" + m_baseName).c_str()); | ||
if (!m_counterBranch) { | ||
throw cms::Exception("LogicError", | ||
"Trying to save an extension table for " + m_baseName + | ||
" before having saved the corresponding main table\n"); | ||
} | ||
} else { | ||
if (tree.FindBranch(("n" + m_baseName).c_str()) != nullptr) { | ||
throw cms::Exception("LogicError", "Trying to save multiple main tables for " + m_baseName + "\n"); | ||
} | ||
m_counterBranch = tree.Branch(("n" + m_baseName).c_str(), &m_counter, ("n" + m_baseName + "/i").c_str()); | ||
m_counterBranch->SetTitle(m_doc.c_str()); | ||
} | ||
} | ||
std::string varsize = m_singleton ? "" : "[n" + m_baseName + "]"; | ||
for (std::vector<NamedBranchPtr> *branches : {&m_floatBranches, &m_intBranches, &m_uint8Branches}) { | ||
for (auto &pair : *branches) { | ||
std::string branchName = makeBranchName(m_baseName, pair.name); | ||
pair.branch = | ||
tree.Branch(branchName.c_str(), (void *)nullptr, (branchName + varsize + "/" + pair.rootTypeCode).c_str()); | ||
pair.branch->SetTitle(pair.title.c_str()); | ||
} | ||
} | ||
} | ||
|
||
void LumiOutputBranches::fill(const edm::LuminosityBlockForOutput &iLumi, TTree &tree, bool extensions) { | ||
if (m_extension != DontKnowYetIfMainOrExtension) { | ||
if (extensions != m_extension) | ||
return; // do nothing, wait to be called with the proper flag | ||
} | ||
|
||
edm::Handle<nanoaod::FlatTable> handle; | ||
iLumi.getByToken(m_token, handle); | ||
const nanoaod::FlatTable &tab = *handle; | ||
m_counter = tab.size(); | ||
m_singleton = tab.singleton(); | ||
if (!m_branchesBooked) { | ||
m_extension = tab.extension() ? IsExtension : IsMain; | ||
if (extensions != m_extension) | ||
return; // do nothing, wait to be called with the proper flag | ||
defineBranchesFromFirstEvent(tab); | ||
m_doc = tab.doc(); | ||
m_branchesBooked = true; | ||
branch(tree); | ||
} | ||
if (!m_singleton && m_extension == IsExtension) { | ||
if (m_counter != *reinterpret_cast<UInt_t *>(m_counterBranch->GetAddress())) { | ||
throw cms::Exception("LogicError", | ||
"Mismatch in number of entries between extension and main table for " + tab.name()); | ||
} | ||
} | ||
for (auto &pair : m_floatBranches) | ||
fillColumn<float>(pair, tab); | ||
for (auto &pair : m_intBranches) | ||
fillColumn<int>(pair, tab); | ||
for (auto &pair : m_uint8Branches) | ||
fillColumn<uint8_t>(pair, tab); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
#ifndef PhysicsTools_NanoAOD_LumiOutputBranches_h | ||
#define PhysicsTools_NanoAOD_LumiOutputBranches_h | ||
|
||
#include <string> | ||
#include <vector> | ||
#include <TTree.h> | ||
#include "FWCore/Framework/interface/LuminosityBlockForOutput.h" | ||
#include "DataFormats/NanoAOD/interface/FlatTable.h" | ||
#include "DataFormats/Provenance/interface/BranchDescription.h" | ||
#include "FWCore/Utilities/interface/EDGetToken.h" | ||
|
||
class LumiOutputBranches { | ||
public: | ||
LumiOutputBranches(const edm::BranchDescription *desc, const edm::EDGetToken &token) | ||
: m_token(token), m_extension(DontKnowYetIfMainOrExtension), m_branchesBooked(false) { | ||
if (desc->className() != "nanoaod::FlatTable") | ||
throw cms::Exception("Configuration", "NanoAODOutputModule can only write out nanoaod::FlatTable objects"); | ||
} | ||
|
||
void defineBranchesFromFirstEvent(const nanoaod::FlatTable &tab); | ||
void branch(TTree &tree); | ||
|
||
/// Fill the current table, if extensions == table.extension(). | ||
/// This parameter is used so that the fill is called first for non-extensions and then for extensions | ||
void fill(const edm::LuminosityBlockForOutput &iLumi, TTree &tree, bool extensions); | ||
|
||
private: | ||
edm::EDGetToken m_token; | ||
std::string m_baseName; | ||
bool m_singleton; | ||
enum { IsMain = 0, IsExtension = 1, DontKnowYetIfMainOrExtension = 2 } m_extension; | ||
std::string m_doc; | ||
UInt_t m_counter; | ||
struct NamedBranchPtr { | ||
std::string name, title, rootTypeCode; | ||
TBranch *branch; | ||
NamedBranchPtr(const std::string &aname, | ||
const std::string &atitle, | ||
const std::string &rootType, | ||
TBranch *branchptr = nullptr) | ||
: name(aname), title(atitle), rootTypeCode(rootType), branch(branchptr) {} | ||
}; | ||
TBranch *m_counterBranch; | ||
std::vector<NamedBranchPtr> m_floatBranches; | ||
std::vector<NamedBranchPtr> m_intBranches; | ||
std::vector<NamedBranchPtr> m_uint8Branches; | ||
bool m_branchesBooked; | ||
|
||
template <typename T> | ||
void fillColumn(NamedBranchPtr &pair, const nanoaod::FlatTable &tab) { | ||
int idx = tab.columnIndex(pair.name); | ||
if (idx == -1) | ||
throw cms::Exception("LogicError", "Missing column in input for " + m_baseName + "_" + pair.name); | ||
pair.branch->SetAddress(const_cast<T *>(&tab.columnData<T>(idx).front())); // SetAddress should take a const * ! | ||
} | ||
}; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this module (template) need to be
edm::one
? Could it beedm::stream
?If it needs to stay
edm::one
for some reason, please use alsoedm::LuminosityBlockCache
extension to tell the framework the the module can process events from multiple LuminosityBlocks concurrently.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dear @makortel,
At the time of development I tried to use the
edm::stream
(as in SimpleFlatTableProducerBase) guided by the FWMultithreadedFrameworkStreamModuleInterface Twiki however, this resulted in a series of compilation errors that I was not able to resolve. Usingedm::one
solved the issues.If you have any suggestions on how to make
edm::stream
work, I would be grateful.Best,
Mateusz
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What kind of compilation errors did you get?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first one is:
/afs/cern.ch/work/m/mzarucki/nanoAOD/CMSSW_12_0_0_pre3/src/PhysicsTools/NanoAOD/interface/SimpleFlatTableProducer.h:315:8: error: 'void SimpleFlatTableProducerBaseLumi<T, TProd>::endLuminosityBlockProduce(edm::LuminosityBlock&, const edm::EventSetup&) [with T = GenFilterInfo; TProd = GenFilterInfo]' marked 'final', but is not virtual
which can be solved by just removing the
final
specifier for theendLuminosityBlockProduce
method.A following compilation error is:
/cvmfs/cms.cern.ch/slc7_amd64_gcc900/cms/cmssw/CMSSW_12_0_0_pre3/src/FWCore/Framework/interface/stream/callAbilities.h:455:43: error: 'globalEndLuminosityBlockProduce' is not a member of 'LumiSingletonSimpleFlatTableProducer<GenFilterInfo>' 455 | T::globalEndLuminosityBlockProduce(Lumi, iES, iRC);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My bad, after further thought stream module type actually wouldn't help. I was thinking we could use the "streams" to work around the thread-unsafety of
StringObjectFunction
andStringCutObjectSelector
, but the LuminosityBlock transitions of stream modules are global (i.e. can occur concurrently).So the best way to support "processing Events from multiple LuminosityBlocks concurrently" would be to use the
edm::LuminosityBlockCache
extension. Since you don't really need the cache, you could declare it as e.g.edm::LuminosityBlockCache<int>
and inglobalBeginLuminosityBlock()
returnnullptr
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dear @makortel,
Therefore, is
edm:one
fine to use for this module?As suggested, I have added the
edm:LuminosityBlockCache
extension as follows:I have also added the
globalBeginLuminosityBlock
method which returnsnullptr
.Unfortunately, I get the following compilation errors:
Is there something obvious that I might be missing here?
Best regards,
Mateusz
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of
LuminosityBlockCache
requires overriding alsovoid SimpleFlatTableProducerBaseLumi::globalEndLuminosityBlock(edm::LuminosityBlock const&, edm::EventSetup const&) override {}
.(sorry for not mentioning it earlier)
https://twiki.cern.ch/twiki/bin/view/CMSPublic/FWMultithreadedFrameworkOneModuleInterface#edm_LuminosityBlockCacheT
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the clarification!
I have made the discussed updates to support processing events from multiple LuminosityBlocks concurrently in a4a7f44
I would be grateful if you could have a look whether this is what you were expecting.
Cheers,
Mateusz
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it looks good now. Thanks!