diff --git a/UserTools/EBMRD/EBMRD.cpp b/UserTools/EBMRD/EBMRD.cpp new file mode 100644 index 000000000..c00047144 --- /dev/null +++ b/UserTools/EBMRD/EBMRD.cpp @@ -0,0 +1,237 @@ +#include "EBMRD.h" + +EBMRD::EBMRD() : Tool() {} + +bool EBMRD::Initialise(std::string configfile, DataModel &data) +{ + + /////////////////// Useful header /////////////////////// + if (configfile != "") + m_variables.Initialise(configfile); // loading config file + // m_variables.Print(); + + m_data = &data; // assigning transient data pointer + ///////////////////////////////////////////////////////////////// + + m_variables.Get("verbosityEBMRD", verbosityEBMRD); + matchTargetTrigger = 8; + m_variables.Get("matchTargetTrigger", matchTargetTrigger); + matchTolerance_ns = 2000000; // default 2ms + m_variables.Get("matchTolerance_ns", matchTolerance_ns); + exePerMatch = 500; + m_variables.Get("exePerMatch", exePerMatch); + matchToAllTriggers = 0; + m_variables.Get("matchToAllTriggers", matchToAllTriggers); + + matchedMRDNumber = 0; + + return true; +} + +bool EBMRD::Execute() +{ + m_data->CStore.Get("RunCode", currentRunCode); + + m_data->CStore.Get("MRDEvents", MRDEvents); + m_data->CStore.Get("MRDEventTriggerTypes", MRDEventTriggerTypes); + m_data->CStore.Get("MRDBeamLoopback", MRDBeamLoopback); + m_data->CStore.Get("MRDCosmicLoopback", MRDCosmicLoopback); + m_data->CStore.Get("NewMRDDataAvailable", NewMRDDataAvailable); + + m_data->CStore.Get("PairedMRDTriggerTimestamp", PairedCTCTimeStamps); + m_data->CStore.Get("PairedMRDTimeStamps", PairedMRDTimeStamps); + + Log("EBMRD: NewMRDDataAvailable = " + std::to_string(NewMRDDataAvailable) + ", Current loaded MRDEvents size is " + std::to_string(MRDEvents.size()), v_message, verbosityEBMRD); + Log("EBMRD: Current buffer size is " + std::to_string(MRDEventsBuffer.size()), v_message, verbosityEBMRD); + // loop the MRDEvents, save every event to MRDEventsBuffer if it's not already in the buffer + int newLoadedEvents = 0; + for (std::pair>> p : MRDEvents) + { + uint64_t MTCtime = p.first; + std::vector> WaveMap = p.second; + // if find the MTCtime in the PairedMRDTimeStamps, then skip + if (PairedMRDTimeStamps.size() > 0) + { + bool skip = false; + for (std::pair> pair : PairedMRDTimeStamps) + { + for (uint64_t t : pair.second) + { + if (t == MTCtime) + { + skip = true; + break; + } + } + if (skip) + break; + } + if (skip) + continue; + } + if (MRDEventsBuffer.find(MTCtime) == MRDEventsBuffer.end()) + { + MRDEventsBuffer.emplace(MTCtime, WaveMap); + newLoadedEvents++; + } + } + Log("EBMRD: Finished loading MRDEvents to buffer, Buffer_MRDEvents size is now " + std::to_string(MRDEventsBuffer.size()) + " new loaded events = " + std::to_string(newLoadedEvents), v_message, verbosityEBMRD); + + bool stopLoop = false; + m_data->vars.Get("StopLoop", stopLoop); + int runNum = thisRunNum; + m_data->vars.Get("RunNumber", thisRunNum); + bool ForceMRDMatching = false; + m_data->CStore.Get("ForceMRDMatching", ForceMRDMatching); + + if (exeNum % exePerMatch == 0 || runNum != thisRunNum || stopLoop || ForceMRDMatching) + { + Log("EBMRD: exeNum = " + std::to_string(exeNum) + ". Doing matching now", v_message, verbosityEBMRD); + if (matchToAllTriggers) + { + Matching(0, 0); + } + else + { + bool BeamTriggerGroupped = false; + m_data->CStore.Get("BeamTriggerGroupped", BeamTriggerGroupped); + bool CosmicTriggerGroupped = false; + m_data->CStore.Get("CosmicTriggerGroupped", CosmicTriggerGroupped); + bool NuMITriggerGroupped = false; + m_data->CStore.Get("NuMITriggerGroupped", NuMITriggerGroupped); + + + if (BeamTriggerGroupped) + Matching(matchTargetTrigger, 14); + if (CosmicTriggerGroupped) + { + Matching(36, 36); + Matching(45, 46); + } + if(NuMITriggerGroupped) + Matching(42, 46); + + if(!BeamTriggerGroupped && !CosmicTriggerGroupped && !NuMITriggerGroupped) + Log("EBMRD: BeamTriggerGroupped and CosmicTriggerGroupped are false, no beam trigger groupped in the grouper, stop matching", v_message, verbosityEBMRD); + } + } + + m_data->CStore.Set("PairedMRDTriggerTimestamp", PairedCTCTimeStamps); + m_data->CStore.Set("PairedMRDTimeStamps", PairedMRDTimeStamps); + m_data->CStore.Set("PairedMRD_TriggerIndex", PairedMRD_TriggerIndex); + m_data->CStore.Set("MRDHitMapRunCode", MRDHitMapRunCode); + + exeNum++; + return true; +} + +bool EBMRD::Finalise() +{ + Log("\033[1;34mEBMRD: Finalising\033[0m", v_message, verbosityEBMRD); + Log("EBMRD: Matched MRD number = " + std::to_string(matchedMRDNumber), v_message, verbosityEBMRD); + Log("EBMRD: Unmatched MRD number = " + std::to_string(MRDEventsBuffer.size()), v_message, verbosityEBMRD); + return true; +} + +bool EBMRD::Matching(int targetTrigger, int matchToTrack) +{ + cout << "\033[1;34m******* EBMRD : Matching *******\033[0m" << endl; + std::map>> GroupedTriggersInTotal; // each map is a group of triggers, with the key is the target trigger word + m_data->CStore.Get("GroupedTriggersInTotal", GroupedTriggersInTotal); + + Log("EBMRD: Got GroupedTriggersInTotal[14] size: " + std::to_string(GroupedTriggersInTotal[14].size()), v_message, verbosityEBMRD); + + vector matchedMRDTimes; + std::map matchedNumberInTrack; + + // loop the MRDEventsBuffer keys, and loop all the grouped triggers + // in each group of trigger, find the target trigger word and it's time + // fine the minimum time difference, if smaller than matchTolerance_ns, then save the time to PairedCTCTimeStamps and PairedMRDTimeStamps + int loopNum = 0; + for (std::pair>> mrdpair : MRDEventsBuffer) + { + if (verbosityEBMRD > 11) + cout << "******************EBMRD: new MRD event: " << loopNum << endl; + uint64_t MTCtime = mrdpair.first; + std::vector> WaveMap = mrdpair.second; + // set minDT to 5 min + uint64_t minDT = 5 * 60 * 1e9; + uint64_t minDTTrigger = 0; + uint64_t dt = 0; + uint32_t matchedTrigWord = 0; + int matchedTrack = 0; + int matchedIndex = 0; + for (std::pair>> pair : GroupedTriggersInTotal) + { + int TrackTriggerWord = pair.first; + if (TrackTriggerWord != matchToTrack && !matchToAllTriggers) + { + Log("EBMRD: Skipping TrackTriggerWord " + std::to_string(TrackTriggerWord), v_debug, verbosityEBMRD); + continue; + } + if (matchedNumberInTrack.find(TrackTriggerWord) == matchedNumberInTrack.end()) + matchedNumberInTrack.emplace(TrackTriggerWord, 0); + + vector> groupedTriggers = pair.second; + + for (int i = 0; i < groupedTriggers.size(); i++) + { + map groupedTrigger = groupedTriggers.at(i); + // itearte over all the grouped triggers, if the value is target trigger, then calculate the time difference + for (std::pair p : groupedTrigger) + { + if (matchToAllTriggers || p.second == targetTrigger) + { + if (MTCtime > p.first) + { + dt = MTCtime - p.first; + } + else + { + dt = p.first - MTCtime; + } + if (dt < minDT) + { + minDT = dt; + minDTTrigger = p.first; + matchedTrigWord = p.second; + matchedIndex = p.second; + matchedTrack = TrackTriggerWord; + + // if(verbosityEBMRD > 11) cout<<"EBMRD: dt: "< pair : matchedNumberInTrack) + { + Log("EBMRD: Match finished, matched number in Track " + std::to_string(pair.first) + " is " + std::to_string(pair.second), v_message, verbosityEBMRD); + } + + return true; +} \ No newline at end of file diff --git a/UserTools/EBMRD/EBMRD.h b/UserTools/EBMRD/EBMRD.h new file mode 100644 index 000000000..0722d5ae3 --- /dev/null +++ b/UserTools/EBMRD/EBMRD.h @@ -0,0 +1,63 @@ +#ifndef EBMRD_H +#define EBMRD_H + +#include +#include + +#include "Tool.h" + +/** + * \class EBPMT + * + * $Author: Yue Feng $ + * $Date: 2024/04 $ + * Contact: yuef@iaistate.edu + * + */ + +class EBMRD : public Tool +{ + +public: + EBMRD(); ///< Simple constructor + bool Initialise(std::string configfile, DataModel &data); ///< Initialise Function for setting up Tool resources. @param configfile The path and name of the dynamic configuration file to read in. @param data A reference to the transient data class used to pass information between Tools. + bool Execute(); ///< Execute function used to perform Tool purpose. + bool Finalise(); ///< Finalise function used to clean up resources. + bool Matching(int targetTrigger, int matchToTrack); + +private: + int verbosityEBMRD; + int matchTargetTrigger; + uint64_t matchTolerance_ns; + + int currentRunCode; + + int v_message = 1; + int v_warning = 2; + int v_error = 3; + int v_debug = 4; + + int matchedMRDNumber = 0; + int exeNum = 0; + + std::map>> MRDEvents; // Key: {MTCTime}, value: "WaveMap" with key (CardID,ChannelID), value FinishedWaveform + std::map MRDEventTriggerTypes; // Key: {MTCTime}, value: string noting what type of trigger occured for the event + std::map MRDBeamLoopback; // Key: {MTCTime}, value: string noting what type of trigger occured for the event + std::map MRDCosmicLoopback; // KEY: {MTCTime}, value: Cosmic loopback TDC value + + std::map>> MRDEventsBuffer; + + bool NewMRDDataAvailable; + + std::map> PairedCTCTimeStamps; + std::map> PairedMRD_TriggerIndex; + std::map> PairedMRDTimeStamps; + std::map MRDHitMapRunCode; // Key: {MTCTime}, value: RunCode + + bool matchToAllTriggers; + + int thisRunNum; + int exePerMatch; +}; + +#endif diff --git a/UserTools/EBMRD/README.md b/UserTools/EBMRD/README.md new file mode 100644 index 000000000..3aed04355 --- /dev/null +++ b/UserTools/EBMRD/README.md @@ -0,0 +1,35 @@ +# EBMRD + +EBMRD tool is a part of Event Building version 2 tool chain. +For reference slides, see: +https://annie-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=5633 + +EBMRD match the MRD timestamp to grouped trigger, and save the matching results to CStore for EBSaver. + +## Data + + +**PairedCTCTimeStamps** +After matching, the matched trigger timestamp will be saved here. The key is the main trigger word for each run type. +Saved as PairedMRDTriggerTimestamp in CStore. + +**PairedMRDTimeStamps** +After matching, the matched MRD timestamp will be saved here. The key is the main trigger word for each run type. +This and PairedCTCTimeStamps have the same index. A little bit dangerous, but overall works well. +Saved as PairedMRDTimeStamps in CStore + + +## Configuration + +**matchTargetTrigger** +This gives which trigger word that the MRD timestamps should be matched to. + +**matchTolerance_ns** +This gives the maximum allowed time tolerance between the MRD timestmap and the target trigger timestamp. + +**exePerMatch** +This gives how many loops need to be past for one matching between MRD timestmaps and target trigger timestamps. +500 is generally fine with beam runs. 100 would be better for AmBe runs + +**matchToAllTriggers** +1 or 0. 1 means match MRD timestamps to all possible triggers, 0 means only match to the target trigger. diff --git a/UserTools/Factory/Factory.cpp b/UserTools/Factory/Factory.cpp index c986c48b7..98ead3503 100644 --- a/UserTools/Factory/Factory.cpp +++ b/UserTools/Factory/Factory.cpp @@ -174,5 +174,6 @@ if (tool=="BackTracker") ret=new BackTracker; if (tool=="PrintDQ") ret=new PrintDQ; if (tool=="AssignBunchTimingMC") ret=new AssignBunchTimingMC; if (tool=="FitRWMWaveform") ret=new FitRWMWaveform; +if (tool=="EBMRD") ret=new EBMRD; return ret; } diff --git a/UserTools/Unity.h b/UserTools/Unity.h index 7e64d4e9b..372300682 100644 --- a/UserTools/Unity.h +++ b/UserTools/Unity.h @@ -182,3 +182,4 @@ #include "PrintDQ.h" #include "AssignBunchTimingMC.h" #include "FitRWMWaveform.h" +#include "EBMRD.h"