SMRT

smrt.core package

Submodules

smrt.core.atmosphere module

class AtmosphereBase

Bases: object

__add__(other)

Return a new snowpack made by setting the atmosphere

Parameters:other – the snowpack to add.
__iadd__(other)
__dict__ = mappingproxy({'__module__': 'smrt.core.atmosphere', '__add__': <function AtmosphereBase.__add__>, '__iadd__': <function AtmosphereBase.__iadd__>, '__dict__': <attribute '__dict__' of 'AtmosphereBase' objects>, '__weakref__': <attribute '__weakref__' of 'AtmosphereBase' objects>, '__doc__': None})
__doc__ = None
__module__ = 'smrt.core.atmosphere'
__weakref__

list of weak references to the object (if defined)

smrt.core.error module

Definition of the Exception specific to SMRT.

exception SMRTError

Bases: Exception

Error raised by the model

__doc__ = 'Error raised by the model'
__module__ = 'smrt.core.error'
__weakref__

list of weak references to the object (if defined)

exception SMRTWarning

Bases: Warning

Warning raised by the model

__doc__ = 'Warning raised by the model'
__module__ = 'smrt.core.error'
__weakref__

list of weak references to the object (if defined)

smrt_warn(message)

smrt.core.filelock module

A platform independent file lock that supports the with-statement.

exception Timeout(lock_file)

Bases: TimeoutError

Raised when the lock could not be acquired in timeout seconds.

__init__(lock_file)
lock_file = None

The path of the file lock.

__str__()

Return str(self).

__doc__ = '\n Raised when the lock could not be acquired in *timeout*\n seconds.\n '
__module__ = 'smrt.core.filelock'
__weakref__

list of weak references to the object (if defined)

class BaseFileLock(lock_file, timeout=-1)

Bases: object

Implements the base class of a file lock.

__init__(lock_file, timeout=-1)
lock_file

The path to the lock file.

timeout

You can set a default timeout for the filelock. It will be used as fallback value in the acquire method, if no timeout value (None) is given.

If you want to disable the timeout, set it to a negative value.

A timeout of 0 means, that there is exactly one attempt to acquire the file lock.

New in version 2.0.0.

_acquire()

Platform dependent. If the file lock could be acquired, self._lock_file_fd holds the file descriptor of the lock file.

_release()

Releases the lock and sets self._lock_file_fd to None.

is_locked

True, if the object holds the file lock.

Changed in version 2.0.0: This was previously a method and is now a property.

acquire(timeout=None, poll_intervall=0.05)

Acquires the file lock or fails with a Timeout error.

# You can use this method in the context manager (recommended)
with lock.acquire():
    pass

# Or use an equivalent try-finally construct:
lock.acquire()
try:
    pass
finally:
    lock.release()
Parameters:
  • timeout (float) – The maximum time waited for the file lock. If timeout < 0, there is no timeout and this method will block until the lock could be acquired. If timeout is None, the default timeout is used.
  • poll_intervall (float) – We check once in poll_intervall seconds if we can acquire the file lock.
Raises:

Timeout – if the lock could not be acquired in timeout seconds.

Changed in version 2.0.0: This method returns now a proxy object instead of self, so that it can be used in a with statement without side effects.

release(force=False)

Releases the file lock.

Please note, that the lock is only completly released, if the lock counter is 0.

Also note, that the lock file itself is not automatically deleted.

Parameters:force (bool) – If true, the lock counter is ignored and the lock is released in every case.
__enter__()
__exit__(exc_type, exc_value, traceback)
__del__()
__dict__ = mappingproxy({'__module__': 'smrt.core.filelock', '__doc__': '\n Implements the base class of a file lock.\n ', '__init__': <function BaseFileLock.__init__>, 'lock_file': <property object>, 'timeout': <property object>, '_acquire': <function BaseFileLock._acquire>, '_release': <function BaseFileLock._release>, 'is_locked': <property object>, 'acquire': <function BaseFileLock.acquire>, 'release': <function BaseFileLock.release>, '__enter__': <function BaseFileLock.__enter__>, '__exit__': <function BaseFileLock.__exit__>, '__del__': <function BaseFileLock.__del__>, '__dict__': <attribute '__dict__' of 'BaseFileLock' objects>, '__weakref__': <attribute '__weakref__' of 'BaseFileLock' objects>})
__doc__ = '\n Implements the base class of a file lock.\n '
__module__ = 'smrt.core.filelock'
__weakref__

list of weak references to the object (if defined)

class WindowsFileLock(lock_file, timeout=-1)

Bases: smrt.core.filelock.BaseFileLock

Uses the msvcrt.locking() function to hard lock the lock file on windows systems.

_acquire()

Platform dependent. If the file lock could be acquired, self._lock_file_fd holds the file descriptor of the lock file.

_release()

Releases the lock and sets self._lock_file_fd to None.

__doc__ = '\n Uses the :func:`msvcrt.locking` function to hard lock the lock file on\n windows systems.\n '
__module__ = 'smrt.core.filelock'
class UnixFileLock(lock_file, timeout=-1)

Bases: smrt.core.filelock.BaseFileLock

Uses the fcntl.flock() to hard lock the lock file on unix systems.

_acquire()

Platform dependent. If the file lock could be acquired, self._lock_file_fd holds the file descriptor of the lock file.

_release()

Releases the lock and sets self._lock_file_fd to None.

__doc__ = '\n Uses the :func:`fcntl.flock` to hard lock the lock file on unix systems.\n '
__module__ = 'smrt.core.filelock'
class SoftFileLock(lock_file, timeout=-1)

Bases: smrt.core.filelock.BaseFileLock

Simply watches the existence of the lock file.

_acquire()

Platform dependent. If the file lock could be acquired, self._lock_file_fd holds the file descriptor of the lock file.

__doc__ = '\n Simply watches the existence of the lock file.\n '
__module__ = 'smrt.core.filelock'
_release()

Releases the lock and sets self._lock_file_fd to None.

FileLock

Alias for the lock, which should be used for the current platform. On Windows, this is an alias for WindowsFileLock, on Unix for UnixFileLock and otherwise for SoftFileLock.

alias of smrt.core.filelock.UnixFileLock

smrt.core.fresnel module

fresnel coefficients formulae used in the packages smrt.interface and smrt.substrate.

fresnel_coefficients(eps_1, eps_2, mu1)

compute the reflection in two polarizations (H and V).

Parameters:
  • eps_1 – permittivity of medium 1.
  • eps_2 – permittivity of medium 2.
  • mu1 – cosine zenith angle in medium 1.
Returns:

rv, rh, mu2 the cosine of the angle in medium 2

brewster_angle(eps_1, eps_2)

compute the brewster angle

Parameters:
  • eps_1 – permittivity of medium 1.
  • eps_2 – permittivity of medium 2.
Returns:

angle in radians

fresnel_reflection_matrix(eps_1, eps_2, mu1, npol)

compute the fresnel reflection matrix for/in medium 1 laying above medium 2.

Parameters:
  • npol – number of polarizations to return.
  • eps_1 – permittivity of medium 1.
  • eps_2 – permittivity of medium 2.
  • mu1 – cosine zenith angle in medium 1.
Returns:

a matrix or the diagional depending on return_as_diagonal

fresnel_transmission_matrix(eps_1, eps_2, mu1, npol)

compute the fresnel reflection matrix for/in medium 1 laying above medium 2.

Parameters:
  • npol – number of polarizations to return.
  • eps_1 – permittivity of medium 1.
  • eps_2 – permittivity of medium 2.
  • mu1 – cosine zenith angle in medium 1.
Returns:

a matrix or the diagional depending on return_as_diagonal

smrt.core.globalconstants module

Global constants used throughout the model are defined here and imported as needed. The constants are:

Parameter Description Value
DENSITY_OF_ICE Density of pure ice at 273.15K 916.7 kg m -3
FREEZING_POINT Freezing point of pure water 273.15 K
C_SPEED Speed of light in a vacuum 2.99792458 x 10 8 ms -1
PERMITTIVITY_OF_AIR Relative permittivity of air 1

Usage example:

from smrt.core.globalconstants import DENSITY_OF_ICE

smrt.core.interface module

This module implements the base class for all the substrate models. To create a substrate, it is recommended to use help functions such as make_soil() rather than the class constructor.

