diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 707711d63ef66513a694a2a3557f36b72e74f8c0..f75cf02e8163b8be2fd31c812394944b9a83faee 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,5 +1,5 @@ -############################################################################### -## (c) Copyright 2023 CERN for the benefit of the LHCb Collaboration # +################################################################################ +## (c) Copyright 2000-2023 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". # @@ -25,6 +25,15 @@ check-copyright: default: image: gitlab-registry.cern.ch/lhcb-core/lbdocker/centos7-build:latest +python-linting: + stage: Lint + tags: + - cvmfs + script: + - . /cvmfs/lhcb.cern.ch/lib/LbEnv.sh + # TODO: get rid of ignores and run on full directory ! + - flake8 --extend-ignore E501 $(find Phys/StrippingConf/python/StrippingConf/ -name '*.py') + .setup_script_2016: before_script: - source /cvmfs/lhcb.cern.ch/lib/LbEnv diff --git a/Phys/StrippingConf/python/StrippingConf/Configuration.py b/Phys/StrippingConf/python/StrippingConf/Configuration.py old mode 100755 new mode 100644 index 479a36ebc3c052f882e5335fd6e71662b0a97e95..5d1f9d9b413d7b5a27c694243f3a9c11f85b8c33 --- a/Phys/StrippingConf/python/StrippingConf/Configuration.py +++ b/Phys/StrippingConf/python/StrippingConf/Configuration.py @@ -1,5 +1,5 @@ ############################################################################### -# (c) Copyright 2000-2019 CERN for the benefit of the LHCb Collaboration # +# (c) Copyright 2000-2023 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". # @@ -9,44 +9,44 @@ # or submit itself to any jurisdiction. # ############################################################################### """ -High level configuration tools for StrippingConf, to be used with Moore and DaVinci +High level configuration tools for StrippingConf, +to be used with Moore and DaVinci. """ -__author__ = "Anton Poluektov <A.O.Poluektov@warwick.ac.uk>" +from __future__ import print_function +__author__ = "Anton Poluektov <A.O.Poluektov@warwick.ac.uk>" +from StrippingStream import StrippingStream +from Configurables import StrippingAlg +from Gaudi.Configuration import log, WARNING # -# Configuration of stripping framework. +# Configuration of stripping framework. # -from os import environ -from pprint import * -from Gaudi.Configuration import * -from Configurables import StrippingAlg -from StrippingStream import StrippingStream -from StrippingLine import StrippingLine -from Utils import limitCombinatorics - -class StrippingConf ( object ) : - - def __init__( self, - name = "", - TESPrefix = 'Strip', - HDRLocation = 'Phys/DecReports', - Streams = [], - DSTStreams = [], - MicroDSTStreams = [], - GlobalFlavourTagging = True, - BadEventSelection = None, - AcceptBadEvents = True, - MaxCandidates = None, - MaxCombinations = None, - ActiveMDSTStream = False, - Verbose = False ) : - - log.info("Initialising StrippingConf "+ name) - if name == "" : +from Utils import limitCombinatorics + + +class StrippingConf (object): + + def __init__(self, + name="", + TESPrefix='Strip', + HDRLocation='Phys/DecReports', + Streams=[], + DSTStreams=[], + MicroDSTStreams=[], + GlobalFlavourTagging=True, + BadEventSelection=None, + AcceptBadEvents=True, + MaxCandidates=None, + MaxCombinations=None, + ActiveMDSTStream=False, + Verbose=False): + + log.info("Initialising StrippingConf " + name) + if name == "": self._name = "StrippingGlobal" - else : + else: self._name = name self._verbose = Verbose @@ -66,32 +66,33 @@ class StrippingConf ( object ) : self.MaxCandidates = MaxCandidates self.MaxCombinations = MaxCombinations - ## To be uncommented to limit combinatorics for StandardParticles - if self.MaxCandidates != None or self.MaxCombinations != None: + # To be uncommented to limit combinatorics for StandardParticles + if self.MaxCandidates is not None or self.MaxCombinations is not None: self.limitCombForStdParticles() - ## Forces the limits on all configurables that implement the option... - if self.MaxCandidates != None or self.MaxCombinations != None: + # Forces the limits on all configurables that implement the option... + if self.MaxCandidates is not None or self.MaxCombinations is not None: self.checkAllForCombLimit() self.checkFlavourTagging(Streams) linesForFT = [] if self._GlobalFlavourTagging: - for stream in Streams: - for line in stream.lines: - if line._EnableFlavourTagging: - line._EnableFlavourTagging = False - linesForFT += [ line ] + for stream in Streams: + for line in stream.lines: + if line._EnableFlavourTagging: + line._EnableFlavourTagging = False + linesForFT += [line] - for stream in Streams : + for stream in Streams: self.appendStream(stream) - # Global FT locations have to be filled after appending streams, - # because outputLocations of lines can be redefined + # Global FT locations have to be filled after appending streams, + # because outputLocations of lines can be redefined if self._GlobalFlavourTagging: - for line in linesForFT: - self._taggingLocations += [ line.outputLocation().replace("/Particles","") ] + for line in linesForFT: + self._taggingLocations += [ + line.outputLocation().replace("/Particles", "")] if self._GlobalFlavourTagging and self._taggingLocations != []: self.appendFlavourTagging() @@ -100,437 +101,497 @@ class StrippingConf ( object ) : self.checkUniqueOutputLocations() if self._verbose: - self.checkRawEventRequests() - self.checkMDSTFlag() + self.checkRawEventRequests() + self.checkMDSTFlag() if self._activeMDST: - mdstLines = [ line for line in self.activeLines(self.MicroDSTStreams) if line.MDSTFlag ] + mdstLines = [line for line in self.activeLines( + self.MicroDSTStreams) if line.MDSTFlag] if self._verbose: - mdstLinesNames = [ line.name() for line in mdstLines ] + mdstLinesNames = [line.name() for line in mdstLines] log.warning("The lines going to FTAG.DST are") - print mdstLinesNames - log.warning("This was the former MDST.DST which is now a regular DST stream. This implementation should only be present in S28") - + print(mdstLinesNames) + log.warning( + "This was the former MDST.DST which is now a regular DST stream. This implementation should only be present in S28") # noqa + if mdstLines != []: - mdstStream = StrippingStream( "FTAG", Lines = mdstLines ) - self.appendStream(mdstStream) + mdstStream = StrippingStream("FTAG", Lines=mdstLines) + self.appendStream(mdstStream) else: - log.warning("No line has been selected to go to the FTAG stream (former MDST), thus it will be skipped") - + log.warning( + "No line has been selected to go to the FTAG stream (former MDST), thus it will be skipped") # noqa + from Gaudi.Configuration import appendPostConfigAction - appendPostConfigAction ( defaultToolConfigCheck ) + appendPostConfigAction(defaultToolConfigCheck) - def checkRawEventRequests(self) : - for stream in self.activeStreams() : stream.checkRawEventRequests() + def checkRawEventRequests(self): + for stream in self.activeStreams(): + stream.checkRawEventRequests() - def checkMDSTFlag(self) : - for stream in self.activeStreams() : stream.checkMDSTFlag() + def checkMDSTFlag(self): + for stream in self.activeStreams(): + stream.checkMDSTFlag() - def checkFlavourTagging(self,streams) : - for stream in streams : - if stream.name() in self.DSTStreams : stream.checkFlavourTagging(disableFT=True,verbose=self._verbose) - elif stream.name() in self.MicroDSTStreams : stream.checkFlavourTagging(disableFT=False,verbose=self._verbose) - else : stream.checkFlavourTagging(disableFT=False,verbose=self._verbose) + def checkFlavourTagging(self, streams): + for stream in streams: + if stream.name() in self.DSTStreams: + stream.checkFlavourTagging( + disableFT=True, verbose=self._verbose) + elif stream.name() in self.MicroDSTStreams: + stream.checkFlavourTagging( + disableFT=False, verbose=self._verbose) + else: + stream.checkFlavourTagging( + disableFT=False, verbose=self._verbose) - def checkAppendedLines (self) : + def checkAppendedLines(self): """ Check if all declared lines are appended to streams """ allAppended = True from StrippingLine import strippingLines - for line in strippingLines() : - if not line.isAppended() : - log.warning("Line " + line.name() + " is declared but not appended to any stream") + for line in strippingLines(): + if not line.isAppended(): + log.warning("Line " + line.name() + + " is declared but not appended to any stream") allAppended = False - - if allAppended : + + if allAppended: log.info("All declared lines are appended to streams") - def checkUniqueOutputLocations (self) : + def checkUniqueOutputLocations(self): """ Check if the output locations of all active lines are unique """ log.info("Checking uniqueness of output locations") - import sys locations = {} - for stream in self.activeStreams() : - for line in stream.lines : + for stream in self.activeStreams(): + for line in stream.lines: location = line.outputLocation() - if location and location != '' : - if location not in locations.keys() : - locations[location] = [ (line.name(),stream.name()) ] - else : - locations[location] += [ (line.name(),stream.name()) ] + if location and location != '': + if location not in locations.keys(): + locations[location] = [(line.name(), stream.name())] + else: + locations[location] += [(line.name(), stream.name())] locationsUnique = True locationsUniqueSameStream = True message = '' messagesamestream = '' - for loc, nameandstream in locations.iteritems() : - if len(nameandstream) > 1 : + for loc, nameandstream in locations.iteritems(): + if len(nameandstream) > 1: innermessage = '' innerlines = {} for ns in nameandstream: - if innermessage=='': - innermessage=str(ns[0])+"(stream "+str(ns[1])+")" + if innermessage == '': + innermessage = str(ns[0])+"(stream "+str(ns[1])+")" else: - innermessage+=" ,"+str(ns[0])+"(stream "+str(ns[1])+")" - if ns[1] not in innerlines.keys() : + innermessage += " ," + \ + str(ns[0])+"(stream "+str(ns[1])+")" + if ns[1] not in innerlines.keys(): innerlines[ns[1]] = [ns[0]] else: - innerlines[ns[1]] += [ ns[0] ] - message += "\tLines "+innermessage+" share the same output location '"+loc+"'\n" - #sys.stderr.write(message) + innerlines[ns[1]] += [ns[0]] + message += "\tLines "+innermessage+" share the same output location '"+loc+"'\n" # noqa + # sys.stderr.write(message) locationsUnique = False - #print innerlines - - for stinner, linner in innerlines.iteritems() : - if len(linner) > 1 : + # print innerlines + + for stinner, linner in innerlines.iteritems(): + if len(linner) > 1: inmsg = '' for inl in linner: - if inmsg=='': - inmsg=str(inl)+"(stream "+stinner+")" + if inmsg == '': + inmsg = str(inl)+"(stream "+stinner+")" else: - inmsg=" ,"+str(inl)+"(stream "+stinner+")" - messagesamestream+="\tLines "+inmsg+" share the same output location '"+loc+"' and the same stream '"+stinner+"! Please remove duplicates in configuration'\n" + inmsg = " ,"+str(inl)+"(stream "+stinner+")" + messagesamestream += "\tLines "+inmsg + \ + " share the same output location '"+loc + \ + "' and the same stream '"+stinner+"! Please remove duplicates in configuration'\n" # noqa locationsUniqueSameStream = False - - - - if not locationsUnique : - #raise Exception('\n' + message) + + if not locationsUnique: + # raise Exception('\n' + message) log.warning('\n' + message) - if not locationsUniqueSameStream : - #raise Exception('\n' + message) + if not locationsUniqueSameStream: + # raise Exception('\n' + message) raise Exception('\n' + messagesamestream) - - def activeStreams (self) : + def activeStreams(self): """ - Return the list of all active StrippingStreams. + Return the list of all active StrippingStreams. """ return self._streams - def activeLines (self,selStream = [] ) : + def activeLines(self, selStream=[]): """ - Return the list of all stripping lines + Return the list of all stripping lines. """ streams = self.activeStreams() lines = [] for stream in streams: - if selStream != [] and stream.name() in selStream: - for line in stream.lines: - lines.append(line) - elif selStream == []: - for line in stream.lines: - lines.append(line) - + if selStream != [] and stream.name() in selStream: + for line in stream.lines: + lines.append(line) + elif selStream == []: + for line in stream.lines: + lines.append(line) + return lines - def sequence (self) : + def sequence(self): """ Return GaudiSequencer containing stream sequencers """ from Configurables import GaudiSequencer - log.debug("Initialising GaudiSequencer/"+ self._name) - if self._sequence == None : - log.debug("Initialising GaudiSequencer/"+ self._name) + log.debug("Initialising GaudiSequencer/" + self._name) + if self._sequence is None: + log.debug("Initialising GaudiSequencer/" + self._name) selSeq = GaudiSequencer(self._name+"_Selection", - ModeOR = True, - ShortCircuit = False, - OutputLevel = WARNING, - Members = self._streamSequencers) + ModeOR=True, + ShortCircuit=False, + OutputLevel=WARNING, + Members=self._streamSequencers) - self._sequence = GaudiSequencer(self._name,Members = [selSeq]) + self._sequence = GaudiSequencer(self._name, Members=[selSeq]) if self._GlobalFlavourTagging and self._taggingLocations != []: self._sequence.Members += [self._taggingSeq] return self._sequence - def selections (self) : + def selections(self): """ Return list of selection names for TagCreator """ - _selections = [ self._name ] - for stream in self._streams : + _selections = [self._name] + for stream in self._streams: streamName = stream.sequence().name() _selections.append(streamName) - for line in stream.lines : + for line in stream.lines: _selections.append(line.name()) return _selections - def appendStreams(self, streams) : + def appendStreams(self, streams): """ Append a list of streams to the configuration. """ - for stream in streams : + for stream in streams: self.appendStream(stream) - - def appendStream(self, stream) : + + def appendStream(self, stream): """ Append a StrippingStream to the configuration. Takes care of adding corresponding sequencer to _streamSequencers list. """ - log.info(self._name+ " appending stream "+ stream.name()) - - if stream.TESPrefix == None : + log.info(self._name + " appending stream " + stream.name()) + + if stream.TESPrefix is None: stream.TESPrefix = self._tesPrefix stream.HDRLocation = self._hdrLocation - if stream.BadEventSelection == "Override" : - if isinstance(self.BadEventSelection,dict): - if stream.name() in self.BadEventSelection.keys(): - stream.BadEventSelection = self.BadEventSelection[stream.name()] - log.info(self._name+ " setting BadEventSelection for stream "+ stream.name() + " as " + str(stream.BadEventSelection)) - else: - stream.BadEventSelection = self.BadEventSelection['default'] - log.info(self._name+ " setting BadEventSelection for stream "+ stream.name() + " as " + str(stream.BadEventSelection)) - log.info(self._name+ " setting BadEventSelection for stream "+ stream.name()) + if stream.BadEventSelection == "Override": + if isinstance(self.BadEventSelection, dict): + if stream.name() in self.BadEventSelection.keys(): + stream.BadEventSelection = self.BadEventSelection[stream.name()] # noqa + log.info(self._name + + " setting BadEventSelection for stream " + + stream.name() + " as " + + str(stream.BadEventSelection)) + else: + stream.BadEventSelection = self.BadEventSelection['default'] # noqa + log.info(self._name + + " setting BadEventSelection for stream " + + stream.name() + " as " + + str(stream.BadEventSelection)) + log.info(self._name + + " setting BadEventSelection for stream " + + stream.name()) else: - stream.BadEventSelection = self.BadEventSelection - if stream.AcceptBadEvents == None : - if isinstance(self.AcceptBadEvents,dict): - if stream.name() in self.AcceptBadEvents.keys(): - stream.AcceptBadEvents = self.AcceptBadEvents[stream.name()] - log.info(self._name+ " setting AcceptBadEvents for stream "+ stream.name() + " as " + str(stream.AcceptBadEvents)) - else: - stream.AcceptBadEvents = self.AcceptBadEvents['default'] - log.info(self._name+ " setting AcceptBadEvents for stream "+ stream.name() + " as " + str(stream.AcceptBadEvents)) - log.info(self._name+ " setting AcceptBadEvents for stream "+ stream.name()) + stream.BadEventSelection = self.BadEventSelection + if stream.AcceptBadEvents is None: + if isinstance(self.AcceptBadEvents, dict): + if stream.name() in self.AcceptBadEvents.keys(): + stream.AcceptBadEvents = self.AcceptBadEvents[stream.name( + )] + log.info(self._name + + " setting AcceptBadEvents for stream " + + stream.name() + " as " + + str(stream.AcceptBadEvents)) + else: + stream.AcceptBadEvents = self.AcceptBadEvents['default'] + log.info(self._name + + " setting AcceptBadEvents for stream " + + stream.name() + + " as " + str(stream.AcceptBadEvents)) + log.info( + self._name + " setting AcceptBadEvents for stream " + + stream.name()) else: - stream.AcceptBadEvents = self.AcceptBadEvents + stream.AcceptBadEvents = self.AcceptBadEvents + + if stream.MaxCandidates == "Override": + stream.MaxCandidates = self.MaxCandidates + if stream.MaxCombinations == "Override": + stream.MaxCombinations = self.MaxCombinations - if stream.MaxCandidates == "Override" : - stream.MaxCandidates = self.MaxCandidates - if stream.MaxCombinations == "Override" : - stream.MaxCombinations = self.MaxCombinations - stream.createConfigurables() self._streams.append(stream) self._appendSequencer(stream) - def appendFlavourTagging(self) : + def appendFlavourTagging(self): from Configurables import BTagging, BTaggingTool, GaudiSequencer from FlavourTagging.Tunings import applyTuning - btag = BTagging( "BTag_Global",Inputs = self._taggingLocations ) + btag = BTagging("BTag_Global", Inputs=self._taggingLocations) btag.addTool(BTaggingTool) applyTuning(btag.BTaggingTool) - self._taggingSeq = GaudiSequencer("BTaggingSequence", Members = [btag]) - - def _appendSequencer(self, stream) : + self._taggingSeq = GaudiSequencer("BTaggingSequence", Members=[btag]) + + def _appendSequencer(self, stream): self._streamSequencers.append(stream.sequence()) - def decReportLocations(self) : + def decReportLocations(self): locs = [] - for stream in self._streams : - for line in stream.lines : + for stream in self._streams: + for line in stream.lines: loc = line.decReportLocation() - if loc != None and loc not in locs : locs.append(loc) + if loc is not None and loc not in locs: + locs.append(loc) return locs - def limitCombForStdParticles(self,incidentName = 'ExceedsCombinatoricsLimit'): + def limitCombForStdParticles(self, + incidentName='ExceedsCombinatoricsLimit'): from StandardParticles import locations as stdLoc - for loc,alg in stdLoc.iteritems(): - if hasattr(type(alg),'StopAtMaxCandidates') and \ - hasattr(type(alg),'MaxCandidates') and \ - hasattr(type(alg),'StopAtMaxCombinations') and \ - hasattr(type(alg),'MaxCombinations'): - if self.MaxCandidates != None: + for loc, alg in stdLoc.iteritems(): + if hasattr(type(alg), 'StopAtMaxCandidates') and \ + hasattr(type(alg), 'MaxCandidates') and \ + hasattr(type(alg), 'StopAtMaxCombinations') and \ + hasattr(type(alg), 'MaxCombinations'): + if self.MaxCandidates is not None: alg.StopAtMaxCandidates = True alg.MaxCandidates = self.MaxCandidates - if self.MaxCombinations != None: + if self.MaxCombinations is not None: alg.StopAtMaxCombinations = True alg.MaxCombinations = self.MaxCombinations - if self.MaxCandidates != None or self.MaxCombinations != None : + if self.MaxCandidates is not None or self.MaxCombinations is not None: # noqa alg.StopIncidentType = incidentName - ## comment to be removed once performed some more test - #if self._verbose: log.warning('Changed parameters StopAtMaxCandidates = '+str(alg.StopAtMaxCandidates)+' MaxCandidates = '+str(alg.MaxCandidates)+' StopIncidentType = '+str(alg.StopIncidentType)+' for algorithm '+str(alg.name())) - + # comment to be removed once performed some more test + # if self._verbose: log.warning('Changed parameters StopAtMaxCandidates = '+str(alg.StopAtMaxCandidates)+' MaxCandidates = '+str(alg.MaxCandidates)+' StopIncidentType = '+str(alg.StopIncidentType)+' for algorithm '+str(alg.name())) # noqa # Loops over all known configurables and applies MaxCandidate limits - def checkAllForCombLimit(self) : - '''Limit the combinatorics of all configurables using self.MaxCandidates and self.MaxCombinations, - unless these have already been configured. This is normally called before the streams are appended - & their configurables created.''' - if self.MaxCandidates == None and self.MaxCombinations == None : + def checkAllForCombLimit(self): + ''' + Limit the combinatorics of all configurables + using self.MaxCandidates and self.MaxCombinations, + unless these have already been configured. + This is normally called before the streams are appended + & their configurables created. + ''' + + if self.MaxCandidates is None and self.MaxCombinations is None: return from Gaudi.Configuration import allConfigurables - - for conf in allConfigurables.values() : - limitCombinatorics(conf, self.MaxCandidates, self.MaxCombinations, False) + + for conf in allConfigurables.values(): + limitCombinatorics(conf, self.MaxCandidates, + self.MaxCombinations, False) # ============================================================================= -# Some useful decorations +# Some useful decorations # ============================================================================= -## Calculate the effective length of the string -# which is the length from the last '\n'-symbol -def len1 ( line ) : +# Calculate the effective length of the string +# which is the length from the last '\n'-symbol +def len1(line): """ Calculate the effective length of the line, - which is thw length from the last '\n'-symbol + which is thw length from the last '\n'-symbol """ _i = line.rfind('\n') return len(line) if _i < 0 else len(line) - _i -## the major properties/attributes -_stripping_props_ = [ 'AcceptFraction' , - 'PercertPass' , - 'L0Channels' , - 'InputSelection' , - 'InputSelection1' , - 'InputSelection2' , - 'InputSelection3' , - 'InputSelections' , - 'OutputSelection' , - 'RecoName' , - 'MatchName' , - 'FilterDescription' ] - -## Get the tuple of major interesting properties for Hlt1 objects -def strippingProps () : + +# the major properties/attributes +_stripping_props_ = ['AcceptFraction', + 'PercertPass', + 'L0Channels', + 'InputSelection', + 'InputSelection1', + 'InputSelection2', + 'InputSelection3', + 'InputSelections', + 'OutputSelection', + 'RecoName', + 'MatchName', + 'FilterDescription'] + +# Get the tuple of major interesting properties for Hlt1 objects + + +def strippingProps(): """ Get the tuple of major interesting properties for Hlt1 objects """ - _stripping_props_.sort() + _stripping_props_.sort() return tuple(_stripping_props_) # ============================================================================= -## Try to promote a string to the corresponding configurable -def string2Configurable( name ) : +# Try to promote a string to the corresponding configurable +def string2Configurable(name): # try to decode it into something reasonable - (n,t) = (name,None) if name.find('/') == -1 else name.split('/') + (n, t) = (name, None) if name.find('/') == -1 else name.split('/') from Gaudi.Configuration import allConfigurables cfg = allConfigurables.get(n) - if cfg : - if ( t and cfg.getType() == t ) or cfg.getType() == 'ConfigurableGeneric' : + if cfg: + if (t and cfg.getType() == t) or cfg.getType() == 'ConfigurableGeneric': # noqa return cfg - else : - print 'got something for %s, don\'t know what to do with %s'%(self,str(cfg)) + else: + print('got something for %s, don\'t know what to do with %s' % + (name, str(cfg))) return None - print 'cannot convert %s into a known configurable' % name + print('cannot convert %s into a known configurable' % name) return None # ============================================================================= -## Print the major properties/attributes of the configurables +# Print the major properties/attributes of the configurables # @param obj the object to be inspected -# @param lst list of attributes/properties +# @param lst list of attributes/properties # @param line the (output) line # @paral l1 the indentation parameter # @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl # @date 2008-08-06 -def prnt ( obj , # the object - lst = [] , # list of 'major' properties - line = '' , # the line to eb updated - l1 = 65 ) : # the indentation/format parameter + + +def prnt(obj, # the object + lst=[], # list of 'major' properties + line='', # the line to eb updated + l1=65): # the indentation/format parameter """ Print the major properties/attributes of the configurables @param obj the object to be inspected - @param lst list of attributes/properties + @param lst list of attributes/properties @param line the (output) line @paral l1 the indentation parameter @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl @date 2008-08-06 >>> obj = ... # get the object/configurable - >>> print prnt ( obj , [ 'OutputLevel' , 'Members'] ) # print... - + >>> print prnt ( obj , [ 'OutputLevel' , 'Members'] ) # print... + """ - if not lst : lst = strippingProps () - elif list is type(lst) : pass - elif tuple is type(lst) : pass - else : lst = [ lst ] + if not lst: + lst = strippingProps() + elif list is type(lst): + pass + elif tuple is type(lst): + pass + else: + lst = [lst] # - for item in lst : - if hasattr ( obj , item ) : - if l1 < len1( line ) : line += '\n' + l1*' ' - line += "%-15s : %s" % ( item , getattr ( obj , item ) ) - return line + for item in lst: + if hasattr(obj, item): + if l1 < len1(line): + line += '\n' + l1*' ' + line += "%-15s : %s" % (item, getattr(obj, item)) + return line # ============================================================================= -## The helper function for narcissic self-print of sequences & algorithms +# The helper function for narcissic self-print of sequences & algorithms # @param self the object to be inspected # @param level the recursion level -# @param lst the list of major properties/attributes +# @param lst the list of major properties/attributes # @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl # @date 2008-08-06 -def __enroll__ ( self , ## the object - level = 0 , ## the recursion level - lst = [] ) : ## the major properties + + +def __enroll__(self, # the object + level=0, # the recursion level + lst=[]): # the major properties """ - The helper function for narcissic self-print of sequences & algorithms + The helper function for narcissic self-print of sequences & algorithms @param self the object to be inspected @param level the recursion level - @param lst the list of major properties/attributes + @param lst the list of major properties/attributes @author Vanya BELYAEV Ivan.Belyaev@nikhef.nl @date 2008-08-06 - + """ - if type(self) == str : + if type(self) == str: cfg = string2Configurable(self) - if cfg : self = cfg - if hasattr ( self , 'sequence' ) : - return __enroll__ ( self.sequence() , level ) - if hasattr ( self , 'sequencer' ) : - return __enroll__ ( self.sequencer() , level ) + if cfg: + self = cfg + if hasattr(self, 'sequence'): + return __enroll__(self.sequence(), level) + if hasattr(self, 'sequencer'): + return __enroll__(self.sequencer(), level) _tab = 50 - _indent_ = ('%-3d'%level) + level * ' ' - try: line = _indent_ + self.name () - except: line = _indent_ + ( self if type(self) == str else '<UNKNOWN>' ) - - if len1(line)>( _tab-1): line += '\n'+ _tab*' ' - else : line += (_tab-len1(line))*' ' - try: line += '%-25.25s'%self.getType() - except: line += '<UNKNOWN>' - - line = prnt ( self , lst , line, l1 = _tab+25 ) + '\n' - - # use the recursion - if hasattr ( self , 'Members' ) : - for _m in getattr(self,'Members') : line += __enroll__ ( _m , level + 1 , lst ) - - if type(self) is StrippingAlg : - for i in [ 'Prescale','ODIN','L0DU','HLT','Filter1','Postscale' ] : - if hasattr(self,i) : line += __enroll__( getattr(self,i), level + 1, lst ) - - if type(self) is StrippingConf : + _indent_ = ('%-3d' % level) + level * ' ' + try: + line = _indent_ + self.name() + except: # noqa + line = _indent_ + (self if type(self) == str else '<UNKNOWN>') + + if len1(line) > (_tab-1): + line += '\n' + _tab*' ' + else: + line += (_tab-len1(line))*' ' + try: + line += '%-25.25s' % self.getType() + except: # noqa + line += '<UNKNOWN>' + + line = prnt(self, lst, line, l1=_tab+25) + '\n' + + # use the recursion + if hasattr(self, 'Members'): + for _m in getattr(self, 'Members'): + line += __enroll__(_m, level + 1, lst) + + if type(self) is StrippingAlg: + for i in ['Prescale', 'ODIN', 'L0DU', 'HLT', 'Filter1', 'Postscale']: + if hasattr(self, i): + line += __enroll__(getattr(self, i), level + 1, lst) + + if type(self) is StrippingConf: lines = 0 - for i in self.activeStreams() : + for i in self.activeStreams(): lines += len(i.sequence().Members) - line += "Summary: " + len(self.sequence().Members) + " streams, " + lines + " lines\n" + line += "Summary: " + len(self.sequence().Members) + \ + " streams, " + lines + " lines\n" return line -def defaultToolConfigCheck () : + +def defaultToolConfigCheck(): from Gaudi.Configuration import allConfigurables - + log.info('Checking if public tools have default configuration') - for conf in allConfigurables.values() : - if conf.name().find('ToolSvc.')>=0 : + for conf in allConfigurables.values(): + if conf.name().find('ToolSvc.') >= 0: difference = [] - if isinstance(type(conf).__slots__,dict) : - for k,v in type(conf).__slots__.iteritems() : - if hasattr(conf, k) : - val = getattr(conf,k) - if val not in allConfigurables.values() : - if v != val : - difference.append( (k, v, val ) ) - if len(difference) > 0 : - log.warning( 'tool %s has non-default configuration! Attributes that differ:' % conf.name() ) - for d in difference : - log.warning( ' %s = %s (default = %s)' % ( d[0], str(d[2]), str(d[1]) ) ) - - -for conf in [ StrippingAlg, StrippingStream, StrippingConf] : - if conf : - conf.__str__ = __enroll__ - + if isinstance(type(conf).__slots__, dict): + for k, v in type(conf).__slots__.iteritems(): + if hasattr(conf, k): + val = getattr(conf, k) + if val not in allConfigurables.values(): + if v != val: + difference.append((k, v, val)) + if len(difference) > 0: + log.warning( + 'tool %s has non-default configuration! Attributes that differ:' % conf.name()) # noqa + for d in difference: + log.warning(' %s = %s (default = %s)' % + (d[0], str(d[2]), str(d[1]))) + + +for conf in [StrippingAlg, StrippingStream, StrippingConf]: + if conf: + conf.__str__ = __enroll__ diff --git a/Phys/StrippingConf/python/StrippingConf/StrippingConfigurableUser.py b/Phys/StrippingConf/python/StrippingConf/StrippingConfigurableUser.py old mode 100755 new mode 100644 index f10e7d7a07d680a1c76026e09c3aaa1f16700714..6200459c70eb02aa7d79115fa3aa9533ae7579e1 --- a/Phys/StrippingConf/python/StrippingConf/StrippingConfigurableUser.py +++ b/Phys/StrippingConf/python/StrippingConf/StrippingConfigurableUser.py @@ -18,7 +18,6 @@ __all__ = ( 'StrippingConfigurableUser' ) -from GaudiConf.Configuration import * from Configurables import LHCbConfigurableUser diff --git a/Phys/StrippingConf/python/StrippingConf/StrippingLine.py b/Phys/StrippingConf/python/StrippingConf/StrippingLine.py index c40e31bd36c6efc17d7230139429cb1caa634dab..7acce40146b82c5f91faf7d7ea16bc5bdaf3f3b9 100755 --- a/Phys/StrippingConf/python/StrippingConf/StrippingLine.py +++ b/Phys/StrippingConf/python/StrippingConf/StrippingLine.py @@ -1,6 +1,6 @@ #!/usr/bin/env python ############################################################################### -# (c) Copyright 2000-2019 CERN for the benefit of the LHCb Collaboration # +# (c) Copyright 2000-2023 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". # @@ -10,6 +10,8 @@ # or submit itself to any jurisdiction. # ############################################################################### +from __future__ import print_function + # # StrippingLine # @@ -112,7 +114,7 @@ def _add_to_stripping_lines_( line ) : """ lname = line.name() if lname in _stripping_lines__: - raise ValueError,"Created StrippingLine with duplicate name %s" % lname + raise ValueError,"Created StrippingLine with duplicate name %s" % lname # noqa _stripping_lines__[lname] = line @@ -865,8 +867,8 @@ class StrippingLine(object): lines) matches[expr] = linematches if not linematches : - print 'WARNING: For line', self.name(), 'trigger requirement', \ - expr, 'doesn\'t match any trigger line!' + print('WARNING: For line' + self.name() + 'trigger requirement' + + expr + 'doesn\'t match any trigger line!') return matches def _extract_hlt_exprs(self, code) : diff --git a/Phys/StrippingConf/python/StrippingConf/StrippingStream.py b/Phys/StrippingConf/python/StrippingConf/StrippingStream.py old mode 100755 new mode 100644 index 69f9bd0a539d6829d16ea93be127ddc507e27a99..d1487d95a3085b1fb7300c5fe28ce411b8010808 --- a/Phys/StrippingConf/python/StrippingConf/StrippingStream.py +++ b/Phys/StrippingConf/python/StrippingConf/StrippingStream.py @@ -1,6 +1,6 @@ #!/usr/bin/env python ############################################################################### -# (c) Copyright 2000-2019 CERN for the benefit of the LHCb Collaboration # +# (c) Copyright 2000-2023 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". # @@ -14,50 +14,49 @@ # StrippingStream # -__all__ = ( - 'StrippingStream' - ) +__all__ = ('StrippingStream') -from Gaudi.Configuration import * -from Gaudi.Configuration import GaudiSequencer, Sequencer, Configurable -from Configurables import LHCbConfigurableUser +from Gaudi.Configuration import log, GaudiSequencer +from Gaudi.Configuration import WARNING from copy import copy -class StrippingStream ( object ) : - def __init__ ( self, - name = 'StrippingStream', - Lines = [], # List of stream lines - BadEventSelection = "Override", # Bad event selection algo - # By default, it will be - # overridden in StrippingConf, - # but can be set to None here - # to cancel bad event check - - AcceptBadEvents = None, # If None, will be overridden - # in StrippingConf - MaxCandidates = "Override", - MaxCombinations = "Override", - TESPrefix = None - ) : +class StrippingStream(object): + def __init__(self, + name='StrippingStream', + Lines=[], # List of stream lines + BadEventSelection="Override", # Bad event selection algo + # By default, it will be + # overridden in StrippingConf, + # but can be set to None here + # to cancel bad event check + AcceptBadEvents=None, # If None, will be overridden + # in StrippingConf + MaxCandidates="Override", + MaxCombinations="Override", + TESPrefix=None + ): self._name = name self.lines = [] for line in Lines: - if line.prescale() > 0: - self.lines += [line] - else: - log.warning('Line '+line.name()+' has prescale <= 0, it will be removed from stream '+self.name()) + if line.prescale() > 0: + self.lines += [line] + else: + log.warning('Line '+line.name() + + ' has prescale <= 0, it will be removed from stream ' + + self.name() + ) - for line in Lines : - line.declareAppended() + for line in Lines: + line.declareAppended() self.algs = [] self.seq = None self.streamLine = None # Line with OR of all stream lines, created in createConfigurables() self.eventSelectionLine = None # Line to mark bad events, created in createConfigurables() - self.goodEventFilter = None # filter to reject bad events + self.goodEventFilter = None # filter to reject bad events self.BadEventSelection = BadEventSelection self.AcceptBadEvents = AcceptBadEvents self.MaxCandidates = MaxCandidates @@ -65,46 +64,48 @@ class StrippingStream ( object ) : self.TESPrefix = TESPrefix # Prefix for DecReports location, configured when appending stream self.HDRLocation = 'Phys/DecReports' # DecReports location, configured when appending to StrippingConf - def name(self) : + def name(self): return self._name - def clone(self, name) : - return StrippingStream(name, Lines = copy(self.lines), - BadEventSelection = self.BadEventSelection, - AcceptBadEvents = self.AcceptBadEvents, - MaxCandidates = self.MaxCandidates, - MaxCombinations = self.MaxCombinations) - - def appendLines (self, lines) : - for line in lines : + def clone(self, name): + return StrippingStream(name, + Lines=copy(self.lines), + BadEventSelection=self.BadEventSelection, + AcceptBadEvents=self.AcceptBadEvents, + MaxCandidates=self.MaxCandidates, + MaxCombinations=self.MaxCombinations + ) + + def appendLines(self, lines): + for line in lines: self.lines.append(line) line.declareAppended() - def createConfigurables(self) : - from Configurables import StrippingCheck - + def createConfigurables(self): # Create configurables - if self.TESPrefix == None : self.TESPrefix = self._name + if self.TESPrefix is None: + self.TESPrefix = self._name from StrippingLine import StrippingLine # If the BadEventsSelection was not given neither in StrippingConf nor in StrippingStream - if self.BadEventSelection == "Override" : + if self.BadEventSelection == "Override": self.BadEventSelection = None # Make the line to mark bad events (those satisfying BadEventSelection) - if self.BadEventSelection != None : + if self.BadEventSelection is not None: # create the line that select bad events self.eventSelectionLine = StrippingLine("Stream"+self.name()+"BadEvent", - checkPV = False, - algos = [ self.BadEventSelection ] ) - self.eventSelectionLine.createConfigurable( self.TESPrefix, self.HDRLocation ) + checkPV=False, + algos=[self.BadEventSelection] + ) + self.eventSelectionLine.createConfigurable(self.TESPrefix, self.HDRLocation) self.eventSelectionLine.declareAppended() - if self.AcceptBadEvents != False : + if self.AcceptBadEvents is not False: # Need to think a bit more on this log.error("NOT POSSIBLE TO ACCEPT BAD EVENTS WITH THE CURRENT CONFIGURATION OF STRIPPINGCONF!!!") @@ -112,68 +113,70 @@ class StrippingStream ( object ) : else: - # Create a filter that negates the bad events (select good events). + # Create a filter that negates the bad events (select good events). # This filter will be inserted at the beginning of the filters run by all the lines. from Configurables import LoKi__VoidFilter as Filter - self.goodEventFilter = Filter( "StrippingGoodEventCondition"+self.name() , - Code = " ALG_EXECUTED('%s') & ~ALG_PASSED('%s') " - % (self.eventSelectionLine.name(), self.eventSelectionLine.name()) , - Preambulo = [ "from LoKiHlt.algorithms import *" ] ) - - - for line in self.lines : - if line.MaxCandidates == "Override" : + self.goodEventFilter = Filter("StrippingGoodEventCondition"+self.name(), + Code=" ALG_EXECUTED('%s') & ~ALG_PASSED('%s') " + % (self.eventSelectionLine.name(), self.eventSelectionLine.name()), + Preambulo=["from LoKiHlt.algorithms import *"] + ) + + for line in self.lines: + if line.MaxCandidates == "Override": line.MaxCandidates = self.MaxCandidates - if line.MaxCombinations == "Override" : + if line.MaxCombinations == "Override": line.MaxCombinations = self.MaxCombinations - if self.BadEventSelection != None : - if not self.AcceptBadEvents != False : + if self.BadEventSelection is not None: + if self.AcceptBadEvents is not True: # inserting filter for good events inside the lines - if not "StrippingGoodEventCondition" in line._members[0].name() : - line._members.insert(0,self.goodEventFilter) + if "StrippingGoodEventCondition" not in line._members[0].name(): + line._members.insert(0, self.goodEventFilter) - if line.prescale() > 0. : - line.createConfigurable( self.TESPrefix, self.HDRLocation ) - log.debug("ADDING configurable " + line.configurable().name() + "to stream " + self.name() ) + if line.prescale() > 0.: + line.createConfigurable(self.TESPrefix, self.HDRLocation) + log.debug("ADDING configurable " + line.configurable().name() + "to stream " + self.name()) self.algs.append(line.configurable()) - - else : - line.RequiredRawEvents = None #forcing None rawevents to avoid (harmless) errors from the DSTWriter - log.warning("Line " + line.name() + " has zero prescale, skipping" ) + else: + line.RequiredRawEvents = None # forcing None rawevents to avoid (harmless) errors from the DSTWriter + log.warning("Line " + line.name() + " has zero prescale, skipping") # Make the line for stream decision (OR of all stream lines) linesSeq = GaudiSequencer("StrippingStreamSeq"+self.name(), - ModeOR = True, - #ShortCircuit = False, - OutputLevel = WARNING, - Members = self.algs) - - self.streamLine = StrippingLine("Stream"+self.name(), checkPV = False, algos = [ linesSeq ] ) - ## I think it is redundant, otherwise if it comes out it is needed - ## uncomment the following lines - #if self.BadEventSelection != None : - # if not self.AcceptBadEvents != False : - # if not "StrippingGoodEventCondition" in self.streamLine._members[0].name() : + ModeOR=True, + # ShortCircuit=False, + OutputLevel=WARNING, + Members=self.algs) + + self.streamLine = StrippingLine("Stream"+self.name(), + checkPV=False, + algos=[linesSeq]) + # I think it is redundant, otherwise if it comes out it is needed + # uncomment the following lines + # if self.BadEventSelection != None: + # if not self.AcceptBadEvents != False: + # if not "StrippingGoodEventCondition" in self.streamLine._members[0].name(): # self.streamLine._members.insert(0,self.goodEventFilter) - self.streamLine.createConfigurable( self.TESPrefix, self.HDRLocation ) + self.streamLine.createConfigurable(self.TESPrefix, self.HDRLocation) self.streamLine.declareAppended() - def sequence ( self ) : - if self.seq == None : + def sequence(self): + if self.seq is None: - if self.eventSelectionLine == None: + if self.eventSelectionLine is None: # We don't care of BadEvents, thus not insert bad event line in the stream sequence self.seq = GaudiSequencer("StrippingSequenceStream"+self.name(), - ModeOR = True, - ShortCircuit = False, - OutputLevel = WARNING, - Members = self.algs + [ self.streamLine.configurable() ] ) + ModeOR=True, + ShortCircuit=False, + OutputLevel=WARNING, + Members=self.algs + [self.streamLine.configurable()] + ) else: - if self.AcceptBadEvents != False : + if self.AcceptBadEvents: # Need to think a bit more on this log.error("NOT POSSIBLE TO ACCEPT BAD EVENTS WITH THE CURRENT CONFIGURATION OF STRIPPINGCONF!!!") @@ -183,96 +186,100 @@ class StrippingStream ( object ) : # since we care of bad events we have to protect the execution of lines and stream-line # inserting them in a sequence with ModeOR = True and ShortCircuit = False. lineSeq = GaudiSequencer("StrippingProtectedSequence"+self.name(), - ModeOR = True, - ShortCircuit = False, - OutputLevel = WARNING, - Members = self.algs + [ self.streamLine.configurable() ] ) + ModeOR=True, + ShortCircuit=False, + OutputLevel=WARNING, + Members=self.algs + [self.streamLine.configurable()] + ) # We need a badEventSeq with IgnoreFilterPassed = True in order to always run the protected sequence with # lines and stream-lines badEventSeq = GaudiSequencer("StrippingBadEventSequence"+self.name(), - Members = [ self.eventSelectionLine.configurable() ], - OutputLevel = WARNING, - IgnoreFilterPassed = True) + Members=[self.eventSelectionLine.configurable()], + OutputLevel=WARNING, + IgnoreFilterPassed=True) - # The final sequence is an AND sequence of the badEventSeq and the lines + stream-lines - # algorithms (protected sequence) + # The final sequence is an AND sequence of the badEventSeq + # and the lines + stream-lines algorithms (protected sequence) self.seq = GaudiSequencer("StrippingSequenceStream"+self.name(), - OutputLevel = WARNING, - Members = [ badEventSeq, lineSeq ] ) + OutputLevel=WARNING, + Members=[badEventSeq, lineSeq] + ) return self.seq - - def outputLocations (self) : + def outputLocations(self): outputList = [] - for i in self.lines : + for i in self.lines: output = i.outputLocation() - if output : + if output: outputList.append(output) return outputList - - def filterMembers( self ) : + def filterMembers(self): _members = [] - for line in self.lines : + for line in self.lines: lineMembers = line.filterMembers() - for i in lineMembers : - if i not in _members : _members.append(i) + for i in lineMembers: + if i not in _members: + _members.append(i) return _members - - def getRequiredRawEvents(self) : - rawEvents = { } - for line in self.lines : - if ( line.RequiredRawEvents != None ) : - rawEvents[line.name()] = [ "/Event/"+r+"/RawEvent#1" for r in line.RequiredRawEvents ] + def getRequiredRawEvents(self): + rawEvents = {} + for line in self.lines: + if (line.RequiredRawEvents is not None): + rawEvents[line.name()] = ["/Event/" + r + "/RawEvent#1" for r in line.RequiredRawEvents] return rawEvents + def checkRawEventRequests(self): + for line in self.lines: + if line.RequiredRawEvents is not None: + log.debug("Stream='"+self.name() + "' Line='" + line.name() + + "' Requests RawEvents " + str(line.RequiredRawEvents)) - def checkRawEventRequests(self) : - for line in self.lines : - if line.RequiredRawEvents != None : - log.debug("Stream='"+self.name()+"' Line='"+line.name()+ - "' Requests RawEvents "+str(line.RequiredRawEvents)) - - def checkMDSTFlag(self) : - for line in self.lines : - if line.MDSTFlag : - log.debug("Stream='"+self.name()+"' Line='"+line.name()+ + def checkMDSTFlag(self): + for line in self.lines: + if line.MDSTFlag: + log.debug("Stream='" + self.name() + "' Line='" + line.name() + "' Requests to go to MDST.DST") - def checkFlavourTagging(self,disableFT=False,verbose=False) : - for line in self.lines : - if line._EnableFlavourTagging : - if verbose : log.debug("Stream='"+self.name()+"' Line='"+line.name()+ - "' Requests to run FlavourTagging") + def checkFlavourTagging(self, disableFT=False, verbose=False): + for line in self.lines: + if line._EnableFlavourTagging: + if verbose: + log.debug("Stream='" + self.name() + "' Line='" + line.name() + + "' Requests to run FlavourTagging") if disableFT: line._EnableFlavourTagging = False - log.warning("Stream='"+self.name()+"' Line='"+line.name()+"' Requests Flavor Tagging but is not assigned to a micro-dst stream, Flavour Tagging has been disabled") + log.warning("Stream='" + self.name() + "' Line='" + + line.name() + + "' Requests Flavor Tagging but is not assigned to a micro-dst stream, Flavour Tagging has been disabled") # noqa - def checkPVRefit(self) : - for line in self.lines : + def checkPVRefit(self): + for line in self.lines: sel = line.selection() - #for algo in line._algos: - if sel != None: + # for algo in line._algos: + if sel is not None: props = sel.algorithm().getProperties() if props.has_key('ReFitPVs'): - if props['ReFitPVs'] == True: - log.warning("Stream='"+self.name()+"' Line='"+line.name()+ - "' Requests to refit the PV") + if props['ReFitPVs']: + log.warning("Stream='" + self.name() + "' Line='" + + line.name() + "' Requests to refit the PV") - def getRelatedInfoLocations(self) : + def getRelatedInfoLocations(self): locations = [] - for line in self.lines : - if line.RelatedInfoTools != None : - for tool in line.RelatedInfoTools : - if 'Locations' in tool.keys() : + for line in self.lines: + if line.RelatedInfoTools is not None: + for tool in line.RelatedInfoTools: + if 'Locations' in tool.keys(): locs = tool['Locations'] - for part,loc in locs.iteritems() : - if loc not in locations : locations += [ loc ] - if 'Location' in tool.keys() : + for part, loc in locs.iteritems(): + if loc not in locations: + locations += [loc] + if 'Location' in tool.keys(): loc = tool['Location'] - if loc not in locations : locations += [ loc ] - log.info("RelatedInfoLocations for stream %s: %s" % (self.name(), str(locations)) ) + if loc not in locations: + locations += [loc] + log.info("RelatedInfoLocations for stream %s: %s" % (self.name(), str(locations))) return locations diff --git a/Phys/StrippingConf/python/StrippingConf/Utils.py b/Phys/StrippingConf/python/StrippingConf/Utils.py index dc34518f1e7463db91405011180967b92d34e000..bca422c6bfdee314690ef1d0a2e853af81f77afa 100644 --- a/Phys/StrippingConf/python/StrippingConf/Utils.py +++ b/Phys/StrippingConf/python/StrippingConf/Utils.py @@ -1,5 +1,5 @@ ############################################################################### -# (c) Copyright 2000-2019 CERN for the benefit of the LHCb Collaboration # +# (c) Copyright 2000-2023 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". # @@ -19,17 +19,22 @@ from Gaudi.Configuration import log def _limitCombinatoricsMaxCandidates(configurable, MaxCandidates, MaxCombinations, force, incidentName): - '''Limit combinatorics of a configurable assuming it has MaxCandidates, - StopAtMaxCandidates, MaxCombinations, StopAtMaxCombinations and StopIncidentType attributes.''' + ''' + Limit combinatorics of a configurable assuming it has MaxCandidates, + StopAtMaxCandidates, MaxCombinations, StopAtMaxCombinations + and StopIncidentType attributes. + ''' didsomething = False - if (force or not configurable.isPropertySet('MaxCandidates')) and None != MaxCandidates: + if (force or not configurable.isPropertySet('MaxCandidates')) and \ + (MaxCandidates is not None): log.debug("Forcing MaxCandidates settings for " + configurable.name()) configurable.MaxCandidates = MaxCandidates configurable.StopAtMaxCandidates = True didsomething = True - if (force or not configurable.isPropertySet('MaxCombinations')) and None != MaxCombinations: - log.debug("Forcing MaxCombinations settings for " + configurable.name()) + if (force or not configurable.isPropertySet('MaxCombinations')) and \ + (MaxCombinations is not None): + log.debug("Forcing MaxCombinations settings for " + configurable.name()) # noqa configurable.MaxCombinations = MaxCombinations configurable.StopAtMaxCombinations = True didsomething = True @@ -38,11 +43,18 @@ def _limitCombinatoricsMaxCandidates(configurable, MaxCandidates, return didsomething -def _limitCombinatoricsMaxParticles(configurable, MaxCandidates, force, incidentName): - '''Limit combinatorics for a configurable assuming it's got MaxParticles & StopIncidentType - attributes.''' +def _limitCombinatoricsMaxParticles(configurable, + MaxCandidates, + force, + incidentName): + ''' + Limit combinatorics for a configurable + assuming it's got MaxParticles & StopIncidentType + attributes. + ''' - if (force or not configurable.isPropertySet('MaxParticles')) and None != MaxCandidates: + if (force or not configurable.isPropertySet('MaxParticles')) and \ + (MaxCandidates is not None): log.debug("Forcing MaxParticles settings for " + configurable.name()) configurable.MaxParticles = MaxCandidates configurable.StopIncidentType = incidentName @@ -82,9 +94,11 @@ def limitCombinatorics(configurable, force, incidentName='ExceedsCombinatoricsLimit'): """ - - This function has the highest call counts. So it needs careful optimization. - - Because the action is reactive, it's best to order the case of most-probable - to the least-probable to exit the check as early as possible. + - This function has the highest call counts. + So it needs careful optimization. + - Because the action is reactive, it's best to order + the case of most-probable to the least-probable + to exit the check as early as possible. """ # Check the name by string is MUCH FASTER than by class. @@ -102,13 +116,22 @@ def limitCombinatorics(configurable, conf, MaxCandidates, MaxCombinations, force, incidentName) return val - if classname in ('CombineParticles', 'DaVinci__N3BodyDecays', 'DaVinci__N4BodyDecays', 'DaVinci__N5BodyDecays'): - return _limitCombinatoricsMaxCandidates(configurable, MaxCandidates, MaxCombinations, force, incidentName) + if classname in ('CombineParticles', + 'DaVinci__N3BodyDecays', + 'DaVinci__N4BodyDecays', + 'DaVinci__N5BodyDecays' + ): + return _limitCombinatoricsMaxCandidates(configurable, + MaxCandidates, + MaxCombinations, + force, + incidentName) if classname == 'StrippingAlg': val = False stages = ['Filter1'] - for conf in [getattr(configurable, stage) for stage in stages if hasattr(configurable, stage)]: + for conf in [getattr(configurable, stage) + for stage in stages if hasattr(configurable, stage)]: val |= limitCombinatorics( conf, MaxCandidates, MaxCombinations, force, incidentName) if val: @@ -116,15 +139,28 @@ def limitCombinatorics(configurable, return val if classname in ('SubPIDMMFilter', 'SubstitutePID'): - return _limitCombinatoricsMaxParticles(configurable, MaxCandidates, force, incidentName) + return _limitCombinatoricsMaxParticles(configurable, + MaxCandidates, + force, + incidentName) # Generic handling (slow) - if hasattr(type(configurable), 'StopAtMaxCandidates') and hasattr(type(configurable), 'MaxCandidates') and \ - hasattr(type(configurable), 'StopAtMaxCombinations') and hasattr(type(configurable), 'MaxCombinations'): - return _limitCombinatoricsMaxCandidates(configurable, MaxCandidates, MaxCombinations, force, incidentName) - - if hasattr(configurable, 'MaxParticles') and hasattr(configurable, 'StopIncidentType'): - return _limitCombinatoricsMaxParticles(configurable, MaxCandidates, force, incidentName) + if hasattr(type(configurable), 'StopAtMaxCandidates') and \ + hasattr(type(configurable), 'MaxCandidates') and \ + hasattr(type(configurable), 'StopAtMaxCombinations') and \ + hasattr(type(configurable), 'MaxCombinations'): + return _limitCombinatoricsMaxCandidates(configurable, + MaxCandidates, + MaxCombinations, + force, + incidentName) + + if (hasattr(configurable, 'MaxParticles') and + hasattr(configurable, 'StopIncidentType')): + return _limitCombinatoricsMaxParticles(configurable, + MaxCandidates, + force, + incidentName) # Generic handling (slow) if hasattr(configurable, 'Members'): @@ -135,5 +171,4 @@ def limitCombinatorics(configurable, i, MaxCandidates, MaxCombinations, force, incidentName) return val - # log.warning('Not able to set MaxCandidates and MaxCombinations to algorithm '+str(type(configurable))+'/'+configurable.name()) return False