CMS 3D CMS Logo

TableOutputFields.cc
Go to the documentation of this file.
1 #include "TableOutputFields.h"
2 
3 namespace {
4  void printTable(const nanoaod::FlatTable& table) {
5  std::cout << "FlatTable {\n";
6  std::cout << " name: " << (table.name().empty() ? "// anon" : table.name()) << "\n";
7  std::cout << " singleton: " << (table.singleton() ? "true" : "false") << "\n";
8  std::cout << " size: " << table.size() << "\n";
9  std::cout << " extension: " << (table.extension() ? "true" : "false") << "\n";
10  std::cout << " fields: {\n";
11  for (std::size_t i = 0; i < table.nColumns(); i++) {
12  std::cout << " " << (table.columnName(i).empty() ? "// anon" : table.columnName(i)) << ": ";
13  switch (table.columnType(i)) {
15  std::cout << "f32,";
16  break;
18  std::cout << "i32,";
19  break;
21  std::cout << "u8,";
22  break;
24  std::cout << "bool,";
25  break;
26  default:
27  throw cms::Exception("LogicError", "Unsupported type");
28  }
29  std::cout << "\n";
30  }
31  std::cout << " }\n}\n";
32  }
33 } // anonymous namespace
34 
36  for (const auto& field : m_floatFields) {
37  std::cout << " " << field.getFlatTableName() << ": f32,\n";
38  }
39  for (const auto& field : m_intFields) {
40  std::cout << " " << field.getFlatTableName() << ": i32,\n";
41  }
42  for (const auto& field : m_uint8Fields) {
43  std::cout << " " << field.getFlatTableName() << ": u8,\n";
44  }
45  for (const auto& field : m_boolFields) {
46  std::cout << " " << field.getFlatTableName() << ": bool,\n";
47  }
48 }
49 
52  event.getByToken(m_token, handle);
54  for (std::size_t i = 0; i < table.nColumns(); i++) {
55  switch (table.columnType(i)) {
58  break;
60  m_intFields.emplace_back(FlatTableField<int>(table, i, model));
61  break;
64  break;
67  break;
68  default:
69  throw cms::Exception("LogicError", "Unsupported type");
70  }
71  }
72 }
73 
75  for (auto& field : m_floatFields) {
76  field.fill(table, i);
77  }
78  for (auto& field : m_intFields) {
79  field.fill(table, i);
80  }
81  for (auto& field : m_uint8Fields) {
82  field.fill(table, i);
83  }
84  for (auto& field : m_boolFields) {
85  field.fill(table, i);
86  }
87 }
88 
90 
92 
95  event.getByToken(m_token, handle);
97  for (std::size_t i = 0; i < table.nColumns(); i++) {
98  switch (table.columnType(i)) {
100  m_vfloatFields.emplace_back(FlatTableField<std::vector<float>>(table, i, model));
101  break;
103  m_vintFields.emplace_back(FlatTableField<std::vector<int>>(table, i, model));
104  break;
106  m_vuint8Fields.emplace_back(FlatTableField<std::vector<std::uint8_t>>(table, i, model));
107  break;
109  m_vboolFields.emplace_back(FlatTableField<std::vector<bool>>(table, i, model));
110  break;
111  default:
112  throw cms::Exception("LogicError", "Unsupported type");
113  }
114  }
115 }
118  event.getByToken(m_token, handle);
119  const auto& table = *handle;
120  for (auto& field : m_vfloatFields) {
121  field.fillVectored(table);
122  }
123  for (auto& field : m_vintFields) {
124  field.fillVectored(table);
125  }
126  for (auto& field : m_vuint8Fields) {
127  field.fillVectored(table);
128  }
129  for (auto& field : m_vboolFields) {
130  field.fillVectored(table);
131  }
132 }
133 
135 
137  if (m_collectionName.empty()) {
138  m_collectionName = table.name();
139  }
140  if (table.extension()) {
141  m_extensions.emplace_back(TableOutputFields(table_token));
142  return;
143  }
144  if (hasMainTable()) {
145  throw cms::Exception("LogicError", "Trying to save multiple main tables for " + m_collectionName + "\n");
146  }
147  m_main = TableOutputFields(table_token);
148 }
149 
150 void TableCollection::createFields(const edm::EventForOutput& event, RNTupleModel& eventModel) {
151  auto collectionModel = RNTupleModel::Create();
152  m_main.createFields(event, *collectionModel);
153  for (auto& extension : m_extensions) {
154  extension.createFields(event, *collectionModel);
155  }
157  event.getByToken(m_main.getToken(), handle);
158  const nanoaod::FlatTable& table = *handle;
159  collectionModel->SetDescription(table.doc());
160  m_collection = eventModel.MakeCollection(m_collectionName, std::move(collectionModel));
161 }
162 
165  event.getByToken(m_main.getToken(), handle);
166  const auto& main_table = *handle;
167  auto table_size = main_table.size();
168  for (std::size_t i = 0; i < table_size; i++) {
169  m_main.fillEntry(main_table, i);
170  for (auto& ext : m_extensions) {
172  event.getByToken(ext.getToken(), handle);
173  const auto& ext_table = *handle;
174  if (ext_table.size() != table_size) {
175  throw cms::Exception("LogicError",
176  "Mismatch in number of entries between extension and main table for " + m_collectionName);
177  }
178  ext.fillEntry(ext_table, i);
179  }
180  m_collection->Fill();
181  }
182 }
183 
185  std::cout << "Collection: " << m_collectionName << " {\n";
186  m_main.print();
187  for (const auto& ext : m_extensions) {
188  ext.print();
189  }
190  std::cout << "}\n";
191 }
192 
194 
196 
198 
200  // skip empty tables -- requirement of RNTuple to define schema before filling
201  if (table.nColumns() == 0) {
202  std::cout << "Warning: skipping empty table: \n";
203  printTable(table);
204  return;
205  }
206  // Can handle either anonymous table or anonymous column but not both
207  // - anonymous table: use column names directly as top-level fields
208  // - anonymous column: use the table name as the field name
209  if (table.name().empty() && hasAnonymousColumn(table)) {
210  throw cms::Exception("LogicError", "Anonymous FlatTable and anonymous field");
211  }
212  // case 1: create a top-level RNTuple field for each table column
213  if (table.name().empty() || hasAnonymousColumn(table)) {
214  if (table.singleton()) {
215  m_singletonFields.emplace_back(TableOutputFields(table_token));
216  } else {
217  m_vectorFields.emplace_back(TableOutputVectorFields(table_token));
218  }
219  return;
220  }
221  // case 2: Named singleton and vector tables are both written as RNTuple collections.
222  auto collection = std::find_if(m_collections.begin(), m_collections.end(), [&](const TableCollection& c) {
223  return c.getCollectionName() == table.name();
224  });
225  if (collection == m_collections.end()) {
226  m_collections.emplace_back(TableCollection());
227  m_collections.back().add(table_token, table);
228  return;
229  }
230  collection->add(table_token, table);
231 }
232 
234  for (const auto& collection : m_collections) {
235  collection.print();
236  std::cout << "\n";
237  }
238 }
239 
240 void TableCollectionSet::createFields(const edm::EventForOutput& event, RNTupleModel& eventModel) {
241  for (auto& collection : m_collections) {
242  if (!collection.hasMainTable()) {
243  throw cms::Exception("LogicError",
244  "Trying to save an extension table for " + collection.getCollectionName() +
245  " without the corresponding main table\n");
246  }
247  collection.createFields(event, eventModel);
248  }
249  for (auto& table : m_singletonFields) {
250  table.createFields(event, eventModel);
251  }
252  for (auto& table : m_vectorFields) {
253  table.createFields(event, eventModel);
254  }
255 }
256 
258  for (auto& collection : m_collections) {
259  collection.fill(event);
260  }
261  for (auto& fields : m_singletonFields) {
263  event.getByToken(fields.getToken(), handle);
264  const auto& table = *handle;
265  fields.fillEntry(table, 0);
266  }
267  for (auto& fields : m_vectorFields) {
268  fields.fill(event);
269  }
270 }
271 
273  int num_anon = 0;
274  for (std::size_t i = 0; i < table.nColumns(); i++) {
275  if (table.columnName(i).empty()) {
276  num_anon++;
277  }
278  }
279  if (num_anon > 1) {
280  throw cms::Exception("LogicError",
281  "FlatTable `" + table.name() + "` has " + std::to_string(num_anon) + "anonymous fields");
282  }
283  return num_anon;
284 }
void fillEntry(const nanoaod::FlatTable &table, std::size_t i)
TableOutputFields m_main
const edm::EDGetToken & getToken() const
std::vector< TableOutputFields > m_singletonFields
std::vector< FlatTableField< std::vector< float > > > m_vfloatFields
void createFields(const edm::EventForOutput &event, RNTupleModel &eventModel)
edm::EDGetToken m_token
static std::string to_string(const XMLCh *ch)
std::vector< FlatTableField< bool > > m_boolFields
std::string m_collectionName
std::shared_ptr< RNTupleCollectionWriter > m_collection
std::vector< FlatTableField< std::vector< bool > > > m_vboolFields
const std::string & getCollectionName() const
std::vector< FlatTableField< std::uint8_t > > m_uint8Fields
void fill(const edm::EventForOutput &event)
std::vector< TableOutputVectorFields > m_vectorFields
std::vector< TableOutputFields > m_extensions
std::vector< FlatTableField< int > > m_intFields
std::vector< FlatTableField< std::vector< int > > > m_vintFields
void createFields(const edm::EventForOutput &event, RNTupleModel &model)
std::vector< FlatTableField< float > > m_floatFields
void fill(const edm::EventForOutput &event)
void add(const edm::EDGetToken &table_token, const nanoaod::FlatTable &table)
static bool hasAnonymousColumn(const nanoaod::FlatTable &table)
void add(const edm::EDGetToken &table_token, const nanoaod::FlatTable &table)
std::vector< FlatTableField< std::vector< std::uint8_t > > > m_vuint8Fields
void fill(const edm::EventForOutput &event)
constexpr bool isUninitialized() const noexcept
Definition: EDGetToken.h:55
Definition: memstream.h:15
std::vector< TableCollection > m_collections
void createFields(const edm::EventForOutput &event, RNTupleModel &model)
void createFields(const edm::EventForOutput &event, RNTupleModel &eventModel)
def move(src, dest)
Definition: eostools.py:511
Definition: event.py:1