Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modify RPC and GEM unpacker blocks in EMTF unpacker to match the new Run 3 format #39388

Merged
merged 2 commits into from
Sep 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
242 changes: 138 additions & 104 deletions EventFilter/L1TRawToDigi/plugins/implementations_stage2/EMTFBlockGEM.cc
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ namespace l1t {
// payload[0] = bits 0-15, payload[1] = 16-31, payload[3] = 32-47, etc.
auto payload = block.payload();

// Run 3 has a different EMTF DAQ output format since August 26th
// Computed as (Year - 2000)*2^9 + Month*2^5 + Day (see Block.cc and EMTFBlockTrailers.cc)
bool run3_DAQ_format =
(getAlgoVersion() >=
11546); // Firmware from 26.08.22 which enabled new Run 3 DAQ format for GEMs - EY 13.09.22

int nTPs = run3_DAQ_format ? 2 : 1;

// Check Format of Payload
l1t::emtf::GEM GEM_;
for (int err = 0; err < checkFormat(block); ++err) {
Expand All @@ -139,118 +147,144 @@ namespace l1t {
uint16_t GEMc = payload[2];
uint16_t GEMd = payload[3];

// res is a pointer to a collection of EMTFDaqOut class objects
// There is one EMTFDaqOut for each MTF7 (60 deg. sector) in the event
EMTFDaqOutCollection* res;
res = static_cast<EMTFCollections*>(coll)->getEMTFDaqOuts();
int iOut = res->size() - 1;

EMTFHitCollection* res_hit;
res_hit = static_cast<EMTFCollections*>(coll)->getEMTFHits();
EMTFHit Hit_;

// TODO: Verify this is correct for GEM
GEMPadDigiClusterCollection* res_GEM;
res_GEM = static_cast<EMTFCollections*>(coll)->getEMTFGEMPadClusters();

////////////////////////////
// Unpack the GEM Data Record
////////////////////////////

GEM_.set_pad(GetHexBits(GEMa, 0, 8));
GEM_.set_partition(GetHexBits(GEMa, 9, 11));
GEM_.set_cluster_size(GetHexBits(GEMa, 12, 14));

GEM_.set_cluster_id(GetHexBits(GEMb, 8, 11));
GEM_.set_link(GetHexBits(GEMb, 12, 14));

GEM_.set_gem_bxn(GetHexBits(GEMc, 0, 11));
GEM_.set_bc0(GetHexBits(GEMc, 14, 14));

GEM_.set_tbin(GetHexBits(GEMd, 0, 2));
GEM_.set_vp(GetHexBits(GEMd, 3, 3));

// GEM_.set_dataword(uint64_t dataword);

// Convert specially-encoded GEM quantities
// TODO: is the RPC or CSC method for this function better... - JS 06.07.20
int _station, _ring, _sector, _subsector, _neighbor, _layer;
convert_GEM_location(_station,
_ring,
_sector,
_subsector,
_neighbor,
_layer,
(res->at(iOut)).PtrEventHeader()->Sector(),
GEM_.ClusterID(),
GEM_.Link());

// Rotate by 20 deg to match GEM convention in CMSSW) // FIXME VERIFY
// int _sector_gem = (_subsector < 5) ? _sector : (_sector % 6) + 1; //
int _sector_gem = _sector;
// Rotate by 2 to match GEM convention in CMSSW (GEMDetId.h) // FIXME VERIFY
int _subsector_gem = ((_subsector + 1) % 6) + 1;
// Define chamber number) // FIXME VERIFY
int _chamber = (_sector_gem - 1) * 6 + _subsector_gem;
// Define CSC-like subsector) // FIXME WHY?? VERIFY
int _subsector_csc = (_station != 1) ? 0 : ((_chamber % 6 > 2) ? 1 : 2);

Hit_.set_station(_station);
Hit_.set_ring(_ring);
Hit_.set_sector(_sector);
Hit_.set_subsector(_subsector_csc);
Hit_.set_chamber(_chamber);
Hit_.set_neighbor(_neighbor);

// Fill the EMTFHit
ImportGEM(Hit_, GEM_, (res->at(iOut)).PtrEventHeader()->Endcap(), (res->at(iOut)).PtrEventHeader()->Sector());

// Set the stub number for this hit
// Each chamber can send up to 2 stubs per BX // FIXME is this true for GEM, are stubs relevant for GEMs?
// Also count stubs in corresponding CSC chamber; GEM hit counting is on top of LCT counting
Hit_.set_stub_num(0);
// See if matching hit is already in event record
bool exact_duplicate = false;
for (auto const& iHit : *res_hit) {
if (Hit_.BX() == iHit.BX() && Hit_.Endcap() == iHit.Endcap() && Hit_.Station() == iHit.Station() &&
Hit_.Chamber() == iHit.Chamber()) {
if ((iHit.Is_CSC() == 1 && iHit.Ring() == 2) ||
(iHit.Is_GEM() == 1)) { // Copied from RPC, but GEM has no ring 2/3...
if (Hit_.Neighbor() == iHit.Neighbor()) {
Hit_.set_stub_num(Hit_.Stub_num() + 1);
if (iHit.Is_GEM() == 1 && iHit.Ring() == Hit_.Ring() && iHit.Roll() == Hit_.Roll() &&
iHit.Pad() == Hit_.Pad()) {
exact_duplicate = true;
for (int i = 0; i < nTPs; i++) {
// res is a pointer to a collection of EMTFDaqOut class objects
// There is one EMTFDaqOut for each MTF7 (60 deg. sector) in the event
EMTFDaqOutCollection* res;
res = static_cast<EMTFCollections*>(coll)->getEMTFDaqOuts();
int iOut = res->size() - 1;

EMTFHitCollection* res_hit;
res_hit = static_cast<EMTFCollections*>(coll)->getEMTFHits();
EMTFHit Hit_;

// TODO: Verify this is correct for GEM
GEMPadDigiClusterCollection* res_GEM;
res_GEM = static_cast<EMTFCollections*>(coll)->getEMTFGEMPadClusters();

////////////////////////////
// Unpack the GEM Data Record
////////////////////////////
if (run3_DAQ_format) { // Run 3 DAQ format has 2 TPs per block
if (i == 1) {
GEM_.set_pad(GetHexBits(GEMa, 0, 8));
GEM_.set_partition(GetHexBits(GEMa, 9, 11));
GEM_.set_cluster_size(GetHexBits(GEMa, 12, 14));

GEM_.set_tbin(GetHexBits(GEMb, 0, 2));
GEM_.set_vp(GetHexBits(GEMb, 3, 3));
GEM_.set_bc0(GetHexBits(GEMb, 7, 7));
GEM_.set_cluster_id(GetHexBits(GEMb, 8, 11));
GEM_.set_link(GetHexBits(GEMb, 12, 14));
} else if (i == 2) {
GEM_.set_pad(GetHexBits(GEMc, 0, 8));
GEM_.set_partition(GetHexBits(GEMc, 9, 11));
GEM_.set_cluster_size(GetHexBits(GEMc, 12, 14));

GEM_.set_tbin(GetHexBits(GEMd, 0, 2));
GEM_.set_vp(GetHexBits(GEMd, 3, 3));
GEM_.set_bc0(GetHexBits(GEMd, 7, 7));
GEM_.set_cluster_id(GetHexBits(GEMd, 8, 11));
GEM_.set_link(GetHexBits(GEMd, 12, 14));
}
} else {
GEM_.set_pad(GetHexBits(GEMa, 0, 8));
GEM_.set_partition(GetHexBits(GEMa, 9, 11));
GEM_.set_cluster_size(GetHexBits(GEMa, 12, 14));

GEM_.set_cluster_id(GetHexBits(GEMb, 8, 11));
GEM_.set_link(GetHexBits(GEMb, 12, 14));

GEM_.set_gem_bxn(GetHexBits(GEMc, 0, 11));
GEM_.set_bc0(GetHexBits(GEMc, 14, 14));

GEM_.set_tbin(GetHexBits(GEMd, 0, 2));
GEM_.set_vp(GetHexBits(GEMd, 3, 3));

// GEM_.set_dataword(uint64_t dataword);
}

// Convert specially-encoded GEM quantities
// TODO: is the RPC or CSC method for this function better... - JS 06.07.20
int _station, _ring, _sector, _subsector, _neighbor, _layer;
convert_GEM_location(_station,
_ring,
_sector,
_subsector,
_neighbor,
_layer,
(res->at(iOut)).PtrEventHeader()->Sector(),
GEM_.ClusterID(),
GEM_.Link());

// Rotate by 20 deg to match GEM convention in CMSSW) // FIXME VERIFY
// int _sector_gem = (_subsector < 5) ? _sector : (_sector % 6) + 1; //
int _sector_gem = _sector;
// Rotate by 2 to match GEM convention in CMSSW (GEMDetId.h) // FIXME VERIFY
int _subsector_gem = ((_subsector + 1) % 6) + 1;
// Define chamber number) // FIXME VERIFY
int _chamber = (_sector_gem - 1) * 6 + _subsector_gem;
// Define CSC-like subsector) // FIXME WHY?? VERIFY
int _subsector_csc = (_station != 1) ? 0 : ((_chamber % 6 > 2) ? 1 : 2);

Hit_.set_station(_station);
Hit_.set_ring(_ring);
Hit_.set_sector(_sector);
Hit_.set_subsector(_subsector_csc);
Hit_.set_chamber(_chamber);
Hit_.set_neighbor(_neighbor);

// Fill the EMTFHit
ImportGEM(Hit_, GEM_, (res->at(iOut)).PtrEventHeader()->Endcap(), (res->at(iOut)).PtrEventHeader()->Sector());

// Set the stub number for this hit
// Each chamber can send up to 2 stubs per BX // FIXME is this true for GEM, are stubs relevant for GEMs?
// Also count stubs in corresponding CSC chamber; GEM hit counting is on top of LCT counting
Hit_.set_stub_num(0);
// See if matching hit is already in event record
bool exact_duplicate = false;
for (auto const& iHit : *res_hit) {
if (Hit_.BX() == iHit.BX() && Hit_.Endcap() == iHit.Endcap() && Hit_.Station() == iHit.Station() &&
Hit_.Chamber() == iHit.Chamber()) {
if ((iHit.Is_CSC() == 1 && iHit.Ring() == 2) ||
(iHit.Is_GEM() == 1)) { // Copied from RPC, but GEM has no ring 2/3...
if (Hit_.Neighbor() == iHit.Neighbor()) {
Hit_.set_stub_num(Hit_.Stub_num() + 1);
if (iHit.Is_GEM() == 1 && iHit.Ring() == Hit_.Ring() && iHit.Roll() == Hit_.Roll() &&
iHit.Pad() == Hit_.Pad()) {
exact_duplicate = true;
}
}
}
}
} // End loop: for (auto const & iHit : *res_hit)

// Reject TPs with out-of-range BX values. This needs to be adjusted if we increase l1a_window parameter in EMTF config - EY 03.08.2022
if (Hit_.BX() > 3 or Hit_.BX() < -3) {
edm::LogWarning("L1T|EMTF") << "EMTF unpacked GEM digis with out-of-range BX! BX " << Hit_.BX()
<< ", endcap " << Hit_.Endcap() << ", station " << Hit_.Station()
<< ", neighbor " << Hit_.Neighbor() << ", ring " << Hit_.Ring() << ", chamber "
<< Hit_.Chamber() << ", roll " << Hit_.Roll() << ", pad " << Hit_.Pad()
<< std::endl;
return true;
}
} // End loop: for (auto const & iHit : *res_hit)

// Reject TPs with out-of-range BX values. This needs to be adjusted if we increase l1a_window parameter in EMTF config - EY 03.08.2022
if (Hit_.BX() > 3 or Hit_.BX() < -3) {
edm::LogWarning("L1T|EMTF") << "EMTF unpacked GEM digis with out-of-range BX! BX " << Hit_.BX()
<< ", endcap " << Hit_.Endcap() << ", station " << Hit_.Station() << ", neighbor "
<< Hit_.Neighbor() << ", ring " << Hit_.Ring() << ", chamber " << Hit_.Chamber()
<< ", roll " << Hit_.Roll() << ", pad " << Hit_.Pad() << std::endl;
return true;
}

// TODO: Re-enable once GEM TP data format is fixed
// if (exact_duplicate)
// edm::LogWarning("L1T|EMTF") << "EMTF unpacked duplicate GEM digis: BX " << Hit_.BX() << ", endcap "
// << Hit_.Endcap() << ", station " << Hit_.Station() << ", neighbor "
// << Hit_.Neighbor() << ", ring " << Hit_.Ring() << ", chamber " << Hit_.Chamber()
// << ", roll " << Hit_.Roll() << ", pad " << Hit_.Pad() << std::endl;
// TODO: Re-enable once GEM TP data format is fixed
// if (exact_duplicate)
// edm::LogWarning("L1T|EMTF") << "EMTF unpacked duplicate GEM digis: BX " << Hit_.BX() << ", endcap "
// << Hit_.Endcap() << ", station " << Hit_.Station() << ", neighbor "
// << Hit_.Neighbor() << ", ring " << Hit_.Ring() << ", chamber " << Hit_.Chamber()
// << ", roll " << Hit_.Roll() << ", pad " << Hit_.Pad() << std::endl;

(res->at(iOut)).push_GEM(GEM_);
if (!exact_duplicate)
res_hit->push_back(Hit_);
(res->at(iOut)).push_GEM(GEM_);
if (!exact_duplicate)
res_hit->push_back(Hit_);

if (!exact_duplicate)
res_GEM->insertDigi(Hit_.GEM_DetId(), Hit_.CreateGEMPadDigiCluster());
if (!exact_duplicate)
res_GEM->insertDigi(Hit_.GEM_DetId(), Hit_.CreateGEMPadDigiCluster());

// Finished with unpacking one GEM Data Record
// Finished with unpacking one GEM Data Record
}
return true;

} // End bool GEMBlockUnpacker::unpack
Expand Down
Loading