def plot(v, origin=None, ax=None, color='k', marker='.', linestyle='-', **kwargs): """ Plot a vector from origin. Args: :v: | vec3 vector. :origin: | vec3 vector with same size attributes as in :v:. :ax: | None, optional | axes handle. | If None, create new figure with axes ax. :color: | 'k', optional | color specifier. :marker: | '.', optional | marker specifier. :linestyle: | '-', optional | linestyle specifier :**kwargs: | other keyword specifiers for plot. Returns: :ax: | handle to figure axes. """ if ax is None: fig = plt.figure() ax = fig.add_subplot(111, projection='3d') if origin is None: origin = vec3(np.zeros(v.x.shape), np.zeros(v.x.shape), np.zeros(v.x.shape)) ax.plot(np.hstack([origin.x, v.x]), np.hstack([origin.y, v.y]), np.hstack([origin.z, v.z]), color=color, marker=marker, **kwargs) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_zlabel('z') return ax
def plot(self, plt_type='3d', ax=None, title=None, **kwargs): """ Plot color coordinates. Args: :plt_type: | '3d' or 3 or '2d or 2, optional | -'3d' or 3: plot all 3 dimensions (lightness and chromaticity) | -'2d' or 2: plot only chromaticity dimensions. :ax: | None or axes handles, optional | None: create new figure axes, else use :ax: for plotting. :title: | None or str, optional | Give plot a title. :**kwargs: | additional arguments for use with matplotlib.pyplot.scatter Returns: :gca: | handle to current axes. """ L, a, b = self.split_() if ax is None: fig = plt.figure() if (plt_type == '2d') | (plt_type == 2): if ax is None: ax = fig.add_subplot(111) ax.scatter(a, b, **kwargs) else: if ax is None: ax = fig.add_subplot(111, projection='3d') ax.scatter(a, b, L, **kwargs) ax.set_zlabel(_CSPACE_AXES[self.dtype][0]) ax.set_xlabel(_CSPACE_AXES[self.dtype][1]) ax.set_ylabel(_CSPACE_AXES[self.dtype][2]) if title is not None: ax.set_title(title) return plt.gca()
def plot(self, ax=None, title=None, **kwargs): """ Plot tristimulus or cone fundamental values. Args: :ax: | None or axes handles, optional | None: create new figure axes, else use :ax: for plotting. :title: | None or str, optional | Give plot a title. :**kwargs: | additional arguments for use with matplotlib.pyplot.scatter Returns: :gca: | handle to current axes. """ X, Y, Z = self.split_() if ax is None: fig = plt.figure() ax = fig.add_subplot(111, projection='3d') if self.dtype == 'xyz': ax.scatter(X, Z, Y, **kwargs) ax.set_xlabel(_CSPACE_AXES[self.dtype][0]) ax.set_ylabel(_CSPACE_AXES[self.dtype][2]) ax.set_zlabel(_CSPACE_AXES[self.dtype][1]) elif self.dtype == 'lms': ax.scatter(X, Y, Z, **kwargs) ax.set_xlabel(_CSPACE_AXES[self.dtype][0]) ax.set_ylabel(_CSPACE_AXES[self.dtype][1]) ax.set_zlabel(_CSPACE_AXES[self.dtype][2]) if title is not None: ax.set_title(title) return plt.gca()
bar = np.vstack((wl3, np.empty((3, wl3.shape[0])))) _CMF['types'].append(cieobs) _CMF[cieobs] = {'bar': bar} _CMF[cieobs]['K'] = K _CMF[cieobs]['M'] = M #return _CMF if __name__ == '__main__': outcmf = 'lms' out = outcmf + ',trans_lens,trans_macula,sens_photopig,LMSa' LMS, trans_lens, trans_macula, sens_photopig, LMSa = cie2006cmfsEx(out=out) plt.figure() plt.plot(LMS[0], LMS[1], color='r', linestyle='--') plt.plot(LMS[0], LMS[2], color='g', linestyle='--') plt.plot(LMS[0], LMS[3], color='b', linestyle='--') plt.title('cie2006cmfsEx(...)') plt.show() out = outcmf + ',var_age,vAll' LMS_All, var_age, vAll = genMonteCarloObs(n_obs=10, fieldsize=10, list_Age=[32], out=out) plt.figure() plt.plot(LMS_All[0], LMS_All[1], color='r', linestyle='-') plt.plot(LMS_All[0], LMS_All[2], color='g', linestyle='-')
def render_image(img = None, spd = None, rfl = None, out = 'img_hyp', \ refspd = None, D = None, cieobs = _CIEOBS, \ cspace = 'ipt', cspace_tf = {},\ k_neighbours = 4, show = True, verbosity = 0, show_ref_img = True,\ stack_test_ref = 12,\ write_to_file = None): """ Render image under specified light source spd. Args: :img: | None or str or ndarray with uint8 rgb image. | None load a default image. :spd: | ndarray, optional | Light source spectrum for rendering :rfl: | ndarray, optional | Reflectance set for color coordinate to rfl mapping. :out: | 'img_hyp' or str, optional | (other option: 'img_ren': rendered image under :spd:) :refspd: | None, optional | Reference spectrum for color coordinate to rfl mapping. | None defaults to D65 (srgb has a D65 white point) :D: | None, optional | Degree of (von Kries) adaptation from spd to refspd. :cieobs: | _CIEOBS, optional | CMF set for calculation of xyz from spectral data. :cspace: | 'ipt', optional | Color space for color coordinate to rfl mapping. :cspace_tf: | {}, optional | Dict with parameters for xyz_to_cspace and cspace_to_xyz transform. :k_neighbours: | 4 or int, optional | Number of nearest neighbours for reflectance spectrum interpolation. | Neighbours are found using scipy.cKDTree :show: | True, optional | Show images. :verbosity: | 0, optional | If > 0: make a plot of the color coordinates of original and rendered image pixels. :show_ref_img: | True, optional | True: shows rendered image under reference spd. False: shows original image. :write_to_file: | None, optional | None: do nothing, else: write to filename(+path) in :write_to_file: :stack_test_ref: | 12, optional | - 12: left (test), right (ref) format for show and imwrite | - 21: top (test), bottom (ref) | - 1: only show/write test | - 2: only show/write ref | - 0: show both, write test Returns: :returns: | img_hyp, img_ren, | ndarrays with hyperspectral image and rendered images """ # Get image: #imread = lambda x: plt.imread(x) #matplotlib.pyplot if img is not None: if isinstance(img, str): img = plt.imread(img) # use matplotlib.pyplot's imread else: img = plt.imread(_HYPSPCIM_DEFAULT_IMAGE) # Convert to 2D format: rgb = img.reshape(img.shape[0] * img.shape[1], 3) * 1.0 # *1.0: make float rgb[rgb == 0] = _EPS # avoid division by zero for pure blacks. # Get unique rgb values and positions: rgb_u, rgb_indices = np.unique(rgb, return_inverse=True, axis=0) # get Ref spd: if refspd is None: refspd = _CIE_ILLUMINANTS['D65'].copy() # Convert rgb_u to xyz and lab-type values under assumed refspd: xyz_wr = spd_to_xyz(refspd, cieobs=cieobs, relative=True) xyz_ur = colortf(rgb_u, tf='srgb>xyz') # Estimate rfl's for xyz_ur: rfl_est, xyzri = xyz_to_rfl(xyz_ur, rfl = rfl, out = 'rfl_est,xyz_est', \ refspd = refspd, D = D, cieobs = cieobs, \ cspace = cspace, cspace_tf = cspace_tf,\ k_neighbours = k_neighbours, verbosity = verbosity) # Get default test spd if none supplied: if spd is None: spd = _CIE_ILLUMINANTS['F4'] # calculate xyz values under test spd: xyzti, xyztw = spd_to_xyz(spd, rfl=rfl_est, cieobs=cieobs, out=2) # Chromatic adaptation from test spd to refspd: if D is not None: xyzti = cat.apply(xyzti, xyzw1=xyztw, xyzw2=xyz_wr, D=D) # Convert xyzti under test spd to srgb: rgbti = colortf(xyzti, tf='srgb') / 255 # Reconstruct original locations for rendered image rgbs: img_ren = rgbti[rgb_indices] img_ren.shape = img.shape # reshape back to 3D size of original # For output: if show_ref_img == True: rgb_ref = colortf(xyzri, tf='srgb') / 255 img_ref = rgb_ref[rgb_indices] img_ref.shape = img.shape # reshape back to 3D size of original img_str = 'Rendered (under ref. spd)' img = img_ref else: img_str = 'Original' img = img / 255 if (stack_test_ref > 0) | show == True: if stack_test_ref == 21: img_original_rendered = np.vstack( (img_ren, np.ones((4, img.shape[1], 3)), img)) img_original_rendered_str = 'Rendered (under test spd)\n ' + img_str elif stack_test_ref == 12: img_original_rendered = np.hstack( (img_ren, np.ones((img.shape[0], 4, 3)), img)) img_original_rendered_str = 'Rendered (under test spd) | ' + img_str elif stack_test_ref == 1: img_original_rendered = img_ren img_original_rendered_str = 'Rendered (under test spd)' elif stack_test_ref == 2: img_original_rendered = img img_original_rendered_str = img_str elif stack_test_ref == 0: img_original_rendered = img_ren img_original_rendered_str = 'Rendered (under test spd)' if write_to_file is not None: # Convert from RGB to BGR formatand write: #print('Writing rendering results to image file: {}'.format(write_to_file)) with warnings.catch_warnings(): warnings.simplefilter("ignore") imsave(write_to_file, img_original_rendered) if show == True: # show images using pyplot.show(): plt.figure() plt.imshow(img_original_rendered) plt.title(img_original_rendered_str) plt.gca().get_xaxis().set_ticklabels([]) plt.gca().get_yaxis().set_ticklabels([]) if stack_test_ref == 0: plt.figure() plt.imshow(img_str) plt.title(img_str) plt.axis('off') if 'img_hyp' in out.split(','): # Create hyper_spectral image: rfl_image_2D = rfl_est[ rgb_indices + 1, :] # create array with all rfls required for each pixel img_hyp = rfl_image_2D.reshape(img.shape[0], img.shape[1], rfl_image_2D.shape[1]) # Setup output: if out == 'img_hyp': return img_hyp elif out == 'img_ren': return img_ren else: return eval(out)
def plot_cri_graphics(data, cri_type = None, hbins = 16, start_hue = 0.0, scalef = 100, \ plot_axis_labels = False, bin_labels = None, plot_edge_lines = True, \ plot_center_lines = False, plot_bin_colors = True, \ axtype = 'polar', ax = None, force_CVG_layout = True, vf_model_type = _VF_MODEL_TYPE, vf_pcolorshift = _VF_PCOLORSHIFT, vf_color = 'k', \ vf_bin_labels = _VF_PCOLORSHIFT['labels'], vf_plot_bin_colors = True, \ scale_vf_chroma_to_sample_chroma = False,\ plot_VF = True, plot_CF = False, plot_SF = False): """ Plot graphical information on color rendition properties. Args: :data: | ndarray with spectral data or dict with pre-computed metrics. :cri_type: | None, optional | If None: defaults to cri_type = 'iesrf'. | :hbins:, :start_hue: and :scalef: are ignored if cri_type not None | and values are replaced by those in cri_type['rg_pars'] :hbins: | 16 or ndarray with sorted hue bin centers (°), optional :start_hue: | 0.0, optional :scalef: | 100, optional | Scale factor for graphic. :plot_axis_labels: | False, optional | Turns axis ticks on/off (True/False). :bin_labels: | None or list[str] or '#', optional | Plots labels at the bin center hues. | - None: don't plot. | - list[str]: list with str for each bin. | (len(:bin_labels:) = :nhbins:) | - '#': plots number. :plot_edge_lines: | True or False, optional | Plot grey bin edge lines with '--'. :plot_center_lines: | False or True, optional | Plot colored lines at 'center' of hue bin. :plot_bin_colors: | True, optional | Colorize hue bins. :axtype: | 'polar' or 'cart', optional | Make polar or Cartesian plot. :ax: | None or 'new' or 'same', optional | - None or 'new' creates new plot | - 'same': continue plot on same axes. | - axes handle: plot on specified axes. :force_CVG_layout: | False or True, optional | True: Force plot of basis of CVG. :vf_model_type: | _VF_MODEL_TYPE or 'M6' or 'M5', optional | Type of polynomial vector field model to use for the calculation of base color shift and metameric uncertainty. :vf_pcolorshift: | _VF_PCOLORSHIFT or user defined dict, optional | The polynomial models of degree 5 and 6 can be fully specified or summarized by the model parameters themselved OR by calculating the dCoverC and dH at resp. 5 and 6 hues. :VF_pcolorshift: specifies these hues and chroma level. :vf_color: | 'k', optional | For plotting the vector fields. :vf_plot_bin_colors: | True, optional | Colorize hue bins of VF graph. :scale_vf_chroma_to_sample_chroma: | False, optional | Scale chroma of reference and test vf fields such that average of binned reference chroma equals that of the binned sample chroma before calculating hue bin metrics. :vf_bin_labels: | see :bin_labels: | Set VF model hue-bin labels. :plot_CF: | False, optional | Plot circle fields. :plot_VF: | True, optional | Plot vector fields. :plot_SF: | True, optional | Plot sample shifts. Returns: :returns: | (data, | [plt.gcf(),ax_spd, ax_CVG, ax_locC, ax_locH, ax_VF], | cmap ) | | :data: dict with color rendering data | with keys: | - 'SPD' : ndarray test SPDs | - 'bjabt': ndarray with binned jab data under test SPDs | - 'bjabr': ndarray with binned jab data under reference SPDs | - 'cct' : ndarray with CCT of test SPD | - 'duv' : ndarray with distance to blackbody locus of test SPD | - 'Rf' : ndarray with general color fidelity indices | - 'Rg' : ndarray with gamut area indices | - 'Rfi' : ndarray with specific color fidelity indices | - 'Rfhi' : ndarray with local (hue binned) fidelity indices | - 'Rcshi': ndarray with local chroma shifts indices | - 'Rhshi': ndarray with local hue shifts indices | - 'Rt' : ndarray with general metameric uncertainty index Rt | - 'Rti' : ndarray with specific metameric uncertainty indices Rti | - 'Rfhi_vf' : ndarray with local (hue binned) fidelity indices | obtained from VF model predictions at color space | pixel coordinates | - 'Rcshi_vf': ndarray with local chroma shifts indices | (same as above) | - 'Rhshi_vf': ndarray with local hue shifts indices | (same as above) | | :[...]: list with handles to current figure and 5 axes. | | :cmap: list with rgb colors for hue bins (for use in other plotting fcns) """ if not isinstance(data,dict): data = spd_to_ies_tm30_metrics(data, cri_type = cri_type, hbins = hbins, start_hue = start_hue, scalef = scalef, vf_model_type = vf_model_type, vf_pcolorshift = vf_pcolorshift, scale_vf_chroma_to_sample_chroma = scale_vf_chroma_to_sample_chroma) Rcshi, Rf, Rfchhi_vf, Rfhi, Rfhi_vf, Rfhshi_vf, Rfi, Rg, Rhshi, Rt, Rti, SPD, bjabr, bjabt, cct, cri_type, dataVF, duv = [data[x] for x in sorted(data.keys())] hbins = cri_type['rg_pars']['nhbins'] start_hue = cri_type['rg_pars']['start_hue'] scalef = cri_type['rg_pars']['normalized_chroma_ref'] #layout = np.array([[3,3,0,0],[1,0,2,2],[0,0,2,1],[2,2,1,1],[0,2,1,1],[1,2,1,1]]) #layout = np.array([[6,6,0,0],[0,3,3,3],[3,3,3,3],[0,0,3,2],[2,2,2,2],[2,0,2,2],[4,0,2,2]]) layout = np.array([[6,7,0,0],[0,4,3,3],[3,4,3,3],[0,0,4,2],[2,0,2,2],[4,2,2,2],[4,0,2,2],[2,2,2,2]]) def create_subplot(layout,n, polar = False, frameon = True): ax = plt.subplot2grid(layout[0,0:2], layout[n,0:2], colspan = layout[n,2], rowspan = layout[n,3], polar = polar, frameon = frameon) return ax for i in range(cct.shape[0]): fig = plt.figure(figsize=(10, 6), dpi=144) # Plot CVG: ax_CVG = create_subplot(layout,1, polar = True, frameon = False) figCVG, ax, cmap = plot_ColorVectorGraphic(bjabt[...,i,:], bjabr[...,i,:], hbins = hbins, axtype = axtype, ax = ax_CVG, plot_center_lines = plot_center_lines, plot_edge_lines = plot_edge_lines, plot_bin_colors = plot_bin_colors, scalef = scalef, force_CVG_layout = force_CVG_layout, bin_labels = '#') # Plot VF: ax_VF = create_subplot(layout,2, polar = True, frameon = False) if i == 0: hbin_cmap = None ax_VF, hbin_cmap = plot_VF_PX_models([dataVF[i]], dataPX = None, plot_VF = plot_VF, plot_PX = None, axtype = 'polar', ax = ax_VF, \ plot_circle_field = plot_CF, plot_sample_shifts = plot_SF, plot_bin_colors = vf_plot_bin_colors, \ plot_samples_shifts_at_pixel_center = False, jabp_sampled = None, \ plot_VF_colors = [vf_color], plot_PX_colors = ['r'], hbin_cmap = hbin_cmap, force_CVG_layout = True, bin_labels = vf_bin_labels) # Plot test SPD: ax_spd = create_subplot(layout,3) ax_spd.plot(SPD[0],SPD[i+1]/SPD[i+1].max(),'r-') ax_spd.text(730,0.9,'CCT = {:1.0f} K'.format(cct[i][0]),fontsize = 9, horizontalalignment='left',verticalalignment='center',rotation = 0, color = np.array([1,1,1])*0.3) ax_spd.text(730,0.8,'Duv = {:1.4f}'.format(duv[i][0]),fontsize = 9, horizontalalignment='left',verticalalignment='center',rotation = 0, color = np.array([1,1,1])*0.3) ax_spd.text(730,0.7,'IES Rf = {:1.0f}'.format(Rf[:,i][0]),fontsize = 9, horizontalalignment='left',verticalalignment='center',rotation = 0, color = np.array([1,1,1])*0.3) ax_spd.text(730,0.6,'IES Rg = {:1.0f}'.format(Rg[:,i][0]),fontsize = 9, horizontalalignment='left',verticalalignment='center',rotation = 0, color = np.array([1,1,1])*0.3) ax_spd.text(730,0.5,'Rt = {:1.0f}'.format(Rt[:,i][0]),fontsize = 9, horizontalalignment='left',verticalalignment='center',rotation = 0, color = np.array([1,1,1])*0.3) ax_spd.set_xlabel('Wavelength (nm)', fontsize = 9) ax_spd.set_ylabel('Rel. spectral intensity', fontsize = 9) ax_spd.set_xlim([360,830]) # Plot local color fidelity, Rfhi: ax_Rfi = create_subplot(layout,4) for j in range(hbins): ax_Rfi.bar(range(hbins)[j],Rfhi[j,i], color = cmap[j], width = 1,edgecolor = 'k', alpha = 0.4) ax_Rfi.text(range(hbins)[j],Rfhi[j,i]*1.1, '{:1.0f}'.format(Rfhi[j,i]) ,fontsize = 9,horizontalalignment='center',verticalalignment='center',color = np.array([1,1,1])*0.3) ax_Rfi.set_ylim([0,120]) xticks = np.arange(hbins) xtickslabels = ['{:1.0f}'.format(ii+1) for ii in range(hbins)] ax_Rfi.set_xticks(xticks) ax_Rfi.set_xticklabels(xtickslabels, fontsize = 8) ax_Rfi.set_ylabel(r'Local color fidelity $R_{f,hi}$') ax_Rfi.set_xlabel('Hue bin #') # Plot local chroma shift, Rcshi: ax_locC = create_subplot(layout,5) for j in range(hbins): ax_locC.bar(range(hbins)[j],Rcshi[j,i], color = cmap[j], width = 1,edgecolor = 'k', alpha = 0.4) ax_locC.text(range(hbins)[j],-np.sign(Rcshi[j,i])*0.1, '{:1.0f}%'.format(100*Rcshi[j,i]) ,fontsize = 9,horizontalalignment='center',verticalalignment='center',rotation = 90, color = np.array([1,1,1])*0.3) ylim = np.array([np.abs(Rcshi.min()),np.abs(Rcshi.min()),0.2]).max()*1.5 ax_locC.set_ylim([-ylim,ylim]) ax_locC.set_ylabel(r'Local chroma shift, $R_{cs,hi}$') ax_locC.set_xticklabels([]) ax_locC.set_yticklabels(['{:1.2f}'.format(ii) for ii in ax_locC.set_ylim()], color = 'white') # Plot local hue shift, Rhshi: ax_locH = create_subplot(layout,6) for j in range(hbins): ax_locH.bar(range(hbins)[j],Rhshi[j,i], color = cmap[j], width = 1,edgecolor = 'k', alpha = 0.4) ax_locH.text(range(hbins)[j],-np.sign(Rhshi[j,i])*0.2, '{:1.3f}'.format(Rhshi[j,i]) ,fontsize = 9,horizontalalignment='center',verticalalignment='center',rotation = 90, color = np.array([1,1,1])*0.3) ylim = np.array([np.abs(Rhshi.min()),np.abs(Rhshi.min()),0.2]).max()*1.5 ax_locH.set_ylim([-ylim,ylim]) ax_locH.set_ylabel(r'Local hue shift, $R_{hs,hi}$') ax_locH.set_xticklabels([]) ax_locH.set_yticklabels(['{:1.2f}'.format(ii) for ii in ax_locH.set_ylim()], color = 'white') # Plot local color fidelity of VF, vfRfhi: ax_vfRfi = create_subplot(layout,7) for j in range(hbins): ax_vfRfi.bar(range(hbins)[j],Rfhi_vf[j,i], color = cmap[j], width = 1,edgecolor = 'k', alpha = 0.4) ax_vfRfi.text(range(hbins)[j],Rfhi_vf[j,i]*1.1, '{:1.0f}'.format(Rfhi_vf[j,i]) ,fontsize = 9,horizontalalignment='center',verticalalignment='center',color = np.array([1,1,1])*0.3) ax_vfRfi.set_ylim([0,120]) xticks = np.arange(hbins) xtickslabels = ['{:1.0f}'.format(ii+1) for ii in range(hbins)] ax_vfRfi.set_xticks(xticks) ax_vfRfi.set_xticklabels(xtickslabels, fontsize = 8) ax_vfRfi.set_ylabel(r'Local VF color fidelity $vfR_{f,hi}$') ax_vfRfi.set_xlabel('Hue bin #') plt.tight_layout() return data, [plt.gcf(),ax_spd, ax_CVG, ax_locC, ax_locH, ax_VF], cmap
def plot_hue_bins(hbins = 16, start_hue = 0.0, scalef = 100, \ plot_axis_labels = False, bin_labels = '#', plot_edge_lines = True, \ plot_center_lines = False, plot_bin_colors = True, \ axtype = 'polar', ax = None, force_CVG_layout = False): """ Makes basis plot for Color Vector Graphic (CVG). Args: :hbins: | 16 or ndarray with sorted hue bin centers (°), optional :start_hue: | 0.0, optional :scalef: | 100, optional | Scale factor for graphic. :plot_axis_labels: | False, optional | Turns axis ticks on/off (True/False). :bin_labels: | None or list[str] or '#', optional | Plots labels at the bin center hues. | - None: don't plot. | - list[str]: list with str for each bin. | (len(:bin_labels:) = :nhbins:) | - '#': plots number. :plot_edge_lines: | True or False, optional | Plot grey bin edge lines with '--'. :plot_center_lines: | False or True, optional | Plot colored lines at 'center' of hue bin. :plot_bin_colors: | True, optional | Colorize hue bins. :axtype: | 'polar' or 'cart', optional | Make polar or Cartesian plot. :ax: | None or 'new' or 'same', optional | - None or 'new' creates new plot | - 'same': continue plot on same axes. | - axes handle: plot on specified axes. :force_CVG_layout: | False or True, optional | True: Force plot of basis of CVG on first encounter. Returns: :returns: | gcf(), gca(), list with rgb colors for hue bins (for use in other plotting fcns) """ # Setup hbincenters and hsv_hues: if isinstance(hbins, float) | isinstance(hbins, int): nhbins = hbins dhbins = 360 / (nhbins) # hue bin width hbincenters = np.arange(start_hue + dhbins / 2, 360, dhbins) hbincenters = np.sort(hbincenters) else: hbincenters = hbins idx = np.argsort(hbincenters) if isinstance(bin_labels, list) | isinstance(bin_labels, np.ndarray): bin_labels = bin_labels[idx] hbincenters = hbincenters[idx] nhbins = hbincenters.shape[0] hbincenters = hbincenters * np.pi / 180 # Setup hbin labels: if bin_labels is '#': bin_labels = ['#{:1.0f}'.format(i + 1) for i in range(nhbins)] # initializing the figure cmap = None if (ax == None) or (ax == 'new'): fig = plt.figure() newfig = True else: newfig = False rect = [0.1, 0.1, 0.8, 0.8] # setting the axis limits in [left, bottom, width, height] if axtype == 'polar': # the polar axis: if newfig == True: ax = fig.add_axes(rect, polar=True, frameon=False) else: #cartesian axis: if newfig == True: ax = fig.add_axes(rect) if (newfig == True) | (force_CVG_layout == True): # Calculate hue-bin boundaries: r = np.vstack( (np.zeros(hbincenters.shape), scalef * np.ones(hbincenters.shape))) theta = np.vstack((np.zeros(hbincenters.shape), hbincenters)) #t = hbincenters.copy() dU = np.roll(hbincenters.copy(), -1) dL = np.roll(hbincenters.copy(), 1) dtU = dU - hbincenters dtL = hbincenters - dL dtU[dtU < 0] = dtU[dtU < 0] + 2 * np.pi dtL[dtL < 0] = dtL[dtL < 0] + 2 * np.pi dL = hbincenters - dtL / 2 dU = hbincenters + dtU / 2 dt = (dU - dL) dM = dL + dt / 2 # Setup color for plotting hue bins: hsv_hues = hbincenters - 30 * np.pi / 180 hsv_hues = hsv_hues / hsv_hues.max() edges = np.vstack( (np.zeros(hbincenters.shape), dL)) # setup hue bin edges array if axtype == 'cart': if plot_center_lines == True: hx = r * np.cos(theta) hy = r * np.sin(theta) if bin_labels is not None: hxv = np.vstack((np.zeros(hbincenters.shape), 1.3 * scalef * np.cos(hbincenters))) hyv = np.vstack((np.zeros(hbincenters.shape), 1.3 * scalef * np.sin(hbincenters))) if plot_edge_lines == True: hxe = np.vstack( (np.zeros(hbincenters.shape), 1.2 * scalef * np.cos(dL))) hye = np.vstack( (np.zeros(hbincenters.shape), 1.2 * scalef * np.sin(dL))) # Plot hue-bins: for i in range(nhbins): # Create color from hue angle: c = np.abs(np.array(colorsys.hsv_to_rgb(hsv_hues[i], 0.84, 0.9))) #c = [abs(c[0]),abs(c[1]),abs(c[2])] # ensure all positive elements if i == 0: cmap = [c] else: cmap.append(c) if axtype == 'polar': if plot_edge_lines == True: ax.plot(edges[:, i], r[:, i] * 1.2, color='grey', marker='None', linestyle=':', linewidth=3, markersize=2) if plot_center_lines == True: if np.mod(i, 2) == 1: ax.plot(theta[:, i], r[:, i], color=c, marker=None, linestyle='--', linewidth=2) else: ax.plot(theta[:, i], r[:, i], color=c, marker='o', linestyle='-', linewidth=3, markersize=10) if plot_bin_colors == True: bar = ax.bar(dM[i], r[1, i], width=dt[i], color=c, alpha=0.15) if bin_labels is not None: ax.text(hbincenters[i], 1.3 * scalef, bin_labels[i], fontsize=12, horizontalalignment='center', verticalalignment='center', color=np.array([1, 1, 1]) * 0.3) if plot_axis_labels == False: ax.set_xticklabels([]) ax.set_yticklabels([]) else: if plot_edge_lines == True: ax.plot(hxe[:, i], hye[:, i], color='grey', marker='None', linestyle=':', linewidth=3, markersize=2) if plot_center_lines == True: if np.mod(i, 2) == 1: ax.plot(hx[:, i], hy[:, i], color=c, marker=None, linestyle='--', linewidth=2) else: ax.plot(hx[:, i], hy[:, i], color=c, marker='o', linestyle='-', linewidth=3, markersize=10) if bin_labels is not None: ax.text(hxv[1, i], hyv[1, i], bin_labels[i], fontsize=12, horizontalalignment='center', verticalalignment='center', color=np.array([1, 1, 1]) * 0.3) ax.axis(1.1 * np.array( [hxv.min(), hxv.max(), hyv.min(), hyv.max()])) if plot_axis_labels == False: ax.set_xticklabels([]) ax.set_yticklabels([]) else: plt.xlabel("a'") plt.ylabel("b'") plt.plot(0, 0, color='k', marker='o', linestyle=None) return plt.gcf(), plt.gca(), cmap
def plot_spectrum_colors(spd = None, spdmax = None,\ wavelength_height = -0.05, wavelength_opacity = 1.0, wavelength_lightness = 1.0,\ cieobs = _CIEOBS, show = True, axh = None,\ show_grid = True,ylabel = 'Spectral intensity (a.u.)',xlim=None,\ **kwargs): """ Plot the spectrum colors. Args: :spd: | None, optional | Spectrum :spdmax: | None, optional | max ylim is set at 1.05 or (1+abs(wavelength_height)*spdmax) :wavelength_opacity: | 1.0, optional | Sets opacity of wavelength rectangle. :wavelength_lightness: | 1.0, optional | Sets lightness of wavelength rectangle. :wavelength_height: | -0.05 or 'spd', optional | Determine wavelength bar height | if not 'spd': x% of spd.max() :axh: | None or axes handle, optional | Determines axes to plot data in. | None: make new figure. :show: | True or False, optional | Invoke matplotlib.pyplot.show() right after plotting :cieobs: | luxpy._CIEOBS or str, optional | Determines CMF set to calculate spectrum locus or other. :show_grid: | True, optional | Show grid (True) or not (False) :ylabel: | 'Spectral intensity (a.u.)' or str, optional | Set y-axis label. :xlim: | None, optional | list or ndarray with xlimits. :kwargs: | additional keyword arguments for use with matplotlib.pyplot. Returns: """ cmfs = _CMF[cieobs]['bar'] wavs = cmfs[0:1].T SL = cmfs[1:4].T srgb = xyz_to_srgb(wavelength_lightness*100*SL) srgb = srgb/srgb.max() if show == True: if axh is None: fig = plt.figure() axh = fig.add_subplot(111) if (wavelength_height == 'spd') & (spd is not None): if spdmax is None: spdmax = np.nanmax(spd[1:,:]) y_min, y_max = 0.0, spdmax*(1.05) if xlim is None: x_min, x_max = spd[0,:].min(), spd[0,:].max() else: x_min, x_max = xlim SLrect = np.vstack([ (x_min, 0.0), spd.T, (x_max, 0.0), ]) wavelength_height = y_max spdmax = 1 else: if (spdmax is None) & (spd is not None): spdmax = np.nanmax(spd[1:,:]) y_min, y_max = wavelength_height*spdmax, spdmax*(1 + np.abs(wavelength_height)) elif (spdmax is None) & (spd is None): spdmax = 1 y_min, y_max = wavelength_height, 0 elif (spdmax is not None): y_min, y_max = wavelength_height*spdmax, spdmax#*(1 + np.abs(wavelength_height)) if xlim is None: x_min, x_max = wavs.min(), wavs.max() else: x_min, x_max = xlim SLrect = np.vstack([ (x_min, 0.0), (x_min, wavelength_height*spdmax), (x_max, wavelength_height*spdmax), (x_max, 0.0), ]) axh.set_xlim([x_min,x_max]) axh.set_ylim([y_min,y_max]) polygon = Polygon(SLrect, facecolor=None, edgecolor=None) axh.add_patch(polygon) padding = 0.1 axh.bar(x = wavs - padding, height = wavelength_height*spdmax, width = 1 + padding, color = srgb, align = 'edge', linewidth = 0, clip_path = polygon) if spd is not None: axh.plot(spd[0:1,:].T,spd[1:,:].T, color = 'k', label = 'spd') if show_grid == True: plt.grid() axh.set_xlabel('Wavelength (nm)',kwargs) axh.set_ylabel(ylabel, kwargs) #plt.show() return axh else: return None
def plot_chromaticity_diagram_colors(diagram_samples = 256, diagram_opacity = 1.0, diagram_lightness = 0.25,\ cieobs = _CIEOBS, cspace = 'Yxy', cspace_pars = {},\ show = True, axh = None,\ show_grid = True, label_fontname = 'Times New Roman', label_fontsize = 12,\ **kwargs): """ Plot the chromaticity diagram colors. Args: :diagram_samples: | 256, optional | Sampling resolution of color space. :diagram_opacity: | 1.0, optional | Sets opacity of chromaticity diagram :diagram_lightness: | 0.25, optional | Sets lightness of chromaticity diagram :axh: | None or axes handle, optional | Determines axes to plot data in. | None: make new figure. :show: | True or False, optional | Invoke matplotlib.pyplot.show() right after plotting :cieobs: | luxpy._CIEOBS or str, optional | Determines CMF set to calculate spectrum locus or other. :cspace: | luxpy._CSPACE or str, optional | Determines color space / chromaticity diagram to plot data in. | Note that data is expected to be in specified :cspace: :cspace_pars: | {} or dict, optional | Dict with parameters required by color space specified in :cspace: | (for use with luxpy.colortf()) :show_grid: | True, optional | Show grid (True) or not (False) :label_fontname: | 'Times New Roman', optional | Sets font type of axis labels. :label_fontsize: | 12, optional | Sets font size of axis labels. :kwargs: | additional keyword arguments for use with matplotlib.pyplot. Returns: """ offset = _EPS ii, jj = np.meshgrid(np.linspace(offset, 1 + offset, diagram_samples), np.linspace(1+offset, offset, diagram_samples)) ij = np.dstack((ii, jj)) SL = _CMF[cieobs]['bar'][1:4].T SL = np.vstack((SL,SL[0])) SL = 100.0*SL/SL[:,1,None] SL = colortf(SL, tf = cspace, tfa0 = cspace_pars) Y,x,y = asplit(SL) SL = np.vstack((x,y)).T ij2D = ij.reshape((diagram_samples**2,2)) ij2D = np.hstack((diagram_lightness*100*np.ones((ij2D.shape[0],1)), ij2D)) xyz = colortf(ij2D, tf = cspace + '>xyz', tfa0 = cspace_pars) xyz[xyz < 0] = 0 xyz[np.isinf(xyz.sum(axis=1)),:] = np.nan xyz[np.isnan(xyz.sum(axis=1)),:] = offset srgb = xyz_to_srgb(xyz) srgb = srgb/srgb.max() srgb = srgb.reshape((diagram_samples,diagram_samples,3)) if show == True: if axh is None: fig = plt.figure() axh = fig.add_subplot(111) polygon = Polygon(SL, facecolor='none', edgecolor='none') axh.add_patch(polygon) image = axh.imshow( srgb, interpolation='bilinear', extent = (0.0, 1, -0.05, 1), clip_path=None, alpha=diagram_opacity) image.set_clip_path(polygon) plt.plot(x,y, color = 'darkgray') if cspace == 'Yxy': plt.xlim([0,1]) plt.ylim([0,1]) elif cspace == 'Yuv': plt.xlim([0,0.6]) plt.ylim([0,0.6]) if (cspace is not None): xlabel = _CSPACE_AXES[cspace][1] ylabel = _CSPACE_AXES[cspace][2] if (label_fontname is not None) & (label_fontsize is not None): plt.xlabel(xlabel, fontname = label_fontname, fontsize = label_fontsize) plt.ylabel(ylabel, fontname = label_fontname, fontsize = label_fontsize) if show_grid == True: plt.grid() #plt.show() return axh else: return None
def plot_color_data(x,y,z=None, axh=None, show = True, cieobs =_CIEOBS, \ cspace = _CSPACE, formatstr = 'k-', **kwargs): """ Plot color data from x,y [,z]. Args: :x: | float or ndarray with x-coordinate data :y: | float or ndarray with y-coordinate data :z: | None or float or ndarray with Z-coordinate data, optional | If None: make 2d plot. :axh: | None or axes handle, optional | Determines axes to plot data in. | None: make new figure. :show: | True or False, optional | Invoke matplotlib.pyplot.show() right after plotting :cieobs: | luxpy._CIEOBS or str, optional | Determines CMF set to calculate spectrum locus or other. :cspace: | luxpy._CSPACE or str, optional | Determines color space / chromaticity diagram to plot data in. | Note that data is expected to be in specified :cspace: :formatstr: | 'k-' or str, optional | Format str for plotting (see ?matplotlib.pyplot.plot) :kwargs: | additional keyword arguments for use with matplotlib.pyplot. Returns: :returns: | None (:show: == True) | or | handle to current axes (:show: == False) """ x = np.atleast_1d(x) y = np.atleast_1d(y) if 'grid' in kwargs.keys(): plt.grid(kwargs['grid']);kwargs.pop('grid') if z is not None: z = np.atleast_1d(z) if axh is None: fig = plt.figure() axh = plt.axes(projection='3d') axh.plot3D(x,y,z,formatstr, linewidth = 2,**kwargs) plt.zlabel(_CSPACE_AXES[cspace][0], kwargs) else: plt.plot(x,y,formatstr,linewidth = 2,**kwargs) plt.xlabel(_CSPACE_AXES[cspace][1], kwargs) plt.ylabel(_CSPACE_AXES[cspace][2], kwargs) if 'label' in kwargs.keys(): plt.legend() if show == True: plt.show() else: return plt.gca()
def plotellipse(v, cspace_in = 'Yxy', cspace_out = None, nsamples = 100, \ show = True, axh = None, \ line_color = 'darkgray', line_style = ':', line_width = 1, line_marker = '', line_markersize = 4,\ plot_center = False, center_marker = 'o', center_color = 'darkgray', center_markersize = 4,\ show_grid = True, label_fontname = 'Times New Roman', label_fontsize = 12,\ out = None): """ Plot ellipse(s) given in v-format [Rmax,Rmin,xc,yc,theta]. Args: :v: | (Nx5) ndarray | ellipse parameters [Rmax,Rmin,xc,yc,theta] :cspace_in: | 'Yxy', optional | Color space of v. | If None: no color space assumed. Axis labels assumed ('x','y'). :cspace_out: | None, optional | Color space to plot ellipse(s) in. | If None: plot in cspace_in. :nsamples: | 100 or int, optional | Number of points (samples) in ellipse boundary :show: | True or boolean, optional | Plot ellipse(s) (True) or not (False) :axh: | None, optional | Ax-handle to plot ellipse(s) in. | If None: create new figure with axes. :line_color: | 'darkgray', optional | Color to plot ellipse(s) in. :line_style: | ':', optional | Linestyle of ellipse(s). :line_width': | 1, optional | Width of ellipse boundary line. :line_marker: | 'none', optional | Marker for ellipse boundary. :line_markersize: | 4, optional | Size of markers in ellipse boundary. :plot_center: | False, optional | Plot center of ellipse: yes (True) or no (False) :center_color: | 'darkgray', optional | Color to plot ellipse center in. :center_marker: | 'o', optional | Marker for ellipse center. :center_markersize: | 4, optional | Size of marker of ellipse center. :show_grid: | True, optional | Show grid (True) or not (False) :label_fontname: | 'Times New Roman', optional | Sets font type of axis labels. :label_fontsize: | 12, optional | Sets font size of axis labels. :out: | None, optional | Output of function | If None: returns None. Can be used to output axh of newly created | figure axes or to return Yxys an ndarray with coordinates of | ellipse boundaries in cspace_out (shape = (nsamples,3,N)) Returns: :returns: None, or whatever set by :out:. """ Yxys = np.zeros((nsamples,3,v.shape[0])) ellipse_vs = np.zeros((v.shape[0],5)) for i,vi in enumerate(v): # Set sample density of ellipse boundary: t = np.linspace(0, 2*np.pi, nsamples) a = vi[0] # major axis b = vi[1] # minor axis xyc = vi[2:4,None] # center theta = vi[-1] # rotation angle # define rotation matrix: R = np.hstack(( np.vstack((np.cos(theta), np.sin(theta))), np.vstack((-np.sin(theta), np.cos(theta))))) # Calculate ellipses: Yxyc = np.vstack((1, xyc)).T Yxy = np.vstack((np.ones((1,nsamples)), xyc + np.dot(R, np.vstack((a*np.cos(t), b*np.sin(t))) ))).T Yxys[:,:,i] = Yxy # Convert to requested color space: if (cspace_out is not None) & (cspace_in is not None): Yxy = colortf(Yxy, cspace_in + '>' + cspace_out) Yxyc = colortf(Yxyc, cspace_in + '>' + cspace_out) Yxys[:,:,i] = Yxy # get ellipse parameters in requested color space: ellipse_vs[i,:] = math.fit_ellipse(Yxy[:,1:]) #de = np.sqrt((Yxy[:,1]-Yxyc[:,1])**2 + (Yxy[:,2]-Yxyc[:,2])**2) #ellipse_vs[i,:] = np.hstack((de.max(),de.min(),Yxyc[:,1],Yxyc[:,2],np.nan)) # nan because orientation is xy, but request is some other color space. Change later to actual angle when fitellipse() has been implemented # plot ellipses: if show == True: if (axh is None) & (i == 0): fig = plt.figure() axh = fig.add_subplot(111) if (cspace_in is None): xlabel = 'x' ylabel = 'y' else: xlabel = _CSPACE_AXES[cspace_in][1] ylabel = _CSPACE_AXES[cspace_in][2] if (cspace_out is not None): xlabel = _CSPACE_AXES[cspace_out][1] ylabel = _CSPACE_AXES[cspace_out][2] if plot_center == True: plt.plot(Yxyc[:,1],Yxyc[:,2],color = center_color, linestyle = 'none', marker = center_marker, markersize = center_markersize) plt.plot(Yxy[:,1],Yxy[:,2],color = line_color, linestyle = line_style, linewidth = line_width, marker = line_marker, markersize = line_markersize) plt.xlabel(xlabel, fontname = label_fontname, fontsize = label_fontsize) plt.ylabel(ylabel, fontname = label_fontname, fontsize = label_fontsize) if show_grid == True: plt.grid() #plt.show() Yxys = np.transpose(Yxys,axes=(0,2,1)) if out is not None: return eval(out) else: return None