Beispiel #1
0
_PHOTORECEPTORS = ['l-cone', 'm-cone', 's-cone', 'rod', 'iprgc']
_Ee_SYMBOLS = ['Ee,lc', 'Ee,mc', 'Ee,sc', 'Ee,r', 'Ee,z']
_E_SYMBOLS = ['E,lc', 'E,mc', 'E,sc', 'E,r', 'E,z']
_Q_SYMBOLS = ['Q,lc', 'Q,mc', 'Q,sc', 'Q,r', 'Q,z']
_Ee_UNITS = ['W⋅m−2', 'W⋅m−2', 'W⋅m−2', 'W⋅m−2', 'W⋅m−2']
_E_UNITS = ['lux', 'lux', 'lux', 'lux', 'lux']
_Q_UNITS = [
    'photons/m2/s', 'photons/m2/s', 'photons/m2/s', 'photons/m2/s',
    'photons/m2/s'
]
_QUANTITIES = ['erythropic', 'chloropic', 'cyanopic', 'rhodopic',
               'melanopic']  #irradiance, illuminance

_ACTIONSPECTRA = getdata(_PKG_PATH + _SEP + 'toolboxes' + _SEP +
                         'photbiochem' + _SEP + 'data' + _SEP +
                         'cie_tn003_2015_SI_action_spectra.dat',
                         header='infer',
                         kind='np',
                         verbosity=0).T

# Calculate correction factor for Km in standard air:
na = _BB['na']  # n for standard air
c = _BB['c']  # m/s light speed
lambdad = c / (na * 54 * 1e13) / (1e-9)  # 555 nm lambda in standard air
Km_correction_factor = 1 / (1 - (1 - 0.9998567) * (lambdad - 555)
                            )  # correction factor for Km in standard air


