40#ifndef XAOD_STANDALONE
48#include <boost/core/demangle.hpp>
58#include <gtest/gtest.h>
114 else if (
columnName.find (
".") != std::string::npos)
115 throw std::runtime_error (
"branch name does not contain AuxDyn or Aux: " +
m_branchName);
128 throw std::runtime_error (
"branch name does not contain AuxDyn or Aux: " +
m_branchName);
135 throw std::runtime_error (
"failed to get branch: " +
m_branchName);
146 throw std::runtime_error (
"branch not connected: " +
m_branchName);
147 if (
m_branch->GetEntry (entry) <= 0)
148 throw std::runtime_error (
"failed to get entry " + std::to_string (entry) +
" for branch: " +
m_branchName);
150 throw std::runtime_error (
"got nullptr reading data for branch: " +
m_branchName);
163 return static_cast<float>(
m_branch->GetZipBytes()) /
m_branch->GetEntries();
170 return static_cast<float>(
m_branch->GetTotBytes()) /
m_branch->GetEntries();
179 return m_branch->GetListOfBaskets()->GetSize();
206 else if (
columnName.find (
".") != std::string::npos)
207 throw std::runtime_error (
"branch name does not contain AuxDyn or Aux: " +
m_branchName);
220 throw std::runtime_error (
"branch name does not contain AuxDyn or Aux: " +
m_branchName);
227 throw std::runtime_error (
"failed to get branch: " +
m_branchName);
236 std::span<const T>
getEntry (Long64_t entry, std::size_t size)
239 throw std::runtime_error (
"branch not connected: " +
m_branchName);
251 throw std::runtime_error (
"requested size exceeds buffer size for branch: " +
m_branchName);
255 if (size > 0 &&
m_branch->GetEntry (entry) <= 0)
256 throw std::runtime_error (
"failed to get entry " + std::to_string (entry) +
" for branch: " +
m_branchName);
257 return std::span<const T>(
m_dataVec.data(), size);
264 return static_cast<float>(
m_branch->GetZipBytes()) /
m_branch->GetEntries();
271 return static_cast<float>(
m_branch->GetTotBytes()) /
m_branch->GetEntries();
280 return m_branch->GetListOfBaskets()->GetSize();
308 col.columnIndex =
header.getColumnIndex (col.name);
325 std::array<ColumnarOffsetType, 2>
data = {0, 0};
332 virtual bool connect (TTree * , std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& , std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
363 result.name =
"EventCount(auto)";
386 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& , std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
388 auto iter = requestedColumns.find (
outputColumns.at(0).name);
389 if (iter == requestedColumns.end())
392 requestedColumns.erase (iter);
410 outData.push_back (branchData);
446 std::vector<ColumnarOffsetType>
offsets = {0};
459 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
461 auto iter = requestedColumns.find (
outputColumns.at(0).name);
462 if (iter == requestedColumns.end())
469 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
471 requestedColumns.erase (iter);
473 if (
auto offsetIter = offsetColumns.find (
outputColumns.at(1).name); offsetIter != offsetColumns.end())
479 if (iter != requestedColumns.end())
481 requestedColumns.erase (iter);
501 outData.insert (
outData.end(), branchData.begin(), branchData.end());
515 throw std::runtime_error (
"offset column not filled yet: " +
outputColumns.at(1).name);
517 throw std::runtime_error (
"offset column does not match: " +
outputColumns.at(1).name);
556 virtual bool connect (TTree * , std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
558 auto iter = requestedColumns.find (
outputColumns.at(0).name);
559 if (iter == requestedColumns.end())
565 const auto offsetName = iter->second.offsetName;
566 if (offsetName.empty())
567 throw std::runtime_error (
"missing offset column for: " +
outputColumns.at(0).name);
569 requestedColumns.erase (iter);
571 if (
auto offsetIter = offsetColumns.find (offsetName); offsetIter != offsetColumns.end())
574 throw std::runtime_error (
"missing offset column for: " +
outputColumns.at(0).name);
612 std::vector<ColumnarOffsetType>
offsets = {0};
625 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& , std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
627 auto iter = requestedColumns.find (
outputColumns.at(0).name);
628 if (iter == requestedColumns.end())
635 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
637 requestedColumns.erase (iter);
640 if (iter == requestedColumns.end())
642 requestedColumns.erase (iter);
660 for (
auto&
data : branchData)
702 std::vector<ColumnarOffsetType>
offsets = {0};
719 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
721 auto iter = requestedColumns.find (
outputColumns.at(0).name);
722 if (iter == requestedColumns.end())
729 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
731 if (iter->second.linkTargetNames.size() != 1)
732 throw std::runtime_error (
"expected exactly one link target name for: " +
outputColumns.at(0).name);
736 if (
auto offsetIter = offsetColumns.find (iter->second.linkTargetNames.at(0)); offsetIter != offsetColumns.end())
739 throw std::runtime_error (
"missing offset column: " + iter->second.linkTargetNames.at(0));
741 requestedColumns.erase (iter);
744 if (iter == requestedColumns.end())
746 requestedColumns.erase (iter);
765 throw std::runtime_error (
"target offset column not yet filled for: " +
outputColumns.at(0).name);
766 for (
auto&
data : branchData)
768 for (
auto& element :
data)
770 if (element.isDefault() || (element.key() == 0 && element.index() == 0))
783 throw std::runtime_error(
784 std::format(
"target key mismatch: {:x} != {:x} for {} with element index {}",
851 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& , std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
853 auto iter = requestedColumns.find (
outputColumns.at(0).name);
854 if (iter == requestedColumns.end())
861 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
863 requestedColumns.erase (iter);
866 if (iter == requestedColumns.end())
871 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(2).name);
873 requestedColumns.erase (iter);
876 if (iter == requestedColumns.end())
879 requestedColumns.erase (iter);
898 for (
auto& outerData : branchData)
900 for (
auto& innerData : outerData)
947 std::vector<ColumnarOffsetType>
offsets = {0};
964 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
966 auto iter = requestedColumns.find (
outputColumns.at(0).name);
967 if (iter == requestedColumns.end())
974 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
976 if (iter->second.linkTargetNames.size() != 1)
977 throw std::runtime_error (
"expected exactly one link target name for: " +
outputColumns.at(0).name);
981 if (
auto targetOffsetIter = offsetColumns.find (iter->second.linkTargetNames.at(0)); targetOffsetIter != offsetColumns.end())
984 throw std::runtime_error (
"missing offset column(vector-link): " + iter->second.linkTargetNames.at(0));
986 requestedColumns.erase (iter);
988 if (
auto offsetIter = offsetColumns.find (
outputColumns.at(1).name); offsetIter != offsetColumns.end())
994 if (iter != requestedColumns.end())
997 requestedColumns.erase (iter);
1013 const auto& branchData =
branchReader.getEntry (entry);
1017 throw std::runtime_error (
"target offset column not yet filled for: " +
outputColumns.at(0).name);
1018 for (
auto& element : branchData)
1020 if (element.isDefault() || (element.key() == 0 && element.index() == 0))
1033 throw std::runtime_error (
"target key mismatch: " + std::to_string (element.key()) +
" != " + std::to_string (
targetKey) +
" for " +
outputColumns.at(0).name);
1042 throw std::runtime_error (
"offset column not filled yet: " +
outputColumns.at(1).name);
1044 throw std::runtime_error (
"offset column does not match: " +
outputColumns.at(1).name);
1084 template<
typename T>
1110 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
1112 auto iter = requestedColumns.find (
outputColumns.at(0).name);
1113 if (iter == requestedColumns.end())
1122 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
1124 const auto& linkContainers = iter->second.linkTargetNames;
1125 for (
const auto&
container : linkContainers)
1130 throw std::runtime_error (
"no key known for link container: " +
container);
1131 if (
auto targetOffsetIter = offsetColumns.find (
container); targetOffsetIter != offsetColumns.end())
1134 throw std::runtime_error (
"missing offset column: " +
container);
1137 requestedColumns.erase (iter);
1139 if (
auto offsetIter = offsetColumns.find (
outputColumns.at(1).name); offsetIter != offsetColumns.end())
1145 if (iter != requestedColumns.end())
1148 requestedColumns.erase (iter);
1152 if (iter != requestedColumns.end())
1155 requestedColumns.erase (iter);
1172 auto branchDataKey =
branchReaderKey.getEntry (entry, branchDataSize);
1178 if (targetOffsetColumn->size() <=
offsets.size())
1179 throw std::runtime_error (
"target offset column not yet filled for: " +
outputColumns.at(0).name);
1183 if (branchDataIndex[
index] ==
static_cast<UInt_t
>(-1))
1190 keyIndex = std::distance(
targetKeys.begin(), keyIter);
1195 std::cout <<
"assume target key for " <<
outputColumns.at(0).name <<
" is " << std::hex << branchDataKey[
index] << std::dec << std::endl;
1196 }
else if (branchDataKey[
index] != 0)
1198 std::ostringstream
error;
1199 error <<
"target key mismatch: read " << std::hex << branchDataKey[
index];
1200 error <<
", expected one of";
1202 error <<
" " << key;
1204 throw std::runtime_error (std::move (
error).
str());
1212 auto targetOffset = targetOffsetColumn.at (
offsets.size()-1);
1214 linkIndex += targetOffset;
1215 if (linkIndex >= targetOffsetColumn.at(
offsets.size()))
1216 throw std::runtime_error (std::format (
"index out of range for link: {} >= {} (base index {})",
outputColumns.at(0).name, linkIndex, targetOffsetColumn.at(
offsets.size()), targetOffset));
1225 throw std::runtime_error (
"offset column not filled yet: " +
outputColumns.at(1).name);
1227 throw std::runtime_error (
"offset column does not match: " +
outputColumns.at(1).name);
1269 template<
typename T>
1286 std::unordered_map<SG::sgkey_t,std::unordered_set<std::string>>
unknownKeys;
1301 for (
auto& [key, forbiddenContainer] :
unknownKeys)
1303 std::cout <<
"unknown key: " << std::hex << key << std::dec <<
", allowed containers:";
1306 if (forbiddenContainer.find (
container) == forbiddenContainer.end())
1309 std::cout << std::endl;
1313 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& offsetColumns, std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
1315 auto iter = requestedColumns.find (
outputColumns.at(0).name);
1316 if (iter == requestedColumns.end())
1323 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
1325 if (
containers.empty() || iter->second.variantLinkKeyColumn.empty())
1326 throw std::runtime_error (
"no variant link containers for: " +
outputColumns.at(0).name);
1327 if (iter->second.variantLinkKeyColumn !=
outputColumns.at(2).name)
1328 throw std::runtime_error (
"variant link key column mismatch: " + iter->second.variantLinkKeyColumn +
" != " +
outputColumns.at(2).name);
1333 if (!offsetColumns.contains (
container))
1334 throw std::runtime_error (
"missing offset column(variant-link): " +
container);
1346 requestedColumns.erase (iter);
1349 if (iter != requestedColumns.end())
1352 requestedColumns.erase (iter);
1356 if (iter != requestedColumns.end())
1359 requestedColumns.erase (iter);
1374 const auto& branchData =
branchReader.getEntry (entry);
1377 for (
auto&
data : branchData)
1379 for (
auto& element :
data)
1381 if (element.isDefault() || (element.key() == 0 && element.index() == 0))
1387 for (std::size_t i = 0; i <
containers.size(); ++i)
1392 throw std::runtime_error (
"invalid index: " + std::to_string (element.index()) +
" in container: " +
containers[i] +
" with size: " + std::to_string (
containerOffsets[i]->back()));
1395 throw std::runtime_error (
"container offset not yet filled for: " +
containers[i]);
1405 auto& forbiddenContainers =
unknownKeys[element.key()];
1406 for (std::size_t i = 0; i <
containers.size(); ++i)
1474 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& , std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
1476 auto iter = requestedColumns.find (
outputColumns.at(0).name);
1477 if (iter == requestedColumns.end())
1484 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
1486 requestedColumns.erase (iter);
1489 if (iter == requestedColumns.end())
1494 requestedColumns.erase (iter);
1497 if (iter != requestedColumns.end())
1500 requestedColumns.erase (iter);
1516 const auto& branchData =
branchReader.getEntry (entry);
1519 for (
auto&
data : branchData)
1568 outputColumns.push_back ({.name = val_columnName, .isOffset =
true});
1569 outputColumns.push_back ({.name = val_columnName +
".name.data"});
1570 outputColumns.push_back ({.name = val_columnName +
".name.offset", .isOffset =
true});
1571 outputColumns.push_back ({.name = val_columnName +
".nameHash"});
1574 virtual bool connect (TTree * , std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>&
offsetColumns, std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
1576 if (
auto iter = requestedColumns.find (
outputColumns.at(0).name);
1577 iter != requestedColumns.end())
1578 requestedColumns.erase (iter);
1583 if (
auto iter = requestedColumns.find (
outputColumns.at(1).name);
1584 iter != requestedColumns.end())
1587 requestedColumns.erase (iter);
1590 if (
auto iter = requestedColumns.find (
outputColumns.at(2).name);
1591 iter != requestedColumns.end())
1594 requestedColumns.erase (iter);
1597 if (
auto iter = requestedColumns.find (
outputColumns.at(3).name);
1598 iter != requestedColumns.end())
1601 requestedColumns.erase (iter);
1627 namesHash.push_back (std::hash<std::string> () (termName));
1671 virtual bool connect (TTree *
tree, std::unordered_map<std::string,
const std::vector<ColumnarOffsetType>*>& , std::unordered_map<std::string,ColumnInfo>& requestedColumns)
override
1673 auto iter = requestedColumns.find (
outputColumns.at(0).name);
1674 if (iter == requestedColumns.end())
1681 throw std::runtime_error (
"offset name mismatch: " + iter->second.offsetName +
" != " +
outputColumns.at(1).name);
1683 requestedColumns.erase (iter);
1686 if (iter == requestedColumns.end())
1691 requestedColumns.erase (iter);
1705 const auto& branchData =
branchReader.getEntry (entry);
1708 for (
auto data : branchData)
1753 std::unique_ptr<ToolColumnVectorMap> toolWrapper;
1754 bool noRepeatCall =
false;
1755 bool runToolTwice =
false;
1763 , noRepeatCall (td.noRepeatCall)
1764 , runToolTwice (
config.runToolTwice)
1765 , benchmarkCall (
"",
config.batchSize)
1766 , benchmarkCall2 (
"",
config.batchSize)
1770 throw std::runtime_error (
"tool is not a ColumnarTool<ColumnarModeArray>: " + td.
name);
1773 toolWrapper = std::make_unique<ToolColumnVectorMap> (columnHeader, *tool);
1777 void call (ColumnVectorData& columnData)
1780 columnData.callNoCheck (*tool);
1782 if (runToolTwice && !noRepeatCall)
1785 columnData.callNoCheck (*tool);
1794 ColumnarPhysLiteTest ::
1795 ColumnarPhysLiteTest ()
1797 static std::once_flag flag;
1798 std::call_once (flag, [] ()
1800#ifdef XAOD_STANDALONE
1807 auto *fileName = getenv (
"ASG_TEST_FILE_LITE_MC");
1808 if (fileName ==
nullptr)
1809 throw std::runtime_error (
"missing ASG_TEST_FILE_LITE_MC");
1810 file.reset (TFile::Open (fileName,
"READ"));
1812 throw std::runtime_error (
"failed to open file");
1813 tree =
dynamic_cast<TTree*
> (
file->Get (
"CollectionTree"));
1815 throw std::runtime_error (
"failed to open tree");
1818 ColumnarPhysLiteTest :: ~ColumnarPhysLiteTest () =
default;
1820 std::string ColumnarPhysLiteTest :: makeUniqueName ()
1822 static std::atomic<unsigned>
index = 0;
1823 return "UniquePhysliteTestTool" + std::to_string(++
index);
1826 bool ColumnarPhysLiteTest ::
1832 void ColumnarPhysLiteTest :: setupKnownColumns (std::span<const TestDefinition> testDefinitions)
1836 knownColumns.push_back (std::make_shared<ColumnDataEventCount> ());
1838 tree->SetMakeClass (1);
1840 std::unordered_map<std::string,TBranch*> branches;
1842 TIter branchIter (
tree->GetListOfBranches());
1843 TObject *obj =
nullptr;
1844 while ((obj = branchIter()))
1846 TBranch *branch =
nullptr;
1847 if ((branch =
dynamic_cast<TBranch*
>(obj)))
1849 branches.emplace (branch->GetName(), branch);
1850 TIter subBranchIter (branch->GetListOfBranches());
1851 while ((obj = subBranchIter()))
1853 if (
auto subBranch =
dynamic_cast<TBranch*
>(obj))
1854 branches.emplace (subBranch->GetName(), subBranch);
1860 for (
const auto& [name, branch] : branches)
1862 if (name.find (
"AuxDyn.") != std::string::npos ||
1863 name.find (
"Aux.") != std::string::npos)
1865 TClass *branchClass =
nullptr;
1866 EDataType branchType {};
1867 branch->GetExpectedType (branchClass, branchType);
1868 if (branchClass ==
nullptr)
1893 if (*branchClass->GetTypeInfo() ==
typeid(std::vector<float>))
1896 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<char>))
1899 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::int8_t>))
1902 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::uint8_t>))
1905 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::int16_t>))
1908 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::uint16_t>))
1911 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::int32_t>))
1914 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::uint32_t>))
1917 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::int64_t>))
1920 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::uint64_t>))
1923 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::vector<float>>))
1926 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::vector<std::int32_t>>))
1929 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::vector<std::uint64_t>>))
1932 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::vector<std::vector<std::size_t>>>))
1935 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::vector<std::vector<unsigned char>>>))
1938 }
else if (*branchClass->GetTypeInfo() ==
typeid(std::vector<std::string>))
1940 knownColumns.push_back (std::make_shared<ColumnDataMetNames> (branch->GetName()));
1952 knownColumns.push_back (std::make_shared<ColumnDataSamplingPattern> (
"egammaClusters"));
1972 std::vector<std::string> allMetTermNames;
1973 for (
const auto& td : testDefinitions)
1977 if (std::find (allMetTermNames.begin(), allMetTermNames.end(), name) == allMetTermNames.end())
1978 allMetTermNames.push_back (name);
1981 if (!allMetTermNames.empty())
1982 knownColumns.push_back (std::make_shared<ColumnDataOutputMet> (
"OutputMET", allMetTermNames));
2001 using namespace asg::msgUserCode;
2008 for (
auto& [name, info] : requestedColumns)
2009 std::cout <<
"requested columns: " << name << std::endl;
2017 std::set<std::string> unclaimedColumns;
2018 for (
auto& column : requestedColumns)
2020 if (!column.second.isOptional)
2021 unclaimedColumns.insert (column.first);
2023 std::cout <<
"optional column not claimed: " << column.first << std::endl;
2027 const auto& info = requestedColumns.at (columnName);
2030 auto offsetIter = std::find_if (
usedColumns.begin(),
usedColumns.end(), [&] (
const std::shared_ptr<TestUtils::IColumnData>& column)
2032 for (auto& output : column->outputColumns)
2034 if (output.name == info.offsetName)
2041 std::shared_ptr<TestUtils::IColumnData> myColumn;
2042 if (*info.type ==
typeid(
float))
2043 myColumn = std::make_shared<TestUtils::ColumnDataOutVector<float>> (info.name, 0);
2044 else if (*info.type ==
typeid(
char))
2045 myColumn = std::make_shared<TestUtils::ColumnDataOutVector<char>> (info.name, 0);
2046 else if (*info.type ==
typeid(std::uint16_t))
2047 myColumn = std::make_shared<TestUtils::ColumnDataOutVector<std::uint16_t>> (info.name, 0);
2048 else if (*info.type ==
typeid(std::uint64_t))
2049 myColumn = std::make_shared<TestUtils::ColumnDataOutVector<std::uint64_t>> (info.name, 0);
2052 ANA_MSG_WARNING (
"unhandled column type: " << info.name <<
" " << info.type->name());
2058 ANA_MSG_WARNING (
"failed to connect dynamic output column: " << info.name);
2064 if (!unclaimedColumns.empty())
2066 std::string message =
"columns not claimed:";
2067 for (
auto& column : unclaimedColumns)
2068 message +=
" " + column;
2069 throw std::runtime_error (message);
2078 void ColumnarPhysLiteTest :: doCallMulti (
const std::vector<TestDefinition>& testDefinitions)
2080 using namespace asg::msgUserCode;
2084 for (
const auto& td : testDefinitions)
2090 throw std::runtime_error (
"tool does not support systematics");
2091 std::cout <<
"applying systematic variation: " << td.
sysName << std::endl;
2093 throw std::runtime_error (
"failed to apply systematic variation: " + td.
sysName);
2103 std::vector<TestUtils::ToolData> toolDataVec;
2104 for (
const auto& td : testDefinitions)
2105 toolDataVec.emplace_back (userConfiguration, td, columnHeader);
2114 column->connectColumnIndices (columnHeader);
2117 Benchmark benchmarkCheck (
"", userConfiguration.batchSize);
2121 const auto startTime = std::chrono::high_resolution_clock::now();
2122 bool endLoop =
false;
2123 for (; !endLoop; ++entry)
2133 if ((entry + 1) % userConfiguration.batchSize == 0)
2138 column->collectColumnData ();
2141 column->setData (columnData);
2147 for (
auto& toolData : toolDataVec)
2148 toolData.call (columnData);
2150 column->clearColumns ();
2151 if ((std::chrono::high_resolution_clock::now() - startTime) > userConfiguration.targetTime)
2156 column->collectColumnData ();
2160 std::cout <<
"Total entries read: " << entry << std::endl;
2161 const float emptyTime = benchmarkEmpty.
getEntryTime(0).value();
2166 std::cout <<
"Check data time: " <<
checkTime.value() <<
"ns" << std::endl;
2169 std::vector<TestUtils::BranchPerfData> branchPerfData;
2171 summary.name =
"total";
2172 summary.timeRead = 0;
2173 summary.timeUnpack = 0;
2174 summary.timeShallowCopy = 0;
2175 summary.entries = std::nullopt;
2176 summary.nullEntries = std::nullopt;
2179 branchPerfData.push_back (column->getPerfData (emptyTime));
2180 summary.timeRead.value() += branchPerfData.back().timeRead.value_or(0);
2181 summary.timeUnpack.value() += branchPerfData.back().timeUnpack.value_or(0);
2182 summary.timeShallowCopy.value() += branchPerfData.back().timeShallowCopy.value_or(0);
2184 std::sort (branchPerfData.begin(), branchPerfData.end(), [] (
const auto&
a,
const auto& b) {return a.name < b.name;});
2185 branchPerfData.insert (branchPerfData.end(), summary);
2186 const std::size_t nameWidth = std::max_element (branchPerfData.begin(), branchPerfData.end(), [] (
const auto&
a,
const auto& b) {return a.name.size() < b.name.size();})->name.size();
2187 std::string
header = std::format (
"{:{}} | read(ns) | unpack(ns) | size(B) | rate(MB/s) | compression | baskets | entries | null",
"branch name", nameWidth);
2188 std::cout <<
"\n" <<
header << std::endl;
2189 std::cout << std::string (
header.size(),
'-') << std::endl;
2190 for (
auto&
data : branchPerfData)
2192 if (
data.name ==
"total")
2193 std::cout << std::string (
header.size(),
'-') << std::endl;
2194 std::cout << std::format (
"{:{}} |",
data.name, nameWidth);
2196 std::cout << std::format (
"{:>9.0f} |",
data.timeRead.value());
2199 if (
data.timeUnpack)
2200 std::cout << std::format (
"{:>11.1f} |",
data.timeUnpack.value());
2204 std::cout << std::format (
"{:>8.1f} |",
data.entrySize.value());
2207 if (
data.timeRead &&
data.entrySize)
2208 std::cout << std::format (
"{:>11.1f} |", (
data.entrySize.value() / (
data.timeRead.value() * 1e-3 * 1.024 * 1.024)));
2211 if (
data.entrySize &&
data.uncompressedSize)
2212 std::cout << std::format (
"{:>12.2f} |",
float (
data.uncompressedSize.value()) /
data.entrySize.value());
2215 if (
data.numBaskets)
2216 std::cout << std::format (
"{:>8} |",
data.numBaskets.value());
2220 std::cout << std::format (
"{:>8.2f} |",
static_cast<float>(
data.entries.value())/
numberOfEvents);
2223 if (
data.nullEntries &&
data.entries)
2224 std::cout << std::format (
"{:>4.0f}%",
static_cast<float>(
data.nullEntries.value()) /
data.entries.value() * 100.0f);
2225 std::cout << std::endl;
2229 std::vector<TestUtils::ToolPerfData> toolPerfData;
2230 for (
auto& toolData : toolDataVec)
2232 toolPerfData.emplace_back ();
2233 toolPerfData.back().name = toolData.name;
2234 toolPerfData.back().timeCall = toolData.benchmarkCall.getEntryTime (emptyTime);
2235 if (userConfiguration.runToolTwice)
2236 toolPerfData.back().timeCall2 = toolData.benchmarkCall2.getEntryTime (emptyTime);
2238 const std::size_t nameWidth = std::max_element (toolPerfData.begin(), toolPerfData.end(), [] (
const auto&
a,
const auto& b) {return a.name.size() < b.name.size();})->name.size();
2239 std::string
header = std::format (
"{:{}} | call(ns) | call2(ns)",
"tool name", nameWidth);
2240 std::cout <<
"\n" <<
header << std::endl;
2241 std::cout << std::string (
header.size(),
'-') << std::endl;
2242 for (
auto&
data : toolPerfData)
2244 std::cout << std::format (
"{:{}} |",
data.name, nameWidth);
2246 std::cout << std::format (
"{:>9.0f} |",
data.timeCall.value());
2250 std::cout << std::format (
"{:>10.0f}",
data.timeCall2.value());
2253 std::cout << std::endl;
2256 if (toolPerfData.size() > 1)
2258 std::optional<float> totalCall, totalCall2;
2259 for (
const auto&
data : toolPerfData)
2262 totalCall = totalCall.value_or (0) +
data.timeCall.value();
2264 totalCall2 = totalCall2.value_or (0) +
data.timeCall2.value();
2266 std::cout << std::string (
header.size(),
'-') << std::endl;
2267 std::cout << std::format (
"{:{}} |",
"total", nameWidth);
2269 std::cout << std::format (
"{:>9.0f} |", totalCall.value());
2273 std::cout << std::format (
"{:>10.0f}", totalCall2.value());
2276 std::cout << std::endl;
2284 const auto& testDefinition = testDefinitions[0];
char data[hepevt_bytes_allocation_ATLAS]
A number of constexpr particle constants to avoid hardcoding them directly in various places.
Class to wrap a set of SystematicVariations.
a class that holds the columnar data for a single call
void checkData() const
do a basic check of the data vector
void setColumn(std::size_t columnIndex, std::size_t size, CT *dataPtr)
set the data for the given column
the header information for the entire columnar data vector
static constexpr std::size_t nullIndex
the index used for an invalid index (always has to be 0)
std::unordered_map< std::string, ColumnInfo > getAllColumnInfo() const
get all columns as a map of ColumnInfo for use with IColumnData::connect
this is a simple benchmarking helper class wrapping timers from std::chrono
static float getTickDuration()
std::optional< float > getEntryTime(float emptyTime) const
std::string columnName() const
BranchReaderArray(const std::string &val_branchName)
std::string containerName() const
void connectTree(TTree *tree)
std::vector< T > m_dataVec
std::span< const T > getEntry(Long64_t entry, std::size_t size)
std::optional< unsigned > numBaskets()
BranchReaderArray(const BranchReaderArray &)=delete
std::optional< float > uncompressedSize() const
std::optional< float > entrySize() const
BranchReaderArray & operator=(const BranchReaderArray &)=delete
void setIsStatic(bool isStatic)
const std::string & branchName() const
std::optional< float > entrySize() const
std::string columnName() const
BranchReader(const BranchReader &)=delete
BranchReader(const std::string &val_branchName)
std::string containerName() const
std::optional< unsigned > numBaskets()
BranchReader & operator=(const BranchReader &)=delete
void connectTree(TTree *tree)
const T & getEntry(Long64_t entry)
std::optional< float > uncompressedSize() const
const T & getCachedEntry() const
virtual void collectColumnData()=0
std::vector< OutputColumnInfo > outputColumns
virtual void setData(ColumnVectorData &columnData)=0
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns)=0
virtual void clearColumns()=0
virtual ~IColumnData() noexcept=default
virtual void getEntry(Long64_t entry)=0
void connectColumnIndices(const ColumnVectorHeader &header)
lookup and store column indices from the header for all enabled output columns
virtual BranchPerfData getPerfData(float emptyTime)=0
IAppMgrUI * Init(const char *options="POOLRootAccess/basic.opts")
Bootstraps (creates and configures) the Gaudi Application with the provided options file.
constexpr double muonMassInMeV
the mass of the muon (in MeV)
uint32_t sgkey_t
Type used for hashed StoreGate key+CLID pairs.
void runXaodArrayTest(const UserConfiguration &userConfiguration, const TestDefinition &testDefinition, TFile *file)
void runXaodTest(const UserConfiguration &userConfiguration, std::span< const TestDefinition > testDefinitions, TFile *file)
const std::unordered_map< std::string, SG::sgkey_t > knownKeys
constexpr unsigned columnarAccessMode
const std::string numberOfEventsName
the name used for the column containing the number of events
void renameContainers(IColumnarTool &tool, const std::vector< std::pair< std::string, std::string > > &renames)
rename containers in the columnar tool
std::size_t ColumnarOffsetType
the type used for the size and offsets in the columnar data
constexpr ColumnarOffsetType invalidObjectIndex
the value for an invalid element index
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
std::size_t erase_if(T_container &container, T_Func pred)
@ Jet
The object is a jet.
@ Muon
The object is a muon.
StatusCode Init(const char *appname)
Function initialising ROOT/PyROOT for using the ATLAS EDM.
a struct that contains meta-information about each column that's needed to interface the column with ...
std::size_t LinkIndexType
the type used for columns that represent element links
static constexpr LinkIndexType invalidLinkValue
the value used for an invalid link (a.k.a. empty/null link)
static LinkIndexType mergeLinkKeyIndex(LinkIndexType key, LinkIndexType index)
merge a key and index value into a link value
std::vector< std::shared_ptr< TestUtils::IColumnData > > knownColumns
std::vector< std::shared_ptr< TestUtils::IColumnData > > usedColumns
std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > offsetColumns
void setupKnownColumns(std::span< const TestUtils::TestDefinition > testDefinitions)
void setupColumns(const ColumnVectorHeader &columnHeader)
std::unique_ptr< TFile > file
void doCallMulti(const std::vector< TestUtils::TestDefinition > &testDefinitions)
the performance data for reading a single branch/column
virtual void setData(ColumnVectorData &columnData) override
virtual void getEntry(Long64_t) override
virtual void clearColumns() override
virtual bool connect(TTree *, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
std::array< ColumnarOffsetType, 2 > data
virtual BranchPerfData getPerfData(float) override
virtual void collectColumnData() override
std::vector< char > columnData
virtual void collectColumnData() override
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
virtual void setData(ColumnVectorData &colData) override
std::vector< ColumnarOffsetType > offsets
virtual BranchPerfData getPerfData(float emptyTime) override
virtual void getEntry(Long64_t entry) override
Benchmark benchmarkUnpack
ColumnDataMetNames(const std::string &val_branchName)
std::vector< std::size_t > columnHashData
BranchReader< std::vector< std::string > > branchReader
virtual void clearColumns() override
ColumnDataOutVector(const std::string &val_columnName, const T &val_defaultValue)
virtual void setData(ColumnVectorData &columnData) override
virtual void collectColumnData() override
virtual BranchPerfData getPerfData(float) override
const std::vector< ColumnarOffsetType > * offsetColumn
virtual void clearColumns() override
virtual void getEntry(Long64_t) override
virtual bool connect(TTree *, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
virtual void setData(ColumnVectorData &colData) override
std::vector< std::size_t > namesHash
virtual void clearColumns() override
virtual void getEntry(Long64_t) override
virtual void collectColumnData() override
const std::vector< ColumnarOffsetType > * offsetColumns
virtual BranchPerfData getPerfData(float) override
virtual bool connect(TTree *, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
std::vector< char > namesData
std::vector< std::string > termNames
ColumnDataOutputMet(const std::string &val_columnName, std::vector< std::string > val_termNames)
std::vector< ColumnarOffsetType > namesOffsets
std::vector< ColumnarOffsetType > offsets
BranchReader< xAOD::CaloClusterContainer > branchReader
virtual void clearColumns() override
virtual void getEntry(Long64_t entry) override
std::vector< std::uint32_t > columnData
Benchmark benchmarkUnpack
virtual BranchPerfData getPerfData(float emptyTime) override
ColumnDataSamplingPattern(const std::string &val_branchName)
std::vector< ColumnarOffsetType > offsets
virtual void collectColumnData() override
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
virtual void setData(ColumnVectorData &colData) override
virtual void clearColumns() override
virtual void collectColumnData() override
virtual void setData(ColumnVectorData &columnData) override
virtual BranchPerfData getPerfData(float emptyTime) override
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
ColumnDataScalar(const std::string &val_branchName)
BranchReader< T > branchReader
virtual void getEntry(Long64_t entry) override
Benchmark benchmarkUnpack
virtual void getEntry(Long64_t entry) override
virtual void collectColumnData() override
BranchReader< std::vector< ElementLink< T > > > branchReader
virtual void setData(ColumnVectorData &colData) override
ColumnDataVectorLink(const std::string &val_branchName)
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
virtual BranchPerfData getPerfData(float emptyTime) override
Benchmark benchmarkUnpack
const std::vector< ColumnarOffsetType > * offsetColumn
std::string targetContainerName
std::vector< typename CM::LinkIndexType > columnData
const std::vector< ColumnarOffsetType > * targetOffsetColumn
std::vector< ColumnarOffsetType > offsets
virtual void clearColumns() override
BranchReader< Int_t > branchReaderSize
const std::vector< ColumnarOffsetType > * offsetColumn
std::vector< typename CM::LinkKeyType > keyColumnData
virtual void setData(ColumnVectorData &colData) override
BranchReaderArray< UInt_t > branchReaderIndex
std::vector< typename CM::LinkIndexType > columnData
std::vector< ColumnarOffsetType > offsets
std::vector< SG::sgkey_t > targetKeys
std::vector< const std::vector< ColumnarOffsetType > * > targetOffsetColumns
virtual BranchPerfData getPerfData(float emptyTime) override
virtual void collectColumnData() override
BranchReaderArray< UInt_t > branchReaderKey
ColumnDataVectorSplitLink(const std::string &val_branchName)
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
virtual void getEntry(Long64_t entry) override
virtual void clearColumns() override
Benchmark benchmarkUnpack
Benchmark benchmarkUnpack
std::vector< ColumnarOffsetType > offsets
virtual void getEntry(Long64_t entry) override
std::string targetContainerName
ColumnDataVectorVectorLink(const std::string &val_branchName)
BranchReader< std::vector< std::vector< ElementLink< T > > > > branchReader
virtual BranchPerfData getPerfData(float emptyTime) override
virtual void setData(ColumnVectorData &colData) override
virtual void collectColumnData() override
std::vector< typename CM::LinkIndexType > columnData
virtual void clearColumns() override
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
const std::vector< ColumnarOffsetType > * targetOffsetColumn
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
std::vector< std::string > containers
std::vector< const std::vector< ColumnarOffsetType > * > containerOffsets
ColumnDataVectorVectorVariantLink(const std::string &val_branchName)
std::vector< SG::sgkey_t > containerKeys
virtual void clearColumns() override
virtual void getEntry(Long64_t entry) override
Benchmark benchmarkUnpack
virtual void setData(ColumnVectorData &colData) override
virtual BranchPerfData getPerfData(float emptyTime) override
std::vector< ColumnarOffsetType > offsets
std::vector< typename CM::LinkIndexType > columnData
virtual void collectColumnData() override
BranchReader< std::vector< std::vector< ElementLink< T > > > > branchReader
~ColumnDataVectorVectorVariantLink()
std::vector< typename CM::LinkKeyType > keysColumn
std::unordered_map< SG::sgkey_t, std::unordered_set< std::string > > unknownKeys
std::vector< ColumnarOffsetType > outerOffsets
virtual void clearColumns() override
std::vector< T > columnData
std::vector< ColumnarOffsetType > innerOffsets
virtual void collectColumnData() override
virtual BranchPerfData getPerfData(float emptyTime) override
Benchmark benchmarkUnpack
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
BranchReader< std::vector< std::vector< std::vector< T > > > > branchReader
virtual void getEntry(Long64_t entry) override
virtual void setData(ColumnVectorData &colData) override
ColumnDataVectorVectorVector(const std::string &val_branchName)
std::vector< T > columnData
virtual BranchPerfData getPerfData(float emptyTime) override
virtual void clearColumns() override
virtual void collectColumnData() override
std::vector< ColumnarOffsetType > offsets
BranchReader< std::vector< std::vector< T > > > branchReader
virtual void setData(ColumnVectorData &colData) override
Benchmark benchmarkUnpack
ColumnDataVectorVector(const std::string &val_branchName)
virtual void getEntry(Long64_t entry) override
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
std::vector< ColumnarOffsetType > offsets
BranchReader< std::vector< T > > branchReader
virtual bool connect(TTree *tree, std::unordered_map< std::string, const std::vector< ColumnarOffsetType > * > &offsetColumns, std::unordered_map< std::string, ColumnInfo > &requestedColumns) override
virtual BranchPerfData getPerfData(float emptyTime) override
virtual void getEntry(Long64_t entry) override
Benchmark benchmarkUnpack
virtual void setData(ColumnVectorData &columnData) override
ColumnDataVector(const std::string &val_branchName)
virtual void collectColumnData() override
const std::vector< ColumnarOffsetType > * offsetColumn
virtual void clearColumns() override
the general configuration for a single test
std::string sysName
the systematic variation to apply (empty for nominal)
std::vector< std::string > metTermNames
the MET output term names (if empty, MET output columns are omitted)
std::string name
the name identifier for the test
std::vector< std::pair< std::string, std::string > > containerRenames
the container name remappings to apply
asg::AsgTool * tool
the tool being tested
a struct holding user configuration for the PHYSLITE tests
static UserConfiguration fromEnvironment()
create a UserConfiguration, loading from the file pointed to by the COLUMNAR_TEST_CONFIG environment ...