Spectrum sub-package
- py:
__init__.py
spdx_ietm2714.py
- basics/
__init__.py
cmf.py
spectral.py
spectral_databases.py
- namespace:
luxpy
spectrum: sub-package supporting basic spectral calculations
spectrum/cmf.py
- luxpy._CMF:
Dict with keys ‘types’ and xx are dicts with keys ‘bar’, ‘K’, ‘M’* luxpy._CMF[‘types’] = [‘1931_2’,’1964_10’,‘2006_2’,’2006_10’,’2015_2’,’2015_10’,‘1931_2_judd1951’,’1931_2_juddvos1978’,‘1951_20_scotopic’]* luxpy._CMF[x][‘bar’] = numpy array with CMFs for type xbetween 360 nm and 830 nm (has shape: (4,471))* luxpy._CMF[x][‘K’] = Constant converting Watt to lumen for CMF type x.* luxpy._CMF[x][‘M’] = XYZ to LMS conversion matrix for CMF type x.Matrix is numpy array with shape: (3,3)* luxpy._CMF[x][‘N’] = XYZ to RGB conversion matrix for CMF type x.Matrix is numpy array with shape: (3,3)Notes:
- All functions have been expanded (when necessary) using zeros to a
full 360-830 range. This way those wavelengths do not contribute in the calculation, AND are not extrapolated using the closest known value, as per CIE recommendation.
- There is no XYZ to LMS conversion matrices defined for the
1931 2° Judd corrected (1951) cmf sets. The Hunt-Pointer-Estevez conversion matrix of the 1931 2° is therefore used as an approximation!
- The XYZ to LMS conversion matrix M for the Judd-Vos XYZ CMFs is the one
that converts to the 1979 Smith-Pokorny cone fundamentals.
- The XYZ to LMS conversion matrix for the 1964 10° XYZ CMFs is set
to the one of the CIE 2006 10° cone fundamentals, as not matrix has been officially defined for this CMF set.
- The K lm to Watt conversion factors for the Judd and Judd-Vos cmf
sets have been set to 683.002 lm/W (same as for standard 1931 2°).
- The 1951 scoptopic V’ function has been replicated in the 3
xbar, ybar, zbar columns to obtain a data format similar to the photopic color matching functions. This way V’ can be called in exactly the same way as other V functions can be called from the X,Y,Z cmf sets. The K value has been set to 1700.06 lm/W and the conversion matrix has been filled with NaN’s.
The ‘2015_x’ (with x = 2 or 10) are the same XYZ-CMFs as stored in ‘2006_x’.
- _CMF[x][‘M’] for x equal to ‘2006_2’ (=’2015_2’) or ‘2006_10’ (=’2015_10’) is NOT
normalized to illuminant E! These are the original matrices as defined by [1] & [2].
- _CMF[x][‘N’] stores known or calculated conversion matrices from
xyz to rgb. If not available, N has been filled with NaNs.
spectrum/spectral.py
- _WL3:
Default wavelength specification in vector-3 format: numpy.array([start, end, spacing])
- _INTERP_REFERENCE:
Sets the specific interpolation for spectrum types: [‘spd’,’cmf’,’rfl’,’none’]
- _INTERP_SETTINGS_ALL:
Nested Dict with interpolation settings per spectral type [‘spd’,’cmf’,’rfl’,’none’] for various interp_reference keys.
- _INTERP_SETTINGS:
Nested Dict with interpolation settings per spectral type [‘spd’,’cmf’,’rfl’,’none’].
- _INTERP_TYPES:
Dict with interpolation types associated with various types of spectral data according to CIE recommendation:
- getwlr():
Get/construct a wavelength range from a (start, stop, spacing) 3-vector.
- getwld():
Get wavelength spacing of numpy.ndarray with wavelengths.
- spd_normalize():
Spectrum normalization (supports: area, max, lambda, radiometric, photometric and quantal energy units).
- cie_interp():
Interpolate / extrapolate spectral data following standard [CIE15:2018, “Colorimetry,” CIE, Vienna, Austria, 2018.]
- spd():
All-in-one function that can:1. Read spectral data from data file or take input directly as ndarray.2. Interpolate spectral data.3. Normalize spectral data.- xyzbar():
Get color matching functions.
- vlbar():
Get Vlambda function.
- vlbar_cie_mesopic():
Get CIE mesopic luminous efficiency function Vmesm according to CIE191:2010
- get_cie_mesopic_adaptation():
Get the mesopic adaptation state according to CIE191:2010
- spd_to_xyz_legacy():
Calculates xyz tristimulus values from spectral data. (luxpy version <= 1.11.4)
- spd_to_xyz_barebones():
Calculates xyz tristimulus values from equal wavelength spectral data (no additional processing)
- spd_to_xyz():
Calculates xyz tristimulus values from spectral data.
- spd_to_ler():
Calculates Luminous efficacy of radiation (LER) from spectral data.
- spd_to_power():
Calculate power of spectral data in radiometric, photometric or quantal energy units.
- detect_peakwl():
Detect peak wavelengths and fwhm of peaks in spectrum spd.
spectrum/spectral_databases.py
- _S_PATH:
Path to light source spectra data.
- _R_PATH:
Path to with spectral reflectance data
- _IESTM3015:
Database with spectral reflectances related to and light source spectra contained excel calculator of IES TM30-15 publication.
- _IESTM3018:
Database with spectral reflectances related to and light source spectra contained excel calculator of IES TM30-18 publication.
- _IESTM3015_S:
Database with only light source spectra contained in the IES TM30-15 excel calculator.
- _IESTM3018_S:
Database with only light source spectra contained in the IES TM30-18 excel calculator.
- _CIE_ILLUMINANTS:
Database with CIE illuminants:* ‘E’, ‘D65’, ‘A’, ‘C’,* ‘F1’, ‘F2’, ‘F3’, ‘F4’, ‘F5’, ‘F6’, ‘F7’, ‘F8’, ‘F9’, ‘F10’, ‘F11’, ‘F12’- _CIE_E, _CIE_D65, _CIE_A, _CIE_C, _CIE_F4:
Some CIE illuminants for easy use.
- _CRI_RFL:
Database with spectral reflectance functions for various color rendition calculators:- _MUNSELL:
Database (dict) with 1269 Munsell spectral reflectance functions and Value (V), Chroma (C), hue (h) and (ab) specifications.
- _RFL:
Database (dict) with RFLs, including:* all those in _CRI_RFL,* the 1269 Matt Munsell samples (see also _MUNSELL),* the 24 Macbeth ColorChecker samples,* the 215 samples proposed by Opstelten, J.J. , 1983, The establishment of a representative set of test coloursfor the specification of the colour rendering properties of light sources, CIE-20th session, Amsterdam.* the 114120 RFLs from capbone.com/spectral-reflectance-database/
spectrum/illuminants.py
- _BB:
Dict with constants for blackbody radiator calculation constant are (c1, c2, n, na, c, h, k).
- _S012_DAYLIGHTPHASE:
ndarray with CIE S0,S1, S2 curves for daylight phase calculation (linearly interpolated to 1 nm).
- _CRI_REF_TYPES:
Dict with blackbody to daylight transition (mixing) ranges for various types of reference illuminants used in color rendering index calculations.
- blackbody():
Calculate blackbody radiator spectrum.
- _DAYLIGHT_LOCI_PARAMETERS:
dict with parameters for daylight loci for various CMF sets; used by daylightlocus().
- _DAYLIGHT_M12_COEFFS:
dict with coefficients in weights M1 & M2 for daylight phases for various CMF sets.
- get_daylightloci_parameters():
Get parameters for the daylight loci functions xD(1000/CCT) and yD(xD); used by daylightlocus().
- get_daylightphase_Mi_coeffs():
Get coefficients of Mi weights of daylight phase for specific cieobs following Judd et al. (1964).
- _get_daylightphase_Mi_values():
Get daylight phase coefficients M1, M2 following Judd et al. (1964).
- _get_daylightphase_Mi():
Get daylight phase coefficients M1, M2 following Judd et al. (1964)
- daylightlocus():
Calculates daylight chromaticity from cct.
- daylightphase():
Calculate daylight phase spectrum.
- cri_ref():
- Calculates a reference illuminant spectrum based on cct for color
rendering index calculations.
- (CIE15:2018, “Colorimetry,” CIE, Vienna, Austria, 2018.,
cie224:2017, CIE 2017 Colour Fidelity Index for accurate scientific use. (2017), ISBN 978-3-902842-61-9., IES-TM-30-15: Method for Evaluating Light Source Color Rendition. New York, NY: The Illuminating Engineering Society of North America.
- spd_to_indoor():
Convert spd to indoor variant by multiplying it with the CIE spectral transmission for glass.
spectrum/spdx_iestm2714.py
- _SPDX_TEMPLATE:
template dictionary for SPDX data.
- read_spdx():
Read xml file or convert xml string with spdx data to dictionary.
- write_spdx():
Convert spdx dictionary to xml string (and write to .spdx file)
References
Judd, D. B., MacAdam, D. L., Wyszecki, G., Budde, H. W., Condit, H. R., Henderson, S. T., & Simonds, J. L. (1964). Spectral Distribution of Typical Daylight as a Function of Correlated Color Temperature. J. Opt. Soc. Am., 54(8), 1031–1040. https://doi.org/10.1364/JOSA.54.001031
- luxpy.spectrum.getwlr(wl3=None)[source]
Get/construct a wavelength range from a 3-vector (start, stop, spacing).
- Args:
- wl3:
- list[start, stop, spacing], optional(defaults to luxpy._WL3)
- Returns:
- returns:
- ndarray (.shape = (n,)) with n wavelengths ranging fromstart to stop, with wavelength interval equal to spacing.
- luxpy.spectrum.getwld(wl)[source]
Get wavelength spacing.
- Args:
- wl:
- ndarray with wavelengths
- Returns:
- returns:
- - float: for equal wavelength spacings- ndarray (.shape = (n,)): for unequal wavelength spacings
- luxpy.spectrum.spd_normalize(data, norm_type=None, norm_f=1, wl=True, cieobs='1931_2', K=None, interp_settings=None)[source]
Normalize a spectral power distribution (SPD).
- Args:
- data:
- ndarray
- 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 correctedto standard air, cfr. CIE TN003-2015)- ‘qu’: to :norm_f: quantal energy units
- norm_f:
- 1, optionalNormalization factor that determines the size of normalizationfor ‘max’ and ‘area’or which wavelength is normalized to 1 for ‘lambda’ option.
- wl:
- True or False, optionalIf True, the first column of data contains wavelengths.
- cieobs:
- _CIEOBS or str or ndarray, optionalType of cmf set to use for normalization using photometric units(norm_type == ‘pu’)
- K:
- None, optionalLuminous efficacy of radiation.Must be supplied if cieobs is an array for norm_type == ‘pu’
- Returns:
- returns:
- ndarray with normalized data.
- luxpy.spectrum.spectral_interp(data, wl_new, stype='cmf', interp_settings={'cmf': {'etype': 'linear', 'fill_value': None, 'itype': 'linear', 'negative_values_allowed': False}, 'general': {'choose_most_efficient_interpolator': False, 'extrap_log': False, 'force_scipy_interpolator': False, 'interp_log': False, 'scipy_interpolator': 'interp1d', 'sprague_allowed': False, 'sprague_method': 'spargue_cie224_2017'}, 'none': {'etype': 'linear', 'fill_value': None, 'itype': 'cubic', 'negative_values_allowed': False}, 'rfl': {'etype': 'linear', 'fill_value': None, 'itype': 'cubic', 'negative_values_allowed': False}, 'spd': {'etype': 'linear', 'fill_value': None, 'itype': 'cubic', 'negative_values_allowed': False}}, itype=None, etype=None, fill_value=None, negative_values_allowed=False, delete_nans=True, force_scipy_interpolator=False, scipy_interpolator='InterpolatedUnivariateSpline', interp_log=False, extrap_log=False, choose_most_efficient_interpolator=False, verbosity=0)[source]
Perform a 1-dimensional interpolation of spectral data
- Args:
- data:
- ndarray with (n+1,N)-dimensional spectral data (0-row: wavelengths, remaining n rows: data)
- wl_new:
- ndarray of new wavelengths (N,)
- stype:
- None, optionalType of spectral data: None or (‘spd’, ‘cmf’, ‘rfl’)If None: itype, etype and fill_value kwargs should not be none!
- itype:
- None or str, optionalsupported options for str: ‘linear’, ‘quadratic’, ‘cubic’If None: use value in interp_settings.
- etype:
- None, or str, optionaloptions:- ‘extrapolate’,’ext’: use method specified in :itype: to extrapolate.- ‘zeros’: out-of-bounds values are filled with zeros- ‘const’: out-of-bounds values are filled with nearest value- ‘fill_value’: value of tuple (2,) of values is used to fill out-of-bounds values- ‘linear’,’quadratic’,’cubic’: use of of these methods (slows down functionif this method is different from the one in :itype:)If None: use value in intp_settings.
- fill_value:
- None or str or float or int or tupple, optionalIf etype == ‘fill_value’: use fill_value to set lower- and upper-out-of-bounds values when extrapolating(‘extrapolate’ when etype requires extrapolation)If None: use value in interp_settings.
- negative_values_allowed:
- False, optionalIf False: negative values are clipped to zero.
- delete_nans:
- True, optionalIf NaNs are present, remove them and (and try to) interpolate without them.
- force_scipy_interpolator:
- False, optionalIf False: numpy.interp function is used for linear interpolation when no or linear extrapolation is used/required (fast!).
- scipy_interpolator:
- ‘InterpolatedUnivariateSpline’, optionaloptions: ‘InterpolatedUnivariateSpline’, ‘interp1d’
- w,bbox,check_finite:
- see scipy.interpolate.InterpolatedUnivariateSpline()
- interp_log:
- Perform interpolation method (‘linear’, ‘quadratic’, or ‘cubic’) in log space.
- extrap_log:
- Perform extrapolation method (‘linear’, ‘quadratic’, or ‘cubic’) in log space.
- Returns:
- data_new:
- ndarray with interpolated (n+1,N)-dimensional spectral data(0-row: wavelengths, remaining n rows: interpolated data)
- Note:
‘numpy.interp’ is fastest (but only works for linear interpolation and linear or no extrapolation)
For linear interpolation: ‘interp1d’ is faster for Y (N,…) with N > 1, else ‘InterpolatedUnivariateSpline’ is faster
For ‘cubic’ interpolation: ‘InterpolatedUnivariateSpline’ is faster for Y (N,…) with N > 1, else ‘interp1d’ is faster
- luxpy.spectrum.cie_interp(data, wl_new, datatype='none', interp_settings={'cmf': {'etype': 'linear', 'fill_value': None, 'itype': 'linear', 'negative_values_allowed': False}, 'general': {'choose_most_efficient_interpolator': False, 'extrap_log': False, 'force_scipy_interpolator': False, 'interp_log': False, 'scipy_interpolator': 'interp1d', 'sprague_allowed': False, 'sprague_method': 'spargue_cie224_2017'}, 'none': {'etype': 'linear', 'fill_value': None, 'itype': 'linear', 'negative_values_allowed': False}, 'rfl': {'etype': 'linear', 'fill_value': None, 'itype': 'cubic', 'negative_values_allowed': False}, 'spd': {'etype': 'linear', 'fill_value': None, 'itype': 'cubic', 'negative_values_allowed': False}}, kind=None, extrap_kind=None, extrap_values=None, sprague_allowed=None, sprague_method='sprague_cie224_2017', negative_values_allowed=None, interp_log=None, extrap_log=None, force_scipy_interpolator=None, scipy_interpolator=None, choose_most_efficient_interpolator=None, verbosity=0)[source]
Interpolate / extrapolate spectral data following standard CIE15-2018.
The kind of interpolation depends on the spectrum type defined in :datatype:(or in :kind: for legacy puprposes-> overrules :datatype:).- Args:
- data:
- ndarray with spectral data(.shape = (number of spectra + 1, number of original wavelengths))
- wl_new:
- None or ndarray with new wavelengths or [start wavelength, stop wavelength, wavelength interval]If None: no interpolation is done, a copy of the original data is returned.
- datatype:
- ‘spd’ (light source) or ‘rfl’ (reflectance) or ‘cmf’ (color matching functions) or ‘none’ (undefined), optionalSpecifies a type of spectral data.Is used to select the interpolation and extrapolation defaults, specifiedin :interp_settings:.
- interp_settings:
- _INTERP_SETTINGS or dict, optionalDictionary of dictionaries (see _INTERP_SETTINGS), with at least a key entrywith the interpolation and extrapolation settings for the type specified in:datatype: (or :kind: if string with spectrum datatype) and one key entry ‘none’(‘none’ is used in case :extrap_kind: is None or ‘ext’).
- kind:
- None, optional- If None: the value from interp_settings is used, based on the value of :datatype:.- If :kind: is a spectrum type (see :interp_settings:), the correctinterpolation type is automatically chosen based on the values in :interp_settings:(The use of the slow(er) ‘sprague5’ or ‘sprague_cie224_2017’ can be toggled on using :sprague_allowed:).- Or :kind: can be ‘linear’, ‘quadratic’, ‘cubic’ (or ‘sprague5’, or ‘sprague_cie224_2017, or ‘lagrange5’).(see luxpy.spectral_interp?)
- sprague_allowed:
- None, optionalIf None: the value from interp_settings is used.If True: When kind is a spectral data type that corresponds to ‘cubic’ interpolation,then a cubic spline interpolation will be used in case ofunequal wavelength spacings, otherwise a 5th order Sprague or Sprague as defined in CIE224-2017 will be used.If False: always use ‘cubic’, don’t use ‘sprague5’ or ‘sprague_cie224_2017’.This is the default, as differences are minimal anduse of the ‘sprague’ functions is a lot slower (‘sprague5’ = slowest )!
- sprague_method:
- ‘sprague_cie224_2017’, optionalSpecific sprague method used for interpolation. (Only for equal spacings, ‘sprague_cie224_2017’ also on for 5 nm -> 1nm)- options: ‘sprague5’ (use luxpy.math.interp1_sprague5), ‘sprague_cie224_2017’ (use luxpy.interp1_sprague_cie224_2017)
- negative_values_allowed:
- None, optionalIf None: the value from interp_settings is used.If False: negative values are clipped to zero.
- extrap_kind:
- None, optionalIf None or ‘ext’: use the method specified interp_settings[datatype].If ‘kind’ or ‘itype’:- If possible, use the same method as the interpolation method(only for ‘linear’, ‘quadratic’, ‘cubic’),- otherwise: use the method specified :interp_settings[‘none’]:.Other options: ‘linear’ (or ‘cie167:2005’), ‘quadratic’ (or ‘cie15:2018’),‘nearest’ (or ‘cie15:2004’ or ‘const’ or ‘flat’), ‘cubic’, ‘fill_value’ (use value(s)n in extrap_values)- If ‘linear’,’quadratic’,’cubic’: slow down of functionin case this method is different from the interpolation method used.CIE15:2018 states that based on a 2017 paper by Wang that ‘quadratic’ is ‘better’.However, no significant difference was found between ‘quadratic’ and ‘linear’ methods.Also see note 1 below, for why the CIE67:2005 recommended ‘linear’ extrapolationis set as the default.
- extrap_values:
- None, optionalIf float or list or ndarray, use those values to fill extrapolated value(s) when :extrap_kind:S == ‘fill_value’.
- extrap_log:
- None, optionalIf None: the value from interp_settings is used.If True: extrap the log of the spectral values(not CIE recommended but in most cases seems to give amore realistic estimate, but can sometimes seriously fail,especially for the ‘quadratic’ extrapolation case (see note 1)!!!)If any zero or negative values are present in a spectrum, then the log is NOT taken.
- interp_log:
- None, optionalIf None: the value from interp_settings is used.Take log before interpolating the spectral data, afterwards take exp of interpolated data.If any zero or negative values are present in a spectrum, then the log is NOT taken.
- force_scipy_interpolator:
- None, optionalIf None: the value from interp_settings is used.If False: numpy.interp function is used for linear interpolation when no or linear extrapolation is used/required (fast!).
- scipy_interpolator:
- None, optionalIf None: the value from interp_settings is used.options: ‘InterpolatedUnivariateSpline’, ‘interp1d’
- Returns:
- returns:
- ndarray of interpolated spectral data.(.shape = (number of spectra + 1, number of wavelength in wl_new))
- Notes:
- 1. Type of extrapolation: ‘quadratic’ vs ‘linear’; impact of extrapolating log spectral values:Using a ‘linear’ or ‘quadratic’ extrapolation, as mentioned inCIE167:2005 and CIE15:2018, resp., can lead to extreme large valueswhen setting :extrap_log: (not CIE recommended) to True.A quick test with the IES TM30 spectra (400 nm - 700 nm, 5 nm spacing)shows that ‘linear’ is better than ‘quadratic’ in terms ofmean, median and max DEu’v’ with the original spectra (380 nm - 780 nm, 5 nm spacing).This conferms the recommendation from CIE167:2005 to use ‘linear’ extrapolation.Setting :extrap_log: to True reduces the median, but inflates the mean due to someextremely large DEu’v’ values. However, the increase in mean and max DEu’v’ is muchlarger for the ‘quadratic’ case, suggesting that ‘linear’ extrapolationis likely a more suitable recommendation. When using a 1 nm spacing‘linear’ is more similar to ‘quadratic’ when :extrap_log: is False, otherwise ‘linear’remains the ‘best’. Hence the choice to use the CIE167:2005 recommended linear extrapolation as default!
- luxpy.spectrum.spd(data=None, wl=None, interp_settings=None, kind=None, extrap_kind=None, extrap_values=None, sep=',', header=None, datatype='spd', norm_type=None, norm_f=None, **kwargs)[source]
- All-in-one function that can:1. Read spectral data from data file or take input directly as ndarray.2. Interpolate spectral data.3. Normalize spectral data.
- Args:
- data:
- - str with path to file containing spectral data- ndarray with spectral data(.shape = (number of spectra + 1, number of original wavelengths))
- wl:
- None, optionalNew wavelength range for interpolation.If None: no interpolation will be done.
- kind:
- None, optional- None: use defaults in interp_settings for specified datatype.- str with interpolation type or spectrum type (if spectrum type: overrides anything set in :datatype:)
- extrap_kind:
- None, optional- None: use defaults in interp_settings for specified datatype.- str with extrapolation type
- extrap_values:
- None, optionalControls extrapolation. See cie_interp.
- header:
- None or ‘infer’, optional- None: no header in file- ‘infer’: infer headers from file
- sep:
- ‘,’ or ‘ ‘ or other char, optionalColumn separator in case :data: specifies a data file.
- datatype’:
- ‘spd’ (light source) or ‘rfl’ (reflectance) or ‘cmf’ (color matching functions) or ‘none’ (undefined), optionalSpecifies a type of spectral data.Is used to determine interpolation and extrapolation defaults.
- 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 correctedto standard air, cfr. CIE TN003-2015)- ‘qu’: to :norm_f: quantal energy units
- norm_f:
- 1, optionalNormalization factor that determines the size of normalizationfor ‘max’ and ‘area’or which wavelength is normalized to 1 for ‘lambda’ option.
- Returns:
- returns:
- ndarray with interpolated and/or normalized spectral data.
- luxpy.spectrum.xyzbar(cieobs='1931_2', src='dict', wl_new=None, interp_settings=None, kind=None, extrap_kind=None, extrap_values=None)[source]
Get color matching functions.
- Args:
- cieobs:
- luxpy._CIEOBS, optionalSets the type of color matching functions to load.
- src:
- ‘dict’ or ‘file’, optionalDetermines whether to load cmfs from file (./data/cmfs/)or from dict defined in .cmf.py
- wl:
- None, optionalNew wavelength range for interpolation.If None: no interpolation is done.
- kind:
- None, optional- None: use defaults in interp_settings for “cmf” datatype.- str with interpolation type
- extrap_kind:
- None, optional- None: use defaults in interp_settings for specified datatype.- str with extrapolation type
- extrap_values:
- None, optionalControls extrapolation. See cie_interp.
- Returns:
- returns:
- ndarray with CMFs
- References:
- luxpy.spectrum.vlbar(cieobs='1931_2', K=None, src='dict', wl_new=None, interp_settings=None, kind=None, extrap_kind=None, extrap_values=None, out=1)[source]
Get Vlambda functions.
- Args:
- cieobs:
- str or ndarray, optionalIf str: Sets the type of Vlambda function to obtain.
- K:
- None, optionalLuminous efficacy of radiation.Must be supplied if cieobs is an array
- src:
- ‘dict’ or array, optional- ‘dict’: get from ybar from _CMF- ‘array’: ndarray in :cieobs:Determines whether to load cmfs from file (./data/cmfs/)or from dict defined in .cmf.pyVlambda is obtained by collecting Ybar.
- wl:
- None, optionalNew wavelength range for interpolation.If None: no interpolation is done.
- kind:
- None, optional- None: use defaults in interp_settings for “cmf” datatype.- str with interpolation type
- extrap_kind:
- None, optional- None: use defaults in interp_settings for specified datatype.- str with extrapolation type
- extrap_values:
- None, optionalControls extrapolation. See cie_interp.
- out:
- 1 or 2, optional1: returns Vlambda2: returns (Vlambda, Km)
- Returns:
- returns:
- ndarray with Vlambda of type :cieobs:
- References:
- luxpy.spectrum.vlbar_cie_mesopic(m=[1], wl_new=None, out=1, Lp=None, Ls=None, SP=None, interp_settings=None, kind=None, extrap_kind=None, extrap_values=None)[source]
Get CIE mesopic luminous efficiency function Vmesm according to CIE191:2010
- Args:
- m:
- float or list or ndarray with mesopic adaptation coefficients
- wl:
- None, optionalNew wavelength range for interpolation.If None: no interpolation is done.
- out:
- 1 or 2, optional1: returns Vmesm2: returns (Vmes, Kmesm)
- Lp:
- None, optionalfloat or ndarray with photopic adaptation luminanceIf not None: use this (and SP or Ls) to calculate themesopic adaptation coefficient
- Ls:
- None, optionalfloat or ndarray with scotopic adaptation luminanceIf None: SP must be supplied.
- SP:
- None, optionalS/P ratioIf None: Ls must be supplied.
- kind:
- None, optional- None: use defaults in interp_settings for “cmf” datatype.- str with interpolation type
- extrap_kind:
- None, optional- None: use defaults in interp_settings for specified datatype.- str with extrapolation type
- extrap_values:
- None, optionalControls extrapolation. See cie_interp.
- Returns:
- Vmes:
- ndarray with mesopic luminous efficiency functionfor adaptation coefficient(s) m
- Kmes:
- ndarray with luminous efficacies of 555 nm monochromatic lightfor for adaptation coefficient(s) m
- Reference:
- luxpy.spectrum.get_cie_mesopic_adaptation(Lp, Ls=None, SP=None)[source]
Get the mesopic adaptation state according to CIE191:2010
- Args:
- Lp:
- float or ndarray with photopic adaptation luminance
- Ls:
- None, optionalfloat or ndarray with scotopic adaptation luminanceIf None: SP must be supplied.
- SP:
- None, optionalS/P ratioIf None: Ls must be supplied.
- Returns:
- Lmes:
- mesopic adaptation luminance
- m:
- mesopic adaptation coefficient
- Reference:
- luxpy.spectrum.spd_to_xyz(spds, cieobs='1931_2', K=None, relative=True, rfl=None, out=None, cie_std_dev_obs=None, rounding=None, matmul=True, interpolate_to='spd', interp_settings={'cmf': {'etype': 'linear', 'fill_value': None, 'itype': 'linear', 'negative_values_allowed': False}, 'general': {'choose_most_efficient_interpolator': False, 'extrap_log': False, 'force_scipy_interpolator': False, 'interp_log': False, 'scipy_interpolator': 'interp1d', 'sprague_allowed': False, 'sprague_method': 'spargue_cie224_2017'}, 'none': {'etype': 'linear', 'fill_value': None, 'itype': 'linear', 'negative_values_allowed': False}, 'rfl': {'etype': 'linear', 'fill_value': None, 'itype': 'cubic', 'negative_values_allowed': False}, 'spd': {'etype': 'linear', 'fill_value': None, 'itype': 'cubic', 'negative_values_allowed': False}}, kind=None, extrap_kind=None, extrap_values=None, negative_values_allowed=None, sprague_allowed=None, sprague_method='sprague_cie224_2017', force_scipy_interpolator=None, scipy_interpolator=None, choose_most_efficient_interpolator=None, verbosity=0)[source]
Calculate tristimulus values from spectral data.
- Args:
- spds:
- ndarray with (N+1,number of wavelengths)-dimensional spectral data (0-row: wavelengths, remaining n rows: data)
- cieobs:
- luxpy._CIEOBS or str or ndarray, optionalDetermines the color matching functions to be used in thecalculation of XYZ.If ndarray: color matching functions (3+1,number of wavelengths). (0-row: spectral wavelengths)
- K:
- None, optionale.g. K = 683 lm/W for ‘1931_2’ (relative == False)or K = 100/sum(spd*dl) (relative == True)
- relative:
- True, optionalIf False: use K, else calculate K = 100 ./ Yw
- rfl:
- None, optionalIf not None, must be ndarray with (M+1,number of wavelengths)-dimensional spectral reflectance data (0-row: wavelengths, remaining n rows: data)
- out:
- None or 1 or 2, optionalDetermines 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.
- matmul:
- True, optionalIf True: use matrix multiplication and broadcasting to calculate tristimulus values, else use sumproduct with loop over cmfs.
- rounding:
- None, optionalif not None: round xyz output to this many decimals. (see math.round for more options).
- interpolate_to:
- ‘spd’, optionalInterpolate other spectral data to the wavelengths of specified spectral type.Options: ‘spd’ or ‘cmf’
- interp_settings:
- Nested Dict with interpolation settings per spectral type [‘spd’,’cmf’,’rfl’,’none’].Keys per spectrum type:- ‘itype’: strsupported options for str: ‘linear’, ‘quadratic’, ‘cubic’- ‘etype’: strsupported options:+ ‘extrapolate’+ ‘zeros’: out-of-bounds values are filled with zeros+ ‘const’: out-of-bounds values are filled with nearest value+ ‘fill_value’: value of tuple (2,) of values is used to fill out-of-bounds values- ‘fill_value’: str or float or int or tupple, optionalIf ext == ‘fill_value’: use fill_value to set lower- and upper-out-of-bounds values when extrapolating(‘extrapolate’ when etype requires extrapolation)
- negative_values_allowed:
- None, optionalIf False: after interpolation/extrapolation, any negative values are clipped to zero.If None: use the value in the interp_settings dictionary.
- force_scipy_interpolator:
- None, optionalIf False: numpy.interp function is used for linear interpolation when no or linear extrapolation is used/required (fast!).If None: use the value in the interp_settings dictionary.
- scipy_interpolator:
- None, optionaloptions: ‘InterpolatedUnivariateSpline’, ‘interp1d’If None: use the value in the interp_settings dictionary.
- choose_most_efficient_interpolator:
- None, optionalIf True: Choose most efficient interpolatorIf None: use the value in the interp_settings dictionary.
- 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) valuesNote 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 setof values of the first dimension. The following valuesalong this dimension are the sample (rfl) xyz values.If out == 2: (ndarray of xyz, ndarray of xyzw) valueswith xyz.shape = (rfl.shape[0],data.shape[0],3)and with xyzw.shape = (data.shape[0],3)
- luxpy.spectrum.spd_to_xyz_barebones(spd, cmf, K=1.0, relative=True, rfl=None, wl=None, matmul=True)[source]
Calculate tristimulus values from equal wavelength spectral data.
- Args:
- spd:
- ndarray with (N+1,number of wavelengths)-dimensional spectral data (0-row: wavelengths, remaining n rows: data)
- cmf:
- color matching functions (3+1,number of wavelengths). (0-row: spectral wavelengths)
- K:
- 1.0, optionale.g. K = 683 lm/W for ‘1931_2’ (relative == False)or K = 100/sum(spd*dl) (relative == True)
- relative:
- False, optionalIf False: use K, else calculate K = 100 ./ Yw
- rfl:
- None, optionalIf not None, must be ndarray with (M+1,number of wavelengths)-dimensional spectral reflectance data (0-row: wavelengths, remaining n rows: data)
- wl:
- None, optionalIf None: first row of all spectral data are the wavelengths, else wl is ndarray with corresponding wavelengths of shape (number of wavelength,).
- matmul:
- True, optionalIf True: use matrix multiplication and broadcasting to calculate tristimulus values, else use sumproduct with loop over cmfs.
- Returns:
- XYZ, XYZw:
- ndarrays with tristimulus values (X,Y,Z are on last dimension)- XYZ: tristim. values of all rfls (if rfl is None: same as XYZw) [M,N,3]- XYZw: tristim. values of all white points (purely spds are used) [N,3]
- luxpy.spectrum.spd_to_ler(data, cieobs='1931_2', K=None, interp_settings=None, kind=None, extrap_kind=None, extrap_values=None)[source]
Calculates Luminous efficacy of radiation (LER) from spectral data.
- Args:
- data:
- ndarray 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.
- cieobs:
- luxpy._CIEOBS, optionalDetermines the color matching function set used in thecalculation of LER. For cieobs = ‘1931_2’ the ybar CMF curve equalsthe CIE 1924 Vlambda curve.
- K:
- None, optionale.g. K = 683 lm/W for ‘1931_2’
- Returns:
- ler:
- ndarray of LER values.
- References:
- luxpy.spectrum.spd_to_power(data, ptype='ru', cieobs='1931_2', K=None, interp_settings=None, kind=None, extrap_kind=None, extrap_values=None)[source]
Calculate power of spectral data in radiometric, photometric or quantal energy units.
- Args:
- data:
- ndarray with spectral data
- ptype:
- ‘ru’ or str, optionalstr: - ‘ru’: in radiometric units- ‘pu’: in photometric units- ‘pusa’: in photometric units with Km correctedto standard air (cfr. CIE TN003-2015)- ‘qu’: in quantal energy units
- cieobs:
- _CIEOBS or str or ndarray, optionalType of cmf set to use for photometric units.
- K:
- None, optionalLuminous efficacy of radiation, must be supplied if cieobs is an array.
- Returns:
- returns:
- ndarray with normalized spectral data (SI units)
- luxpy.spectrum.detect_peakwl(spd, n=1, verbosity=1, **kwargs)[source]
Detect primary peak wavelengths and fwhm in spectrum spd.
- Args:
- spd:
- ndarray with spectral data (2xN).First row should be wavelengths.
- n:
- 1, optionalThe number of peaks to try to detect in spd.
- verbosity:
- Make a plot of the detected peaks, their fwhm, etc.
- kwargs:
- Additional input arguments for scipy.signal.find_peaks.
- Returns:
- prop:
- list of dictionaries with keys:- ‘peaks_idx’ : index of detected peaks- ‘peaks’ : peak wavelength values (nm)- ‘heights’ : height of peaks- ‘fwhms’ : full-width-half-maxima of peaks- ‘fwhms_mid’ : wavelength at the middle of the fwhm-range of the peaks (if this is different from the values in ‘peaks’, then their is some non-symmetry in the peaks)- ‘fwhms_mid_heights’ : height at the middle of the peak
- luxpy.spectrum.create_spectral_interpolator(S, wl=None, kind=1, ext=0)[source]
Create an interpolator of kind for spectral data S.
- Args:
- S:
- Spectral data arrayRow 0 should contain wavelengths if :wl: is None.
- wl:
- None, optionalWavelengthsIf wl is None: row 0 of S should contain wavelengths.
- kind:
- 1, optionalOrder of spline functions used in interpolator (1<=kind<=5)Interpolator = scipy.interpolate.InterpolatedUnivariateSpline
- Returns:
- interpolators:
- List of interpolator functions for each row in S (minus wl-row if present).
- Note:
Nan’s, +infs, -infs will be ignored when generating the interpolators.
- luxpy.spectrum.wls_shift(shfts, log_shft=False, wl=None, S=None, interpolators=None, kind=1, ext=0)[source]
Wavelength-shift array S over shft wavelengths.
- Args:
- shfts:
- array with wavelength shifts.
- log_shft:
- False, optionalIf True: shift in log10 wavelength space.
- wl:
- None, optionalWavelengths to returnIf wl is None: S will be used and row 0 should contain wavelengths.
- S:
- None, optionalSpectral data array.Row 0 should contain wavelengths if :wl: is None.If None: interpolators should be precalculated + wl must contain wavelength array !
- interpolators:
- None, optionalPre-calculated interpolators for the (non-wl) rows in S.If None: will be generated from :S: (which should contain wavelengths on row 0)with specified :kind: using scipy.interpolate.InterpolatedUnivariateSplineIf not None and S is not None: interpolators take precedence
- kind:
- 1, optionalOrder of spline functions used in interpolator (1<=kind<=5)
- Returns:
- wavelength_shifted:
- array with wavelength-shifted S (or interpolators) evaluated at wl.(row 0 contains)
- Note:
Nan’s, +infs, -infs will be ignored when generating the interpolators.
- luxpy.spectrum.spd_to_xyz_legacy(data, relative=True, rfl=None, cieobs='1931_2', K=None, out=None, cie_std_dev_obs=None)[source]
Calculates xyz tristimulus values from spectral data.
- Args:
- data:
- ndarray 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, optionalCalculate 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, optionalDetermines the color matching functions to be used in thecalculation of XYZ.
- K:
- None, optionale.g. K = 683 lm/W for ‘1931_2’ (relative == False)or K = 100/sum(spd*dl) (relative == True)
- out:
- None or 1 or 2, optionalDetermines 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) valuesNote 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 setof values of the first dimension. The following valuesalong this dimension are the sample (rfl) xyz values.If out == 2: (ndarray of xyz, ndarray of xyzw) valueswith xyz.shape = (rfl.shape[0],data.shape[0],3)and with xyzw.shape = (data.shape[0],3)
- References:
- luxpy.spectrum.cri_ref(ccts, wl3=None, ref_type='ciera', mix_range=None, cieobs=None, cieobs_Y_normalization=None, norm_type=None, norm_f=None, force_daylight_below4000K=False, n=None, daylight_locus=None, round_daylightphase_Mi_to_cie_recommended=False, interp_settings=None)[source]
Calculates a reference illuminant spectrum based on cct for color rendering index calculations .
- Args:
- ccts:
- list of int/floats or ndarray with ccts.
- wl3:
- None, optionalNew wavelength range for interpolation.Defaults to wavelengths specified by luxpy._WL3.
- ref_type:
- str or list[str], optionalSpecifies the type of reference spectrum to be calculated.Defaults to luxpy._CRI_REF_TYPE.If :ref_type: is list of strings, then for each cct in :ccts:a different reference illuminant can be specified.If :ref_type: == ‘spd’, then :ccts: is assumed to be an ndarrayof reference illuminant spectra.
- mix_range:
- None or ndarray, optionalDetermines the cct range between which the reference illuminant isa weigthed mean of a Planckian and Daylight Phase spectrum.Weighthing is done as described in IES TM30:SPDreference = (Te-T)/(Te-Tb)*Planckian+(T-Tb)/(Te-Tb)*daylightwith Tb and Te are resp. the starting and end CCTs of themixing range and whereby the Planckian and Daylight SPDshave been normalized for equal luminous flux.If None: use the default specified for :ref_type:.Can be a ndarray with shape[0] > 1, in which different mixingranges will be used for cct in :ccts:.
- cieobs:
- None, optionalRequired when calculating daylightphase (adjust locus parameters to cieobs)If None: value in _CRI_REF_TYPES will be used (with None here corresponding to _CIEOBS).
- cieobs_Y_normalization:
- None, optionalRequired for the normalization of the Planckian and Daylight SPDswhen calculating a ‘mixed’ reference illuminant.If None: value in _CRI_REF_TYPES will be used,with None here resulting in the use of the value as specified in :cieobs:
- 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 correctedto standard air, cfr. CIE TN003-2015)- ‘qu’: to :norm_f: quantal energy units
- norm_f:
- 1, optionalNormalization factor that determines the size of normalizationfor ‘max’ and ‘area’or which wavelength is normalized to 1 for ‘lambda’ option.
- force_daylight_below4000K:
- False or True, optionalDaylight locus approximation is not defined below 4000 K,but by setting this to True, the calculation can be forced tocalculate it anyway.
- n:
- None, optionalRefractive index (for use in calculation of blackbody radiators).If None: use the one stored in _BB[‘n’]
- daylight_locus:
- None, optionaldict with xD(T) and yD(xD) parameters to calculate daylight locusfor specified cieobs.If None: use pre-calculated values.If ‘calc’: calculate them on the fly.
- round_daylightphase_Mi_to_cie_recommended:
- False, optionalIf True: Round M1, M2 values to 3 decimals as recommended by CIE (not that TM30 does not do this, which gives slight errors when calculating a daylight phase (equivalent of around 0.75 K for 6500 K illuminant))Rounding causes larger errors from target CCT! Therefore, the default is set to False!Note that neither CIE224-2017 or IES TM30 rounds M1 and M2 to 3 decimals!
- Returns:
- returns:
- ndarray with reference illuminant spectra.(:returns:[0] contains wavelengths)
- Note:
Future versions will have the ability to take a dict as input for ref_type. This way other reference illuminants can be specified than the ones in _CRI_REF_TYPES.
- luxpy.spectrum.blackbody(cct, wl3=None, n=None, relative=True)[source]
Calculate blackbody radiator spectrum for correlated color temperature (cct).
- Args:
- cct:
- int or float(for list of cct values, use cri_ref() with ref_type = ‘BB’)
- wl3:
- None, optionalNew wavelength range for interpolation.Defaults to wavelengths specified by luxpy._WL3.
- n:
- None, optionalRefractive index.If None: use the one stored in _BB[‘n’]
- relative:
- False, optionalTrue: return relative spectrum normalized to 560 nmFalse: return absolute spectral radiance (Planck’s law; W/(sr.m².nm))
- Returns:
- returns:
- ndarray with blackbody radiator spectrum(:returns:[0] contains wavelengths)
- References:
- luxpy.spectrum.spd_to_indoor(spd, interp_settings=None)[source]
Convert spd to indoor variant by multiplying it with the CIE spectral transmission for glass.
- luxpy.spectrum.daylightlocus(cct, force_daylight_below4000K=False, cieobs=None, daylight_locus=None, use_published_daylightlocus_coeffs_when_cieobs_is_1931_2=True, interp_settings=None)[source]
Calculates daylight chromaticity (xD,yD) from correlated color temperature (cct).
- Args:
- cct:
- int or float or list of int/floats or ndarray
- force_daylight_below4000K:
- False or True, optionalDaylight locus approximation is not defined below 4000 K,but by setting this to True, the calculation can be forced tocalculate it anyway.
- cieobs:
- CMF set corresponding to xD, yD output.If None: use default CIE15-20xx locus for ‘1931_2’Else: use the locus specified in :daylight_locus:
- daylight_locus:
- None, optionaldict with xD(T) and yD(xD) parameters to calculate daylight locusfor specified cieobs.If None: use pre-calculated values.If ‘calc’: calculate them on the fly.
- use_published_daylightlocus_coeffs_when_cieobs_is_1931_2:
- True, optionalUse published coefficients for CIE 1931 2° CMFs (see CIE015 colorimetry)
- Returns:
- (xD, yD):
- (ndarray of x-coordinates, ndarray of y-coordinates)
- References:
- luxpy.spectrum.daylightphase(cct, wl3=None, nominal_cct=False, force_daylight_below4000K=False, verbosity=None, n=None, cieobs=None, daylight_locus=None, daylight_Mi_coeffs=None, force_tabulated_xyD_Mi_when_cieobs_is_1931_2=True, round_Mi_to_cie_recommended=False, interp_settings=None)[source]
Calculate daylight phase spectrum for correlated color temperature (cct).
- Args:
- cct:
- int or float(for list of cct values, use cri_ref() with ref_type = ‘DL’)
- wl3:
- None, optionalNew wavelength range for interpolation.Defaults to wavelengths specified by luxpy._WL3.
- nominal_cct:
- False, optionalIf cct is nominal (e.g. when calculating D65): multiply cct firstby 1.4388/1.4380 to account for change in ‘c2’ in definition of Planckian.
- cieobs:
- None or str or ndarray, optionalCMF set to use when calculating coefficients for daylight locus and for M1, M2 weights.If None: use standard coefficients for CIE 1931 2° CMFs (for Si at 10 nm).Else: calculate coefficients following Appendix C of CIE15-2004 and Judd (1964).
- force_daylight_below4000K:
- False or True, optionalDaylight locus approximation is not defined below 4000 K,but by setting this to True, the calculation can be forced tocalculate it anyway.
- verbosity:
- None, optionalIf None: do not print warning when CCT < 4000 K.
- n:
- None, optionalRefractive index (for use in calculation of blackbody radiators).If None: use the one stored in _BB[‘n’]
- daylight_locus:
- None, optionaldict with xD(T) and yD(xD) parameters to calculate daylight locusfor specified cieobs.If None: use pre-calculated values.If ‘calc’: calculate them on the fly.
- daylight_Mi_coeffs:
- None, optionaldict with coefficients for M1 & M2 weights for specified cieobs.If None: use pre-calculated values.If ‘calc’: calculate them on the fly.
- force_tabulated_xyD_Mi_when_cieobs_is_1931_2:
- True, optionalIf cieobs is ‘1931_2’, then use tabulated values for xD, yD and Mi coefficients.
- round_daylightphase_Mi_to_cie_recommended:
- False, optionalIf True: Round M1, M2 values to 3 decimals as recommended by CIE (not that TM30 does not do this, which gives slight errors when calculating a daylight phase (equivalent of around 0.75 K for 6500 K illuminant))Rounding causes larger errors from target CCT! Therefore, the default is set to False!Note that neither CIE224-2017 or IES TM30 rounds M1 and M2 to 3 decimals!
- Returns:
- returns:
- ndarray with daylight phase spectrum(:returns:[0] contains wavelengths)
- References:
- luxpy.spectrum.get_daylightloci_parameters(ccts=None, cieobs=None, wl3=[300, 830, 10], verbosity=0, use_1931_2_published_daylightlocus_coeffs=False, interp_settings=None)[source]
Get parameters for the daylight loci functions xD(1000/CCT) and yD(xD).
- Args:
- ccts:
- None, optionalndarray with CCTs, if None: ccts = np.arange(4000,25000,250)
- cieobs:
- None or list of str or list of ndarrays, optionalCMF sets to determine parameters for.If None: get for all CMFs sets in _CMF (except scoptopic and deviate observer)
- wl3:
- [300,830,10], optionalWavelength range and spacing of daylight phases to be determinedfrom ‘1931_2’. The default setting results in parameters very closeto that in CIE15-2004/2018.
- use_1931_2_published_daylightlocus_coeffs:
- False, optionalUse published coefficients for CIE 1931 2° CMFs (see CIE015 colorimetry)
- verbosity:
- 0, optionalprint parameters and make plots.
- Returns:
- dayloci:
- dict with parameters for each cieobsIf cieobs contains ndarrays, then keys in dict will belabeled ‘cmf_0’, ‘cmf_1’, …
- luxpy.spectrum.get_daylightphase_Mi_coeffs(cieobs=None, wl3=None, S012_daylightphase=None, use_1931_2_published_Mcoeffs=False, interp_settings=None)[source]
Get coefficients of Mi weights of daylight phase for specific cieobs
- Args:
- cieobs:
- None or str or ndarray or list of str or list of ndarrays, optionalCMF set to get coefficients for.If None: get coeffs for all CMFs in _CMF
- wl3:
- None, optionalWavelength range to interpolate S012_daylightphase to.
- S012_daylightphase:
- None, optionalDaylight phase component functions.If None: use _S012_DAYLIGHTPHASE
- use_1931_2_published_Mcoeffs:
- False, optionalUse published coefficients of CIE 1931 2° CMFs (see CIE015 colorimetry), even when cieobs is not ‘1931_2’!
- Returns:
- Mcoeffs:
- Dictionary with i,j,k,i1,j1,k1,i2,j2,k2 for each cieobs in :cieobs:If cieobs contains ndarrays, then keys in dict will belabeled ‘cmf_0’, ‘cmf_1’, …
- luxpy.spectrum.read_spdx(spdx)[source]
Read xml file or convert xml string with spdx data to dictionary.
- Args:
- spdx:
- xml string or file with spdx data.
- Returns:
- spdx_dict:
- spdx data in a dictionary.
- luxpy.spectrum.write_spdx(spdx_dict, filename=None)[source]
Convert spdx dictionary to xml string (and write to .spdx file).
- Args:
- spdx_dict:
- dictionary with spdx keys (see _SPDX for keys).
- filename:
- None, optionalstring with filename to write xml data to.
- Returns:
- spdx_xml:
- string with xml data in spdx dictionary.
SPD class
- py:
SPD.py
- namespace:
luxpy
- class luxpy.spectrum.SPD.SPD(spd=None, wl=None, ax0iswl=True, dtype='spd', wl_new=None, interp_method='auto', negative_values_allowed=False, extrap_values='ext', norm_type=None, norm_f=1, header=None, sep=',')[source]
- read_csv_(file, header=None, sep=',')[source]
Reads spectral data from file.
- Args:
- file:
- filename
- header:
- None or ‘infer’, optionalIf ‘infer’: headers will be inferred from file itself.If None: no headers are expected from file.
- sep:
- ‘,’, optionalColumn separator.
- Returns:
- returns:
- ndarray with spectral data (first row are wavelengths)
- Note:
Spectral data in file should be organized in columns with the first column containing the wavelengths.
- plot(ylabel='Spectrum', wavelength_bar=True, *args, **kwargs)[source]
Make a plot of the spectral data in SPD instance.
- Returns:
- returns:
- handle to current axes.
- getwld_()[source]
Get wavelength spacing of SPD instance.
- Returns:
- returns:
- float: for equal wavelength spacingsndarray (.shape = (n,)): for unequal wavelength spacings
- normalize(norm_type=None, norm_f=1, cieobs='1931_2', K=None, interp_settings=None)[source]
Normalize spectral power distributions in SPD instance.
- Args:
- 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 correctedto standard air, cfr. CIE TN003-2015)- ‘qu’: to :norm_f: quantal energy units
- norm_f:
- 1, optionalDetermines size of normalization for ‘max’ and ‘area’ or which wavelength is normalized to 1 for ‘lambda’ option.
- cieobs:
- _CIEOBS or str, optionalType of cmf set to use for normalization using photometric units (norm_type == ‘pu’)
- cie_interp(wl_new, kind='auto', sprague_allowed=False, sprague_method='sprague_cie224_2017', negative_values_allowed=False, extrap_values='ext', extrap_kind='linear', extrap_log=False)[source]
Interpolate / extrapolate spectral data following standard CIE15-2018.
The interpolation type depends on the spectrum type defined in :kind:.- Args:
- wl_new:
- ndarray with new wavelengths
- kind:
- ‘auto’, optionalIf :kind: is None, return original data.If :kind: is a spectrum type, the correctinterpolation type if automatically chosen.(The use of the slow(er) ‘sprague5’ can be toggled on using :sprague_allowed:).If kind = ‘auto’: use self.dtypeOr :kind: can be any interpolation type supported byluxpy.math.interp1or can be ‘sprague’ (uses luxpy.math.interp1_sprague5) or ‘sprague_cie224_2017’ (uses luxpy.math.interp1_sprague_cie224_2017).
- sprague_allowed:
- None, optionalIf None: the value from interp_settings is used.If True: When kind is a spectral data type that corresponds to ‘cubic’ interpolation,then a cubic spline interpolation will be used in case ofunequal wavelength spacings, otherwise a 5th order Sprague or Sprague as defined in CIE224-2017 will be used.If False: always use ‘cubic’, don’t use ‘sprague5’ or ‘sprague_cie224_2017’.This is the default, as differences are minimal anduse of the ‘sprague’ functions is a lot slower (‘sprague5’ = slowest )!
- sprague_method:
- ‘sprague_cie224_2017’, optionalSpecific sprague method used for interpolation. (Only for equal spacings, ‘sprague_cie224_2017’ also on for 5 nm -> 1nm)- options: ‘sprague5’ (use luxpy.math.interp1_sprague5), ‘sprague_cie224_2017’ (use luxpy.interp1_sprague_cie224_2017)
- negative_values_allowed:
- False, optionalIf False: negative values are clipped to zero
- extrap_values:
- ‘ext’, optionalIf ‘ext’: extrapolate using ‘linear’ (‘cie167:2005’ r), ‘quadratic’ (‘cie15:2018’)‘nearest’ (‘cie15:2004’) recommended or other (e.g. ‘cubic’) methods.If None: use CIE15:2004 recommended ‘nearest value’ approach when extrapolating.If float or list or ndarray, use those values to fill extrapolated value(s).
- extrap_kind:
- ‘linear’, optionalExtrapolation method used when :extrap_values: is set to ‘ext’.Options: ‘linear’ (‘cie167:2005’), ‘quadratic’ (‘cie15:2018’),‘nearest’ (‘cie15:2004’), ‘cubic’CIE15:2018 states that based on a 2017 paper by Wang that ‘quadratic’ is ‘better’.However, no significant difference was found between ‘quadratic’ and ‘linear’ methods.Also see note 1 below, for why the CIE67:2005 recommended ‘linear’ extrapolationis set as the default.
- extrap_log:
- False, optionalIf True: extrap the log of the spectral values(not CIE recommended but in most cases seems to give amore realistic estimate, but can sometimes seriously fail,especially for the ‘quadratic’ extrapolation case (see note 1)!!!)
- Returns:
- returns:
- ndarray of interpolated spectral data.(.shape = (number of spectra+1, number of wavelength in wl_new))
- Notes:
- 1. Type of extrapolation: ‘quadratic’ vs ‘linear’; impact of extrapolating log spectral values:Using a ‘linear’ or ‘quadratic’ extrapolation, as mentioned inCIE167:2005 and CIE15:2018, resp., can lead to extreme large valueswhen setting :extrap_log: (not CIE recommended) to True.A quick test with the IES TM30 spectra (400 nm - 700 nm, 5 nm spacing)shows that ‘linear’ is better than ‘quadratic’ in terms ofmean, median and max DEu’v’ with the original spectra (380 nm - 780 nm, 5 nm spacing).This conferms the recommendation from CIE167:2005 to use ‘linear’ extrapolation.Setting :extrap_log: to True reduces the median, but inflates the mean due to someextremely large DEu’v’ values. However, the increase in mean and max DEu’v’ is muchlarger for the ‘quadratic’ case, suggesting that ‘linear’ extrapolationis likely a more suitable recommendation. When using a 1 nm spacing‘linear’ is more similar to ‘quadratic’ when :extrap_log: is False, otherwise ‘linear’remains the ‘best’. Hence the choice to use the CIE167:2005 recommended linear extrapolation as default!
- to_xyz(relative=True, rfl=None, cieobs='1931_2', out=None)[source]
Calculates xyz tristimulus values from spectral data and return as instance of XYZ.
- Args:
- relative:
- True or False, optionalCalculate relative XYZ (Yw = 100) or absolute XYZ (Y = Luminance)
- rfl:
- ndarray with spectral reflectance functions.Will be interpolated if wavelengths don’t match those of :data:
- cieobs:
- luxpy._CIEOBS, optionalDetermines the color matching functions to be used in the calculation of XYZ.
- out:
- None or 1 or 2, optionalDetermines number and shape of output. (see :returns:)
- Returns:
- returns:
- luxpy.XYZ instance with ndarray .value field: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) valuesNote 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 firstset of values of the first dimension.The following values along this dimension are thesample (rfl) xyz values.If out == 2: (ndarray of xyz, ndarray of xyzw) valueswith xyz.shape = (rfl.shape[0],data.shape[0],3)and with xyzw.shape = (data.shape[0],3)
- References: