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, const int &stripMax) const
StatusCode doThresholdCheckForRealHits (SiChargedDiodeCollection &collectione, SCT_FrontEndData &data, const int &stripMax) const
StatusCode doThresholdCheckForCrosstalkHits (SiChargedDiodeCollection &collection, SCT_FrontEndData &data, const int &stripMax) const
StatusCode doClustering (SiChargedDiodeCollection &collection, SCT_FrontEndData &data, const int &stripMax) const
StatusCode prepareGainAndOffset (SiChargedDiodeCollection &collection, const Identifier &moduleId, CLHEP::HepRandomEngine *rndmEngine, SCT_FrontEndData &data, const int &stripMax) const
StatusCode prepareGainAndOffset (SiChargedDiodeCollection &collection, int side, const Identifier &moduleId, CLHEP::HepRandomEngine *rndmEngine, SCT_FrontEndData &data, const int &stripMax) const
StatusCode randomNoise (SiChargedDiodeCollection &collection, const Identifier &moduleId, CLHEP::HepRandomEngine *rndmEngine, SCT_FrontEndData &data, const int &stripMax) const
StatusCode randomNoise (SiChargedDiodeCollection &collection, const Identifier &moduleId, int side, CLHEP::HepRandomEngine *rndmEngine, SCT_FrontEndData &data, const 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 29 of file SCT_FrontEnd.cxx.

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

◆ ~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 969 of file SCT_FrontEnd.cxx.

969 {
970 const SiCellId ndiode(strip); // !< create a new diode
971 const SiCharge noiseCharge(2 * m_Threshold, 0, SiCharge::noise); // !< add some noise to it
972 collection.add(ndiode, noiseCharge); // !< add it to the collection
973
974 // Get the strip back to check
975 SiChargedDiode *NoiseDiode = (collection.find(strip));
976 if (NoiseDiode == nullptr) {
977 return StatusCode::FAILURE;
978 }
979 SiHelper::SetTimeBin(*NoiseDiode, tbin, &msg()); // set timebin info
980 return StatusCode::SUCCESS;
981}
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,
const int & stripMax ) const

Definition at line 875 of file SCT_FrontEnd.cxx.

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

Definition at line 646 of file SCT_FrontEnd.cxx.

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

Definition at line 799 of file SCT_FrontEnd.cxx.

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

◆ doThresholdCheckForRealHits()

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

Definition at line 721 of file SCT_FrontEnd.cxx.

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

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

◆ initialize()

StatusCode SCT_FrontEnd::initialize ( )
overridevirtual

AlgTool InterfaceID.

AlgTool initialize

Definition at line 36 of file SCT_FrontEnd.cxx.

36 {
37 if (m_NoiseOn and (not m_analogueNoiseOn)) {
38 ATH_MSG_FATAL("AnalogueNoiseOn/m_analogueNoiseOn should be true if NoiseOn/m_NoiseOn is true.");
39 return StatusCode::FAILURE;
40 }
41
42 ATH_MSG_DEBUG("SCT_FrontEnd::initialize()");
43 // Get SCT helper
44 ATH_CHECK(detStore()->retrieve(m_sct_id, "SCT_ID"));
45 // Get SCT detector manager
47 // Get the amplifier tool
48 ATH_CHECK(m_sct_amplifier.retrieve());
49 ATH_MSG_DEBUG("SCT Amplifier tool located ");
50
51 // Get the SCT_ReadCaliDataSvc
52 if (m_useCalibData) {
54 ATH_MSG_DEBUG("CalibChipData Service located ");
55 } else {
57 }
58
59 constexpr float fC = 6242.2;
61
62#ifdef SCT_DIG_DEBUG
63 ATH_MSG_INFO("\tNoise factors:");
64 ATH_MSG_INFO("\tBarrel = " << m_NoiseBarrel << " Outer Barrel = " << m_NoiseBarrel3 <<
65 " EC, inners = " << m_NoiseInners << " EC, middles = " << m_NoiseMiddles <<
66 " EC, short middles = " << m_NoiseShortMiddles << " EC, outers = " << m_NoiseOuters);
67 ATH_MSG_INFO("\tThreshold=" << m_Threshold << " fC, time of Threshold=" << m_timeOfThreshold);
68#endif
69
70 ATH_MSG_INFO("m_Threshold (Threshold) = " << m_Threshold);
71 ATH_MSG_INFO("m_timeOfThreshold (TimeOfThreshold) = " << m_timeOfThreshold);
72 ATH_MSG_INFO("m_data_compression_mode (DataCompressionMode) = " << m_data_compression_mode);
73 ATH_MSG_INFO("m_data_readout_mode (DataReadOutMode) = " << m_data_readout_mode);
74
75 // Check configuration. If it is invalid, abort this job.
79 ATH_MSG_FATAL("m_data_compression_mode = " << m_data_compression_mode
80 << " is invalid. Abort this job!!!");
81 return StatusCode::FAILURE;
82 }
84 ATH_MSG_FATAL("m_data_readout_mode = " << m_data_readout_mode
85 << " is invalid. Abort this job!!!");
86 return StatusCode::FAILURE;
87 }
90 ATH_MSG_FATAL("m_data_compression_mode = " << m_data_compression_mode
91 << (m_data_compression_mode==Level_X1X ? " (Level_X1X)" : " (AnyHit_1XX_X1X_XX1)")
92 << " requires timing information."
93 << " However, m_data_readout_mode = " << m_data_readout_mode
94 << " (Condensed) does not keep timing information. Abort this job!!!");
95 return StatusCode::FAILURE;
96 }
97
98 return StatusCode::SUCCESS;
99}
#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
retrieve(aClass, aKey=None)
Definition PyKernel.py:110

◆ initVectors()

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

Definition at line 111 of file SCT_FrontEnd.cxx.

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

◆ meanValue()

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

Definition at line 983 of file SCT_FrontEnd.cxx.

983 {
984 float mean_value = 0.0;
985 int nData = 0;
986 const unsigned int vec_size = calibDataVect.size();
987
988 for (unsigned int i = 0; i < vec_size; ++i) {
989 if (calibDataVect[i] > 0.1) {
990 mean_value += calibDataVect[i];
991 ++nData;
992 }
993 }
994
995 if (nData == 0) {
996 return -1;
997 } else {
998 return mean_value / nData;
999 }
1000}
ATH_ALWAYS_INLINE constexpr size_t vec_size()
Return the number of elements in a vectorized type.
Definition vec.h:227

◆ prepareGainAndOffset() [1/2]

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

Definition at line 129 of file SCT_FrontEnd.cxx.

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

◆ prepareGainAndOffset() [2/2]

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

Definition at line 232 of file SCT_FrontEnd.cxx.

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

◆ 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 575 of file SCT_FrontEnd.cxx.

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

◆ randomNoise() [1/2]

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

Definition at line 353 of file SCT_FrontEnd.cxx.

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

Definition at line 473 of file SCT_FrontEnd.cxx.

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

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: