ATLAS Offline Software
Loading...
Searching...
No Matches
SCT_FrontEnd Class Reference

#include <SCT_FrontEnd.h>

Inheritance diagram for SCT_FrontEnd:
Collaboration diagram for SCT_FrontEnd:

Public Member Functions

 SCT_FrontEnd (const std::string &type, const std::string &name, const IInterface *parent)
 constructor
virtual ~SCT_FrontEnd ()=default
 Destructor.
virtual StatusCode initialize () override
 AlgTool InterfaceID.
virtual StatusCode finalize () override
 AlgTool finalize.
virtual void process (SiChargedDiodeCollection &collection, CLHEP::HepRandomEngine *rndmEngine) const override
 process the collection of pre digits: needed to go through all single-strip pre-digits to calculate the amplifier response add noise (this could be moved elsewhere later) apply threshold do clustering stripMax is for benefit of ITkStrips which can have different numbers of strips for module - for SCT this is always 768
StatusCode doSignalChargeForHits (SiChargedDiodeCollection &collectione, SCT_FrontEndData &data, int stripMax) const
StatusCode doThresholdCheckForRealHits (SiChargedDiodeCollection &collectione, SCT_FrontEndData &data, int stripMax) const
StatusCode doThresholdCheckForCrosstalkHits (SiChargedDiodeCollection &collection, SCT_FrontEndData &data, int stripMax) const
StatusCode doClustering (SiChargedDiodeCollection &collection, SCT_FrontEndData &data, int stripMax) const
StatusCode prepareGainAndOffset (const EventContext &ctx, SiChargedDiodeCollection &collection, const Identifier &moduleId, CLHEP::HepRandomEngine *rndmEngine, SCT_FrontEndData &data, int stripMax) const
StatusCode prepareGainAndOffset (const EventContext &ctx, SiChargedDiodeCollection &collection, int side, const Identifier &moduleId, CLHEP::HepRandomEngine *rndmEngine, SCT_FrontEndData &data, int stripMax) const
StatusCode randomNoise (const EventContext &ctx, SiChargedDiodeCollection &collection, const Identifier &moduleId, CLHEP::HepRandomEngine *rndmEngine, SCT_FrontEndData &data, int stripMax) const
StatusCode randomNoise (const EventContext &ctx, SiChargedDiodeCollection &collection, const Identifier &moduleId, int side, CLHEP::HepRandomEngine *rndmEngine, SCT_FrontEndData &data, int stripMax) const
StatusCode addNoiseDiode (SiChargedDiodeCollection &collection, int strip, int tbin) const
StatusCode initVectors (int strips, SCT_FrontEndData &data) const

Static Public Member Functions

static float meanValue (std::vector< float > &calibDataVect)

Private Types

enum  CompressionMode { Level_X1X =1 , Edge_01X =2 , AnyHit_1XX_X1X_XX1 =3 }
enum  ReadOutMode { Condensed =0 , Expanded =1 }

Private Attributes

FloatProperty m_NoiseBarrel {this, "NoiseBarrel", 1500.0, "Noise factor, Barrel (in the case of no use of calibration data)"}
FloatProperty m_NoiseBarrel3 {this, "NoiseBarrel3", 1541.0, "Noise factor, Barrel3 (in the case of no use of calibration data)"}
FloatProperty m_NoiseInners {this, "NoiseInners", 1090.0, "Noise factor, EC Inners (in the case of no use of calibration data)"}
FloatProperty m_NoiseMiddles {this, "NoiseMiddles", 1557.0, "Noise factor, EC Middles (in the case of no use of calibration data)"}
FloatProperty m_NoiseShortMiddles {this, "NoiseShortMiddles", 940.0, "Noise factor, EC Short Middles (in the case of no use of calibration data)"}
FloatProperty m_NoiseOuters {this, "NoiseOuters", 1618.0, "Noise factor, Ec Outers (in the case of no use of calibration data)"}
DoubleProperty m_NOBarrel {this, "NOBarrel", 1.5e-5, "Noise factor, Barrel (in the case of no use of calibration data)"}
DoubleProperty m_NOBarrel3 {this, "NOBarrel3", 2.1e-5, "Noise factor, Barrel3 (in the case of no use of calibration data)"}
DoubleProperty m_NOInners {this, "NOInners", 5.0e-9, "Noise Occupancy, EC Inners (in the case of no use of calibration data)"}
DoubleProperty m_NOMiddles {this, "NOMiddles", 2.7e-5, "Noise Occupancy, EC Middles (in the case of no use of calibration data)"}
DoubleProperty m_NOShortMiddles {this, "NOShortMiddles", 2.0e-9, "Noise Occupancy, EC Short Middles (in the case of no use of calibration data)"}
DoubleProperty m_NOOuters {this, "NOOuters", 3.5e-5, "Noise Occupancy, Ec Outers (in the case of no use of calibration data)"}
BooleanProperty m_NoiseOn {this, "NoiseOn", true, "To know if noise is on or off when using calibration data"}
BooleanProperty m_analogueNoiseOn {this, "AnalogueNoiseOn", true, "To know if analogue noise is on or off"}
FloatProperty m_GainRMS {this, "GainRMS", 0.031, "Gain spread parameter within the strips for a given Chip gain"}
FloatProperty m_Ospread {this, "Ospread", 0.0001, "offset spread within the strips for a given Chip offset"}
FloatProperty m_OGcorr {this, "OffsetGainCorrelation", 0.00001, "Gain/offset correlation for the strips"}
FloatProperty m_Threshold {this, "Threshold", 1.0, "Threshold"}
FloatProperty m_timeOfThreshold {this, "TimeOfThreshold", 30.0, "Threshold time"}
ShortProperty m_data_compression_mode {this, "DataCompressionMode", Edge_01X, "Front End Data Compression Mode: 1 is level mode X1X (default), 2 is edge mode 01X, 3 is any hit mode (1XX|X1X|XX1)"}
ShortProperty m_data_readout_mode {this, "DataReadOutMode", Condensed, "Front End Data Read out mode Mode: 0 is condensed mode and 1 is expanded mode"}
BooleanProperty m_useCalibData {this, "UseCalibData", true, "Flag to set the use of calibration data for noise, Gain,offset etc."}
ToolHandle< IAmplifierm_sct_amplifier {this, "SCT_Amp", "SCT_Amp", "Handle the Amplifier tool"}
 Handle the Amplifier tool.
ToolHandle< ISCT_ReadCalibChipDataToolm_ReadCalibChipDataTool {this, "SCT_ReadCalibChipDataTool", "SCT_ReadCalibChipDataTool", "Tool to retrieve chip calibration information"}
 Handle to the Calibration ConditionsTool.
const InDetDD::SCT_DetectorManagerm_SCTdetMgr {nullptr}
 Handle to SCT detector manager.
const SCT_IDm_sct_id {nullptr}
 Handle to SCT ID helper.
StringProperty m_detMgrName {this, "DetectorManager", "SCT", "Name of DetectorManager to retrieve"}

Detailed Description

Definition at line 70 of file SCT_FrontEnd.h.

Member Enumeration Documentation

◆ CompressionMode

Enumerator
Level_X1X 
Edge_01X 
AnyHit_1XX_X1X_XX1 

Definition at line 107 of file SCT_FrontEnd.h.

107{ Level_X1X=1, Edge_01X=2, AnyHit_1XX_X1X_XX1=3 }; // Used for m_data_compression_mode (DataCompressionMode)

◆ ReadOutMode

Enumerator
Condensed 
Expanded 

Definition at line 108 of file SCT_FrontEnd.h.

108{ Condensed=0, Expanded=1 }; // Used for m_data_readout_mode (DataReadOutMode)

Constructor & Destructor Documentation

◆ SCT_FrontEnd()

SCT_FrontEnd::SCT_FrontEnd ( const std::string & type,
const std::string & name,
const IInterface * parent )

constructor

Definition at line 30 of file SCT_FrontEnd.cxx.

31 : base_class(type, name, parent) {
32}

◆ ~SCT_FrontEnd()

virtual SCT_FrontEnd::~SCT_FrontEnd ( )
virtualdefault

Destructor.

Member Function Documentation

◆ addNoiseDiode()

StatusCode SCT_FrontEnd::addNoiseDiode ( SiChargedDiodeCollection & collection,
int strip,
int tbin ) const

Definition at line 975 of file SCT_FrontEnd.cxx.

