4#include "FairLinkManager.h"
5#include "FairRootManager.h"
7#include "FairRuntimeDb.h"
12#include "TVirtualMC.h"
23 LOG(debug3) <<
"BmnFHCal default constructor called";
32 LOG(debug3) <<
"BmnFHCal constructor called with name: " << name <<
" and active: " << active;
37 LOG(debug3) <<
"BmnFHCal destructor called";
51 LOG(debug3) <<
"BmnFHCal Initialize method called";
52 FairDetector::Initialize();
57 LOG(debug3) <<
"BmnFHCal BeginEvent method called";
63 LOG(debug4) <<
"BmnFHCal GetHit method called";
65 for (
Int_t i = nEntries - 1;
i >= 0;
i--) {
67 if (hit->GetAddress() == address) {
76 constexpr double BirkConst = 12.6;
77 return (step > 0) ? edep / (1.0 + (BirkConst / step) * edep) : edep;
82 LOG(debug4) <<
"BmnFHCal ProcessHits method called for event " << gMC->CurrentEvent();
89 LOG(debug4) <<
"BmnFHCal::ProcessHits. trackID = " << gMC->GetStack()->GetCurrentTrackNumber() <<
" "
91 <<
". Edep = " << gMC->Edep() <<
" Time = " << gMC->TrackTime() * 1.0e09;
93 if (gMC->IsTrackEntering() || !
fPoint) {
95 fPoint->SetEventID(gMC->CurrentEvent());
98 gMC->TrackPosition(tPos);
99 gMC->TrackMomentum(tMom);
103 fPoint->SetTime(gMC->TrackTime() * 1.0e09);
104 fPoint->SetLength(gMC->TrackLength());
108 assert(
fPoint->GetAddress() ==
fGeoHandler->GetAddressFromPath(gMC->CurrentVolPath()));
110 double weighted_time =
fPoint->GetEnergyLoss() *
fPoint->GetTime() + dEdep * gMC->TrackTime() * 1.0e09;
112 if (
fPoint->GetEnergyLoss() > 0.)
113 fPoint->SetTime(weighted_time /
fPoint->GetEnergyLoss());
115 if (gMC->IsTrackExiting() || gMC->IsTrackStop() || gMC->IsTrackDisappeared()) {
116 if (
fPoint->GetEnergyLoss() > std::numeric_limits<double>::epsilon()) {
118 if (surface_track >= 0) {
119 fPoint->SetTrackID(surface_track);
121 FairLink(
"MCTrack", surface_track,
fPoint->GetEnergyLoss()));
138 LOG(debug3) <<
"BmnFHCal EndOfEvent method called";
145 LOG(debug3) <<
"BmnFHCal Register method called";
146 FairRootManager::Instance()->Register(
"FHCalPoint",
"FHCal",
fCollection,
kTRUE);
151 LOG(debug3) <<
"BmnFHCal GetCollection method called with iColl: " << iColl;
154 hit->SetEntryNr(FairLink(
"FHCalPoint",
i, hit->GetEnergyLoss()));
158 LOG(debug3) <<
"BmnFHCal::GetCollection Links: " << hit->GetNLinks();
159 if (FairLogger::GetLogger()->IsLogNeeded(fair::Severity::debug3) && hit->GetNLinks()) {
160 hit->PrintLinkInfo();
170 LOG(debug3) <<
"BmnFHCal Print method called";
172 std::cout <<
"-I- BmnFHCal: " << nHits <<
" points registered in event " << gMC->CurrentEvent() << std::endl;
174 if (FairLogger::GetLogger()->IsLogNeeded(fair::Severity::debug4)) {
184 LOG(debug3) <<
"BmnFHCal Reset method called";
190 TString fileName = GetGeometryFileName();
192 LOG(info) <<
"Constructing FHCal geometry from ROOT file %s" << fileName.
Data();
193 ConstructRootGeometry();
196 FairGeoLoader* geoLoad = FairGeoLoader::Instance();
197 FairGeoInterface* geoFace = geoLoad->getGeoInterface();
207 FairRun* fRun = FairRun::Instance();
208 FairRuntimeDb* rtdb = FairRun::Instance()->GetRuntimeDb();
214 FairGeoNode* node = NULL;
215 FairGeoVolume* aVol = NULL;
216 while ((node = (FairGeoNode*)iter.
Next())) {
217 aVol =
dynamic_cast<FairGeoVolume*
>(node);
218 if (node->isSensitive()) {
225 par->setInputVersion(fRun->GetRunId(), 1);
227 ProcessNodes(volList);
232 LOG(debug4) <<
"BmnFHCal CheckIfSensitive method called with name: " << name;
246 LOG(debug4) <<
"UpdateHit: Updating hit at address " << existing.
GetAddress()
247 <<
" with current E_loss = " << existing.GetEnergyLoss()
248 <<
" update E_loss += " << update.GetEnergyLoss();
250 const double eloss_existing = existing.GetEnergyLoss();
251 const double eloss_update = update.GetEnergyLoss();
252 const double eloss_total = eloss_existing + eloss_update;
254 if (eloss_total == 0)
257 const double weight_existing = eloss_existing / eloss_total;
258 const double weight_update = eloss_update / eloss_total;
260 TVector3 pos_existing, mom_existing;
261 existing.Position(pos_existing);
262 existing.Momentum(mom_existing);
265 update.Position(pos_update);
266 update.Momentum(mom_update);
268 existing.SetPosition(weight_existing * pos_existing + weight_update * pos_update);
269 existing.SetMomentum(weight_existing * mom_existing + weight_update * mom_update);
270 existing.SetTime(weight_existing * existing.GetTime() + weight_update * update.GetTime());
271 existing.SetLength(weight_existing * existing.GetLength() + weight_update * update.GetLength());
272 if (weight_update > weight_existing)
273 existing.SetTrackID(update.GetTrackID());
274 existing.SetEnergyLoss(eloss_total);
279 int current_id = start_track_id;
283 LOG(debug4) <<
Form(
"BmnFHCal::GetSurfaceMCTrack. Current particle %d is primary", current_id);
289 LOG(error) <<
Form(
"BmnFHCal::GetSurfaceMCTrack. Current track with id %d has mother but it is "
290 "not stored in MC stack",
294 if (mother_id == current_id) {
295 LOG(error) <<
"BmnFHCal::GetSurfaceMCTrack. Infinite loop detected for track ID: " << current_id;
299 TVector3 current_vtx(current->
Vx(), current->
Vy(), current->
Vz());
303 LOG(debug4) <<
Form(
"BmnFHCal::GetSurfaceMCTrack. Current track with id %d has vtx (%.2f %.2f "
304 "%.2f) inside detector. Its mother %d vtx (%.2f %.2f %.2f) is outside",
305 current_id, current_vtx.
X(), current_vtx.
Y(), current_vtx.
Z(), mother_id,
306 mother_vtx.
X(), mother_vtx.
Y(), mother_vtx.
Z());
310 current_id = mother_id;
static double CalculateEnergyLoss(double step, double edep)
char * Form(const char *fmt,...)
static std::string GetInfoString(uint32_t address)
Return a formatted string with all address components.
TObjArray * GetGeoSensitiveNodes()
static const TString SensitiveVolume_name
TObjArray * GetGeoPassiveNodes()
virtual void Print(const Option_t *opt="") const override
uint32_t GetAddress() const
int GetSurfaceMCTrack(int start_track_id)
Determines the surface-level Monte Carlo track ID associated with the given starting track ID.
std::unique_ptr< BmnFHCalGeo > fGeoHandler
BmnFHCalPoint * AddHit(BmnFHCalPoint *point)
Adds the hit to hits collection.
BmnFHCalPoint * GetHit(uint32_t address)
Retrieves a hit from the collection based on the detector address.
virtual ~BmnFHCal()
Destructor.
virtual void Reset() override
Clears the hit collection.
std::unique_ptr< BmnFHCalPoint > fPoint
virtual void Print(Option_t *) const override
Screen output of hit collection.
BmnFHCal()
Default constructor.
std::map< uint32_t, FairMultiLinkedData > fMultiLinkMap
virtual void ConstructGeometry() override
Constructs geometry from files.
void UpdateHit(BmnFHCalPoint &existing, const BmnFHCalPoint &update)
Updates an existing hit by merging information from a new hit, weighting position,...
virtual void EndOfEvent() override
Called at the end of each event.
virtual void Initialize() override
Initializes detector and FairRun.
virtual void Register() override
Registers the hit collection in the ROOT manager.
TClonesArray * fCollection
virtual void BeginEvent() override
Called at the beginning of each event.
virtual TClonesArray * GetCollection(Int_t iColl) const override
Accessor to the hit collection.
virtual Bool_t ProcessHits(FairVolume *vol=nullptr) override
Processes hits and creates BmnFHCalPoints.
virtual Bool_t CheckIfSensitive(std::string name) override
Checks whether a volume is sensitive based on its name.
TObject * Next() override
Int_t GetEntriesFast() const
void AddLast(TObject *obj) override
Int_t GetFirstMother() const
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
const char * Data() const
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const