Example #1
0
        def __str__(self):
            """Print the algorithm sequence in a user-friendly way

            This function takes care of printing the full configuration of every
            algorithm in the sequence.
            """

            result = AnaAlgorithmConfig._printHeader('AlgSequence/%s' %
                                                     self.name())
            result += '\n'
            for algOrSeq in self._algsAndSequences:
                result += '| %s\n' % indentBy(str(algOrSeq), '| ')
                pass
            result += AnaAlgorithmConfig._printFooter('AlgSequence/%s' %
                                                      self.name())
            return result
Example #2
0
 def test_insertAlg(self):
     self.seq.insert(1, AnaAlgorithmConfig('AlgType3/Algorithm3'))
     self.assertEqual(len(self.seq), 3)
     self.assertEqual(self.seq[0].name(), 'Algorithm1')
     self.assertEqual(self.seq[1].name(), 'Algorithm3')
     self.assertEqual(self.seq[2].name(), 'Algorithm2')
     return
Example #3
0
def createAlgorithm(typeName, instanceName):
    """Create an algorithm configurable

    This function is used to create an algorithm "configurable" in a dual-use
    way, either returning an actual Athena configurable, or an appropriately
    configured EL::AnaAlgorithmConfig instance.

    Keyword arguments:
      typeName     -- The C++ type name of the algorithm
      instanceName -- The instance name of the algorithm to create
    """

    try:
        # Try to get a configurable for this C++ class "from Athena".
        # If this succeeds, we're obviously in an Athena environment.

        # First off, construct a "python type name" for the class, replacing the
        # '::' namespace delimeters with '__'.
        pythonTypeName = typeName.replace('::', '__')

        # Now look up the Athena configurable of this algorithm:
        from AthenaCommon import CfgMgr
        algClass = getattr(CfgMgr, pythonTypeName)

        # Return the object:
        return algClass(instanceName)

    except ImportError:
        # If that didn't work, then apparently we're in an EventLoop
        # environment, so we need to use AnaAlgorithmConfig as the base class
        # for the user's class.
        from AnaAlgorithm.AnaAlgorithmConfig import AnaAlgorithmConfig
        return AnaAlgorithmConfig('%s/%s' % (typeName, instanceName))

    pass
Example #4
0
def createPublicTool(typeName, toolName):
    """Helper function for setting up a public tool for a dual-use algorithm

    This function is meant to be used in the analysis algorithm sequence
    configurations for setting up public tools on the analysis algorithms.
    Public tools that could then be configured with a syntax shared between
    Athena and EventLoop.

    Keyword arguments:
      typeName -- The C++ type name of the private tool
      toolName -- The property name with which the tool handle was declared on
                  the algorithm. Also the instance name of the tool.
    """

    try:
        # Try to set up a public tool of this type for Athena. If this succeeds,
        # we're obviously in an Athena environment.

        # First off, construct a "python type name" for the class, replacing the
        # '::' namespace delimeters with '__'.
        pythonTypeName = typeName.replace('::', '__')

        # Now look up the Athena configurable of this tool:
        from AthenaCommon import CfgMgr
        toolClass = getattr(CfgMgr, pythonTypeName)

        # Add an instance of the tool to the ToolSvc:
        from AthenaCommon.AppMgr import ToolSvc
        if not hasattr(ToolSvc, toolName):
            ToolSvc += toolClass(toolName)
            pass

        # Return the member on the ToolSvc:
        return getattr(ToolSvc, toolName)

    except ImportError:
        # If that didn't work, then apparently we're in an EventLoop
        # environment, so let's use the EventLoop specific formalism.
        from AnaAlgorithm.AnaAlgorithmConfig import AnaAlgorithmConfig
        tool = AnaAlgorithmConfig('%s/%s' % (typeName, toolName))
        tool.setIsPublicTool(True)
        return tool