975 {
976 const SiCellId ndiode(strip); // !< create a new diode
977 const SiCharge noiseCharge(2 * m_Threshold, 0, SiCharge::noise); // !< add some noise to it
978 collection.add(ndiode, noiseCharge); // !< add it to the collection
979
980 // Get the strip back to check
981 SiChargedDiode *NoiseDiode = (collection.find(strip));
982 if (NoiseDiode == nullptr) {
983 return StatusCode::FAILURE;
984 }
985 SiHelper::SetTimeBin(*NoiseDiode, tbin, &msg()); // set timebin info
986 return StatusCode::SUCCESS;
987}
FloatProperty m_Threshold
SiChargedDiode * find(const InDetDD::SiCellId &siId)
void add(const InDetDD::SiCellId &diode, const T &charge)
static void SetTimeBin(SiChargedDiode &chDiode, int time, MsgStream *log=nullptr)
Definition SiHelper.h:149
MsgStream & msg
Definition testRead.cxx:32

◆ doClustering()

StatusCode SCT_FrontEnd::doClustering ( SiChargedDiodeCollection & collection,
SCT_FrontEndData & data,
int stripMax ) const

Definition at line 881 of file SCT_FrontEnd.cxx.

881 {
882 // ********************************
883 // now do clustering
884 // ********************************
885 int strip = 0;
886 int clusterSize = 0;
887
888 const SCT_ModuleSideDesign& sctDesign = static_cast<const SCT_ModuleSideDesign&>(collection.design());
889
890 SiCellId hitStrip;
891
893 do {
894 if (data.m_StripHitsOnWafer[strip] > 0) {
895 // ====== First step: Get the cluster size
896 // ===================================================
897 int clusterFirstStrip = strip;
898
899 // Find end of cluster. In multi-row sensors, cluster cannot span rows.
900 int row = sctDesign.row(strip);
901 if (row < 0) {
902 row = 0;
903 }
904
905 int lastStrip1DInRow = 0;
906 for (int i = 0; i < row + 1; ++i) {
907 lastStrip1DInRow += sctDesign.diodesInRow(i);
908 }
909
910 while (strip < lastStrip1DInRow-1 and data.m_StripHitsOnWafer[strip +1] > 0) {
911 ++strip; // !< Find first strip hit and add up the following strips
912 }
913 int clusterLastStrip = strip;
914
915 clusterSize = (clusterLastStrip - clusterFirstStrip) + 1;
916 hitStrip = SiCellId(clusterFirstStrip);
917 SiChargedDiode& HitDiode = *(collection.find(hitStrip));
918 SiHelper::SetStripNum(HitDiode, clusterSize, &msg());
919
920 SiChargedDiode *PreviousHitDiode = &HitDiode;
921 for (int i = clusterFirstStrip+1; i <= clusterLastStrip; ++i) {
922 hitStrip = SiCellId(i);
923 SiChargedDiode& HitDiode2 = *(collection.find(hitStrip));
924 SiHelper::ClusterUsed(HitDiode2, true);
925 PreviousHitDiode->setNextInCluster(&HitDiode2);
926 PreviousHitDiode = &HitDiode2;
927 }
928 }
929 ++strip; // !< This is the starting point of the next cluster within this collection
930 } while (strip < strip_max);
931 } else {
932 // Expanded read out mode, basically one RDO/strip per cluster
933 // But if consecutively fired strips have the same time bin, those are converted into one cluster.
934 do {
935 clusterSize = 1;
936 if (data.m_StripHitsOnWafer[strip] > 0) {
937 hitStrip = SiCellId(strip);
938 SiChargedDiode& hitDiode = *(collection.find(hitStrip));
939 int timeBin = SiHelper::GetTimeBin(hitDiode);
940 SiChargedDiode* previousHitDiode = &hitDiode;
941 // Check if consecutively fired strips have the same time bin
942 for (int newStrip=strip+1; newStrip<strip_max; newStrip++) {
943 if (not (data.m_StripHitsOnWafer[newStrip]>0)) break;
944 SiCellId newHitStrip = SiCellId(newStrip);
945 SiChargedDiode& newHitDiode = *(collection.find(newHitStrip));
946 if (timeBin!=SiHelper::GetTimeBin(newHitDiode)) break;
947 SiHelper::ClusterUsed(newHitDiode, true);
948 previousHitDiode->setNextInCluster(&newHitDiode);
949 previousHitDiode = &newHitDiode;
950 clusterSize++;
951 }
952 SiHelper::SetStripNum(hitDiode, clusterSize, &msg());
953
954#ifdef SCT_DIG_DEBUG
955 ATH_MSG_DEBUG("RDO Strip = " << strip << ", tbin = " <<
956 SiHelper::GetTimeBin(hitDiode) <<
957 ", HitInfo(1=real, 2=crosstalk, 3=noise): " <<
958 data.m_StripHitsOnWafer[strip]);
959#endif
960 }
961 strip += clusterSize; // If more than one strip fires, those following strips are skipped.
962 } while (strip < strip_max);
963 }
964
965 // clusters below threshold, only from pre-digits that existed before no
966 // pure noise clusters below threshold will be made
967 // D. Costanzo. I don't see why we should cluster the strips below
968 // threshold. I'll pass on the info of strips below threshold
969 // to the SDOs. I'll leave the SCT experts the joy to change this if they
970 // don't like what I did or if this requires too much memory/disk
971
972 return StatusCode::SUCCESS;
973}
#define ATH_MSG_DEBUG(x)
virtual int row(int stripId1Dim) const
virtual int diodesInRow(const int row) const
ShortProperty m_data_readout_mode
const InDetDD::DetectorDesign & design() const
void setNextInCluster(SiChargedDiode *nextInCluster)
static void ClusterUsed(SiChargedDiode &chDiode, bool flag)
Definition SiHelper.h:121
static void SetStripNum(SiChargedDiode &chDiode, int nstrip, MsgStream *log=nullptr)
Definition SiHelper.h:139
static int GetTimeBin(SiChargedDiode &chDiode)
Definition SiHelper.h:203
row
Appending html table to final .html summary file.

◆ doSignalChargeForHits()

StatusCode SCT_FrontEnd::doSignalChargeForHits ( SiChargedDiodeCollection & collectione,
SCT_FrontEndData & data,
int stripMax ) const

Definition at line 652 of file SCT_FrontEnd.cxx.

652 {
653 using list_t = SiTotalCharge::list_t;
654
655 // *****************************************************************************
656 // Loop over the diodes (strips ) and for each of them define the total signal
657 // *****************************************************************************
658
659 // set up number of needed bins depending on the compression mode
660 short bin_max = 0;
662 bin_max = m_data_compression_mode;
663 } else {
664 bin_max = 3;
665 }
666
667 std::vector<float> response(bin_max);
668
669 SiChargedDiodeIterator i_chargedDiode = collection.begin();
670 SiChargedDiodeIterator i_chargedDiode_end = collection.end();
671 for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
672 const SiChargedDiode& diode = (*i_chargedDiode).second;
673 // should be const as we aren't trying to change it here - but getReadoutCell() is not a const method...
674 unsigned int flagmask = diode.flag() & 0xFE;
675 // Get the flag for this diode ( if flagmask = 1 If diode is disconnected/disabled skip it)
676 if (!flagmask) { // If the diode is OK (not flagged)
677 const SiReadoutCellId& roCell = diode.getReadoutCell();
678
679 if (roCell.isValid()) {
680 int strip = roCell.strip();
681
682 const list_t &ChargesOnStrip = diode.totalCharge().chargeComposition();
683
685 // Amplifier response
686 m_sct_amplifier->response(ChargesOnStrip, m_timeOfThreshold, response);
687 for (short bin = 0; bin < bin_max; ++bin) {
688 data.m_Analogue[bin][strip] += data.m_GainFactor[strip] * response[bin];
689 }
690 // Add Crosstalk signal for neighboring strip
691 m_sct_amplifier->crosstalk(ChargesOnStrip, m_timeOfThreshold, response);
692 for (short bin = 0; bin < bin_max; ++bin) {
693 if (strip + 1 < strip_max) {
694 data.m_Analogue[bin][strip + 1] += data.m_GainFactor[strip + 1] * response[bin];
695 }
696 if (strip > 0) {
697 data.m_Analogue[bin][strip - 1] += data.m_GainFactor[strip - 1] * response[bin];
698 }
699 }
700 } else { // Expanded
701 // Amplifier response
702 m_sct_amplifier->response(ChargesOnStrip, m_timeOfThreshold, response);
703 for (short bin = 0; bin < bin_max; ++bin) {
704 data.m_Analogue[bin][strip] += data.m_GainFactor[strip] * response[bin];
705 }
706 // Add Crosstalk signal for neighboring strip
707 m_sct_amplifier->crosstalk(ChargesOnStrip, m_timeOfThreshold, response);
708 for (short bin = 0; bin < bin_max; ++bin) {
709 if (strip + 1 < strip_max) {
710 data.m_Analogue[bin][strip + 1] += data.m_GainFactor[strip + 1] * response[bin];
711 }
712 if (strip > 0) {
713 data.m_Analogue[bin][strip - 1] += data.m_GainFactor[strip - 1] * response[bin];
714 }
715 }
716 }
717 } else { // if roCell not valid
718 ATH_MSG_WARNING("\t Cannot get the cell ");
719 }
720 } else {// If diode is disconnected/disabled skip it
721 ATH_MSG_WARNING("\tDisabled or disconnected diode (strip)");
722 }
723 }
724 return StatusCode::SUCCESS;
725}
#define ATH_MSG_WARNING(x)
MDT_Response response
SiChargedDiodeMap::iterator SiChargedDiodeIterator
int strip() const
Get strip number. Equivalent to phiIndex().
Definition SiCellId.h:131
bool isValid() const
Test if its in a valid state.
Definition SiCellId.h:136
ToolHandle< IAmplifier > m_sct_amplifier
Handle the Amplifier tool.
FloatProperty m_timeOfThreshold
ShortProperty m_data_compression_mode
int flag() const
const SiTotalCharge & totalCharge() const
const InDetDD::SiReadoutCellId & getReadoutCell() const
std::vector< SiCharge > list_t
const list_t & chargeComposition() const

