ATLAS Offline Software
Loading...
Searching...
No Matches
FPGATrackSimMapMakerAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
7
8#include "TH2.h"
9#include "TFile.h"
10
11#include "GaudiKernel/IEventProcessor.h"
12
13
15// Initialize
16
17FPGATrackSimMapMakerAlg::FPGATrackSimMapMakerAlg (const std::string& name, ISvcLocator* pSvcLocator) :
18 AthAlgorithm(name, pSvcLocator)
19{
20}
21
22
24{
25
26 m_monitorFile.reset (new TFile((m_outFileName.value() + "region" + std::to_string(m_region) + ".root").c_str(), "RECREATE"));
27 std::stringstream ss(m_description);
28 std::string line;
29 ATH_MSG_INFO("Tag config:");
30 if (m_description.value() != "")
31 while (std::getline(ss, line, '\n'))
32 ATH_MSG_INFO('\t' << line);
33
34 // reset Hit and Module vectors
35 m_pbHits.clear(); m_peHits.clear(); m_sbHits.clear(); m_seHits.clear(); m_allHits.clear();
36 m_track2modules.clear(); m_track2slice.clear(); m_slice2modules.clear();
37 m_key_etamods.clear(); m_key_etamods2.clear(); m_usedTracks.clear();
38 m_radii.clear(); m_keylayer.clear(); m_keylayer2.clear();
39 m_modules.clear();
40
41 // Set up the module relabel tool.
43
44 // We need to select this before calling parseKeyString() in case the user
45 // has specified a plane (logical layer) as the keystring.
46 // If running with the new regions. Don't use the hardcoded layer assignments. Use either a generic one
47 // or one passed in via a flag.
48 ATH_MSG_INFO("Using Python configuration for regions. All pixel layers -> first stage, all strip layers -> second stage");
49 m_planes = &(m_overridePlanes.value());
50 m_planes2 = &(m_overridePlanes2.value());
51
53 ATH_CHECK(m_evtSel.retrieve());
54
55 ATH_CHECK(m_hitSGInputTool.retrieve(EnableTool{!m_hitSGInputTool.empty()}));
56 ATH_CHECK(m_hitInputTool.retrieve(EnableTool{!m_hitInputTool.empty()}));
57
58 ATH_MSG_DEBUG("initialize() Instantiating root objects");
59 ATH_MSG_DEBUG("initialize() Finished");
60
61
62 return StatusCode::SUCCESS;
63}
64
66// MAIN EXECUTE ROUTINE //
68
69StatusCode FPGATrackSimMapMakerAlg::execute(const EventContext& /*ctx*/)
70{
71 // Read inputs
72 bool done = false;
73 ATH_CHECK(readInputs(done));
74
75 if (done) {
76 SmartIF<IEventProcessor> appMgr{service("ApplicationMgr")};
77 if (!appMgr) {
78 ATH_MSG_ERROR("Failed to retrieve ApplicationMgr as IEventProcessor");
79 return StatusCode::FAILURE;
80 }
81 return appMgr->stopRun();
82 }
83
84 // Reset data pointers
85 m_eventHeader.reset();
86
87 return StatusCode::SUCCESS;
88}
89
90
92// INPUT READING AND PROCESSING //
94
95
97{
98 // Read primary input
99 if ( !m_hitSGInputTool.empty()) {
100 ATH_CHECK(m_hitSGInputTool->readData(&m_eventHeader, Gaudi::Hive::currentContext()));
101 ATH_MSG_DEBUG("Loaded " << m_eventHeader.nHits() << " hits in event header from SG");
102 }
103 else {
104 ATH_CHECK(m_hitInputTool->readData(&m_eventHeader, done));
105 if (done)
106 {
107 ATH_MSG_INFO("Cannot read more events from file, returning");
108 return StatusCode::SUCCESS; // end of loop over events
109 }
110 }
111
112 // Ask the event selection service if this event really falls within the region.
113 if (!m_evtSel->selectEvent(&m_eventHeader))
114 {
115 ATH_MSG_DEBUG("Event skipped by: " << m_evtSel->name());
116 return StatusCode::SUCCESS;
117 }
118
119 FPGATrackSimEventInfo eventinfo = m_eventHeader.event();
120 ATH_MSG_DEBUG ("Getting Event " << eventinfo);
121
122 for (auto hit: m_eventHeader.hits()) // fill track to modules map and hit vectors
123 {
124 // barcode cut: these hits are not associated with our single muon tracks
125 if (hit.getBarcodePt() == 0) continue;
126
127 SiliconTech det = hit.getDetType();
128 DetectorZone bec = hit.getDetectorZone();
129 int lyr = hit.getPhysLayer();
130 int eta = hit.getEtaModule();
131 int phi = hit.getPhiModule();
132
133 if (hit.isPixel() && hit.isBarrel()) {
134 m_pbHits.push_back(hit);
135 if (lyr > m_pbmax) m_pbmax = lyr;
136 }
137 else if (hit.isPixel() && !hit.isBarrel()) {
138 // Perform the layer + module number remapping using our tool.
139 m_moduleRelabel->remap(hit);
140 eta = hit.getEtaModule();
141 lyr = hit.getPhysLayer();
142
143 m_peHits.push_back(hit);
144 if (bec == DetectorZone::posEndcap && lyr > m_pemax[0]) m_pemax[0] = lyr;
145 if (bec == DetectorZone::negEndcap && lyr > m_pemax[1]) m_pemax[1] = lyr;
146 }
147 else if (!hit.isPixel() && hit.isBarrel()) {
148 m_sbHits.push_back(hit);
149 if (lyr > m_sbmax) m_sbmax = lyr;
150 }
151 else if (!hit.isPixel() && !hit.isBarrel()) {
152 m_seHits.push_back(hit);
153 if (bec == DetectorZone::posEndcap && lyr > m_semax[0]) m_semax[0] = lyr;
154 if (bec == DetectorZone::negEndcap && lyr > m_semax[1]) m_semax[1] = lyr;
155 }
156 else ATH_MSG_ERROR("Invalid Region");
157
158 // keep track of all etamods on the key layer for slicing
159 if (isOnKeyLayer(1,det,bec,lyr)) {
160 m_key_etamods[eta] += 1;
161 }
162
163 if (m_key2) // if doing 2D slicing
164 if (isOnKeyLayer(2,det,bec,lyr)) m_key_etamods2.insert(eta);
165
166 // Keep a global record of all modules as we see them, indexed by the ID tuple.
167 Module mod = Module(det, bec, lyr, eta, phi);
168 auto [it, inserted] = m_modules.try_emplace(mod.moduleId(), mod);
169 Module* modref = &(it->second);
170
171 if (std::find(m_track2modules[hit.getEventIndex()].begin(), m_track2modules[hit.getEventIndex()].end(), modref) == m_track2modules[hit.getEventIndex()].end())
172 m_track2modules[hit.getEventIndex()].push_back(modref);
173 m_allHits.push_back(hit);
174 }
175
176 return StatusCode::SUCCESS;
177}
178
179
180
181
183// OUTPUT WRITING AND MONITORING //
185StatusCode FPGATrackSimMapMakerAlg::writePmapAndRmap(std::vector<FPGATrackSimHit> const & pbHits, std::vector<FPGATrackSimHit> const & peHits, std::vector<FPGATrackSimHit> const & sbHits, std::vector<FPGATrackSimHit> const & seHits, int reg)
186{
187 // Plane Map
188
189 // to avoid vector _M_range_check errors, print at least one line for each DetectorZone
190 if (m_pbmax == -1) m_pbmax = 0;
191 if (m_sbmax == -1) m_sbmax = 0;
192 if (m_pemax[0] == -1) m_pemax[0] = 0;
193 if (m_pemax[1] == -1) m_pemax[1] = 0;
194 if (m_semax[0] == -1) m_semax[0] = 0;
195 if (m_semax[1] == -1) m_semax[1] = 0;
196
197 std::string pmap_path = m_outFileName.value() + "region" + std::to_string(m_region) + ".pmap";
198 ATH_MSG_INFO("Creating pmap: " << pmap_path);
199 std::ostringstream buffer;
200
201 buffer << m_geoTag.value() << "\n" << m_planes->size() << " logical_s1\n" << m_planes2->size() << " logical_s2\n";
202 buffer << m_pbmax+1 << " pixel barrel \n" << m_pemax[0]+1 << " pixel endcap+ \n" << m_pemax[1]+1 << " pixel endcap- \n";
203 buffer << m_sbmax+1 << " SCT barrel \n" << m_semax[0]+1 << " SCT endcap+\n" << m_semax[1]+1 << " SCT endcap-\n";
204 buffer << "! silicon endCap physDisk physLayer ['stereo' stripSide <strip only>] 'plane1' logiLayer1 'plane2' logiLayer2\n";
205 buffer << "\nregion " << reg << "\n";
206
207 int p1,p2;
208 for (int lyr = 0; lyr <= m_pbmax; lyr++) { // Pixel Barrel
209 p1 = findPlane(m_planes, "pb" + std::to_string(lyr));
210 p2 = findPlane(m_planes2, "pb" + std::to_string(lyr));
211 buffer << "pixel 0 -1 " << lyr << " plane1 " << p1 << " plane2 " << p2 << "\n";
212 }
213 for (int lyr = 0; lyr <= m_pemax[0]; lyr++) { // Pixel Postive Endap
214 p1 = findPlane(m_planes, "pe" + std::to_string(lyr) + "+");
215 p2 = findPlane(m_planes2, "pe" + std::to_string(lyr) + "+");
216 buffer << "pixel 1 " << lyr << " " << lyr << " plane1 " << p1 << " plane2 " << p2 << "\n";
217 }
218 for (int lyr = 0; lyr <= m_pemax[1]; lyr++) { // Pixel Negative Endcap
219 p1 = findPlane(m_planes, "pe" + std::to_string(lyr) + "-");
220 p2 = findPlane(m_planes2, "pe" + std::to_string(lyr) + "-");
221 buffer << "pixel 2 " << lyr << " " << lyr << " plane1 " << p1 << " plane2 " << p2 << "\n";
222 }
223 for (int lyr = 0; lyr <= m_sbmax; lyr++) { // Strip Barrel
224 p1 = findPlane(m_planes, "sb" + std::to_string(lyr));
225 p2 = findPlane(m_planes2, "sb" + std::to_string(lyr));
226 buffer << "SCT 0 -1 " << lyr << " stereo " << lyr % 2 << " plane1 " << p1 << " plane2 " << p2 << "\n";
227 }
228 for (int lyr = 0; lyr <= m_semax[0]; lyr++) { // Strip Positive Endcap
229 p1 = findPlane(m_planes, "se" + std::to_string(lyr) + "+");
230 p2 = findPlane(m_planes2, "se" + std::to_string(lyr) + "+");
231 buffer << "SCT 1 " << lyr/2 << " " << lyr << " stereo " << lyr % 2 << " plane1 " << p1 << " plane2 " << p2 << "\n";
232 }
233 for (int lyr = 0; lyr <= m_semax[1]; lyr++) { // Strip Negative Endcap
234 p1 = findPlane(m_planes, "se" + std::to_string(lyr) + "-");
235 p2 = findPlane(m_planes2, "se" + std::to_string(lyr) + "-");
236 buffer << "SCT 2 " << lyr/2 << " " << lyr << " stereo " << lyr % 2 << " plane1 " << p1 << " plane2 " << p2 << "\n";
237 }
238
239 // Region Map
240 std::string rmap_path = m_outFileName.value() + "region" + std::to_string(m_region) + ".rmap";
241 ATH_MSG_INFO("Creating rmap: " << rmap_path);
242 std::ofstream rmap(rmap_path, std::ofstream::out);
243 rmap << "towers 1 phi 16\n\n0\n";
244
248
252
253 rmap.close();
254
255
256// Now write out to disk directly without reopening
257 std::ofstream outputFile(pmap_path);
258 if (!outputFile) {
259 ATH_MSG_ERROR("Error: Unable to open file for writing: " << pmap_path);
260 return StatusCode::FAILURE;
261 }
262
263 std::string fileContent = buffer.str();
264 for (int i = 0; i < m_nSlices; ++i) {
265 outputFile << fileContent << '\n';
266 }
267 outputFile.close();
268 return StatusCode::SUCCESS;
269}
270
271StatusCode FPGATrackSimMapMakerAlg::writeSubrmap(std::vector<FPGATrackSimHit> const & allHits)
272{
273 /* ---------- Create z-slices ---------- */
274
275 // BEFORE DOING ANYTHING ELSE, apply global trimming to m_key_etamods.
276 std::set<int> key_etamods;
277 // First, sum up the total number of hits in the key layer. There should be a one-liner for this...
278 float total_hits = 0;
279 for (auto const &etamod : m_key_etamods) {
280 total_hits += etamod.second;
281 }
282 ATH_MSG_INFO("Found " << total_hits << " hits in the key layer, applying global trim factor of " << m_globalTrim << "%");
283 if (total_hits == 0)[[unlikely]]{
284 ATH_MSG_ERROR("FPGATrackSimMapMakerAlg::writeSubrmap: Failure due to zero total hits.");
285 return StatusCode::FAILURE;
286 }
287 // Then, do the trim.
288 for (auto const &etamod : m_key_etamods) {
289 if (m_globalTrim == 0 || ((etamod.second / total_hits) >= m_globalTrim*0.01)) {
290 key_etamods.insert(etamod.first);
291 } else {
292 ATH_MSG_INFO("Eta module " << etamod.first << " only contains " << etamod.second << " out of " << total_hits << " hits, excluding from slices.");
293 }
294 }
295
296 if (m_nSlices.value() == -1) m_nSlices.value() = key_etamods.size(); //default is full granularity slicing
297 float etasPerSlice = float(key_etamods.size())/m_nSlices.value();
298 std::vector<std::vector<int>> key_modules_for_slices; // indexed by slice, holds module eta values
299
300 // easier to use vector than set, convert m_key_etamods into key_etas
301 std::vector<int> key_etas;
302 std::vector<int> key_etas2; // used if 2D slicing
303 key_etas.insert(key_etas.end(), key_etamods.begin(), key_etamods.end());
304
305 for (unsigned i = 0; i < key_etas.size(); i++)
306 {
307 if (i >= (key_modules_for_slices.size() * etasPerSlice)) key_modules_for_slices.push_back(std::vector<int>());
308 key_modules_for_slices.back().push_back(key_etas[i]);
309 }
310
311 std::map<int, int> keymod2slice;
312 for (unsigned s = 0; s < key_modules_for_slices.size(); s++)
313 for (unsigned e = 0; e < key_modules_for_slices[s].size(); e++)
314 keymod2slice[key_modules_for_slices[s][e]] = s;
315
316 std::string key = m_keystring.value();
317 key.erase(std::remove(key.begin(), key.end(), ','), key.end());
318 key.erase(std::remove(key.begin(), key.end(), ' '), key.end());
319 std::string key2 = m_keystring2.value();
320 key2.erase(std::remove(key2.begin(), key2.end(), ','), key2.end());
321 key2.erase(std::remove(key2.begin(), key2.end(), ' '), key2.end());
322
323 ATH_MSG_INFO("Doing z-slicing");
324 if (key_etamods.size() == 0) ATH_MSG_ERROR("Found 0 slices using the keystring: '" << m_keystring << "'");
325 ATH_MSG_INFO("Nslices = " << std::to_string(m_nSlices.value()) << ":");
326
327 std::stringstream eta_slices;
328 for (unsigned s = 0; s < key_modules_for_slices.size(); s++){
329 for (unsigned e = 0; e < key_modules_for_slices[s].size(); e++){
330 eta_slices << key_modules_for_slices[s][e] << " ";
331 }
332 eta_slices << ", ";
333 }
334 ATH_MSG_INFO(eta_slices.str());
335
336 // 2D key layer slicing
337 if (m_key2)
338 { // make new slices from combinations of keylayer1 slices and keylayer2 slices
339
340 /*------------- setup keylayer2 keymodule to slice map -------------- */
341 std::vector<std::vector<int>> key_modules_for_slices2;
342 float etasPerSlice2 = float(m_key_etamods2.size())/m_nSlices.value();
343 key_etas2.insert(key_etas2.end(), m_key_etamods2.begin(), m_key_etamods2.end());
344 for (unsigned i = 0; i < key_etas2.size(); i++)
345 {
346 if (i >= (key_modules_for_slices2.size() * etasPerSlice2)) key_modules_for_slices2.push_back(std::vector<int>());
347 key_modules_for_slices2.back().push_back(key_etas2[i]);
348 }
349
350 std::map<int, int> keymod2slice2;
351 for (unsigned s = 0; s < key_modules_for_slices2.size(); s++)
352 for (unsigned e = 0; e < key_modules_for_slices2[s].size(); e++)
353 keymod2slice2[key_modules_for_slices2[s][e]] = s;
354 /*----------------------------------------------------------------- */
355
356 int new_nSlice = m_nSlices.value();
357 for (int s1 = 0; s1 < m_nSlices.value(); s1++){ // loop over keylayer1's slices
358 for (int s2 = 0; s2 < m_nSlices.value(); s2++){ // loop over keylayer2's slices
359
360 for (auto& pair: m_track2modules) // track loop
361 {
362 if (m_usedTracks.find(pair.first) != m_usedTracks.end()) continue; // skip if already assigned a slice to this track
363 bool key1 = false;
364 bool key2 = false;
365 for (auto& m: pair.second) // module loop
366 {
367 if (isOnKeyLayer(1,m->det,m->bec,m->lyr))
368 if (keymod2slice[m->eta] == s1) key1 = true;
369
370 if (isOnKeyLayer(2,m->det,m->bec,m->lyr))
371 if (keymod2slice2[m->eta] == s2) key2 = true;
372 }
373
374 if (key1 && key2)
375 {
376 int newSlice = m_nSlices.value()*s1 + s2;
377 m_track2slice[pair.first] = newSlice;
378 m_usedTracks.insert(pair.first);
379 if (newSlice + 1 > new_nSlice) new_nSlice = newSlice + 1; // find max slice, to set new total number of slices
380 }
381 }
382 }
383 }
384 m_nSlices.value() = new_nSlice;
385 ATH_MSG_INFO("These slices were further divided based on the key layer 2: '" << key2 << "'. Now nSlices = " << m_nSlices.value());
386 ATH_MSG_INFO("Using " << m_usedTracks.size() << " tracks out of " << m_maxEvents << ". The rest were missing a hit in one or both of the key layers");
387 }
388
389
390 // 1D key layer slicing
391 else
392 {
393 for (const FPGATrackSimHit& hit: allHits) // Fill the track to slice map
394 {
395 if (m_usedTracks.find(hit.getEventIndex()) != m_usedTracks.end()) continue; // skip if already done a hit from this track
396 if (isOnKeyLayer(1,hit.getDetType(),hit.getDetectorZone(), hit.getPhysLayer()))
397 { // if hit is in key layer, add it's barcode to the map
398 if (keymod2slice.count(hit.getEtaModule()) > 0) {
399 int s = keymod2slice[hit.getEtaModule()];
400 m_track2slice[hit.getEventIndex()] = s;
401 m_usedTracks.insert(hit.getEventIndex());
402 }
403 }
404 }
405 ATH_MSG_INFO("Using " << m_usedTracks.size() << " tracks out of " << m_maxEvents << ". The rest missed the key layer");
406 }
407
408 std::string subrmap_path = m_outFileName.value() + "region" + std::to_string(m_region) + ".subrmap";
409
410 ATH_MSG_INFO("Creating subrmap: " << subrmap_path);
411 std::ofstream subrmap(subrmap_path, std::ofstream::out);
412 subrmap << "towers " << m_nSlices.value() << " phi 16\n\n";
413
414 // Resize numTracks vector to be equal to the number of slices
415 // Now that this just stores module pointers we could loop over m_modules instead.
416 for (auto& pair: m_track2modules) {
417 for (Module* m: pair.second) {
418 if (m->numTracks.empty()) {
419 m->numTracks.resize(m_nSlices.value(), 0);
420 }
421 }
422 }
423
424
425 // Count tracks per slice
426 ATH_MSG_INFO("Counting number of tracks per slice.");
427 std::vector<std::vector<int>> slicedTracks (m_nSlices.value()); // vector of tracks, indexed by slice
428 for (auto trk: m_usedTracks) {
429 int s = m_track2slice[trk];
430 slicedTracks[s].push_back(trk);
431 std::vector<Module*> mods = m_track2modules[trk];
432 for (Module* mod: mods) {
433 mod->numTracks[s]++;
434 }
435 }
436
437 if (m_drawSlices)
438 drawSlices(allHits);
439
440 // Now do trimming and Fill slice2module map
441 int trimmed = 0;
442 for (int s = 0; s < m_nSlices.value(); s++) {
443 ATH_MSG_INFO("Applying local trimming in slice " << s);
444 for (auto trk : slicedTracks[s]) {
445 auto it = std::remove_if (m_track2modules[trk].begin(),
446 m_track2modules[trk].end(),
447 [&] (const Module* m) {
448 return 100 * ( float(m->numTracks[s]) / float(slicedTracks[s].size()) ) < m_trim;
449 });
450 trimmed += m_track2modules[trk].end() - it;
451 m_track2modules[trk].erase (it, m_track2modules[trk].end());
452
453 ATH_MSG_DEBUG("About to query trk2slice");
454 int s = m_track2slice[trk];
455 ATH_MSG_DEBUG("Queried trk2slice.");
456 // add all modules from track to slices
457 if (m_track2modules[trk].size() > 0) {
458 ATH_MSG_DEBUG("About to insert trk2modules");
459 m_slice2modules[s].insert( m_slice2modules[s].end(), m_track2modules[trk].begin(), m_track2modules[trk].end() );
460 ATH_MSG_DEBUG("Inserted trk2modules.");
461 }
462 }
463 }
464 ATH_MSG_INFO("Trimmed off " << trimmed << " modules that were hit by less than " << m_trim << "% of tracks");
465
466 /* ---------- Print z-slice map ---------- */
467
468 for (int s = 0; s < m_nSlices.value(); s++)
469 {
470 subrmap << s << "\n";
474
478 subrmap << "\n\n";
479 }
480
481 subrmap.close();
482 return StatusCode::SUCCESS;
483}
484
486{
487 std::string slicingType = "";
488 if (m_key2) slicingType = "2D";
489
490 std::string etapat_path = m_outFileName.value() + "region" + std::to_string(m_region) + ".patt";
491
492 ATH_MSG_INFO("Creating eta patterns file: " << etapat_path);
493 std::ofstream etapat(etapat_path, std::ofstream::out);
494
495 // assign logical layer to each module
496 for (auto& pair: m_track2modules) {
497 for (auto& m: pair.second)
498 {
499 if (m->det == SiliconTech::pixel && m->bec == DetectorZone::barrel) m->plane = findPlane(m_planes, "pb" + std::to_string(m->lyr));
500 if (m->det == SiliconTech::pixel && m->bec == DetectorZone::posEndcap) m->plane = findPlane(m_planes, "pe" + std::to_string(m->lyr) + "+");
501 if (m->det == SiliconTech::pixel && m->bec == DetectorZone::negEndcap) m->plane = findPlane(m_planes, "pe" + std::to_string(m->lyr) + "-");
502
503 if (m->det == SiliconTech::strip && m->bec == DetectorZone::barrel) m->plane = findPlane(m_planes, "sb" + std::to_string(m->lyr));
504 if (m->det == SiliconTech::strip && m->bec == DetectorZone::posEndcap) m->plane = findPlane(m_planes, "se" + std::to_string(m->lyr) + "+");
505 if (m->det == SiliconTech::strip && m->bec == DetectorZone::negEndcap) m->plane = findPlane(m_planes, "se" + std::to_string(m->lyr) + "-");
506 }
507 }
508
509 for(auto trk: m_usedTracks)
510 {
511 std::stringstream track_etapatts;
512 unsigned planesDone = 0;
513 for (unsigned p = 0; p < (m_planes)->size(); p++)
514 {
515 for (const Module* m : m_track2modules[trk]) {
516 if (m->plane == static_cast<int>(p))
517 {
518 track_etapatts << std::to_string(static_cast<int>(m->det)) << "\t" << std::to_string(static_cast<int>(m->bec)) << "\t" << std::to_string(m->eta) << "\t\t";
519 planesDone++;
520 break;
521 }
522 }
523 }
524 if (planesDone == (m_planes)->size())
525 etapat << track_etapatts.str() << "\n";
526
527 }
528 etapat.close();
529 return StatusCode::SUCCESS;
530}
531
532StatusCode FPGATrackSimMapMakerAlg::writeRadiiFile(std::vector<FPGATrackSimHit> const & allHits)
533{
534 // calculate mean radii.
535 m_radii.resize(m_nSlices.value(), std::vector<std::vector<float>>(m_planes2->size(),std::vector<float>(0)));
536 for (const auto& hit: allHits)
537 {
538 SiliconTech det = hit.getDetType();
539 DetectorZone bec = hit.getDetectorZone();
540 int lyr = hit.getPhysLayer();
541 int slice = m_track2slice[hit.getEventIndex()];
542 int plane = -1;
543 if (det == SiliconTech::pixel && bec == DetectorZone::barrel) plane = findPlane(m_planes2, "pb" + std::to_string(lyr));
544 if (det == SiliconTech::pixel && bec == DetectorZone::posEndcap) plane = findPlane(m_planes2, "pe" + std::to_string(lyr) + "+");
545 if (det == SiliconTech::pixel && bec == DetectorZone::negEndcap) plane = findPlane(m_planes2, "pe" + std::to_string(lyr) + "-");
546 if (det == SiliconTech::strip && bec == DetectorZone::barrel) plane = findPlane(m_planes2, "sb" + std::to_string(lyr));
547 if (det == SiliconTech::strip && bec == DetectorZone::posEndcap) plane = findPlane(m_planes2, "se" + std::to_string(lyr) + "+");
548 if (det == SiliconTech::strip && bec == DetectorZone::negEndcap) plane = findPlane(m_planes2, "se" + std::to_string(lyr) + "-");
549
550 if (plane != -1) {
551 m_radii[slice][plane].push_back(hit.getR());
552 }
553 }
554
555 // print file
556 std::string radii_path = m_outFileName.value() + "region" + std::to_string(m_region) + "_radii.txt";
557
558 ATH_MSG_INFO("Creating radii file: " << radii_path);
559 std::ofstream radfile(radii_path, std::ofstream::out);
560 for (int s = 0; s < m_nSlices.value(); s++){
561 radfile << std::to_string(s) << " ";
562 for (unsigned p = 0; p < (m_planes2)->size(); p++){
563 if (m_radii[s][p].size() != 0){
564 // "If left to type inference, op operates on values of the same type as
565 // init which can result in unwanted casting of the iterator elements."
566 // https://en.cppreference.com/w/cpp/algorithm/accumulate
567 float avg = std::accumulate(m_radii[s][p].begin(), m_radii[s][p].end(), 0.0f) / float(m_radii[s][p].size());
568 radfile << std::setprecision(3) << std::fixed << avg << " ";
569 } else {
570 int avg = -1;
571 radfile << avg << " ";
572 }
573 }
574 radfile << "\n";
575 }
576
577 // Calculate global mean radii by reversing the order of the above two loops.
578 radfile << -1 << " ";
579 for (unsigned p = 0; p < (m_planes2)->size(); p++) {
580 float avg = 0;
581 int count = 0;
582 for (int s = 0; s < m_nSlices.value(); s++) {
583 if (m_radii[s][p].size() != 0) {
584 avg = std::accumulate(m_radii[s][p].begin(), m_radii[s][p].end(), avg);
585 count += m_radii[s][p].size();
586 }
587 }
588 if (count > 0) {
589 avg /= float(count);
590 radfile << std::setprecision(3) << std::fixed << avg << " ";
591 } else {
592 radfile << -1 << " ";
593 }
594 }
595 radfile << '\n';
596
597 radfile.close();
598
599 return StatusCode::SUCCESS;
600}
601
602StatusCode FPGATrackSimMapMakerAlg::writeMedianZFile(std::vector<FPGATrackSimHit> const & allHits)
603{
604 // calculate median z. We do this globally and slice-by-slice.
605 m_z.resize(m_nSlices.value(), std::vector<std::vector<float>>((m_planes2)->size(),std::vector<float>(0)));
606 for (const auto& hit: allHits)
607 {
608 SiliconTech det = hit.getDetType();
609 DetectorZone bec = hit.getDetectorZone();
610 int lyr = hit.getPhysLayer();
611 int slice = m_track2slice[hit.getEventIndex()];
612 int plane = -1;
613 if (det == SiliconTech::pixel && bec == DetectorZone::barrel) plane = findPlane(m_planes2, "pb" + std::to_string(lyr));
614 if (det == SiliconTech::pixel && bec == DetectorZone::posEndcap) plane = findPlane(m_planes2, "pe" + std::to_string(lyr) + "+");
615 if (det == SiliconTech::pixel && bec == DetectorZone::negEndcap) plane = findPlane(m_planes2, "pe" + std::to_string(lyr) + "-");
616 if (det == SiliconTech::strip && bec == DetectorZone::barrel) plane = findPlane(m_planes2, "sb" + std::to_string(lyr));
617 if (det == SiliconTech::strip && bec == DetectorZone::posEndcap) plane = findPlane(m_planes2, "se" + std::to_string(lyr) + "+");
618 if (det == SiliconTech::strip && bec == DetectorZone::negEndcap) plane = findPlane(m_planes2, "se" + std::to_string(lyr) + "-");
619
620 if (plane != -1) {
621 m_z[slice][plane].push_back(hit.getZ());
622 }
623 }
624
625 // print file
626 std::string zed_path = m_outFileName.value() + "region" + std::to_string(m_region) + "_z.txt";
627
628 ATH_MSG_INFO("Creating median z file: " << zed_path);
629 std::ofstream zedfile(zed_path, std::ofstream::out);
630 for (int s = 0; s < m_nSlices.value(); s++){
631 zedfile << std::to_string(s) << " ";
632 for (unsigned p = 0; p < (m_planes2)->size(); p++){
633 if (m_z[s][p].size() != 0){
634 float minZ = *std::min_element(m_z[s][p].begin(), m_z[s][p].end());
635 float maxZ = *std::max_element(m_z[s][p].begin(), m_z[s][p].end());
636 float median = (minZ + maxZ)/2;
637 zedfile << std::setprecision(3) << std::fixed << median << " ";
638 } else {
639 int median = -1;
640 zedfile << median << " ";
641 }
642 }
643 zedfile << '\n';
644 }
645
646 // Now do this globally. Note: should this be meanZ instead of medianZ in the forward region?
647 zedfile << -1 << " ";
648 for (unsigned p = 0; p < (m_planes2)->size(); p++) {
649 float minZ = 0;
650 float maxZ = 0;
651 bool doneInitial = false;
652 for (int s = 0; s < m_nSlices.value(); s++) {
653 if (m_z[s][p].size() != 0) {
654 float newMinZ = *std::min_element(m_z[s][p].begin(), m_z[s][p].end());
655 float newMaxZ = *std::max_element(m_z[s][p].begin(), m_z[s][p].end());
656 // slightly clunky, but z can be positive and negative so there's not a sane initial/placeholder value.
657 if (doneInitial) {
658 minZ = std::min(minZ, newMinZ);
659 maxZ = std::max(maxZ, newMaxZ);
660 } else {
661 minZ = newMinZ;
662 maxZ = newMaxZ;
663 doneInitial = true;
664 }
665 }
666 }
667 if (doneInitial) {
668 float median = (minZ + maxZ)/2;
669 zedfile << std::setprecision(3) << std::fixed << median << " ";
670 } else {
671 int median = -1;
672 zedfile << median << " ";
673 }
674 }
675 zedfile << '\n';
676
677 zedfile.close();
678
679 return StatusCode::SUCCESS;
680}
681
682// Finalize
684{
685 // Write the output
691 m_monitorFile.reset();
692 delete m_moduleRelabel;
693 m_moduleRelabel = nullptr;
694 return StatusCode::SUCCESS;
695}
696
697
699// Helpers
700
701void FPGATrackSimMapMakerAlg::drawSlices(std::vector<FPGATrackSimHit> const & allHits)
702{
703 m_monitorFile->cd();
704
705 std::vector<TH2F*> h_slicemap;
706 char hname[20];
707
708 for (unsigned i = 0; i < (unsigned)m_nSlices.value(); i++)
709 {
710 sprintf(hname,"rz_slice%u",i);
711 // This should just default to the entire range, I think.
712 // The user can reduce the binning.
713 TH2F *h = new TH2F(hname,hname,7000,-3500,3500,1200,0,1200);
714 h_slicemap.push_back(h);
715 }
716
717 for (const auto& hit: allHits)
718 {
719 if (m_usedTracks.find(hit.getEventIndex()) == m_usedTracks.end()) continue; // skip if we don't use this track
720 int s = m_track2slice[hit.getEventIndex()];
721 h_slicemap[s]->Fill(hit.getZ(),hit.getR());
722 }
723
724 for (int i = 0; i < m_nSlices.value(); i++)
725 h_slicemap[i]->Write();
726
727}
728
730{
731 int det = static_cast<int>(t_det);
732 int bec = static_cast<int>(t_bec);
733 if (keynum == 1)
734 if (m_keylayer["det"].find(det) != m_keylayer["det"].end() && m_keylayer["bec"].find(bec) != m_keylayer["bec"].end() && m_keylayer["lyr"].find(lyr) != m_keylayer["lyr"].end())
735 return true;
736
737 if (keynum == 2)
738 if (m_keylayer2["det"].find(det) != m_keylayer2["det"].end() && m_keylayer2["bec"].find(bec) != m_keylayer2["bec"].end() && m_keylayer2["lyr"].find(lyr) != m_keylayer2["lyr"].end())
739 return true;
740
741 return false;
742}
743
744int FPGATrackSimMapMakerAlg::findPlane(const std::vector<std::vector<std::string>>* planes, const std::string& test) // find what plane a layer is assigned to.
745{
746 int pcounter = 0;
747 for (auto& plane : *planes) {
748 for (auto& layer : plane) {
749 if (test == layer) return pcounter;
750 }
751 pcounter ++;
752 }
753 return -1;
754}
755
756std::string FPGATrackSimMapMakerAlg::makeRmapLines(std::vector<FPGATrackSimHit> const & hits, SiliconTech det, DetectorZone bec, int max)
757{
758 std::stringstream rmap_line;
759 std::set<int> etas, phis;
760
761 for(int lyr = 0; lyr <= max; lyr++)
762 {
763 etas.clear();
764 phis.clear();
765 for (const auto& hit: hits)
766 {
767 if(static_cast<int>(hit.getPhysLayer()) == lyr && hit.getDetectorZone() == bec) // cast from uint to int just to remove Wsign-compare warnings
768 {
769 etas.insert(hit.getEtaModule());
770 phis.insert(hit.getPhiModule());
771 }
772 }
773 if (etas.size() != 0) rmap_line << static_cast<int>(det) << " " << static_cast<int>(bec) << " " << lyr << " " << *phis.begin() << " " << *phis.rbegin() << " " << phis.size() << " " << *etas.begin() << " " << *etas.rbegin() << " " << etas.size() << "\n";
774 else rmap_line << static_cast<int>(det) << " " << static_cast<int>(bec) << " " << lyr << " 0 0 0 0 0 0\n";
775
776 }
777
778 return rmap_line.str();
779}
780
782{
783 // Parse keystring and define the Key Layer
784 std::string delimiter = ",";
785 std::string s = m_keystring.value();
786 std::string det, bec, lyr;
787 std::map <std::string, std::vector<std::string>> abrevs = { {"pb",{"pixel","barrel"}}, {"pe",{"pixel","endcap"}}, {"sb",{"strip","barrel"}}, {"se",{"strip","endcap"}} };
788 if( s.find(delimiter) != std::string::npos) // keylayer format is 'strip,barrel,4'
789 {
790 try {
791 std::string det = s.substr(0, s.find(delimiter));
792 s.erase(0, s.find(delimiter) + delimiter.length());
793 std::string bec = s.substr(0, s.find(delimiter));
794 s.erase(0, s.find(delimiter) + delimiter.length());
795 std::string lyr = s.substr(0, s.find(delimiter));
796 s.erase(0, s.find(delimiter) + delimiter.length());
797 m_keylayer["det"].insert(static_cast<int>(m_det2tech[det]));
798 m_keylayer["bec"].insert(static_cast<int>(m_bec2zone[bec]));
799 m_keylayer["lyr"].insert(std::stoi(lyr));
800 ATH_MSG_INFO("Using key layer: " << m_keystring.value());
801 } catch (...){
802 ATH_MSG_ERROR("Invalid KeyString: '" << m_keystring.value() << "'." << "Accepted formats are 'strip,posEndcap,2', 'pixel,barrel,3', or 'plane 0'");
803 }
804 }
805 else // keylayer format is 'plane 0'
806 {
807 std::string delimiter = " ";
808 try {
809 s.erase(0, s.find(delimiter) + delimiter.length());
810 std::string plane = s.substr(0, s.find(delimiter));
811 std::vector<std::string> s = (m_planes)->at(std::stoi(plane));
812 for (unsigned i = 0; i < s.size(); i++){
813 std::string reg = s[i].substr(0, 2);
814 std::vector<std::string> zone = abrevs[reg];
815 if (s[i].back() == '+') zone[1] = "posEndcap";
816 if (s[i].back() == '-') zone[1] = "negEndcap";
817 s[i].erase(std::remove(s[i].begin(), s[i].end(), '+'), s[i].end());
818 s[i].erase(std::remove(s[i].begin(), s[i].end(), '-'), s[i].end());
819 std::string lyr = s[i].substr(2);
820 m_keylayer["det"].insert(static_cast<int>(m_det2tech[zone[0]]));
821 m_keylayer["bec"].insert(static_cast<int>(m_bec2zone[zone[1]]));
822 m_keylayer["lyr"].insert(std::stoi(lyr));
823 }
824 ATH_MSG_INFO("Using key layer (in plane X format) " << m_keystring.value());
825 } catch (...){
826 ATH_MSG_ERROR("Invalid KeyString: '" << m_keystring.value() << "'." << "Accepted formats are 'strip,posEndcap,2', 'pixel,barrel,3', or 'plane 0'");
827 }
828 }
829
830 // if 2D slicing
831 if (m_keystring2.value() != "")
832 {
833 m_key2 = true;
834 std::string s = m_keystring2.value();
835 if( s.find(delimiter) != std::string::npos) // keylayer format is 'strip,barrel,8'
836 {
837 try {
838 std::string det = s.substr(0, s.find(delimiter));
839 s.erase(0, s.find(delimiter) + delimiter.length());
840 std::string bec = s.substr(0, s.find(delimiter));
841 s.erase(0, s.find(delimiter) + delimiter.length());
842 std::string lyr = s.substr(0, s.find(delimiter));
843 s.erase(0, s.find(delimiter) + delimiter.length());
844 m_keylayer2["det"].insert(static_cast<int>(m_det2tech[det]));
845 m_keylayer2["bec"].insert(static_cast<int>(m_bec2zone[bec]));
846 m_keylayer2["lyr"].insert(std::stoi(lyr));
847 ATH_MSG_INFO("Using key layer (2D): " << m_keystring2.value());
848 } catch (...){
849 ATH_MSG_ERROR("Invalid KeyString2: '" << m_keystring2.value() << "'." << "Accepted formats are 'strip,posEndcap,2', 'pixel,barrel,3', or 'plane 0'");
850 }
851 }
852 else // keylayer format is 'plane 0'
853 {
854 std::string delimiter = " ";
855 try {
856 s.erase(0, s.find(delimiter) + delimiter.length());
857 std::string plane = s.substr(0, s.find(delimiter));
858 std::vector<std::string> s = (m_planes)->at(std::stoi(plane));
859 for (unsigned i = 0; i < s.size(); i++){
860 std::string reg = s[i].substr(0, 2);
861 std::vector<std::string> zone = abrevs[reg];
862 if (s[i].back() == '+') zone[1] = "posEndcap";
863 if (s[i].back() == '-') zone[1] = "negEndcap";
864 s[i].erase(std::remove(s[i].begin(), s[i].end(), '+'), s[i].end());
865 s[i].erase(std::remove(s[i].begin(), s[i].end(), '-'), s[i].end());
866 std::string lyr = s[i].substr(2);
867 m_keylayer2["det"].insert(static_cast<int>(m_det2tech[zone[0]]));
868 m_keylayer2["bec"].insert(static_cast<int>(m_bec2zone[zone[1]]));
869 m_keylayer2["lyr"].insert(std::stoi(lyr));
870 }
871 ATH_MSG_INFO("Using key layer (2D) (in plane X format): " << m_keystring2.value());
872 } catch (...){
873 ATH_MSG_ERROR("Invalid KeyString2: '" << m_keystring2.value() << "'." << "Accepted formats are 'strip,posEndcap,2', 'pixel,barrel,3', or 'plane 0'");
874 }
875 }
876 }
877}
878
879std::string FPGATrackSimMapMakerAlg::makeSubrmapLines(std::vector<Module*> const & allmods, SiliconTech det, DetectorZone bec, int max)
880{
881 std::stringstream subrmap_line;
882 std::set<int> etas, phis;
883
884 std::vector<Module*> mods;
885 for (auto* mod: allmods) // just want modules in pb/pe/sb/se etc, not all at once
886 if (mod->det == det && mod->bec == bec) mods.push_back(mod);
887
888 for(int lyr = 0; lyr <= max; lyr++)
889 {
890 etas.clear();
891 phis.clear();
892 for (auto mod: mods)
893 {
894 if(mod->lyr == lyr)
895 {
896 etas.insert(mod->eta);
897 phis.insert(mod->phi);
898 }
899 }
900 if (etas.size() != 0) subrmap_line << static_cast<int>(det) << " " << static_cast<int>(bec) << " " << lyr << " " << *phis.begin() << " " << *phis.rbegin() << " " << phis.size() << " " << *etas.begin() << " " << *etas.rbegin() << " " << etas.size() << "\n";
901 else subrmap_line << static_cast<int>(det) << " " << static_cast<int>(bec) << " " << lyr << " 0 0 0 0 0 0\n";
902
903 }
904
905 return subrmap_line.str();
906}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
SiliconTech
DetectorZone
static Double_t ss
size_t size() const
Number of registered mappings.
#define max(a, b)
Definition cfImp.cxx:41
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor with parameters:
Header file for AthHistogramAlgorithm.
std::unique_ptr< TFile > m_monitorFile
StatusCode writePmapAndRmap(std::vector< FPGATrackSimHit > const &pbHits, std::vector< FPGATrackSimHit > const &peHits, std::vector< FPGATrackSimHit > const &sbHits, std::vector< FPGATrackSimHit > const &seHits, int region)
Gaudi::Property< float > m_trim
std::string makeSubrmapLines(std::vector< Module * > const &allmods, SiliconTech det, DetectorZone bec, int max)
StatusCode writeRadiiFile(std::vector< FPGATrackSimHit > const &allHits)
ToolHandle< IFPGATrackSimInputTool > m_hitSGInputTool
std::vector< std::vector< std::vector< float > > > m_radii
FPGATrackSimMapMakerAlg(const std::string &name, ISvcLocator *pSvcLocator)
std::string makeRmapLines(std::vector< FPGATrackSimHit > const &hits, SiliconTech det, DetectorZone bec, int max)
bool isOnKeyLayer(int keynum, SiliconTech det, DetectorZone bec, int lyr)
std::map< std::string, std::set< int > > m_keylayer2
std::map< std::string, std::set< int > > m_keylayer
StatusCode execute(const EventContext &ctx) override
Execute method.
Gaudi::Property< std::string > m_description
std::vector< FPGATrackSimHit > m_sbHits
Gaudi::Property< float > m_globalTrim
std::map< FPGATrackSimModuleId, Module > m_modules
FPGATrackSimEventInputHeader m_eventHeader
std::map< std::string, SiliconTech > m_det2tech
std::vector< FPGATrackSimHit > m_seHits
std::vector< FPGATrackSimHit > m_pbHits
Gaudi::Property< std::string > m_keystring2
Gaudi::Property< std::string > m_outFileName
const std::vector< std::vector< std::string > > * m_planes
std::map< int, int > m_track2slice
ToolHandle< IFPGATrackSimEventInputHeaderTool > m_hitInputTool
int findPlane(const std::vector< std::vector< std::string > > *planes, const std::string &test)
Gaudi::Property< std::string > m_keystring
std::map< int, std::vector< Module * > > m_track2modules
Gaudi::Property< std::vector< std::vector< std::string > > > m_overridePlanes
StatusCode writeMedianZFile(std::vector< FPGATrackSimHit > const &allHits)
Gaudi::Property< bool > m_remapModules
const std::vector< std::vector< std::string > > * m_planes2
Gaudi::Property< bool > m_drawSlices
FPGATrackSimModuleRelabel * m_moduleRelabel
Gaudi::Property< int > m_region
std::vector< std::vector< std::vector< float > > > m_z
std::map< int, int > m_key_etamods
Gaudi::Property< std::vector< std::vector< std::string > > > m_overridePlanes2
std::vector< FPGATrackSimHit > m_peHits
Gaudi::Property< std::string > m_geoTag
std::map< int, std::vector< Module * > > m_slice2modules
std::map< std::string, DetectorZone > m_bec2zone
std::vector< FPGATrackSimHit > m_allHits
StatusCode readInputs(bool &done)
StatusCode writeSubrmap(std::vector< FPGATrackSimHit > const &allHits)
Gaudi::Property< int > m_maxEvents
ServiceHandle< IFPGATrackSimEventSelectionSvc > m_evtSel
void drawSlices(std::vector< FPGATrackSimHit > const &allHits)
Gaudi::Property< int > m_nSlices
STL class.
std::string find(const std::string &s)
return a remapped string
Definition hcg.cxx:140
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:148
static const std::string delimiter("/")
DataModel_detail::iterator< DVL > remove(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, const T &value)
Specialization of remove for DataVector/List.
DataModel_detail::iterator< DVL > remove_if(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, Predicate pred)
Specialization of remove_if for DataVector/List.
#define unlikely(x)