open traces recursively
[deliverable/lttng-analyses.git] / ascii_graph / __init__.py
CommitLineData
846cf979
JD
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4from __future__ import unicode_literals
5import sys
6
846cf979 7
8054fc4c
SG
8class Pyasciigraph:
9 def __init__(self, line_length=79, min_graph_length=50,
10 separator_length=2):
846cf979 11 """Constructor of Pyasciigraph
8054fc4c 12
846cf979 13 :param int line_length: the max number of char on a line
8054fc4c 14 if any line cannot be shorter,
846cf979
JD
15 it will go over this limit
16 :param int min_graph_length: the min number of char used by the graph
17 :param int separator_length: the length of field separator
18 """
19 self.line_length = line_length
20 self.separator_length = separator_length
21 self.min_graph_length = min_graph_length
22
23 def _u(self, x):
24 if sys.version < '3':
25 import codecs
26 return codecs.unicode_escape_decode(x)[0]
27 else:
28 return x
29
30 def _get_maximum(self, data):
31 all_max = {}
32 all_max['value_max_length'] = 0
33 all_max['info_max_length'] = 0
34 all_max['max_value'] = 0
35
36 for (info, value) in data:
37 if value > all_max['max_value']:
38 all_max['max_value'] = value
39
40 if len(info) > all_max['info_max_length']:
41 all_max['info_max_length'] = len(info)
8054fc4c 42
846cf979
JD
43 if len(str(value)) > all_max['value_max_length']:
44 all_max['value_max_length'] = len(str(value))
45 return all_max
46
47 def _gen_graph_string(self, value, max_value, graph_length, start_value):
40fbd9cc
JD
48 if max_value == 0:
49 number_of_square = int(value * graph_length)
50 else:
51 number_of_square = int(value * graph_length / max_value)
846cf979
JD
52 number_of_space = int(start_value - number_of_square)
53 return '█' * number_of_square + self._u(' ') * number_of_space
54
55 def _gen_info_string(self, info, start_info, line_length):
56 number_of_space = (line_length - start_info - len(info))
57 return info + self._u(' ') * number_of_space
58
bc9bd1f5 59 def _gen_value_string(self, value, start_value, start_info, unit):
846cf979 60 number_space = start_info -\
8054fc4c
SG
61 start_value -\
62 len(str(value)) -\
63 self.separator_length
846cf979 64
8054fc4c 65 return ' ' * number_space +\
bc9bd1f5 66 str(value) + str(unit) +\
8054fc4c 67 ' ' * self.separator_length
846cf979
JD
68
69 def _sanitize_string(self, string):
8054fc4c 70 # get the type of a unicode string
846cf979
JD
71 unicode_type = type(self._u('t'))
72 input_type = type(string)
73 if input_type is str:
ddefe9a6 74 if sys.version_info.major < 3: # pragma: no cover
846cf979 75 info = unicode(string)
8054fc4c 76 else:
846cf979
JD
77 info = string
78 elif input_type is unicode_type:
79 info = string
80 elif input_type is int or input_type is float:
ddefe9a6 81 if sys.version_info.major < 3: # pragma: no cover
846cf979
JD
82 info = unicode(string)
83 else:
84 info = str(string)
85 return info
86
87 def _sanitize_data(self, data):
88 ret = []
89 for item in data:
90 ret.append((self._sanitize_string(item[0]), item[1]))
91 return ret
92
bc9bd1f5 93 def graph(self, label, data, sort=0, with_value=True, unit=""):
846cf979 94 """function generating the graph
8054fc4c 95
846cf979
JD
96 :param string label: the label of the graph
97 :param iterable data: the data (list of tuple (info, value))
98 info must be "castable" to a unicode string
99 value must be an int or a float
100 :param int sort: flag sorted
101 0: not sorted (same order as given) (default)
102 1: increasing order
103 2: decreasing order
104 :param boolean with_value: flag printing value
105 True: print the numeric value (default)
106 False: don't print the numeric value
107 :rtype: a list of strings (each lines)
108
109 """
110 result = []
111 san_data = self._sanitize_data(data)
112 san_label = self._sanitize_string(label)
113
114 if sort == 1:
8054fc4c
SG
115 san_data = sorted(san_data, key=lambda value: value[1],
116 reverse=False)
846cf979 117 elif sort == 2:
8054fc4c
SG
118 san_data = sorted(san_data, key=lambda value: value[1],
119 reverse=True)
846cf979
JD
120
121 all_max = self._get_maximum(san_data)
8054fc4c 122
846cf979 123 real_line_length = max(self.line_length, len(label))
8054fc4c 124
846cf979 125 min_line_length = self.min_graph_length +\
8054fc4c
SG
126 2 * self.separator_length +\
127 all_max['value_max_length'] +\
128 all_max['info_max_length']
846cf979
JD
129
130 if min_line_length < real_line_length:
8054fc4c 131 # calcul of where to start info
846cf979 132 start_info = self.line_length -\
8054fc4c
SG
133 all_max['info_max_length']
134 # calcul of where to start value
846cf979 135 start_value = start_info -\
8054fc4c
SG
136 self.separator_length -\
137 all_max['value_max_length']
138 # calcul of where to end graph
846cf979 139 graph_length = start_value -\
8054fc4c 140 self.separator_length
846cf979 141 else:
8054fc4c 142 # calcul of where to start value
846cf979 143 start_value = self.min_graph_length +\
8054fc4c
SG
144 self.separator_length
145 # calcul of where to start info
846cf979 146 start_info = start_value +\
8054fc4c
SG
147 all_max['value_max_length'] +\
148 self.separator_length
149 # calcul of where to end graph
846cf979 150 graph_length = self.min_graph_length
8054fc4c 151 # calcul of the real line length
846cf979
JD
152 real_line_length = min_line_length
153
154 result.append(san_label)
8054fc4c 155 result.append(self._u('#') * real_line_length)
846cf979
JD
156
157 for item in san_data:
158 info = item[0]
159 value = item[1]
160
161 graph_string = self._gen_graph_string(
8054fc4c
SG
162 value,
163 all_max['max_value'],
164 graph_length,
165 start_value)
846cf979 166
452b4312
JD
167 if with_value:
168 value_string = self._gen_value_string(
169 value,
170 start_value,
171 start_info, unit)
172 else:
173 value_string = ""
846cf979
JD
174
175 info_string = self._gen_info_string(
8054fc4c
SG
176 info,
177 start_info,
178 real_line_length)
846cf979
JD
179 new_line = graph_string + value_string + info_string
180 result.append(new_line)
181
182 return result
183
184if __name__ == '__main__':
8054fc4c
SG
185 test = [('long_label', 423), ('sl', 1234), ('line3', 531),
186 ('line4', 200), ('line5', 834)]
846cf979 187 graph = Pyasciigraph()
8054fc4c 188 for line in graph.graph('test print', test):
846cf979 189 print(line)
This page took 0.032347 seconds and 5 git commands to generate.