Source code for xopto.materials.absorption.base

# -*- coding: utf-8 -*-
################################ Begin license #################################
# Copyright (C) Laboratory of Imaging technologies,
#               Faculty of Electrical Engineering,
#               University of Ljubljana.
#
# This file is part of PyXOpto.
#
# PyXOpto is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# PyXOpto is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with PyXOpto. If not, see <https://www.gnu.org/licenses/>.
################################# End license ##################################

from typing import Tuple
import warnings

import numpy as np
from scipy.interpolate import interp1d


DEFAULT_WAVELENGTHS = np.linspace(400e-9, 1000e-9, 601)
''' Default wavelengths for plots. '''

[docs]class Interpolator:
[docs] @classmethod def fromfile(cls, filename: str, *args, **kwargs) -> 'Interpolator': ''' Create an interpolator from a numpy data file. The independent variable (wavelengths) should be stored in the first column, the dependent variable (absorption coefficient) in the second column Parameters ---------- filename: str Source file. args: tuple Positional arguments passed to `:py:func:scipy.interpolate.interp1d`. kwargs: dict Keyword arguments passed to `:py:func:scipy.interpolate.interp1d`. Returns ------- interpolator: Interpolator Interpolator instance. ''' data = np.load(filename) return cls(data[:, 0], data[:, 1], *args, **kwargs)
def __init__(self, wavelength: np.ndarray, absorption: np.ndarray, *args, **kwargs): ''' Prepare an interpolator for the given x and y data. Parameters ---------- wavelength: np.ndarray Wavelengths (m) of light at which the absorption coefficient is defined. absorption: np.ndarray Absorption coefficient (1/m) at the wavelengths of light. Points that will define the interpolation function. args, kwargs: tuple, dict Optional positional and keyword arguments passed to the intep1d function of scipy.interpolate module. ''' self._wavelength = np.array(wavelength) self._wavelength_range = (float(wavelength.min()), float(wavelength.max())) self._absorption = np.array(absorption) self._interpolator = interp1d( self._wavelength, self._absorption, *args, **kwargs) def __call__(self, wavelength: np.ndarray or float) -> np.ndarray or float: ''' Parameters ---------- wavelength: float, np.ndarray The wavelengths of light (m) at which to estimate the absorption coefficient. Returns ------- result: float, np.ndarray The estimated values of the absorption coefficient. ''' res = self._interpolator(wavelength) if isinstance(wavelength, (float, int)): res = float(res) return res
[docs] def is_valid_range(self, wavelength: float or np.ndarray) -> bool: ''' Check the wavelngths of light (m) for valid range. Parameters ---------- wavelength: float, np.ndarray Wavelengths of light to check for valid range. Returns ------- ok: bool Returns True if all the wavelengthsare within the valid range. ''' return not (np.all(wavelength >= self._wavelength_range[0]) and \ np.all(wavelength <= self._wavelength_range[1]))
[docs] def check_range(self, wavelength: float or np.ndarray): ''' Checks if the wavelength of light is within the valid range. Parameters ---------- wavelength: float or np.ndarray Temperature(s) to check. Note ---- Reports a warning if the wavelength of light is not within the valid range. If the wavelength input argument is a numpy array, the call reports a warning if any of the wavelengths are not within the valid range. ''' if not self.is_valid_range(wavelength): warnings.warn( 'Wavelength is out of valid range '\ '[{:.1f}, {:.1f}] K!'.format(*self._wavelength_range) )
def _get_wavelength(self): return self._wavelength wavelength = property(_get_wavelength, None, None, 'Wavelengths of light (m) at which the absorption ' 'coefficient was measured.') def _get_absorption(self): return self._absorption absorption = property(_get_wavelength, None, None, 'Measured values of the absorption coefficient (1/m).')
[docs] def range(self): ''' Return the valid range of wavelengths. Returns ------- range: (float, float) Valid range of wavelengths as a tuple (low, high). ''' return self._range
[docs] def plot(self, wavelength: np.ndarray = None, label=None, show=False): ''' Plots the wavelength dependence of the absorption coefficient. Parameters ---------- wavlength: np.ndarray Wavelengths of light. label: str Plot label. show: bool Show the plot window if True. ''' import matplotlib.pyplot as pp if wavelength is None: wavelength = self.wavelength pp.semilogy(wavelength*1e9, self(wavelength), label=label) pp.xlabel('Wavelength (nm)') pp.ylabel('Absorption coefficient (1/cm)') if show: pp.show()
[docs]class Absorption: def __init__(self, t=293, trange: Tuple[float, float]=None): ''' Base class of material density. Parameters ---------- t: float Default medium temperature. trange: Tuple[float, float] or None Valid temperature range in K as (min, max). ''' self._temperature = float(t) if isinstance(trange, (float, int)): trange = (float(trange), float(trange)) elif trange is not None: trange = (float(trange[0]), float(trange[1])) self._temperature_range = trange
[docs] def is_valid_temperature(self, temperature: float or np.ndarray) -> bool: ''' Checks if the temperature of the medium is within the valid range. Parameters ---------- temperature: float or np.ndarray Temperature to check. Returns ------- valid: bool Returns True if the temperature is within the valid range. If the temperature input argument is a numpy array, the call returns True only if all the temperatures are within the valid range. ''' if self._temperature_range is not None: t = np.asarray(temperature) res = np.logical_and(t >= self._temperature_range[0], t <= self._temperature_range[1]) return np.all(res) return True
[docs] def plot(self, **kwargs): ''' Plot the temperature dependence of the density. Parameters ---------- kwargs: dict Keyword arguments passed to the __call__ method of the instance. ''' import matplotlib.pyplot as pp temperature = np.linspace( self._temperature_range[0], self._temperature_range[1], 100 ) pp.plot(temperature, self(temperature, **kwargs)) pp.xlabel('Temperature (K)') pp.ylabel('Density (kg/m^3)') pp.title('{:s}.{:s}'.format(self.material, self.__class__.__name__)) pp.show()
[docs] def check_temperature(self, t: float or np.ndarray): ''' Checks if the temperature of medium is within the valid range. Parameters ---------- temperature: float or np.ndarray Temperature(s) to check. Note ---- Reports a warning if the temperature of the medium is not within the valid range. If the temperature input argument is a numpy array, the call reports a warning if any of the temperatures are not within the valid range. ''' if not self.is_valid_temperature(t): warnings.warn( 'Temperature is out of valid range '\ '[{:.1f}, {:.1f}] K!'.format(*self._temperature_range) )
def _get_temperature(self) -> float: return self._temperature def _set_temperature(self, t: float): t = float(t) if not self.is_valid_temperature(t): warnings.warn('Default temperature {:.1f} K is out of valid range '\ '[{:.1f}, {:.1f}] K!'.format(*self._temperature_range)) self._temperature = t temperature = property(_get_temperature, _set_temperature, None, 'Default temperature of the material in K.') t = property(_get_temperature, _set_temperature, None, 'Default temperature of the material in K.') def _get_temperature_range(self) -> Tuple[float, float] or None: return self._temperature_range trange = property(_get_temperature_range, None, None, 'Valid temperature range in K.') def __str__(self): return '{:s}.{:s}(t={})'.format( self.material, self.__class__.__name__, self._temperature) def __repr__(self): return '{} # id {}'.format(self.__str__(), id(self))