Specifying the Atmosphere

One of the most important and complicated steps in constructing a radiative transfer calculation is building a representation of the atmosphere. To perform a radiative transfer calculation, a few things are needed:

  • A set of constituent molecules which make up the atmosphere. For each of these molecules we need to know the amount of the molecule, specified with sasktran.Climatology, and the scattering/absorption cross sections, specified as a sasktran.OpticalProperty. The combination of these two objects is a sasktran.Species.

  • A sasktran.Climatology that provides the pressure and temperature profiles of the atmosphere, this is often referred to as the atmospheric state. These profiles are used when calculating cross sections of the atmospheric constitutents. By default this is sasktran.MSIS90

  • A sasktran.BRDF object which describes the reflectance of the surface of the Earth. This could be as simple as a constant number between 0–1 indicating a Lambertian surface.

All of these things are combined together with the sasktran.Atmosphere class which is the input to the radiative transfer model.


A sasktran.Climatology object is essentially a lookup table of profiles where the tables keys are quantities name. A grid (altitude and potentially geographic) definition is also associated.

Users can defined their own user defined climatologies using the sasktran.ClimatologyUserDefined class. Some climatologies that we use a lot are built into SASKTRAN (see `Useful Climatology Shorthands`_).

Available Climatologies

sasktran.ClimatologyUserDefined(altitudes, …)

A special climatology which handles user defined values.


A two dimensional user defined climatology in altitude and angle within a user specified plane.

sasktran.ClimatologyUserDefined3D(lats, …)

A user defined climatology class for profiles which have a geographic dependence.


The Labow volume mixing ratio climatology of ozone.


A climatology for the NO2 number density based upon the Prather photo-chemical box model.

sasktran.MSIS90([include_o2, includes, …])

A climatology that implements the MSIS-90 atmospheric model, (Hedin 1991).


A climatology of number density, pressure, and temperature based on the ERA interim reanalysis.

sasktran.GloSSAC(wavelength_nm[, extend])

The global stratospheric aerosol extinction climatology at 8 wavelengths from 386-3400nm that spans from 1979-2016 and incorporates data from numerous satellite datasets.

Optical Properties

Available Optical Properties


An optical property object that provides Rayleigh molecular scattering in dry-air.


Tabulated high resolution cross-sections of O3 measured by Daumont, Brion and Malicet in the early 1990’s [1].



Calculates the absorption cross section of NO2 molecules from 230 nm to 1000 nm at 220 K to 294 K following [1]


Calculates the absorption cross section of NO2 molecules from 230 nm to 795 nm and 221K to 293K.

sasktran.HITRANChemical(chemical_name[, …])

Calculates the optical absorption and extinction of various atmospheric molecules using the Voigt line-shape and the HITRAN spectral line database.


Specialized OpticalProperty which supports Mie Aerosol calculations.


Generic optical property container that is applicable to a wide variety of optical properties.


Scattering non-spherical ice crystals based upon the database from Baum.


Calculates the absorption cross section of SO2 molecules from 227 nm to 420 nm at 298 K, 318 K, 338 K, and 358 K following [1] and [2].

The Species Object

The Species class is a combination of a Climatology and OpticalProperty, linking them together. In most cases creating the Species is as simple as:

import sasktran as sk

ozone_species = sk.Species(climatology=sk.Labow(), optical_property=sk.O3DBM())

The Species object can then be added to the Atmosphere object through:

atmosphere = sk.Atmosphere()

atmosphere['ozone'] = ozone_species

However, there can be issues with this simple approach if the Climatology used supports multiple species. For example, trying:

msis = sk.MSIS90(True)

air = sk.Species(climatology=msis, optical_property=sk.Rayleigh())

will raise the error ValueError: Could not automatically infer the species key, use species= one of [‘SKCLIMATOLOGY_PRESSURE_PA’, ‘SKCLIMATOLOGY_AIRNUMBERDENSITY_CM3’, ‘SKCLIMATOLOGY_TEMPERATURE_K’, ‘SKCLIMATOLOGY_O2_CM3’] this is because the msis object supports multiple atmospheric constituents, and which one was intended to be used could not automatically be determined. Here we need to do:

air = sk.Species(climatology=msis, optical_property=sk.Rayleigh(), species='SKCLIMATOLOGY_AIRNUMBERDENSITY_CM3')

this species can then be added to the Atmosphere object in the same way:

atmosphere['air'] = air

The Atmospheric State

The atmospheric state is a special Climatology which supports both pressure and temperature. These pressure and temperature profiles are used to calculate the cross sections of the atmospheric constituents, they are not used to define Rayleigh scattering within the atmosphere, that is done with a separate Climatology and OpticalProperty.

By default the atmospheric state is set to the MSIS90 climatology, however it can be changed through:

import sasktran as sk

atmosphere = sk.Atmosphere()

atmosphere.atmospheric_state = sk.ECMWF()

The atmospheric state climatology must support the two keys:



Thus if you are trying to set the atmospheric state as a UserDefinedClimatology it is necessary that both of these keys are supported.


The BRDF object controls the surface reflectance inside the radiative transfer model. This could be as simple as a scalar which represents an isotropically reflecting Lambertian surface:

import sasktran as sk

atmosphere = sk.Atmosphere()

atmosphere.brdf = 0.3

There are also many available special BRDF’s:

atmosphere.brdf = sk.Kokhanovsky()

Available BRDF’s


Class which implements a Lambertian Bidirectional Reflectance Distribution Function.

sasktran.Kokhanovsky(L, M)

Implementation of the snow BRDF from Kokhanovsky 2012.

sasktran.Roujean(surface[, spectral_region])

Implementation of the BRDF from Roujean 1992 for heterogenous surfaces.

sasktran.CoxMunk(wind_speed, water_index)

Implementation of the water BRDF based on Cox and Munk 1954 and Spurr 2002.

sasktran.Rahman(rho0, theta, k)

Implementation of the Semiempirical Rahman BRDF based on Rahman 1993 and Spurr 2002.

sasktran.Hapke(omega, delta, b0)

Implementation of a vegetation BRDF based on Hapke 2012 and Spurr 2002.

sasktran.MODIS(f_iso, f_vol, f_geo)

Implementation of the Ross-thick Li-sparse-reciprocal BRDF used in MODIS’ Albedo/BRDF product.

Kernel Based BRDF’s

For advanced users it is possible to combine multiple BRDF Kernels together to create a hybrid BRDF object. The main class which enables this is the LinearCombination object.:

import sasktran as sk

brdf = sk.LinearCombination()

brdf.kernels = [sk.Lambertian(0.3), sk.RoujeanKernel()]

Available Kernels


Implements the Roujean kernel from Roujean 1992 and Spurr 2002.

sasktran.LiKernel(name, crown_shape, …)

Base class for Li kernels from Wanner 1995 and Spurr 2002.

sasktran.LiSparseKernel(crown_shape, …)

The Li-sparse kernel models sparse canopy where mutual shadowing can be ignored.


The Li-sparse-reciprocal kernel is a variation on the Li-sparse kernel which allows the incident/viewing angles to be swapped without changing the BRDF’s value (reciprocal) - See the MODIS Albedo/BRDF ATBD.

sasktran.LiDenseKernel([crown_shape, …])

The Li-dense kernel models dense canopy where mutual shadowing cannot be ignored.


The Ross-thin kernel models canopies with a small leaf area index (LAI) - see Wanner 1995 and Spurr 2002.


The Ross-thick kernel models canopies with a large leaf area index (LAI) - see Wanner 1995 and Spurr 2002.