◆ doThresholdCheckForCrosstalkHits()

StatusCode SCT_FrontEnd::doThresholdCheckForCrosstalkHits ( SiChargedDiodeCollection & collection,
SCT_FrontEndData & data,
int stripMax ) const

Definition at line 805 of file SCT_FrontEnd.cxx.

805 {
806 // Check for noise+crosstalk strips above threshold
807 // data.m_StripHitsOnWafer: real hits above threshold == 1 or below/disconnected
808 // == -1
809 // =0 for free strips or strips with charge to be checked (data.m_Analogue[1]!=0)
810 // Set 2 for crosstalk noise hits and -2 for below ones
811
812 for (int strip = 0; strip < strip_max; strip++) {
813 // Find strips with data.m_StripHitsOnWafer[strip] == 0
814 if (data.m_StripHitsOnWafer[strip] != 0) { // real hits already checked
815 continue;
816 }
817 if (data.m_Analogue[1][strip] > 0) { // Better way of doing this?!
818 // set data.m_StripHitsOnWafer to x in prepareGainAndOffset
820 if ((data.m_Analogue[0][strip] >= m_Threshold or data.m_Analogue[1][strip] < m_Threshold)) {
821 data.m_StripHitsOnWafer[strip] = -2; // Below threshold
822 } else {
823 data.m_StripHitsOnWafer[strip] = 2; // Crosstalk+Noise hit
824 if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, 2)) {
825
826 ATH_MSG_ERROR("Can't add noise hit diode to collection (5)");
827 }
828 }
829 } else { // Expanded
830 int have_hit_bin = 0;
831 if (data.m_Analogue[0][strip] >= m_Threshold) {
832 have_hit_bin = 4;
833 }
834 if (data.m_Analogue[1][strip] >= m_Threshold) {
835 have_hit_bin += 2;
836 }
837 if (data.m_Analogue[2][strip] >= m_Threshold) {
838 have_hit_bin += 1;
839 }
840 if (m_data_compression_mode == Level_X1X) { // !< level and expanded mode
841 if (have_hit_bin == 2 or have_hit_bin == 3 or have_hit_bin == 6 or have_hit_bin == 7) {
842 data.m_StripHitsOnWafer[strip] = 2; // Crosstalk+Noise hit
843 if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, have_hit_bin)) {
844 ATH_MSG_ERROR("Can't add noise hit diode to collection (6)");
845 }
846 } else {
847 data.m_StripHitsOnWafer[strip] = -2; // Below threshold
848 }
849 } else if (m_data_compression_mode == Edge_01X) { // !< edge and expanded mode
850 if (have_hit_bin == 2 or have_hit_bin == 3) {
851 data.m_StripHitsOnWafer[strip] = 2; // Noise hit
852 if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, have_hit_bin)) {
853 ATH_MSG_ERROR("Can't add noise hit diode to collection (7)");
854 }
855 } else {
856 data.m_StripHitsOnWafer[strip] = -2; // Below threshold
857 }
858 } else if (m_data_compression_mode == AnyHit_1XX_X1X_XX1) { // !< any hit mode
859 if (have_hit_bin == 0) {
860 data.m_StripHitsOnWafer[strip] = -2; // Below threshold
861 } else {
862 data.m_StripHitsOnWafer[strip] = 2; // !< Crosstalk+Noise hit
863 if (m_data_readout_mode == Expanded) { // !< check for exp mode or not
864 if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, have_hit_bin)) {
865 ATH_MSG_ERROR("Can't add noise hit diode to collection (8)");
866 }
867 } else {
868 if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, 2)) {
869 ATH_MSG_ERROR("Can't add noise hit diode to collection (9)");
870 }
871 }
872 }
873 }
874 }
875 }
876 }
877
878 return StatusCode::SUCCESS;
879}
#define ATH_MSG_ERROR(x)
StatusCode addNoiseDiode(SiChargedDiodeCollection &collection, int strip, int tbin) const

◆ doThresholdCheckForRealHits()

StatusCode SCT_FrontEnd::doThresholdCheckForRealHits ( SiChargedDiodeCollection & collectione,
SCT_FrontEndData & data,
int stripMax ) const

Definition at line 727 of file SCT_FrontEnd.cxx.

727 {
728 // **********************************************************************************
729 // Flag strips below threshold and flag the threshold check into data.m_StripHitsOnWafer
730 // **********************************************************************************
731
732 SiChargedDiodeIterator i_chargedDiode = collection.begin();
733 SiChargedDiodeIterator i_chargedDiode_end = collection.end();
734
735 for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
736 SiChargedDiode& diode = (*i_chargedDiode).second;
737 const SiReadoutCellId& roCell = diode.getReadoutCell();
738 if (roCell.isValid()) {
739 int strip = roCell.strip();
740 if (strip > -1 and strip < strip_max) {
742 if ((data.m_Analogue[0][strip] >= m_Threshold or data.m_Analogue[1][strip] < m_Threshold)) {
743 SiHelper::belowThreshold(diode, true); // Below strip diode signal threshold
744 data.m_StripHitsOnWafer[strip] = -1;
745 } else if (((0x10 & diode.flag()) == 0x10) or ((0x4 & diode.flag()) == 0x4)) {
746 // previously a crazy strip number could have screwed things up here.
747 data.m_StripHitsOnWafer[strip] = -1;
748 } else {
749 data.m_StripHitsOnWafer[strip] = 1;
750 SiHelper::SetTimeBin(diode, 2, &msg()); // set timebin info
751 }
752 } else { // Expanded
753 int have_hit_bin = 0;
754 if (data.m_Analogue[0][strip] >= m_Threshold) {
755 have_hit_bin = 4;
756 }
757 if (data.m_Analogue[1][strip] >= m_Threshold) {
758 have_hit_bin += 2;
759 }
760 if (data.m_Analogue[2][strip] >= m_Threshold) {
761 have_hit_bin += 1;
762 }
763 if (((0x10 & diode.flag()) == 0x10) || ((0x4 & diode.flag()) == 0x4)) {
764 // previously a crazy strip number could have screwed things up here.
765 data.m_StripHitsOnWafer[strip] = -1;
766 } else if (m_data_compression_mode == Level_X1X) { // !< level and expanded mode
767 if (have_hit_bin == 2 or have_hit_bin == 3 or have_hit_bin == 6 or have_hit_bin == 7) {
768 data.m_StripHitsOnWafer[strip] = 1;
769 SiHelper::SetTimeBin(diode, have_hit_bin, &msg());
770 } else {
771 SiHelper::belowThreshold(diode, true); // Below strip diode signal threshold
772 data.m_StripHitsOnWafer[strip] = -1;
773 }
774 } else if (m_data_compression_mode == Edge_01X) { // !< edge and expanded mode
775 if (have_hit_bin == 2 or have_hit_bin == 3) {
776 data.m_StripHitsOnWafer[strip] = 1;
777 SiHelper::SetTimeBin(diode, have_hit_bin, &msg());
778 } else {
779 SiHelper::belowThreshold(diode, true); // Below strip diode signal threshold
780 data.m_StripHitsOnWafer[strip] = -1;
781 }
782 } else if (m_data_compression_mode == AnyHit_1XX_X1X_XX1) { // !< any hit mode
783 if (have_hit_bin == 0) {
784 SiHelper::belowThreshold(diode, true); // Below strip diode signal threshold
785 data.m_StripHitsOnWafer[strip] = -1;
786 } else {
787 data.m_StripHitsOnWafer[strip] = 1;
788 if (m_data_readout_mode == Expanded) { // !< check for exp mode or not
789 SiHelper::SetTimeBin(diode, have_hit_bin, &msg());
790 } else {
791 SiHelper::SetTimeBin(diode, 2, &msg());
792 }
793 }
794 }
795 }
796 }
797 }
798 }
799 return StatusCode::SUCCESS;
800}
static void belowThreshold(SiChargedDiode &chDiode, bool flag, bool mask=false)
Definition SiHelper.h:84

◆ finalize()

StatusCode SCT_FrontEnd::finalize ( )
overridevirtual

AlgTool finalize.

Definition at line 102 of file SCT_FrontEnd.cxx.

102 {
103#ifdef SCT_DIG_DEBUG
104 ATH_MSG_INFO("SCT_FrontEnd::finalize()");
105#endif
106 return StatusCode::SUCCESS;
107}
#define ATH_MSG_INFO(x)

◆ initialize()

StatusCode SCT_FrontEnd::initialize ( )
overridevirtual

AlgTool InterfaceID.

AlgTool initialize

Definition at line 37 of file SCT_FrontEnd.cxx.

37 {
38 if (m_NoiseOn and (not m_analogueNoiseOn)) {
39 ATH_MSG_FATAL("AnalogueNoiseOn/m_analogueNoiseOn should be true if NoiseOn/m_NoiseOn is true.");
40 return StatusCode::FAILURE;
41 }
42
43 ATH_MSG_DEBUG("SCT_FrontEnd::initialize()");
44 // Get SCT helper
45 ATH_CHECK(detStore()->retrieve(m_sct_id, "SCT_ID"));
46 // Get SCT detector manager
47 ATH_CHECK(detStore()->retrieve(m_SCTdetMgr,m_detMgrName));
48 // Get the amplifier tool
49 ATH_CHECK(m_sct_amplifier.retrieve());
50 ATH_MSG_DEBUG("SCT Amplifier tool located ");
51
52 // Get the SCT_ReadCaliDataSvc
53 if (m_useCalibData) {
55 ATH_MSG_DEBUG("CalibChipData Service located ");
56 } else {
58 }
59
60 constexpr float fC = 6242.2;
62
63#ifdef SCT_DIG_DEBUG
64 ATH_MSG_INFO("\tNoise factors:");
65 ATH_MSG_INFO("\tBarrel = " << m_NoiseBarrel << " Outer Barrel = " << m_NoiseBarrel3 <<
66 " EC, inners = " << m_NoiseInners << " EC, middles = " << m_NoiseMiddles <<
67 " EC, short middles = " << m_NoiseShortMiddles << " EC, outers = " << m_NoiseOuters);
68 ATH_MSG_INFO("\tThreshold=" << m_Threshold << " fC, time of Threshold=" << m_timeOfThreshold);
69#endif
70
71 ATH_MSG_INFO("m_Threshold (Threshold) = " << m_Threshold);
72 ATH_MSG_INFO("m_timeOfThreshold (TimeOfThreshold) = " << m_timeOfThreshold);
73 ATH_MSG_INFO("m_data_compression_mode (DataCompressionMode) = " << m_data_compression_mode);
74 ATH_MSG_INFO("m_data_readout_mode (DataReadOutMode) = " << m_data_readout_mode);
75
76 // Check configuration. If it is invalid, abort this job.
80 ATH_MSG_FATAL("m_data_compression_mode = " << m_data_compression_mode
81 << " is invalid. Abort this job!!!");
82 return StatusCode::FAILURE;
83 }
85 ATH_MSG_FATAL("m_data_readout_mode = " << m_data_readout_mode
86 << " is invalid. Abort this job!!!");
87 return StatusCode::FAILURE;
88 }
91 ATH_MSG_FATAL("m_data_compression_mode = " << m_data_compression_mode
92 << (m_data_compression_mode==Level_X1X ? " (Level_X1X)" : " (AnyHit_1XX_X1X_XX1)")
93 << " requires timing information."
94 << " However, m_data_readout_mode = " << m_data_readout_mode
95 << " (Condensed) does not keep timing information. Abort this job!!!");
96 return StatusCode::FAILURE;
97 }
98
99 return StatusCode::SUCCESS;
100}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
FloatProperty m_NoiseShortMiddles
BooleanProperty m_analogueNoiseOn
BooleanProperty m_NoiseOn
FloatProperty m_NoiseOuters
ToolHandle< ISCT_ReadCalibChipDataTool > m_ReadCalibChipDataTool
Handle to the Calibration ConditionsTool.
FloatProperty m_NoiseBarrel3
BooleanProperty m_useCalibData
FloatProperty m_NoiseInners
const InDetDD::SCT_DetectorManager * m_SCTdetMgr
Handle to SCT detector manager.
const SCT_ID * m_sct_id
Handle to SCT ID helper.
FloatProperty m_NoiseBarrel
StringProperty m_detMgrName
FloatProperty m_NoiseMiddles

◆ initVectors()

StatusCode SCT_FrontEnd::initVectors ( int strips,
SCT_FrontEndData & data ) const

Definition at line 112 of file SCT_FrontEnd.cxx.

112 {
113 data.m_GainFactor.resize(strips);
114
116 data.m_Analogue[0].resize(strips);
117 data.m_Analogue[1].resize(strips);
118 } else { // Expanded
119 data.m_Analogue[0].resize(strips);
120 data.m_Analogue[1].resize(strips);
121 data.m_Analogue[2].resize(strips);
122 }
123
124 return StatusCode::SUCCESS;
125}

◆ meanValue()

float SCT_FrontEnd::meanValue ( std::vector< float > & calibDataVect)
static

Definition at line 989 of file SCT_FrontEnd.cxx.

989 {
990 // Tell clang not to allow spurious FPEs.
992 float mean_value = 0.0;
993 int nData = 0;
994
995 for (float calibData : calibDataVect) {
996 if (calibData > 0.1) {
997 mean_value += calibData;
998 ++nData;
999 }
1000 }
1001
1002 if (nData == 0) {
1003 return -1;
1004 } else {
1005 return mean_value / nData;
1006 }
1007}
#define CXXUTILS_TRAPPING_FP
Definition trapping_fp.h:24

◆ prepareGainAndOffset() [1/2]

StatusCode SCT_FrontEnd::prepareGainAndOffset ( const EventContext & ctx,
SiChargedDiodeCollection & collection,
const Identifier & moduleId,
CLHEP::HepRandomEngine * rndmEngine,
SCT_FrontEndData & data,
int stripMax ) const

Definition at line 130 of file SCT_FrontEnd.cxx.

