FairShip
Loading...
Searching...
No Matches
MTCDetHit.cxx
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-3.0-or-later
2// SPDX-FileCopyrightText: Copyright CERN for the benefit of the SHiP
3// Collaboration
4
5#include "MTCDetHit.h"
6
7#include <TMath.h>
8#include <TRandom.h>
9
10#include <vector>
11
12#include "FairLogger.h"
13#include "FairRunSim.h"
14#include "MTCDetPoint.h"
15#include "MTCDetector.h"
16#include "TGeoBBox.h"
17#include "TGeoManager.h"
18#include "TGeoNavigator.h"
19#include "TROOT.h"
20
21namespace {
22constexpr Float_t n_photons_min = 3.5f;
23constexpr Float_t n_photons_max = 104.0f;
24constexpr Float_t time_res = 150e-3f; // 150 ps
25constexpr Float_t signal_speed = 15.0f; // cm/ns
26const Float_t inv_signal_speed = 1.0f / signal_speed;
27// parameters for simulating the digitized information
28constexpr Float_t light_attenuation_params[2] = {20., 300.}; // x_0, lambda
29constexpr Float_t n_pixels_to_qdc_params[4] = {0.172, -1.31, 0.006,
30 0.33}; // A, B, sigma_A, sigma_B
31
32Float_t light_attenuation(Float_t distance) {
33 return TMath::Exp(-(distance - light_attenuation_params[0]) /
34 light_attenuation_params[1]);
35}
36
37Float_t sipm_saturation(Float_t ly) {
38 Float_t factor = 1 - TMath::Exp(-ly / n_photons_max);
39 return n_photons_max * factor;
40}
41
42Float_t n_pixels_to_qdc(Float_t npix) {
43 Float_t A =
44 gRandom->Gaus(n_pixels_to_qdc_params[0], n_pixels_to_qdc_params[2]);
45 Float_t B =
46 gRandom->Gaus(n_pixels_to_qdc_params[1], n_pixels_to_qdc_params[3]);
47 return A * npix + B;
48}
49} // namespace
50
51// ----- Default constructor -------------------------------------------
52MTCDetHit::MTCDetHit() : SHiP::DetectorHit() {}
53
54// Optimized MTCDetHit Constructor
55
56MTCDetHit::MTCDetHit(int SiPMChan, const std::vector<MTCDetPoint*>& points,
57 const std::vector<Float_t>& weights) {
58 auto* MTCDet =
59 dynamic_cast<MTCDetector*>(gROOT->GetListOfGlobals()->FindObject("MTC"));
60 if (!MTCDet) {
61 LOG(fatal) << "MTCDetHit: MTCDetector not found";
62 return;
63 }
64
65 fDetectorID = SiPMChan; // Set the detector ID
66 // Determine plane type once
67 const int plane_type = GetStationType();
68
69 Float_t total_light_yield = 0.0f;
70 Float_t earliest_to_A = std::numeric_limits<Float_t>::max();
71 Float_t earliest_to_B = std::numeric_limits<Float_t>::max();
72 const size_t n = points.size();
73 Float_t signal_sum = 0.0f;
74 bool hit_flag = false;
75
76 // Separate handling for scintillating mat (plane_type == 2)
77 if (plane_type == 2) {
78 Float_t x_temp = 0.0, y_temp = 0.0, z_temp = 0.0;
79 for (auto* pt : points) {
80 signal_sum += pt->GetEnergyLoss();
81 // Track earliest arrival time
82 Float_t arrival = pt->GetTime();
83 earliest_to_B = std::min(earliest_to_B, arrival);
84 x_temp += pt->GetX();
85 y_temp += pt->GetY();
86 z_temp += pt->GetZ();
87 }
88 time = gRandom->Gaus(earliest_to_B, time_res);
89 // for scintillating tiles set simulated coordinates so far as the realistic
90 // geometry is not yet done.
91 Xch = x_temp / n;
92 Ych = y_temp / n;
93 Zch = z_temp / n;
94 signals = signal_sum;
95 return;
96 }
97
98 // Fiber hit processing
99 total_light_yield = 0.0f;
100
101 TVector3 sipmA, sipmB;
102 MTCDet->GetSiPMPosition(SiPMChan, sipmA, sipmB);
103 // Define only X and Z coordinates for Sci-Fi.
104 Xch = sipmB.X();
105 Zch = sipmB.Z();
106
107 for (size_t i = 0; i < n; ++i) {
108 auto* pt = points[i];
109 Float_t energy = pt->GetEnergyLoss();
110 Float_t weight = weights[i];
111 Float_t signal = energy * weight;
112
113 // Distance from deposit to SiPM
114 TVector3 impact(pt->GetX(), pt->GetY(), pt->GetZ());
115 const Float_t distance = (sipmB - impact).Mag();
116
117 // Light yield before attenuation
118 Float_t light_yield = signal * 1e6f * 0.16f;
119 light_yield *= light_attenuation(distance);
120 total_light_yield += light_yield;
121
122 // Track earliest arrival time
123 Float_t arrival = pt->GetTime() + distance * inv_signal_speed;
124 earliest_to_A = std::min(earliest_to_A, arrival);
125 }
126
127 // Apply statistical smearing and saturation
128 const Int_t smeared_light_yield = gRandom->Poisson(total_light_yield);
129 const Float_t n_pixels = sipm_saturation(smeared_light_yield);
130 signals = n_pixels_to_qdc(n_pixels);
131
132 // Final hit decision and time
133 hit_flag = (smeared_light_yield > n_photons_min);
134 flag = hit_flag;
135 time = gRandom->Gaus(earliest_to_A, time_res);
136}
137
138// ----- Public method GetEnergy -------------------------------------------
139Float_t MTCDetHit::GetEnergy() const {
140 // to be calculated from digis and calibration constants, missing!
141 return signals;
142}
143
144// ----- Public method Print -------------------------------------------
145void MTCDetHit::Print() const {
146 std::cout << Form(
147 "MTCDetHit: Detector ID %d, Layer %d, Station Type %d, SiPM %d, Channel "
148 "%d, Signal %.2f, Time %.3f \n",
150 signals, time);
151}
Definition: diagrams_a.h:3
Definition: diagrams_b.h:4
Int_t GetSiPMChan() const
Definition: MTCDetHit.h:57
Float_t time
Definition: MTCDetHit.h:69
Int_t GetStationType() const
Definition: MTCDetHit.h:53
Bool_t flag
flag
Definition: MTCDetHit.h:71
Float_t signals
Definition: MTCDetHit.h:68
Float_t Ych
Definition: MTCDetHit.h:70
Float_t Zch
Definition: MTCDetHit.h:70
Float_t GetEnergy() const
Definition: MTCDetHit.cxx:139
Float_t Xch
Definition: MTCDetHit.h:70
void Print() const
Definition: MTCDetHit.cxx:145
Int_t GetSiPM() const
Definition: MTCDetHit.h:56
Int_t GetLayer() const
Definition: MTCDetHit.h:50
Int_t fDetectorID
Detector unique identifier.
Definition: DetectorHit.h:40
#define B
Definition: memgrp.cpp:39
Definition: Detector.h:18