diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 00000000..03a0673a --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,26 @@ +name: pre-commit + +on: [push, pull_request] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: cvmfs-contrib/github-action-cvmfs@v4 + - uses: aidasoft/run-lcg-view@v4 + with: + container: el9 + view-path: /cvmfs/sw-nightlies.hsf.org/key4hep + run: | + python -m venv /root/pre-commit-venv + source /root/pre-commit-venv/bin/activate + pip install pre-commit + export PYTHONPATH=$VIRTUAL_ENV/lib/python3.$(python3 -c 'import sys; print(f"{sys.version_info[1]}")')/site-packages:$PYTHONPATH + # Newer versions of git are more cautious around the github runner + # environment and without this git rev-parse --show-cdup in pre-commit + # fails + git config --global --add safe.directory $(pwd) + pre-commit run --show-diff-on-failure \ + --color=always \ + --all-files diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..ccdf6218 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,13 @@ +repos: + - repo: local + hooks: + - id: ruff-format + name: ruff-format + entry: ruff format --force-exclude + types: [python] + language: system + - id: ruff-isort + name: ruff-isort + entry: ruff check --select I --fix --force-exclude + types: [python] + language: system diff --git a/.ruff.toml b/.ruff.toml new file mode 100644 index 00000000..5ac82934 --- /dev/null +++ b/.ruff.toml @@ -0,0 +1,10 @@ +target-version = "py311" + +line-length = 99 + +[format] +# Make things format the same way as black +quote-style = "double" +indent-style = "space" +skip-magic-trailing-comma = false +line-ending = "auto" diff --git a/StandardConfig/production/CaloDigi/FcalDigi.py b/StandardConfig/production/CaloDigi/FcalDigi.py index 2e64ae28..70433134 100644 --- a/StandardConfig/production/CaloDigi/FcalDigi.py +++ b/StandardConfig/production/CaloDigi/FcalDigi.py @@ -2,7 +2,6 @@ from Configurables import MarlinProcessorWrapper - MySimpleBCalDigi = MarlinProcessorWrapper("MySimpleBCalDigi") MySimpleBCalDigi.ProcessorType = "SimpleFCalDigi" MySimpleBCalDigi.Parameters = { diff --git a/StandardConfig/production/CaloDigi/SiWEcalDigi.py b/StandardConfig/production/CaloDigi/SiWEcalDigi.py index 68a6f4f3..b11ed38e 100644 --- a/StandardConfig/production/CaloDigi/SiWEcalDigi.py +++ b/StandardConfig/production/CaloDigi/SiWEcalDigi.py @@ -2,18 +2,14 @@ from Configurables import MarlinProcessorWrapper -MergeCollectionsEcalBarrelHits = MarlinProcessorWrapper( - "MergeCollectionsEcalBarrelHits" -) +MergeCollectionsEcalBarrelHits = MarlinProcessorWrapper("MergeCollectionsEcalBarrelHits") MergeCollectionsEcalBarrelHits.ProcessorType = "MergeCollections" MergeCollectionsEcalBarrelHits.Parameters = { "InputCollections": ["ECalBarrelSiHitsEven", "ECalBarrelSiHitsOdd"], "OutputCollection": ["EcalBarrelCollection"], } -MergeCollectionsEcalEndcapHits = MarlinProcessorWrapper( - "MergeCollectionsEcalEndcapHits" -) +MergeCollectionsEcalEndcapHits = MarlinProcessorWrapper("MergeCollectionsEcalEndcapHits") MergeCollectionsEcalEndcapHits.ProcessorType = "MergeCollections" MergeCollectionsEcalEndcapHits.Parameters = { "InputCollections": ["ECalEndcapSiHitsEven", "ECalEndcapSiHitsOdd"], diff --git a/StandardConfig/production/HighLevelReco/HighLevelReco.py b/StandardConfig/production/HighLevelReco/HighLevelReco.py index 7c8346f7..162fb02a 100644 --- a/StandardConfig/production/HighLevelReco/HighLevelReco.py +++ b/StandardConfig/production/HighLevelReco/HighLevelReco.py @@ -13,9 +13,7 @@ "PFOCollectionName": ["PandoraPFOs"], } -MyComputeShowerShapesProcessor = MarlinProcessorWrapper( - "MyComputeShowerShapesProcessor" -) +MyComputeShowerShapesProcessor = MarlinProcessorWrapper("MyComputeShowerShapesProcessor") MyComputeShowerShapesProcessor.ProcessorType = "ComputeShowerShapesProcessor" MyComputeShowerShapesProcessor.Parameters = { "ClusterCollectionName": ["PandoraClusters"], @@ -291,9 +289,7 @@ "BuildUpVertexCollectionName": ["BuildUpVertex"], "PFOCollection": ["PandoraPFOs"], "PrimaryVertexCollectionName": ["PrimaryVertex"], - "PrimaryVertexFinder.BeamspotConstraint": [ - cms_energy_config["LCFIPlusBeamspotConstraint"] - ], + "PrimaryVertexFinder.BeamspotConstraint": [cms_energy_config["LCFIPlusBeamspotConstraint"]], "PrimaryVertexFinder.BeamspotSmearing": ["0"], "PrimaryVertexFinder.Chi2Threshold": ["25."], "PrimaryVertexFinder.TrackMaxD0": ["20."], diff --git a/StandardConfig/production/ILDReconstruction.py b/StandardConfig/production/ILDReconstruction.py index 40e15ac8..c4becc2b 100644 --- a/StandardConfig/production/ILDReconstruction.py +++ b/StandardConfig/production/ILDReconstruction.py @@ -222,9 +222,7 @@ def get_cms_energy_config( geoSvc.EnableGeant4Geo = False svcList.append(geoSvc) -is_FCCee_model, cms_e, cms_energy_config = get_cms_energy_config( - compact_file, reco_args.cmsEnergy -) +is_FCCee_model, cms_e, cms_energy_config = get_cms_energy_config(compact_file, reco_args.cmsEnergy) CONSTANTS = { "CMSEnergy": str(cms_e), "BeamCalCalibrationFactor": str(reco_args.beamCalCalibFactor), @@ -303,9 +301,7 @@ def get_cms_energy_config( "BCalCollections": ["BCAL"], "BCalCollectionsSimCaloHit": ["BeamCalCollection"], "CollectCalibrationDetails": ["0"], - "ECalBarrelCollectionsSimCaloHit": [ - CONSTANTS["ECalBarrelSimHitCollections"] - ], + "ECalBarrelCollectionsSimCaloHit": [CONSTANTS["ECalBarrelSimHitCollections"]], "ECalCollections": [ "EcalBarrelCollectionRec", "EcalBarrelCollectionGapHits", @@ -314,21 +310,15 @@ def get_cms_energy_config( "EcalEndcapRingCollectionRec", ], "ECalCollectionsSimCaloHit": [CONSTANTS["ECalSimHitCollections"]], - "ECalEndCapCollectionsSimCaloHit": [ - CONSTANTS["ECalEndcapSimHitCollections"] - ], + "ECalEndCapCollectionsSimCaloHit": [CONSTANTS["ECalEndcapSimHitCollections"]], "ECalOtherCollectionsSimCaloHit": [CONSTANTS["ECalRingSimHitCollections"]], - "HCalBarrelCollectionsSimCaloHit": [ - CONSTANTS["HCalBarrelSimHitCollections"] - ], + "HCalBarrelCollectionsSimCaloHit": [CONSTANTS["HCalBarrelSimHitCollections"]], "HCalCollections": [ "HcalBarrelCollectionRec", "HcalEndcapsCollectionRec", "HcalEndcapRingCollectionRec", ], - "HCalEndCapCollectionsSimCaloHit": [ - CONSTANTS["HCalEndcapSimHitCollections"] - ], + "HCalEndCapCollectionsSimCaloHit": [CONSTANTS["HCalEndcapSimHitCollections"]], "HCalOtherCollectionsSimCaloHit": [CONSTANTS["HCalRingSimHitCollections"]], "LCalCollections": ["LCAL"], "LCalCollectionsSimCaloHit": ["LumiCalCollection"], @@ -352,9 +342,7 @@ def get_cms_energy_config( # Make sure that all collections are always available by patching in missing # ones on-the-fly -collPatcherRec = MarlinProcessorWrapper( - "CollPatcherREC", ProcessorType="PatchCollections" -) +collPatcherRec = MarlinProcessorWrapper("CollPatcherREC", ProcessorType="PatchCollections") collPatcherRec.Parameters = { "PatchCollections": parse_collection_patch_file(REC_COLLECTION_CONTENTS_FILE) } @@ -365,9 +353,7 @@ def get_cms_energy_config( output_commands.extend(get_drop_collections(CONSTANTS, True)) # get_drop_collections incorrectly splits "type edm4hep::..." into two separate drops output_commands.append("drop type edm4hep::RecDqdxCollection") - io_handler.add_edm4hep_writer( - f"{reco_args.outputFileBase}_REC.edm4hep.root", output_commands - ) + io_handler.add_edm4hep_writer(f"{reco_args.outputFileBase}_REC.edm4hep.root", output_commands) if reco_args.lcioOutput in ("on", "only"): @@ -419,9 +405,7 @@ def get_cms_energy_config( svcList.append(auditorSvc) auditorSvc.Auditors = [AlgTimingAuditor()] -app_mgr = ApplicationMgr( - TopAlg=algList, EvtSel="NONE", EvtMax=3, ExtSvc=svcList, OutputLevel=INFO -) +app_mgr = ApplicationMgr(TopAlg=algList, EvtSel="NONE", EvtMax=3, ExtSvc=svcList, OutputLevel=INFO) app_mgr.AuditAlgorithms = True app_mgr.AuditTools = True diff --git a/StandardConfig/production/Tracking/TrackingDigi.py b/StandardConfig/production/Tracking/TrackingDigi.py index 4ce8d3e5..04f170ad 100644 --- a/StandardConfig/production/Tracking/TrackingDigi.py +++ b/StandardConfig/production/Tracking/TrackingDigi.py @@ -16,9 +16,7 @@ ], } -VXDPlanarDigiProcessor_CMOSVXD5 = MarlinProcessorWrapper( - "VXDPlanarDigiProcessor_CMOSVXD5" -) +VXDPlanarDigiProcessor_CMOSVXD5 = MarlinProcessorWrapper("VXDPlanarDigiProcessor_CMOSVXD5") VXDPlanarDigiProcessor_CMOSVXD5.ProcessorType = "DDPlanarDigiProcessor" VXDPlanarDigiProcessor_CMOSVXD5.Parameters = { "ForceHitsOntoSurface": ["true"], diff --git a/StandardConfig/production/Tracking/TrackingDigi_FCCeeMDI.py b/StandardConfig/production/Tracking/TrackingDigi_FCCeeMDI.py index 38dd4f63..5403ff64 100644 --- a/StandardConfig/production/Tracking/TrackingDigi_FCCeeMDI.py +++ b/StandardConfig/production/Tracking/TrackingDigi_FCCeeMDI.py @@ -42,9 +42,7 @@ "TrackerHitCollectionName": ["InnerTrackerBarrelHits"], } -InnerEndcapPlanarDigiProcessor = MarlinProcessorWrapper( - "InnerEndcapPlanarDigiProcessor" -) +InnerEndcapPlanarDigiProcessor = MarlinProcessorWrapper("InnerEndcapPlanarDigiProcessor") InnerEndcapPlanarDigiProcessor.ProcessorType = "DDPlanarDigiProcessor" InnerEndcapPlanarDigiProcessor.Parameters = { "IsStrip": ["false"], diff --git a/StandardConfig/production/Tracking/TrackingReco_FCCeeMDI.py b/StandardConfig/production/Tracking/TrackingReco_FCCeeMDI.py index ad94e075..d97775e8 100644 --- a/StandardConfig/production/Tracking/TrackingReco_FCCeeMDI.py +++ b/StandardConfig/production/Tracking/TrackingReco_FCCeeMDI.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 from Configurables import MarlinProcessorWrapper - from py_utils import encode_CT_steps_dict_to_legacy_list CT_MAX_DIST = "0.03" # RANDOM VALUE COPYIED FROM CLDRECO diff --git a/StandardConfig/production/ddsim_steer.py b/StandardConfig/production/ddsim_steer.py index 5c081327..bf117029 100644 --- a/StandardConfig/production/ddsim_steer.py +++ b/StandardConfig/production/ddsim_steer.py @@ -1,20 +1,21 @@ ###################################################################### # -# standard steering file for ILD simulation -# +# standard steering file for ILD simulation +# # # ###################################################################### -from DDSim.DD4hepSimulation import DD4hepSimulation -from g4units import m, mm, GeV, MeV, rad import os +from DDSim.DD4hepSimulation import DD4hepSimulation +from g4units import GeV, MeV, m, mm, rad + SIM = DD4hepSimulation() ## The compact XML file SIM.compactFile = "" ## Lorentz boost for the crossing angle, in radian! -SIM.crossingAngleBoost = 7.e-3*rad +SIM.crossingAngleBoost = 7.0e-3 * rad SIM.enableDetailedShowerMode = True SIM.enableG4GPS = False SIM.enableG4Gun = False @@ -51,49 +52,52 @@ ################################################################################ ## Action holding sensitive detector actions ## The default tracker and calorimeter actions can be set with -## +## ## >>> SIM = DD4hepSimulation() ## >>> SIM.action.tracker = ('Geant4TrackerWeightedAction', {'HitPositionCombination': 2, 'CollectSingleDeposits': False}) ## >>> SIM.action.calo = "Geant4CalorimeterAction" -## +## ## for specific subdetectors specific sensitive detectors can be set based on pattern matching -## +## ## >>> SIM = DD4hepSimulation() ## >>> SIM.action.mapActions['tpc'] = "TPCSDAction" -## +## ## and additional parameters for the sensitive detectors can be set when the map is given a tuple -## +## ## >>> SIM = DD4hepSimulation() ## >>> SIM.action.mapActions['ecal'] =( "CaloPreShowerSDAction", {"FirstLayerNumber": 1} ) -## -## +## +## ################################################################################ -## set the default calorimeter action +## set the default calorimeter action SIM.action.calo = "Geant4ScintillatorCalorimeterAction" ## create a map of patterns and actions to be applied to sensitive detectors -## example: SIM.action.mapActions['tpc'] = "TPCSDAction" +## example: SIM.action.mapActions['tpc'] = "TPCSDAction" SIM.action.mapActions = {} -SIM.action.mapActions['tpc'] = "TPCSDAction" +SIM.action.mapActions["tpc"] = "TPCSDAction" -## set the default tracker action -SIM.action.tracker = ('Geant4TrackerWeightedAction', {'HitPositionCombination': 2, 'CollectSingleDeposits': False}) +## set the default tracker action +SIM.action.tracker = ( + "Geant4TrackerWeightedAction", + {"HitPositionCombination": 2, "CollectSingleDeposits": False}, +) ################################################################################ -## Configuration for the magnetic field (stepper) +## Configuration for the magnetic field (stepper) ################################################################################ ## --- used in v01-19-05 : SIM.field.delta_chord = 1e-05 SIM.field.delta_intersection = 1e-05 -SIM.field.delta_one_step = .5e-03*mm +SIM.field.delta_one_step = 0.5e-03 * mm SIM.field.eps_max = 1e-04 SIM.field.eps_min = 1e-05 SIM.field.equation = "Mag_UsualEqRhs" -SIM.field.largest_step = 10.*m -SIM.field.min_chord_step = 1.e-2*mm +SIM.field.largest_step = 10.0 * m +SIM.field.min_chord_step = 1.0e-2 * mm SIM.field.stepper = "HelixSimpleRunge" ## --- default values in ddsim @@ -109,78 +113,82 @@ ################################################################################ ## Configuration for sensitive detector filters -## +## ## Set the default filter for tracker or caliromter ## >>> SIM.filter.tracker = "edep1kev" ## >>> SIM.filter.calo = "" -## +## ## Assign a filter to a sensitive detector via pattern matching ## >>> SIM.filter.mapDetFilter['FTD'] = "edep1kev" -## +## ## Or more than one filter: ## >>> SIM.filter.mapDetFilter['FTD'] = ["edep1kev", "geantino"] -## +## ## Don't use the default filter or anything else: ## >>> SIM.filter.mapDetFilter['TPC'] = None ## or "" or [] -## +## ## Create a custom filter. The dictionary is used to instantiate the filter later on ## >>> SIM.filter.filters['edep3kev'] = dict(name="EnergyDepositMinimumCut/3keV", parameter={"Cut": 3.0*keV} ) -## -## +## +## ################################################################################ -## default filter for calorimeter sensitive detectors; this is applied if no other filter is used for a calorimeter +## default filter for calorimeter sensitive detectors; this is applied if no other filter is used for a calorimeter SIM.filter.calo = "edep0" -## list of filter objects: map between name and parameter dictionary -SIM.filter.filters = {'edep0': {'parameter': {'Cut': 0.0}, 'name': 'EnergyDepositMinimumCut/Cut0'}, 'geantino': {'parameter': {}, 'name': 'GeantinoRejectFilter/GeantinoRejector'}, 'edep1kev': {'parameter': {'Cut': 0.001}, 'name': 'EnergyDepositMinimumCut'}} +## list of filter objects: map between name and parameter dictionary +SIM.filter.filters = { + "edep0": {"parameter": {"Cut": 0.0}, "name": "EnergyDepositMinimumCut/Cut0"}, + "geantino": {"parameter": {}, "name": "GeantinoRejectFilter/GeantinoRejector"}, + "edep1kev": {"parameter": {"Cut": 0.001}, "name": "EnergyDepositMinimumCut"}, +} -## a map between patterns and filter objects, using patterns to attach filters to sensitive detector +## a map between patterns and filter objects, using patterns to attach filters to sensitive detector SIM.filter.mapDetFilter = {} -SIM.filter.mapDetFilter['TPC'] = None +SIM.filter.mapDetFilter["TPC"] = None ## default filter for tracking sensitive detectors; this is applied if no other filter is used for a tracker SIM.filter.tracker = "edep1kev" ################################################################################ -## Configuration for the GuineaPig InputFiles +## Configuration for the GuineaPig InputFiles ################################################################################ ## Set the number of pair particles to simulate per event. ## Only used if inputFile ends with ".pairs" ## If "-1" all particles will be simulated in a single event -## +## SIM.guineapig.particlesPerEvent = "-1" ################################################################################ -## Configuration for the DDG4 ParticleGun +## Configuration for the DDG4 ParticleGun ################################################################################ -## direction of the particle gun, 3 vector +## direction of the particle gun, 3 vector SIM.gun.direction = (0, 0, 1) ## choose the distribution of the random direction for theta -## +## ## Options for random distributions: -## +## ## 'uniform' is the default distribution, flat in theta ## 'cos(theta)' is flat in cos(theta) ## 'eta', or 'pseudorapidity' is flat in pseudorapity ## 'ffbar' is distributed according to 1+cos^2(theta) -## +## ## Setting a distribution will set isotrop = True -## +## SIM.gun.distribution = None SIM.gun.energy = 10000.0 ## isotropic distribution for the particle gun -## +## ## use the options phiMin, phiMax, thetaMin, and thetaMax to limit the range of randomly distributed directions ## if one of these options is not None the random distribution will be set to True and cannot be turned off! -## +## SIM.gun.isotrop = False SIM.gun.multiplicity = 1 SIM.gun.particle = "mu-" @@ -189,14 +197,14 @@ ## Minimal azimuthal angle for random distribution SIM.gun.phiMin = None -## position of the particle gun, 3 vector +## position of the particle gun, 3 vector SIM.gun.position = (0.0, 0.0, 0.0) SIM.gun.thetaMax = None SIM.gun.thetaMin = None ################################################################################ -## Configuration for the output levels of DDG4 components +## Configuration for the output levels of DDG4 components ################################################################################ ## Output level for input sources @@ -213,58 +221,58 @@ ################################################################################ -## Configuration for the Particle Handler/ MCTruth treatment +## Configuration for the Particle Handler/ MCTruth treatment ################################################################################ ## Enable lots of printout on simulated hits and MC-truth information SIM.part.enableDetailedHitsAndParticleInfo = False -## Keep all created particles +## Keep all created particles SIM.part.keepAllParticles = False ## Minimal distance between particle vertex and endpoint of parent after ## which the vertexIsNotEndpointOfParent flag is set -## +## SIM.part.minDistToParentVertex = 2.2e-14 ## MinimalKineticEnergy to store particles created in the tracking region -SIM.part.minimalKineticEnergy = 1*MeV +SIM.part.minimalKineticEnergy = 1 * MeV -## Printout at End of Tracking +## Printout at End of Tracking SIM.part.printEndTracking = False -## Printout at Start of Tracking +## Printout at Start of Tracking SIM.part.printStartTracking = False ## List of processes to save, on command line give as whitespace separated string in quotation marks -SIM.part.saveProcesses = ['Decay'] +SIM.part.saveProcesses = ["Decay"] ################################################################################ -## Configuration for the PhysicsList +## Configuration for the PhysicsList ################################################################################ # this needs to be set to False if any standard physics list is used: SIM.physics.decays = False -SIM.physics.list = "QGSP_BERT" # "FTFP_BERT" +SIM.physics.list = "QGSP_BERT" # "FTFP_BERT" ## location of particle.tbl file containing extra particles and their lifetime information -## -SIM.physics.pdgfile = os.path.join( os.environ.get("DD4HEP"), "DDG4/examples/particle.tbl") +## +SIM.physics.pdgfile = os.path.join(os.environ.get("DD4HEP"), "DDG4/examples/particle.tbl") ## The global geant4 rangecut for secondary production -## +## ## Default is 0.7 mm as is the case in geant4 10 -## +## ## To disable this plugin and be absolutely sure to use the Geant4 default range cut use "None" -## +## ## Set printlevel to DEBUG to see a printout of all range cuts, ## but this only works if range cut is not "None" -## -SIM.physics.rangecut = 0.1*mm +## +SIM.physics.rangecut = 0.1 * mm ################################################################################ -## Properties for the random number generator +## Properties for the random number generator ################################################################################ ## If True, calculate random seed for each event based on eventID and runID @@ -275,4 +283,3 @@ SIM.random.replace_gRandom = True SIM.random.seed = None SIM.random.type = None - diff --git a/StandardConfig/production/py_utils.py b/StandardConfig/production/py_utils.py index 1bf8d203..e8931c5f 100644 --- a/StandardConfig/production/py_utils.py +++ b/StandardConfig/production/py_utils.py @@ -1,9 +1,9 @@ -import os -from io import TextIOWrapper -from typing import Union, Optional, Dict, Any, List -import importlib.util import importlib.abc +import importlib.util +import os from importlib.machinery import SourceFileLoader +from io import TextIOWrapper +from typing import Any, Dict, List, Optional, Union def import_from( @@ -89,9 +89,7 @@ class SequenceLoader: define all of them. """ - def __init__( - self, alg_list: list, global_vars: Optional[Dict[str, Any]] = None - ) -> None: + def __init__(self, alg_list: list, global_vars: Optional[Dict[str, Any]] = None) -> None: """Initialize the SequenceLoader This initializes a SequenceLoader with the list of algorithms to which