From a2e9ecc734dd5159b2a1f8720c4007c7a0446c47 Mon Sep 17 00:00:00 2001 From: Wojciech Krupa <wojciech.krupa@cern.ch> Date: Fri, 7 Feb 2025 13:55:45 +0100 Subject: [PATCH] Squashed commit of the following: commit 9899e93dda1a5d4acdb67e0d12a911ee36e5ab49 Author: Gitlab CI <noreply@cern.ch> Date: Fri Feb 7 11:46:53 2025 +0000 pre-commit fixes patch generated by https://gitlab.cern.ch/lhcb/Rec/-/jobs/50602420 commit 5d54670cea06224b36434550e72e1a9d02e90c6c Author: Wojciech Krupa <wojciech.krupa@cern.ch> Date: Fri Feb 7 12:45:37 2025 +0100 implementation of suggestions from software mainteiners commit eb795ea0db16c7b97f0cf50cccf8eeeda1543803 Author: Wojciech Krupa <wojciech.krupa@cern.ch> Date: Fri Feb 7 12:45:09 2025 +0100 removing code which goes in different MR commit 8ad04b2b8e1090866b29b5324faefea4d1e64153 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Wed Feb 5 15:45:56 2025 +0100 Fixed test_decayfinder for undefined behavior This test is using heavily cppyy, but ownership and scoping of C++ object is inexistent there, leading to undefined behavior The fix is as horrible as the code : make all local variables global to be sure nothing is deleted which should not be. This test should probaby be rewritten in plain C++ commit b8f51801b366f622c0545376abb7732015c4b95e Author: Chishuai Wang <chishuai.wang@cern.ch> Date: Fri Feb 7 09:46:08 2025 +0000 FT Beam Time Analysis commit 24d84649229d5f386f2d103a501d15c61c8b6817 Author: RefBot <lhcbsoft@cern.ch> Date: Thu Feb 6 18:01:15 2025 +0100 Update References for: LHCb!4925 based on lhcb-master-mr/12476 [skip ci] commit 126442f11a400c0abb917f8151ddf7076274bdca Author: RefBot <lhcbsoft@cern.ch> Date: Wed Feb 5 18:21:28 2025 +0100 Update References for: Rec!4258 based on lhcb-master-mr/12456 [skip ci] commit acaec379c5f2325fd3a57d5118bbef97f9eff7d3 Author: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Wed Feb 5 11:24:42 2025 +0000 Update TestFileDB tag for RICH 2023 data tests commit 9daad83778c09a89edd78e13fd2d57741d48f95e Author: Miguel Ruiz Diaz <miguel.ruiz.diaz@cern.ch> Date: Wed Feb 5 12:15:38 2025 +0000 Eta distribution of track residuals added to FTTrackMonitor commit 089f01e686a8ed4238c00ecf25c262fdfd6b70e6 Author: Laurent Dufour <laurent.dufour@cern.ch> Date: Wed Feb 5 08:07:00 2025 +0000 Algorithm to apply a global coordinate transform to PVs commit 0be4ee2f9f75dafa307ddb8265d8889c778775d6 Author: Marco Clemencic <marco.clemencic@cern.ch> Date: Tue Feb 4 11:19:06 2025 +0100 Add dependencies to be able to collect pytest tests in LoKiPhys commit fe4ad5b17761aba4c1fbab97b8b418ea9d772e7e Author: Yingrui Hou <yingrui.hou@cern.ch> Date: Tue Feb 4 11:39:05 2025 +0100 Add a map of the SciFi hit efficiency commit 71cbbe820b96ae9b7fabac0ce5b42490e5a4a051 Author: Mark Waterlaat <mark.waterlaat@cern.ch> Date: Tue Feb 4 10:55:21 2025 +0100 Add track error to in sensor check commit 53106fe1352ddabd114218ee67bdb972f345504f Author: RefBot <lhcbsoft@cern.ch> Date: Fri Jan 31 06:00:45 2025 +0100 Update References for: Detector!667 based on lhcb-master-mr/12409 [skip ci] commit cf5496a3f1a35e9501b1d07588251f04f0c94e89 Author: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Fri Jan 31 11:20:47 2025 +0000 Adapt RichFutureRecSys/examples/RichFuture.py to new options format commit 35dfe12cad122bb41d5f6319c440c74d6ccf1640 Author: Michel De Cian <michel.de.cian@cern.ch> Date: Fri Jan 31 10:23:33 2025 +0100 Fix MuonUT truthmatching in PrTrackAssociator commit 2430664d7e6100a234c97db8beaf620da10e806e Author: Gitlab CI <noreply@cern.ch> Date: Thu Feb 6 14:32:21 2025 +0000 pre-commit fixes patch generated by https://gitlab.cern.ch/lhcb/Rec/-/jobs/50549692 commit 8b48dfe2acf0de481e3d1b6d850614fdf5324f7f Author: Wojciech Krupa <wojciech.krupa@cern.ch> Date: Thu Feb 6 15:31:42 2025 +0100 implementation of mainteiners suggestions commit 63818812eae8058b6220e2534a70c633ba578b42 Author: Wojciech Krupa <wojciech.krupa@cern.ch> Date: Thu Feb 6 10:55:40 2025 +0100 fixing default input commit 80fb43370ef49f0742b51ab3de9a6d57337eb32f Author: Gitlab CI <noreply@cern.ch> Date: Thu Feb 6 09:07:57 2025 +0000 pre-commit fixes patch generated by https://gitlab.cern.ch/lhcb/Rec/-/jobs/50527840 commit 99b45b4786ecffedc1a678f2fe8bed14627320e6 Author: Wojciech Krupa <wojciech.krupa@cern.ch> Date: Thu Feb 6 10:07:20 2025 +0100 cleaning the code in terms of unused parameter warnings commit e1f217c6cddb98ff8edae7face9160260d55732f Author: Gitlab CI <noreply@cern.ch> Date: Fri Jan 31 13:51:19 2025 +0000 pre-commit fixes patch generated by https://gitlab.cern.ch/lhcb/Rec/-/jobs/50199317 commit c6ccf71ad2fc9e1ddb0588a1549beb23cce16195 Author: Wojciech Krupa <wojciech.krupa@cern.ch> Date: Fri Jan 31 14:43:54 2025 +0100 implementation of new ut monitors commit 0b3fe2d8c5b3bf1bb1bdd68b54d79e07dba22ab4 Merge: 62950ce792 eb485834e4 Author: Christopher Rob Jones <jonesc@hep.phy.cam.ac.uk> Date: Wed Jan 29 22:39:39 2025 +0100 Merge branch 'suppress-psabi-note-on-arm-gcc' into 'master' Suppress psabi compiler notes on ARM/GCC functor builds See merge request lhcb/Rec!4246 commit eb485834e4d0c701415f53065deae36be7affec4 Author: Christopher Rob Jones <jonesc@hep.phy.cam.ac.uk> Date: Wed Jan 29 22:39:39 2025 +0100 Suppress psabi compiler notes on ARM/GCC functor builds commit 62950ce79280242de7ff71483665517255fd4360 Merge: 462014aa7b e0ab21256a Author: Christopher Rob Jones <jonesc@hep.phy.cam.ac.uk> Date: Tue Jan 28 17:59:08 2025 +0100 Merge branch 'ft-nzs-digit-moni-test-extend-timeout' into 'master' Extend timeout for FT nzs_digit_monitoring test to 1200 to cover dbg builds See merge request lhcb/Rec!4245 commit e0ab21256a43e88f3e8806a10b8320988d5d15b6 Author: Christopher Rob Jones <jonesc@hep.phy.cam.ac.uk> Date: Tue Jan 28 17:59:08 2025 +0100 Extend timeout for FT nzs_digit_monitoring test to 1200 to cover dbg builds commit 462014aa7b57f0c11f988c0d345c27a8bc296275 Merge: f2b6d96adc 27382eff1e Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Tue Jan 28 11:06:47 2025 +0100 Merge branch 'better-use-of-pytest' into 'master' Replace gaudi_add_tests(pytest...) with gaudi_add_pytest(...) See merge request lhcb/Rec!4243 commit 27382eff1e86884da44c4bdcc747c3ea4dd1773f Author: Marco Clemencic <marco.clemencic@cern.ch> Date: Mon Jan 27 10:43:03 2025 +0100 Replace gaudi_add_tests(pytest...) with gaudi_add_pytest(...) and adapt some tests to work better under pytest commit f2b6d96adc5abb5275a37ded68f8e9df1e64c80b Merge: d0c08479b3 7f9194c1b7 Author: Christopher Rob Jones <jonesc@hep.phy.cam.ac.uk> Date: Fri Jan 24 18:24:33 2025 +0100 Merge branch 'add-arm-specific-refs' into 'master' Add some additional arm specific ref files See merge request lhcb/Rec!4240 commit 7f9194c1b76786eb87fe12bed63612643236a86c Author: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Fri Jan 24 16:30:31 2025 +0000 Add some additional arm specific ref files commit d0c08479b325b9d340a6bfc397bec912c146115a Merge: 2750265e12 8ea62e659a Author: Mark Smith <mark.smith@cern.ch> Date: Fri Jan 24 11:46:43 2025 +0100 Merge branch 'release_v37r1' into 'master' Release v37r1 See merge request lhcb/Rec!4239 commit 8ea62e659adf6cb3cd4d8ee39fa48d8214eb7bcf Author: Mark Smith <mark.smith@cern.ch> Date: Fri Jan 24 11:21:48 2025 +0100 Release v37r1 commit 2750265e12553ea2bcb32578656995b8bf949989 Merge: 56c53d6979 100d1571d2 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Thu Jan 23 14:38:36 2025 +0100 Merge branch 'use-pre-commit' into 'master' Update clang-format and switch to Ruff for Python linting and formatting See merge request lhcb/Rec!4224 commit 100d1571d2315cfce7622f4e9abc2d33dc2bb0c7 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Thu Jan 16 17:03:03 2025 +0100 Fixed issues found by the new indentation/lint tools commit 0924d62a600706b218c10a9d51ef401a22aa0624 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Wed Jan 22 14:01:59 2025 +0100 Full reindentation of the code commit f1a69789548f1c00bebb7b966784790743c25012 Author: Marco Clemencic <marco.clemencic@cern.ch> Date: Tue Jan 14 17:19:36 2025 +0100 fix formatting for RealTel40Format/MCLDstFiles.py commit 10c024a9a6854311d0342f0e205c9e50af75d7e6 Author: Marco Clemencic <marco.clemencic@cern.ch> Date: Tue Jan 14 17:14:57 2025 +0100 Update clang-format and switch to Ruff for Python linting and formatting commit 56c53d6979a280b4c23dbb228273d942ffa739d4 Merge: 5af6d311d3 63e24b2d6b Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Tue Jan 21 17:18:15 2025 +0100 Merge branch 'sponce_fixResChecker' into 'master' Fixed Histogram paths in TrackResChecker when split_type is False See merge request lhcb/Rec!4234 commit 63e24b2d6baa196593abaa30c89d0e42c2616295 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Tue Jan 21 08:30:22 2025 +0100 Fixed Histogram paths in TrackResChecker when split_type is False It is supposed to use "ALL" and "Unknown" had been introduced when switching to new histograms commit 5af6d311d31033ed37638fc30c820b7ffff29393 Merge: 6a352902a1 4006a969cd Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Sat Jan 18 21:20:09 2025 +0100 Merge branch 'improve_interpolator' into 'master' Improve track interpolator See merge request lhcb/Rec!4230 commit 4006a969cd0b9a04fae2a06344e5066fc0b76596 Author: Ya Zhao <ya.zhao@cern.ch> Date: Sat Jan 18 21:20:09 2025 +0100 Improve track interpolator commit 6a352902a17d3c4aeeefc082beab8e225079ee49 Merge: daffb32eaa 166032dda6 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Fri Jan 17 10:59:53 2025 +0100 Merge branch 'ref_bot_LHCb4840_Moore4195' into 'master' Update References for: LHCb!4840, Moore!4195 based on lhcb-master-mr/12236 See merge request lhcb/Rec!4225 commit 5f3e2b47495590bb26ec1203158da8aab067945d Author: Marco Clemencic <marco.clemencic@cern.ch> Date: Tue Jan 14 17:13:15 2025 +0100 fix for Python3 commit 166032dda65172b96a0b5acbda906baaec655d67 Author: RefBot <lhcbsoft@cern.ch> Date: Thu Jan 16 10:07:36 2025 +0100 Update References for: LHCb!4840, Moore!4195 based on lhcb-master-mr/12236 [skip ci] commit daffb32eaac50c33b74d76d3192ec50d0ff2296d Merge: 9e96e1d3b7 ecf320cb0d Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Wed Jan 15 14:27:58 2025 +0100 Merge branch 'sponce_DropHistoAlg' into 'master' Dropped usage of GaudiHistoAlg in Rec, replace it with new Histograms See merge request lhcb/Rec!4200 commit 9e96e1d3b7a9e5b1898360680f4951d6855b1176 Merge: 52540b432f b27cd7e263 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Wed Jan 15 13:37:31 2025 +0100 Merge branch 'mstahl_velomatch_to_master' into 'master' Improvements for matching downstream composites to Velo tracks See merge request lhcb/Rec!4141 commit b27cd7e263162aa05932156321e338fee5d51fad Author: mstahl <marian.stahl@cern.ch> Date: Tue Jan 14 17:02:17 2025 +0100 better handling of particle fitting and extrapolation commit 52540b432f478641c621fd36e2ccab80c155c293 Merge: 930689bcf4 77f428f8f1 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Tue Jan 14 08:51:50 2025 +0100 Merge branch 'sponce_fixRef' into 'master' Fixed bad ref file for test_extrapolators See merge request lhcb/Rec!4222 commit 77f428f8f18ac7fa5922b86abdd0ab93333b92fd Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Tue Jan 14 08:50:48 2025 +0100 Fixed bad ref file for test_extrapolators commit 930689bcf4f0019e0d1399c22784f5069e905970 Merge: c21d9fead0 902c88ec93 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Mon Jan 13 17:08:05 2025 +0100 Merge branch 'sponce_cleanupRef' into 'master' Dropped temporary ref files introduced for the move to Gaudi v39r2 and now useless See merge request lhcb/Rec!4221 commit 902c88ec931a53e172b2f378521a261e5ea84561 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Mon Jan 13 17:05:28 2025 +0100 Dropped temporary ref files introduced for the move to Gaudi v39r2 and now useless commit c21d9fead03d3b2133e62092b5e2e0989cba5621 Merge: 4a2d226053 e398788b47 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Mon Jan 13 17:00:15 2025 +0100 Merge branch 'sponce_Gaudiv39r2' into 'master' Ref update for move to Gaudi v39r2 See merge request lhcb/Rec!4218 commit e398788b47cfe52be48a524c3e128e02d0da3d69 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Mon Jan 13 10:26:58 2025 +0100 Ref update for move to Gaudi v39r2 commit 4a2d226053663bd1233a4bafefb3c79136883907 Merge: 8a1c1a7313 50a85cd5ea Author: Christopher Rob Jones <jonesc@hep.phy.cam.ac.uk> Date: Mon Jan 13 12:55:44 2025 +0100 Merge branch 'rich-tests-make-root-filename-test-specific' into 'master' Make RICH test ROOT filenames test specific See merge request lhcb/Rec!4219 commit 8a1c1a731336702d7e8d37a3b6eae60b97c8e0e3 Merge: 6251c857ea 8927e61456 Author: Christopher Rob Jones <jonesc@hep.phy.cam.ac.uk> Date: Mon Jan 13 12:50:25 2025 +0100 Merge branch 'remove-old-gaudi-workarounds-RICH' into 'master' RichDetectorHits: Remove workarounds for Gaudi < v39 See merge request lhcb/Rec!4220 commit 534ef114115d1faa1ff2b5e001cd41c00735387c Author: mstahl <marian.stahl@cern.ch> Date: Sat Nov 23 15:45:13 2024 +0100 refactor downstream composite to velo track matching commit 8927e614561a76b074f2497687424d39ca0cb02a Author: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Mon Jan 13 10:41:46 2025 +0000 RichDetectorHits: Remove workarounds for Gaudi < v39 commit 50a85cd5ea1d37de1616399bdef71e2357db9ff1 Author: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Mon Jan 13 10:30:58 2025 +0000 Make RICH test ROOT filenames test specific commit 51012651d28e64fdf9c17f4d1ea3bd93b34097fb Author: mstahl <marian.stahl@cern.ch> Date: Thu Nov 14 13:10:24 2024 +0100 fix state to particle conversion; adapt to new logic of what is considered basic particle commit 9c106ce31d2a110908d5e16f3ab62156baa0a648 Author: mstahl <marian.stahl@cern.ch> Date: Sun Nov 10 14:17:09 2024 +0100 First draft of offline hyperon VeloMatching commit 6251c857ea3e425100decadd3b8ae9de220e6fa6 Merge: 2eb88ae937 8d3ad3db78 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Mon Jan 13 08:54:59 2025 +0100 Merge branch 'interpolator_PrKalmanFitResult' into 'master' adapt interpolator to PrKalmanFitResult See merge request lhcb/Rec!4123 commit 8d3ad3db789a546a5246defe8fc4bee0ed6e12f2 Author: Ya Zhao <ya.zhao@cern.ch> Date: Mon Jan 13 08:54:59 2025 +0100 adapt interpolator to PrKalmanFitResult commit ecf320cb0da91399008fbb5f67d54da9ffc07758 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Fri Jan 10 11:02:10 2025 +0100 Fixed TriggerObjectsCompatibilityProfileChecker for gaudi v39 commit 13c843d65da5e8eff9fdfe73a86d22320f690ad4 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Tue Dec 17 11:57:35 2024 +0100 Dropped usage of GaudiHistoAlg in TrackMuonMatchMonitor, use new histograms instead commit 491d8102212e2d137c2295184161bfbaf5752fdd Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Mon Dec 16 15:10:35 2024 +0100 Dropped unused TrackV0Monitor commit a22c171d06a3de6c0dde2c104daf4eef016c6c42 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Fri Dec 13 17:46:42 2024 +0100 Replaced GaudiHistoAlg with new histograms in TrackResChecker and TrackCheckerBase commit 68e21b23012ee32cd96b11f4139b7121f83b0d7b Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Thu Dec 12 17:58:30 2024 +0100 Dropped unused TriggerObjectsCompatibilityChecker commit e494580768a46e56c20e99bbd0290cb0bd282cdd Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Thu Dec 12 16:59:34 2024 +0100 Dropped unused TrackEffChecker commit 22cde50b8ae62924cdfc7247ed56926afc8846aa Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Thu Dec 12 16:51:51 2024 +0100 Dropped unused ExtrapolatorChecker commit 37bd4637610b1edc68188213ef30ae6bb65aa470 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Thu Dec 12 16:05:06 2024 +0100 Dropped unused TrackCloneChecker commit 7524e49891d0cc7f78b8ebe1e47e4c8edb1524b0 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Thu Dec 12 08:36:08 2024 +0100 Dropped unused TrackMonitorBase commit bffd6fec09b5f5476274ef404530400057d66e23 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Wed Dec 11 18:34:38 2024 +0100 Dropped unused TrackDiMuonMonitor commit 5d498dd808019610c4861053ce8007c55162fde4 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Wed Dec 11 18:29:46 2024 +0100 Dropped DEBUGHISTOGRAMS in TrackCloneKiller and TrackBestTrackCreator The functionnality is not used anymore and the code behind is obsolete (usage of old histograms) commit 436cf242731721e1e88a7a64fa417c83386c7749 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Wed Dec 11 14:28:03 2024 +0100 Dropped unused RecProcessingTimeMoni commit 2628b523bdc06a9cbf67771f0a6d4b3bfcfc599e Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Wed Dec 11 14:27:08 2024 +0100 Dropped unused ProcStatAbortMoni commit f073850a7feca382430e7e0a7fbac8c2a524f73d Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Wed Dec 11 14:21:03 2024 +0100 Dropped unused EventTimeMonitor commit df3a750f7d0f92b7932ecd9a186b675723d2490c Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Wed Dec 11 14:15:50 2024 +0100 Dropped usage of GaudiHistoAlg and use new histograms commit 2eb88ae937d20dc563a320cc55df49cc86b6c6dd Merge: e597be061c 0556dc83c5 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Thu Jan 9 15:48:15 2025 +0100 Merge branch 'sponce_fixref' into 'master' Fixed ref files of rich decoding for v3 platforms See merge request lhcb/Rec!4214 commit 0556dc83c518c99c9264fdbee0e53eea37aa44a4 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Thu Jan 9 15:44:45 2025 +0100 Fixed ref files od rich decoding for v3 platforms commit e597be061c8438a32be052b996905d6bcffdf068 Merge: 7ba7e14249 1d6c582d98 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Thu Jan 9 12:21:36 2025 +0100 Merge branch 'RichRecon-PIDNtupleCreation-Dec10-2024' into 'master' Rich PID ntuple creation software See merge request lhcb/Rec!4181 commit 1d6c582d98eecc27077f39e71ec1769afdb837ad Author: Sajan Easo <sajan.easo@cern.ch> Date: Thu Jan 9 12:21:36 2025 +0100 Rich PID ntuple creation software commit 7ba7e142499bb9ba26180c18ab7b63f38cb7e7c3 Merge: 6dca5d7842 dd6e88d1ef Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Tue Jan 7 19:07:24 2025 +0100 Merge branch 'ahennequ_velokalman' into 'master' Implements VeloKalman for V1 tracks Closes #587 See merge request lhcb/Rec!4113 commit dd6e88d1efd0a0dbb2c1390d5763b97d9e9090ed Author: Arthur Marius Hennequin <arthur.hennequin@cern.ch> Date: Tue Jan 7 19:07:24 2025 +0100 Implements VeloKalman for V1 tracks commit 6dca5d78428904bd19200c873b10e138928d7859 Merge: 68c2c7ad8f 1cdb58c724 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Tue Jan 7 17:24:06 2025 +0100 Merge branch 'ref_bot_Detector288_LHCb3757_Rec3107_Moore1758' into 'master' Update References for: Detector!288, LHCb!3757, Rec!3107, Moore!1758 based on lhcb-master-mr/12160 See merge request lhcb/Rec!4212 commit 68c2c7ad8f593265695389dfb72f0e19988e1c66 Merge: 10b3ae73d4 3674550c1c Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Tue Jan 7 17:23:42 2025 +0100 Merge branch 'sponce_calohisto' into 'master' Modernized Calo monitoring and dropped MoniAlg See merge request lhcb/Rec!3107 commit 1cdb58c72464f5bde657ce3ccc126a957734ea5d Author: RefBot <lhcbsoft@cern.ch> Date: Tue Jan 7 17:05:03 2025 +0100 Update References for: Detector!288, LHCb!3757, Rec!3107, Moore!1758 based on lhcb-master-mr/12160 [skip ci] commit 10b3ae73d4bcba94d965fb0e45bb63cf0647a626 Merge: f63240858f 07bb72185e Author: Miroslav Saur <miroslav.saur@cern.ch> Date: Tue Jan 7 09:21:05 2025 +0100 Merge branch 'wh_updatevertexmonitor' into 'master' Update of TrackVertexMonitor and TrackParticleMonitor for alignment See merge request lhcb/Rec!4119 commit 07bb72185e16f7fa3ba5a48fa109ec29f3a62a89 Author: Wouter Hulsbergen <wouterh@nikhef.nl> Date: Tue Jan 7 09:21:04 2025 +0100 Update of TrackVertexMonitor and TrackParticleMonitor for alignment commit 3674550c1c699e5242a4565440b10557b588d792 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Tue May 7 18:11:42 2024 +0200 Modernized CaloFutureLEDMonitor and dropped dependency on CaloFutureMoniAlg commit d7d2f5acaee597c37800977a1109b1abec586fb1 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Wed Dec 14 12:47:22 2022 +0100 Moved most of cellid based histo sink code to LHCb commit 198ce53d4a76da5a3dc0ca53104dcddb904a21f3 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Fri Nov 18 18:37:44 2022 +0100 Extended CaloHistogramSink to Profile histograms Also allows to either store them as is, or convert to a pair of regular histogrms for mean and rms commit 5da8fddc26b66f3885bd6d3e322f1235b09efb16 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Thu Sep 22 15:25:52 2022 +0200 Added a new Root histogram Sink for cellId based histograms This sink is recreating the original 2D histogram in the output Root file for regular CellID Histograms. For CellID histograms with an extra dimension (you can see them as a set of 1D histograms, one per cell), a 3D ROOT histogram is created allowing to either extract the 1D histogram for a given cell by fixing the first 2 coordinates, or to extract a 2D view of the Calorimeter for a given value of the 3rd parameter. commit e6d70f0cd467f153641c055684258371dee20b29 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Tue Sep 6 16:45:46 2022 +0200 Dropped CaloFutureMoniAlg, now unused commit 04b6002b3d890c7dc241f49862d77b2359e16c81 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Fri Sep 2 14:23:09 2022 +0200 Modernized CaloFutureTimeAlignment and dropped dependency on CaloFutureMoniAlg commit 00866f8a4e7d4fe6f00acfb27873d1904de4e7b6 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Thu Sep 1 08:33:58 2022 +0200 Modernized CaloFuturePedestal and dropped dependency on CaloFutureMoniAlg commit 20180fba11a443f3aba2bca15d082afb0394d3a2 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Thu Sep 1 10:24:37 2022 +0200 Modernized CaloFutureDigitMonitor and dropped dependency on CaloFutureMoniAlg commit 0cb2fb3342a586f4d61b015f70307b7c18b74de7 Author: Sebastien Ponce <sebastien.ponce@cern.ch> Date: Thu Sep 1 10:24:29 2022 +0200 Modernized CaloFutureClusterMonitor and dropped dependency on CaloFutureMoniAlg --- CMakeLists.txt | 1 + .../src/UpdateVertexCoordinatesOffline.cpp | 2 +- Tr/TrackMonitors/CMakeLists.txt | 2 + Tr/TrackMonitors/src/UTGlobalEffMon.cpp | 279 ++++++++ UT/UTMonitors/CMakeLists.txt | 39 + UT/UTMonitors/src/UTBSMonitor.cpp | 456 ++++++++++++ UT/UTMonitors/src/UTDigitsMonitor.cpp | 668 ++++++++++++++++++ UT/UTMonitors/src/UTErrorMonitor.cpp | 351 +++++++++ UT/UTMonitors/src/UTNZSMonitor.cpp | 372 ++++++++++ UT/UTMonitors/src/UTSuperTAEMonitor.cpp | 179 +++++ UT/UTMonitors/src/UTTAEMonitor.cpp | 165 +++++ .../src/UTVeloUTCorrelationsMonitor.cpp | 134 ++++ 12 files changed, 2647 insertions(+), 1 deletion(-) create mode 100644 Tr/TrackMonitors/src/UTGlobalEffMon.cpp create mode 100644 UT/UTMonitors/CMakeLists.txt create mode 100644 UT/UTMonitors/src/UTBSMonitor.cpp create mode 100644 UT/UTMonitors/src/UTDigitsMonitor.cpp create mode 100644 UT/UTMonitors/src/UTErrorMonitor.cpp create mode 100644 UT/UTMonitors/src/UTNZSMonitor.cpp create mode 100644 UT/UTMonitors/src/UTSuperTAEMonitor.cpp create mode 100644 UT/UTMonitors/src/UTTAEMonitor.cpp create mode 100644 UT/UTMonitors/src/UTVeloUTCorrelationsMonitor.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e39c8b20683..5b33a74c59b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -137,6 +137,7 @@ lhcb_add_subdirectories( Phys/FunctorCache Utils/CatboostStandaloneEvaluator Vis/PhoenixAlgs + UT/UTMonitors ) gaudi_install(CMAKE diff --git a/Phys/TrackRefitting/src/UpdateVertexCoordinatesOffline.cpp b/Phys/TrackRefitting/src/UpdateVertexCoordinatesOffline.cpp index 0dc413eaa23..b3b63dc6632 100644 --- a/Phys/TrackRefitting/src/UpdateVertexCoordinatesOffline.cpp +++ b/Phys/TrackRefitting/src/UpdateVertexCoordinatesOffline.cpp @@ -148,4 +148,4 @@ namespace LHCb { }; DECLARE_COMPONENT_WITH_ID( UpdateVertexCoordinatesOffline, "UpdateVertexCoordinatesOffline" ) -} // namespace LHCb \ No newline at end of file +} // namespace LHCb diff --git a/Tr/TrackMonitors/CMakeLists.txt b/Tr/TrackMonitors/CMakeLists.txt index fffb7419700..f0304ba1e2a 100644 --- a/Tr/TrackMonitors/CMakeLists.txt +++ b/Tr/TrackMonitors/CMakeLists.txt @@ -35,6 +35,8 @@ gaudi_add_module(TrackMonitors src/TrackVertexMonitor.cpp src/TrackVPOverlapMonitor.cpp src/UTTrackMonitor.cpp + src/UTTrackMonitor.cpp + src/UTGlobalEffMon.cpp src/VPTrackMonitor.cpp src/VPHitEfficiencyMonitor.cpp src/VertexCompare.cpp diff --git a/Tr/TrackMonitors/src/UTGlobalEffMon.cpp b/Tr/TrackMonitors/src/UTGlobalEffMon.cpp new file mode 100644 index 00000000000..476775432d2 --- /dev/null +++ b/Tr/TrackMonitors/src/UTGlobalEffMon.cpp @@ -0,0 +1,279 @@ +/*****************************************************************************\ +* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration * +* * +* This software is distributed under the terms of the GNU General Public * +* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". * +* * +* In applying this licence, CERN does not waive the privileges and immunities * +* granted to it by virtue of its status as an Intergovernmental Organization * +* or submit itself to any jurisdiction. * +\*****************************************************************************/ + +#include "DetDesc/DetectorElement.h" +#include "Event/FitNode.h" +#include "Event/PrFitNode.h" +#include "Event/PrHits.h" +#include "Event/PrKalmanFitResult.h" +#include "Event/State.h" +#include "Event/Track.h" +#include "Gaudi/Accumulators/Histogram.h" +#include "GaudiKernel/Algorithm.h" +#include "GaudiKernel/PhysicalConstants.h" +#include "Kernel/LHCbID.h" +#include "Kernel/UTNames.h" +#include "LHCbAlgs/Consumer.h" +#include "TrackKernel/TrackFunctors.h" +#include "TrackMonitorTupleBase.h" +#include "UTDAQ/UTDAQHelper.h" +#include "UTDAQ/UTInfo.h" +#include <algorithm> +#include <bitset> +#include <cstdint> +#include <iomanip> +#include <string> +#include <vector> + +/** @class UTGlobalEffMon UTGlobalEffMon.h + */ + +using namespace LHCb; +using namespace Gaudi; + +template <typename T> +class Mutable { + mutable T m_t; + +public: + template <typename... Args> + requires std::is_constructible_v<T, Args...> + Mutable( Args&&... args ) : m_t{ std::forward<Args>( args )... } {} + + template <typename Arg> + decltype( auto ) operator[]( Arg&& arg ) const { + return m_t[std::forward<Arg>( arg )]; + } +}; + +namespace { + template <class TrackContainer, class Predicate> + std::vector<const LHCb::Track*> myselect( const TrackContainer& tracks, Predicate&& selector ) { + std::vector<const LHCb::Track*> rc; + std::copy_if( tracks.begin(), tracks.end(), std::back_inserter( rc ), std::forward<Predicate>( selector ) ); + return rc; + } + + auto TrackTypePredicate = []( LHCb::Track::Types atype ) { + return [=]( const LHCb::Track* track ) { return track->type() == atype; }; + }; + + auto TrackBackwardPredicate = []( const LHCb::Track* track ) { return track->isVeloBackward(); }; + + auto TrackForwardPredicate = []() { return [=]( const LHCb::Track* track ) { return !track->isVeloBackward(); }; }; + + auto TrackVeloSidePredicate = []( int asign ) { + // +1: left side only, 0: overlap track, -1: right side only + // for asign > 0 select left-side tracks only, for a < 0 select right-side tracks, reject overlap tracks + return [=]( const LHCb::Track* track ) { + int side = 0; + bool allhitsleft = true; + bool allhitsright = true; + + const std::vector<LHCb::LHCbID>& track_ids = track->lhcbIDs(); + for ( const auto& track_id : track_ids ) { + if ( !track_id.isVP() ) continue; + + auto vp_id = track_id.vpID(); + // 0 should be right, 1 left side + bool sidepos = ( vp_id.sidepos() == LHCb::Detector::VPChannelID::Side::A ); + + allhitsleft = allhitsleft && sidepos; + allhitsright = allhitsright && !sidepos; + } + if ( allhitsleft ) side = +1; + if ( allhitsright ) side = -1; + return side * asign > 0; + }; + }; + +} // namespace + +template <typename OWNER, typename K, typename H, typename A> +void buildHistogram( OWNER owner, std::map<K, H>& h, K k, std::string name, std::string labels, A axis ) { + h.emplace( std::piecewise_construct, std::forward_as_tuple( k ), std::forward_as_tuple( owner, name, labels, axis ) ); +} + +template <typename TFitResult, typename TNode> +class UTGlobalEffMon + : public LHCb::Algorithm::Consumer<void( LHCb::Track::Range const&, DetectorElement const& ), + LHCb::DetDesc::usesBaseAndConditions<TrackMonitorTupleBase, DetectorElement>> { + +public: + UTGlobalEffMon( const std::string& name, ISvcLocator* pSvcLocator ); + StatusCode initialize() override; + void operator()( LHCb::Track::Range const& tracks, DetectorElement const& ) const override; + +private: + mutable Gaudi::Accumulators::Histogram<1> m_h_ntracks{ + this, "h_ntracks", "Number of long track; Number of long tracks;Events", { 1000, 0, 5000 } }; + mutable Gaudi::Accumulators::Histogram<1> m_h_nutlay{ + this, "h_nutlay", "Number of UT layers per long track; Number of UT layers;Number of tracks", { 5, -0.5, 4.5 } }; + mutable Gaudi::Accumulators::Histogram<1> m_h_nutlay_high_mult{ + this, + "h_nutlay_high_mult", + "Number of UT layers per long track high mult ; Number of UT layers;Number of tracks high mult", + { 5, -0.5, 4.5 } }; + // full-width sensor 2D bins + mutable Gaudi::Accumulators::Histogram<2> m_h_all3{ this, + "h_all3", + "All tracks Y vs X UTbX-midplane;X [mm];Y [mm]", + { { 18, -860.4, +860.4 }, { 14, -669.2, +669.2 } } }; + mutable Gaudi::Accumulators::Histogram<2> m_h_pass3{ this, + "h_pass3", + "UT-matched tracks Y vs X UTbX-midplane;X [mm];Y [mm]", + { { 18, -860.4, +860.4 }, { 14, -669.2, +669.2 } } }; + + mutable Gaudi::Accumulators::Histogram<2> m_h_pass3_low_mult{ + this, + "h_pass3_low_mult", + "UT-matched tracks Y vs X UTbX-midplane low mult;X [mm];Y [mm]", + { { 18, -860.4, +860.4 }, { 14, -669.2, +669.2 } } }; + + mutable Gaudi::Accumulators::Histogram<1> m_h_residual_inner{ + this, + "h_residual_inner", + "UT track residual - inner detector;residual [mm];number of UT clusters", + { 1000, -0.5, 0.5 } }; + mutable Gaudi::Accumulators::Histogram<1> m_h_residual_outer{ + this, + "h_residual_outer", + "UT track residual - outer detector;residual [mm];number of UT clusters", + { 1000, -0.5, 0.5 } }; + + mutable Gaudi::Accumulators::Histogram<1> m_h_residualpull_inner{ + this, + "h_residualpull_inner", + "UT track residual pull - inner detector;pull;number of UT clusters", + { 100, -5, 5 } }; + mutable Gaudi::Accumulators::Histogram<1> m_h_residualpull_outer{ + this, + "h_residualpull_outer", + "UT track residual pull - outer detector;pull;number of UT clsuters", + { 100, -5, 5 } }; +}; + +using UTDataTrMonitor = UTGlobalEffMon<LHCb::TrackFitResult, LHCb::FitNode>; +using UTDataTrMonitor_PrKalman = UTGlobalEffMon<LHCb::PrKalmanFitResult, LHCb::Pr::Tracks::Fit::Node>; +DECLARE_COMPONENT_WITH_ID( UTDataTrMonitor, "UTGlobalEffMon" ) +DECLARE_COMPONENT_WITH_ID( UTDataTrMonitor_PrKalman, "UTGlobalEffMon_PrKalman" ) + +template <typename TFitResult, typename TNode> +StatusCode UTGlobalEffMon<TFitResult, TNode>::initialize() { + return Consumer::initialize().andThen( [&] {} ); +} + +template <typename TFitResult, typename TNode> +UTGlobalEffMon<TFitResult, TNode>::UTGlobalEffMon( const std::string& name, ISvcLocator* pSvcLocator ) + : Consumer( name, pSvcLocator, + { { "TracksInContainer", LHCb::TrackLocation::Default }, + { "StandardGeometryTop", LHCb::standard_geometry_top } } ) {} + +template <typename TFitResult, typename TNode> +void UTGlobalEffMon<TFitResult, TNode>::operator()( LHCb::Track::Range const& tracks, + const DetectorElement& lhcb ) const { + auto& geometry = *lhcb.geometry(); + const double zutlay3 = 2652.5; + const double UT_sensor_width = 95.6; // do not change this because you think this is not correct! + int nTracks = tracks.size(); + + if ( nTracks > 10000 ) { nTracks = 10000; } // saturation + ++m_h_ntracks[nTracks]; + + for ( const LHCb::Track* track : tracks ) { + auto fitResult = dynamic_cast<const TFitResult*>( track->fitResult() ); + if ( fitResult ) { + LHCb::StateVector aState; + extrapolator()->propagate( *track, zutlay3, aState, geometry ).ignore(); + if ( aState.x() < -9990 ) { continue; } // Skip unphysical tracks + + // tracks must be within UT layer 3 acceptance (exclude also generous region around the beam pipe ) + double tr2utlax3 = aState.x(); + double tr2utlay3 = aState.y(); + if ( fabs( tr2utlax3 ) > 9 * UT_sensor_width ) continue; + if ( fabs( tr2utlay3 ) > 7 * UT_sensor_width ) continue; + if ( sqrt( pow( tr2utlay3, 2 ) + pow( tr2utlax3, 2 ) ) < 45 ) continue; + + // PT cut + try { + + auto cState = track->closestToBeamState(); + if ( cState.pt() < 1000.0 ) continue; + + } catch ( ... ) { continue; } + + // all tracks passing the cuts (for efficiency map denominator) + ++m_h_all3[{ tr2utlax3, tr2utlay3 }]; + + const double kDummy = 1000.0; + + int _tr2ut[4] = { -1, -1, -1, -1 }; + double _tr2utr[4] = { kDummy, kDummy, kDummy, kDummy }; + double _tr2utchi[4] = { 0.0, 0.0, 0.0, 0.0 }; + + unsigned int utnode = 0; + for ( const auto& node : nodes( *fitResult ) ) { + if ( !( node.hasMeasurement() && node.isHitOnTrack() && node.isUT() ) ) continue; + if ( node.isOutlier() ) continue; + LHCb::LHCbID lhcbID = id( node ); + + Detector::UT::ChannelID chan = lhcbID.utID(); + + unsigned int chID = static_cast<unsigned int>( chan ); + + double res = node.residual(); + double chi = res / node.errResidual(); + double ares = fabs( res ); + unsigned int _layer = ( chID >> 18 ) & 3; + + // Loop over layers + if ( ares < fabs( _tr2utr[_layer] ) ) { + _tr2utr[_layer] = res; + _tr2utchi[_layer] = chi; + _tr2ut[_layer] = chID; + } + utnode++; + + } // nodes loop + + unsigned int nlay = 0; + for ( int layer = 0; layer < 4; ++layer ) { + if ( _tr2ut[layer] != -1 ) { + ++nlay; + // Extract values from the current layer + UInt_t _mo = ( _tr2ut[layer] >> 10 ) & 7; + UInt_t _st = ( _tr2ut[layer] >> 14 ) & 15; + bool inner = ( _st == 0 ) && ( _mo == 3 || _mo == 4 ); + if ( inner ) { + ++m_h_residual_inner[_tr2utr[layer]]; + ++m_h_residualpull_inner[_tr2utchi[layer]]; + } else { + ++m_h_residual_outer[_tr2utr[layer]]; + ++m_h_residualpull_outer[_tr2utchi[layer]]; + } + } + } + + // tracks matched to UT hits (for nominator of efficiency map) + if ( nlay > 0 ) ++m_h_pass3[{ tr2utlax3, tr2utlay3 }]; + + // change it for protons 2025 + ++m_h_nutlay_high_mult[nlay]; + + if ( nTracks > 4 && nTracks <= 100 ) { // you may want to move these limits to be configurable parameters + + // UT layer counting for efficiency and ghost rate estimates + ++m_h_nutlay[nlay]; + if ( nlay > 0 ) ++m_h_pass3_low_mult[{ tr2utlax3, tr2utlay3 }]; + } + } + } +} diff --git a/UT/UTMonitors/CMakeLists.txt b/UT/UTMonitors/CMakeLists.txt new file mode 100644 index 00000000000..b5e97abfb01 --- /dev/null +++ b/UT/UTMonitors/CMakeLists.txt @@ -0,0 +1,39 @@ +############################################################################### +# (c) Copyright 2000-2021 CERN for the benefit of the LHCb Collaboration # +# # +# This software is distributed under the terms of the GNU General Public # +# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". # +# # +# In applying this licence, CERN does not waive the privileges and immunities # +# granted to it by virtue of its status as an Intergovernmental Organization # +# or submit itself to any jurisdiction. # +############################################################################### +#[=======================================================================[.rst: +UT/UTMonitors +------------- +#]=======================================================================] + +gaudi_add_module(UTMonitors + SOURCES + src/UTDigitsMonitor.cpp + src/UTTAEMonitor.cpp + src/UTSuperTAEMonitor.cpp + src/UTErrorMonitor.cpp + src/UTNZSMonitor.cpp + src/UTBSMonitor.cpp + src/UTVeloUTCorrelationsMonitor.cpp + LINK + Boost::headers + Gaudi::GaudiAlgLib + Gaudi::GaudiKernel + Gaudi::GaudiUtilsLib + LHCb::DAQEventLib + LHCb::DigiEvent + LHCb::LHCbAlgsLib + LHCb::LHCbKernel + LHCb::RecEvent + LHCb::UTDetLib + LHCb::UTKernelLib + LHCb::UTTELL1Event + ROOT::Hist +) diff --git a/UT/UTMonitors/src/UTBSMonitor.cpp b/UT/UTMonitors/src/UTBSMonitor.cpp new file mode 100644 index 00000000000..c6de3a6d622 --- /dev/null +++ b/UT/UTMonitors/src/UTBSMonitor.cpp @@ -0,0 +1,456 @@ +/***************************************************************************** \ +* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration * +* * +* This software is distributed under the terms of the GNU General Public * +* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". * +* * +* In applying this licence, CERN does not waive the privileges and immunities * +* granted to it by virtue of its status as an Intergovernmental Organization * +* or submit itself to any jurisdiction. * +\*****************************************************************************/ + +#include "Event/UTDigit.h" +#include "GaudiAlg/GaudiHistoAlg.h" +#include "Kernel/IUTReadoutTool.h" +#include "Kernel/UTDAQBoard.h" +#include "Kernel/UTDAQDefinitions.h" +#include "Kernel/UTDAQID.h" +#include "LHCbAlgs/Consumer.h" +#include "LHCbAlgs/Transformer.h" +#include "UTDAQ/UTCoordinatesMap.h" +#include "UTDAQ/UTDAQHelper.h" +#include "UTDAQ/UTInfo.h" +#include "UTDet/DeUTDetector.h" +#include <Event/RawBank.h> +#include <Event/RawEvent.h> +#include <Gaudi/Accumulators/Histogram.h> +#include <Gaudi/Accumulators/HistogramArray.h> +#include <Kernel/IUTReadoutTool.h> +#include <TMath.h> +#include <mutex> +#include <optional> +#include <string> + +/** @class UTBSMonitor UTBSMonitor.cpp + * -------------------------------------------------- + * Counters for additional monitoring of UT + * The algorithm produces several useful histograms + * @author Wojciech Krupa + * @date 07/06/2024 + * -------------------------------------------------- + **/ + +using namespace LHCb; +namespace GA = Gaudi::Accumulators; + +// Definition of axis +const GA::Axis<double> AxisADC = GA::Axis<double>( 64, -32.5, 31.5, "nADC" ); //-32, 31 +const GA::Axis<double> AxisADC_signed = GA::Axis<double>( 32, -0.5, 31.5, "nADC" ); // 0-31 +const GA::Axis<double> AxisDIGIT = GA::Axis<double>( 101, -0.5, 7000.5, "UTDigits (size of digit container)" ); +const GA::Axis<double> AxisHits = GA::Axis<double>( 100, -0.5, 1500.5, "Hits" ); +const GA::Axis<double> AxisUAChannels = GA::Axis<double>( 268288, 0, 268288, "GlobalChannel_ID" ); +const GA::Axis<double> AxisUCChannels = GA::Axis<double>( 268288, 268288, 536576, "GlobalChannel_ID" ); +const GA::Axis<double> AxisUAChips = GA::Axis<double>( 2096, -0.5, 2095.5, "GlobalASIC_ID" ); +const GA::Axis<double> AxisUCChips = GA::Axis<double>( 2096, 2095.5, 4191.5, "GlobalASIC_ID" ); +const GA::Axis<double> AxisThresholds = GA::Axis<double>( 32, -0.5, 31.5, "Threshold" ); +const GA::Axis<double> AxisChannels = GA::Axis<double>( 64, -0.5, 63.5, "Channels" ); +const GA::Axis<double> AxisUA_aUChips = GA::Axis<double>( 496, -0.5, 495.5, "GlobalASIC_ID" ); +const GA::Axis<double> AxisUA_aXChips = GA::Axis<double>( 496, 495.5, 991.5, "GlobalASIC_ID" ); +const GA::Axis<double> AxisUA_bVChips = GA::Axis<double>( 552, 991.5, 1543.5, "GlobalASIC_ID" ); +const GA::Axis<double> AxisUA_bXChips = GA::Axis<double>( 552, 1543.5, 2095.5, "GlobalASIC_ID" ); +const GA::Axis<double> AxisUC_aUChips = GA::Axis<double>( 496, 2095.5, 2591.5, "GlobalASIC_ID" ); +const GA::Axis<double> AxisUC_aXChips = GA::Axis<double>( 496, 2591.5, 3087.5, "GlobalASIC_ID" ); +const GA::Axis<double> AxisUC_bVChips = GA::Axis<double>( 552, 3087.5, 3639.5, "GlobalASIC_ID" ); +const GA::Axis<double> AxisUC_bXChips = GA::Axis<double>( 552, 3639.5, 4191.5, "GlobalASIC_ID" ); + +std::vector<unsigned int> m_channel_counter( 536577, 0 ); +std::vector<unsigned int> m_asic_counter( 4192, 0 ); +std::map<unsigned int, unsigned int> m_threshold_counter; +std::map<unsigned int, unsigned int> m_maxchannel_counter; + +// 2D plots +const double positionasic[4][3] = { + { -0.4375, -0.3125, -0.1875 }, // Chip 0 + { -0.1875, -0.0625, -0.0625 }, // Chip 1 + { +0.1875, +0.0625, +0.0625 }, // Chip 2 + { +0.4375, +0.3125, +0.1875 } // Chip 3 +}; + +// UT layers +const std::array<std::string, 4> UT_layers = { "UTaX", "UTaU", "UTbV", "UTbX" }; + +enum class masks { channel = 0x000001ff, lane = 0x00000e00, board = 0x000ff000 }; +template <masks m> +[[nodiscard]] static constexpr unsigned int extract( unsigned int i ) { + constexpr auto b = std::countr_zero( static_cast<unsigned int>( m ) ); + return ( i & static_cast<unsigned int>( m ) ) >> b; +} + +// Tools for booking histograms +namespace Utility { + template <typename T, typename OWNER> + void map_emplace( T& t, typename T::key_type key, OWNER* owner, std::string const& title, + Gaudi::Accumulators::Axis<typename T::mapped_type::AxisArithmeticType> axis1 ) { + t.emplace( std::piecewise_construct, std::forward_as_tuple( key ), + std::forward_as_tuple( owner, key, title, axis1 ) ); + } +} // namespace Utility +/** ------------------------------------------------------------------------------------------------------------------------ */ + +class UTBSMonitor + : public LHCb::Algorithm::Consumer<void( UTDigits const&, UTDigits const&, DeUTDetector const& ), + LHCb::DetDesc::usesBaseAndConditions<GaudiHistoAlg, DeUTDetector>> { +public: + UTBSMonitor( const std::string& name, ISvcLocator* svcloc ) + : Consumer{ name, + svcloc, + { { "InputData", UTDigitLocation::UTDigits }, + { "InputErrorData", UTDigitLocation::UTDigits }, + { "UTLocation", DeUTDetLocation::location() } } } {} + ToolHandle<IUTReadoutTool> readoutTool{ this, "ReadoutTool", "UTReadoutTool" }; + + StatusCode initialize() override { + return Consumer::initialize().andThen( [&] { + // Set the top directory to UT + if ( histoTopDir().empty() ) setHistoTopDir( "" ); + + for ( const auto& module : UTMap.getModulesNames() ) { + for ( unsigned int i = 0; i < 4; i++ ) + Utility::map_emplace( m_1d_ADCCounter, module + ".Chip" + std::to_string( i ), this, + module + ".Chip" + std::to_string( i ), { 32, -0.5, 31.5 } ); + } + } ); + } + + void operator()( const UTDigits& digitsCont, const UTDigits& digitserrCont, DeUTDetector const& det ) const override { + + // General counters + const unsigned int nDigits = digitsCont.size() + digitserrCont.size(); + + if ( msgLevel( MSG::DEBUG ) ) debug() << "---------- Found nDigits: " << nDigits << endmsg; + ++m_nDigits[nDigits]; + + // Hitmaps plots and ADC + std::fill( m_channel_counter.begin(), m_channel_counter.end(), 0 ); + std::fill( m_asic_counter.begin(), m_asic_counter.end(), 0 ); + + // For maxADC plots + unsigned int prev_channel = 0; + unsigned int prev_adc = 0; + LHCb::UTDigit* aDigit_max; + + // UT bank + for ( const auto& d : digitsCont ) { + + fillHeatPlots( d ); + + // First event + if ( prev_channel == 0 ) { + prev_channel = d->strip(); + prev_adc = d->depositedCharge(); + aDigit_max = d; + continue; + } + // If cluster size >1 + if ( d->strip() - prev_channel == 1 ) + if ( d->depositedCharge() > prev_adc ) aDigit_max = d; // if ADC max in claster + // End of cluster + if ( d->strip() - prev_channel != 1 ) { + fillHeatPlots_MAX( aDigit_max ); + aDigit_max = d; + } + + prev_channel = d->strip(); + prev_adc = d->depositedCharge(); + } + + // UTError bank + for ( const auto& d : digitserrCont ) { + + fillHeatPlots( d ); + + // First event + if ( prev_channel == 0 ) { + prev_channel = d->strip(); + prev_adc = d->depositedCharge(); + aDigit_max = d; + continue; + } + // If cluster size >1 + if ( d->strip() - prev_channel == 1 ) + if ( d->depositedCharge() > prev_adc ) aDigit_max = d; // if ADC max in claster + // End of cluster + if ( d->strip() - prev_channel != 1 ) { + fillHeatPlots_MAX( aDigit_max ); + aDigit_max = d; + } + + prev_channel = d->strip(); + prev_adc = d->depositedCharge(); + } + + // Channel hit counters + for ( size_t i = 0; i < m_channel_counter.size(); ++i ) { + if ( i <= 268288 ) + hitRateChannels_UA[i] += m_channel_counter[i]; + else + hitRateChannels_UC[i] += m_channel_counter[i]; + } + + // Chip hit counters + for ( size_t i = 0; i < m_asic_counter.size(); ++i ) { + if ( i <= 495 ) { + hitRateChipAverage_UA_aU[i] += m_asic_counter[i]; + hitRateChipAverage_UA_aU_radial[UTMap.getRadialID( i )] += m_asic_counter[i]; + } else if ( i <= 991 ) { + hitRateChipAverage_UA_aX[i] += m_asic_counter[i]; + hitRateChipAverage_UA_aX_radial[UTMap.getRadialID( i )] += m_asic_counter[i]; + } else if ( i <= 1543 ) { + hitRateChipAverage_UA_bV[i] += m_asic_counter[i]; + hitRateChipAverage_UA_bV_radial[UTMap.getRadialID( i )] += m_asic_counter[i]; + } else if ( i <= 2095 ) { + hitRateChipAverage_UA_bX[i] += m_asic_counter[i]; + hitRateChipAverage_UA_bX_radial[UTMap.getRadialID( i )] += m_asic_counter[i]; + } else if ( i <= 2591 ) { + hitRateChipAverage_UC_aU[i] += m_asic_counter[i]; + hitRateChipAverage_UC_aU_radial[UTMap.getRadialID( i )] += m_asic_counter[i]; + } else if ( i <= 3087 ) { + hitRateChipAverage_UC_aX[i] += m_asic_counter[i]; + hitRateChipAverage_UC_aX_radial[UTMap.getRadialID( i )] += m_asic_counter[i]; + } else if ( i <= 3639 ) { + hitRateChipAverage_UC_bV[i] += m_asic_counter[i]; + hitRateChipAverage_UC_bV_radial[UTMap.getRadialID( i )] += m_asic_counter[i]; + } else if ( i <= 4191 ) { + hitRateChipAverage_UC_bX[i] += m_asic_counter[i]; + hitRateChipAverage_UC_bX_radial[UTMap.getRadialID( i )] += m_asic_counter[i]; + } + } + + std::map<unsigned int, unsigned int> count_th; // for summary plots + std::map<unsigned int, unsigned int> count_ch; + + for ( size_t i = 0; i < m_asic_counter.size(); ++i ) { + if ( m_asic_counter[i] > 0 ) { + if ( m_asic_counter[i] > m_maxchannel_counter[i] ) { + m_maxchannel_counter[i] = m_asic_counter[i]; + } // for profile histo + unsigned int channelID = + UTMap.getChannel( UTMap.getASICName( i ).substr( 0, UTMap.getASICName( i ).find( '.' ) ) ); + fillHeatMap( channelID + 128 * std::atoi( &UTMap.getASICName( i ).back() ), m_threshold_counter[i], + m_maxchannel_counter[i], det ); + + ++count_th[m_threshold_counter[i]]; + ++count_ch[m_maxchannel_counter[i]]; + } + } + + for ( const auto& entry : count_th ) { ZS_thresholds[entry.first] += entry.second; } + for ( const auto& entry : count_ch ) { ZS_channels[entry.first] += entry.second; } + } + +private: + mutable UTCoordinatesMap UTMap; + + // General plots + // Digits counter + mutable GA::Histogram<1> m_nDigits{ this, "nDigits", "Total nDigits", AxisDIGIT }; + // ADC counter + mutable GA::Histogram<1> m_nADC{ this, "nADC", "Total nADC", AxisADC_signed }; + + // Hitrate counters - channel + mutable GA::ProfileHistogram<1> hitRateChannels_UA{ this, "hitRateChannels_UA", "hitRateChannels_UA", + AxisUAChannels }; + mutable GA::ProfileHistogram<1> hitRateChannels_UC{ this, "hitRateChannels_UC", "hitRateChannels_UC", + AxisUCChannels }; + + // Hitrate counters - chips + mutable GA::ProfileHistogram<1> hitRateChipAverage_UA_aU{ this, "Average_hitRate_UAaU", "Average_hitRate_UAaU", + AxisUA_aUChips }; + mutable GA::ProfileHistogram<1> hitRateChipAverage_UA_aX{ this, "Average_hitRate_UAaX", "Average_hitRate_UAaX", + AxisUA_aXChips }; + mutable GA::ProfileHistogram<1> hitRateChipAverage_UA_bV{ this, "Average_hitRate_UAbV", "Average_hitRate_UAbV", + AxisUA_bVChips }; + mutable GA::ProfileHistogram<1> hitRateChipAverage_UA_bX{ this, "Average_hitRate_UAbX", "Average_AhitRate_UAbX", + AxisUA_bXChips }; + mutable GA::ProfileHistogram<1> hitRateChipAverage_UC_aU{ this, "Average_hitRate_UCaU", "Average_hitRate_UCaU", + AxisUC_aUChips }; + mutable GA::ProfileHistogram<1> hitRateChipAverage_UC_aX{ this, "Average_hitRate_UCaX", "Average_hitRate_UCaX", + AxisUC_aXChips }; + mutable GA::ProfileHistogram<1> hitRateChipAverage_UC_bV{ this, "Average_hitRate_UCbV", "Average_hitRate_UCbV", + AxisUC_bVChips }; + mutable GA::ProfileHistogram<1> hitRateChipAverage_UC_bX{ this, "Average_hitRate_UCbX", "Average_hitRate_UCbX", + AxisUC_bXChips }; + + // Hitrate counters - chip radial + mutable GA::ProfileHistogram<1> hitRateChipAverage_UA_aU_radial{ this, "Average_hitRate_UAaU_radial", + "Average_hitRate_UAaU_radial", AxisUA_aUChips }; + mutable GA::ProfileHistogram<1> hitRateChipAverage_UA_aX_radial{ this, "Average_hitRate_UAaX_radial", + "Average_hitRate_UAaX_radial", AxisUA_aXChips }; + mutable GA::ProfileHistogram<1> hitRateChipAverage_UA_bV_radial{ this, "Average_hitRate_UAbV_radial", + "Average_hitRate_UAbV_radial", AxisUA_bVChips }; + mutable GA::ProfileHistogram<1> hitRateChipAverage_UA_bX_radial{ this, "Average_hitRate_UAbX_radial", + "Average_AhitRate_UAbX_radial", AxisUA_bXChips }; + mutable GA::ProfileHistogram<1> hitRateChipAverage_UC_aU_radial{ this, "Average_hitRate_UCaU_radial", + "Average_hitRate_UCaU_radial", AxisUC_aUChips }; + mutable GA::ProfileHistogram<1> hitRateChipAverage_UC_aX_radial{ this, "Average_hitRate_UCaX_radial", + "Average_hitRate_UCaX_radial", AxisUC_aXChips }; + mutable GA::ProfileHistogram<1> hitRateChipAverage_UC_bV_radial{ this, "Average_hitRate_UCbV_radial", + "Average_hitRate_UCbV_radial", AxisUC_bVChips }; + mutable GA::ProfileHistogram<1> hitRateChipAverage_UC_bX_radial{ this, "Average_hitRate_UCbX_radial", + "Average_hitRate_UCbX_radial", AxisUC_bXChips }; + + // Special ADC counters - average ADC + mutable GA::ProfileHistogram<1> ADCChipAverage_UA_aU{ this, "Average_ADC_UAaU", "Average_ADC_UAaU", AxisUA_aUChips }; + mutable GA::ProfileHistogram<1> ADCChipAverage_UA_aX{ this, "Average_ADC_UAaX", "Average_ADC_UAaX", AxisUA_aXChips }; + mutable GA::ProfileHistogram<1> ADCChipAverage_UA_bV{ this, "Average_ADC_UAbV", "Average_ADC_UAbV", AxisUA_bVChips }; + mutable GA::ProfileHistogram<1> ADCChipAverage_UA_bX{ this, "Average_ADC_UAbX", "Average_ADC_UAbX", AxisUA_bXChips }; + mutable GA::ProfileHistogram<1> ADCChipAverage_UC_aU{ this, "Average_ADC_UCaU", "Average_ADC_UCaU", AxisUC_aUChips }; + mutable GA::ProfileHistogram<1> ADCChipAverage_UC_aX{ this, "Average_ADC_UCaX", "Average_ADC_UCaX", AxisUC_aXChips }; + mutable GA::ProfileHistogram<1> ADCChipAverage_UC_bV{ this, "Average_ADC_UCbV", "Average_ADC_UCbV", AxisUC_bVChips }; + mutable GA::ProfileHistogram<1> ADCChipAverage_UC_bX{ this, "Average_ADC_UCbX", "Average_ADC_UCbX", AxisUC_bXChips }; + + // Hitmap - channel limit & zs threshold per ASIC - 1D + mutable GA::ProfileHistogram<1> ZS_thresholds{ this, "ZS_thresholds", "ZS_thresholds", AxisThresholds }; + mutable GA::ProfileHistogram<1> ZS_channels{ this, "ZS_channels", "ZS_channels", AxisChannels }; + + // Hitmap - channel limit & zs threshold per ASIC - 2D + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::ProfileHistogram<2>, 4> m_2d_ZS_th_chips{ + this, + []( int i ) { return fmt::format( "UT_ZS_th_Chips_Layer{}", i ); }, + []( int i ) { return fmt::format( "zs_th of Layer{}", i ); }, + { 144, -9, 9, "Staves (ASICs)" }, + { 28, -7, 7, "Modules" } }; + + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::ProfileHistogram<2>, 4> m_2d_ZS_ch_chips{ + this, + []( int i ) { return fmt::format( "UT_ZS_ch_Chips_Layer{}", i ); }, + []( int i ) { return fmt::format( "zs_channel of Layer{}", i ); }, + { 144, -9, 9, "Staves (ASICs)" }, + { 28, -7, 7, "Modules" } }; + + // The container for pedestal per channel + mutable std::map<std::string, GA::Histogram<1>> m_1d_ADCCounter; + + void fillHeatPlots( const LHCb::UTDigit* aDigit ) const { + + // Let's find where we are + std::tuple<float, float, float, float, std::string, std::string> tuple = + UTMap.getTuple( aDigit->module(), aDigit->face(), aDigit->stave(), aDigit->side(), aDigit->sector() ); + std::string module_name = std::get<4>( tuple ); + std::string type = std::get<5>( tuple ); + + // What a beautiful line of code + unsigned int globalASIC_ID = UTMap.getASICNumber( UT_layers[aDigit->layer()] + "_" + module_name + ".Chip" + + std::to_string( aDigit->strip() / 128 ) ); + ++m_channel_counter[globalASIC_ID * 128 + aDigit->strip() % 128]; + ++m_asic_counter[globalASIC_ID]; + + if ( globalASIC_ID <= 495 ) + ADCChipAverage_UA_aU[globalASIC_ID] += aDigit->depositedCharge(); + else if ( globalASIC_ID <= 991 ) + ADCChipAverage_UA_aX[globalASIC_ID] += aDigit->depositedCharge(); + else if ( globalASIC_ID <= 1543 ) + ADCChipAverage_UA_bV[globalASIC_ID] += aDigit->depositedCharge(); + else if ( globalASIC_ID <= 2095 ) + ADCChipAverage_UA_bX[globalASIC_ID] += aDigit->depositedCharge(); + else if ( globalASIC_ID <= 2591 ) + ADCChipAverage_UC_aU[globalASIC_ID] += aDigit->depositedCharge(); + else if ( globalASIC_ID <= 3087 ) + ADCChipAverage_UC_aX[globalASIC_ID] += aDigit->depositedCharge(); + else if ( globalASIC_ID <= 3639 ) + ADCChipAverage_UC_bV[globalASIC_ID] += aDigit->depositedCharge(); + else if ( globalASIC_ID <= 4191 ) + ADCChipAverage_UC_bX[globalASIC_ID] += aDigit->depositedCharge(); + + if ( m_threshold_counter[globalASIC_ID] == 0 ) + m_threshold_counter[globalASIC_ID] = 31; // we can't start from zero to minimise and we can't init all asics with + // 31 because we want keep disabled empty + + if ( aDigit->depositedCharge() < m_threshold_counter[globalASIC_ID] ) + m_threshold_counter[globalASIC_ID] = aDigit->depositedCharge(); + + // ADC counter + ++m_nADC[aDigit->depositedCharge()]; + } + + void fillHeatPlots_MAX( const LHCb::UTDigit* aDigit ) const { + // Let's find where we are + std::tuple<float, float, float, float, std::string, std::string> tuple = + UTMap.getTuple( aDigit->module(), aDigit->face(), aDigit->stave(), aDigit->side(), aDigit->sector() ); + std::string module_name = std::get<4>( tuple ); + std::string type = std::get<5>( tuple ); + ++m_1d_ADCCounter.at( UT_layers[aDigit->layer()] + "_" + module_name + ".Chip" + + std::to_string( aDigit->strip() / 128 ) )[aDigit->depositedCharge()]; + } + + void fillHeatMap( unsigned int channel, unsigned int zs_th, unsigned int ch, DeUTDetector const& det ) const { + Detector::UT::ChannelID channelID( channel ); + + // Let's find where we are + auto tuple = + UTMap.getTuple( channelID.module(), channelID.face(), channelID.stave(), channelID.side(), channelID.sector() ); + + float x = std::get<0>( tuple ); + float y = std::get<1>( tuple ); + std::string module_name = std::get<4>( tuple ); + std::string type = std::get<5>( tuple ); + auto aSector = det.findSector( channelID ); + +#ifdef USE_DD4HEP + auto trajStrip0 = aSector.createTraj( 0, 0 ); + auto trajStrip511 = aSector.createTraj( 511, 0 ); + auto trajStrip127 = aSector.createTraj( 127, 0 ); +#else + auto trajStrip0 = aSector->trajectory( channelID, 0 ); + auto trajStrip511 = aSector->trajectory( LHCb::Detector::UT::ChannelID{ channelID + 511 }, 0 ); + auto trajStrip127 = aSector->trajectory( LHCb::Detector::UT::ChannelID{ channelID + 127 }, 0 ); +#endif + double stripx0 = -1 * ( trajStrip0.endPoint().x() + trajStrip0.beginPoint().x() ) * 0.5; + double stripx511 = -1 * ( trajStrip511.endPoint().x() + trajStrip511.beginPoint().x() ) * 0.5; + double stripx127 = -1 * ( trajStrip127.endPoint().x() + trajStrip127.beginPoint().x() ) * 0.5; + double stripy = ( trajStrip0.endPoint().y() + trajStrip0.beginPoint().y() ) * 0.5; + + double stripwidth = stripx511 - stripx0; + double stripwidth2 = stripx127 - stripx0; + int chip; + + if ( stripwidth > 0 ) + chip = int( channelID.strip() / 128 ); + else + chip = 3 - int( channelID.strip() / 128 ); + + double positionasic_one = positionasic[chip][0]; + double positionasic_two = positionasic[chip][1]; + double positionasic_thr = positionasic[chip][2]; + + // CHIPS Maps // + if ( ( channelID.stave() > 1 ) || ( fabs( y ) > 2 ) ) { + m_2d_ZS_th_chips[channelID.layer()][{ x + positionasic_one, y + 0.25 }] += zs_th; + m_2d_ZS_th_chips[channelID.layer()][{ x + positionasic_one, y - 0.25 }] += zs_th; + m_2d_ZS_th_chips[channelID.layer()][{ x + positionasic_two, y + 0.25 }] += zs_th; + m_2d_ZS_th_chips[channelID.layer()][{ x + positionasic_two, y - 0.25 }] += zs_th; + if ( ch > 0 ) { + m_2d_ZS_ch_chips[channelID.layer()][{ x + positionasic_one, y + 0.25 }] += ch; + m_2d_ZS_ch_chips[channelID.layer()][{ x + positionasic_one, y - 0.25 }] += ch; + m_2d_ZS_ch_chips[channelID.layer()][{ x + positionasic_two, y + 0.25 }] += ch; + m_2d_ZS_ch_chips[channelID.layer()][{ x + positionasic_two, y - 0.25 }] += ch; + } + } + if ( ( ( channelID.stave() == 1 ) && ( fabs( y ) < 2 ) ) || + ( ( channelID.stave() == 0 ) && ( fabs( y ) == 1.5 ) ) ) { + + m_2d_ZS_th_chips[channelID.layer()][{ x + positionasic_thr, y + 0.25 }] += zs_th; + m_2d_ZS_th_chips[channelID.layer()][{ x + positionasic_thr, y - 0.25 }] += zs_th; + if ( ch > 0 ) { + m_2d_ZS_ch_chips[channelID.layer()][{ x + positionasic_thr, y + 0.25 }] += ch; + m_2d_ZS_ch_chips[channelID.layer()][{ x + positionasic_thr, y - 0.25 }] += ch; + } + } + if ( ( channelID.stave() == 0 ) && ( fabs( y ) < 1 ) ) { + m_2d_ZS_th_chips[channelID.layer()][{ x + positionasic_thr, y }] += zs_th; + if ( ch > 0 ) m_2d_ZS_ch_chips[channelID.layer()][{ x + positionasic_thr, y }] += ch; + } + } + +}; // End of class UTBSMonitor +DECLARE_COMPONENT( UTBSMonitor ) diff --git a/UT/UTMonitors/src/UTDigitsMonitor.cpp b/UT/UTMonitors/src/UTDigitsMonitor.cpp new file mode 100644 index 00000000000..f1bfd7fe03f --- /dev/null +++ b/UT/UTMonitors/src/UTDigitsMonitor.cpp @@ -0,0 +1,668 @@ +/***************************************************************************** \ +* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration * +* * +* This software is distributed under the terms of the GNU General Public * +* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". * +* * +* In applying this licence, CERN does not waive the privileges and immunities * +* granted to it by virtue of its status as an Intergovernmental Organization * +* or submit itself to any jurisdiction. * +\*****************************************************************************/ + +#include "Event/UTDigit.h" +#include "GaudiAlg/GaudiHistoAlg.h" +#include "Kernel/IUTReadoutTool.h" +#include "Kernel/UTDAQBoard.h" +#include "Kernel/UTDAQDefinitions.h" +#include "Kernel/UTDAQID.h" +#include "LHCbAlgs/Consumer.h" +#include "LHCbAlgs/Transformer.h" +#include "UTDAQ/UTCoordinatesMap.h" +#include "UTDAQ/UTDAQHelper.h" +#include "UTDAQ/UTInfo.h" +#include "UTDet/DeUTDetector.h" +#include <Event/ODIN.h> +#include <Event/RawBank.h> +#include <Event/RawEvent.h> +#include <Gaudi/Accumulators/Histogram.h> +#include <Gaudi/Accumulators/HistogramArray.h> +#include <Kernel/IUTReadoutTool.h> +#include <mutex> +#include <optional> +#include <string> + +/** @class UTDigitsMonitor UTDigitsMonitor.cpp + * -------------------------------------------------- + * Counters for Monet online monitoring of the UT + * The algorithm produces several useful histograms + * @author Wojciech Krupa + * @date 2024/03/20 + * -------------------------------------------------- + **/ + +using namespace LHCb; +namespace GA = Gaudi::Accumulators; + +// Definition of axis +const GA::Axis<double> AxisADC = GA::Axis<double>( 64, -32.5, 31.5, "nADC" ); //-32, 31 +const GA::Axis<double> AxisADC_signed = GA::Axis<double>( 32, -0.5, 31.5, "nADC" ); // 0-31 +const GA::Axis<double> AxisBCID = GA::Axis<double>( 3565, -0.5, 3564.5, "BunchID" ); // +const GA::Axis<double> AxisDIGIT = GA::Axis<double>( 1000, -0.5, 100000.5, "UTDigits (size of digit container)" ); +const GA::Axis<double> AxisXnaturalunits = GA::Axis<double>( 36, -9, 9, "Staves (Sectors)" ); +const GA::Axis<double> AxisXnaturalunits4x = GA::Axis<double>( 144, -9, 9, "Staves (ASICs)" ); +const GA::Axis<double> AxisYnaturalunits = GA::Axis<double>( 28, -7, 7, "Modules" ); + +// Definition of histogram names +const std::array<std::string, 4> s_HistNames = { "UTA_Tell_40_vs_ASIC_Flow0", "UTA_Tell_40_vs_ASIC_Flow1", + "UTC_Tell_40_vs_ASIC_Flow0", "UTC_Tell_40_vs_ASIC_Flow1" }; + +const std::array<std::string, 4> s_HistNames_Counter = { + "UTA_Tell_40_EventsCounter_Flow0", "UTA_Tell_40_EventsCounter_Flow1", "UTC_Tell_40_EventsCounter_Flow0", + "UTC_Tell_40_EventsCounter_Flow1" }; + +const std::array<std::string, 6> s_HistNames_BXType = { "nADC", "nADC_A", "nADC_B", "nADC_C", "nADC_D" }; + +const std::array<std::string, 6> s_HistNames_BXType_labels = { + "Total nADC", "Total nADC - type A sensors", "Total nADC - type B sensors", "Total nADC - type C sensors", + "Total nADC - type D sensors" }; + +const std::array<std::string, 15> s_HistNames_EventType = { "NoBias", + "Lumi", + "Isolated", + "Leading", + "Trailing", + "Empty before isolated", + "Empty after isolated", + "Empty before leading", + "Empty after trailing", + "Empty after 19 clock from trailling", + "NoBias bb", + "Lumi bb", + "Isolated bb", + "Leading bb", + "Trailing bb" }; + +const std::array<std::string, 15> s_HistNames_EventType_labels = { "NoBias", + "Lumi", + "Isolated - ADC", + "Leading - ADC", + "Trailing - ADC", + "Empty before isolated - ADC", + "Empty after isolated - ADC", + "Empty before leading - ADC", + "Empty after trailing - ADC", + "Empty after 19 clock from trailling - ADC", + "NoBias bb - ADC", + "Lumi bb - ADC", + "Isolated bb - ADC", + "Leading bb - ADC", + "Trailing bb - ADC" }; + +// UT layers +const std::array<std::string, 4> UT_layers = { "UTaX", "UTaU", "UTbV", "UTbX" }; + +// 2D plots +const double positionasic[4][3] = { + { -0.4375, -0.3125, -0.1875 }, // Chip 0 + { -0.1875, -0.0625, -0.0625 }, // Chip 1 + { +0.1875, +0.0625, +0.0625 }, // Chip 2 + { +0.4375, +0.3125, +0.1875 } // Chip 3 +}; + +enum class masks { channel = 0x000001ff, lane = 0x00000e00, board = 0x000ff000 }; + +template <masks m> +[[nodiscard]] static constexpr unsigned int extract( unsigned int i ) { + constexpr auto b = std::countr_zero( static_cast<unsigned int>( m ) ); + return ( i & static_cast<unsigned int>( m ) ) >> b; +} + +/** ------------------------------------------------------------------------------------------------------------------------ */ + +class UTDigitsMonitor + : public LHCb::Algorithm::Consumer<void( UTDigits const&, UTDigits const&, DeUTDetector const&, LHCb::ODIN const& ), + LHCb::DetDesc::usesBaseAndConditions<GaudiHistoAlg, DeUTDetector>> { +public: + UTDigitsMonitor( const std::string& name, ISvcLocator* svcloc ) + : Consumer{ name, + svcloc, + { { "InputData", UTDigitLocation::UTDigits }, + { "InputErrorData", UTDigitLocation::UTDigits }, + { "UTLocation", DeUTDetLocation::location() }, + { "ODINLocation", LHCb::ODINLocation::Default } } } {} + ToolHandle<IUTReadoutTool> readoutTool{ this, "ReadoutTool", "UTReadoutTool" }; + + StatusCode initialize() override { + return Consumer::initialize().andThen( [&] { + // Set the top directory to UT + if ( histoTopDir().empty() ) setHistoTopDir( "" ); + } ); + } + + void operator()( const UTDigits& digitsCont, const UTDigits& errdigitsCont, DeUTDetector const& det, + LHCb::ODIN const& odin ) const override { + + // General counters + const unsigned int nDigits = digitsCont.size() + errdigitsCont.size(); + const unsigned int nBuncId = odin.bunchId(); + + if ( msgLevel( MSG::DEBUG ) ) debug() << "---------- Found nDigits: " << nDigits << endmsg; + ++m_nDigits[nDigits]; + ++m_nBuncId[nBuncId]; + ++m_nDigitsnBuncId[{ nBuncId, nDigits }]; + + if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::BeamCrossing ) + ++m_nDigits_bb[nDigits]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::Beam1 ) + ++m_nDigits_be[nDigits]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::Beam2 ) + ++m_nDigits_eb[nDigits]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::NoBeam ) + ++m_nDigits_ee[nDigits]; + + // ------------------------------------------------------- + // Loop on digits + // side==1 is Aside (left), side==0 is Cside (right) + // ------------------------------------------------------- + // Hitmaps plots and ADC + + // Commisioning per side histograms + unsigned int ua_size = 0; + unsigned int uc_size = 0; + unsigned int ua_error_size = 0; + unsigned int uc_error_size = 0; + + // For max ADC plots + unsigned int prev_channel = 0; + unsigned int prev_adc = 0; + LHCb::UTDigit* aDigit_max; + + // UT bank + for ( const auto& d : digitsCont ) { + fillHeatMap( d, det ); + fillADC( d, odin ); + + if ( d->face() == 0 ) + uc_size++; + else if ( d->face() == 1 ) + ua_size++; + + UTDAQID daqID = readoutTool->channelIDToDAQID( d->channelID() ); + auto board_ID = daqID.board(); + unsigned int sourceID = UTMap.getSourceIDfromBoardNumber( board_ID ); + + if ( sourceID != prevSourceID ) { fillBankHistograms( sourceID ); } + prevSourceID = sourceID; + + // Cluster max ADC counters + // First event + if ( prev_channel == 0 ) { + prev_channel = d->strip(); + prev_adc = d->depositedCharge(); + aDigit_max = d; + continue; + } + // If cluster size >1 + if ( d->strip() - prev_channel == 1 ) + if ( d->depositedCharge() > prev_adc ) aDigit_max = d; // if ADC max in claster + // End of cluster + if ( d->strip() - prev_channel != 1 ) { + fillADC_clusterMAX( aDigit_max ); + aDigit_max = d; + } + + prev_channel = d->strip(); + prev_adc = d->depositedCharge(); + } + + // UT error bank + for ( const auto& d : errdigitsCont ) { + fillHeatMap( d, det ); + fillADC( d, odin ); + + if ( d->face() == 0 ) + uc_error_size++; + else if ( d->face() == 1 ) + ua_error_size++; + + UTDAQID daqID = readoutTool->channelIDToDAQID( d->channelID() ); + auto board_ID = daqID.board(); + unsigned int sourceID = UTMap.getSourceIDfromBoardNumber( board_ID ); + + if ( sourceID != prevSourceID ) { fillBankHistograms( sourceID ); } + + prevSourceID = sourceID; + + // Cluster max ADC counters + // First event + if ( prev_channel == 0 ) { + prev_channel = d->strip(); + prev_adc = d->depositedCharge(); + aDigit_max = d; + continue; + } + // If cluster size >1 + if ( d->strip() - prev_channel == 1 ) + if ( d->depositedCharge() > prev_adc ) aDigit_max = d; // if ADC max in claster + // End of cluster + if ( d->strip() - prev_channel != 1 ) { + fillADC_clusterMAX( aDigit_max ); + aDigit_max = d; + } + + prev_channel = d->strip(); + prev_adc = d->depositedCharge(); + } + + // Commisioning per side histograms + ++m_nDigits_UA[ua_size + ua_error_size]; + ++m_nDigits_UC[uc_size + uc_error_size]; + } + +private: + mutable UTCoordinatesMap UTMap; + mutable unsigned int prevSourceID = 0; + + // General plots + mutable GA::Histogram<1> m_nBuncId{ this, "nBuncId", "Bunch IDs", AxisBCID }; + mutable GA::Histogram<2> m_nDigitsnBuncId{ this, "nDigitsnBuncId", "nBuncId vs BunchIDs", AxisBCID, AxisDIGIT }; + + // Digits counters + mutable GA::Histogram<1> m_nDigits{ this, "nDigits", "Total nDigits", AxisDIGIT }; + mutable GA::Histogram<1> m_nDigits_UA{ this, "nDigits_UA", "Total nDigits UA", AxisDIGIT }; + mutable GA::Histogram<1> m_nDigits_UC{ this, "nDigits_UC", "Total nDigits UC", AxisDIGIT }; + + // Split for event type + mutable GA::Histogram<1> m_nDigits_bb{ this, "nDigits_bb", "Total nDigits bb", AxisDIGIT }; + mutable GA::Histogram<1> m_nDigits_be{ this, "nDigits_be", "Total nDigits be", AxisDIGIT }; + mutable GA::Histogram<1> m_nDigits_eb{ this, "nDigits_eb", "Total nDigits eb", AxisDIGIT }; + mutable GA::Histogram<1> m_nDigits_ee{ this, "nDigits_ee", "Total nDigits ee", AxisDIGIT }; + + // ADC counters + mutable GA::Histogram<1> m_nADC{ this, "nADC", "Total nADC", AxisADC_signed }; + mutable GA::Histogram<1> m_nADC_A{ this, "nADC_A", "Total nADC - type A sensors", AxisADC_signed }; + mutable GA::Histogram<1> m_nADC_B{ this, "nADC_B", "Total nADC - type B sensors", AxisADC_signed }; + mutable GA::Histogram<1> m_nADC_C{ this, "nADC_C", "Total nADC - type C sensors", AxisADC_signed }; + mutable GA::Histogram<1> m_nADC_D{ this, "nADC_D", "Total nADC - type D sensors", AxisADC_signed }; + + // Cluster max counters + mutable GA::Histogram<1> m_nADC_clusterMAX{ this, "nADC_clusterMAX", "Total nADC", AxisADC_signed }; + mutable GA::Histogram<1> m_nADC_A_clusterMAX{ this, "nADC_A_clusterMAX", "Total nADC - type A sensors", + AxisADC_signed }; + mutable GA::Histogram<1> m_nADC_B_clusterMAX{ this, "nADC_B_clusterMAX", "Total nADC - type B sensors", + AxisADC_signed }; + mutable GA::Histogram<1> m_nADC_C_clusterMAX{ this, "nADC_C_clusterMAX", "Total nADC - type C sensors", + AxisADC_signed }; + mutable GA::Histogram<1> m_nADC_D_clusterMAX{ this, "nADC_D_clusterMAX", "Total nADC - type D sensors", + AxisADC_signed }; + + // Split for A/C side (comissioning) + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<1>, 5> m_1d_ua{ + this, + []( int i ) { return fmt::format( "{}", "UA_" + s_HistNames_BXType[i] ); }, + []( int i ) { return fmt::format( "{}", "UA " + s_HistNames_BXType_labels[i] ); }, + { 32, -0.5, 31.5, "nADC" } }; + + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<1>, 5> m_1d_uc{ + this, + []( int i ) { return fmt::format( "{}", "UC_" + s_HistNames_BXType[i] ); }, + []( int i ) { return fmt::format( "{}", "UC " + s_HistNames_BXType_labels[i] ); }, + { 32, -0.5, 31.5, "nADC" } }; + + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<1>, 5> m_1d_bb{ + this, + []( int i ) { return fmt::format( "{}_bb", s_HistNames_BXType[i] ); }, + []( int i ) { return fmt::format( "{}_bb", s_HistNames_BXType_labels[i] ); }, + { 32, -0.5, 31.5, "nADC" } }; + + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<1>, 5> m_1d_be{ + this, + []( int i ) { return fmt::format( "{}_be", s_HistNames_BXType[i] ); }, + []( int i ) { return fmt::format( "{}_be", s_HistNames_BXType_labels[i] ); }, + { 32, -0.5, 31.5, "nADC" } }; + + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<1>, 5> m_1d_eb{ + this, + []( int i ) { return fmt::format( "{}_eb", s_HistNames_BXType[i] ); }, + []( int i ) { return fmt::format( "{}_eb", s_HistNames_BXType_labels[i] ); }, + { 32, -0.5, 31.5, "nADC" } }; + + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<1>, 5> m_1d_ee{ + this, + []( int i ) { return fmt::format( "{}_ee", s_HistNames_BXType[i] ); }, + []( int i ) { return fmt::format( "{}_ee", s_HistNames_BXType_labels[i] ); }, + { 32, -0.5, 31.5, "nADC" } }; + + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<1>, 15> m_1d_type{ + this, + []( int i ) { return fmt::format( "{}", s_HistNames_EventType[i] ); }, + []( int i ) { return fmt::format( "{}", s_HistNames_EventType_labels[i] ); }, + { 32, -0.5, 31.5, "nADC" } }; + + mutable GA::Histogram<2> m_nADCvsBCID{ this, "nADCvsBuncId", "nADC vs BuncId", AxisBCID, AxisADC_signed }; + + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<2>, 4> m_2d_hitmap_sectors{ + this, + []( int i ) { return fmt::format( "UT_HitMap_Sectors_Layer{}", i ); }, + []( int i ) { return fmt::format( "Sectors of Layer{} (ASICs)", i ); }, + { 36, -9, 9, "Staves (ASICs)" }, + { 28, -7, 7, "Modules" } }; + + // UT Hitmaps per asic physical position + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<2>, 4> m_2d_hitmap_chips{ + this, + []( int i ) { return fmt::format( "UT_HitMap_Chips_Layer{}", i ); }, + []( int i ) { return fmt::format( "ASICs of Layer{}", i ); }, + { 144, -9, 9, "Staves (ASICs)" }, + { 28, -7, 7, "Modules" } }; + + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<2>, 4> m_2d_hitmap_tell40_eff{ + this, + []( int i ) { return fmt::format( "UT_HitMap_TELL40_Eff_Layer{}", i ); }, + []( int i ) { return fmt::format( "TELL40 of Layer{} (ASICs)", i ); }, + { 36, -9, 9, "Staves (ASICs)" }, + { 28, -7, 7, "Modules" } }; + + // TELL40 plots + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<2>, s_HistNames.size()> + m_UT_Tell_40_vs_asic{ this, + []( int i ) { return fmt::format( "{}", s_HistNames[i] ); }, + []( int i ) { return fmt::format( "{}", s_HistNames[i] ); }, + { 54, 0, 54 }, + { 24, 0, 24 } }; + + // TELL40 plots - counter + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<1>, s_HistNames_Counter.size()> + m_UT_Tell_40_events{ this, + []( int i ) { return fmt::format( "{}", s_HistNames_Counter[i] ); }, + []( int i ) { return fmt::format( "{}", s_HistNames_Counter[i] ); }, + { 54, 0, 54 } }; + + void fillBankHistograms( const int sourceID ) const { + + int SourceID_ = sourceID / 1000; + + if ( UTMap.getTELL40( sourceID ).find( "UA" ) != std::string::npos ) { + if ( SourceID_ == 10 ) { + ++m_UT_Tell_40_events[0][UTMap.getTELL40Bin( sourceID )]; + } else if ( SourceID_ == 11 ) { + ++m_UT_Tell_40_events[1][UTMap.getTELL40Bin( sourceID )]; + } + + } else if ( UTMap.getTELL40( sourceID ).find( "UC" ) != std::string::npos ) { + if ( SourceID_ == 12 ) { + ++m_UT_Tell_40_events[2][UTMap.getTELL40Bin( sourceID )]; + } else if ( SourceID_ == 13 ) { + ++m_UT_Tell_40_events[3][UTMap.getTELL40Bin( sourceID )]; + } + } + + auto modules = UTMap.getNamesfromTELL40( UTMap.getTELL40( sourceID ) ); + for ( const auto& module : modules ) { + unsigned int channel = UTMap.getChannel( module ); + + Detector::UT::ChannelID channelID( channel ); + + // Let's find where we are + auto tuple = UTMap.getTuple( channelID.module(), channelID.face(), channelID.stave(), channelID.side(), + channelID.sector() ); + + float x = std::get<0>( tuple ); + float y = std::get<1>( tuple ); + std::string module_name = std::get<4>( tuple ); + std::string type = std::get<5>( tuple ); + + // SECTORS Maps // + if ( ( channelID.stave() > 1 ) || ( fabs( y ) > 2 ) ) { + ++m_2d_hitmap_tell40_eff[channelID.layer()][{ x + 0.25, y + 0.25 }]; + ++m_2d_hitmap_tell40_eff[channelID.layer()][{ x + 0.25, y - 0.25 }]; + ++m_2d_hitmap_tell40_eff[channelID.layer()][{ x - 0.25, y + 0.25 }]; + ++m_2d_hitmap_tell40_eff[channelID.layer()][{ x - 0.25, y - 0.25 }]; + } + if ( ( ( channelID.stave() == 1 ) && ( fabs( y ) < 2 ) ) || + ( ( channelID.stave() == 0 ) && ( fabs( y ) == 1.5 ) ) ) { + ++m_2d_hitmap_tell40_eff[channelID.layer()][{ x, y + 0.25 }]; + ++m_2d_hitmap_tell40_eff[channelID.layer()][{ x, y - 0.25 }]; + } + if ( ( channelID.stave() == 0 ) && ( fabs( y ) < 1 ) ) { ++m_2d_hitmap_tell40_eff[channelID.layer()][{ x, y }]; } + } + } + + void fillADC( const LHCb::UTDigit* aDigit, LHCb::ODIN const& odin ) const { + + ++m_nADCvsBCID[{ odin.bunchId(), aDigit->depositedCharge() }]; + std::string type = std::get<5>( + UTMap.getTuple( aDigit->module(), aDigit->face(), aDigit->stave(), aDigit->side(), aDigit->sector() ) ); + + if ( odin.eventTypeBit( LHCb::ODIN::EventTypes::NoBias ) ) ++m_1d_type[0][aDigit->depositedCharge()]; + if ( odin.eventTypeBit( LHCb::ODIN::EventTypes::Lumi ) ) ++m_1d_type[1][aDigit->depositedCharge()]; + if ( odin.eventTypeBit( LHCb::ODIN::EventTypes::et_bit_08 ) ) ++m_1d_type[2][aDigit->depositedCharge()]; + if ( odin.eventTypeBit( LHCb::ODIN::EventTypes::et_bit_09 ) ) ++m_1d_type[3][aDigit->depositedCharge()]; + if ( odin.eventTypeBit( LHCb::ODIN::EventTypes::et_bit_10 ) ) ++m_1d_type[4][aDigit->depositedCharge()]; + if ( odin.eventTypeBit( LHCb::ODIN::EventTypes::et_bit_11 ) ) ++m_1d_type[5][aDigit->depositedCharge()]; + if ( odin.eventTypeBit( LHCb::ODIN::EventTypes::et_bit_12 ) ) ++m_1d_type[6][aDigit->depositedCharge()]; + if ( odin.eventTypeBit( LHCb::ODIN::EventTypes::et_bit_13 ) ) ++m_1d_type[7][aDigit->depositedCharge()]; + if ( odin.eventTypeBit( LHCb::ODIN::EventTypes::et_bit_14 ) ) ++m_1d_type[8][aDigit->depositedCharge()]; + if ( odin.eventTypeBit( LHCb::ODIN::EventTypes::et_bit_15 ) ) ++m_1d_type[9][aDigit->depositedCharge()]; + + if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::BeamCrossing ) { + if ( odin.eventTypeBit( LHCb::ODIN::EventTypes::NoBias ) ) ++m_1d_type[10][aDigit->depositedCharge()]; + if ( odin.eventTypeBit( LHCb::ODIN::EventTypes::Lumi ) ) ++m_1d_type[11][aDigit->depositedCharge()]; + if ( odin.eventTypeBit( LHCb::ODIN::EventTypes::et_bit_08 ) ) ++m_1d_type[12][aDigit->depositedCharge()]; + if ( odin.eventTypeBit( LHCb::ODIN::EventTypes::et_bit_09 ) ) ++m_1d_type[13][aDigit->depositedCharge()]; + if ( odin.eventTypeBit( LHCb::ODIN::EventTypes::et_bit_10 ) ) ++m_1d_type[14][aDigit->depositedCharge()]; + } + + ++m_nADC[aDigit->depositedCharge()]; + + if ( aDigit->face() == 0 ) { + ++m_1d_uc[0][aDigit->depositedCharge()]; + if ( type == "A" ) ++m_1d_uc[1][aDigit->depositedCharge()]; + if ( type == "B" ) ++m_1d_uc[2][aDigit->depositedCharge()]; + if ( type == "C" ) ++m_1d_uc[3][aDigit->depositedCharge()]; + if ( type == "D" ) ++m_1d_uc[4][aDigit->depositedCharge()]; + } else if ( aDigit->face() == 1 ) { + ++m_1d_ua[0][aDigit->depositedCharge()]; + if ( type == "A" ) ++m_1d_ua[1][aDigit->depositedCharge()]; + if ( type == "B" ) ++m_1d_ua[2][aDigit->depositedCharge()]; + if ( type == "C" ) ++m_1d_ua[3][aDigit->depositedCharge()]; + if ( type == "D" ) ++m_1d_ua[4][aDigit->depositedCharge()]; + } + + if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::BeamCrossing ) + ++m_1d_bb[0][aDigit->depositedCharge()]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::Beam1 ) + ++m_1d_be[0][aDigit->depositedCharge()]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::Beam2 ) + ++m_1d_eb[0][aDigit->depositedCharge()]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::NoBeam ) + ++m_1d_ee[0][aDigit->depositedCharge()]; + + if ( type == "A" ) { + ++m_nADC_A[aDigit->depositedCharge()]; + if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::BeamCrossing ) + ++m_1d_bb[1][aDigit->depositedCharge()]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::Beam1 ) + ++m_1d_be[1][aDigit->depositedCharge()]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::Beam2 ) + ++m_1d_eb[1][aDigit->depositedCharge()]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::NoBeam ) + ++m_1d_ee[1][aDigit->depositedCharge()]; + } else if ( type == "B" ) { + ++m_nADC_B[aDigit->depositedCharge()]; + if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::BeamCrossing ) + ++m_1d_bb[2][aDigit->depositedCharge()]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::Beam1 ) + ++m_1d_be[2][aDigit->depositedCharge()]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::Beam2 ) + ++m_1d_eb[2][aDigit->depositedCharge()]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::NoBeam ) + ++m_1d_ee[2][aDigit->depositedCharge()]; + } else if ( type == "C" ) { + ++m_nADC_C[aDigit->depositedCharge()]; + if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::BeamCrossing ) + ++m_1d_bb[3][aDigit->depositedCharge()]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::Beam1 ) + ++m_1d_be[3][aDigit->depositedCharge()]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::Beam2 ) + ++m_1d_eb[3][aDigit->depositedCharge()]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::NoBeam ) + ++m_1d_ee[3][aDigit->depositedCharge()]; + } else if ( type == "D" ) { + ++m_nADC_D[aDigit->depositedCharge()]; + if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::BeamCrossing ) + ++m_1d_bb[4][aDigit->depositedCharge()]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::Beam1 ) + ++m_1d_be[4][aDigit->depositedCharge()]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::Beam2 ) + ++m_1d_eb[4][aDigit->depositedCharge()]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::NoBeam ) + ++m_1d_ee[4][aDigit->depositedCharge()]; + } + + Detector::UT::ChannelID channelID = aDigit->channelID(); + UTDAQID daqID = readoutTool->channelIDToDAQID( channelID ); + auto board_ID = daqID.board(); + unsigned int sourceID = UTMap.getSourceIDfromBoardNumber( board_ID ); + int SourceID_ = sourceID / 1000; + + unsigned int asic_times_lane = int( aDigit->strip() / 128 ) + 4 * extract<masks::lane>( aDigit->getdaqID() ); + + // Sadly we (I) can't do it better. But at least its ok! + if ( UTMap.getTELL40( sourceID ).find( "UA" ) != std::string::npos ) { + if ( SourceID_ == 10 ) { + if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x4" ) { + ++m_UT_Tell_40_vs_asic[0][{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_4_Flow0_Bin( asic_times_lane ) }]; + } else if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x5" ) { + ++m_UT_Tell_40_vs_asic[0][{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_5_Flow0_Bin( asic_times_lane ) }]; + } else if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "4x3" || + UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x3" || + UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "Jx3" ) { + ++m_UT_Tell_40_vs_asic[0][{ UTMap.getTELL40Bin( sourceID ), asic_times_lane }]; + } + } else if ( SourceID_ == 11 ) { + if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x4" ) { + if ( asic_times_lane == 16 || asic_times_lane == 17 ) + ++m_UT_Tell_40_vs_asic[0][{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_4_Flow0_Bin( asic_times_lane ) }]; + else + ++m_UT_Tell_40_vs_asic[1][{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_4_Flow1_Bin( asic_times_lane ) }]; + } else if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x5" ) + ++m_UT_Tell_40_vs_asic[1][{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_5_Flow1_Bin( asic_times_lane ) }]; + else if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "4x3" || + UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x3" || + UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "Jx3" ) + ++m_UT_Tell_40_vs_asic[1][{ UTMap.getTELL40Bin( sourceID ), asic_times_lane }]; + } + + } else if ( UTMap.getTELL40( sourceID ).find( "UC" ) != std::string::npos ) { + if ( SourceID_ == 12 ) { + if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x4" ) { + ++m_UT_Tell_40_vs_asic[2][{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_4_Flow0_Bin( asic_times_lane ) }]; + } else if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x5" ) { + ++m_UT_Tell_40_vs_asic[2][{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_5_Flow0_Bin( asic_times_lane ) }]; + } else if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "4x3" || + UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x3" || + UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "Jx3" ) { + ++m_UT_Tell_40_vs_asic[2][{ UTMap.getTELL40Bin( sourceID ), asic_times_lane }]; + } + } + + else if ( SourceID_ == 13 ) { + if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x4" ) { + if ( asic_times_lane == 16 || asic_times_lane == 17 ) + ++m_UT_Tell_40_vs_asic[2][{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_4_Flow0_Bin( asic_times_lane ) }]; + else + ++m_UT_Tell_40_vs_asic[3][{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_4_Flow1_Bin( asic_times_lane ) }]; + } else if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x5" ) + ++m_UT_Tell_40_vs_asic[3][{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_5_Flow1_Bin( asic_times_lane ) }]; + else if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "4x3" || + UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x3" || + UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "Jx3" ) + ++m_UT_Tell_40_vs_asic[3][{ UTMap.getTELL40Bin( sourceID ), asic_times_lane }]; + } + } + } + + // Fill clusterMAX counters + void fillADC_clusterMAX( const LHCb::UTDigit* aDigit ) const { + + std::string type = std::get<5>( + UTMap.getTuple( aDigit->module(), aDigit->face(), aDigit->stave(), aDigit->side(), aDigit->sector() ) ); + + ++m_nADC_clusterMAX[aDigit->depositedCharge()]; + + if ( type == "A" ) { + ++m_nADC_A_clusterMAX[aDigit->depositedCharge()]; + } else if ( type == "B" ) { + ++m_nADC_B_clusterMAX[aDigit->depositedCharge()]; + } else if ( type == "C" ) { + ++m_nADC_C_clusterMAX[aDigit->depositedCharge()]; + } else if ( type == "D" ) { + ++m_nADC_D_clusterMAX[aDigit->depositedCharge()]; + } + } + + void fillHeatMap( const LHCb::UTDigit* aDigit, DeUTDetector const& det ) const { + + // Let's find where we are + std::tuple<float, float, float, float, std::string, std::string> tuple = + UTMap.getTuple( aDigit->module(), aDigit->face(), aDigit->stave(), aDigit->side(), aDigit->sector() ); + float x = std::get<0>( tuple ); + float y = std::get<1>( tuple ); + std::string module_name = std::get<4>( tuple ); + std::string type = std::get<5>( tuple ); + auto chanID = aDigit->channelID(); + auto aSector = det.findSector( chanID ); + +// This may be useful but allows to get only position of hybrind. It can be used to get ASIC position. +#ifdef USE_DD4HEP + auto trajStrip0 = aSector.createTraj( 0, 0 ); + auto trajStrip511 = aSector.createTraj( 511, 0 ); +#else + auto trajStrip0 = aSector->trajectory( chanID, 0 ); + auto trajStrip511 = aSector->trajectory( LHCb::Detector::UT::ChannelID{ chanID + 511 }, 0 ); +#endif + double stripx0 = -1 * ( trajStrip0.endPoint().x() + trajStrip0.beginPoint().x() ) * 0.5; + double stripx511 = -1 * ( trajStrip511.endPoint().x() + trajStrip511.beginPoint().x() ) * 0.5; + double stripwidth = stripx511 - stripx0; + int chip; + + if ( stripwidth > 0 ) + chip = int( aDigit->strip() / 128 ); + else + chip = 3 - int( aDigit->strip() / 128 ); + + double positionasic_one = positionasic[chip][0]; + double positionasic_two = positionasic[chip][1]; + double positionasic_thr = positionasic[chip][2]; + + // Sectors Maps // + if ( ( aDigit->stave() > 1 ) || ( fabs( y ) > 2 ) ) { + ++m_2d_hitmap_sectors[aDigit->layer()][{ x + 0.25, y + 0.25 }]; + ++m_2d_hitmap_sectors[aDigit->layer()][{ x + 0.25, y - 0.25 }]; + ++m_2d_hitmap_sectors[aDigit->layer()][{ x - 0.25, y + 0.25 }]; + ++m_2d_hitmap_sectors[aDigit->layer()][{ x - 0.25, y - 0.25 }]; + } + if ( ( ( aDigit->stave() == 1 ) && ( fabs( y ) < 2 ) ) || ( ( aDigit->stave() == 0 ) && ( fabs( y ) == 1.5 ) ) ) { + ++m_2d_hitmap_sectors[aDigit->layer()][{ x, y + 0.25 }]; + ++m_2d_hitmap_sectors[aDigit->layer()][{ x, y - 0.25 }]; + } + if ( ( aDigit->stave() == 0 ) && ( fabs( y ) < 1 ) ) { ++m_2d_hitmap_sectors[aDigit->layer()][{ x, y }]; } + + // Chips Maps // + if ( ( aDigit->stave() > 1 ) || ( fabs( y ) > 2 ) ) { + ++m_2d_hitmap_chips[aDigit->layer()][{ x + positionasic_one, y + 0.25 }]; + ++m_2d_hitmap_chips[aDigit->layer()][{ x + positionasic_one, y - 0.25 }]; + ++m_2d_hitmap_chips[aDigit->layer()][{ x + positionasic_two, y + 0.25 }]; + ++m_2d_hitmap_chips[aDigit->layer()][{ x + positionasic_two, y - 0.25 }]; + } + if ( ( ( aDigit->stave() == 1 ) && ( fabs( y ) < 2 ) ) || ( ( aDigit->stave() == 0 ) && ( fabs( y ) == 1.5 ) ) ) { + ++m_2d_hitmap_chips[aDigit->layer()][{ x + positionasic_thr, y + 0.25 }]; + ++m_2d_hitmap_chips[aDigit->layer()][{ x + positionasic_thr, y - 0.25 }]; + } + if ( ( aDigit->stave() == 0 ) && ( fabs( y ) < 1 ) ) { + ++m_2d_hitmap_chips[aDigit->layer()][{ x + positionasic_thr, y }]; + } + } +}; // End of class UTDigitsMonitor +DECLARE_COMPONENT( UTDigitsMonitor ) diff --git a/UT/UTMonitors/src/UTErrorMonitor.cpp b/UT/UTMonitors/src/UTErrorMonitor.cpp new file mode 100644 index 00000000000..cd315fd0c04 --- /dev/null +++ b/UT/UTMonitors/src/UTErrorMonitor.cpp @@ -0,0 +1,351 @@ +/*****************************************************************************\ +* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration * +* * +* This software is distributed under the terms of the GNU General Public * +* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". * +* * +* In applying this licence, CERN does not waive the privileges and immunities * +* granted to it by virtue of its status as an Intergovernmental Organization * +* or submit itself to any jurisdiction. * +\*****************************************************************************/ +#include "Event/UTErrorASIC.h" +#include "GaudiAlg/GaudiHistoAlg.h" +#include "Kernel/IUTReadoutTool.h" +#include "LHCbAlgs/Consumer.h" +#include "UTDAQ/UTCoordinatesMap.h" +#include "UTDet/DeUTDetector.h" +#include <Gaudi/Accumulators/Histogram.h> +#include <Gaudi/Accumulators/HistogramArray.h> +#include <Kernel/UTDAQID.h> + +using namespace LHCb; + +/** @class UTErrorMonitor UTErrorMonitor.h + * -------------------------------------------------- + * Class for monitoring UTError and UTSpecial banks + * @author Wojciech Krupa (wokrupa@cern.ch) based on code by: + * @author C. Hadjivasiliou + * @date 2024/03/20 + * -------------------------------------------------- + */ + +enum class masks { channel = 0x000001ff, lane = 0x00000e00, board = 0x000ff000 }; /// Enumeration for use in bit packing + +// Definition of axis +namespace GA = Gaudi::Accumulators; +const GA::Axis<double> AxisADC = GA::Axis<double>( 64, -32.5, 31.5, "nADC" ); //-32, 31 +const GA::Axis<double> AxisCalib = GA::Axis<double>( 256, -0.5, 256.5, "CalibStep" ); +const GA::Axis<double> AxisBCID = GA::Axis<double>( 3565, -0.5, 3564.5, "BunchID" ); +const GA::Axis<double> AxisDIGIT = GA::Axis<double>( 101, -0.5, 100.5, "UTDigits (size of digit container)" ); +const GA::Axis<double> AxisXnaturalunits = GA::Axis<double>( 36, -9, 9, "Staves (Sectors)" ); +const GA::Axis<double> AxisXnaturalunits4x = GA::Axis<double>( 144, -9, 9, "Staves (ASICs)" ); +const GA::Axis<double> AxisYnaturalunits = GA::Axis<double>( 28, -7, 7, "Modules" ); + +// Definition of histogram names +const std::array<std::string, 4> s_HistBanksNames = { "UTA_BankType_vs_TELL40_Flow0", "UTA_BankType_vs_TELL40_Flow1", + "UTC_BankType_vs_TELL40_Flow0", "UTC_BankType_vs_TELL40_Flow1" }; + +const std::array<std::string, 4> s_HistBanksNames2 = { + "UTA_BankType_vs_TELL40_Error_Flow0", "UTA_BankType_vs_TELL40_Error_Flow1", "UTC_BankType_vs_TELL40_Error_Flow0", + "UTC_BankType_vs_TELL40_Error_Flow1" }; + +// UTError Types +const std::array<std::string, 12> s_SpecialSubtypeMap = { + "UTA_BusyEvent_vs_TELL40_Flow0", "UTA_BusyEvent_vs_TELL40_Flow1", "UTC_BusyEvent_vs_TELL40_Flow0", + "UTC_BusyEvent_vs_TELL40_Flow1", "UTA_BufferFull_vs_TELL40_Flow0", "UTA_BufferFull_vs_TELL40_Flow1", + "UTC_BufferFull_vs_TELL40_Flow0", "UTC_BufferFull_vs_TELL40_Flow1", "UTA_BufferFullN_vs_TELL40_Flow0", + "UTA_BufferFullN_vs_TELL40_Flow1", "UTC_BufferFullN_vs_TELL40_Flow0", "UTC_BufferFullN_vs_TELL40_Flow1" }; + +// 2D plots +const double positionasic[4][3] = { + { -0.4375, -0.3125, -0.1875 }, // Chip 0 + { -0.1875, -0.0625, -0.0625 }, // Chip 1 + { +0.1875, +0.0625, +0.0625 }, // Chip 2 + { +0.4375, +0.3125, +0.1875 } // Chip 3 +}; +using namespace LHCb; + +template <masks m> +[[nodiscard]] static constexpr unsigned int extract( unsigned int i ) { + constexpr auto b = std::countr_zero( static_cast<unsigned int>( m ) ); + return ( i & static_cast<unsigned int>( m ) ) >> b; +} + +class UTErrorMonitor + : public LHCb::Algorithm::Consumer<void( UTErrorASICs const&, DeUTDetector const& ), + LHCb::DetDesc::usesBaseAndConditions<GaudiHistoAlg, DeUTDetector>> { + +public: + /// constructer + UTErrorMonitor( const std::string& name, ISvcLocator* svcloc ) + : Consumer{ + name, + svcloc, + { { "InputData", UTErrorASICLocation::UTErrorASICs }, { "UTLocation", DeUTDetLocation::location() } } } {} + + ToolHandle<IUTReadoutTool> readoutTool{ this, "ReadoutTool", "UTReadoutTool" }; + + // UTCoordinations map + mutable UTCoordinatesMap UTMap; + + // TELL40 vs banktype plots + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<2>, s_HistBanksNames.size()> + m_UT_Tell_40_vs_banktype{ this, + []( int i ) { return fmt::format( "{}", s_HistBanksNames[i] ); }, + []( int i ) { return fmt::format( "{}", s_HistBanksNames[i] ); }, + { 54, 0, 54 }, + { 19, 0, 19 } }; + + // TELL40 vs banktype plots + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<2>, s_HistBanksNames2.size()> + m_UT_Tell_40_vs_banktype_error{ this, + []( int i ) { return fmt::format( "{}", s_HistBanksNames2[i] ); }, + []( int i ) { return fmt::format( "{}", s_HistBanksNames2[i] ); }, + { 54, 0, 54 }, + { 3, 0, 3 } }; + + // TELL40 vs packetID (UTError) plots + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<2>, s_SpecialSubtypeMap.size()> + m_2d_packetype{ this, + []( int i ) { return fmt::format( "{}", s_SpecialSubtypeMap[i] ); }, + []( int i ) { return fmt::format( "{}", s_SpecialSubtypeMap[i] ); }, + { 54, 0, 54 }, + { 24, 0, 24 } }; + + // 2D plot for geometrical pos of UTErrorKnown + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<2>, 4> m_asics_UTError_Known{ + this, + []( int i ) { return fmt::format( "UTError_Known_Layer{}", i ); }, + []( int i ) { return fmt::format( "UTError_Known_Layer{}", i ); }, + { 144, -9, 9, "Staves (ASICs)" }, + { 28, -7, 7, "Modules" } }; + + // Error type counters + mutable GA::Histogram<1> m_nErrorsTypeCounter{ this, "ErrorsTypeCounter", "ErrorsTypeCounter", { 19, 0, 19 } }; + // Number of ASICs in error per event - subtype 19 + mutable GA::Histogram<1> m_ASICs_nErrorsType19{ + this, "Number_ASICs_Error_19", "Number of ASICs in Error - subtype 19", { 1001, -0.5, 1000.5 } }; + // Number of ASICs in error per event - subtype 20 + mutable GA::Histogram<1> m_ASICs_nErrorsType20{ + this, "Number_ASICs_Error_20", "Number of ASICs in Error - subtype 20", { 1001, -0.5, 1000.5 } }; + // Number of ASICs in error per event - subtype 21 + mutable GA::Histogram<1> m_ASICs_nErrorsType21{ + this, "Number_ASICs_Error_21", "Number of ASICs in Error - subtype 21", { 1001, -0.5, 1000.5 } }; + + /// initialize + StatusCode initialize() override { + return Consumer::initialize().andThen( [&] { + // Set the top directory to UT + if ( histoTopDir().empty() ) setHistoTopDir( "" ); + } ); + } + + /// execute + void operator()( const UTErrorASICs& errorsCont, DeUTDetector const& det ) const override { + // number of errors + unsigned int asic_inError_19 = 0; + unsigned int asic_inError_20 = 0; + unsigned int asic_inError_21 = 0; + + plot( (double)errorsCont.size(), "nErrors", -0.5, 9999.5, 10000 ); + // histos per bank type + // histos per error + for ( const auto& e : errorsCont ) { + + // Handling UTError enocded in strip 1 + if ( e->strip() % 128 == 1 && e->packetId() == 19 ) asic_inError_19++; + if ( e->strip() % 128 == 1 && e->packetId() == 20 ) asic_inError_20++; + if ( e->strip() % 128 == 1 && e->packetId() == 21 ) asic_inError_21++; + + fillBankHistograms( e ); + fillHeatMap_Error( e, det ); + } + + // Bank type counter + if ( asic_inError_19 > 1000 ) asic_inError_19 = 1000; // saturation + if ( asic_inError_20 > 1000 ) asic_inError_20 = 1000; // saturation + if ( asic_inError_21 > 1000 ) asic_inError_21 = 1000; // saturation + + ++m_ASICs_nErrorsType19[asic_inError_19]; + ++m_ASICs_nErrorsType20[asic_inError_20]; + ++m_ASICs_nErrorsType21[asic_inError_21]; + } + +private: + void fillBankHistograms( const LHCb::UTErrorASIC* aError ) const { + // Channel and source ID + auto chanID = aError->channelID(); + UTDAQID daqID = readoutTool->channelIDToDAQID( chanID ); + auto board_ID = daqID.board(); + unsigned int sourceID = UTMap.getSourceIDfromBoardNumber( board_ID ); + int y = aError->bankType(); + auto LaneID = extract<masks::lane>( aError->getdaqID() ); + int SourceID_ = sourceID / 1000; + unsigned int asic_times_lane = aError->asic() + 4 * LaneID; + + // Bank type counter + ++m_nErrorsTypeCounter[y]; + + // Sadly we (I) can't do it better. But at least its ok! + // Normal ErrorType + if ( ( aError->strip() == 0 && LaneID == 0 ) || + ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x4" && aError->strip() == 256 && LaneID == 0 ) ) { + // TELL40 vs Bank Type + if ( UTMap.getTELL40( sourceID ).find( "UA" ) != std::string::npos ) { + if ( sourceID / 1000 == 10 ) // 10346-10269 + ++m_UT_Tell_40_vs_banktype[0][{ UTMap.getTELL40Bin( sourceID ), y }]; + else if ( sourceID / 1000 == 11 ) // 11370-11293 + ++m_UT_Tell_40_vs_banktype[1][{ UTMap.getTELL40Bin( sourceID ), y }]; + } else if ( UTMap.getTELL40( sourceID ).find( "UC" ) != std::string::npos ) { + if ( sourceID / 1000 == 12 ) // 12366-12291 + ++m_UT_Tell_40_vs_banktype[2][{ UTMap.getTELL40Bin( sourceID ), y }]; + else if ( sourceID / 1000 == 13 ) // 13371-13315 + ++m_UT_Tell_40_vs_banktype[3][{ UTMap.getTELL40Bin( sourceID ), y }]; + } + } + + if ( aError->strip() % 128 == 1 && + ( aError->packetId() == 19 || aError->packetId() == 20 || aError->packetId() == 21 ) ) { + + // TELL40 vs Bank Type + if ( UTMap.getTELL40( sourceID ).find( "UA" ) != std::string::npos ) { + if ( sourceID / 1000 == 10 ) // 10346-10269 + ++m_UT_Tell_40_vs_banktype_error[0][{ UTMap.getTELL40Bin( sourceID ), aError->packetId() - 19 }]; + else if ( sourceID / 1000 == 11 ) // 11370-11293 + ++m_UT_Tell_40_vs_banktype_error[1][{ UTMap.getTELL40Bin( sourceID ), aError->packetId() - 19 }]; + } else if ( UTMap.getTELL40( sourceID ).find( "UC" ) != std::string::npos ) { + if ( sourceID / 1000 == 12 ) // 12366-12291 + ++m_UT_Tell_40_vs_banktype_error[2][{ UTMap.getTELL40Bin( sourceID ), aError->packetId() - 19 }]; + else if ( sourceID / 1000 == 13 ) // 13371-13315 + ++m_UT_Tell_40_vs_banktype_error[3][{ UTMap.getTELL40Bin( sourceID ), aError->packetId() - 19 }]; + } + + // Suberror plots + if ( UTMap.getTELL40( sourceID ).find( "UA" ) != std::string::npos ) { + if ( SourceID_ == 10 ) { + if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x4" ) { + ++m_2d_packetype[( aError->packetId() - 19 ) * 4] + [{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_4_Flow0_Bin( asic_times_lane ) }]; + } else if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x5" ) { + ++m_2d_packetype[( aError->packetId() - 19 ) * 4] + [{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_5_Flow0_Bin( asic_times_lane ) }]; + } else if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "4x3" || + UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x3" || + UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "Jx3" ) { + ++m_2d_packetype[( aError->packetId() - 19 ) * 4][{ UTMap.getTELL40Bin( sourceID ), asic_times_lane }]; + } + } else if ( SourceID_ == 11 ) { + if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x4" ) { + if ( asic_times_lane == 16 || asic_times_lane == 17 ) + ++m_2d_packetype[( aError->packetId() - 19 ) * 4] + [{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_4_Flow0_Bin( asic_times_lane ) }]; + else + ++m_2d_packetype[( aError->packetId() - 19 ) * 4 + 1] + [{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_4_Flow1_Bin( asic_times_lane ) }]; + } else if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x5" ) + ++m_2d_packetype[( aError->packetId() - 19 ) * 4 + 1] + [{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_5_Flow1_Bin( asic_times_lane ) }]; + else if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "4x3" || + UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x3" || + UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "Jx3" ) + ++m_2d_packetype[( aError->packetId() - 19 ) * 4 + 1][{ UTMap.getTELL40Bin( sourceID ), asic_times_lane }]; + } + + } else if ( UTMap.getTELL40( sourceID ).find( "UC" ) != std::string::npos ) { + if ( SourceID_ == 12 ) { + if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x4" ) { + ++m_2d_packetype[( aError->packetId() - 19 ) * 4 + 2] + [{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_4_Flow0_Bin( asic_times_lane ) }]; + } else if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x5" ) { + ++m_2d_packetype[( aError->packetId() - 19 ) * 4 + +2] + [{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_5_Flow0_Bin( asic_times_lane ) }]; + } else if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "4x3" || + UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x3" || + UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "Jx3" ) { + ++m_2d_packetype[( aError->packetId() - 19 ) * 4 + 2][{ UTMap.getTELL40Bin( sourceID ), asic_times_lane }]; + } + } + + else if ( SourceID_ == 13 ) { + if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x4" ) { + if ( asic_times_lane == 16 || asic_times_lane == 17 ) + ++m_2d_packetype[( aError->packetId() - 19 ) * 4 + 2] + [{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_4_Flow0_Bin( asic_times_lane ) }]; + else + ++m_2d_packetype[( aError->packetId() - 19 ) * 4 + 3] + [{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_4_Flow1_Bin( asic_times_lane ) }]; + } else if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x5" ) + ++m_2d_packetype[( aError->packetId() - 19 ) * 4 + 3] + [{ UTMap.getTELL40Bin( sourceID ), UTMap.get2_5_Flow1_Bin( asic_times_lane ) }]; + else if ( UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "4x3" || + UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "2x3" || + UTMap.getFlavour( UTMap.getTELL40( sourceID ) ) == "Jx3" ) + ++m_2d_packetype[( aError->packetId() - 19 ) * 4 + 3][{ UTMap.getTELL40Bin( sourceID ), asic_times_lane }]; + } + } + } + } + + void incrementHistogram( GA::Histogram<2>& histogram, double x, double y, double positionasic_one, + double positionasic_two ) const { + ++histogram[{ x + positionasic_one, y + 0.25 }]; + ++histogram[{ x + positionasic_two, y + 0.25 }]; + ++histogram[{ x + positionasic_one, y - 0.25 }]; + ++histogram[{ x + positionasic_two, y - 0.25 }]; + } + + void fillHeatMap_Error( const LHCb::UTErrorASIC* aError, DeUTDetector const& det ) const { + + // Let's find out where we are in the UT, it should be reoptimised in the future + // To be checked if it works properly! + + if ( aError->strip() % 128 == 1 ) { + std::tuple<float, float, float, float, std::string, std::string> tuple = + UTMap.getTuple( aError->module(), aError->face(), aError->stave(), aError->side(), aError->sector() ); + + float x = std::get<0>( tuple ); + float y = std::get<1>( tuple ); + std::string module_name = std::get<4>( tuple ); + std::string type = std::get<5>( tuple ); + auto chanID = aError->channelID(); + auto aSector = det.findSector( chanID ); +#ifdef USE_DD4HEP + auto trajStrip0 = aSector.createTraj( 0, 0 ); + auto trajStrip511 = aSector.createTraj( 511, 0 ); +#else + auto trajStrip0 = aSector->trajectory( chanID, 0 ); + auto trajStrip511 = aSector->trajectory( LHCb::Detector::UT::ChannelID{ chanID + 511 }, 0 ); +#endif + double stripx0 = -1 * ( trajStrip0.endPoint().x() + trajStrip0.beginPoint().x() ) * 0.5; + double stripx511 = -1 * ( trajStrip511.endPoint().x() + trajStrip511.beginPoint().x() ) * 0.5; + double stripwidth = stripx511 - stripx0; + int chip; + + if ( stripwidth > 0 ) + chip = int( aError->strip() / 128 ); + else + chip = 3 - int( aError->strip() / 128 ); + + double positionasic_one = positionasic[chip][0]; + double positionasic_two = positionasic[chip][1]; + double positionasic_thr = positionasic[chip][2]; + + // Chip is in its correct geometrical order + // Sector map // + if ( ( aError->stave() > 1 ) || ( fabs( y ) > 2 ) ) { + assert( aError->layer() >= 0 && aError->layer() <= 3 ); + incrementHistogram( m_asics_UTError_Known[aError->layer()], x, y, positionasic_one, positionasic_two ); + } + + if ( ( ( aError->stave() == 1 ) && ( fabs( y ) < 2 ) ) || ( ( aError->stave() == 0 ) && ( fabs( y ) == 1.5 ) ) ) { + ++m_asics_UTError_Known[aError->layer() == 0][{ x + positionasic_thr, y + 0.25 }]; + ++m_asics_UTError_Known[aError->layer() == 0][{ x + positionasic_thr, y - 0.25 }]; + } + if ( ( aError->stave() == 0 ) && ( fabs( y ) < 1 ) ) { + ++m_asics_UTError_Known[aError->layer()][{ x + positionasic_thr, y }]; + } + } + } +}; + +DECLARE_COMPONENT( UTErrorMonitor ) diff --git a/UT/UTMonitors/src/UTNZSMonitor.cpp b/UT/UTMonitors/src/UTNZSMonitor.cpp new file mode 100644 index 00000000000..c24ffae4793 --- /dev/null +++ b/UT/UTMonitors/src/UTNZSMonitor.cpp @@ -0,0 +1,372 @@ +/***************************************************************************** \ +* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration * +* * +* This software is distributed under the teRMS_ADC of the GNU General Public * +* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". * +* * +* In applying this licence, CERN does not waive the privileges and immunities * +* granted to it by virtue of its status as an Intergovernmental Organization * +* or submit itself to any jurisdiction. * +\*****************************************************************************/ + +#include "Event/UTDigit.h" +#include "GaudiAlg/GaudiHistoAlg.h" +#include "Kernel/IUTReadoutTool.h" +#include "Kernel/UTDAQBoard.h" +#include "Kernel/UTDAQDefinitions.h" +#include "Kernel/UTDAQID.h" +#include "LHCbAlgs/Consumer.h" +#include "LHCbAlgs/Transformer.h" +#include "UTDAQ/UTCoordinatesMap.h" +#include "UTDAQ/UTDAQHelper.h" +#include "UTDAQ/UTInfo.h" +#include "UTDet/DeUTDetector.h" +#include <Event/ODIN.h> +#include <Event/RawBank.h> +#include <Event/RawEvent.h> +#include <Gaudi/Accumulators/Histogram.h> +#include <Gaudi/Accumulators/HistogramArray.h> +#include <Kernel/IUTReadoutTool.h> +#include <algorithm> +#include <mutex> +#include <optional> +#include <string> + +/** @class UTNZSMonitor UTNZSMonitor.cpp + * -------------------------------------------------- + * Class for monitoring UTNZS banks + * @author Wojciech Krupa (wokrupa@cern.ch): + * @date 2024/02/10 + * -------------------------------------------------- + */ +using namespace LHCb; +namespace GA = Gaudi::Accumulators; + +// Definition of axis +const GA::Axis<double> AxisADC = GA::Axis<double>( 64, -32.5, 31.5, "nADC" ); //-32, 31 +const GA::Axis<double> AxisCalib = GA::Axis<double>( 257, -0.5, 256.5, "CalibStep" ); +const GA::Axis<double> AxisBCID = GA::Axis<double>( 3565, -0.5, 3564.5, "BunchID" ); +const GA::Axis<double> AxisDIGIT = GA::Axis<double>( 101, -0.5, 100.5, "UTDigits (size of digit container)" ); +const GA::Axis<double> AxisXnaturalunits = GA::Axis<double>( 36, -9, 9, "Staves (Sectors)" ); +const GA::Axis<double> AxisXnaturalunits4x = GA::Axis<double>( 144, -9, 9, "Staves (ASICs)" ); +const GA::Axis<double> AxisYnaturalunits = GA::Axis<double>( 28, -7, 7, "Modules" ); +const GA::Axis<double> AxisModule = GA::Axis<double>( 512, 0, 512, "Strips" ); + +enum class masks { channel = 0x000001ff, lane = 0x00000e00, board = 0x000ff000 }; + +const std::array<std::string, 4> s_HistNames = { "UTA_Tell_40_vs_ASIC_Flow0", "UTA_Tell_40_vs_ASIC_Flow1", + "UTC_Tell_40_vs_ASIC_Flow0", "UTC_Tell_40_vs_ASIC_Flow1" }; + +const std::array<std::string, 4> s_HistBanksNames = { "UTA_BankType_vs_TELL40_Flow0", "UTA_BankType_vs_TELL40_Flow1", + "UTC_BankType_vs_TELL40_Flow0", "UTC_BankType_vs_TELL40_Flow1" }; + +// UT layers +const std::array<std::string, 4> UT_layers = { "UTaX", "UTaU", "UTbV", "UTbX" }; + +// 2D plots +const double positionasic[4][3] = { + { -0.4375, -0.3125, -0.1875 }, // Chip 0 + { -0.1875, -0.0625, -0.0625 }, // Chip 1 + { +0.1875, +0.0625, +0.0625 }, // Chip 2 + { +0.4375, +0.3125, +0.1875 } // Chip 3 +}; + +template <masks m> +[[nodiscard]] static constexpr unsigned int extract( unsigned int i ) { + constexpr auto b = std::countr_zero( static_cast<unsigned int>( m ) ); + return ( i & static_cast<unsigned int>( m ) ) >> b; +} + +// Tools for booking histograms +namespace Utility { + template <typename T, typename OWNER> + void map_emplace( T& t, typename T::key_type key, OWNER* owner, std::string const& title, + Gaudi::Accumulators::Axis<typename T::mapped_type::AxisArithmeticType> axis1 ) { + t.emplace( std::piecewise_construct, std::forward_as_tuple( key ), + std::forward_as_tuple( owner, key, title, axis1 ) ); + } + template <typename T, typename OWNER> + void map_emplace( T& t, typename T::key_type key, OWNER* owner, std::string const& title, + Gaudi::Accumulators::Axis<typename T::mapped_type::AxisArithmeticType> axis1, + Gaudi::Accumulators::Axis<typename T::mapped_type::AxisArithmeticType> axis2 ) { + t.emplace( std::piecewise_construct, std::forward_as_tuple( key ), + std::forward_as_tuple( owner, key, title, axis1, axis2 ) ); + } + +} // namespace Utility + +/** ------------------------------------------------------------------------------------------------------------------------ */ +class UTNZSMonitor + : public LHCb::Algorithm::Consumer<void( UTDigits const&, UTDigits const&, DeUTDetector const&, LHCb::ODIN const& ), + LHCb::DetDesc::usesBaseAndConditions<GaudiHistoAlg, DeUTDetector>> { +public: + UTNZSMonitor( const std::string& name, ISvcLocator* svcloc ) + : Consumer{ name, + svcloc, + { { "InputData", UTDigitLocation::UTDigits }, + { "InputErrData", UTDigitLocation::UTDigits }, + { "UTLocation", DeUTDetLocation::location() }, + { "ODINLocation", LHCb::ODINLocation::Default } } } {} + ToolHandle<IUTReadoutTool> readoutTool{ this, "ReadoutTool", "UTReadoutTool" }; + + StatusCode initialize() override; + void operator()( const UTDigits&, const UTDigits&, DeUTDetector const&, LHCb::ODIN const& ) const override; + void fillADC( const LHCb::UTDigit*, LHCb::ODIN const& ) const; + void fillFlow( const LHCb::UTDigit* ) const; + void incrementHistogram( GA::ProfileHistogram<2>&, double, double, double, double, float ) const; + void fillHeatMap_naturalunits( const LHCb::UTDigit*, DeUTDetector const& ) const; + +private: + mutable UTCoordinatesMap UTMap; + + // TELL40 plots + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::Histogram<2>, s_HistNames.size()> + m_UT_Tell_40_vs_asic{ this, + []( int i ) { return fmt::format( "{}", s_HistNames[i] ); }, + []( int i ) { return fmt::format( "{}", s_HistNames[i] ); }, + { 54, 0, 54 }, + { 24, 0, 24 } }; + + // The container for Mean_ADC per channel + mutable std::map<std::string, GA::ProfileHistogram<1>> m_2d_Mean_ADCCounter; + mutable std::map<std::string, GA::ProfileHistogram<1>> m_2d_RMS_ADCCounter; + mutable std::map<std::string, GA::Histogram<2>> m_2d_ADCCounter; + + // 2D plots with MCMS value per chip + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::ProfileHistogram<2>, 4> m_UT_mcm_strip{ + this, + []( int i ) { return fmt::format( "MCM_strip_Layer{}", i ); }, + []( int i ) { return fmt::format( "MCM_strip_Layer{} (ASICs)", i ); }, + { 144, -9, 9, "Staves (ASICs)" }, + { 28, -7, 7, "Modules" } }; + + // 2D plots with MCMS strip per chip + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::ProfileHistogram<2>, 4> m_UT_mcm_mu{ + this, + []( int i ) { return fmt::format( "MCM_mu_Layer{}", i ); }, + []( int i ) { return fmt::format( "MCM_mu_Layer{} (ASICs)", i ); }, + { 144, -9, 9, "Staves (ASICs)" }, + { 28, -7, 7, "Modules" } }; + + // 2D plots with MCMS strip per chip + mutable Gaudi::Accumulators::HistogramArray<Gaudi::Accumulators::ProfileHistogram<2>, 4> m_UT_MCM_rms_ADC{ + this, + []( int i ) { return fmt::format( "MCM_rms_Layer{}", i ); }, + []( int i ) { return fmt::format( "MCM_rms_Layer{} (ASICs)", i ); }, + { 144, -9, 9, "Staves (ASICs)" }, + { 28, -7, 7, "Modules" } }; + + // 1D plots: ADC + mutable GA::Histogram<2> m_nADCvsBCID{ this, "ADCvsBuncId", "ADC vs BuncId", AxisBCID, AxisADC }; + mutable GA::Histogram<2> m_nADCvsCalibStep{ this, "ADCvsCalibStep", "ADC vs CalibStep", AxisCalib, AxisADC }; + + mutable std::map<std::string, Gaudi::Accumulators::SigmaCounter<>> RawADC; + mutable std::map<std::string, Gaudi::Accumulators::SigmaCounter<>> mcm; + +}; // End of class UTNZSMonitor +DECLARE_COMPONENT( UTNZSMonitor ) + +StatusCode UTNZSMonitor::initialize() { + return Consumer::initialize().andThen( [&] { + // Set the top directory to UT + if ( histoTopDir().empty() ) setHistoTopDir( "" ); + + for ( const auto& module : UTMap.getModulesNames() ) { + Utility::map_emplace( m_2d_Mean_ADCCounter, "Mean_ADC_" + module, this, "Mean_ADC_" + module, { 512, 0, 512 } ); + Utility::map_emplace( m_2d_RMS_ADCCounter, "RMS_ADC_" + module, this, "RMS_ADC_" + module, { 512, 0, 512 } ); + Utility::map_emplace( m_2d_ADCCounter, "ADC_" + module, this, "ADC_" + module, { 512, 0, 512 }, + { 64, -32.5, 31.5 } ); + } + } ); +} + +void UTNZSMonitor::operator()( const UTDigits& digitsCont, const UTDigits& errdigitsCont, DeUTDetector const& det, + LHCb::ODIN const& odin ) const { + + // General counters + // ------------------------------------------------------- + // Loop on digits + // side==1 is Aside (left), side==0 is Cside (right) + // ------------------------------------------------------- + for ( const UTDigit* d : digitsCont ) { + fillFlow( d ); + fillADC( d, odin ); + fillHeatMap_naturalunits( d, det ); + } + + for ( const UTDigit* d : errdigitsCont ) { + fillFlow( d ); + fillADC( d, odin ); + fillHeatMap_naturalunits( d, det ); + } + // ------------------------------------------------------- + // end loop on digits + // ------------------------------------------------------- +} // end execute + +void UTNZSMonitor::fillADC( const LHCb::UTDigit* aDigit, LHCb::ODIN const& odin ) const { + + // Summary plots + ++m_nADCvsBCID[{ odin.bunchId(), aDigit->depositedCharge() }]; + ++m_nADCvsCalibStep[{ odin.calibrationStep(), aDigit->depositedCharge() }]; + + // ADC counter + auto tuple = UTMap.getTuple( aDigit->module(), aDigit->face(), aDigit->stave(), aDigit->side(), aDigit->sector() ); + std::string module_name = std::get<4>( tuple ); + + RawADC[UT_layers[aDigit->layer()] + "_" + module_name + "_" + std::to_string( aDigit->strip() )] += + aDigit->depositedCharge(); + + m_2d_Mean_ADCCounter.at( "Mean_ADC_" + UT_layers[aDigit->layer()] + "_" + module_name )[aDigit->strip()] += + RawADC[UT_layers[aDigit->layer()] + "_" + module_name + "_" + std::to_string( aDigit->strip() )].mean(); + m_2d_RMS_ADCCounter.at( "RMS_ADC_" + UT_layers[aDigit->layer()] + "_" + module_name )[aDigit->strip()] += + RawADC[UT_layers[aDigit->layer()] + "_" + module_name + "_" + std::to_string( aDigit->strip() )] + .standard_deviation(); + ++m_2d_ADCCounter.at( "ADC_" + UT_layers[aDigit->layer()] + "_" + + module_name )[{ aDigit->strip(), aDigit->depositedCharge() }]; +} + +void UTNZSMonitor::fillFlow( const LHCb::UTDigit* aDigit ) const { + Detector::UT::ChannelID channelID = aDigit->channelID(); + UTDAQID daqID = readoutTool->channelIDToDAQID( channelID ); + unsigned int board_ID = daqID.board(); + unsigned int sourceID = UTMap.getSourceIDfromBoardNumber( board_ID ); + int SourceID_ = sourceID / 1000; + + unsigned int asic_times_lane = aDigit->asic() % 4 + 4 * extract<masks::lane>( aDigit->getdaqID() ); + + // Get TELL40 and Flavour only once + std::string tell40 = UTMap.getTELL40( sourceID ); + std::string flavour = UTMap.getFlavour( tell40 ); + int tell40Bin = UTMap.getTELL40Bin( sourceID ); + + // Check if the strip is aligned for filling + if ( aDigit->strip() % 128 == 0 ) { + if ( tell40.find( "UA" ) != std::string::npos ) { + // Handle UA sourceID_ == 10 and 11 + if ( SourceID_ == 10 ) { + if ( flavour == "2x4" ) { + ++m_UT_Tell_40_vs_asic[0][{ tell40Bin, UTMap.get2_4_Flow0_Bin( asic_times_lane ) }]; + } else if ( flavour == "2x5" ) { + ++m_UT_Tell_40_vs_asic[0][{ tell40Bin, UTMap.get2_5_Flow0_Bin( asic_times_lane ) }]; + } else if ( flavour == "4x3" || flavour == "2x3" || flavour == "Jx3" ) { + ++m_UT_Tell_40_vs_asic[0][{ tell40Bin, asic_times_lane }]; + } + } else if ( SourceID_ == 11 ) { + if ( flavour == "2x4" ) { + if ( asic_times_lane == 16 || asic_times_lane == 17 ) { + ++m_UT_Tell_40_vs_asic[0][{ tell40Bin, UTMap.get2_4_Flow0_Bin( asic_times_lane ) }]; + } else { + ++m_UT_Tell_40_vs_asic[1][{ tell40Bin, UTMap.get2_4_Flow1_Bin( asic_times_lane ) }]; + } + } else if ( flavour == "2x5" ) { + ++m_UT_Tell_40_vs_asic[1][{ tell40Bin, UTMap.get2_5_Flow1_Bin( asic_times_lane ) }]; + } else if ( flavour == "4x3" || flavour == "2x3" || flavour == "Jx3" ) { + ++m_UT_Tell_40_vs_asic[1][{ tell40Bin, asic_times_lane }]; + } + } + } else if ( tell40.find( "UC" ) != std::string::npos ) { + // Handle UC sourceID_ == 12 and 13 + if ( SourceID_ == 12 ) { + if ( flavour == "2x4" ) { + ++m_UT_Tell_40_vs_asic[2][{ tell40Bin, UTMap.get2_4_Flow0_Bin( asic_times_lane ) }]; + } else if ( flavour == "2x5" ) { + ++m_UT_Tell_40_vs_asic[2][{ tell40Bin, UTMap.get2_5_Flow0_Bin( asic_times_lane ) }]; + } else if ( flavour == "4x3" || flavour == "2x3" || flavour == "Jx3" ) { + ++m_UT_Tell_40_vs_asic[2][{ tell40Bin, asic_times_lane }]; + } + } else if ( SourceID_ == 13 ) { + if ( flavour == "2x4" ) { + if ( asic_times_lane == 16 || asic_times_lane == 17 ) { + ++m_UT_Tell_40_vs_asic[2][{ tell40Bin, UTMap.get2_4_Flow0_Bin( asic_times_lane ) }]; + } else { + ++m_UT_Tell_40_vs_asic[3][{ tell40Bin, UTMap.get2_4_Flow1_Bin( asic_times_lane ) }]; + } + } else if ( flavour == "2x5" ) { + ++m_UT_Tell_40_vs_asic[3][{ tell40Bin, UTMap.get2_5_Flow1_Bin( asic_times_lane ) }]; + } else if ( flavour == "4x3" || flavour == "2x3" || flavour == "Jx3" ) { + ++m_UT_Tell_40_vs_asic[3][{ tell40Bin, asic_times_lane }]; + } + } + } + } +} + +void UTNZSMonitor::incrementHistogram( GA::ProfileHistogram<2>& histogram, double x, double y, double positionasic_one, + double positionasic_two, float val ) const { + + histogram[{ x + positionasic_one, y + 0.25 }] += val; + histogram[{ x + positionasic_two, y + 0.25 }] += val; + histogram[{ x + positionasic_one, y - 0.25 }] += val; + histogram[{ x + positionasic_two, y - 0.25 }] += val; +} + +void UTNZSMonitor::fillHeatMap_naturalunits( const LHCb::UTDigit* aDigit, DeUTDetector const& det ) const { + + if ( aDigit->strip() % 128 == 0 ) { + + std::tuple<float, float, float, float, std::string, std::string> tuple = + UTMap.getTuple( aDigit->module(), aDigit->face(), aDigit->stave(), aDigit->side(), aDigit->sector() ); + + // Let's find out where we are + float x = std::get<0>( tuple ); + float y = std::get<1>( tuple ); + std::string module_name = std::get<4>( tuple ); + std::string type = std::get<5>( tuple ); + auto chanID = aDigit->channelID(); + auto aSector = det.findSector( chanID ); +#ifdef USE_DD4HEP + auto trajStrip0 = aSector.createTraj( 0, 0 ); + auto trajStrip511 = aSector.createTraj( 511, 0 ); +#else + auto trajStrip0 = aSector->trajectory( chanID, 0 ); + auto trajStrip511 = aSector->trajectory( LHCb::Detector::UT::ChannelID{ chanID + 511 }, 0 ); +#endif + double stripx0 = -1 * ( trajStrip0.endPoint().x() + trajStrip0.beginPoint().x() ) * 0.5; + double stripx511 = -1 * ( trajStrip511.endPoint().x() + trajStrip511.beginPoint().x() ) * 0.5; + double stripwidth = stripx511 - stripx0; + int chip; + + if ( stripwidth > 0 ) + chip = int( aDigit->strip() / 128 ); + else + chip = 3 - int( aDigit->strip() / 128 ); + + double positionasic_one = positionasic[chip][0]; + double positionasic_two = positionasic[chip][1]; + double positionasic_thr = positionasic[chip][2]; + + float mcm_val = aDigit->mcmVal() + 0.0001; // protection against 0 value in bin which caused problem in displaying + // histogram sometimes even bigger statistic the average is 0. Monet + // interpret it as empty bin what is not true. won't process more + // than O(4) NMZS events per run so it wont be a problem + + mcm[UT_layers[aDigit->layer()] + "_" + module_name + "_" + std::to_string( chip )] += mcm_val; + float mcm_mu = mcm[UT_layers[aDigit->layer()] + "_" + module_name + "_" + std::to_string( chip )].mean() + 0.0001; + float MCM_rms_ADC = + mcm[UT_layers[aDigit->layer()] + "_" + module_name + "_" + std::to_string( chip )].standard_deviation() + 0.001; + + // Sector map // + if ( ( aDigit->stave() > 1 ) || ( fabs( y ) > 2 ) ) { + incrementHistogram( m_UT_mcm_strip[aDigit->layer()], x, y, positionasic_one, positionasic_two, + aDigit->mcmStrip() ); + incrementHistogram( m_UT_mcm_mu[aDigit->layer()], x, y, positionasic_one, positionasic_two, mcm_mu ); + incrementHistogram( m_UT_MCM_rms_ADC[aDigit->layer()], x, y, positionasic_one, positionasic_two, MCM_rms_ADC ); + } + + if ( ( ( aDigit->stave() == 1 ) && ( fabs( y ) < 2 ) ) || ( ( aDigit->stave() == 0 ) && ( fabs( y ) == 1.5 ) ) ) { + m_UT_mcm_strip[aDigit->layer()][{ x + positionasic_thr, y + 0.25 }] += aDigit->mcmStrip(); + m_UT_mcm_strip[aDigit->layer()][{ x + positionasic_thr, y - 0.25 }] += aDigit->mcmStrip(); + m_UT_mcm_mu[aDigit->layer()][{ x + positionasic_thr, y + 0.25 }] += mcm_mu; + m_UT_mcm_mu[aDigit->layer()][{ x + positionasic_thr, y - 0.25 }] += mcm_mu; + m_UT_MCM_rms_ADC[aDigit->layer()][{ x + positionasic_thr, y + 0.25 }] += MCM_rms_ADC; + m_UT_MCM_rms_ADC[aDigit->layer()][{ x + positionasic_thr, y - 0.25 }] += MCM_rms_ADC; + } + + if ( ( aDigit->stave() == 0 ) && ( fabs( y ) < 1 ) ) { + { m_UT_mcm_strip[aDigit->layer()][{ x + positionasic_thr, y }] += aDigit->mcmStrip(); } + { m_UT_mcm_mu[aDigit->layer()][{ x + positionasic_thr, y }] += mcm_mu; } + { m_UT_MCM_rms_ADC[aDigit->layer()][{ x + positionasic_thr, y }] += MCM_rms_ADC; } + } + } +} diff --git a/UT/UTMonitors/src/UTSuperTAEMonitor.cpp b/UT/UTMonitors/src/UTSuperTAEMonitor.cpp new file mode 100644 index 00000000000..b22c76ed5fc --- /dev/null +++ b/UT/UTMonitors/src/UTSuperTAEMonitor.cpp @@ -0,0 +1,179 @@ +/*****************************************************************************\ +* (c) Copyright 2020 CERN for the benefit of the LHCb Collaboration * +* * +* This software is distributed under the terms of the GNU General Public * +* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". * +* * +* In applying this licence, CERN does not waive the privileges and immunities * +* granted to it by virtue of its status as an Intergovernmental Organization * +* or submit itself to any jurisdiction. * +\*****************************************************************************/ + +#include "Event/ODIN.h" +#include "Event/TAEUtils.h" +#include "Event/UTDigit.h" +#include "Gaudi/Accumulators/Histogram.h" +#include "GaudiAlg/GaudiHistoAlg.h" +#include "GaudiKernel/GaudiException.h" +#include "GaudiKernel/PhysicalConstants.h" +#include "GaudiKernel/SystemOfUnits.h" +#include "Kernel/IUTReadoutTool.h" +#include "Kernel/STLExtensions.h" +#include "Kernel/UTDAQID.h" +#include "LHCbAlgs/Consumer.h" +#include "LHCbAlgs/MergingTransformer.h" +#include "UTDAQ/UTCoordinatesMap.h" +#include "UTDet/DeUTDetector.h" + +/** @class UTSuperTAEMonitor UTSuperTAEMonitor.cpp + * -------------------------------------------------- + * Counters for additional monitoring of UT (UT in global) + * The algorithm produces several useful histograms + * @author Wojciech Krupa + * @date 2024/10/07 + * -------------------------------------------------- + **/ + +using ODIN = LHCb::ODIN; +using ODINVector = Gaudi::Functional::vector_of_const_<ODIN const*>; +using InputVector = Gaudi::Functional::vector_of_const_<LHCb::UTDigits const*>; +using BXTypes = LHCb::ODIN::BXTypes; +using EventTypes = LHCb::ODIN::EventTypes; +using namespace LHCb; +namespace GA = Gaudi::Accumulators; + +// Tools for booking histograms +namespace Utility { + template <typename T, typename OWNER> + void map_emplace( T& t, typename T::key_type key, OWNER* owner, std::string const& title, + Gaudi::Accumulators::Axis<typename T::mapped_type::AxisArithmeticType> axis1, + Gaudi::Accumulators::Axis<typename T::mapped_type::AxisArithmeticType> axis2 ) { + t.emplace( std::piecewise_construct, std::forward_as_tuple( key ), + std::forward_as_tuple( owner, key, title, axis1, axis2 ) ); + } +} // namespace Utility + +class UTSuperTAEMonitor final : public LHCb::Algorithm::MergingConsumer<void( ODINVector const&, InputVector const& )> { + +public: + UTSuperTAEMonitor( const std::string&, ISvcLocator* ); + StatusCode initialize() override; + void operator()( ODINVector const&, InputVector const& ) const override; + void fillHistograms( const LHCb::UTDigit*, LHCb::ODIN const&, int ) const; + +private: + LHCb::TAE::Handler m_taeHandler{ this }; + mutable UTCoordinatesMap UTMap; + Gaudi::Property<signed int> m_HalfWindow{ this, "HalfWindow", 3 }; + + using Histogram1D = GA::Histogram<1, GA::atomicity::full, float>; + using Histogram2D = GA::Histogram<2, GA::atomicity::full, float>; + using ProfileHistogram = GA::ProfileHistogram<1, GA::atomicity::full, float>; + using ProfileHistogram2D = GA::ProfileHistogram<2, GA::atomicity::full, float>; + using Axis = GA::Axis<float>; + + // Definition of axis + const GA::Axis<double> AxisADC = GA::Axis<double>( 64, -32.5, 31.5, "nADC" ); //-32-31 + const GA::Axis<double> AxisADC_signed = GA::Axis<double>( 32, -0.5, 31.5, "nADC" ); // 0-31 + const GA::Axis<double> AxisBCID = GA::Axis<double>( 3565, -0.5, 3564.5, "BunchID" ); // + const GA::Axis<double> AxisDIGIT = GA::Axis<double>( 101, -0.5, 100.5, "UTDigits (size of digit container)" ); + const GA::Axis<double> AxisTAE = + GA::Axis<double>( 2 * m_HalfWindow + 1, -1 * m_HalfWindow - 0.5, m_HalfWindow + 0.5, "TAE index" ); + + const std::array<std::string, 4> UT_layers = { "UTaX", "UTaU", "UTbV", "UTbX" }; + + // General TAE counters + mutable Gaudi::Accumulators::Histogram<1> m_bxtype{ this, "BXType", "BXType", { 4, -0.5, 3.5 } }; + mutable Gaudi::Accumulators::Histogram<1> m_trgtype{ this, "TrgType", "TrgType", { 16, -0.5, 15.5 } }; + mutable Gaudi::Accumulators::Histogram<2> m_bcid_bxtype{ + this, "BXTypeVsBXID", "BXTypeVsBXID", AxisBCID, { 4, -0.5, 3.5 } }; + mutable Gaudi::Accumulators::Histogram<2> m_bcid_trgtype{ + this, "TrgTypeVsBXID", "TrgTypeVsBXID", AxisBCID, { 16, -0.5, 15.5 } }; + mutable Gaudi::Accumulators::WeightedHistogram<2> m_bcid_taesummary{ + this, "TAESummary", "TAE summary", AxisBCID, { 14, -0.5, -0.5 + 14 } }; + mutable Gaudi::Accumulators::Histogram<2> m_bcid_taeindex{ + this, "TAEIndex", "TAE index", AxisBCID, { 64, -0.5, -0.5 + 64 } }; + + // Counters TAE step vs ADC per DCB or per quadrant or UT + mutable std::map<std::string, GA::Histogram<2>> m_2d_DCB_tae_adc; + mutable std::map<std::string, GA::Histogram<2>> m_2d_DCBQuadrant_tae_adc; + mutable Gaudi::Accumulators::Histogram<2> m_2d_UT_tae_adc{ this, "UTTAE", "UTTAE", AxisTAE, AxisADC_signed }; +}; + +// Declaration of the Algorithm Factory +DECLARE_COMPONENT( UTSuperTAEMonitor ) + +UTSuperTAEMonitor::UTSuperTAEMonitor( const std::string& name, ISvcLocator* pSvcLocator ) + : LHCb::Algorithm::MergingConsumer<void( ODINVector const&, InputVector const& )>( + name, pSvcLocator, { KeyValues{ "ODINVector", {} }, KeyValues{ "InputVector", {} } } ){}; + +StatusCode UTSuperTAEMonitor::initialize() { + return base_class::initialize().andThen( [&] { + // Set the top directory to UT + // Initialise counters + for ( const auto& DCB : UTMap.getDCBsAside() ) { + Utility::map_emplace( m_2d_DCB_tae_adc, DCB, this, DCB, AxisTAE, AxisADC_signed ); + } + for ( const auto& DCB : UTMap.getDCBsCside() ) { + Utility::map_emplace( m_2d_DCB_tae_adc, DCB, this, DCB, AxisTAE, AxisADC_signed ); + } + for ( const auto& DCBQuadrant : UTMap.getDCBQuadrants() ) { + Utility::map_emplace( m_2d_DCBQuadrant_tae_adc, DCBQuadrant, this, DCBQuadrant, AxisTAE, AxisADC_signed ); + } + } ); +} + +void UTSuperTAEMonitor::operator()( ODINVector const& odinVector, InputVector const& inputVector ) const { + + auto taeEvents = m_taeHandler.arrangeTAE( odinVector, inputVector, 3 ); + + if ( taeEvents.empty() ) { return; } + + for ( auto it = taeEvents.begin(); it != taeEvents.end(); ++it ) { + int offset = it->first; // 0 is central, negative for Prev, positive for Next + const LHCb::ODIN& odin = it->second.first; + const LHCb::UTDigits& digitsCont = it->second.second; + + for ( auto d_it = digitsCont.begin(); d_it != digitsCont.end(); ++d_it ) { fillHistograms( *d_it, odin, offset ); } + } +} + +void UTSuperTAEMonitor::fillHistograms( const LHCb::UTDigit* aDigit, LHCb::ODIN const& odin, int offset ) const { + + // Let's find where we are in UT + auto tuple = UTMap.getTuple( aDigit->module(), aDigit->face(), aDigit->stave(), aDigit->side(), aDigit->sector() ); + std::string module_name = std::get<4>( tuple ); + auto y_p = std::get<1>( tuple ); + std::string position = ( y_p > 0 ) ? "T" : "B"; + std::string side = ( aDigit->side() == 0 ) ? "C" : "A"; + std::array<std::string, 4> layer = { "UTaX", "UTaU", "UTbV", "UTbX" }; + std::string station = ( aDigit->layer() < 2 ) ? "a" : "b"; + std::string dcb_name = UTMap.getDCB( layer[aDigit->layer()] + "_" + module_name ); + int TAEindex = offset; // + + // Let's find where we are in the LHCb + auto bcid = odin.bunchId(); + auto bx = static_cast<uint8_t>( odin.bunchCrossingType() ); + auto trgtype = odin.triggerType(); + + // simple counters + ++m_bxtype[bx]; + ++m_trgtype[trgtype]; + ++m_bcid_bxtype[{ bcid, bx }]; + ++m_bcid_trgtype[{ bcid, trgtype }]; + + // summary plots this should be replaced by odin.eventType soon as below + double weight = 1; + int offset2 = 0; + m_bcid_taesummary[{ bcid, offset2 + bx }] += weight; + offset2 += 4; + m_bcid_taesummary[{ bcid, offset2++ }] += weight * odin.isTAE(); + m_bcid_taesummary[{ bcid, offset2++ }] += weight * odin.timeAlignmentEventCentral(); + m_bcid_taesummary[{ bcid, offset2++ }] += weight * odin.timeAlignmentEventFirst(); + + ++m_bcid_taeindex[{ bcid, odin.timeAlignmentEventIndex() }]; + ++m_2d_UT_tae_adc[{ TAEindex, aDigit->depositedCharge() }]; + ++m_2d_DCB_tae_adc.at( dcb_name )[{ TAEindex, aDigit->depositedCharge() }]; + ++m_2d_DCBQuadrant_tae_adc.at( + UTMap.getDCBQuadrant( layer[aDigit->layer()] + "_" + module_name ) )[{ TAEindex, aDigit->depositedCharge() }]; +}; diff --git a/UT/UTMonitors/src/UTTAEMonitor.cpp b/UT/UTMonitors/src/UTTAEMonitor.cpp new file mode 100644 index 00000000000..8d64c8f747f --- /dev/null +++ b/UT/UTMonitors/src/UTTAEMonitor.cpp @@ -0,0 +1,165 @@ +/*****************************************************************************\ +* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration * +* * +* This software is distributed under the terms of the GNU General Public * +* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". * +* * +* In applying this licence, CERN does not waive the privileges and immunities * +* granted to it by virtue of its status as an Intergovernmental Organization * +* or submit itself to any jurisdiction. * +\*****************************************************************************/ + +#include "Event/ODIN.h" +#include "Event/UTDigit.h" +#include "Gaudi/Accumulators/Histogram.h" +#include "GaudiAlg/GaudiHistoAlg.h" +#include "Kernel/IUTReadoutTool.h" +#include "Kernel/STLExtensions.h" +#include "Kernel/UTDAQID.h" +#include "LHCbAlgs/Consumer.h" +#include "UTDAQ/UTCoordinatesMap.h" + +/** @class UTTAEMonitor UTTAEMonitor.h + * -------------------------------------------------- + * Class for monitoring TAE in Monet (UT in local) + * @author W. Krupa + * @author C. Hadjivasiliou + * @date 2024/03/19 + * -------------------------------------------------- + **/ + +namespace GA = Gaudi::Accumulators; +using namespace LHCb; +using EventTypes = LHCb::ODIN::EventTypes; + +// Tools for booking histograms +namespace Utility { + template <typename T, typename OWNER> + void map_emplace( T& t, typename T::key_type key, OWNER* owner, std::string const& title, + Gaudi::Accumulators::Axis<typename T::mapped_type::AxisArithmeticType> axis1, + Gaudi::Accumulators::Axis<typename T::mapped_type::AxisArithmeticType> axis2 ) { + t.emplace( std::piecewise_construct, std::forward_as_tuple( key ), + std::forward_as_tuple( owner, key, title, axis1, axis2 ) ); + } +} // namespace Utility + +const std::array<std::string, 4> UT_layers = { "UTaX", "UTaU", "UTbV", "UTbX" }; + +class UTTAEMonitor : public LHCb::Algorithm::Consumer<void( UTDigits const&, UTDigits const&, LHCb::ODIN const& ), + LHCb::DetDesc::usesBaseAndConditions<GaudiHistoAlg>> { + +public: + UTTAEMonitor( const std::string&, ISvcLocator* ); + StatusCode initialize() override; + void operator()( const UTDigits&, const UTDigits&, LHCb::ODIN const& ) const override; + void fillHistograms( const LHCb::UTDigit*, LHCb::ODIN const& ) const; + + ToolHandle<IUTReadoutTool> readoutTool{ this, "ReadoutTool", "UTReadoutTool" }; + mutable UTCoordinatesMap UTMap; + Gaudi::Property<signed int> m_HalfWindow{ this, "HalfWindow", 3 }; + + // Definition of axis + const GA::Axis<double> AxisADC = GA::Axis<double>( 64, -32.5, 31.5, "nADC" ); //-32-31 + const GA::Axis<double> AxisADC_signed = GA::Axis<double>( 32, -0.5, 31.5, "nADC" ); // 0-31 + const GA::Axis<double> AxisBCID = GA::Axis<double>( 3565, -0.5, 3564.5, "BunchID" ); // + const GA::Axis<double> AxisDIGIT = GA::Axis<double>( 101, -0.5, 100.5, "UTDigits (size of digit container)" ); + const GA::Axis<double> AxisTAE = GA::Axis<double>( 2 * m_HalfWindow + 1, -1 * m_HalfWindow - 0.5, m_HalfWindow + 0.5, + "TAE index" ); // for windows 3 - central is 4 +private: + // General counters + mutable Gaudi::Accumulators::Histogram<1> m_bxtype{ this, "BXType", "BXType", { 4, -0.5, 3.5 } }; + mutable Gaudi::Accumulators::Histogram<1> m_trgtype{ this, "TrgType", "TrgType", { 16, -0.5, 15.5 } }; + mutable Gaudi::Accumulators::Histogram<2> m_bcid_bxtype{ + this, "BXTypeVsBXID", "BXTypeVsBXID", AxisBCID, { 4, -0.5, 3.5 } }; + mutable Gaudi::Accumulators::Histogram<2> m_bcid_trgtype{ + this, "TrgTypeVsBXID", "TrgTypeVsBXID", AxisBCID, { 16, -0.5, 15.5 } }; + mutable Gaudi::Accumulators::WeightedHistogram<2> m_bcid_taesummary{ + this, "TAESummary", "TAE summary", AxisBCID, { 14, -0.5, -0.5 + 14 } }; + mutable Gaudi::Accumulators::Histogram<2> m_bcid_taeindex{ + this, "TAEIndex", "TAE index", AxisBCID, { 64, -0.5, -0.5 + 64 } }; + + // Counters TAE step vs ADC per DCB or per quadrant or UT + mutable std::map<std::string, GA::Histogram<2>> m_2d_DCB_tae_adc; + mutable std::map<std::string, GA::Histogram<2>> m_2d_DCBQuadrant_tae_adc; + mutable Gaudi::Accumulators::Histogram<2> m_2d_UT_tae_adc{ this, "UTTAE", "UTTAE", AxisTAE, AxisADC_signed }; +}; +DECLARE_COMPONENT( UTTAEMonitor ) + +UTTAEMonitor::UTTAEMonitor( const std::string& name, ISvcLocator* svcloc ) + : Consumer{ name, + svcloc, + { { "InputData", UTDigitLocation::UTDigits }, + { "InputErrorData", UTDigitLocation::UTDigits }, + { "ODINLocation", LHCb::ODINLocation::Default } } } {} + +StatusCode UTTAEMonitor::initialize() { + return Consumer::initialize().andThen( [&] { + // Set the top directory to UT + if ( histoTopDir().empty() ) setHistoTopDir( "UT/" ); + for ( const auto& DCB : UTMap.getDCBsAside() ) { + Utility::map_emplace( m_2d_DCB_tae_adc, DCB, this, DCB, AxisTAE, AxisADC_signed ); + } + for ( const auto& DCB : UTMap.getDCBsCside() ) { + Utility::map_emplace( m_2d_DCB_tae_adc, DCB, this, DCB, AxisTAE, AxisADC_signed ); + } + for ( const auto& DCBQuadrant : UTMap.getDCBQuadrants() ) { + Utility::map_emplace( m_2d_DCBQuadrant_tae_adc, DCBQuadrant, this, DCBQuadrant, AxisTAE, AxisADC_signed ); + } + } ); +} + +void UTTAEMonitor::operator()( const UTDigits& digitsCont, const UTDigits& errdigitsCont, + LHCb::ODIN const& odin ) const { + + // Loop over UTDigits + for ( const auto& d : digitsCont ) { fillHistograms( d, odin ); } + // Loop over UTErrDigits + for ( const auto& d : errdigitsCont ) { fillHistograms( d, odin ); } +} + +void UTTAEMonitor::fillHistograms( const LHCb::UTDigit* aDigit, LHCb::ODIN const& odin ) const { + + // Let's find where we are in UT + auto tuple = UTMap.getTuple( aDigit->module(), aDigit->face(), aDigit->stave(), aDigit->side(), aDigit->sector() ); + std::string module_name = std::get<4>( tuple ); + auto y_p = std::get<1>( tuple ); + std::string position = ( y_p > 0 ) ? "T" : "B"; + std::string side = ( aDigit->side() == 0 ) ? "C" : "A"; + std::array<std::string, 4> layer = { "UTaX", "UTaU", "UTbV", "UTbX" }; + std::string station = ( aDigit->layer() < 2 ) ? "a" : "b"; + std::string dcb_name = UTMap.getDCB( layer[aDigit->layer()] + "_" + module_name ); + unsigned int TAEindex = odin.timeAlignmentEventIndex(); + + // Let's find where we are in the LHCb + auto bcid = odin.bunchId(); + auto bx = static_cast<uint8_t>( odin.bunchCrossingType() ); + auto trgtype = odin.triggerType(); + + // simple counters + ++m_bxtype[bx]; + ++m_trgtype[trgtype]; + ++m_bcid_bxtype[{ bcid, bx }]; + ++m_bcid_trgtype[{ bcid, trgtype }]; + + // summary plots this should be replace by odin.eventType soon as below + double weight = 1; + int offset = 0; + m_bcid_taesummary[{ bcid, offset + bx }] += weight; + offset += 4; + m_bcid_taesummary[{ bcid, offset++ }] += weight * odin.isTAE(); + m_bcid_taesummary[{ bcid, offset++ }] += weight * odin.timeAlignmentEventCentral(); + m_bcid_taesummary[{ bcid, offset++ }] += weight * odin.timeAlignmentEventFirst(); + + // for ( auto const& et : TAEEventTypes ) { m_bcid_taesummary[{bcid, offset++}] += weight * odin.eventTypeBit( et + // );} + + ++m_bcid_taeindex[{ bcid, odin.timeAlignmentEventIndex() }]; + + if ( TAEindex != 0 ) { + int offset = TAEindex - m_HalfWindow - 1; // let's alligne that with superTAE + ++m_2d_UT_tae_adc[{ offset, aDigit->depositedCharge() }]; + ++m_2d_DCB_tae_adc.at( dcb_name )[{ offset, aDigit->depositedCharge() }]; + ++m_2d_DCBQuadrant_tae_adc.at( + UTMap.getDCBQuadrant( layer[aDigit->layer()] + "_" + module_name ) )[{ offset, aDigit->depositedCharge() }]; + } +}; diff --git a/UT/UTMonitors/src/UTVeloUTCorrelationsMonitor.cpp b/UT/UTMonitors/src/UTVeloUTCorrelationsMonitor.cpp new file mode 100644 index 00000000000..eb9a0ad0f69 --- /dev/null +++ b/UT/UTMonitors/src/UTVeloUTCorrelationsMonitor.cpp @@ -0,0 +1,134 @@ +/***************************************************************************** \ +* (c) Copyright 2000-2018 CERN for the benefit of the LHCb Collaboration * +* * +* This software is distributed under the terms of the GNU General Public * +* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". * +* * +* In applying this licence, CERN does not waive the privileges and immunities * +* granted to it by virtue of its status as an Intergovernmental Organization * +* or submit itself to any jurisdiction. * +\*****************************************************************************/ + +#include "Event/ODIN.h" +#include "Event/RawBank.h" +#include "Event/RawEvent.h" +#include "Event/UTDigit.h" +#include "Gaudi/Accumulators/Histogram.h" +#include "Gaudi/Accumulators/HistogramArray.h" +#include "GaudiAlg/GaudiHistoAlg.h" +#include "Kernel/IUTReadoutTool.h" +#include "Kernel/UTDAQBoard.h" +#include "Kernel/UTDAQDefinitions.h" +#include "Kernel/UTDAQID.h" +#include "LHCbAlgs/Consumer.h" +#include "LHCbAlgs/Transformer.h" +#include "UTDAQ/UTCoordinatesMap.h" +#include "UTDAQ/UTDAQHelper.h" +#include "UTDAQ/UTInfo.h" + +// Needed for VELO +#include "Event/VPFullCluster.h" +#include "Kernel/VPConstants.h" + +/** @class UTVeloUTCorrelationsMonitor UTVeloUTCorrelationsMonitor.cpp + * -------------------------------------------------- + * Counters for Monet: correlation monitors + * The algorithm produces correlation plots for hits + * @author Paolo Gandini + * @author Wojciech Krupa + * @date 2024/04/20 + * -------------------------------------------------- + **/ + +using namespace LHCb; +namespace GA = Gaudi::Accumulators; + +// Definition of axis +const GA::Axis<double> AxisADC = GA::Axis<double>( 64, -32.5, 31.5, "nADC" ); //-32, 31 +const GA::Axis<double> AxisADC_signed = GA::Axis<double>( 31, -0.5, 31.5, "nADC" ); // 0-31 +const GA::Axis<double> AxisBCID = GA::Axis<double>( 3565, -0.5, 3564.5, "BunchID" ); // +const GA::Axis<double> AxisDIGIT = GA::Axis<double>( 1001, -0.5, 10000.5, "# UT" ); +const GA::Axis<double> AxisVeloDIGIT = GA::Axis<double>( 1001, -0.5, 10000.5, "# Velo" ); + +// UT layers +const std::array<std::string, 4> UT_layers = { "UTaX", "UTaU", "UTbV", "UTbX" }; + +enum class masks { channel = 0x000001ff, lane = 0x00000e00, board = 0x000ff000 }; +template <masks m> +[[nodiscard]] static constexpr unsigned int extract( unsigned int i ) { + constexpr auto b = std::countr_zero( static_cast<unsigned int>( m ) ); + return ( i & static_cast<unsigned int>( m ) ) >> b; +} + +/** ------------------------------------------------------------------------------------------------------------------------ */ +class UTVeloUTCorrelationsMonitor + : public LHCb::Algorithm::Consumer<void( UTDigits const&, UTDigits const&, LHCb::ODIN const&, + std::vector<VPFullCluster> const& ), + LHCb::DetDesc::usesBaseAndConditions<GaudiHistoAlg>> { +public: + UTVeloUTCorrelationsMonitor( const std::string& name, ISvcLocator* svcloc ) + : Consumer{ name, + svcloc, + { + { "InputData", UTDigitLocation::UTDigits }, + { "InputErrorData", UTDigitLocation::UTDigits }, + { "ODINLocation", LHCb::ODINLocation::Default }, + { "VeloClusterLocation", LHCb::VPFullClusterLocation::Default }, + } } {} + ToolHandle<IUTReadoutTool> readoutTool{ this, "ReadoutTool", "UTReadoutTool" }; + + void operator()( const UTDigits&, const UTDigits&, LHCb::ODIN const&, + const std::vector<LHCb::VPFullCluster>& ) const override; + + StatusCode initialize() override { + return Consumer::initialize().andThen( [&] { + // Set the top directory to UT + if ( histoTopDir().empty() ) setHistoTopDir( "" ); + } ); + } + +private: + // General plots + mutable GA::Histogram<1> m_nUTDigits{ this, "nUTDigits", "Total UT Digits", AxisDIGIT }; + mutable GA::Histogram<1> m_nVeloDigits{ this, "nVeloDigits", "Total Velo Digits", AxisVeloDIGIT }; + mutable GA::Histogram<2> m_nUTnVeloDigits{ this, "nUTnVeloDigits", "nUT vs nVELO", AxisDIGIT, AxisVeloDIGIT }; + mutable GA::Histogram<2> m_nUTnVeloDigits_bb{ this, "nUTnVeloDigits_bb", "nUT vs nVELO - bb", AxisDIGIT, + AxisVeloDIGIT }; + mutable GA::Histogram<2> m_nUTnVeloDigits_be{ this, "nUTnVeloDigits_be", "nUT vs nVELO - be", AxisDIGIT, + AxisVeloDIGIT }; + mutable GA::Histogram<2> m_nUTnVeloDigits_eb{ this, "nUTnVeloDigits_eb", "nUT vs nVELO - eb", AxisDIGIT, + AxisVeloDIGIT }; + mutable GA::Histogram<2> m_nUTnVeloDigits_ee{ this, "nUTnVeloDigits_ee", "nUT vs nVELO - ee", AxisDIGIT, + AxisVeloDIGIT }; + + mutable GA::HistogramArray<GA::Histogram<2>, 4> m_nUTnVeloDigits_bx{ + this, + []( int i ) { return fmt::format( "nUTnVeloDigits_bx{}", i ); }, + []( int i ) { return fmt::format( "nUTnVeloDigits BXID{}", i ); }, + { 201, -0.5, 400.5, "# UT" }, + { 201, -0.5, 400.5, "# Velo" } }; + +}; // End of class UTVeloUTCorrelationsMonitor +DECLARE_COMPONENT( UTVeloUTCorrelationsMonitor ) + +void UTVeloUTCorrelationsMonitor::operator()( const UTDigits& digitsCont, const UTDigits& errdigitsCont, + LHCb::ODIN const& odin, + const std::vector<LHCb::VPFullCluster>& vpClusters ) const { + + // General counters + const unsigned int nBuncId = odin.bunchId(); + const int bunchCrossingType = (int)odin.bunchCrossingType(); + ++m_nUTDigits[digitsCont.size() + errdigitsCont.size()]; + ++m_nVeloDigits[vpClusters.size()]; + ++m_nUTnVeloDigits[{ digitsCont.size() + errdigitsCont.size(), vpClusters.size() }]; + ++m_nUTnVeloDigits_bx[bunchCrossingType][{ digitsCont.size() + errdigitsCont.size(), vpClusters.size() }]; + + if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::BeamCrossing ) + ++m_nUTnVeloDigits_bb[{ digitsCont.size() + errdigitsCont.size(), vpClusters.size() }]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::Beam1 ) + ++m_nUTnVeloDigits_be[{ digitsCont.size() + errdigitsCont.size(), vpClusters.size() }]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::Beam2 ) + ++m_nUTnVeloDigits_eb[{ digitsCont.size() + errdigitsCont.size(), vpClusters.size() }]; + else if ( odin.bunchCrossingType() == LHCb::ODIN::BXTypes::NoBeam ) + ++m_nUTnVeloDigits_ee[{ digitsCont.size() + errdigitsCont.size(), vpClusters.size() }]; +} -- GitLab