make_interface(inst_class_or_modulename, broadcast=True, **kwargs)

return an instance corresponding to the interface model with the provided arguments.

This function imports the interface module if necessary and return an instance of the interface class with the provided arguments in **kwargs.

Parameters:
  • inst_class_or_modulename – a class, and instance or the name of the python module in smrt/interface
  • **kwargs

    all the arguments required by the interface class

class Interface(**kwargs)

Bases: object

Abstract class for interface between layer and substrate at the bottom of the snowpack. It provides argument handling.

Build the interface

Parameters:**kwargs

parameters such as roughness_rms, corr_length, Q, N, etc are required or optional depending on the model.

See the document of the model.

args = []
optional_args = {}
__init__(**kwargs)

Build the interface

Parameters:**kwargs

parameters such as roughness_rms, corr_length, Q, N, etc are required or optional depending on the model.

See the document of the model.

__dict__ = mappingproxy({'__module__': 'smrt.core.interface', '__doc__': ' Abstract class for interface between layer and substrate at the bottom of the snowpack.\nIt provides argument handling.\n', 'args': [], 'optional_args': {}, '__init__': <function Interface.__init__>, '__dict__': <attribute '__dict__' of 'Interface' objects>, '__weakref__': <attribute '__weakref__' of 'Interface' objects>})
__doc__ = ' Abstract class for interface between layer and substrate at the bottom of the snowpack.\nIt provides argument handling.\n'
__module__ = 'smrt.core.interface'
__weakref__

list of weak references to the object (if defined)

class SubstrateBase(temperature=None, permittivity_model=None)

Bases: object

Abstract class for substrate at the bottom of the snowpack. It provides calculation of the permittivity constant for soil case. Argument handline is delegated to the instance of the interface

Build the substrate at the base of the snowpack

Parameters:
  • temperature – temperature of the base of the snowpack. Can be the effective temperature if the substrate is slightly transparent
  • permittivity_model – a function that return the permittivity as a function of frequency and temperature. Can also be a numerical value.
  • **kwargs

    other parameters such as roughness_rms, corr_length, Q, N, etc are required or optional depending on the model. See the document of the model.

__init__(temperature=None, permittivity_model=None)

Build the substrate at the base of the snowpack

Parameters:
  • temperature – temperature of the base of the snowpack. Can be the effective temperature if the substrate is slightly transparent
  • permittivity_model – a function that return the permittivity as a function of frequency and temperature. Can also be a numerical value.
  • **kwargs

    other parameters such as roughness_rms, corr_length, Q, N, etc are required or optional depending on the model. See the document of the model.

permittivity(frequency)

compute the permittivity for the given frequency using permittivity_model. This method returns None when no permittivity model is available. This must be handled by the calling code and interpreted suitably.

__add__(other)
__iadd__(other)
__dict__ = mappingproxy({'__module__': 'smrt.core.interface', '__doc__': ' Abstract class for substrate at the bottom of the snowpack.\nIt provides calculation of the permittivity constant for soil case. Argument handline is delegated to the instance of the interface\n', '__init__': <function SubstrateBase.__init__>, 'permittivity': <function SubstrateBase.permittivity>, '__add__': <function SubstrateBase.__add__>, '__iadd__': <function SubstrateBase.__iadd__>, '__dict__': <attribute '__dict__' of 'SubstrateBase' objects>, '__weakref__': <attribute '__weakref__' of 'SubstrateBase' objects>})
__doc__ = ' Abstract class for substrate at the bottom of the snowpack.\nIt provides calculation of the permittivity constant for soil case. Argument handline is delegated to the instance of the interface\n'
__module__ = 'smrt.core.interface'
__weakref__

list of weak references to the object (if defined)

substrate_from_interface(interface_cls)

this decorator transform an interface class into a substrate class with automatic method

class Substrate(temperature=None, permittivity_model=None, **kwargs)

Bases: smrt.core.interface.SubstrateBase, smrt.core.interface.Interface

__init__(temperature=None, permittivity_model=None, **kwargs)

Build the substrate at the base of the snowpack

Parameters:
  • temperature – temperature of the base of the snowpack. Can be the effective temperature if the substrate is slightly transparent
  • permittivity_model – a function that return the permittivity as a function of frequency and temperature. Can also be a numerical value.
  • **kwargs

    other parameters such as roughness_rms, corr_length, Q, N, etc are required or optional depending on the model. See the document of the model.

__doc__ = None
__module__ = 'smrt.core.interface'
get_substrate_model(substrate_model)

return the class corresponding to the substrate model called name. This function imports the correct module if possible and returns the class

smrt.core.layer module

Layer instance contains all the properties for a single snow layer (e.g. temperature, frac_volume, etc). It also contains a microstructure attribute that holds the microstructural properties (e.g. radius, corr_length, etc). The class of this attribute defines the microstructure model to use (see smrt.microstructure_model package).

To create a single layer, it is recommended to use the function make_snow_layer() rather than the class constructor. However it is usually more convenient to create a snowpack using make_snowpack().

For developers

The Layer class should not be modified at all even if you need new properties to define the layer (e.g. brine concentration, humidity, …). If the property you need to add is related to geometric aspects, it is probably better to use an existing microstructure model or to create a new one. If the new parameter is not related to geometrical aspect, write a function similar to make_snow_layer() (choose an explicit name for your purpose). In this function, create the layer by calling the Layer constructor as in make_snow_layer() and then add your properties with lay.myproperty=xxx, … See the example of liquid water in make_snow_layer(). This approach avoids specialization of the Layer class. The new function can be in any file (inc. out of smrt directories), and should be added in make_medium if it is of general interest and written in a generic way, that is, covers many use cases for many users with default arguments, etc.

class Layer(thickness, microstructure_model=None, temperature=273.15, permittivity_model=None, inclusion_shape=None, **kwargs)

Bases: object

Contains the properties for a single layer including the microstructure attribute which holds the microstructure properties.

To create layer, it is recommended to use of the functions make_snow_layer() and similar

Build a snow layer.

Parameters:
  • thickness – thickness of snow layer in m
  • microstructure_model – module name of microstructure model to be used
  • temperature – temperature of layer in K
  • permittivity_model – list or tuple of permittivity value or model for the background and materials (e.g. air and ice). The permittivity can be

given as a complex (or real) value or a function that return a value (see smrt.permittivity modules) :param inclusion_shape: assumption for shape of air/brine inclusions (so far, “spheres” and “random_needles” (i.e. elongated ellipsoidal inclusions) and “mix_spheres_needles” are implemented)

__init__(thickness, microstructure_model=None, temperature=273.15, permittivity_model=None, inclusion_shape=None, **kwargs)

Build a snow layer.

Parameters:
  • thickness – thickness of snow layer in m
  • microstructure_model – module name of microstructure model to be used
  • temperature – temperature of layer in K
  • permittivity_model – list or tuple of permittivity value or model for the background and materials (e.g. air and ice). The permittivity can be

given as a complex (or real) value or a function that return a value (see smrt.permittivity modules) :param inclusion_shape: assumption for shape of air/brine inclusions (so far, “spheres” and “random_needles” (i.e. elongated ellipsoidal inclusions) and “mix_spheres_needles” are implemented)

ssa

return the SSA, compute it if necessary

frac_volume
permittivity(i, frequency)

return the permittivity of the i-th medium depending on the frequency and internal layer properties. Usually i=0 is air and i=1 is ice for dry snow with a low or moderate density.

Parameters:
  • i – number of the medium. 0 is reserved for the background
  • frequency – frequency of the wave (Hz)
Returns:

complex permittivity of the i-th medium

basic_checks()

Function to provide very basic input checks on the layer information

Currently checks:

  • temperature is between 100 and the freezing point (Kelvin units check),
  • density is between 1 and DENSITY_OF_ICE (SI units check)
  • layer thickness is above zero
inverted_medium()

return the layer with inverted autocorrelation and inverted permittivities.

__setattr__(name, value)

Implement setattr(self, name, value).

update(**kwargs)

update the attributes. This method is to be used when recalculation of the state of the object is necessary. See for instance SnowLayer.

