import numpy as np
from vayesta.core.util import einsum
[docs]def make_histogram(
values, bins, labels=None, binwidth=5, height=6, fill=":", show_number=False, invertx=True, rstrip=True
):
hist = np.histogram(values, bins)[0]
if invertx:
bins, hist = bins[::-1], hist[::-1]
hmax = hist.max()
width = binwidth * len(hist)
plot = np.zeros((height + show_number, width), dtype=str)
plot[:] = " "
if hmax > 0:
for i, hval in enumerate(hist):
colstart = i * binwidth
colend = (i + 1) * binwidth
barheight = int(np.rint(height * hval / hmax))
if barheight == 0:
continue
# Top
plot[-barheight, colstart + 1 : colend - 1] = "_"
if show_number:
number = " {:^{w}s}".format("(%d)" % hval, w=binwidth - 1)
for idx, i in enumerate(range(colstart, colend)):
plot[-barheight - 1, i] = number[idx]
if barheight == 1:
continue
# Fill
if fill:
plot[-barheight + 1 :, colstart + 1 : colend] = fill
# Left/right border
plot[-barheight + 1 :, colstart] = "|"
plot[-barheight + 1 :, colend - 1] = "|"
lines = ["".join(plot[r, :].tolist()) for r in range(height)]
# Baseline
lines.append("+" + ((width - 2) * "-") + "+")
if labels:
if isinstance(labels, str):
lines += [labels]
else:
lines += ["".join(["{:^{w}}".format(l, w=binwidth) for l in labels])]
if rstrip:
lines = [line.rstrip() for line in lines]
txt = "\n".join(lines)
return txt
[docs]def make_horizontal_histogram(values, bins=None, maxbarlength=50, invertx=True):
if bins is None:
bins = np.hstack([-np.inf, np.logspace(-3, -12, 10)[::-1], np.inf])
hist = np.histogram(values, bins)[0]
if invertx:
bins, hist = bins[::-1], hist[::-1]
cumsum = 0
lines = [" {:^13s} {:^4s} {:^51s}".format("Interval", "Sum", "Histogram").rstrip()]
for i, hval in enumerate(hist):
cumsum += hval
barlength = int(maxbarlength * hval / hist.max())
if hval == 0:
bar = ""
else:
barlength = max(barlength, 1)
bar = ((barlength - 1) * "|") + "]" + (" (%d)" % hval)
# log.info(" %5.0e - %5.0e %4d |%s", bins[i+1], bins[i], cumsum, bar)
lines.append(" %5.0e - %5.0e %4d |%s" % (bins[i + 1], bins[i], cumsum, bar))
txt = "\n".join(lines)
return txt
if __name__ == "__main__":
vals = sorted(np.random.rand(30))
print(make_vertical_histogram(vals))
print("")
bins = np.linspace(0, 1, 12)
# for line in horizontal_histogram(vals, bins):
labels = " " + "".join("{:{w}}".format("E-%d" % d, w=6) for d in range(3, 13))
print(make_histogram(vals, bins, labels=labels))