130 {
131 // now we need to generate gain and offset channel by channel: some algebra
132 // for generation of partially correlated random numbers
134 float A = 4.0f * W * W + 1.0f;
135 float x1 = (A - std::sqrt(A)) / (2.0f * A);
136 float sinfi = std::sqrt(x1);
137 float cosfi = std::sqrt(1.0 - x1);
138
139 sinfi = sinfi * m_OGcorr / std::abs(m_OGcorr);
141 float D = (m_GainRMS * m_GainRMS - m_Ospread * m_Ospread) / (cosfi * cosfi - sinfi * sinfi);
142 float S1 = std::sqrt((S + D) * 0.5f);
143 float S2 = std::sqrt((S - D) * 0.5f);
144 float Noise = 0;
145 int mode = 1;
146
147 // To set noise values for different module types, barrel, EC, inners, middles, short middles, and outers
148 if (m_analogueNoiseOn) {
149 if (m_sct_id->barrel_ec(moduleId) == 0) { // barrel_ec=0 corresponds to barrel
150 if (m_sct_id->layer_disk(moduleId) == 3) { // outer barrel layer 10 degrees warmer
151 Noise = m_NoiseBarrel3;
152 } else {
153 Noise = m_NoiseBarrel;
154 }
155 } else {
156 int moduleType = m_sct_id->eta_module(moduleId);
157 switch (moduleType) { // eta = 0, 1, or 2 corresponds to outers, middles and inners?! (at least in the offline world)
158 case 0: {
159 Noise = m_NoiseOuters;
160 break;
161 }
162 case 1: {
163 if (m_sct_id->layer_disk(moduleId) == 7) {
164 Noise = m_NoiseShortMiddles;
165 } else {
166 Noise = m_NoiseMiddles;
167 }
168 break;
169 }
170 case 2: {
171 Noise = m_NoiseInners;
172 break;
173 }
174 default: {
175 Noise = m_NoiseBarrel;
176 ATH_MSG_ERROR("moduleType(eta): " << moduleType << " unknown, using barrel");
177 }
178 }// end of switch structure
179 }
180 }
181
182 // Loop over collection and setup gain/offset/noise for the hit and neighbouring strips
183 SiChargedDiodeIterator i_chargedDiode = collection.begin();
184 SiChargedDiodeIterator i_chargedDiode_end = collection.end();
185
186 for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
187 const SiChargedDiode& diode = (*i_chargedDiode).second;
188 // should be const as we aren't trying to change it here - but getReadoutCell() is not a const method...
189 unsigned int flagmask = diode.flag() & 0xFE;
190 // Get the flag for this diode ( if flagmask = 1 If diode is disconnected/disabled skip it)
191 if (!flagmask) { // If the diode is OK (not flagged)
192 const SiReadoutCellId& roCell = diode.getReadoutCell();
193 if (roCell.isValid()) {
194 int strip = roCell.strip();
195 int i = std::max(strip - 1, 0);
196 int i_end = std::min(strip + 2, strip_max);
197
198 // loop over strips
199 for (; i < i_end; i++) {
200 // Need to check if strip is already setup
201 if (data.m_Analogue[1][i] <= 0.0) {
202 float g = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.0, S1);
203 float o = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.0, S2);
204
205 data.m_GainFactor[i] = 1.0f + (cosfi * g + sinfi * o);
206 //offset per channel
207 float offset_val = (cosfi * o - sinfi * g);
208 //noise factor per channel (from calib data noise per chip)
209 float noise_val = Noise * mode;
210
211 // Fill the noise and offset values into the Analogue
213 data.m_Analogue[0][i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
214 data.m_Analogue[1][i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
215 } else { // Expanded
216 data.m_Analogue[0][i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
217 data.m_Analogue[1][i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
218 data.m_Analogue[2][i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
219 }
220 }
221 }
222 }
223 }
224 }
225
226 return StatusCode::SUCCESS;
227}
struct TBPatternUnitContext S2
struct TBPatternUnitContext S1
FloatProperty m_GainRMS
FloatProperty m_Ospread
FloatProperty m_OGcorr
SiChargedDiodeIterator begin()

◆ prepareGainAndOffset() [2/2]

StatusCode SCT_FrontEnd::prepareGainAndOffset ( const EventContext & ctx,
SiChargedDiodeCollection & collection,
int side,
const Identifier & moduleId,
CLHEP::HepRandomEngine * rndmEngine,
SCT_FrontEndData & data,
int stripMax ) const

Definition at line 233 of file SCT_FrontEnd.cxx.

233 {
234 // Get chip data from calib DB
235 std::vector<float> gainByChipVect = m_ReadCalibChipDataTool->getNPtGainData(moduleId, side, "GainByChip", ctx);
236 std::vector<float> gainRMSByChipVect = m_ReadCalibChipDataTool->getNPtGainData(moduleId, side, "GainRMSByChip", ctx);
237 std::vector<float> offsetByChipVect = m_ReadCalibChipDataTool->getNPtGainData(moduleId, side, "OffsetByChip", ctx);
238 std::vector<float> offsetRMSByChipVect = m_ReadCalibChipDataTool->getNPtGainData(moduleId, side, "OffsetRMSByChip", ctx);
239 std::vector<float> noiseByChipVect(6, 0.0);
240
241 if (m_analogueNoiseOn) { // Check if noise should be on or off
242 noiseByChipVect = m_ReadCalibChipDataTool->getNPtGainData(moduleId, side, "NoiseByChip", ctx);
243 }
244
245 // Need to check if empty, most should have data, but a few old DEAD modules don't
246 if (gainByChipVect.empty() or noiseByChipVect.empty()) {
247 ATH_MSG_DEBUG("No calibration data in cond DB for module " << moduleId << " using JO values");
248 if (StatusCode::SUCCESS != prepareGainAndOffset(ctx, collection, moduleId, rndmEngine, data,strip_max)) {
249 return StatusCode::FAILURE;
250 } else {
251 return StatusCode::SUCCESS;
252 }
253 }
254
255 // Don't really need to set up values for each chip...
256 float gainMeanValue = meanValue(gainByChipVect);
257 if (gainMeanValue < 0.0) {
258 ATH_MSG_DEBUG("All chip gain values are 0 for module " << moduleId << " using JO values");
259 if (StatusCode::SUCCESS != prepareGainAndOffset(ctx, collection, moduleId, rndmEngine, data,strip_max)) {
260 return StatusCode::FAILURE;
261 } else {
262 return StatusCode::SUCCESS;
263 }
264 }
265
266 std::vector<float> gain(6, 0.0);
267 std::vector<float> offset(6, 0.0);
268 std::vector<float> S1(6, 0.0);
269 std::vector<float> S2(6, 0.0);
270 std::vector<float> sinfi(6, 0.0);
271 std::vector<float> cosfi(6, 0.0);
272 float gainRMS = 0.0;
273 float offsetRMS = 0.0;
274
275 for (int i = 0; i < 6; ++i) {
276 // Some very few chips have 0 values, dead/bypassed/etc, so check and use some fixed values instead
277 if (gainByChipVect[i] > 0.1) {
278 gain[i] = gainByChipVect[i] / gainMeanValue;
279 offset[i] = offsetByChipVect[i] / m_Threshold;
280 gainRMS = gainRMSByChipVect[i] / gainMeanValue;
281 offsetRMS = offsetRMSByChipVect[i] / m_Threshold;
282 } else {
283 // Tell clang not to allow spurious FPEs.
285 gain[i] = 55.0f / gainMeanValue;
286 offset[i] = 42.0f / m_Threshold;
287 gainRMS = 1.3f / gainMeanValue;
288 offsetRMS = 2.0f / m_Threshold;
289 }
290
291 float W = m_OGcorr * gainRMS * offsetRMS / (gainRMS * gainRMS - offsetRMS * offsetRMS);
292 float A = 4.0f * W * W + 1.0f;
293 float x1 = (A - std::sqrt(A)) / (2.0f * A);
294 sinfi[i] = std::sqrt(x1);
295 cosfi[i] = std::sqrt(1.0f - x1);
296 sinfi[i] = sinfi[i] * m_OGcorr / std::abs(m_OGcorr);
297 float S = gainRMS * gainRMS + offsetRMS * offsetRMS;
298 float D = (gainRMS * gainRMS - offsetRMS * offsetRMS) / (cosfi[i] * cosfi[i] - sinfi[i] * sinfi[i]);
299 S1[i] = std::sqrt((S + D) / 2.0f);
300 S2[i] = std::sqrt((S - D) / 2.0f);
301 }
302
303 // Loop over collection and setup gain/offset/noise for the hit and neighbouring strips
304 SiChargedDiodeIterator i_chargedDiode = collection.begin();
305 SiChargedDiodeIterator i_chargedDiode_end = collection.end();
306
307 for (; i_chargedDiode != i_chargedDiode_end; ++i_chargedDiode) {
308 const SiChargedDiode& diode = (*i_chargedDiode).second;
309 // should be const as we aren't trying to change it here - but getReadoutCell() is not a const method...
310 unsigned int flagmask = diode.flag() & 0xFE;
311 // Get the flag for this diode ( if flagmask = 1 If diode is disconnected/disabled skip it)
312 if (!flagmask) { // If the diode is OK (not flagged)
313 const SiReadoutCellId& roCell = diode.getReadoutCell();
314
315 if (roCell.isValid()) {
316 int strip = roCell.strip();
317 int i = std::max(strip - 1, 0);
318 int i_end = std::min(strip + 2, strip_max);
319
320 // loop over strips
321 for (; i < i_end; i++) {
322 // Need to check if strip is already setup
323 if (data.m_Analogue[1][i] <= 0.0) {
324 // Values depends on which chip the strip is on (complex when strip is on chip edge)
325 int chip = i / 128;
326 float g = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.0, S1[chip]);
327 float o = CLHEP::RandGaussZiggurat::shoot(rndmEngine, 0.0, S2[chip]);
328
329 data.m_GainFactor[i] = gain[chip] + (cosfi[chip] * g + sinfi[chip] * o);
330 //offset per channel
331 float offset_val = offset[chip] + (cosfi[chip] * o - sinfi[chip] * g);
332 //noise factor per channel (from calib data noise per chip)
333 float noise_val = noiseByChipVect[chip];
334
335 // Fill the noise and offset values into the Analogue
337 data.m_Analogue[0][i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
338 data.m_Analogue[1][i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
339 } else { // Expanded
340 data.m_Analogue[0][i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
341 data.m_Analogue[1][i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
342 data.m_Analogue[2][i] = offset_val + noise_val * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
343 }
344 }
345 }
346 }
347 }
348 }
349
350 return StatusCode::SUCCESS;
351}
StatusCode prepareGainAndOffset(const EventContext &ctx, SiChargedDiodeCollection &collection, const Identifier &moduleId, CLHEP::HepRandomEngine *rndmEngine, SCT_FrontEndData &data, int stripMax) const
static float meanValue(std::vector< float > &calibDataVect)

◆ process()

void SCT_FrontEnd::process ( SiChargedDiodeCollection & collection,
CLHEP::HepRandomEngine * rndmEngine ) const
overridevirtual

process the collection of pre digits: needed to go through all single-strip pre-digits to calculate the amplifier response add noise (this could be moved elsewhere later) apply threshold do clustering stripMax is for benefit of ITkStrips which can have different numbers of strips for module - for SCT this is always 768

Definition at line 578 of file SCT_FrontEnd.cxx.

578 {
579
580 const EventContext& ctx = Gaudi::Hive::currentContext();
581
582 // get SCT module side design
583 const SCT_ModuleSideDesign *p_design = static_cast<const SCT_ModuleSideDesign*>(&(collection.design()));
584
585 SCT_FrontEndData data;
586
587 // Check number of strips in design and from manager(max number of strips on any module)
588 // The design value should always be equal or lower than the manager one
589 // However, no resizing is now done in case of a lower value
590 const int strip_max = p_design->cells();
591 // Init vectors
592 if (StatusCode::SUCCESS != initVectors(strip_max, data)) {
593 ATH_MSG_ERROR("Can't resize class variable vectors");
594 return;
595 }
596
597 // Contains strip hit info, reset to 0 for each wafer processed
598 data.m_StripHitsOnWafer.assign(strip_max, 0);
599
600 // data.m_Analogue contains the charge for each bin on each hit strip
601 // These vectors were cleared in initVectors().
602
603 // Get wafer, moduleId and side
604 Identifier waferId = collection.identify();
605 Identifier moduleId = m_sct_id->module_id(waferId);
606 const int side = m_sct_id->side(waferId);
607
608 // Check if collection empty
609 if (not collection.empty()) {
610 // Setup gain/offset/noise to the hit and neighbouring strips
611 if (m_useCalibData) { // Use calib cond DB data
612 if (StatusCode::SUCCESS != prepareGainAndOffset(ctx, collection, side, moduleId, rndmEngine, data, strip_max)) {
613 ATH_MSG_ERROR("\tCan't prepare Gain and Offset");
614 }
615 } else { // Use JO values
616 if (StatusCode::SUCCESS != prepareGainAndOffset(ctx, collection, moduleId, rndmEngine, data,strip_max)) {
617 ATH_MSG_ERROR("\tCan't prepare Gain and Offset");
618 }
619 }
620
621 if (StatusCode::SUCCESS != doSignalChargeForHits(collection, data, strip_max)) {
622 ATH_MSG_ERROR("\tCan't doSignalChargeForHits");
623 }
624
625 if (StatusCode::SUCCESS != doThresholdCheckForRealHits(collection, data, strip_max)) {
626 ATH_MSG_ERROR("\tCan't doThresholdCheckForRealHits");
627 }
628
629 if (StatusCode::SUCCESS != doThresholdCheckForCrosstalkHits(collection, data, strip_max)) {
630 ATH_MSG_ERROR("\tCan't doThresholdCheckForCrosstalkHits");
631 }
632 }
633
634 if (m_NoiseOn) {
635 if (m_useCalibData) { // Check if using DB or not
636 if (StatusCode::SUCCESS != randomNoise(ctx, collection, moduleId, side, rndmEngine, data, strip_max)) {
637 ATH_MSG_ERROR("\tCan't do random noise on wafer?!");
638 }
639 } else { // Use JO fixed values
640 if (StatusCode::SUCCESS != randomNoise(ctx, collection, moduleId, rndmEngine, data,strip_max)) {
641 ATH_MSG_ERROR("\tCan't do random noise on wafer?!");
642 }
643 }
644 }
645
646 // Check for strips above threshold and do clustering
647 if (StatusCode::SUCCESS != doClustering(collection, data,strip_max)) {
648 ATH_MSG_ERROR("\tCan't cluster the hits?!");
649 }
650}
int cells() const
number of readout stips within module side:
StatusCode doClustering(SiChargedDiodeCollection &collection, SCT_FrontEndData &data, int stripMax) const
StatusCode doSignalChargeForHits(SiChargedDiodeCollection &collectione, SCT_FrontEndData &data, int stripMax) const
StatusCode doThresholdCheckForCrosstalkHits(SiChargedDiodeCollection &collection, SCT_FrontEndData &data, int stripMax) const
StatusCode doThresholdCheckForRealHits(SiChargedDiodeCollection &collectione, SCT_FrontEndData &data, int stripMax) const
StatusCode initVectors(int strips, SCT_FrontEndData &data) const
StatusCode randomNoise(const EventContext &ctx, SiChargedDiodeCollection &collection, const Identifier &moduleId, CLHEP::HepRandomEngine *rndmEngine, SCT_FrontEndData &data, int stripMax) const
virtual Identifier identify() const override final

◆ randomNoise() [1/2]

StatusCode SCT_FrontEnd::randomNoise ( const EventContext & ctx,
SiChargedDiodeCollection & collection,
const Identifier & moduleId,
CLHEP::HepRandomEngine * rndmEngine,
SCT_FrontEndData & data,
int stripMax ) const

Definition at line 356 of file SCT_FrontEnd.cxx.

356 {
357 // Add random noise
358
359 double occupancy = 0.0;
360 double NoiseOccupancy = 0.0;
361 float Noise = 0.0;
362 int nNoisyStrips = 0;
363 double mode = 1.;
364
365 const bool noise_expanded_mode = (m_data_compression_mode == AnyHit_1XX_X1X_XX1 and m_data_readout_mode == Expanded);
366
367 // Will give 3 times as much noise occupancy if running in any hit expanded mode
368 if (noise_expanded_mode) {
369 mode = 3.;
370 }
371
372 // Sets fixed noise occupancy values for different module types, barrel, EC,
373 // inners, middles
374 // short middles, and outers
375 if (m_sct_id->barrel_ec(moduleId) == 0) { // barrel_ec=0 corresponds to barrel
376 if (m_sct_id->layer_disk(moduleId) == 3) { // outer barrel layer 10 degrees warmer
377 NoiseOccupancy = m_NOBarrel3;
378 Noise = m_NoiseBarrel3;
379 } else {
380 NoiseOccupancy = m_NOBarrel;
381 Noise = m_NoiseBarrel;
382 }
383 } else {
384 int moduleType = m_sct_id->eta_module(moduleId);
385 switch (moduleType) { // eta = 0, 1, or 2 corresponds to outers, middles and inners?! (at least in the offline world)
386 case 0: {
387 NoiseOccupancy = m_NOOuters;
388 Noise = m_NoiseOuters;
389 break;
390 }
391 case 1: {
392 if (m_sct_id->layer_disk(moduleId) == 7) {
393 NoiseOccupancy = m_NOShortMiddles;
394 Noise = m_NoiseShortMiddles;
395 } else {
396 NoiseOccupancy = m_NOMiddles;
397 Noise = m_NoiseMiddles;
398 }
399 break;
400 }
401 case 2: {
402 NoiseOccupancy = m_NOInners;
403 Noise = m_NoiseInners;
404 break;
405 }
406 default: {
407 NoiseOccupancy = m_NOBarrel;
408 Noise = m_NoiseBarrel;
409 ATH_MSG_WARNING("moduleType(eta): " << moduleType << " unknown, using barrel");
410 }
411 }// end of switch structure
412 }
413
414 // Calculate the number of "free strips"
415 int nEmptyStrips = 0;
416 std::vector<int> emptyStrips;
417 emptyStrips.reserve(strip_max);
418 for (int i = 0; i < strip_max; i++) {
419 if (data.m_StripHitsOnWafer[i] == 0) {
420 emptyStrips.push_back(i);
421 ++nEmptyStrips;
422 }
423 }
424
425 if (nEmptyStrips != 0) {
426 // Should randomize the fixed NO values, so we get some differences per
427 // wafer
428 occupancy = CLHEP::RandGaussZiggurat::shoot(rndmEngine, NoiseOccupancy, NoiseOccupancy * 0.1);
429
430 // Modify the occupancy if threshold is not 1.0 fC
431 if (m_Threshold > 6242.3 or m_Threshold < 6242.1) {
432 const float fC = 6242.2;
433 occupancy = occupancy * exp(-(0.5 / (Noise * Noise) * (m_Threshold * m_Threshold - fC * fC)));
434 }
435 nNoisyStrips = CLHEP::RandPoisson::shoot(rndmEngine, strip_max * occupancy * mode);
436
437 // Check and adapt the number of noisy strips to the number of free strips
438 if (nEmptyStrips < nNoisyStrips) {
439 nNoisyStrips = nEmptyStrips;
440 }
441
442 // Find random strips to get noise hits
443 for (int i = 0; i < nNoisyStrips; i++) {
444 int index = CLHEP::RandFlat::shootInt(rndmEngine, nEmptyStrips - i); // strip == 10, 12 free strips
445 // have vector [10000100100200211001] 20 strips
446 int strip = emptyStrips.at(index);
447 emptyStrips.erase(emptyStrips.begin()+index); // Erase it not to use it again
448 if (data.m_StripHitsOnWafer[strip]!=0) {
449 ATH_MSG_ERROR(index << "-th empty strip, strip " << strip << " should be empty but is not empty! Something is wrong!");
450 }
451 data.m_StripHitsOnWafer[strip] = 3; // !< Random Noise hit
452 // Add tbin info to noise diode
453 if (noise_expanded_mode) { // !< if any hit mode, any time bin otherwise fixed tbin=2
454 int noise_tbin = CLHEP::RandFlat::shootInt(rndmEngine, 3);
455 // !< random number 0, 1 or 2
456 if (noise_tbin == 0) {
457 noise_tbin = 4; // !< now 1,2 or 4
458 }
459 if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, noise_tbin)) {
460 ATH_MSG_ERROR("Can't add noise hit diode to collection (1)");
461 }
462 } else {
463 if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, 2)) {
464 ATH_MSG_ERROR("Can't add noise hit diode to collection (2)");
465 }
466 }
467 }
468 }
469
470 return StatusCode::SUCCESS;
471}
DoubleProperty m_NOShortMiddles
DoubleProperty m_NOMiddles
DoubleProperty m_NOInners
DoubleProperty m_NOOuters
DoubleProperty m_NOBarrel3
DoubleProperty m_NOBarrel
str index
Definition DeMoScan.py:362

