Source code for pyrism.core.auxiliary

# -*- coding: utf-8 -*-
from __future__ import division

import numpy as np


class Memorize(dict):
    def __getattr__(self, name):
        try:
            return self[name]
        except KeyError:
            raise AttributeError(name)

    __setattr__ = dict.__setitem__
    __delattr__ = dict.__delitem__

    def __repr__(self):
        if self.keys():
            m = max(map(len, list(self.keys()))) + 1
            return '\n'.join([k.rjust(m) + ': ' + repr(v)
                              for k, v in sorted(self.items())])
        else:
            return self.__class__.__name__ + "()"

    def __dir__(self):
        return list(self.keys())


[docs]class ReflectanceResult(dict): """ Represents the reflectance result. Returns ------- All returns are attributes! BSC.ref, BSC.refdB, BSC.ms.ref, BSC.ms.refdB : array_like Radar Backscatter values (polarization-independent). BSC.VV, BSC.HH, BSC.VVdB, BSC.HHdB, BSC.ms.VV, BSC.ms.HH, BSC.ms.VVdB, BSC.ms.HHdB : array_like Radar Backscatter values (polarization-dependent). BRDF.ref, BRDF.refdB, BRDF.ms.ref, BRDF.ms.refdB : array_like BRDF reflectance values (polarization-independent). BRDF.VV, BRDF.HH, BRDF.VVdB, BRDF.HHdB, BSC.ms.VV, BRDF.ms.HH, BRDF.ms.VVdB, BRDF.ms.HHdB : array_like BRDF reflectance values (polarization-dependent). BRF.ref, BRF.refdB, BRF.ms.ref, BRF.ms.refdB : array_like BRF reflectance values (polarization-independent). BRF.VV, BRF.HH, BRF.VVdB, BRF.HHdB, BSC.ms.VV, BRF.ms.HH, BRF.ms.VVdB, BRF.ms.HHdB : array_like BRF reflectance values (polarization-dependent). Notes ----- There may be additional attributes not listed above depending of the specific solver. Since this class is essentially a subclass of dict with attribute accessors, one can see which attributes are available using the `keys()` method. adar Backscatter values of multi scattering contribution of surface and volume The attribute 'ms' is the multi scattering contribution. This is only available if it is calculated. For detailed parametrisation one can use BSC.ms.sms or BSC.ms.smv for the multiple scattering contribution of surface or volume, respectively. """ def __getattr__(self, name): try: return self[name] except KeyError: raise AttributeError(name) __setattr__ = dict.__setitem__ __delattr__ = dict.__delitem__ def __repr__(self): if self.keys(): m = max(map(len, list(self.keys()))) + 1 return '\n'.join([k.rjust(m) + ': ' + repr(v) for k, v in sorted(self.items())]) else: return self.__class__.__name__ + "()" def __dir__(self): return list(self.keys())
[docs]class SailResult(dict): """ Represents the sail result. Returns ------- All returns are attributes! SDR.ref, SDR.refdB : array_like Directional reflectance factor. BHR.ref, BHR.refdB : array_like Bi-hemispherical reflectance factor. DHR.ref, DHR.refdB : array_like Directional-Hemispherical reflectance factor. HDR.ref, HDR.refdB : array_like Hemispherical-Directional reflectance factor. Note ---- All returns have in addition the attributes `L8.Bx` and `ASTER.Bx`. L8 is the Landsat 8 average reflectance values for Bx band (B2 until B7). `ASTER` is the ASTER average reflectance for Bx band (B1 until B9). Notes ----- There may be additional attributes not listed above depending of the specific solver. Since this class is essentially a subclass of dict with attribute accessors, one can see which attributes are available using the `keys()` method. adar Backscatter values of multi scattering contribution of surface and volume The attribute 'ms' is the multi scattering contribution. This is only available if it is calculated. For detailed parametrisation one can use BSC.ms.sms or BSC.ms.smv for the multiple scattering contribution of surface or volume, respectively. """ def __getattr__(self, name): try: return self[name] except KeyError: raise AttributeError(name) __setattr__ = dict.__setitem__ __delattr__ = dict.__delitem__ def __repr__(self): if self.keys(): m = max(map(len, list(self.keys()))) + 1 return '\n'.join([k.rjust(m) + ': ' + repr(v) for k, v in sorted(self.items())]) else: return self.__class__.__name__ + "()" def __dir__(self): return list(self.keys())
[docs]class EmissivityResult(dict): """ Represents the reflectance result. Returns ------- All returns are attributes! EMS.ref, EMS.refdB : array_like Emission values (polarization-independent). EMS.VV, EMS.HH, EMS.VVdB, EMS.HHdB : array_like Emission values (polarization-dependent). EMN.VV, EMN.HH, EMN.VVdB, EMN.HHdB : array_like Due to the several conversions in ROM this output format delivers the emission values divided through the sensing geometry times 4pi. This attribute is only for the I2EM.Emissivity class. If you want to calculate the emissivity of a scene, use this output from I2EM.Emissivity. Notes ----- There may be additional attributes not listed above depending of the specific solver. Since this class is essentially a subclass of dict with attribute accessors, one can see which attributes are available using the `keys()` method. adar Backscatter values of multi scattering contribution of surface and volume The attribute 'ms' is the multi scattering contribution. This is only available if it is calculated. For detailed parametrisation one can use BSC.ms.sms or BSC.ms.smv for the multiple scattering contribution of surface or volume, respectively. """ def __getattr__(self, name): try: return self[name] except KeyError: raise AttributeError(name) __setattr__ = dict.__setitem__ __delattr__ = dict.__delitem__ def __repr__(self): if self.keys(): m = max(map(len, list(self.keys()))) + 1 return '\n'.join([k.rjust(m) + ': ' + repr(v) for k, v in sorted(self.items())]) else: return self.__class__.__name__ + "()" def __dir__(self): return list(self.keys())
def rad(angle): """ Convert degrees to radians. Parameter: ---------- angle : (int, float or array_like) Angle in [DEG]. """ return angle * np.pi / 180.0 def deg(angle): """ Convert radians to degree. Parameter: ---------- angle : (int, float or array_like) Angle in [RAD]. """ return angle * 180. / np.pi def sec(angle): """ Secant of an angle. """ return 1 / np.cos(angle) def cot(x): """ Cotangent of an angle. """ return 1 / np.tan(x) def dB(x): """ Convert a linear value to dB. """ with np.errstate(invalid='ignore'): return 10 * np.log10(x) def linear(x): """ Convert a dB value in linear. """ return 10 ** (x / 10) def BRDF(BSC, iza, vza, angle_unit='RAD'): """ Convert a Radar Backscatter Coefficient (BSC) into a BRDF. Note ----- Hot spot direction is vza == iza and raa = 0.0 Parameters ---------- BSC : int, float or array_like Radar Backscatter Coefficient (sigma 0). iza : int, float or array_like Sun or incidence zenith angle. vza : int, float or array_like View or scattering zenith angle. angle_unit : {'DEG', 'RAD'} (default = 'RAD'), optional * 'DEG': All input angles (iza, vza, raa) are in [DEG]. * 'RAD': All input angles (iza, vza, raa) are in [RAD]. Returns ------- BRDF value : int, float or array_like """ if angle_unit == 'RAD': return BSC / (np.cos(iza) * np.cos(vza) * (4 * np.pi)) elif angle_unit == 'DEG': return BSC / (np.cos(rad(iza)) * np.cos(rad(vza)) * (4 * np.pi)) else: raise ValueError("angle_unit must be 'RAD' or 'DEG'") def BRF(BRDF): """ Convert a BRDF into a BRF. Note ----- Hot spot direction is vza == iza and raa = 0.0 Parameters ---------- BRDF : int, float or array_like BRDF value. Returns ------- BRF value : int, float or array_like """ return np.pi * BRDF def BSC(BRDF, iza, vza, angle_unit='RAD'): """ Convert a BRDF in to a Radar Backscatter Coefficient (BSC). Note ----- Hot spot direction is vza == iza and raa = 0.0 Parameters ---------- BSC : int, float or array_like Radar Backscatter Coefficient (sigma 0). iza : int, float or array_like Sun or incidence zenith angle. vza : int, float or array_like View or scattering zenith angle. angle_unit : {'DEG', 'RAD'} (default = 'RAD'), optional * 'DEG': All input angles (iza, vza, raa) are in [DEG]. * 'RAD': All input angles (iza, vza, raa) are in [RAD]. Returns ------- BRDF value : int, float or array_like """ if angle_unit == 'RAD': return BRDF * np.cos(iza) * np.cos(vza) * 4 * np.pi elif angle_unit == 'DEG': return BRDF * np.cos(rad(iza)) * np.cos(rad(vza)) * (4 * np.pi) else: raise ValueError("angle_unit must be 'RAD' or 'DEG'") def align_all(data, constant_values='default'): max_len = max_length(data) if constant_values == 'default': return np.asarray( [np.pad(item, (0, max_len - len(item)), 'constant', constant_values=item[-1]) for item in data]) else: return np.asarray( [np.pad(item, (0, max_len - len(item)), 'constant', constant_values=constant_values) for item in data]) def max_length(data): return np.max([len(item) for item in data]) def asarrays(data): return [np.asarray(item).flatten() for item in data] def load_param(): sensing = Memorize(freq=1.26, iza=35, vza=30, raa=50) # W1 W1 = Memorize(hs=0.3, l=30, S=0.8, C=0.15, mv=0.2, pb=1.7, p0=0.31831, N=1, Cab=20, Cxc=3, Cb=0.4, Cw=0.0005, Cm=0.0085, LAI=1, lza=45, zmax=30, bsp=15, h=15, r=3, hb=1, bspr=5, mg=0.19, T0=16, a=0.02) W2 = Memorize(hs=0.55, l=28, S=0.8, C=0.15, mv=0.35, pb=1.7, p0=0.31831, N=1.5, Cab=35, Cxc=5, Cb=0.15, Cw=0.003, Cm=0.0055, LAI=4, lza=45, zmax=30, bsp=15, h=15, r=3, hb=1, bspr=5, mg=0.28, T0=20, a=0.02) W3 = Memorize(hs=0.60, l=25, S=0.8, C=0.15, mv=0.45, pb=1.7, p0=0.31831, N=2.2, Cab=47, Cxc=9, Cb=0, Cw=0.005, Cm=0.002, LAI=7, lza=45, zmax=30, bsp=15, h=15, r=3, hb=1, bspr=5, mg=0.51, T0=24, a=0.02) return Memorize(sensing=sensing, W1=W1, W2=W2, W3=W3)