From 18db38f1587114a5221e5dcc9167eb0c3e3878c7 Mon Sep 17 00:00:00 2001 From: nathanielerowe <70993723+nathanielerowe@users.noreply.github.com> Date: Thu, 14 May 2026 16:30:30 -0500 Subject: [PATCH 1/3] Enhance BNBRetriever with new BeamFolder handling Updated BNBSpillInfo creation to include additional parameters and set epsilon values for new BeamFolder instances. --- .../BNBRetriever/BNBRetriever_module.cc | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/sbncode/BeamSpillInfoRetriever/BNBRetriever/BNBRetriever_module.cc b/sbncode/BeamSpillInfoRetriever/BNBRetriever/BNBRetriever_module.cc index 903d52873..028f5f6a5 100644 --- a/sbncode/BeamSpillInfoRetriever/BNBRetriever/BNBRetriever_module.cc +++ b/sbncode/BeamSpillInfoRetriever/BNBRetriever/BNBRetriever_module.cc @@ -26,6 +26,9 @@ #include "sbnobj/Common/POTAccounting/BNBSpillInfo.h" +#include "sbncode/BeamSpillInfoRetriever/POTTools.h" +#include "sbncode/BeamSpillInfoRetriever/getFOM.h" + #include "ifdh_art/IFBeamService/IFBeam_service.h" #include "ifbeam_c.h" #include "MWRData.h" @@ -130,6 +133,8 @@ class sbn::BNBRetriever : public art::EDProducer { // art::ServiceHandle ifbeam_handle; std::unique_ptr bfp; + std::unique_ptr offsets; + std::unique_ptr vp873; std::unique_ptr bfp_mwr; // @@ -260,6 +265,8 @@ sbn::BNBRetriever::BNBRetriever(Parameters const& params) raw_data_label(params().RawDataLabel()), fDeviceUsedForTiming(params().DeviceUsedForTiming()), bfp( ifbeam_handle->getBeamFolder(params().Bundle(), params().URL(), params().TimeWindow())), + vp873( ifbeam_handle->getBeamFolder(params().VP873Bundle(), params().URL(), params().TimeWindow())), + offsets( ifbeam_handle->getBeamFolder(params().OffsetBundle(), params().URL(), params().TimeWindow())), bfp_mwr( ifbeam_handle->getBeamFolder(params().MultiWireBundle(), params().URL(), params().MWR_TimeWindow())), fTriggerDatabaseFile(params().TriggerDatabaseFile()) { @@ -278,7 +285,9 @@ sbn::BNBRetriever::BNBRetriever(Parameters const& params) // bfp->set_epsilon(0.02); //20 ms, this was tuned by hand and compared to IFBeamDB times bfp_mwr->set_epsilon(0.5); - + vp873->set_epsilon(0.02); + offsets->set_epsilon(600); + //bfp_mwr->setValidWindow(86400); bfp_mwr->setValidWindow(3605); produces< std::vector< sbn::BNBSpillInfo >, art::InSubRun >(); @@ -633,8 +642,9 @@ int sbn::BNBRetriever::matchMultiWireData( }//end loop over MWR devices - sbn::BNBSpillInfo spillInfo = makeBNBSpillInfo(eventID, times_temps[i], MWRdata, matched_MWR); - + sbn::BNBSpillInfo spillInfo = sbn::pot::makeBNBSpillInfo(eventID, times_temps[i], MWRdata, matched_MWR, bfp, offsets, vp873); + double const spillFOM = sbn::getBNBqualityFOM(spillInfo); + spillInfo.FOM = spillFOM; beamInfos.push_back(std::move(spillInfo)); // We do not write these to the art::Events because From ab3bbb72306329ad3df2eecf18a09f283d356c67 Mon Sep 17 00:00:00 2001 From: nathanielerowe <70993723+nathanielerowe@users.noreply.github.com> Date: Thu, 14 May 2026 16:31:05 -0500 Subject: [PATCH 2/3] Add VP873Bundle and OffsetBundle to configuration --- sbncode/BeamSpillInfoRetriever/job/bnbspillinfo.fcl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sbncode/BeamSpillInfoRetriever/job/bnbspillinfo.fcl b/sbncode/BeamSpillInfoRetriever/job/bnbspillinfo.fcl index 3aece8658..4675b8664 100644 --- a/sbncode/BeamSpillInfoRetriever/job/bnbspillinfo.fcl +++ b/sbncode/BeamSpillInfoRetriever/job/bnbspillinfo.fcl @@ -8,6 +8,8 @@ bnbspillinfo: { URL: "" #keep this blank and we're good Bundle: "BoosterNeutrinoBeam_read" MultiWireBundle: "BNBMultiWire" + VP873Bundle: "BNB_monitor" + OffsetBundle: "BNB_BPM_settings" TimeWindow: "700" #seconds MWR_TimeWindow: "3601" #seconds raw_data_label: "daq" From f3dd7994e3f94223a46d982a4ddc5a6185e0122e Mon Sep 17 00:00:00 2001 From: Nathaniel Date: Mon, 18 May 2026 19:50:18 -0500 Subject: [PATCH 3/3] buildable version --- .../BNBEXTRetriever/CMakeLists.txt | 20 - .../BNBRetriever/BNBRetriever_module.cc | 821 ------------------ .../BNBRetriever/CMakeLists.txt | 34 - .../BNBRetriever/MWRData.cpp | 71 -- .../BNBRetriever/MWRData.h | 39 - sbncode/BeamSpillInfoRetriever/CMakeLists.txt | 19 +- .../ICARUSBNBEXTRetriever/CMakeLists.txt | 12 + .../ICARUSBNBEXTRetriever_module.cc} | 36 +- .../ICARUSBNBRetriever/CMakeLists.txt | 14 + .../ICARUSBNBRetriever_module.cc | 493 +++++++++++ .../{SBNDPOTTools.cpp => POTTools.cpp} | 153 ++-- sbncode/BeamSpillInfoRetriever/POTTools.h | 92 ++ .../SBNDBNBEXTRetriever/CMakeLists.txt | 2 +- .../SBNDBNBEXTRetriever_module.cc | 7 +- .../SBNDBNBRetriever/CMakeLists.txt | 2 +- .../SBNDBNBRetriever_module.cc | 33 +- .../SBNDBNBZEROBIASRetriever/CMakeLists.txt | 2 +- .../SBNDBNBZEROBIASRetriever_module.cc | 32 +- sbncode/BeamSpillInfoRetriever/SBNDPOTTools.h | 42 - 19 files changed, 775 insertions(+), 1149 deletions(-) delete mode 100644 sbncode/BeamSpillInfoRetriever/BNBEXTRetriever/CMakeLists.txt delete mode 100644 sbncode/BeamSpillInfoRetriever/BNBRetriever/BNBRetriever_module.cc delete mode 100644 sbncode/BeamSpillInfoRetriever/BNBRetriever/CMakeLists.txt delete mode 100644 sbncode/BeamSpillInfoRetriever/BNBRetriever/MWRData.cpp delete mode 100644 sbncode/BeamSpillInfoRetriever/BNBRetriever/MWRData.h create mode 100644 sbncode/BeamSpillInfoRetriever/ICARUSBNBEXTRetriever/CMakeLists.txt rename sbncode/BeamSpillInfoRetriever/{BNBEXTRetriever/BNBEXTRetriever_module.cc => ICARUSBNBEXTRetriever/ICARUSBNBEXTRetriever_module.cc} (83%) create mode 100644 sbncode/BeamSpillInfoRetriever/ICARUSBNBRetriever/CMakeLists.txt create mode 100644 sbncode/BeamSpillInfoRetriever/ICARUSBNBRetriever/ICARUSBNBRetriever_module.cc rename sbncode/BeamSpillInfoRetriever/{SBNDPOTTools.cpp => POTTools.cpp} (69%) create mode 100644 sbncode/BeamSpillInfoRetriever/POTTools.h delete mode 100644 sbncode/BeamSpillInfoRetriever/SBNDPOTTools.h diff --git a/sbncode/BeamSpillInfoRetriever/BNBEXTRetriever/CMakeLists.txt b/sbncode/BeamSpillInfoRetriever/BNBEXTRetriever/CMakeLists.txt deleted file mode 100644 index 1c49f8646..000000000 --- a/sbncode/BeamSpillInfoRetriever/BNBEXTRetriever/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ - -cet_build_plugin(BNBEXTRetriever art::module - LIBRARIES - art::Persistency_Common - art::Utilities canvas::canvas - cetlib::cetlib cetlib_except::cetlib_except - messagefacility::MF_MessageLogger - sbnobj::Common_POTAccounting - sbndaq_artdaq_core::sbndaq-artdaq-core_Overlays_Common - sbndaq_artdaq_core::sbndaq-artdaq-core_Overlays - sbndaq_artdaq_core::sbndaq-artdaq-core_Overlays_ICARUS - artdaq_core::artdaq-core_Utilities - lardata::Utilities - larcore::Geometry_AuxDetGeometry_service -) - -install_headers() -install_fhicl() -install_source() - diff --git a/sbncode/BeamSpillInfoRetriever/BNBRetriever/BNBRetriever_module.cc b/sbncode/BeamSpillInfoRetriever/BNBRetriever/BNBRetriever_module.cc deleted file mode 100644 index 028f5f6a5..000000000 --- a/sbncode/BeamSpillInfoRetriever/BNBRetriever/BNBRetriever_module.cc +++ /dev/null @@ -1,821 +0,0 @@ -/** ******************************************************************** - * @file BNBRetriever_module.cc - * @date Wed April 9 2021 - * @author J. Zennamo (FNAL) - * - * Based heavily on code by Z. Pavlovic written for MicroBooNE - * Based heavily on code by NOvA collaboration (Thanks NOvA!): - * https://cdcvs.fnal.gov/redmine/projects/novaart/repository/entry/trunk/IFDBSpillInfo/BNBInfo_module.cc - * Database implementation by Justin Mueller - */ - -#include "art/Framework/Core/EDProducer.h" -#include "art/Framework/Core/ModuleMacros.h" -#include "art/Framework/Principal/Event.h" -#include "art/Framework/Principal/Handle.h" -#include "art/Framework/Principal/Run.h" -#include "art/Framework/Principal/SubRun.h" -#include "canvas/Utilities/InputTag.h" -#include "fhiclcpp/types/Atom.h" -#include "messagefacility/MessageLogger/MessageLogger.h" -#include "larcorealg/CoreUtils/counter.h" - -#include "artdaq-core/Data/Fragment.hh" -#include "sbndaq-artdaq-core/Overlays/ICARUS/ICARUSTriggerV3Fragment.hh" -#include "sbnobj/Common/Trigger/ExtraTriggerInfo.h" - -#include "sbnobj/Common/POTAccounting/BNBSpillInfo.h" - -#include "sbncode/BeamSpillInfoRetriever/POTTools.h" -#include "sbncode/BeamSpillInfoRetriever/getFOM.h" - -#include "ifdh_art/IFBeamService/IFBeam_service.h" -#include "ifbeam_c.h" -#include "MWRData.h" - -#include -#include -#include - -#include -#include -#include - -namespace sbn { - class BNBRetriever; -} - -class sbn::BNBRetriever : public art::EDProducer { -public: - - struct Config { - - using Name = fhicl::Name; - using Comment = fhicl::Comment; - - fhicl::Atom TimePadding { - Name{ "TimePadding" }, - Comment{ "extension to the time window considered when collecting spills [seconds]" }, - 0.0333 // default - }; - - fhicl::Atom RawDataLabel { - Name{ "raw_data_label" }, - Comment{ "art data product instance name for trigger information (product label is 'daq')" } - }; - - fhicl::Atom DeviceUsedForTiming { - Name{ "DeviceUsedForTiming" }, - Comment{ "name in the IFBeam database of the device used to extract spill times" } - }; - - fhicl::Atom URL { - Name{ "URL" }, - Comment{ "IFBeam database access URL" } - }; - - fhicl::Atom Bundle { - Name{ "Bundle" }, - Comment{ "" } // explain what this is and which database/table it's looking for - }; - - fhicl::Atom TimeWindow { - Name{ "TimeWindow" }, - Comment{ "" } // explain what this is, what's for and its unit - }; - - fhicl::Atom MultiWireBundle { - Name{ "MultiWireBundle" }, - Comment{ "" } // explain what this is and which database/table it's looking for - }; - - fhicl::Atom MWR_TimeWindow { - Name{ "MWR_TimeWindow" }, - Comment{ "" } // explain what this is, what's for and its unit - }; - - fhicl::Atom TriggerDatabaseFile { - Name{ "TriggerDatabaseFile" }, - Comment{ "" } // explain what this is, what's for and its unit - }; - - - }; // Config - - using Parameters = art::EDProducer::Table; - - - explicit BNBRetriever(Parameters const& params); - // The compiler-generated destructor is fine for non-base - // classes without bare pointers or other resource use. - - // Plugins should not be copied or assigned. - BNBRetriever(BNBRetriever const&) = delete; - BNBRetriever(BNBRetriever&&) = delete; - BNBRetriever& operator=(BNBRetriever const&) = delete; - BNBRetriever& operator=(BNBRetriever&&) = delete; - - // Required functions. - void produce(art::Event& e) override; - void beginSubRun(art::SubRun& sr) override; - void endSubRun(art::SubRun& sr) override; - -private: - // input labels - std::vector< sbn::BNBSpillInfo > fOutbeamInfos; - double fTimePad; - std::string fURL; - MWRData mwrdata; - int run_number; - std::string raw_data_label; - std::string fDeviceUsedForTiming; - unsigned int TotalBeamSpills; - // - art::ServiceHandle ifbeam_handle; - std::unique_ptr bfp; - std::unique_ptr offsets; - std::unique_ptr vp873; - std::unique_ptr bfp_mwr; - - // - std::string fTriggerDatabaseFile; - sqlite3 *db; - int rc; - - struct TriggerInfo_t { - int gate_type = 0; ///< Source of the spill: `1`: BNB, `2`: NuMI - double t_current_event = 0; - double t_previous_event = 0; - unsigned int number_of_gates_since_previous_event = 0; // FIXME needs to be integral type - std::int64_t WR_to_Spill_conversion = 0; - }; - - struct MWRdata_t { - std::vector< std::vector > MWR_times; - std::vector< std::vector< std::vector< int > > > unpacked_MWR; - }; - - - static constexpr double MWRtoroidDelay = -0.035; ///< the same time point is measured _t_ by MWR and _t + MWRtoroidDelay`_ by the toroid [ms] - - /// Returns the information of the trigger in the current event. - TriggerInfo_t extractTriggerInfo(art::Event const& e) const; - - /** - * @brief Determines spill times and extracts data based on multiwire devices. - * @param triggerInfo information from the trigger of this event - * @return times and unpacked data, per device (`"M875BB"`, `"M876BB"`, `"MMBTBB"`) - */ - MWRdata_t extractSpillTimes(TriggerInfo_t const& triggerInfo) const; - - /** - * @brief Matches spill times with multiwire chamber data from the database. - * @param eventID ID of the event the information is associated to - * @param triggerInfo information from the trigger of this event - * @param MWRdata data from multiwire chambers - * @param isFirstEventInRun whether we are processing the first event of the run - * @param[out] beamInfos container to _add_ spill information records to - * @return count of matched spills - */ - int matchMultiWireData( - art::EventID const& eventID, - TriggerInfo_t const& triggerInfo, - MWRdata_t const& MWRdata, bool isFirstEventInRun, - std::vector< sbn::BNBSpillInfo >& beamInfos - ) const; - - /** - * @brief Assembles and returns a spill information record. - * @param eventID ID of the event the information is associated to - * @param time time of the spill - * @param MWRdata all extracted data from multiwire chambers - * @param matched_MWR data from multiwire chambers matched with the time - * @return a `sbn::BNBSpillInfo` object with information on the spill at `time` - */ - sbn::BNBSpillInfo makeBNBSpillInfo - (art::EventID const& eventID, double time, MWRdata_t const& MWRdata, std::vector const& matched_MWR) const; - -/** - * @brief SQLite callback function for retrieving trigger_type from a query. - * @param data Pointer to the integer where the trigger type will be stored. - * @param argc Count of the number of columns returned by the query. - * @param argv Array of c-strings containing the column data of the query. - * @param columns Array of c-strings listing the names of the columns. - * @return 0 if successful. - */ -// int callback_trigger_type(void *data, -// int argc, -// char **argv, -// char **columns); - -/** - * @brief Queries the trigger database and finds the trigger_type of the matching trigger (if any). - * @param db The pointer to the SQLite database instance. - * @param run The run number of the current event (helps with queries). - * @param gate_time The time in milliseconds of the gate. - * @param threshold The required absolute time difference between gate and trigger. - * @return trigger_type -1: No matching trigger, 0: Majority, 1: MinBias - */ - int get_trigger_type_matching_gate(sqlite3 *db, - int func(void*,int,char**,char**), - int run, - long long int gate_time, - float threshold) const; - -}; - -int callback_trigger_type(void *data, int argc, char **argv, char **columns) -{ - int *result = static_cast(data); - // Does this query return non-NULL values? - if(argc > 0 && argv[0]) - *result = std::stoi(argv[0]); - else - *result = -1; - - return 0; -} - -int sbn::BNBRetriever::get_trigger_type_matching_gate(sqlite3 *db, int func(void*,int,char**,char**), int run, long long int gate_time, float threshold) const -{ - int trigger_type(-1), query_status; - std::stringstream query; - query << "SELECT trigger_type FROM triggerdata WHERE gate_type=1 AND run_number =" - << run - << " AND ABS(1000000000*wr_seconds + wr_nanoseconds - " - << std::fixed << gate_time - << ") < " - << threshold*1000000 - << " ORDER BY ABS(1000000000*wr_seconds + wr_nanoseconds - " - << std::fixed << gate_time - << ") LIMIT 1;"; - - query_status = sqlite3_exec(db, query.str().c_str(), func, &trigger_type, NULL); - if (query_status != SQLITE_OK) - { - mf::LogError("BNBEXTRetriever") << "SQL error: " << sqlite3_errmsg(db); - trigger_type = -1; - } - return trigger_type; -} - -sbn::BNBRetriever::BNBRetriever(Parameters const& params) - : EDProducer{params}, - fTimePad(params().TimePadding()), - raw_data_label(params().RawDataLabel()), - fDeviceUsedForTiming(params().DeviceUsedForTiming()), - bfp( ifbeam_handle->getBeamFolder(params().Bundle(), params().URL(), params().TimeWindow())), - vp873( ifbeam_handle->getBeamFolder(params().VP873Bundle(), params().URL(), params().TimeWindow())), - offsets( ifbeam_handle->getBeamFolder(params().OffsetBundle(), params().URL(), params().TimeWindow())), - bfp_mwr( ifbeam_handle->getBeamFolder(params().MultiWireBundle(), params().URL(), params().MWR_TimeWindow())), - fTriggerDatabaseFile(params().TriggerDatabaseFile()) -{ - - // Check fTimePad is positive - if (fTimePad < 0) { - throw art::Exception(art::errors::Configuration) - << "Parameter `TimePadding` must be non-negative (" << fTimePad << " was specified).\n"; - }//End Time check - - // how close in time does the spill time have to be from the DAQ time (in seconds). - // If these are too large then it fails to capture the device - // If these are too small then the time jitter in devices means we miss good data - // - // These values should likely not be changed unless authors of the IFBeam API are consulted - // - bfp->set_epsilon(0.02); //20 ms, this was tuned by hand and compared to IFBeamDB times - bfp_mwr->set_epsilon(0.5); - vp873->set_epsilon(0.02); - offsets->set_epsilon(600); - - //bfp_mwr->setValidWindow(86400); - bfp_mwr->setValidWindow(3605); - produces< std::vector< sbn::BNBSpillInfo >, art::InSubRun >(); - TotalBeamSpills = 0; - - cet::search_path sp("FW_SEARCH_PATH"); - std::string trigDB_path = sp.find_file(fTriggerDatabaseFile.c_str()); - - rc = sqlite3_open(trigDB_path.c_str(), &db); - if(rc) - { - fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); - throw art::Exception(art::errors::NotFound) - << "Can't open database: " << sqlite3_errmsg(db); - } - -} - - -void sbn::BNBRetriever::produce(art::Event& e) -{ - - // If this is the first event in the run, then ignore it - // We do not currently have the ability to figure out the first - // spill that the DAQ was sensitive to, so don't try to save any - // spill information - // - // TODO: long-term goal -- can we fix this? - // FIXME This is wrong.... - // Need to use: ICARUSTriggerV3Fragment long getTotalTriggerBNBMaj() const - - if (e.event() == 1) return; - - run_number = e.id().run(); - - TriggerInfo_t const triggerInfo = extractTriggerInfo(e); - - //We only want to process BNB gates, i.e. type 1 - if(triggerInfo.gate_type != 1) return; - // Keep track of the number of beam gates the DAQ thinks - // are in this job - TotalBeamSpills += triggerInfo.number_of_gates_since_previous_event; - - - MWRdata_t const MWRdata = extractSpillTimes(triggerInfo); - - - int const spill_count = matchMultiWireData(e.id(), triggerInfo, MWRdata, e.event() == 1, fOutbeamInfos); - - - if(spill_count > int(triggerInfo.number_of_gates_since_previous_event)) - mf::LogDebug("BNBRetriever")<< "Event Spills : " << spill_count << ", DAQ Spills : " << triggerInfo.number_of_gates_since_previous_event << " \t \t ::: WRONG!"<< std::endl; - else - mf::LogDebug("BNBRetriever")<< "Event Spills : " << spill_count << ", DAQ Spills : " << triggerInfo.number_of_gates_since_previous_event << std::endl; - -}//end iteration over art::Events - - -sbn::BNBRetriever::TriggerInfo_t sbn::BNBRetriever::extractTriggerInfo(art::Event const& e) const { - - //Here we read in the artdaq Fragments and extract three pieces of information: - // 1. The time of the current event, t_current_event - // 2. the time of the previously triggered event, t_previous_event (NOTE: Events are non-sequential!) - // 3. the number of beam spills since the previously triggered event, number_of_gates_since_previous_event - - auto const & raw_data = e.getProduct< std::vector >({ raw_data_label, "ICARUSTriggerV3" }); - auto const & extraTrigInfo = e.getProduct< sbn::ExtraTriggerInfo >("daqTrigger"); - - TriggerInfo_t triggerInfo; - - triggerInfo.WR_to_Spill_conversion = extraTrigInfo.WRtimeToTriggerTime; - - for(auto raw_datum : raw_data){ - - uint64_t artdaq_ts = raw_datum.timestamp(); - icarus::ICARUSTriggerV3Fragment frag(raw_datum); - std::string data = frag.GetDataString(); - char *buffer = const_cast(data.c_str()); - icarus::ICARUSTriggerInfo datastream_info = icarus::parse_ICARUSTriggerV3String(buffer); - triggerInfo.gate_type = datastream_info.gate_type; - triggerInfo.number_of_gates_since_previous_event = frag.getDeltaGatesBNBMaj(); - - /* - The DAQ trigger time is issued at the Beam Extraction Signal (BES) which is issued - 36 ms *after* the $1D of the BNB, which is what is used in the IFBeam database - - We subtract 36ms from the Trigger time to match our triggers to the spills in the - IFBeam database - - */ - - triggerInfo.t_current_event = static_cast(artdaq_ts-3.6e7)/(1000000000.0); //check this offset... - if(triggerInfo.gate_type == 1) - triggerInfo.t_previous_event = (static_cast(frag.getLastTimestampBNBMaj()-3.6e7))/(1e9); - else - triggerInfo.t_previous_event = (static_cast(frag.getLastTimestampOther()-3.6e7))/(1000000000.0); - - } - - mf::LogDebug("BNBRetriever") << std::setprecision(19) << "Previous : " << triggerInfo.t_previous_event << ", Current : " << triggerInfo.t_current_event << ", Spill Count " << triggerInfo.number_of_gates_since_previous_event << std::endl; - - return triggerInfo; -} - - -sbn::BNBRetriever::MWRdata_t sbn::BNBRetriever::extractSpillTimes(TriggerInfo_t const& triggerInfo) const { - - // These lines get everything primed within the IFBeamDB - // They seem redundant but they are needed - // try{auto cur_vec_temp = bfp->GetNamedVector((triggerInfo.t_previous_event)-fTimePad,"E:THCURR");} catch (WebAPIException &we) {} - try{auto cur_vec_temp = bfp->GetNamedVector((triggerInfo.t_current_event)+fTimePad,"E:THCURR");} catch (WebAPIException &we) {} - try{auto packed_M876BB_temp = bfp_mwr->GetNamedVector((triggerInfo.t_current_event)+fTimePad,"E:M875BB{4440:888}.RAW");} catch (WebAPIException &we) {} - - //The multiwire chambers provide their - // data in a vector format but we'll have - // to sort through it in std::string format - // to correctly unpack it - std::vector< std::vector< std::vector< int > > > unpacked_MWR; - std::vector< std::vector< double> > MWR_times; - unpacked_MWR.resize(3); - MWR_times.resize(3); - std::string packed_data_str; - - //Create a list of all the MWR devices with their different - // memory buffer increments - // generally in the format: "E:.{Memory Block}" - std::vector vars = bfp_mwr->GetDeviceList(); - mf::LogDebug("BNBRetriever") << " Number of MWR Device Blocks Found : " << vars.size() << std::endl; - // Tracking the time from the IFBeamDB - double time_for_mwr; - - // this is an iterator to track which of the - // three devices we will be working with - int dev = 0; - - // The MWR devices are annoying and have confusing buffer - // what we'll do is sort through all of them first and then - // match them to the closest spills in time - // - - // int t_steps = int(((triggerInfo.t_previous_event - fTimePad) - (triggerInfo.t_current_event + fTimePad))/0.5)+25; - int t_steps = int(((triggerInfo.t_current_event + fTimePad) - (triggerInfo.t_previous_event - fTimePad - 20.))/0.5)+25; - mf::LogDebug("BNBRetriever") << " t_steps " << t_steps << std::endl; - - for(int t = 0; t < t_steps; t++){//Iterate through time increments - for (std::string const& var : vars) {// Iterate through the devices - - //Make sure we have a device - if(var.empty()){ - //mf::LogDebug("BNBRetriever") << " NO MWR DEVICES?!" << std::endl; - continue; - } - /// Check the device name and interate the double-vector index - if(var.find("M875BB") != std::string::npos ) dev = 0; - else if(var.find("M876BB") != std::string::npos ) dev = 1; - else if(var.find("MMBTBB") != std::string::npos ) dev = 2; - else{ - //mf::LogDebug("BNBRetriever") << " NOT matched to a MWR DEVICES?!" << var << std::endl; - continue;} - - time_for_mwr = 0; - - try{ - //Pull the MWR data for the device - // these data are "packed" - std::vector packed_MWR = bfp_mwr->GetNamedVector((triggerInfo.t_previous_event)-20.-fTimePad+double(0.5*t),var,&time_for_mwr); - - //We'll convert this into a format - // that we can unpack doubles >> strings - // - packed_data_str.clear(); - packed_data_str += std::to_string(int(time_for_mwr)); - packed_data_str.append(","); - packed_data_str.append(var); - packed_data_str.append(",,"); - - /* for(auto const value: packed_MWR){ - packed_data_str += ','; - packed_data_str += std::to_string(int(value)); - }*/ - for(int j = 0; j < int(packed_MWR.size()); j++){ - packed_data_str += std::to_string(int(packed_MWR[j])); - if(j < int(packed_MWR.size())-1) - packed_data_str.append(","); - } - - // Use Zarko's unpacking function to turn this into consumeable data - std::vector MWR_times_temp; - - // There is a 35 ms offset between the toriod and the MWR times - // we'll just remove that here to match to the spill times - std::vector< std::vector< int > > unpacked_MWR_temp = mwrdata.unpackMWR(packed_data_str,MWR_times_temp,MWRtoroidDelay); - - //There are four events that are packed into one MWR IFBeam entry - for(std::size_t s: util::counter(unpacked_MWR_temp.size())){ - - // If this entry has a unique time them store it for later - if(std::find(MWR_times[dev].begin(), MWR_times[dev].end(), MWR_times_temp[s]) == MWR_times[dev].end()){ - unpacked_MWR[dev].push_back(unpacked_MWR_temp[s]); - MWR_times[dev].push_back(MWR_times_temp[s]); - }//check for unique time - }//Iterate through the unpacked events - }//try - catch (WebAPIException &we) { - //Ignore when we can't find the MWR devices - // they don't always report and the timing of them can be annoying - - }//catch - }// Iterate over all the multiwire devices - }// Iterate over all times - - mf::LogDebug("BNBRetriever") << " Number of MWR[0] times : " << MWR_times[0].size() << std::endl; - mf::LogDebug("BNBRetriever") << " Number of MWR[0]s : " << unpacked_MWR[0].size() << std::endl; - mf::LogDebug("BNBRetriever") << " Number of MWR[1] times : " << MWR_times[1].size() << std::endl; - mf::LogDebug("BNBRetriever") << " Number of MWR[1]s : " << unpacked_MWR[1].size() << std::endl; - mf::LogDebug("BNBRetriever") << " Number of MWR[2] times : " << MWR_times[2].size() << std::endl; - mf::LogDebug("BNBRetriever") << " Number of MWR[2]s : " << unpacked_MWR[2].size() << std::endl; - - return { std::move(MWR_times), std::move(unpacked_MWR) }; -} - - -int sbn::BNBRetriever::matchMultiWireData( - art::EventID const& eventID, - TriggerInfo_t const& triggerInfo, - MWRdata_t const& MWRdata, bool isFirstEventInRun, - std::vector< sbn::BNBSpillInfo >& beamInfos -) const { - - auto const& [ MWR_times, unpacked_MWR ] = MWRdata; // alias - - //Here we will start collecting all the other beamline devices - // First we get the times that the beamline device fired - // we have to pick a specific variable to use - std::vector times_temps = bfp->GetTimeList(fDeviceUsedForTiming); - - mf::LogDebug("BNBRetriever") << "matchMultiWireData:: Number of time spills : " << times_temps.size() << std::endl; - - // We'll keep track of how many of these spills match to our - // DAQ trigger times - int spill_count = 0; - int spills_removed = 0; - std::vector matched_MWR; - matched_MWR.resize(3); - - - // NOTE: for now, this is dead code because we don't - // do anything for the first event in a run. We may want to revisit - // this later to understand if there is a way we can do the POT - // accounting in the first event. - // - // Need to handle the first event in a run differently - if(isFirstEventInRun){ - - //We'll remove the spills after our event - int spills_after_our_target = 0; - // iterate through all the spills to find the - // spills that are after our triggered event - for (size_t i = 0; i < times_temps.size(); i++) { - if(times_temps[i] > (triggerInfo.t_current_event+fTimePad)){ - spills_after_our_target++; - } - }//end loop through spill times - - // Remove the spills after our trigger - times_temps.erase(times_temps.end()-spills_after_our_target,times_temps.end()); - - // Remove the spills before the start of our Run - times_temps.erase(times_temps.begin(), times_temps.end() - std::min(int(triggerInfo.number_of_gates_since_previous_event), int(times_temps.size()))); - - }//end fix for "first event" - - ///reject time_stamps which have a trigger_type == 1 from data-base - //To-Do - - // mf::LogDebug("BNBRetriever") << "Total number of Times we're going to test: " << times_temps.size() << std::endl; - // mf::LogDebug("BNBRetriever") << std::setprecision(19) << "Upper Limit : " << (triggerInfo.t_current_event)+fTimePad << std::endl; - // mf::LogDebug("BNBRetriever") << std::setprecision(19) << "Lower Limit : " << (triggerInfo.t_previous_event)+fTimePad << std::endl; - - // Iterating through each of the beamline times - for (size_t i = 0; i < times_temps.size(); i++) { - - // Only continue if these times are matched to our DAQ time - //mf::LogDebug("BNBRetriever") << std::setprecision(19) << "Time # : " << i << std::endl; - - if(!isFirstEventInRun){//We already addressed the "first event" above - if(times_temps[i] > (triggerInfo.t_current_event)+fTimePad){ - //mf::LogDebug("BNBRetriever") << std::setprecision(19) << "Removed! : " << times_temps[i] << std::endl; - spills_removed++; - continue;} - if(times_temps[i] <= (triggerInfo.t_previous_event)+fTimePad){ - spills_removed++; - //mf::LogDebug("BNBRetriever") << std::setprecision(19) << "Removed! : " << times_temps[i] << std::endl; - continue;} - } - - //check if this spill is is minbias - /* - 40 ms was selected to be close to but outside the 66 ms - time of the next spill (when the beam is running at 15 Hz) - DocDB 33155 provides documentation of this - */ - - mf::LogDebug("BNBRetriever") << std::setprecision(19) << "matchMultiWireData:: trigger type : " << get_trigger_type_matching_gate(db, callback_trigger_type, run_number, times_temps[i]*1.e9-triggerInfo.WR_to_Spill_conversion+3.6e7, 40.) << " times : spill " << times_temps[i]*1.e9 << " - " << triggerInfo.WR_to_Spill_conversion << " + " << 3.6e7 << std::endl; - - if(get_trigger_type_matching_gate(db, callback_trigger_type, run_number, times_temps[i]*1.e9-triggerInfo.WR_to_Spill_conversion+3.6e7, 40.) == 1){ - mf::LogDebug("BNBRetriever") << std::setprecision(19) << "matchMultiWireData:: Skipped a MinBias gate at : " << times_temps[i]*1000. << std::endl; - - continue; - } - - //Great we found a matched spill! Let's count it - spill_count++; - - //Loop through the multiwire devices: - - for(int dev = 0; dev < int(MWR_times.size()); dev++){ - - //Loop through the multiwire times: - double Tdiff = 1000000000.; - matched_MWR[dev] = 0; - - for(int mwrt = 0; mwrt < int(MWR_times[dev].size()); mwrt++){ - - //found a candidate match! - if(fabs((MWR_times[dev][mwrt] - times_temps[i])) >= Tdiff){continue;} - - bool best_match = true; - - //Check for a better match... - for (size_t j = 0; j < times_temps.size(); j++) { - if( j == i) continue; - if(times_temps[j] > (triggerInfo.t_current_event+fTimePad)){continue;} - if(times_temps[j] <= (triggerInfo.t_previous_event+fTimePad)){continue;} - - //is there a better match later in the spill sequence - if(fabs((MWR_times[dev][mwrt] - times_temps[j])) < - fabs((MWR_times[dev][mwrt] - times_temps[i]))){ - //we can have patience... - best_match = false; - break; - } - }//end better match check - - //Verified best match! - if(best_match == true){ - matched_MWR[dev] = mwrt; - Tdiff = fabs((MWR_times[dev][mwrt] - times_temps[i])); - } - - }//end loop over MWR times - - }//end loop over MWR devices - - sbn::BNBSpillInfo spillInfo = sbn::pot::makeBNBSpillInfo(eventID, times_temps[i], MWRdata, matched_MWR, bfp, offsets, vp873); - double const spillFOM = sbn::getBNBqualityFOM(spillInfo); - spillInfo.FOM = spillFOM; - beamInfos.push_back(std::move(spillInfo)); - - // We do not write these to the art::Events because - // we can filter events but want to keep all the POT - // information, so we'll write it to the SubRun - - }//end iteration over beam device times - - // mf::LogDebug("BNBRetriever") << "matchMultiWireData:: Total spills counted: " << spill_count << " Total spills removed : " << spills_removed << std::endl; - - return spill_count; -} - - -sbn::BNBSpillInfo sbn::BNBRetriever::makeBNBSpillInfo - (art::EventID const& eventID, double time, MWRdata_t const& MWRdata, std::vector const& matched_MWR) const -{ - - auto const& [ MWR_times, unpacked_MWR ] = MWRdata; // alias - - // initializing all of our device carriers - // device definitions can be found in BNBSpillInfo.h - - double TOR860 = 0; // units e12 protons - double TOR875 = 0; // units e12 protons - double LM875A = 0; // units R/s - double LM875B = 0; // units R/s - double LM875C = 0; // units R/s - double HP873 = 0; // units mm - double VP873 = 0; // units mm - double HP875 = 0; // units mm - double VP875 = 0; // units mm - double HPTG1 = 0; // units mm - double VPTG1 = 0; // units mm - double HPTG2 = 0; // units mm - double VPTG2 = 0; // units mm - double BTJT2 = 0; // units Deg C - double THCURR = 0; // units kiloAmps - double M875HS = 0; // units mm - double M875VS = 0; // units mm - double M875HM = 0; // units mm - double M875VM = 0; // units mm - double M876HS = 0; // units mm - double M876VS = 0; // units mm - double M876HM = 0; // units mm - double M876VM = 0; // units mm - - double TOR860_time = 0; // units s - - // Here we request all the devices - // since sometimes devices fail to report we'll - // allow each to throw an exception but still move forward - // interpreting these failures will be part of the beam quality analyses - try{bfp->GetNamedData(time, "E:TOR860@",&TOR860,&TOR860_time);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:TOR875",&TOR875);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:LM875A",&LM875A);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:LM875B",&LM875B);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:LM875C",&LM875C);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:HP873",&HP873);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:VP873",&VP873);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:HP875",&HP875);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:VP875",&VP875);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:HPTG1",&HPTG1);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:VPTG1",&VPTG1);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:HPTG2",&HPTG2);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:VPTG2",&VPTG2);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:BTJT2",&BTJT2);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:THCURR",&THCURR);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:M875HS",&M875HS);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:M875VS",&M875VS);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:M875HM",&M875HM);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:M875VM",&M875VM);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:M876HS",&M876HS);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:M876VS",&M876VS);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:M876HM",&M876HM);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:M876VM",&M876VM);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - - //crunch the times - unsigned long int time_closest_int = (int) TOR860_time; - double time_closest_ns = (TOR860_time - time_closest_int)*1e9; - - //Store everything in our data-product - sbn::BNBSpillInfo beamInfo; - beamInfo.TOR860 = TOR860*1e12; //add in factor of 1e12 protons to get correct POT units - beamInfo.TOR875 = TOR875*1e12; //add in factor of 1e12 protons to get correct POT units - beamInfo.LM875A = LM875A; - beamInfo.LM875B = LM875B; - beamInfo.LM875C = LM875C; - beamInfo.HP873 = HP873; - beamInfo.VP873 = VP873; - beamInfo.HP875 = HP875; - beamInfo.VP875 = VP875; - beamInfo.HPTG1 = HPTG1; - beamInfo.VPTG1 = VPTG1; - beamInfo.HPTG2 = HPTG2; - beamInfo.VPTG2 = VPTG2; - beamInfo.BTJT2 = BTJT2; - beamInfo.THCURR = THCURR; - beamInfo.M875HS = M875HS; - beamInfo.M875VS = M875VS; - beamInfo.M875HM = M875HM; - beamInfo.M875VM = M875VM; - beamInfo.M876HS = M876HS; - beamInfo.M876VS = M876VS; - beamInfo.M876HM = M876HM; - beamInfo.M876VM = M876VM; - beamInfo.spill_time_s = time_closest_int; - beamInfo.spill_time_ns = time_closest_ns; - - for(auto const& MWRdata: unpacked_MWR){ - std::ignore = MWRdata; - assert(!MWRdata.empty()); - } - - if(unpacked_MWR[0].empty()){ - beamInfo.M875BB.clear(); - beamInfo.M875BB_spill_time_diff = -999;//units in seconds - } - else{ - beamInfo.M875BB = unpacked_MWR[0][matched_MWR[0]]; - beamInfo.M875BB_spill_time_diff = (MWR_times[0][matched_MWR[0]] - time); - } - - if(unpacked_MWR[1].empty()){ - beamInfo.M876BB.clear(); - beamInfo.M876BB_spill_time_diff = -999;//units in seconds - } - else{ - beamInfo.M876BB = unpacked_MWR[1][matched_MWR[1]]; - beamInfo.M876BB_spill_time_diff = (MWR_times[1][matched_MWR[1]] - time); - } - - if(unpacked_MWR[2].empty()){ - beamInfo.MMBTBB.clear(); - beamInfo.MMBTBB_spill_time_diff = -999;//units in seconds - } - else{ - beamInfo.MMBTBB = unpacked_MWR[2][matched_MWR[2]]; - beamInfo.MMBTBB_spill_time_diff = (MWR_times[2][matched_MWR[2]] - time); - } - // We do not write these to the art::Events because - // we can filter events but want to keep all the POT - // information, so we'll write it to the SubRun - - beamInfo.event = eventID.event(); // the rest of ID is known by art::SubRun - - return beamInfo; -} - - -void sbn::BNBRetriever::beginSubRun(art::SubRun& sr) -{ - return; -} - -//____________________________________________________________________________ -void sbn::BNBRetriever::endSubRun(art::SubRun& sr) -{ - // We will add all of the BNBSpillInfo data-products to the - // art::SubRun so it persists - // currently this is ~2.7 kB/event or ~0.07 kB/spill - -mf::LogDebug("BNBRetriever")<< "Total number of DAQ Spills : " << TotalBeamSpills << std::endl; -mf::LogDebug("BNBRetriever")<< "Total number of Selected Spills : " << fOutbeamInfos.size() << std::endl; - - auto p = std::make_unique< std::vector< sbn::BNBSpillInfo > >(); - std::swap(*p, fOutbeamInfos); - - sr.put(std::move(p), art::subRunFragment()); - - return; -} - -DEFINE_ART_MODULE(sbn::BNBRetriever) diff --git a/sbncode/BeamSpillInfoRetriever/BNBRetriever/CMakeLists.txt b/sbncode/BeamSpillInfoRetriever/BNBRetriever/CMakeLists.txt deleted file mode 100644 index a34b60d6a..000000000 --- a/sbncode/BeamSpillInfoRetriever/BNBRetriever/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -find_package(ifbeam) -find_package(ifdh_art) - - -art_make_library(LIBRARIES Boost::system - LIBRARY_NAME sbn_BNBSpillInfoRetriever_MWRData - SOURCE MWRData.cpp -) - - -cet_build_plugin(BNBRetriever art::module - LIBRARIES - art::Persistency_Common - art::Utilities canvas::canvas - cetlib::cetlib cetlib_except::cetlib_except - ROOT::X3d - Boost::system - messagefacility::MF_MessageLogger - ifbeam::ifbeam - ifdh_art::IFBeam_service - SQLite::SQLite3 - sbndaq_artdaq_core::sbndaq-artdaq-core_Overlays_Common - sbndaq_artdaq_core::sbndaq-artdaq-core_Overlays - sbndaq_artdaq_core::sbndaq-artdaq-core_Overlays_ICARUS - artdaq_core::artdaq-core_Utilities - sbn_BNBSpillInfoRetriever_MWRData - sbnobj::Common_POTAccounting - larcorealg::CoreUtils -) - -install_headers() -install_fhicl() -install_source() - diff --git a/sbncode/BeamSpillInfoRetriever/BNBRetriever/MWRData.cpp b/sbncode/BeamSpillInfoRetriever/BNBRetriever/MWRData.cpp deleted file mode 100644 index 48d0bda3f..000000000 --- a/sbncode/BeamSpillInfoRetriever/BNBRetriever/MWRData.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "MWRData.h" - -using namespace std; - -namespace sbn{ - - std::vector< std::vector < int > > MWRData::unpackMWR(std::string packed_data, std::vector &time_stamp, double timeoffset) const -{ - - std::vector > unpacked_data; - unpacked_data.resize(4); - short data[444]; - - std::vector row(0); - boost::split(row, packed_data, boost::is_any_of(",")); - if (row.size()==447) { - for (int i=3;i<447;i++) { - data[i-3]=atoi(row[i].c_str()); - } - string devname=row[1].substr(0,8); - for (int idev=0;idev<4;idev++) { - mwrpulse_t mwr=getMWRdata(data,idev); - time_stamp.push_back(mwr.sheader.timesec+mwr.sheader.timensec/1000000000.+timeoffset); - for (int ich=0;ich<48;ich++) { - unpacked_data[idev].push_back(mwr.hor[ich]); - } - for (int ich=0;ich<48;ich++) { - unpacked_data[idev].push_back(mwr.ver[ich]); - } - } - } else { - cout <<"BeamSpillInfoRetriever: MRWData: Bad data!"< -namespace sbn{ -class MWRData -{ - typedef struct swicheader_t { - long timesec; - long timensec; - long gpstime1; - long gpstime2; - short boosterevent; - short mievent; - short hz15micnt; - long delta1f; - short pulsemi; - short pulsesc; - } swicheader_t; - - typedef struct mwrpulse_t { - short hor[48]; - short ver[48]; - swicheader_t sheader; - } mwrpulse_t; - - static long flipByte(long data) - { - return ((data>>16)&0x0000FFFF) | ((data<<16)&0xFFFF0000); - } - - mwrpulse_t getMWRdata(short* data, int nblock) const; - - public: - std::vector< std::vector < int > > unpackMWR(std::string packed_data, std::vector &time_stamp, double timeoffset=0) const; -}; -} - -#endif /* #ifndef _MWRDATA_H */ diff --git a/sbncode/BeamSpillInfoRetriever/CMakeLists.txt b/sbncode/BeamSpillInfoRetriever/CMakeLists.txt index 1ba5595c9..5332b931d 100644 --- a/sbncode/BeamSpillInfoRetriever/CMakeLists.txt +++ b/sbncode/BeamSpillInfoRetriever/CMakeLists.txt @@ -1,15 +1,20 @@ -add_subdirectory(BNBRetriever) +find_package(ifbeam) +find_package(ifdh_art) + +include_directories( + ${IFBEAM_FQ_DIR}/include + ${IFDH_ART_INC} +) + add_subdirectory(SBNDBNBRetriever) add_subdirectory(SBNDBNBZEROBIASRetriever) add_subdirectory(SBNDBNBEXTRetriever) add_subdirectory(NuMIRetriever) -add_subdirectory(BNBEXTRetriever) add_subdirectory(NuMIEXTRetriever) +add_subdirectory(ICARUSBNBEXTRetriever) +add_subdirectory(ICARUSBNBRetriever) add_subdirectory(job) -find_package(ifbeam) -find_package(ifdh_art) - art_make_library(LIBRARIES Boost::system LIBRARY_NAME sbn_MWRData SOURCE MWRData.cpp @@ -28,8 +33,8 @@ art_make_library( sbn_MWRData larcorealg::CoreUtils - LIBRARY_NAME sbn_SBNDPOTTools - SOURCE SBNDPOTTools.cpp + LIBRARY_NAME sbn_POTTools + SOURCE POTTools.cpp ) art_make_library( diff --git a/sbncode/BeamSpillInfoRetriever/ICARUSBNBEXTRetriever/CMakeLists.txt b/sbncode/BeamSpillInfoRetriever/ICARUSBNBEXTRetriever/CMakeLists.txt new file mode 100644 index 000000000..416f70c33 --- /dev/null +++ b/sbncode/BeamSpillInfoRetriever/ICARUSBNBEXTRetriever/CMakeLists.txt @@ -0,0 +1,12 @@ +find_package(ifbeam) +find_package(ifdh_art) + +cet_build_plugin(ICARUSBNBEXTRetriever art::module + LIBRARIES + sbn_POTTools +) + +install_headers() +install_fhicl() +install_source() + diff --git a/sbncode/BeamSpillInfoRetriever/BNBEXTRetriever/BNBEXTRetriever_module.cc b/sbncode/BeamSpillInfoRetriever/ICARUSBNBEXTRetriever/ICARUSBNBEXTRetriever_module.cc similarity index 83% rename from sbncode/BeamSpillInfoRetriever/BNBEXTRetriever/BNBEXTRetriever_module.cc rename to sbncode/BeamSpillInfoRetriever/ICARUSBNBEXTRetriever/ICARUSBNBEXTRetriever_module.cc index 14ea73741..96674365f 100644 --- a/sbncode/BeamSpillInfoRetriever/BNBEXTRetriever/BNBEXTRetriever_module.cc +++ b/sbncode/BeamSpillInfoRetriever/ICARUSBNBEXTRetriever/ICARUSBNBEXTRetriever_module.cc @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////////////////// -// Class: BNBEXTRetriever +// Class: ICARUSBNBEXTRetriever // Plugin Type: producer -// File: BNBEXTRetriever_module.cc +// File: ICARUSBNBEXTRetriever_module.cc // // Created by hand Thurs June 24th 2021 by J. Zennamo (FNAL) // @@ -16,16 +16,16 @@ #include "canvas/Utilities/InputTag.h" #include "fhiclcpp/types/Atom.h" #include "messagefacility/MessageLogger/MessageLogger.h" -#include "lardata/Utilities/AssociationUtil.h" +/*#include "lardata/Utilities/AssociationUtil.h" #include "lardataobj/Utilities/sparse_vector.h" #include "larcoreobj/SimpleTypesAndConstants/RawTypes.h" -#include "larcorealg/Geometry/Exceptions.h" +#include "larcorealg/Geometry/Exceptions.h"*/ #include "artdaq-core/Data/Fragment.hh" #include "sbndaq-artdaq-core/Overlays/ICARUS/ICARUSTriggerV3Fragment.hh" -#include "lardataalg/DetectorInfo/DetectorPropertiesStandard.h" -#include "lardata/DetectorInfoServices/DetectorPropertiesService.h" +/*#include "lardataalg/DetectorInfo/DetectorPropertiesStandard.h" +#include "lardata/DetectorInfoServices/DetectorPropertiesService.h"*/ #include "sbnobj/Common/POTAccounting/EXTCountInfo.h" #include @@ -36,10 +36,10 @@ #include namespace sbn { - class BNBEXTRetriever; + class ICARUSBNBEXTRetriever; } -class sbn::BNBEXTRetriever : public art::EDProducer { +class sbn::ICARUSBNBEXTRetriever : public art::EDProducer { public: struct Config { @@ -57,15 +57,15 @@ class sbn::BNBEXTRetriever : public art::EDProducer { using Parameters = art::EDProducer::Table; - explicit BNBEXTRetriever(Parameters const& params); + explicit ICARUSBNBEXTRetriever(Parameters const& params); // The compiler-generated destructor is fine for non-base // classes without bare pointers or other resource use. // Plugins should not be copied or assigned. - BNBEXTRetriever(BNBEXTRetriever const&) = delete; - BNBEXTRetriever(BNBEXTRetriever&&) = delete; - BNBEXTRetriever& operator=(BNBEXTRetriever const&) = delete; - BNBEXTRetriever& operator=(BNBEXTRetriever&&) = delete; + ICARUSBNBEXTRetriever(ICARUSBNBEXTRetriever const&) = delete; + ICARUSBNBEXTRetriever(ICARUSBNBEXTRetriever&&) = delete; + ICARUSBNBEXTRetriever& operator=(ICARUSBNBEXTRetriever const&) = delete; + ICARUSBNBEXTRetriever& operator=(ICARUSBNBEXTRetriever&&) = delete; // Required functions. void produce(art::Event& e) override; @@ -85,7 +85,7 @@ class sbn::BNBEXTRetriever : public art::EDProducer { }; -sbn::BNBEXTRetriever::BNBEXTRetriever(Parameters const& params) +sbn::ICARUSBNBEXTRetriever::ICARUSBNBEXTRetriever(Parameters const& params) : EDProducer{params}, raw_data_label_(params().RawDataLabel()) { @@ -97,7 +97,7 @@ sbn::BNBEXTRetriever::BNBEXTRetriever(Parameters const& params) scale_factor = 0; } -void sbn::BNBEXTRetriever::produce(art::Event& e) +void sbn::ICARUSBNBEXTRetriever::produce(art::Event& e) { //Here we read in the artdaq Fragments and extract three pieces of information: @@ -152,7 +152,7 @@ void sbn::BNBEXTRetriever::produce(art::Event& e) } //end loop over events -void sbn::BNBEXTRetriever::beginSubRun(art::SubRun& sr) +void sbn::ICARUSBNBEXTRetriever::beginSubRun(art::SubRun& sr) { TotalEXTCounts = 0; totalMinBias = 0; @@ -162,7 +162,7 @@ void sbn::BNBEXTRetriever::beginSubRun(art::SubRun& sr) } //____________________________________________________________________________ -void sbn::BNBEXTRetriever::endSubRun(art::SubRun& sr) +void sbn::ICARUSBNBEXTRetriever::endSubRun(art::SubRun& sr) { // We will add all of the EXTCountInfo data-products to the // art::SubRun so it persists @@ -186,4 +186,4 @@ void sbn::BNBEXTRetriever::endSubRun(art::SubRun& sr) return; } -DEFINE_ART_MODULE(sbn::BNBEXTRetriever) +DEFINE_ART_MODULE(sbn::ICARUSBNBEXTRetriever) diff --git a/sbncode/BeamSpillInfoRetriever/ICARUSBNBRetriever/CMakeLists.txt b/sbncode/BeamSpillInfoRetriever/ICARUSBNBRetriever/CMakeLists.txt new file mode 100644 index 000000000..6b1a7a729 --- /dev/null +++ b/sbncode/BeamSpillInfoRetriever/ICARUSBNBRetriever/CMakeLists.txt @@ -0,0 +1,14 @@ +find_package(ifbeam) +find_package(ifdh_art) + +cet_build_plugin(ICARUSBNBRetriever art::module + LIBRARIES + sbn_POTTools + sbn_getFOM + SQLite::SQLite3 +) + +install_headers() +install_fhicl() +install_source() + diff --git a/sbncode/BeamSpillInfoRetriever/ICARUSBNBRetriever/ICARUSBNBRetriever_module.cc b/sbncode/BeamSpillInfoRetriever/ICARUSBNBRetriever/ICARUSBNBRetriever_module.cc new file mode 100644 index 000000000..077eb4c9e --- /dev/null +++ b/sbncode/BeamSpillInfoRetriever/ICARUSBNBRetriever/ICARUSBNBRetriever_module.cc @@ -0,0 +1,493 @@ +/** ******************************************************************** + * @file ICARUSBNBRetriever_module.cc + * @date Wed April 9 2021 + * @author J. Zennamo (FNAL) + * + * Based heavily on code by Z. Pavlovic written for MicroBooNE + * Based heavily on code by NOvA collaboration (Thanks NOvA!): + * https://cdcvs.fnal.gov/redmine/projects/novaart/repository/entry/trunk/IFDBSpillInfo/BNBInfo_module.cc + * Database implementation by Justin Mueller + */ + +#include "art/Framework/Core/EDProducer.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "sbnobj/Common/POTAccounting/BNBSpillInfo.h" +#include "sbncode/BeamSpillInfoRetriever/POTTools.h" +#include "sbnobj/Common/Trigger/ExtraTriggerInfo.h" +#include "sbndaq-artdaq-core/Overlays/ICARUS/ICARUSTriggerV3Fragment.hh" +#include +#include "sbncode/BeamSpillInfoRetriever/POTTools.h" +#include "sbncode/BeamSpillInfoRetriever/getFOM.h" + +namespace sbn { + class ICARUSBNBRetriever; +} + +class sbn::ICARUSBNBRetriever : public art::EDProducer { +public: + + struct Config { + + using Name = fhicl::Name; + using Comment = fhicl::Comment; + + fhicl::Atom TimePadding { + Name{ "TimePadding" }, + Comment{ "extension to the time window considered when collecting spills [seconds]" }, + 0.0333 // default + }; + + fhicl::Atom BESOffset { + Name{ "BESOffset" }, + Comment{ "Offset between beam early warning signal and $1D [seconds]" }, + }; + + fhicl::Atom RawDataLabel { + Name{ "raw_data_label" }, + Comment{ "art data product instance name for trigger information (product label is 'daq')" } + }; + + fhicl::Atom DeviceUsedForTiming { + Name{ "DeviceUsedForTiming" }, + Comment{ "name in the IFBeam database of the device used to extract spill times" } + }; + + fhicl::Atom URL { + Name{ "URL" }, + Comment{ "IFBeam database access URL" } + }; + + fhicl::Atom Bundle { + Name{ "Bundle" }, + Comment{ "Name of the collection of devices to grab from IFbeam for everything except MWRdevices." } + }; + + fhicl::Atom TimeWindow { + Name{ "TimeWindow" }, + Comment{ "Window of time in seconds to use for non-mwr ifbeam queries." } + }; + + fhicl::Atom MultiWireBundle { + Name{ "MultiWireBundle" }, + Comment{ "name of collections of devices to grab from IFbeam for use as MWRdevices." } + }; + + fhicl::Atom VP873Bundle { + Name{ "VP873Bundle" }, + Comment{ "name of collections of devices to grab from IFbeam for use as VP873." } + }; + + fhicl::Atom OffsetBundle { + Name{ "OffsetBundle" }, + Comment{ "name of collections of devices to grab from IFbeam for use for offsets." } + }; + fhicl::Atom MWR_TimeWindow { + Name{ "MWR_TimeWindow" }, + Comment{ "Window of time in seconds to use for mwr ifbeam queries." } + }; + + fhicl::Atom TriggerDatabaseFile { + Name{ "TriggerDatabaseFile" }, + Comment{ "path of local database of all recorded events and their trigger, in SQLite format" } + }; + + + }; // Config + + using Parameters = art::EDProducer::Table; + + + explicit ICARUSBNBRetriever(Parameters const& params); + // The compiler-generated destructor is fine for non-base + // classes without bare pointers or other resource use. + + // Plugins should not be copied or assigned. + ICARUSBNBRetriever(ICARUSBNBRetriever const&) = delete; + ICARUSBNBRetriever(ICARUSBNBRetriever&&) = delete; + ICARUSBNBRetriever& operator=(ICARUSBNBRetriever const&) = delete; + ICARUSBNBRetriever& operator=(ICARUSBNBRetriever&&) = delete; + + // Required functions. + void produce(art::Event& e) override; + void beginSubRun(art::SubRun& sr) override; + void endSubRun(art::SubRun& sr) override; + +private: + // input labels + std::vector< sbn::BNBSpillInfo > fOutbeamInfos; + double fTimePad; + double fBESOffset; + std::string fURL; + MWRData mwrdata; + int run_number; + std::string raw_data_label; + std::string fDeviceUsedForTiming; + unsigned int TotalBeamSpills; + // + art::ServiceHandle ifbeam_handle; + std::unique_ptr bfp; + std::unique_ptr vp873; + std::unique_ptr offsets; + std::unique_ptr bfp_mwr; + + // + std::string fTriggerDatabaseFile; + sqlite3 *db; + int rc; + + static constexpr double MWRtoroidDelay = -0.035; ///< the same time point is measured _t_ by MWR and _t + MWRtoroidDelay`_ by the toroid [ms] + + /// Returns the information of the trigger in the current event. + sbn::pot::TriggerInfo_t extractTriggerInfo(art::Event const& e) const; + /** + * @brief Matches spill times with multiwire chamber data from the database. + * @param eventID ID of the event the information is associated to + * @param triggerInfo information from the trigger of this event + * @param MWRdata data from multiwire chambers + * @param isFirstEventInRun whether we are processing the first event of the run + * @param[out] beamInfos container to _add_ spill information records to + * @return count of matched spills + */ + int matchMultiWireData( + art::EventID const& eventID, + sbn::pot::TriggerInfo_t const& triggerInfo, + sbn::pot::MWRdata_t const& MWRdata, + std::vector< sbn::BNBSpillInfo >& beamInfos + ) const; + +/** + * @brief SQLite callback function for retrieving trigger_type from a query. + * @param data Pointer to the integer where the trigger type will be stored. + * @param argc Count of the number of columns returned by the query. + * @param argv Array of c-strings containing the column data of the query. + * @param columns Array of c-strings listing the names of the columns. + * @return 0 if successful. + */ +// int callback_trigger_type(void *data, +// int argc, +// char **argv, +// char **columns); + +/** + * @brief Queries the trigger database and finds the trigger_type of the matching trigger (if any). + * @param db The pointer to the SQLite database instance. + * @param run The run number of the current event (helps with queries). + * @param gate_time The time in milliseconds of the gate. + * @param threshold The required absolute time difference between gate and trigger. + * @return trigger_type -1: No matching trigger, 0: Majority, 1: MinBias + */ + int get_trigger_type_matching_gate(sqlite3 *db, + int func(void*,int,char**,char**), + int run, + long long int gate_time, + float threshold) const; + +}; + +int callback_trigger_type(void *data, int argc, char **argv, char **columns) +{ + int *result = static_cast(data); + // Does this query return non-NULL values? + if(argc > 0 && argv[0]) + *result = std::stoi(argv[0]); + else + *result = -1; + + return 0; +} + +int sbn::ICARUSBNBRetriever::get_trigger_type_matching_gate(sqlite3 *db, int func(void*,int,char**,char**), int run, long long int gate_time, float threshold) const +{ + int trigger_type(-1), query_status; + std::stringstream query; + query << "SELECT trigger_type FROM triggerdata WHERE gate_type=1 AND run_number =" + << run + << " AND ABS(1000000000*wr_seconds + wr_nanoseconds - " + << std::fixed << gate_time + << ") < " + << threshold*1000000 + << " ORDER BY ABS(1000000000*wr_seconds + wr_nanoseconds - " + << std::fixed << gate_time + << ") LIMIT 1;"; + + query_status = sqlite3_exec(db, query.str().c_str(), func, &trigger_type, NULL); + if (query_status != SQLITE_OK) + { + mf::LogError("BNBEXTRetriever") << "SQL error: " << sqlite3_errmsg(db); + trigger_type = -1; + } + return trigger_type; +} + +sbn::ICARUSBNBRetriever::ICARUSBNBRetriever(Parameters const& params) + : EDProducer{params}, + fTimePad(params().TimePadding()), + fBESOffset(params().BESOffset()), + raw_data_label(params().RawDataLabel()), + fDeviceUsedForTiming(params().DeviceUsedForTiming()), + bfp( ifbeam_handle->getBeamFolder(params().Bundle(), params().URL(), params().TimeWindow())), + vp873( ifbeam_handle->getBeamFolder(params().VP873Bundle(), params().URL(), params().TimeWindow())), + offsets( ifbeam_handle->getBeamFolder(params().OffsetBundle(), params().URL(), params().TimeWindow())), + bfp_mwr( ifbeam_handle->getBeamFolder(params().MultiWireBundle(), params().URL(), params().MWR_TimeWindow())), + fTriggerDatabaseFile(params().TriggerDatabaseFile()) +{ + + // Check fTimePad is positive + if (fTimePad < 0) { + throw art::Exception(art::errors::Configuration) + << "Parameter `TimePadding` must be non-negative (" << fTimePad << " was specified).\n"; + }//End Time check + + // how close in time does the spill time have to be from the DAQ time (in seconds). + // If these are too large then it fails to capture the device + // If these are too small then the time jitter in devices means we miss good data + // + // These values should likely not be changed unless authors of the IFBeam API are consulted + // + bfp->set_epsilon(0.02); //20 ms, this was tuned by hand and compared to IFBeamDB times + bfp_mwr->set_epsilon(0.5); + vp873->set_epsilon(0.02); + offsets->set_epsilon(600); + + //bfp_mwr->setValidWindow(86400); + bfp_mwr->setValidWindow(3605); + produces< std::vector< sbn::BNBSpillInfo >, art::InSubRun >(); + TotalBeamSpills = 0; + + cet::search_path sp("FW_SEARCH_PATH"); + std::string trigDB_path = sp.find_file(fTriggerDatabaseFile.c_str()); + + rc = sqlite3_open(trigDB_path.c_str(), &db); + if(rc) + { + fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db)); + throw art::Exception(art::errors::NotFound) + << "Can't open database: " << sqlite3_errmsg(db); + } + +} + + +void sbn::ICARUSBNBRetriever::produce(art::Event& e) +{ + + // If this is the first event in the run, then ignore it + // We do not currently have the ability to figure out the first + // spill that the DAQ was sensitive to, so don't try to save any + // spill information + + if (e.event() == 1) return; + + run_number = e.id().run(); + + sbn::pot::TriggerInfo_t const triggerInfo = extractTriggerInfo(e); + + //We only want to process BNB gates, i.e. type 1 + if(triggerInfo.gate_type != 1) return; + // Keep track of the number of beam gates the DAQ thinks + // are in this job + TotalBeamSpills += triggerInfo.number_of_gates_since_previous_event; + sbn::pot::MWRdata_t const MWRdata = extractSpillTimes(triggerInfo, bfp, bfp_mwr, fTimePad, MWRtoroidDelay, mwrdata); + + int const spill_count = matchMultiWireData(e.id(), triggerInfo, MWRdata, fOutbeamInfos); + + if(spill_count > int(triggerInfo.number_of_gates_since_previous_event)) + mf::LogDebug("ICARUSBNBRetriever")<< "Event Spills : " << spill_count << ", DAQ Spills : " << triggerInfo.number_of_gates_since_previous_event << " \t \t ::: WRONG!"<< std::endl; + else + mf::LogDebug("ICARUSBNBRetriever")<< "Event Spills : " << spill_count << ", DAQ Spills : " << triggerInfo.number_of_gates_since_previous_event << std::endl; + +}//end iteration over art::Events + + +sbn::pot::TriggerInfo_t sbn::ICARUSBNBRetriever::extractTriggerInfo(art::Event const& e) const { + + //Here we read in the artdaq Fragments and extract three pieces of information: + // 1. The time of the current event, t_current_event + // 2. the time of the previously triggered event, t_previous_event (NOTE: Events are non-sequential!) + // 3. the number of beam spills since the previously triggered event, number_of_gates_since_previous_event + + auto const & raw_data = e.getProduct< std::vector >({ raw_data_label, "ICARUSTriggerV3" }); + auto const & extraTrigInfo = e.getProduct< sbn::ExtraTriggerInfo >("daqTrigger"); + + sbn::pot::TriggerInfo_t triggerInfo; + + triggerInfo.WR_to_Spill_conversion = extraTrigInfo.WRtimeToTriggerTime; + + for(auto raw_datum : raw_data){ + + uint64_t artdaq_ts = raw_datum.timestamp(); + icarus::ICARUSTriggerV3Fragment frag(raw_datum); + std::string data = frag.GetDataString(); + char *buffer = const_cast(data.c_str()); + icarus::ICARUSTriggerInfo datastream_info = icarus::parse_ICARUSTriggerV3String(buffer); + triggerInfo.gate_type = datastream_info.gate_type; + triggerInfo.number_of_gates_since_previous_event = frag.getDeltaGatesBNBMaj(); + + /* + The DAQ trigger time is issued at the Beam Extraction Signal (BES) which is issued + 36 ms *after* the $1D of the BNB, which is what is used in the IFBeam database + + We subtract 36ms from the Trigger time to match our triggers to the spills in the + IFBeam database + + */ + + double BESinTSUnits = fBESOffset*1e9; // flc param is in seconds need to convert to match TS + triggerInfo.t_current_event = static_cast(artdaq_ts-BESinTSUnits)/(1000000000.0); //check this offset... + if(triggerInfo.gate_type == 1) + triggerInfo.t_previous_event = (static_cast(frag.getLastTimestampBNBMaj()-BESinTSUnits))/(1e9); + else + triggerInfo.t_previous_event = (static_cast(frag.getLastTimestampOther()-BESinTSUnits))/(1000000000.0); + + } + + mf::LogDebug("ICARUSBNBRetriever") << std::setprecision(19) << "Previous : " << triggerInfo.t_previous_event << ", Current : " << triggerInfo.t_current_event << ", Spill Count " << triggerInfo.number_of_gates_since_previous_event << std::endl; + + return triggerInfo; +} + +int sbn::ICARUSBNBRetriever::matchMultiWireData( + art::EventID const& eventID, + sbn::pot::TriggerInfo_t const& triggerInfo, + sbn::pot::MWRdata_t const& MWRdata, + std::vector< sbn::BNBSpillInfo >& beamInfos +) const { + + auto const& [ MWR_times, unpacked_MWR ] = MWRdata; // alias + + //Here we will start collecting all the other beamline devices + // First we get the times that the beamline device fired + // we have to pick a specific variable to use + std::vector times_temps = bfp->GetTimeList(fDeviceUsedForTiming); + + mf::LogDebug("ICARUSBNBRetriever") << "matchMultiWireData:: Number of time spills : " << times_temps.size() << std::endl; + + // We'll keep track of how many of these spills match to our + // DAQ trigger times + int spill_count = 0; + int spills_removed = 0; + std::vector matched_MWR; + matched_MWR.resize(3); + + ///reject time_stamps which have a trigger_type == 1 from data-base + //To-Do + + // mf::LogDebug("ICARUSBNBRetriever") << "Total number of Times we're going to test: " << times_temps.size() << std::endl; + // mf::LogDebug("ICARUSBNBRetriever") << std::setprecision(19) << "Upper Limit : " << (triggerInfo.t_current_event)+fTimePad << std::endl; + // mf::LogDebug("ICARUSBNBRetriever") << std::setprecision(19) << "Lower Limit : " << (triggerInfo.t_previous_event)+fTimePad << std::endl; + + // Iterating through each of the beamline times + for (size_t i = 0; i < times_temps.size(); i++) { + + // Only continue if these times are matched to our DAQ time + //mf::LogDebug("ICARUSBNBRetriever") << std::setprecision(19) << "Time # : " << i << std::endl; + + if(times_temps[i] > (triggerInfo.t_current_event)+fTimePad){ + //mf::LogDebug("ICARUSBNBRetriever") << std::setprecision(19) << "Removed! : " << times_temps[i] << std::endl; + spills_removed++; + continue;} + if(times_temps[i] <= (triggerInfo.t_previous_event)+fTimePad){ + spills_removed++; + //mf::LogDebug("ICARUSBNBRetriever") << std::setprecision(19) << "Removed! : " << times_temps[i] << std::endl; + continue;} + + //check if this spill is is minbias + /* + 40 ms was selected to be close to but outside the 66 ms + time of the next spill (when the beam is running at 15 Hz) + DocDB 33155 provides documentation of this + */ + + double BESinTSUnits = fBESOffset*1e9; // flc param is in seconds need to convert to match TS + mf::LogDebug("ICARUSBNBRetriever") << std::setprecision(19) << "matchMultiWireData:: trigger type : " << get_trigger_type_matching_gate(db, callback_trigger_type, run_number, times_temps[i]*1.e9-triggerInfo.WR_to_Spill_conversion+BESinTSUnits, 40.) << " times : spill " << times_temps[i]*1.e9 << " - " << triggerInfo.WR_to_Spill_conversion << " + " << BESinTSUnits << std::endl; + + if(get_trigger_type_matching_gate(db, callback_trigger_type, run_number, times_temps[i]*1.e9-triggerInfo.WR_to_Spill_conversion+BESinTSUnits, 40.) == 1){ + mf::LogDebug("ICARUSBNBRetriever") << std::setprecision(19) << "matchMultiWireData:: Skipped a MinBias gate at : " << times_temps[i]*1000. << std::endl; + + continue; + } + + //Great we found a matched spill! Let's count it + spill_count++; + + //Loop through the multiwire devices: + + for(int dev = 0; dev < int(MWR_times.size()); dev++){ + + //Loop through the multiwire times: + double Tdiff = 1000000000.; + matched_MWR[dev] = 0; + + for(int mwrt = 0; mwrt < int(MWR_times[dev].size()); mwrt++){ + + //found a candidate match! + if(fabs((MWR_times[dev][mwrt] - times_temps[i])) >= Tdiff){continue;} + + bool best_match = true; + + //Check for a better match... + for (size_t j = 0; j < times_temps.size(); j++) { + if( j == i) continue; + if(times_temps[j] > (triggerInfo.t_current_event+fTimePad)){continue;} + if(times_temps[j] <= (triggerInfo.t_previous_event+fTimePad)){continue;} + + //is there a better match later in the spill sequence + if(fabs((MWR_times[dev][mwrt] - times_temps[j])) < + fabs((MWR_times[dev][mwrt] - times_temps[i]))){ + //we can have patience... + best_match = false; + break; + } + }//end better match check + + //Verified best match! + if(best_match == true){ + matched_MWR[dev] = mwrt; + Tdiff = fabs((MWR_times[dev][mwrt] - times_temps[i])); + } + + }//end loop over MWR times + + }//end loop over MWR devices + + sbn::BNBSpillInfo spillInfo = sbn::pot::makeBNBSpillInfo(eventID, times_temps[i], MWRdata, matched_MWR, bfp, offsets, vp873); + double const spillFOM = sbn::getBNBqualityFOM(spillInfo); + spillInfo.FOM = spillFOM; + + beamInfos.push_back(std::move(spillInfo)); + + // We do not write these to the art::Events because + // we can filter events but want to keep all the POT + // information, so we'll write it to the SubRun + + }//end iteration over beam device times + + // mf::LogDebug("ICARUSBNBRetriever") << "matchMultiWireData:: Total spills counted: " << spill_count << " Total spills removed : " << spills_removed << std::endl; + + return spill_count; +} + +void sbn::ICARUSBNBRetriever::beginSubRun(art::SubRun& sr) +{ + return; +} + +//____________________________________________________________________________ +void sbn::ICARUSBNBRetriever::endSubRun(art::SubRun& sr) +{ + // We will add all of the BNBSpillInfo data-products to the + // art::SubRun so it persists + // currently this is ~2.7 kB/event or ~0.07 kB/spill + +mf::LogDebug("ICARUSBNBRetriever")<< "Total number of DAQ Spills : " << TotalBeamSpills << std::endl; +mf::LogDebug("ICARUSBNBRetriever")<< "Total number of Selected Spills : " << fOutbeamInfos.size() << std::endl; + + auto p = std::make_unique< std::vector< sbn::BNBSpillInfo > >(); + std::swap(*p, fOutbeamInfos); + + sr.put(std::move(p), art::subRunFragment()); + + return; +} + +DEFINE_ART_MODULE(sbn::ICARUSBNBRetriever) diff --git a/sbncode/BeamSpillInfoRetriever/SBNDPOTTools.cpp b/sbncode/BeamSpillInfoRetriever/POTTools.cpp similarity index 69% rename from sbncode/BeamSpillInfoRetriever/SBNDPOTTools.cpp rename to sbncode/BeamSpillInfoRetriever/POTTools.cpp index bcdb6e380..a83d5f304 100644 --- a/sbncode/BeamSpillInfoRetriever/SBNDPOTTools.cpp +++ b/sbncode/BeamSpillInfoRetriever/POTTools.cpp @@ -1,12 +1,10 @@ -#include "SBNDPOTTools.h" +#include "POTTools.h" using namespace std; -namespace sbn{ +namespace sbn::pot{ - // Function for extracting the PTB information (current timestamp, - // previous timestamp, gate counter). Used in SBND modules only. - sbn::PTBInfo_t extractPTBInfo(art::Handle > cont_frags, int HLT) { + sbn::pot::PTBInfo_t extractPTBInfo(art::Handle > cont_frags, int HLT) { bool foundHLT = false; PTBInfo_t PTBInfo; for (auto const& cont : *cont_frags) @@ -22,11 +20,11 @@ namespace sbn{ if (ctb_frag.Trigger(word_i)->IsHLT() && ctb_frag.Trigger(word_i)->IsTrigger(HLT)) { foundHLT = true; - uint64_t RawprevPTBTimeStamp = ctb_frag.PTBWord(word_i)->prevTS * 20; - uint64_t RawcurrPTBTimeStamp = ctb_frag.Trigger(word_i)->timestamp * 20; - double currTS_candidate = std::bitset<64>(RawcurrPTBTimeStamp/20).to_ullong()/50e6; + uint64_t RawprevPTBTimeStamp = ctb_frag.PTBWord(word_i)->prevTS; + uint64_t RawcurrPTBTimeStamp = ctb_frag.Trigger(word_i)->timestamp; + std::uint64_t currTS_candidate = std::bitset<64>(RawcurrPTBTimeStamp).to_ullong() * 20; if(currTS_candidate < PTBInfo.currPTBTimeStamp){ - PTBInfo.prevPTBTimeStamp = std::bitset<64>(RawprevPTBTimeStamp / 20).to_ullong()/50e6; + PTBInfo.prevPTBTimeStamp = std::bitset<64>(RawprevPTBTimeStamp).to_ullong() * 20; PTBInfo.currPTBTimeStamp = currTS_candidate; PTBInfo.GateCounter = ctb_frag.Trigger(word_i)->gate_counter; } @@ -45,7 +43,35 @@ namespace sbn{ } } - // Function for extracting the TDC timestamp. Used in SBND modules only. + std::vector extractAllPTBInfo(std::vector const& cont_frags) { + std::vector PTBInfoVec; + for (auto const& cont : cont_frags) + { + artdaq::ContainerFragment cont_frag(cont); + for (size_t fragi = 0; fragi < cont_frag.block_count(); ++fragi) + { + artdaq::Fragment frag = *cont_frag[fragi]; + sbndaq::CTBFragment ctb_frag(frag); + for(size_t word_i = 0; word_i < ctb_frag.NWords(); ++word_i) + { + if(ctb_frag.Trigger(word_i)){ + PTBInfo_t PTBInfo; + uint64_t RawprevPTBTimeStamp = ctb_frag.PTBWord(word_i)->prevTS; + uint64_t RawcurrPTBTimeStamp = ctb_frag.Trigger(word_i)->timestamp; + PTBInfo.prevPTBTimeStamp = std::bitset<64>(RawprevPTBTimeStamp).to_ullong() * 20; + PTBInfo.currPTBTimeStamp = std::bitset<64>(RawcurrPTBTimeStamp).to_ullong() * 20; + PTBInfo.GateCounter = ctb_frag.Trigger(word_i)->gate_counter; + PTBInfo.isHLT = ctb_frag.Trigger(word_i)->IsHLT(); + PTBInfo.triggerWord = ctb_frag.Trigger(word_i)->trigger_word; + PTBInfoVec.push_back(PTBInfo); + } + } + } + } + + return PTBInfoVec; + } + double extractTDCTimeStamp(art::Handle > cont_frags) { double TDCTimeStamp = 0; @@ -62,8 +88,6 @@ namespace sbn{ return TDCTimeStamp; } - // Collect device information to make BNBSpillInfo object. Used in - // ICARUS and SBND modules. sbn::BNBSpillInfo makeBNBSpillInfo (art::EventID const& eventID, double time, MWRdata_t const& MWRdata, std::vector const& matched_MWR, std::unique_ptr const& bfp, const std::unique_ptr & offsets,const std::unique_ptr & vp873) { @@ -78,6 +102,8 @@ namespace sbn{ double LM875A = -999; // units R/s double LM875B = -999; // units R/s double LM875C = -999; // units R/s + double HP873 = -999; // units mm + double VP873 = -999; // units mm; not in the first IFBeam query bunch double HP875 = -999; // units mm double VP875 = -999; // units mm double HPTG1 = -999; // units mm @@ -86,55 +112,66 @@ namespace sbn{ double VPTG2 = -999; // units mm double BTJT2 = -999; // units Deg C double THCURR = -999; // units kiloAmps + double M875HS = -999; // units mm + double M875VS = -999; // units mm + double M875HM = -999; // units mm + double M875VM = -999; // units mm + double M876HS = -999; // units mm + double M876VS = -999; // units mm + double M876HM = -999; // units mm + double M876VM = -999; // units mm - double VP873 = -999; //units mm; not in the first IFBeam query bunch - double HP875Offset = -999;//units mm; make a another separate IFBeam query bunch for offsets - double VP875Offset = -999;//units mm - double VP873Offset = -999;//units mm - double HPTG1Offset = -999;//units mm - double HPTG2Offset = -999;//units mm - double VPTG1Offset = -999;//units mm - double VPTG2Offset = -999;//units mm + double HP875Offset =-999;//units mm; make a another separate IFBeam query bunch for offsets + double VP875Offset =-999;//units mm + double VP873Offset =-999;//units mm + double HPTG1Offset =-999;//units mm + double HPTG2Offset =-999;//units mm + double VPTG1Offset =-999;//units mm + double VPTG2Offset =-999;//units mm double TOR860_time = -999; // units s - double FOM = -999; + double FOM =-999; // Here we request all the devices // since sometimes devices fail to report we'll // allow each to throw an exception but still move forward // interpreting these failures will be part of the beam quality analyses - - try{bfp->GetNamedData(time, "E:TOR860@",&TOR860,&TOR860_time);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:TOR875",&TOR875);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:LM875A",&LM875A);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:LM875B",&LM875B);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:LM875C",&LM875C);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:HP875",&HP875);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:VP875",&VP875);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:HPTG1",&HPTG1);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:VPTG1",&VPTG1);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:HPTG2",&HPTG2);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:VPTG2",&VPTG2);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:BTJT2",&BTJT2);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{bfp->GetNamedData(time, "E:THCURR",&THCURR);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - - - try{vp873->GetNamedData(time, "E:VP873",&VP873);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - - try{offsets->GetNamedData(time, "E_VP873S",&VP873Offset);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{offsets->GetNamedData(time, "E_HP875S",&HP875Offset);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{offsets->GetNamedData(time, "E_VP875S",&VP875Offset);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{offsets->GetNamedData(time, "E_HPTG1S",&HPTG1Offset);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{offsets->GetNamedData(time, "E_HPTG2S",&HPTG2Offset);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{offsets->GetNamedData(time, "E_VPTG1S",&VPTG1Offset);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - try{offsets->GetNamedData(time, "E_VPTG2S",&VPTG2Offset);}catch (WebAPIException &we) {mf::LogDebug("SBNDBNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:TOR860@",&TOR860,&TOR860_time);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:TOR875",&TOR875);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:LM875A",&LM875A);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:LM875B",&LM875B);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:LM875C",&LM875C);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:HP873",&HP873);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{vp873->GetNamedData(time, "E:VP873",&VP873);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:HP875",&HP875);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:VP875",&VP875);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:HPTG1",&HPTG1);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:VPTG1",&VPTG1);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:HPTG2",&HPTG2);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:VPTG2",&VPTG2);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:BTJT2",&BTJT2);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:THCURR",&THCURR);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:M875HS",&M875HS);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:M875VS",&M875VS);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:M875HM",&M875HM);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:M875VM",&M875VM);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:M876HS",&M876HS);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:M876VS",&M876VS);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:M876HM",&M876HM);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{bfp->GetNamedData(time, "E:M876VM",&M876VM);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{offsets->GetNamedData(time, "E_VP873S",&VP873Offset);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{offsets->GetNamedData(time, "E_HP875S",&HP875Offset);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{offsets->GetNamedData(time, "E_VP875S",&VP875Offset);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{offsets->GetNamedData(time, "E_HPTG1S",&HPTG1Offset);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{offsets->GetNamedData(time, "E_HPTG2S",&HPTG2Offset);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{offsets->GetNamedData(time, "E_VPTG1S",&VPTG1Offset);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} + try{offsets->GetNamedData(time, "E_VPTG2S",&VPTG2Offset);}catch (WebAPIException &we) {mf::LogDebug("BNBRetriever")<< "At time : " << time << " " << "got exception: " << we.what() << "\n";} - //crunch the times unsigned long int time_closest_int = (int) TOR860_time; double time_closest_ns = (TOR860_time - time_closest_int)*1e9; @@ -146,6 +183,8 @@ namespace sbn{ beamInfo.LM875A = LM875A; beamInfo.LM875B = LM875B; beamInfo.LM875C = LM875C; + beamInfo.HP873 = HP873; + beamInfo.VP873 = VP873; beamInfo.HP875 = HP875; beamInfo.VP875 = VP875; beamInfo.HPTG1 = HPTG1; @@ -154,6 +193,14 @@ namespace sbn{ beamInfo.VPTG2 = VPTG2; beamInfo.BTJT2 = BTJT2; beamInfo.THCURR = THCURR; + beamInfo.M875HS = M875HS; + beamInfo.M875VS = M875VS; + beamInfo.M875HM = M875HM; + beamInfo.M875VM = M875VM; + beamInfo.M876HS = M876HS; + beamInfo.M876VS = M876VS; + beamInfo.M876HM = M876HM; + beamInfo.M876VM = M876VM; beamInfo.spill_time_s = time_closest_int; beamInfo.spill_time_ns = time_closest_ns; beamInfo.VP873 = VP873; @@ -166,8 +213,7 @@ namespace sbn{ beamInfo.VPTG2Offset = VPTG2Offset; beamInfo.FOM = FOM; - - + for(auto const& MWRdata: unpacked_MWR){ std::ignore = MWRdata; assert(!MWRdata.empty()); @@ -212,9 +258,6 @@ namespace sbn{ return beamInfo; } - // Returns true if a time in IFBeam corresponds to a broken clock false if - // it is a real spill. Check this by seeing if all devices fire at once or - // if time is just a single outlier. bool BrokenClock(double time, std::unique_ptr const& bfp) { double TOR860 = -999; // units e12 protons @@ -263,8 +306,7 @@ namespace sbn{ } } - // extract spill times from the IFBeam data base. Used in SBND and ICARUS. - sbn::MWRdata_t extractSpillTimes(TriggerInfo_t const& triggerInfo, std::unique_ptr const& bfp, std::unique_ptr const& bfp_mwr, double fTimePad, double MWRtoroidDelay, sbn::MWRData mwrdata) { + sbn::pot::MWRdata_t extractSpillTimes(TriggerInfo_t const& triggerInfo, std::unique_ptr const& bfp, std::unique_ptr const& bfp_mwr, double fTimePad, double MWRtoroidDelay, sbn::MWRData mwrdata) { // These lines get everything primed within the IFBeamDB. try{bfp->FillCache((triggerInfo.t_current_event)+fTimePad);} catch (WebAPIException &we) {}; @@ -375,6 +417,3 @@ namespace sbn{ } } - - - diff --git a/sbncode/BeamSpillInfoRetriever/POTTools.h b/sbncode/BeamSpillInfoRetriever/POTTools.h new file mode 100644 index 000000000..1e54647a8 --- /dev/null +++ b/sbncode/BeamSpillInfoRetriever/POTTools.h @@ -0,0 +1,92 @@ +#ifndef _SBNDPOTTOOLS_H +#define _SBNDPOTTOOLS_H + +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "ifdh_art/IFBeamService/IFBeam_service.h" + +#include "sbnobj/Common/POTAccounting/BNBSpillInfo.h" +#include "sbndaq-artdaq-core/Overlays/SBND/PTBFragment.hh" +#include "sbndaq-artdaq-core/Overlays/SBND/TDCTimestampFragment.hh" +#include "artdaq-core/Data/ContainerFragment.hh" + +#include "sbncode/BeamSpillInfoRetriever/MWRData.h" +#include "larcorealg/CoreUtils/counter.h" +#include + +namespace sbn::pot{ + + typedef struct PTBInfo_t { + std::uint64_t currPTBTimeStamp = UINT64_MAX; ///< Timestamp in UTC nanoseconds since Unix epoch (converted from 20ns clock ticks) + std::uint64_t prevPTBTimeStamp = 0; + unsigned int GateCounter = 0; + bool isHLT = false; + uint64_t triggerWord = 0; ///< Timestamp in s since beam extraction signal + } PTBInfo_t; + + typedef struct TriggerInfo_t { + int gate_type = 0; ///< Source of the spill: `1`: BNB, `2`: NuMI + double t_current_event = 0; ///< Timestamp in UTC seconds since Unix epoch (converted from 20ns clock ticks) + double t_previous_event = 0; + unsigned int number_of_gates_since_previous_event = 0; + std::int64_t WR_to_Spill_conversion = 0; + } TriggerInfo_t; + + typedef struct MWRdata_t { + std::vector< std::vector > MWR_times; + std::vector< std::vector< std::vector< int > > > unpacked_MWR; + } MWRdata_t; + + /** + * @brief Extracts information from PTB for a single HLT for use in SBND POT accounting. + * + * @param cont_frags The PTB fragments to examine. + * @param HLT The high level trigger we are searching for. + */ + PTBInfo_t extractPTBInfo(art::Handle > cont_frags, int HLT); + + /** + * @brief Extracts ALL PTB information for using in SBND CAF files. + * + * @param cont_frags The PTB fragments to examine. + * @return Vector of PTBInfo_t containing all triggers found. + */ + std::vector extractAllPTBInfo(std::vector const& cont_frags); + + /** + * @brief Extracts information from TDC for use in SBND POT accounting. + * + * @param cont_frags The TDC fragments to examine. + */ + double extractTDCTimeStamp(art::Handle > cont_frags); + + /** + * @brief Checks for a known IFBeam issue where TOR clocks are incorrect. + * @return true if a time in IFBeam corresponds to a broken clock false if + * it is a real spill. + * @details Check validity by seeing if all devices fire at once or + * if time is just a single outlier. + * @param time The time for which we want to check for a spill. + * @param bfp beamfolder object to check. + */ + bool BrokenClock(double time, std::unique_ptr const& bfp); + + /** + * @brief extract spill times from the IFBeam data base. Used in SBND and ICARUS. + * + * @param triggerInfo triggerInfo object to match + * @param bfp beamfolder to match + * @param bfp_mwr mwr devices have separate daq system, much treat separately + * @param fTimePad Padding to use in ifbeam queries + * @param MWRtoroidDelay Delay between MWR and toroids + * @param mwrdata MWRData to unpack + */ + MWRdata_t extractSpillTimes(TriggerInfo_t const& triggerInfo, std::unique_ptr const& bfp, std::unique_ptr const& bfp_mwr, double fTimePad, double MWRtoroidDelay, sbn::MWRData mwrdata ); + /** + * @brief Compile spill information into BNBSpillInfo object + */ + sbn::BNBSpillInfo makeBNBSpillInfo(art::EventID const& eventID, double time, MWRdata_t const& MWRdata, std::vector const& matched_MWR, std::unique_ptr const& bfp, std::unique_ptr const& offsets, std::unique_ptr const& vp873); +} + +#endif diff --git a/sbncode/BeamSpillInfoRetriever/SBNDBNBEXTRetriever/CMakeLists.txt b/sbncode/BeamSpillInfoRetriever/SBNDBNBEXTRetriever/CMakeLists.txt index d7f43205a..8a16ef2e9 100644 --- a/sbncode/BeamSpillInfoRetriever/SBNDBNBEXTRetriever/CMakeLists.txt +++ b/sbncode/BeamSpillInfoRetriever/SBNDBNBEXTRetriever/CMakeLists.txt @@ -3,7 +3,7 @@ find_package(ifdh_art) cet_build_plugin(SBNDBNBEXTRetriever art::module LIBRARIES - sbn_SBNDPOTTools + sbn_POTTools ) install_headers() diff --git a/sbncode/BeamSpillInfoRetriever/SBNDBNBEXTRetriever/SBNDBNBEXTRetriever_module.cc b/sbncode/BeamSpillInfoRetriever/SBNDBNBEXTRetriever/SBNDBNBEXTRetriever_module.cc index 298734bff..a8b3f9d67 100644 --- a/sbncode/BeamSpillInfoRetriever/SBNDBNBEXTRetriever/SBNDBNBEXTRetriever_module.cc +++ b/sbncode/BeamSpillInfoRetriever/SBNDBNBEXTRetriever/SBNDBNBEXTRetriever_module.cc @@ -8,7 +8,7 @@ #include "art/Framework/Core/EDProducer.h" #include "messagefacility/MessageLogger/MessageLogger.h" #include "sbnobj/Common/POTAccounting/EXTCountInfo.h" -#include "sbncode/BeamSpillInfoRetriever/SBNDPOTTools.h" +#include "sbncode/BeamSpillInfoRetriever/POTTools.h" namespace sbn { class SBNDBNBEXTRetriever; @@ -28,11 +28,10 @@ class sbn::SBNDBNBEXTRetriever : public art::EDProducer { SBNDBNBEXTRetriever & operator = (SBNDBNBEXTRetriever const &) = delete; SBNDBNBEXTRetriever & operator = (SBNDBNBEXTRetriever &&) = delete; - private: // Declare member data here. std::vector< sbn::EXTCountInfo > fOutExtInfos; - TriggerInfo_t extractTriggerInfo(art::Event const& e) const; + sbn::pot::TriggerInfo_t extractTriggerInfo(art::Event const& e) const; // input labels float TotalEXTCounts; }; @@ -47,7 +46,7 @@ void sbn::SBNDBNBEXTRetriever::produce(art::Event & e) { art::InputTag PTB_itag("daq", "ContainerPTB"); auto PTB_cont_frags = e.getHandle(PTB_itag); - PTBInfo_t PTBInfo = extractPTBInfo(PTB_cont_frags, 4); + sbn::pot::PTBInfo_t PTBInfo = sbn::pot::extractPTBInfo(PTB_cont_frags, 4); int SingleEventGateCounter = PTBInfo.GateCounter; TotalEXTCounts += SingleEventGateCounter; diff --git a/sbncode/BeamSpillInfoRetriever/SBNDBNBRetriever/CMakeLists.txt b/sbncode/BeamSpillInfoRetriever/SBNDBNBRetriever/CMakeLists.txt index ca297fcdd..efbf13789 100644 --- a/sbncode/BeamSpillInfoRetriever/SBNDBNBRetriever/CMakeLists.txt +++ b/sbncode/BeamSpillInfoRetriever/SBNDBNBRetriever/CMakeLists.txt @@ -3,7 +3,7 @@ find_package(ifdh_art) cet_build_plugin(SBNDBNBRetriever art::module LIBRARIES - sbn_SBNDPOTTools + sbn_POTTools sbn_getFOM ) diff --git a/sbncode/BeamSpillInfoRetriever/SBNDBNBRetriever/SBNDBNBRetriever_module.cc b/sbncode/BeamSpillInfoRetriever/SBNDBNBRetriever/SBNDBNBRetriever_module.cc index f2d077daf..e6465d45b 100644 --- a/sbncode/BeamSpillInfoRetriever/SBNDBNBRetriever/SBNDBNBRetriever_module.cc +++ b/sbncode/BeamSpillInfoRetriever/SBNDBNBRetriever/SBNDBNBRetriever_module.cc @@ -8,10 +8,9 @@ #include "art/Framework/Core/EDProducer.h" #include "messagefacility/MessageLogger/MessageLogger.h" #include "sbnobj/Common/POTAccounting/BNBSpillInfo.h" -#include "sbncode/BeamSpillInfoRetriever/SBNDPOTTools.h" +#include "sbncode/BeamSpillInfoRetriever/POTTools.h" #include "sbncode/BeamSpillInfoRetriever/getFOM.h" - namespace sbn { class SBNDBNBRetriever; } @@ -45,11 +44,11 @@ class sbn::SBNDBNBRetriever : public art::EDProducer { art::ServiceHandle ifbeam_handle; static constexpr double MWRtoroidDelay = -0.035; ///< the same time point is measured _t_ by MWR and _t + MWRtoroidDelay`_ by the toroid [ms] - TriggerInfo_t extractTriggerInfo(art::Event const& e) const; + sbn::pot::TriggerInfo_t extractTriggerInfo(art::Event const& e) const; int matchMultiWireData( art::EventID const& eventID, - TriggerInfo_t const& triggerInfo, - MWRdata_t const& MWRdata, + sbn::pot::TriggerInfo_t const& triggerInfo, + sbn::pot::MWRdata_t const& MWRdata, std::vector< sbn::BNBSpillInfo >& beamInfos ) const; unsigned int TotalBeamSpills; @@ -89,14 +88,14 @@ void sbn::SBNDBNBRetriever::produce(art::Event & e) } mf::LogDebug("SBNDBNBRetriever")<< "ptb_event: " << e.event() << std::endl; - TriggerInfo_t const triggerInfo = extractTriggerInfo(e); + sbn::pot::TriggerInfo_t const triggerInfo = extractTriggerInfo(e); if (triggerInfo.t_previous_event == 0) { return; } TotalBeamSpills += triggerInfo.number_of_gates_since_previous_event; - MWRdata_t const MWRdata = extractSpillTimes(triggerInfo, bfp, bfp_mwr, fTimePad, MWRtoroidDelay, mwrdata); + sbn::pot::MWRdata_t const MWRdata = extractSpillTimes(triggerInfo, bfp, bfp_mwr, fTimePad, MWRtoroidDelay, mwrdata); int const spill_count = matchMultiWireData(e.id(), triggerInfo, MWRdata, fOutbeamInfos); @@ -106,7 +105,7 @@ void sbn::SBNDBNBRetriever::produce(art::Event & e) mf::LogDebug("SBNDBNBRetriever")<< "Event Spills : " << spill_count << ", DAQ Spills : " << triggerInfo.number_of_gates_since_previous_event << std::endl; } -sbn::TriggerInfo_t sbn::SBNDBNBRetriever::extractTriggerInfo(art::Event const& e) const { +sbn::pot::TriggerInfo_t sbn::SBNDBNBRetriever::extractTriggerInfo(art::Event const& e) const { // Using TDC for current event, but PTB for previous event. Exception for case where no TDC. art::InputTag PTB_itag("daq", "ContainerPTB"); auto PTB_cont_frags = e.getHandle(PTB_itag); @@ -114,23 +113,23 @@ sbn::TriggerInfo_t sbn::SBNDBNBRetriever::extractTriggerInfo(art::Event const& e art::InputTag TDC_itag("daq", "ContainerTDCTIMESTAMP"); auto TDC_cont_frags = e.getHandle(TDC_itag); - TriggerInfo_t triggerInfo; - PTBInfo_t PTBInfo = extractPTBInfo(PTB_cont_frags, 2); + sbn::pot::TriggerInfo_t triggerInfo; + sbn::pot::PTBInfo_t PTBInfo = sbn::pot::extractPTBInfo(PTB_cont_frags, 2); if (TDC_cont_frags) { - double TDCTimeStamp = extractTDCTimeStamp(TDC_cont_frags); + double TDCTimeStamp = sbn::pot::extractTDCTimeStamp(TDC_cont_frags); triggerInfo.t_current_event = TDCTimeStamp - fBESOffset; } else{ // If missing TDC, use PTB instead mf::LogDebug("SBNDBNBRetriever") << " Missing TDC Container Fragments!!! " << std::endl; - triggerInfo.t_current_event = PTBInfo.currPTBTimeStamp - fBESOffset; + triggerInfo.t_current_event = PTBInfo.currPTBTimeStamp / 1e9 - fBESOffset; } - triggerInfo.t_previous_event = PTBInfo.prevPTBTimeStamp - fBESOffset; + triggerInfo.t_previous_event = PTBInfo.prevPTBTimeStamp / 1e9 - fBESOffset; triggerInfo.number_of_gates_since_previous_event = PTBInfo.GateCounter; - double PTBandCurrOffset = PTBInfo.currPTBTimeStamp - triggerInfo.t_current_event - fBESOffset; + double PTBandCurrOffset = PTBInfo.currPTBTimeStamp / 1e9 - triggerInfo.t_current_event - fBESOffset; // Catch for an issue seen a few times where PTB off by a second. // Only need to correct prevTS because either currTS is from TDC @@ -146,8 +145,8 @@ sbn::TriggerInfo_t sbn::SBNDBNBRetriever::extractTriggerInfo(art::Event const& e int sbn::SBNDBNBRetriever::matchMultiWireData( art::EventID const& eventID, - TriggerInfo_t const& triggerInfo, - MWRdata_t const& MWRdata, + sbn::pot::TriggerInfo_t const& triggerInfo, + sbn::pot::MWRdata_t const& MWRdata, std::vector< sbn::BNBSpillInfo >& beamInfos ) const { @@ -176,7 +175,7 @@ int sbn::SBNDBNBRetriever::matchMultiWireData( spills_removed++; continue;} - if(BrokenClock(times_temps[i], bfp)){ + if(sbn::pot::BrokenClock(times_temps[i], bfp)){ continue; } diff --git a/sbncode/BeamSpillInfoRetriever/SBNDBNBZEROBIASRetriever/CMakeLists.txt b/sbncode/BeamSpillInfoRetriever/SBNDBNBZEROBIASRetriever/CMakeLists.txt index 4c95779dd..7890fbd93 100644 --- a/sbncode/BeamSpillInfoRetriever/SBNDBNBZEROBIASRetriever/CMakeLists.txt +++ b/sbncode/BeamSpillInfoRetriever/SBNDBNBZEROBIASRetriever/CMakeLists.txt @@ -3,7 +3,7 @@ find_package(ifdh_art) cet_build_plugin(SBNDBNBZEROBIASRetriever art::module LIBRARIES - sbn_SBNDPOTTools + sbn_POTTools sbn_getFOM ) diff --git a/sbncode/BeamSpillInfoRetriever/SBNDBNBZEROBIASRetriever/SBNDBNBZEROBIASRetriever_module.cc b/sbncode/BeamSpillInfoRetriever/SBNDBNBZEROBIASRetriever/SBNDBNBZEROBIASRetriever_module.cc index 3e0fa2446..298e0df91 100644 --- a/sbncode/BeamSpillInfoRetriever/SBNDBNBZEROBIASRetriever/SBNDBNBZEROBIASRetriever_module.cc +++ b/sbncode/BeamSpillInfoRetriever/SBNDBNBZEROBIASRetriever/SBNDBNBZEROBIASRetriever_module.cc @@ -8,7 +8,7 @@ #include "art/Framework/Core/EDProducer.h" #include "messagefacility/MessageLogger/MessageLogger.h" #include "sbnobj/Common/POTAccounting/BNBSpillInfo.h" -#include "sbncode/BeamSpillInfoRetriever/SBNDPOTTools.h" +#include "sbncode/BeamSpillInfoRetriever/POTTools.h" #include "sbncode/BeamSpillInfoRetriever/getFOM.h" namespace sbn { @@ -44,11 +44,11 @@ class sbn::SBNDBNBZEROBIASRetriever : public art::EDProducer { std::vector< sbn::BNBSpillInfo > fOutbeamInfos; std::vector< sbn::BNBSpillInfo > fOutbeamInfosTotal; - TriggerInfo_t extractTriggerInfo(art::Event const& e) const; + sbn::pot::TriggerInfo_t extractTriggerInfo(art::Event const& e) const; void matchMultiWireData( art::EventID const& eventID, - TriggerInfo_t const& triggerInfo, - MWRdata_t const& MWRdata, + sbn::pot::TriggerInfo_t const& triggerInfo, + sbn::pot::MWRdata_t const& MWRdata, std::vector< sbn::BNBSpillInfo >& beamInfos ) const; unsigned int TotalBeamSpills; @@ -89,7 +89,7 @@ void sbn::SBNDBNBZEROBIASRetriever::produce(art::Event & e) return; } - TriggerInfo_t const triggerInfo = extractTriggerInfo(e); + sbn::pot::TriggerInfo_t const triggerInfo = extractTriggerInfo(e); if (triggerInfo.t_previous_event == 0) { auto p = std::make_unique< std::vector< sbn::BNBSpillInfo > >(); @@ -99,7 +99,7 @@ void sbn::SBNDBNBZEROBIASRetriever::produce(art::Event & e) } TotalBeamSpills += triggerInfo.number_of_gates_since_previous_event; - MWRdata_t const MWRdata = extractSpillTimes(triggerInfo, bfp, bfp_mwr, fTimePad, MWRtoroidDelay, mwrdata); + sbn::pot::MWRdata_t const MWRdata = extractSpillTimes(triggerInfo, bfp, bfp_mwr, fTimePad, MWRtoroidDelay, mwrdata); matchMultiWireData(e.id(), triggerInfo, MWRdata, fOutbeamInfos); fOutbeamInfosTotal.insert(fOutbeamInfosTotal.end(),fOutbeamInfos.begin(),fOutbeamInfos.end()); @@ -108,7 +108,7 @@ void sbn::SBNDBNBZEROBIASRetriever::produce(art::Event & e) e.put(std::move(p)); } -sbn::TriggerInfo_t sbn::SBNDBNBZEROBIASRetriever::extractTriggerInfo(art::Event const& e) const { +sbn::pot::TriggerInfo_t sbn::SBNDBNBZEROBIASRetriever::extractTriggerInfo(art::Event const& e) const { // Using TDC for current event, but PTB for previous event art::InputTag PTB_itag("daq", "ContainerPTB"); auto PTB_cont_frags = e.getHandle(PTB_itag); @@ -116,23 +116,23 @@ sbn::TriggerInfo_t sbn::SBNDBNBZEROBIASRetriever::extractTriggerInfo(art::Event art::InputTag TDC_itag("daq", "ContainerTDCTIMESTAMP"); auto TDC_cont_frags = e.getHandle(TDC_itag); - TriggerInfo_t triggerInfo; - PTBInfo_t PTBInfo = extractPTBInfo(PTB_cont_frags, 1); + sbn::pot::TriggerInfo_t triggerInfo; + sbn::pot::PTBInfo_t PTBInfo = sbn::pot::extractPTBInfo(PTB_cont_frags, 1); if (TDC_cont_frags) { - double TDCTimeStamp = extractTDCTimeStamp(TDC_cont_frags); + double TDCTimeStamp = sbn::pot::extractTDCTimeStamp(TDC_cont_frags); triggerInfo.t_current_event = TDCTimeStamp - fBESOffset; } else{ // If missing TDC, use PTB instead mf::LogDebug("SBNDBNBZEROBIASRetriever") << " Missing TDC Container Fragments!!!" << std::endl; - triggerInfo.t_current_event = PTBInfo.currPTBTimeStamp - fBESOffset; + triggerInfo.t_current_event = PTBInfo.currPTBTimeStamp / 1e9 - fBESOffset; } - triggerInfo.t_previous_event = PTBInfo.prevPTBTimeStamp - fBESOffset; + triggerInfo.t_previous_event = PTBInfo.prevPTBTimeStamp / 1e9 - fBESOffset; triggerInfo.number_of_gates_since_previous_event = PTBInfo.GateCounter; - double PTBandCurrOffset = PTBInfo.currPTBTimeStamp - triggerInfo.t_current_event - fBESOffset; + double PTBandCurrOffset = PTBInfo.currPTBTimeStamp / 1e9 - triggerInfo.t_current_event - fBESOffset; // Catch for an issue seen a few times where PTB off by a second. // Only need to correct prevTS because either currTS is from TDC @@ -148,8 +148,8 @@ sbn::TriggerInfo_t sbn::SBNDBNBZEROBIASRetriever::extractTriggerInfo(art::Event void sbn::SBNDBNBZEROBIASRetriever::matchMultiWireData( art::EventID const& eventID, - TriggerInfo_t const& triggerInfo, - MWRdata_t const& MWRdata, + sbn::pot::TriggerInfo_t const& triggerInfo, + sbn::pot::MWRdata_t const& MWRdata, std::vector< sbn::BNBSpillInfo >& beamInfos ) const { @@ -184,7 +184,7 @@ void sbn::SBNDBNBZEROBIASRetriever::matchMultiWireData( spills_removed++; continue;} - if(BrokenClock(times_temps[i], bfp)){ + if(sbn::pot::BrokenClock(times_temps[i], bfp)){ continue; } diff --git a/sbncode/BeamSpillInfoRetriever/SBNDPOTTools.h b/sbncode/BeamSpillInfoRetriever/SBNDPOTTools.h deleted file mode 100644 index a43b09691..000000000 --- a/sbncode/BeamSpillInfoRetriever/SBNDPOTTools.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef _SBNDPOTTOOLS_H -#define _SBNDPOTTOOLS_H - -#include "art/Framework/Principal/Event.h" -#include "art/Framework/Principal/Handle.h" -#include "messagefacility/MessageLogger/MessageLogger.h" -#include "ifdh_art/IFBeamService/IFBeam_service.h" - -#include "sbnobj/Common/POTAccounting/BNBSpillInfo.h" -#include "sbndaq-artdaq-core/Overlays/SBND/PTBFragment.hh" -#include "sbndaq-artdaq-core/Overlays/SBND/TDCTimestampFragment.hh" -#include "artdaq-core/Data/ContainerFragment.hh" - -#include "sbncode/BeamSpillInfoRetriever/MWRData.h" -#include "larcorealg/CoreUtils/counter.h" - -namespace sbn{ - typedef struct PTBInfo_t { - double currPTBTimeStamp = 1e20; - double prevPTBTimeStamp = 0; - unsigned int GateCounter = 0; - } PTBInfo_t; - - typedef struct TriggerInfo_t { - double t_current_event = 0; - double t_previous_event = 0; - unsigned int number_of_gates_since_previous_event = 0; - } TriggerInfo_t; - - typedef struct MWRdata_t { - std::vector< std::vector > MWR_times; - std::vector< std::vector< std::vector< int > > > unpacked_MWR; - } MWRdata_t; - - PTBInfo_t extractPTBInfo(art::Handle > cont_frags, int HLT); - double extractTDCTimeStamp(art::Handle > cont_frags); - bool BrokenClock(double time, std::unique_ptr const& bfp); - MWRdata_t extractSpillTimes(TriggerInfo_t const& triggerInfo, std::unique_ptr const& bfp, std::unique_ptr const& bfp_mwr, double fTimePad, double MWRtoroidDelay, sbn::MWRData mwrdata ); - sbn::BNBSpillInfo makeBNBSpillInfo(art::EventID const& eventID, double time, MWRdata_t const& MWRdata, std::vector const& matched_MWR, std::unique_ptr const& bfp, std::unique_ptr const& offsets, std::unique_ptr const& vp873); -} - -#endif