◆ randomNoise() [2/2]

StatusCode SCT_FrontEnd::randomNoise ( const EventContext & ctx,
SiChargedDiodeCollection & collection,
const Identifier & moduleId,
int side,
CLHEP::HepRandomEngine * rndmEngine,
SCT_FrontEndData & data,
int stripMax ) const

Definition at line 476 of file SCT_FrontEnd.cxx.

476 {
477 const int n_chips = 6;
478 const int chipStripmax = strip_max / n_chips;
479 std::vector<float> NOByChipVect(n_chips, 0.0);
480 std::vector<float> ENCByChipVect(n_chips, 0.0);
481 std::vector<int> nNoisyStrips(n_chips, 0);
482 double mode = 1.;
483
484 const bool noise_expanded_mode = (m_data_compression_mode == AnyHit_1XX_X1X_XX1 and m_data_readout_mode == Expanded);
485
486 // Will give 3 times as much noise occupancy if running in any hit expanded mode
487 if (noise_expanded_mode) {
488 mode = 3.;
489 }
490
491 // Get chip data from calib DB
492 NOByChipVect = m_ReadCalibChipDataTool->getNoiseOccupancyData(moduleId, side, "OccupancyByChip", ctx);
493 ENCByChipVect = m_ReadCalibChipDataTool->getNPtGainData(moduleId, side, "NoiseByChip", ctx);
494
495 // Need to check if empty, most should have data, but a few old DEAD modules don't, and 9C...
496 if (NOByChipVect.empty()) {
497 ATH_MSG_DEBUG("No calibration data in cond DB for module " << moduleId << " using JO values");
498 if (StatusCode::SUCCESS != randomNoise(ctx, collection, moduleId, rndmEngine, data,strip_max)) {
499 return StatusCode::FAILURE;
500 } else {
501 return StatusCode::SUCCESS;
502 }
503 } else {
504 for (int i = 0; i < n_chips; i++) {
505 // A 0 value can mean two things now, chip out of config for long time and no value was uploaded
506 // or its short middles and inners and the value is for all purposes 0! so ok.
507
508 // Modify the occupancy if threshold is not 1.0 fC
509 if (m_Threshold > 6242.3 or m_Threshold < 6242.1) {
510 constexpr float fC = 6242.2;
511 NOByChipVect[i] = NOByChipVect[i] * exp(-(0.5 / (ENCByChipVect[i]*ENCByChipVect[i]) * (m_Threshold*m_Threshold - fC*fC)));
512 }
513
514 nNoisyStrips[i] = CLHEP::RandPoisson::shoot(rndmEngine, chipStripmax * NOByChipVect[i] * mode);
515 }
516 }
517
518 // Loop over the chips on the wafer
519 for (int chip_index = 0; chip_index < n_chips; ++chip_index) {
520 int chip_strip_offset = chipStripmax * chip_index; // First strip number on chip
521
522 // Calculate the number of "free strips" on this chip
523 int nEmptyStripsOnChip = 0;
524 std::vector<int> emptyStripsOnChip;
525 emptyStripsOnChip.reserve(chipStripmax);
526 for (int i = 0; i < chipStripmax; i++) {
527 if (data.m_StripHitsOnWafer[i + chip_strip_offset] == 0) {
528 emptyStripsOnChip.push_back(i);
529 ++nEmptyStripsOnChip;
530 }
531 }
532
533 // if no empty strips on chip do nothing
534 if (nEmptyStripsOnChip != 0) {
535 // Check and adapt the number of noisy strips to the number of free strips
536 if (nEmptyStripsOnChip < nNoisyStrips[chip_index]) {
537 nNoisyStrips[chip_index] = nEmptyStripsOnChip;
538 }
539
540 // Find random strips to get noise hits
541 for (int i = 0; i < nNoisyStrips[chip_index]; i++) {
542 int index = CLHEP::RandFlat::shootInt(rndmEngine, nEmptyStripsOnChip - i);
543 int strip_on_chip = emptyStripsOnChip.at(index);
544 emptyStripsOnChip.erase(emptyStripsOnChip.begin()+index); // Erase it not to use it again
545 int strip = strip_on_chip + chip_strip_offset;
546 if (data.m_StripHitsOnWafer[strip]!=0) {
547 ATH_MSG_ERROR(index << "-th empty strip, strip " << strip << " should be empty but is not empty! Something is wrong!");
548 }
549 data.m_StripHitsOnWafer[strip] = 3; // !< Random Noise hit
550 // Add tbin info to noise diode
551 if (noise_expanded_mode) { // !< if any hit mode, any time bin
552 // !< otherwise fixed tbin=2
553 int noise_tbin = CLHEP::RandFlat::shootInt(rndmEngine, 3);
554 // !< random number 0, 1 or 2
555 if (noise_tbin == 0) {
556 noise_tbin = 4; // !< now 1, 2 or 4
557 }
558 if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, noise_tbin)) {
559 ATH_MSG_ERROR("Can't add noise hit diode to collection (3)");
560 }
561 } else {
562 if (StatusCode::SUCCESS != addNoiseDiode(collection, strip, 2)) {
563 ATH_MSG_ERROR("Can't add noise hit diode to collection (4)");
564 }
565 }
566 }
567 }
568 }
569
570 return StatusCode::SUCCESS;
571}

