goodruns

goodruns provides an implementation of an ATLAS Good Run List (GRL) reader/writer in Python, and collection of useful command-line tools.

Requirements

goodruns requires at least Python 2.5. Unlike the standard ATLAS GoodRunsLists package, goodruns does not depend on ROOT for XML processing unless you are reading from or writing to a ROOT file (see below). For faster XML reading/writing goodruns will optionally use lxml if installed. Install PyYAML if you would like to convert GRLs into YAML format.

Installation

Install the latest released version of goodruns with pip:

pip install --user goodruns

Omit the --user for a system-wide installation (requires root privileges). Add ${HOME}/.local/bin to your ${PATH} if using --user and if it is not there already (put this in your .bashrc):

export PATH=${HOME}/.local/bin${PATH:+:$PATH}

To upgrade an existing installation, add the -U option in the pip command above.

Usage

An example of how to use goodruns:

from goodruns import GRL

grl = GRL('grl.xml')
# or:
grl = GRL('http://atlasdqm.web.cern.ch/atlasdqm/grlgen/path/to/grl.xml')
# or (if '/path/to/grl' is a ROOT.TObjString in data.root):
grl = GRL('data.root:/path/to/grl')

# check if the GRL contains the lumiblock 231 in run 186356:
if (186356, 231) in grl:
    # do something
    pass

The GRL is automatically optimized (lumiblocks are merged and sorted):

>>> from goodruns import GRL
>>> a = GRL()
>>> a.insert(1, (1,4))
>>> a.insert(1, (7,10))
>>> a
---------------
RUN: 1
LUMIBLOCKS:
  1 - 4
  7 - 10
>>> a.insert(1, (6,7))
>>> a
---------------
RUN: 1
LUMIBLOCKS:
  1 - 4
  6 - 10
>>> a.insert(1, (5,5))
>>> a
---------------
RUN: 1
LUMIBLOCKS:
  1 - 10

Command-line Tools

goodruns also provides a collection of command-line tools for combining, manipulating, and inspecting GRLs. As above GRLs may be XML files, URLs, or in ROOT files.

grl diff

Use grl diff to determine the GRL containing the runs/lumiblocks in A.xml but not in B.xml:

grl diff A.xml B.xml

In other words, B.xml is subtracted from A.xml. All command-line tools print on stdout. Redirect stdout to a file to save the result:

grl diff A.xml B.xml > C.xml

You may supply more than two GRLs to grl diff:

grl diff A.xml B.xml C.xml D.xml > E.xml

which results in the GRL E=((A-B)-C)-D). This is equivalent to:

grl diff A.xml B.xml | grl diff C.xml | grl diff D.xml > E.xml

The output of one command can be piped into any of the other commands in goodruns.

grl and, grl or, grl xor

These scripts implement logical combinations of GRLs. Logical AND:

grl and A.xml B.xml > C.xml

OR:

grl or A.xml B.xml > C.xml

and XOR (exclusive OR):

grl xor A.xml B.xml > C.xml

Again, these commands can be combined arbitrarily:

grl and A.xml B.xml | grl or C.xml | grl xor D.xml > E.xml

and any GRL argument can also be a ROOT file or URL:

grl and data.root:/path/to/grl http://atlasdqm.web.cern.ch/path/to/grl.xml

grl clip

Use grl clip to truncate a GRL between a starting run/lumiblock and ending run/lumiblock:

grl clip --help
usage: grl clip [-h] [-o OUTPUT] [-f FORMAT] [--startrun STARTRUN]
                [--startlb STARTLB] [--endrun ENDRUN] [--endlb ENDLB]
                [grl]

positional arguments:
  grl

optional arguments:
  -h, --help            show this help message and exit
  -o OUTPUT, --output OUTPUT
                        Output filename (optional)
  -f FORMAT, --format FORMAT
                        Output format: xml, yml, txt, py, cut
  --startrun STARTRUN   Start run
  --startlb STARTLB     Start lumiblock
  --endrun ENDRUN       End run
  --endlb ENDLB         End lumiblock

grl convert

grl convert can convert a GRL from XML format into YAML:

grl convert -f yml A.xml
186178:
- !!python/tuple [125, 156]
- !!python/tuple [158, 161]
186179:
- !!python/tuple [382, 388]
- !!python/tuple [390, 390]
- !!python/tuple [396, 396]
- !!python/tuple [398, 415]
- !!python/tuple [417, 431]
- !!python/tuple [433, 453]
- !!python/tuple [455, 469]
- !!python/tuple [471, 474]
- !!python/tuple [476, 479]
186180:
- !!python/tuple [114, 116]
- !!python/tuple [118, 124]
- !!python/tuple [126, 140]
- !!python/tuple [144, 149]
- !!python/tuple [151, 170]
- !!python/tuple [173, 176]
...