__dict__ = mappingproxy({'__module__': 'smrt.core.layer', '__doc__': ' Contains the properties for a single layer including the microstructure attribute which holds the microstructure properties.\n\n To create layer, it is recommended to use of the functions :py:meth:`make_snow_layer` and similar\n\n ', '__init__': <function Layer.__init__>, 'ssa': <property object>, 'frac_volume': <property object>, 'permittivity': <function Layer.permittivity>, 'basic_checks': <function Layer.basic_checks>, 'inverted_medium': <function Layer.inverted_medium>, '__setattr__': <function Layer.__setattr__>, 'update': <function Layer.update>, '__dict__': <attribute '__dict__' of 'Layer' objects>, '__weakref__': <attribute '__weakref__' of 'Layer' objects>})
__doc__ = ' Contains the properties for a single layer including the microstructure attribute which holds the microstructure properties.\n\n To create layer, it is recommended to use of the functions :py:meth:`make_snow_layer` and similar\n\n '
__module__ = 'smrt.core.layer'
__weakref__

list of weak references to the object (if defined)

get_microstructure_model(modulename, classname=None)

return the class corresponding to the microstructure_model defined in modulename.

This function import the correct module if possible and return the class. It is used internally and should not be needed for normal usage.

Parameters:modulename – name of the python module in smrt/microstructure_model
make_microstructure_model(modelname_or_class, **kwargs)

create an microstructure instance.

This function is called internally and should not be needed for normal use.

param modelname_or_class:
 name of the module or directly the class.
param type:string
param **kwargs:all the arguments need for the specific autocorrelation.
returns:instance of the autocorrelation modelname with the parameters given in **kwargs
Example:

To import the StickyHardSpheres class with spheres radius of 1mm, stickiness of 0.5 and fractional_volume of 0.3:

shs = make_autocorrelation("StickyHardSpheres", radius=0.001, stickiness=0.5, frac_volume=0.3)
layer_properties(*required_arguments, optional_arguments=None, **kwargs)

This decorator is used for the permittivity functions (or any other functions) to inject layer’s attributes as arguments. The decorator declares the layer properties needed to call the function and the optional ones. This allows permittivity functions to use any property of the layer, as long as it is defined.

smrt.core.lib module

get(x, i, name=None)
check_argument_size(x, n, name=None)
is_sequence(x)
len_atleast_1d(x)
class smrt_diag(arr)

Bases: object

Scipy.sparse is very slow for diagonal matrix and numpy has no good support for linear algebra. This diag class implements simple diagonal object without numpy subclassing (but without much features). It seems that proper subclassing numpy and overloading matmul is a very difficult problem.

__array_ufunc__ = None
__init__(arr)

Initialize self. See help(type(self)) for accurate signature.

diagonal()
shape
__len__()
__rmatmul__(other)
__matmul__(other)
__rmul__(other)
__mul__(other)
__add__(other)
__radd__(other)
__sub__(other)
__iadd__(other)
__isub__(other)
__getitem__(key)
check_type(other)
__dict__ = mappingproxy({'__module__': 'smrt.core.lib', '__doc__': 'Scipy.sparse is very slow for diagonal matrix and numpy has no good support for linear algebra. This diag class\n implements simple diagonal object without numpy subclassing (but without much features).\n It seems that proper subclassing numpy and overloading matmul is a very difficult problem.', '__array_ufunc__': None, '__init__': <function smrt_diag.__init__>, 'diagonal': <function smrt_diag.diagonal>, 'shape': <property object>, '__len__': <function smrt_diag.__len__>, '__rmatmul__': <function smrt_diag.__rmatmul__>, '__matmul__': <function smrt_diag.__matmul__>, '__rmul__': <function smrt_diag.__rmul__>, '__mul__': <function smrt_diag.__mul__>, '__add__': <function smrt_diag.__add__>, '__radd__': <function smrt_diag.__radd__>, '__sub__': <function smrt_diag.__sub__>, '__iadd__': <function smrt_diag.__iadd__>, '__isub__': <function smrt_diag.__isub__>, '__getitem__': <function smrt_diag.__getitem__>, 'check_type': <function smrt_diag.check_type>, '__dict__': <attribute '__dict__' of 'smrt_diag' objects>, '__weakref__': <attribute '__weakref__' of 'smrt_diag' objects>})
__doc__ = 'Scipy.sparse is very slow for diagonal matrix and numpy has no good support for linear algebra. This diag class\n implements simple diagonal object without numpy subclassing (but without much features).\n It seems that proper subclassing numpy and overloading matmul is a very difficult problem.'
__module__ = 'smrt.core.lib'
__weakref__

list of weak references to the object (if defined)

class smrt_matrix(mat, mtype=None)

Bases: object

SMRT uses two formats of matrix: one most suitable to implement emmodel where equations are different for each polarization and another one suitable for DORT computation where stream and polarization are collapsed in one dimension to allow matrix operation. In addition, the reflection and transmission matrix are often diagonal matrix, which needs to be handled because it saves space and allow much faster operations. This class implemented all these features.

__init__(mat, mtype=None)

Initialize self. See help(type(self)) for accurate signature.

static empty(dims, mtype=None)
static zeros(dims, mtype=None)
static ones(dims, mtype=None)
static full(dims, value, mtype=None)
npol
isnull()
compress(mode=None, auto_reduce_npol=False)

compress a matrix. This comprises several actions: 1) select one mode, if relevant (dense5, and diagonal5). 2) reduce the number of polarization from 3 to 2 if mode==0 and auto_reduce_npol=True. 3) convert the format of the matrix to compressed numpy, involving a change of the dimension order (pola and streams are merged).

__rmul__(other)
__mul__(other)
__truediv__(other)
__add__(other)
__sub__(other)
__abs__()
__getitem__(key)
__setitem__(key, v)
diagonal
sel(**kwargs)
__repr__()

Return repr(self).

__dict__ = mappingproxy({'__module__': 'smrt.core.lib', '__doc__': 'SMRT uses two formats of matrix: one most suitable to implement emmodel where equations are different for each polarization and another one suitable\n for DORT computation where stream and polarization are collapsed in one dimension to allow matrix operation. In addition, the reflection and transmission matrix\n are often diagonal matrix, which needs to be handled because it saves space and allow much faster operations. This class implemented all these features.\n\n ', '__init__': <function smrt_matrix.__init__>, 'empty': <staticmethod object>, 'zeros': <staticmethod object>, 'ones': <staticmethod object>, 'full': <staticmethod object>, 'npol': <property object>, 'isnull': <function smrt_matrix.isnull>, 'compress': <function smrt_matrix.compress>, '__rmul__': <function smrt_matrix.__rmul__>, '__mul__': <function smrt_matrix.__mul__>, '__truediv__': <function smrt_matrix.__truediv__>, '__add__': <function smrt_matrix.__add__>, '__sub__': <function smrt_matrix.__sub__>, '__abs__': <function smrt_matrix.__abs__>, '__getitem__': <function smrt_matrix.__getitem__>, '__setitem__': <function smrt_matrix.__setitem__>, 'diagonal': <property object>, 'sel': <function smrt_matrix.sel>, '__repr__': <function smrt_matrix.__repr__>, '__dict__': <attribute '__dict__' of 'smrt_matrix' objects>, '__weakref__': <attribute '__weakref__' of 'smrt_matrix' objects>})
__doc__ = 'SMRT uses two formats of matrix: one most suitable to implement emmodel where equations are different for each polarization and another one suitable\n for DORT computation where stream and polarization are collapsed in one dimension to allow matrix operation. In addition, the reflection and transmission matrix\n are often diagonal matrix, which needs to be handled because it saves space and allow much faster operations. This class implemented all these features.\n\n '
__module__ = 'smrt.core.lib'
__weakref__

list of weak references to the object (if defined)

isnull(m)

return true if the smrt matrix is null

generic_ft_even_matrix(phase_function, m_max, nsamples=None)

Calculation of the Fourier decomposed of the phase or reflection or transmission matrix provided by the function.

This method calculates the Fourier decomposition modes and return the output.

Coefficients within the phase function are

Passive case (m = 0 only) and active (m = 0)

M  = [Pvvp  Pvhp]
     [Phvp  Phhp]

Active case (m > 0):

M =  [Pvvp Pvhp Pvup]
     [Phvp Phhp Phup]
     [Puvp Puhp Puup]
