Welcome, guest | Sign In | My Account | Store | Cart

Takes a stream of numbers and outputs simple ASCII graphs of those numbers

Python, 134 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#!/usr/bin/env python
#Copyright 2005 Drew Gulino
##This program is free software; you can redistribute it and/or modify
##    it under the terms of the GNU General Public License as published by
##    the Free Software Foundation; either version 2 of the License, or
##    (at your option) any later version.
##
##    This program is distributed in the hope that it will be useful,
##    but WITHOUT ANY WARRANTY; without even the implied warranty of
##    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##    GNU General Public License for more details.
##
##    You should have received a copy of the GNU General Public License
##    along with this program; if not, write to the Free Software
##    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import sys,os,getopt
from getopt import GetoptError

class Tgraph:

    def __init__(self,display_number,columns,symbol,threshold,maximum):
        self.maximum = maximum
        self.display_number = display_number
        self.columns = columns
        self.symbol = symbol
        self.threshold = threshold

    def __del__(self):
        reset = os.popen('tput sgr0').read()
        sys.stdout.write( reset )

    def graph(self,num,max_num):
        sys.stdout.softspace = 0
        if num > 0:
            scale = float(self.columns / max_num)
            characters = int(num*scale)
            for iter in (range(0,characters)):
#                sys.stdout.softspace = 0    #This removes extra spaces after print statements
#                print self.symbol,
                sys.stdout.write(self.symbol)
                sys.stdout.flush()
            if self.display_number:
                sys.stdout.write(str(num))
                sys.stdout.write("\n")
                sys.stdout.flush()
            else:
                sys.stdout.write("\n")
                sys.stdout.flush()
        else:
            if self.display_number:
                sys.stdout.write(str(num))
                sys.stdout.write("\n")
                sys.stdout.flush()

def usage(progname):
    print "Usage: " + progname
    version()
    print "[-h --help]"
    print "[-v --version]"
    print "[-n --no_number] Don't display number w/graph"
    print "[-c --columns=] Display columns(default = 72)"
    print "[-s --symbol=] Symbol to display(default = '*')"
    print "[-t --threshold=] Will color lines over this value"
    print "[-m --maximum=] Presets the scale for this maximum value(default = 0)"

def version():
    print "version: 1.1"

def main(argv, stdout, environ):
    #TODO: Auto detect number of columns in display
    progname = argv[0]
    symbol = "*"
    columns = int(os.popen('tput cols').read()) - 8
    #columns = 72
    number = 0
    display_number = 1
    threshold = 0
    maximum = 0

    bold = os.popen('tput bold').read()
    reset = os.popen('tput sgr0').read()
    dim = os.popen('tput setaf 0').read()
    red = os.popen('tput setaf 1').read()
    green = os.popen('tput setaf 2').read()
    yellow = os.popen('tput setaf 3').read()
    blue = os.popen('tput setaf 4').read()
    magenta = os.popen('tput setaf 5').read()
    try:
        arglist, args = getopt.getopt(argv[1:], "hvnc:s:t:m:", ["help", "version", "no_number","columns=", "symbol=", "threshold=", "maximum"])
    except GetoptError:
        print "Invalid Option!"
        usage(progname)
        return

    # Parse command line arguments
    for (field, val) in arglist:
        if field in ("-h", "--help"):
            usage(progname)
            return
        if field in ("-v", "--version"):
            version()
            return
        if field in ("-n", "--number"):
            display_number = 0
        if field in ("-c", "--columns"):
            columns = int(val)
        if field in ("-s", "--symbol"):
            symbol = val
        if field in ("-t", "--threshold"):
            threshold = val
        if field in ("-m", "--maximum"):
                maximum = val


    tgraph = Tgraph(display_number,columns,symbol,threshold,maximum)
    while 1:
        number = sys.stdin.readline()
        if not number: break
        number = float(number)
        if number > float(tgraph.maximum):
            tgraph.maximum = number
            sys.stdout.write( bold )
        else:
            sys.stdout.write( reset )
        if tgraph.threshold > 0:
            if number >= float(tgraph.threshold):
                sys.stdout.write( red )
            else:
                sys.stdout.write( reset )
        tgraph.graph(float(number),float(tgraph.maximum))

if __name__ == "__main__":
    main(sys.argv, sys.stdout, os.environ)

I'm always monitoring logs and usually a single column of numbers in a log. This script takes as input a single newline separated list of numbers and outputs simple ASCII graphs.

This script is handy when network, system restrictions or just plain lack of time make installing a real GUI solution more trouble than it's worth.

It auto scales when numbers go over a set threshold. It also colors the line when it goes over another set threshold.

This script requires the 'tput' command for colors and bolding. I wanted to have this script run on most *nix platforms without installing anything else, so I didn't want to require a ncurses library.

example (unfortunately no colors):

test.txt:

10
1
50
10
100
1

Command: $ cat test.txt | ./tgraph.py -m 50 -c 80

Output:

*****10.0
1.0
***************************50.0
*****10.0
****************************************************100.0
1.0

You just have to awk/perl/pyliner to get the column you want to graph in multi-column output.