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  color = "grey" if self.primary else "white"
44  if current_node:
45  color = "darkslategray2" if viewing_dependents else "gold"
46 
47  tooltip = ("[Virtual]" if self.virtual else "[Primary]") + " " + tooltip
48  label = self.name
49 
50 
51  if current_node:
52  # Clicking on the current node toggles between views
53  if viewing_dependents:
54  url = f"../{self.name}.svg"
55  label += r"\n[Deep dependants]"
56  else:
57  url = f"{DEPENDSON_DIR}/{self.name}.svg"
58  label += r"\n[Dependencies]"
59  else:
60  url = "%s.svg" % self.name
61 
62  return f'{self.name} [fillcolor={color}, style=filled, URL="{url}", tooltip="{tooltip}", label="{label}"];'
63 
64 def build_tree(all_logic: Mapping[str, DefectLogic]) -> dict[str, Node]:
65 
66  all_nodes: dict[str, Node] = {}
67 
68  def make_primary(current_logic: str) -> Node:
69  if current_logic in all_nodes:
70  return all_nodes[current_logic]
71  all_nodes[current_logic] = node = Node(current_logic)
72  return node
73 
74  def explore_virtual(current_logic: str) -> Node:
75  if current_logic in all_nodes:
76  return all_nodes[current_logic]
77 
78  this_logic = all_logic[current_logic]
79  all_nodes[current_logic] = node = Node(current_logic)
80 
81  for name in this_logic.clauses:
82  if name in all_logic:
83  child = explore_virtual(name)
84  else:
85  child = make_primary(name)
86 
87  child.parents.add(node)
88  node.children.add(child)
89 
90  return node
91 
92  for name in all_logic:
93  explore_virtual(name)
94 
95  return all_nodes
96 
97 def walk(node: Node, visited: set[Node], visit_primary: bool, fd: TextIO):
98  visited.add(node)
99 
100  for subnode in sorted(node.children, key=Node.get_name):
101  if subnode.virtual or (subnode.primary and visit_primary):
102  print(f"{node.name} -> {subnode.name}", file=fd)
103  walk(subnode, visited, visit_primary, fd)
104 
105 def dump_visited(fd: TextIO, current_node: Node, nodes: set[Node],
106  descs: Mapping[Union[str, int], str], parents: bool):
107  for node in sorted(nodes, key=Node.get_name):
108  at_current_node = node.name == current_node.name
109  description = descs.get(node.name, node.name)
110  # Line breaks in defect descriptions mess up the svg generation
111  description = description.replace('\n', ' ')
112  print(node.dot(at_current_node, description, parents), file=fd)
113 
114 def build_dependency_graph(output_dir: str, node: Node, descs: Mapping[Union[str, int], str]):
115 
116  with open("%s/%s.dot" % (output_dir, node.name), "w") as fd:
117  print(f"strict digraph {node.name} {{", file=fd)
118  print("rankdir=LR;\n", file=fd)
119 
120  visited = set()
121 
122  for parent in sorted(node.parents, key=Node.get_name):
123  print(f"{parent.name} -> {node.name}", file=fd)
124  visited.add(parent)
125 
126  walk(node, visited, node.has_primary_children, fd)
127 
128  dump_visited(fd, node, visited, descs, parents=False)
129 
130  print("}", file=fd)
131 
132 def build_parent_tree(output_dir: str, node: Node, descs: Mapping[Union[str, int], str]):
133 
134  visited = set([node])
135 
136  with open(f"{output_dir}/{DEPENDSON_DIR}/{node.name}.dot", "w") as fd:
137  def walk_parents(node):
138  visited.add(node)
139  for parent in node.parents:
140  print(f"{parent.name} -> {node.name}", file=fd)
141  walk_parents(parent)
142 
143  print(f"strict digraph {node.name} {{", file=fd)
144  print("rankdir=LR;\n", file=fd)
145 
146  walk_parents(node)
147 
148  dump_visited(fd, node, visited, descs, parents=True)
149 
150  print("}", file=fd)
151 
152 def render_all_flags(output_dir: str, all_nodes: dict[str, Node], descs: Mapping[Union[str, int], str]):
153 
154  path = "%s/%s" % (output_dir, DEPENDSON_DIR)
155  if not isdir(path):
156  makedirs(path)
157 
158  for _, node in sorted(all_nodes.items()):
159  build_dependency_graph(output_dir, node, descs)
160  build_parent_tree(output_dir, node, descs)
161 
162 def main():
163 
164  parser = ArgumentParser(description="Dump defect viewer information")
165 
166  parser.add_argument("-t", "--tag", default="HEAD", help="Defect tag")
167  parser.add_argument("-o", "--output", default=".", help="Directory to dump files")
168 
169  args = parser.parse_args()
170 
171  # Instantiate the Defect DB
172  db = DefectsDB(tag=args.tag)
173 
174  descs = db.all_defect_descriptions
175 
176  # Build node objects
177  all_nodes = build_tree(db.virtual_defect_logics)
178 
179  # Write outputs
180  output_dir = "%s/%s" % (args.output, args.tag)
181  render_all_flags(output_dir, all_nodes, descs)
182 
183 if __name__ == "__main__":
184  main()
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:152
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:132
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:64
defects_dump_graph.main
def main()
Definition: defects_dump_graph.py:162
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:97
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename T::value_type > sorted(T begin, T end)
Helper function to create a sorted vector from an unsorted one.
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
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:114
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:105
Trk::open
@ open
Definition: BinningType.h:40
Cut::all
@ all
Definition: SUSYToolsAlg.cxx:64
Muon::print
std::string print(const MuPatSegment &)
Definition: MuonTrackSteering.cxx:28
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:30
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