Parameters:
  • phase_function – must be a function taking dphi as input. It is assumed that phi is symmetrical (it is in cos(phi))
  • m_max – maximum Fourier decomposition mode needed
set_max_numerical_threads(nthreads)

set the maximum number of threads for a few known library. This is useful to disable parallel computing in SMRT when using parallel computing to call multiple // SMRT runs. This avoid over-committing the CPUs and results in much better performance. Inspire from joblib.

smrt.core.model module

A model in SMRT is composed of the electromagnetic scattering theory (smrt.emmodel) and the radiative transfer solver (smrt.rtsolver). The smrt.emmodel is responsible for computation of the scattering and absorption coefficients and the phase function of a layer. It is applied to each layer and it is even possible to choose different emmodel for each layer (for instance for a complex medium made of different materials: snow, soil, water, atmosphere, …). The smrt.rtsolver is responsible for propagation of the incident or emitted energy through the layers, up to the surface, and eventually through the atmosphere.

To build a model, use the make_model() function with the type of emmodel and type of rtsolver as arguments. Then call the Model.run() method of the model instance by specifying the sensor (smrt.core.sensor.Sensor), snowpack (smrt.core.snowpack.Snowpack) and optionally atmosphere (see smrt.atmosphere). The results are returned as a Result which can then been interrogated to retrieve brightness temperature, backscattering coefficient, etc.

Example:

m = make_model("iba", "rtsolver")

result = m.run(sensor, snowpack)  # sensor and snowpack are created before

print(result.TbV())

The model can be run on a list of snowpacks or even more conveniently on a pandas.Series or pandas.DataFrame including snowpacks. The first advantage is that by setting parallel_computation=True, the Model.run() method performs the simulation in parallel

on all the available cores of your machine and even possibly remotely on a high performance cluster using dask. The second advantage is that the returned Result object contains all the simulations and provide an easier way to plot the results or compute statistics.
If a list of snowpacks is provided, it is recommended to also set the snowpack_dimension argument. It takes the form of a tuple
(list of snowpack_dimension values, dimension name). The name and values are used to define the coordinates in the Result object. This is useful with timeseries or sensitivity analysis for instance.

Example:

snowpacks = []
times = []
for file in filenames:
    #  create a snowpack for each time series
    sp = ...
    snowpacks.append(sp)
    times.append(sp)

# now run the model

res = m.run(sensor, snowpacks, snowpack_dimension=('time', times))

The res variable has now a coordinate time and res.TbV() returns a timeseries.

Using pandas.Series offers an even more elegant way to run SMRT and assemble the results of all the simulations.

thickness_list = np.arange(0, 10, 1) snowpacks = pd.Series([make_snowpack(thickness=t, ……..) for t in thickness_list], index=thickness_list) # snowpacks is a pandas Series of snowpack objects with the thickness as index

# now run the model

res = m.run(sensor, snowpacks, parallel_computation=True)

# convert the result into a datframe res = res.to_dataframe()

The res variable is a dataframe with the thickness as index and the channels of the sensor as column.

Using pandas.DataFrame is similar. One column must contain Snowpack objects (see snowpack_column argument). The results of the simulations are automatically joined with this dataframe and returned by to_dataframe() or to_dataframe().

# df is a DataFrame with several parameters in each row.

# add a snowpack object for each row df[‘snowpack’] = [make_snowpack(thickness=row[‘thickness’], ……..) for i, row in df.iterrows()]]

# now run the model res = m.run(sensor, snowpacks, parallel_computation=True)

# convert the result into a datframe res = res.to_dataframe()

The res variable is a pandas.DataFrame equal to df + the results at all sensor’s channel added.

make_model(emmodel, rtsolver=None, emmodel_options=None, rtsolver_options=None, emmodel_kwargs=None, rtsolver_kwargs=None)

create a new model with a given EM model and RT solver. The model is then ready to be run using the Model.run() method. This function is the privileged way to create models compared to class instantiation. It supports automatic import of the emmodel and rtsolver modules.

Parameters:emmodel – type of emmodel to use. Can be given by the name of a file/module in the emmodel directory (as a string) or a class.

List (and dict, respectively) can be provided when a different emmodel is needed for every layer (or every kind of layer medium). :type emmodel: string or class or list of strings or classes or dict of strings or classes. If a list of emmodels is given, the size must be the same as the number of layers in the snowpack. If a dict is given, the keys are the kinds of medium and the values are the associated emmodels to each sort of medium. The layer attribute ‘medium’ is used to determine the emmodel to use for each layer. :type emmodel: string or class; or list of strings or classes; or dict of strings or classes. :param rtsolver: type of RT solver to use. Can be given by the name of a file/module in the rtsolver directeory (as a string) or a class. :type rtsolver: string or class. Can be None when only computation of the layer electromagnetic properties is needed. :param emmodel_options: extra arguments to use to create emmodel instance. Valid arguments depend on the selected emmodel. It is documented in for each emmodel class. :type emmodel_options: dict or a list of dict. In the latter case, the size of the list must be the same as the number of layers in the snowpack. :param rtsolver_options: extra to use to create the rtsolver instance (see __init__ of the solver used). :type rtsolver_options: dict

Returns:a model instance
get_emmodel(emmodel)

get a new emmodel class from the file name

make_emmodel(emmodel, sensor, layer, **emmodel_options)

create a new emmodel instance based on the emmodel class or string :param emmodel: type of emmodel to use. Can be given by the name of a file/module in the emmodel directory (as a string) or a class. :param sensor: sensor to use for the calculation. :param layer: layer to use for the calculation

class Model(emmodel, rtsolver, emmodel_options=None, rtsolver_options=None)

Bases: object

This class drives the whole calculation

create a new model. It is not recommended to instantiate Model class directly. Instead use the make_model() function.

__init__(emmodel, rtsolver, emmodel_options=None, rtsolver_options=None)

create a new model. It is not recommended to instantiate Model class directly. Instead use the make_model() function.

set_rtsolver_options(options=None, **kwargs)

set the option for the rtsolver

set_emmodel_options(options=None, **kwargs)

set the options for the emmodel

run(sensor, snowpack, atmosphere=None, snowpack_dimension=None, snowpack_column='snowpack', progressbar=False, parallel_computation=False, runner=None)

Run the model for the given sensor configuration and return the results

Parameters:
  • sensor – sensor to use for the calculation
  • snowpack – snowpack to use for the calculation. Can be a single snowpack, a list of snowpack, a dict of snowpack or a SensitivityStudy object.
  • snowpack_dimension – name and values (as a tuple) of the dimension to create for the results when a list of snowpack is provided. E.g. time, point, longitude, latitude. By default the dimension is called ‘snowpack’ and the values are rom 1 to the number of snowpacks.
  • snowpack_column – when snowpack is a DataFrame this argument is used to specify which column contians the Snowpack objects
  • progressbar – if True, display a progress bar during multi-snowpacks computation
  • parallel_computation – if True, use the joblib library to run the simulation in parallel. Otherwise, the simulations are run sequentially. See ‘runner’ arguments.
  • runner – a ‘runner’ is a function (or more likely a class with a __call__ method) that takes a function and a list/generator of simulations, executes the function on each simulation and returns a list of results. ‘parallel_computation’ allows to select between two default (basic) runners (sequential and joblib). Use ‘runner’ for more advanced parallel distributed computations.
Returns:

result of the calculation(s) as a Results instance

prepare_simulations(sensor, snowpack, snowpack_dimension, snowpack_column)
prepare_emmodels(sensor, snowpack)
run_single_simulation(simulation, atmosphere)
run_later(sensor, snowpack, **kwargs)
__dict__ = mappingproxy({'__module__': 'smrt.core.model', '__doc__': ' This class drives the whole calculation\n ', '__init__': <function Model.__init__>, 'set_rtsolver_options': <function Model.set_rtsolver_options>, 'set_emmodel_options': <function Model.set_emmodel_options>, 'run': <function Model.run>, 'prepare_simulations': <function Model.prepare_simulations>, 'prepare_emmodels': <function Model.prepare_emmodels>, 'run_single_simulation': <function Model.run_single_simulation>, 'run_later': <function Model.run_later>, '__dict__': <attribute '__dict__' of 'Model' objects>, '__weakref__': <attribute '__weakref__' of 'Model' objects>})
__doc__ = ' This class drives the whole calculation\n '
__module__ = 'smrt.core.model'
__weakref__

