From 0d694c61f6dee493bdf3774149e7c0637487be95 Mon Sep 17 00:00:00 2001 From: Joseph Earl Lambert <joseph.earl.lambert@cern.ch> Date: Fri, 3 May 2024 11:38:56 +0200 Subject: [PATCH] Add unit test for the text configuration update FullCPAlgorithmsTest so that the order matches the text config and is identical to the yaml config --- .../AnalysisAlgorithmsConfig/CMakeLists.txt | 15 +- .../data/for_compare.yaml | 30 +++- .../python/ConfigText_unitTest.py | 161 ++++++++++++++---- .../python/FullCPAlgorithmsTest.py | 147 ++++++++-------- 4 files changed, 239 insertions(+), 114 deletions(-) diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/CMakeLists.txt b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/CMakeLists.txt index a669f73dc73c..bcfda4923cca 100644 --- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/CMakeLists.txt +++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/CMakeLists.txt @@ -56,11 +56,6 @@ else() endif() -atlas_add_test( ConfigTextUnitTest - SCRIPT python/ConfigText_unitTest.py --text-config ${CONFIG_PATH} - POST_EXEC_SCRIPT nopost.sh - PROPERTIES TIMEOUT 30 ) - # This runs test jobs for both sequences and block configs. Currently # (26 Apr 24) we are running both, but the tests that compare their # output are disabled (i.e. commented out). The comparisons had @@ -71,6 +66,16 @@ atlas_add_test( ConfigTextUnitTest # out comparison tests. +atlas_add_test( ConfigTextCompareBuilder + SCRIPT python/ConfigText_unitTest.py --text-config ${CONFIG_PATH} --compare-builder --check-order + POST_EXEC_SCRIPT nopost.sh + PROPERTIES TIMEOUT 30 ) + +atlas_add_test( ConfigTextCompareBlock + SCRIPT python/ConfigText_unitTest.py --text-config ${CONFIG_PATH} --compare-block --check-order + POST_EXEC_SCRIPT nopost.sh + PROPERTIES TIMEOUT 30 ) + add_test_job( TestJobDataSequence data --for-compare --no-systematics ) add_test_job( TestJobDataConfig data --for-compare --block-config --no-systematics ) add_test_job( TestJobDataTextConfig data --for-compare --text-config ${CONFIG_PATH} --no-systematics ) diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/for_compare.yaml b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/for_compare.yaml index 6cbbab165e36..44d4ac7e83bb 100644 --- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/for_compare.yaml +++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/data/for_compare.yaml @@ -63,7 +63,29 @@ TauJets: quality: 'Tight' PtEtaSelection: {} -GeneratorLevelAnalysis: {} +SystObjectLink: + - containerName: 'AnaJets' + - containerName: 'AnaElectrons' + - containerName: 'AnaPhotons' + - containerName: 'AnaMuons' + - containerName: 'AnaTauJets' + +ObjectCutFlow: + - containerName: 'AnaJets' + selectionName: 'jvt' + - containerName: 'AnaElectrons' + selectionName: 'loose' + - containerName: 'AnaPhotons' + selectionName: 'tight' + - containerName: 'AnaMuons' + selectionName: 'medium' + - containerName: 'AnaTauJets' + selectionName: 'tight' + +GeneratorLevelAnalysis: + - saveCutBookkeepers: True + runNumber: 284500 + cutBookkeepersSystematics: True # containerName and selectionName must be defined in their respective blocks MissingET: @@ -87,8 +109,6 @@ OverlapRemoval: muons: 'AnaMuons.medium' Thinning: - - containerName: 'AnaJets' - outputName: 'OutJets' - containerName: 'AnaElectrons' outputName: 'OutElectrons' selectionName: 'loose' @@ -101,6 +121,8 @@ Thinning: - containerName: 'AnaTauJets' outputName: 'OutTauJets' selectionName: 'tight' + - containerName: 'AnaJets' + outputName: 'OutJets' # After configuring each container, many variables will be saved automatically. Output: @@ -118,7 +140,7 @@ Output: '': 'EventInfo' commands: - 'disable jet_select_baselineJvt.*' - - 'disable el_select_loose.*' - 'disable mu_select_medium.*' - 'disable ph_select_tight.*' - 'disable tau_select_tight.*' + - 'disable el_select_loose.*' diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigText_unitTest.py b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigText_unitTest.py index 82dddaa25895..5c18b175f475 100755 --- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigText_unitTest.py +++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/ConfigText_unitTest.py @@ -4,10 +4,51 @@ # # @author Joseph Lambert -def compareTextBuilder(yamlPath='') : +def compareConfigSeq(seq1, seq2, *, checkOrder=False): + """Compares two ConfigSequences""" + blocks1 = seq1._blocks + blocks2 = seq2._blocks + print("Block order for each config sequence") + print("\033[4m{0:<30} {1:<30}\033[0m".format("Sequence1", "Sequence2")) + for i in range(max(len(blocks1), len(blocks2))): + name1, name2 = '', '' + if i < len(blocks1): + name1 = blocks1[i].__class__.__name__ + if i < len(blocks2): + name2 = blocks2[i].__class__.__name__ + print(f"{name1:<30} {name2}") + if not checkOrder: + print("Sorting blocks by name (will not sort blocks with same name)") + blocks1.sort(key=lambda x: x.__class__.__name__) + blocks2.sort(key=lambda x: x.__class__.__name__) + if len(blocks1) != len(blocks2): + raise Exception("Number of blocks are different") + for i in range(len(blocks1)): + block1 = blocks1[i] + block2 = blocks2[i] + name1 = block1.__class__.__name__ + name2 = block2.__class__.__name__ + if name1 != name2: + raise Exception(f"In position {i} " + f"the first sequence results in {name1} " + f"and the second sequence results in {name2}") + for name in block1.getOptions(): + if name == 'groupName': + continue + value1 = block1.getOptionValue(name) + value2 = block2.getOptionValue(name) + if value1 != value2: + raise Exception(f"For block {name1}, the block " + f"option {name} the first sequence results in {value1} " + f"and the second sequence results in {value2}") + + +def compareTextBuilder(yamlPath='', *, checkOrder=False) : """ - Return result of comparing a ConfigSequence produced using the provided - YAML file and the one produced by the Builder sequence below. + Create a configSequence using provided YAML file and a + configSequence using ConfigText python commands and compare. + + Will raise an exception if configSequences differ """ # create text config object to build text configurations from AnalysisAlgorithmsConfig.ConfigText import TextConfig @@ -109,8 +150,38 @@ def compareTextBuilder(yamlPath='') : config.setOptions (containerName='AnaTauJets') config.setOptions (selectionDecoration='selectPtEta') + config.addBlock ('SystObjectLink') + config.setOptions (containerName='AnaJets') + config.addBlock ('SystObjectLink') + config.setOptions (containerName='AnaElectrons') + config.addBlock ('SystObjectLink') + config.setOptions (containerName='AnaPhotons') + config.addBlock ('SystObjectLink') + config.setOptions (containerName='AnaMuons') + config.addBlock ('SystObjectLink') + config.setOptions (containerName='AnaTauJets') + + config.addBlock ('ObjectCutFlow') + config.setOptions (containerName='AnaJets') + config.setOptions (selectionName='jvt') + config.addBlock ('ObjectCutFlow') + config.setOptions (containerName='AnaElectrons') + config.setOptions (selectionName='loose') + config.addBlock ('ObjectCutFlow') + config.setOptions (containerName='AnaPhotons') + config.setOptions (selectionName='tight') + config.addBlock ('ObjectCutFlow') + config.setOptions (containerName='AnaMuons') + config.setOptions (selectionName='medium') + config.addBlock ('ObjectCutFlow') + config.setOptions (containerName='AnaTauJets') + config.setOptions (selectionName='tight') + # GeneratorLevelAnalysis config.addBlock( 'GeneratorLevelAnalysis') + config.setOptions (saveCutBookkeepers=True) + config.setOptions (runNumber=284500) + config.setOptions (cutBookkeepersSystematics=True) # MissingET config.addBlock ('MissingET') @@ -133,9 +204,6 @@ def compareTextBuilder(yamlPath='') : # Thinning config.addBlock ('Thinning') - config.setOptions (containerName='AnaJets') - config.setOptions (outputName='OutJets') - config.addBlock ('Thinning') config.setOptions (containerName='AnaElectrons') config.setOptions (selectionName='loose') config.setOptions (outputName='OutElectrons') @@ -151,6 +219,9 @@ def compareTextBuilder(yamlPath='') : config.setOptions (containerName='AnaTauJets') config.setOptions (selectionName='tight') config.setOptions (outputName='OutTauJets') + config.addBlock ('Thinning') + config.setOptions (containerName='AnaJets') + config.setOptions (outputName='OutJets') config.addBlock ('Output') config.setOptions (treeName='analysis') @@ -167,45 +238,45 @@ def compareTextBuilder(yamlPath='') : config.setOptions (containers=outputContainers) disable_commands = [ 'disable jet_select_baselineJvt.*', - 'disable el_select_loose.*', 'disable mu_select_medium.*', 'disable ph_select_tight.*', 'disable tau_select_tight.*', + 'disable el_select_loose.*', ] config.setOptions (commands=disable_commands) # configure ConfigSequence configSeq = config.configure() + # create text config object to build text configurations + textConfig = TextConfig(yamlPath) + textConfigSeq = textConfig.configure() + + # compare - will raise error if False + compareConfigSeq(configSeq, textConfigSeq, checkOrder=checkOrder) + - ## produce ConfigSequecne with yaml file +def compareBlockConfig(yamlPath='', *, checkOrder=False) : + """ + Create a configSequence using provided YAML file and a + configSequence using the block configuration and compare. + + Will raise an exception if configSequences differ + """ + # create configSeq for block configuration + from AnalysisAlgorithmsConfig.FullCPAlgorithmsTest import makeSequenceBlocks + configSeq = makeSequenceBlocks(dataType='fullsim', algSeq=None, + forCompare=True, isPhyslite=False, forceEGammaFullSimConfig=True, + returnConfigSeq=True) + + # create text config object to build text configurations + from AnalysisAlgorithmsConfig.ConfigText import TextConfig textConfig = TextConfig(yamlPath) textConfigSeq = textConfig.configure() - ## Compare - buildBlocks = configSeq._blocks - textBlocks = textConfigSeq._blocks - if len(buildBlocks) != len(textBlocks): - raise Exception("Number of blocks are different") - for i in range(len(buildBlocks)): - buildBlock = buildBlocks[i] - textBlock = textBlocks[i] - buildName = buildBlock.__class__.__name__ - textName = textBlock.__class__.__name__ - if buildName != textName: - raise Exception(f"In position {i} " - f"the yaml file results in {textName} " - f"and the builder results in {buildName}") - for name in buildBlock.getOptions(): - if name == 'groupName': - continue - build = buildBlock.getOptionValue(name) - text = textBlock.getOptionValue(name) - if build != text: - raise Exception(f"For block {buildName}, the block " - f"option {name} the yaml file results in {text} " - f"and the builder results in {build}") - + # compare - will raise error if False + compareConfigSeq(configSeq, textConfigSeq, checkOrder=checkOrder) + if __name__ == '__main__': import os @@ -213,12 +284,32 @@ if __name__ == '__main__': parser = optparse.OptionParser() parser.add_option('--text-config', dest='text_config', default='', action='store', - help='Perform unit tests using the provided yaml file') + help='YAML file used in unit test') + parser.add_option('--compare-block', dest='compare_block', + default=False, action='store_true', + help='Compare config sequence from YAML and block configuration') + parser.add_option('--compare-builder', dest='compare_builder', + default=False, action='store_true', + help='Compare config sequence from YAML and python configuration') + parser.add_option('--check-order', dest='check_order', + default=False, action='store_true', + help='Require blocks to be in the same order') (options, args) = parser.parse_args() textConfig = options.text_config + compareBlock = options.compare_block + compareBuilder = options.compare_builder + checkOrder = options.check_order if not os.path.isfile(textConfig): raise FileNotFoundError(f"{textConfig} is not a file") - # compare text and builder - compareTextBuilder(textConfig) + # compare YAML and builder + if compareBuilder: + print("Comparing config sequences from the block and text" + "configuration methods") + compareTextBuilder(textConfig, checkOrder=checkOrder) + # compare YAML and block config + if compareBlock: + print("Comparing config sequences from the block and block" + "configuration methods") + compareBlockConfig(textConfig, checkOrder=checkOrder) diff --git a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py index 22a579ecb40b..3a2a008547d5 100644 --- a/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py +++ b/PhysicsAnalysis/Algorithms/AnalysisAlgorithmsConfig/python/FullCPAlgorithmsTest.py @@ -650,7 +650,9 @@ def makeSequenceOld (dataType, algSeq, forCompare, isPhyslite, noSystematics, fo def makeSequenceBlocks (dataType, algSeq, forCompare, isPhyslite, - geometry=None, autoconfigFromFlags=None, noSystematics=None, onlyNominalOR=False, forceEGammaFullSimConfig=False) : + geometry=None, autoconfigFromFlags=None, noSystematics=None, + onlyNominalOR=False, forceEGammaFullSimConfig=False, + returnConfigSeq=False) : vars = [] metVars = [] @@ -715,8 +717,8 @@ def makeSequenceBlocks (dataType, algSeq, forCompare, isPhyslite, if not forCompare : configSeq.setOptionValue ('.recalibratePhyslite', False) - # Add systematic object links - configSeq += config.makeConfig('SystObjectLink', containerName='AnaJets') + configSeq += config.makeConfig( 'Jets.JVT', + containerName='AnaJets' ) btagger = "DL1dv01" btagWP = "FixedCutBEff_60" @@ -727,9 +729,6 @@ def makeSequenceBlocks (dataType, algSeq, forCompare, isPhyslite, configSeq.setOptionValue ('.btagger', btagger) configSeq.setOptionValue ('.btagWP', btagWP) - configSeq += config.makeConfig( 'Jets.JVT', - containerName='AnaJets' ) - if not forCompare: configSeq += config.makeConfig( 'Jets.FlavourTaggingEventSF', containerName='AnaJets.baselineJvt', @@ -743,9 +742,6 @@ def makeSequenceBlocks (dataType, algSeq, forCompare, isPhyslite, jetCollection='AntiKt10UFOCSSKSoftDropBeta100Zcut10Jets' ) configSeq.setOptionValue ('.postfix', 'largeR_jets' ) outputContainers['larger_jet_'] = 'OutLargeRJets' - - # Add systematic object links - configSeq += config.makeConfig('SystObjectLink', containerName='AnaLargeRJets') if not forCompare : configSeq.setOptionValue ('.recalibratePhyslite', False) @@ -756,9 +752,26 @@ def makeSequenceBlocks (dataType, algSeq, forCompare, isPhyslite, configSeq.setOptionValue ('.postfix', 'track_jets' ) outputContainers['track_jet_'] = 'OutTrackJets' + configSeq += config.makeConfig ('Jets.PtEtaSelection', + containerName='AnaJets') + configSeq.setOptionValue ('.selectionDecoration', 'selectPtEta') + configSeq.setOptionValue ('.minPt', jetMinPt) + configSeq.setOptionValue ('.maxEta', jetMaxEta) + if largeRJets : + configSeq += config.makeConfig ('Jets.PtEtaSelection', + containerName='AnaLargeRJets') + configSeq.setOptionValue ('.selectionDecoration', 'selectPtEta') + configSeq.setOptionValue ('.minPt', jetMinPt) + configSeq.setOptionValue ('.maxEta', jetMaxEta) + if trackJets : + configSeq += config.makeConfig ('Jets.PtEtaSelection', + containerName='AnaTrackJets') + configSeq.setOptionValue ('.selectionDecoration', 'selectPtEta') + configSeq.setOptionValue ('.minPt', jetMinPt) + configSeq.setOptionValue ('.maxEta', jetMaxEta) + # Include, and then set up the electron analysis algorithm sequence: - likelihood = True recomputeLikelihood=False configSeq += config.makeConfig ('Electrons', @@ -779,8 +792,12 @@ def makeSequenceBlocks (dataType, algSeq, forCompare, isPhyslite, configSeq.setOptionValue ('.isolationWP', 'Loose_VarRad') configSeq.setOptionValue ('.recomputeLikelihood', recomputeLikelihood) - # Add systematic object links - configSeq += config.makeConfig('SystObjectLink', containerName='AnaElectrons') + configSeq += config.makeConfig ('Electrons.PtEtaSelection', + containerName='AnaElectrons') + configSeq.setOptionValue ('.selectionDecoration', 'selectPtEta') + configSeq.setOptionValue ('.minPt', electronMinPt) + configSeq.setOptionValue ('.maxEta', electronMaxEta) + # Include, and then set up the photon analysis algorithm sequence: configSeq += config.makeConfig ('Photons', @@ -799,8 +816,11 @@ def makeSequenceBlocks (dataType, algSeq, forCompare, isPhyslite, configSeq.setOptionValue ('.isolationWP', 'FixedCutTight') configSeq.setOptionValue ('.recomputeIsEM', False) - # Add systematic object links - configSeq += config.makeConfig('SystObjectLink', containerName='AnaPhotons') + configSeq += config.makeConfig ('Photons.PtEtaSelection', + containerName='AnaPhotons') + configSeq.setOptionValue ('.selectionDecoration', 'selectPtEta') + configSeq.setOptionValue ('.minPt', photonMinPt) + configSeq.setOptionValue ('.maxEta', photonMaxEta) # set up the muon analysis algorithm sequence: @@ -820,8 +840,11 @@ def makeSequenceBlocks (dataType, algSeq, forCompare, isPhyslite, # configSeq.setOptionValue ('.quality', 'Tight') # configSeq.setOptionValue ('.isolation', 'Loose_VarRad') - # Add systematic object links - configSeq += config.makeConfig('SystObjectLink', containerName='AnaMuons') + configSeq += config.makeConfig ('Muons.PtEtaSelection', + containerName='AnaMuons') + configSeq.setOptionValue ('.selectionDecoration', 'selectPtEta') + configSeq.setOptionValue ('.minPt', muonMinPt) + configSeq.setOptionValue ('.maxEta', muonMaxEta) # Include, and then set up the tau analysis algorithm sequence: @@ -832,7 +855,22 @@ def makeSequenceBlocks (dataType, algSeq, forCompare, isPhyslite, selectionName='tight') configSeq.setOptionValue ('.quality', 'Tight') + configSeq += config.makeConfig ('TauJets.PtEtaSelection', + containerName='AnaTauJets') + configSeq.setOptionValue ('.selectionDecoration', 'selectPtEta') + configSeq.setOptionValue ('.minPt', tauMinPt) + configSeq.setOptionValue ('.maxEta', tauMaxEta) + + # Add systematic object links + configSeq += config.makeConfig('SystObjectLink', containerName='AnaJets') + if largeRJets: + configSeq += config.makeConfig('SystObjectLink', containerName='AnaLargeRJets') + if trackJets: + configSeq += config.makeConfig('SystObjectLink', containerName='AnaTrackJets') + configSeq += config.makeConfig('SystObjectLink', containerName='AnaElectrons') + configSeq += config.makeConfig('SystObjectLink', containerName='AnaPhotons') + configSeq += config.makeConfig('SystObjectLink', containerName='AnaMuons') configSeq += config.makeConfig('SystObjectLink', containerName='AnaTauJets') @@ -844,60 +882,6 @@ def makeSequenceBlocks (dataType, algSeq, forCompare, isPhyslite, configSeq.setOptionValue ('.cutBookkeepersSystematics', True) - configSeq += config.makeConfig ('Electrons.PtEtaSelection', - containerName='AnaElectrons') - configSeq.setOptionValue ('.selectionDecoration', 'selectPtEta') - configSeq.setOptionValue ('.minPt', electronMinPt) - configSeq.setOptionValue ('.maxEta', electronMaxEta) - configSeq += config.makeConfig ('Photons.PtEtaSelection', - containerName='AnaPhotons') - configSeq.setOptionValue ('.selectionDecoration', 'selectPtEta') - configSeq.setOptionValue ('.minPt', photonMinPt) - configSeq.setOptionValue ('.maxEta', photonMaxEta) - configSeq += config.makeConfig ('Muons.PtEtaSelection', - containerName='AnaMuons') - configSeq.setOptionValue ('.selectionDecoration', 'selectPtEta') - configSeq.setOptionValue ('.minPt', muonMinPt) - configSeq.setOptionValue ('.maxEta', muonMaxEta) - configSeq += config.makeConfig ('TauJets.PtEtaSelection', - containerName='AnaTauJets') - configSeq.setOptionValue ('.selectionDecoration', 'selectPtEta') - configSeq.setOptionValue ('.minPt', tauMinPt) - configSeq.setOptionValue ('.maxEta', tauMaxEta) - configSeq += config.makeConfig ('Jets.PtEtaSelection', - containerName='AnaJets') - configSeq.setOptionValue ('.selectionDecoration', 'selectPtEta') - configSeq.setOptionValue ('.minPt', jetMinPt) - configSeq.setOptionValue ('.maxEta', jetMaxEta) - if largeRJets : - configSeq += config.makeConfig ('Jets.PtEtaSelection', - containerName='AnaLargeRJets') - configSeq.setOptionValue ('.selectionDecoration', 'selectPtEta') - configSeq.setOptionValue ('.minPt', jetMinPt) - configSeq.setOptionValue ('.maxEta', jetMaxEta) - if trackJets : - configSeq += config.makeConfig ('Jets.PtEtaSelection', - containerName='AnaTrackJets') - configSeq.setOptionValue ('.selectionDecoration', 'selectPtEta') - configSeq.setOptionValue ('.minPt', jetMinPt) - configSeq.setOptionValue ('.maxEta', jetMaxEta) - - configSeq += config.makeConfig ('ObjectCutFlow', - containerName='AnaElectrons', - selectionName='loose') - configSeq += config.makeConfig ('ObjectCutFlow', - containerName='AnaPhotons', - selectionName='tight') - configSeq += config.makeConfig ('ObjectCutFlow', - containerName='AnaMuons', - selectionName='medium') - configSeq += config.makeConfig ('ObjectCutFlow', - containerName='AnaTauJets', - selectionName='tight') - configSeq += config.makeConfig ('ObjectCutFlow', - containerName='AnaJets', - selectionName='jvt') - # Include, and then set up the met analysis algorithm config: configSeq += config.makeConfig ('MissingET', containerName='AnaMET') @@ -948,6 +932,25 @@ def makeSequenceBlocks (dataType, algSeq, forCompare, isPhyslite, selectionCutsDict = exampleSelectionCuts, noFilter = True) + # ObjectCutFlow blocks + configSeq += config.makeConfig ('ObjectCutFlow', + containerName='AnaJets', + selectionName='jvt') + configSeq += config.makeConfig ('ObjectCutFlow', + containerName='AnaElectrons', + selectionName='loose') + configSeq += config.makeConfig ('ObjectCutFlow', + containerName='AnaPhotons', + selectionName='tight') + configSeq += config.makeConfig ('ObjectCutFlow', + containerName='AnaMuons', + selectionName='medium') + configSeq += config.makeConfig ('ObjectCutFlow', + containerName='AnaTauJets', + selectionName='tight') + + + # Thinning blocks configSeq += config.makeConfig ('Thinning', containerName='AnaElectrons') configSeq.setOptionValue ('.selectionName', 'loose') @@ -1013,6 +1016,10 @@ def makeSequenceBlocks (dataType, algSeq, forCompare, isPhyslite, disable_commands.append('disable el_select_loose.*') configSeq.setOptionValue ('.commands', disable_commands) + # return configSeq for unit test + if returnConfigSeq: + return configSeq + configAccumulator = ConfigAccumulator (algSeq, dataType, isPhyslite, geometry, autoconfigFromFlags=autoconfigFromFlags, noSystematics=noSystematics) configSeq.fullConfigure (configAccumulator) -- GitLab