Skip to content

Commit

Permalink
Fix random DQM path order from ConfigBuilder in case of duplicate DQM…
Browse files Browse the repository at this point in the history
… sequences

PromptReco for Heavy Ions was generating different RECO configurations
for each job of the same Primary Dataset (and Run). This caused
problems during merging as the ParameterSet registry grew.

The difference between the RECO configurations was in how the DQM
sequences were assigned to DQM Paths. One source for random shuffling
was found to be in ConfigBuilder in case the expansion of the DQM
sequence specifier leads to duplicate sequences.

This commit fixes the path ordering, and adds a test for it.

Co-authored-by: Christopher Jones <[email protected]>
  • Loading branch information
makortel and Dr15Jones committed Sep 20, 2023
1 parent d8722ce commit fa87b9c
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 2 deletions.
5 changes: 3 additions & 2 deletions Configuration/Applications/python/ConfigBuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import collections
from subprocess import Popen,PIPE
import FWCore.ParameterSet.DictTypes as DictTypes
from FWCore.ParameterSet.OrderedSet import OrderedSet
class Options:
pass

Expand Down Expand Up @@ -2052,7 +2053,7 @@ def prepare_DQM(self, stepSpec = 'DQMOffline'):
self.expandMapping(postSequenceList,autoDQM,index=1)

if len(set(sequenceList))!=len(sequenceList):
sequenceList=list(set(sequenceList))
sequenceList=list(OrderedSet(sequenceList))
print("Duplicate entries for DQM:, using",sequenceList)

pathName='dqmoffline_step'
Expand Down Expand Up @@ -2099,7 +2100,7 @@ def prepare_HARVESTING(self, stepSpec = None):
self.expandMapping(harvestingList,combined_mapping,index=-1)

if len(set(harvestingList))!=len(harvestingList):
harvestingList=list(set(harvestingList))
harvestingList=list(OrderedSet(harvestingList))
print("Duplicate entries for HARVESTING, using",harvestingList)

for name in harvestingList:
Expand Down
1 change: 1 addition & 0 deletions Configuration/Applications/test/BuildFile.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<test name="TestConfigurationApplicationsConfigBuilder" command="python3 ${LOCALTOP}/src/Configuration/Applications/test/ConfigBuilderTest.py"/>
80 changes: 80 additions & 0 deletions Configuration/Applications/test/ConfigBuilderTest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import FWCore.ParameterSet.Config as cms
from Configuration.Applications.ConfigBuilder import ConfigBuilder, defaultOptions

import copy

def prepareDQMSequenceOrder():
options = copy.deepcopy(defaultOptions)
options.scenario = "Test"

process = cms.Process("Test")
process.a1 = cms.EDAnalyzer("A1")
process.a2 = cms.EDAnalyzer("A2")
process.a3 = cms.EDAnalyzer("A3")
process.a4 = cms.EDAnalyzer("A4")
process.seq1 = cms.Sequence(process.a1)
process.seq2 = cms.Sequence(process.a2)
process.seq3 = cms.Sequence(process.a3)
process.seq4 = cms.Sequence(process.a4)
process.ps1 = cms.Sequence()
process.ps2 = cms.Sequence()
process.ps3 = cms.Sequence()
process.ps3 = cms.Sequence()
process.ps4 = cms.Sequence()
return (options, process)

if __name__=="__main__":
import unittest

class TestModuleCommand(unittest.TestCase):
def setUp(self):
"""Nothing to do """
None

def testDQMSequenceOrder(self):
def extract(process, count):
if count == 0:
return []
ret = list(process.dqmoffline_step.moduleNames())
for i in range(1, count):
ret.extend(list(getattr(process, f"dqmoffline_{i}_step").moduleNames()))
return ret

# DQM sequences are unique
(options, process) = prepareDQMSequenceOrder()
order = [3, 1, 2]
cb = ConfigBuilder(options, process)
cb.prepare_DQM("+".join(f"seq{o}" for o in order))
self.assertEqual([f"a{o}" for o in order], extract(process, len(order)))

# Code in prepare_DQM() call assumes the 'sequenceList`
# has at least as many elements as `postSequenceList`. We
# can't fake 'postSequenceList' as it is also derived from
# the prepare_DQM() argument, but duplicates are not
# removed. The only handle we have (besides code changes,
# that are beyond this bug fix), is to modify the autoDQM.
from DQMOffline.Configuration.autoDQM import autoDQM
autoDQM_orig = copy.deepcopy(autoDQM)
autoDQM.clear()
autoDQM["alias1"] = ["seq1", "ps1", "not needed"]
autoDQM["alias2"] = ["seq2", "ps2", "not needed"]
autoDQM["alias3"] = ["seq3", "ps3", "not needed"]
# seq4 is used only to have the expanded and uniquified
# 'sequenceList' to have at least as many elements as
# 'postSequenceList'
autoDQM["alias4"] = ["seq2+seq4", "ps4", "not needed"]

order = [2, 1, 3]
cb = ConfigBuilder(options, process)
cb.prepare_DQM("+".join(f"@alias{o}" for o in order))
self.assertEqual([f"a{o}" for o in order], extract(process, len(order)))

cb = ConfigBuilder(options, process)
order = [2, 1, 4, 3]
cb.prepare_DQM("+".join(f"@alias{o}" for o in order))
self.assertEqual([f"a{o}" for o in order], extract(process, len(order)))

autoDQM.clear()
autoDQM.update(autoDQM_orig)

unittest.main()

0 comments on commit fa87b9c

Please sign in to comment.