]>
Commit | Line | Data |
---|---|---|
1a1fdef7 | 1 | /************************************************************************** |
2 | * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * | |
3 | * * | |
4 | * Author: The ALICE Off-line Project. * | |
5 | * Contributors are mentioned in the code where appropriate. * | |
6 | * * | |
7 | * Permission to use, copy, modify and distribute this software and its * | |
8 | * documentation strictly for non-commercial purposes is hereby granted * | |
9 | * without fee, provided that the above copyright notice appears in all * | |
10 | * copies and that both the copyright notice and this permission notice * | |
11 | * appear in the supporting documentation. The authors make no claims * | |
12 | * about the suitability of this software for any purpose. It is * | |
13 | * provided "as is" without express or implied warranty. * | |
14 | **************************************************************************/ | |
15 | ||
16 | /* $Id$ */ | |
17 | ||
18 | //____________________________________________________________________ | |
19 | // | |
20 | // Forward Multiplicity Detector based on Silicon wafers. | |
21 | // | |
22 | // This class is a singleton that handles various parameters of | |
23 | // the FMD detectors. | |
088f8e79 | 24 | // Eventually, this class will use the Conditions DB to get the |
25 | // various parameters, which code can then request from here. | |
1a1fdef7 | 26 | // |
8f6ee336 | 27 | #include "AliLog.h" // ALILOG_H |
28 | #include "AliFMDParameters.h" // ALIFMDPARAMETERS_H | |
29 | #include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H | |
30 | #include "AliFMDRing.h" // ALIFMDRING_H | |
31 | #include "AliFMDCalibGain.h" // ALIFMDCALIBGAIN_H | |
32 | #include "AliFMDCalibPedestal.h" // ALIFMDCALIBPEDESTAL_H | |
33 | #include "AliFMDCalibSampleRate.h" // ALIFMDCALIBPEDESTAL_H | |
1a1fdef7 | 34 | #include <Riostream.h> |
35 | ||
36 | //==================================================================== | |
37 | ClassImp(AliFMDParameters) | |
38 | #if 0 | |
39 | ; // This is here to keep Emacs for indenting the next line | |
40 | #endif | |
41 | ||
42 | //____________________________________________________________________ | |
43 | AliFMDParameters* AliFMDParameters::fgInstance = 0; | |
44 | ||
45 | //____________________________________________________________________ | |
46 | AliFMDParameters* | |
47 | AliFMDParameters::Instance() | |
48 | { | |
49 | // Get static instance | |
50 | if (!fgInstance) fgInstance = new AliFMDParameters; | |
51 | return fgInstance; | |
52 | } | |
53 | ||
54 | //____________________________________________________________________ | |
55 | AliFMDParameters::AliFMDParameters() | |
8f6ee336 | 56 | : fSiDeDxMip(1.664), |
57 | fFixedPulseGain(0), | |
58 | fEdepMip(0), | |
59 | fZeroSuppression(0), | |
60 | fSampleRate(0), | |
61 | fPedestal(0), | |
62 | fPulseGain(0), | |
63 | fDeadMap(0) | |
1a1fdef7 | 64 | { |
65 | // Default constructor | |
66 | SetVA1MipRange(); | |
67 | SetAltroChannelSize(); | |
68 | SetChannelsPerAltro(); | |
69 | SetZeroSuppression(); | |
70 | SetSampleRate(); | |
71 | SetPedestal(); | |
72 | SetPedestalWidth(); | |
73 | SetPedestalFactor(); | |
8f6ee336 | 74 | SetThreshold(); |
1a1fdef7 | 75 | } |
76 | ||
8f6ee336 | 77 | //__________________________________________________________________ |
78 | Float_t | |
79 | AliFMDParameters::GetThreshold() const | |
80 | { | |
81 | if (!fPulseGain) return fFixedThreshold; | |
82 | return fPulseGain->Threshold(); | |
83 | } | |
84 | ||
85 | //__________________________________________________________________ | |
86 | Float_t | |
87 | AliFMDParameters::GetPulseGain(UShort_t detector, Char_t ring, | |
88 | UShort_t sector, UShort_t strip) const | |
89 | { | |
90 | // Returns the pulser calibrated gain for strip # strip in sector # | |
91 | // sector or ring id ring of detector # detector. | |
92 | // | |
93 | // For simulation, this is normally set to | |
94 | // | |
95 | // VA1_MIP_Range | |
96 | // ------------------ * MIP_Energy_Loss | |
97 | // ALTRO_channel_size | |
98 | // | |
99 | if (!fPulseGain) { | |
100 | if (fFixedPulseGain <= 0) | |
101 | fFixedPulseGain = fVA1MipRange * GetEdepMip() / fAltroChannelSize; | |
102 | return fFixedPulseGain; | |
103 | } | |
104 | return fPulseGain->Value(detector, ring, sector, strip); | |
105 | } | |
106 | ||
107 | //__________________________________________________________________ | |
108 | Bool_t | |
109 | AliFMDParameters::IsDead(UShort_t detector, Char_t ring, | |
110 | UShort_t sector, UShort_t strip) const | |
111 | { | |
112 | if (!fDeadMap) return kFALSE; | |
113 | return fDeadMap->operator()(detector, ring, sector, strip); | |
114 | } | |
115 | ||
116 | //__________________________________________________________________ | |
117 | UShort_t | |
118 | AliFMDParameters::GetZeroSuppression(UShort_t detector, Char_t ring, | |
119 | UShort_t sector, UShort_t strip) const | |
120 | { | |
121 | if (!fZeroSuppression) return fFixedZeroSuppression; | |
122 | // Need to map strip to ALTRO chip. | |
123 | return fZeroSuppression->operator()(detector, ring, sector, strip/128); | |
124 | } | |
125 | ||
126 | //__________________________________________________________________ | |
127 | UShort_t | |
128 | AliFMDParameters::GetSampleRate(UShort_t ddl) const | |
129 | { | |
130 | if (!fSampleRate) return fFixedSampleRate; | |
131 | // Need to map sector to digitizier card. | |
132 | return fSampleRate->Rate(ddl); | |
133 | } | |
1a1fdef7 | 134 | |
8f6ee336 | 135 | //__________________________________________________________________ |
136 | Float_t | |
137 | AliFMDParameters::GetPedestal(UShort_t detector, Char_t ring, | |
138 | UShort_t sector, UShort_t strip) const | |
139 | { | |
140 | if (!fPedestal) return fFixedPedestal; | |
141 | return fPedestal->Value(detector, ring, sector, strip); | |
142 | } | |
143 | ||
144 | //__________________________________________________________________ | |
145 | Float_t | |
146 | AliFMDParameters::GetPedestalWidth(UShort_t detector, Char_t ring, | |
147 | UShort_t sector, UShort_t strip) const | |
148 | { | |
149 | if (!fPedestal) return fFixedPedestalWidth; | |
150 | return fPedestal->Width(detector, ring, sector, strip); | |
151 | } | |
152 | ||
153 | ||
1a1fdef7 | 154 | |
155 | //__________________________________________________________________ | |
156 | Float_t | |
157 | AliFMDParameters::GetEdepMip() const | |
158 | { | |
159 | // Get energy deposited by a MIP in the silicon sensors | |
8f6ee336 | 160 | if (fEdepMip <= 0){ |
161 | AliFMDGeometry* fmd = AliFMDGeometry::Instance(); | |
162 | fEdepMip = (fSiDeDxMip | |
163 | * fmd->GetRing('I')->GetSiThickness() | |
164 | * fmd->GetSiDensity()); | |
165 | } | |
166 | return fEdepMip; | |
1a1fdef7 | 167 | } |
168 | ||
bf000c32 | 169 | //__________________________________________________________________ |
170 | Bool_t | |
171 | AliFMDParameters::Hardware2Detector(UInt_t ddl, UInt_t addr, UShort_t& det, | |
172 | Char_t& ring, UShort_t& sec, | |
173 | UShort_t& str) const | |
174 | { | |
175 | // Translate a hardware address to detector coordinates. | |
176 | // The detector is simply | |
177 | // | |
178 | // ddl - kBaseDDL + 1 | |
179 | // | |
180 | // The ring number, sector, and strip number is given by the addr | |
181 | // argument. The address argument, has the following format | |
182 | // | |
183 | // 12 7 4 0 | |
184 | // +-------------+----------+----------+ | |
185 | // | Board | ALTRO | Channel | | |
186 | // +-------------+----------+----------+ | |
187 | // | |
188 | // The board number identifier among other things the ring. There's | |
189 | // up to 4 boards per DDL, and the two first (0 and 1) corresponds | |
190 | // to the inner rings, while the two last (2 and 3) corresponds to | |
191 | // the outer rings. | |
192 | // | |
193 | // The board number and ALTRO number together identifies the sensor, | |
194 | // and hence. The lower board number (0 or 2) are the first N / 2 | |
195 | // sensors (where N is the number of sensors in the ring). | |
196 | // | |
197 | // There are 3 ALTRO's per card, and each ALTRO serves up to 4 | |
198 | // sensors. Which of sensor is determined by the channel number. | |
199 | // For the inner rings, the map is | |
200 | // | |
201 | // ALTRO 0, Channel 0 to 7 -> Sensor 0 or 5 | |
202 | // ALTRO 0, Channel 8 to 15 -> Sensor 1 or 6 | |
203 | // ALTRO 1, Channel 0 to 7 -> Sensor 2 or 7 | |
204 | // ALTRO 2, Channel 0 to 7 -> Sensor 3 or 8 | |
205 | // ALTRO 2, Channel 8 to 15 -> Sensor 4 or 9 | |
206 | // | |
207 | // For the outer rings, the map is | |
208 | // | |
209 | // ALTRO 0, Channel 0 to 3 -> Sensor 0 or 10 | |
210 | // ALTRO 0, Channel 4 to 7 -> Sensor 1 or 11 | |
211 | // ALTRO 0, Channel 8 to 11 -> Sensor 2 or 12 | |
212 | // ALTRO 0, Channel 12 to 15 -> Sensor 3 or 13 | |
213 | // ALTRO 1, Channel 0 to 3 -> Sensor 4 or 14 | |
214 | // ALTRO 1, Channel 4 to 7 -> Sensor 5 or 15 | |
215 | // ALTRO 2, Channel 0 to 3 -> Sensor 6 or 16 | |
216 | // ALTRO 2, Channel 4 to 7 -> Sensor 7 or 17 | |
217 | // ALTRO 2, Channel 8 to 11 -> Sensor 8 or 18 | |
218 | // ALTRO 2, Channel 12 to 15 -> Sensor 9 or 19 | |
219 | // | |
220 | // Which divison of the sensor we're in, depends on the channel | |
221 | // number only. For the inner rings, the map is | |
222 | // | |
223 | // Channel 0 -> Sector 0, strips 0-127 | |
224 | // Channel 1 -> Sector 1, strips 0-127 | |
225 | // Channel 3 -> Sector 0, strips 128-255 | |
226 | // Channel 4 -> Sector 1, strips 128-255 | |
227 | // Channel 5 -> Sector 0, strips 256-383 | |
228 | // Channel 6 -> Sector 1, strips 256-383 | |
229 | // Channel 7 -> Sector 0, strips 384-511 | |
230 | // Channel 8 -> Sector 1, strips 384-511 | |
231 | // | |
232 | // There are only half as many strips in the outer sensors, so there | |
233 | // only 4 channels are used for a full sensor. The map is | |
234 | // | |
235 | // Channel 0 -> Sector 0, strips 0-127 | |
236 | // Channel 1 -> Sector 1, strips 0-127 | |
237 | // Channel 3 -> Sector 0, strips 128-255 | |
238 | // Channel 4 -> Sector 1, strips 128-255 | |
239 | // | |
240 | // With this information, we can decode the hardware address to give | |
241 | // us detector coordinates, unique at least up a 128 strips. We | |
242 | // return the first strip in the given range. | |
243 | // | |
244 | det = (ddl - kBaseDDL) + 1; | |
245 | UInt_t board = (addr >> 7) & 0x1F; | |
246 | UInt_t altro = (addr >> 4) & 0x7; | |
247 | UInt_t chan = (addr & 0xf); | |
248 | if (board > 3) { | |
249 | AliError(Form("Invalid board address %d for the FMD", board)); | |
250 | return kFALSE; | |
251 | } | |
252 | if (altro > 2) { | |
253 | AliError(Form("Invalid ALTRO address %d for the FMD digitizer %d", | |
254 | altro, board)); | |
255 | return kFALSE; | |
256 | } | |
257 | ring = (board > 1 ? 'O' : 'I'); | |
258 | UInt_t nsen = (ring == 'I' ? 10 : 20); | |
259 | UInt_t nsa = (ring == 'I' ? 2 : 4); // Sensors per ALTRO | |
260 | UInt_t ncs = (ring == 'I' ? 8 : 4); // Channels per sensor | |
261 | UInt_t sen = (board % 2) * nsen / 2; // Base for half-ring | |
262 | sen += chan / ncs + (altro == 0 ? 0 : | |
263 | altro == 1 ? nsa : UInt_t(1.5 * nsa)); | |
264 | sec = 2 * sen + (chan % 2); | |
265 | str = (chan % ncs) / 2 * 128; | |
266 | return kTRUE; | |
267 | } | |
268 | ||
269 | //__________________________________________________________________ | |
270 | Bool_t | |
271 | AliFMDParameters::Detector2Hardware(UShort_t det, Char_t ring, UShort_t sec, | |
272 | UShort_t str, UInt_t& ddl, UInt_t& addr) | |
273 | const | |
274 | { | |
275 | // Translate detector coordinates to a hardware address. | |
276 | // The ddl is simply | |
277 | // | |
278 | // kBaseDDL + (det - 1) | |
279 | // | |
280 | // The ring number, sector, and strip number must be encoded into a | |
281 | // hardware address. The address argument, will have the following | |
282 | // format on output | |
283 | // | |
284 | // 12 7 4 0 | |
285 | // +-------------+----------+----------+ | |
286 | // | Board | ALTRO | Channel | | |
287 | // +-------------+----------+----------+ | |
288 | // | |
289 | // The board number is given by the ring and sector. The inner | |
290 | // rings board 0 and 1, while the outer are 2 and 3. Which of these | |
291 | // depends on the sector. The map is | |
292 | // | |
293 | // Ring I, sector 0- 9 -> board 0 | |
294 | // Ring I, sector 10-19 -> board 1 | |
295 | // Ring O, sector 0-19 -> board 2 | |
296 | // Ring O, sector 20-39 -> board 3 | |
297 | // | |
298 | // There are 3 ALTRO's per board. The ALTRO number is given by the | |
299 | // sector number. For the inner rings, these are given by | |
300 | // | |
301 | // Sector 0- 3 or 10-13 -> ALTRO 0 | |
302 | // Sector 4- 5 or 14-15 -> ALTRO 1 | |
303 | // Sector 6- 9 or 16-19 -> ALTRO 2 | |
304 | // | |
305 | // For the outers, it's given by | |
306 | // | |
307 | // Sector 0- 7 or 20-27 -> ALTRO 0 | |
308 | // Sector 8-11 or 28-31 -> ALTRO 1 | |
309 | // Sector 12-19 or 32-39 -> ALTRO 2 | |
310 | // | |
311 | // The channel number is given by the sector and strip number. For | |
312 | // the inners, the map is | |
313 | // | |
314 | // Sector 0, strips 0-127 -> Channel 0 | |
315 | // Sector 0, strips 128-255 -> Channel 2 | |
316 | // Sector 0, strips 256-383 -> Channel 4 | |
317 | // Sector 0, strips 384-511 -> Channel 6 | |
318 | // Sector 1, strips 0-127 -> Channel 1 | |
319 | // Sector 1, strips 128-255 -> Channel 3 | |
320 | // Sector 1, strips 256-383 -> Channel 5 | |
321 | // Sector 1, strips 384-511 -> Channel 7 | |
322 | // Sector 2, strips 0-127 -> Channel 8 | |
323 | // Sector 2, strips 128-255 -> Channel 10 | |
324 | // Sector 2, strips 256-383 -> Channel 12 | |
325 | // Sector 2, strips 384-511 -> Channel 14 | |
326 | // Sector 3, strips 0-127 -> Channel 9 | |
327 | // Sector 3, strips 128-255 -> Channel 11 | |
328 | // Sector 3, strips 256-383 -> Channel 13 | |
329 | // Sector 3, strips 384-511 -> Channel 15 | |
330 | // | |
331 | // and so on, up to sector 19. For the outer, the map is | |
332 | // | |
333 | // Sector 0, strips 0-127 -> Channel 0 | |
334 | // Sector 0, strips 128-255 -> Channel 2 | |
335 | // Sector 1, strips 0-127 -> Channel 1 | |
336 | // Sector 1, strips 128-255 -> Channel 3 | |
337 | // Sector 2, strips 0-127 -> Channel 4 | |
338 | // Sector 2, strips 128-255 -> Channel 6 | |
339 | // Sector 3, strips 0-127 -> Channel 5 | |
340 | // Sector 3, strips 128-255 -> Channel 7 | |
341 | // Sector 4, strips 0-127 -> Channel 8 | |
342 | // Sector 4, strips 128-255 -> Channel 10 | |
343 | // Sector 5, strips 0-127 -> Channel 9 | |
344 | // Sector 5, strips 128-255 -> Channel 11 | |
345 | // Sector 6, strips 0-127 -> Channel 12 | |
346 | // Sector 6, strips 128-255 -> Channel 14 | |
347 | // Sector 7, strips 0-127 -> Channel 13 | |
348 | // Sector 7, strips 128-255 -> Channel 15 | |
349 | // | |
350 | // and so on upto sector 40. | |
351 | // | |
352 | // With this information, we can decode the detector coordinates to | |
353 | // give us a unique hardware address | |
354 | // | |
355 | ddl = kBaseDDL + (det - 1); | |
356 | UInt_t nsen = (ring == 'I' ? 10 : 20); | |
357 | UInt_t nsa = (ring == 'I' ? 2 : 4); // Sensors per ALTRO | |
358 | UInt_t ncs = (ring == 'I' ? 8 : 4); // Channels per sensor | |
359 | UInt_t bbase = (ring == 'I' ? 0 : 2); | |
360 | UInt_t board = bbase + sec / nsen; | |
361 | UInt_t lsen = (sec - (board - bbase) * nsen); | |
362 | UInt_t altro = (lsen < 2 * nsa ? 0 : (lsen < 3 * nsa ? 1 : 2)); | |
363 | UInt_t sbase = (lsen < 2 * nsa ? 0 : (lsen < 3 * nsa ? 2*nsa : 3*nsa)); | |
364 | UInt_t chan = (sec % 2) + (lsen-sbase) / 2 * ncs + 2 * str / 128; | |
365 | AliDebug(40, Form("\n" | |
366 | " chan = (%d %% 2) + (%d-%d) / %d * %d + 2 * %d / 128\n" | |
367 | " = %d + %d + %d = %d", | |
368 | sec, lsen, sbase, 2, ncs, str, | |
369 | (sec % 2), (lsen - sbase) / 2 * ncs, | |
370 | 2 * str / 128, chan)); | |
371 | addr = chan + (altro << 4) + (board << 7); | |
372 | ||
373 | return kTRUE; | |
374 | } | |
375 | ||
376 | ||
377 | ||
378 | ||
1a1fdef7 | 379 | //____________________________________________________________________ |
380 | // | |
381 | // EOF | |
382 | // |