ATLAS Offline Software
defects_dump_graph.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 from os import makedirs
4 from os.path import isdir
5 from argparse import ArgumentParser
6 from typing import Mapping, Union, TextIO
7 
8 from DQDefects import DefectsDB
9 from DQDefects.virtual_logic import DefectLogic
10 
11 DEPENDSON_DIR = "dependson"
12 
13 class Node(object):
14  def __init__(self, name: str):
15  self.name = name
16  self.children = set()
17  self.parents = set()
18 
19  def get_name(self) -> str:
20  return self.name
21 
22  @property
23  def virtual(self) -> bool:
24  return bool(self.children)
25 
26  @property
27  def primary(self) -> bool:
28  return not self.virtual
29 
30  @property
31  def has_primary_children(self) -> bool:
32  return any(c.primary for c in self.children)
33 
34  @property
35  def only_primary_children(self) -> bool:
36  return all(c.primary for c in self.children)
37 
38  def __repr__(self):
39  return (f'<Node {self.name} parents="{[n.name for n in self.parents]}" '
40  f'children="{[n.name for n in self.children]}">')
41 
42  def dot(self, current_node=False, tooltip: str ="", viewing_dependents: bool =False) -> str:
43  import html
44  color = "grey" if self.primary else "white"
45  if current_node:
46  color = "darkslategray2" if viewing_dependents else "gold"
47 
48  tooltip = ("[Virtual]" if self.virtual else "[Primary]") + " " + html.escape(tooltip, True)
49  label = self.name
50 
51 
52  if current_node:
53  # Clicking on the current node toggles between views
54  if viewing_dependents:
55  url = f"../{self.name}.svg"
56  label += r"\n[Deep dependants]"
57  else:
58  url = f"{DEPENDSON_DIR}/{self.name}.svg"
59  label += r"\n[Dependencies]"
60  else:
61  url = "%s.svg" % self.name
62 
63  return f'{self.name} [fillcolor={color}, style=filled, URL="{url}", tooltip="{tooltip}", label="{label}"];'
64 
65 def build_tree(all_logic: Mapping[str, DefectLogic]) -> dict[str, Node]:
66 
67  all_nodes: dict[str, Node] = {}
68 
69  def make_primary(current_logic: str) -> Node:
70  if current_logic in all_nodes:
71  return all_nodes[current_logic]
72  all_nodes[current_logic] = node = Node(current_logic)
73  return node
74 
75  def explore_virtual(current_logic: str) -> Node:
76  if current_logic in all_nodes:
77  return all_nodes[current_logic]
78 
79  this_logic = all_logic[current_logic]
80  all_nodes[current_logic] = node = Node(current_logic)
81 
82  for name in this_logic.clauses:
83  if name in all_logic:
84  child = explore_virtual(name)
85  else:
86  child = make_primary(name)
87 
88  child.parents.add(node)
89  node.children.add(child)
90 
91  return node
92 
93  for name in all_logic:
94  explore_virtual(name)
95 
96  return all_nodes
97 
98 def walk(node: Node, visited: set[Node], visit_primary: bool, fd: TextIO):
99  visited.add(node)
100 
101  for subnode in sorted(node.children, key=Node.get_name):
102  if subnode.virtual or (subnode.primary and visit_primary):
103  print(f"{node.name} -> {subnode.name}", file=fd)
104  walk(subnode, visited, visit_primary, fd)
105 
106 def dump_visited(fd: TextIO, current_node: Node, nodes: set[Node],
107  descs: Mapping[Union[str, int], str], parents: bool):
108  for node in sorted(nodes, key=Node.get_name):
109  at_current_node = node.name == current_node.name
110  description = descs.get(node.name, node.name)
111  # Line breaks in defect descriptions mess up the svg generation
112  description = description.replace('\n', ' ')
113  print(node.dot(at_current_node, description, parents), file=fd)
114 
115 def build_dependency_graph(output_dir: str, node: Node, descs: Mapping[Union[str, int], str]):
116 
117  with open("%s/%s.dot" % (output_dir, node.name), "w") as fd:
118  print(f"strict digraph {node.name} {{", file=fd)
119  print("rankdir=LR;\n", file=fd)
120 
121  visited = set()
122 
123  for parent in sorted(node.parents, key=Node.get_name):
124  print(f"{parent.name} -> {node.name}", file=fd)
125  visited.add(parent)
126 
127  walk(node, visited, node.has_primary_children, fd)
128 
129  dump_visited(fd, node, visited, descs, parents=False)
130 
131  print("}", file=fd)
132 
133 def build_parent_tree(output_dir: str, node: Node, descs: Mapping[Union[str, int], str]):
134 
135  visited = set([node])
136 
137  with open(f"{output_dir}/{DEPENDSON_DIR}/{node.name}.dot", "w") as fd:
138  def walk_parents(node):
139  visited.add(node)
140  for parent in node.parents:
141  print(f"{parent.name} -> {node.name}", file=fd)
142  walk_parents(parent)
143 
144  print(f"strict digraph {node.name} {{", file=fd)
145  print("rankdir=LR;\n", file=fd)
146 
147  walk_parents(node)
148 
149  dump_visited(fd, node, visited, descs, parents=True)
150 
151  print("}", file=fd)
152 
153 def render_all_flags(output_dir: str, all_nodes: dict[str, Node], descs: Mapping[Union[str, int], str]):
154 
155  path = "%s/%s" % (output_dir, DEPENDSON_DIR)
156  if not isdir(path):
157  makedirs(path)
158 
159  for _, node in sorted(all_nodes.items()):
160  build_dependency_graph(output_dir, node, descs)
161  build_parent_tree(output_dir, node, descs)
162 
163 def main():
164 
165  parser = ArgumentParser(description="Dump defect viewer information")
166 
167  parser.add_argument("-t", "--tag", default="HEAD", help="Defect tag")
168  parser.add_argument("-o", "--output", default=".", help="Directory to dump files")
169 
170  args = parser.parse_args()
171 
172  # Instantiate the Defect DB
173  db = DefectsDB(tag=args.tag)
174 
175  descs = db.all_defect_descriptions
176 
177  # Build node objects
178  all_nodes = build_tree(db.virtual_defect_logics)
179 
180  # Write outputs
181  output_dir = "%s/%s" % (args.output, args.tag)
182  render_all_flags(output_dir, all_nodes, descs)
183 
184 if __name__ == "__main__":
185  main()
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename R::value_type > sorted(const R &r, PROJ proj={})
Helper function to create a sorted vector from an unsorted range.
defects_dump_graph.Node.parents
parents
Definition: defects_dump_graph.py:17
defects_dump_graph.Node.virtual
bool virtual(self)
Definition: defects_dump_graph.py:23
defects_dump_graph.Node
Definition: defects_dump_graph.py:13
defects_dump_graph.render_all_flags
def render_all_flags(str output_dir, dict[str, Node] all_nodes, Mapping[Union[str, int], str] descs)
Definition: defects_dump_graph.py:153
defects_dump_graph.Node.dot
str dot(self, current_node=False, str tooltip="", bool viewing_dependents=False)
Definition: defects_dump_graph.py:42
defects_dump_graph.build_parent_tree
def build_parent_tree(str output_dir, Node node, Mapping[Union[str, int], str] descs)
Definition: defects_dump_graph.py:133
defects_dump_graph.Node.name
name
Definition: defects_dump_graph.py:15
defects_dump_graph.Node.__init__
def __init__(self, str name)
Definition: defects_dump_graph.py:14
defects_dump_graph.build_tree
dict[str, Node] build_tree(Mapping[str, DefectLogic] all_logic)
Definition: defects_dump_graph.py:65
defects_dump_graph.main
def main()
Definition: defects_dump_graph.py:163
defects_dump_graph.Node.get_name
str get_name(self)
Definition: defects_dump_graph.py:19
defects_dump_graph.walk
def walk(Node node, set[Node] visited, bool visit_primary, TextIO fd)
Definition: defects_dump_graph.py:98
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:232
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:25
defects_dump_graph.build_dependency_graph
def build_dependency_graph(str output_dir, Node node, Mapping[Union[str, int], str] descs)
Definition: defects_dump_graph.py:115
defects_dump_graph.dump_visited
def dump_visited(TextIO fd, Node current_node, set[Node] nodes, Mapping[Union[str, int], str] descs, bool parents)
Definition: defects_dump_graph.py:106
Trk::open
@ open
Definition: BinningType.h:40
defects_dump_graph.Node.only_primary_children
bool only_primary_children(self)
Definition: defects_dump_graph.py:35
defects_dump_graph.Node.has_primary_children
bool has_primary_children(self)
Definition: defects_dump_graph.py:31
defects_dump_graph.Node.children
children
Definition: defects_dump_graph.py:16
pickleTool.object
object
Definition: pickleTool.py:29
defects_dump_graph.Node.__repr__
def __repr__(self)
Definition: defects_dump_graph.py:38
defects_dump_graph.Node.primary
bool primary(self)
Definition: defects_dump_graph.py:27
xAOD::bool
setBGCode setTAP setLVL2ErrorBits bool
Definition: TrigDecision_v1.cxx:60
Cut::all
@ all
Definition: SUSYToolsAlg.cxx:67