def spd_to_aopicE(sid,
                  Ee=None,
                  E=None,
                  Q=None,
from luxpy.utils import np, sp, plt, _PKG_PATH, _SEP, getdata

__all__ = [
    '_INDVCMF_DATA_PATH', '_INDVCMF_DATA', '_INDVCMF_STD_DEV_ALL_PARAM',
    '_INDVCMF_CATOBSPFCTR', '_INDVCMF_M_2d', '_INDVCMF_M_10d'
]
__all__ += [
    'cie2006cmfsEx', 'getMonteCarloParam', 'genMonteCarloObs', 'getCatObs'
]

_INDVCMF_DATA_PATH = _PKG_PATH + _SEP + 'toolboxes' + _SEP + 'indvcmf' + _SEP + 'data' + _SEP

# Load data from files:
_INDVCMF_DATA = {}
_INDVCMF_DATA['rmd'] = getdata(_INDVCMF_DATA_PATH +
                               'asano_cie2006_RelativeMacularDensity.dat',
                               header=None).T
_INDVCMF_DATA['LMSa'] = getdata(_INDVCMF_DATA_PATH + 'asano_cie2006_Alms.dat',
                                header=None).T
_INDVCMF_DATA['docul'] = getdata(_INDVCMF_DATA_PATH +
                                 'asano_cie2006_docul.dat',
                                 header=None).T
_INDVCMF_DATA['USCensus2010population'] = getdata(
    _INDVCMF_DATA_PATH + 'asano_USCensus2010Population.dat',
    header='infer',
    verbosity=0).T
_INDVCMF_DATA['CatObsPfctr'] = getdata(_INDVCMF_DATA_PATH +
                                       'asano_CatObsPfctr.dat',
                                       header=None).T

# Store var of. physiological parameters in dict:
Beispiel #3
0
def spd_to_xyz(data,
               relative=True,
               rfl=None,
               cieobs=_CIEOBS,
               K=None,
               out=None,
               cie_std_dev_obs=None):
    """
    Calculates xyz tristimulus values from spectral data.
       
    Args: 
        :data: 
            | ndarray or pandas.dataframe with spectral data
            | (.shape = (number of spectra + 1, number of wavelengths))
            | Note that :data: is never interpolated, only CMFs and RFLs. 
            | This way interpolation errors due to peaky spectra are avoided. 
            | Conform CIE15-2018.
        :relative: 
            | True or False, optional
            | Calculate relative XYZ (Yw = 100) or absolute XYZ (Y = Luminance)
        :rfl: 
            | ndarray with spectral reflectance functions.
            | Will be interpolated if wavelengths do not match those of :data:
        :cieobs:
            | luxpy._CIEOBS or str, optional
            | Determines the color matching functions to be used in the 
            | calculation of XYZ.
        :K: 
            | None, optional
            |   e.g.  K  = 683 lm/W for '1931_2' (relative == False) 
            |   or K = 100/sum(spd*dl)        (relative == True)
        :out:
            | None or 1 or 2, optional
            | Determines number and shape of output. (see :returns:)
        :cie_std_dev_obs: 
            | None or str, optional
            | - None: don't use CIE Standard Deviate Observer function.
            | - 'f1': use F1 function.
    
    Returns:
        :returns:
            | If rfl is None:
            |    If out is None: ndarray of xyz values 
            |        (.shape = (data.shape[0],3))
            |    If out == 1: ndarray of xyz values 
            |        (.shape = (data.shape[0],3))
            |    If out == 2: (ndarray of xyz, ndarray of xyzw) values
            |        Note that xyz == xyzw, with (.shape = (data.shape[0],3))
            | If rfl is not None:
            |   If out is None: ndarray of xyz values 
            |         (.shape = (rfl.shape[0],data.shape[0],3))
            |   If out == 1: ndarray of xyz values 
            |       (.shape = (rfl.shape[0]+1,data.shape[0],3))
            |        The xyzw values of the light source spd are the first set 
            |        of values of the first dimension. The following values 
            |       along this dimension are the sample (rfl) xyz values.
            |    If out == 2: (ndarray of xyz, ndarray of xyzw) values
            |        with xyz.shape = (rfl.shape[0],data.shape[0],3)
            |        and with xyzw.shape = (data.shape[0],3)
             
    References:
        1. `CIE15:2018, “Colorimetry,” CIE, Vienna, Austria, 2018. <https://doi.org/10.25039/TR.015.2018>`_
    """

    data = getdata(data,
                   kind='np') if isinstance(data, pd.DataFrame) else np2d(
                       data)  # convert to np format and ensure 2D-array

    # get wl spacing:
    dl = getwld(data[0])

    # get cmf,k for cieobs:
    if isinstance(cieobs, str):
        if K is None: K = _CMF[cieobs]['K']
        scr = 'dict'
    else:
        scr = 'cieobs'
        if (K is None) & (relative == False): K = 1

    # Interpolate to wl of data:
    cmf = xyzbar(cieobs=cieobs, scr=scr, wl_new=data[0], kind='np')

    # Add CIE standard deviate observer function to cmf if requested:
    if cie_std_dev_obs is not None:
        cmf_cie_std_dev_obs = xyzbar(cieobs='cie_std_dev_obs_' +
                                     cie_std_dev_obs.lower(),
                                     scr=scr,
                                     wl_new=data[0],
                                     kind='np')
        cmf[1:] = cmf[1:] + cmf_cie_std_dev_obs[1:]

    # Rescale xyz using k or 100/Yw:
    if relative == True: K = 100.0 / np.dot(data[1:], cmf[2, :] * dl)

    # Interpolate rfls to lambda range of spd and calculate xyz:
    if rfl is not None:
        rfl = cie_interp(data=np2d(rfl), wl_new=data[0], kind='rfl')
        rfl = np.concatenate((np.ones((1, data.shape[1])),
                              rfl[1:]))  #add rfl = 1 for light source spectrum
        xyz = K * np.array(
            [np.dot(rfl, (data[1:] * cmf[i + 1, :] * dl).T)
             for i in range(3)])  #calculate tristimulus values
        rflwasnotnone = 1
    else:
        rfl = np.ones((1, data.shape[1]))
        xyz = (K * (np.dot((cmf[1:] * dl), data[1:].T))[:, None, :])
        rflwasnotnone = 0
    xyz = np.transpose(xyz, [1, 2, 0])  #order [rfl,spd,xyz]

    # Setup output:
    if out == 2:
        xyzw = xyz[0, ...]
        xyz = xyz[rflwasnotnone:, ...]
        if rflwasnotnone == 0: xyz = np.squeeze(xyz, axis=0)
        return xyz, xyzw
    elif out == 1:
        if rflwasnotnone == 0: xyz = np.squeeze(xyz, axis=0)
        return xyz
    else:
        xyz = xyz[rflwasnotnone:, ...]
        if rflwasnotnone == 0: xyz = np.squeeze(xyz, axis=0)
        return xyz
Beispiel #4
0
def spd(data = None, interpolation = None, kind = 'np', wl = None,\
        columns = None, sep = ',',header = None, datatype = 'S', \
        norm_type = None, norm_f = None):
    """
    | All-in-one function that can:
    |    1. Read spectral data from data file or take input directly 
         as pandas.dataframe or ndarray.
    |    2. Convert spd-like data from ndarray to pandas.dataframe and back.
    |    3. Interpolate spectral data.
    |    4. Normalize spectral data.
            
    Args:
        :data: 
            | - str with path to file containing spectral data
            | - ndarray with spectral data
            | - pandas.dataframe with spectral data
            | (.shape = (number of spectra + 1, number of original wavelengths))
        :interpolation:
            | None, optional
            | - None: don't interpolate
            | - str with interpolation type or spectrum type
        :kind: 
            | str ['np','df'], optional 
            | Determines type(:returns:), np: ndarray, df: pandas.dataframe
        :wl: 
            | None, optional
            | New wavelength range for interpolation. 
            | Defaults to wavelengths specified by luxpy._WL3.
        :columns: 
            | -  None or list[str] of column names for dataframe, optional
        :header: 
            | None or 'infer', optional
            | - None: no header in file
            | - 'infer': infer headers from file
        :sep: 
            | ',' or '\t' or other char, optional
            | Column separator in case :data: specifies a data file. 
        :datatype': 
            | 'S' (light source) or 'R' (reflectance) or other, optional
            | Specifies a type of spectral data. 
            | Is used when creating column headers when :column: is None.
        :norm_type: 
            | None, optional 
            |       - 'lambda': make lambda in norm_f equal to 1
            |       - 'area': area-normalization times norm_f
            |       - 'max': max-normalization times norm_f
            |       - 'ru': to :norm_f: radiometric units 
            |       - 'pu': to :norm_f: photometric units 
            |       - 'pusa': to :norm_f: photometric units (with Km corrected
            |                             to standard air, cfr. CIE TN003-2015)
            |       - 'qu': to :norm_f: quantal energy units
        :norm_f:
            | 1, optional
            | Normalization factor that determines the size of normalization 
              for 'max' and 'area' 
              or which wavelength is normalized to 1 for 'lambda' option.
    
    Returns:
        :returns: 
            | ndarray or pandas.dataframe 
            | with interpolated and/or normalized spectral data.
    """
    transpose = True if isinstance(
        data, str
    ) else False  #when spd comes from file -> transpose (columns in files should be different spectra)

    # Wavelength definition:
    wl = getwlr(wl)

    # Data input:
    if data is not None:
        if (interpolation is None) & (norm_type is None):
            data = getdata(data=data,
                           kind='np',
                           columns=columns,
                           sep=sep,
                           header=header,
                           datatype=datatype,
                           copy=True)
            if (transpose == True): data = data.T
        else:
            data = getdata(
                data=data,
                kind='np',
                columns=columns,
                sep=sep,
                header=header,
                datatype=datatype,
                copy=True)  #interpolation requires np-array as input
            if (transpose == True): data = data.T
            data = cie_interp(data=data, wl_new=wl, kind=interpolation)
            data = spd_normalize(data,
                                 norm_type=norm_type,
                                 norm_f=norm_f,
                                 wl=True)

        if isinstance(data, pd.DataFrame):
            columns = data.columns  #get possibly updated column names

    else:
        data = np2d(wl)

    if ((data.shape[0] - 1) == 0): columns = None  #only wavelengths

    if kind == 'df': data = data.T

    # convert to desired kind:
    data = getdata(
        data=data, kind=kind, columns=columns, datatype=datatype,
        copy=False)  # already copy when data is not None, else new anyway

    return data
Reference:
    AS/NZS1680.2.5 (1997). INTERIOR LIGHTING PART 2.5: HOSPITAL AND MEDICAL TASKS.

.. codeauthor:: Kevin A.G. Smet (ksmet1977 at gmail.com)
"""
from luxpy import deltaE, _CIE_ILLUMINANTS, spd_to_xyz, blackbody, xyz_to_cct
from luxpy.utils import np, _PKG_PATH, _SEP, getdata

__all__ = [
    '_COI_RFL_BLOOD', '_COI_CIEOBS', '_COI_CSPACE', 'spd_to_COI_ASNZS1680'
]

# Reflectance spectra of 100% and 50% oxygenated blood
_COI_RFL_BLOOD = getdata(_PKG_PATH + _SEP + 'toolboxes' + _SEP +
                         'photbiochem' + _SEP + 'data' + _SEP +
                         'ASNZS_1680.2.5_1997_cyanosisindex_100_50.dat',
                         header=None,
                         kind='np',
                         verbosity=0).T

_COI_CIEOBS = '1931_2'  # default CMF set

_COI_CSPACE = 'lab'

_COI_REF = blackbody(4000, )


def spd_to_COI_ASNZS1680(S=None,
                         tf=_COI_CSPACE,
                         cieobs=_COI_CIEOBS,
                         out='COI,cct',
                         extrapolate_rfl=False):
Beispiel #6
0
        Light. Res. Technol. 44, 516.
        <https://doi.org/10.1177/1477153512467607>`_


Also see notes in doc_string of spd_to_CS_CLa_lrc()

.. codeauthor:: Kevin A.G. Smet (ksmet1977 at gmail.com)
"""
from luxpy import _CIE_ILLUMINANTS, getwld, cie_interp, _IESTM3015, blackbody, spd_to_power
from luxpy.utils import np, _PKG_PATH, _SEP, getdata
from scipy import integrate

__all__=['_LRC_CLA_CS_CONST','spd_to_CS_CLa_lrc']


_LRC_CLA_CS_EFF_FCN = getdata(_PKG_PATH + _SEP + 'toolboxes' + _SEP + 'photbiochem' + _SEP  + 'data' + _SEP + 'LRC2012_CS_CLa_efficiency_functions.dat', header = 'infer', kind ='np', verbosity = 0).T


_LRC_CLA_CS_CONST = {'CLa_2012' : {'Norm' : 1622, 'k': 0.2616, 'a_b_y':0.6201, 'a_rod' : 3.2347, 'RodSat' : 6.52,\
                           'Vphotl': _LRC_CLA_CS_EFF_FCN[1], 'Vscotl': _LRC_CLA_CS_EFF_FCN[2], \
                           'Vl_mpl': _LRC_CLA_CS_EFF_FCN[3], 'Scl_mpl': _LRC_CLA_CS_EFF_FCN[4],\
                           'Mcl' : _LRC_CLA_CS_EFF_FCN[5], 'WL' : _LRC_CLA_CS_EFF_FCN[0]},\
                  'CLa':   {'Norm' : 1547.9, 'k': 0.2616, 'a_b_y':0.7, 'a_rod' : 3.3, 'RodSat' : 6.5215,\
                           'Vphotl': _LRC_CLA_CS_EFF_FCN[1], 'Vscotl': _LRC_CLA_CS_EFF_FCN[2], \
                           'Vl_mpl': _LRC_CLA_CS_EFF_FCN[3], 'Scl_mpl': _LRC_CLA_CS_EFF_FCN[4],\
                           'Mcl' : _LRC_CLA_CS_EFF_FCN[5], 'WL' : _LRC_CLA_CS_EFF_FCN[0]}}



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):