# AUTOGENERATED FILE! PLEASE DON'T EDIT HERE. EDIT THE SOURCE NOTEBOOKS INSTEAD
"""
This module is for color formats, units and whatnot. This is exposed
automatically with::
from k1lib.imports import *
fmt.txt # exposed
"""
import k1lib, math, re; from k1lib import cli
from typing import Dict, Iterator, Tuple
pygments = k1lib.dep.pygments
__all__ = ["generic", "metricPrefixes", "size", "fromSize", "dollar", "sizeOf",
"comp", "compRate", "time", "item", "throughput", "txt",
"js", "py", "html", "sql", "cpp", "java", "php", "ruby",
"h", "pre", "row", "col", "colors", "rmAnsi"]
k1lib.settings.add("fmt", k1lib.Settings().add("separator", True, "whether to have a space between the number and the unit"), "from k1lib.fmt module");
settings = k1lib.settings.fmt
metricPrefixes = {-8:"y",-7:"z",-6:"a",-5:"f",-4:"p",-3:"n",-2:"u",-1:"m",0:"",1:"k",2:"M",3:"G",4:"T",5:"P",6:"E",7:"Z",8:"Y"}
#metricPrefixes = ["", "k", "M", "G", "T", "P", "E", "Z", "Y"]
[docs]def generic(x, units:Dict[int, str]): # generic
c = " " if settings.separator else "" # generic
for i, unit in units.items(): # generic
upperBound = 1000 * 1000**i # generic
if abs(x) < upperBound: # generic
return f"{round(1e3*x/upperBound, 2)}{c}{unit}" # generic
return (f"{round(1e3*x/upperBound, 2)}{c}{unit}").strip() # generic
def _jsF_generic(units): # _jsF_generic
def inner(meta): # _jsF_generic
fIdx = cli.init._jsFAuto(); dataIdx = cli.init._jsDAuto(); unitsIdx = cli.init._jsDAuto() # _jsF_generic
return f"""
{unitsIdx} = {[list(x) for x in units.items()]};
{fIdx} = ({dataIdx}) => {{
for (const e of {unitsIdx}) {{
const upperBound = 1000 * 1000**e[0];
if (Math.abs({dataIdx}) < upperBound) return `${{Math.round(1e3*{dataIdx}/upperBound*100)/100}}{' ' if settings.separator else ''}${{e[1]}}`;
}}
}}""", fIdx # _jsF_generic
return inner # _jsF_generic
sizes = {i: f"{p}B" for i, p in metricPrefixes.items() if i >= 0}; #sizes[0] = "bytes" # _jsF_generic
[docs]def size(_bytes=0): # size
"""Formats disk size.
Example::
# returns "50.0 bytes"
fmt.size(50)
# returns "12.0 MB"
fmt.size(1.2e7)
""" # size
return generic(_bytes, sizes) # size
k1lib.settings.cli.kjs.jsF[size] = _jsF_generic(sizes) # size
sizeInv = {"k": 1e3, "m": 1e6, "g": 1e9, "t": 1e12, "p": 1e15, "e": 1e18, "z": 1e21, "y": 1e24} # size
[docs]def fromSize(s:str) -> int: # this is ugly I know, doesn't fit well into others. But making a generalized version seems hard, and I just need this right now # fromSize
"""Grabs size from string representation.
Example::
fromSize("31.5k") # returns 31500
fromSize("31.5kB") # also returns 31500
""" # fromSize
s = s.lower().replace(" ", "").rstrip("b"); ch = s[-1] # fromSize
if ch in sizeInv: return int(float(s[:-1])*sizeInv[ch]) # fromSize
return int(s) # fromSize
dollars = {i: f"{p}$" for i, p in metricPrefixes.items() if i >= 0}; #sizes[0] = "bytes" # fromSize
[docs]def dollar(_dollar=0): # dollar
"""Formats dollar.
Example::
# returns '50.0 $'
fmt.dollar(50)
# returns '12.0 M$'
fmt.dollar(1.2e7)
I know this format looks kinda terrible, instead of "million" or "billion"
written out loud, but that's long, so let's still do the short metric prefix""" # dollar
return generic(_dollar, dollars) # dollar
k1lib.settings.cli.kjs.jsF[dollar] = _jsF_generic(dollars) # dollar
[docs]def sizeOf(l:Iterator[float]) -> Tuple[str, Iterator[float]]: # sizeOf
"""Figures out appropriate scale, scales back the Iterator, and return both.
Example::
x = torch.abs(torch.randn(2)) * 1e4 + 1e5
label, t = fmt.sizeOf(x) # label is "kB"
(t | toTensor()).min() # min value should be close to 100""" # sizeOf
l = list(l | cli.apply(lambda n: abs(n))) # sizeOf
v = l | cli.toMax() # sizeOf
v = math.log10(v) if v > 0 else -math.log10(-v) # sizeOf
idx = math.floor(v/3) # sizeOf
coef = 1.0/1000**idx # sizeOf
return sizes[idx], l | cli.apply(lambda x: x * coef) | cli.deref() # sizeOf
computations = {i: f"{p}FLOPs" for i, p in metricPrefixes.items() if i >= 0} # sizeOf
[docs]def comp(flop=0): # comp
"""Formats computation amount.
Example::
# returns "50.0 FLOPs"
fmt.computation(50)
# returns "50.0 MFLOPs"
fmt.computation(5e7)
""" # comp
return generic(flop, computations) # comp
k1lib.settings.cli.kjs.jsF[comp] = _jsF_generic(computations) # comp
computationRates = {i: f"{p}FLOPS" for i, p in metricPrefixes.items() if i >= 0} # comp
[docs]def compRate(flops=0): # compRate
"""Formats computation rate.
Example::
# returns "50.0 FLOPS"
fmt.computationRate(50)
# returns "50.0 MFLOPS"
fmt.computationRate(5e7)
""" # compRate
return generic(flops, computationRates) # compRate
k1lib.settings.cli.kjs.jsF[compRate] = _jsF_generic(computationRates) # compRate
times = {i:f"{p}s" for i, p in metricPrefixes.items() if i <= 0} # compRate
[docs]def time(seconds=0): # time
"""Formats small times.
Example::
fmt.time(50) # returns "50.0 s"
fmt.time(4000) # returns "4000.0 s"
fmt.time(0.02) # returns "20.0 ms"
fmt.time(1e-5) # returns "10.0 us"
""" # time
return generic(seconds, times) # time
k1lib.settings.cli.kjs.jsF[time] = _jsF_generic(times) # time
items = {0: "", 1: "k", 2: "M", 3: "B", 4: "T"} # time
[docs]def item(n=0): # item
"""Formats generic item.
Example::
# returns "50.0"
fmt.item(50)
# returns "500.0 k"
fmt.item(5e5)
""" # item
return generic(n, items) # item
k1lib.settings.cli.kjs.jsF[item] = _jsF_generic(items) # item
[docs]def throughput(n, unit=""): # throughput
"""Formats item throughput.
Example::
# returns "3.16/year"
fmt.throughput(1e-7)
# returns "2.63/month"
fmt.throughput(1e-6)
# returns "3.6/hour"
fmt.throughput(1e-3)
# returns "100.0 k/s"
throughput(1e5)
# returns "100.0 k epochs/s"
throughput(1e5, " epochs")
:param n: items per second
:param unit: optional item unit""" # throughput
if n < 10/(365.25*86400): return item(n*(365.25*86400)) + f"{unit}/year" # throughput
if n < 10/(30.4375*86400): return item(n*(30.4375*86400)) + f"{unit}/month" # throughput
if n < 10/86400: return item(n*86400) + f"{unit}/day" # throughput
if n < 10/3600: return item(n*3600) + f"{unit}/hour" # throughput
if n < 10/60: return item(n*60) + f"{unit}/minute" # throughput
return item(n) + f"{unit}/s" # throughput
_esc = '\033[' # throughput
_end = f'{_esc}0m' # throughput
[docs]class txt: # txt
"""Text formatting.
Example::
# will print out red text
print(fmt.txt.red("some text"))""" # txt
[docs] @staticmethod # txt
def darkcyan(s:str): return f"{_esc}36m{s}{_end}" # txt
[docs] @staticmethod # txt
def red(s:str): return f"{_esc}91m{s}{_end}" # txt
[docs] @staticmethod # txt
def green(s:str): return f"{_esc}92m{s}{_end}" # txt
[docs] @staticmethod # txt
def yellow(s:str): return f"{_esc}93m{s}{_end}" # txt
[docs] @staticmethod # txt
def blue(s:str): return f"{_esc}94m{s}{_end}" # txt
[docs] @staticmethod # txt
def purple(s:str): return f"{_esc}95m{s}{_end}" # txt
[docs] @staticmethod # txt
def cyan(s:str): return f"{_esc}96m{s}{_end}" # txt
[docs] @staticmethod # txt
def bold(s:str): return f"{_esc}1m{s}{_end}" # txt
[docs] @staticmethod # txt
def grey(s:str): return f"{_esc}38;2;150;150;150m{s}{_end}" # txt
[docs] @staticmethod # txt
def darkgrey(s:str): return f"{_esc}38;2;100;100;100m{s}{_end}" # txt
[docs] @staticmethod # txt
def underline(s:str): return f"{_esc}4m{s}{_end}" # txt
[docs] @staticmethod # txt
def identity(s:str): return f"{s}" # txt
def pygmentsCss(): return "<style>" + pygments.formatters.HtmlFormatter().get_style_defs(".highlight") + "</style>" # pygmentsCss
[docs]def js(s:str) -> str: # js
"""Makes javascript code pretty, returns html""" # js
return k1lib.viz.Html(pygmentsCss() + pygments.highlight(s, pygments.lexers.JavascriptLexer(), pygments.formatters.HtmlFormatter())) # js
[docs]def py(s:str) -> str: # py
"""Makes python code pretty, returns html""" # py
return k1lib.viz.Html(pygmentsCss() + pygments.highlight(s, pygments.lexers.PythonLexer(), pygments.formatters.HtmlFormatter())) # py
[docs]def html(s:str) -> str: # html
"""Makes html code pretty, returns html""" # html
return k1lib.viz.Html(pygmentsCss() + pygments.highlight(s, pygments.lexers.HtmlLexer(), pygments.formatters.HtmlFormatter())) # html
[docs]def sql(s:str) -> str: # sql
"""Makes sql code pretty, returns html""" # sql
return k1lib.viz.Html(pygmentsCss() + pygments.highlight(s, pygments.lexers.SqlLexer(), pygments.formatters.HtmlFormatter())) # sql
[docs]def cpp(s:str) -> str: # cpp
"""Makes cpp code pretty, returns html""" # cpp
return k1lib.viz.Html(pygmentsCss() + pygments.highlight(s, pygments.lexers.CLexer(), pygments.formatters.HtmlFormatter())) # cpp
[docs]def java(s:str) -> str: # java
"""Makes java code pretty, returns html""" # java
return k1lib.viz.Html(pygmentsCss() + pygments.highlight(s, pygments.lexers.JavaLexer(), pygments.formatters.HtmlFormatter())) # java
[docs]def php(s:str) -> str: # php
"""Makes php code pretty, returns html""" # php
return k1lib.viz.Html(pygmentsCss() + pygments.highlight(s, pygments.lexers.PhpLexer(), pygments.formatters.HtmlFormatter())) # php
[docs]def ruby(s:str) -> str: # ruby
"""Makes ruby code pretty, returns html""" # ruby
return k1lib.viz.Html(pygmentsCss() + pygments.highlight(s, pygments.lexers.RubyLexer(), pygments.formatters.HtmlFormatter())) # ruby
[docs]def h(code:str, level:int=1) -> str: # h
"""Wraps content inside a 'h' html tag.
Example::
fmt.h("abc", 2) # returns "<h2>abc</h2>"
:param level: what's the header level?""" # h
return f"<h{level}>{code}</h{level}>" # h
def _jsF_h(meta, level=3): # _jsF_h
fIdx = cli.init._jsFAuto(); dataIdx = cli.init._jsDAuto() # _jsF_h
return f"{fIdx} = ({dataIdx}) => `<h{level}>${{{dataIdx}}}</h{level}>`", fIdx # _jsF_h
k1lib.settings.cli.kjs.jsF[h] = _jsF_h # _jsF_h
[docs]def pre(code:str, extras:str="") -> str: # pre
"""Wraps content inside a 'pre' html tag.
Example::
fmt.pre("abc")
""" # pre
return f"<pre style='font-family: monospace' {extras} >{code}</pre>" # pre
def _jsF_pre(meta): # _jsF_pre
fIdx = cli.init._jsFAuto(); dataIdx = cli.init._jsDAuto() # _jsF_pre
return f"{fIdx} = ({dataIdx}) => `<pre style='font-family: monospace'>${{{dataIdx}}}</pre>`", fIdx # _jsF_pre
k1lib.settings.cli.kjs.jsF[pre] = _jsF_pre # _jsF_pre
[docs]def col(args, margin=10): # col
"""Creates a html col of all the elements.
Example::
fmt.col(["abc", "def"]) | aS(IPython.display.HTML)
""" # col
return args | cli.apply(lambda x: f"<div style='margin: {margin}px'>{x}</div>") | cli.join("") | cli.aS(lambda x: f"<div style='display: flex; flex-direction: column'>{x}</div>") # col
def _jsF_col(meta, margin=10): # _jsF_col
fIdx = cli.init._jsFAuto(); dataIdx = cli.init._jsDAuto() # _jsF_col
fIdx2 = cli.init._jsFAuto(); dataIdx2 = cli.init._jsDAuto() # _jsF_col
return f"""
{fIdx2} = ({dataIdx2}) => `<div style='margin: {margin}px'>${{{dataIdx2}}}</div>`
{fIdx} = ({dataIdx}) => `<div style='display: flex; flex-direction: column'>${{{dataIdx}.map({fIdx2}).join('')}}</div>`
""", fIdx # _jsF_col
k1lib.settings.cli.kjs.jsF[col] = _jsF_col # _jsF_col
[docs]def row(args, margin=10): # row
"""Creates a html row of all the elements.
Example::
fmt.row(["abc", "def"]) | aS(IPython.display.HTML)
""" # row
return args | cli.apply(lambda x: f"<div style='margin: {margin}px'>{x}</div>") | cli.join("") | cli.aS(lambda x: f"<div style='display: flex; flex-direction: row'>{x}</div>") # row
def _jsF_row(meta, margin=10): # _jsF_row
fIdx = cli.init._jsFAuto(); dataIdx = cli.init._jsDAuto() # _jsF_row
fIdx2 = cli.init._jsFAuto(); dataIdx2 = cli.init._jsDAuto() # _jsF_row
return f"""
{fIdx2} = ({dataIdx2}) => `<div style='margin: {margin}px'>${{{dataIdx2}}}</div>`
{fIdx} = ({dataIdx}) => `<div style='display: flex; flex-direction: row'>${{{dataIdx}.map({fIdx2}).join('')}}</div>`
""", fIdx # _jsF_row
k1lib.settings.cli.kjs.jsF[row] = _jsF_row # _jsF_row
settings.add("colors", ["#8dd3c7", "#ffffb3", "#bebada", "#fb8072", "#80b1d3", "#fdb462", "#b3de69", "#fccde5", "#d9d9d9", "#bc80bd", "#ccebc5", "#ffed6f"], "List of colors to cycle through in fmt.colors()") # _jsF_row
[docs]def colors(): # colors
"""Returns an infinite iterator that cycles through 12 colors.
Example::
fmt.colors() | head(3) | deref()
Color scheme taken from https://colorbrewer2.org/#type=qualitative&scheme=Set3&n=12""" # colors
return settings.colors | cli.repeatFrom() # colors
ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])') # colors
[docs]def rmAnsi(text): # rmAnsi
"""Removes ansi escape characters, courtesy of https://stackoverflow.com/questions/14693701/how-can-i-remove-the-ansi-escape-sequences-from-a-string-in-python.""" # rmAnsi
return ansi_escape.sub('', text) # rmAnsi