root/trunk/src/visual_logging.py

Revision 386, 5.1 KB (checked in by apdavison, 3 years ago)

Can now plot images/matrices in visual_logging, as well as use the matplotlib kwargs.

Line 
1"""
2NeuroTools.visual_logging
3=========================
4
5Log graphs, rather than text. This is useful when dealing with large data
6structures, such as arrays. x-y data is plotted as a PNG file, which is stored
7inside a zip archive.
8
9You can specify a logging level such that only graphs with an importance above
10that level will be created. e.g., if the logging level is set to WARNING,
11log graphs with a level of DEBUG or INFO will not be created.
12
13The interface is a restricted version of that available in the standard
14library's logging module.
15
16Functions
17---------
18
19basicConfig - specify the zipfile that will be used to store the graphs, and
20              the logging level (DEBUG, INFO, WARN, etc)
21debug       - plots data with level DEBUG
22info        - plots data with level INFO
23warning     - plots data with level WARNING
24error       - plots data with level ERROR
25critical    - plots data with level CRITICAL
26exception   - plots data with level ERROR
27log         - plots data with a user-specified level
28
29"""
30
31import zipfile, atexit, os
32from NeuroTools import check_dependency
33from datetime import datetime
34from logging import CRITICAL, DEBUG, ERROR, FATAL, INFO, WARN, WARNING, NOTSET
35from time import sleep
36
37if check_dependency('pylab'):
38    import pylab
39
40_filename = 'visual_log.zip'
41_zipfile = None
42_level = INFO
43_last_timestamp = ''
44
45def _remove_if_empty():
46    if len(_zipfile.namelist()) == 0 and os.path.exists(_filename):
47        os.remove(_filename)
48
49def basicConfig(filename, level=INFO):
50    global _zipfile, _filename, _level
51    _filename = filename
52    _level = level
53    #_zipfile.close()
54    if os.path.exists(filename) and zipfile.is_zipfile(filename):
55        mode = 'a'
56    else:
57        mode = 'w'
58    _zipfile = zipfile.ZipFile(filename, mode=mode, compression=zipfile.ZIP_DEFLATED)
59    atexit.register(_zipfile.close)
60    atexit.register(_remove_if_empty)
61
62def _reopen():
63    global _zipfile
64    if (_zipfile.fp is None) or _zipfile.fp.closed:
65        _zipfile = zipfile.ZipFile(_filename, mode='a', compression=zipfile.ZIP_DEFLATED)
66
67def flush():
68    """Until the zipfile is closed (normally on exit), the zipfile cannot
69    be accessed by other tools. Calling flush() closes the zipfile, which
70    will be reopened the next time a log function is called.
71    """
72    _zipfile.close()
73
74def _get_timestamp():
75    """At the moment, it is not possible to create visual
76    logs at a rate of more than one/second."""
77    global _last_timestamp
78    timestamp = datetime.now().strftime('%Y%m%d-%H%M%S')
79    while timestamp == _last_timestamp:
80        sleep(0.1)
81        timestamp = datetime.now().strftime('%Y%m%d-%H%M%S')
82    _last_timestamp = timestamp
83    return timestamp
84
85def _plot_fig(ydata, xdata, xlabel, ylabel, title, **kwargs):
86    _reopen()
87    timestamp = _get_timestamp()
88    # create figure
89    pylab.clf()
90    if xdata is not None:
91        pylab.plot(xdata, ydata, **kwargs)
92    else:
93        if hasattr(ydata, 'shape') and len(ydata.shape) > 1:
94            pylab.matshow(ydata, **kwargs)
95            pylab.colorbar()
96        else:
97            pylab.plot(ydata)
98    pylab.xlabel(xlabel)
99    pylab.ylabel(ylabel)
100    pylab.title(title)
101    # add it to the zipfile
102    fig_name = timestamp + '.png'
103    pylab.savefig(fig_name)
104    _zipfile.write(fig_name,
105                   os.path.join(os.path.basename(os.path.splitext(_filename)[0]), fig_name))
106    os.remove(timestamp+'.png')
107
108def debug(ydata, xdata=None, xlabel='', ylabel='', title='', **kwargs):
109    if _level <= DEBUG:
110        _plot_fig(ydata, xdata, xlabel, ylabel, title, **kwargs)
111
112def info(ydata, xdata=None, xlabel='', ylabel='', title='', **kwargs):
113    if _level <= INFO:
114        _plot_fig(ydata, xdata, xlabel, ylabel, title, **kwargs)
115
116def warning(ydata, xdata=None, xlabel='', ylabel='', title='', **kwargs):
117    if _level <= WARNING:
118        _plot_fig(ydata, xdata, xlabel, ylabel, title, **kwargs)
119
120def error(ydata, xdata=None, xlabel='', ylabel='', title='', **kwargs):
121    if _level <= ERROR:
122        _plot_fig(ydata, xdata, xlabel, ylabel, title, **kwargs)
123
124def critical(ydata, xdata=None, xlabel='', ylabel='', title='', **kwargs):
125    if _level <= CRITICAL:
126        _plot_fig(ydata, xdata, xlabel, ylabel, title, **kwargs)
127
128def exception(ydata, xdata=None, xlabel='', ylabel='', title='', **kwargs):
129    if _level <= ERROR:
130        _plot_fig(ydata, xdata, xlabel, ylabel, title, **kwargs)
131
132def log(level, ydata, xdata=None, xlabel='', ylabel='', title='', **kwargs):
133    if _level <= level:
134        _plot_fig(ydata, xdata, xlabel, ylabel, title, **kwargs)
135
136def test():
137    test_file = 'visual_logging_test.zip'
138    if os.path.exists(test_file):
139        os.remove(test_file)
140    basicConfig(test_file, level=DEBUG)
141    xdata = pylab.arange(0, 2*pylab.pi, 0.02*pylab.pi)
142    debug(pylab.sin(xdata), xdata, 'x', 'sin(x)', 'visual_logging test 1')
143    flush()
144    debug(0.5*pylab.sin(2*xdata-0.3), xdata, 'x', 'sin(2x-0.3)/2')
145    debug(pylab.sqrt(xdata), xdata, 'x', 'sqrt(x)')
146    flush()
147    zf = zipfile.ZipFile(test_file, 'r')
148    print zf.namelist()
149    assert len(zf.namelist()) == 3, zf.namelist()
150    zf.close()
151   
152# ==============================================================================
153if __name__ == '__main__':
154    test()
Note: See TracBrowser for help on using the browser.