|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | + |
| 3 | +""" |
| 4 | +Plotting terminal based barplots |
| 5 | +""" |
| 6 | + |
| 7 | +from .utils.helpers import * |
| 8 | +from .histogram import calc_bins, read_numbers |
| 9 | + |
| 10 | +def plot_bar(f, height=20.0, bincount=None, binwidth=None, pch="o", |
| 11 | + colour="default", title="", xlab=None, showSummary=False, |
| 12 | + regular=False, return_str=False): |
| 13 | + ''' Plot bar. |
| 14 | +
|
| 15 | + Parameters |
| 16 | + ---------- |
| 17 | + f : list(number), numpy.ndarray, str(filepath) |
| 18 | + input array |
| 19 | + height : float |
| 20 | + the height of the histogram in # of lines |
| 21 | + bincount : int |
| 22 | + number of bins in the histogram |
| 23 | + binwidth : int |
| 24 | + width of bins in the histogram |
| 25 | + pch : str |
| 26 | + shape of the bars in the plot, e.g 'o' |
| 27 | + colour : str |
| 28 | + white,aqua,pink,blue,yellow,green,red,grey,black,default,ENDC |
| 29 | + title : str |
| 30 | + title at the top of the plot, None = no title |
| 31 | + xlab : boolean |
| 32 | + whether or not to display x-axis labels |
| 33 | + showSummary : boolean |
| 34 | + whether or not to display a summary |
| 35 | + regular : boolean |
| 36 | + whether or not to start y-labels at 0 |
| 37 | + return_str : boolean |
| 38 | + return string represent the plot or print it out, default: False |
| 39 | +
|
| 40 | + Example |
| 41 | + ------- |
| 42 | + >>> y = np.random.rand(50) |
| 43 | + >>> plot_bar(y, bincount=50, colour='red') |
| 44 | +
|
| 45 | + >>> 0.971| |
| 46 | + >>> 0.923| o o o o |
| 47 | + >>> 0.875| o o o o o oo |
| 48 | + >>> 0.827| o o o o o o ooo |
| 49 | + >>> 0.779| o o o o o o o o ooo |
| 50 | + >>> 0.731| o o o o o o o o o ooo |
| 51 | + >>> 0.683| oo oo o o o o o o o o o ooo |
| 52 | + >>> 0.635| oo oo o oo o o o o o oo o ooo |
| 53 | + >>> 0.587| oo oo o oo o ooo o o oo o ooo |
| 54 | + >>> 0.539| oo oo o oooo ooo o o oo o ooo o |
| 55 | + >>> 0.491| ooo ooo o oooo ooo o o ooo o ooo o |
| 56 | + >>> 0.443| ooo ooo oo ooooo oooo o o ooo o ooo o |
| 57 | + >>> 0.395| ooo ooo ooooooooo oooo o o ooo o ooo o |
| 58 | + >>> 0.347| oooo ooo ooooooooo ooooo o o ooo o ooo o |
| 59 | + >>> 0.299| oooo ooo ooooooooo ooooo o o ooo o ooo o |
| 60 | + >>> 0.251| oooo ooo ooooooooo ooooo o o ooo o ooo o o |
| 61 | + >>> 0.203| oooo ooo ooooooooo ooooo ooo ooo o ooo o o |
| 62 | + >>> 0.155| oooo ooo oo ooooooooo ooooo ooo ooo ooooooo oo |
| 63 | + >>> 0.107| ooooo ooo oo ooooooooo oooooooooo ooooooooooo ooo |
| 64 | + >>> 0.059| ooooo oooooo ooooooooo ooooooooooooooooooooooo ooo |
| 65 | + >>> 0.011| oooooooooooooooooooooo ooooooooooooooooooooooooooo |
| 66 | + >>> -------------------------------------------------- |
| 67 | + ''' |
| 68 | + if pch is None: |
| 69 | + pch = "o" |
| 70 | + |
| 71 | + splot = '' |
| 72 | + if isinstance(f, str): |
| 73 | + f = open(f).readlines() |
| 74 | + |
| 75 | + # ====== Create data ====== # |
| 76 | + min_val, max_val = None, None |
| 77 | + n, mean, sd = 0.0, 0.0, 0.0 |
| 78 | + |
| 79 | + # pick mode and get data |
| 80 | + numbers = [i for i in read_numbers(f)] |
| 81 | + int_mode = False |
| 82 | + if numbers[0].is_integer(): |
| 83 | + int_mode = True |
| 84 | + |
| 85 | + # rescale big enough to show on bars |
| 86 | + min_orig = min(numbers) # original |
| 87 | + max_orig = max(numbers) |
| 88 | + numbers = [1000 * (i - min_orig) / (max_orig - min_orig + 1e-8) for i in numbers] |
| 89 | + |
| 90 | + # statistics |
| 91 | + n = len(numbers) |
| 92 | + min_val = min(numbers) |
| 93 | + max_val = max(numbers) |
| 94 | + mean = sum(numbers) / n |
| 95 | + sd = (sum([(mean - i)**2 for i in numbers]) / (n - 1)) ** 0.5 |
| 96 | + |
| 97 | + # bins is index |
| 98 | + if bincount is not None: |
| 99 | + bincount = min(bincount, n) |
| 100 | + bins = list(calc_bins(n, 0., n + 0., bincount, binwidth)) |
| 101 | + bins = [int(i) for i in bins] |
| 102 | + hist = dict((i, 0) for i in range(len(bins) - 1)) |
| 103 | + |
| 104 | + # hist is the mean value of array with indices within bin |
| 105 | + for idx, (i, j) in enumerate(zip(bins, bins[1:])): |
| 106 | + arr = numbers[i:j] |
| 107 | + hist[idx] = sum(arr) / len(arr) # calculate mean |
| 108 | + |
| 109 | + # ====== Start plot ====== # |
| 110 | + min_y, max_y = min(hist.values()), max(hist.values()) |
| 111 | + |
| 112 | + start = max(min_y, 1) |
| 113 | + stop = max_y + 1 |
| 114 | + |
| 115 | + if regular: |
| 116 | + start = 1 |
| 117 | + |
| 118 | + if height is None: |
| 119 | + height = stop - start |
| 120 | + if height > 20: |
| 121 | + height = 20 |
| 122 | + |
| 123 | + ys = list(drange(start, stop, float(stop - start) / height)) |
| 124 | + ys.reverse() |
| 125 | + |
| 126 | + nlen = max(len(str(min_y)), len(str(max_y))) + 1 |
| 127 | + |
| 128 | + if title: |
| 129 | + splot += print_return_str( |
| 130 | + box_text(title, max(len(hist) * 2, len(title)), nlen), |
| 131 | + return_str=return_str) |
| 132 | + splot += print_return_str('', return_str=return_str) |
| 133 | + |
| 134 | + used_labs = set() |
| 135 | + for y in ys: |
| 136 | + if int_mode: |
| 137 | + ylab = '%d' % int(y * (max_orig - min_orig + 1e-8) / 1000 + min_orig) |
| 138 | + else: |
| 139 | + ylab = '%.3f' % float(y * (max_orig - min_orig + 1e-8) / 1000 + min_orig) |
| 140 | + if ylab in used_labs: |
| 141 | + ylab = "" |
| 142 | + else: |
| 143 | + used_labs.add(ylab) |
| 144 | + ylab = " " * (nlen - len(ylab)) + ylab + "|" |
| 145 | + |
| 146 | + splot += print_return_str(ylab, end=' ', return_str=return_str) |
| 147 | + |
| 148 | + for i in range(len(hist)): |
| 149 | + if int(y) <= hist[i]: |
| 150 | + splot += printcolour(pch, True, colour, return_str) |
| 151 | + else: |
| 152 | + splot += printcolour(" ", True, colour, return_str) |
| 153 | + splot += print_return_str('', return_str=return_str) |
| 154 | + xs = hist.keys() |
| 155 | + |
| 156 | + splot += print_return_str(" " * (nlen + 1) + "-" * len(xs), |
| 157 | + return_str=return_str) |
| 158 | + |
| 159 | + if xlab: |
| 160 | + xlen = len(str(float((max_y) / height) + max_y)) |
| 161 | + for i in range(0, xlen): |
| 162 | + splot += printcolour(" " * (nlen + 1), True, colour, return_str) |
| 163 | + for x in range(0, len(hist)): |
| 164 | + num = str(bins[x]) |
| 165 | + if x % 2 != 0: |
| 166 | + pass |
| 167 | + elif i < len(num): |
| 168 | + splot += print_return_str(num[i], end=' ', |
| 169 | + return_str=return_str) |
| 170 | + else: |
| 171 | + splot += print_return_str(" ", end=' ', |
| 172 | + return_str=return_str) |
| 173 | + splot += print_return_str('', return_str=return_str) |
| 174 | + |
| 175 | + center = max(map(len, map(str, [n, min_val, mean, max_val]))) |
| 176 | + center += 15 |
| 177 | + |
| 178 | + if showSummary: |
| 179 | + splot += print_return_str('', return_str=return_str) |
| 180 | + splot += print_return_str("-" * (2 + center), return_str=return_str) |
| 181 | + splot += print_return_str("|" + "Summary".center(center) + "|", |
| 182 | + return_str=return_str) |
| 183 | + splot += print_return_str("-" * (2 + center), return_str=return_str) |
| 184 | + summary = "|" + ("observations: %d" % n).center(center) + "|\n" |
| 185 | + summary += "|" + ("min value: %f" % min_val).center(center) + "|\n" |
| 186 | + summary += "|" + ("mean : %f" % mean).center(center) + "|\n" |
| 187 | + summary += "|" + ("sd : %f" % sd).center(center) + "|\n" |
| 188 | + summary += "|" + ("max value: %f" % max_val).center(center) + "|\n" |
| 189 | + summary += "-" * (2 + center) |
| 190 | + splot += print_return_str(summary, return_str=return_str) |
| 191 | + |
| 192 | + if return_str: |
| 193 | + return splot |
0 commit comments