list of weak references to the object (if defined)

class SequentialRunner(progressbar=False)

Bases: object

Run the simulations sequentially on a single (local) core. This is the most simple way to run smrt simulations, but the efficiency is poor.

__init__(progressbar=False)

Initialize self. See help(type(self)) for accurate signature.

__call__(function, argument_list)

Call self as a function.

__dict__ = mappingproxy({'__module__': 'smrt.core.model', '__doc__': 'Run the simulations sequentially on a single (local) core. This is the most simple way to run smrt simulations, but the \nefficiency is poor.', '__init__': <function SequentialRunner.__init__>, '__call__': <function SequentialRunner.__call__>, '__dict__': <attribute '__dict__' of 'SequentialRunner' objects>, '__weakref__': <attribute '__weakref__' of 'SequentialRunner' objects>})
__doc__ = 'Run the simulations sequentially on a single (local) core. This is the most simple way to run smrt simulations, but the \nefficiency is poor.'
__module__ = 'smrt.core.model'
__weakref__

list of weak references to the object (if defined)

class JoblibParallelRunner(backend='loky', n_jobs=-1, max_numerical_threads=1)

Bases: object

Run the simulations on the local machine on all the cores, using the joblib library for parallelism.

Joblib is a lightweight library for embarasingly parallel task.

Parameters:
  • backend – see joblib documentation. The default ‘loky’ is the recommended backend.
  • n_jobs – see joblib documentation. The default is to use all the cores.
  • max_numerical_threadsset_max_numerical_threads(). The default avoid miximing different

parallelism techniques.

__init__(backend='loky', n_jobs=-1, max_numerical_threads=1)

Joblib is a lightweight library for embarasingly parallel task.

Parameters:
  • backend – see joblib documentation. The default ‘loky’ is the recommended backend.
  • n_jobs – see joblib documentation. The default is to use all the cores.
  • max_numerical_threadsset_max_numerical_threads(). The default avoid miximing different

parallelism techniques.

__dict__ = mappingproxy({'__module__': 'smrt.core.model', '__doc__': 'Run the simulations on the local machine on all the cores, using the joblib library for parallelism.', '__init__': <function JoblibParallelRunner.__init__>, '__call__': <function JoblibParallelRunner.__call__>, '__dict__': <attribute '__dict__' of 'JoblibParallelRunner' objects>, '__weakref__': <attribute '__weakref__' of 'JoblibParallelRunner' objects>})
__doc__ = 'Run the simulations on the local machine on all the cores, using the joblib library for parallelism.'
__module__ = 'smrt.core.model'
__weakref__

list of weak references to the object (if defined)

__call__(function, argument_list)

Call self as a function.

smrt.core.optional_numba module

smrt.core.plugin module

register_package(pkg)
import_class

Import the modulename and return either the class named “classname” or the first class defined in the module if classname is None.

Parameters:
  • scope – scope where to search for the module.
  • modulename – name of the module to load.
  • classname – name of the class to read from the module.
do_import_class(modulename, classname)

smrt.core.progressbar module

A progress bar copied and adapted from pyMC code (dec 2014)

class TextProgressBar(iterations, printer, width=40, interval=None)

Bases: smrt.core.progressbar.ProgressBar

Use Progress

__init__(iterations, printer, width=40, interval=None)

Initialize self. See help(type(self)) for accurate signature.

animate(i, dummy=None)
progbar(i)
bar(percent)
__doc__ = 'Use :class:`Progress`'
__module__ = 'smrt.core.progressbar'
progress_bar(iters, interval=None)

A progress bar for Python/IPython/IPython notebook

Parameters:
  • iters (int) – number of iterations (steps in the loop)
  • interval – number of intervals to use to update the progress bar (20 by default)
from easydev import progress_bar
pb = progress_bar(10)
for i in range(1,10):
    import time
    time.sleep(0.1)
    pb.animate(i)
class Progress(iters, interval=None)

Bases: object

Generic progress bar for python, IPython, IPython notebook

from easydev import Progress
pb = Progress(100, interval=1)
pb.animate(10)
__init__(iters, interval=None)

Initialize self. See help(type(self)) for accurate signature.

animate(i)
_get_elapsed()
elapsed
__dict__ = mappingproxy({'__module__': 'smrt.core.progressbar', '__doc__': 'Generic progress bar for python, IPython, IPython notebook\n\n ::\n\n from easydev import Progress\n pb = Progress(100, interval=1)\n pb.animate(10)\n ', '__init__': <function Progress.__init__>, 'animate': <function Progress.animate>, '_get_elapsed': <function Progress._get_elapsed>, 'elapsed': <property object>, '__dict__': <attribute '__dict__' of 'Progress' objects>, '__weakref__': <attribute '__weakref__' of 'Progress' objects>})
__doc__ = 'Generic progress bar for python, IPython, IPython notebook\n\n ::\n\n from easydev import Progress\n pb = Progress(100, interval=1)\n pb.animate(10)\n '
__module__ = 'smrt.core.progressbar'
__weakref__

list of weak references to the object (if defined)

smrt.core.result module

The results of RT Solver are hold by the Result class. This class provides several functions to access to the Stokes Vector and Muller matrix in a simple way. Most notable ones are Result.TbV() and Result.TbH() for the passive mode calculations and Result.sigmaHH() and Result.sigmaVV(). Result.to_dataframe() is also very convenient for the sensors with a channel map (all specific satellite sensors have such a map, only generic sensors as smrt.sensor_list.active() and smrt.sensor_list.passive() does not provide a map by default).

In addition, the RT Solver stores some information in Result.other_data. Currently this includes the effective_permittivity, ks and ka for each layer. The data are accessed directly with e.g. result.other_data[‘ks’].

To save results of calculations in a file, simply use the pickle module or other serialization schemes. We may provide a unified and inter-operable solution in the future.

Under the hood, Result uses xarray module which provides multi-dimensional array with explicit, named, dimensions. Here the common dimensions are frequency, polarization, polarization_inc, theta_inc, theta, and phi. They are created by the RT Solver. The interest

of using named dimension is that slice of the xarray (i.e. results) can be selected based on the dimension name whereas with numpy the order of the dimensions matters. Because this is very convenient, users may be interested in adding other dimensions specific to their context such

as time, longitude, latitude, points, … To do so, smrt.core.model.Model.run() accepts a list of snowpack and optionally the parameter snowpack_dimension is used to specify the name and values of the new dimension to build.

Example:

times = [datetime(2012, 1, 1), datetime(2012, 1, 5), , datetime(2012, 1, 10)]
snowpacks = [snowpack_1jan, snowpack_5jan, snowpack_10jan]

res = model.run(sensor, snowpacks, snowpack_dimension=('time', times))

The res variable is a Result instance, so that for all the methods of this class that can be called, they will return a timeseries. For instance result.TbV(theta=53) returns a time-series of brightness temperature at V polarization and 53° incidence angle and the following code plots this timeseries:

plot(times, result.TbV(theta=53))
open_result(filename)

read a result save to disk. See Result.save() method.

make_result(sensor, *args, **kwargs)

create an active or passive result object according to the mode

class Result(intensity, coords=None, channel_map=None, other_data={}, mother_df=None)

Bases: object

Contains the results of a/many computations and provides convenience functions to access these results

Construct results array with the given intensity array (numpy array or xarray) and dimensions if numpy array is given

__init__(intensity, coords=None, channel_map=None, other_data={}, mother_df=None)

Construct results array with the given intensity array (numpy array or xarray) and dimensions if numpy array is given

coords

Return the coordinates of the result (theta, frequency, …). Note that the coordinates are also result attribute, so result.frequency works (and so on for all the coordinates).

__getattr__(attr)
save(filename)

