Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2026-07-16 08:13:56

0001 #ifndef Fun4All_TpcTimeFrameBuilderRun3_H
0002 #define Fun4All_TpcTimeFrameBuilderRun3_H
0003 
0004 #include "TpcTimeFrameBuilderBase.h"
0005 
0006 #include <algorithm>
0007 #include <array>
0008 #include <bitset>
0009 #include <cstdint>
0010 #include <deque>
0011 #include <functional>
0012 #include <iostream>
0013 #include <limits>
0014 #include <list>
0015 #include <map>
0016 #include <optional>
0017 #include <queue>
0018 #include <set>
0019 #include <string>
0020 #include <utility>
0021 #include <vector>
0022 
0023 class Packet;
0024 class TpcRawHit;
0025 class TpcRawHitv3;
0026 using TpcRawHitRun3_typ = TpcRawHitv3;
0027 class PHTimer;
0028 class TH1;
0029 class TH2;
0030 class TTree;
0031 
0032 // NOLINTNEXTLINE(hicpp-special-member-functions)
0033 class TpcTimeFrameBuilderRun3 : public TpcTimeFrameBuilderBase
0034 {
0035  public:
0036   explicit TpcTimeFrameBuilderRun3(const int packet_id);
0037   ~TpcTimeFrameBuilderRun3() override;
0038 
0039   // delete copy and move constructors and assignment operators to avoid unsafe copying
0040   TpcTimeFrameBuilderRun3(const TpcTimeFrameBuilderRun3&) = delete;
0041   TpcTimeFrameBuilderRun3& operator=(const TpcTimeFrameBuilderRun3&) = delete;
0042   TpcTimeFrameBuilderRun3(TpcTimeFrameBuilderRun3&&) = delete;
0043   TpcTimeFrameBuilderRun3& operator=(TpcTimeFrameBuilderRun3&&) = delete;
0044 
0045   int ProcessPacket(Packet *) override;
0046   bool isMoreDataRequired(const uint64_t &gtm_bco) const override;
0047   void CleanupUsedPackets(const uint64_t &bclk) override;
0048   std::vector<TpcRawHit *> &getTimeFrame(const uint64_t &gtm_bco) override;
0049 
0050   void setVerbosity(int i) override;
0051   void setFastBCOSkip(bool fastBCOSkip = true)
0052   {
0053     m_fastBCOSkip = fastBCOSkip;
0054   }
0055 
0056   void fillBadFeeMap() override;
0057 
0058   // enable saving of digital current debug TTree with file name `name`
0059   void SaveDigitalCurrentDebugTTree(const std::string &name) override;
0060   void SaveBXCounterSyncCDBTTree(const std::string &name) override;
0061 
0062  protected:
0063   // Length for the 256-bit wide Round Robin Multiplexer for the data stream
0064   static const size_t DAM_DMA_WORD_LENGTH = 16;
0065 
0066   static const uint16_t FEE_PACKET_MAGIC_KEY_1 = 0xfe;
0067   static const uint16_t FEE_PACKET_MAGIC_KEY_2 = 0xed;
0068   static const uint16_t FEE_PACKET_MAGIC_KEY_3_DC = 0xdcdc;  // Digital Current word[3]
0069 
0070   static const uint16_t FEE_MAGIC_KEY = 0xba00;
0071   static const uint16_t GTM_MAGIC_KEY = 0xbb00;
0072   static const uint16_t GTM_LVL1_ACCEPT_MAGIC_KEY = 0xbbf0;
0073   static const uint16_t GTM_ENDAT_MAGIC_KEY = 0xbbf1;
0074   static const uint16_t GTM_MODEBIT_MAGIC_KEY = 0xbbf2;
0075 
0076   static const uint16_t MAX_FEECOUNT = 26;              // that many FEEs
0077   static const uint16_t MAX_SAMPA = 8;                  // that many FEEs
0078   static const uint16_t MAX_CHANNELS = MAX_SAMPA * 32;  // that many channels per FEE
0079                                                         //  static const uint16_t  HEADER_LENGTH  = 5;
0080   static const uint16_t HEADER_LENGTH = 7;
0081   static const uint16_t MAX_PACKET_LENGTH = 1025;
0082 
0083   static const uint16_t GL1_BCO_MATCH_WINDOW = 256;  // BCOs
0084 
0085   int m_hitFormat = -1;
0086 
0087   uint16_t reverseBits(const uint16_t x) const;
0088   std::pair<uint16_t, uint16_t> crc16_parity(const uint32_t fee, const uint16_t l) const;
0089 
0090   //! DMA word structure
0091   struct dma_word
0092   {
0093     uint16_t dma_header = 0;
0094     uint16_t data[DAM_DMA_WORD_LENGTH - 1] = {0};
0095   };
0096 
0097   int decode_gtm_data(const dma_word &gtm_word);
0098   int process_fee_data(unsigned int fee_id);
0099   void process_fee_data_waveform(const unsigned int &fee_id, std::deque<uint16_t> &data_buffer);
0100   void process_fee_data_digital_current(const unsigned int &fee_id, std::deque<uint16_t> &data_buffer);
0101 
0102   struct gtm_payload
0103   {
0104     uint16_t pkt_type = 0;
0105     bool is_endat = false;
0106     bool is_lvl1 = false;
0107     bool is_modebit = false;
0108     uint64_t bco = 0;
0109     uint32_t lvl1_count = 0;
0110     uint32_t endat_count = 0;
0111     uint64_t last_bco = 0;
0112     uint8_t modebits = 0;
0113     uint8_t userbits = 0;
0114   };
0115 
0116   struct fee_payload
0117   {
0118     uint16_t fee_id = 0;
0119     uint16_t adc_length = 0;
0120     uint16_t sampa_address = 0;
0121     uint16_t sampa_channel = 0;
0122     uint16_t channel = 0;
0123     uint16_t type = 0;
0124     uint16_t user_word = 0;
0125     uint32_t bx_timestamp = 0;
0126     uint64_t gtm_bco = 0;
0127     bool has_clock_sync = false;
0128 
0129     uint16_t data_crc = 0;
0130     uint16_t calc_crc = 0;
0131 
0132     uint16_t data_parity = 0;
0133     uint16_t calc_parity = 0;
0134 
0135     std::vector<std::pair<uint16_t, std::vector<uint16_t>>> waveforms;
0136   };
0137 
0138   struct digital_current_payload
0139   {
0140     static const int MAX_CHANNELS = 8;
0141 
0142     uint64_t gtm_bco{std::numeric_limits<uint64_t>::max()};
0143     uint32_t bx_timestamp_predicted{std::numeric_limits<uint32_t>::max()};
0144 
0145     uint16_t fee{std::numeric_limits<uint16_t>::max()};
0146     uint16_t pkt_length{std::numeric_limits<uint16_t>::max()};
0147     uint16_t channel{std::numeric_limits<uint16_t>::max()};
0148     // uint16_t sampa_max_channel {std::numeric_limits<uint16_t>::max()};
0149     uint16_t sampa_address{std::numeric_limits<uint16_t>::max()};
0150     uint32_t bx_timestamp{0};
0151     uint32_t current[MAX_CHANNELS]{0};
0152     uint32_t nsamples[MAX_CHANNELS]{0};
0153     uint16_t data_crc{std::numeric_limits<uint16_t>::max()};
0154     uint16_t calc_crc = {std::numeric_limits<uint16_t>::max()};
0155     // uint16_t type {std::numeric_limits<uint16_t>::max()};
0156   };
0157 
0158   class DigitalCurrentDebugTTree
0159   {
0160    public:
0161     explicit DigitalCurrentDebugTTree(const std::string &name);
0162     virtual ~DigitalCurrentDebugTTree();
0163 
0164     void fill(const digital_current_payload &payload);
0165 
0166    private:
0167     digital_current_payload m_payload;
0168 
0169     std::string m_name;
0170     TTree *m_tDigitalCurrent = nullptr;
0171   };
0172   DigitalCurrentDebugTTree *m_digitalCurrentDebugTTree = nullptr;
0173 
0174   // -------------------------
0175   // GTM Matcher
0176   // Initially developped by Hugo Pereira Da Costa as `MicromegasBcoMatchingInformation`
0177   // -------------------------
0178   class BcoMatchingInformation
0179   {
0180    public:
0181     //! constructor
0182     explicit BcoMatchingInformation(const std::string &name);
0183 
0184     //!@name accessor
0185     //@{
0186 
0187     //! verbosity
0188     int verbosity() const
0189     {
0190       return m_verbosity;
0191     }
0192 
0193     //! true if matching information is verified
0194     /**
0195      * matching information is verified if at least one match
0196      * between gtm_bco and fee_bco is found
0197      */
0198     bool is_verified() const
0199     {
0200       return m_verified_from_modebits || m_verified_from_data;
0201     }
0202 
0203     //! matching between fee bco and lvl1 bco
0204     using m_gtm_fee_bco_matching_pair_t = std::pair<uint64_t, uint32_t>;
0205     using m_fee_gtm_bco_matching_pair_t = std::pair<uint32_t, uint64_t>;
0206     struct BXCounterSyncObservation
0207     {
0208       uint64_t bx_counter_sync_gtm_bco = 0;
0209       uint64_t bco_reference_gtm_bco = 0;
0210       m_gtm_fee_bco_matching_pair_t m_bco_reference = {0, 0};
0211     };
0212 
0213     //! expect two but tollerate up to four BX_COUNTER_SYNC_T observations to define the reference clock, depending on data quality. The first few observations will be saved in the CDB for future reference.
0214     static constexpr size_t kMaxBXCounterSyncObservations = 4;
0215 
0216     //! get reference bco
0217     const std::optional<m_gtm_fee_bco_matching_pair_t> &get_reference_bco() const
0218     {
0219       return m_bco_reference;
0220     }
0221 
0222     const std::array<BXCounterSyncObservation, kMaxBXCounterSyncObservations> &get_bx_counter_sync_observations() const
0223     {
0224       return m_bx_counter_sync_observations;
0225     }
0226 
0227     size_t get_bx_counter_sync_observation_count() const
0228     {
0229       return m_bx_counter_sync_observation_count;
0230     }
0231 
0232     //! whether FEE data has moved pass the given gtm_bco
0233     bool isMoreDataRequired(const uint64_t &gtm_bco) const;
0234 
0235     //! get predicted fee_bco from gtm_bco
0236     std::optional<uint32_t> get_predicted_fee_bco(uint64_t) const;
0237 
0238     //! print gtm bco information
0239     void print_gtm_bco_information() const;
0240 
0241     //! get size of m_gtm_bco_trig_list
0242     size_t get_gtm_bco_trig_list_size() const
0243     {
0244       return m_gtm_bco_trig_list.size();
0245     }
0246 
0247     //! get size of m_bco_heartbeat_list
0248     size_t get_bco_heartbeat_list_size() const
0249     {
0250       return m_bco_heartbeat_list.size();
0251     }
0252 
0253     //! get size of m_gtm_bco_trigger_map
0254     size_t get_gtm_bco_trigger_map_size() const
0255     {
0256       return m_gtm_bco_trigger_map.size();
0257     }
0258 
0259     //! get size of m_bco_matching_list
0260     size_t get_bco_matching_list_size() const
0261     {
0262       return m_bco_matching_list.size();
0263     }
0264 
0265     //@}
0266 
0267     //!@name modifiers
0268     //@{
0269 
0270     //! verbosity
0271     void set_verbosity(int value)
0272     {
0273       m_verbosity = value;
0274     }
0275 
0276     /// set gtm clock with rollover correction
0277     uint64_t get_gtm_rollover_correction(const uint64_t &gtm_bco) const;
0278 
0279     //! find reference from data
0280     std::optional<uint64_t> find_reference_heartbeat(const fee_payload &HeartBeatPacket);
0281 
0282     //! save all GTM BCO clocks from packet data
0283     void save_gtm_bco_information(const gtm_payload &gtm_tagger);
0284 
0285     // //! find gtm bco matching a given fee
0286     // std::optional<uint64_t> find_gtm_bco(uint32_t /*fee_gtm*/);
0287 
0288     //! cleanup
0289     void cleanup();
0290 
0291     //! cleanup
0292     void cleanup(uint64_t /*ref_bco*/);
0293 
0294     m_gtm_fee_bco_matching_pair_t find_dc_read_bco() const
0295     {
0296       return m_gtm_bco_dc_read;
0297     }
0298     //@}
0299 
0300     /* see: https://git.racf.bnl.gov/gitea/Instrumentation/sampa_data/src/branch/fmtv2/README.md */
0301     enum SampaDataType
0302     {
0303       HEARTBEAT_T = 0b000,
0304       TRUNCATED_DATA_T = 0b001,
0305       TRUNCATED_TRIG_EARLY_DATA_T = 0b011,
0306       NORMAL_DATA_T = 0b100,
0307       LARGE_DATA_T = 0b101,
0308       TRIG_EARLY_DATA_T = 0b110,
0309       TRIG_EARLY_LARGE_DATA_T = 0b111,
0310     };
0311 
0312     // Command   | OLD Mode-Bit | New Mode-Number | Function
0313     // ======================================================
0314     // NOP       |     0b000    |             0x0 | No Operation
0315     // BX_SYNC   |     0b001    |             0x1 | SAMPA Beam-crossing sync
0316     // H_BEAT    |     0b010    |             0x2 | Generates Heartbeat frame
0317     // TRIG      |     0b100    |             0x3 | Trigger data when FEM user bit is 0b01, otherwise the level 1 accept is used when FEM user bit is 0b00
0318     // CLK_SYNC  |     N/A      |             0x4 | Reset and align 40 MHz and 20 MHz clocks to SAMPA
0319     // SAMPA_RST |     N/A      |             0x5 | Hard reset SAMPA
0320     // DC_START  |     N/A      |             0x6 | Start digital current reading
0321     // DC_STOP   |     N/A      |             0x7 | Stop and send digital current packet
0322     enum ModeBitType
0323     {
0324       BX_COUNTER_SYNC_T = 0x1,
0325       ELINK_HEARTBEAT_T = 0x2,
0326       DC_STOP_SEND_T = 0x7
0327       // SAMPA_EVENT_TRIGGER_T = 2,
0328       // CLEAR_LV1_LAST_T = 6,
0329       // CLEAR_LV1_ENDAT_T = 7
0330     };
0331 
0332     // get the difference between two BCO WITHOUT rollover corrections
0333     template <class T>
0334     inline static constexpr T get_bco_diff(
0335         const T &first, const T &second)
0336     {
0337       return first < second ? (second - first) : (first - second);
0338     }
0339 
0340     // get the difference between two BCO with rollover corrections
0341     inline static constexpr uint32_t get_fee_bco_diff(
0342         const uint32_t &first, const uint32_t &second)  // NOLINT(misc-unused-parameters)
0343     {
0344       const uint32_t diff_raw = get_bco_diff(first, second);
0345       const uint32_t half_range = 1U << (m_FEE_CLOCK_BITS - 1);
0346       const uint32_t full_range = 1U << m_FEE_CLOCK_BITS;
0347       return (diff_raw <= half_range) ? diff_raw : full_range - diff_raw;
0348     }
0349 
0350    private:
0351     void save_bx_counter_sync_observation(uint64_t bx_counter_sync_gtm_bco,
0352                                           uint64_t bco_reference_gtm_bco,
0353                                           const m_gtm_fee_bco_matching_pair_t &bco_reference);
0354 
0355     std::string m_name;
0356 
0357     //! verbosity
0358     unsigned int m_verbosity = 0;
0359 
0360     //! verified
0361     bool m_verified_from_modebits = false;
0362 
0363     bool m_verified_from_data = false;
0364 
0365     //! list of available bco, sorted in time with rollover corrected
0366     std::list<uint64_t> m_gtm_bco_trig_list;
0367 
0368     //! last digital current readout GTM BCO
0369     m_gtm_fee_bco_matching_pair_t m_gtm_bco_dc_read = {0, 0};
0370 
0371     //! list of available GTM -> FEE bco mapping for synchronization
0372     std::optional<m_gtm_fee_bco_matching_pair_t> m_bco_reference = std::nullopt;
0373 
0374     //! first BX_COUNTER_SYNC_T observations saved for future CDB reference studies
0375     std::array<BXCounterSyncObservation, kMaxBXCounterSyncObservations> m_bx_counter_sync_observations;
0376     size_t m_bx_counter_sync_observation_count = 0;
0377 
0378     // std::optional< std::pair< uint64_t, uint32_t > > m_bco_reference_candidate = std::nullopt;
0379     //! not yet matched heart beats
0380     std::list<m_gtm_fee_bco_matching_pair_t> m_bco_heartbeat_list;
0381     static constexpr unsigned int m_max_bco_heartbeat_list_size = 16;
0382 
0383     // //! list of heart beat GTM BCO that is still to be matched
0384     // std::queue<uint64_t> m_heartbeat_gtm_bco_queue;
0385     // static constexpr unsigned int m_max_heartbeat_queue_size = 16;
0386 
0387     //! list of available GTM -> FEE bco mapping for trigger association
0388     std::map<uint64_t, uint32_t> m_gtm_bco_trigger_map;
0389 
0390     std::list<m_fee_gtm_bco_matching_pair_t> m_bco_matching_list;
0391 
0392     // define limit for matching two lvl1 and EnDAT tagger BCOs
0393     static constexpr int m_max_lv1_endat_bco_diff = 16;
0394 
0395     // define limit for matching two fee_bco
0396     static constexpr unsigned int m_max_fee_bco_diff = 64;
0397 
0398     // define limit for matching gtm_bco from lvl1 to enddat
0399 
0400     // define limit for matching fee_bco to fee_bco_predicted
0401     static constexpr unsigned int m_max_gtm_bco_diff = 256;
0402 
0403     //   // needed to avoid memory leak. Assumes that we will not be assembling more than 50 events at the same time
0404     static constexpr unsigned int m_max_matching_data_size = 10;
0405 
0406     //! max time in GTM BCO for FEE data to sync over to datastream
0407     static constexpr unsigned int m_max_fee_sync_time = 1024 * 8;
0408 
0409     //! fixed GTM BCO offset applied when BX_COUNTER_SYNC_T defines the reference clock
0410     static constexpr uint64_t kBXCounterSyncGtmBcoOffset = 0;
0411     //! fixed FEE BCO offset applied when BX_COUNTER_SYNC_T defines the reference clock
0412     static constexpr uint64_t kBXCounterSyncFEEBcoOffset = 12;
0413 
0414     static constexpr unsigned int m_FEE_CLOCK_BITS = 20;
0415     static constexpr unsigned int m_GTM_CLOCK_BITS = 40;
0416 
0417     //! Run3 FEE firmware
0418     static constexpr int64_t m_clock_ratio_numerator = 30;
0419     static constexpr int64_t m_clock_ratio_denominator = 8;
0420 
0421     TH1 *m_hNorm = nullptr;
0422     TH1 *m_hFEEClockAdjustment_MatchedReference = nullptr;
0423     TH1 *m_hFEEClockAdjustment_MatchedNew = nullptr;
0424     TH1 *m_hFEEClockAdjustment_Unmatched = nullptr;
0425     TH1 *m_hGTMNewEventSpacing = nullptr;
0426     // TH1 *m_hFindGTMBCO_MatchedExisting_BCODiff = nullptr;
0427     // TH1 *m_hFindGTMBCO_MatchedNew_BCODiff = nullptr;
0428 
0429   };  //   class BcoMatchingInformation
0430 
0431  private:
0432   std::vector<std::deque<uint16_t>> m_feeData;
0433 
0434   std::map<int, std::set<int>> m_maskedFEEs;
0435 
0436   int m_verbosity = 0;
0437   int m_packet_id = 0;
0438 
0439   //! common prefix for QA histograms
0440   std::string m_HistoPrefix;
0441   std::string m_bxCounterSyncCDBTTreeName;
0442 
0443   static constexpr uint32_t kFEEClockMask = (1U << 20U) - 1U;
0444   static constexpr uint32_t kRun3FeeMatchWindow = (GL1_BCO_MATCH_WINDOW * 30U + 7U) / 8U;
0445   static constexpr int32_t kRun3ExactMatchWindow = 6; // allow for 1BCO offset from different clock freq. + 1BCO for possible missing first sync
0446   static constexpr uint32_t kRun3FEEClockPerADCClock = 2U;
0447   static constexpr uint32_t kRun3TruncatedWaveformRecoveryWindow = 1024U;
0448   static constexpr uint32_t kRun3TruncatedWaveformRecoveryFEEWindow =
0449       kRun3TruncatedWaveformRecoveryWindow * kRun3FEEClockPerADCClock;
0450   static constexpr int kRun3NormalizationBaseBinCount = 20;
0451   static constexpr int kRun3NormalizationBinCount = kRun3NormalizationBaseBinCount + MAX_FEECOUNT;
0452 
0453   static int64_t get_signed_fee_bco_diff(uint32_t first, uint32_t second);
0454   static uint32_t get_fee_bco_diff(uint32_t first, uint32_t second);
0455   size_t move_time_hits(uint32_t fee_bco, uint16_t fee, std::vector<TpcRawHit *> &timeframe);
0456   size_t count_time_hits(uint32_t fee_bco, uint16_t fee) const;
0457   size_t time_hit_bucket_count() const;
0458   std::optional<uint32_t> find_fuzzy_fee_bco(uint32_t predicted_fee_bco, uint16_t fee) const;
0459   size_t recover_truncated_waveforms(uint32_t predicted_fee_bco, uint16_t fee, std::vector<TpcRawHit *> &timeframe);
0460   size_t append_shifted_waveforms(TpcRawHitRun3_typ *target, const TpcRawHit &source, uint32_t fee_clock_shift) const;
0461   void cleanup_time_hit_map(uint64_t bclk_rollover_corrected, uint32_t fee_clock_window);
0462   void flush_previous_timeframe_qa_cache(uint64_t current_gtm_bco);
0463   void fill_waveform_gl1_spacing(TH1 *waveform_adc_cache, TH2 *waveform_gl1_spacing, uint64_t gtm_bco_spacing) const;
0464   void cache_waveform_adc(TH1 *waveform_adc_cache, const std::vector<TpcRawHit *> &timeframe) const;
0465   void cache_timeframe_qa(uint64_t gtm_bco, const std::vector<TpcRawHit *> &timeframe, const std::bitset<MAX_FEECOUNT> &exact_matched_fees);
0466   void write_bx_counter_sync_cdb_tree() const;
0467 
0468   //! FEE -> FEE BCO -> cached TpcRawHit for Run3 exact-ratio matching
0469   std::vector<std::map<uint32_t, std::vector<TpcRawHit *>>> m_timeHitMap;
0470 
0471   //! rollover-corrected GTM BCO -> matched TpcRawHit returned to the input manager
0472   std::map<uint64_t, std::vector<TpcRawHit *>> m_timeFrameMap;
0473 
0474   //! previous timeframe QA state, filled once the next GTM BCO defines the GL1 spacing
0475   std::optional<uint64_t> m_previousTimeFrameGtmBco;
0476   std::bitset<MAX_FEECOUNT> m_previousTimeFrameExactFees;
0477   std::bitset<MAX_FEECOUNT> m_previousTimeFrameRecoveredFees;
0478   int m_hNormTruncatedWaveformRecoveryFeeFirstBin = 0;
0479   static const size_t kMaxRawHitLimit = 10000;  // 10k hits per event > 256ch/fee * 26fee
0480   std::queue<uint64_t> m_UsedTimeFrameSet;
0481 
0482   //! fast skip mode when searching for particular GL1 BCO over long segment of files
0483   bool m_fastBCOSkip = false;
0484 
0485   //! map bco_information_t to packet id
0486   std::vector<BcoMatchingInformation> m_bcoMatchingInformation_vec;
0487 
0488   //! QA area
0489 
0490   PHTimer *m_packetTimer = nullptr;
0491 
0492   TH1 *m_hNorm = nullptr;
0493   TH2 *m_hFEEDataStream = nullptr;
0494   TH1 *m_hFEEChannelPacketCount = nullptr;
0495   TH2 *m_hFEESAMPAADC = nullptr;
0496   TH1 *m_hFEESAMPAHeartBeatSync = nullptr;
0497 
0498   TH1 *h_PacketLength = nullptr;
0499   TH1 *h_PacketLength_Padding = nullptr;
0500   TH1 *h_PacketLength_Residual = nullptr;
0501 
0502   TH1 *h_GTMClockDiff_Matched = nullptr;
0503   TH1 *h_GTMClockDiff_Unmatched = nullptr;
0504   TH1 *h_GTMClockDiff_Dropped = nullptr;
0505   TH1 *h_TimeFrame_Matched_Size = nullptr;
0506   TH2 *h_Run3_FEE_GTMMatching_ClockDiff = nullptr;
0507   TH1 *h_Run3TimeFrameExactHit_FEE = nullptr;
0508   TH1 *h_Run3TimeFrameFuzzyHit_FEE = nullptr;
0509   TH1 *h_Run3PreviousTimeFrameWaveformADC = nullptr;
0510   TH1 *h_Run3PreviousTimeFrameRecoveredWaveformADC = nullptr;
0511   TH2 *h_Run3Waveform_GL1Spacing = nullptr;
0512   TH2 *h_Run3WaveformRecovered_GL1Spacing = nullptr;
0513   TH2 *h_Run3FEE_TimeFrameCount_GL1Spacing = nullptr;
0514   TH2 *h_Run3FEE_TimeFrameRecoveredCount_GL1Spacing = nullptr;
0515   TH2 *h_Run3FEE_TriggerCount_GL1Spacing = nullptr;
0516 
0517   TH2 *h_ProcessPacket_Time = nullptr;
0518 };
0519 
0520 #endif