6
6
7
7
import numpy as np
8
8
import matplotlib .pyplot as plt
9
+ from collections import namedtuple
9
10
10
11
from .common import open_input
11
12
12
13
from .parsers import PARSERS
13
14
14
15
16
+ Axis = namedtuple ("Axis" , ["desc" , "attr" , "scale" , "scale_kwargs" ], defaults = [None , None , None , None ])
17
+ TIMESERIES = Axis ("Time" , "timestamp" )
18
+
19
+
15
20
class Plotter ():
16
21
"""Rudimentary plotter of data values against timestamp"""
17
- def __init__ (self , y_name , y_desc = None ):
18
- self ._x_name = 'timestamp'
19
- self ._y_name = y_name
20
- if y_desc is None :
21
- self ._y_desc = y_name
22
- else :
23
- self ._y_desc = y_desc
22
+ def __init__ (self , x , y ):
23
+ self ._x = x
24
+ self ._y = y
24
25
self ._x_data = []
25
26
self ._y_data = []
26
27
28
+ @staticmethod
29
+ def _extract_attr (axis , data ):
30
+ return getattr (data , axis .attr )
31
+
32
+ def _set_yscale (self , ax ):
33
+ if self ._y .scale is not None :
34
+ ax .set_yscale (self ._y .scale , ** (self ._y .scale_kwargs or {}))
35
+ elif any ((abs (v ) > 10 for v in self ._y_data )):
36
+ ax .set_yscale ("symlog" , linthresh = 10 )
37
+
27
38
def append (self , data ):
28
39
"""Append x and y data points extracted from `data`"""
29
- x_val = getattr (data , self ._x_name )
30
- self ._x_data .append (x_val )
31
- y_val = getattr (data , self ._y_name )
32
- self ._y_data .append (y_val )
40
+ self ._x_data .append (self ._extract_attr (self ._x , data ))
41
+ self ._y_data .append (self ._extract_attr (self ._y , data ))
33
42
34
43
def plot (self , filename ):
35
44
"""Plot data to `filename`"""
36
45
fig , (ax1 , ax2 ) = plt .subplots (2 , constrained_layout = True )
37
46
fig .set_size_inches (10 , 8 )
38
47
ax1 .axhline (0 , color = 'black' )
39
- if any ((abs (v ) > 10 for v in self ._y_data )):
40
- ax1 .set_yscale ('symlog' , linthresh = 10 )
48
+ self ._set_yscale (ax1 )
49
+ if self ._x .scale is not None :
50
+ ax1 .set_xscale (self ._x .scale , ** (self ._x .scale_kwargs or {}))
41
51
ax1 .plot (self ._x_data , self ._y_data , '.' )
42
52
ax1 .grid ()
43
- ax1 .set_title (f'{ self ._x_name } vs { self ._y_desc } ' )
53
+ ax1 .set_title (f'{ self ._x . desc } vs { self ._y . desc } ' )
44
54
counts , bins = np .histogram (
45
55
np .array (self ._y_data , dtype = float ),
46
56
bins = 'scott' ,
47
57
)
48
58
ax2 .hist (bins [:- 1 ], bins , weights = counts )
49
- ax2 .set_yscale ('symlog' , linthresh = 10 )
50
- ax2 .set_title (f'Histogram of { self ._y_desc } ' )
59
+ self ._set_yscale (ax2 )
60
+ if self ._x .scale is not None :
61
+ ax2 .set_xscale (self ._x .scale , ** (self ._x .scale_kwargs or {}))
62
+ ax2 .set_title (f'Histogram of { self ._y .desc } ' )
51
63
plt .savefig (filename )
52
64
53
-
54
65
def main ():
55
66
"""Plot data parsed from log messages from a single source.
56
67
@@ -75,7 +86,7 @@ def main():
75
86
)
76
87
args = aparser .parse_args ()
77
88
parser = PARSERS [args .parser ]()
78
- plotter = Plotter (parser .y_name )
89
+ plotter = Plotter (TIMESERIES , Axis ( parser .y_name , parser . y_name ) )
79
90
with open_input (args .input ) as fid :
80
91
method = parser .canonical if args .canonical else parser .parse
81
92
for parsed in method (fid ):
0 commit comments