save a result to disk. Under the hood, this is a netCDF file produced by xarray (http://xarray.pydata.org/en/stable/io.html).

sel_data(channel=None, **kwargs)
return_as_dataframe(name, channel_axis=None, **kwargs)
to_series(**kwargs)

return the result as a series with the channels defined in the sensor as index. This requires that the sensor has declared a channel list.

__dict__ = mappingproxy({'__module__': 'smrt.core.result', '__doc__': ' Contains the results of a/many computations and provides convenience functions to access these results\n\n ', '__init__': <function Result.__init__>, 'coords': <property object>, '__getattr__': <function Result.__getattr__>, 'save': <function Result.save>, 'sel_data': <function Result.sel_data>, 'return_as_dataframe': <function Result.return_as_dataframe>, 'to_series': <function Result.to_series>, '__dict__': <attribute '__dict__' of 'Result' objects>, '__weakref__': <attribute '__weakref__' of 'Result' objects>})
__doc__ = ' Contains the results of a/many computations and provides convenience functions to access these results\n\n '
__module__ = 'smrt.core.result'
__weakref__

list of weak references to the object (if defined)

class PassiveResult(intensity, coords=None, channel_map=None, other_data={}, mother_df=None)

Bases: smrt.core.result.Result

Construct results array with the given intensity array (numpy array or xarray) and dimensions if numpy array is given

mode = 'P'
sel_data(channel=None, **kwargs)
Tb(channel=None, **kwargs)

Return brightness temperature. Any parameter can be added to slice the results (e.g. frequency=37e9 or polarization=’V’). See xarray slicing with sel method (to document). It is also posisble to select by channel if the sensor has a channel_map.

Parameters:
  • channel – channel to select
  • **kwargs

    any parameter to slice the results.

Tb_as_dataframe(channel_axis=None, **kwargs)

See PassiveResult().to_dataframe

to_dataframe(channel_axis='auto', **kwargs)

Return brightness temperature as a pandas.DataFrame. Any parameter can be added to slice the results (e.g. frequency=37e9 or polarization=’V’). See xarray slicing with sel method (to document). In addition channel_axis controls the format of the output. If set to None, the DataFrame has a multi-index with all the dimensions (frequency, polarization, …). If channel_axis is set to “column”, and if the sensor has a channel map, the channels are in columns and the other dimensions are in index. If set to “index”, the channel are in index with all the other dimensions.

The most conviennent is probably channel_axis=”column” while channel_axis=None (default) contains all the data even those not corresponding to a channel and applies to any sensor even those without channel_map. If set to “auto”, the channel_axis is “column” if the channel map exit, otherwise is None.

Parameters:channel_axis – controls whether to use the sensor channel or not and if yes, as a column or index.
TbV(**kwargs)

Return V polarization. Any parameter can be added to slice the results (e.g. frequency=37e9). See xarray slicing with sel method (to document)

TbH(**kwargs)

Return H polarization. Any parameter can be added to slice the results (e.g. frequency=37e9). See xarray slicing with sel method (to document)

polarization_ratio(ratio='H_V', **kwargs)

Return polarization ratio. Any parameter can be added to slice the results (e.g. frequency=37e9). See xarray slicing with sel method (to document)

__doc__ = None
__module__ = 'smrt.core.result'
class ActiveResult(intensity, coords=None, channel_map=None, other_data={}, mother_df=None)

Bases: smrt.core.result.Result

Construct results array with the given intensity array (numpy array or xarray) and dimensions if numpy array is given

mode = 'A'
sel_data(channel=None, return_backscatter=False, **kwargs)
sigma(channel=None, **kwargs)

Return backscattering coefficient. Any parameter can be added to slice the results (e.g. frequency=37e9 or polarization=’V’). See xarray slicing with sel method (to document). It is also posisble to select by channel if the sensor has a channel_map.

Parameters:
  • channel – channel to select
  • **kwargs

    any parameter to slice the results.

sigma_dB(channel=None, **kwargs)

Return backscattering coefficient. Any parameter can be added to slice the results (e.g. frequency=37e9, polarization_inc=’V’, polarization=’V’). See xarray slicing with sel method (to document)

sigma_as_dataframe(channel_axis=None, **kwargs)

Return backscattering coefficient as a pandas.DataFrame. Any parameter can be added to slice the results (e.g. frequency=37e9 or polarization=’V’). See xarray slicing with sel method (to document). In addition channel_axis controls the format of the output. If set to None, the DataFrame has a multi-index formed with all the dimensions (frequency, polarization, …). If channel_axis is set to “column”, and if the sensor has named channels (channel_map in SMRT wording), the channel are in columns and the other dimensions are in index. If set to “index”, the channel are in index with all the other dimensions.

The most conviennent is probably channel_axis=”column” while channel_axis=None (default) contains all the data even those not corresponding to a channel and applies to any sensor even those without channel_map.

Parameters:channel_axis – controls whether to use the sensor channel or not and if yes, as a column or index.
sigma_dB_as_dataframe(channel_axis=None, **kwargs)

See ActiveResult().to_dataframe

to_dataframe(channel_axis=None, **kwargs)

Return backscattering coefficient in dB as a pandas.DataFrame. Any parameter can be added to slice the results (e.g. frequency=37e9 or polarization=’V’). See xarray slicing with sel method (to document). In addition channel_axis controls the format of the output. If set to None, the DataFrame has a multi-index with all the dimensions (frequency, polarization, …). If channel_axis is set to “column”, and if the sensor has named channels (channel_map in SMRT wording), the channel are in columns and the other dimensions are in index. If set to “index”, the channel are in index with all the other dimensions.

If channel_axis is set to “column”, and if the sensor has a channel map, the channels are in columns and the other dimensions are in index. If set to “index”, the channel are in index with all the other dimensions.

The most conviennent is probably channel_axis=”column” while channel_axis=None (default) contains all the data even those not corresponding to a channel and applies to any sensor even those without channel_map. If set to “auto”, the channel_axis is “column” if the channel map exit, otherwise is None.

Parameters:channel_axis – controls whether to use the sensor channel or not and if yes, as a column or index.
to_series(**kwargs)

return backscattering coefficients in dB as a series with the channels defined in the sensor as index. This requires that the sensor has declared a channel list.

sigmaVV(**kwargs)

Return VV backscattering coefficient. Any parameter can be added to slice the results (e.g. frequency=37e9). See xarray slicing with sel method (to document)

sigmaVV_dB(**kwargs)

Return VV backscattering coefficient in dB. Any parameter can be added to slice the results (e.g. frequency=37e9). See xarray slicing with sel method (to document)

sigmaHH(**kwargs)

Return HH backscattering coefficient. Any parameter can be added to slice the results (e.g. frequency=37e9). See xarray slicing with sel method (to document)

sigmaHH_dB(**kwargs)

Return HH backscattering coefficient in dB. Any parameter can be added to slice the results (e.g. frequency=37e9). See xarray slicing with sel method (to document)

sigmaHV(**kwargs)

Return HV backscattering coefficient. Any parameter can be added to slice the results (e.g. frequency=37e9). See xarray slicing with sel method (to document)

sigmaHV_dB(**kwargs)

Return HV backscattering coefficient in dB. Any parameter can be added to slice the results (e.g. frequency=37e9). See xarray slicing with sel method (to document)

sigmaVH(**kwargs)

Return VH backscattering coefficient. Any parameter can be added to slice the results (e.g. frequency=37e9). See xarray slicing with sel method (to document)

sigmaVH_dB(**kwargs)

Return VH backscattering coefficient in dB. Any parameter can be added to slice the results (e.g. frequency=37e9). See xarray slicing with sel method (to document)

__doc__ = None
__module__ = 'smrt.core.result'
concat_results(result_list, coord)

Concatenate several results from smrt.core.model.Model.run() (of type Result) into a single result (of type Result). This extends the number of dimension in the xarray hold by the instance. The new dimension is specified with coord

Parameters:
  • result_list – list of results returned by smrt.core.model.Model.run() or other functions.
  • coord – a tuple (dimension_name, dimension_values) for the new dimension. Dimension_values must be a sequence or

array with the same length as result_list.

Returns:Result instance
_strongsqueeze(x)

smrt.core.run_promise module

honour_all_promises(directory_or_filename, save_result_to=None, show_progress=True, force_compute=True)

Honour many promises and save the results

Parameters:
  • directory_or_filename – can be a directory, a filename or a list of them
  • save_result_to – directory where to save the results. If None, the results are not saved. The results are always returned as a list by this function.
  • show_progress – print progress of the calculation.
  • force_computate – If False and if a result or lock file is present, the computation is skipped. The order of promise processing is randomized to allow more efficient parallel computation using many calls of this function on the same directory. A lock file is used between the start of a computation and writting the result in order to prevent from running several times the same computation. If the process is interupted (e.g. walltime on clusters), the lock file may persist and prevent any future computation. In this case, lock files must be manually deleted. IF False, the save_result_to argument must be set to a valid directory where the results.
honour_promise(filename, save_result_to=None, force_compute=True)

Honour a promise and optionally save the result.

Parameters:
  • filename – file name of the promise
  • save_result_to – directory where to save the result.
  • force_compute – see honour_all_promise.
load_promise(filename)
class RunPromise(model, sensor, snowpack, kwargs)

Bases: object

__init__(model, sensor, snowpack, kwargs)

Initialize self. See help(type(self)) for accurate signature.

run()
save(directory=None, filename=None)
__dict__ = mappingproxy({'__module__': 'smrt.core.run_promise', '__init__': <function RunPromise.__init__>, 'run': <function RunPromise.run>, 'save': <function RunPromise.save>, '__dict__': <attribute '__dict__' of 'RunPromise' objects>, '__weakref__': <attribute '__weakref__' of 'RunPromise' objects>, '__doc__': None})
__doc__ = None
__module__ = 'smrt.core.run_promise'
__weakref__

list of weak references to the object (if defined)

smrt.core.sensitivity_study module

SensitivityStudy is used to easily conduct sensitivity studies.

Example:

times = [datetime(2012, 1, 1), datetime(2012, 1, 5), , datetime(2012, 1, 10)]
snowpacks = SensitivityStudy("time", times, [snowpack_1jan, snowpack_5jan, snowpack_10jan])


res = model.run(sensor, snowpacks)

The res variable is a Result instance, so that for all the methods of this class that can be called, they will return a timeseries. For instance result.TbV(theta=53) returns a time-series of brightness temperature at V polarization and 53° incidence angle and the following code plots this timeseries:

plot(times, result.TbV(theta=53))
class SensitivityStudy(name, values, snowpacks)

Bases: object

__init__(name, values, snowpacks)

Initialize self. See help(type(self)) for accurate signature.

__getitem__(key)
__dict__ = mappingproxy({'__module__': 'smrt.core.sensitivity_study', '__init__': <function SensitivityStudy.__init__>, '__getitem__': <function SensitivityStudy.__getitem__>, '__dict__': <attribute '__dict__' of 'SensitivityStudy' objects>, '__weakref__': <attribute '__weakref__' of 'SensitivityStudy' objects>, '__doc__': None})
__doc__ = None
__module__ = 'smrt.core.sensitivity_study'
__weakref__

list of weak references to the object (if defined)

sensitivity_study(name, values, snowpacks)

create a sensitivity study

Parameters:
  • name – name of the variable to investigate
  • values – values taken by the variable
  • snowpacks – list of snowpacks. Can be a sequence or a function that takes one argument and return a snowpack.

In the latter case, the function is called for each values to build the list of snowpacks

smrt.core.sensor module

The sensor configuration includes all the information describing the sensor viewing geometry (incidence, …) and operating parameters (frequency, polarization, …). The easiest and recommended way to create a Sensor instance is to use one of the convenience functions such as passive(), active(), amsre(), etc. Adding a function for a new or unlisted sensor can be done in sensor_list if the sensor is common and of general interest. Otherwise, we recommend to add these functions in your own files (outside of smrt directories).

passive(frequency, theta, polarization=None, channel_map=None, name=None)

Generic configuration for passive microwave sensor.

Return a Sensor for a microwave radiometer with given frequency, incidence angle and polarization

Parameters:
  • frequency – frequency in Hz
  • theta – viewing angle or list of viewing angles in degrees from vertical. Note that some RT solvers compute all viewing angles whatever this configuration because it is internally needed part of the multiple scattering calculation. It it therefore often more efficient to call the model once with many viewing angles instead of calling it many times with a single angle.
  • polarization (list of characters) – H and/or V polarizations. Both polarizations is the default. Note that most RT solvers compute all the polarizations whatever this configuration because the polarizations are coupled in the RT equation.
  • channel_map (dict) – map channel names (keys) to configuration (values). A configuration is a dict with frequency, polarization and other such parameters to be used by Result to select the results.
  • name (string) – name of the sensor
Returns:

Sensor instance

Usage example:

from smrt import sensor
radiometer = sensor.passive(18e9, 50)
radiometer = sensor.passive(18e9, 50, "V")
radiometer = sensor.passive([18e9,36.5e9], [50,55], ["V","H"])
channel_map_for_radar(frequency=None, polarization='HV', order='fp')

return a channel_map to convert channel name to frequency and polarization. This function assumes the frequency is coded as a two-digit number in GHz with leading 0 if necessary. The polarization is after the frequency if order is ‘fp’ and before if order is ‘pf’.

active(frequency, theta_inc, theta=None, phi=None, polarization_inc=None, polarization=None, channel_map=None, name=None)

Configuration for active microwave sensor.

Return a Sensor for a radar with given frequency, incidence and viewing angles and polarization

If polarizations are not specified, quad-pol is the default (VV, VH, HV and HH). If the angle of incident radiation is not specified, backscatter will be simulated

Parameters:
  • frequency – frequency in Hz
  • theta_inc – incident angle in degrees from the vertical
  • theta – viewing zenith angle in degrees from the vertical. By default, it is equal to theta_inc which corresponds to the backscatter direction
  • phi – viewing azimuth angle in degrees from the incident direction. By default, it is pi which corresponds to the backscatter direction
  • polarization_inc (list of 1-character strings) – list of polarizations of the incidence wave (‘H’ or ‘V’ or both.)
  • polarization (list of 1-character strings) – list of viewing polarizations (‘H’ or ‘V’ or both)
  • channel_map (dict) – map channel names (keys) to configuration (values). A configuration is a dict with frequency, polarization and other such parameters to be used by Result to select the results.
  • name (string) – name of the sensor
Returns:

Sensor instance

Usage example:

from smrt import sensor
scatterometer = sensor.active(frequency=18e9, theta_inc=50)
scatterometer = sensor.active(18e9, 50, 50, 0, "V", "V")
scatterometer = sensor.active([18e9,36.5e9], theta=50, theta_inc=50, polarization_inc=["V", "H"], polarization=["V", "H"])
altimeter(channel, **kwargs)
make_multi_channel_altimeter(config, channel)
class SensorBase

Bases: object

__dict__ = mappingproxy({'__module__': 'smrt.core.sensor', '__dict__': <attribute '__dict__' of 'SensorBase' objects>, '__weakref__': <attribute '__weakref__' of 'SensorBase' objects>, '__doc__': None})
__doc__ = None
__module__ = 'smrt.core.sensor'
__weakref__

list of weak references to the object (if defined)

class Sensor(frequency=None, theta_inc_deg=None, theta_deg=None, phi_deg=None, polarization_inc=None, polarization=None, channel_map=None, name=None, wavelength=None)

Bases: smrt.core.sensor.SensorBase

Configuration for sensor. Use of the functions passive(), active(), or the sensor specific functions e.g. amsre() are recommended to access this class.

Build a Sensor. Setting theta_inc to None means passive mode

Parameters:
  • frequency – Microwave frequency in Hz
  • theta_inc_deg – zenith angle in degrees of incident radiation emitted from the active sensor

:param polarization_inc. List of single character (H or V) for the incident wave :param theta_deg: zenith angle in degrees at which the observation is made :param phi_deg: azimuth angle at which the observation is made :param polarization: List of single character (H or V) :param channel_map: map channel names (keys) to configuration (values). A configuration is a dict with frequency, polarization and other

such parameters to be used by Result to select the results.
Parameters:
  • name – name of the sensor
  • wavelength – wavelength of the sensor. Can be set instead of the frequency.
__init__(frequency=None, theta_inc_deg=None, theta_deg=None, phi_deg=None, polarization_inc=None, polarization=None, channel_map=None, name=None, wavelength=None)

Build a Sensor. Setting theta_inc to None means passive mode

Parameters:
  • frequency – Microwave frequency in Hz
  • theta_inc_deg – zenith angle in degrees of incident radiation emitted from the active sensor

:param polarization_inc. List of single character (H or V) for the incident wave :param theta_deg: zenith angle in degrees at which the observation is made :param phi_deg: azimuth angle at which the observation is made :param polarization: List of single character (H or V) :param channel_map: map channel names (keys) to configuration (values). A configuration is a dict with frequency, polarization and other

such parameters to be used by Result to select the results.
Parameters:
  • name – name of the sensor
  • wavelength – wavelength of the sensor. Can be set instead of the frequency.
wavelength
wavenumber
mode

“A” for active or “P” for passive.

Type:returns the mode of observation
basic_checks()
configurations()
iterate(axis)

Iterate over the configuration for the given axis.

Parameters:axis – one of the attribute of the sensor (frequency, …) to iterate along
__doc__ = ' Configuration for sensor.\n Use of the functions :py:func:`passive`, :py:func:`active`, or the sensor specific functions\n e.g. :py:func:`amsre` are recommended to access this class.\n\n '
__module__ = 'smrt.core.sensor'
class SensorList(sensor_list, axis='channel')

Bases: smrt.core.sensor.SensorBase

__init__(sensor_list, axis='channel')

Initialize self. See help(type(self)) for accurate signature.

channel
frequency
configurations()
iterate(axis=None)
__doc__ = None
__module__ = 'smrt.core.sensor'
class Altimeter(frequency, altitude, beamwidth, pulse_bandwidth, sigma_p=None, off_nadir_angle=0, beam_asymmetry=0, ngate=1024, nominal_gate=40, theta_inc_deg=0.0, polarization_inc=None, polarization=None, channel=None)

Bases: smrt.core.sensor.Sensor

Configuration for altimeter. Use of the functions altimeter(), or the sensor specific functions e.g. envisat_ra2() are recommended to access this class.

__init__(frequency, altitude, beamwidth, pulse_bandwidth, sigma_p=None, off_nadir_angle=0, beam_asymmetry=0, ngate=1024, nominal_gate=40, theta_inc_deg=0.0, polarization_inc=None, polarization=None, channel=None)

Build a Sensor. Setting theta_inc to None means passive mode

Parameters:
  • frequency – Microwave frequency in Hz
  • theta_inc_deg – zenith angle in degrees of incident radiation emitted from the active sensor

:param polarization_inc. List of single character (H or V) for the incident wave :param theta_deg: zenith angle in degrees at which the observation is made :param phi_deg: azimuth angle at which the observation is made :param polarization: List of single character (H or V) :param channel_map: map channel names (keys) to configuration (values). A configuration is a dict with frequency, polarization and other

such parameters to be used by Result to select the results.
Parameters:
  • name – name of the sensor
  • wavelength – wavelength of the sensor. Can be set instead of the frequency.
__doc__ = ' Configuration for altimeter.\n Use of the functions :py:func:`altimeter`, or the sensor specific functions\n e.g. :py:func:`envisat_ra2` are recommended to access this class.\n\n '
__module__ = 'smrt.core.sensor'

smrt.core.snowpack module

Snowpack instance contains the description of the snowpack, including a list of layers and interfaces between the layers, and the substrate (soil, ice, …).

To create a snowpack, it is recommended to use the make_snowpack() function which avoids the complexity of creating each layer and then the snowpack from the layers. For more complex media (like lake ice or sea ice), it may be necessary to directly call the functions to create the different layers (such as make_snow_layer()).

Example:

# create a 10-m thick snowpack with a single layer,
# density is 350 kg/m3. The exponential autocorrelation function is
# used to describe the snow and the "size" parameter is therefore
# the correlation length which is given as an optional
# argument of this function (but is required in practice)

sp = make_snowpack([10], "exponential", [350], corr_length=[3e-3])
class Snowpack(layers=None, interfaces=None, substrate=None, atmosphere=None)

Bases: object

holds the description of the snowpack, including the layers, interfaces, and the substrate

__init__(layers=None, interfaces=None, substrate=None, atmosphere=None)

Initialize self. See help(type(self)) for accurate signature.

nlayer

return the number of layers

layer_thicknesses

return the thickness of each layer

layer_depths

return the depth of the bottom of each layer

bottom_layer_depths

return the depth of the bottom of each layer

top_layer_depths

return the depth of the bottom of each layer

mid_layer_depths

return the depth of the bottom of each layer

z

return the depth of each interface, that is, 0 and the depth of the bottom of each layer

layer_densities

return the density of each layer

profile(property_name, where='all', raise_attributeerror=False)

return the vertical profile of property_name. The property is searched either in the layer, microstructure or interface.

Parameters:
  • property_name – name of the property
  • where – where to search the property. Can be ‘all’, ‘layer’, ‘microstructure’, or ‘interface’
  • raise_attributeerror – raise an attribute error if the attribute is not found
append(layer, interface=None)

append a new layer at the bottom of the stack of layers. The interface is that at the top of the appended layer.

Parameters:
  • layer – instance of Layer
  • interface – type of interface. By default, flat surface (Flat) is considered meaning the coefficients are calculated with Fresnel coefficient and using the effective permittivity of the surrounding layers
delete(ilayer)

delete a layer and the upper interface

Parameters:ilayer – index of the layer
copy()

make a shallow copy of a snowpack by copying the list of layers and interfaces but not the layers and interfaces themselves which are still shared with the original snowpack. This method allows the user to create a new snowpack and remove, append or replace some layers or interfaces afterward. It does not allow to alter the layers or interfaces without changing the original snowpack. See py:meth:~deepcopy.

deepcopy()

make a deep copy of a snowpack.

basic_check()
check_addition_validity(other)
update_layer_number()
__add__(other)

Return a new snowpack made of the first snowpack (or layer) stacked on top of the second snowpack (or layer or substrate).

Note

if a layer is added on top (at bottom), the top (bottom) interface is duplicated.

Parameters:other – the snowpack, a layer or a substrate to add to the first argument.
Example:

# duplicate the top layer: newsp = sp.layers[0] + wetsp

__radd__(other)
__iadd__(other)

Inplace addition of object to snowpack. See __add__() description.

to_dataframe(default_columns=True, other_columns=None)
__repr__()

Return repr(self).

_repr_html_()

use by IPython notebook to display a snowpack in a pretty format

__dict__ = mappingproxy({'__module__': 'smrt.core.snowpack', '__doc__': 'holds the description of the snowpack, including the layers, interfaces, and the substrate\n\n', '__init__': <function Snowpack.__init__>, 'nlayer': <property object>, 'layer_thicknesses': <property object>, 'layer_depths': <property object>, 'bottom_layer_depths': <property object>, 'top_layer_depths': <property object>, 'mid_layer_depths': <property object>, 'z': <property object>, 'layer_densities': <property object>, 'profile': <function Snowpack.profile>, 'append': <function Snowpack.append>, 'delete': <function Snowpack.delete>, 'copy': <function Snowpack.copy>, 'deepcopy': <function Snowpack.deepcopy>, 'basic_check': <function Snowpack.basic_check>, 'check_addition_validity': <function Snowpack.check_addition_validity>, 'update_layer_number': <function Snowpack.update_layer_number>, '__add__': <function Snowpack.__add__>, '__radd__': <function Snowpack.__radd__>, '__iadd__': <function Snowpack.__iadd__>, 'to_dataframe': <function Snowpack.to_dataframe>, '__repr__': <function Snowpack.__repr__>, '_repr_html_': <function Snowpack._repr_html_>, '__dict__': <attribute '__dict__' of 'Snowpack' objects>, '__weakref__': <attribute '__weakref__' of 'Snowpack' objects>})
__doc__ = 'holds the description of the snowpack, including the layers, interfaces, and the substrate\n\n'
__module__ = 'smrt.core.snowpack'
__weakref__

list of weak references to the object (if defined)

smrt.core.test_globalconstants module

smrt.core.test_interface module

smrt.core.test_layer module

smrt.core.test_lib module

setup_func_sp()
setup_func_em(testpack=None)

smrt.core.test_result module

smrt.core.test_sensor module

smrt.core.test_snowpack module

create_two_snowpacks()

Module contents

The core package contains the SMRT machinery. It provides the infrastructure that provides basic objects and orchestrates the “science” modules in the other packages (such as smrt.emmodel or smrt.rtsolver).

Amongst all, we suggest looking at the documentation of the Result object.

For developers

We strongly warn against changing anything in this directory. In principle this is not needed because no “science” is present and most objects and functions are generic enough to be extendable from outside (without affecting the core definition). Ask advice from the authors if you really want to change something here.