#!@PYTHON@
"""
:py:class:`ColorTable` collection of methods to generate color bars
===================================================================
Usage ::
import graphqt.ColorTable as ct
ctab = ct.color_table_monochr256()
ctab = ct.color_table_rainbow(ncolors=1000, hang1=250, hang2=-20)
ctab = ct.color_table_interpolated()
ctab = ct.color_table_interpolated(points=[0, 100, 200, 400, 500, 650, 700], colors=[0xffffff, 0xffff00, 0x00ff00, 0xff0000, 0xff00ff, 0x0000ff, 0])
See:
- :class:`IVMain`
- :class:`IVMainTabs`
- :class:`IVMainButtons`
- :class:`IVImageCursorInfo`
- :class:`IVConfigParameters`
- :class:`IVTabDataControl`
- :class:`IVTabFileName`
- `graphqt documentation <https://lcls-psana.github.io/graphqt/py-modindex.html>`_.
Created on Dec 6, 2015 by Mikhail Dubrovin
"""
#------------------------------
from PyQt4 import QtGui #, QtCore
from PyQt4.QtCore import Qt
import numpy as np
from math import floor
#------------------------------
[docs]class Storage :
"""Store for shared parameters."""
def __init__(self) :
self.ictab = 0
def color_table_index(self) :
return self.ictab
#------------------------------
STOR = Storage()
#------------------------------
def print_colors(arr) :
sh = arr.shape
for row in arr :
for v in row :
qc = QtGui.QColor(v & 0xFFFFFF) # rgb part only
#print v, qc.red(), qc.green(), qc.blue()
print '%4d' % qc.red(),
print ''
[docs]def apply_color_table(arr, ctable=None, amin=None, amax=None) :
''' Returns numpy array with colors in stead of intensities
'''
# color_table_monochr256()
# color_table_linear(ncolors=100)
ctab = ctable if ctable is not None else color_table_rainbow(ncolors=1000, hang1=0, hang2=360)
# color_table_monochr256() # color_table_def()
min = np.amin(arr) if amin is None else amin
max = np.amax(arr) if amax is None else amax
if min==max : max+=1
f = float(ctab.size-1)/(max-min)
ict = np.require(f*(arr-min), dtype=np.int) # array of indexes in color table
imax = len(ctab) - 1
cond = np.logical_and(ict>0, ict<len(ctab))
ict = np.select((cond, ict>imax), (ict, imax), default=0)
return ctab[ict]
#print 'XXX:indexes:\n', ict
#a = ctab[ict]
#print 'XXX:arr of colors:\n', a
#print_colors(a)
#return a
[docs]def color_table_monochr256(inverted=False) :
''' Returns numpy array with monochrome table of 256 colors
'''
ncolors=256
inds = range(ncolors-1,-1,-1) if inverted else range(ncolors)
return np.array([c + c*0x100 + c*0x10000 + 0xff000000 for c in inds], dtype=np.uint32)
[docs]def color_table_linear(ncolors=100) :
''' Returns numpy array with ncolors constructed from entire range of RGB colors
'''
f = 1./ncolors
return np.array([0xffffff*c*f + 0xff000000 for c in range(ncolors)], dtype=np.uint32)
[docs]def interpolate_colors(ctab, p1, p2, c1, c2) :
'''Fills color table ctab between index/points p1 and p2 for interpolated colors from c1 to c2
'''
#print p1, p2, c1, c2
A = 0xff000000
R = 0x00ff0000
G = 0x0000ff00
B = 0x000000ff
r1, r2 = (c1&R)>>16, (c2&R)>>16
g1, g2 = (c1&G)>>8, (c2&G)>>8
b1, b2 = c1&B, c2&B
np = p2-p1
#print 'XXX: c1, c2, p1, p2, r1, r2, g1, g2, b1, b2:', hex(c1), hex(c2), p1, p2, r1, r2, g1, g2, b1, b2
if np<1 :
ctab[p1] = c1 + A
return
fr = float(r2-r1) / np
fg = float(g2-g1) / np
fb = float(b2-b1) / np
for p in range(p1,p2) :
dp = p-p1
r = r1 + int(floor(fr*dp))
g = g1 + int(floor(fg*dp))
b = b1 + int(floor(fb*dp))
ctab[p] = A + b + g*0x100 + r*0x10000
#print 'hex(r), hex(r<<16)', hex(r), hex(r<<16)
#print 'hex(b), hex(b<<8)', hex(b), hex(b<<8)
#ctab[p] = A + (b + g<<8 + r<<16) & 0xffffff
#color = ctab[p]
#qc = QtGui.QColor(color & 0xFFFFFF) # rgb part only
#print 'XXX: point:%4d %10s %4d %4d %4d' % (p, hex(color), qc.red(), qc.green(), qc.blue())
#def color_table_interpolated(points=[0, 200, 400, 600, 800],\
# colors=[0, 0x0000ff, 0x00ff00, 0xff0000, 0xffffff]) :
#def color_table_interpolated(points=[0, 200, 400, 600, 800],\
# colors=[0, 0x0000ff, 0xff0000, 0x00ff00, 0xffffff]) :
[docs]def color_table_interpolated(points=[0, 50, 200, 300, 500, 600, 700],\
colors=[0, 0x0000ff, 0xff00ff, 0xff0000, 0x00ff00, 0xffff00, 0xffffff]) :
''' Returns numpy array of colors linearly-interpolated between points with defined colors
'''
#print 'XXX: number of colors: %d' % points[-1]
ctab = np.zeros(points[-1], dtype=np.uint32)
for i,p in enumerate(points[:-1]) :
p1, p2 = p, points[i+1]
c1, c2 = colors[i], colors[i+1]
interpolate_colors(ctab, p1, p2, c1, c2)
return ctab
#return color_table_monochr256()
def color_table_rainbow(ncolors=1000, hang1=250, hang2=-20) :
ct = ColorTable(ncolors, hang1, hang2)
return ct.np_ctable()
#------------------------------
[docs]def next_color_table(ict=None) :
"""Returns color table selected in loop or requested by index ict : int among pre-defined
"""
if ict is None : STOR.ictab += 1
else : STOR.ictab = ict
#print 'Color table # %d' % STOR.ictab
if STOR.ictab == 2 : return color_table_rainbow(ncolors=1000, hang1=-20, hang2=250)
elif STOR.ictab == 3 : return color_table_monochr256()
elif STOR.ictab == 4 : return color_table_monochr256(inverted=True)
elif STOR.ictab == 5 : return color_table_rainbow(ncolors=1000, hang1=-120, hang2=100)
elif STOR.ictab == 6 : return color_table_rainbow(ncolors=1000, hang1=100, hang2=-120)
elif STOR.ictab == 7 : return color_table_interpolated()
elif STOR.ictab == 8 : return color_table_interpolated(points=[0, 100, 200, 400, 500, 650, 700],\
colors=[0xffffff, 0xffff00, 0x00ff00, 0xff0000, 0xff00ff, 0x0000ff, 0])
else :
STOR.ictab = 1
return color_table_rainbow()
#return color_table_monochr256()
#return color_table_interpolated()
#------------------------------
def get_pixmap(ind, orient='H', size=(200,30)) :
ctab = next_color_table(ict=ind)
arr = array_for_color_bar(ctab, orient=orient)#, width = 10)
(h,w) = arr.shape
image = QtGui.QImage(arr, w, h, QtGui.QImage.Format_ARGB32)
pixmap= QtGui.QPixmap.fromImage(image.scaled(size[0], size[1], Qt.IgnoreAspectRatio, Qt.FastTransformation))
return pixmap
#------------------------------
[docs]def array_for_color_bar(ctab=color_table_monochr256(), orient='V', width=2) :
"""Returns 2-d array made of repeated 1-d array ctab to display as a color bar
"""
arr = [(c,c) for c in ctab[::-1]] if orient=='V' else\
[ctab for r in range(width)]
npa = np.array(arr, dtype=np.uint32) #.T
#print 'XXX array for color bar:\n', npa
#print 'XXX shape: ', npa.shape
return npa
#------------------------------
#------------------------------
#------------------------------
[docs]class ColorTable():
'''Creates and provide access to color table
'''
[docs] def __init__(self, ncolors=1000, hang1=0, hang2=360, vmin=-10000, vmax=10000):
'''Makes color table - list of QColors of length ncolors
'''
self.make_ctable_for_hue_range(ncolors, hang1, hang2)
self.set_value_range(vmin, vmax)
[docs] def make_ctable_for_hue_range(self, ncolors=1000, hang1=0, hang2=360) :
'''Makes color table in the range of hue values
'''
self.ncolors = ncolors
self.hang1 = float(hang1)
self.hang2 = float(hang2)
dhang = (self.hang2 - self.hang1)/ncolors
self.ctable = []
for ic in range(ncolors) :
hang = self.hang1 + dhang * ic
hnorm = float(hang % 360)/360.
#print 'hang:%7.2f rest(hang,360)=%7.2f' % (hang, hang % 360)
qc = QtGui.QColor()
qc.setHsvF(hnorm, 1., 1., alpha=1.)
self.ctable.append(qc)
[docs] def int_ctable(self) :
'''converts list of QColor to list of integer rgba values
'''
return [c.rgba() for c in self.ctable]
def np_ctable(self) :
return np.array(self.int_ctable(), dtype=np.uint32)
[docs] def set_ncolors(self, ncolors) :
'''Sets the number of color in table and re-generate color table
'''
self.make_ctable_for_hue_range(ncolors, self.hang1, self.hang2)
self.set_value_range(self.vmin, self.vmax)
[docs] def set_hue_range(self, hang1, hang2) :
'''Sets the range of hue angles and re-generate color table
'''
self.make_ctable_for_hue_range(self.ncolors, hang1, hang2)
self.set_value_range(self.vmin, self.vmax)
[docs] def set_value_range(self, vmin, vmax) :
'''Sets the range of values which will be mapped to color table
'''
self.vmin = float(vmin)
self.vmax = float(vmax)
self.vfct = self.ncolors/(self.vmax - self.vmin)
[docs] def color_for_value(self, v) :
'''Returns color mapped to the value in the color table
'''
if v < self.vmin : return self.ctable[0]
elif v < self.vmax : return self.ctable[self.vfct*v]
else : return self.ctable[-1]
def print_color_table(self):
for ic, qc in enumerate(self.ctable) :
print 'i:%4d R:%3d G:%3d B:%3d' % (ic, qc.red(), qc.green(), qc.blue())
#------------------------------
def test():
ct = ColorTable()
ct.print_color_table()
#------------------------------
if __name__ == '__main__':
test()
#------------------------------