diff --git a/Detectors/Upgrades/ALICE3/FCT/base/include/FCTBase/FCTBaseParam.h b/Detectors/Upgrades/ALICE3/FCT/base/include/FCTBase/FCTBaseParam.h index 52e32cd5f68a3..f498d05280ed0 100644 --- a/Detectors/Upgrades/ALICE3/FCT/base/include/FCTBase/FCTBaseParam.h +++ b/Detectors/Upgrades/ALICE3/FCT/base/include/FCTBase/FCTBaseParam.h @@ -26,7 +26,8 @@ namespace fct enum FCTGeometry { Default = 0, - Telescope = 1 + Telescope = 1, + Segmented = 2 }; struct FCTBaseParam : public o2::conf::ConfigurableParamHelper { @@ -42,6 +43,10 @@ struct FCTBaseParam : public o2::conf::ConfigurableParamHelper { Float_t etaOut = 1.5; Float_t Layerx2X0 = 0.01; + // FCTGeometry::Segmented parameters + Int_t nRadSeg = 2; + Int_t nAziSeg = 5; + // FCTGeometry::External file std::string configFile = ""; // Overrides geoModel parameter when provided diff --git a/Detectors/Upgrades/ALICE3/FCT/base/include/FCTBase/GeometryTGeo.h b/Detectors/Upgrades/ALICE3/FCT/base/include/FCTBase/GeometryTGeo.h index 511438ac8af88..c2abe34067ea9 100644 --- a/Detectors/Upgrades/ALICE3/FCT/base/include/FCTBase/GeometryTGeo.h +++ b/Detectors/Upgrades/ALICE3/FCT/base/include/FCTBase/GeometryTGeo.h @@ -92,24 +92,28 @@ class GeometryTGeo : public o2::itsmft::GeometryTGeo static const char* getFCTVolPattern() { return sVolumeName.c_str(); } static const char* getFCTInnerVolPattern() { return sInnerVolumeName.c_str(); } static const char* getFCTLayerPattern() { return sLayerName.c_str(); } + static const char* getFCTSegmentPattern() { return sSegmentName.c_str(); } static const char* getFCTChipPattern() { return sChipName.c_str(); } static const char* getFCTSensorPattern() { return sSensorName.c_str(); } static const char* composeSymNameFCT(Int_t d) { return Form("%s_%d", o2::detectors::DetID(o2::detectors::DetID::FCT).getName(), d); } static const char* composeSymNameLayer(Int_t d, Int_t lr); + static const char* composeSymNameLayer(Int_t d, Int_t lr, Int_t sec, Int_t mod); static const char* composeSymNameChip(Int_t d, Int_t lr); + static const char* composeSymNameChip(Int_t d, Int_t lr, Int_t sec, Int_t mod); static const char* composeSymNameSensor(Int_t d, Int_t lr); + static const char* composeSymNameSensor(Int_t d, Int_t lr, Int_t sec, Int_t mod); protected: - static constexpr int MAXLAYERS = 15; ///< max number of active layers + static constexpr int MAXACTIVE = 200; ///< max number of active layers/segments - Int_t mNumberOfLayers; ///< number of layers + Int_t mNumberOfActives; ///< number of layers/segments (whichever is selected) static std::string sInnerVolumeName; ///< Mother inner volume name static std::string sVolumeName; ///< Mother volume name + static std::string sSegmentName; ///< Segment name static std::string sLayerName; ///< Layer name static std::string sChipName; ///< Chip name - - static std::string sSensorName; ///< Sensor name + static std::string sSensorName; ///< Sensor name private: static std::unique_ptr sInstance; ///< singletone instance diff --git a/Detectors/Upgrades/ALICE3/FCT/base/src/GeometryTGeo.cxx b/Detectors/Upgrades/ALICE3/FCT/base/src/GeometryTGeo.cxx index 72cde0aa13519..298cb5c432a2b 100644 --- a/Detectors/Upgrades/ALICE3/FCT/base/src/GeometryTGeo.cxx +++ b/Detectors/Upgrades/ALICE3/FCT/base/src/GeometryTGeo.cxx @@ -51,6 +51,7 @@ std::unique_ptr GeometryTGeo::sInstance; std::string GeometryTGeo::sVolumeName = "FCTV"; ///< Mother volume name std::string GeometryTGeo::sInnerVolumeName = "FCTInner"; ///< Mother inner volume name +std::string GeometryTGeo::sSegmentName = "FCTSegment"; ///< Segment name std::string GeometryTGeo::sLayerName = "FCTLayer"; ///< Layer name std::string GeometryTGeo::sChipName = "FCTChip"; ///< Sensor name std::string GeometryTGeo::sSensorName = "FCTSensor"; ///< Sensor name @@ -104,6 +105,24 @@ const char* GeometryTGeo::composeSymNameSensor(Int_t d, Int_t lr) return Form("%s/%s%d", composeSymNameChip(d, lr), getFCTSensorPattern(), lr); } +//__________________________________________________________________________ +const char* GeometryTGeo::composeSymNameLayer(Int_t d, Int_t lr, Int_t sec, Int_t mod) +{ + return Form("%s/%s%dSec%dMod%d", composeSymNameFCT(d), getFCTSegmentPattern(), lr, sec, mod); +} + +//__________________________________________________________________________ +const char* GeometryTGeo::composeSymNameChip(Int_t d, Int_t lr, Int_t sec, Int_t mod) +{ + return Form("%s/%s%dSec%dMod%d", composeSymNameLayer(d, lr, sec, mod), getFCTChipPattern(), lr, sec, mod); +} + +//__________________________________________________________________________ +const char* GeometryTGeo::composeSymNameSensor(Int_t d, Int_t lr, Int_t sec, Int_t mod) +{ + return Form("%s/%s%dSec%dMod%d", composeSymNameChip(d, lr, sec, mod), getFCTSensorPattern(), lr, sec, mod); +} + //__________________________________________________________________________ void GeometryTGeo::fillMatrixCache(int mask) { diff --git a/Detectors/Upgrades/ALICE3/FCT/simulation/CMakeLists.txt b/Detectors/Upgrades/ALICE3/FCT/simulation/CMakeLists.txt index d858b33518f45..f8b1475af6112 100644 --- a/Detectors/Upgrades/ALICE3/FCT/simulation/CMakeLists.txt +++ b/Detectors/Upgrades/ALICE3/FCT/simulation/CMakeLists.txt @@ -11,6 +11,7 @@ o2_add_library(FCTSimulation SOURCES src/FCTLayer.cxx + src/FCTSegment.cxx src/Detector.cxx PUBLIC_LINK_LIBRARIES O2::FCTBase O2::ITSMFTSimulation @@ -18,6 +19,7 @@ o2_add_library(FCTSimulation o2_target_root_dictionary(FCTSimulation HEADERS include/FCTSimulation/Detector.h - include/FCTSimulation/FCTLayer.h) + include/FCTSimulation/FCTLayer.h + include/FCTSimulation/FCTSegment.h) o2_data_file(COPY data DESTINATION Detectors/FCT/simulation) diff --git a/Detectors/Upgrades/ALICE3/FCT/simulation/include/FCTSimulation/Detector.h b/Detectors/Upgrades/ALICE3/FCT/simulation/include/FCTSimulation/Detector.h index 99fe068b55a22..41c0477835109 100644 --- a/Detectors/Upgrades/ALICE3/FCT/simulation/include/FCTSimulation/Detector.h +++ b/Detectors/Upgrades/ALICE3/FCT/simulation/include/FCTSimulation/Detector.h @@ -46,7 +46,8 @@ namespace o2 namespace fct { class FCTLayer; -} +class FCTSegment; +} // namespace fct } // namespace o2 namespace o2 @@ -54,6 +55,7 @@ namespace o2 namespace fct { class FCTLayer; +class FCTSegment; class Detector : public o2::base::DetImpl { @@ -109,10 +111,11 @@ class Detector : public o2::base::DetImpl void PreTrack() override { ; } /// Returns the number of layers - Int_t getNumberOfLayers() const { return mNumberOfLayers; } + Int_t getNumberOfLayers() const { return mNumberOfActives; } void buildBasicFCT(const FCTBaseParam& param); void buildFCTV1(); + void buildSegmentedFCT(const FCTBaseParam& param); void buildFCTFromFile(std::string); GeometryTGeo* mGeometryTGeo; //! access to geometry details @@ -120,11 +123,11 @@ class Detector : public o2::base::DetImpl void exportLayout(); private: - std::vector mLayerID; + std::vector mActiveID; std::vector mConverterLayerId; - std::vector mLayerName; + std::vector mActiveName; std::vector mConverterLayerName; - Int_t mNumberOfLayers; + Int_t mNumberOfActives; Int_t mNumberOfConverterLayers; /// this is transient data about track passing the sensor @@ -154,6 +157,7 @@ class Detector : public o2::base::DetImpl std::vector mLayers; std::vector mConverterLayers; + std::vector mSegments; bool mIsPipeActivated = true; //! If Alice 3 pipe is present append inner disks to vacuum volume to avoid overlaps template diff --git a/Detectors/Upgrades/ALICE3/FCT/simulation/include/FCTSimulation/FCTSegment.h b/Detectors/Upgrades/ALICE3/FCT/simulation/include/FCTSimulation/FCTSegment.h new file mode 100644 index 0000000000000..aa427781469a7 --- /dev/null +++ b/Detectors/Upgrades/ALICE3/FCT/simulation/include/FCTSimulation/FCTSegment.h @@ -0,0 +1,89 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file FCTSegment.h +/// \brief Definition of the FCTSegment class + +#ifndef ALICEO2_FCT_SEGMENT_H_ +#define ALICEO2_FCT_SEGMENT_H_ + +#include "Rtypes.h" // for Double_t, Int_t, Bool_t, etc +#include "FCTSimulation/Detector.h" // for Detector, Detector::Model + +class TGeoVolume; + +namespace o2 +{ +namespace fct +{ + +/// This class defines the Geometry for the FCT segment TGeo. This is a work class used +/// to study different configurations during the development of the ALICE3 EndCaps +class FCTSegment : public TObject +{ + public: + // Default constructor + FCTSegment() = default; + + // Segment constructor + FCTSegment(Int_t layerNumber, Int_t sectorNumber, Int_t moduleNumber, std::string segmentName, Double_t x, Double_t y, Double_t z, Double_t vertL, Double_t innerL, Double_t outerL, Double_t rotX, Double_t rotY, Double_t rotZ, Float_t segmentx2X0); + + /// Copy constructor + FCTSegment(const FCTSegment&) = default; + + /// Assignment operator + FCTSegment& operator=(const FCTSegment&) = default; + + /// Default destructor + ~FCTSegment() override; + + /// getters + auto getLayerNumber() const { return mLayerNumber; } + auto getSectorNumber() const { return mSectorNumber; } + auto getModuleNumber() const { return mModuleNumber; } + auto getX() const { return mX; } + auto getY() const { return mY; } + auto getZ() const { return mZ; } + auto getXRot() const { return mX; } + auto getYRot() const { return mY; } + auto getZRot() const { return mZ; } + auto getVertL() const { return mVertL; } + auto getInnerL() const { return mInnerL; } + auto getOuterL() const { return mOuterL; } + auto getx2X0() const { return mx2X0; } + + /// Creates the actual Segment and places inside its mother volume + /// \param motherVolume the TGeoVolume owing the volume structure + virtual void createSegment(TGeoVolume* motherVolume); + + private: + Int_t mLayerNumber = -1; + Int_t mSectorNumber = -1; + Int_t mModuleNumber = -1; + std::string mSegmentName; ///< Current segment name + Double_t mVertL; ///< Vertical length of the trapezoid + Double_t mInnerL; ///< Inner side length of the trapezoid + Double_t mOuterL; ///< Outer side length of the trapezoid + Double_t mX; ///< X position of the segment + Double_t mY; ///< Y position of the segment + Double_t mZ; ///< Z position of the segment + Double_t mRotX; ///< X rotation of the segment + Double_t mRotY; ///< X rotation of the segment + Double_t mRotZ; ///< X rotation of the segment + Double_t mChipThickness; ///< Chip thickness + Double_t mx2X0; ///< segment material budget x/X0 + + ClassDefOverride(FCTSegment, 0); // ALICE 3 EndCaps geometry +}; +} // namespace fct +} // namespace o2 + +#endif diff --git a/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx b/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx index 458df289d0bb2..4f09ebb1c42ab 100644 --- a/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx +++ b/Detectors/Upgrades/ALICE3/FCT/simulation/src/Detector.cxx @@ -16,6 +16,7 @@ #include "FCTBase/GeometryTGeo.h" #include "FCTSimulation/Detector.h" #include "FCTSimulation/FCTLayer.h" +#include "FCTSimulation/FCTSegment.h" #include "FCTBase/FCTBaseParam.h" #include "DetectorsBase/Stack.h" @@ -79,10 +80,10 @@ void Detector::buildFCTFromFile(std::string configFileName) -77.5 3.92 14.35 0.0042 1 */ - mLayerName.clear(); + mActiveName.clear(); mLayers.clear(); mConverterLayers.clear(); - mLayerID.clear(); + mActiveID.clear(); LOG(info) << "Building FCT Detector: From file"; LOG(info) << " FCT detector configuration: " << configFileName; @@ -124,7 +125,7 @@ void Detector::buildFCTFromFile(std::string configFileName) iss >> Layerx2X0; std::string layerName = GeometryTGeo::getFCTLayerPattern() + std::string("_") + std::to_string(layerNumber); - mLayerName.push_back(layerName); + mActiveName.push_back(layerName); if (layerType == 0) { LOG(info) << "Adding Disk Layer " << layerName << " at z = " << z_layer << " ; r_in = " << r_in << " ; r_out = " << r_out_l_side << " x/X0 = " << Layerx2X0; layerNumberDisk++; @@ -143,8 +144,8 @@ void Detector::buildFCTFromFile(std::string configFileName) layerNumber++; } - mNumberOfLayers = layerNumber; - LOG(info) << " Loaded FCT Detector with " << mNumberOfLayers << " layers"; + mNumberOfActives = layerNumber; + LOG(info) << " Loaded FCT Detector with " << mNumberOfActives << " layers"; LOG(info) << " Of which " << layerNumberDisk << " are disks"; LOG(info) << " Of which " << layerNumberSquare << " are disks"; } @@ -186,23 +187,76 @@ void Detector::buildBasicFCT(const FCTBaseParam& param) auto etaIn = param.etaIn; auto etaOut = param.etaOut; auto Layerx2X0 = param.Layerx2X0; - mNumberOfLayers = param.nLayers; - mLayerID.clear(); + mNumberOfActives = param.nLayers; + mActiveID.clear(); Int_t type = 0; // Disk - for (Int_t layerNumber = 0; layerNumber < mNumberOfLayers; layerNumber++) { - std::string layerName = GeometryTGeo::getFCTLayerPattern() + std::to_string(layerNumber); // + mNumberOfLayers * direction); - mLayerName.push_back(layerName); + for (Int_t layerNumber = 0; layerNumber < mNumberOfActives; layerNumber++) { + std::string layerName = GeometryTGeo::getFCTLayerPattern() + std::to_string(layerNumber); // + mNumberOfActives * direction); + mActiveName.push_back(layerName); // Adds evenly spaced layers - Float_t layerZ = z_first + (layerNumber * z_length / (mNumberOfLayers - 1)) * std::copysign(1, z_first); + Float_t layerZ = z_first + (layerNumber * z_length / (mNumberOfActives - 1)) * std::copysign(1, z_first); Float_t rIn = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaIn)))); Float_t rOut = std::abs(layerZ * std::tan(2.f * std::atan(std::exp(-etaOut)))); mLayers.emplace_back(layerNumber, layerName, layerZ, rIn, rOut, Layerx2X0, type); } } +void Detector::buildSegmentedFCT(const FCTBaseParam& param){ + // Build the FCT with its layers segmented in trapezoids. The z distance is the same as the default configuration + LOG(info) << "Building FCT Detector: Segmented Telescope"; + + int numberOfLayers = 11; + Float_t layersx2X0 = 1.e-2; + std::vector> layersConfig{ + {442.0, 5.0, 17.0, layersx2X0}, // {z_layer, r_in, r_out, Layerx2X0} + {444.0, 5.0, 17.0, layersx2X0}, + {446.0, 5.0, 17.0, layersx2X0}, + {448.0, 5.0, 17.0, layersx2X0}, + {450.0, 5.0, 17.0, layersx2X0}, + {452.0, 5.0, 17.0, layersx2X0}, + {460.0, 5.0, 17.0, layersx2X0}, + {470.0, 5.0, 18.0, layersx2X0}, + {480.0, 5.0, 18.0, layersx2X0}, + {490.0, 5.0, 19.0, layersx2X0}, + {500.0, 5.0, 19.0, layersx2X0}}; + + mActiveID.clear(); + mActiveName.clear(); + mLayers.clear(); + + Double_t segAngle = 2.*TMath::Pi() / (Double_t)param.nAziSeg; + const Float_t kRadDeg = 180./TMath::Pi(); + int segmentNumber = 0; + for (int layerNumber = 0; layerNumber < numberOfLayers; layerNumber++) { + Double_t zPosTrap = layersConfig[layerNumber][0]; + Double_t rIn = layersConfig[layerNumber][1]; + Double_t rOut = layersConfig[layerNumber][2]; + Double_t x2X0 = layersConfig[layerNumber][3]; + Double_t radialSegLength = (rOut - rIn) / ((Double_t)(param.nRadSeg)); + Double_t trapezoidVertLength = radialSegLength*TMath::Cos(segAngle/2.); + for (int radialNumber = 0; radialNumber < param.nRadSeg; radialNumber++) { + for (int azimuthalNumber = 0; azimuthalNumber < param.nAziSeg; azimuthalNumber++) { + Double_t innerTrapLength = TMath::Sqrt(2. * (rIn + radialNumber * radialSegLength)*(rIn + radialNumber * radialSegLength) * (1. - TMath::Cos(segAngle))); + Double_t outerTrapLength = TMath::Sqrt(2. * (rIn + (radialNumber + 1) * radialSegLength)*(rIn + (radialNumber + 1) * radialSegLength) * (1. - TMath::Cos(segAngle))); + Double_t innerTrapCenterR = (rIn + radialNumber * radialSegLength)*TMath::Cos(segAngle/2.); + Double_t outerTrapCenterR = (rIn + (radialNumber + 1) * radialSegLength)*TMath::Cos(segAngle/2.); + Double_t rTrapCenter = outerTrapCenterR - 0.5*(outerTrapCenterR - innerTrapCenterR); + Double_t xPosTrap = rTrapCenter * TMath::Cos(azimuthalNumber * segAngle); + Double_t yPosTrap = rTrapCenter * TMath::Sin(azimuthalNumber * segAngle); + Double_t xRot = -90 + azimuthalNumber*segAngle*kRadDeg; + std::string segmentName = Form("%s_Lay_%d_Sec_%d_Mod_%d", o2::fct::GeometryTGeo::getFCTLayerPattern(), layerNumber, azimuthalNumber, radialNumber); + mActiveName.push_back(segmentName); + mSegments.emplace_back(layerNumber, azimuthalNumber, radialNumber, segmentName, xPosTrap, yPosTrap, zPosTrap, trapezoidVertLength, innerTrapLength, outerTrapLength, xRot, 0., 0., x2X0); + segmentNumber++; + } + } + } + mNumberOfActives = segmentNumber; +} + //_________________________________________________________________________________________________ void Detector::buildFCTV1() { @@ -210,7 +264,7 @@ void Detector::buildFCTV1() LOG(info) << "Building FCT Detector: V1"; - mNumberOfLayers = 11; + mNumberOfActives = 11; Float_t layersx2X0 = 1.e-2; std::vector> layersConfig{ @@ -226,15 +280,15 @@ void Detector::buildFCTV1() {490.0, 5.0, 19.0, layersx2X0}, {500.0, 5.0, 19.0, layersx2X0}}; - mLayerID.clear(); - mLayerName.clear(); + mActiveID.clear(); + mActiveName.clear(); mLayers.clear(); Int_t type = 0; // Disk - for (int layerNumber = 0; layerNumber < mNumberOfLayers; layerNumber++) { + for (int layerNumber = 0; layerNumber < mNumberOfActives; layerNumber++) { std::string layerName = GeometryTGeo::getFCTLayerPattern() + std::to_string(layerNumber); - mLayerName.push_back(layerName); + mActiveName.push_back(layerName); Float_t z = layersConfig[layerNumber][0]; Float_t rIn = layersConfig[layerNumber][1]; @@ -263,9 +317,9 @@ Detector::Detector(const Detector& rhs) /// Container for data points mHits(o2::utils::createSimVector()) { - mLayerID = rhs.mLayerID; - mLayerName = rhs.mLayerName; - mNumberOfLayers = rhs.mNumberOfLayers; + mActiveID = rhs.mActiveID; + mActiveName = rhs.mActiveName; + mNumberOfActives = rhs.mNumberOfActives; } //_________________________________________________________________________________________________ @@ -296,10 +350,11 @@ Detector& Detector::operator=(const Detector& rhs) // base class assignment base::Detector::operator=(rhs); - mLayerID = rhs.mLayerID; - mLayerName = rhs.mLayerName; - mNumberOfLayers = rhs.mNumberOfLayers; + mActiveID = rhs.mActiveID; + mActiveName = rhs.mActiveName; + mNumberOfActives = rhs.mNumberOfActives; mLayers = rhs.mLayers; + mSegments = rhs.mSegments; mTrackData = rhs.mTrackData; /// Container for data points @@ -328,7 +383,7 @@ Bool_t Detector::ProcessHits(FairVolume* vol) } Int_t lay = 0, volID = vol->getMCid(); - while ((lay <= mLayerID.size()) && (volID != mLayerID[lay])) { + while ((lay <= mActiveID.size()) && (volID != mActiveID[lay])) { ++lay; } @@ -479,6 +534,9 @@ void Detector::ConstructGeometry() case Telescope: buildBasicFCT(fctBaseParam); // BasicFCT = Parametrized telescopic detector (equidistant layers) break; + case Segmented: + buildSegmentedFCT(fctBaseParam); // Layers of the FCT are segmented in trapezoids. + break; default: LOG(fatal) << "Invalid Geometry.\n"; break; @@ -536,14 +594,25 @@ void Detector::createGeometry() for (Int_t iLayer = 0; iLayer < mConverterLayers.size(); iLayer++) { mConverterLayers[iLayer].createLayer(volFCT); } + for (Int_t iSegment = 0; iSegment < mSegments.size(); iSegment++){ + mSegments[iSegment].createSegment(volFCT); + } vALIC->AddNode(volFCT, 2, new TGeoTranslation(0., 30., 0.)); } - LOG(info) << "Registering FCT SensitiveLayerIDs:"; + if(mLayers.size()){LOG(info) << "Registering FCT SensitiveLayerIDs:";} for (int iLayer = 0; iLayer < mLayers.size(); iLayer++) { auto layerID = gMC ? TVirtualMC::GetMC()->VolId(Form("%s_%d", GeometryTGeo::getFCTSensorPattern(), mLayers[iLayer].getLayerNumber())) : 0; - mLayerID.push_back(layerID); - LOG(info) << " mLayerID[" << mLayers[iLayer].getLayerNumber() << "] = " << layerID; + mActiveID.push_back(layerID); + LOG(info) << " mActiveID[" << mLayers[iLayer].getLayerNumber() << "] = " << layerID; + } + + if(mSegments.size()){LOG(info) << "Registering FCT SensitiveSegmentIDs:";} + for (int iSegment = 0; iSegment < mSegments.size(); iSegment++) { + auto segmentID = gMC ? TVirtualMC::GetMC()->VolId(Form("%s_Lay_%d_Sec_%d_Mod_%d", GeometryTGeo::getFCTSensorPattern(), mSegments[iSegment].getLayerNumber(), mSegments[iSegment].getSectorNumber(), mSegments[iSegment].getModuleNumber())) : 0; + mActiveID.push_back(segmentID); + LOG(info) << " mActiveID[" + << "Layer: " << mSegments[iSegment].getLayerNumber() << " Sector: " << mSegments[iSegment].getSectorNumber() << " Module: " << mSegments[iSegment].getModuleNumber() << "] = " << segmentID; } } @@ -553,16 +622,20 @@ void Detector::defineSensitiveVolumes() TGeoManager* geoManager = gGeoManager; TGeoVolume* v; - TString volumeName; LOG(info) << "Adding FCT Sensitive Volumes"; // The names of the FCT sensitive volumes have the format: FCTSensor_(0,1)_(0...sNumberLayers-1) for (Int_t iLayer = 0; iLayer < mLayers.size(); iLayer++) { - volumeName = o2::fct::GeometryTGeo::getFCTSensorPattern() + std::to_string(mLayers[iLayer].getLayerNumber()); v = geoManager->GetVolume(Form("%s_%d", GeometryTGeo::getFCTSensorPattern(), mLayers[iLayer].getLayerNumber())); LOG(info) << "Adding FCT Sensitive Volume => " << v->GetName(); AddSensitiveVolume(v); } + + for (Int_t iSegment = 0; iSegment < mSegments.size(); iSegment++) { + v = geoManager->GetVolume(Form("%s_Lay_%d_Sec_%d_Mod_%d", GeometryTGeo::getFCTSensorPattern(), mSegments[iSegment].getLayerNumber(), mSegments[iSegment].getSectorNumber(), mSegments[iSegment].getModuleNumber())); + LOG(info) << "Adding FCT Sensitive Volume => " << v->GetName(); + AddSensitiveVolume(v); + } } //_________________________________________________________________________________________________ diff --git a/Detectors/Upgrades/ALICE3/FCT/simulation/src/FCTSegment.cxx b/Detectors/Upgrades/ALICE3/FCT/simulation/src/FCTSegment.cxx new file mode 100644 index 0000000000000..c2c658b77dedd --- /dev/null +++ b/Detectors/Upgrades/ALICE3/FCT/simulation/src/FCTSegment.cxx @@ -0,0 +1,94 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file FCTSegment.cxx +/// \brief Implementation of the FCTSegment class +/// \author Mario Sitta +/// \author Chinorat Kobdaj (kobdaj@g.sut.ac.th) + +#include "FCTSimulation/FCTSegment.h" +#include "FCTBase/GeometryTGeo.h" +#include "FCTSimulation/Detector.h" + +#include // for LOG + +#include // for TGeoManager, gGeoManager +#include // for TGeoCombiTrans, TGeoRotation, etc +#include +#include // for TGeoTrap +#include // for TGeoVolume, TGeoVolumeAssembly +#include // for TGeoCompositeShape +#include // for TGeoCombiTrans +#include "TMathBase.h" // for Abs +#include // for Sin, RadToDeg, DegToRad, Cos, Tan, etc + +#include // for snprintf + +using namespace TMath; +using namespace o2::fct; +using namespace o2::itsmft; + +ClassImp(FCTSegment); + +FCTSegment::~FCTSegment() = default; + +FCTSegment::FCTSegment(Int_t layerNumber, Int_t sectorNumber, Int_t moduleNumber, std::string segmentName, Double_t x, Double_t y, Double_t z, Double_t vertL, Double_t innerL, Double_t outerL, Double_t rotX, Double_t rotY, Double_t rotZ, Float_t segmentx2X0) : mLayerNumber(layerNumber), mSectorNumber(sectorNumber), mModuleNumber(moduleNumber), mSegmentName(segmentName), mx2X0(segmentx2X0), mX(x), mY(y), mZ(z), mRotX(rotX), mRotY(rotY), mRotZ(rotZ), mVertL(vertL), mInnerL(innerL), mOuterL(outerL) +{ + + Float_t Si_X0 = 9.37; // In cm + mChipThickness = mx2X0 * Si_X0; + LOG(info) << "Creating FCT segment: Layer " << mLayerNumber << " Sector: " << mSectorNumber << " Module: " << mModuleNumber; + LOG(info) << " Using silicon X0 = " << Si_X0 << " to emulate segment radiation length."; + LOG(info) << " Segment z = " << mZ << " ; vertL = " << mVertL << " ; innerL = " << mInnerL << " ; outerL = " << mOuterL << " ; x2X0 = " << mx2X0 << " ; ChipThickness = " << mChipThickness; +} + +void FCTSegment::createSegment(TGeoVolume* motherVolume) +{ + if (mLayerNumber < 0 || mSectorNumber < 0 || mModuleNumber < 0) { + return; + } + // Create tube, set sensitive volume, add to mother volume + + std::string chipName = Form("%s_Lay_%d_Sec_%d_Mod_%d", o2::fct::GeometryTGeo::getFCTChipPattern(), mLayerNumber, mSectorNumber, mModuleNumber); + std::string sensName = Form("%s_Lay_%d_Sec_%d_Mod_%d", GeometryTGeo::getFCTSensorPattern(), mLayerNumber, mSectorNumber, mModuleNumber); + TGeoTrap *sensor = new TGeoTrap(mChipThickness/2., 0., 0., + mVertL/2., mInnerL/2., mOuterL/2., 0., + mVertL/2., mInnerL/2., mOuterL/2., 0.); + TGeoTrap *chip = new TGeoTrap(mChipThickness/2., 0., 0., + mVertL/2., mInnerL/2., mOuterL/2., 0., + mVertL/2., mInnerL/2., mOuterL/2., 0.); + TGeoTrap *segment = new TGeoTrap(mChipThickness/2., 0., 0., + mVertL/2., mInnerL/2., mOuterL/2., 0., + mVertL/2., mInnerL/2., mOuterL/2., 0.); + + TGeoMedium* medSi = gGeoManager->GetMedium("FCT_SILICON$"); + TGeoMedium* medAir = gGeoManager->GetMedium("FCT_AIR$"); + + TGeoVolume* sensVol = new TGeoVolume(sensName.c_str(), sensor, medSi); + sensVol->SetLineColor(kSpring + 5); + TGeoVolume* chipVol = new TGeoVolume(chipName.c_str(), chip, medSi); + chipVol->SetLineColor(kSpring + 5); + TGeoVolume* segmentVol = new TGeoVolume(mSegmentName.c_str(), segment, medAir); + segmentVol->SetLineColor(kSpring + 5); + + LOG(info) << "Inserting " << sensVol->GetName() << " inside " << chipVol->GetName(); + chipVol->AddNode(sensVol, 1, nullptr); + + LOG(info) << "Inserting " << chipVol->GetName() << " inside " << segmentVol->GetName(); + segmentVol->AddNode(chipVol, 1, nullptr); + + // Finally put everything in the mother volume + auto FwdSegmentRotation = new TGeoRotation("FwdSegmentRotation", mRotX, mRotY, mRotZ); + auto FwdSegmentCombiTrans = new TGeoCombiTrans(mX, mY, mZ, FwdSegmentRotation); + + LOG(info) << "Inserting " << segmentVol->GetName() << " inside " << motherVolume->GetName(); + motherVolume->AddNode(segmentVol, 1, FwdSegmentCombiTrans); +} \ No newline at end of file diff --git a/Detectors/Upgrades/ALICE3/FCT/simulation/src/FCTSimulationLinkDef.h b/Detectors/Upgrades/ALICE3/FCT/simulation/src/FCTSimulationLinkDef.h index 295f76b3b35af..096853b8b668a 100644 --- a/Detectors/Upgrades/ALICE3/FCT/simulation/src/FCTSimulationLinkDef.h +++ b/Detectors/Upgrades/ALICE3/FCT/simulation/src/FCTSimulationLinkDef.h @@ -16,6 +16,7 @@ #pragma link off all functions; #pragma link C++ class o2::fct::FCTLayer + ; +#pragma link C++ class o2::fct::FCTSegment + ; #pragma link C++ class o2::fct::Detector + ; #pragma link C++ class o2::base::DetImpl < o2::fct::Detector> + ;