Member Data Documentation

◆ m_analogueNoiseOn

BooleanProperty SCT_FrontEnd::m_analogueNoiseOn {this, "AnalogueNoiseOn", true, "To know if analogue noise is on or off"}
private

Definition at line 123 of file SCT_FrontEnd.h.

123{this, "AnalogueNoiseOn", true, "To know if analogue noise is on or off"};

◆ m_data_compression_mode

ShortProperty SCT_FrontEnd::m_data_compression_mode {this, "DataCompressionMode", Edge_01X, "Front End Data Compression Mode: 1 is level mode X1X (default), 2 is edge mode 01X, 3 is any hit mode (1XX|X1X|XX1)"}
private

Definition at line 129 of file SCT_FrontEnd.h.

129{this, "DataCompressionMode", Edge_01X, "Front End Data Compression Mode: 1 is level mode X1X (default), 2 is edge mode 01X, 3 is any hit mode (1XX|X1X|XX1)"};

◆ m_data_readout_mode

ShortProperty SCT_FrontEnd::m_data_readout_mode {this, "DataReadOutMode", Condensed, "Front End Data Read out mode Mode: 0 is condensed mode and 1 is expanded mode"}
private

Definition at line 130 of file SCT_FrontEnd.h.

130{this, "DataReadOutMode", Condensed, "Front End Data Read out mode Mode: 0 is condensed mode and 1 is expanded mode"};

◆ m_detMgrName

StringProperty SCT_FrontEnd::m_detMgrName {this, "DetectorManager", "SCT", "Name of DetectorManager to retrieve"}
private

Definition at line 140 of file SCT_FrontEnd.h.

