|
| 1 | +// Copyright 2019-2020 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 | +#ifndef ALICEO2_TRK_GEOMETRYTGEO_H |
| 13 | +#define ALICEO2_TRK_GEOMETRYTGEO_H |
| 14 | + |
| 15 | +#include <memory> |
| 16 | +#include <DetectorsCommonDataFormats/DetMatrixCache.h> |
| 17 | +#include "DetectorsCommonDataFormats/DetID.h" |
| 18 | +#include "TRKBase/TRKBaseParam.h" |
| 19 | + |
| 20 | +namespace o2 |
| 21 | +{ |
| 22 | +namespace trk |
| 23 | +{ |
| 24 | +class GeometryTGeo : public o2::detectors::DetMatrixCache |
| 25 | +{ |
| 26 | + public: |
| 27 | + using Mat3D = o2::math_utils::Transform3D; |
| 28 | + using DetMatrixCache::getMatrixL2G; |
| 29 | + using DetMatrixCache::getMatrixT2GRot; |
| 30 | + using DetMatrixCache::getMatrixT2L; |
| 31 | + // this method is not advised for ITS: for barrel detectors whose tracking frame is just a rotation |
| 32 | + // it is cheaper to use T2GRot |
| 33 | + using DetMatrixCache::getMatrixT2G; |
| 34 | + GeometryTGeo(bool build = false, int loadTrans = 0); |
| 35 | + ~GeometryTGeo(); |
| 36 | + void Build(int loadTrans); |
| 37 | + void fillMatrixCache(int mask); |
| 38 | + static GeometryTGeo* Instance() |
| 39 | + { |
| 40 | + if (!sInstance) { |
| 41 | + sInstance = std::make_unique<GeometryTGeo>(true, 0); |
| 42 | + } |
| 43 | + return sInstance.get(); |
| 44 | + }; |
| 45 | + static const char* getTRKVolPattern() { return sVolumeName.c_str(); } |
| 46 | + static const char* getTRKLayerPattern() { return sLayerName.c_str(); } |
| 47 | + static const char* getTRKPetalAssemblyPattern() { return sPetalAssemblyName.c_str(); } |
| 48 | + static const char* getTRKPetalPattern() { return sPetalName.c_str(); } |
| 49 | + static const char* getTRKPetalDiskPattern() { return sPetalDiskName.c_str(); } |
| 50 | + static const char* getTRKPetalLayerPattern() { return sPetalLayerName.c_str(); } |
| 51 | + static const char* getTRKStavePattern() { return sStaveName.c_str(); } |
| 52 | + static const char* getTRKHalfStavePattern() { return sHalfStaveName.c_str(); } |
| 53 | + static const char* getTRKModulePattern() { return sModuleName.c_str(); } |
| 54 | + static const char* getTRKChipPattern() { return sChipName.c_str(); } |
| 55 | + static const char* getTRKSensorPattern() { return sSensorName.c_str(); } |
| 56 | + static const char* getTRKDeadzonePattern() { return sDeadzoneName.c_str(); } |
| 57 | + static const char* getTRKMetalStackPattern() { return sMetalStackName.c_str(); } |
| 58 | + |
| 59 | + static const char* getTRKWrapVolPattern() { return sWrapperVolumeName.c_str(); } |
| 60 | + |
| 61 | + int getNumberOfChips() const { return mSize; } |
| 62 | + |
| 63 | + /// Determines the number of active parts in the Geometry |
| 64 | + int extractNumberOfLayersMLOT(); |
| 65 | + int extractNumberOfLayersVD() const; |
| 66 | + int extractNumberOfPetalsVD() const; |
| 67 | + int extractNumberOfActivePartsVD() const; |
| 68 | + int extractNumberOfDisksVD() const; |
| 69 | + int extractNumberOfChipsPerPetalVD() const; |
| 70 | + int extractNumberOfStavesMLOT(int lay) const; |
| 71 | + int extractNumberOfHalfStavesMLOT(int lay) const; |
| 72 | + int extractNumberOfModulesMLOT(int lay) const; |
| 73 | + int extractNumberOfChipsMLOT(int lay) const; |
| 74 | + |
| 75 | + /// Extract number following the prefix in the name string |
| 76 | + int extractVolumeCopy(const char* name, const char* prefix) const; |
| 77 | + |
| 78 | + int getNumberOfLayersMLOT() const { return mNumberOfLayersMLOT; } |
| 79 | + int getNumberOfActivePartsVD() const { return mNumberOfActivePartsVD; } |
| 80 | + int getNumberOfHalfStaves(int lay) const { return mNumberOfHalfStaves[lay]; } |
| 81 | + |
| 82 | + bool isOwner() const { return mOwner; } |
| 83 | + void setOwner(bool v) { mOwner = v; } |
| 84 | + |
| 85 | + void Print(Option_t* opt = "") const; |
| 86 | + void PrintChipID(int index, int subDetID, int petalcase, int disk, int lay, int stave, int halfstave, int mod, int chip) const; |
| 87 | + |
| 88 | + int getSubDetID(int index) const; |
| 89 | + int getPetalCase(int index) const; |
| 90 | + int getDisk(int index) const; |
| 91 | + int getLayer(int index) const; |
| 92 | + int getStave(int index) const; |
| 93 | + int getHalfStave(int index) const; |
| 94 | + int getModule(int index) const; |
| 95 | + int getChip(int index) const; |
| 96 | + |
| 97 | + void defineMLOTSensors(); |
| 98 | + int getBarrelLayer(int) const; |
| 99 | + |
| 100 | + // sensor ref X and alpha for ML & OT |
| 101 | + void extractSensorXAlphaMLOT(int, float&, float&); |
| 102 | + |
| 103 | + // cache for tracking frames (ML & OT) |
| 104 | + bool isTrackingFrameCachedMLOT() const { return !mCacheRefXMLOT.empty(); } |
| 105 | + void fillTrackingFramesCacheMLOT(); |
| 106 | + |
| 107 | + float getSensorRefAlphaMLOT(int chipId) const |
| 108 | + { |
| 109 | + assert(getSubDetID(chipId) != 0 && "Called MLOT getter with VD chipId"); |
| 110 | + const int local = chipId - getNumberOfActivePartsVD(); |
| 111 | + assert(local >= 0 && local < (int)mCacheRefAlphaMLOT.size()); |
| 112 | + return mCacheRefAlphaMLOT[local]; |
| 113 | + } |
| 114 | + |
| 115 | + float getSensorXMLOT(int chipId) const |
| 116 | + { |
| 117 | + assert(getSubDetID(chipId) != 0 && "Called MLOT getter with VD chipId"); |
| 118 | + const int local = chipId - getNumberOfActivePartsVD(); |
| 119 | + assert(local >= 0 && local < (int)mCacheRefXMLOT.size()); |
| 120 | + return mCacheRefXMLOT[local]; |
| 121 | + } |
| 122 | + |
| 123 | + // create matrix for tracking to local frame for MLOT |
| 124 | + TGeoHMatrix& createT2LMatrixMLOT(int); |
| 125 | + |
| 126 | + /// This routine computes the chip index number from the subDetID, petal, disk, layer, stave /// TODO: retrieve also from chip when chips will be available |
| 127 | + /// This routine computes the chip index number from the subDetID, petal, disk, layer, stave, half stave, module, chip |
| 128 | + /// \param int subDetID The subdetector ID, 0 for VD, 1 for MLOT |
| 129 | + /// \param int petalcase The petal case number for VD, from 0 to 3 |
| 130 | + /// \param int disk The disk number for VD, from 0 to 5 |
| 131 | + /// \param int lay The layer number. Starting from 0 both for VD and MLOT |
| 132 | + /// \param int stave The stave number for MLOT. Starting from 0 |
| 133 | + /// \param int halfstave The half stave number for MLOT. Can be 0 or 1 |
| 134 | + /// \param int module The module number for MLOT, from 0 to 10 (or 20) |
| 135 | + /// \param int chip The chip number for MLOT, from 0 to 8 |
| 136 | + unsigned short getChipIndex(int subDetID, int petalcase, int disk, int lay, int stave, int halfstave, int mod, int chip) const; |
| 137 | + |
| 138 | + /// This routine computes the chip index number from the subDetID, volume, layer, stave, half stave, module, chip |
| 139 | + /// \param int subDetID The subdetector ID, 0 for VD, 1 for MLOT |
| 140 | + /// \param int volume is needed only with the current configuration for VD where each single element is a volume. // TODO: when the geometry naming scheme will be changed, change this method |
| 141 | + /// \param int lay The layer number for the MLOT. In the current configuration for VD this is not needed. // TODO: when the geometry naming scheme will be changed, change this method |
| 142 | + /// \param int stave The stave number in each layer for MLOT. Starting from 0. |
| 143 | + /// \param int halfstave The half stave number for MLOT. Can be 0 or 1 |
| 144 | + /// \param int module The module number for MLOT, from 0 to 10 (or 20) |
| 145 | + /// \param int chip The chip number for MLOT, from 0 to 8 |
| 146 | + unsigned short getChipIndex(int subDetID, int volume, int lay, int stave, int halfstave, int mod, int chip) const; |
| 147 | + |
| 148 | + /// This routine computes subDetID, petal, disk, layer, stave, half stave, module, chip, given the chip index number |
| 149 | + /// \param int index The chip index number, starting from 0 |
| 150 | + /// \param int subDetID The subdetector ID, 0 for VD, 1 for MLOT |
| 151 | + /// \param int petalcase The petal case number for VD, from 0 to 3 |
| 152 | + /// \param int disk The disk number for VD, from 0 to 5 |
| 153 | + /// \param int lay The layer number. Starting from 0 both for VD and MLOT |
| 154 | + /// \param int stave The stave number for MLOT. Starting from 0 |
| 155 | + /// \param int halfstave The half stave number for MLOT. Can be 0 or 1 |
| 156 | + /// \param int module The module number for MLOT, from 0 to 10 (or 20) |
| 157 | + /// \param int chip The chip number for MLOT, from 0 to 8 |
| 158 | + bool getChipID(int index, int& subDetID, int& petalcase, int& disk, int& lay, int& stave, int& halfstave, int& mod, int& chip) const; |
| 159 | + |
| 160 | + unsigned short getLastChipIndex(int lay) const { return mLastChipIndex[lay]; } |
| 161 | + unsigned short getFirstChipIndex(int lay, int petalcase, int subDetID) const |
| 162 | + { |
| 163 | + /// Get the first chip index of the active petal (VD) or layer (MLOT) |
| 164 | + if (subDetID == 0) { // VD |
| 165 | + return (petalcase == 0) ? 0 : mLastChipIndexVD[petalcase - 1] + 1; |
| 166 | + } else if (subDetID == 1) { // MLOT |
| 167 | + return mLastChipIndex[lay + mNumberOfPetalsVD - 1] + 1; |
| 168 | + } |
| 169 | + return -1; // not found |
| 170 | + } |
| 171 | + |
| 172 | + /// Get the transformation matrix of the SENSOR (not necessary the same as the chip) |
| 173 | + /// for a given chip 'index' by quering the TGeoManager |
| 174 | + TGeoHMatrix* extractMatrixSensor(int index) const; |
| 175 | + |
| 176 | + TString getMatrixPath(int index) const; |
| 177 | + |
| 178 | +#ifdef ENABLE_UPGRADES |
| 179 | + static const char* composeSymNameTRK(int d) |
| 180 | + { |
| 181 | + return Form("%s_%d", o2::detectors::DetID(o2::detectors::DetID::TRK).getName(), d); |
| 182 | + } |
| 183 | +#endif |
| 184 | + |
| 185 | + static const char* composeSymNameLayer(int d, int layer); |
| 186 | + static const char* composeSymNameStave(int d, int layer); |
| 187 | + static const char* composeSymNameModule(int d, int layer); |
| 188 | + static const char* composeSymNameChip(int d, int layer); |
| 189 | + static const char* composeSymNameSensor(int d, int layer); |
| 190 | + |
| 191 | + protected: |
| 192 | + static constexpr int MAXLAYERS = 20; ///< max number of active layers |
| 193 | + |
| 194 | + static std::string sVolumeName; |
| 195 | + static std::string sLayerName; |
| 196 | + static std::string sPetalAssemblyName; |
| 197 | + static std::string sPetalName; |
| 198 | + static std::string sPetalDiskName; |
| 199 | + static std::string sPetalLayerName; |
| 200 | + static std::string sStaveName; |
| 201 | + static std::string sHalfStaveName; |
| 202 | + static std::string sModuleName; |
| 203 | + static std::string sChipName; |
| 204 | + static std::string sSensorName; |
| 205 | + static std::string sDeadzoneName; |
| 206 | + static std::string sMetalStackName; |
| 207 | + |
| 208 | + static std::string sWrapperVolumeName; ///< Wrapper volume name, not implemented at the moment |
| 209 | + |
| 210 | + Int_t mNumberOfLayersMLOT; ///< number of layers |
| 211 | + Int_t mNumberOfActivePartsVD; ///< number of layers |
| 212 | + Int_t mNumberOfLayersVD; ///< number of layers |
| 213 | + Int_t mNumberOfPetalsVD; ///< number of Petals = chip in each VD layer |
| 214 | + Int_t mNumberOfDisksVD; ///< number of Disks = 6 |
| 215 | + std::vector<int> mNumberOfStaves; ///< Number Of Staves per layer in ML/OT |
| 216 | + std::vector<int> mNumberOfHalfStaves; ///< Number Of Half staves in each stave of the layer in ML/OT |
| 217 | + std::vector<int> mNumberOfModules; ///< Number Of Modules per stave (half stave) in ML/OT |
| 218 | + std::vector<int> mNumberOfChips; ///< number of chips per module in ML/OT |
| 219 | + std::vector<int> mNumberOfChipsPerLayerVD; ///< number of chips per layer VD ( = number of petals) |
| 220 | + std::vector<int> mNumberOfChipsPerLayerMLOT; ///< number of chips per layer MLOT |
| 221 | + std::vector<int> mNumbersOfChipPerDiskVD; ///< numbersOfChipPerDiskVD |
| 222 | + std::vector<int> mNumberOfChipsPerPetalVD; ///< numbersOfChipPerPetalVD |
| 223 | + // std::vector<int> mNumberOfChipsPerStave; ///< number of chips per stave in ML/OT |
| 224 | + // std::vector<int> mNumberOfChipsPerHalfStave; ///< number of chips per half stave in ML/OT |
| 225 | + // std::vector<int> mNumberOfChipsPerModule; ///< number of chips per module in ML/OT |
| 226 | + std::vector<unsigned short> mLastChipIndex; ///< max ID of the detctor in the petal(VD) or layer(MLOT) |
| 227 | + std::vector<unsigned short> mLastChipIndexVD; ///< max ID of the detctor in the layer for the VD |
| 228 | + std::vector<unsigned short> mLastChipIndexMLOT; ///< max ID of the detctor in the layer for the MLOT |
| 229 | + |
| 230 | + std::array<char, MAXLAYERS> mLayerToWrapper; ///< Layer to wrapper correspondence, not implemented yet |
| 231 | + |
| 232 | + bool mOwner = true; //! is it owned by the singleton? |
| 233 | + |
| 234 | + std::vector<int> sensorsMLOT; |
| 235 | + std::vector<float> mCacheRefXMLOT; /// cache for X of ML and OT |
| 236 | + std::vector<float> mCacheRefAlphaMLOT; /// cache for sensor ref alpha ML and OT |
| 237 | + |
| 238 | + eMLOTLayout mLayoutMLOT; // ML and OT detector layout design |
| 239 | + |
| 240 | + private: |
| 241 | + static std::unique_ptr<o2::trk::GeometryTGeo> sInstance; |
| 242 | +}; |
| 243 | + |
| 244 | +} // namespace trk |
| 245 | +} // namespace o2 |
| 246 | +#endif |
0 commit comments