Source code for crikit.ui.classes_ui

"""
User Interface and Visualization Classes (crikit.ui.classes_ui)
===============================================================

BW : Grayscale images

SingleColor : Single-color images

_ColorMath : Container of math operations

"""

import numpy as _np
import copy as _copy
import matplotlib as _mpl

[docs]class BW: """ """ def __init__(self, **kwargs): self._default_attributes = { 'title':None, 'setflag':0, 'setmax':None, 'setmin':None, 'compress_low':None, 'compress_high':None, 'setgain':1, 'xunits':'Pixels', 'yunits':'Pixels' } self._default_attributes.update(kwargs) self._grayscaleimage = None self.title = self._default_attributes['title'] self.setflag = self._default_attributes['setflag'] self.setmax = self._default_attributes['setmax'] self.setmin = self._default_attributes['setmin'] self.compress_high = self._default_attributes['compress_high'] self.compress_low = self._default_attributes['compress_low'] self.setgain = self._default_attributes['setgain'] self.xunits = self._default_attributes['xunits'] self.yunits = self._default_attributes['yunits'] self._x = None self._y = None @property def image(self): """ For image from property settings (limits, compression, etc) """ img = self.grayscaleimage if (self.setmax is None or self.setmin is None): return img*self.setgain else: mask_pass = (img >= self.setmin)*(img <= self.setmax) mask_low = (img < self.setmin) mask_high = (img > self.setmax) img = (mask_pass*img + self.compress_low*mask_low*self.setmin + self.compress_high*mask_high*self.setmax) return img*self.setgain @property def winextent(self): return (self.x.min(), self.x.max(), self.y.min(), self.y.max()) @property def maxer(self): return self.grayscaleimage.max() @property def minner(self): return self.grayscaleimage.min() @property def std(self): try: temp = self.grayscaleimage.std() return temp except: return None @property def mean(self): try: temp = self.grayscaleimage.mean() return temp except: return None @property def ylen(self): return self._grayscaleimage.shape[0] @property def xlen(self): return self._grayscaleimage.shape[1] @property def grayscaleimage(self): return self._grayscaleimage @grayscaleimage.setter def grayscaleimage(self, value): try: if value.ndim == 2: self._grayscaleimage = value if (_np.equal(self._x,None).any() or _np.equal(self._y,None).any() or self._x.size != value.shape[1] or self._y.size != value.shape[0]): self._x = _np.linspace(1, value.shape[1], value.shape[1]) self._y = _np.linspace(1, value.shape[0], value.shape[0]) else: pass except: print('Set grayscaleimage error') @grayscaleimage.deleter def grayscaleimage(self): self.__init__() @property def x(self): if self._x is not None: return self._x else: self._x = _np.arange(self.xlen) self.xunits = self._default_attributes['xunits'] return self._x @x.deleter def x(self): self._x = _np.linspace(1, self.xlen, self.xlen) self.xunits = self.XUNITS @property def y(self): if self._y is not None: return self._y else: self._y = _np.arange(self.ylen) self.yunits = self._default_attributes['yunits'] return self._y @y.deleter def y(self): self._y = _np.linspace(1, self.ylen, self.ylen) self.yunits = self.YUNITS
[docs] def set_x(self, value, units = None): if value is None: pass else: if self.xlen == value.size: self._x = value if units is not None: self.xunits = units else: pass
[docs] def set_y(self, value, units = None): if value is None: pass else: if self.ylen == value.size: self._y = value if units is not None: self.yunits = units else: pass
[docs]class _ColorMath: opfreq1 = None opfreq2 = None opfreq3 = None operation = None condfreq1 = None condfreq2 = None condfreq3 = None condoperation = None inequality = None inequalityval = None def __init__(self): pass
[docs]class CompositeColor(BW): """ """ def __init__(self, sgl_color_list = None): BW.__init__(self) self.bgcolor = [0,0,0] self.mode = 0 # 0: emission; 1: absorption if sgl_color_list is None: self.sgl_color_list = [] else: self.sgl_color_list = sgl_color_list @property def mode_txt(self): if self.mode == 0: return 'Emission' else: return 'Absorption' @property def image(self): #print(self.sgl_color_list) if len(self.sgl_color_list) == 0: return _np.zeros(self.grayscaleimage.shape) else: if self.mode == 0: # Emission img_emission = _np.zeros(self.sgl_color_list[0].image.shape) list_imgs = _copy.deepcopy(self.sgl_color_list) for img in list_imgs: img.bgcolor = [0,0,0] img_emission += img.image img_emission[img_emission>1] = 1 return img_emission elif self.mode == 1: # Absorption img_absorption = _np.zeros(self.sgl_color_list[0].image.shape) img_frac_coverage = _np.zeros(self.sgl_color_list[0].grayscaleimage.shape) img_num_covered = _np.zeros(self.sgl_color_list[0].grayscaleimage.shape) list_imgs = _copy.deepcopy(self.sgl_color_list) for img in list_imgs: if (img.grayscaleimage.nonzero()[0].size == 0) | (img.setgain == 0.0): pass else: img.bgcolor = [0,0,0] temp = 1*img.imageGS temp -= temp.min() if temp.max() != 0: temp /= temp.max() img_absorption += temp[:,:,None]*img.colormap img_frac_coverage += temp img_num_covered += (temp > 0) img_frac_coverage[img_frac_coverage>1] = 1 img_absorb_bg = (1-img_frac_coverage)[:,:,None]*[1,1,1] img_absorb_bg[img_absorb_bg<0] = 0 img_absorption /= (img_num_covered+1e-10)[:,:,None] img_absorption += img_absorb_bg return img_absorption elif self.mode == 2: # Absorption version 2 img_emission = _np.zeros(self.sgl_color_list[0].image.shape) list_imgs = _copy.deepcopy(self.sgl_color_list) # Start with emission image BUT white background # This addition will BRIGHTEN as well # thus needs contrast enhancement later num = 0 for img in list_imgs: img.bgcolor = [1,1,1] temp = img.image if (temp.max() != temp.min()) & (img.setgain != 0.0): img_emission += temp num += 1 # Average if num != 0: img_emission /= num # This enhances contrast # Yes, the first step cancels out the step above # but this keep the norm. and contrast steps separate img_emission *= num img_emission -= (num-1) img_emission[img_emission<0] = 0 img_emission[img_emission>1] = 1 return img_emission @property def ylen(self): return self.sgl_color_list[0].image.shape[0] # return self.grayscaleimage.shape[0] @property def xlen(self): return self.sgl_color_list[0].image.shape[1]
# return self.grayscaleimage.shape[1]
[docs]class SingleColor(BW, _ColorMath): """ """ def __init__(self): BW.__init__(self) self.bgcolor = [0,0,0] self.colormap = [1,0,0] def __add__(self, other): return self.image + other.image @property def image(self): if (self.setmax is None or self.setmin is None): scaled_gs = SingleColor._imgnorm(self.grayscaleimage) scaled_gain_gs = scaled_gs*self.setgain final_scaled_gs = SingleColor._imgnormcompress(scaled_gain_gs) return SingleColor._bwtocolor(final_scaled_gs, self.colormap, self.bgcolor) else: fudge_factor = .001 fudge_amt = _np.abs((self.setmax - self.setmin)*fudge_factor) fudged_min = self.setmin - fudge_amt fudged_max = self.setmax + fudge_amt # if self.compress == True: mask_pass = (self.grayscaleimage >= fudged_min) * \ (self.grayscaleimage <= fudged_max) mask_low = (self.grayscaleimage < fudged_min) mask_high = (self.grayscaleimage > fudged_max) masked_img = mask_pass*self.grayscaleimage + \ self.compress_low*mask_low*fudged_min + \ self.compress_high*mask_high*fudged_max scaled_gs = SingleColor._imgnorm(masked_img) scaled_gain_gs = scaled_gs*self.setgain final_scaled_gs = SingleColor._imgnormcompress(scaled_gain_gs) return SingleColor._bwtocolor(final_scaled_gs, self.colormap, self.bgcolor) # else: # mask = (self.grayscaleimage >= fudged_min) * \ # (self.grayscaleimage <= fudged_max) # masked_img = self.grayscaleimage*mask # scaled_gs = SingleColor._imgnorm(masked_img) # scaled_gain_gs = scaled_gs*self.setgain # final_scaled_gs = SingleColor._imgnormcompress(scaled_gain_gs) # return SingleColor._bwtocolor(final_scaled_gs, self.colormap) @property def imageGS(self): """ Returns self.grayscaleimage with limits applied """ if (self.setmax is None or self.setmin is None): return self.grayscaleimage else: # if self.compress == True: mask_pass = (self.grayscaleimage >= self.setmin)*(self.grayscaleimage <= self.setmax) mask_low = (self.grayscaleimage < self.setmin) mask_high = (self.grayscaleimage > self.setmax) masked_img = (mask_pass*self.grayscaleimage + self.compress_low*mask_low*self.setmin + self.compress_high*mask_high*self.setmax) return masked_img # else: # mask = (self.grayscaleimage >= self.setmin)*(self.grayscaleimage <= self.setmax) # masked_img = self.grayscaleimage*mask # return masked_img
[docs] @staticmethod def _imgnorm(img, low = None, high = None): """ Normalize intensity (B&W) image. Values at low -> 0 high -> 1 """ # If now provided low or high values, set to min() and max() if low is None: low = img.min() if high is None: high = img.max() # Ensure high and low values are different if high == low: return 0*img # Return 0's, if same else: return (img - low)/(high - low)
[docs] @staticmethod def _imgnormcompress(img): """ Compress normalized image. Values: > 1 -> 1 < 0 -> 0 """ mask_pass = (img <= 1)*(img >= 0) mask_high = (img > 1) return mask_pass*img + mask_high
[docs] @staticmethod def _bwtocolor(gs, colormap, bgcolor=[0,0,0]): """ Convert normalized [0,1] B&W image (gs) to color, applying a 3-value list colormap (colormap) """ # img = _np.ones((gs.shape[0], gs.shape[1], 3)) # gs_3d = _np.dot(gs[:,:,None],_np.ones((1,3))) # return (img*colormap)*gs_3d return (1-gs[:,:,None])*bgcolor + gs[:,:,None]*colormap