Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:10:41

0001 #include "EventFilter/GctRawToDigi/src/GctFormatTranslateV38.h"
0002 
0003 // C++ headers
0004 #include <iostream>
0005 #include <cassert>
0006 #include <algorithm>
0007 #include <cmath>
0008 
0009 // Framework headers
0010 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0011 
0012 // Namespace resolution
0013 using std::cout;
0014 using std::endl;
0015 using std::make_pair;
0016 using std::pair;
0017 
0018 // INITIALISE STATIC VARIABLES
0019 /*** Setup BlockID to BlockLength Map ***/
0020 const GctFormatTranslateV38::BlockLengthMap GctFormatTranslateV38::m_blockLength = {
0021     // Miscellaneous Blocks
0022     {0x000, 0},  // NULL
0023     // ConcJet FPGA
0024     {0x580, 12},  // ConcJet: Input TrigPathA (Jet Cands)
0025     {0x581, 2},   // ConcJet: Input TrigPathB (HF Rings)
0026     {0x582, 4},   // ConcJet: Input TrigPathC (MissHt)
0027     {0x583, 8},   // ConcJet: Jet Cands and Counts Output to GT
0028     {0x587, 4},   // ConcJet: BX & Orbit Info
0029     // ConcElec FPGA
0030     {0x680, 16},  // ConcElec: Input TrigPathA (EM Cands)
0031     {0x681, 6},   // ConcElec: Input TrigPathB (Et Sums)
0032     {0x682, 2},   // ConcElec: Input TrigPathC (Ht Sums)
0033     {0x683, 6},   // ConcElec: EM Cands and Energy Sums Output to GT
0034     {0x686, 2},   // ConcElec: Test (GT Serdes Loopback)
0035     {0x687, 4},   // ConcElec: BX & Orbit Info
0036     // Electron Leaf FPGAs
0037     {0x800, 20},  // Leaf0ElecPosEtaU1: Sort Input
0038     {0x803, 4},   // Leaf0ElecPosEtaU1: Sort Output
0039     {0x804, 15},  // Leaf0ElecPosEtaU1: Raw Input
0040     {0x880, 16},  // Leaf0ElecPosEtaU2: Sort Input
0041     {0x883, 4},   // Leaf0ElecPosEtaU2: Sort Output
0042     {0x884, 12},  // Leaf0ElecPosEtaU2: Raw Input
0043     {0xc00, 20},  // Leaf0ElecNegEtaU1: Sort Input
0044     {0xc03, 4},   // Leaf0ElecNegEtaU1: Sort Output
0045     {0xc04, 15},  // Leaf0ElecNegEtaU1: Raw Input
0046     {0xc80, 16},  // Leaf0ElecNegEtaU2: Sort Input
0047     {0xc83, 4},   // Leaf0ElecNegEtaU2: Sort Output
0048     {0xc84, 12},  // Leaf0ElecNegEtaU2: Raw Input
0049     // Wheel Pos-eta Jet FPGA
0050     {0x300, 27},  // WheelPosEtaJet: Input TrigPathA (Jet Sort)
0051     {0x301, 3},   // WheelPosEtaJet: Input TrigPathB (MissHt)
0052     {0x303, 6},   // WheelPosEtaJet: Output TrigPathA (Jet Sort)
0053     {0x305, 2},   // WheelPosEtaJet: Output TrigPathB (MissHt)
0054     {0x306,
0055      32},  // WheelPosEtaJet: Test (deprecated)  (Doesn't exist in V27.1 format, but does in V24 & V25, so keep for CRUZET2 data compatibility reasons)
0056     {0x307,
0057      4},  // WheelPosEtaJet: Info (deprecated)  (Doesn't exist in V27.1 format, but does in V24 & V25, so keep for CRUZET2 data compatibility reasons)
0058     // Wheel Pos-eta Energy FPGA
0059     {0x380, 21},  // WheelPosEtaEnergy: Input TrigPathA (Et)
0060     {0x381, 6},   // WheelPosEtaEnergy: Input TrigPathB (Ht)
0061     {0x383, 7},   // WheelPosEtaEnergy: Output TrigPathA (Et)
0062     {0x385, 2},   // WheelPosEtaEnergy: Output TrigPathB (Ht)
0063     {0x386, 32},  // WheelPosEtaEnergy: Test
0064     {0x387,
0065      6},  // WheelPosEtaEnergy: BX & Orbit Info   (Potential data incompatibility between V24/V25 where block length=4, and V27.1 where block length=6)
0066     // Wheel Neg-eta Jet FPGA
0067     {0x700, 27},  // WheelNegEtaJet: Input TrigPathA (Jet Sort)
0068     {0x701, 3},   // WheelNegEtaJet: Input TrigPathB (MissHt)
0069     {0x703, 6},   // WheelNegEtaJet: Output TrigPathA (Jet Sort)
0070     {0x705, 2},   // WheelNegEtaJet: Output TrigPathB (MissHt)
0071     {0x706,
0072      32},  // WheelNegEtaJet: Test (deprecated)  (Doesn't exist in V27.1 format, but does in V24 & V25, so keep for CRUZET2 data compatibility reasons)
0073     {0x707,
0074      4},  // WheelNegEtaJet: Info (deprecated)  (Doesn't exist in V27.1 format, but does in V24 & V25, so keep for CRUZET2 data compatibility reasons)
0075     // Wheel Neg-eta Energy FPGA
0076     {0x780, 21},  // WheelNegEtaEnergy: Input TrigPathA (Et)
0077     {0x781, 6},   // WheelNegEtaEnergy: Input TrigPathB (Ht)
0078     {0x783, 7},   // WheelNegEtaEnergy: Output TrigPathA (Et)
0079     {0x785, 2},   // WheelNegEtaEnergy: Output TrigPathB (Ht)
0080     {0x786, 32},  // WheelNegEtaEnergy: Test
0081     {0x787,
0082      6},  // WheelNegEtaEnergy: BX & Orbit Info   (Potential data incompatibility between V24/V25 where block length=4, and V27.1 where block length=6)
0083     // Jet Leaf FPGAs - Positive Eta
0084     {0x900, 13},  // Leaf1JetPosEtaU1: JF2 Input
0085     {0x901, 3},   // Leaf1JetPosEtaU1: JF2 Shared Received
0086     {0x902, 3},   // Leaf1JetPosEtaU1: JF2 Shared Sent
0087     {0x903, 10},  // Leaf1JetPosEtaU1: JF2 Output
0088     {0x904, 8},   // Leaf1JetPosEtaU1: JF2 Raw Input
0089     {0x908, 13},  // Leaf1JetPosEtaU1: JF3 Input
0090     {0x909, 3},   // Leaf1JetPosEtaU1: JF3 Shared Received
0091     {0x90a, 3},   // Leaf1JetPosEtaU1: JF3 Shared Sent
0092     {0x90b, 10},  // Leaf1JetPosEtaU1: JF3 Output
0093     {0x90c, 8},   // Leaf1JetPosEtaU1: JF3 Raw Input
0094     {0x980, 6},   // Leaf1JetPosEtaU2: Eta0 Input
0095     {0x984, 6},   // Leaf1JetPosEtaU2: Eta0 Raw Input
0096     {0x988, 13},  // Leaf1JetPosEtaU2: JF1 Input
0097     {0x989, 3},   // Leaf1JetPosEtaU2: JF1 Shared Received
0098     {0x98a, 3},   // Leaf1JetPosEtaU2: JF1 Shared Sent
0099     {0x98b, 10},  // Leaf1JetPosEtaU2: JF1 Output
0100     {0x98c, 8},   // Leaf1JetPosEtaU2: JF1 Raw Input
0101     {0xa00, 13},  // Leaf2JetPosEtaU1: JF2 Input
0102     {0xa01, 3},   // Leaf2JetPosEtaU1: JF2 Shared Received
0103     {0xa02, 3},   // Leaf2JetPosEtaU1: JF2 Shared Sent
0104     {0xa03, 10},  // Leaf2JetPosEtaU1: JF2 Output
0105     {0xa04, 8},   // Leaf2JetPosEtaU1: JF2 Raw Input
0106     {0xa08, 13},  // Leaf2JetPosEtaU1: JF3 Input
0107     {0xa09, 3},   // Leaf2JetPosEtaU1: JF3 Shared Received
0108     {0xa0a, 3},   // Leaf2JetPosEtaU1: JF3 Shared Sent
0109     {0xa0b, 10},  // Leaf2JetPosEtaU1: JF3 Output
0110     {0xa0c, 8},   // Leaf2JetPosEtaU1: JF3 Raw Input
0111     {0xa80, 6},   // Leaf2JetPosEtaU2: Eta0 Input
0112     {0xa84, 6},   // Leaf2JetPosEtaU2: Eta0 Raw Input
0113     {0xa88, 13},  // Leaf2JetPosEtaU2: JF1 Input
0114     {0xa89, 3},   // Leaf2JetPosEtaU2: JF1 Shared Received
0115     {0xa8a, 3},   // Leaf2JetPosEtaU2: JF1 Shared Sent
0116     {0xa8b, 10},  // Leaf2JetPosEtaU2: JF1 Output
0117     {0xa8c, 8},   // Leaf2JetPosEtaU2: JF1 Raw Input
0118     {0xb00, 13},  // Leaf3JetPosEtaU1: JF2 Input
0119     {0xb01, 3},   // Leaf3JetPosEtaU1: JF2 Shared Received
0120     {0xb02, 3},   // Leaf3JetPosEtaU1: JF2 Shared Sent
0121     {0xb03, 10},  // Leaf3JetPosEtaU1: JF2 Output
0122     {0xb04, 8},   // Leaf3JetPosEtaU1: JF2 Raw Input
0123     {0xb08, 13},  // Leaf3JetPosEtaU1: JF3 Input
0124     {0xb09, 3},   // Leaf3JetPosEtaU1: JF3 Shared Received
0125     {0xb0a, 3},   // Leaf3JetPosEtaU1: JF3 Shared Sent
0126     {0xb0b, 10},  // Leaf3JetPosEtaU1: JF3 Output
0127     {0xb0c, 8},   // Leaf3JetPosEtaU1: JF3 Raw Input
0128     {0xb80, 6},   // Leaf3JetPosEtaU2: Eta0 Input
0129     {0xb84, 6},   // Leaf3JetPosEtaU2: Eta0 Raw Input
0130     {0xb88, 13},  // Leaf3JetPosEtaU2: JF1 Input
0131     {0xb89, 3},   // Leaf3JetPosEtaU2: JF1 Shared Received
0132     {0xb8a, 3},   // Leaf3JetPosEtaU2: JF1 Shared Sent
0133     {0xb8b, 10},  // Leaf3JetPosEtaU2: JF1 Output
0134     {0xb8c, 8},   // Leaf3JetPosEtaU2: JF1 Raw Input
0135     // Jet Leaf FPGAs - Negative Eta
0136     {0xd00, 13},  // Leaf1JetNegEtaU1: JF2 Input
0137     {0xd01, 3},   // Leaf1JetNegEtaU1: JF2 Shared Received
0138     {0xd02, 3},   // Leaf1JetNegEtaU1: JF2 Shared Sent
0139     {0xd03, 10},  // Leaf1JetNegEtaU1: JF2 Output
0140     {0xd04, 8},   // Leaf1JetNegEtaU1: JF2 Raw Input
0141     {0xd08, 13},  // Leaf1JetNegEtaU1: JF3 Input
0142     {0xd09, 3},   // Leaf1JetNegEtaU1: JF3 Shared Received
0143     {0xd0a, 3},   // Leaf1JetNegEtaU1: JF3 Shared Sent
0144     {0xd0b, 10},  // Leaf1JetNegEtaU1: JF3 Output
0145     {0xd0c, 8},   // Leaf1JetNegEtaU1: JF3 Raw Input
0146     {0xd80, 6},   // Leaf1JetNegEtaU2: Eta0 Input
0147     {0xd84, 6},   // Leaf1JetNegEtaU2: Eta0 Raw Input
0148     {0xd88, 13},  // Leaf1JetNegEtaU2: JF1 Input
0149     {0xd89, 3},   // Leaf1JetNegEtaU2: JF1 Shared Received
0150     {0xd8a, 3},   // Leaf1JetNegEtaU2: JF1 Shared Sent
0151     {0xd8b, 10},  // Leaf1JetNegEtaU2: JF1 Output
0152     {0xd8c, 8},   // Leaf1JetNegEtaU2: JF1 Raw Input
0153     {0xe00, 13},  // Leaf2JetNegEtaU1: JF2 Input
0154     {0xe01, 3},   // Leaf2JetNegEtaU1: JF2 Shared Received
0155     {0xe02, 3},   // Leaf2JetNegEtaU1: JF2 Shared Sent
0156     {0xe03, 10},  // Leaf2JetNegEtaU1: JF2 Output
0157     {0xe04, 8},   // Leaf2JetNegEtaU1: JF2 Raw Input
0158     {0xe08, 13},  // Leaf2JetNegEtaU1: JF3 Input
0159     {0xe09, 3},   // Leaf2JetNegEtaU1: JF3 Shared Received
0160     {0xe0a, 3},   // Leaf2JetNegEtaU1: JF3 Shared Sent
0161     {0xe0b, 10},  // Leaf2JetNegEtaU1: JF3 Output
0162     {0xe0c, 8},   // Leaf2JetNegEtaU1: JF3 Raw Input
0163     {0xe80, 6},   // Leaf2JetNegEtaU2: Eta0 Input
0164     {0xe84, 6},   // Leaf2JetNegEtaU2: Eta0 Raw Input
0165     {0xe88, 13},  // Leaf2JetNegEtaU2: JF1 Input
0166     {0xe89, 3},   // Leaf2JetNegEtaU2: JF1 Shared Received
0167     {0xe8a, 3},   // Leaf2JetNegEtaU2: JF1 Shared Sent
0168     {0xe8b, 10},  // Leaf2JetNegEtaU2: JF1 Output
0169     {0xe8c, 8},   // Leaf2JetNegEtaU2: JF1 Raw Input
0170     {0xf00, 13},  // Leaf3JetNegEtaU1: JF2 Input
0171     {0xf01, 3},   // Leaf3JetNegEtaU1: JF2 Shared Received
0172     {0xf02, 3},   // Leaf3JetNegEtaU1: JF2 Shared Sent
0173     {0xf03, 10},  // Leaf3JetNegEtaU1: JF2 Output
0174     {0xf04, 8},   // Leaf3JetNegEtaU1: JF2 Raw Input
0175     {0xf08, 13},  // Leaf3JetNegEtaU1: JF3 Input
0176     {0xf09, 3},   // Leaf3JetNegEtaU1: JF3 Shared Received
0177     {0xf0a, 3},   // Leaf3JetNegEtaU1: JF3 Shared Sent
0178     {0xf0b, 10},  // Leaf3JetNegEtaU1: JF3 Output
0179     {0xf0c, 8},   // Leaf3JetNegEtaU1: JF3 Raw Input
0180     {0xf80, 6},   // Leaf3JetNegEtaU2: Eta0 Input
0181     {0xf84, 6},   // Leaf3JetNegEtaU2: Eta0 Raw Input
0182     {0xf88, 13},  // Leaf3JetNegEtaU2: JF1 Input
0183     {0xf89, 3},   // Leaf3JetNegEtaU2: JF1 Shared Received
0184     {0xf8a, 3},   // Leaf3JetNegEtaU2: JF1 Shared Sent
0185     {0xf8b, 10},  // Leaf3JetNegEtaU2: JF1 Output
0186     {0xf8c, 8}    // Leaf3JetNegEtaU2: JF1 Raw Input
0187 };
0188 
0189 /*** Setup BlockID to BlockName Map ***/
0190 const GctFormatTranslateV38::BlockNameMap GctFormatTranslateV38::m_blockName = {
0191     // Miscellaneous Blocks
0192     {0x000, "NULL"},
0193     // ConcJet FPGA
0194     {0x580, "ConcJet: Input TrigPathA (Jet Cands)"},
0195     {0x581, "ConcJet: Input TrigPathB (HF Rings)"},
0196     {0x582, "ConcJet: Input TrigPathC (MissHt)"},
0197     {0x583, "ConcJet: Jet Cands and Counts Output to GT"},
0198     {0x587, "ConcJet: BX & Orbit Info"},
0199     // ConcElec FPGA
0200     {0x680, "ConcElec: Input TrigPathA (EM Cands)"},
0201     {0x681, "ConcElec: Input TrigPathB (Et Sums)"},
0202     {0x682, "ConcElec: Input TrigPathC (Ht Sums)"},
0203     {0x683, "ConcElec: EM Cands and Energy Sums Output to GT"},
0204     {0x686, "ConcElec: Test (GT Serdes Loopback)"},
0205     {0x687, "ConcElec: BX & Orbit Info"},
0206     // Electron Leaf FPGAs
0207     {0x800, "Leaf0ElecPosEtaU1: Sort Input"},
0208     {0x803, "Leaf0ElecPosEtaU1: Sort Output"},
0209     {0x804, "Leaf0ElecPosEtaU1: Raw Input"},
0210     {0x880, "Leaf0ElecPosEtaU2: Sort Input"},
0211     {0x883, "Leaf0ElecPosEtaU2: Sort Output"},
0212     {0x884, "Leaf0ElecPosEtaU2: Raw Input"},
0213     {0xc00, "Leaf0ElecNegEtaU1: Sort Input"},
0214     {0xc03, "Leaf0ElecNegEtaU1: Sort Output"},
0215     {0xc04, "Leaf0ElecNegEtaU1: Raw Input"},
0216     {0xc80, "Leaf0ElecNegEtaU2: Sort Input"},
0217     {0xc83, "Leaf0ElecNegEtaU2: Sort Output"},
0218     {0xc84, "Leaf0ElecNegEtaU2: Raw Input"},
0219     // Wheel Pos-eta Jet FPGA
0220     {0x300, "WheelPosEtaJet: Input TrigPathA (Jet Sort)"},
0221     {0x301, "WheelPosEtaJet: Input TrigPathB (MissHt)"},
0222     {0x303, "WheelPosEtaJet: Output TrigPathA (Jet Sort)"},
0223     {0x305, "WheelPosEtaJet: Output TrigPathB (MissHt)"},
0224     {0x306,
0225      "WheelPosEtaJet: Test (deprecated)"},  // (Doesn't exist in V27.1 format, but does in V24 & V25, so keep for CRUZET2 data compatibility reasons)
0226     {0x307,
0227      "WheelPosEtaJet: Info (deprecated)"},  // (Doesn't exist in V27.1 format, but does in V24 & V25, so keep for CRUZET2 data compatibility reasons)
0228     // Wheel Pos-eta Energy FPGA
0229     {0x380, "WheelPosEtaEnergy: Input TrigPathA (Et)"},
0230     {0x381, "WheelPosEtaEnergy: Input TrigPathB (Ht)"},
0231     {0x383, "WheelPosEtaEnergy: Output TrigPathA (Et)"},
0232     {0x385, "WheelPosEtaEnergy: Output TrigPathB (Ht)"},
0233     {0x386, "WheelPosEtaEnergy: Test"},
0234     {0x387, "WheelPosEtaEnergy: BX & Orbit Info"},
0235     // Wheel Neg-eta Jet FPGA
0236     {0x700, "WheelNegEtaJet: Input TrigPathA (Jet Sort)"},
0237     {0x701, "WheelNegEtaJet: Input TrigPathB (MissHt)"},
0238     {0x703, "WheelNegEtaJet: Output TrigPathA (Jet Sort)"},
0239     {0x705, "WheelNegEtaJet: Output TrigPathB (MissHt)"},
0240     {0x706,
0241      "WheelNegEtaJet: Test (deprecated)"},  // (Doesn't exist in V27.1 format, but does in V24 & V25, so keep for CRUZET2 data compatibility reasons)
0242     {0x707,
0243      "WheelNegEtaJet: Info (deprecated)"},  // (Doesn't exist in V27.1 format, but does in V24 & V25, so keep for CRUZET2 data compatibility reasons)
0244     // Wheel Neg-eta Energy FPGA
0245     {0x780, "WheelNegEtaEnergy: Input TrigPathA (Et)"},
0246     {0x781, "WheelNegEtaEnergy: Input TrigPathB (Ht)"},
0247     {0x783, "WheelNegEtaEnergy: Output TrigPathA (Et)"},
0248     {0x785, "WheelNegEtaEnergy: Output TrigPathB (Ht)"},
0249     {0x786, "WheelNegEtaEnergy: Test"},
0250     {0x787, "WheelNegEtaEnergy: BX & Orbit Info"},
0251     // Jet Leaf FPGAs - Positive Eta
0252     {0x900, "Leaf1JetPosEtaU1: JF2 Input"},
0253     {0x901, "Leaf1JetPosEtaU1: JF2 Shared Received"},
0254     {0x902, "Leaf1JetPosEtaU1: JF2 Shared Sent"},
0255     {0x903, "Leaf1JetPosEtaU1: JF2 Output"},
0256     {0x904, "Leaf1JetPosEtaU1: JF2 Raw Input"},
0257     {0x908, "Leaf1JetPosEtaU1: JF3 Input"},
0258     {0x909, "Leaf1JetPosEtaU1: JF3 Shared Received"},
0259     {0x90a, "Leaf1JetPosEtaU1: JF3 Shared Sent"},
0260     {0x90b, "Leaf1JetPosEtaU1: JF3 Output"},
0261     {0x90c, "Leaf1JetPosEtaU1: JF3 Raw Input"},
0262     {0x980, "Leaf1JetPosEtaU2: Eta0 Input"},  // Next Leaf Start
0263     {0x984, "Leaf1JetPosEtaU2: Eta0 Raw Input"},
0264     {0x988, "Leaf1JetPosEtaU2: JF1 Input"},
0265     {0x989, "Leaf1JetPosEtaU2: JF1 Shared Received"},
0266     {0x98a, "Leaf1JetPosEtaU2: JF1 Shared Sent"},
0267     {0x98b, "Leaf1JetPosEtaU2: JF1 Output"},
0268     {0x98c, "Leaf1JetPosEtaU2: JF1 Raw Input"},
0269     {0xa00, "Leaf2JetPosEtaU1: JF2 Input"},  // Next Leaf Start
0270     {0xa01, "Leaf2JetPosEtaU1: JF2 Shared Received"},
0271     {0xa02, "Leaf2JetPosEtaU1: JF2 Shared Sent"},
0272     {0xa03, "Leaf2JetPosEtaU1: JF2 Output"},
0273     {0xa04, "Leaf2JetPosEtaU1: JF2 Raw Input"},
0274     {0xa08, "Leaf2JetPosEtaU1: JF3 Input"},
0275     {0xa09, "Leaf2JetPosEtaU1: JF3 Shared Received"},
0276     {0xa0a, "Leaf2JetPosEtaU1: JF3 Shared Sent"},
0277     {0xa0b, "Leaf2JetPosEtaU1: JF3 Output"},
0278     {0xa0c, "Leaf2JetPosEtaU1: JF3 Raw Input"},
0279     {0xa80, "Leaf2JetPosEtaU2: Eta0 Input"},  // Next Leaf Start
0280     {0xa84, "Leaf2JetPosEtaU2: Eta0 Raw Input"},
0281     {0xa88, "Leaf2JetPosEtaU2: JF1 Input"},
0282     {0xa89, "Leaf2JetPosEtaU2: JF1 Shared Received"},
0283     {0xa8a, "Leaf2JetPosEtaU2: JF1 Shared Sent"},
0284     {0xa8b, "Leaf2JetPosEtaU2: JF1 Output"},
0285     {0xa8c, "Leaf2JetPosEtaU2: JF1 Raw Input"},
0286     {0xb00, "Leaf3JetPosEtaU1: JF2 Input"},  // Next Leaf Start
0287     {0xb01, "Leaf3JetPosEtaU1: JF2 Shared Received"},
0288     {0xb02, "Leaf3JetPosEtaU1: JF2 Shared Sent"},
0289     {0xb03, "Leaf3JetPosEtaU1: JF2 Output"},
0290     {0xb04, "Leaf3JetPosEtaU1: JF2 Raw Input"},
0291     {0xb08, "Leaf3JetPosEtaU1: JF3 Input"},
0292     {0xb09, "Leaf3JetPosEtaU1: JF3 Shared Received"},
0293     {0xb0a, "Leaf3JetPosEtaU1: JF3 Shared Sent"},
0294     {0xb0b, "Leaf3JetPosEtaU1: JF3 Output"},
0295     {0xb0c, "Leaf3JetPosEtaU1: JF3 Raw Input"},
0296     {0xb80, "Leaf3JetPosEtaU2: Eta0 Input"},  // Next Leaf Start
0297     {0xb84, "Leaf3JetPosEtaU2: Eta0 Raw Input"},
0298     {0xb88, "Leaf3JetPosEtaU2: JF1 Input"},
0299     {0xb89, "Leaf3JetPosEtaU2: JF1 Shared Received"},
0300     {0xb8a, "Leaf3JetPosEtaU2: JF1 Shared Sent"},
0301     {0xb8b, "Leaf3JetPosEtaU2: JF1 Output"},
0302     {0xb8c, "Leaf3JetPosEtaU2: JF1 Raw Input"},
0303     // Jet Leaf FPGAs - Negative Eta
0304     {0xd00, "Leaf1JetNegEtaU1: JF2 Input"},  // START OF NEG ETA JET LEAVES
0305     {0xd01, "Leaf1JetNegEtaU1: JF2 Shared Received"},
0306     {0xd02, "Leaf1JetNegEtaU1: JF2 Shared Sent"},
0307     {0xd03, "Leaf1JetNegEtaU1: JF2 Output"},
0308     {0xd04, "Leaf1JetNegEtaU1: JF2 Raw Input"},
0309     {0xd08, "Leaf1JetNegEtaU1: JF3 Input"},
0310     {0xd09, "Leaf1JetNegEtaU1: JF3 Shared Received"},
0311     {0xd0a, "Leaf1JetNegEtaU1: JF3 Shared Sent"},
0312     {0xd0b, "Leaf1JetNegEtaU1: JF3 Output"},
0313     {0xd0c, "Leaf1JetNegEtaU1: JF3 Raw Input"},
0314     {0xd80, "Leaf1JetNegEtaU2: Eta0 Input"},  // Next Leaf Start
0315     {0xd84, "Leaf1JetNegEtaU2: Eta0 Raw Input"},
0316     {0xd88, "Leaf1JetNegEtaU2: JF1 Input"},
0317     {0xd89, "Leaf1JetNegEtaU2: JF1 Shared Received"},
0318     {0xd8a, "Leaf1JetNegEtaU2: JF1 Shared Sent"},
0319     {0xd8b, "Leaf1JetNegEtaU2: JF1 Output"},
0320     {0xd8c, "Leaf1JetNegEtaU2: JF1 Raw Input"},
0321     {0xe00, "Leaf2JetNegEtaU1: JF2 Input"},  // Next Leaf Start
0322     {0xe01, "Leaf2JetNegEtaU1: JF2 Shared Received"},
0323     {0xe02, "Leaf2JetNegEtaU1: JF2 Shared Sent"},
0324     {0xe03, "Leaf2JetNegEtaU1: JF2 Output"},
0325     {0xe04, "Leaf2JetNegEtaU1: JF2 Raw Input"},
0326     {0xe08, "Leaf2JetNegEtaU1: JF3 Input"},
0327     {0xe09, "Leaf2JetNegEtaU1: JF3 Shared Received"},
0328     {0xe0a, "Leaf2JetNegEtaU1: JF3 Shared Sent"},
0329     {0xe0b, "Leaf2JetNegEtaU1: JF3 Output"},
0330     {0xe0c, "Leaf2JetNegEtaU1: JF3 Raw Input"},
0331     {0xe80, "Leaf2JetNegEtaU2: Eta0 Input"},  // Next Leaf Start
0332     {0xe84, "Leaf2JetNegEtaU2: Eta0 Raw Input"},
0333     {0xe88, "Leaf2JetNegEtaU2: JF1 Input"},
0334     {0xe89, "Leaf2JetNegEtaU2: JF1 Shared Received"},
0335     {0xe8a, "Leaf2JetNegEtaU2: JF1 Shared Sent"},
0336     {0xe8b, "Leaf2JetNegEtaU2: JF1 Output"},
0337     {0xe8c, "Leaf2JetNegEtaU2: JF1 Raw Input"},
0338     {0xf00, "Leaf3JetNegEtaU1: JF2 Input"},  // Next Leaf Start
0339     {0xf01, "Leaf3JetNegEtaU1: JF2 Shared Received"},
0340     {0xf02, "Leaf3JetNegEtaU1: JF2 Shared Sent"},
0341     {0xf03, "Leaf3JetNegEtaU1: JF2 Output"},
0342     {0xf04, "Leaf3JetNegEtaU1: JF2 Raw Input"},
0343     {0xf08, "Leaf3JetNegEtaU1: JF3 Input"},
0344     {0xf09, "Leaf3JetNegEtaU1: JF3 Shared Received"},
0345     {0xf0a, "Leaf3JetNegEtaU1: JF3 Shared Sent"},
0346     {0xf0b, "Leaf3JetNegEtaU1: JF3 Output"},
0347     {0xf0c, "Leaf3JetNegEtaU1: JF3 Raw Input"},
0348     {0xf80, "Leaf3JetNegEtaU2: Eta0 Input"},  // Next Leaf Start
0349     {0xf84, "Leaf3JetNegEtaU2: Eta0 Raw Input"},
0350     {0xf88, "Leaf3JetNegEtaU2: JF1 Input"},
0351     {0xf89, "Leaf3JetNegEtaU2: JF1 Shared Received"},
0352     {0xf8a, "Leaf3JetNegEtaU2: JF1 Shared Sent"},
0353     {0xf8b, "Leaf3JetNegEtaU2: JF1 Output"},
0354     {0xf8c, "Leaf3JetNegEtaU2: JF1 Raw Input"}};
0355 
0356 /*** Setup BlockID to Unpack-Function Map ***/
0357 const GctFormatTranslateV38::BlockIdToUnpackFnMap GctFormatTranslateV38::m_blockUnpackFn = {
0358     // Miscellaneous Blocks
0359     {0x000, &GctFormatTranslateV38::blockDoNothing},  // NULL
0360     // ConcJet FPGA
0361     {0x580, &GctFormatTranslateV38::blockToGctTrigObjects},            // ConcJet: Input TrigPathA (Jet Cands)
0362     {0x581, &GctFormatTranslateV38::blockToGctInternRingSums},         // ConcJet: Input TrigPathB (HF Rings)
0363     {0x582, &GctFormatTranslateV38::blockToGctInternHtMissPostWheel},  // ConcJet: Input TrigPathC (MissHt)
0364     {0x583, &GctFormatTranslateV38::blockToGctJetCandsAndCounts},      // ConcJet: Jet Cands and Counts Output to GT
0365     {0x587, &GctFormatTranslateV38::blockDoNothing},                   // ConcJet: BX & Orbit Info
0366     // ConcElec FPGA
0367     {0x680, &GctFormatTranslateV38::blockToGctInternEmCand},          // ConcElec: Input TrigPathA (EM Cands)
0368     {0x681, &GctFormatTranslateV38::blockToGctInternEtSums},          // ConcElec: Input TrigPathB (Et Sums)
0369     {0x682, &GctFormatTranslateV38::blockToGctInternEtSums},          // ConcElec: Input TrigPathC (Ht Sums)
0370     {0x683, &GctFormatTranslateV38::blockToGctEmCandsAndEnergySums},  // ConcElec: EM Cands and Energy Sums Output to GT
0371     {0x686, &GctFormatTranslateV38::blockDoNothing},                  // ConcElec: Test (GT Serdes Loopback)
0372     {0x687, &GctFormatTranslateV38::blockDoNothing},                  // ConcElec: BX & Orbit Info
0373     // Electron Leaf FPGAs
0374     {0x800, &GctFormatTranslateV38::blockToGctInternEmCand},       // Leaf0ElecPosEtaU1: Sort Input
0375     {0x803, &GctFormatTranslateV38::blockToGctInternEmCand},       // Leaf0ElecPosEtaU1: Sort Output
0376     {0x804, &GctFormatTranslateV38::blockToFibresAndToRctEmCand},  // Leaf0ElecPosEtaU1: Raw Input
0377     {0x880, &GctFormatTranslateV38::blockToGctInternEmCand},       // Leaf0ElecPosEtaU2: Sort Input
0378     {0x883, &GctFormatTranslateV38::blockToGctInternEmCand},       // Leaf0ElecPosEtaU2: Sort Output
0379     {0x884, &GctFormatTranslateV38::blockToFibresAndToRctEmCand},  // Leaf0ElecPosEtaU2: Raw Input
0380     {0xc00, &GctFormatTranslateV38::blockToGctInternEmCand},       // Leaf0ElecNegEtaU1: Sort Input
0381     {0xc03, &GctFormatTranslateV38::blockToGctInternEmCand},       // Leaf0ElecNegEtaU1: Sort Output
0382     {0xc04, &GctFormatTranslateV38::blockToFibresAndToRctEmCand},  // Leaf0ElecNegEtaU1: Raw Input
0383     {0xc80, &GctFormatTranslateV38::blockToGctInternEmCand},       // Leaf0ElecNegEtaU2: Sort Input
0384     {0xc83, &GctFormatTranslateV38::blockToGctInternEmCand},       // Leaf0ElecNegEtaU2: Sort Output
0385     {0xc84, &GctFormatTranslateV38::blockToFibresAndToRctEmCand},  // Leaf0ElecNegEtaU2: Raw Input
0386     // Wheel Pos-eta Jet FPGA
0387     {0x300, &GctFormatTranslateV38::blockToGctJetClusterMinimal},      // WheelPosEtaJet: Input TrigPathA (Jet Sort)
0388     {0x301, &GctFormatTranslateV38::blockToGctInternHtMissPreWheel},   // WheelPosEtaJet: Input TrigPathB (MissHt)
0389     {0x303, &GctFormatTranslateV38::blockToGctTrigObjects},            // WheelPosEtaJet: Output TrigPathA (Jet Sort)
0390     {0x305, &GctFormatTranslateV38::blockToGctInternHtMissPostWheel},  // WheelPosEtaJet: Output TrigPathB (MissHt)
0391     {0x306,
0392      &GctFormatTranslateV38::
0393          blockDoNothing},  // WheelPosEtaJet: Test (deprecated)  (Doesn't exist in V27.1 format, but does in V24 & V25, so keep for CRUZET2 data compatibility reasons)
0394     {0x307,
0395      &GctFormatTranslateV38::
0396          blockDoNothing},  // WheelPosEtaJet: Info (deprecated)  (Doesn't exist in V27.1 format, but does in V24 & V25, so keep for CRUZET2 data compatibility reasons)
0397     // Wheel Pos-eta Energy FPGA
0398     {0x380,
0399      &GctFormatTranslateV38::blockToGctWheelInputInternEtAndRingSums},  // WheelPosEtaEnergy: Input TrigPathA (Et)
0400     {0x381, &GctFormatTranslateV38::blockToGctInternEtSums},            // WheelPosEtaEnergy: Input TrigPathB (Ht)
0401     {0x383,
0402      &GctFormatTranslateV38::blockToGctWheelOutputInternEtAndRingSums},  // WheelPosEtaEnergy: Output TrigPathA (Et)
0403     {0x385, &GctFormatTranslateV38::blockToGctInternEtSums},             // WheelPosEtaEnergy: Output TrigPathB (Ht)
0404     {0x386, &GctFormatTranslateV38::blockDoNothing},                     // WheelPosEtaEnergy: Test
0405     {0x387,
0406      &GctFormatTranslateV38::
0407          blockDoNothing},  // WheelPosEtaEnergy: BX & Orbit Info   (Potential data incompatibility between V24/V25 where block length=4, and V27.1 where block length=6)
0408     // Wheel Neg-eta Jet FPGA
0409     {0x700, &GctFormatTranslateV38::blockToGctJetClusterMinimal},      // WheelNegEtaJet: Input TrigPathA (Jet Sort)
0410     {0x701, &GctFormatTranslateV38::blockToGctInternHtMissPreWheel},   // WheelNegEtaJet: Input TrigPathB (MissHt)
0411     {0x703, &GctFormatTranslateV38::blockToGctTrigObjects},            // WheelNegEtaJet: Output TrigPathA (Jet Sort)
0412     {0x705, &GctFormatTranslateV38::blockToGctInternHtMissPostWheel},  // WheelNegEtaJet: Output TrigPathB (MissHt)
0413     {0x706,
0414      &GctFormatTranslateV38::
0415          blockDoNothing},  // WheelNegEtaJet: Test (deprecated)  (Doesn't exist in V27.1 format, but does in V24 & V25, so keep for CRUZET2 data compatibility reasons)
0416     {0x707,
0417      &GctFormatTranslateV38::
0418          blockDoNothing},  // WheelNegEtaJet: Info (deprecated)  (Doesn't exist in V27.1 format, but does in V24 & V25, so keep for CRUZET2 data compatibility reasons)
0419     // Wheel Neg-eta Energy FPGA
0420     {0x780,
0421      &GctFormatTranslateV38::blockToGctWheelInputInternEtAndRingSums},  // WheelNegEtaEnergy: Input TrigPathA (Et)
0422     {0x781, &GctFormatTranslateV38::blockToGctInternEtSums},            // WheelNegEtaEnergy: Input TrigPathB (Ht)
0423     {0x783,
0424      &GctFormatTranslateV38::blockToGctWheelOutputInternEtAndRingSums},  // WheelNegEtaEnergy: Output TrigPathA (Et)
0425     {0x785, &GctFormatTranslateV38::blockToGctInternEtSums},             // WheelNegEtaEnergy: Output TrigPathB (Ht)
0426     {0x786, &GctFormatTranslateV38::blockDoNothing},                     // WheelNegEtaEnergy: Test
0427     {0x787,
0428      &GctFormatTranslateV38::
0429          blockDoNothing},  // WheelNegEtaEnergy: BX & Orbit Info   (Potential data incompatibility between V24/V25 where block length=4, and V27.1 where block length=6)
0430     // Jet Leaf FPGAs - Positive Eta
0431     {0x900, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf1JetPosEtaU1: JF2 Input
0432     {0x901, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf1JetPosEtaU1: JF2 Shared Received
0433     {0x902, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf1JetPosEtaU1: JF2 Shared Sent
0434     {0x903, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf1JetPosEtaU1: JF2 Output
0435     {0x904, &GctFormatTranslateV38::blockToFibres},                        // Leaf1JetPosEtaU1: JF2 Raw Input
0436     {0x908, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf1JetPosEtaU1: JF3 Input
0437     {0x909, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf1JetPosEtaU1: JF3 Shared Received
0438     {0x90a, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf1JetPosEtaU1: JF3 Shared Sent
0439     {0x90b, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf1JetPosEtaU1: JF3 Output
0440     {0x90c, &GctFormatTranslateV38::blockToFibres},                        // Leaf1JetPosEtaU1: JF3 Raw Input
0441     {0x980, &GctFormatTranslateV38::blockDoNothing},                       // Leaf1JetPosEtaU2: Eta0 Input
0442     {0x984, &GctFormatTranslateV38::blockToFibres},                        // Leaf1JetPosEtaU2: Eta0 Raw Input
0443     {0x988, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf1JetPosEtaU2: JF1 Input
0444     {0x989, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf1JetPosEtaU2: JF1 Shared Received
0445     {0x98a, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf1JetPosEtaU2: JF1 Shared Sent
0446     {0x98b, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf1JetPosEtaU2: JF1 Output
0447     {0x98c, &GctFormatTranslateV38::blockToFibres},                        // Leaf1JetPosEtaU2: JF1 Raw Input
0448     {0xa00, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf2JetPosEtaU1: JF2 Input
0449     {0xa01, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf2JetPosEtaU1: JF2 Shared Received
0450     {0xa02, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf2JetPosEtaU1: JF2 Shared Sent
0451     {0xa03, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf2JetPosEtaU1: JF2 Output
0452     {0xa04, &GctFormatTranslateV38::blockToFibres},                        // Leaf2JetPosEtaU1: JF2 Raw Input
0453     {0xa08, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf2JetPosEtaU1: JF3 Input
0454     {0xa09, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf2JetPosEtaU1: JF3 Shared Received
0455     {0xa0a, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf2JetPosEtaU1: JF3 Shared Sent
0456     {0xa0b, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf2JetPosEtaU1: JF3 Output
0457     {0xa0c, &GctFormatTranslateV38::blockToFibres},                        // Leaf2JetPosEtaU1: JF3 Raw Input
0458     {0xa80, &GctFormatTranslateV38::blockDoNothing},                       // Leaf2JetPosEtaU2: Eta0 Input
0459     {0xa84, &GctFormatTranslateV38::blockToFibres},                        // Leaf2JetPosEtaU2: Eta0 Raw Input
0460     {0xa88, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf2JetPosEtaU2: JF1 Input
0461     {0xa89, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf2JetPosEtaU2: JF1 Shared Received
0462     {0xa8a, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf2JetPosEtaU2: JF1 Shared Sent
0463     {0xa8b, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf2JetPosEtaU2: JF1 Output
0464     {0xa8c, &GctFormatTranslateV38::blockToFibres},                        // Leaf2JetPosEtaU2: JF1 Raw Input
0465     {0xb00, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf3JetPosEtaU1: JF2 Input
0466     {0xb01, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf3JetPosEtaU1: JF2 Shared Received
0467     {0xb02, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf3JetPosEtaU1: JF2 Shared Sent
0468     {0xb03, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf3JetPosEtaU1: JF2 Output
0469     {0xb04, &GctFormatTranslateV38::blockToFibres},                        // Leaf3JetPosEtaU1: JF2 Raw Input
0470     {0xb08, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf3JetPosEtaU1: JF3 Input
0471     {0xb09, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf3JetPosEtaU1: JF3 Shared Received
0472     {0xb0a, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf3JetPosEtaU1: JF3 Shared Sent
0473     {0xb0b, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf3JetPosEtaU1: JF3 Output
0474     {0xb0c, &GctFormatTranslateV38::blockToFibres},                        // Leaf3JetPosEtaU1: JF3 Raw Input
0475     {0xb80, &GctFormatTranslateV38::blockDoNothing},                       // Leaf3JetPosEtaU2: Eta0 Input
0476     {0xb84, &GctFormatTranslateV38::blockToFibres},                        // Leaf3JetPosEtaU2: Eta0 Raw Input
0477     {0xb88, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf3JetPosEtaU2: JF1 Input
0478     {0xb89, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf3JetPosEtaU2: JF1 Shared Received
0479     {0xb8a, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf3JetPosEtaU2: JF1 Shared Sent
0480     {0xb8b, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf3JetPosEtaU2: JF1 Output
0481     {0xb8c, &GctFormatTranslateV38::blockToFibres},                        // Leaf3JetPosEtaU2: JF1 Raw Input
0482     // Jet Leaf FPGAs - Negative Eta
0483     {0xd00, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf1JetNegEtaU1: JF2 Input
0484     {0xd01, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf1JetNegEtaU1: JF2 Shared Received
0485     {0xd02, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf1JetNegEtaU1: JF2 Shared Sent
0486     {0xd03, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf1JetNegEtaU1: JF2 Output
0487     {0xd04, &GctFormatTranslateV38::blockToFibres},                        // Leaf1JetNegEtaU1: JF2 Raw Input
0488     {0xd08, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf1JetNegEtaU1: JF3 Input
0489     {0xd09, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf1JetNegEtaU1: JF3 Shared Received
0490     {0xd0a, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf1JetNegEtaU1: JF3 Shared Sent
0491     {0xd0b, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf1JetNegEtaU1: JF3 Output
0492     {0xd0c, &GctFormatTranslateV38::blockToFibres},                        // Leaf1JetNegEtaU1: JF3 Raw Input
0493     {0xd80, &GctFormatTranslateV38::blockDoNothing},                       // Leaf1JetNegEtaU2: Eta0 Input
0494     {0xd84, &GctFormatTranslateV38::blockToFibres},                        // Leaf1JetNegEtaU2: Eta0 Raw Input
0495     {0xd88, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf1JetNegEtaU2: JF1 Input
0496     {0xd89, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf1JetNegEtaU2: JF1 Shared Received
0497     {0xd8a, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf1JetNegEtaU2: JF1 Shared Sent
0498     {0xd8b, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf1JetNegEtaU2: JF1 Output
0499     {0xd8c, &GctFormatTranslateV38::blockToFibres},                        // Leaf1JetNegEtaU2: JF1 Raw Input
0500     {0xe00, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf2JetNegEtaU1: JF2 Input
0501     {0xe01, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf2JetNegEtaU1: JF2 Shared Received
0502     {0xe02, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf2JetNegEtaU1: JF2 Shared Sent
0503     {0xe03, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf2JetNegEtaU1: JF2 Output
0504     {0xe04, &GctFormatTranslateV38::blockToFibres},                        // Leaf2JetNegEtaU1: JF2 Raw Input
0505     {0xe08, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf2JetNegEtaU1: JF3 Input
0506     {0xe09, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf2JetNegEtaU1: JF3 Shared Received
0507     {0xe0a, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf2JetNegEtaU1: JF3 Shared Sent
0508     {0xe0b, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf2JetNegEtaU1: JF3 Output
0509     {0xe0c, &GctFormatTranslateV38::blockToFibres},                        // Leaf2JetNegEtaU1: JF3 Raw Input
0510     {0xe80, &GctFormatTranslateV38::blockDoNothing},                       // Leaf2JetNegEtaU2: Eta0 Input
0511     {0xe84, &GctFormatTranslateV38::blockToFibres},                        // Leaf2JetNegEtaU2: Eta0 Raw Input
0512     {0xe88, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf2JetNegEtaU2: JF1 Input
0513     {0xe89, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf2JetNegEtaU2: JF1 Shared Received
0514     {0xe8a, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf2JetNegEtaU2: JF1 Shared Sent
0515     {0xe8b, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf2JetNegEtaU2: JF1 Output
0516     {0xe8c, &GctFormatTranslateV38::blockToFibres},                        // Leaf2JetNegEtaU2: JF1 Raw Input
0517     {0xf00, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf3JetNegEtaU1: JF2 Input
0518     {0xf01, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf3JetNegEtaU1: JF2 Shared Received
0519     {0xf02, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf3JetNegEtaU1: JF2 Shared Sent
0520     {0xf03, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf3JetNegEtaU1: JF2 Output
0521     {0xf04, &GctFormatTranslateV38::blockToFibres},                        // Leaf3JetNegEtaU1: JF2 Raw Input
0522     {0xf08, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf3JetNegEtaU1: JF3 Input
0523     {0xf09, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf3JetNegEtaU1: JF3 Shared Received
0524     {0xf0a, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf3JetNegEtaU1: JF3 Shared Sent
0525     {0xf0b, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf3JetNegEtaU1: JF3 Output
0526     {0xf0c, &GctFormatTranslateV38::blockToFibres},                        // Leaf3JetNegEtaU1: JF3 Raw Input
0527     {0xf80, &GctFormatTranslateV38::blockDoNothing},                       // Leaf3JetNegEtaU2: Eta0 Input
0528     {0xf84, &GctFormatTranslateV38::blockToFibres},                        // Leaf3JetNegEtaU2: Eta0 Raw Input
0529     {0xf88, &GctFormatTranslateV38::blockToRctCaloRegions},                // Leaf3JetNegEtaU2: JF1 Input
0530     {0xf89, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf3JetNegEtaU2: JF1 Shared Received
0531     {0xf8a, &GctFormatTranslateV38::blockToGctJetPreCluster},              // Leaf3JetNegEtaU2: JF1 Shared Sent
0532     {0xf8b, &GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster},  // Leaf3JetNegEtaU2: JF1 Output
0533     {0xf8c, &GctFormatTranslateV38::blockToFibres},                        // Leaf3JetNegEtaU2: JF1 Raw Input
0534 };
0535 
0536 /*** Setup RCT Em Crate Map ***/
0537 const GctFormatTranslateV38::BlkToRctCrateMap GctFormatTranslateV38::m_rctEmCrate = {
0538     {0x804, 13}, {0x884, 9}, {0xc04, 4}, {0xc84, 0}};
0539 
0540 /*** Setup RCT jet crate map. ***/
0541 const GctFormatTranslateV38::BlkToRctCrateMap GctFormatTranslateV38::m_rctJetCrate = {
0542     {0x900, 9},   // PosEta Leaf 1 JF2
0543     {0x908, 10},  // PosEta Leaf 1 JF3
0544     {0x988, 17},  // PosEta Leaf 1 JF1
0545     {0xa00, 12},  // PosEta Leaf 2 JF2
0546     {0xa08, 13},  // PosEta Leaf 2 JF3
0547     {0xa88, 11},  // PosEta Leaf 2 JF1
0548     {0xb00, 15},  // PosEta Leaf 3 JF2
0549     {0xb08, 16},  // PosEta Leaf 3 JF3
0550     {0xb88, 14},  // PosEta Leaf 3 JF1
0551     {0xd00, 0},   // NegEta Leaf 1 JF2
0552     {0xd08, 1},   // NegEta Leaf 1 JF3
0553     {0xd88, 8},   // NegEta Leaf 1 JF1
0554     {0xe00, 3},   // NegEta Leaf 2 JF2
0555     {0xe08, 4},   // NegEta Leaf 2 JF3
0556     {0xe88, 2},   // NegEta Leaf 2 JF1
0557     {0xf00, 6},   // NegEta Leaf 3 JF2
0558     {0xf08, 7},   // NegEta Leaf 3 JF3
0559     {0xf88, 5}    // NegEta Leaf 3 JF1
0560 };
0561 
0562 /*** Setup Block ID map for pipeline payload positions of isolated Internal EM Cands. ***/
0563 const GctFormatTranslateV38::BlockIdToEmCandIsoBoundMap GctFormatTranslateV38::m_internEmIsoBounds = {
0564     {0x680, IsoBoundaryPair(8, 15)},
0565     {0x800, IsoBoundaryPair(0, 9)},
0566     {0x803, IsoBoundaryPair(0, 1)},
0567     {0x880, IsoBoundaryPair(0, 7)},
0568     {0x883, IsoBoundaryPair(0, 1)},
0569     {0xc00, IsoBoundaryPair(0, 9)},
0570     {0xc03, IsoBoundaryPair(0, 1)},
0571     {0xc80, IsoBoundaryPair(0, 7)},
0572     {0xc83, IsoBoundaryPair(0, 1)}};
0573 
0574 // PUBLIC METHODS
0575 
0576 GctFormatTranslateV38::GctFormatTranslateV38(bool hltMode,
0577                                              bool unpackSharedRegions,
0578                                              unsigned numberOfGctSamplesToUnpack,
0579                                              unsigned numberOfRctSamplesToUnpack)
0580     : GctFormatTranslateBase(hltMode, unpackSharedRegions),
0581       m_numberOfGctSamplesToUnpack(numberOfGctSamplesToUnpack),
0582       m_numberOfRctSamplesToUnpack(numberOfRctSamplesToUnpack) {}
0583 
0584 GctFormatTranslateV38::~GctFormatTranslateV38() {}
0585 
0586 GctBlockHeader GctFormatTranslateV38::generateBlockHeader(const unsigned char* data) const {
0587   // Turn the four 8-bit header words into the full 32-bit header.
0588   uint32_t hdr = data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24);
0589 
0590   //  Bit mapping of V35 header:
0591   //  --------------------------
0592   //  11:0   => block_id  Unique pipeline identifier.
0593   //   - 3:0    =>> pipe_id There can be up to 16 different pipelines per FPGA.
0594   //   - 6:4    =>> reserved  Do not use yet. Set to zero.
0595   //   - 11:7   =>> fpga geograpical add  The VME geographical address of the FPGA.
0596   //  15:12  => event_id  Determined locally.  Not reset by Resync.
0597   //  19:16  => number_of_time_samples  If time samples 15 or more then value = 15.
0598   //  31:20  => event_bcid  The bunch crossing the data was recorded.
0599 
0600   unsigned blockId = hdr & 0xfff;
0601   unsigned blockLength = 0;  // Set to zero until we know it's a valid block
0602   unsigned nSamples = (hdr >> 16) & 0xf;
0603   unsigned bxId = (hdr >> 20) & 0xfff;
0604   unsigned eventId = (hdr >> 12) & 0xf;
0605   bool valid = (blockLengthMap().find(blockId) != blockLengthMap().end());
0606 
0607   if (valid) {
0608     blockLength = blockLengthMap().find(blockId)->second;
0609   }
0610 
0611   return GctBlockHeader(blockId, blockLength, nSamples, bxId, eventId, valid);
0612 }
0613 
0614 // conversion
0615 bool GctFormatTranslateV38::convertBlock(const unsigned char* data, const GctBlockHeader& hdr) {
0616   // if the block has no time samples, don't bother with it.
0617   if (hdr.nSamples() < 1) {
0618     return true;
0619   }
0620 
0621   if (!checkBlock(hdr)) {
0622     return false;
0623   }  // Check the block to see if it's possible to unpack.
0624 
0625   // The header validity check above will protect against
0626   // the map::find() method returning the end of the map,
0627   // assuming the block header definitions are up-to-date.
0628   (this->*m_blockUnpackFn.find(hdr.blockId())->second)(data,
0629                                                        hdr);  // Calls the correct unpack function, based on block ID.
0630 
0631   return true;
0632 }
0633 
0634 // PROTECTED METHODS
0635 
0636 uint32_t GctFormatTranslateV38::generateRawHeader(const uint32_t blockId,
0637                                                   const uint32_t nSamples,
0638                                                   const uint32_t bxId,
0639                                                   const uint32_t eventId) const {
0640   //  Bit mapping of V35 header:
0641   //  --------------------------
0642   //  11:0   => block_id  Unique pipeline identifier.
0643   //   - 3:0    =>> pipe_id There can be up to 16 different pipelines per FPGA.
0644   //   - 6:4    =>> reserved  Do not use yet. Set to zero.
0645   //   - 11:7   =>> fpga geograpical add  The VME geographical address of the FPGA.
0646   //  15:12  => event_id  Determined locally.  Not reset by Resync.
0647   //  19:16  => number_of_time_samples  If time samples 15 or more then value = 15.
0648   //  31:20  => event_bxId  The bunch crossing the data was recorded.
0649 
0650   return ((bxId & 0xfff) << 20) | ((nSamples & 0xf) << 16) | ((eventId & 0xf) << 12) | (blockId & 0xfff);
0651 }
0652 
0653 // PRIVATE METHODS
0654 
0655 // Throughout the code, bx refers to the hardware definition of time-samples
0656 // ie. if 5 time samples are unpacked, they are bx=0, 1, 2, 3, 4 in order
0657 // what is written to digi would be -2, -1, 0, +1, +2
0658 
0659 // Output EM Candidates unpacking
0660 void GctFormatTranslateV38::blockToGctEmCandsAndEnergySums(const unsigned char* d, const GctBlockHeader& hdr) {
0661   const unsigned int id = hdr.blockId();
0662   const unsigned int nSamples = hdr.nSamples();
0663 
0664   // Re-interpret pointer.  p16 will be pointing at the 16 bit word that
0665   // contains the rank0 non-isolated electron of the zeroth time-sample.
0666   const uint16_t* p16 = reinterpret_cast<const uint16_t*>(d);
0667 
0668   // UNPACK EM CANDS
0669 
0670   const unsigned int emCandCategoryOffset =
0671       nSamples * 4;  // Offset to jump from the non-iso electrons to the isolated ones.
0672   const unsigned int timeSampleOffset = nSamples * 2;  // Offset to jump to next candidate pair in the same time-sample.
0673 
0674   unsigned int samplesToUnpack =
0675       std::min(nSamples, m_numberOfGctSamplesToUnpack);  // Unpack as many as asked for if they are in the raw data
0676   unsigned int centralSample =
0677       (unsigned)std::ceil((double)nSamples / 2.) - 1;  // think this works when nSamples is even, need to check!!!
0678   unsigned int firstSample = centralSample - (unsigned)std::ceil((double)samplesToUnpack / 2.) + 1;
0679   unsigned int lastSample = centralSample + (unsigned)(samplesToUnpack / 2);
0680 
0681   LogDebug("GCT") << "Unpacking output EM.  Central sample=" << centralSample << " first=" << firstSample
0682                   << " last=" << lastSample;
0683 
0684   for (unsigned int iso = 0; iso < 2; ++iso)  // loop over non-iso/iso candidate pairs
0685   {
0686     bool isoFlag = (iso == 1);
0687 
0688     // Get the correct collection to put them in.
0689     L1GctEmCandCollection* em;
0690     if (isoFlag) {
0691       em = colls()->gctIsoEm();
0692     } else {
0693       em = colls()->gctNonIsoEm();
0694     }
0695 
0696     for (unsigned int bx = firstSample; bx <= lastSample; ++bx)  // loop over samples to be unpacked
0697     {
0698       // cand0Offset will give the offset on p16 to get the rank 0 candidate
0699       // of the correct category and timesample.
0700       const unsigned int cand0Offset = iso * emCandCategoryOffset + bx * 2;
0701 
0702       em->push_back(L1GctEmCand(p16[cand0Offset], isoFlag, id, 0, (int)bx - (int)centralSample));  // rank0 electron
0703       em->push_back(L1GctEmCand(
0704           p16[cand0Offset + timeSampleOffset], isoFlag, id, 1, (int)bx - (int)centralSample));         // rank1 electron
0705       em->push_back(L1GctEmCand(p16[cand0Offset + 1], isoFlag, id, 2, (int)bx - (int)centralSample));  // rank2 electron
0706       em->push_back(L1GctEmCand(
0707           p16[cand0Offset + timeSampleOffset + 1], isoFlag, id, 3, (int)bx - (int)centralSample));  // rank3 electron
0708 
0709       LogDebug("GCT") << "Unpacked a bunch of EG.  iso=" << iso << " bx=" << bx << std::endl;
0710     }
0711   }
0712 
0713   p16 += emCandCategoryOffset * 2;  // Move the pointer over the data we've already unpacked.
0714 
0715   // UNPACK ENERGY SUMS
0716 
0717   for (unsigned int bx = firstSample; bx <= lastSample; ++bx)  // loop over all time samples
0718   {
0719     const unsigned int offset = bx * 2;
0720     colls()->gctEtTot()->push_back(L1GctEtTotal(p16[offset], (int)bx - (int)centralSample));    // Et total
0721     colls()->gctEtHad()->push_back(L1GctEtHad(p16[offset + 1], (int)bx - (int)centralSample));  // Et hadronic
0722   }
0723 
0724   p16 += nSamples * 2;
0725 
0726   // 32-bit pointer for getting Missing Et.
0727   const uint32_t* p32 = reinterpret_cast<const uint32_t*>(p16);
0728 
0729   for (unsigned int bx = firstSample; bx <= lastSample; ++bx) {
0730     colls()->gctEtMiss()->push_back(L1GctEtMiss(p32[bx], (int)bx - (int)centralSample));  // Et Miss
0731     LogDebug("GCT") << "Unpacked energy sums bx=" << bx << std::endl;
0732   }
0733 }
0734 
0735 void GctFormatTranslateV38::blockToGctJetCandsAndCounts(const unsigned char* d, const GctBlockHeader& hdr) {
0736   const unsigned int id = hdr.blockId();         // Capture block ID.
0737   const unsigned int nSamples = hdr.nSamples();  // Number of time-samples.
0738 
0739   // Re-interpret block payload pointer to 16 bits so it sees one candidate at a time.
0740   // p16 points to the start of the block payload, at the rank0 tau jet candidate.
0741   const uint16_t* p16 = reinterpret_cast<const uint16_t*>(d);
0742 
0743   // UNPACK JET CANDS
0744 
0745   const unsigned int jetCandCategoryOffset = nSamples * 4;  // Offset to jump from one jet category to the next.
0746   const unsigned int timeSampleOffset = nSamples * 2;  // Offset to jump to next candidate pair in the same time-sample.
0747 
0748   unsigned int samplesToUnpack =
0749       std::min(nSamples, m_numberOfGctSamplesToUnpack);  // Unpack as many as asked for if they are in the raw data
0750   unsigned int centralSample =
0751       (unsigned)std::ceil((double)nSamples / 2.) - 1;  // think this works when nSamples is even, need to check!!!
0752   unsigned int firstSample = centralSample - (unsigned)std::ceil((double)samplesToUnpack / 2.) + 1;
0753   unsigned int lastSample = centralSample + (unsigned)(samplesToUnpack / 2);
0754 
0755   LogDebug("GCT") << "Unpacking output Jets. Samples to unpack=" << samplesToUnpack << " central=" << centralSample
0756                   << " first=" << firstSample << " last=" << lastSample;
0757 
0758   // Loop over the different catagories of jets
0759   for (unsigned int iCat = 0; iCat < NUM_JET_CATEGORIES; ++iCat) {
0760     L1GctJetCandCollection* const jets = gctJets(iCat);
0761     assert(jets->empty());  // The supplied vector should be empty.
0762 
0763     bool tauflag = (iCat == TAU_JETS);
0764     bool forwardFlag = (iCat == FORWARD_JETS);
0765 
0766     // Loop over the different timesamples (bunch crossings).
0767     for (unsigned int bx = firstSample; bx <= lastSample; ++bx) {
0768       // cand0Offset will give the offset on p16 to get the rank 0 Jet Cand of the correct category and timesample.
0769       const unsigned int cand0Offset = iCat * jetCandCategoryOffset + bx * 2;
0770 
0771       // Rank 0 Jet.
0772       jets->push_back(L1GctJetCand(p16[cand0Offset], tauflag, forwardFlag, id, 0, (int)bx - (int)centralSample));
0773       // Rank 1 Jet.
0774       jets->push_back(
0775           L1GctJetCand(p16[cand0Offset + timeSampleOffset], tauflag, forwardFlag, id, 1, (int)bx - (int)centralSample));
0776       // Rank 2 Jet.
0777       jets->push_back(L1GctJetCand(p16[cand0Offset + 1], tauflag, forwardFlag, id, 2, (int)bx - (int)centralSample));
0778       // Rank 3 Jet.
0779       jets->push_back(L1GctJetCand(
0780           p16[cand0Offset + timeSampleOffset + 1], tauflag, forwardFlag, id, 3, (int)bx - (int)centralSample));
0781     }
0782   }
0783 
0784   p16 += NUM_JET_CATEGORIES * jetCandCategoryOffset;  // Move the pointer over the data we've already unpacked.
0785 
0786   // NOW UNPACK: HFBitCounts, HFRingEtSums and Missing Ht
0787 
0788   // Re-interpret block payload pointer to 32 bits so it sees six jet counts at a time.
0789   const uint32_t* p32 = reinterpret_cast<const uint32_t*>(p16);
0790 
0791   for (unsigned int bx = firstSample; bx <= lastSample; ++bx)  // loop over all time samples
0792   {
0793     // Channel 0 carries both HF counts and sums
0794     colls()->gctHfBitCounts()->push_back(
0795         L1GctHFBitCounts::fromConcHFBitCounts(id, 6, (int)bx - (int)centralSample, p32[bx]));
0796     colls()->gctHfRingEtSums()->push_back(
0797         L1GctHFRingEtSums::fromConcRingSums(id, 6, (int)bx - (int)centralSample, p32[bx]));
0798 
0799     // Channel 1 carries Missing HT.
0800     colls()->gctHtMiss()->push_back(L1GctHtMiss(p32[bx + nSamples], (int)bx - (int)centralSample));
0801   }
0802 }
0803 
0804 // Internal EM Candidates unpacking
0805 void GctFormatTranslateV38::blockToGctInternEmCand(const unsigned char* d, const GctBlockHeader& hdr) {
0806   // Don't want to do this in HLT optimisation mode!
0807   if (hltMode()) {
0808     LogDebug("GCT") << "HLT mode - skipping unpack of internal EM Cands";
0809     return;
0810   }
0811 
0812   unsigned int id = hdr.blockId();
0813   unsigned int nSamples = hdr.nSamples();
0814   unsigned int numCandPairs = hdr.blockLength();
0815 
0816   // Debug assertion to prevent problems if definitions not up to date.
0817   auto found = internEmIsoBounds().find(id);
0818   assert(found != internEmIsoBounds().end());
0819 
0820   unsigned int lowerIsoPairBound = found->second.first;
0821   unsigned int upperIsoPairBound = found->second.second;
0822 
0823   // Re-interpret pointer to 16 bits so it sees one candidate at a time.
0824   const uint16_t* p = reinterpret_cast<const uint16_t*>(d);
0825 
0826   // Loop over timesamples (i.e. bunch crossings)
0827   for (unsigned int bx = 0; bx < nSamples; ++bx) {
0828     // Loop over candidate pairs (i.e. each iteration unpacks a pair of candidates)
0829     for (unsigned int candPair = 0; candPair < numCandPairs; ++candPair) {
0830       // Is the candidate electron pair an isolated pair or not?
0831       bool iso = ((candPair >= lowerIsoPairBound) && (candPair <= upperIsoPairBound));
0832 
0833       // Loop over the two electron candidates in each pair
0834       for (unsigned int i = 0; i < 2; ++i) {
0835         unsigned offset = 2 * (bx + candPair * nSamples) + i;
0836         uint16_t candRaw = p[offset];
0837         colls()->gctInternEm()->push_back(L1GctInternEmCand(candRaw, iso, id, candPair * 2 + i, bx));
0838       }
0839     }
0840   }
0841 }
0842 
0843 // Input EM Candidates unpacking
0844 // this is the last time I deal the RCT bit assignment travesty!!!
0845 void GctFormatTranslateV38::blockToRctEmCand(const unsigned char* d, const GctBlockHeader& hdr) {
0846   // Don't want to do this in HLT optimisation mode!
0847   if (hltMode()) {
0848     LogDebug("GCT") << "HLT mode - skipping unpack of RCT EM Cands";
0849     return;
0850   }
0851 
0852   unsigned int id = hdr.blockId();
0853   unsigned int nSamples = hdr.nSamples();
0854   unsigned int length = hdr.blockLength();
0855 
0856   // re-interpret pointer
0857   const uint16_t* p = reinterpret_cast<const uint16_t*>(d);
0858 
0859   // arrays of source card data
0860   uint16_t sfp[2][4];  // [ cycle ] [ SFP ]
0861   uint16_t eIsoRank[4];
0862   uint16_t eIsoCard[4];
0863   uint16_t eIsoRgn[4];
0864   uint16_t eNonIsoRank[4];
0865   uint16_t eNonIsoCard[4];
0866   uint16_t eNonIsoRgn[4];
0867   uint16_t MIPbits[7][2];
0868   uint16_t QBits[7][2];
0869 
0870   unsigned int bx = 0;
0871 
0872   auto found = rctEmCrateMap().find(id);
0873   assert(found != rctEmCrateMap().end());
0874   // loop over crates
0875   for (unsigned int crate = found->second; crate < found->second + length / 3; ++crate) {
0876     // read SC SFP words
0877     for (unsigned short iSfp = 0; iSfp < 4; ++iSfp) {
0878       for (unsigned short cyc = 0; cyc < 2; ++cyc) {
0879         if (iSfp == 0) {
0880           sfp[cyc][iSfp] = 0;
0881         }       // muon bits
0882         else {  // EM candidate
0883           sfp[cyc][iSfp] = *p;
0884           ++p;
0885         }
0886       }
0887       p = p + 2 * (nSamples - 1);
0888     }
0889 
0890     // fill SC arrays
0891     srcCardRouting().SFPtoEMU(eIsoRank, eIsoCard, eIsoRgn, eNonIsoRank, eNonIsoCard, eNonIsoRgn, MIPbits, QBits, sfp);
0892 
0893     // create EM cands
0894     for (unsigned short int i = 0; i < 4; ++i) {
0895       colls()->rctEm()->push_back(L1CaloEmCand(eIsoRank[i], eIsoRgn[i], eIsoCard[i], crate, true, i, bx));
0896     }
0897     for (unsigned short int i = 0; i < 4; ++i) {
0898       colls()->rctEm()->push_back(L1CaloEmCand(eNonIsoRank[i], eNonIsoRgn[i], eNonIsoCard[i], crate, false, i, bx));
0899     }
0900   }
0901 }
0902 
0903 // Input RCT region unpacking
0904 void GctFormatTranslateV38::blockToRctCaloRegions(const unsigned char* d, const GctBlockHeader& hdr) {
0905   // Don't want to do this in HLT optimisation mode!
0906   if (hltMode()) {
0907     LogDebug("GCT") << "HLT mode - skipping unpack of RCT Regions";
0908     return;
0909   }
0910 
0911   unsigned int id = hdr.blockId();
0912   unsigned int nSamples = hdr.nSamples();
0913   unsigned int length = hdr.blockLength();
0914 
0915   // Debug assertion to prevent problems if definitions not up to date.
0916   auto found = rctJetCrateMap().find(id);
0917   assert(found != rctJetCrateMap().end());
0918 
0919   // get crate (need this to get ieta and iphi)
0920   unsigned int crate = found->second;
0921 
0922   // re-interpret pointer
0923   const uint16_t* p = reinterpret_cast<const uint16_t*>(d);
0924 
0925   // eta and phi
0926   unsigned int ieta;
0927   unsigned int iphi;
0928 
0929   for (unsigned int i = 0; i < length; ++i) {
0930     for (uint16_t bx = 0; bx < nSamples; ++bx) {
0931       // First figure out eta and phi
0932       if (crate < 9) {  // negative eta
0933         ieta = 12 - i;
0934         iphi = 2 * ((11 - crate) % 9);
0935       } else {  // positive eta
0936         ieta = 9 + i;
0937         iphi = 2 * ((20 - crate) % 9);
0938       }
0939 
0940       // Skip the first four regions (i.e. where i<2) which are duplicates (shared data).
0941       if (i > 1) {
0942         // First region is phi=0
0943         colls()->rctCalo()->push_back(L1CaloRegion::makeRegionFromUnpacker(*p, ieta, iphi, id, i, bx));
0944         ++p;
0945         // Second region is phi=1
0946         if (iphi > 0) {
0947           iphi -= 1;
0948         } else {
0949           iphi = 17;
0950         }
0951         colls()->rctCalo()->push_back(L1CaloRegion::makeRegionFromUnpacker(*p, ieta, iphi, id, i, bx));
0952         ++p;
0953       }
0954       // Unpack the shared data if asked for debugging
0955       else if (unpackSharedRegions()) {
0956         // First region is phi=0
0957         colls()->rctCalo()->push_back(L1CaloRegion::makeRegionFromUnpacker(*p, ieta, iphi, id, i, bx));
0958         ++p;
0959         // Second region is phi=1
0960         if (iphi > 0) {
0961           iphi -= 1;
0962         } else {
0963           iphi = 17;
0964         }
0965         colls()->rctCalo()->push_back(L1CaloRegion::makeRegionFromUnpacker(*p, ieta, iphi, id, i, bx));
0966         ++p;
0967 
0968       } else {  // Skip the shared data
0969         ++p;
0970         ++p;
0971       }
0972     }
0973   }
0974 }
0975 
0976 // Fibre unpacking
0977 void GctFormatTranslateV38::blockToFibres(const unsigned char* d, const GctBlockHeader& hdr) {
0978   // Don't want to do this in HLT optimisation mode!
0979   if (hltMode()) {
0980     LogDebug("GCT") << "HLT mode - skipping unpack of GCT Fibres";
0981     return;
0982   }
0983 
0984   unsigned int id = hdr.blockId();
0985   unsigned int nSamples = hdr.nSamples();
0986   unsigned int length = hdr.blockLength();
0987 
0988   // re-interpret pointer
0989   const uint32_t* p = reinterpret_cast<const uint32_t*>(d);
0990 
0991   for (unsigned int i = 0; i < length; ++i) {
0992     for (unsigned int bx = 0; bx < nSamples; ++bx) {
0993       colls()->gctFibres()->push_back(L1GctFibreWord(*p, id, i, bx));
0994       ++p;
0995     }
0996   }
0997 }
0998 
0999 void GctFormatTranslateV38::blockToFibresAndToRctEmCand(const unsigned char* d, const GctBlockHeader& hdr) {
1000   this->blockToRctEmCand(d, hdr);
1001   this->blockToFibres(d, hdr);
1002 }
1003 
1004 void GctFormatTranslateV38::blockToGctInternEtSums(const unsigned char* d, const GctBlockHeader& hdr) {
1005   // Don't want to do this in HLT optimisation mode!
1006 
1007   if (hltMode()) {
1008     LogDebug("GCT") << "HLT mode - skipping unpack of internal Et Sums";
1009     return;
1010   }
1011 
1012   unsigned int id = hdr.blockId();
1013   unsigned int nSamples = hdr.nSamples();
1014   unsigned int length = hdr.blockLength();
1015 
1016   // Re-interpret pointer to 32 bits
1017   const uint32_t* p = reinterpret_cast<const uint32_t*>(d);
1018 
1019   for (unsigned int i = 0; i < length; ++i) {
1020     // Loop over timesamples (i.e. bunch crossings)
1021     for (unsigned int bx = 0; bx < nSamples; ++bx) {
1022       colls()->gctInternEtSums()->push_back(L1GctInternEtSum::fromTotalEtOrHt(id, i, bx, *p));
1023       ++p;
1024     }
1025   }
1026 }
1027 
1028 void GctFormatTranslateV38::blockToGctInternEtSumsAndJetCluster(const unsigned char* d, const GctBlockHeader& hdr) {
1029   // Don't want to do this in HLT optimisation mode!
1030   if (hltMode()) {
1031     LogDebug("GCT") << "HLT mode - skipping unpack of internal Jet Cands";
1032     return;
1033   }
1034 
1035   unsigned int id = hdr.blockId();
1036   unsigned int nSamples = hdr.nSamples();
1037   unsigned int length = hdr.blockLength();
1038 
1039   // Re-interpret pointer to 32 bits
1040   const uint32_t* p = reinterpret_cast<const uint32_t*>(d);
1041 
1042   for (unsigned int i = 0; i < length; ++i) {
1043     // Loop over timesamples (i.e. bunch crossings)
1044     for (unsigned int bx = 0; bx < nSamples; ++bx) {
1045       if (i < 2)
1046         colls()->gctInternEtSums()->push_back(L1GctInternEtSum::fromJetMissEt(id, i, bx, *p));
1047       if (i == 3) {
1048         colls()->gctInternEtSums()->push_back(L1GctInternEtSum::fromJetTotEt(id, i, bx, *p));
1049         colls()->gctInternEtSums()->push_back(L1GctInternEtSum::fromJetTotHt(id, i, bx, *p));
1050       }
1051       if (i > 4)
1052         colls()->gctInternJets()->push_back(L1GctInternJetData::fromJetCluster(L1CaloRegionDetId(0, 0), id, i, bx, *p));
1053       ++p;
1054     }
1055   }
1056 }
1057 
1058 void GctFormatTranslateV38::blockToGctTrigObjects(const unsigned char* d, const GctBlockHeader& hdr) {
1059   // Don't want to do this in HLT optimisation mode!
1060   if (hltMode()) {
1061     LogDebug("GCT") << "HLT mode - skipping unpack of internal Jet Cands";
1062     return;
1063   }
1064 
1065   unsigned int id = hdr.blockId();
1066   unsigned int nSamples = hdr.nSamples();
1067   unsigned int length = hdr.blockLength();
1068 
1069   // Re-interpret pointer to 16 bits so it sees one candidate at a time.
1070   const uint16_t* p = reinterpret_cast<const uint16_t*>(d);
1071 
1072   for (unsigned int i = 0; i < length; ++i) {
1073     // Loop over timesamples (i.e. bunch crossings)
1074     for (unsigned int bx = 0; bx < nSamples; ++bx) {
1075       colls()->gctInternJets()->push_back(
1076           L1GctInternJetData::fromGctTrigObject(L1CaloRegionDetId(0, 0), id, i, bx, *p));
1077       ++p;
1078       colls()->gctInternJets()->push_back(
1079           L1GctInternJetData::fromGctTrigObject(L1CaloRegionDetId(0, 0), id, i, bx, *p));
1080       ++p;
1081     }
1082   }
1083 }
1084 
1085 void GctFormatTranslateV38::blockToGctJetClusterMinimal(const unsigned char* d, const GctBlockHeader& hdr) {
1086   // Don't want to do this in HLT optimisation mode!
1087   if (hltMode()) {
1088     LogDebug("GCT") << "HLT mode - skipping unpack of internal Jet Cands";
1089     return;
1090   }
1091 
1092   unsigned int id = hdr.blockId();
1093   unsigned int nSamples = hdr.nSamples();
1094   unsigned int length = hdr.blockLength();
1095 
1096   // Re-interpret pointer to 16 bits so it sees one candidate at a time.
1097   const uint16_t* p = reinterpret_cast<const uint16_t*>(d);
1098 
1099   for (unsigned int i = 0; i < length; ++i) {
1100     // Loop over timesamples (i.e. bunch crossings)
1101     for (unsigned int bx = 0; bx < nSamples; ++bx) {
1102       colls()->gctInternJets()->push_back(
1103           L1GctInternJetData::fromJetClusterMinimal(L1CaloRegionDetId(0, 0), id, i, bx, *p));
1104       ++p;
1105       colls()->gctInternJets()->push_back(
1106           L1GctInternJetData::fromJetClusterMinimal(L1CaloRegionDetId(0, 0), id, i, bx, *p));
1107       ++p;
1108     }
1109   }
1110 }
1111 
1112 void GctFormatTranslateV38::blockToGctJetPreCluster(const unsigned char* d, const GctBlockHeader& hdr) {
1113   // Don't want to do this in HLT optimisation mode!
1114   if (hltMode()) {
1115     LogDebug("GCT") << "HLT mode - skipping unpack of internal Jet Cands";
1116     return;
1117   }
1118 
1119   unsigned int id = hdr.blockId();
1120   unsigned int nSamples = hdr.nSamples();
1121   unsigned int length = hdr.blockLength();
1122 
1123   // Re-interpret pointer to 16 bits so it sees one candidate at a time.
1124   const uint16_t* p = reinterpret_cast<const uint16_t*>(d);
1125 
1126   for (unsigned int i = 0; i < length; ++i) {
1127     // Loop over timesamples (i.e. bunch crossings)
1128     for (unsigned int bx = 0; bx < nSamples; ++bx) {
1129       colls()->gctInternJets()->push_back(
1130           L1GctInternJetData::fromJetPreCluster(L1CaloRegionDetId(0, 0), id, i, bx, *p));
1131       ++p;
1132       colls()->gctInternJets()->push_back(
1133           L1GctInternJetData::fromJetPreCluster(L1CaloRegionDetId(0, 0), id, i, bx, *p));
1134       ++p;
1135     }
1136   }
1137 }
1138 
1139 void GctFormatTranslateV38::blockToGctInternRingSums(const unsigned char* d, const GctBlockHeader& hdr) {
1140   // Don't want to do this in HLT optimisation mode!
1141   if (hltMode()) {
1142     LogDebug("GCT") << "HLT mode - skipping unpack of internal HF ring data";
1143     return;
1144   }
1145 
1146   unsigned int id = hdr.blockId();
1147   unsigned int nSamples = hdr.nSamples();
1148   unsigned int length = hdr.blockLength();
1149 
1150   // Re-interpret pointer to 32 bits
1151   const uint32_t* p = reinterpret_cast<const uint32_t*>(d);
1152 
1153   for (unsigned int i = 0; i < length / 2; ++i) {
1154     // Loop over timesamples (i.e. bunch crossings)
1155     for (unsigned int bx = 0; bx < nSamples; ++bx) {
1156       colls()->gctInternHFData()->push_back(L1GctInternHFData::fromConcRingSums(id, i, bx, *p));
1157       ++p;
1158     }
1159     for (unsigned int bx = 0; bx < nSamples; ++bx) {
1160       colls()->gctInternHFData()->push_back(L1GctInternHFData::fromConcBitCounts(id, i, bx, *p));
1161       ++p;
1162     }
1163   }
1164 }
1165 
1166 void GctFormatTranslateV38::blockToGctWheelInputInternEtAndRingSums(const unsigned char* d, const GctBlockHeader& hdr) {
1167   // Don't want to do this in HLT optimisation mode!
1168   if (hltMode()) {
1169     LogDebug("GCT") << "HLT mode - skipping unpack of wheel input internal Et sums and HF ring data";
1170     return;
1171   }
1172 
1173   unsigned int id = hdr.blockId();
1174   unsigned int nSamples = hdr.nSamples();
1175   unsigned int length = hdr.blockLength();
1176 
1177   // Re-interpret pointer to 32 bits
1178   const uint32_t* p = reinterpret_cast<const uint32_t*>(d);
1179 
1180   for (unsigned int i = 0; i < length; ++i) {
1181     // Loop over timesamples (i.e. bunch crossings)
1182     for (unsigned int bx = 0; bx < nSamples; ++bx) {
1183       if (i < 3) {
1184         colls()->gctInternEtSums()->push_back(L1GctInternEtSum::fromTotalEtOrHt(id, i, bx, *p));
1185       } else if (i > 2 && i < 9) {
1186         colls()->gctInternEtSums()->push_back(L1GctInternEtSum::fromMissEtxOrEty(id, i, bx, *p));
1187       } else if (i > 8 && i < 15) {
1188         colls()->gctInternHFData()->push_back(L1GctInternHFData::fromWheelRingSums(id, i, bx, *p));
1189       } else if (i > 14) {
1190         colls()->gctInternHFData()->push_back(L1GctInternHFData::fromWheelBitCounts(id, i, bx, *p));
1191       }
1192       ++p;
1193     }
1194   }
1195 }
1196 
1197 void GctFormatTranslateV38::blockToGctWheelOutputInternEtAndRingSums(const unsigned char* d,
1198                                                                      const GctBlockHeader& hdr) {
1199   // Don't want to do this in HLT optimisation mode!
1200   if (hltMode()) {
1201     LogDebug("GCT") << "HLT mode - skipping unpack of wheel output internal Et sums and HF ring data";
1202     return;
1203   }
1204 
1205   unsigned int id = hdr.blockId();
1206   unsigned int nSamples = hdr.nSamples();
1207   unsigned int length = hdr.blockLength();
1208 
1209   // Re-interpret pointer to 32 bits
1210   const uint32_t* p = reinterpret_cast<const uint32_t*>(d);
1211 
1212   for (unsigned int i = 0; i < length; ++i) {
1213     // Loop over timesamples (i.e. bunch crossings)
1214     for (unsigned int bx = 0; bx < nSamples; ++bx) {
1215       if (i < 1) {
1216         colls()->gctInternEtSums()->push_back(L1GctInternEtSum::fromTotalEtOrHt(id, i, bx, *p));
1217       } else if (i > 0 && i < 3) {
1218         colls()->gctInternEtSums()->push_back(L1GctInternEtSum::fromMissEtxOrEty(id, i, bx, *p));
1219       } else if (i > 2 && i < 5) {
1220         colls()->gctInternHFData()->push_back(L1GctInternHFData::fromWheelRingSums(id, i, bx, *p));
1221       } else if (i > 4) {
1222         colls()->gctInternHFData()->push_back(L1GctInternHFData::fromWheelBitCounts(id, i, bx, *p));
1223       }
1224       ++p;
1225     }
1226   }
1227 }
1228 
1229 void GctFormatTranslateV38::blockToGctInternHtMissPreWheel(const unsigned char* d, const GctBlockHeader& hdr) {
1230   // Don't want to do this in HLT optimisation mode!
1231   if (hltMode()) {
1232     LogDebug("GCT") << "HLT mode - skipping unpack of pre-wheel internal Missing Ht data";
1233     return;
1234   }
1235 
1236   unsigned int id = hdr.blockId();
1237   unsigned int nSamples = hdr.nSamples();
1238   unsigned int length = hdr.blockLength();
1239 
1240   // Re-interpret pointer to 32 bits
1241   const uint32_t* p = reinterpret_cast<const uint32_t*>(d);
1242 
1243   for (unsigned int iLength = 0; iLength < length; ++iLength) {
1244     // Loop over timesamples (i.e. bunch crossings)
1245     for (unsigned int bx = 0; bx < nSamples; ++bx) {
1246       colls()->gctInternHtMiss()->push_back(L1GctInternHtMiss::unpackerMissHtxHty(id, iLength, bx, *p));
1247       ++p;
1248     }
1249   }
1250 }
1251 
1252 void GctFormatTranslateV38::blockToGctInternHtMissPostWheel(const unsigned char* d, const GctBlockHeader& hdr) {
1253   // Don't want to do this in HLT optimisation mode!
1254   if (hltMode()) {
1255     LogDebug("GCT") << "HLT mode - skipping unpack of post-wheel internal Missing Ht data";
1256     return;
1257   }
1258 
1259   unsigned int id = hdr.blockId();
1260   unsigned int nSamples = hdr.nSamples();
1261   unsigned int length = hdr.blockLength();
1262 
1263   // Re-interpret pointer to 32 bits
1264   const uint32_t* p = reinterpret_cast<const uint32_t*>(d);
1265 
1266   for (unsigned int iLength = 0; iLength < length; ++iLength) {
1267     // Loop over timesamples (i.e. bunch crossings)
1268     for (unsigned int bx = 0; bx < nSamples; ++bx) {
1269       if (iLength % 2) {
1270         colls()->gctInternHtMiss()->push_back(L1GctInternHtMiss::unpackerMissHty(id, iLength, bx, *p));
1271       }  // Hty on odd numbers
1272       else {
1273         colls()->gctInternHtMiss()->push_back(L1GctInternHtMiss::unpackerMissHtx(id, iLength, bx, *p));
1274       }  // Htx on even numbers
1275       ++p;
1276     }
1277   }
1278 }
1279 
1280 //  LocalWords:  rctJetCrate