or plain text:

grl convert -f txt A.xml
---------------
RUN: 186178
LUMIBLOCKS:
  125 - 156
  158 - 161
---------------
RUN: 186179
LUMIBLOCKS:
  382 - 388
  390
  396
  398 - 415
  417 - 431
  433 - 453
  455 - 469
  471 - 474
  476 - 479
---------------
RUN: 186180
LUMIBLOCKS:
  114 - 116
  118 - 124
  126 - 140
  144 - 149
  151 - 170
  173 - 176
...

grl convert will also convert a GRL into Python code (dict of lists of tuples) or (as a joke) a ROOT TCut expression.

grl runs

grl runs simply prints the run numbers, one per line, contained within a GRL:

grl runs A.xml
186178
186179
186180
...

Quickly print the runs contained in a GRL from a URL:

grl runs http://atlasdqm.web.cern.ch/path/to/grl.xml

grl find

grl find prints the GRLs containing a run number and lumiblock number (if any). The lumiblock number is optional, and if left unset all GRLs containing the run will be printed. For example, you can determine which ROOT file contains the run 215643 and lumiblock 400 with the following command:

grl find --path Lumi/tau --pattern "*.root*" --run 215643 --lb 400 globbed*path*

Documentation

goodruns.grl

This module provides the main GRL class and utility functions

goodruns.grl.clipped(grl, startrun=None, startlb=None, endrun=None, endlb=None)[source]

Return a clipped GRL between startrun, startlb and endrun, endlb (inclusive).

grl: GRL

startrun: [ int | None ]

startlb: [ int | None ]

endrun: [ int | None ]

endlb: [ int | None ]

goodruns.grl.diffed(*args)[source]

Return the difference of multiple GRLs: (((A-B)-C)-D) ...)

args: tuple of GRLs

goodruns.grl.ored(*args)[source]

Return the OR of multiple GRLs: A | B | C ...

args: tuple of GRLs

goodruns.grl.anded(*args)[source]

Return the AND of multiple GRLs: A & B & C ...

args: tuple of GRLs

goodruns.grl.xored(*args)[source]

Return the XOR of multiple GRLs: A ^ B ^ C ...

args: tuple of GRLs

class goodruns.grl.LumiblockRange[source]

A 2-tuple consisting of the lower and upper bounds of a lumiblock range.

as_set()[source]

Convert self to set of lumiblocks

intersects(lbrange)[source]

Determine if self intersects with another lumiblock range

lbrange: LumiblockRange

class goodruns.grl.GRL(grl=None, from_string=False, format=None)[source]

The main GRL class holds a python dictionary mapping runs to a list of lumiblock ranges (2-tuples)

grl: [ dict | str | None ]

from_string: bool
If True, interpret grl as xml string and not filename
clip(startrun=None, startlb=None, endrun=None, endlb=None)[source]

Clip the GRL between startrun, startlb and endrun, endlb (inclusive)

startrun: [ int | None ]

startlb: [ int | None ]

endrun: [ int | None ]

endlb: [ int | None ]

cut(runname='RunNumber', lbname='lbn')[source]

Convert this GRL into a TCut expression.

runname: str

lbname: str

from_dict(d)[source]

Convert dict to GRL

d: dict

from_string(string)[source]

Insert runs and lumiblocks from XML string

string: str

from_xml(tree)[source]

Insert runs and lumiblocks from XML

tree: ElementTree

has_run(run)[source]

Returns True if run is in GRL, else False

run: int

insert(run, lbrange)[source]

Insert a lumiblock range into a run

run: int

lbrange: [ LumiblockRange | tuple ]

items()[source]

Iterate over (run, lbranges) in GRL

iterlbranges()[source]

Iterate over (run, lbrange) in GRL

iterruns()[source]

Iterate over runs in GRL

remove(run, lbrange)[source]

Remove a lumiblock range from a run

run: int

lbrange: LumiblockRange

runs()[source]

Return list of runs in GRL

save(name)[source]

Save GRL to file by name. Determine format from extension.

name: str

str(format='xml')[source]

Return string repr of self in the specified format

format: str

to_dict()[source]

Convert self to dict

write(filehandle, format='xml')[source]

Write the GRL in the specified format to the file object.

filehandle: file

format: str