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