ATLAS Offline Software
Loading...
Searching...
No Matches
SortedCollectionCreator.py
Go to the documentation of this file.
1# Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
2
3__author__ = "Marcin Nowak"
4__doc__ = """
5Create a sorted collection of Event references from a set of Athnea files containing EventInfoTags
6(or from other compatible APR Event collections)
7"""
8
9
11 """Creates a sorted (APR) collection of event references from input files"""
12
13 def __init__(self, name="sortEvents"):
14 from AthenaCommon import Logging
15 Logging.log.name = name
16 self.name = name
17 self.info = Logging.log.info
18 self.debug = Logging.log.debug
19 self.verbose = Logging.log.verbose
20 self.collDescription = None
21 self.collSvc = None
22
23 def loadRoot(self):
24 """import ROOT, create CollectionSvc"""
25 import ROOT
26 self.pool = ROOT.pool
27 self.collSvc = self.pool.CollectionService()
28 self.collSvc.setMessageSvcQuiet()
29
30 def readCollectionDescription(self, collection):
31 """read Collection Description and remember it"""
32 desc = collection.description()
33 self.debug("Reading Collection Description from {}".format(desc.name()))
34 # read attributes' names and types from the description and remember them
35 for an in range(0, desc.numberOfAttributeColumns()):
36 attr = desc.attributeColumn(an)
37 name = attr.name()
38 self.attrNames.append(name)
39 self.attrTypes[name] = attr.type()
40 # make a local copy of the description
41 self.collDescription = self.pool.CollectionDescription( desc )
42
43
44 def readInputCollections(self, inputCollections):
45 """read all input collections into memory"""
46 self.collDescription = None
47 self.allRows = []
48 self.attrNames = []
49 self.attrTypes = {}
50 for inFileName in inputCollections:
51 self.debug("Opening {}".format(inFileName))
52 iColl = self.collSvc.open( "Input", inFileName)
53 self.debug("{} opened".format(inFileName))
54 if self.collDescription is None:
56 self.info("Reading Events from {}".format(inFileName))
57
58 cursor = iColl.cursor()
59
60 while cursor.next():
61 row = cursor.currentRow()
62 # put the token first in the attribute list, for convenience
63 t = [ row.token().toString() ]
64 for nam in self.attrNames:
65 t.append( row.attributeList()[nam].data[ self.attrTypes[nam] ]() )
66 self.allRows.append(t)
67
68 iColl.close()
69
70 for t in self.allRows:
71 self.verbose( (t[1:], t[0]) )
72 self.verbose('='*80)
73 self.info("Finished reading input collections, total events read: {}".format(len(self.allRows)) )
74
75 def sortEvents(self, sortAttrName, sortReverse=False):
76 """sort the events based on an attribute name"""
77 self.info("Sorting on attribute {}, sort order {}".format(sortAttrName, ("Descending" if sortReverse else "Ascending") ))
78 # add 1 to offsets because the Ref is first
79 attrPos = self.attrNames.index(sortAttrName)+1
80 self.allRows.sort( key=lambda t: t[attrPos], reverse=sortReverse )
81
82 for t in self.allRows:
83 self.verbose( (t[1:], t[0]) )
84 self.verbose('='*80)
85
86 def writeCollection(self, outputCollection, outputCollectionType):
87 """write sorted collection into a Collection file"""
88 self.info("Writing Event collection {}".format(outputCollection))
89 self.collDescription.setName("Sorting")
90 self.collDescription.setType(outputCollectionType)
91 self.collDescription.setConnection(outputCollection)
92 # create the output collection (file)
93 dstColl = self.collSvc.create(self.collDescription)
94 row = self.pool.CollectionRowBuffer()
95 dstColl.initNewRow( row )
96 for t in self.allRows:
97 row.token().fromString( t[0] )
98 for idx,nam in enumerate(self.attrNames):
99 type = self.attrTypes[nam]
100 row.attributeList()[nam].setValue[type]( t[idx+1] )
101 dstColl.insertRow( row )
102
103 dstColl.commit()
104 dstColl.close()
105
106 def execute(self, inputCollections, outputCollection, outputCollectionType, sortAttribute="LumiBlockN",
107 sortOrder="Ascending"):
108 sort_opts = ("Ascending", "Descending")
109 self.info("Executing SortedCollectionCreator, inputs={}, output='{}' ({}), sort by: {}, order: {}"
110 .format(inputCollections, outputCollection, outputCollectionType, sortAttribute, sortOrder))
111 if isinstance(inputCollections, str):
112 inputs = [inputCollections]
113 else:
114 inputs = inputCollections
115 if sortOrder.lower() not in [opt.lower() for opt in sort_opts]:
116 raise Exception(self.name + ": Accepted sortOrder values are: " + str(sort_opts))
117 sortReverse = ( sortOrder.lower()[0] == "d" )
118 self.loadRoot()
119 self.readInputCollections(inputs)
120 self.sortEvents(sortAttribute, sortReverse)
121 self.writeCollection(outputCollection, outputCollectionType)
122
123 def executeInSubprocess(self, *args, **kwargs):
124 import multiprocessing
125 # Default start method changed from fork to spawn in python 3.14.
126 # Need to force it back.
127 multiprocessing.set_start_method('fork')
128 process = multiprocessing.Process( target=self.execute, args=args, kwargs=kwargs)
129 self.debug("Sorting Events in a subprocess")
130 process.start()
131 process.join() # Wait for completion
132 return process.exitcode
133
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
std::string toString(const float number)
Pipe a number to a string.
writeCollection(self, outputCollection, outputCollectionType)
execute(self, inputCollections, outputCollection, outputCollectionType, sortAttribute="LumiBlockN", sortOrder="Ascending")
Definition index.py:1