140{this, "DetectorManager", "SCT", "Name of DetectorManager to retrieve"};

◆ m_GainRMS

FloatProperty SCT_FrontEnd::m_GainRMS {this, "GainRMS", 0.031, "Gain spread parameter within the strips for a given Chip gain"}
private

Definition at line 124 of file SCT_FrontEnd.h.

124{this, "GainRMS", 0.031, "Gain spread parameter within the strips for a given Chip gain"};

◆ m_NOBarrel

DoubleProperty SCT_FrontEnd::m_NOBarrel {this, "NOBarrel", 1.5e-5, "Noise factor, Barrel (in the case of no use of calibration data)"}
private

Definition at line 116 of file SCT_FrontEnd.h.

116{this, "NOBarrel", 1.5e-5, "Noise factor, Barrel (in the case of no use of calibration data)"};

◆ m_NOBarrel3

DoubleProperty SCT_FrontEnd::m_NOBarrel3 {this, "NOBarrel3", 2.1e-5, "Noise factor, Barrel3 (in the case of no use of calibration data)"}
private

Definition at line 117 of file SCT_FrontEnd.h.

117{this, "NOBarrel3", 2.1e-5, "Noise factor, Barrel3 (in the case of no use of calibration data)"};

◆ m_NOInners

DoubleProperty SCT_FrontEnd::m_NOInners {this, "NOInners", 5.0e-9, "Noise Occupancy, EC Inners (in the case of no use of calibration data)"}
private

Definition at line 118 of file SCT_FrontEnd.h.

118{this, "NOInners", 5.0e-9, "Noise Occupancy, EC Inners (in the case of no use of calibration data)"};

◆ m_NoiseBarrel

FloatProperty SCT_FrontEnd::m_NoiseBarrel {this, "NoiseBarrel", 1500.0, "Noise factor, Barrel (in the case of no use of calibration data)"}
private

Definition at line 110 of file SCT_FrontEnd.h.

110{this, "NoiseBarrel", 1500.0, "Noise factor, Barrel (in the case of no use of calibration data)"};

◆ m_NoiseBarrel3

FloatProperty SCT_FrontEnd::m_NoiseBarrel3 {this, "NoiseBarrel3", 1541.0, "Noise factor, Barrel3 (in the case of no use of calibration data)"}
private

Definition at line 111 of file SCT_FrontEnd.h.

111{this, "NoiseBarrel3", 1541.0, "Noise factor, Barrel3 (in the case of no use of calibration data)"};

◆ m_NoiseInners

FloatProperty SCT_FrontEnd::m_NoiseInners {this, "NoiseInners", 1090.0, "Noise factor, EC Inners (in the case of no use of calibration data)"}
private

Definition at line 112 of file SCT_FrontEnd.h.

112{this, "NoiseInners", 1090.0, "Noise factor, EC Inners (in the case of no use of calibration data)"};

◆ m_NoiseMiddles

FloatProperty SCT_FrontEnd::m_NoiseMiddles {this, "NoiseMiddles", 1557.0, "Noise factor, EC Middles (in the case of no use of calibration data)"}
private

Definition at line 113 of file SCT_FrontEnd.h.

113{this, "NoiseMiddles", 1557.0, "Noise factor, EC Middles (in the case of no use of calibration data)"};

◆ m_NoiseOn

BooleanProperty SCT_FrontEnd::m_NoiseOn {this, "NoiseOn", true, "To know if noise is on or off when using calibration data"}
private

Definition at line 122 of file SCT_FrontEnd.h.

122{this, "NoiseOn", true, "To know if noise is on or off when using calibration data"};

◆ m_NoiseOuters

FloatProperty SCT_FrontEnd::m_NoiseOuters {this, "NoiseOuters", 1618.0, "Noise factor, Ec Outers (in the case of no use of calibration data)"}
private

Definition at line 115 of file SCT_FrontEnd.h.

115{this, "NoiseOuters", 1618.0, "Noise factor, Ec Outers (in the case of no use of calibration data)"};

◆ m_NoiseShortMiddles

FloatProperty SCT_FrontEnd::m_NoiseShortMiddles {this, "NoiseShortMiddles", 940.0, "Noise factor, EC Short Middles (in the case of no use of calibration data)"}
private

Definition at line 114 of file SCT_FrontEnd.h.

114{this, "NoiseShortMiddles", 940.0, "Noise factor, EC Short Middles (in the case of no use of calibration data)"};

◆ m_NOMiddles

DoubleProperty SCT_FrontEnd::m_NOMiddles {this, "NOMiddles", 2.7e-5, "Noise Occupancy, EC Middles (in the case of no use of calibration data)"}
private

Definition at line 119 of file SCT_FrontEnd.h.

119{this, "NOMiddles", 2.7e-5, "Noise Occupancy, EC Middles (in the case of no use of calibration data)"};

◆ m_NOOuters

DoubleProperty SCT_FrontEnd::m_NOOuters {this, "NOOuters", 3.5e-5, "Noise Occupancy, Ec Outers (in the case of no use of calibration data)"}
private

Definition at line 121 of file SCT_FrontEnd.h.

121{this, "NOOuters", 3.5e-5, "Noise Occupancy, Ec Outers (in the case of no use of calibration data)"};

◆ m_NOShortMiddles

DoubleProperty SCT_FrontEnd::m_NOShortMiddles {this, "NOShortMiddles", 2.0e-9, "Noise Occupancy, EC Short Middles (in the case of no use of calibration data)"}
private

Definition at line 120 of file SCT_FrontEnd.h.

120{this, "NOShortMiddles", 2.0e-9, "Noise Occupancy, EC Short Middles (in the case of no use of calibration data)"};

◆ m_OGcorr

FloatProperty SCT_FrontEnd::m_OGcorr {this, "OffsetGainCorrelation", 0.00001, "Gain/offset correlation for the strips"}
private

Definition at line 126 of file SCT_FrontEnd.h.

126{this, "OffsetGainCorrelation", 0.00001, "Gain/offset correlation for the strips"};

◆ m_Ospread

FloatProperty SCT_FrontEnd::m_Ospread {this, "Ospread", 0.0001, "offset spread within the strips for a given Chip offset"}
private

Definition at line 125 of file SCT_FrontEnd.h.

125{this, "Ospread", 0.0001, "offset spread within the strips for a given Chip offset"};

◆ m_ReadCalibChipDataTool

ToolHandle<ISCT_ReadCalibChipDataTool> SCT_FrontEnd::m_ReadCalibChipDataTool {this, "SCT_ReadCalibChipDataTool", "SCT_ReadCalibChipDataTool", "Tool to retrieve chip calibration information"}
private

Handle to the Calibration ConditionsTool.

Definition at line 134 of file SCT_FrontEnd.h.

134{this, "SCT_ReadCalibChipDataTool", "SCT_ReadCalibChipDataTool", "Tool to retrieve chip calibration information"};

◆ m_sct_amplifier

ToolHandle<IAmplifier> SCT_FrontEnd::m_sct_amplifier {this, "SCT_Amp", "SCT_Amp", "Handle the Amplifier tool"}
private

Handle the Amplifier tool.

Definition at line 133 of file SCT_FrontEnd.h.

133{this, "SCT_Amp", "SCT_Amp", "Handle the Amplifier tool"};

◆ m_sct_id

const SCT_ID* SCT_FrontEnd::m_sct_id {nullptr}
private

Handle to SCT ID helper.

Definition at line 137 of file SCT_FrontEnd.h.

137{nullptr};

◆ m_SCTdetMgr

const InDetDD::SCT_DetectorManager* SCT_FrontEnd::m_SCTdetMgr {nullptr}
private

Handle to SCT detector manager.

Definition at line 136 of file SCT_FrontEnd.h.

136{nullptr};

◆ m_Threshold

FloatProperty SCT_FrontEnd::m_Threshold {this, "Threshold", 1.0, "Threshold"}
private

Definition at line 127 of file SCT_FrontEnd.h.

127{this, "Threshold", 1.0, "Threshold"};

◆ m_timeOfThreshold

FloatProperty SCT_FrontEnd::m_timeOfThreshold {this, "TimeOfThreshold", 30.0, "Threshold time"}
private

Definition at line 128 of file SCT_FrontEnd.h.

128{this, "TimeOfThreshold", 30.0, "Threshold time"};

◆ m_useCalibData

BooleanProperty SCT_FrontEnd::m_useCalibData {this, "UseCalibData", true, "Flag to set the use of calibration data for noise, Gain,offset etc."}
private

Definition at line 131 of file SCT_FrontEnd.h.

131{this, "UseCalibData", true, "Flag to set the use of calibration data for noise, Gain,offset etc."};

The documentation for this class was generated from the following files: