|
| 1 | +// Copyright 2019-2026 CERN and copyright holders of ALICE O2. |
| 2 | +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. |
| 3 | +// All rights not expressly granted are reserved. |
| 4 | +// |
| 5 | +// This software is distributed under the terms of the GNU General Public |
| 6 | +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". |
| 7 | +// |
| 8 | +// In applying this license CERN does not waive the privileges and immunities |
| 9 | +// granted to it by virtue of its status as an Intergovernmental Organization |
| 10 | +// or submit itself to any jurisdiction. |
| 11 | + |
| 12 | +/// \file TopologyDictionary.h |
| 13 | +/// \brief Positions and errors of TRK and FT3 clusters per layer and pixel pattern |
| 14 | +/// |
| 15 | +/// As the ITS's topology dictionary, measured from MC, but per layer: the |
| 16 | +/// layer's depth (the local y positions are taken at) and, per common pattern |
| 17 | +/// and per group of rare ones, the width (normalised median absolute |
| 18 | +/// deviation) and median of the residuals hit - centre of gravity across |
| 19 | +/// (local x) and along (local z). Every pattern finds an entry: its own, else |
| 20 | +/// its group's. On the VD the dictionary works in the flat frame of |
| 21 | +/// SegmentationChip::curvedToFlat; getClusterCoordinates returns O2's curved |
| 22 | +/// local coordinates. |
| 23 | + |
| 24 | +#ifndef ALICEO2_TRKFT3_TOPOLOGYDICTIONARY_H |
| 25 | +#define ALICEO2_TRKFT3_TOPOLOGYDICTIONARY_H |
| 26 | + |
| 27 | +#include "DataFormatsTRKFT3/Cluster.h" |
| 28 | +#include "DetectorsCommonDataFormats/DetID.h" |
| 29 | +#include "MathUtils/Cartesian.h" |
| 30 | +#include <Rtypes.h> |
| 31 | +#include <algorithm> |
| 32 | +#include <string> |
| 33 | +#include <unordered_map> |
| 34 | +#include <vector> |
| 35 | + |
| 36 | +namespace o2::trkft3 |
| 37 | +{ |
| 38 | + |
| 39 | +template <int DetID> |
| 40 | +class BuildTopologyDictionary; |
| 41 | + |
| 42 | +/// A common pattern, or the group of the rare patterns with the same span |
| 43 | +/// classes (spans 1 to 5, 6 or more) on both axes. |
| 44 | +struct DictionaryEntry { |
| 45 | + std::vector<unsigned char> pattern; ///< row span, column span, pixel bits as the clusteriser streams them; empty for a group |
| 46 | + float xCOG = 0.f; ///< centre of gravity from the reference pixel across [pitches] |
| 47 | + float zCOG = 0.f; ///< along [pitches] |
| 48 | + float xWidth = 0.f; ///< the residuals' width across [cm] |
| 49 | + float zWidth = 0.f; ///< along [cm] |
| 50 | + float xOffset = 0.f; ///< the residuals' median across [cm] |
| 51 | + float zOffset = 0.f; ///< along [cm] |
| 52 | + bool isGroup = false; |
| 53 | + |
| 54 | + ClassDefNV(DictionaryEntry, 1); |
| 55 | +}; |
| 56 | + |
| 57 | +struct LayerDictionary { |
| 58 | + float depth = 0.f; ///< the local y positions are taken at [cm] |
| 59 | + std::vector<DictionaryEntry> entries; ///< the common patterns, most frequent first, then the groups |
| 60 | + std::unordered_multimap<unsigned long, int> hashMap; ///< itsmft::ClusterTopology hash -> common pattern's entry |
| 61 | + |
| 62 | + ClassDefNV(LayerDictionary, 1); |
| 63 | +}; |
| 64 | + |
| 65 | +template <int DetID> |
| 66 | +class TopologyDictionary |
| 67 | +{ |
| 68 | + static_assert(DetID == o2::detectors::DetID::TRK || DetID == o2::detectors::DetID::FT3, "only TRK and FT3 dictionaries are supported"); |
| 69 | + |
| 70 | + public: |
| 71 | + using ClusterType = Cluster<DetID>; |
| 72 | + |
| 73 | + static constexpr int NSpanClasses = 6; ///< spans 1 to 5, 6 or more |
| 74 | + static constexpr int NGroups = NSpanClasses * NSpanClasses; ///< one group per pair of span classes, row class major |
| 75 | + |
| 76 | + static constexpr int spanClass(int span) noexcept { return std::min(span, NSpanClasses) - 1; } |
| 77 | + static constexpr int groupOf(int rowSpan, int colSpan) noexcept { return spanClass(rowSpan) * NSpanClasses + spanClass(colSpan); } |
| 78 | + |
| 79 | + /// A cluster's layer: TRK's VD layers, then ML/OT (GeometryTGeo::getLayerTRK); FT3's discs. -1 for none (a VD disc). |
| 80 | + static int layerOf(const ClusterType& cluster) noexcept; |
| 81 | + /// A point from O2's local frame to the layer's flat frame (the VD's unrolled; elsewhere the same). |
| 82 | + static math_utils::Point3D<float> localToFlat(const ClusterType& cluster, const math_utils::Point3D<float>& local) noexcept; |
| 83 | + /// The cluster's centre of gravity in the flat frame at y = 0. \a pattern: row span, column span, pixel bits. |
| 84 | + static math_utils::Point3D<float> centreOfGravity(const ClusterType& cluster, const unsigned char* pattern) noexcept; |
| 85 | + |
| 86 | + [[nodiscard]] int getNumberOfLayers() const noexcept { return static_cast<int>(mLayers.size()); } |
| 87 | + [[nodiscard]] const LayerDictionary& getLayer(int layer) const { return mLayers.at(layer); } |
| 88 | + [[nodiscard]] const DictionaryEntry& getEntry(int layer, int id) const { return mLayers.at(layer).entries.at(id); } |
| 89 | + |
| 90 | + /// The pattern's entry on the layer: its own if it is common, else its group's. |
| 91 | + [[nodiscard]] int findID(int layer, const unsigned char* pattern) const; |
| 92 | + |
| 93 | + /// The position in the flat frame: the entry's centre of gravity, plus its offsets if applied, at the layer's depth. |
| 94 | + [[nodiscard]] math_utils::Point3D<float> getFlatCoordinates(const ClusterType& cluster, const unsigned char* pattern, int id) const; |
| 95 | + /// The same in O2's local frame: curved on the VD. |
| 96 | + [[nodiscard]] math_utils::Point3D<float> getClusterCoordinates(const ClusterType& cluster, const unsigned char* pattern, int id) const; |
| 97 | + [[nodiscard]] math_utils::Point3D<float> getClusterCoordinates(const ClusterType& cluster, const unsigned char* pattern) const |
| 98 | + { |
| 99 | + return getClusterCoordinates(cluster, pattern, findID(layerOf(cluster), pattern)); |
| 100 | + } |
| 101 | + |
| 102 | + [[nodiscard]] bool getApplyOffsets() const noexcept { return mApplyOffsets; } |
| 103 | + void setApplyOffsets(bool apply) noexcept { mApplyOffsets = apply; } |
| 104 | + |
| 105 | + void print() const; |
| 106 | + |
| 107 | + static TopologyDictionary* loadFrom(const std::string& fileName, const std::string& objName = "ccdb_object"); |
| 108 | + |
| 109 | + private: |
| 110 | + friend class BuildTopologyDictionary<DetID>; |
| 111 | + |
| 112 | + std::vector<LayerDictionary> mLayers; |
| 113 | + bool mApplyOffsets = false; |
| 114 | + |
| 115 | + ClassDefNV(TopologyDictionary, 1); |
| 116 | +}; |
| 117 | + |
| 118 | +using TRKTopologyDictionary = TopologyDictionary<o2::detectors::DetID::TRK>; |
| 119 | +using FT3TopologyDictionary = TopologyDictionary<o2::detectors::DetID::FT3>; |
| 120 | + |
| 121 | +} // namespace o2::trkft3 |
| 122 | + |
| 123 | +#endif |
0 commit comments