Source code for xopto.materials.ri.sucrose

# -*- 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 ##################################

import os.path
import warnings

import numpy as np
from .base import RefractiveIndex
from xopto import DATA_PATH
from xopto.materials.ri.util.model import Sellmeier_3


[docs]class Naglic(RefractiveIndex): material = 'sucrose' def __init__(self, t: float = 293.15): ''' Refractive index of sucrose as given/used in: "P. Naglič, Y. Zelinskyi, B. Likar, and B. Miran. Determination of refractive index, size, and solid content of monodisperse polystyrene microsphere suspensions for the characterization of optical phantoms, BOE, Vol. 11, Issue 4, 1901-18 (2020)" Parameters ---------- t: float Default temperature (K) of the medium. Defaults to 293.15 K (20 C). ''' super().__init__(t=t, trange=(293.15, 298.15), wrange=(400e-9, 800e-9)) filename_20c = os.path.join( DATA_PATH, 'materials', 'ri', 'sucrose_20c_sellmeier_ri.npz') filename_25c = os.path.join( DATA_PATH, 'materials', 'ri', 'sucrose_25c_sellmeier_ri.npz') wavelength_pp = lambda wavelength: wavelength*1e6 data_20c = np.load(filename_20c) self._brix_20c = data_20c['brix'] self._ri_sellmeier_20c = \ [Sellmeier_3(item, wavelength_pp) for item in data_20c['coeffs']] data_25c = np.load(filename_25c) self._brix_25c = data_25c['brix'] self._ri_sellmeier_25c = \ [Sellmeier_3(item, wavelength_pp) for item in data_25c['coeffs']] self._brix_range = (0.0, 60.0)
[docs] def is_valid_brix(self, brix: float or np.ndarray) -> bool: ''' Check if the Brix value is within the valid range. Parameters ---------- brix: float or np.ndarray Degree Brix value (1 Brix equals 1 g of sucrose in 100 g of solution). Defaults to 0 Brix, i.e. pure water. Returns ------- valid: bool True if the Brix value is within the valid range. ''' if self._brix_range is not None: brix = np.asarray(brix) res = np.logical_and(brix >= self._brix_range[0], brix <= self._brix_range[1]) return np.all(res) return True
[docs] def check_brix(self, brix: float or np.ndarray): ''' Check if the Brix value is within valid range and display a warning if not. Parameters ---------- brix: float or np.ndarray Degree Brix value (1 Brix equals 1 g of sucrose in 100 g of solution). Defaults to 0 Brix, i.e. pure water. ''' if not self.is_valid_brix(brix): warnings.warn( 'Brix value out of valid range '\ '[{:.1f}, {:.1f}] Brix!'.format( self._brix_range[0], self._brix_range[1]) )
def __call__(self, wavelength: float or np.ndarray, brix: float = 0.0, temperature: float or None = None) -> float or np.ndarray: ''' Calculate the refractive index of the medium. Parameters ---------- wavelength: float or np.ndarray Wavelength of light (m). Valid range is approx. from 400 to 800 nm. brix: float Degree Brix value (1 Brix equals 1 g of sucrose in 100 g of solution). Defaults to 0 Brix, i.e. pure water. temperature: float or None Temperature (K) of the medium. Valid range is from 293 K (20 C) to 298 K (25 C). Defaults to 293.15 K. Returns ------- ri: float or np.ndarray Refractive index at the given wavelength(s) and Brix value. ''' if temperature is None: temperature = self.t self.check_temperature(temperature) self.check_brix(brix) brix = brix/100.0 # using relative Brix values internally w = np.asarray(wavelength, dtype=np.float64) self.check_wavelengths(w) ri_20c = [ri(w) for ri in self._ri_sellmeier_20c] ri_25c = [ri(w) for ri in self._ri_sellmeier_25c] # model uses C t = temperature - 273.15 p_20c = np.polyfit(self._brix_20c, ri_20c, deg=4) p_25c = np.polyfit(self._brix_25c, ri_25c, deg=4) ri_20c = np.polyval(p_20c, brix) ri_25c = np.polyval(p_25c, brix) result = (ri_25c - ri_20c)/(25.0 - 20.0) * (t - 20.0) + ri_20c if isinstance(wavelength, float): result = float(result) return result
# Global instances for immediate use. naglic = Naglic() default = Naglic()