Running a Minimal Job

Last update: 09 Nov 2021 [History] [Edit]

Minimal Job

For the purpose of this tutorial we will use one file for simplicity. Create tutorial.py and make it executable using chmod +x tutorial.py.

#!/usr/bin/env python

if __name__ == "__main__":
    from AthenaCommon.Configurable import Configurable
    Configurable.configurableRun3Behavior = 1

    # Setup flags
    from AthenaConfiguration.AllConfigFlags import ConfigFlags
    from AthenaConfiguration.TestDefaults import defaultTestFiles
    ConfigFlags.Input.Files = defaultTestFiles.HITS
    ConfigFlags.lock()

    # Setup main services
    from AthenaConfiguration.MainServicesConfig import MainServicesCfg
    cfg = MainServicesCfg(ConfigFlags)

    # Dump the pickle file
    with open("BeamSpot.pkl", "wb") as f:
        cfg.store(f)

    # Execute
    import sys
    sys.exit(not cfg.run(maxEvents=3).isSuccess())

This minimal fragment runs 3 events on the HITS input but does not do anything beyond that.

The next step is to add BeamSpotCondAlgCfg in the job. Add it to the primary ComponentAccumulator using the below snippet and try again.

    from BeamSpotConditions.BeamSpotConditionsConfig import BeamSpotCondAlgCfg
    cfg.merge(BeamSpotCondAlgCfg(ConfigFlags))

You should now see in the logs:

BeamSpotCondAlg                                      INFO Read from condDB status 0 pos (0,0,0) sigma (30,30,500) tilt (0,0) sigmaXY 0
BeamSpotCondAlg                                      INFO Recorded new InDet::BeamSpotData to BeamSpotData with range {[0,l:0] - [141748,l:0]} into conditions store.

Reading and Writing Files

At this point we do not read or write any files. The input file was only used for autoconfiguration of the job. Today we will only use simulated files so we need to read (and also write) POOL files.

Usually reading files is configured immediately after main services. Add the following snippet and try running the job again. You should see some indication that the file was loaded from CVMFS.

    from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
    cfg.merge(PoolReadCfg(ConfigFlags))

To write the output we first need to adapt the flags to tell the job to write anything. To write a RDO file ConfigFlags.Output.RDOFileName = "myRDO.pool.root" needs to be set. Then a list of containers to be written out needs to be provided. Note that xAOD::EventInfo is written out by default, but we will configure it explicitly:

    if ConfigFlags.Output.doWriteRDO:
        from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
        cfg.merge(OutputStreamCfg(ConfigFlags, "RDO", ItemList=[
            "xAOD::EventInfo#EventInfo",
            "xAOD::EventAuxInfo#EventInfoAux.",
        ]))

As you quickly find out xAOD::EventInfo is not present in the file and we need to build it. Sometimes you may want to run algorithms conditionally based on what is present in the input file. ConfigFlags.Input.Collections array is autoconfigured based on the input file and helps you with that.

    # Check if running on legacy HITS
    if "EventInfo" not in ConfigFlags.Input.Collections:
        from xAODEventInfoCnv.xAODEventInfoCnvConfig import EventInfoCnvAlgCfg
        cfg.merge(EventInfoCnvAlgCfg(ConfigFlags))

You can check using checkFile myRDO.pool.root that some information is actually in the output file.

Summary

You have now learned how to setup a basic ComponentAccumulator-based job. Such jobs are ideal as unit tests which test the smallest chunks of the configuration. Next you will write your own configuration fragment. For now this is how the current file should look like:

#!/usr/bin/env python

if __name__ == "__main__":
    from AthenaCommon.Configurable import Configurable
    Configurable.configurableRun3Behavior = 1

    from AthenaConfiguration.AllConfigFlags import ConfigFlags
    from AthenaConfiguration.TestDefaults import defaultTestFiles
    ConfigFlags.Input.Files = defaultTestFiles.HITS
    ConfigFlags.Output.RDOFileName = "myRDO.pool.root"
    ConfigFlags.lock()

    from AthenaConfiguration.MainServicesConfig import MainServicesCfg
    cfg = MainServicesCfg(ConfigFlags)

    from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg
    cfg.merge(PoolReadCfg(ConfigFlags))

    # Check if running on legacy HITS
    if "EventInfo" not in ConfigFlags.Input.Collections:
        from xAODEventInfoCnv.xAODEventInfoCnvConfig import EventInfoCnvAlgCfg
        cfg.merge(EventInfoCnvAlgCfg(ConfigFlags))

    from BeamSpotConditions.BeamSpotConditionsConfig import BeamSpotCondAlgCfg
    cfg.merge(BeamSpotCondAlgCfg(ConfigFlags))

    if ConfigFlags.Output.doWriteRDO:
        from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg
        cfg.merge(OutputStreamCfg(ConfigFlags, "RDO", ItemList=[
            "xAOD::EventInfo#EventInfo",
            "xAOD::EventAuxInfo#EventInfoAux.",
        ]))

    with open("BeamSpot.pkl", "wb") as f:
        cfg.store(f)

    import sys
    sys.exit(not cfg.run(maxEvents=3).isSuccess())