Example #5
0
 def setUp(self):
     self.seq = AlgSequence('MainSequence')
     self.seq += AnaAlgorithmConfig('PreSelectionAlg/PreSelection')
     self.seq += AlgSequence('MuonSequence')
     self.seq.MuonSequence += \
       AnaAlgorithmConfig( 'MuonAnalysisAlg/MuonAnalysis' )
     self.seq.MuonSequence += \
       AnaAlgorithmConfig( 'MuonHistoAlg/MuonHistogramming' )
     self.seq += AlgSequence('JetSequence')
     self.seq.JetSequence += AlgSequence('JetPreSequence')
     self.seq.JetSequence.JetPreSequence += \
       AnaAlgorithmConfig( 'JetPreSelectorAlg/JetPreSelector' )
     self.seq.JetSequence.JetPreSequence += \
       AnaAlgorithmConfig( 'JetDecoratorAlg/JetDecorator' )
     self.seq.JetSequence += \
       AnaAlgorithmConfig( 'JetAnalysisAlg/JetAnalysis' )
     self.seq.JetSequence += \
       AnaAlgorithmConfig( 'JetHistoAlg/JetHistogramming' )
     self.seq += AnaAlgorithmConfig('PostProcessingAlg/PostProcessing')
     return
Example #6
0
  def algorithm(self, className, options):
    # check first argument
    if isinstance(className, unicode): className = className.encode('utf-8')
    if not isinstance(className, str):
      raise TypeError("className must be a string")

    if not isinstance(options, dict):
      raise TypeError("Must pass in a dictionary of options")

    # if m_name not set, randomly generate it
    algName = options.get("m_name", None)
    if algName is None:
      algName = str(NameGenerator())
      logger.warning("Setting missing m_name={0:s} for instance of {1:s}".format(algName, className))
      options['m_name'] = algName
    if not isinstance(algName, str) and not isinstance(algName, unicode):
      raise TypeError("'m_name' must be a string for instance of {0:s}".format(className))

    # handle deprecation of m_debug, m_verbose
    if 'm_debug' in options:
      logger.warning("m_debug is being deprecated. See https://github.com/UCATLAS/xAODAnaHelpers/pull/882 . Set m_msgLevel='debug'")
    if 'm_verbose' in options:
      logger.warning("m_verbose is being deprecated. See https://github.com/UCATLAS/xAODAnaHelpers/pull/882 . Set m_msgLevel='verbose'.")

    # handle msgLevels, can be string or integer
    msgLevel = options.get("m_msgLevel", "info")
    if isinstance(msgLevel, unicode): msgLevel = msgLevel.encode('utf-8')
    if not isinstance(msgLevel, str) and not isinstance(msgLevel, int):
      raise TypeError("m_msgLevel must be a string or integer for instance of {0:s}".format(className))
    if isinstance(msgLevel, str):
      if not hasattr(ROOT.MSG, msgLevel.upper()):
        raise ValueError("m_msgLevel must be a valid MSG::level: {0:s}".format(msgLevel))
      msgLevel = getattr(ROOT.MSG, msgLevel.upper())
    options['m_msgLevel'] = msgLevel

    # Construct the given constructor
    #    (complicated b/c we have to deal nesting of namespaces)
    alg = reduce(lambda x,y: getattr(x, y, None), className.split('::'), ROOT)
    if alg is None:
      raise AttributeError(className)

    # get a list of parent classes
    parents = inspect.getmro(alg)
    if ROOT.EL.Algorithm in parents:
      # Construct an instance of the alg and set its attributes
      alg_obj = alg()
      alg_obj.SetName(algName)
      self._log.append((className,algName))
      alg_obj.setMsgLevel(msgLevel)
      for k,v in options.iteritems():
        # only crash on algorithm configurations that aren't m_msgLevel and m_name (xAH specific)
        if not hasattr(alg_obj, k) and k not in ['m_msgLevel', 'm_name']:
          raise AttributeError(k)
        elif hasattr(alg_obj, k):
          #handle unicode from json
          if isinstance(v, unicode): v = v.encode('utf-8')
          self._log.append((algName, k, v))
          try:
            setattr(alg_obj, k, v)
          except:
            logger.error("There was a problem setting {0:s} to {1} for {2:s}::{3:s}".format(k, v, className, algName))
            raise
    elif ROOT.EL.AnaAlgorithm in parents:
      alg_obj = AnaAlgorithmConfig(className)
      alg_obj.setName(algName)
      self._log.append((className, algName))
      # TODO
      #setattr(alg_obj, "OutputLevel", msgLevel)
      for k,v in options.iteritems():
        if k in ['m_msgLevel', 'm_name']: continue
        if isinstance(v, unicode): v = v.encode('utf-8')
        self._log.append((algName, k, v))
        try:
          setattr(alg_obj, k, v)
        except:
          logger.error("There was a problem setting {0:s} to {1} for {2:s}::{3:s}".format(k, v, className, algName))
          raise
    else:
      raise TypeError("Algorithm {0:s} is not an EL::Algorithm or EL::AnaAlgorithm. I do not know how to configure it. {1}".format(className, parents))

    # Add the constructed algo to the list of algorithms to run
    self._algorithms.append(alg_obj)
Example #7
0
    def algorithm(self, className, options):
        # check first argument
        if isinstance(className, unicode):
            className = className.encode('utf-8')
        if not isinstance(className, str):
            raise TypeError("className must be a string")

        if not isinstance(options, dict):
            raise TypeError("Must pass in a dictionary of options")

        # if m_name not set, randomly generate it
        algName = options.get("m_name", None)
        if algName is None:
            algName = str(NameGenerator())
            logger.warning(
                "Setting missing m_name={0:s} for instance of {1:s}".format(
                    algName, className))
            options['m_name'] = algName
        if not isinstance(algName, str) and not isinstance(algName, unicode):
            raise TypeError(
                "'m_name' must be a string for instance of {0:s}".format(
                    className))

        # handle deprecation of m_debug, m_verbose
        if 'm_debug' in options:
            logger.warning(
                "m_debug is being deprecated. See https://github.com/UCATLAS/xAODAnaHelpers/pull/882 . Set m_msgLevel='debug'"
            )
        if 'm_verbose' in options:
            logger.warning(
                "m_verbose is being deprecated. See https://github.com/UCATLAS/xAODAnaHelpers/pull/882 . Set m_msgLevel='verbose'."
            )

        # handle msgLevels, can be string or integer
        msgLevel = options.get("m_msgLevel", "info")
        if isinstance(msgLevel, unicode): msgLevel = msgLevel.encode('utf-8')
        if not isinstance(msgLevel, str) and not isinstance(msgLevel, int):
            raise TypeError(
                "m_msgLevel must be a string or integer for instance of {0:s}".
                format(className))
        if isinstance(msgLevel, str):
            if not hasattr(ROOT.MSG, msgLevel.upper()):
                raise ValueError(
                    "m_msgLevel must be a valid MSG::level: {0:s}".format(
                        msgLevel))
            msgLevel = getattr(ROOT.MSG, msgLevel.upper())
        options['m_msgLevel'] = msgLevel

        # Construct the given constructor
        #    (complicated b/c we have to deal nesting of namespaces)
        alg = reduce(lambda x, y: getattr(x, y, None), className.split('::'),
                     ROOT)
        if alg is None:
            raise AttributeError(className)

        # get a list of parent classes
        parents = inspect.getmro(alg)
        if ROOT.EL.Algorithm in parents:
            # Construct an instance of the alg and set its attributes
            alg_obj = alg()
            alg_obj.SetName(algName)
            self._log.append((className, algName))
            alg_obj.setMsgLevel(msgLevel)
            for k, v in options.items():
                # only crash on algorithm configurations that aren't m_msgLevel and m_name (xAH specific)
                if not hasattr(alg_obj, k) and k not in [
                        'm_msgLevel', 'm_name'
                ]:
                    raise AttributeError(k)
                elif hasattr(alg_obj, k):
                    self._set_algo_attribute(alg_obj, k, v, className, algName)
        elif ROOT.EL.AnaAlgorithm in parents:
            alg_obj = AnaAlgorithmConfig(className)
            alg_obj.setName(algName)
            self._log.append((className, algName))
            # TODO
            #setattr(alg_obj, "OutputLevel", msgLevel)
            for k, v in options.items():
                if k in ['m_msgLevel', 'm_name']: continue
                self._set_algo_attribute(alg_obj, k, v, className, algName)
        else:
            raise TypeError(
                "Algorithm {0:s} is not an EL::Algorithm or EL::AnaAlgorithm. I do not know how to configure it. {1}"
                .format(className, parents))

        # Add the constructed algo to the list of algorithms to run
        self._algorithms.append(alg_obj)
