def getwld_(self): """ Get wavelength spacing of SPD instance. Returns: :returns: | float: for equal wavelength spacings | ndarray (.shape = (n,)): for unequal wavelength spacings """ return getwld(self.wl)
def _cri_ref_i(cct, wl3=_WL, ref_type='iestm30', mix_range=[4000, 5000], cieobs='1931_2', force_daylight_below4000K=False, n=None, daylight_locus=None): """ Calculates a reference illuminant spectrum based on cct for color rendering index calculations. """ if mix_range is None: mix_range = _CRI_REF_TYPES[ref_type] if (cct < mix_range[0]) | (ref_type == 'BB'): return blackbody(cct, wl3, n=n) elif (cct > mix_range[0]) | (ref_type == 'DL'): return daylightphase( cct, wl3, force_daylight_below4000K=force_daylight_below4000K, cieobs=cieobs, daylight_locus=daylight_locus) else: SrBB = blackbody(cct, wl3, n=n) SrDL = daylightphase( cct, wl3, verbosity=None, force_daylight_below4000K=force_daylight_below4000K, cieobs=cieobs, daylight_locus=daylight_locus) cmf = _CMF[cieobs]['bar'] if isinstance(cieobs, str) else cieobs wl = SrBB[0] ld = getwld(wl) SrBB = 100.0 * SrBB[1] / np.array(np.sum(SrBB[1] * cmf[2] * ld)) SrDL = 100.0 * SrDL[1] / np.array(np.sum(SrDL[1] * cmf[2] * ld)) Tb, Te = float(mix_range[0]), float(mix_range[1]) cBB, cDL = (Te - cct) / (Te - Tb), (cct - Tb) / (Te - Tb) if cBB < 0.0: cBB = 0.0 elif cBB > 1: cBB = 1.0 if cDL < 0.0: cDL = 0.0 elif cDL > 1: cDL = 1.0 Sr = SrBB * cBB + SrDL * cDL Sr[Sr == float('NaN')] = 0.0 Sr = np.vstack((wl, (Sr / Sr[_POS_WL560]))) return Sr
def fCLa(wl, Elv, integral, Norm = None, k = None, a_b_y = None, a_rod = None, RodSat = None,\ Vphotl = None, Vscotl = None, Vl_mpl = None, Scl_mpl = None, Mcl = None, WL = None): """ Local helper function that calculate CLa from El based on Eq. 1 in Rea et al (2012). Args: The various model parameters as described in the paper and contained in the dict _LRC_CONST. Returns: ndarray with CLa values. References: 1. `Rea MS, Figueiro MG, Bierman A, and Hamner R (2012). Modelling the spectral sensitivity of the human circadian system. Light. Res. Technol. 44, 386–396. <https://doi.org/10.1177/1477153511430474>`_ 2. `Rea MS, Figueiro MG, Bierman A, and Hamner R (2012). Erratum: Modeling the spectral sensitivity of the human circadian system (Lighting Research and Technology (2012) 44:4 (386-396)). Light. Res. Technol. 44, 516. <https://doi.org/10.1177/1477153512467607>`_ """ dl = getwld(wl) # Calculate piecewise function in Eq. 1 in Rea et al. 2012: #calculate value of condition function (~second term of 1st fcn): cond_number = integral( Elv * Scl_mpl * dl) - k * integral(Elv * Vl_mpl * dl) # Calculate second fcn: fcn2 = integral(Elv * Mcl * dl) # Calculate last term of 1st fcn: fcn1_3 = a_rod * (1 - np.exp(-integral(Vscotl * Elv * dl) / RodSat)) # Satisfying cond. is effectively adding fcn1_2 and fcn1_3 to fcn1_1: CLa = Norm * (fcn2 + 1 * (cond_number >= 0) * (a_b_y * cond_number - fcn1_3)) return CLa
def spd_to_aopicE(sid, Ee = None, E = None, Q = None, cieobs = _CIEOBS, sid_units = 'W/m2', out = 'Eeas,Eas'): """ Calculate alpha-opic irradiance (Ee,α) and equivalent luminance (Eα) values for the l-cone, m-cone, s-cone, rod and iprgc (α) photoreceptor cells following CIE technical note TN 003:2015. Args: :sid: | numpy.ndarray with retinal spectral irradiance in :sid_units: | (if 'uW/cm2', sid will be converted to SI units 'W/m2') :Ee: | None, optional | If not None: normalize :sid: to an irradiance of :Ee: :E: | None, optional | If not None: normalize :sid: to an illuminance of :E: | Note that E is calculate using a Km factor corrected to standard air. :Q: | None, optional | If not None: nNormalize :sid: to a quantal energy of :Q: :cieobs: | _CIEOBS or str, optional | Type of cmf set to use for photometric units. :sid_units: | 'W/m2', optional | Other option 'uW/m2', input units of :sid: :out: | 'Eeas, Eas' or str, optional | Determines values to return. Returns: :returns: | (Eeas, Eas) with Eeas and Eas resp. numpy.ndarrays with the α-opic irradiance and equivalent illuminance values of all spectra in :sid: in SI-units. | (other choice can be set using :out:) """ outlist = out.split(',') # Convert to Watt/m²: if sid_units == 'uW/cm2': sid[1:] = sid[1:]/100 elif sid_units == 'W/m2': pass else: raise Exception("spd_to_aopicE(): {} unsupported units for SID.".format(sid_units)) # Normalize sid to Ee: if Ee is not None: sid = spd_normalize(sid, norm_type = 'ru', norm_f = Ee) elif E is not None: sid = spd_normalize(sid, norm_type = 'pusa', norm_f = E) elif Q is not None: sid = spd_normalize(sid, norm_type = 'qu', norm_f = Q) # Get sid irradiance (W/m²): if 'Ee' in outlist: Ee = spd_to_power(sid, cieobs = cieobs, ptype = 'ru') # Get sid illuminance (lx): if 'E' in outlist: E = spd_to_power(sid, cieobs = cieobs, ptype = 'pusa') #photometric units (Km corrected to standard air) # Get sid quantal energy (photons/m²/s): if 'Q' in outlist: Q = spd_to_power(sid, cieobs = cieobs, ptype = 'qu') # get SI actinic action spectra, sa: sa = spd(_ACTIONSPECTRA, wl = sid[0], interpolation = 'cmf', norm_type = 'max') # get wavelength spacing: dl = getwld(sid[0]) # Calculate all alpha-opics Ee's: Eeas = (np.dot((sa[1:]*dl),sid[1:].T)).T # Calculate equivalent alpha-opic E's: Vl, Km = vlbar(cieobs = cieobs, wl_new = sid[0], out = 2) Eas = Km*Km_correction_factor*Eeas*(Vl[1].sum()/sa[1:].sum(axis = 1)) #Prepare output: if out == 'Eeas,Eas': return Eeas,Eas elif out == 'Eeas': return Eeas elif out == 'Eas': return Eas else: eval(out)
def spd_to_CS_CLa_lrc(El = None, E = None, \ sum_sources = False, interpolate_sources = True): """ Calculate Circadian Stimulus (CS) and Circadian Light [LRC: Rea et al 2012]. Args: :El: | ndarray, optional | Defaults to D65 | light source spectral irradiance distribution :E: | None, float or ndarray, optional | Illuminance of light sources. | If None: El is used as is, otherwise El is renormalized to have an illuminance equal to E. :sum_sources: | False, optional | - False: calculate CS and CLa for all sources in El array. | - True: sum sources in El to a single source and perform calc. :interpolate_sources: | True, optional | - True: El is interpolated to wavelength range of efficiency | functions (as in LRC calculator). | - False: interpolate efficiency functions to source range. | Source interpolation is not recommended due to possible | errors for peaky spectra. | (see CIE15-2004, "Colorimetry"). Returns: :CS: | ndarray with Circadian stimulus values :CLa: | ndarray with Circadian Light values Notes: 1. The original 2012 (E.q. 1) had set the peak wavelength of the melanopsin at 480 nm. Rea et al. later published a corrigendum with updated model parameters for k, a_{b-y} and a_rod. The comparison table between showing values calculated for a number of sources with the old and updated parameters were very close (~1 unit voor CLa). 2. In that corrrection paper they did not mention a change in the factor (1622) that multiplies the (sum of) the integral(s) in Eq. 1. HOWEVER, the excel calculator released in 2017 and the online calculator show that factor to have a value of 1547.9. The change in values due to the new factor is much larger than their the updated mentioned in note 1! 3. For reasons of consistency the calculator uses the latest model parameters, as could be read from the excel calculator. They values adopted are: multiplier 1547.9, k = 0.2616, a_{b-y} = 0.7 and a_rod = 3.3. 4. The parameter values to convert CLa to CS were also taken from the 2017 excel calculator. References: 1. `LRC Online Circadian stimulus calculator <http://www.lrc.rpi.edu/cscalculator/>`_ 2. `LRC Excel based Circadian stimulus calculator. <http://www.lrc.rpi.edu/resources/CSCalculator_2017_10_03_Mac.xlsm>`_ 3. `Rea MS, Figueiro MG, Bierman A, and Hamner R (2012). Modelling the spectral sensitivity of the human circadian system. Light. Res. Technol. 44, 386–396. <https://doi.org/10.1177/1477153511430474>`_ 4. `Rea MS, Figueiro MG, Bierman A, and Hamner R (2012). Erratum: Modeling the spectral sensitivity of the human circadian system (Lighting Research and Technology (2012) 44:4 (386-396)). Light. Res. Technol. 44, 516. <https://doi.org/10.1177/1477153512467607>`_ """ # Create copy of dict with model parameters and spectral data: cs_cl_lrs = _LRC_CLA_CS_CONST['CLa'].copy() # Interpolate efficiency functions to light source wl-range: if interpolate_sources is False: cs_cl_lrs = interpolate_efficiency_functions(El[0], cs_cl_lrs) else: El = cie_interp(El, cs_cl_lrs['WL'], kind='spd') # Get wavelength spacing: dl = getwld(El[0]) # Separate wavelengths and data: wl = El[0] Elv = El[1:].copy() # define integral function: integral = lambda x: integrate.trapz(x, x=wl, axis=-1) #integral = lambda x: np.sum(x, axis = -1) # Rescale El to E (if not None): if E is not None: # Calculate current E value of El: E_cv = np.atleast_2d(683.002 * integral(cs_cl_lrs['Vphotl'] * Elv * dl)) # Rescale El to supplied E: Elv = (E / E_cv).T * Elv # Sum all sources in array if requested: if sum_sources == True: Elv = Elv.sum(axis=0, keepdims=True) # Calculate Circadian light using model param. and spectral data: CLa = fCLa(wl, Elv, integral, **cs_cl_lrs) # Calculate Circadian stimulus: CS = 0.7 * (1 - (1 / (1 + (CLa / 355.7)**1.1026))) return CS, CLa