FairShip
Loading...
Searching...
No Matches
MTCDetector.py
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 Collaboration
3
4import global_variables
5import ROOT
6import SciFiMapping
7from BaseDetector import BaseDetector
8
9
11 def __init__(self, name, intree, branchName=None, outtree=None) -> None:
12 super().__init__(name, intree, branchName, outtree=outtree)
13 # add MTC module to the list of globals to use it later in the MTCDetHit class. Consistent with SND@LHC approach.
14 # make SiPM to fibre mapping
15 if intree.GetBranch("MTCDetPoint"):
16 lsOfGlobals = ROOT.gROOT.GetListOfGlobals()
17 if global_variables.modules["MTC"] not in lsOfGlobals:
18 lsOfGlobals.Add(global_variables.modules["MTC"])
19 mapping = SciFiMapping.SciFiMapping(global_variables.modules)
20 mapping.make_mapping()
21 self.sipm_to_fibre_map_U, self.sipm_to_fibre_map_V = mapping.get_sipm_to_fibre_map()
22
23 def digitize(self) -> None:
24 """Digitize SND/MTC MC hits.
25
26 Example of fiberID: 123051820, where:
27 - 1: MTC unique ID
28 - 23: layer number
29 - 0: station type (0 for +5 degrees, 1 for -5 degrees, 2 for scint plane)
30 - 5: z-layer number (0-5)
31 - 1820: local fibre ID within the station
32 Example of SiPM global channel (what is seen in the output file): 123001123, where:
33 - 1: MTC unique ID
34 - 23: layer number
35 - 0: station type (0 for +5 degrees, 1 for -5 degrees)
36 - 0: mat number (only 0 by June 2025). In future, if multiple mats per station are used,
37 this number will be 0-N. Currently, this digit is allocated by SiPM channel ID!
38 - 1: SiPM number (automatically assigned based on fibre aggregation settings)
39 - 123: number of the SiPM channel (0-N). The channel number depends on the fibre aggregation setting.
40 """
41 hit_container = {}
42 mc_points = {}
43 norm = {}
44 for k, mc_point in enumerate(self.intree.MTCDetPoint):
45 det_id = mc_point.GetDetectorID()
46 # 0: +5 deg, 1: -5 deg, 2: scint plane
47 station_type = mc_point.GetLayerType()
48 energy_loss = mc_point.GetEnergyLoss()
49
50 if station_type == 0:
51 # +5 degrees fiber station uses U fibers
52 fibre_map = self.sipm_to_fibre_map_U
53 elif station_type == 1:
54 # -5 degrees fiber station uses V fibers
55 fibre_map = self.sipm_to_fibre_map_V
56 elif station_type == 2:
57 # Scint Plane. Preserve the same logic as for fibre stations,
58 # but use the det_id directly as the global channel.
59 global_channel = det_id
60 if global_channel not in hit_container:
61 hit_container[global_channel] = []
62 mc_points[global_channel] = {}
63 norm[global_channel] = 0
64
65 weight = 1
66 # Append (energy_loss, weight) instead of (mc_point, weight)
67 hit_container[global_channel].append([mc_point, weight])
68 d_e = energy_loss * weight
69 mc_points[global_channel][k] = d_e
70 norm[global_channel] += d_e
71 continue
72 else:
73 # Skip any other station_type values
74 continue
75 # For station_type 0 or 1, look up the local fibre ID
76 loc_fibre_id = det_id % 1_000_000
77 if loc_fibre_id not in fibre_map:
78 # If there is no entry for this fibre ID, skip
79 print(
80 f"MTC digitization: no mapping found for fibre ID {loc_fibre_id} in station type {station_type}. Skipping."
81 )
82 continue
83
84 for sipm_chan, chan_info in fibre_map[loc_fibre_id].items():
85 global_channel = (det_id // 1_000_000) * 1_000_000 + sipm_chan
86 if global_channel not in hit_container:
87 hit_container[global_channel] = []
88 mc_points[global_channel] = {}
89 norm[global_channel] = 0
90
91 weight = chan_info["weight"]
92 hit_container[global_channel].append([mc_point, weight])
93 d_e = energy_loss * weight
94 mc_points[global_channel][k] = d_e
95 norm[global_channel] += d_e
96
97 for det_id in hit_container:
98 all_points = ROOT.std.vector("MTCDetPoint*")()
99 all_weights = ROOT.std.vector("Float_t")()
100
101 for entry in hit_container[det_id]:
102 all_points.push_back(entry[0])
103 all_weights.push_back(entry[1])
104 det_hit = ROOT.MTCDetHit(det_id, all_points, all_weights)
105 self.det.push_back(det_hit)
106 # digi2MCPoints will be added later
107 # for idx, de_value in mc_points[det_id].items():
108 # mc_links.Add(det_id, idx, de_value / norm[det_id])
None __init__(self, name, intree, branchName=None, outtree=None)
Definition: MTCDetector.py:11