├── LICENSE ├── README.md └── quickhist └── quickhist /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Nagarjuna Kumar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | quickhist 2 | ========= 3 | 4 | **NOTE:** requires `numpy` 5 | 6 | 7 | Plots the distribution of the input data, and provides some basic stats. 8 | 9 | Try: 10 | 11 | for x in $( seq 1 100000 ); do echo $(( ($RANDOM + $RANDOM + $RANDOM) )) ; done | quickhist 12 | 13 | ``` 14 | 15 | │ ╻╻┃┃┃╻┃╻╻╻ 16 | │ ╻┃┃┃┃┃┃┃┃┃┃┃╻╻ 17 | │ ╻┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃╻ 18 | │ ╻┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃ 19 | prop. │ ╻┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃╻ 20 | │ ╻┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃╻ 21 | │ ╻┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃╻ 22 | │ ╻┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃╻╻ 23 | │ ╻╻┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃╻╻ 24 | │ ╻╻╻┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃╻╻ 25 | └────────────────────────────────────────────────────────────── 26 | 1601.0 97480.0 27 | 28 | count : 100000 29 | 25th perc. : 37635.75 30 | 50th perc. : 49159.0 31 | 75th perc. : 60738.0 32 | ``` 33 | 34 | for x in $( seq 1 100000 ); do echo $RANDOM ; done | quickhist 35 | 36 | ``` 37 | │ ┃ 38 | │ ┃ ╻╻╻ ┃ ╻╻┃ ╻ ┃┃ ╻╻╻╻┃ ╻┃ ┃ ┃╻╻╻ ╻╻ ╻╻ ╻ ┃ ╻╻┃╻ 39 | │┃┃┃┃ ┃┃┃ ┃┃┃┃┃┃┃┃┃┃╻┃┃┃┃┃╻┃┃┃┃┃╻┃┃┃┃╻┃┃ ┃┃┃┃ ┃ ╻╻┃┃╻┃╻┃┃┃┃┃ 40 | │┃┃┃┃╻┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃ 41 | prop. │┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃ 42 | │┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃ 43 | │┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃ 44 | │┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃ 45 | │┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃ 46 | │┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃┃ 47 | └────────────────────────────────────────────────────────────── 48 | 5.0 32765.0 49 | 50 | count : 10000 51 | 25th perc. : 8156.5 52 | 50th perc. : 16158.5 53 | 75th perc. : 24324.0 54 | ``` 55 | -------------------------------------------------------------------------------- /quickhist/quickhist: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2015 Nagarjuna Kumarappan 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | # THE SOFTWARE. 22 | # 23 | # Author: Nagarjuna Kumarappan 24 | 25 | 26 | import sys 27 | from numpy import histogram,percentile 28 | import argparse 29 | from math import floor 30 | 31 | # Constants 32 | CHARS={'full_top':'┃', 'half_top':'╻', 'fill':'┃'} 33 | 34 | def draw_hist(normed_hist_list,shape,args): 35 | """ takes a list of histogram bin counts and shape(min,max) of input """ 36 | 37 | # TODO make the offset configurable 38 | y_offset = ' ' 39 | y_label = ' prop. ' 40 | 41 | print "" 42 | # Build plot from top level 43 | for depth in range(args.height-1,-1,-1): 44 | 45 | # Draw Y axis 46 | if depth == args.height/2: 47 | sys.stdout.write(y_label+'│') 48 | else: 49 | sys.stdout.write(y_offset+'│') 50 | 51 | # Draw bars 52 | for item in normed_hist_list: 53 | floored_item = floor(item) 54 | if floored_item >= depth: 55 | if floored_item == depth and item % 1 < 0.75 and item%1 >0.25: 56 | sys.stdout.write( CHARS['half_top'] ) 57 | elif floored_item == depth and item % 1 > 0.75 : 58 | sys.stdout.write( CHARS['full_top'] ) 59 | elif floored_item > depth: 60 | sys.stdout.write( CHARS['fill'] ) 61 | else: 62 | sys.stdout.write(' ') 63 | continue 64 | else: 65 | sys.stdout.write(' ') 66 | print "" 67 | 68 | # Draw X axis 69 | print y_offset + '└'+ "─"*(args.bins+2) 70 | print y_offset + str(shape[0]) + ' '*(args.bins-3) + str(shape[1]) 71 | 72 | 73 | def parse_args(): 74 | parser = argparse.ArgumentParser(description='draw a histogram from stdin', add_help=False) 75 | parser.add_argument('-b', '--bins', type=int, help='the number of bins (default=60)', default=60) 76 | parser.add_argument('-h', '--height', type=int, help='the height of the plot (default=10)', default=10) 77 | parser.add_argument('-?', '--help', action='help', help='show this help and exit') 78 | return parser.parse_args(sys.argv[1:]) 79 | 80 | 81 | def main(): 82 | 83 | args = parse_args() 84 | input_data = sys.stdin.read().strip('\n') 85 | input_list = input_data.split('\n') 86 | 87 | # Convert input to floats 88 | try: 89 | input_list = map(float,input_list) 90 | except: 91 | raise SystemError("Failed to convert input to float") 92 | 93 | 94 | hist_list,bin_edges = histogram(input_list,bins=args.bins) 95 | max_count = max(hist_list) 96 | shape = ( min(input_list), max(input_list) ) 97 | normed_hist_list = [ float(x)*args.height/max_count for x in hist_list ] 98 | 99 | # Draw the histogram 100 | draw_hist(normed_hist_list,shape,args) 101 | 102 | # Calculate stats on data 103 | print '\ncount :',len(input_list) 104 | for perc in [25,50,75]: 105 | print "{0}th perc. :".format(perc), percentile(input_list,perc) 106 | 107 | 108 | if __name__ == '__main__': 109 | main() 110 | --------------------------------------------------------------------------------