ATLAS Offline Software
HLTCFDot.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 
3 
5 
6 from AthenaCommon.AlgSequence import AthSequencer
7 from TriggerMenuMT.HLT.Config.ControlFlow.HLTCFTools import algColor
8 from TriggerMenuMT.HLT.Config.ControlFlow.HLTCFComponents import isPassSequence
9 import itertools
10 from AthenaCommon.CFElements import isSequence
11 
12 
13 DrawHypoTools=True
14 
15 def drawHypoTools(file, all_hypos):
16  all_hypos=list(set(all_hypos))
17  for hp in all_hypos:
18  for hypotool in hp.Alg.HypoTools:
19  file.write(" \"%s\"[fillcolor=yellow,style=filled,shape= Mdiamond]\n" % hypotool.getName())
20  file.write(" \"%s\" -> \"%s\" [style=dashed, color=grey]\n" % (hp.Alg.name, hypotool.getName()))
21 
22 
24  def _dump (seq, indent):
25  o = list()
26  if isSequence(seq):
27  for c in seq.Members:
28  if isSequence(c):
29  o.append( ("%s[color=%s, shape=circle, width=.5, fixedsize=true ,style=filled]\n"%(c.name,_seqColor(c)), indent) )
30  else:
31  o.append( ("%s[fillcolor=%s,style=filled]\n"%(c.name,algColor(c)), indent) )
32  o.append( ("%s -> %s\n"%(seq.name, c.name), indent))
33  o.extend( _dump (c, indent+1) )
34  return o
35 
36  def _parOR (seq):
37  try:
38  if seq.ModeOR is True:
39  if seq.Sequential is False:
40  if seq.StopOverride is True:
41  return True
42  except AttributeError:
43  return False # Offline sequence may not have these set
44  return False
45 
46  def _seqAND(seq):
47  try:
48  if seq.ModeOR is False:
49  if seq.Sequential is True:
50  if seq.StopOverride is False:
51  return True
52  except AttributeError:
53  return False # Offline sequence may not have these set
54  return False
55 
56  def _seqColor(seq):
57  if _parOR(seq):
58  return "red"
59  if _seqAND(seq):
60  return "dodgerblue3"
61 
62  return "black"
63 
64 
65 
66  with open('%s.CF.dot'%stepCF.name, mode="wt") as file:
67  #strict
68  file.write( 'digraph step { \n'\
69  +' concentrate=true;\n'\
70  +' rankdir="LR";\n'
71  +' node [ shape=polygon, fontname=Helvetica ]\n'\
72  +' edge [ fontname=Helvetica ]\n'
73  +' %s [shape=Mdiamond]\n'%stepCF.name)
74 
75  indent=0
76  # out = [("%s[color=%s shape=circle]\n"%(stepCF.getName(),_seqColor(stepCF)), indent)]
77  out = [("",indent)]
78  out.extend( _dump( stepCF, indent=indent+1 ) )
79  for n,i in out:
80  line= " "*i+ n
81  file.write(line)
82 
83  file.write( '}\n')
84 
85 
86 
87 def all_DataFlow_to_dot(name, step_list):
88  with open('%s.dot'%(name), mode="wt") as file:
89  file.write( 'digraph step { \n'\
90  +' concentrate=true;\n'\
91  +' rankdir="LR";\n'
92  +' node [ shape=polygon, fontname=Helvetica ]\n'\
93  +' edge [ fontname=Helvetica ]\n'
94  +' %s [shape=Mdiamond]\n'%name)
95 
96  nstep=1
97  last_step_hypoNodes=[]
98  all_hypos=[]
99  for cfseq_list in step_list:
100  # loop over steps
101  step_connections = []
102  step_connections.extend(last_step_hypoNodes)
103  # reset the last step
104  last_step_hypoNodes =[]
105  for cfseq in cfseq_list:
106  file.write(" %s[fillcolor=%s style=filled]\n"%(cfseq.sequenceCA.filterNode.Alg.name,algColor(cfseq.sequenceCA.filterNode.Alg)))
107  step_connections.append(cfseq.sequenceCA.filterNode)
108  file.write( '\n subgraph cluster_%s {\n'%(cfseq.sequenceCA.step.name)\
109  +' concentrate=true;\n'
110  +' node [color=white style=filled]\n'\
111  +' style=filled\n'\
112  +' color=lightgrey\n'\
113  +' fontname=Helvetica\n'\
114  +' label = %s\n'%(cfseq.sequenceCA.step.name))
115 
116  cfseq_algs = []
117  cfseq_algs.append(cfseq.sequenceCA.filterNode)
118 
119  if len(cfseq.sequenceCA.step.sequences)==0:
120  last_step_hypoNodes.append(cfseq.sequenceCA.filterNode)
121 
122  for menuseq in cfseq.sequenceCA.step.sequences:
123  cfseq_algs, all_hypos, last_step_hypoNodes = menuseq.buildDFDot(cfseq_algs,
124  all_hypos,
125  last_step_hypoNodes,
126  file)
127 
128 
129  if cfseq.sequenceCA.step.combo is not None:
130  file.write(" %s[color=%s]\n"%(cfseq.sequenceCA.step.combo.Alg.name, algColor(cfseq.sequenceCA.step.combo.Alg)))
131  cfseq_algs.append(cfseq.sequenceCA.step.combo)
132  last_step_hypoNodes.append(cfseq.sequenceCA.step.combo)
133  file.write(' }\n')
134  file.write(findConnections(cfseq_algs))
135  file.write('\n')
136 
137 # print ("Step connections: ")
138 # print (step_connections)
139  file.write(findConnections(step_connections))
140  nstep+=1
141 
142  file.write( '}')
143  file.close()
144 
145 
146 def stepCF_DataFlow_to_dot(name, cfseq_list):
147  with open( '%s.DF.dot'%name, mode="wt" ) as file:
148  #strict
149  file.write( 'digraph step { \n'\
150  +' concentrate=true; \n'\
151  +' rankdir="LR";\n'
152  +' node [ shape=polygon, fontname=Helvetica ]\n'\
153  +' edge [ fontname=Helvetica ]\n'
154  +' %s [shape=Mdiamond]\n'%name)
155 
156 
157  all_hypos = []
158  for cfseq in cfseq_list:
159  file.write(" %s[fillcolor=%s style=filled]\n"%(cfseq.sequenceCA.filterNode.Alg.name,algColor(cfseq.sequenceCA.filterNode.Alg)))
160  for inp in cfseq.sequenceCA.filterNode.getInputList():
161  file.write(addConnection(name, cfseq.sequenceCA.filterNode.Alg.name, inp))
162 
163  file.write( '\n subgraph cluster_%s {\n'%(cfseq.sequenceCA.step.name)\
164  +' concentrate=true;\n'
165  +' node [color=white style=filled]\n'\
166  +' style=filled\n'\
167  +' color=lightgrey\n'\
168  +' fontname=Helvetica\n'\
169  +' label = %s\n'%(cfseq.sequenceCA.step.name))
170 
171  cfseq_algs = []
172  cfseq_algs.append(cfseq.sequenceCA.filterNode)
173 
174  for menuseq in cfseq.sequenceCA.step.sequences:
175  cfseq_algs, all_hypos, _ = menuseq.buildDFDot(cfseq_algs,
176  all_hypos,
177  None,
178  file)
179  if cfseq.sequenceCA.step.combo is not None:
180  file.write(" %s[color=%s]\n"%(cfseq.sequenceCA.step.combo.Alg.name, algColor(cfseq.sequenceCA.step.combo.Alg)))
181  cfseq_algs.append(cfseq.sequenceCA.step.combo)
182  file.write(' }\n')
183 
184  file.write(findConnections(cfseq_algs))
185  file.write('\n')
186 
187  if DrawHypoTools:
188  drawHypoTools(file, all_hypos)
189 
190  file.write( '}')
191  file.close()
192 
193 
194 def findConnections(alg_list):
195  lineconnect=''
196 
197  alg_set = set(alg_list) # make them unique
198  for nodeA, nodeB in itertools.permutations(alg_set, 2):
199  if isPassSequence(nodeA) or isPassSequence(nodeB):
200  continue
201  ins=nodeB.getInputList()
202  outs=nodeA.getOutputList()
203  dataIntersection = list(set(outs) & set(ins))
204  if len(dataIntersection) > 0:
205  for line in dataIntersection:
206  lineconnect+=addConnection(nodeA.Alg.name, nodeB.Alg.name, line)
207  #print ("Data connections between ", compName(nodeA.Alg)," and ",compName(nodeB.Alg) ,": ", line)
208 
209  return lineconnect
210 
211 
213  lineconnect=''
214  import itertools
215  for nodeA, nodeB in itertools.combinations(alg_list, 2):
216  lineconnect+=findDHconnections(nodeA, nodeB)
217  return lineconnect
218 
219 def findDHconnections(nodeA, nodeB):
220  lineconnect=''
221  # search connections vis DH
222  outs= getValuesProperties(nodeA)
223  ins = getValuesProperties(nodeB)
224  dataIntersection = list(set(outs) & set(ins))
225  if len(dataIntersection) > 0:
226  for line in dataIntersection:
227  lineconnect+=addConnection(nodeA.Alg.name, nodeB.Alg.name, line)
228  #print 'Data DH connections between %s and %s: %s'%(nodeA.Alg.getName(), nodeB.Alg.getName(), line)
229  return lineconnect
230 
231 
232 
234  Excluded = ["StoreGateSvc/DetectorStore", "StoreGateSvc"]
235  values = []
236  algs = []
237  if isinstance(node.Alg, AthSequencer):
238  seq=node.Alg
239  seq.Members.pop(0) # remove InputMaker
240  else:
241  algs.append(node.Alg)
242 
243 
244  for alg in algs:
245  for k, cval in alg.getValuedProperties().items():
246  if type(cval) is list:
247  for val in cval:
248  if val == '': # CAT type(val) is None ??
249  if val not in Excluded:
250  values.append(val)
251  elif cval == '': # CAT type(val) is None ??
252  if cval not in Excluded:
253  values.append(cval)
254  else:
255  continue
256  return set(values)
257 
258 
259 def addConnection(nodeA, nodeB, label=''):
260  line = " %s -> %s \n"%(nodeA,nodeB)
261  #line = " %s -> %s [label=%s]\n"%(nodeA,nodeB,label)
262  # print line
263  return line
264 
HLTCFDot.getValuesProperties
def getValuesProperties(node)
Definition: HLTCFDot.py:233
HLTCFDot.addConnection
def addConnection(nodeA, nodeB, label='')
Definition: HLTCFDot.py:259
HLTCFDot.drawHypoTools
def drawHypoTools(file, all_hypos)
Definition: HLTCFDot.py:15
HLTCFDot.findDHconnections
def findDHconnections(nodeA, nodeB)
Definition: HLTCFDot.py:219
HLTCFDot.findConnections
def findConnections(alg_list)
Definition: HLTCFDot.py:194
HLTCFComponents.isPassSequence
def isPassSequence(alg)
Definition: HLTCFComponents.py:85
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:224
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:79
Trk::open
@ open
Definition: BinningType.h:40
HLTCFDot.all_DataFlow_to_dot
def all_DataFlow_to_dot(name, step_list)
Definition: HLTCFDot.py:87
HLTCFDot.stepCF_ControlFlow_to_dot
def stepCF_ControlFlow_to_dot(stepCF)
Definition: HLTCFDot.py:23
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
HLTCFDot.stepCF_DataFlow_to_dot
def stepCF_DataFlow_to_dot(name, cfseq_list)
Definition: HLTCFDot.py:146
python.CFElements.isSequence
def isSequence(obj)
Definition: CFElements.py:96
HLTCFTools.algColor
def algColor(alg)
Definition: HLTCFTools.py:15
HLTCFDot.findConnections_within_sequence
def findConnections_within_sequence(alg_list)
Definition: HLTCFDot.py:212