diff --git a/core/data/sts/CbmStsHit.h b/core/data/sts/CbmStsHit.h index c488edd1fe86c269f48b2c658cc91818a4190781..d8f0e9edc97e14bee67088c2e3f34acd5b99eae4 100644 --- a/core/data/sts/CbmStsHit.h +++ b/core/data/sts/CbmStsHit.h @@ -73,6 +73,14 @@ public: **/ double GetDu() const { return fDu; } + /** @brief Error of coordinate across front-side strips + ** @value Coordinate error [cm] + ** + ** Note that this error is defined only in the + ** local coordinate system of the sensor. + **/ + void SetDu(Double_t du) { fDu = du; } + /** @brief Error of coordinate across front-side strips ** @value Coordinate error [cm] @@ -82,6 +90,14 @@ public: **/ double GetDv() const { return fDv; } + /** @brief Error of coordinate across front-side strips + ** @value Coordinate error [cm] + ** + ** Note that this error is defined only in the + ** local coordinate system of the sensor. + **/ + void SetDv(Double_t dv) { fDv = dv; } + /** Index of cluster at the front side ** @value Front-side cluster index diff --git a/reco/L1/CbmL1.h b/reco/L1/CbmL1.h index 053f37eb32ca25d01b98c50ae72e5ddf3deddf38..4fa41786056ae729e9197d1b8943939ec4a4a91a 100644 --- a/reco/L1/CbmL1.h +++ b/reco/L1/CbmL1.h @@ -232,7 +232,7 @@ public: L1Algo* algo {nullptr}; // for access to L1 Algorithm from L1::Instance TString fMuchDigiFile {}; // Much digitization file name - bool fUseHitErrors {false}; + bool fUseHitErrors {true}; bool fMissingHits {false}; L1Algo::TrackingMode fTrackingMode {L1Algo::TrackingMode::kSts}; diff --git a/reco/L1/L1Algo/L1Algo.h b/reco/L1/L1Algo/L1Algo.h index 7cd96beee2fdacf5ac9781aeda2b8349cbde0590..a737c6583a4b6d9854e571e1fdc1e545ba7b39ad 100644 --- a/reco/L1/L1Algo/L1Algo.h +++ b/reco/L1/L1Algo/L1Algo.h @@ -256,7 +256,7 @@ public: L1Vector<int> fStripToTrackB {"L1Algo::fStripToTrackB"}; // back strip to track pointers int fNThreads {0}; - bool fUseHitErrors {0}; + bool fUseHitErrors {true}; bool fMissingHits {0}; TrackingMode fTrackingMode {kSts}; diff --git a/reco/detectors/sts/CMakeLists.txt b/reco/detectors/sts/CMakeLists.txt index ef23952641d3d80c817ac9adfc703d803a1a7337..78c904eb80ac1a738a800e89eda9a6ac064884a2 100644 --- a/reco/detectors/sts/CMakeLists.txt +++ b/reco/detectors/sts/CMakeLists.txt @@ -17,6 +17,7 @@ CbmStsAlgoFindHitsOrtho.cxx CbmStsFindTracks.cxx CbmStsFindTracksEvents.cxx CbmStsRecoModule.cxx +CbmRecoStsPixel.cxx CbmStsTrackFinderIdeal.cxx unpack/CbmStsUnpackAlgo.cxx diff --git a/reco/detectors/sts/CbmRecoStsLinkDef.h b/reco/detectors/sts/CbmRecoStsLinkDef.h index 2c014febe70b1801663ea606503360d4aa9193aa..a0d5a184b26a702aac5e22e8bdd94c337881bfc1 100644 --- a/reco/detectors/sts/CbmRecoStsLinkDef.h +++ b/reco/detectors/sts/CbmRecoStsLinkDef.h @@ -17,6 +17,9 @@ #pragma link C++ class CbmStsFindTracksEvents + ; #pragma link C++ class CbmStsFindTracksQa + ; #pragma link C++ class CbmStsRecoModule + ; + +#pragma link C++ class CbmRecoStsPixel + ; + #pragma link C++ class CbmStsTrackFinderIdeal + ; #pragma link C++ class CbmStsUnpackAlgo + ; diff --git a/reco/detectors/sts/CbmRecoStsPixel.cxx b/reco/detectors/sts/CbmRecoStsPixel.cxx new file mode 100644 index 0000000000000000000000000000000000000000..54ea91ff37b5b521dc903de79a98e4a3987fb7fc --- /dev/null +++ b/reco/detectors/sts/CbmRecoStsPixel.cxx @@ -0,0 +1,314 @@ +/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergey Gorbunov [committer] */ + +/** @file CbmRecoStsPixel.cxx + ** @author Sergey Gorbunov + ** @since 09.12.2021 + **/ + +#include "CbmRecoStsPixel.h" + +#include "CbmAddress.h" +#include "CbmDigiManager.h" +#include "CbmEvent.h" +#include "CbmMCDataArray.h" +#include "CbmMCDataManager.h" +#include "CbmStsDigi.h" +#include "CbmStsModule.h" +#include "CbmStsParSetModule.h" +#include "CbmStsParSetSensor.h" +#include "CbmStsParSetSensorCond.h" +#include "CbmStsParSim.h" +#include "CbmStsPoint.h" +#include "CbmStsRecoModule.h" +#include "CbmStsSetup.h" +#include "CbmStsStation.h" + +#include <FairField.h> +#include <FairRun.h> +#include <FairRuntimeDb.h> + +#include <TClonesArray.h> +#include <TGeoBBox.h> +#include <TGeoPhysicalNode.h> +#include <TRandom.h> + +#include <iomanip> + +using std::fixed; +using std::left; +using std::right; +using std::setprecision; +using std::setw; +using std::stringstream; +using std::vector; + + +ClassImp(CbmRecoStsPixel) + + + // ----- Constructor --------------------------------------------------- + CbmRecoStsPixel::CbmRecoStsPixel(ECbmRecoMode mode) + : FairTask("RecoStsPixel", 1) + , fMode(mode) +{ +} +// ------------------------------------------------------------------------- + + +// ----- Destructor ---------------------------------------------------- +CbmRecoStsPixel::~CbmRecoStsPixel() {} +// ------------------------------------------------------------------------- + + +// ----- End-of-run action --------------------------------------------- +void CbmRecoStsPixel::Finish() {} +// ------------------------------------------------------------------------- + + +// ----- Initialisation ------------------------------------------------ +InitStatus CbmRecoStsPixel::Init() +{ + + // --- Something for the screen + std::cout << std::endl; + LOG(info) << "=========================================================="; + LOG(info) << GetName() << ": Initialising "; + + // --- Check IO-Manager + FairRootManager* ioman = FairRootManager::Instance(); + assert(ioman); + + // --- In event mode: get input array (CbmEvent) + if (fMode == kCbmRecoEvent) { + LOG(info) << GetName() << ": Using event-by-event mode"; + fEvents = dynamic_cast<TClonesArray*>(ioman->GetObject("CbmEvent")); + if (nullptr == fEvents) { + LOG(warn) << GetName() << ": Event mode selected but no event array found!"; + return kFATAL; + } //? Event branch not present + } //? Event mode + else { + LOG(info) << GetName() << ": Using time-based mode"; + } + + + // --- Digi Manager + fDigiManager = CbmDigiManager::Instance(); + fDigiManager->Init(); + + // --- Check input array (StsDigis) + if (!fDigiManager->IsPresent(ECbmModuleId::kSts)) { + LOG(fatal) << GetName() << ": No StsDigi branch in input!"; + return kERROR; + } + + if (!fDigiManager->IsMatchPresent(ECbmModuleId::kSts)) { + LOG(error) << GetName() << " sts digi matches are not present"; + return kERROR; + } + + CbmMCDataManager* mcManager = (CbmMCDataManager*) ioman->GetObject("MCDataManager"); + if (!mcManager) { + LOG(error) << GetName() << ": No CbmMCDataManager!"; + return kERROR; + } + + fStsPoints = mcManager->InitBranch("StsPoint"); + + if (!fStsPoints) { + LOG(fatal) << GetName() << ": No StsPoint branch in input!"; + return kERROR; + } + + + // --- Register output array + fClusters = new TClonesArray("CbmStsCluster", 1); + ioman->Register("StsCluster", "Clusters in STS", fClusters, IsOutputBranchPersistent("StsCluster")); + + // --- Register output array + fHits = new TClonesArray("CbmStsHit", 1); + ioman->Register("StsHit", "Hits in STS", fHits, IsOutputBranchPersistent("StsHit")); + + // --- Simulation settings + assert(fParSim); + LOG(info) << GetName() << ": Sim settings " << fParSim->ToString(); + + // --- Module parameters + assert(fParSetModule); + LOG(info) << GetName() << ": Module parameters " << fParSetModule->ToString(); + + // --- Sensor parameters + assert(fParSetSensor); + LOG(info) << GetName() << ": Sensor parameters " << fParSetModule->ToString(); + + // --- Sensor conditions + assert(fParSetCond); + //assert(fParSetCond->IsSet()); + LOG(info) << GetName() << ": Sensor conditions " << fParSetCond->ToString(); + + // --- Initialise STS setup + fSetup = CbmStsSetup::Instance(); + if (!fSetup->IsInit()) { fSetup->Init(nullptr); } + if (!fSetup->IsModuleParsInit()) { fSetup->SetModuleParameters(fParSetModule); } + if (!fSetup->IsSensorParsInit()) { fSetup->SetSensorParameters(fParSetSensor); } + if (!fSetup->IsSensorCondInit()) { fSetup->SetSensorConditions(fParSetCond); } + + // make sure that the STS digis were produced by the experimental Pixel digitiser + if (strcmp(fParSetSensor->getDescription(), "Experimental STS Pixels")) { + LOG(error) << GetName() << " STS digis must be produced by the CbmStsDigitizePixel digitizer"; + return kERROR; + } + + LOG(info) << GetName() << ": Initialisation successful."; + LOG(info) << "=========================================================="; + + return kSUCCESS; +} +// ------------------------------------------------------------------------- + + +// ----- Task execution ------------------------------------------------ +void CbmRecoStsPixel::Exec(Option_t*) +{ + + // --- Clear hit output array + fHits->Delete(); + + // --- Reset cluster output array + fClusters->Delete(); + + if (fMode == kCbmRecoTimeslice) { + // --- Time-slice mode: process entire array + ProcessData(nullptr); + } + else { + // --- Event mode: loop over events + assert(fEvents); + for (Int_t iEvent = 0; iEvent < fEvents->GetEntriesFast(); iEvent++) { + CbmEvent* event = dynamic_cast<CbmEvent*>(fEvents->At(iEvent)); + assert(event); + ProcessData(event); + } //# events + } //? event mode +} +// ------------------------------------------------------------------------- + + +// ----- Process one time slice or event ------------------------------- +void CbmRecoStsPixel::ProcessData(CbmEvent* event) +{ + if (!fDigiManager->IsMatchPresent(ECbmModuleId::kSts)) { + LOG(error) << GetName() << ": No StsDigi branch in input!"; + return; + } + + Int_t nDigis = (event ? event->GetNofData(ECbmDataType::kStsDigi) : fDigiManager->GetNofDigis(ECbmModuleId::kSts)); + int nHits = 0; + + for (Int_t iDigi = 0; iDigi < nDigis; iDigi++) { + + UInt_t digiIndex = (event ? event->GetIndex(ECbmDataType::kStsDigi, iDigi) : iDigi); + const CbmStsDigi* digi = fDigiManager->Get<const CbmStsDigi>(digiIndex); + assert(digi); + + // Check system ID. There are pulser digis in which will be ignored here. + Int_t systemId = CbmAddress::GetSystemId(digi->GetAddress()); + if (systemId != ToIntegralType(ECbmModuleId::kSts)) { continue; } + + const CbmMatch* match = fDigiManager->GetMatch(ECbmModuleId::kSts, digiIndex); + assert(match); + + // make sure that the digi was produced by CbmStsDigitizePixel task + if (digi->GetChannel() != 0 || match->GetNofLinks() != 1) { + LOG(error) << GetName() << " sts digis were not produced by CbmStsDigitizePixel task"; + break; + } + + // the digi was produced by one MC point + + const CbmLink& link = match->GetLink(0); + CbmStsPoint* pt = dynamic_cast<CbmStsPoint*>(fStsPoints->Get(link.GetFile(), link.GetEntry(), link.GetIndex())); + + // create one cluster and one hit per digi + + UInt_t iCluster = fClusters->GetEntriesFast(); + CbmStsCluster* cluster = new ((*fClusters)[iCluster]) CbmStsCluster; + cluster->AddDigi(iDigi); + if (event) event->AddData(ECbmDataType::kStsCluster, iCluster); + + UInt_t iHit = fHits->GetEntriesFast(); + CbmStsHit* hit = new ((*fHits)[iHit]) CbmStsHit; + + hit->SetAddress(digi->GetAddress()); + hit->SetFrontClusterId(iCluster); + hit->SetBackClusterId(iCluster); + + int ista = CbmStsSetup::Instance()->GetStationNumber(hit->GetAddress()); + if (ista < 0 || ista >= CbmStsSetup::Instance()->GetNofStations()) { + LOG(error) << "wrong Sts station number " << ista; + break; + } + + CbmStsStation* station = CbmStsSetup::Instance()->GetStation(ista); + double staZ = station->GetZ(); + + if (fabs(pt->GetZ() - staZ) > 1.) { + LOG(error) << "Sts point Z " << pt->GetZ() << " is far from the station Z " << staZ; + break; + } + + double dx = pt->GetXOut() - pt->GetXIn(); + double dy = pt->GetYOut() - pt->GetYIn(); + double dz = pt->GetZOut() - pt->GetZIn(); + if (fabs(dz) > 1.e-2) { + hit->SetX(pt->GetXIn() + dx * (staZ - pt->GetZIn()) / dz); + hit->SetY(pt->GetYIn() + dy * (staZ - pt->GetZIn()) / dz); + hit->SetZ(staZ); + } + else { + hit->SetX(pt->GetXIn()); + hit->SetY(pt->GetYIn()); + hit->SetZ(pt->GetZIn()); + } + + Double_t pitchX = station->GetSensorPitch(0); + Double_t pitchY = station->GetSensorPitch(1); + + assert(pitchX > 1.e-5); + assert(pitchY > 1.e-5); + + hit->SetX((floor(hit->GetX() / pitchX) + 0.5) * pitchX); + hit->SetY((floor(hit->GetY() / pitchY) + 0.5) * pitchY); + + hit->SetDx(pitchX / sqrt(12.)); + hit->SetDy(pitchY / sqrt(12.)); + hit->SetDxy(0.); + hit->SetDu(hit->GetDx()); + hit->SetDv(hit->GetDy()); + + hit->SetTime(digi->GetTime()); + const CbmStsParModule& module = fParSetModule->GetParModule(digi->GetAddress()); + const CbmStsParAsic& asic = module.GetParAsic(0); + hit->SetTimeError(asic.GetTimeResol()); + + if (event) event->AddData(ECbmDataType::kStsHit, iHit); + nHits++; + } // digis + + LOG(info) << GetName() << " Processed " << nDigis << " digis, created " << nHits << " hits"; +} +// ------------------------------------------------------------------------- + + +// ----- Connect parameter container ----------------------------------- +void CbmRecoStsPixel::SetParContainers() +{ + FairRuntimeDb* db = FairRun::Instance()->GetRuntimeDb(); + fParSim = dynamic_cast<CbmStsParSim*>(db->getContainer("CbmStsParSim")); + fParSetModule = dynamic_cast<CbmStsParSetModule*>(db->getContainer("CbmStsParSetModule")); + fParSetSensor = dynamic_cast<CbmStsParSetSensor*>(db->getContainer("CbmStsParSetSensor")); + fParSetCond = dynamic_cast<CbmStsParSetSensorCond*>(db->getContainer("CbmStsParSetSensorCond")); +} +// ------------------------------------------------------------------------- diff --git a/reco/detectors/sts/CbmRecoStsPixel.h b/reco/detectors/sts/CbmRecoStsPixel.h new file mode 100644 index 0000000000000000000000000000000000000000..d450bd2020b96862a7b1075a7f8150c3aba9d7fa --- /dev/null +++ b/reco/detectors/sts/CbmRecoStsPixel.h @@ -0,0 +1,137 @@ +/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergey Gorbunov [committer] */ + +/** @file CbmRecoStsPixel.h + ** @author Sergey Gorbunov + ** @since 09.12.2021 + **/ + + +#ifndef CbmRecoStsPixel_H +#define CbmRecoStsPixel_H 1 + +#include "CbmRecoSts.h" + +#include <FairTask.h> + +#include <TStopwatch.h> + + +class CbmDigiManager; +class CbmEvent; +class CbmStsElement; +class CbmStsParAsic; +class CbmStsParModule; +class CbmStsParSensor; +class CbmStsParSensorCond; +class CbmStsParSetModule; +class CbmStsParSetSensor; +class CbmStsParSetSensorCond; +class CbmStsParSim; +class CbmStsRecoModule; +class CbmStsSensor; +class CbmStsSetup; +class CbmMCDataArray; + +/** @class CbmRecoStsPixel + ** @brief Task class for local reconstruction in the STS Pixel detector + ** @author Sergey Gorbunov + ** @since 09.12.2021 + ** @date 09.12.2021 + ** + ** Local reconstruction for the experimental STS Pixel detector + ** + ** The STS digis must be produced by the CbmStsDigitizePixel task. + ** To run it, replace CbmRecoSts task by CbmRecoStsPixel task in the run_reco.C macro + ** + **/ +class CbmRecoStsPixel : public FairTask { + +public: + /** @brief Constructor **/ + CbmRecoStsPixel(ECbmRecoMode mode = kCbmRecoTimeslice); + + + /** @brief Copy constructor (disabled) **/ + CbmRecoStsPixel(const CbmRecoStsPixel&) = delete; + + + /** @brief Assignment operator (disabled) **/ + CbmRecoStsPixel operator=(const CbmRecoStsPixel&) = delete; + + + /** @brief Destructor **/ + ~CbmRecoStsPixel(); + + + /** @brief Task execution **/ + void Exec(Option_t* opt); + + + /** @brief End-of-run action **/ + void Finish(); + + + /** @brief Initialisation **/ + InitStatus Init(); + + + /** @brief Set event-by-event mode + ** @param choice If true, event-by-event mode is used + ** + ** In the event-by-event mode, the event objects in the input tree + ** are used, and events are processed one after the other. + ** An event builder has to be run before, creating the event objects. + ** By default, time-slice mode is applied. + ** + ** Alternative to using SetMode. + **/ + void SetEventMode(Bool_t choice = kTRUE) { fMode = (choice ? kCbmRecoEvent : kCbmRecoTimeslice); } + + + /** @brief Set execution mode + ** @param mode Time-slice or event + ** + ** In the time-slice mode, the entire time-slice (input arrays) + ** will be processed. In the event mode, events read from the event + ** branch are processed one after the other. + **/ + void SetMode(ECbmRecoMode mode) { fMode = mode; } + + + /** @brief Define the needed parameter containers **/ + void SetParContainers(); + + +private: + /** @brief Process one time slice or event + ** @param event Pointer to CbmEvent object + ** + ** If a null event pointer is given, the entire input array is processed. + **/ + void ProcessData(CbmEvent* event = nullptr); + +private: + // --- I/O + TClonesArray* fEvents = nullptr; //! Input array of events + CbmDigiManager* fDigiManager = nullptr; //! Interface to digi branch + CbmMCDataArray* fStsPoints {nullptr}; + TClonesArray* fClusters = nullptr; //! Output cluster array + TClonesArray* fHits = nullptr; //! Output hit array + + // --- Setup and parameters + CbmStsSetup* fSetup = nullptr; //! Instance of STS setup + CbmStsParSim* fParSim = nullptr; ///< Simulation settings + CbmStsParSetModule* fParSetModule = nullptr; ///< Module parameters + CbmStsParSetSensor* fParSetSensor = nullptr; ///< Sensor parameters + CbmStsParSetSensorCond* fParSetCond = nullptr; ///< Sensor conditions + + + // --- Settings + ECbmRecoMode fMode = kCbmRecoEvent; ///< Time-slice or event + + ClassDef(CbmRecoStsPixel, 0); +}; + +#endif diff --git a/sim/detectors/sts/CMakeLists.txt b/sim/detectors/sts/CMakeLists.txt index 786c18bc3b84ae37cf9e15225fb0e8b6815c435f..656935a95a69371900fe2821a2d116617540308e 100644 --- a/sim/detectors/sts/CMakeLists.txt +++ b/sim/detectors/sts/CMakeLists.txt @@ -20,6 +20,8 @@ CbmStsSimSensorDssdOrtho.cxx CbmStsSimSensorDssdStereo.cxx CbmStsSimSensorFactory.cxx +CbmStsDigitizePixel.cxx + qa/CbmStsDigitizeQa.cxx qa/CbmStsDigitizeQaReport.cxx ) @@ -103,6 +105,7 @@ FILES CbmStsDigitize.h CbmStsSimSensorDssdOrtho.h CbmStsSimSensorFactory.h CbmStsTrackStatus.h + CbmStsDigitizePixel.h DESTINATION include ) # --------------------------------------------------------- diff --git a/sim/detectors/sts/CbmStsDigitizePixel.cxx b/sim/detectors/sts/CbmStsDigitizePixel.cxx new file mode 100644 index 0000000000000000000000000000000000000000..19cfa8efcda35c51e096e63ff0075b9cc3b251e8 --- /dev/null +++ b/sim/detectors/sts/CbmStsDigitizePixel.cxx @@ -0,0 +1,301 @@ +/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergey Gorbunov [committer] */ + +/** @file CbmStsDigitizePixel.cxx + ** @author Sergey Gorbunov + ** @date 09.12.2021 + **/ + +// Include class header +#include "CbmStsDigitizePixel.h" + +// Includes from C++ +#include <cassert> +#include <cstring> +#include <fstream> +#include <iomanip> +#include <iostream> +#include <sstream> + +// Includes from ROOT +#include "TClonesArray.h" +#include "TGeoBBox.h" +#include "TGeoMatrix.h" +#include "TGeoPhysicalNode.h" +#include "TGeoVolume.h" +#include <TMCProcess.h> + +// Includes from FairRoot +#include "FairEventHeader.h" +#include "FairField.h" +#include "FairLink.h" +#include "FairMCEventHeader.h" +#include "FairMCPoint.h" +#include "FairRunAna.h" +#include "FairRunSim.h" +#include "FairRuntimeDb.h" +#include <Logger.h> + +// Includes from CbmRoot +#include "CbmStsDigi.h" +#include "CbmStsParSetModule.h" +#include "CbmStsPoint.h" +#include "CbmStsSetup.h" + +// Includes from STS +#include "CbmStsModule.h" +#include "CbmStsParAsic.h" +#include "CbmStsParModule.h" +#include "CbmStsParSensor.h" +#include "CbmStsParSensorCond.h" +#include "CbmStsParSetModule.h" +#include "CbmStsParSetSensor.h" +#include "CbmStsParSetSensorCond.h" +#include "CbmStsParSim.h" +#include "CbmStsPhysics.h" +#include "CbmStsSensor.h" +#include "CbmStsSetup.h" +#include "CbmStsSimSensorFactory.h" + + +using std::fixed; +using std::left; +using std::right; +using std::setprecision; +using std::setw; +using std::string; +using std::stringstream; + +using namespace CbmSts; + +ClassImp(CbmStsDigitizePixel); + +// ----- Standard constructor ------------------------------------------ +CbmStsDigitizePixel::CbmStsDigitizePixel(Double_t pitchXcm, Double_t pitchYcm, Double_t pitchTns) + : CbmDigitize<CbmStsDigi>("StsDigitizePixel") + , fPitchXcm(pitchXcm) + , fPitchYcm(pitchYcm) + , fPitchTns(pitchTns) +{ +} +// ------------------------------------------------------------------------- + + +// ----- Destructor ---------------------------------------------------- +CbmStsDigitizePixel::~CbmStsDigitizePixel() {} +// ------------------------------------------------------------------------- + + +// ----- Finish run --------------------------------------------------- +void CbmStsDigitizePixel::Finish() {} +// ------------------------------------------------------------------------- + + +// ----- Get parameter container from runtime DB ----------------------- +void CbmStsDigitizePixel::SetParContainers() +{ + assert(FairRunAna::Instance()); + FairRuntimeDb* rtdb = FairRunAna::Instance()->GetRuntimeDb(); + fParSim = static_cast<CbmStsParSim*>(rtdb->getContainer("CbmStsParSim")); + fParSetModule = static_cast<CbmStsParSetModule*>(rtdb->getContainer("CbmStsParSetModule")); + fParSetSensor = static_cast<CbmStsParSetSensor*>(rtdb->getContainer("CbmStsParSetSensor")); + fParSetCond = static_cast<CbmStsParSetSensorCond*>(rtdb->getContainer("CbmStsParSetSensorCond")); +} +// ------------------------------------------------------------------------- + + +// ----- Initialisation ----------------------------------------------- +InitStatus CbmStsDigitizePixel::Init() +{ + + // --- Instantiate StsPhysics + CbmStsPhysics::Instance(); + + // Initialise the STS setup interface from TGeoManager + fSetup = CbmStsSetup::Instance(); + if (!fSetup->IsInit()) { fSetup->Init(nullptr); } + + // --- Initialise parameters + InitParams(); + + // --- Get FairRootManager instance + FairRootManager* ioman = FairRootManager::Instance(); + assert(ioman); + + // --- Get input array (CbmStsPoint) + fPoints = (TClonesArray*) ioman->GetObject("StsPoint"); + assert(fPoints); + + // always create matches + + SetCreateMatches(kTRUE); + + RegisterOutput(); + + return kSUCCESS; +} +// ------------------------------------------------------------------------- + + +// ----- Private method ReInit ----------------------------------------- +InitStatus CbmStsDigitizePixel::ReInit() { return Init(); } +// ------------------------------------------------------------------------- + + +// ----- Task execution ------------------------------------------------ +void CbmStsDigitizePixel::Exec(Option_t* /*opt*/) +{ + TStopwatch timer; + + // --- Get current event time. + GetEventInfo(); + + // ----- Process points from MC event --------------------------------- + + assert(fPoints); + + std::vector<std::pair<double, int>> sortedPoints; + sortedPoints.reserve(fPoints->GetEntriesFast()); + + for (Int_t iPoint = 0; iPoint < fPoints->GetEntriesFast(); iPoint++) { + const CbmStsPoint* point = (const CbmStsPoint*) fPoints->At(iPoint); + sortedPoints.push_back(std::make_pair(point->GetTime(), iPoint)); + } + + std::sort(sortedPoints.begin(), sortedPoints.end(), + [](std::pair<double, int>& left, std::pair<double, int>& right) { return left.first < right.first; }); + + for (UInt_t iSorted = 0; iSorted < sortedPoints.size(); iSorted++) { + Int_t iPoint = sortedPoints[iSorted].second; + const CbmStsPoint* point = (const CbmStsPoint*) fPoints->At(iPoint); + + UInt_t address = static_cast<UInt_t>(point->GetDetectorID()); + UShort_t channel = 0; + double timef = fCurrentEventTime + point->GetTime(); + timef = (floor(timef / fPitchTns) + 0.5) * fPitchTns; + Long64_t time = Long64_t(round(timef)); + UShort_t adc = 30; + assert(time >= 0); + + // Create digi and (if required) match and send them to DAQ + // The time is sent separately from the digi in double precision. + // It will be set in the digi later, when creating the timestamp for the time slice. + + CbmStsDigi* digi = new CbmStsDigi(address, channel, 0, adc); + CbmMatch* digiMatch = nullptr; + if (fCreateMatches) { + digiMatch = new CbmMatch; + digiMatch->AddLink(CbmLink(1., iPoint, fCurrentMCEntry, fCurrentInput)); + } + SendData(time, digi, digiMatch); + } + + timer.Stop(); + if (fCreateMatches) { std::cout << "create matches" << std::endl; } + // --- Event log + LOG(info) << left << setw(15) << GetName() << "[" << fixed << setprecision(3) << timer.RealTime() << " s]" + << " Points processed " << fPoints->GetEntriesFast(); +} +// ------------------------------------------------------------------------- + + +// ----- Initialise parameters ----------------------------------------- +void CbmStsDigitizePixel::InitParams() +{ + + // --- The parameter containers are completely initialised here. + // --- Any contents possibly obtained from the runtimeDb are ignored + // --- and overwritten. + + // --- Simulation settings + assert(fParSim); + + // --- Simulation settings + { + fParSim->SetEventMode(fEventMode); // from CbmDigitizeBase + fParSim->SetGenerateNoise(fProduceNoise); // from CbmDigitizeBase + if (fEventMode) fParSim->SetGenerateNoise(kFALSE); + fParSim->setChanged(); + fParSim->setInputVersion(-2, 1); + LOG(info) << GetName() << "--- Settings: " << fParSim->ToString(); + } + + + { // --- Module parameters + + UInt_t nChannels = 2048; // Number of module readout channels + UInt_t nAsicChannels = 128; // Number of readout channels per ASIC + + // --- ASIC parameters + UShort_t nAdc = 32; // Number of ADC channels (5 bit) + Double_t dynRange = 75000.; // Dynamic range [e] + Double_t threshold = 3000.; // Threshold [e] + Double_t timeResol = fPitchTns / sqrt(12.); // Time resolution [ns] + Double_t deadTime = 800.; // Channel dead time [ns] + Double_t noiseRms = 1000.; // RMS of noise [e] + Double_t znr = 3.9789e-3; // Zero-crossing noise rate [1/ns] + CbmStsParAsic userParAsic(nAsicChannels, nAdc, dynRange, threshold, timeResol, deadTime, noiseRms, znr); + + CbmStsParModule userParModule(nChannels, nAsicChannels); + userParModule.SetAllAsics(userParAsic); + + assert(fParSetModule); + fParSetModule->clear(); + for (Int_t iModule = 0; iModule < fSetup->GetNofModules(); iModule++) { + UInt_t address = fSetup->GetModule(iModule)->GetAddress(); + fParSetModule->SetParModule(address, userParModule); + } + + fParSetModule->setChanged(); + fParSetModule->setInputVersion(-2, 1); + LOG(info) << GetName() << "--- Using global ASIC parameters: \n " << userParAsic.ToString(); + LOG(info) << GetName() << "--- Module parameters: " << fParSetModule->ToString(); + } + + // --- Sensor parameters + { + assert(fParSetSensor); + fParSetSensor->clear(); + + // --- Sensor parameters + + for (Int_t iSensor = 0; iSensor < fSetup->GetNofSensors(); iSensor++) { + CbmStsSensor* sensor = fSetup->GetSensor(iSensor); + UInt_t address = sensor->GetAddress(); + TGeoBBox* box = dynamic_cast<TGeoBBox*>(sensor->GetPnode()->GetShape()); + assert(box); + Double_t lX = 2. * box->GetDX(); + Double_t lY = 2. * box->GetDY(); + Double_t lZ = 2. * box->GetDZ(); + Double_t dY = lY; + + // Create a sensor parameter object and add it to the container + CbmStsParSensor par(CbmStsSensorClass::kDssdStereo); + + // sensor parameters currently not used by the tracker + + par.SetPar(0, lX); // Extension in x + par.SetPar(1, lY); // Extension in y + par.SetPar(2, lZ); // Extension in z + par.SetPar(3, dY); // Active size in y + par.SetPar(4, 1024.); // Number of strips front side + par.SetPar(5, 1024.); // Number of strips back side + + // sensor parameters used by the tracker + + par.SetPar(6, fPitchXcm); // Strip pitch front side + par.SetPar(7, fPitchYcm); // Strip pitch back side + par.SetPar(8, 0.); // Stereo angle front side [deg] + par.SetPar(9, 90); // Stereo angle back side [deg] + + fParSetSensor->SetParSensor(address, par); + } + + LOG(info) << GetName() << "--- Sensor parameters: " << fParSetSensor->ToString(); + fParSetSensor->setChanged(); + fParSetSensor->setInputVersion(-2, 1); + fParSetSensor->setDescription("Experimental STS Pixels"); + } +} +// ------------------------------------------------------------------------- diff --git a/sim/detectors/sts/CbmStsDigitizePixel.h b/sim/detectors/sts/CbmStsDigitizePixel.h new file mode 100644 index 0000000000000000000000000000000000000000..dee43b80af14d6a838a1a17ba41c981f0ef4fe4c --- /dev/null +++ b/sim/detectors/sts/CbmStsDigitizePixel.h @@ -0,0 +1,130 @@ +/* Copyright (C) 2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergey Gorbunov [committer] */ + +/** @file CbmStsDigitizePixel.h + ** @author Sergey Gorbunov + ** @date 09.12.2021 + **/ + +#ifndef CbmStsDigitizePixel_H +#define CbmStsDigitizePixel_H 1 + +#include "CbmDefs.h" +#include "CbmDigitize.h" +#include "CbmMatch.h" +#include "CbmStsDefs.h" +#include "CbmStsDigi.h" +#include "CbmStsPhysics.h" +#include "CbmStsSimModule.h" +#include "CbmStsSimSensor.h" + +#include "TStopwatch.h" + +#include <map> + +class TClonesArray; +class CbmStsPoint; +class CbmStsParAsic; +class CbmStsParModule; +class CbmStsParSensor; +class CbmStsParSensorCond; +class CbmStsParSetModule; +class CbmStsParSetSensor; +class CbmStsParSetSensorCond; +class CbmStsParSim; +class CbmStsSetup; +class CbmStsSimSensorFactory; + + +/** @class CbmStsDigitizePixel + ** + ** @brief Task class for simulating the detector response of the experimental STS Pixel setup + ** @author Sergey Gorbunov + ** @since 09.12.2021 + ** + ** A digitiser for the experimental STS Pixel detector + ** + ** To run it, add the following line to run_digi.C macro: + ** + ** run.SetDigitizer(ECbmModuleId::kSts, new CbmStsDigitizePixel); + ** + **/ +class CbmStsDigitizePixel : public CbmDigitize<CbmStsDigi> { + +public: + /** Constructor **/ + CbmStsDigitizePixel(Double_t pitchXcm = 0.0010, Double_t pitchYcm = 0.0010, Double_t pitchTns = 20); + + + /** Destructor **/ + virtual ~CbmStsDigitizePixel(); + + + /** @brief Detector system ID + ** @return kSts + **/ + ECbmModuleId GetSystemId() const { return ECbmModuleId::kSts; } + + /** + * \brief Inherited from FairTask. + */ + virtual void SetParContainers(); + + + /** Execution **/ + virtual void Exec(Option_t* opt); + + + /** Re-initialisation **/ + virtual InitStatus ReInit(); + + /** End-of-run action **/ + virtual void Finish(); + + + /** Initialisation **/ + virtual InitStatus Init(); + + /// set pitch X [cm] + void SetPitchX(double pitchXcm) { fPitchXcm = pitchXcm; } + + /// set pitch Y [cm] + void SetPitchY(double pitchYcm) { fPitchYcm = pitchYcm; } + + /// set pitch Time [ns] + void SetPitchT(double pitchTns) { fPitchTns = pitchTns; } + +private: + Bool_t fIsInitialised; ///< kTRUE if Init() was called + + //std::map<Int_t, CbmStsDigitizeParameters*> fModuleParameterMap; ///< Individual module parameter map + CbmStsSetup* fSetup; //! STS setup interface + TClonesArray* fPoints {nullptr}; ///< Input array of CbmStsPoint + + // --- Module and sensor parameters for runtime DB output + CbmStsParSim* fParSim = nullptr; ///< Simulation settings + CbmStsParSetModule* fParSetModule = nullptr; ///< Module parameter + CbmStsParSetSensor* fParSetSensor = nullptr; ///< Sensor parameters + CbmStsParSetSensorCond* fParSetCond = nullptr; ///< Sensor conditions + + // data members + + Double_t fPitchXcm {0.0058}; // pitch in X [cm] + Double_t fPitchYcm {0.0058}; // pitch in Y [cm] + Double_t fPitchTns {20}; // pitch in time [ns] + + /** @brief Initialise the parameters **/ + void InitParams(); + + /** Process StsPoints from MCEvent **/ + void ProcessMCEvent(); + + /** Prevent usage of copy constructor and assignment operator **/ + CbmStsDigitizePixel(const CbmStsDigitizePixel&); + CbmStsDigitizePixel operator=(const CbmStsDigitizePixel&); + + ClassDef(CbmStsDigitizePixel, 0); +}; + +#endif diff --git a/sim/detectors/sts/CbmStsSimLinkDef.h b/sim/detectors/sts/CbmStsSimLinkDef.h index 17ed0b7552897372309e8ae435130e84202194ab..281d7ca5105a65696af89fa49478cfcbf1d6410b 100644 --- a/sim/detectors/sts/CbmStsSimLinkDef.h +++ b/sim/detectors/sts/CbmStsSimLinkDef.h @@ -21,5 +21,6 @@ #pragma link C++ class CbmStsSimSensorDssdStereo + ; #pragma link C++ class CbmStsSimSensorDssdOrtho + ; #pragma link C++ class CbmStsSimSensorFactory + ; +#pragma link C++ class CbmStsDigitizePixel + ; #endif /* __CINT__ */