From 4b700795475b6d1b272ded19333ea8eaaeb68648 Mon Sep 17 00:00:00 2001 From: Leonhard Reichenbach Date: Tue, 16 Apr 2024 10:46:58 +0200 Subject: [PATCH 1/9] make output less verbose --- CLDConfig/CLDReconstruction.py | 2 +- CLDConfig/HighLevelReco/JetClusteringOrRenaming.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CLDConfig/CLDReconstruction.py b/CLDConfig/CLDReconstruction.py index 19617e4..bc4c533 100644 --- a/CLDConfig/CLDReconstruction.py +++ b/CLDConfig/CLDReconstruction.py @@ -165,7 +165,7 @@ lcioConvTool.collNameMapping = { "MCParticle": "MCParticles" } - lcioConvTool.OutputLevel = DEBUG + lcioConvTool.OutputLevel = WARNING # attach to the last non output processor EventNumber.Lcio2EDM4hepTool = lcioConvTool diff --git a/CLDConfig/HighLevelReco/JetClusteringOrRenaming.py b/CLDConfig/HighLevelReco/JetClusteringOrRenaming.py index c19b505..9e7bfc5 100644 --- a/CLDConfig/HighLevelReco/JetClusteringOrRenaming.py +++ b/CLDConfig/HighLevelReco/JetClusteringOrRenaming.py @@ -25,7 +25,7 @@ RenameCollection.ProcessorType = "MergeCollections" RenameCollection.Parameters = { "CollectionParameterIndex": ["0"], - "InputCollectionIDs": [], + "InputCollectionIDs": ["0"], "InputCollections": ["PandoraPFOs"], "OutputCollection": ["PFOsFromJets"] } From 452823e9440ed61ea646c1ffbc3f88bbe84ca969 Mon Sep 17 00:00:00 2001 From: Leonhard Reichenbach Date: Tue, 23 Apr 2024 16:12:54 +0200 Subject: [PATCH 2/9] introduce function for lcio2edm4hep conversion attachment --- CLDConfig/CLDReconstruction.py | 15 ++++----------- CLDConfig/py_utils.py | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/CLDConfig/CLDReconstruction.py b/CLDConfig/CLDReconstruction.py index bc4c533..e25cbfb 100644 --- a/CLDConfig/CLDReconstruction.py +++ b/CLDConfig/CLDReconstruction.py @@ -22,7 +22,7 @@ from Configurables import k4DataSvc, MarlinProcessorWrapper from k4MarlinWrapper.inputReader import create_reader, attach_edm4hep2lcio_conversion from k4FWCore.parseArgs import parser -from py_utils import SequenceLoader +from py_utils import SequenceLoader, attach_lcio2edm4hep_conversion import ROOT ROOT.gROOT.SetBatch(True) @@ -159,16 +159,6 @@ algList.append(Output_DST) if CONFIG["OutputMode"] == "EDM4Hep": - from Configurables import Lcio2EDM4hepTool - lcioConvTool = Lcio2EDM4hepTool("lcio2EDM4hep") - lcioConvTool.convertAll = True - lcioConvTool.collNameMapping = { - "MCParticle": "MCParticles" - } - lcioConvTool.OutputLevel = WARNING -# attach to the last non output processor - EventNumber.Lcio2EDM4hepTool = lcioConvTool - from Configurables import PodioOutput out = PodioOutput("PodioOutput", filename = f"{reco_args.outputBasename}_edm4hep.root") out.outputCommands = ["keep *"] @@ -177,6 +167,9 @@ # We need to convert the inputs in case we have EDM4hep input attach_edm4hep2lcio_conversion(algList, read) +# We need to convert the outputs in case we have EDM4hep output +attach_lcio2edm4hep_conversion(algList) + from Configurables import ApplicationMgr ApplicationMgr( TopAlg = algList, EvtSel = 'NONE', diff --git a/CLDConfig/py_utils.py b/CLDConfig/py_utils.py index 8d72391..2d9fe55 100644 --- a/CLDConfig/py_utils.py +++ b/CLDConfig/py_utils.py @@ -21,6 +21,7 @@ import importlib.util import importlib.abc from importlib.machinery import SourceFileLoader +from Configurables import PodioOutput, MarlinProcessorWrapper def import_from( @@ -128,3 +129,27 @@ def load(self, sequence: str) -> None: seq = getattr(seq_module, seq_name) self.alg_list.extend(seq) + + + +def attach_lcio2edm4hep_conversion(algList: list) -> None: + """Attaches a conversion from lcio to edm4hep at the last MarlinWrapper in algList if necessary + """ + # need to attach a conversion if there are edm4hep outputs and marlin wrappers + if not any((isinstance(alg, PodioOutput) for alg in algList)): + # no edm4hep output -> no conversion :) + return + # find last marlin wrapper + for alg in reversed(algList): + if isinstance(alg, MarlinProcessorWrapper): + break + + from Configurables import Lcio2EDM4hepTool + lcioConvTool = Lcio2EDM4hepTool("lcio2EDM4hep") + lcioConvTool.convertAll = True + lcioConvTool.collNameMapping = { + "MCParticle": "MCParticles", + } + + alg.Lcio2EDM4hepTool = lcioConvTool + From 2188cdadd37928b136bf672550aad1f3401baee5 Mon Sep 17 00:00:00 2001 From: Leonhard Reichenbach Date: Tue, 23 Apr 2024 16:14:04 +0200 Subject: [PATCH 3/9] hide output writer code behind function --- CLDConfig/CLDReconstruction.py | 45 +++++++++++------------------ CLDConfig/py_utils.py | 53 ++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 28 deletions(-) diff --git a/CLDConfig/CLDReconstruction.py b/CLDConfig/CLDReconstruction.py index e25cbfb..d66c1b4 100644 --- a/CLDConfig/CLDReconstruction.py +++ b/CLDConfig/CLDReconstruction.py @@ -22,7 +22,7 @@ from Configurables import k4DataSvc, MarlinProcessorWrapper from k4MarlinWrapper.inputReader import create_reader, attach_edm4hep2lcio_conversion from k4FWCore.parseArgs import parser -from py_utils import SequenceLoader, attach_lcio2edm4hep_conversion +from py_utils import SequenceLoader, attach_lcio2edm4hep_conversion, create_writer import ROOT ROOT.gROOT.SetBatch(True) @@ -131,38 +131,27 @@ # event number processor, down here to attach the conversion back to edm4hep to it algList.append(EventNumber) + +DST_KEEPLIST = ["MCParticlesSkimmed", "MCPhysicsParticles", "RecoMCTruthLink", "SiTracks", "SiTracks_Refitted", "PandoraClusters", "PandoraPFOs", "SelectedPandoraPFOs", "LooseSelectedPandoraPFOs", "TightSelectedPandoraPFOs", "RefinedVertexJets", "RefinedVertexJets_rel", "RefinedVertexJets_vtx", "RefinedVertexJets_vtx_RP", "BuildUpVertices", "BuildUpVertices_res", "BuildUpVertices_RP", "BuildUpVertices_res_RP", "BuildUpVertices_V0", "BuildUpVertices_V0_res", "BuildUpVertices_V0_RP", "BuildUpVertices_V0_res_RP", "PrimaryVertices", "PrimaryVertices_res", "PrimaryVertices_RP", "PrimaryVertices_res_RP", "RefinedVertices", "RefinedVertices_RP"] + +DST_SUBSETLIST = ["EfficientMCParticles", "InefficientMCParticles", "MCPhysicsParticles"] + +# TODO: replace all the ugly strings by something sensible like Enum if CONFIG["OutputMode"] == "LCIO": - Output_REC = MarlinProcessorWrapper("Output_REC") - Output_REC.OutputLevel = WARNING - Output_REC.ProcessorType = "LCIOOutputProcessor" - Output_REC.Parameters = { - "DropCollectionNames": [], - "DropCollectionTypes": [], - "FullSubsetCollections": ["EfficientMCParticles", "InefficientMCParticles"], - "KeepCollectionNames": [], - "LCIOOutputFile": [f"{reco_args.outputBasename}_REC.slcio"], - "LCIOWriteMode": ["WRITE_NEW"] - } - - Output_DST = MarlinProcessorWrapper("Output_DST") - Output_DST.OutputLevel = WARNING - Output_DST.ProcessorType = "LCIOOutputProcessor" - Output_DST.Parameters = { - "DropCollectionNames": [], - "DropCollectionTypes": ["MCParticle", "LCRelation", "SimCalorimeterHit", "CalorimeterHit", "SimTrackerHit", "TrackerHit", "TrackerHitPlane", "Track", "ReconstructedParticle", "LCFloatVec"], - "FullSubsetCollections": ["EfficientMCParticles", "InefficientMCParticles", "MCPhysicsParticles"], - "KeepCollectionNames": ["MCParticlesSkimmed", "MCPhysicsParticles", "RecoMCTruthLink", "SiTracks", "SiTracks_Refitted", "PandoraClusters", "PandoraPFOs", "SelectedPandoraPFOs", "LooseSelectedPandoraPFOs", "TightSelectedPandoraPFOs", "RefinedVertexJets", "RefinedVertexJets_rel", "RefinedVertexJets_vtx", "RefinedVertexJets_vtx_RP", "BuildUpVertices", "BuildUpVertices_res", "BuildUpVertices_RP", "BuildUpVertices_res_RP", "BuildUpVertices_V0", "BuildUpVertices_V0_res", "BuildUpVertices_V0_RP", "BuildUpVertices_V0_res_RP", "PrimaryVertices", "PrimaryVertices_res", "PrimaryVertices_RP", "PrimaryVertices_res_RP", "RefinedVertices", "RefinedVertices_RP"], - "LCIOOutputFile": [f"{reco_args.outputBasename}_DST.slcio"], - "LCIOWriteMode": ["WRITE_NEW"] - } + Output_REC = create_writer("lcio", "Output_REC", f"{reco_args.outputBasename}_REC") algList.append(Output_REC) + + Output_DST = create_writer("lcio", "Output_DST", f"{reco_args.outputBasename}_DST", DST_KEEPLIST, DST_SUBSETLIST) algList.append(Output_DST) if CONFIG["OutputMode"] == "EDM4Hep": - from Configurables import PodioOutput - out = PodioOutput("PodioOutput", filename = f"{reco_args.outputBasename}_edm4hep.root") - out.outputCommands = ["keep *"] - algList.append(out) + Output_REC = create_writer("edm4hep", "Output_REC", f"{reco_args.outputBasename}_REC") + algList.append(Output_REC) + + # FIXME: needs https://github.com/key4hep/k4FWCore/issues/226 + # Output_DST = create_writer("edm4hep", "Output_DST", f"{reco_args.outputBasename}_DST", DST_KEEPLIST) + # algList.append(Output_DST) + # We need to convert the inputs in case we have EDM4hep input attach_edm4hep2lcio_conversion(algList, read) diff --git a/CLDConfig/py_utils.py b/CLDConfig/py_utils.py index 2d9fe55..b53af7e 100644 --- a/CLDConfig/py_utils.py +++ b/CLDConfig/py_utils.py @@ -22,6 +22,8 @@ import importlib.abc from importlib.machinery import SourceFileLoader from Configurables import PodioOutput, MarlinProcessorWrapper +from typing import Iterable +from Gaudi.Configuration import WARNING def import_from( @@ -153,3 +155,54 @@ def attach_lcio2edm4hep_conversion(algList: list) -> None: alg.Lcio2EDM4hepTool = lcioConvTool + + +def _create_writer_lcio(writer_name: str, output_name: str, keep_list: Iterable = (), full_subset_list: Iterable = ()): + writer = MarlinProcessorWrapper(writer_name) + writer.OutputLevel = WARNING + writer.ProcessorType = "LCIOOutputProcessor" + + # convert iterables to "real" lists + _full_subset_list = list(full_subset_list) + _keep_list = list(keep_list) + + dropped_types = [] + if _keep_list: + # drop collections of all types + dropped_types = ["MCParticle", "LCRelation", "SimCalorimeterHit", "CalorimeterHit", "SimTrackerHit", "TrackerHit", "TrackerHitPlane", "Track", "ReconstructedParticle", "LCFloatVec"] + + writer.Parameters = { + "DropCollectionNames": [], + "DropCollectionTypes": dropped_types, + "FullSubsetCollections": _full_subset_list, + "KeepCollectionNames": _keep_list, + "LCIOOutputFile": [f"{output_name}.slcio"], + "LCIOWriteMode": ["WRITE_NEW"], + } + + return writer + + +def _create_writer_edm4hep(writer_name: str, output_name: str, keep_list: Iterable = ()): + writer = PodioOutput(writer_name, filename = f"{output_name}.edm4hep.root") + + if keep_list: + writer.outputCommands = ["drop *"] + [f"keep {col}" for col in keep_list] + else: + writer.outputCommands = ["keep *"] + + return writer + + +def create_writer(format: str, writer_name: str, output_name: str, keep_list: Iterable = (), full_subset_list: Iterable = ()): + """ + Creates writer depending on the requested format + In contrast to its name an empty keep_list means keep everything + """ + if format == "lcio": + return _create_writer_lcio(writer_name, output_name, keep_list, full_subset_list) + elif format == "edm4hep": + return _create_writer_edm4hep(writer_name, output_name, keep_list) # FIXME: handle edm4hep subset collections! + else: + return None + # TODO: warn about format being unsupported but without killing --help From ad34156a556692308cf227f83570cb4fbaf8a37c Mon Sep 17 00:00:00 2001 From: Leonhard Reichenbach Date: Tue, 23 Apr 2024 19:01:08 +0200 Subject: [PATCH 4/9] remove outdated TODO --- CLDConfig/CLDReconstruction.py | 1 - 1 file changed, 1 deletion(-) diff --git a/CLDConfig/CLDReconstruction.py b/CLDConfig/CLDReconstruction.py index d66c1b4..05ae147 100644 --- a/CLDConfig/CLDReconstruction.py +++ b/CLDConfig/CLDReconstruction.py @@ -99,7 +99,6 @@ "HowOften": ["1"] } -# TODO: put this somewhere else, needs to be in front of the output for now :( # setup AIDA histogramming and add eventual background overlay algList.append(MyAIDAProcessor) sequenceLoader.load("Overlay/Overlay") From c6ee027acfa98184ed149887136a9ff1feba30ab Mon Sep 17 00:00:00 2001 From: Leonhard Reichenbach Date: Thu, 22 Aug 2024 09:19:02 +0200 Subject: [PATCH 5/9] add explicit argument for compact file --- CLDConfig/CLDReconstruction.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CLDConfig/CLDReconstruction.py b/CLDConfig/CLDReconstruction.py index 05ae147..0c3b1eb 100644 --- a/CLDConfig/CLDReconstruction.py +++ b/CLDConfig/CLDReconstruction.py @@ -32,6 +32,7 @@ parser.add_argument("--outputBasename", help="Basename of the output file(s)", default="output") parser.add_argument("--trackingOnly", action="store_true", help="Run only track reconstruction", default=False) parser.add_argument("--enableLCFIJet", action="store_true", help="Enable LCFIPlus jet clustering parts", default=False) +parser.add_argument("--compactFile", help="Compact detector file to use", type=str, default=os.environ["K4GEO"] + "/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml") reco_args = parser.parse_known_args()[0] algList = [] @@ -55,7 +56,7 @@ from Configurables import GeoSvc, TrackingCellIDEncodingSvc geoservice = GeoSvc("GeoSvc") -geoservice.detectors = [os.environ["K4GEO"]+"/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml"] +geoservice.detectors = [reco_args.compactFile] geoservice.OutputLevel = INFO geoservice.EnableGeant4Geo = False svcList.append(geoservice) From c9fdb294838dd2489716b53c9815550d8987ab98 Mon Sep 17 00:00:00 2001 From: Leonhard Reichenbach Date: Thu, 22 Aug 2024 09:19:51 +0200 Subject: [PATCH 6/9] put all custom arguments into a group --- CLDConfig/CLDReconstruction.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CLDConfig/CLDReconstruction.py b/CLDConfig/CLDReconstruction.py index 0c3b1eb..22ce194 100644 --- a/CLDConfig/CLDReconstruction.py +++ b/CLDConfig/CLDReconstruction.py @@ -28,11 +28,12 @@ ROOT.gROOT.SetBatch(True) -parser.add_argument("--inputFiles", action="extend", nargs="+", metavar=("file1", "file2"), help="One or multiple input files") -parser.add_argument("--outputBasename", help="Basename of the output file(s)", default="output") -parser.add_argument("--trackingOnly", action="store_true", help="Run only track reconstruction", default=False) -parser.add_argument("--enableLCFIJet", action="store_true", help="Enable LCFIPlus jet clustering parts", default=False) -parser.add_argument("--compactFile", help="Compact detector file to use", type=str, default=os.environ["K4GEO"] + "/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml") +parser_group = parser.add_argument_group("CLDReconstruction.py custom options") +parser_group.add_argument("--inputFiles", action="extend", nargs="+", metavar=("file1", "file2"), help="One or multiple input files") +parser_group.add_argument("--outputBasename", help="Basename of the output file(s)", default="output") +parser_group.add_argument("--trackingOnly", action="store_true", help="Run only track reconstruction", default=False) +parser_group.add_argument("--enableLCFIJet", action="store_true", help="Enable LCFIPlus jet clustering parts", default=False) +parser_group.add_argument("--compactFile", help="Compact detector file to use", type=str, default=os.environ["K4GEO"] + "/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml") reco_args = parser.parse_known_args()[0] algList = [] From bf6226282b5b5ce9feca39108922f51a4a27590c Mon Sep 17 00:00:00 2001 From: Leonhard Reichenbach Date: Thu, 22 Aug 2024 10:27:00 +0200 Subject: [PATCH 7/9] add argument group for tracking --- CLDConfig/CLDReconstruction.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CLDConfig/CLDReconstruction.py b/CLDConfig/CLDReconstruction.py index 22ce194..c1b5fda 100644 --- a/CLDConfig/CLDReconstruction.py +++ b/CLDConfig/CLDReconstruction.py @@ -34,6 +34,9 @@ parser_group.add_argument("--trackingOnly", action="store_true", help="Run only track reconstruction", default=False) parser_group.add_argument("--enableLCFIJet", action="store_true", help="Enable LCFIPlus jet clustering parts", default=False) parser_group.add_argument("--compactFile", help="Compact detector file to use", type=str, default=os.environ["K4GEO"] + "/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml") +tracking_group = parser_group.add_mutually_exclusive_group() +tracking_group.add_argument("--conformalTracking", action="store_true", default=True, help="Use conformal tracking pattern recognition") +tracking_group.add_argument("--truthTracking", action="store_true", default=False, help="Cheat tracking pattern recognition") reco_args = parser.parse_known_args()[0] algList = [] @@ -47,8 +50,6 @@ "CalorimeterIntegrationTimeWindowChoices": ["10ns", "400ns"], "Overlay": "False", "OverlayChoices": ["False", "91GeV", "365GeV"], - "Tracking": "Conformal", - "TrackingChoices": ["Truth", "Conformal"], "VertexUnconstrained": "OFF", "VertexUnconstrainedChoices": ["ON", "OFF"], "OutputMode": "EDM4Hep", @@ -108,9 +109,9 @@ sequenceLoader.load("Tracking/TrackingDigi") # tracking -if CONFIG["Tracking"] == "Truth": +if reco_args.truthTracking: sequenceLoader.load("Tracking/TruthTracking") -elif CONFIG["Tracking"] == "Conformal": +elif reco_args.conformalTracking: sequenceLoader.load("Tracking/ConformalTracking") sequenceLoader.load("Tracking/Refit") From c8609ab990b726f68fb90a8f4fed70524b6c44f2 Mon Sep 17 00:00:00 2001 From: Leonhard Reichenbach Date: Fri, 30 Aug 2024 13:07:18 +0200 Subject: [PATCH 8/9] Bump default CLD version to CLD_o2_v07 --- CLDConfig/CLDReconstruction.py | 2 +- test/CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CLDConfig/CLDReconstruction.py b/CLDConfig/CLDReconstruction.py index c1b5fda..107901b 100644 --- a/CLDConfig/CLDReconstruction.py +++ b/CLDConfig/CLDReconstruction.py @@ -33,7 +33,7 @@ parser_group.add_argument("--outputBasename", help="Basename of the output file(s)", default="output") parser_group.add_argument("--trackingOnly", action="store_true", help="Run only track reconstruction", default=False) parser_group.add_argument("--enableLCFIJet", action="store_true", help="Enable LCFIPlus jet clustering parts", default=False) -parser_group.add_argument("--compactFile", help="Compact detector file to use", type=str, default=os.environ["K4GEO"] + "/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml") +parser_group.add_argument("--compactFile", help="Compact detector file to use", type=str, default=os.environ["K4GEO"] + "/FCCee/CLD/compact/CLD_o2_v07/CLD_o2_v07.xml") tracking_group = parser_group.add_mutually_exclusive_group() tracking_group.add_argument("--conformalTracking", action="store_true", default=True, help="Use conformal tracking pattern recognition") tracking_group.add_argument("--truthTracking", action="store_true", default=False, help="Cheat tracking pattern recognition") diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fce9fcc..b898708 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -18,7 +18,7 @@ limitations under the License. ]] include(CTest) -set(DETECTOR $ENV{K4GEO}/FCCee/CLD/compact/CLD_o2_v06/CLD_o2_v06.xml) +set(DETECTOR $ENV{K4GEO}/FCCee/CLD/compact/CLD_o2_v07/CLD_o2_v07.xml) set(CLDConfig_DIR ${CMAKE_CURRENT_LIST_DIR}/../CLDConfig) add_test(NAME ddsim_lcio From ca7e3f5975239d48ba7a64d73fc157dbe834777e Mon Sep 17 00:00:00 2001 From: Leonhard Reichenbach Date: Fri, 30 Aug 2024 13:16:17 +0200 Subject: [PATCH 9/9] Add some more tests for the tracking arguments --- test/CMakeLists.txt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b898708..932f858 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -61,6 +61,24 @@ add_test(NAME LCFIJet ) set_property(TEST LCFIJet APPEND PROPERTY DEPENDS ddsim_edm4hep) +add_test(NAME tracking_truth + WORKING_DIRECTORY ${CLDConfig_DIR} + COMMAND k4run --trackingOnly --truthTracking --inputFiles=test.edm4hep.root --outputBasename=trkOnly_truth_test_edm4hep CLDReconstruction.py --GeoSvc.detectors=${DETECTOR} +) +set_property(TEST tracking_truth APPEND PROPERTY DEPENDS ddsim_edm4hep) + +add_test(NAME tracking_conformal + WORKING_DIRECTORY ${CLDConfig_DIR} + COMMAND k4run --trackingOnly --conformalTracking --inputFiles=test.edm4hep.root --outputBasename=trkOnly_conformal_test_edm4hep CLDReconstruction.py --GeoSvc.detectors=${DETECTOR} +) +set_property(TEST tracking_conformal APPEND PROPERTY DEPENDS ddsim_edm4hep) + +add_test(NAME tracking_both + WORKING_DIRECTORY ${CLDConfig_DIR} + COMMAND k4run --trackingOnly --conformalTracking --truthTracking CLDReconstruction.py +) +set_property(TEST tracking_both APPEND PROPERTY PASS_REGULAR_EXPRESSION "error: argument --truthTracking: not allowed with argument --conformalTracking") + add_test(NAME Help WORKING_DIRECTORY ${CLDConfig_DIR} COMMAND k4run --help CLDReconstruction.py