From 9c392f65f58372fbde0e4d744a8a720c543c82b9 Mon Sep 17 00:00:00 2001 From: Andrea Sofia Triolo Date: Tue, 1 Jul 2025 16:38:12 +0200 Subject: [PATCH 1/4] ALICE3-TRK: Detector.cxx modified to retrieve the correct Detector ID following the chosen indexing scheme --- .../TRK/base/include/TRKBase/GeometryTGeo.h | 8 +- .../ALICE3/TRK/base/src/GeometryTGeo.cxx | 21 +++-- .../include/TRKSimulation/Detector.h | 15 ++++ .../ALICE3/TRK/simulation/src/Detector.cxx | 89 ++++++++++++++++--- 4 files changed, 115 insertions(+), 18 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h b/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h index 852cb138e2be7..b4bdb1f1ab27a 100644 --- a/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h +++ b/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h @@ -80,7 +80,6 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache int getDisk(int index) const; /// This routine computes the chip index number from the subDetID, petal, disk, layer, stave /// TODO: retrieve also from chip when chips will be available - /// in substave /// \param int subDetID The subdetector ID, 0 for VD, 1 for MLOT /// \param int petalcase The petal case number for VD, from 0 to 3 /// \param int disk The disk number for VD, from 0 to 5 @@ -88,6 +87,13 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache /// \param int stave The stave number for MLOT. Starting from 0 int getChipIndex(int subDetID, int petalcase, int disk, int lay, int stave) const; + /// This routine computes the chip index number from the subDetID, volume, layer, stave /// TODO: retrieve also from chip when chips will be available + /// \param int subDetID The subdetector ID, 0 for VD, 1 for MLOT + /// \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 + /// \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 + /// \param int stave The stave number in each layer for MLOT. Starting from 0. + int getChipIndex(int subDetID, int volume, int lay, int stave) const; + /// This routine computes subDetID, petal, disk, layer, stave given the chip index number /// TODO: copute also from chip when chips will be available /// \param int index The chip index number, starting from 0 /// \param int subDetID The subdetector ID, 0 for VD, 1 for MLOT diff --git a/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx index 4547225033498..b8b44f1ed5b29 100644 --- a/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx @@ -155,7 +155,7 @@ int GeometryTGeo::getLayer(int index) const while (index > mLastChipIndex[lay]) { lay++; } - return lay - mNumberOfPetalsVD; /// numeration of MLOT layesrs starting from 1 + return lay - mNumberOfPetalsVD; /// numeration of MLOT layesrs starting from 0 } return -1; /// -1 if not found } @@ -207,6 +207,18 @@ int GeometryTGeo::getChipIndex(int subDetID, int petalcase, int disk, int lay, i return -1; // not found } +//__________________________________________________________________________ +int GeometryTGeo::getChipIndex(int subDetID, int volume, int lay, int stave) const +{ + if (subDetID == 0) { // VD + return volume; /// In the current configuration for VD, each volume is the sensor element = chip. // TODO: when the geometry naming scheme will be changed, change this method + + } else if (subDetID == 1) { // MLOT + return getFirstChipIndex(lay, -1, subDetID) + stave; + } + return -1; // not found +} + //__________________________________________________________________________ bool GeometryTGeo::getChipID(int index, int& subDetID, int& petalcase, int& disk, int& lay, int& stave) const { @@ -291,7 +303,7 @@ TGeoHMatrix* GeometryTGeo::extractMatrixSensor(int index) const auto path = getMatrixPath(index); static TGeoHMatrix matTmp; - gGeoManager->PushPath(); + // gGeoManager->PushPath(); // Preserve the modeler state. // if (!gGeoManager->cd(path.Data())) { // gGeoManager->PopPath(); @@ -440,7 +452,6 @@ int GeometryTGeo::extractNumberOfActivePartsVD() const if (vdV == nullptr) { LOG(fatal) << getName() << " volume " << getTRKVolPattern() << " is not in the geometry"; } - LOG(info) << "Volume name: " << getTRKVolPattern(); // Loop on all TRKV nodes, count Layer volumes by checking names TObjArray* nodes = vdV->GetNodes(); @@ -470,7 +481,6 @@ int GeometryTGeo::extractNumberOfDisksVD() const if (vdV == nullptr) { LOG(fatal) << getName() << " volume " << getTRKVolPattern() << " is not in the geometry"; } - LOG(info) << "Volume name: " << getTRKVolPattern(); // Loop on all TRKV nodes, count Layer volumes by checking names TObjArray* nodes = vdV->GetNodes(); @@ -500,7 +510,6 @@ int GeometryTGeo::extractNumberOfPetalsVD() const if (vdV == nullptr) { LOG(fatal) << getName() << " volume " << getTRKVolPattern() << " is not in the geometry"; } - LOG(info) << "Volume name: " << getTRKVolPattern(); // Loop on all TRKV nodes, count Layer volumes by checking names TObjArray* nodes = vdV->GetNodes(); @@ -530,7 +539,6 @@ int GeometryTGeo::extractNumberOfLayersVD() const if (vdV == nullptr) { LOG(fatal) << getName() << " volume " << getTRKVolPattern() << " is not in the geometry"; } - LOG(info) << "Volume name: " << getTRKVolPattern(); // Loop on all TRKV nodes, count Layer volumes by checking names TObjArray* nodes = vdV->GetNodes(); @@ -560,7 +568,6 @@ int GeometryTGeo::extractNumberOfChipsPerPetalVD() const if (vdV == nullptr) { LOG(fatal) << getName() << " volume " << getTRKVolPattern() << " is not in the geometry"; } - LOG(info) << "Volume name: " << getTRKVolPattern(); // Loop on all TRKV nodes, count Layer volumes by checking names TObjArray* nodes = vdV->GetNodes(); diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h index 31f3da7a00bb4..8ed5737abcb35 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/include/TRKSimulation/Detector.h @@ -31,6 +31,9 @@ namespace trk class Detector : public o2::base::DetImpl { public: + static constexpr Int_t mNumberOfVolumes = 44; /// hardcoded for the current geometry = 8 MLOT layers + 36 volumes in the VD. TODO: automatize or change according to the current geometry + static constexpr Int_t mNumberOfVolumesVD = 36; /// hardcoded for the current geometry = 36 volumes in the VD. TODO: automatize or change according to the current geometry + Detector(bool active); Detector(); ~Detector(); @@ -96,6 +99,18 @@ class Detector : public o2::base::DetImpl void defineSensitiveVolumes(); + protected: + std::vector mSensorID; //! layer identifiers + std::vector mSensorName; //! layer names + + public: + static constexpr Int_t sNumberVDPetalCases = 4; //! Number of VD petals + int getNumberOfLayers() const { return mLayers.size(); } //! Number of TRK layers + int getNumberOfLayersVD() const { return mPetalCases[0].mPetalLayers.size(); } + int getNumberOfDisksVD() const { return mPetalCases[0].mPetalDisks.size(); } + + void Print(FairVolume* vol, int volume, int subDetID, int layer, int stave, int halfstave, int chipID) const; + template friend class o2::base::DetImpl; ClassDefOverride(Detector, 1); diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx index 9b8ffc07b2d0e..e70e7ef31035a 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx @@ -53,6 +53,28 @@ Detector::Detector(bool active) configServices(); } + mSensorName.resize(mNumberOfVolumes); // hardcoded. TODO: change size when a different naming scheme for VD is in place. Ideally could be 4 petals + 8 layers = 12 + int VDvolume = 0; + for (int i = 0; i < 4; i++) { /// VD + for (int j = 0; j < 3; j++) { + mSensorName[VDvolume].Form("%s%d_%s%d_%s%d", GeometryTGeo::getTRKPetalPattern(), i, GeometryTGeo::getTRKPetalLayerPattern(), j, GeometryTGeo::getTRKSensorPattern(), j); + VDvolume++; + } + for (int j = 0; j < 6; j++) { + mSensorName[VDvolume].Form("%s%d_%s%d_%s%d", GeometryTGeo::getTRKPetalPattern(), i, GeometryTGeo::getTRKPetalDiskPattern(), j, GeometryTGeo::getTRKSensorPattern(), j); + VDvolume++; + } + } + + for (int i = 0; i < 8; i++) { /// MLOT + mSensorName[VDvolume].Form("%s%d", GeometryTGeo::getTRKSensorPattern(), i); + VDvolume++; + } + + for (auto vd : mSensorName) { + std::cout << "Volume name: " << vd << std::endl; + } + LOGP(info, "Summary of TRK configuration:"); for (auto& layer : mLayers) { LOGP(info, "Layer: {} name: {} r: {} cm | z: {} cm | thickness: {} cm", layer.getNumber(), layer.getName(), layer.getInnerRadius(), layer.getZ(), layer.getChipThickness()); @@ -241,7 +263,7 @@ void Detector::createGeometry() mPetalCases.clear(); // Add petal cases (the sensitive layers inside the petal cases get constructed here too) auto& trkPars = TRKBaseParam::Instance(); - for (Int_t petalCaseNumber = 0; petalCaseNumber < 4; ++petalCaseNumber) { + for (Int_t petalCaseNumber = 0; petalCaseNumber < sNumberVDPetalCases; ++petalCaseNumber) { mPetalCases.emplace_back(petalCaseNumber, vTRK, trkPars.irisOpen); mServices.excavateFromVacuum(mPetalCases[petalCaseNumber].getFullName()); } @@ -253,6 +275,12 @@ void Detector::InitializeO2Detector() LOG(info) << "Initialize TRK O2Detector"; mGeometryTGeo = GeometryTGeo::Instance(); defineSensitiveVolumes(); + + mSensorID.resize(mNumberOfVolumes); // hardcoded. TODO: change size when a different namingh scheme for VD is in place. Ideally could be 4 petals + 8 layers = 12 + for (int i = 0; i < mNumberOfVolumes; i++) { + mSensorID[i] = gMC ? TVirtualMC::GetMC()->VolId(mSensorName[i]) : 0; // Volume ID from the Geant geometry + LOGP(info, "{}: mSensorID={}", i, mSensorID[i]); + } } void Detector::defineSensitiveVolumes() @@ -264,7 +292,7 @@ void Detector::defineSensitiveVolumes() LOGP(info, "Adding TRK Sensitive Volumes"); // Add petal case sensitive volumes - for (int petalCase = 0; petalCase < 4; ++petalCase) { + for (int petalCase = 0; petalCase < sNumberVDPetalCases; ++petalCase) { // Petal layers for (int petalLayer = 0; petalLayer < mPetalCases[petalCase].mPetalLayers.size(); ++petalLayer) { volumeName = mPetalCases[petalCase].mPetalLayers[petalLayer].getSensorName(); @@ -338,9 +366,28 @@ bool Detector::ProcessHits(FairVolume* vol) return false; } - int lay = vol->getVolumeId(); + int subDetID = -1; + int layer = -1; + int volume = 0; + int stave = -1; int volID = vol->getMCid(); + bool notSens = false; + while ((volume < mNumberOfVolumes) && (notSens = (volID != mSensorID[volume]))) { + ++volume; /// there are 44 volumes, 36 for the VD (1 for each sensing element) and 8 for the MLOT (1 for each layer) + } + + if (notSens) { + return kFALSE; // RS: can this happen? This method must be called for sensors only? + } + + if (volume < mNumberOfVolumesVD) { + subDetID = 0; // VD. For the moment each "chip" is a volume./// TODO: change this logic once the naming scheme is changed + } else { + subDetID = 1; // MLOT + layer = volume - mNumberOfVolumesVD; + } + // Is it needed to keep a track reference when the outer ITS volume is encountered? auto stack = (o2::data::Stack*)fMC->GetStack(); // if (fMC->IsTrackExiting() && (lay == 0 || lay == mLayers.size() - 1)) { @@ -348,7 +395,7 @@ bool Detector::ProcessHits(FairVolume* vol) // Keep the track refs for the innermost and outermost layers only o2::TrackReference tr(*fMC, GetDetId()); tr.setTrackID(stack->GetCurrentTrackNumber()); - tr.setUserId(lay); + tr.setUserId(volume); stack->addTrackReference(tr); } bool startHit = false, stopHit = false; @@ -398,13 +445,18 @@ bool Detector::ProcessHits(FairVolume* vol) TLorentzVector positionStop; fMC->TrackPosition(positionStop); // Retrieve the indices with the volume path - int stave(0), halfstave(0), chipinmodule(0), module; - fMC->CurrentVolOffID(1, chipinmodule); - fMC->CurrentVolOffID(2, module); - fMC->CurrentVolOffID(3, halfstave); - fMC->CurrentVolOffID(4, stave); + // int subDetID, int petalcase, int disk, int lay, int stave + int petal(0), ll(0), stave(0), halfstave(0); + if (subDetID == 1) { + fMC->CurrentVolOffID(1, halfstave); + fMC->CurrentVolOffID(2, stave); + } /// if VD, for the moment the volume is the "chipID" so no need to retrieve other elments - Hit* p = addHit(stack->GetCurrentTrackNumber(), lay, mTrackData.mPositionStart.Vect(), positionStop.Vect(), + int chipID = mGeometryTGeo->getChipIndex(subDetID, volume, layer, stave); + + Print(vol, volume, subDetID, layer, stave, halfstave, chipID); + + Hit* p = addHit(stack->GetCurrentTrackNumber(), chipID, mTrackData.mPositionStart.Vect(), positionStop.Vect(), mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(), mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status); // p->SetTotalEnergy(vmc->Etot()); @@ -424,6 +476,23 @@ o2::itsmft::Hit* Detector::addHit(int trackID, int detID, const TVector3& startP mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus); return &(mHits->back()); } + +void Detector::Print(FairVolume* vol, int volume, int subDetID, int layer, int stave, int halfstave, int chipID) const +{ + int currentVol(0); + LOG(INFO) << "Current volume name: " << fMC->CurrentVolName() << " and ID " << fMC->CurrentVolID(currentVol); + LOG(INFO) << "volume: " << volume << "/" << mNumberOfVolumes - 1; + if (subDetID == 1) { + LOG(INFO) << "off volume name 1 " << fMC->CurrentVolOffName(1) << " halfstave: " << halfstave; + LOG(INFO) << "off volume name 2 " << fMC->CurrentVolOffName(2) << " stave: " << stave; + LOG(INFO) << "SubDetector ID: " << subDetID << " Layer: " << layer << " staveinLayer: " << stave << " Chip ID: " << chipID; + + } else { + LOG(INFO) << "SubDetector ID: " << subDetID << " Chip ID: " << chipID; + } + LOG(INFO); +} + } // namespace trk } // namespace o2 From 1160d89f9e4bb396743a79625969a23f689d4d8a Mon Sep 17 00:00:00 2001 From: Andrea Sofia Triolo Date: Wed, 2 Jul 2025 11:46:52 +0200 Subject: [PATCH 2/4] ALICE3-TRK: considering half staves for the staggered geometry for ML/OT --- .../TRK/base/include/TRKBase/GeometryTGeo.h | 14 +++- .../ALICE3/TRK/base/src/GeometryTGeo.cxx | 82 +++++++++++++++---- .../ALICE3/TRK/simulation/src/Detector.cxx | 2 +- 3 files changed, 77 insertions(+), 21 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h b/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h index b4bdb1f1ab27a..fbd7024260024 100644 --- a/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h +++ b/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h @@ -60,6 +60,7 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache int extractNumberOfDisksVD() const; int extractNumberOfChipsPerPetalVD() const; int extractNumberOfStavesMLOT(int lay) const; + int extractNumberOfHalfStavesMLOT(int lay) const; /// Extract number following the prefix in the name string int extractVolumeCopy(const char* name, const char* prefix) const; @@ -71,10 +72,11 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache void setOwner(bool v) { mOwner = v; } void Print(Option_t* opt = "") const; - void PrintChipID(int index, int subDetID, int petalcase, int disk, int lay, int stave, int indexRetrieved) const; + void PrintChipID(int index, int subDetID, int petalcase, int disk, int lay, int stave, int halfstave, int indexRetrieved) const; int getLayer(int index) const; int getStave(int index) const; + int getHalfStave(int index) const; int getSubDetID(int index) const; int getPetalCase(int index) const; int getDisk(int index) const; @@ -85,14 +87,16 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache /// \param int disk The disk number for VD, from 0 to 5 /// \param int lay The layer number. Starting from 0 both for VD and MLOT /// \param int stave The stave number for MLOT. Starting from 0 - int getChipIndex(int subDetID, int petalcase, int disk, int lay, int stave) const; + /// \param int halfstave The half stave number for MLOT. Can be 0 or 1 + int getChipIndex(int subDetID, int petalcase, int disk, int lay, int stave, int halfstave) const; /// This routine computes the chip index number from the subDetID, volume, layer, stave /// TODO: retrieve also from chip when chips will be available /// \param int subDetID The subdetector ID, 0 for VD, 1 for MLOT /// \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 /// \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 /// \param int stave The stave number in each layer for MLOT. Starting from 0. - int getChipIndex(int subDetID, int volume, int lay, int stave) const; + /// \param int halfstave The half stave number for MLOT. Can be 0 or 1 + int getChipIndex(int subDetID, int volume, int lay, int stave, int halfstave) const; /// This routine computes subDetID, petal, disk, layer, stave given the chip index number /// TODO: copute also from chip when chips will be available /// \param int index The chip index number, starting from 0 @@ -101,7 +105,8 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache /// \param int disk The disk number for VD, from 0 to 5 /// \param int lay The layer number. Starting from 0 both for VD and MLOT /// \param int stave The stave number for MLOT. Starting from 0 - bool getChipID(int index, int& subDetID, int& petalcase, int& disk, int& lay, int& stave) const; + /// \param int halfstave The half stave number for MLOT. Can be 0 or 1 + bool getChipID(int index, int& subDetID, int& petalcase, int& disk, int& lay, int& stave, int& halfstave) const; int getLastChipIndex(int lay) const { return mLastChipIndex[lay]; } int getFirstChipIndex(int lay, int petalcase, int subDetID) const @@ -156,6 +161,7 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache std::vector mNumbersOfChipPerDiskVD; ///< numbersOfChipPerDiskVD std::vector mNumberOfChipsPerPetalVD; ///< numbersOfChipPerPetalVD std::vector mNumberOfStaves; ///< Number Of Staves per layer in ML/OT + std::vector mNumberOfHalfStaves; ///< Number Of Staves in each stave of the layer in ML/OT std::array mLayerToWrapper; ///< Layer to wrapper correspondence bool mOwner = true; //! is it owned by the singleton? diff --git a/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx index b8b44f1ed5b29..02b36c2666f4b 100644 --- a/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx @@ -74,6 +74,7 @@ void GeometryTGeo::Build(int loadTrans) mNumberOfDisksVD = extractNumberOfDisksVD(); mNumberOfStaves.resize(mNumberOfLayersMLOT); + mNumberOfHalfStaves.resize(mNumberOfLayersMLOT); mLastChipIndex.resize(mNumberOfPetalsVD + mNumberOfLayersMLOT); mLastChipIndexVD.resize(mNumberOfPetalsVD); mLastChipIndexMLOT.resize(mNumberOfLayersMLOT); /// ML and OT are part of TRK as the same detector, without disks @@ -85,6 +86,7 @@ void GeometryTGeo::Build(int loadTrans) for (int i = 0; i < mNumberOfLayersMLOT; i++) { std::cout << "Layer MLOT: " << i << std::endl; mNumberOfStaves[i] = extractNumberOfStavesMLOT(i); + mNumberOfHalfStaves[i] = extractNumberOfHalfStavesMLOT(i); } int numberOfChipsTotal = 0; @@ -99,7 +101,7 @@ void GeometryTGeo::Build(int loadTrans) /// filling the information for the MLOT for (int i = 0; i < mNumberOfLayersMLOT; i++) { - mNumberOfChipsPerLayerMLOT[i] = extractNumberOfStavesMLOT(i); // for the moment, considering 1 stave = 1 chip. TODO: add the final segmentation in chips + mNumberOfChipsPerLayerMLOT[i] = extractNumberOfStavesMLOT(i) * extractNumberOfHalfStavesMLOT(i); // for the moment, considering 1 half stave = 1 chip. TODO: add the final segmentation in chips numberOfChipsTotal += mNumberOfChipsPerLayerMLOT[i]; mLastChipIndex[i + mNumberOfPetalsVD] = numberOfChipsTotal - 1; mLastChipIndexMLOT[i] = numberOfChipsTotal - 1; @@ -170,8 +172,26 @@ int GeometryTGeo::getStave(int index) const return -1; } else if (subDetID == 1) { /// MLOT int lay = getLayer(index); - index -= getFirstChipIndex(lay, petalcase, subDetID); - return index; /// |||| + index -= getFirstChipIndex(lay, petalcase, subDetID); // get the index of the sensing element in the layer + return index / mNumberOfHalfStaves[lay]; + } + return -1; /// not found +} + +//__________________________________________________________________________ +int GeometryTGeo::getHalfStave(int index) const +{ + int subDetID = getSubDetID(index); + int lay = getLayer(index); + int petalcase = getPetalCase(index); + int stave = getStave(index); + + if (subDetID == 0) { /// VD + return -1; + } else if (subDetID == 1) { /// MLOT + int lay = getLayer(index); + index -= getFirstChipIndex(lay, petalcase, subDetID); // get the index of the sensing element in the layer + return index % 2; /// 0 = half stave left, 1 = half stave right, as geometry is filled /// TODO: generalize once chips will be in place. Can it be working also with chips? } return -1; /// not found } @@ -193,7 +213,7 @@ int GeometryTGeo::getDisk(int index) const } //__________________________________________________________________________ -int GeometryTGeo::getChipIndex(int subDetID, int petalcase, int disk, int lay, int stave) const +int GeometryTGeo::getChipIndex(int subDetID, int petalcase, int disk, int lay, int stave, int halfstave) const { if (subDetID == 0) { // VD if (lay == -1) { // disk @@ -202,31 +222,32 @@ int GeometryTGeo::getChipIndex(int subDetID, int petalcase, int disk, int lay, i return getFirstChipIndex(lay, petalcase, subDetID) + lay; } } else if (subDetID == 1) { // MLOT - return getFirstChipIndex(lay, petalcase, subDetID) + stave; + return getFirstChipIndex(lay, petalcase, subDetID) + stave * mNumberOfHalfStaves[lay] + halfstave; } return -1; // not found } //__________________________________________________________________________ -int GeometryTGeo::getChipIndex(int subDetID, int volume, int lay, int stave) const +int GeometryTGeo::getChipIndex(int subDetID, int volume, int lay, int stave, int halfstave) const { if (subDetID == 0) { // VD return volume; /// In the current configuration for VD, each volume is the sensor element = chip. // TODO: when the geometry naming scheme will be changed, change this method } else if (subDetID == 1) { // MLOT - return getFirstChipIndex(lay, -1, subDetID) + stave; + return getFirstChipIndex(lay, -1, subDetID) + stave * mNumberOfHalfStaves[lay] + halfstave; } return -1; // not found } //__________________________________________________________________________ -bool GeometryTGeo::getChipID(int index, int& subDetID, int& petalcase, int& disk, int& lay, int& stave) const +bool GeometryTGeo::getChipID(int index, int& subDetID, int& petalcase, int& disk, int& lay, int& stave, int& halfstave) const { subDetID = getSubDetID(index); petalcase = getPetalCase(index); disk = getDisk(index); lay = getLayer(index); stave = getStave(index); + halfstave = getHalfStave(index); return kTRUE; } @@ -236,12 +257,12 @@ TString GeometryTGeo::getMatrixPath(int index) const { // int lay, hba, stav, sstav, mod, chipInMod; - int subDetID, petalcase, disk, lay, stave; //// TODO: add chips in a second step - getChipID(index, subDetID, petalcase, disk, lay, stave); + int subDetID, petalcase, disk, lay, stave, halfstave; //// TODO: add chips in a second step + getChipID(index, subDetID, petalcase, disk, lay, stave, halfstave); - int indexRetrieved = getChipIndex(subDetID, petalcase, disk, lay, stave); + int indexRetrieved = getChipIndex(subDetID, petalcase, disk, lay, stave, halfstave); - PrintChipID(index, subDetID, petalcase, disk, lay, stave, indexRetrieved); + PrintChipID(index, subDetID, petalcase, disk, lay, stave, halfstave, indexRetrieved); // TString path = Form("/cave_1/barrel_1/%s_2/", GeometryTGeo::getTRKVolPattern()); TString path = "/cave_1/barrel_1/TRKV_2/TRKLayer0_1/TRKStave0_1/TRKChip0_1/TRKSensor0_1/"; /// dummy path, to be replaced @@ -617,7 +638,35 @@ int GeometryTGeo::extractNumberOfStavesMLOT(int lay) const } //__________________________________________________________________________ -void GeometryTGeo::PrintChipID(int index, int subDetID, int petalcase, int disk, int lay, int stave, int indexRetrieved) const +int GeometryTGeo::extractNumberOfHalfStavesMLOT(int lay) const +{ + int numberOfHalfStaves = 0; + + std::string staveName = Form("%s%d", getTRKStavePattern(), lay); + TGeoVolume* staveV = gGeoManager->GetVolume(staveName.c_str()); + + if (staveV == nullptr) { + LOG(fatal) << getName() << " volume " << getTRKStavePattern() << " is not in the geometry"; + } + + // Loop on all layV nodes, count Layer volumes by checking names + TObjArray* nodes = staveV->GetNodes(); + // std::cout << "Printing nodes for layer " << lay << std::endl; + // nodes->Print(); + int nNodes = nodes->GetEntriesFast(); + + for (int j = 0; j < nNodes; j++) { + auto nd = dynamic_cast(nodes->At(j)); /// layer node + const char* name = nd->GetName(); + if (strstr(name, getTRKChipPattern()) != nullptr) { + numberOfHalfStaves++; + } + } + return numberOfHalfStaves; +} + +//__________________________________________________________________________ +void GeometryTGeo::PrintChipID(int index, int subDetID, int petalcase, int disk, int lay, int stave, int halfstave, int indexRetrieved) const { std::cout << "\nindex = " << index << std::endl; std::cout << "subDetID = " << subDetID << std::endl; @@ -626,7 +675,8 @@ void GeometryTGeo::PrintChipID(int index, int subDetID, int petalcase, int disk, std::cout << "disk = " << disk << std::endl; std::cout << "first chip index = " << getFirstChipIndex(lay, petalcase, subDetID) << std::endl; std::cout << "stave = " << stave << std::endl; - std::cout << "chck index Retrieved = " << indexRetrieved << std::endl; + std::cout << "halfstave = " << halfstave << std::endl; + std::cout << "check index Retrieved = " << indexRetrieved << std::endl; } //__________________________________________________________________________ @@ -648,11 +698,11 @@ void GeometryTGeo::Print(Option_t*) const for (int i = 0; i < mNumberOfPetalsVD; i++) { LOGF(info, "%d", mNumberOfChipsPerPetalVD[i]); } - LOGF(info, "Number of staves per layer MLOT: "); + LOGF(info, "Number of staves and half staves per layer MLOT: "); for (int i = 0; i < mNumberOfLayersMLOT; i++) { std::string mlot = ""; mlot = (i < 5) ? "ML" : "OT"; - LOGF(info, "Layer: %d, %s, %d staves", i, mlot.c_str(), mNumberOfStaves[i]); + LOGF(info, "Layer: %d, %s, %d staves, %d half staves", i, mlot.c_str(), mNumberOfStaves[i], mNumberOfStaves[i] * mNumberOfHalfStaves[i]); } LOGF(info, "Total number of chips: %d", getNumberOfChips()); diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx index e70e7ef31035a..1f861e9877aac 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx @@ -452,7 +452,7 @@ bool Detector::ProcessHits(FairVolume* vol) fMC->CurrentVolOffID(2, stave); } /// if VD, for the moment the volume is the "chipID" so no need to retrieve other elments - int chipID = mGeometryTGeo->getChipIndex(subDetID, volume, layer, stave); + int chipID = mGeometryTGeo->getChipIndex(subDetID, volume, layer, stave, halfstave); Print(vol, volume, subDetID, layer, stave, halfstave, chipID); From ce15dd2654913d07cdce92187b573aba4ceb3024 Mon Sep 17 00:00:00 2001 From: Andrea Sofia Triolo Date: Thu, 3 Jul 2025 13:39:54 +0200 Subject: [PATCH 3/4] ALICE3-TRK: indexing scheme now working independently from the chosen geometry layout --- .../TRK/base/include/TRKBase/GeometryTGeo.h | 3 ++- .../ALICE3/TRK/base/src/GeometryTGeo.cxx | 26 ++++++++++++------- .../ALICE3/TRK/simulation/src/Detector.cxx | 9 ++++--- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h b/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h index fbd7024260024..0468fb6460805 100644 --- a/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h +++ b/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h @@ -66,7 +66,8 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache int extractVolumeCopy(const char* name, const char* prefix) const; int getNumberOfLayersMLOT() const { return mNumberOfLayersMLOT; } - int getNumberOffActivePartsVD() const { return mNumberOfActivePartsVD; } + int getNumberOfActivePartsVD() const { return mNumberOfActivePartsVD; } + std::vector getNumberOfHalfStaves() const { return mNumberOfHalfStaves; } bool isOwner() const { return mOwner; } void setOwner(bool v) { mOwner = v; } diff --git a/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx index 02b36c2666f4b..69bae0fad9cee 100644 --- a/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/base/src/GeometryTGeo.cxx @@ -54,9 +54,9 @@ GeometryTGeo::GeometryTGeo(bool build, int loadTrans) : DetMatrixCache(detectors void GeometryTGeo::Build(int loadTrans) { ///// current geometry organization: - ///// total elements = 258 = x staves * 8 layers ML+OT + 4 petal cases * (3 layers + 6 disks) + ///// total elements = x staves (*2 half staves if staggered geometry) * 8 layers ML+OT + 4 petal cases * (3 layers + 6 disks) ///// indexing from 0 to 35: VD petals -> layers -> disks - ///// indexing from 36 to 257: MLOT staves + ///// indexing from 36 to y: MLOT staves if (isBuilt()) { LOGP(warning, "Already built"); @@ -107,7 +107,6 @@ void GeometryTGeo::Build(int loadTrans) mLastChipIndexMLOT[i] = numberOfChipsTotal - 1; } - // setSize(mNumberOfLayersMLOT + mNumberOfActivePartsVD); /// temporary, number of chips = number of layers and active parts setSize(numberOfChipsTotal); /// temporary, number of chips = number of staves and active parts fillMatrixCache(loadTrans); } @@ -221,8 +220,12 @@ int GeometryTGeo::getChipIndex(int subDetID, int petalcase, int disk, int lay, i } else { // layer return getFirstChipIndex(lay, petalcase, subDetID) + lay; } - } else if (subDetID == 1) { // MLOT - return getFirstChipIndex(lay, petalcase, subDetID) + stave * mNumberOfHalfStaves[lay] + halfstave; + } else if (subDetID == 1) { // MLOT + if (mNumberOfHalfStaves[lay] == 2) { // staggered geometry + return getFirstChipIndex(lay, petalcase, subDetID) + stave * mNumberOfHalfStaves[lay] + halfstave; + } else if (mNumberOfHalfStaves[lay] == 1) { // turbo geometry + return getFirstChipIndex(lay, petalcase, subDetID) + stave; + } } return -1; // not found } @@ -233,8 +236,12 @@ int GeometryTGeo::getChipIndex(int subDetID, int volume, int lay, int stave, int if (subDetID == 0) { // VD return volume; /// In the current configuration for VD, each volume is the sensor element = chip. // TODO: when the geometry naming scheme will be changed, change this method - } else if (subDetID == 1) { // MLOT - return getFirstChipIndex(lay, -1, subDetID) + stave * mNumberOfHalfStaves[lay] + halfstave; + } else if (subDetID == 1) { // MLOT + if (mNumberOfHalfStaves[lay] == 2) { // staggered geometry + return getFirstChipIndex(lay, -1, subDetID) + stave * mNumberOfHalfStaves[lay] + halfstave; + } else if (mNumberOfHalfStaves[lay] == 1) { // turbo geometry + return getFirstChipIndex(lay, -1, subDetID) + stave; + } } return -1; // not found } @@ -256,7 +263,6 @@ bool GeometryTGeo::getChipID(int index, int& subDetID, int& petalcase, int& disk TString GeometryTGeo::getMatrixPath(int index) const { - // int lay, hba, stav, sstav, mod, chipInMod; int subDetID, petalcase, disk, lay, stave, halfstave; //// TODO: add chips in a second step getChipID(index, subDetID, petalcase, disk, lay, stave, halfstave); @@ -701,8 +707,8 @@ void GeometryTGeo::Print(Option_t*) const LOGF(info, "Number of staves and half staves per layer MLOT: "); for (int i = 0; i < mNumberOfLayersMLOT; i++) { std::string mlot = ""; - mlot = (i < 5) ? "ML" : "OT"; - LOGF(info, "Layer: %d, %s, %d staves, %d half staves", i, mlot.c_str(), mNumberOfStaves[i], mNumberOfStaves[i] * mNumberOfHalfStaves[i]); + mlot = (i < 4) ? "ML" : "OT"; + LOGF(info, "Layer: %d, %s, %d staves, %d half staves per stave", i, mlot.c_str(), mNumberOfStaves[i], mNumberOfHalfStaves[i]); } LOGF(info, "Total number of chips: %d", getNumberOfChips()); diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx index 1f861e9877aac..2ba5f20c29301 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx @@ -445,8 +445,7 @@ bool Detector::ProcessHits(FairVolume* vol) TLorentzVector positionStop; fMC->TrackPosition(positionStop); // Retrieve the indices with the volume path - // int subDetID, int petalcase, int disk, int lay, int stave - int petal(0), ll(0), stave(0), halfstave(0); + int stave(0), halfstave(0); if (subDetID == 1) { fMC->CurrentVolOffID(1, halfstave); fMC->CurrentVolOffID(2, stave); @@ -482,11 +481,13 @@ void Detector::Print(FairVolume* vol, int volume, int subDetID, int layer, int s int currentVol(0); LOG(INFO) << "Current volume name: " << fMC->CurrentVolName() << " and ID " << fMC->CurrentVolID(currentVol); LOG(INFO) << "volume: " << volume << "/" << mNumberOfVolumes - 1; - if (subDetID == 1) { + if (subDetID == 1 and mGeometryTGeo->getNumberOfHalfStaves()[layer] == 2) { // staggered geometry LOG(INFO) << "off volume name 1 " << fMC->CurrentVolOffName(1) << " halfstave: " << halfstave; LOG(INFO) << "off volume name 2 " << fMC->CurrentVolOffName(2) << " stave: " << stave; LOG(INFO) << "SubDetector ID: " << subDetID << " Layer: " << layer << " staveinLayer: " << stave << " Chip ID: " << chipID; - + } else if (subDetID == 1 and mGeometryTGeo->getNumberOfHalfStaves()[layer] == 1) { // turbo geometry + LOG(INFO) << "off volume name 2 " << fMC->CurrentVolOffName(2) << " stave: " << stave; + LOG(INFO) << "SubDetector ID: " << subDetID << " Layer: " << layer << " staveinLayer: " << stave << " Chip ID: " << chipID; } else { LOG(INFO) << "SubDetector ID: " << subDetID << " Chip ID: " << chipID; } From f3e74ca751f399e68d82c69d14b91fbe856bc6c5 Mon Sep 17 00:00:00 2001 From: Andrea Sofia Triolo Date: Fri, 4 Jul 2025 10:38:23 +0200 Subject: [PATCH 4/4] minor fixes --- .../TRK/base/include/TRKBase/GeometryTGeo.h | 2 +- .../ALICE3/TRK/simulation/src/Detector.cxx | 22 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h b/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h index 0468fb6460805..cfd991728d09b 100644 --- a/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h +++ b/Detectors/Upgrades/ALICE3/TRK/base/include/TRKBase/GeometryTGeo.h @@ -67,7 +67,7 @@ class GeometryTGeo : public o2::detectors::DetMatrixCache int getNumberOfLayersMLOT() const { return mNumberOfLayersMLOT; } int getNumberOfActivePartsVD() const { return mNumberOfActivePartsVD; } - std::vector getNumberOfHalfStaves() const { return mNumberOfHalfStaves; } + int getNumberOfHalfStaves(int lay) const { return mNumberOfHalfStaves[lay]; } bool isOwner() const { return mOwner; } void setOwner(bool v) { mOwner = v; } diff --git a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx index 2ba5f20c29301..f5027310fa66d 100644 --- a/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/TRK/simulation/src/Detector.cxx @@ -479,19 +479,19 @@ o2::itsmft::Hit* Detector::addHit(int trackID, int detID, const TVector3& startP void Detector::Print(FairVolume* vol, int volume, int subDetID, int layer, int stave, int halfstave, int chipID) const { int currentVol(0); - LOG(INFO) << "Current volume name: " << fMC->CurrentVolName() << " and ID " << fMC->CurrentVolID(currentVol); - LOG(INFO) << "volume: " << volume << "/" << mNumberOfVolumes - 1; - if (subDetID == 1 and mGeometryTGeo->getNumberOfHalfStaves()[layer] == 2) { // staggered geometry - LOG(INFO) << "off volume name 1 " << fMC->CurrentVolOffName(1) << " halfstave: " << halfstave; - LOG(INFO) << "off volume name 2 " << fMC->CurrentVolOffName(2) << " stave: " << stave; - LOG(INFO) << "SubDetector ID: " << subDetID << " Layer: " << layer << " staveinLayer: " << stave << " Chip ID: " << chipID; - } else if (subDetID == 1 and mGeometryTGeo->getNumberOfHalfStaves()[layer] == 1) { // turbo geometry - LOG(INFO) << "off volume name 2 " << fMC->CurrentVolOffName(2) << " stave: " << stave; - LOG(INFO) << "SubDetector ID: " << subDetID << " Layer: " << layer << " staveinLayer: " << stave << " Chip ID: " << chipID; + LOG(info) << "Current volume name: " << fMC->CurrentVolName() << " and ID " << fMC->CurrentVolID(currentVol); + LOG(info) << "volume: " << volume << "/" << mNumberOfVolumes - 1; + if (subDetID == 1 && mGeometryTGeo->getNumberOfHalfStaves(layer) == 2) { // staggered geometry + LOG(info) << "off volume name 1 " << fMC->CurrentVolOffName(1) << " halfstave: " << halfstave; + LOG(info) << "off volume name 2 " << fMC->CurrentVolOffName(2) << " stave: " << stave; + LOG(info) << "SubDetector ID: " << subDetID << " Layer: " << layer << " staveinLayer: " << stave << " Chip ID: " << chipID; + } else if (subDetID == 1 && mGeometryTGeo->getNumberOfHalfStaves(layer) == 1) { // turbo geometry + LOG(info) << "off volume name 2 " << fMC->CurrentVolOffName(2) << " stave: " << stave; + LOG(info) << "SubDetector ID: " << subDetID << " Layer: " << layer << " staveinLayer: " << stave << " Chip ID: " << chipID; } else { - LOG(INFO) << "SubDetector ID: " << subDetID << " Chip ID: " << chipID; + LOG(info) << "SubDetector ID: " << subDetID << " Chip ID: " << chipID; } - LOG(INFO); + LOG(info); } } // namespace trk