//
// This class is a singleton that handles various parameters of
// the FMD detectors.
+// Eventually, this class will use the Conditions DB to get the
+// various parameters, which code can then request from here.
//
-#include "AliFMDParameters.h" // ALIFMDPARAMETERS_H
-#include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H
-#include "AliFMDRing.h" // ALIFMDRING_H
-#include "AliLog.h" // ALILOG_H
+#include "AliLog.h" // ALILOG_H
+#include "AliFMDParameters.h" // ALIFMDPARAMETERS_H
+#include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H
+#include "AliFMDRing.h" // ALIFMDRING_H
+#include "AliFMDCalibGain.h" // ALIFMDCALIBGAIN_H
+#include "AliFMDCalibPedestal.h" // ALIFMDCALIBPEDESTAL_H
+#include "AliFMDCalibSampleRate.h" // ALIFMDCALIBPEDESTAL_H
#include <Riostream.h>
//====================================================================
//____________________________________________________________________
AliFMDParameters::AliFMDParameters()
- : fSiDeDxMip(1.664)
+ : fSiDeDxMip(1.664),
+ fFixedPulseGain(0),
+ fEdepMip(0),
+ fZeroSuppression(0),
+ fSampleRate(0),
+ fPedestal(0),
+ fPulseGain(0),
+ fDeadMap(0)
{
// Default constructor
SetVA1MipRange();
SetPedestal();
SetPedestalWidth();
SetPedestalFactor();
+ SetThreshold();
}
+//__________________________________________________________________
+Float_t
+AliFMDParameters::GetThreshold() const
+{
+ if (!fPulseGain) return fFixedThreshold;
+ return fPulseGain->Threshold();
+}
+
+//__________________________________________________________________
+Float_t
+AliFMDParameters::GetPulseGain(UShort_t detector, Char_t ring,
+ UShort_t sector, UShort_t strip) const
+{
+ // Returns the pulser calibrated gain for strip # strip in sector #
+ // sector or ring id ring of detector # detector.
+ //
+ // For simulation, this is normally set to
+ //
+ // VA1_MIP_Range
+ // ------------------ * MIP_Energy_Loss
+ // ALTRO_channel_size
+ //
+ if (!fPulseGain) {
+ if (fFixedPulseGain <= 0)
+ fFixedPulseGain = fVA1MipRange * GetEdepMip() / fAltroChannelSize;
+ return fFixedPulseGain;
+ }
+ return fPulseGain->Value(detector, ring, sector, strip);
+}
+
+//__________________________________________________________________
+Bool_t
+AliFMDParameters::IsDead(UShort_t detector, Char_t ring,
+ UShort_t sector, UShort_t strip) const
+{
+ if (!fDeadMap) return kFALSE;
+ return fDeadMap->operator()(detector, ring, sector, strip);
+}
+
+//__________________________________________________________________
+UShort_t
+AliFMDParameters::GetZeroSuppression(UShort_t detector, Char_t ring,
+ UShort_t sector, UShort_t strip) const
+{
+ if (!fZeroSuppression) return fFixedZeroSuppression;
+ // Need to map strip to ALTRO chip.
+ return fZeroSuppression->operator()(detector, ring, sector, strip/128);
+}
+
+//__________________________________________________________________
+UShort_t
+AliFMDParameters::GetSampleRate(UShort_t ddl) const
+{
+ if (!fSampleRate) return fFixedSampleRate;
+ // Need to map sector to digitizier card.
+ return fSampleRate->Rate(ddl);
+}
+//__________________________________________________________________
+Float_t
+AliFMDParameters::GetPedestal(UShort_t detector, Char_t ring,
+ UShort_t sector, UShort_t strip) const
+{
+ if (!fPedestal) return fFixedPedestal;
+ return fPedestal->Value(detector, ring, sector, strip);
+}
+
+//__________________________________________________________________
+Float_t
+AliFMDParameters::GetPedestalWidth(UShort_t detector, Char_t ring,
+ UShort_t sector, UShort_t strip) const
+{
+ if (!fPedestal) return fFixedPedestalWidth;
+ return fPedestal->Width(detector, ring, sector, strip);
+}
+
+
//__________________________________________________________________
Float_t
AliFMDParameters::GetEdepMip() const
{
// Get energy deposited by a MIP in the silicon sensors
- AliFMDGeometry* fmd = AliFMDGeometry::Instance();
- return (fSiDeDxMip
- * fmd->GetRing('I')->GetSiThickness()
- * fmd->GetSiDensity());
+ if (fEdepMip <= 0){
+ AliFMDGeometry* fmd = AliFMDGeometry::Instance();
+ fEdepMip = (fSiDeDxMip
+ * fmd->GetRing('I')->GetSiThickness()
+ * fmd->GetSiDensity());
+ }
+ return fEdepMip;
+}
+
+//__________________________________________________________________
+Bool_t
+AliFMDParameters::Hardware2Detector(UInt_t ddl, UInt_t addr, UShort_t& det,
+ Char_t& ring, UShort_t& sec,
+ UShort_t& str) const
+{
+ // Translate a hardware address to detector coordinates.
+ // The detector is simply
+ //
+ // ddl - kBaseDDL + 1
+ //
+ // The ring number, sector, and strip number is given by the addr
+ // argument. The address argument, has the following format
+ //
+ // 12 7 4 0
+ // +-------------+----------+----------+
+ // | Board | ALTRO | Channel |
+ // +-------------+----------+----------+
+ //
+ // The board number identifier among other things the ring. There's
+ // up to 4 boards per DDL, and the two first (0 and 1) corresponds
+ // to the inner rings, while the two last (2 and 3) corresponds to
+ // the outer rings.
+ //
+ // The board number and ALTRO number together identifies the sensor,
+ // and hence. The lower board number (0 or 2) are the first N / 2
+ // sensors (where N is the number of sensors in the ring).
+ //
+ // There are 3 ALTRO's per card, and each ALTRO serves up to 4
+ // sensors. Which of sensor is determined by the channel number.
+ // For the inner rings, the map is
+ //
+ // ALTRO 0, Channel 0 to 7 -> Sensor 0 or 5
+ // ALTRO 0, Channel 8 to 15 -> Sensor 1 or 6
+ // ALTRO 1, Channel 0 to 7 -> Sensor 2 or 7
+ // ALTRO 2, Channel 0 to 7 -> Sensor 3 or 8
+ // ALTRO 2, Channel 8 to 15 -> Sensor 4 or 9
+ //
+ // For the outer rings, the map is
+ //
+ // ALTRO 0, Channel 0 to 3 -> Sensor 0 or 10
+ // ALTRO 0, Channel 4 to 7 -> Sensor 1 or 11
+ // ALTRO 0, Channel 8 to 11 -> Sensor 2 or 12
+ // ALTRO 0, Channel 12 to 15 -> Sensor 3 or 13
+ // ALTRO 1, Channel 0 to 3 -> Sensor 4 or 14
+ // ALTRO 1, Channel 4 to 7 -> Sensor 5 or 15
+ // ALTRO 2, Channel 0 to 3 -> Sensor 6 or 16
+ // ALTRO 2, Channel 4 to 7 -> Sensor 7 or 17
+ // ALTRO 2, Channel 8 to 11 -> Sensor 8 or 18
+ // ALTRO 2, Channel 12 to 15 -> Sensor 9 or 19
+ //
+ // Which divison of the sensor we're in, depends on the channel
+ // number only. For the inner rings, the map is
+ //
+ // Channel 0 -> Sector 0, strips 0-127
+ // Channel 1 -> Sector 1, strips 0-127
+ // Channel 3 -> Sector 0, strips 128-255
+ // Channel 4 -> Sector 1, strips 128-255
+ // Channel 5 -> Sector 0, strips 256-383
+ // Channel 6 -> Sector 1, strips 256-383
+ // Channel 7 -> Sector 0, strips 384-511
+ // Channel 8 -> Sector 1, strips 384-511
+ //
+ // There are only half as many strips in the outer sensors, so there
+ // only 4 channels are used for a full sensor. The map is
+ //
+ // Channel 0 -> Sector 0, strips 0-127
+ // Channel 1 -> Sector 1, strips 0-127
+ // Channel 3 -> Sector 0, strips 128-255
+ // Channel 4 -> Sector 1, strips 128-255
+ //
+ // With this information, we can decode the hardware address to give
+ // us detector coordinates, unique at least up a 128 strips. We
+ // return the first strip in the given range.
+ //
+ det = (ddl - kBaseDDL) + 1;
+ UInt_t board = (addr >> 7) & 0x1F;
+ UInt_t altro = (addr >> 4) & 0x7;
+ UInt_t chan = (addr & 0xf);
+ if (board > 3) {
+ AliError(Form("Invalid board address %d for the FMD", board));
+ return kFALSE;
+ }
+ if (altro > 2) {
+ AliError(Form("Invalid ALTRO address %d for the FMD digitizer %d",
+ altro, board));
+ return kFALSE;
+ }
+ ring = (board > 1 ? 'O' : 'I');
+ UInt_t nsen = (ring == 'I' ? 10 : 20);
+ UInt_t nsa = (ring == 'I' ? 2 : 4); // Sensors per ALTRO
+ UInt_t ncs = (ring == 'I' ? 8 : 4); // Channels per sensor
+ UInt_t sen = (board % 2) * nsen / 2; // Base for half-ring
+ sen += chan / ncs + (altro == 0 ? 0 :
+ altro == 1 ? nsa : UInt_t(1.5 * nsa));
+ sec = 2 * sen + (chan % 2);
+ str = (chan % ncs) / 2 * 128;
+ return kTRUE;
+}
+
+//__________________________________________________________________
+Bool_t
+AliFMDParameters::Detector2Hardware(UShort_t det, Char_t ring, UShort_t sec,
+ UShort_t str, UInt_t& ddl, UInt_t& addr)
+ const
+{
+ // Translate detector coordinates to a hardware address.
+ // The ddl is simply
+ //
+ // kBaseDDL + (det - 1)
+ //
+ // The ring number, sector, and strip number must be encoded into a
+ // hardware address. The address argument, will have the following
+ // format on output
+ //
+ // 12 7 4 0
+ // +-------------+----------+----------+
+ // | Board | ALTRO | Channel |
+ // +-------------+----------+----------+
+ //
+ // The board number is given by the ring and sector. The inner
+ // rings board 0 and 1, while the outer are 2 and 3. Which of these
+ // depends on the sector. The map is
+ //
+ // Ring I, sector 0- 9 -> board 0
+ // Ring I, sector 10-19 -> board 1
+ // Ring O, sector 0-19 -> board 2
+ // Ring O, sector 20-39 -> board 3
+ //
+ // There are 3 ALTRO's per board. The ALTRO number is given by the
+ // sector number. For the inner rings, these are given by
+ //
+ // Sector 0- 3 or 10-13 -> ALTRO 0
+ // Sector 4- 5 or 14-15 -> ALTRO 1
+ // Sector 6- 9 or 16-19 -> ALTRO 2
+ //
+ // For the outers, it's given by
+ //
+ // Sector 0- 7 or 20-27 -> ALTRO 0
+ // Sector 8-11 or 28-31 -> ALTRO 1
+ // Sector 12-19 or 32-39 -> ALTRO 2
+ //
+ // The channel number is given by the sector and strip number. For
+ // the inners, the map is
+ //
+ // Sector 0, strips 0-127 -> Channel 0
+ // Sector 0, strips 128-255 -> Channel 2
+ // Sector 0, strips 256-383 -> Channel 4
+ // Sector 0, strips 384-511 -> Channel 6
+ // Sector 1, strips 0-127 -> Channel 1
+ // Sector 1, strips 128-255 -> Channel 3
+ // Sector 1, strips 256-383 -> Channel 5
+ // Sector 1, strips 384-511 -> Channel 7
+ // Sector 2, strips 0-127 -> Channel 8
+ // Sector 2, strips 128-255 -> Channel 10
+ // Sector 2, strips 256-383 -> Channel 12
+ // Sector 2, strips 384-511 -> Channel 14
+ // Sector 3, strips 0-127 -> Channel 9
+ // Sector 3, strips 128-255 -> Channel 11
+ // Sector 3, strips 256-383 -> Channel 13
+ // Sector 3, strips 384-511 -> Channel 15
+ //
+ // and so on, up to sector 19. For the outer, the map is
+ //
+ // Sector 0, strips 0-127 -> Channel 0
+ // Sector 0, strips 128-255 -> Channel 2
+ // Sector 1, strips 0-127 -> Channel 1
+ // Sector 1, strips 128-255 -> Channel 3
+ // Sector 2, strips 0-127 -> Channel 4
+ // Sector 2, strips 128-255 -> Channel 6
+ // Sector 3, strips 0-127 -> Channel 5
+ // Sector 3, strips 128-255 -> Channel 7
+ // Sector 4, strips 0-127 -> Channel 8
+ // Sector 4, strips 128-255 -> Channel 10
+ // Sector 5, strips 0-127 -> Channel 9
+ // Sector 5, strips 128-255 -> Channel 11
+ // Sector 6, strips 0-127 -> Channel 12
+ // Sector 6, strips 128-255 -> Channel 14
+ // Sector 7, strips 0-127 -> Channel 13
+ // Sector 7, strips 128-255 -> Channel 15
+ //
+ // and so on upto sector 40.
+ //
+ // With this information, we can decode the detector coordinates to
+ // give us a unique hardware address
+ //
+ ddl = kBaseDDL + (det - 1);
+ UInt_t nsen = (ring == 'I' ? 10 : 20);
+ UInt_t nsa = (ring == 'I' ? 2 : 4); // Sensors per ALTRO
+ UInt_t ncs = (ring == 'I' ? 8 : 4); // Channels per sensor
+ UInt_t bbase = (ring == 'I' ? 0 : 2);
+ UInt_t board = bbase + sec / nsen;
+ UInt_t lsen = (sec - (board - bbase) * nsen);
+ UInt_t altro = (lsen < 2 * nsa ? 0 : (lsen < 3 * nsa ? 1 : 2));
+ UInt_t sbase = (lsen < 2 * nsa ? 0 : (lsen < 3 * nsa ? 2*nsa : 3*nsa));
+ UInt_t chan = (sec % 2) + (lsen-sbase) / 2 * ncs + 2 * str / 128;
+ AliDebug(40, Form("\n"
+ " chan = (%d %% 2) + (%d-%d) / %d * %d + 2 * %d / 128\n"
+ " = %d + %d + %d = %d",
+ sec, lsen, sbase, 2, ncs, str,
+ (sec % 2), (lsen - sbase) / 2 * ncs,
+ 2 * str / 128, chan));
+ addr = chan + (altro << 4) + (board << 7);
+
+ return kTRUE;
}
+
+
+
//____________________________________________________________________
//
// EOF