ATLAS Offline Software
MapperSTG.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include <iostream>
8 //=====================================================================
10 {
11  // Returns the detector-channel index according to ATHENA conventions.
12 
13  int counter {1};
14  int chan = vmm * Muon::nsw::VMM_channels + vmm_chan;
15  const auto& ranges = Muon::nsw::s_stgc_channel_map.at( private_id(channel_type, sector_type, feb_radius, layer) );
16 
17  for (const auto& range : ranges) {
18  int chanFirst = range[0]*Muon::nsw::VMM_channels + range[1];
19  int chanLast = range[2]*Muon::nsw::VMM_channels + range[3];
20  int increment = chanLast >= chanFirst ? 1 : -1;
21 
22  if ( (chan - chanFirst)*(chan - chanLast) <= 0 ) {
23  uint16_t offline_channel = counter + increment*(chan - chanFirst);
24  return AB_to_Athena_channel_number(channel_type, sector_type, feb_radius, layer, offline_channel);
25  }
26 
27  counter += increment*(chanLast - chanFirst) + 1;
28  }
29 
30  return 0; // disconnected vmm channel
31 }
32 
33 
34 //=====================================================================
36 {
37  uint16_t pid = private_id(channel_type, sector_type, feb_radius, layer);
38  const auto& ranges = s_stgc_channel_map.at(pid);
39 
40  int counter{0};
41  for (const auto& range : ranges) {
42  int chanFirst = range[0]*Muon::nsw::VMM_channels + range[1]; // custom id for the first channel in the range
43  int chanLast = range[2]*Muon::nsw::VMM_channels + range[3]; // custom id for the last channel in the range
44  int increment = chanLast >= chanFirst ? 1 : -1;
45  counter += increment*(chanLast - chanFirst) + 1; // number of channels in the range
46  }
47 
48  return counter;
49 }
50 
51 
52 //=====================================================================
53 bool Muon::nsw::MapperSTG::vmm_info (uint8_t channel_type, uint8_t sector_type, uint8_t mod_radius, uint8_t layer, uint16_t channel_number, uint16_t& vmm, uint16_t& vmm_chan) const
54 {
55  // Return vmm and vmm channel given the ATHENA channel index.
56 
57  uint16_t AB_channel = Athena_to_AB_channel_number(channel_type, sector_type, mod_radius, layer, channel_number);
58 
59  uint16_t pid = private_id(channel_type, sector_type, mod_radius, layer);
60  const auto& ranges = s_stgc_channel_map.at(pid);
61 
62  int counter{1};
63  for (const auto& range : ranges) {
64  int chanFirst = range[0]*Muon::nsw::VMM_channels + range[1]; // custom id for the first channel in the range
65  int chanLast = range[2]*Muon::nsw::VMM_channels + range[3]; // custom id for the last channel in the range
66  int increment = chanLast >= chanFirst ? 1 : -1;
67  int nchan = increment*(chanLast - chanFirst) + 1; // number of channels in the range
68 
69  if (AB_channel < counter + nchan) {
70  int chan = chanFirst + increment*(AB_channel - counter);
71  vmm = chan/64;
72  vmm_chan = chan%64;
73  return true;
74  }
75 
76  counter += nchan;
77  }
78 
79  return false;
80 }
81 
82 //=====================================================================
83 bool Muon::nsw::MapperSTG::elink_info (uint8_t channel_type, uint8_t sector_type, uint8_t mod_radius, uint8_t layer, uint16_t channel_number, uint &elink) const
84 {
85  if(mod_radius>0) {elink = 0; return true;} // The boards on Q2 and Q3 are only read out by one elink per board
86  uint16_t vmm{0}, vmm_chan{0};
87  if(!vmm_info (channel_type, sector_type, mod_radius, layer, channel_number, vmm, vmm_chan)) return false;
89  if(geoVmmToRocVmm(vmm) < 4){
90  elink=0;
91  return true;
92  } else{
93  elink=2;
94  return true;
95  }
97  if(geoVmmToRocVmm(vmm)==2){
98  elink=0;
99  return true;
100  } else{
101  elink=2;
102  return true;
103  }
104  }
105  elink = 0;
106  return false;
107 }
108 
109 
110 //=====================================================================
111 
113  constexpr uint16_t vmmRemap[8] = { 2, 3, 0, 1, 5, 4, 6, 7 };
114  return vmmRemap[VMM];
115  }
116 
117 
118 //=====================================================================
120 {
121  // Convert an Adapter-Board channel number into ATHENA channel index.
122 
123  if (channel_number == 0) return channel_number; // invalid (e.g. case of disconnected channel)
124 
126 
127  // AB: wire#1 is on the gas-inlet side; right (left) hand side for pivot (confirm) wedges when looking from the IP.
128  // Athena: wire#1 is on the left-hand side both for pivot and confirm wedges.
129  bool isPivot = (sector_type == 0)^(layer < 4);
130  if (isPivot) channel_number = nchannels(channel_type, sector_type, feb_radius, layer) - channel_number + 1;
131 
132  } else if (channel_type == OFFLINE_CHANNEL_TYPE_PAD) {
133 
134  // AB: pad#1 is on left (right) hand side for even (odd) layers when looking from the IP (counting layers from 0).
135  // Athena: pad#1 is on the right-hand side.
136  uint16_t pid = private_id(channel_type, sector_type, feb_radius, layer);
137  std::pair<uint16_t, uint16_t> pad_grid = s_stgc_pad_grid.at(pid);
138 
139  uint16_t padRow_AB = (channel_number - 1)/pad_grid.second + 1;
140  uint16_t padCol_AB = (channel_number - 1)%pad_grid.second + 1;
141  uint16_t padRow_ATH = pad_grid.first - padRow_AB + 1;
142  uint16_t padCol_ATH = (layer%2==0) ? pad_grid.second - padCol_AB + 1 : padCol_AB; // layer is in [0,7]
143 
144  // Athena pad numbering assumes 18 eta rows (even if a quadruplet has less)
145  channel_number = (padCol_ATH - 1)*18 + padRow_ATH;
146  }
147 
148  return channel_number;
149 }
150 
151 
152 //=====================================================================
154 {
155  // Convert a channel index according to ATHENA numbering convention
156  // into the Adapter-Board channel number.
157 
158  if (channel_number == 0) return channel_number; // invalid (e.g. case of disconnected channel)
159 
161 
162  // AB: wire#1 is on the gas-inlet side; right (left) hand side for pivot (confirm) wedges when looking from the IP.
163  // Athena: wire#1 is on the left-hand side both for pivot and confirm wedges.
164  bool isPivot = (sector_type == 0)^(layer < 4);
165  if (isPivot) channel_number = nchannels(channel_type, sector_type, feb_radius, layer) - channel_number + 1;
166 
167  } else if (channel_type == OFFLINE_CHANNEL_TYPE_PAD) {
168 
169  // AB: pad#1 is on left (right) hand side for even (odd) layers when looking from the IP (counting layers from 0).
170  // Athena: pad#1 is on the right-hand side.
171  uint16_t pid = private_id(channel_type, sector_type, feb_radius, layer);
172  std::pair<uint16_t, uint16_t> pad_grid = s_stgc_pad_grid.at(pid);
173 
174  // Athena pad numbering assumes 18 eta rows (even if a quadruplet has less)
175  uint16_t padRow_ATH = (channel_number - 1)%18 + 1;
176  uint16_t padCol_ATH = (channel_number - 1)/18 + 1;
177  uint16_t padRow_AB = pad_grid.first - padRow_ATH + 1;
178  uint16_t padCol_AB = (layer%2==0) ? pad_grid.second - padCol_ATH + 1 : padCol_ATH; // layer is in [0,7]
179 
180  channel_number = (padRow_AB - 1)*pad_grid.second + padCol_AB;
181  }
182 
183  return channel_number;
184 }
185 
186 
187 //=====================================================================
189 {
190  // Convert a channel index according to the NSWID numbering convention
191  // into ATHENA channel index.
192 
193  if (channel_number == 0) return channel_number; // invalid (e.g. case of disconnected channel)
194 
195  // In NSWID numbering wires and pads follow ATLAS phi.
197 
198  // NSWID: wire#1 is on the left (right) hand side for A-side (C-side) when looking from the IP.
199  // Athena: wire#1 is on the left-hand side both for A- and C-side.
200  if (!sideA) channel_number = nchannels(channel_type, sector_type, feb_radius, layer) - channel_number + 1;
201 
202  } else if (channel_type == OFFLINE_CHANNEL_TYPE_PAD) {
203 
204  // NSWID: pad#1 is on the left (right) hand side for A-side (C-side) when looking from the IP.
205  // Athena: pad#1 is on the right-hand side both for A- and C-side.
206  uint16_t pid = private_id(channel_type, sector_type, feb_radius, layer);
207  std::pair<uint16_t, uint16_t> pad_grid = s_stgc_pad_grid.at(pid);
208 
209  uint16_t padRow = (channel_number - 1)/pad_grid.second + 1;
210  uint16_t padCol_NSW = (channel_number - 1)%pad_grid.second + 1;
211  uint16_t padCol_ATH = (sideA) ? pad_grid.second - padCol_NSW + 1 : padCol_NSW;
212 
213  // Athena pad numbering assumes 18 eta rows (even if a quadruplet has less)
214  channel_number = (padCol_ATH - 1)*18 + padRow;
215  }
216 
217  return channel_number;
218 }
219 
220 
221 //=====================================================================
223 {
224  // Convert a channel index according to ATHENA numbering convention
225  // into NSWID channel index.
226 
227  if (channel_number == 0) return channel_number; // invalid (e.g. case of disconnected channel)
228 
229  // In NSWID numbering wires and pads follow ATLAS phi.
231 
232  // NSWID: wire#1 is on the left (right) hand side for A-side (C-side) when looking from the IP.
233  // Athena: wire#1 is on the left-hand side both for A- and C-side.
234  if (!sideA) channel_number = nchannels(channel_type, sector_type, feb_radius, layer) - channel_number + 1;
235 
236  } else if (channel_type == OFFLINE_CHANNEL_TYPE_PAD) {
237 
238  // NSWID: pad#1 is on the left (right) hand side for A-side (C-side) when looking from the IP.
239  // Athena: pad#1 is on the right-hand side both for A- and C-side.
240  uint16_t pid = private_id(channel_type, sector_type, feb_radius, layer);
241  std::pair<uint16_t, uint16_t> pad_grid = s_stgc_pad_grid.at(pid);
242 
243  // Athena pad numbering assumes 18 eta rows (even if a quadruplet has less)
244  uint16_t padRow = (channel_number - 1)%18 + 1;
245  uint16_t padCol_ATH = (channel_number - 1)/18 + 1;
246  uint16_t padCol_NSW = (sideA) ? pad_grid.second - padCol_ATH + 1 : padCol_ATH;
247  channel_number = (padRow - 1)*pad_grid.second + padCol_NSW;
248  }
249 
250  return channel_number;
251 }
252 
253 
254 
255 
Muon::nsw::VMM_channels
@ VMM_channels
Definition: NSWDecodeHelper.h:32
trigbs_pickEvents.ranges
ranges
Definition: trigbs_pickEvents.py:60
xAOD::uint8_t
uint8_t
Definition: Muon_v1.cxx:557
Muon::nsw::MapperSTG::vmm_info
bool vmm_info(uint8_t channel_type, uint8_t sector_type, uint8_t mod_radius, uint8_t layer, uint16_t channel_number, uint16_t &vmm, uint16_t &vmm_chan) const
Definition: MapperSTG.cxx:53
Muon::nsw::MapperSTG::NSWID_to_Athena_channel_number
uint16_t NSWID_to_Athena_channel_number(uint8_t channel_type, uint8_t sector_type, uint8_t feb_radius, uint8_t layer, uint16_t channel_number, bool sideA) const
Definition: MapperSTG.cxx:188
Muon::nsw::MapperSTG::channel_number
uint16_t channel_number(uint8_t channel_type, uint8_t sector_type, uint8_t feb_radius, uint8_t layer, uint16_t vmm, uint16_t vmm_chan) const
Definition: MapperSTG.cxx:9
PlotCalibFromCool.nchan
nchan
Definition: PlotCalibFromCool.py:564
Muon::nsw::MapperSTG::nchannels
uint16_t nchannels(uint8_t channel_type, uint8_t sector_type, uint8_t feb_radius, uint8_t layer) const
Definition: MapperSTG.cxx:35
Muon::nsw::OFFLINE_CHANNEL_TYPE_PAD
@ OFFLINE_CHANNEL_TYPE_PAD
Definition: NSWDecodeHelper.h:22
Muon::nsw::MapperSTG::geoVmmToRocVmm
uint16_t geoVmmToRocVmm(uint16_t geoVMM) const
Definition: MapperSTG.cxx:112
uint
unsigned int uint
Definition: LArOFPhaseFill.cxx:20
MapperSTG.h
Muon::nsw::MapperSTG::elink_info
bool elink_info(uint8_t channel_type, uint8_t sector_type, uint8_t mod_radius, uint8_t layer, uint16_t channel_number, uint &elink) const
Definition: MapperSTG.cxx:83
xAOD::uint16_t
setWord1 uint16_t
Definition: eFexEMRoI_v1.cxx:88
ReadCellNoiseFromCool.chan
chan
Definition: ReadCellNoiseFromCool.py:52
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
ParticleGun_EoverP_Config.pid
pid
Definition: ParticleGun_EoverP_Config.py:62
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
Muon::nsw::OFFLINE_CHANNEL_TYPE_WIRE
@ OFFLINE_CHANNEL_TYPE_WIRE
Definition: NSWDecodeHelper.h:24
RPDUtils::sideA
unsigned constexpr int sideA
Definition: RPDUtils.h:16
Muon::nsw::MapperSTG::AB_to_Athena_channel_number
uint16_t AB_to_Athena_channel_number(uint8_t channel_type, uint8_t sector_type, uint8_t feb_radius, uint8_t layer, uint16_t channel_number) const
Definition: MapperSTG.cxx:119
Muon::nsw::MapperSTG::Athena_to_AB_channel_number
uint16_t Athena_to_AB_channel_number(uint8_t channel_type, uint8_t sector_type, uint8_t feb_radius, uint8_t layer, uint16_t channel_number) const
Definition: MapperSTG.cxx:153
Muon::nsw::channel_type
channel_type
Definition: NSWDecodeHelper.h:21
Muon::nsw::OFFLINE_CHANNEL_TYPE_STRIP
@ OFFLINE_CHANNEL_TYPE_STRIP
Definition: NSWDecodeHelper.h:23
Muon::nsw::MapperSTG::private_id
static uint16_t private_id(uint8_t channel_type, uint8_t sector_type, uint8_t feb_radius, uint8_t layer)
Definition: MapperSTG.h:263
test_pyathena.counter
counter
Definition: test_pyathena.py:15
Muon::nsw::MapperSTG::Athena_to_NSWID_channel_number
uint16_t Athena_to_NSWID_channel_number(uint8_t channel_type, uint8_t sector_type, uint8_t feb_radius, uint8_t layer, uint16_t channel_number, bool sideA) const
Definition: MapperSTG.cxx:222