ATLAS Offline Software
Loading...
Searching...
No Matches
NSWTP_ROD_Decoder.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4#include "NSWTP_ROD_Decoder.h"
5#include "Identifier/Identifier.h"
6#include "eformat/Issue.h"
7#include "eformat/SourceIdentifier.h"
12
13
14namespace Muon {
15
16using namespace nsw::STGTPSegments;
21using namespace nsw::STGTPMMData;
22using namespace nsw::STGTPStrips;
23//=====================================================================
24NSWTP_ROD_Decoder::NSWTP_ROD_Decoder(const std::string& type, const std::string& name, const IInterface* parent)
25: AthAlgTool(type, name, parent)
26{
27 declareInterface<INSWTP_ROD_Decoder>(this);
28}
29
31 ATH_CHECK(m_idHelperSvc.retrieve());
32 return StatusCode::SUCCESS;
33}
34
35//=====================================================================
37{
38 try {
39 fragment.check();
40 } catch (const eformat::Issue& ex) {
41 ATH_MSG_ERROR(ex.what());
42 return StatusCode::FAILURE;
43 }
44
45 Muon::nsw::NSWTriggerCommonDecoder nsw_trigger_decoder (fragment, "STGL1A");
46
47 if (nsw_trigger_decoder.has_error()) {
48 ATH_MSG_DEBUG("NSW sTGC TP Common Decoder found exceptions while reading this STGL1A fragment from " + std::to_string(fragment.rob_source_id()) + ". Skipping. Error id: "+std::to_string(nsw_trigger_decoder.error_id()));
49 return StatusCode::SUCCESS;
50 }
51
52 if (nsw_trigger_decoder.get_elinks().size()==1) {
53 if (static_cast<Muon::nsw::NSWTriggerSTGL1AElink*>(nsw_trigger_decoder.get_elinks()[0].get())->l1a_versionID() >= 3){
54 ATH_MSG_DEBUG("NSW sTGC TP Common Decoder found only one elink in output but inconsistent L1A version: something off with this fragment. Skipping.");
55 return StatusCode::SUCCESS;
56 }
57 } else if (nsw_trigger_decoder.get_elinks().size()!=3 && nsw_trigger_decoder.get_elinks().size()!=5) {
58 // this is a severe requirement: a single elink missing would imply the whole event is problematic
59 ATH_MSG_DEBUG("NSW sTGC TP Common Decoder didn't give 3 or 5 elinks in output for: something off with this fragment. Skipping.");
60 return StatusCode::SUCCESS;
61 }
62
63 bool consistent = true;
64 const auto l0 = static_cast<Muon::nsw::NSWTriggerSTGL1AElink*>(nsw_trigger_decoder.get_elinks()[0].get());
65 for(const auto& baseLink: nsw_trigger_decoder.get_elinks()) {
66 const auto l = static_cast<Muon::nsw::NSWTriggerSTGL1AElink*>(baseLink.get());
67 if (l0->head_sectID() != l->head_sectID()) {consistent = false; break;}
68 if (l0->L1ID() != l->L1ID()) {consistent = false; break;}
69 if (l0->l1a_versionID() != l->l1a_versionID()) {consistent = false; break;}
70 if (l0->l1a_req_BCID() != l->l1a_req_BCID()) {consistent = false; break;}
71 }
72 if (!consistent) {
73 ATH_MSG_WARNING("NSW sTGC TP Common Decoder found inconsistent header parameters in the elinks: something off with this fragment. Skipping.");
74 return StatusCode::SUCCESS;
75 }
76
77 xAOD::NSWTPRDO* rdo = new xAOD::NSWTPRDO();
78 rdoContainer.push_back(rdo);
79
80 for(const auto& baseLink: nsw_trigger_decoder.get_elinks()){
82 const auto link = static_cast<Muon::nsw::NSWTriggerSTGL1AElink*>(baseLink.get());
83 const std::shared_ptr<Muon::nsw::NSWResourceId>& elinkID = link->elinkId ();
84
85 uint32_t moduleID{0};
86 encodeIdentifierProperty(ModuleIDProperty::stationID, elinkID->is_large_station(), moduleID );
87 encodeIdentifierProperty(ModuleIDProperty::detectorSite, elinkID->station_eta() > 0 , moduleID );
88 encodeIdentifierProperty(ModuleIDProperty::stationEta, std::abs(elinkID->station_eta()) , moduleID );
89 encodeIdentifierProperty(ModuleIDProperty::stationPhi, elinkID->station_phi() , moduleID );
90 rdo->set_moduleID(moduleID);
91
92 // now filling all the header data
93 rdo->set_ROD_L1ID(fragment.rod_lvl1_id ());
94 rdo->set_sectID(link->head_sectID());
95 rdo->set_EC(link->head_EC());
96 rdo->set_BCID(link->head_BCID());
97 rdo->set_L1ID(link->L1ID());
98 rdo->set_window_open_bcid(link->l1a_open_BCID());
99 rdo->set_l1a_request_bcid(link->l1a_req_BCID());
100 rdo->set_window_close_bcid(link->l1a_close_BCID());
101 rdo->set_config_window_open_bcid_offset(link->l1a_open_BCID_offset());
102 rdo->set_config_l1a_request_bcid_offset(link->l1a_req_BCID_offset());
103 rdo->set_config_window_close_bcid_offset(link->l1a_close_BCID_offset());
104
105 // now we are filling all the pad segment variables
106 const std::vector<STGTPPadPacket>& pad_packets = link->pad_packets();
107 for(uint i_packetIndex = 0; i_packetIndex<pad_packets.size(); i_packetIndex++){
108 const STGTPPadPacket& pad_packet = pad_packets.at(i_packetIndex);
109 for(uint i_candidateIndex=0; i_candidateIndex < 4; i_candidateIndex++){ // we have at most 4 candidates in the input
110 if(pad_packet.BandID(i_candidateIndex) == Muon::nsw::STGTPPad::pad_stream_invalid_band_id) continue; // ignore candidates that the trigger processor flags as invalid
111 uint8_t candidateNumber = (i_packetIndex<<4) | i_candidateIndex;
112 rdo->pad_candidateNumber().push_back(candidateNumber);
113 rdo->pad_phiID().push_back(pad_packet.PhiID(i_candidateIndex));
114 rdo->pad_bandID().push_back(pad_packet.BandID(i_candidateIndex));
115 }
116 rdo->pad_BCID().push_back(pad_packet.BCID());
117 rdo->pad_idleFlag().push_back(pad_packet.PadIdleFlag());
118 rdo->pad_coincidence_wedge().push_back(pad_packet.CoincidenceWedge());
119
120 }
121
122 // lets fill the output segments (merged)
123 const std::vector<STGTPSegmentPacket>& segment_packets = link->segment_packet();
124 for(uint i_packetIndex = 0; i_packetIndex<segment_packets.size(); i_packetIndex++){
125 const STGTPSegmentPacket& segment_packet = segment_packets.at(i_packetIndex);
126 uint8_t i_candidateIndex{0};
127 for (const STGTPSegmentPacket::SegmentData& payload : segment_packet.Segments()){
128 // we have at most 8 candidates in the output
130 ++i_candidateIndex;
131 continue; // ignore candidates that the trigger processor flags as invalid
132 }
133 uint32_t word{0}; // word containing all information about the candidate
134 encodeSegmentProperty(MergedSegmentProperty::Monitor, payload.monitor ,word);
135 encodeSegmentProperty(MergedSegmentProperty::Spare, payload.spare ,word);
136 encodeSegmentProperty(MergedSegmentProperty::lowRes, payload.lowRes ,word);
137 encodeSegmentProperty(MergedSegmentProperty::phiRes, payload.phiRes,word);
138 encodeSegmentProperty(MergedSegmentProperty::dTheta, payload.dTheta,word);
139 encodeSegmentProperty(MergedSegmentProperty::phiID, payload.phiID,word);
140 encodeSegmentProperty(MergedSegmentProperty::rIndex, payload.rIndex ,word);
141 uint8_t candidateNumber = (i_packetIndex<<4) | i_candidateIndex;
142 ++i_candidateIndex;
143
144 rdo->merge_segments().push_back(word);
145 rdo->merge_candidateNumber().push_back(candidateNumber);
146 }
147 // the first 12 bit are used for the bcid and the last 4 for sector ID
148 uint16_t merge_BCID_sectorID = (segment_packet.BCID() << 4) | segment_packet.SectorID();
149 rdo->merge_BCID_sectorID().push_back(merge_BCID_sectorID);
150 rdo->merge_valid_segmentSelector().push_back(segment_packet.ValidSegmentSelector());
151 rdo->merge_nsw_segmentSelector().push_back(segment_packet.NSW_SegmentSelector());
152 rdo->merge_LUT_choiceSelection().push_back(segment_packet.LUT_ChoiceSelection());
153 }
154
155 if (link->l1a_versionID() < 3){
156 return StatusCode::SUCCESS;
157 }
158
159 const std::vector<STGTPMMPacket>& mm_packets = link->mm_packet();
160 for(uint i_packetIndex = 0; i_packetIndex<mm_packets.size(); i_packetIndex++){
161 const STGTPMMPacket& mm_packet = mm_packets.at(i_packetIndex);
162 uint8_t i_candidateIndex{0};
163 for (const STGTPMMPacket::MMSegmentData& payload : mm_packet.Segments()){
164 // we have at most 8 candidates in the output - non valid segments marked with a bit, are already skipped
166 ++i_candidateIndex;
167 continue; // ignore candidates that the trigger processor flags as invalid
168 }
169 uint32_t word{0}; // word containing all information about the candidate
170 encodeSegmentProperty(MergedSegmentProperty::Monitor, payload.monitor ,word);
171 encodeSegmentProperty(MergedSegmentProperty::Spare, payload.spare ,word);
172 encodeSegmentProperty(MergedSegmentProperty::lowRes, payload.lowRes ,word);
173 encodeSegmentProperty(MergedSegmentProperty::phiRes, payload.phiRes,word);
174 encodeSegmentProperty(MergedSegmentProperty::dTheta, payload.dTheta,word);
175 encodeSegmentProperty(MergedSegmentProperty::phiID, payload.phiID,word);
176 encodeSegmentProperty(MergedSegmentProperty::rIndex, payload.rIndex ,word);
177 uint8_t candidateNumber = (i_packetIndex<<4) | i_candidateIndex;
178 ++i_candidateIndex;
179
180 rdo->NSWTP_mm_segments().push_back(word);
181 rdo->NSWTP_mm_candidateNumber().push_back(candidateNumber);
182 }
183 // the first 12 bit are used for the bcid and the last 4 for sector ID
184 rdo->NSWTP_mm_BCID().push_back(mm_packet.BCID());
185 }
186
187 // Process strip packets (v3+ only)
188 const std::vector<STGTPStripPacket>& strip_packets = link->strip_packet();
189 for(uint i_packetIndex = 0; i_packetIndex < strip_packets.size(); i_packetIndex++){
190 const STGTPStripPacket& strip_packet = strip_packets.at(i_packetIndex);
191
192 // Store all 112 strip ADC values as bands_charge
193 for(std::size_t i_strip = 0; i_strip < num_strips; ++i_strip) {
194 rdo->NSWTP_strip_bands_charge().push_back(static_cast<uint8_t>(strip_packet.Strip(i_strip)));
195 // Calculate layer: each 14 strips come from a layer in order
196 rdo->NSWTP_strip_bands_layer().push_back(static_cast<uint8_t>(i_strip / 14));
197 rdo->NSWTP_strip_bands_phiID().push_back(static_cast<uint8_t>(strip_packet.PhiIdValue()));
198 rdo->NSWTP_strip_bands_bandID().push_back(static_cast<uint8_t>(strip_packet.BandId()));
199 rdo->NSWTP_strip_bands_BCID().push_back(static_cast<uint16_t>(strip_packet.BCID()));
200 // HLbit not available yet - leave empty or set to 0
201 rdo->NSWTP_strip_bands_HLbit().push_back(0);
202 }
203
204 // Store all 8 offset values as centroids_offset
205 for(std::size_t i_offset = 0; i_offset < num_offsets; ++i_offset) {
206 rdo->NSWTP_strip_centroids_offset().push_back(strip_packet.Offset(i_offset));
207 // Set corresponding layer info for offsets
208 rdo->NSWTP_strip_centroids_layer().push_back(static_cast<uint32_t>(i_offset));
209 rdo->NSWTP_strip_centroids_phiID().push_back(strip_packet.PhiIdValue());
210 rdo->NSWTP_strip_centroids_bandID().push_back(strip_packet.BandId());
211 // loc not available yet - leave empty or set to 0
212 rdo->NSWTP_strip_centroids_loc().push_back(0);
213 }
214
215 // BBbit not available yet - leave empty for now
216 }
217
218 }
219 return StatusCode::SUCCESS;
220
221}
222} // namespace Muon
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
unsigned int uint
AthAlgTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor with parameters:
value_type push_back(value_type pElem)
Add an element to the end of the collection.
NSWTP_ROD_Decoder(const std::string &type, const std::string &name, const IInterface *parent)
StatusCode fillCollection(const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment &fragment, xAOD::NSWTPRDOContainer &rdoContainer) const override
StatusCode initialize() override
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
const std::vector< std::shared_ptr< Muon::nsw::NSWTriggerElink > > & get_elinks() const
std::uint32_t BCID() const
const std::array< MMSegmentData, STGTPMMData::num_mm > & Segments() const
std::uint32_t PadIdleFlag() const
std::uint32_t BCID() const
std::uint32_t CoincidenceWedge() const
std::uint32_t BandID(const std::size_t num) const
std::uint32_t PhiID(const std::size_t num) const
std::uint32_t LUT_ChoiceSelection() const
std::uint32_t ValidSegmentSelector() const
const std::array< SegmentData, STGTPSegments::num_segments > & Segments() const
std::uint32_t BCID() const
std::uint32_t NSW_SegmentSelector() const
std::uint32_t SectorID() const
std::uint32_t PhiIdValue() const
std::uint32_t Offset(std::size_t offset) const
std::uint32_t Strip(std::size_t strip) const
std::uint32_t BCID() const
std::uint32_t BandId() const
const std::vector< uint8_t > & NSWTP_strip_bands_HLbit() const
const std::vector< uint32_t > & NSWTP_strip_centroids_offset() const
const std::vector< uint16_t > & NSWTP_strip_bands_BCID() const
const std::vector< uint8_t > & NSWTP_strip_bands_bandID() const
const std::vector< uint32_t > & NSWTP_mm_BCID() const
const std::vector< uint8_t > & NSWTP_strip_bands_layer() const
const std::vector< uint32_t > & NSWTP_strip_centroids_bandID() const
const std::vector< uint32_t > & NSWTP_mm_segments() const
Encode the Monitoring, Spare, lowRes, phiRes, dTheta, phiID, rIndex information of each candidate.
const std::vector< uint8_t > & NSWTP_strip_bands_phiID() const
const std::vector< uint8_t > & NSWTP_mm_candidateNumber() const
const std::vector< uint32_t > & NSWTP_strip_centroids_layer() const
const std::vector< uint32_t > & NSWTP_strip_centroids_phiID() const
const std::vector< uint32_t > & NSWTP_strip_centroids_loc() const
const std::vector< uint8_t > & NSWTP_strip_bands_charge() const
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130
constexpr int pad_stream_invalid_band_id
constexpr void encodeSegmentProperty(const MergedSegmentProperty prop, const uint32_t word, uint32_t &buffer)
constexpr void encodeIdentifierProperty(const ModuleIDProperty prop, const uint32_t word, uint32_t &buffer)
constexpr std::size_t num_strips
constexpr std::size_t num_offsets
NRpcCablingAlg reads raw condition data and writes derived condition data to the condition store.
nsw::STGTPPadPacket STGTPPadPacket
nsw::STGTPSegmentPacket STGTPSegmentPacket
nsw::STGTPMMPacket STGTPMMPacket
nsw::STGTPStripPacket STGTPStripPacket
eformat::ROBFragment< PointerType > ROBFragment
Definition RawEvent.h:27
NSWTPRDO_v1 NSWTPRDO
Define the version of the NRPC RDO class.
Definition NSWTPRDO.h:13
NSWTPRDOContainer_v1 NSWTPRDOContainer
Define the version of the NRPC RDO container.