diff --git a/Config/Nuclearizer_EM_DEE.cfg b/Config/Nuclearizer_EM_DEE.cfg index dafb0983..16f7989b 100644 --- a/Config/Nuclearizer_EM_DEE.cfg +++ b/Config/Nuclearizer_EM_DEE.cfg @@ -4,7 +4,7 @@ XmlTagLoaderSimulations XmlTagDEESMEX - $(NUCLEARIZER)/../massmodel-cosi-em-edited/COSISMEX.analysis_BGOreading.geo.setup + $(NUCLEARIZER)/../massmodel-cosi-em/COSISMEX.analysis_BGOreading.geo.setup @@ -39,7 +39,7 @@ 10000000 - /Users/parshadkp/Software/Nuclearizer_files/SingleDetBGO-GeD/Cosima/Cs137_singleDetBGO-GeD_sourceHolderPos_1166700Flux_10s_0050_Fluore_.inc1.id1.sim.gz + /Users/parshadkp/Software/Nuclearizer_files/SingleDetBGO-GeD/Cosima/Cs137_singleDetBGO-em-Voxel3D.inc1.id1.sim.gz $(NUCLEARIZER)/../Data/roas/asic_gse_240412194613.hdf.roa @@ -69,10 +69,9 @@ $(NUCLEARIZER)/resource/calibration/COSI_SingleDet/20240819_Am241_Cs137_Co57_LV.ecal - false - - false - 0 + 0 + 35 + 0 diff --git a/include/MSubModuleShieldTrigger.h b/include/MSubModuleShieldTrigger.h index 7d05d454..cd1e485a 100644 --- a/include/MSubModuleShieldTrigger.h +++ b/include/MSubModuleShieldTrigger.h @@ -97,9 +97,6 @@ class MSubModuleShieldTrigger : public MSubModule //! Get shield hit counts int GetShieldHitCounts() const { return m_NumShieldHitCounts; } - //! Get shield veto counter - int GetShieldVetoCounter() const { return m_NumShieldVetoCounts; } - //! Get BGO hits erased int GetBGOHitsErased() const { return m_NumBGOHitsErased; } @@ -155,14 +152,10 @@ class MSubModuleShieldTrigger : public MSubModule //! Number of shield hits before deadtime unsigned long m_NumShieldHitCounts; - //! Number of shield veto counts - unsigned long m_NumShieldVetoCounts; //! Number of BGO hits erased due to deadtime unsigned long m_NumBGOHitsErased; //! Bool to store if corresponding shield ASIC is dead or not bool m_IsShieldDead; - //! Time of last shield veto hit (used for veto window calculation) - double m_ShieldVetoTime; //! First event time in seconds double m_FirstTime; @@ -200,4 +193,4 @@ class MSubModuleShieldTrigger : public MSubModule #endif -//////////////////////////////////////////////////////////////////////////////// \ No newline at end of file +//////////////////////////////////////////////////////////////////////////////// diff --git a/include/MSubModuleStripTrigger.h b/include/MSubModuleStripTrigger.h index 6ae719ad..e88c766c 100644 --- a/include/MSubModuleStripTrigger.h +++ b/include/MSubModuleStripTrigger.h @@ -92,7 +92,7 @@ class MSubModuleStripTrigger : public MSubModule double GetStripsTotalDeadtime() const { return m_StripsTotalDeadtime; } //! Get number of strip hits erased - int GetStripHitsErased() const { return m_StripHitsErased; } + // int GetStripHitsErased() const { return m_StripHitsErased; } //! Get trigger rate for detector int GetTriggerRate(int det) const { @@ -174,9 +174,11 @@ class MSubModuleStripTrigger : public MSubModule //! Stores total dead time of the instrument double m_StripsTotalDeadtime; //! Hits erased due to deadtime - int m_StripHitsErased; + // int m_StripHitsErased; //! Total strip hits counter int m_TotalStripHitsCounter; + //! Total GR hits counter + int m_TotalGRHitsCounter; //! First event time for statistics double m_FirstTime; @@ -186,7 +188,7 @@ class MSubModuleStripTrigger : public MSubModule //! Number of detectors static const int nDets = 16; //! Number of ASICs per detector - static const int nASICs = 4; + static const int nASICs = 6; //! Stores dead time for each ASIC vector> m_ASICDeadTime; diff --git a/resource/calibration/COSI_SingleDet/deadtimeParameters.txt b/resource/calibration/COSI_SingleDet/deadtimeParameters.txt index 61fe6955..1936f865 100644 --- a/resource/calibration/COSI_SingleDet/deadtimeParameters.txt +++ b/resource/calibration/COSI_SingleDet/deadtimeParameters.txt @@ -1,2 +1,4 @@ -CoincidenceWindow (s); DeadtimePerStrip (s); delayAfter1 (s); delayAfter2 (s) -1.4e-6 1e-6 0.2e-6 0.2e-6 \ No newline at end of file +CoincidenceWindow (s); StripDeadtimePerStrip (s); delayAfter1 (s); delayAfter2 (s) +1.4e-6 1e-6 0.2e-6 0.2e-6 +ShieldDeadtimePerStrip (s); ShieldVetoWindow (s); ShieldPulseDuration (s); ShieldDelayBefore (s); ShieldDelayAfter (s) +1e-6 1.5e-6 1.7e-6 0.1e-6 0.4e-6 diff --git a/src/MModuleDEESMEX.cxx b/src/MModuleDEESMEX.cxx index 313a723d..52a6dd29 100644 --- a/src/MModuleDEESMEX.cxx +++ b/src/MModuleDEESMEX.cxx @@ -156,12 +156,13 @@ bool MModuleDEESMEX::AnalyzeEvent(MReadOutAssembly* Event) m_ShieldTrigger.Clear(); m_ShieldTrigger.AnalyzeEvent(Event); if (m_ShieldTrigger.HasVeto() == true) { + Event->SetShieldVeto(true); if (m_ShieldTrigger.GetDeadTimeEnd() > m_DeadTimeEnd) { m_DeadTimeEnd = m_ShieldTrigger.GetDeadTimeEnd(); } // Clean up - + Event->SetAnalysisProgress(MAssembly::c_DetectorEffectsEngine); return true; } else if (m_ShieldTrigger.HasTrigger() == true) { // = energy read out @@ -192,8 +193,7 @@ bool MModuleDEESMEX::AnalyzeEvent(MReadOutAssembly* Event) if (m_StripTrigger.GetDeadTimeEnd() > m_DeadTimeEnd) { m_DeadTimeEnd = m_StripTrigger.GetDeadTimeEnd(); } - // Clean up - + Event->SetGuardRingVeto(true); // <-- mark the event so EventSaver can filter it Event->SetAnalysisProgress(MAssembly::c_DetectorEffectsEngine); return true; } diff --git a/src/MSubModuleDEEIntake.cxx b/src/MSubModuleDEEIntake.cxx index 571b32b8..244f9080 100644 --- a/src/MSubModuleDEEIntake.cxx +++ b/src/MSubModuleDEEIntake.cxx @@ -132,7 +132,8 @@ bool MSubModuleDEEIntake::AnalyzeEvent(MReadOutAssembly* Event) double DetectorDepth = Shape->GetSizeZ(); MString DetectorName = Detector->GetName(); - if (DetectorName.BeginsWith("GeD") == true) { + if (DetectorName.BeginsWith("GeD") == true || DetectorName.BeginsWith("GuardRing") == true) { + DetectorName.RemoveAllInPlace("GuardRingDetector_GeD_"); // Remove prefix GuardRing if existent DetectorName.RemoveAllInPlace("GeD_"); // The number after GeD is the COSI detector ID int DetectorID = DetectorName.ToInt(); @@ -198,29 +199,6 @@ bool MSubModuleDEEIntake::AnalyzeEvent(MReadOutAssembly* Event) return false; } - // int DetectorID = -1; - // if (Tokens[1] == "X0") { - // DetectorID = 0; - // } - // else if (Tokens[1] == "X1") { - // DetectorID = 1; - // } - // else if (Tokens[1] == "Y0") { - // DetectorID = 2; - // } - // else if (Tokens[1] == "Y1") { - // DetectorID = 3; - // } - // else if (Tokens[1] == "Z0") { - // DetectorID = 4; - // } - // else if (Tokens[1] == "Z1") { - // DetectorID = 5; - // } - // else { - // cerr << "ERROR: Detector name does not correspond to any panel " << Tokens[1] << endl; - // return false; - // } MString DetectorID = Tokens[1]; int CrystalID = Tokens[2].ToInt(); diff --git a/src/MSubModuleShieldTrigger.cxx b/src/MSubModuleShieldTrigger.cxx index 17b9ab7b..bb0b121f 100644 --- a/src/MSubModuleShieldTrigger.cxx +++ b/src/MSubModuleShieldTrigger.cxx @@ -65,11 +65,9 @@ MSubModuleShieldTrigger::MSubModuleShieldTrigger() : MSubModule() m_ShieldDelayBefore = 0.1e-6; m_ShieldDelayAfter = 0.4e-6; m_ShieldVetoWindowSize = 1.5e-6; - m_ASICDeadTimePerChannel = 0.0; - m_ShieldVetoTime = 0.0; + m_ASICDeadTimePerChannel = 1e-6; m_NumShieldHitCounts = 0; - m_NumShieldVetoCounts = 0; m_NumBGOHitsErased = 0; m_FirstTime = std::numeric_limits::max(); @@ -173,7 +171,6 @@ double MSubModuleShieldTrigger::CalculateASICDeadtime(vector CrystalIDs) return deadtime; } - //////////////////////////////////////////////////////////////////////////////// @@ -181,16 +178,14 @@ bool MSubModuleShieldTrigger::ProcessShieldHits(MReadOutAssembly* Event) { // Process shield crystal hits to determine veto status - m_EventTime = Event->GetTime().GetAsSeconds(); - - // Track which GeD detectors got hit (for later deadtime update) - list& LVHits = Event->GetDEEStripHitLVListReference(); - for (const MDEEStripHit& Hit : LVHits) { - int DetID = Hit.m_ROE.GetDetectorID(); - if (DetID >= 0 && DetID < nDets) { - m_DetectorsHitForShieldVeto[DetID] = 1; - } - } + // // Track which GeD detectors got hit (for later deadtime update) + // list& LVHits = Event->GetDEEStripHitLVListReference(); + // for (const MDEEStripHit& Hit : LVHits) { + // int DetID = Hit.m_ROE.GetDetectorID(); + // if (DetID >= 0 && DetID < nDets) { + // m_DetectorsHitForShieldVeto[DetID] = 1; + // } + // } // Process shield crystal hits list& CrystalHits = Event->GetDEECrystalHitListReference(); @@ -232,22 +227,17 @@ bool MSubModuleShieldTrigger::ProcessShieldHits(MReadOutAssembly* Event) continue; } - // cout << m_ShieldLastHitTime[ShieldDetGroup] + m_ShieldDeadtime[ShieldDetGroup] << " " << m_EventTime << endl; // Check deadtime conditions if (m_EventTime > (m_ShieldLastHitTime[ShieldDetGroup] + m_ShieldDeadtime[ShieldDetGroup])) { // Event occurred after deadtime - start new veto window m_ShieldHitCrystalID[ShieldDetGroup].clear(); m_ShieldLastHitTime[ShieldDetGroup] = m_EventTime; - m_ShieldVetoTime = m_EventTime; m_ShieldHitCrystalID[ShieldDetGroup].push_back(CrystalID); - m_HasVeto = true; m_TotalShieldDeadtime[ShieldDetGroup] += m_ShieldDeadtime[ShieldDetGroup]; } else if (m_EventTime <= (m_ShieldLastHitTime[ShieldDetGroup] + m_ShieldDelayBefore)) { // Event occurred within coincidence window - add to existing veto - m_ShieldVetoTime = m_EventTime; m_ShieldHitCrystalID[ShieldDetGroup].push_back(CrystalID); - m_HasVeto = true; } else { // Event occurred within deadtime @@ -259,18 +249,7 @@ bool MSubModuleShieldTrigger::ProcessShieldHits(MReadOutAssembly* Event) // Calculate deadtime for each panel group after processing all hits for (int group = 0; group < nShieldPanels; group++) { - if (!m_IsShieldDead) { m_ShieldDeadtime[group] = CalculateASICDeadtime(m_ShieldHitCrystalID[group]); - } - } - - // Check if event is within veto window - if ((m_EventTime <= (m_ShieldVetoTime + m_ShieldVetoWindowSize)) && - (m_EventTime >= m_ShieldVetoTime)) { - m_HasVeto = true; - if (Event->GetSimulatedEvent() != nullptr) { - m_NumShieldVetoCounts += Event->GetSimulatedEvent()->GetNHTs(); - } } return true; @@ -283,7 +262,11 @@ bool MSubModuleShieldTrigger::ProcessShieldHits(MReadOutAssembly* Event) bool MSubModuleShieldTrigger::ParseDeadtimeFile() { // Read in deadtime parameters file - // Format: StripCoincidenceWindow ASICDeadTimePerChannel StripDelayAfter1 StripDelayAfter2 + // Format: + // Row 1: strip trigger header + // Row 2: strip trigger parameters + // Row 3: shield trigger header + // Row 4: shield trigger parameters MParser Parser; if (Parser.Open(m_DeadtimeFileName) == false) { @@ -291,13 +274,22 @@ bool MSubModuleShieldTrigger::ParseDeadtimeFile() return false; } - if (Parser.GetNLines() < 2) { + if (Parser.GetNLines() < 4) { cout << m_Name << ": Deadtime file does not have enough data" << endl; return false; } - // We only need the ASICDeadTimePerChannel (second value) for shield - m_ASICDeadTimePerChannel = Parser.GetTokenizerAt(1)->GetTokenAtAsDouble(1); + MTokenizer* ShieldTokenizer = Parser.GetTokenizerAt(3); + if (ShieldTokenizer->GetNTokens() < 5) { + cout << m_Name << ": Shield deadtime row does not have enough data" << endl; + return false; + } + + m_ASICDeadTimePerChannel = ShieldTokenizer->GetTokenAtAsDouble(0); + m_ShieldVetoWindowSize = ShieldTokenizer->GetTokenAtAsDouble(1); + m_ShieldPulseDuration = ShieldTokenizer->GetTokenAtAsDouble(2); + m_ShieldDelayBefore = ShieldTokenizer->GetTokenAtAsDouble(3); + m_ShieldDelayAfter = ShieldTokenizer->GetTokenAtAsDouble(4); return true; } @@ -314,16 +306,24 @@ bool MSubModuleShieldTrigger::AnalyzeEvent(MReadOutAssembly* Event) m_HasVeto = false; m_IsShieldDead = false; + m_EventTime = Event->GetTime().GetAsSeconds(); + + // First: veto based on shield state from previous events + for (int group = 0; group < nShieldPanels; ++group) { + if (m_EventTime >= m_ShieldLastHitTime[group] && + m_EventTime <= m_ShieldLastHitTime[group] + m_ShieldVetoWindowSize) { + m_HasVeto = true; + } + } + // Process shield hits and check for veto conditions ProcessShieldHits(Event); - // Update time tracking for statistics - double eventTime = Event->GetTime().GetAsSeconds(); - if (eventTime < m_FirstTime) { - m_FirstTime = eventTime; + if (m_EventTime < m_FirstTime) { + m_FirstTime = m_EventTime; } - if (eventTime > m_LastTime) { - m_LastTime = eventTime; + if (m_EventTime > m_LastTime) { + m_LastTime = m_EventTime; } // If vetoed, set the dead time end @@ -370,7 +370,6 @@ void MSubModuleShieldTrigger::Finalize() } cout << "BGO hits erased due to BGO being dead: " << m_NumBGOHitsErased << endl; - cout << "Shield vetoes: " << m_NumShieldVetoCounts << endl; if (simTime > 0) { double rateAfterDT = (m_NumShieldHitCounts - m_NumBGOHitsErased) / simTime; @@ -411,4 +410,4 @@ MXmlNode* MSubModuleShieldTrigger::CreateXmlConfiguration(MXmlNode* Node) // MSubModuleShieldTrigger.cxx: the end... -//////////////////////////////////////////////////////////////////////////////// \ No newline at end of file +//////////////////////////////////////////////////////////////////////////////// diff --git a/src/MSubModuleStripTrigger.cxx b/src/MSubModuleStripTrigger.cxx index 57648665..1613df5e 100644 --- a/src/MSubModuleStripTrigger.cxx +++ b/src/MSubModuleStripTrigger.cxx @@ -69,8 +69,9 @@ MSubModuleStripTrigger::MSubModuleStripTrigger() : MSubModule() m_StripsCurrentDeadtime = 0.0; m_ASICLastHitTime = -10.0; m_StripsTotalDeadtime = 0.0; - m_StripHitsErased = 0; + // m_StripHitsErased = 0; m_TotalStripHitsCounter = 0; + m_TotalGRHitsCounter = 0; m_FirstTime = std::numeric_limits::max(); m_LastTime = 0.0; @@ -154,10 +155,7 @@ double MSubModuleStripTrigger::CalculateASICDeadtime(vector ASICChannels) // Loop through each channel ID and add nearest neighbors for (int ID : ASICChannels) { if (ID == 64) { - if (g_Verbosity >= c_Warning) { - cout << m_Name << ": Warning - Strip ID is 64; should not happen" << endl; - } - continue; + ASICChannelsSet.insert(ID); } else if (ID == 0 || ID == 32) { // Edge case: If ID is 0 or 32, add the channel and the next channel ASICChannelsSet.insert(ID); @@ -207,10 +205,8 @@ bool MSubModuleStripTrigger::CountRate(vector ASICChannels, vector size_t temp_size = ASICChannelsSet.size(); if (ID == 64) { - if (g_Verbosity >= c_Warning) { - cout << m_Name << ": Warning - Strip ID is 64; should not happen" << endl; - } - continue; + // ASICChannelsSet.insert(ID); + continue; // Do not include GR hits in count rate calculation as it has its own readout and does not cause nearest neighbor readout } else if (ID == 0 || ID == 32) { ASICChannelsSet.insert(ID); ASICChannelsSet.insert(ID + 1); @@ -340,10 +336,14 @@ bool MSubModuleStripTrigger::ProcessStripHits(MReadOutAssembly* Event) ASICofDet = 2; } else if (!IsLV && StripID >= 32 && StripID <= 63) { ASICofDet = 3; - // } else if (!IsLV && StripID = 64) { - // ASICofDet = 4; - // } else if (IsLV && StripID = 64) { - // ASICofDet = 5; + } else if (!IsLV && StripID == 64) { + m_HasVeto = true; + m_TotalGRHitsCounter++; + ASICofDet = 4; + } else if (IsLV && StripID == 64) { + m_HasVeto = true; + m_TotalGRHitsCounter++; + ASICofDet = 5; } else { if (g_Verbosity >= c_Warning) { cout << m_Name << ": Warning - Strip not associated with any ASIC" << endl; @@ -383,7 +383,7 @@ bool MSubModuleStripTrigger::ProcessStripHits(MReadOutAssembly* Event) m_ASICHitStripID_noDT[det][ASICofDet].push_back(StripID); m_TempEvtTimes[det][ASICofDet].push_back(m_EventTime); m_IsGeDDead = true; - m_StripHitsErased++; + // m_StripHitsErased++; HitIter = Hits.erase(HitIter); continue; } @@ -490,6 +490,7 @@ void MSubModuleStripTrigger::Finalize() } cout << "Total strip hits after charge sharing (before deadtime): " << m_TotalStripHitsCounter << endl; + cout << "Total GR hits (before deadtime): " << m_TotalGRHitsCounter << endl; cout << "Total dead time of the instrument: " << m_StripsTotalDeadtime << " seconds" << endl; if (simTime > 0) { @@ -497,7 +498,7 @@ void MSubModuleStripTrigger::Finalize() cout << "Livetime fraction: " << liveFraction << endl; } - cout << "Hits erased due to detector being dead: " << m_StripHitsErased << endl; + // cout << "Hits erased due to detector being dead: " << m_StripHitsErased << endl; if (m_TotalStripHitsCounter > 0) { cout << "Avg deadtime per strip hit: " << m_StripsTotalDeadtime / m_TotalStripHitsCounter << " seconds" << endl;