|
31 | 31 | #include <cmath> |
32 | 32 | #include <cstdint> |
33 | 33 | #include <utility> |
| 34 | +#include <vector> |
34 | 35 |
|
35 | 36 | namespace o2::aod |
36 | 37 | { |
@@ -169,99 +170,116 @@ JETTAGGING_TABLES_DEF(Full, "F"); |
169 | 170 | // Tables for full inference of GNN-based b-jet tagger (including track origin, vertex predictions) |
170 | 171 | namespace jetgnnindex |
171 | 172 | { |
172 | | -DECLARE_SOA_INDEX_COLUMN(JTrack, track); //! index of the original track this in-jet track index corresponds to |
173 | | -DECLARE_SOA_COLUMN(TrackIndex, trackIndex, uint8_t); //! in-jet index i (0..N-1) of this constituent track, matching the order of jet.template tracks_as<AnyTracks>() |
174 | | -DECLARE_SOA_COLUMN(EdgeIndex, edgeIndex, uint8_t); //! unique in-jet edge index for the (i,j) constituent-track pair, i<j, triangular order i*(2N-i-1)/2+(j-i-1) |
175 | | -DECLARE_SOA_DYNAMIC_COLUMN(TrackIds, trackIds, //! inverse of the triangular edge indexing above: for n constituent tracks, recovers the (i,j) in-jet track index pair (i<j) this edge connects |
176 | | - [](uint8_t edgeIndex, int n) -> std::pair<uint8_t, uint8_t> { |
177 | | - int i = 0; |
178 | | - int offset = 0; |
179 | | - while (offset + (n - 1 - i) <= static_cast<int>(edgeIndex)) { |
180 | | - offset += (n - 1 - i); |
181 | | - i++; |
182 | | - } |
183 | | - int j = i + 1 + (static_cast<int>(edgeIndex) - offset); |
184 | | - return std::pair<uint8_t, uint8_t>{static_cast<uint8_t>(i), static_cast<uint8_t>(j)}; |
185 | | - }); |
| 173 | +DECLARE_SOA_INDEX_COLUMN(JTrack, track); //! index in JTracks of this GNN input track (not the parent AOD Tracks index) |
| 174 | +DECLARE_SOA_COLUMN(TrackIndex, trackIndex, uint32_t); //! node index in the GNN input after track selection/truncation; need not match the constituent-array position |
| 175 | +// DECLARE_SOA_COLUMN(EdgeIndex, edgeIndex, uint8_t); //! unique in-jet edge index for the (i,j) constituent-track pair, i<j, triangular order i*(2N-i-1)/2+(j-i-1) |
| 176 | +// DECLARE_SOA_DYNAMIC_COLUMN(TrackIds, trackIds, //! inverse of the triangular edge indexing above: for n constituent tracks, recovers the (i,j) in-jet track index pair (i<j) this edge connects |
| 177 | +// [](uint8_t edgeIndex, int n) -> std::pair<uint8_t, uint8_t> { |
| 178 | +// int i = 0; |
| 179 | +// int offset = 0; |
| 180 | +// while (offset + (n - 1 - i) <= static_cast<int>(edgeIndex)) { |
| 181 | +// offset += (n - 1 - i); |
| 182 | +// i++; |
| 183 | +// } |
| 184 | +// int j = i + 1 + (static_cast<int>(edgeIndex) - offset); |
| 185 | +// return std::pair<uint8_t, uint8_t>{static_cast<uint8_t>(i), static_cast<uint8_t>(j)}; |
| 186 | +// }); |
186 | 187 | } // namespace jetgnnindex |
187 | 188 |
|
188 | 189 | namespace jetgnnlabel |
189 | 190 | { |
190 | 191 | DECLARE_SOA_COLUMN(Origin, origin, uint8_t); //! trkOrigin from vertexClustering() (0: non-physical primary, 1: charm, 2: beauty, 3: primary vertex, 4: other secondary) |
191 | 192 | DECLARE_SOA_COLUMN(VertexIndex, vertexIndex, uint8_t); //! trkVtxIndex from vertexClustering() (0: primary vertex, >0: secondary vertex, ranked by distance to PV) |
192 | | -DECLARE_SOA_COLUMN(SameVertex, sameVertex, bool); //! true if the (i,j) constituent-track pair of this edge share the same in-jet vertex cluster (same trkVtxIndex from vertexClustering()) |
| 193 | +// DECLARE_SOA_COLUMN(SameVertex, sameVertex, bool); //! true if the (i,j) constituent-track pair of this edge share the same in-jet vertex cluster (same trkVtxIndex from vertexClustering()) |
193 | 194 | } // namespace jetgnnlabel |
194 | 195 |
|
195 | 196 | namespace jetgnnscore |
196 | 197 | { |
197 | | -DECLARE_SOA_COLUMN(ScoreML, scoreML, float); //! GNN prediction score (track/node level, or edge level symmetrised e.g. averaged from the N*N GNN edge matrix) |
| 198 | +DECLARE_SOA_COLUMN(ScoreML, scoreML, float); //! GNN prediction score (track/node level, or edge level symmetrised e.g. averaged from the N*N GNN edge matrix) |
| 199 | +DECLARE_SOA_COLUMN(OriginScores, originScores, std::vector<float>); //! one score per origin class, in jetgnnlabel::Origin order (0..4); producer defines logits/probabilities |
198 | 200 | } // namespace jetgnnscore |
199 | 201 |
|
200 | | -#define DECLARE_JET_GNNTRACKINDEX_TABLE(_jet_type_, _description_) \ |
201 | | - namespace _jet_type_##gnntrackindextable \ |
202 | | - { \ |
203 | | - DECLARE_SOA_INDEX_COLUMN(_jet_type_, jet); \ |
204 | | - } \ |
205 | | - DECLARE_SOA_TABLE(_jet_type_##GNNTrack, "AOD", _description_, \ |
206 | | - o2::soa::Index<>, \ |
207 | | - _jet_type_##gnntrackindextable::_jet_type_##Id, \ |
208 | | - jetgnnindex::JTrackId, \ |
209 | | - jetgnnindex::TrackIndex); \ |
210 | | - namespace _jet_type_##gnntrackindices \ |
211 | | - { \ |
212 | | - DECLARE_SOA_ARRAY_INDEX_COLUMN(_jet_type_##GNNTrack, tracks); \ |
213 | | - } \ |
214 | | - DECLARE_SOA_TABLE(_jet_type_##GNNTrackIndices, "AOD", _description_ "I", \ |
| 202 | +// GNNTrack has one row per evaluated (jet, track) pair. Its jet and track indices |
| 203 | +// identify the pair independently of the ordering in JetConstituents. |
| 204 | +// GNNTrackIndices is a positional jet extension: write one row for every jet in |
| 205 | +// Jets order, including an empty array for jets without evaluated tracks. Store |
| 206 | +// GNNTrack row indices (e.g. the backbone producer's lastIndex()), not JTrackIds. |
| 207 | +#define DECLARE_JET_GNNTRACKINDEX_TABLE(_jet_type_, _description_) \ |
| 208 | + namespace _jet_type_##gnntrackindextable \ |
| 209 | + { \ |
| 210 | + DECLARE_SOA_INDEX_COLUMN(_jet_type_, jet); \ |
| 211 | + } \ |
| 212 | + DECLARE_SOA_TABLE(_jet_type_##GNNTrack, "AOD", _description_, \ |
| 213 | + o2::soa::Index<>, \ |
| 214 | + _jet_type_##gnntrackindextable::_jet_type_##Id, \ |
| 215 | + jetgnnindex::JTrackId, \ |
| 216 | + jetgnnindex::TrackIndex); \ |
| 217 | + namespace _jet_type_##gnntrackindices \ |
| 218 | + { \ |
| 219 | + DECLARE_SOA_ARRAY_INDEX_COLUMN_FULL(_jet_type_##GNNTrack, tracksGnn, int32_t, _jet_type_##GNNTrack, ""); \ |
| 220 | + } \ |
| 221 | + DECLARE_SOA_TABLE(_jet_type_##GNNTrackIndices, "AOD", _description_ "I", \ |
215 | 222 | _jet_type_##gnntrackindices::_jet_type_##GNNTrackIds); |
216 | 223 |
|
217 | | -#define DECLARE_JET_GNNEDGEINDEX_TABLE(_jet_type_, _description_) \ |
218 | | - namespace _jet_type_##gnnedgeindextable \ |
219 | | - { \ |
220 | | - DECLARE_SOA_INDEX_COLUMN(_jet_type_, jet); \ |
221 | | - } \ |
222 | | - DECLARE_SOA_TABLE(_jet_type_##GNNEdge, "AOD", _description_, \ |
223 | | - o2::soa::Index<>, \ |
224 | | - _jet_type_##gnnedgeindextable::_jet_type_##Id, \ |
225 | | - jetgnnindex::EdgeIndex, \ |
226 | | - jetgnnindex::TrackIds<jetgnnindex::EdgeIndex>); \ |
227 | | - namespace _jet_type_##gnnedgeindices \ |
228 | | - { \ |
229 | | - DECLARE_SOA_ARRAY_INDEX_COLUMN(_jet_type_##GNNEdge, edges); \ |
230 | | - } \ |
231 | | - DECLARE_SOA_TABLE(_jet_type_##GNNEdgeIndices, "AOD", _description_ "I", \ |
232 | | - _jet_type_##gnnedgeindices::_jet_type_##GNNEdgeIds); |
| 224 | +// #define DECLARE_JET_GNNEDGEINDEX_TABLE(_jet_type_, _description_) \ |
| 225 | +// namespace _jet_type_##gnnedgeindextable \ |
| 226 | +// { \ |
| 227 | +// DECLARE_SOA_INDEX_COLUMN(_jet_type_, jet); \ |
| 228 | +// } \ |
| 229 | +// DECLARE_SOA_TABLE(_jet_type_##GNNEdge, "AOD", _description_, \ |
| 230 | +// o2::soa::Index<>, \ |
| 231 | +// _jet_type_##gnnedgeindextable::_jet_type_##Id, \ |
| 232 | +// jetgnnindex::EdgeIndex, \ |
| 233 | +// jetgnnindex::TrackIds<jetgnnindex::EdgeIndex>); \ |
| 234 | +// namespace _jet_type_##gnnedgeindices \ |
| 235 | +// { \ |
| 236 | +// DECLARE_SOA_ARRAY_INDEX_COLUMN(_jet_type_##GNNEdge, edges); \ |
| 237 | +// } \ |
| 238 | +// DECLARE_SOA_TABLE(_jet_type_##GNNEdgeIndices, "AOD", _description_ "I", \ |
| 239 | +// _jet_type_##gnnedgeindices::_jet_type_##GNNEdgeIds); |
233 | 240 |
|
234 | 241 | // In-jet track/edge index backbone tables (own the in-jet ordering + the back-reference to the original track) |
235 | 242 | DECLARE_JET_GNNTRACKINDEX_TABLE(ChargedJet, "CJGNT"); |
236 | 243 | DECLARE_JET_GNNTRACKINDEX_TABLE(ChargedMCDetectorLevelJet, "CDJGNT"); |
237 | | -DECLARE_JET_GNNEDGEINDEX_TABLE(ChargedJet, "CJGNE"); |
238 | | -DECLARE_JET_GNNEDGEINDEX_TABLE(ChargedMCDetectorLevelJet, "CDJGNE"); |
| 244 | +// DECLARE_JET_GNNEDGEINDEX_TABLE(ChargedJet, "CJGNE"); |
| 245 | +// DECLARE_JET_GNNEDGEINDEX_TABLE(ChargedMCDetectorLevelJet, "CDJGNE"); |
239 | 246 |
|
240 | 247 | #undef DECLARE_JET_GNNTRACKINDEX_TABLE |
241 | | -#undef DECLARE_JET_GNNEDGEINDEX_TABLE |
| 248 | +// #undef DECLARE_JET_GNNEDGEINDEX_TABLE |
242 | 249 |
|
243 | 250 | // Truth labels from vertexClustering() (MC detector level only). Thin tables: join positionally with |
244 | 251 | // ChargedMCDetectorLevelJetGNNTrack / ChargedMCDetectorLevelJetGNNEdge (same producer loop, same row order). |
245 | 252 | DECLARE_SOA_TABLE(ChargedMCDetectorLevelJetTrackOriginDef, "AOD", "CDJTOD", jetgnnlabel::Origin); |
246 | 253 | DECLARE_SOA_TABLE(ChargedMCDetectorLevelJetVertexDef, "AOD", "CDJTVD", jetgnnlabel::VertexIndex); |
247 | | -DECLARE_SOA_TABLE(ChargedMCDetectorLevelJetEdgeDef, "AOD", "CDJEDF", jetgnnlabel::SameVertex); |
| 254 | +// DECLARE_SOA_TABLE(ChargedMCDetectorLevelJetEdgeDef, "AOD", "CDJEDF", jetgnnlabel::SameVertex); |
248 | 255 |
|
249 | | -// GNN ScoreML outputs, track (node) level, data and MC detector level. Thin tables: join positionally with |
250 | | -// ChargedJetGNNTrack / ChargedMCDetectorLevelJetGNNTrack. |
251 | | -DECLARE_SOA_TABLE(ChargedJetTrackTags, "AOD", "CJTRKT", jetgnnscore::ScoreML); |
252 | | -DECLARE_SOA_TABLE(ChargedMCDetectorLevelJetTrackTags, "AOD", "CDJTRKT", jetgnnscore::ScoreML); |
| 256 | +// GNN track-origin outputs, data and MC detector level. Thin tables: write one |
| 257 | +// score vector per GNNTrack row, in the same row order as the backbone table. |
| 258 | +// The vector contains classes for this track, not scores for multiple tracks. |
| 259 | +DECLARE_SOA_TABLE(ChargedJetTrackTags, "AOD", "CJTRKT", jetgnnscore::OriginScores); |
| 260 | +DECLARE_SOA_TABLE(ChargedMCDetectorLevelJetTrackTags, "AOD", "CDJTRKT", jetgnnscore::OriginScores); |
253 | 261 |
|
254 | 262 | // GNN ScoreML outputs, edge level, data and MC detector level. Thin tables: join positionally with |
255 | 263 | // ChargedJetGNNEdge / ChargedMCDetectorLevelJetGNNEdge. |
256 | | -DECLARE_SOA_TABLE(ChargedJetEdgeTags, "AOD", "CJEDGT", jetgnnscore::ScoreML); |
257 | | -DECLARE_SOA_TABLE(ChargedMCDetectorLevelJetEdgeTags, "AOD", "CDJEDGT", jetgnnscore::ScoreML); |
258 | | - |
259 | | -// Convenience joined types combining the backbone (in-jet ordering / original-track reference) with the thin |
260 | | -// content tables, so `.template tracks_as<ChargedMCDetectorLevelJetTrackLabels>()` etc. can be used directly. |
261 | | -using ChargedJetGNNTrackLabels = o2::soa::Join<ChargedJetGNNTrack, ChargedJetTrackTags>; |
262 | | -using ChargedJetGNNEdgeLabels = o2::soa::Join<ChargedJetGNNEdge, ChargedJetEdgeTags>; |
| 264 | +// DECLARE_SOA_TABLE(ChargedJetEdgeTags, "AOD", "CJEDGT", jetgnnscore::ScoreML); |
| 265 | +// DECLARE_SOA_TABLE(ChargedMCDetectorLevelJetEdgeTags, "AOD", "CDJEDGT", jetgnnscore::ScoreML); |
| 266 | + |
| 267 | +// Prediction joins do not require MC truth tables. Subscribe to the prediction |
| 268 | +// join and JTracks in the consuming task to bind both index levels: |
| 269 | +// for (auto const& prediction : jet.tracksGnn_as<ChargedJetGNNTrackPredictions>()) { |
| 270 | +// auto track = prediction.track_as<JTracks>(); |
| 271 | +// auto scores = prediction.originScores(); |
| 272 | +// } |
| 273 | +using ChargedJetGNNTrackPredictions = o2::soa::Join<ChargedJetGNNTrack, ChargedJetTrackTags>; |
| 274 | +using ChargedMCDetectorLevelJetGNNTrackPredictions = o2::soa::Join<ChargedMCDetectorLevelJetGNNTrack, ChargedMCDetectorLevelJetTrackTags>; |
| 275 | +using ChargedJetsWithGNNTrackOrigins = o2::soa::Join<ChargedJets, ChargedJetConstituents, ChargedJetGNNTrackIndices>; |
| 276 | +using ChargedMCDetectorLevelJetsWithGNNTrackOrigins = o2::soa::Join<ChargedMCDetectorLevelJets, ChargedMCDetectorLevelJetConstituents, ChargedMCDetectorLevelJetGNNTrackIndices>; |
| 277 | + |
| 278 | +// Convenience joins including truth labels when available (MC detector level). |
| 279 | +using ChargedJetGNNTrackLabels = ChargedJetGNNTrackPredictions; |
| 280 | +// using ChargedJetGNNEdgeLabels = o2::soa::Join<ChargedJetGNNEdge, ChargedJetEdgeTags>; |
263 | 281 | using ChargedMCDetectorLevelJetGNNTrackLabels = o2::soa::Join<ChargedMCDetectorLevelJetGNNTrack, ChargedMCDetectorLevelJetTrackOriginDef, ChargedMCDetectorLevelJetVertexDef, ChargedMCDetectorLevelJetTrackTags>; |
264 | | -using ChargedMCDetectorLevelJetGNNEdgeLabels = o2::soa::Join<ChargedMCDetectorLevelJetGNNEdge, ChargedMCDetectorLevelJetEdgeDef, ChargedMCDetectorLevelJetEdgeTags>; |
| 282 | +// using ChargedMCDetectorLevelJetGNNEdgeLabels = o2::soa::Join<ChargedMCDetectorLevelJetGNNEdge, ChargedMCDetectorLevelJetEdgeDef, ChargedMCDetectorLevelJetEdgeTags>; |
265 | 283 |
|
266 | 284 | } // namespace o2::aod |
267 | 285 |
|
|
0 commit comments