1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
#ifndef DataFormats_L1TCalorimeterPhase2_GCTEmDigiCluster_h
#define DataFormats_L1TCalorimeterPhase2_GCTEmDigiCluster_h
#include <ap_int.h>
#include <vector>
#include "DataFormats/L1TCalorimeterPhase2/interface/CaloCrystalCluster.h"
#include "DataFormats/L1TCalorimeterPhase2/interface/DigitizedClusterCorrelator.h"
namespace l1tp2 {
class GCTEmDigiCluster {
private:
// Data
unsigned long long int clusterData;
// Constants
static constexpr float LSB_PT = 0.5; // 0.5 GeV
// start of the unused bits
static constexpr int n_bits_unused_start = 52;
// Reference to the original float cluster
edm::Ref<l1tp2::CaloCrystalClusterCollection> clusterRef_;
// reference to the original digitized cluster (before duplication in the output links)
edm::Ref<l1tp2::DigitizedClusterCorrelatorCollection> digiClusterRef_;
public:
GCTEmDigiCluster() { clusterData = 0; }
GCTEmDigiCluster(ap_uint<64> data) { clusterData = data; }
GCTEmDigiCluster(ap_uint<12> pt,
int etaCr,
int phiCr,
ap_uint<4> hoe,
ap_uint<2> hoeFlag,
ap_uint<3> iso,
ap_uint<2> isoFlag,
ap_uint<6> fb,
ap_uint<5> timing,
ap_uint<2> shapeFlag,
ap_uint<2> brems) {
// To use .range() we need an ap class member
ap_uint<64> temp_data;
ap_uint<7> etaCrDigitized = abs(etaCr);
ap_int<7> phiCrDigitized = phiCr;
temp_data.range(11, 0) = pt.range();
temp_data.range(18, 12) = etaCrDigitized.range();
temp_data.range(25, 19) = phiCrDigitized.range();
temp_data.range(29, 26) = hoe.range();
temp_data.range(31, 30) = hoeFlag.range();
temp_data.range(34, 32) = iso.range();
temp_data.range(36, 35) = isoFlag.range();
temp_data.range(42, 37) = fb.range();
temp_data.range(47, 43) = timing.range();
temp_data.range(49, 48) = shapeFlag.range();
temp_data.range(51, 50) = brems.range();
clusterData = temp_data;
}
// Setters
void setRef(const edm::Ref<l1tp2::CaloCrystalClusterCollection>& clusterRef) { clusterRef_ = clusterRef; }
void setDigiRef(const edm::Ref<l1tp2::DigitizedClusterCorrelatorCollection>& digiClusterRef) {
digiClusterRef_ = digiClusterRef;
}
// Getters
ap_uint<64> data() const { return clusterData; }
// Other getters
float ptLSB() const { return LSB_PT; }
ap_uint<12> pt() const { return data().range(11, 0); }
float ptFloat() const { return pt() * ptLSB(); }
// crystal eta (unsigned, 7 bits), starting at 0 at real eta = 0, and increasing in the direction of larger abs(real eta)
// to convert to real eta, need to know which link this cluster is in
int eta() const { return (ap_uint<7>)data().range(18, 12); }
// crystal phi (signed, 7 bits), relative to center of the SLR
// to convert to real phi, need to know which SLR this cluster is in
int phi() const { return (ap_int<7>)data().range(25, 19); }
// HoE value and flag: not defined yet in the emulator
ap_uint<4> hoe() const { return data().range(29, 26); }
ap_uint<2> hoeFlag() const { return data().range(31, 30); }
// Raw isolation sum: not saved in the emulator
ap_uint<3> iso() const { return data().range(34, 32); }
// iso flag: two bits, least significant bit is the standalone WP (true or false), second bit is the looseTk WP (true or false)
// e.g. 0b01 : standalone iso flag passed, loose Tk iso flag did not pass
ap_uint<2> isoFlags() const { return data().range(36, 35); }
bool passes_iso() const { return (isoFlags() & 0x1); } // standalone iso WP
bool passes_looseTkiso() const { return (isoFlags() & 0x2); } // loose Tk iso WP
// fb and timing: not saved in the current emulator
ap_uint<6> fb() const { return data().range(42, 37); }
ap_uint<5> timing() const { return data().range(47, 43); }
// shower shape shape flag: two bits, least significant bit is the standalone WP, second bit is the looseTk WP
// e.g. 0b01 : standalone shower shape flag passed, loose Tk shower shape flag did not pass
ap_uint<2> shapeFlags() const { return data().range(49, 48); }
bool passes_ss() const { return (shapeFlags() & 0x1); } // standalone shower shape WP
bool passes_looseTkss() const { return (shapeFlags() & 0x2); } // loose Tk shower shape WP
// brems: not saved in the current emulator
ap_uint<2> brems() const { return data().range(51, 50); }
// Check that unused bits are zero
const int unusedBitsStart() const { return n_bits_unused_start; }
bool passNullBitsCheck(void) const { return ((data() >> unusedBitsStart()) == 0); }
// Get the underlying float cluster
const edm::Ref<l1tp2::CaloCrystalClusterCollection>& clusterRef() const { return clusterRef_; }
// Get the underlying digitized cluster (before duplication and zero-padding)
const edm::Ref<l1tp2::DigitizedClusterCorrelatorCollection>& digiClusterRef() const { return digiClusterRef_; }
};
// Collection typedefs
// This represents the 36 GCTEmDigiClusters in one link (one link spans 4 RCT cards, each RCT card sends 9 clusters (zero-padded and sorted by decreasing pT))
// The ordering of the 4 RCT cards in the link is, e.g. for GCT1.SLR3, real phi -50 to -20 degrees, then real phi -20 to 10 degrees, then real phi 10 to 40 degrees, and lastly real phi 40 to 70 degrees
typedef std::vector<l1tp2::GCTEmDigiCluster> GCTEmDigiClusterLink;
// This represents the 12 links sending GCTEmDigiClusters in the full barrel: there are 12 links = (3 GCT cards) * (two SLRs per GCT) * (one positive eta link and one negative eta link)
// The ordering of the links in this std::vector is (GCT1.SLR1 negEta, GCT.SLR1 posEta, GCT1.SLR3 negEta, GCT1.SLR3 posEta, then analogously for GCT2 and GCT3)
typedef std::vector<l1tp2::GCTEmDigiClusterLink> GCTEmDigiClusterCollection;
} // namespace l1tp2
#endif
|