Some days you just need...
If you have Python3 installed...
- pip3 install --user scipy numpy sty
- copy and save the code below to a file named ./colors
- chmod +x ./colors
- optionally move colors to a directory on your $PATH, or add its containing directory to $PATH
- when you need to clear your mind, run colors.
This is designed to work in the terminal, even if you haven't started an X server. It uses only the core subset of ANSI color codes and only those characters that are mapped in (almost) all terminals. Sampling is biased toward a tertiary color pallet.
#!/usr/bin/env python3 import os,sys from pylab import * from numpy import * from sty import * columns, rows = os.get_terminal_size(0) ''' Approximate RGB values of linux terminal color codes. The first 8 colors are background colors and are slightly darker. The next 8 colors are foreground colors and are slightly brighter. ''' rgb = array([[0,0,0],[1,0,0],[0,1,0],[1,1,0],[0,0,1],[1,0,1],[0,1,1],[1,1,1]]) rgb = concatenate([rgb*0.9,rgb*0.8+0.2]) ''' There are 8 background and 16 foreground colors supported on the linux terminal. Construct all possible combinations with shading characters ░ and ▒. There are more foreground than background colors, so draw pure colors with █ (drawing with a blank space could only use the 8 background colors). ''' colors = {tuple(rgb[j]):bg(0)+fg(j)+'█' for j in range(16)} for i in range(8): for j in range(16): if i!=j: colors[tuple((rgb[i] +rgb[j])/2)] = bg(i)+fg(j)+'▒' colors[tuple((rgb[i]*2+rgb[j])/3)] = bg(i)+fg(j)+'░' ''' Use one-dimensional drift-diffusion to sample a color waterfall. - Define color similarity using a radial-basis kernel. - Adjust transition probabilities so the stationary distribution of the Markov chain is uniform. - Defie a prior to concetrate colors away from grays and extreme values. ''' cc = array([*colors.keys()]) D = sum((cc[None,:,:]-cc[:,None,:])**2,axis=2) P = exp(-D*4) P = P/sum(P,axis=1)[:,None] for i in range(100): P = P/sum(P,axis=0) P = P/sum(P,axis=1)[:,None] P = log(P) prior = -(norm(cc-0.5,axis=1)-0.57)**2*100 NCOLORS = len(cc) i = 0 previous_line = int32(linspace(0,NCOLORS-1,columns)) try: while True: line = '' next_line = [] for c in range(columns): p = exp( P[previous_line[(c-1+columns)%columns]]+ P[previous_line[(c+1)%columns]]+ P[previous_line[c]]+ prior) p = p/sum(p) i = np.random.choice(arange(NCOLORS),p=p) line += colors[tuple(cc[i])] next_line.append(i) previous_line = int32(next_line) print('\n'+line,end='',flush=True) finally: print(rs.all) sys.exit(0)
I like it! (I had to also include a pip3 install of 'matplotlib' before it worked, though)
ReplyDelete