Example #8
0
 def setUp(self):
     self.seq = AlgSequence('TestSequence')
     self.seq += AnaAlgorithmConfig('AlgType1/Algorithm1')
     self.seq += AnaAlgorithmConfig('AlgType2/Algorithm2')
     return
Example #9
0
sh.printContent()

# Create an EventLoop job.
job = ROOT.EL.Job()
job.sampleHandler(sh)
job.options().setDouble(ROOT.EL.Job.optMaxEvents, 500)

# Create the algorithm's configuration. Note that we'll be able to add
# algorithm property settings here later on.
from AnaAlgorithm.AnaAlgorithmConfig import AnaAlgorithmConfig
#std trigger to be validated:
#L1: L1_MU20, L1_MU21
#HLT single iso: HLT_mu26_ivarmedium, HLT_mu28_ivarmedium, HLT_mu26_ivartight, HLT_mu28_ivartight
#HLT single: HLT_mu50, HLT_mu60, HLT_mu80, HLT_mu60_msonly_3layerEC, HLT_mu80_msonly_3layerEC
#HLT multi: HLT_mu22_mu8noL1, HLT_mu20_2mu4noL1, HLT_2mu14, HLT_3mu6_msonly
config = AnaAlgorithmConfig('TrigxAODAnalysis/TrigAnalysisAlg',
                            ChainName=[
                                'HLT_mu24_ivarmedium', 'HLT_mu50', 'HLT_2mu14',
                                'HLT_3mu6_msonly'
                            ],
                            MuonQuality=1,
                            Verbose=2)

job.algsAdd(config)

job.outputAdd(ROOT.EL.OutputStream('ANALYSIS'))

# Run the job using the direct driver.
driver = ROOT.EL.DirectDriver()
driver.submit(job, options.submission_dir)
Example #10
0
# Set up the sample handler object:
sh = ROOT.SH.SampleHandler()
sh.setMetaString("nc_tree", "CollectionTree")

# Add a sample to it, made from the specified input file(s):
chain = ROOT.TChain("CollectionTree")
chain.Add(args.input)
sh.add(ROOT.SH.makeFromTChain("input", chain))

# Create an EventLoop job:
job = ROOT.EL.Job()
job.sampleHandler(sh)

# Add the analysis algorithm(s). First, demonstrate how to set properties for
# an algorithm instance in its constructor.
from AnaAlgorithm.AnaAlgorithmConfig import AnaAlgorithmConfig
electronPlotter = AnaAlgorithmConfig("AnalysisAlgorithm/ElectronPlotter",
                                     InputContainer="Electrons")
job.algsAdd(electronPlotter)

# Then, show how to achieve the same after the algorithm's configuration was
# already created.
muonPlotter = AnaAlgorithmConfig("AnalysisAlgorithm/MuonPlotter")
muonPlotter.InputContainer = "Muons"
job.algsAdd(muonPlotter)

# Run the job:
driver = ROOT.EL.DirectDriver()
driver.submit(job, "AnalysisJob")