84 return StatusCode::FAILURE;
89 return StatusCode::FAILURE;
95 return StatusCode::FAILURE;
99 std::map<std::pair<int,int>, std::pair<std::array<int,11>, std::vector<float>>> towers;
101 constexpr int INVALID_VALUE = -99999;
102 constexpr int MASKED_VALUE = std::numeric_limits<int>::max();
103 constexpr int SATURATED_VALUE = std::numeric_limits<int>::max()-1;
104 constexpr int MISSING_VALUE = -99998;
108 for (
auto digi: *scells) {
109 const auto itr = m_scMap.find(digi->ID().get_compact());
110 if (itr == m_scMap.end()) {
continue; }
111 int val = std::round(digi->energy()/(12.5*std::cosh(digi->eta())));
113 auto elem = ddm->get_element(digi->ID());
118 int sampling = elem->getSampling();
119 isHEC = (sampling >= 8 && sampling <= 11);
123 bool applyTiming =
false;
129 applyTiming = !isHEC;
133 if (isMC && applyTiming && !((digi)->provenance() & 0x200)) {
137 bool isSaturated = (!isMC) ? (digi->quality()) :
false;
138 bool isMasked = ((digi)->provenance()&0x80);
139 bool isInvalid =
m_applyMasking ? ((digi)->provenance()&0x40) :
false;
145 val = SATURATED_VALUE;
149 auto [towerItr, inserted] = towers.try_emplace(itr->second.first);
152 towerItr->second.first.fill(MISSING_VALUE);
153 towerItr->second.second.assign(11, -6000.0f);
156 auto& counts = towerItr->second.first;
157 auto& timing = towerItr->second.second;
159 if (itr->second.second.second == 11) {
160 timing.at(itr->second.second.first) = digi->time();
162 if (itr->second.second.second<11) {
164 if (!isMasked && val!=INVALID_VALUE) {
167 counts.at(itr->second.second.first) = SATURATED_VALUE;
168 counts.at(itr->second.second.second) = SATURATED_VALUE;
170 if(counts.at(itr->second.second.first)!=(SATURATED_VALUE)) {
172 if (counts.at(itr->second.second.first)==MASKED_VALUE || counts.at(itr->second.second.first)==INVALID_VALUE || counts.at(itr->second.second.first)==MISSING_VALUE) {
173 counts.at(itr->second.second.first)=0;
175 counts.at(itr->second.second.first) += val >> 1;
177 if(counts.at(itr->second.second.second)!=(SATURATED_VALUE)) {
179 if (counts.at(itr->second.second.second)==MASKED_VALUE || counts.at(itr->second.second.second)==INVALID_VALUE || counts.at(itr->second.second.second)==MISSING_VALUE) {
180 counts.at(itr->second.second.second)=0;
182 counts.at(itr->second.second.second) += (val - (val >> 1));
188 auto& v = counts.at(itr->second.second.first);
191 if(v==MISSING_VALUE) v = MASKED_VALUE;
192 }
else if(isSaturated) {
195 if(v==INVALID_VALUE || v==MISSING_VALUE) v = 0;
203 static const auto etaIndex = [](
float eta) {
return int(
eta*10 ) + ((
eta<0) ? -1 : 1); };
204 static const auto phiIndex = [](
float phi) {
return int(
phi*32./
M_PI ) + (
phi<0 ? -1 : 1); };
206 if (std::abs(tTower->eta()) > 1.5)
continue;
207 if (tTower->sampling() != 1)
continue;
209 auto coord = std::pair(etaIndex(tTower->eta()), phiIndex(
phi));
211 auto [towerItr, inserted] = towers.try_emplace(
coord);
214 towerItr->second.first.fill(MISSING_VALUE);
215 towerItr->second.second.assign(11, -6000.0f);
217 towerItr->second.first.at(10) = tTower->cpET();
222 ATH_CHECK( eTowers.
record(std::make_unique<xAOD::eFexTowerContainer>(),std::make_unique<xAOD::eFexTowerAuxContainer>()) );
224 static const auto calToFex = [](
int calEt) {
225 if(calEt == MASKED_VALUE)
return 0;
226 if(calEt == SATURATED_VALUE)
return 1023;
227 if( calEt == INVALID_VALUE )
return 1022;
228 if( calEt == MISSING_VALUE )
return 1025;
229 if(calEt<448)
return std::max((calEt&~1)/2+32,1);
230 if(calEt<1472)
return (calEt-448)/4+256;
231 if(calEt<3520)
return (calEt-1472)/8+512;
232 if(calEt<11584)
return (calEt-3520)/32+768;
240 for (
auto& [
coord, towerData] : towers) {
241 auto& counts = towerData.first;
242 auto& timingvec = towerData.second;
244 size_t ni = (std::abs(
coord.first) <= 15) ? 10 : 11;
246 for (
size_t i = 0; i < ni; ++i) {
247 counts[i] = scells->empty() ? 1025 : calToFex(counts[i]);
250 eTowers->push_back(std::make_unique<xAOD::eFexTower>());
251 eTowers->back()->initialize(
252 ((
coord.first < 0 ? 0.5 : -0.5) +
coord.first) * 0.1,
254 std::vector<uint16_t>(counts.begin(), counts.end()),
265 eTowerTiming(*eTowers->back()) = timingvec;
268 return StatusCode::SUCCESS;
280 return StatusCode::FAILURE;
283 ATH_MSG_FATAL(
"Cannot fill sc -> eFexTower mapping with an incomplete sc collection");
284 return StatusCode::FAILURE;
294 doV6Mapping = (hit->FWversion()>1600);
297 ATH_MSG_WARNING(
"Used LATOME Hardware to determine mapping different to python configuration (use V6 Mapping = " << doV6Mapping <<
" )");
303 std::vector<unsigned long long> ps;
304 std::vector<std::pair<float,unsigned long long>> l1;
305 std::vector<std::pair<float,unsigned long long>> l2;
306 std::vector<unsigned long long> l3;
307 std::vector<unsigned long long> had;
308 std::vector<unsigned long long> other;
310 static const auto etaIndex = [](
float eta) {
return int(
eta*10 ) + ((
eta<0) ? -1 : 1); };
311 static const auto phiIndex = [](
float phi) {
return int(
phi*32./ROOT::Math::Pi() ) + (
phi<0 ? -1 : 1); };
312 std::map<std::pair<int,int>,TowerSCells> towers;
313 std::map<unsigned long long,int> eTowerSlots;
315 for (
auto digi: *scells) {
318 if (
auto elem = ddm->get_element(
id); elem && std::abs(elem->eta_raw())<2.5) {
319 float eta = elem->eta_raw();
320 int sampling = elem->getSampling();
321 if(sampling==6 && ddm->getCaloCell_ID()->region(
id)==0 &&
eta<0)
eta-=0.01;
323 unsigned long long val =
id.get_compact();
325 int towerid = -1;
int slot = -1;
bool issplit =
false;
327 eTowerSlots[
id.get_compact()] = slot;
329 auto&
sc = towers[std::pair(etaIndex(
eta),phiIndex(elem->phi_raw()))];
332 sc.ps.push_back(val);
335 sc.l1.push_back({elem->eta(),val});
break;
337 sc.l2.push_back({elem->eta(),val});
break;
339 sc.l3.push_back(val);
break;
340 case 8:
case 9:
case 10:
case 11:
341 sc.had.push_back(val);
break;
343 sc.other.push_back(val);
break;
351 std::vector<size_t> slotVector(11);
352 for(
auto& [
coord,
sc] : towers) {
356 if (
sc.l2.size()==5) {
357 if (
coord.first >= 0) {
358 sc.l3.push_back(
sc.l2.front().second);
359 sc.l2.erase(
sc.l2.begin());
361 sc.l3.push_back(
sc.l2.back().second);
362 sc.l2.resize(
sc.l2.size()-1);
365 if (std::abs(
coord.first)==15) {
372 if (
sc.l1.size()==6) {
373 m_scMap[
sc.l1.at(0).second] = std::pair(
coord,std::pair(1,11));
374 m_scMap[
sc.l1.at(1).second] = std::pair(
coord,(doV6Mapping &&
coord.first < 0) ? std::pair(2,1) : std::pair(1,2));
375 m_scMap[
sc.l1.at(2).second] = std::pair(
coord,std::pair(2,11));
376 m_scMap[
sc.l1.at(3).second] = std::pair(
coord,std::pair(3,11));
377 m_scMap[
sc.l1.at(4).second] = std::pair(
coord,(doV6Mapping &&
coord.first < 0) ? std::pair(4,3) : std::pair(3,4));
378 m_scMap[
sc.l1.at(5).second] = std::pair(
coord,std::pair(4,11));
379 slotVector[1] = eTowerSlots[
sc.l1.at(0).second];
380 slotVector[2] = eTowerSlots[
sc.l1.at(2).second];
381 slotVector[3] = eTowerSlots[
sc.l1.at(3).second];
382 slotVector[4] = eTowerSlots[
sc.l1.at(5).second];
386 if (
sc.l1.size()==1) {
387 m_scMap[
sc.l1.at(0).second] = std::pair(
coord,std::pair(4,11));
388 slotVector[1] = 1; slotVector[2] = 2; slotVector[3] = 3; slotVector[4] = eTowerSlots[
sc.l1.at(0).second];
392 if (!
sc.ps.empty()) {m_scMap[
sc.ps.at(0)] = std::pair(
coord,std::pair(0,11)); slotVector[0] = eTowerSlots[
sc.ps.at(0)]; }
393 if(
sc.l1.size()==4)
for(
size_t i=0;i<4;i++)
if(
sc.l1.size() > i) {m_scMap[
sc.l1.at(i).second] = std::pair(
coord,std::pair(i+1,11)); slotVector[i+1] = eTowerSlots[
sc.l1.at(i).second]; }
394 for(
size_t i=0;i<4;i++)
if(
sc.l2.size() > i) { m_scMap[
sc.l2.at(i).second] = std::pair(
coord,std::pair(i+5,11)); slotVector[i+5] = eTowerSlots[
sc.l2.at(i).second]; }
395 if (!
sc.l3.empty()) {m_scMap[
sc.l3.at(0)] = std::pair(
coord,std::pair(9,11)); slotVector[9] = eTowerSlots[
sc.l3.at(0)]; }
396 if (!
sc.had.empty()) {m_scMap[
sc.had.at(0)] = std::pair(
coord,std::pair(10,11));slotVector[10] = eTowerSlots[
sc.had.at(0)]; }
412 TTree *t =
new TTree(
"mapping",
"mapping");
413 unsigned long long scid = 0;
414 std::pair<int, int>
coord = {0, 0};
415 std::pair<int, int> slot = {-1, -1};
416 t->Branch(
"scid", &scid);
417 t->Branch(
"etaIndex", &
coord.first);
418 t->Branch(
"phiIndex", &
coord.second);
419 t->Branch(
"slot1", &slot.first);
420 t->Branch(
"slot2", &slot.second);
421 for (
auto &[
id, val]: m_scMap) {
430 return StatusCode::SUCCESS;