def xyz_to_cct_HA(xyzw): """ Convert XYZ tristimulus values to correlated color temperature (CCT). Args: :xyzw: | ndarray of tristimulus values Returns: :cct: | ndarray of correlated color temperatures estimates References: 1. `Hernández-Andrés, Javier; Lee, RL; Romero, J (September 20, 1999). Calculating Correlated Color Temperatures Across the Entire Gamut of Daylight and Skylight Chromaticities. Applied Optics. 38 (27), 5703–5709. P <https://www.osapublishing.org/ao/abstract.cfm?uri=ao-38-27-5703>`_ Notes: According to paper small error from 3000 - 800 000 K, but a test with Planckians showed errors up to 20% around 500 000 K; e>0.05 for T>200 000, e>0.1 for T>300 000, ... """ if len(xyzw.shape)>2: raise Exception('xyz_to_cct_HA(): Input xyzw.ndim must be <= 2 !') out_of_range_code = np.nan xe = [0.3366, 0.3356] ye = [0.1735, 0.1691] A0 = [-949.86315, 36284.48953] A1 = [6253.80338, 0.00228] t1 = [0.92159, 0.07861] A2 = [28.70599, 5.4535*1e-36] t2 = [0.20039, 0.01543] A3 = [0.00004, 0.0] t3 = [0.07125,1.0] cct_ranges = np.array([[3000.0,50000.0],[50000.0,800000.0]]) Yxy = xyz_to_Yxy(xyzw) CCT = np.ones((1,Yxy.shape[0]))*out_of_range_code for i in range(2): n = (Yxy[:,1]-xe[i])/(Yxy[:,2]-ye[i]) CCT_i = np2d(np.array(A0[i] + A1[i]*np.exp(np.divide(-n,t1[i])) + A2[i]*np.exp(np.divide(-n,t2[i])) + A3[i]*np.exp(np.divide(-n,t3[i])))) p = (CCT_i >= (1.0-0.05*(i == 0))*cct_ranges[i][0]) & (CCT_i < (1.0+0.05*(i == 0))*cct_ranges[i][1]) CCT[p] = CCT_i[p] p = (CCT_i < (1.0-0.05)*cct_ranges[0][0]) #smaller than smallest valid CCT value CCT[p] = -1 if (np.isnan(CCT.sum()) == True) | (np.any(CCT == -1)): print("Warning: xyz_to_cct_HA(): one or more CCTs out of range! --> (CCT < 3 kK, CCT >800 kK) coded as (-1, NaN) 's") return CCT.T
def plotSL(cieobs =_CIEOBS, cspace = _CSPACE, DL = True, BBL = True, D65 = False,\ EEW = False, cctlabels = False, axh = None, show = True,\ cspace_pars = {}, formatstr = 'k-',\ diagram_colors = False, diagram_samples = 100, diagram_opacity = 1.0,\ diagram_lightness = 0.25,\ **kwargs): """ Plot spectrum locus for cieobs in cspace. Args: :DL: | True or False, optional | True plots Daylight Locus as well. :BBL: | True or False, optional | True plots BlackBody Locus as well. :D65: | False or True, optional | True plots D65 chromaticity as well. :EEW: | False or True, optional | True plots Equi-Energy-White chromaticity as well. :cctlabels: | False or True, optional | Add cct text labels at various points along the blackbody locus. :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) :cspace_pars: | {} or dict, optional | Dict with parameters required by color space specified in :cspace: | (for use with luxpy.colortf()) :diagram_colors: | False, optional | True: plot colored chromaticity diagram. :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 :kwargs: | additional keyword arguments for use with matplotlib.pyplot. Returns: :returns: | None (:show: == True) | or | handle to current axes (:show: == False) """ 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) showcopy = show if np.any([DL,BBL,D65,EEW]): show = False if diagram_colors == True: axh_ = plot_chromaticity_diagram_colors(axh = axh, show = diagram_colors, cspace = cspace, cieobs = cieobs,\ cspace_pars = cspace_pars,\ diagram_samples = diagram_samples,\ diagram_opacity = diagram_opacity,\ diagram_lightness = diagram_lightness,\ label_fontname = None, label_fontsize = None) else: axh_ = axh axh_ = plot_color_data(x,y,axh = axh_, cieobs = cieobs, cspace = cspace, show = show, formatstr=formatstr, **kwargs) if DL == True: if 'label' in kwargs.keys(): # avoid label also being used for DL kwargs.pop('label') plotDL(ccts = None, cieobs = cieobs, cspace = cspace, axh = axh_, show = show, cspace_pars = cspace_pars, formatstr = 'k:', **kwargs) if BBL == True: if 'label' in kwargs.keys(): # avoid label also being used for BB kwargs.pop('label') plotBB(ccts = None, cieobs = cieobs, cspace = cspace, axh = axh_, show = show, cspace_pars = cspace_pars, cctlabels = cctlabels, formatstr = 'k-.', **kwargs) if D65 == True: YxyD65 = colortf(spd_to_xyz(_CIE_ILLUMINANTS['D65']), tf = cspace, tfa0 = cspace_pars) plt.plot(YxyD65[...,1],YxyD65[...,2],'bo') if EEW == True: YxyEEW = colortf(spd_to_xyz(_CIE_ILLUMINANTS['E']), tf = cspace, tfa0 = cspace_pars) plt.plot(YxyEEW[...,1],YxyEEW[...,2],'ko') if showcopy == False: return axh_ else: plt.show()