API Reference
Package Interface
pyRadtran — A complete Python wrapper for libRadtran radiative transfer.
- class pyradtran.AerosolBlock(*args, **kwargs)[source]
Bases:
ProtocolA mass-normalized aerosol species that can report its intensive optics.
- intensive(wl_um: ndarray, n_legendre: int = 32) SpeciesOptics[source]
- property mass_per_particle_kg: float
- name: str
- class pyradtran.AerosolModel(*, modify: list[AerosolModifyEntry] = <factory>)[source]
Bases:
UvspecOptionAbstract base class for all aerosol configurations.
Subclasses implement mode-specific
to_uvspec_lines(). The commonmodifycapability is handled here.- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- modify: list[AerosolModifyEntry]
- class pyradtran.AerosolModifyEntry(*, variable: str, action: str, value: float)[source]
Bases:
UvspecOptionA single aerosol_modify directive.
- variable
Property to modify (gg, ssa, tau, tau550).
- Type:
- action
How to modify (scale or set).
- Type:
- value
Numeric value.
- Type:
- action: str
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- validate_entry() AerosolModifyEntry[source]
- value: float
- variable: str
- class pyradtran.AttributionResult(full: Dataset, contributions: dict[str, Dataset])[source]
Bases:
objectFull-field run plus per-block contribution datasets.
- full: Dataset
- class pyradtran.BudgetResult(transmittance: ndarray, reflectance: ndarray, absorptance: ndarray, wavelength: ndarray)[source]
Bases:
objectSpectral transmittance / reflectance / absorptance of the column.
- absorptance: ndarray
- reflectance: ndarray
- transmittance: ndarray
- wavelength: ndarray
- class pyradtran.BulkSpecies(*, bulk: Any, name: str = 'BulkSpecies')[source]
Bases:
BaseModelSpecies backed by an aerosol3D BulkAerosolOpticsData.
The size-distribution integration is already done in aerosol3D; this class only rescales cross-sections to per-mass, resamples wavelength, and selects the Legendre convention. Duck-typed: accepts any object exposing the BulkAerosolOpticsData attributes (no hard aerosol3D import).
- bulk: Any
- intensive(wl_um: ndarray, n_legendre: int = 32) SpeciesOptics[source]
- property mass_per_particle_kg: float
Volume-weighted per-particle mass from the bulk size distribution.
- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- name: str
- class pyradtran.CompositeAerosol(*, modify: list[~pyradtran.models.aerosol.AerosolModifyEntry] = <factory>, pieces: ~typing.Annotated[list, ~annotated_types.MinLen(min_length=1)], wavelength_grid_um: ~typing.Annotated[list[float], ~annotated_types.MinLen(min_length=1)], altitude_grid_km: ~typing.Annotated[list[float], ~annotated_types.MinLen(min_length=2)], n_legendre: int = 32, output_dir: ~pathlib.Path | None = None)[source]
Bases:
AerosolModelExternally mix any number of Piece blocks via a single explicit-file path.
Each item in
piecesis aPiece(e.g.PlacedBlockorDirectLayerOpticsBlock). They are combined with scattering-optical-depth weighting and written as one explicit.master/.LAYERset. The old mutual-exclusion rules and the single-source shortcut are gone: one path regardless of piece count or type.- evaluate(wl_um=None, z_km=None, n_legendre=None) LayerOptics[source]
Return the mixed (externally combined) LayerOptics without writing files.
- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- n_legendre: int
- output_dir: Path | None
- pieces: list
- to_uvspec_lines() list[str][source]
Single execution path: every Piece -> LayerOptics -> combine -> explicit file.
- validate_grids() CompositeAerosol[source]
- class pyradtran.DataResolver(*, data_root: str | PathLike | None = None, bundled_only: bool = False)[source]
Bases:
objectResolve logical data references to absolute paths under the data root.
- property data_root: Path
The effective data_files_path used for this resolver.
- is_available(category: str, name: str) bool[source]
True if the asset is present on disk.
Unknown (category, name) – not in the bundled manifest – are treated as permissively available (assumed resolvable via an external data root).
- list_bundled(category: str | None = None) list[Asset][source]
List bundled assets, optionally filtered by category.
- resolve(category: str, name: str) Path[source]
Return the absolute path of an asset’s first file.
Raises FileNotFoundError if the (category, name) is unknown to the bundled manifest or its file is missing on disk.
- validate_scene(scene) list[ValidationIssue][source]
Check high-value data references in a Scene against available data.
Returns a list of ValidationIssue for references whose bundled-asset files are missing under the current data root. References absent from the bundled manifest are treated as permissively available (externally).
First batch covers: atmosphere profile, solar_flux_file, mol_abs_param, and OPAC aerosol library.
- class pyradtran.DirectLayerOpticsBlock(master_path: str, name: str = 'explicit_file')[source]
Bases:
objectDirect-route piece: a pre-computed explicit aerosol file set (.master + .LAYER).
The file already contains per-layer tau/ssa/pmom, so no
VerticalProfileis needed —to_layer_opticsparses the file directly. Wavelength resampling is not performed (v1): the requested grid must match the file’s grid.- master_path: str
- name: str = 'explicit_file'
- to_layer_optics(wl_um: ndarray, altitude_km, n_legendre: int = 32) LayerOptics[source]
- class pyradtran.ExponentialProfile(rho0_kg_m3: float, scale_height_km: float)[source]
Bases:
objectrho(z) = rho0 * exp(-z / H), evaluated at the requested altitudes (km).- rho0_kg_m3: float
- scale_height_km: float
- class pyradtran.IntegrationConfig(*, n_radius_grid: int = 200, radius_min_um: float = 0.001, radius_max_um: float = 100.0)[source]
Bases:
BaseModelConfiguration for size-distribution numerical integration.
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- n_radius_grid: int
- radius_max_um: float
- radius_min_um: float
- class pyradtran.LayerOptics(tau: ndarray[tuple[Any, ...], dtype[_ScalarT]], ssa: ndarray[tuple[Any, ...], dtype[_ScalarT]], g: ndarray[tuple[Any, ...], dtype[_ScalarT]], legendre_moments: ndarray[tuple[Any, ...], dtype[_ScalarT]])[source]
Bases:
objectExtensive optical properties per layer.
- class pyradtran.MassProfile(kg_m3_per_layer: tuple[float, ...])[source]
Bases:
objectExplicit per-layer mass concentration (kg/m^3).
Values are stored in descending-altitude layer order (matching the
altitude_grid_kmconvention used byCompositeAerosol).evaluatereturns them verbatim; the altitude argument is accepted only for interface compatibility withExponentialProfile.
- class pyradtran.MieSpecies(*, refractive_index: ~pyradtran.models.aerosol_composite.RefractiveIndex, size_distribution: ~pyradtran.models.aerosol_composite.SizeDistribution, particle_density_kg_m3: ~typing.Annotated[float, ~annotated_types.Gt(gt=0)], integration_config: ~pyradtran.models.aerosol_composite.IntegrationConfig = <factory>, phase_function: ~typing.Literal['hg', 'mie'] = 'hg', name: str = 'MieSpecies')[source]
Bases:
BaseModelMie-computed species from refractive index + size distribution.
- integration_config: IntegrationConfig
- intensive(wl_um: ndarray, n_legendre: int = 32) SpeciesOptics[source]
Compute mass-normalized intensive optical properties.
- Parameters:
wl_um – Wavelengths in micrometers.
n_legendre – Number of Legendre moments to generate. When
phase_function='mie', moments are projected from the real Mie phase function (S1/S2 -> Legendre); the default'hg'derives them from the Henyey-Greenstein approximationg**l.
- Returns:
SpeciesOptics with beta_ext_per_mass, ssa, g, and legendre_moments.
- property mass_per_particle_kg: float
Average particle mass = density * mean volume over the size distribution.
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- name: str
- particle_density_kg_m3: float
- phase_function: Literal['hg', 'mie']
- refractive_index: RefractiveIndex
- size_distribution: SizeDistribution
- class pyradtran.OpacCustom(*, species_file: Annotated[str, MinLen(min_length=1)], rh_pct: float = 50.0, species_names: list[str] | None = None, data_path: str | None = None, n_legendre: int = 32)[source]
Bases:
BaseModelFactory: fold a user OPAC species profile file into
PlacedBlockpieces.Like
OpacPresetbut the mass-concentration profile is a user-supplied ASCII file (same format asstandard_aerosol_files).- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- n_legendre: int
- rh_pct: float
- species_file: str
- to_composite(wavelength_grid_um, output_dir=None)[source]
Wrap
to_placed_blocks()in aCompositeAerosolon the profile grid.
- to_placed_blocks() list[source]
Return one
PlacedBlockper profile species with nonzero mass.
- validate_species() OpacCustom[source]
- class pyradtran.OpacPreset(*, name: OpacPresetName, rh_pct: float = 50.0, species_names: list[str] | None = None, data_path: str | None = None, n_legendre: int = 32)[source]
Bases:
BaseModelFactory: fold an OPAC preset mixture into LEGO
PlacedBlockpieces.Each species with nonzero mass in the preset profile becomes one
MieSpecies(OPAC refractive index + OPAC lognormal atrh_pct) using the real Mie phase function, placed via its preset mass column. The pieces drop intoCompositeAerosol(pieces=...)– the same path as bulk/Mie blocks. No precomputed OPAC tables are read; libRadtran ships only the ingredients (refractive index, size distribution, mass profile).- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- n_legendre: int
- name: OpacPresetName
- rh_pct: float
- to_composite(wavelength_grid_um, output_dir=None)[source]
Wrap
to_placed_blocks()in aCompositeAerosolon the preset grid.
- to_placed_blocks() list[source]
Return one
PlacedBlockper preset species with nonzero mass.
- validate_species() OpacPreset[source]
- class pyradtran.OpacPresetName(value)[source]
Bases:
StrEnumOPAC preset mixture profile names.
These correspond to files in data/aerosol/OPAC/standard_aerosol_files/.
- ANTARCTIC = 'antarctic'
- CONTINENTAL_AVERAGE = 'continental_average'
- CONTINENTAL_CLEAN = 'continental_clean'
- CONTINENTAL_POLLUTED = 'continental_polluted'
- DESERT = 'desert'
- DESERT_SPHEROIDS = 'desert_spheroids'
- MARITIME_CLEAN = 'maritime_clean'
- MARITIME_POLLUTED = 'maritime_polluted'
- MARITIME_TROPICAL = 'maritime_tropical'
- URBAN = 'urban'
- class pyradtran.Piece(*args, **kwargs)[source]
Bases:
ProtocolThe mixing contract: anything
CompositeAerosolaccepts produces per-layerLayerOpticson the shared (wavelength, altitude) grid.- name: str
- to_layer_optics(wl_um: ndarray, altitude_km, n_legendre: int = 32) LayerOptics[source]
- class pyradtran.PlacedBlock(block: AerosolBlock, profile: VerticalProfile, modify: tuple[AerosolModifyEntry, ...] = ())[source]
Bases:
objectIntensity-route piece: a mass-normalized species placed in the column.
Ports the non-OPAC path of
LoadedSpecies.evaluate: the block’s intensive optics are weighted by the profile’s per-layer mass and the layer thickness to give extensive per-layer optical properties.- block: AerosolBlock
- modify: tuple[AerosolModifyEntry, ...] = ()
- property name: str
- profile: VerticalProfile
- to_layer_optics(wl_um: ndarray, altitude_km, n_legendre: int = 32) LayerOptics[source]
- class pyradtran.RefractiveIndex(*, wavelength_um: Annotated[list[float], MinLen(min_length=2)], n_real: list[float], k_imag: Annotated[list[float], MinLen(min_length=1)])[source]
Bases:
BaseModelWavelength-dependent complex refractive index.
Interpolation is log-linear in wavelength.
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- validate_lengths_and_sorted() RefractiveIndex[source]
- class pyradtran.Runner[source]
Bases:
objectExecute uvspec simulations.
Usage:
result = Runner.execute(scene, data_path="/path/to/data") results = Runner.execute_many(scenes, max_workers=4)
Global defaults may be set once via
configure()so thatuvspec_exeanddata_pathdo not need to be repeated on every call:Runner.configure(uvspec_exe="/opt/libRadtran/bin/uvspec", data_path="/opt/libRadtran/data") result = Runner.execute(scene)
- classmethod configure(config: RunnerConfig | None = None, **kwargs) RunnerConfig[source]
Set global default configuration for all Runner executions.
- Parameters:
config – A complete
RunnerConfiginstance, orNone.**kwargs – Individual fields (e.g.
uvspec_exe=..., data_path=...).
- Returns:
The newly set configuration.
- static execute(scene: Scene, uvspec_exe: str | None = None, data_path: str | None = None, keep_temp: bool | None = None, timeout: int | None = None, strict: bool | None = None, config: RunnerConfig | None = None) xr.Dataset[source]
Execute a single uvspec simulation.
- Parameters:
scene – Configured Scene object.
uvspec_exe – Path to uvspec binary. Auto-detected if None.
data_path – Path to libRadtran data directory. Auto-detected if None.
keep_temp – Keep temporary files after execution.
timeout – Maximum execution time in seconds.
strict – If True, raise on missing data references; if None, defaults to
bundled_only(warnings only otherwise).config – Optional
RunnerConfigoverriding global defaults for this call only.
- Returns:
xarray.Dataset with simulation results.
- static execute_many(scenes: list[Scene], uvspec_exe: str | None = None, data_path: str | None = None, max_workers: int | None = None, keep_temp: bool | None = None, timeout: int | None = None, config: RunnerConfig | None = None) list[xr.Dataset][source]
Execute multiple uvspec simulations in parallel.
- Parameters:
scenes – List of configured Scene objects.
uvspec_exe – Path to uvspec binary. Auto-detected if None.
data_path – Path to libRadtran data directory. Auto-detected if None.
max_workers – Maximum parallel workers.
keep_temp – Keep temporary files after execution.
timeout – Maximum execution time in seconds per scene.
config – Optional
RunnerConfigoverriding global defaults.
- Returns:
List of xarray.Dataset results, one per scene.
- class pyradtran.RunnerConfig(uvspec_exe: str | None = None, data_path: str | None = None, max_workers: int = 4, keep_temp: bool = False, timeout: int | None = None, bundled_only: bool = False)[source]
Bases:
objectConfiguration for uvspec execution.
- uvspec_exe
Path to uvspec binary. Auto-detected via PATH if None.
- Type:
str | None
- data_path
Path to libRadtran data directory. Uses env vars if None.
- Type:
str | None
- max_workers
Maximum parallel workers for execute_many().
- Type:
- keep_temp
Keep temporary files after execution (for debugging).
- Type:
- timeout
Maximum uvspec execution time in seconds. None = no timeout.
- Type:
int | None
- bundled_only
Force use of the bundled data subset, ignoring env vars and explicit data_path. For reproducible runs / CI.
- Type:
- bundled_only: bool = False
- keep_temp: bool = False
- max_workers: int = 4
- class pyradtran.Scene(atmosphere: AtmosphereConfig | None = None, source: SourceConfig | None = None, wavelength: WavelengthConfig | None = None, solver: SolverConfig | None = None, output: OutputConfig | None = None, surface: SurfaceConfig | None = None, aerosol: AerosolModel | None = None, cloud: CloudConfig | None = None, mc: McConfig | None = None, sslidar: SslidarConfig | None = None, advanced: AdvancedConfig | None = None, three_d: ThreeDConfig | None = None, special: SpecialConfig | None = None, raw_keywords: list[tuple[str, str]] | None = None)[source]
Bases:
objectImmutable scene builder composing all uvspec configuration models.
Each set_*() method returns a new Scene via deepcopy. Use .clone() for an explicit copy.
Usage:
scene = ( Scene() .set_atmosphere(profile="us", altitude=2.663) .set_source_solar(sza=30.0) .set_wavelength(250.0, 1200.0) .set_solver(method="disort", streams=16) .set_output(quantities=["lambda", "edir"]) )
- build_input(data_files_path: str | None = None) str[source]
Build complete uvspec input text from this Scene.
- Raises:
ValueError – If required components are missing.
- set_aerosol(aerosol: AerosolModel) Scene[source]
Set aerosol configuration from an AerosolModel instance.
- set_aerosol_modify(variable: str, action: str, value: float) Scene[source]
Add an aerosol modification directive.
- Parameters:
variable – Property to modify (gg, ssa, tau, tau550).
action – Modification type (scale or set).
value – Numeric value.
- set_dynamic(method: str = 'dynamic_tenstream', iterations: int | None = None, **kwargs) Scene[source]
- class pyradtran.SizeDistribution(*, kind: Literal['lognormal', 'modified_gamma', 'discrete', 'monodisperse'], params: dict, number_density_per_m3: float = 1.0)[source]
Bases:
BaseModelAerosol particle size distribution.
- kind: Literal['lognormal', 'modified_gamma', 'discrete', 'monodisperse']
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- number_density_per_m3: float
- params: dict
- validate_params() SizeDistribution[source]
- class pyradtran.SpeciesOptics(beta_ext_per_mass: ndarray[tuple[Any, ...], dtype[_ScalarT]], ssa: ndarray[tuple[Any, ...], dtype[_ScalarT]], g: ndarray[tuple[Any, ...], dtype[_ScalarT]], legendre_moments: ndarray[tuple[Any, ...], dtype[_ScalarT]] | None = None)[source]
Bases:
objectMass-normalized intensive optical properties of an aerosol species.
- class pyradtran.TabulatedProfile(z_km: tuple[float, ...], kg_m3: tuple[float, ...])[source]
Bases:
objectMass concentration (kg/m^3) tabulated vs altitude (km).
Linear interpolation in altitude; outside
[z_min, z_max]the value is clipped to the nearest table entry.z_kmmay be ascending or descending. Used to place OPAC preset mass columns, which come on the preset’s own grid.
- class pyradtran.ThreeDConfig(*, atmosphere_file: str | None = None)[source]
Bases:
UvspecOption3D atmospheric field configuration.
Configures 3D atmospheric input fields for MYSTIC and dynamic tenstream solvers.
- atmosphere_file
Path to 3D atmospheric field NetCDF file.
- Type:
str | None
Note
3D cloud fields are specified through CloudConfig: scene.set_cloud(wc_file=(“3D”, “/path/to/cloud3d.nc”)) or scene.set_cloud(ic_file=(“3D”, “/path/to/ic3d.nc”)).
The ipa (independent pixel approximation) for 3D is enabled via McConfig.ipa=True or McConfig.tipa=”dir”/”dir3d”.
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class pyradtran.VerticalProfile(*args, **kwargs)[source]
Bases:
ProtocolColumn placement: returns mass concentration (kg/m^3) at each altitude.
- pyradtran.add_budget_vars(ds: Dataset, *, f_incident: str = 'edir') Dataset[source]
Return a copy of
dswithtransmittance/reflectance/absorptance.Conventions:
T = (edir+edn)@surface / f_incident@TOA,R = eup@TOA / f_incident@TOA,A = 1 - T - R. Surface = lowest zout level, TOA = highest zout level.
- pyradtran.compute_budget(ds: Dataset, *, f_incident: str = 'edir') BudgetResult[source]
Typed companion to
add_budget_vars()returning aBudgetResult.
- pyradtran.compute_component_attribution(build_scene: Callable, composite, execute_many: Callable[[list], list[Dataset]]) AttributionResult[source]
Compute per-block RT contributions by leave-one-out subtraction.
- Parameters:
build_scene – Callable mapping a (possibly leave-one-out) composite to a runnable
Scene.composite – A composite with
.piecesand.model_copy(update=...).execute_many – Callable running a list of scenes in parallel and returning the parsed datasets in the same order (e.g.
lambda scenes: Runner.execute_many(scenes, uvspec_exe=..., data_path=...)).
- Returns:
AttributionResultwhosecontributions[piece.name]isfull - leave_piece_out.
- pyradtran.evaluate_blocks_on_grid(comp, wl_um, z_km, n_legendre: int = 32) dict[str, Dataset][source]
Per-piece
(tau, rho)on the grid; one dataset per block name.taucomes from each piece’sto_layer_optics;rho_kg_m3is added only for pieces that carry aprofile(e.g.PlacedBlock).
- pyradtran.evaluate_composite_on_grid(comp, wl_um, z_km, n_legendre: int = 32) Dataset[source]
Evaluate the mixed composite optics on a (wavelength, layer) grid.
Calls
comp.evaluate(...)(pure analytic mixing — no RT) and wraps the resultingLayerOpticsas anxarray.Datasetwith alayerdimension indexed by layer-center altitude.
- pyradtran.od_to_mass_profile(block: AerosolBlock, tau_ref: float, ref_nm: float, altitude_km, scale_height_km: float) MassProfile[source]
Invert a target column optical depth into an exponential
MassProfile.The returned per-layer masses are chosen so that, evaluated on
altitude_kmwith the block’sbeta_ext_per_massatref_nm, they sum to exactlytau_ref:tau_ref = beta_ext_per_mass(ref) * sum_layers( rho_layer * dz )
This is the discrete, grid-exact inversion (the column OD the RT solver will actually see), replacing the example-side
compute_mass_profileglue.- Parameters:
block – An
AerosolBlockwith a positivebeta_ext_per_massat ref.tau_ref – Target column optical depth at
ref_nm(dimensionless).ref_nm – Reference wavelength in nm.
altitude_km – Layer-boundary altitudes in km, strictly descending.
scale_height_km – Exponential scale height H (km).
- Returns:
A
MassProfilewhose layers follow the exponential shape and whose column OD equalstau_ref.
- pyradtran.run_3d(atmosphere_file: str | None = None, profile: str = 'us', altitude: float = 0.0, sza: float = 30.0, wl_min: float = 300.0, wl_max: float = 2500.0, photons: int = 100000, ipa: bool = False, uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Run 3D Monte Carlo radiative transfer simulation.
- Parameters:
atmosphere_file – Path to 3D atmospheric field file.
profile – Standard atmosphere profile (for 1D fallback).
altitude – Surface altitude in km.
sza – Solar zenith angle in degrees.
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
photons – Number of Monte Carlo photons.
ipa – Use independent pixel approximation.
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with 3D radiative transfer results.
- pyradtran.run_cloudy_scene(ic_properties: str = 'fu', ic_tau: float | None = None, ic_habit: str | None = None, wc_properties: str | None = None, wc_tau: float | None = None, sza: float = 30.0, profile: str = 'us', altitude: float | str = 0.0, pwv: float = 5.0, ozone: float = 300.0, wl_min: float = 300.0, wl_max: float = 2500.0, albedo: float = 0.2, streams: int = 16, uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Run uvspec with cloud layer.
- Parameters:
ic_properties – Ice cloud parameterization (fu, yang, key, baum, etc.).
ic_tau – Ice cloud optical thickness (set via ic_modify).
ic_habit – Ice crystal habit type.
wc_properties – Water cloud parameterization (hu, echam4).
wc_tau – Water cloud optical thickness.
sza – Solar zenith angle in degrees.
profile – Atmospheric profile name.
altitude – Surface altitude in km.
pwv – Precipitable water vapor in mm.
ozone – Ozone column in DU.
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
albedo – Surface albedo.
streams – Number of DISORT streams.
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with irradiance vs wavelength.
- pyradtran.run_lidar(area: float = 1.0, E0: float = 0.1, efficiency: float = 0.5, position: float = 0.0, range_bin: float = 0.1, n_ranges: int = 100, profile: str = 'us', altitude: float = 0.0, wl_min: float = 300.0, wl_max: float = 1100.0, streams: int = 16, uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Run single scattering lidar simulation.
- Parameters:
area – Telescope area in m^2.
E0 – Pulse energy in Joules.
efficiency – Detector efficiency.
position – Lidar position in km.
range_bin – Range bin width in km.
n_ranges – Number of range bins.
profile – Atmospheric profile.
altitude – Surface altitude in km.
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
streams – Number of DISORT streams.
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with lidar signal vs range.
- pyradtran.run_polarized(profile: str = 'us', altitude: float = 0.0, sza: float = 30.0, wl_min: float = 250.0, wl_max: float = 1200.0, photons: int = 100000, streams: int = 16, uvspec_exe: str | None = None, data_path: str | None = None, output_dir: str | None = None) Dataset[source]
Run polarized Monte Carlo simulation.
- Parameters:
profile – Atmospheric profile.
altitude – Surface altitude in km.
sza – Solar zenith angle in degrees.
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
photons – Number of Monte Carlo photons.
streams – Number of streams (for correlated-k).
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with polarized radiance.
- pyradtran.run_satellite(geometry: str = 'MPS', pixel: tuple[int, int] | None = None, profile: str = 'us', sza: float = 60.0, wl_min: float = 300.0, wl_max: float = 2500.0, solver: str = 'disort', streams: int = 16, uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Run satellite-viewing radiative transfer simulation.
- Parameters:
geometry – Satellite geometry name (e.g., MPS, SENTINEL2A).
pixel – Optional (x, y) pixel coordinates for satellite_geometry file.
profile – Standard atmosphere profile.
sza – Solar zenith angle in degrees.
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
solver – RTE solver name.
streams – Number of angular streams.
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with satellite-view radiance/irradiance.
- pyradtran.run_solar_radiance(sza: float = 30.0, airmass: float | None = None, profile: str = 'us', altitude: float | str = 0.0, pwv: float = 5.0, ozone: float = 300.0, wl_min: float = 250.0, wl_max: float = 2500.0, albedo: float = 0.2, streams: int = 16, solver: str = 'disort', uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Calculate solar spectral radiance (direct + diffuse irradiance).
- Parameters:
sza – Solar zenith angle in degrees. Ignored if airmass is set.
airmass – Relative airmass. Overrides sza if provided.
profile – Atmospheric profile name.
altitude – Surface altitude in km, or a preset name.
pwv – Precipitable water vapor in mm.
ozone – Ozone column in DU.
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
albedo – Surface albedo.
streams – Number of DISORT streams.
solver – RTE solver name.
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with irradiance vs wavelength at TOA and surface.
- pyradtran.run_solar_transmittance(airmass: float = 1.0, pwv: float = 5.0, ozone: float = 300.0, profile: str = 'us', altitude: float | str = 0.0, wl_min: float = 250.0, wl_max: float = 1200.0, albedo: float = 0.0, streams: int = 16, uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Calculate solar spectral transmittance.
- Parameters:
airmass – Relative airmass (1.0 = zenith).
pwv – Precipitable water vapor in mm (mol_modify H2O).
ozone – Ozone column in DU (mol_modify O3).
profile – Atmospheric profile name (us, ms, mw, tp, ss, sw).
altitude – Surface altitude in km, or a preset name (“LSST”, “CTIO”).
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
albedo – Surface albedo.
streams – Number of DISORT streams.
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with transmittance vs wavelength.
- pyradtran.run_thermal_brightness(pwv: float = 10.0, profile: str = 'ms', altitude: float = 0.0, wl_min: float = 2500.0, wl_max: float = 50000.0, sur_temperature: float | None = None, streams: int = 16, uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Calculate thermal infrared brightness temperature.
- pyradtran.run_with_opac_custom(species_file: str, rh_pct: float = 50.0, species_names: list[str] | None = None, aerosol_wavelength_step_nm: float = 50.0, output_dir: str | None = None, sza: float = 30.0, profile: str = 'us', altitude: float | str = 0.0, pwv: float = 5.0, ozone: float = 300.0, wl_min: float = 300.0, wl_max: float = 2500.0, albedo: float = 0.2, streams: int = 16, uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Run uvspec with OPAC custom species profile.
- Parameters:
species_file – Path to an ASCII species mass concentration profile file.
rh_pct – Relative humidity (%) for hygroscopic species; snapped to nearest OPAC level.
aerosol_wavelength_step_nm – Spacing of the folded aerosol wavelength grid (nm).
output_dir – Directory for the folded explicit aerosol files (default cwd/aerosol).
species_names – Optional species filter.
sza – Solar zenith angle in degrees.
profile – Atmospheric profile name.
altitude – Surface altitude in km.
pwv – Precipitable water vapor in mm.
ozone – Ozone column in DU.
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
albedo – Surface albedo.
streams – Number of DISORT streams.
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with irradiance vs wavelength.
- pyradtran.run_with_opac_preset(preset: str | OpacPresetName, rh_pct: float = 50.0, species_names: list[str] | None = None, aerosol_wavelength_step_nm: float = 50.0, output_dir: str | None = None, sza: float = 30.0, profile: str = 'us', altitude: float | str = 0.0, pwv: float = 5.0, ozone: float = 300.0, wl_min: float = 300.0, wl_max: float = 2500.0, albedo: float = 0.2, streams: int = 16, uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Run uvspec with OPAC preset mixture profile.
- Parameters:
preset – OPAC preset name (e.g. “continental_average”) or OpacPresetName enum.
rh_pct – Relative humidity (%) for hygroscopic species; snapped to nearest OPAC level.
aerosol_wavelength_step_nm – Spacing of the folded aerosol wavelength grid (nm).
output_dir – Directory for the folded explicit aerosol files (default cwd/aerosol).
species_names – Optional species filter (e.g. [“inso”, “soot”]).
sza – Solar zenith angle in degrees.
profile – Atmospheric profile name.
altitude – Surface altitude in km.
pwv – Precipitable water vapor in mm.
ozone – Ozone column in DU.
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
albedo – Surface albedo.
streams – Number of DISORT streams.
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with irradiance vs wavelength.
Scene
Scene builder with immutable chain API.
Scene composes all Pydantic models into a complete uvspec configuration. Each set_*() method returns a NEW Scene via copy.deepcopy() to avoid mutability traps.
- class pyradtran.scene.Scene(atmosphere: AtmosphereConfig | None = None, source: SourceConfig | None = None, wavelength: WavelengthConfig | None = None, solver: SolverConfig | None = None, output: OutputConfig | None = None, surface: SurfaceConfig | None = None, aerosol: AerosolModel | None = None, cloud: CloudConfig | None = None, mc: McConfig | None = None, sslidar: SslidarConfig | None = None, advanced: AdvancedConfig | None = None, three_d: ThreeDConfig | None = None, special: SpecialConfig | None = None, raw_keywords: list[tuple[str, str]] | None = None)[source]
Bases:
objectImmutable scene builder composing all uvspec configuration models.
Each set_*() method returns a new Scene via deepcopy. Use .clone() for an explicit copy.
Usage:
scene = ( Scene() .set_atmosphere(profile="us", altitude=2.663) .set_source_solar(sza=30.0) .set_wavelength(250.0, 1200.0) .set_solver(method="disort", streams=16) .set_output(quantities=["lambda", "edir"]) )
- build_input(data_files_path: str | None = None) str[source]
Build complete uvspec input text from this Scene.
- Raises:
ValueError – If required components are missing.
- set_aerosol(aerosol: AerosolModel) Scene[source]
Set aerosol configuration from an AerosolModel instance.
- set_aerosol_modify(variable: str, action: str, value: float) Scene[source]
Add an aerosol modification directive.
- Parameters:
variable – Property to modify (gg, ssa, tau, tau550).
action – Modification type (scale or set).
value – Numeric value.
- set_dynamic(method: str = 'dynamic_tenstream', iterations: int | None = None, **kwargs) Scene[source]
Runner
Subprocess execution engine for uvspec.
Runner is decoupled from Scene. Scene holds configuration; Runner executes it by building input, running uvspec, and parsing output.
- class pyradtran.core.runner.Runner[source]
Bases:
objectExecute uvspec simulations.
Usage:
result = Runner.execute(scene, data_path="/path/to/data") results = Runner.execute_many(scenes, max_workers=4)
Global defaults may be set once via
configure()so thatuvspec_exeanddata_pathdo not need to be repeated on every call:Runner.configure(uvspec_exe="/opt/libRadtran/bin/uvspec", data_path="/opt/libRadtran/data") result = Runner.execute(scene)
- classmethod configure(config: RunnerConfig | None = None, **kwargs) RunnerConfig[source]
Set global default configuration for all Runner executions.
- Parameters:
config – A complete
RunnerConfiginstance, orNone.**kwargs – Individual fields (e.g.
uvspec_exe=..., data_path=...).
- Returns:
The newly set configuration.
- static execute(scene: Scene, uvspec_exe: str | None = None, data_path: str | None = None, keep_temp: bool | None = None, timeout: int | None = None, strict: bool | None = None, config: RunnerConfig | None = None) xr.Dataset[source]
Execute a single uvspec simulation.
- Parameters:
scene – Configured Scene object.
uvspec_exe – Path to uvspec binary. Auto-detected if None.
data_path – Path to libRadtran data directory. Auto-detected if None.
keep_temp – Keep temporary files after execution.
timeout – Maximum execution time in seconds.
strict – If True, raise on missing data references; if None, defaults to
bundled_only(warnings only otherwise).config – Optional
RunnerConfigoverriding global defaults for this call only.
- Returns:
xarray.Dataset with simulation results.
- static execute_many(scenes: list[Scene], uvspec_exe: str | None = None, data_path: str | None = None, max_workers: int | None = None, keep_temp: bool | None = None, timeout: int | None = None, config: RunnerConfig | None = None) list[xr.Dataset][source]
Execute multiple uvspec simulations in parallel.
- Parameters:
scenes – List of configured Scene objects.
uvspec_exe – Path to uvspec binary. Auto-detected if None.
data_path – Path to libRadtran data directory. Auto-detected if None.
max_workers – Maximum parallel workers.
keep_temp – Keep temporary files after execution.
timeout – Maximum execution time in seconds per scene.
config – Optional
RunnerConfigoverriding global defaults.
- Returns:
List of xarray.Dataset results, one per scene.
- class pyradtran.core.runner.RunnerConfig(uvspec_exe: str | None = None, data_path: str | None = None, max_workers: int = 4, keep_temp: bool = False, timeout: int | None = None, bundled_only: bool = False)[source]
Bases:
objectConfiguration for uvspec execution.
- bundled_only
Force use of the bundled data subset, ignoring env vars and explicit data_path. For reproducible runs / CI.
- Type:
Core Utilities
Serialize Scene configuration to uvspec input text.
- pyradtran.core.input_builder.build_input_text(atmosphere: AtmosphereConfig, source: SourceConfig, wavelength: WavelengthConfig, solver: SolverConfig, output: OutputConfig, surface: SurfaceConfig | None = None, aerosol: AerosolModel | None = None, cloud: CloudConfig | None = None, mc: McConfig | None = None, sslidar: SslidarConfig | None = None, advanced: AdvancedConfig | None = None, three_d: ThreeDConfig | None = None, raw_keywords: list[tuple[str, str]] | None = None, data_files_path: str | None = None, special: SpecialConfig | None = None) str[source]
Build a complete uvspec input string from configuration models.
Keywords are collected as (phase, line) pairs from each model’s
to_uvspec_items()method, then sorted by phase to guarantee correct uvspec keyword ordering.- Phase assignments:
0 - data_files_path, include directives 1 - atmosphere 2 - source 3 - wavelength 4 - scattering/absorption switches (no_absorption, no_scattering) 5 - aerosol 6 - cloud 7 - surface 8 - solver 9 - output 10 - mc, sslidar 11 - three_d 12 - advanced 13 - raw_keywords (user-supplied, always last)
Parse uvspec output files into xarray.Dataset.
Supports both ASCII (default DISORT 7-column and output_user custom) and NetCDF output formats.
- pyradtran.core.output_parser.HEATING_RATE_COLUMN = 'heating_rate'
Name of the heating-rate data variable when libRadtran’s heat output is requested (e.g. via
solver.dynamic_heat_unit). The ASCII parser handles arbitrary column names; this constant pins the convention used across pyRadtran so callers and the viz layer agree on the variable name.
- pyradtran.core.output_parser.parse_output(output_path: str | Path, format: str = 'netcdf', n_zout: int = 1, column_names: list[str] | None = None, zout_levels_km: Sequence[float] | None = None) Dataset[source]
Parse uvspec output file into xarray.Dataset.
- Parameters:
output_path – Path to uvspec output file.
format – Output format — “netcdf” or “ascii”.
n_zout – Number of zout levels in output (for ASCII multi-level).
column_names – Custom column names for output_user ASCII output.
zout_levels_km – Physical zout altitudes in km. When provided (ASCII path), used as the
zoutcoordinate instead of an integer index.
- Returns:
xarray.Dataset with wavelength (and optionally zout) as coordinates.
- pyradtran.core.output_parser.resolve_zout_tokens(zout: Sequence[float | str], atmosphere_top_km: float = 120.0) list[float][source]
Resolve uvspec
zouttokens (which may contain"toa"/"surface") into numeric altitudes in km above ground level.- Parameters:
zout – Output levels as given to uvspec (floats and/or keyword strings).
atmosphere_top_km – Altitude (km) to which
"toa"/"top"resolve.
- Returns:
List of float altitudes in km, same length and order as
zout.
Temporary file lifecycle management for uvspec data files.
- class pyradtran.core.tempfile_manager.TempFileManager(temp_dir: str | None = None, keep_temp: bool = False)[source]
Bases:
objectManage temporary data files for uvspec execution.
- Parameters:
temp_dir – Directory for temporary files. Defaults to system temp.
keep_temp – If True, don’t delete files on cleanup (for debugging).
Usage:
with TempFileManager() as mgr: path = mgr.write_array("extinction.dat", extinction_data) # files cleaned up on exit
Convenience Functions
High-level convenience functions for common radiative transfer tasks.
- pyradtran.convenience.run_3d(atmosphere_file: str | None = None, profile: str = 'us', altitude: float = 0.0, sza: float = 30.0, wl_min: float = 300.0, wl_max: float = 2500.0, photons: int = 100000, ipa: bool = False, uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Run 3D Monte Carlo radiative transfer simulation.
- Parameters:
atmosphere_file – Path to 3D atmospheric field file.
profile – Standard atmosphere profile (for 1D fallback).
altitude – Surface altitude in km.
sza – Solar zenith angle in degrees.
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
photons – Number of Monte Carlo photons.
ipa – Use independent pixel approximation.
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with 3D radiative transfer results.
- pyradtran.convenience.run_cloudy_scene(ic_properties: str = 'fu', ic_tau: float | None = None, ic_habit: str | None = None, wc_properties: str | None = None, wc_tau: float | None = None, sza: float = 30.0, profile: str = 'us', altitude: float | str = 0.0, pwv: float = 5.0, ozone: float = 300.0, wl_min: float = 300.0, wl_max: float = 2500.0, albedo: float = 0.2, streams: int = 16, uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Run uvspec with cloud layer.
- Parameters:
ic_properties – Ice cloud parameterization (fu, yang, key, baum, etc.).
ic_tau – Ice cloud optical thickness (set via ic_modify).
ic_habit – Ice crystal habit type.
wc_properties – Water cloud parameterization (hu, echam4).
wc_tau – Water cloud optical thickness.
sza – Solar zenith angle in degrees.
profile – Atmospheric profile name.
altitude – Surface altitude in km.
pwv – Precipitable water vapor in mm.
ozone – Ozone column in DU.
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
albedo – Surface albedo.
streams – Number of DISORT streams.
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with irradiance vs wavelength.
- pyradtran.convenience.run_lidar(area: float = 1.0, E0: float = 0.1, efficiency: float = 0.5, position: float = 0.0, range_bin: float = 0.1, n_ranges: int = 100, profile: str = 'us', altitude: float = 0.0, wl_min: float = 300.0, wl_max: float = 1100.0, streams: int = 16, uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Run single scattering lidar simulation.
- Parameters:
area – Telescope area in m^2.
E0 – Pulse energy in Joules.
efficiency – Detector efficiency.
position – Lidar position in km.
range_bin – Range bin width in km.
n_ranges – Number of range bins.
profile – Atmospheric profile.
altitude – Surface altitude in km.
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
streams – Number of DISORT streams.
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with lidar signal vs range.
- pyradtran.convenience.run_polarized(profile: str = 'us', altitude: float = 0.0, sza: float = 30.0, wl_min: float = 250.0, wl_max: float = 1200.0, photons: int = 100000, streams: int = 16, uvspec_exe: str | None = None, data_path: str | None = None, output_dir: str | None = None) Dataset[source]
Run polarized Monte Carlo simulation.
- Parameters:
profile – Atmospheric profile.
altitude – Surface altitude in km.
sza – Solar zenith angle in degrees.
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
photons – Number of Monte Carlo photons.
streams – Number of streams (for correlated-k).
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with polarized radiance.
- pyradtran.convenience.run_satellite(geometry: str = 'MPS', pixel: tuple[int, int] | None = None, profile: str = 'us', sza: float = 60.0, wl_min: float = 300.0, wl_max: float = 2500.0, solver: str = 'disort', streams: int = 16, uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Run satellite-viewing radiative transfer simulation.
- Parameters:
geometry – Satellite geometry name (e.g., MPS, SENTINEL2A).
pixel – Optional (x, y) pixel coordinates for satellite_geometry file.
profile – Standard atmosphere profile.
sza – Solar zenith angle in degrees.
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
solver – RTE solver name.
streams – Number of angular streams.
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with satellite-view radiance/irradiance.
- pyradtran.convenience.run_solar_radiance(sza: float = 30.0, airmass: float | None = None, profile: str = 'us', altitude: float | str = 0.0, pwv: float = 5.0, ozone: float = 300.0, wl_min: float = 250.0, wl_max: float = 2500.0, albedo: float = 0.2, streams: int = 16, solver: str = 'disort', uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Calculate solar spectral radiance (direct + diffuse irradiance).
- Parameters:
sza – Solar zenith angle in degrees. Ignored if airmass is set.
airmass – Relative airmass. Overrides sza if provided.
profile – Atmospheric profile name.
altitude – Surface altitude in km, or a preset name.
pwv – Precipitable water vapor in mm.
ozone – Ozone column in DU.
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
albedo – Surface albedo.
streams – Number of DISORT streams.
solver – RTE solver name.
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with irradiance vs wavelength at TOA and surface.
- pyradtran.convenience.run_solar_transmittance(airmass: float = 1.0, pwv: float = 5.0, ozone: float = 300.0, profile: str = 'us', altitude: float | str = 0.0, wl_min: float = 250.0, wl_max: float = 1200.0, albedo: float = 0.0, streams: int = 16, uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Calculate solar spectral transmittance.
- Parameters:
airmass – Relative airmass (1.0 = zenith).
pwv – Precipitable water vapor in mm (mol_modify H2O).
ozone – Ozone column in DU (mol_modify O3).
profile – Atmospheric profile name (us, ms, mw, tp, ss, sw).
altitude – Surface altitude in km, or a preset name (“LSST”, “CTIO”).
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
albedo – Surface albedo.
streams – Number of DISORT streams.
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with transmittance vs wavelength.
- pyradtran.convenience.run_thermal_brightness(pwv: float = 10.0, profile: str = 'ms', altitude: float = 0.0, wl_min: float = 2500.0, wl_max: float = 50000.0, sur_temperature: float | None = None, streams: int = 16, uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Calculate thermal infrared brightness temperature.
- pyradtran.convenience.run_with_opac_custom(species_file: str, rh_pct: float = 50.0, species_names: list[str] | None = None, aerosol_wavelength_step_nm: float = 50.0, output_dir: str | None = None, sza: float = 30.0, profile: str = 'us', altitude: float | str = 0.0, pwv: float = 5.0, ozone: float = 300.0, wl_min: float = 300.0, wl_max: float = 2500.0, albedo: float = 0.2, streams: int = 16, uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Run uvspec with OPAC custom species profile.
- Parameters:
species_file – Path to an ASCII species mass concentration profile file.
rh_pct – Relative humidity (%) for hygroscopic species; snapped to nearest OPAC level.
aerosol_wavelength_step_nm – Spacing of the folded aerosol wavelength grid (nm).
output_dir – Directory for the folded explicit aerosol files (default cwd/aerosol).
species_names – Optional species filter.
sza – Solar zenith angle in degrees.
profile – Atmospheric profile name.
altitude – Surface altitude in km.
pwv – Precipitable water vapor in mm.
ozone – Ozone column in DU.
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
albedo – Surface albedo.
streams – Number of DISORT streams.
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with irradiance vs wavelength.
- pyradtran.convenience.run_with_opac_preset(preset: str | OpacPresetName, rh_pct: float = 50.0, species_names: list[str] | None = None, aerosol_wavelength_step_nm: float = 50.0, output_dir: str | None = None, sza: float = 30.0, profile: str = 'us', altitude: float | str = 0.0, pwv: float = 5.0, ozone: float = 300.0, wl_min: float = 300.0, wl_max: float = 2500.0, albedo: float = 0.2, streams: int = 16, uvspec_exe: str | None = None, data_path: str | None = None) Dataset[source]
Run uvspec with OPAC preset mixture profile.
- Parameters:
preset – OPAC preset name (e.g. “continental_average”) or OpacPresetName enum.
rh_pct – Relative humidity (%) for hygroscopic species; snapped to nearest OPAC level.
aerosol_wavelength_step_nm – Spacing of the folded aerosol wavelength grid (nm).
output_dir – Directory for the folded explicit aerosol files (default cwd/aerosol).
species_names – Optional species filter (e.g. [“inso”, “soot”]).
sza – Solar zenith angle in degrees.
profile – Atmospheric profile name.
altitude – Surface altitude in km.
pwv – Precipitable water vapor in mm.
ozone – Ozone column in DU.
wl_min – Minimum wavelength in nm.
wl_max – Maximum wavelength in nm.
albedo – Surface albedo.
streams – Number of DISORT streams.
uvspec_exe – Path to uvspec binary.
data_path – Path to libRadtran data directory.
- Returns:
xarray.Dataset with irradiance vs wavelength.
Configuration Models
Base
Base class for all uvspec option models.
- class pyradtran.models.base.UvspecOption[source]
Bases:
BaseModelBase class for uvspec keyword group models.
All models are frozen (immutable) and reject extra fields to catch typos at the Python level rather than at uvspec runtime.
Subclasses must implement
to_uvspec_lines()to serialize their configuration to uvspec input file format.- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
Atmosphere
Atmosphere configuration model.
Maps to uvspec keywords: atmosphere_file, altitude, pressure, mol_modify, mol_abs_param.
Reference: libRadtran src_py/molecular_options.py, src_py/surface_options.py
- class pyradtran.models.atmosphere.AtmosphereConfig(*, profile: ~typing.Annotated[str, ~annotated_types.MinLen(min_length=1)], altitude: ~typing.Annotated[float, ~annotated_types.Ge(ge=-1000000.0), ~annotated_types.Le(le=1000000.0)] = 0.0, pressure: ~types.Annotated[float | None, ~annotated_types.Ge(ge=0), ~annotated_types.Le(le=1000000.0)] = None, mol_modify: list[tuple[str, float, str]] = <factory>, mol_abs_param: str | None = None, crs_model: dict[str, str] | list[dict[str, str]] | None = None, atm_z_grid: list[float] | None = None, radiosonde: bool = False, radiosonde_levels_only: bool = False, mol_file: list[dict[str, str]] | None = None, mol_tau_file: tuple[str, str] | None = None, rayleigh_depol: ~types.Annotated[float | None, ~annotated_types.Ge(ge=0.0), ~annotated_types.Le(le=1.0)] = None, raman: bool = False)[source]
Bases:
UvspecOptionAtmospheric profile and molecular absorption configuration.
- profile
Named AFGL atmosphere or path to custom atmosphere file. Shorthands: us, ms, mw, tp, ss, sw. Full names: US-standard, midlatitude_summer, midlatitude_winter, tropics, subarctic_summer, subarctic_winter.
- Type:
- mol_modify
List of (species, column_value, unit) tuples. Species: O3, O2, H2O, CO2, NO2, BRO, OCLO, HCHO, O4, SO2, CH4, N2O, CO, N2. Units: DU, CM_2, MM.
- mol_abs_param
Molecular absorption parameterization scheme string. Default is reptran coarse (handled by uvspec internally).
- Type:
str | None
- mol_file
List of molecular VMR profile files, each a dict with keys “species”, “file”, and optional “unit”.
- mol_tau_file
Molecular optical thickness file as (kind, filepath) tuple.
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- model_post_init(context: Any, /) None
This function is meant to behave like a BaseModel method to initialize private attributes.
It takes context as an argument since that’s what pydantic-core passes when calling it.
- Parameters:
self – The BaseModel instance.
context – The context.
- to_uvspec_items() list[tuple[int, str]][source]
Return (phase, keyword_line) pairs for priority-sorted output.
Subclasses may override to assign different phases to different keywords. Default phase is 9 (output section).
- to_uvspec_lines() list[str][source]
Serialize this configuration to uvspec input file lines.
- Returns:
List of strings, each being one line of a uvspec input file.
- validate_crs_model() AtmosphereConfig[source]
- validate_mol_modify_entries() AtmosphereConfig[source]
- validate_radiosonde() AtmosphereConfig[source]
Source
Source configuration model.
Maps to uvspec keywords: source, sza, phi0, day_of_year, solar_flux_file, umu, phi, latitude, longitude, time, time_interpolate, time_interval, earth_radius, sza_file, isotropic_source_toa.
Reference: libRadtran src_py/geometry_options.py, src_py/spectral_options.py
- class pyradtran.models.source.SourceConfig(*, source: ~typing.Annotated[str, _PydanticGeneralMetadata(pattern='^(solar|thermal)$')], sza: ~types.Annotated[float | None, ~annotated_types.Ge(ge=0.0), ~annotated_types.Le(le=180.0)] = None, phi0: ~types.Annotated[float | None, ~annotated_types.Ge(ge=-360.0), ~annotated_types.Le(le=360.0)] = None, day_of_year: ~types.Annotated[int | None, ~annotated_types.Ge(ge=1), ~annotated_types.Le(le=366)] = None, solar_flux_file: str | None = None, umu: list[float] = <factory>, phi: list[float] = <factory>, satellite_geometry: str | None = None, satellite_pixel: tuple[int, int] | None = None, latitude: tuple[str, int, int, int] | None = None, longitude: tuple[str, int, int, int] | None = None, time: str | None = None, time_interpolate: bool = False, time_interval: tuple[str, str] | None = None, earth_radius: ~types.Annotated[float | None, ~annotated_types.Ge(ge=0.0)] = None, sza_file: str | None = None, isotropic_source_toa: bool = False)[source]
Bases:
UvspecOptionSolar or thermal radiation source configuration.
- sza
Solar zenith angle in degrees [0, 180]. Required for solar source (unless sza_file or isotropic_source_toa is set).
- Type:
float | None
- satellite_pixel
Pixel coordinates (x, y) for satellite pixel-based geometry.
- latitude
Geographic latitude as (hemisphere, degrees, minutes, seconds).
- longitude
Geographic longitude as (hemisphere, degrees, minutes, seconds).
- check_satellite_consistency() SourceConfig[source]
- check_sza_for_solar() SourceConfig[source]
- check_sza_mutual_exclusion() SourceConfig[source]
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- to_uvspec_items() list[tuple[int, str]][source]
Return (phase, keyword_line) pairs for priority-sorted output.
Subclasses may override to assign different phases to different keywords. Default phase is 9 (output section).
Wavelength
Wavelength configuration model.
Maps to uvspec keywords: wavelength, spline, filter_function_file, wavelength_grid_file, wavelength_index, slit_function_file, spline_file, fluorescence, fluorescence_file, thermal_bands_file, thermal_bandwidth.
Reference: libRadtran src_py/spectral_options.py
- class pyradtran.models.wavelength.WavelengthConfig(*, wavelength_min: Annotated[float | None, Ge(ge=0), Le(le=1000000.0)] = None, wavelength_max: Annotated[float | None, Ge(ge=0), Le(le=1000000.0)] = None, unit: Annotated[str, _PydanticGeneralMetadata(pattern='^(nm|cm-1)$')] = 'nm', spline: str | None = None, filter_function_file: str | None = None, wavelength_grid_file: str | None = None, wavelength_index: tuple[int, int] | None = None, slit_function_file: str | None = None, spline_file: str | None = None, fluorescence: bool = False, fluorescence_file: str | None = None, thermal_bands_file: str | None = None, thermal_bandwidth: tuple[float, str] | None = None)[source]
Bases:
UvspecOptionSpectral range configuration.
- wavelength_min
Shortest wavelength (nm or cm-1), or single wavelength when wavelength_max is not set.
- Type:
float | None
- wavelength_max
Longest wavelength (nm or cm-1). Optional; when None, wavelength_min is treated as a single wavelength value.
- Type:
float | None
- wavelength_grid_file
Path to wavelength grid file (alternative to wavelength_min).
- Type:
str | None
- wavelength_index
Tuple of (start_index, end_index) for wavelength subset.
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- to_uvspec_items() list[tuple[int, str]][source]
Return (phase, keyword_line) pairs for priority-sorted output.
Subclasses may override to assign different phases to different keywords. Default phase is 9 (output section).
- to_uvspec_lines() list[str][source]
Serialize this configuration to uvspec input file lines.
- Returns:
List of strings, each being one line of a uvspec input file.
- validate_wavelength_set() WavelengthConfig[source]
Solver
Solver configuration model.
Maps to uvspec keywords: rte_solver, number_of_streams, pseudospherical, deltam.
Reference: libRadtran src_py/solver_options.py
- class pyradtran.models.solver.SolverConfig(*, method: str, streams: Annotated[int, Ge(ge=1)] = 6, pseudospherical: bool = False, deltam: bool = False, dynamic_iterations: Annotated[int | None, Ge(ge=0)] = None, dynamic_history: bool = False, dynamic_heat_unit: str | None = None, disort_intcor: str | None = None, disort_spherical_albedo: bool = False, schwarzschild_streams: Annotated[int | None, Ge(ge=1)] = None)[source]
Bases:
UvspecOptionRadiative transfer solver configuration.
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- to_uvspec_items() list[tuple[int, str]][source]
Return (phase, keyword_line) pairs for priority-sorted output.
Subclasses may override to assign different phases to different keywords. Default phase is 9 (output section).
- to_uvspec_lines() list[str][source]
Serialize this configuration to uvspec input file lines.
- Returns:
List of strings, each being one line of a uvspec input file.
- validate_solver() SolverConfig[source]
Output
Output configuration model.
Maps to uvspec keywords: output_user, output_quantity, output_process, output_format, quiet, verbose, zout, output_file.
Reference: libRadtran src_py/output_options.py
- class pyradtran.models.output.OutputConfig(*, quantities: list[str] = <factory>, quantity: str | None = None, process: str | None = None, format: str = 'ascii', quiet: bool = True, verbose: bool = False, zout: list[float | str] = <factory>, output_file: str | None = None, heating_rate: str | None = None, write_optical_properties: bool = False)[source]
Bases:
UvspecOptionOutput format and content configuration.
- zout
Output altitudes in km above ground level. Supports float values and special strings like “toa” and “boa”.
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- to_uvspec_items() list[tuple[int, str]][source]
Return (phase, keyword_line) pairs for priority-sorted output.
Subclasses may override to assign different phases to different keywords. Default phase is 9 (output section).
- to_uvspec_lines() list[str][source]
Serialize this configuration to uvspec input file lines.
- Returns:
List of strings, each being one line of a uvspec input file.
- validate_output() OutputConfig[source]
Surface
Surface configuration model.
Maps to uvspec keywords: albedo, albedo_file, albedo_map, albedo_library, sur_temperature, brdf_ambrals, brdf_hapke, brdf_rpv, brdf_cam, bpdf_litvinov, bpdf_maignan, bpdf_tsang_u10.
Reference: libRadtran src/uvspec_lex.l (surface/BRDF options)
- class pyradtran.models.surface.SurfaceConfig(*, albedo: Annotated[float | None, Ge(ge=0.0), Le(le=1.0)] = None, albedo_file: str | None = None, albedo_map: str | tuple[str, str] | None = None, albedo_library: str | None = None, sur_temperature: float | None = None, brdf_ambrals: dict[str, float] | None = None, brdf_hapke: dict[str, float] | None = None, brdf_rpv: dict[str, float] | None = None, brdf_cam: dict[str, float] | None = None, bpdf_litvinov: dict[str, float] | None = None, bpdf_maignan: dict[str, float] | None = None, bpdf_tsang_u10: Annotated[float | None, Ge(ge=0.0), Le(le=100.0)] = None, brdf_rossli_file: str | None = None, brdf_rossli_hotspot: bool = False, brdf_rpv_file: str | None = None, surface_type_map: str | None = None, surface_temperature_map: str | tuple[str, str, float] | None = None)[source]
Bases:
UvspecOptionSurface reflection and temperature configuration.
- albedo_map
Path to spatial albedo map NetCDF file, or tuple (path, variable).
- check_mutual_exclusion() SurfaceConfig[source]
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
Cloud
Cloud configuration model (Phase 2).
Maps to uvspec keywords: ic_file, ic_properties, ic_habit, ic_habit_yang2013, ic_modify, wc_file, wc_properties, wc_modify, cloudcover, cloud_overlap.
Reference: libRadtran src/uvspec_lex.l (cloud options)
- class pyradtran.models.cloud.CloudConfig(*, ic_properties: str | None = None, ic_file: tuple[str, str] | None=None, ic_habit: str | None = None, ic_habit_roughness: str | None = None, ic_modify: list[CloudModifyEntry] = <factory>, wc_properties: str | None = None, wc_file: tuple[str, str] | None=None, wc_modify: list[CloudModifyEntry] = <factory>, modify: list[CloudModifyEntry] = <factory>, cloud_cover_type: str | None = None, cloud_cover: Annotated[float | None, ~annotated_types.Ge(ge=0.0), ~annotated_types.Le(le=1.0)] = None, cloud_overlap: str | None = None, interpolate: bool = False, cloud_fraction_file: str | None = None, cloud_fraction_map: str | tuple[str, str, float] | None=None, wc_saturate: bool = False, ic_saturate: bool = False, wc_ipa: bool = False, wc_layer: Annotated[int | None, ~annotated_types.Ge(ge=0)] = None)[source]
Bases:
UvspecOptionCloud configuration for water and ice clouds.
- ic_modify
List of ice cloud modification directives.
- Type:
- wc_modify
List of water cloud modification directives.
- Type:
- ic_modify: list[CloudModifyEntry]
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- modify: list[CloudModifyEntry]
- to_uvspec_items() list[tuple[int, str]][source]
Return (phase, keyword_line) pairs for priority-sorted output.
Subclasses may override to assign different phases to different keywords. Default phase is 9 (output section).
- to_uvspec_lines() list[str][source]
Serialize this configuration to uvspec input file lines.
- Returns:
List of strings, each being one line of a uvspec input file.
- validate_cloud() CloudConfig[source]
- wc_modify: list[CloudModifyEntry]
- class pyradtran.models.cloud.CloudModifyEntry(*, variable: str, action: str, value: float)[source]
Bases:
UvspecOptionA single cloud modify directive (wc_modify or ic_modify).
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- validate_entry() CloudModifyEntry[source]
Monte Carlo
Monte Carlo (MYSTIC) configuration model.
Maps to uvspec keywords: mc_photons, mc_backward, mc_escape, mc_vroom, mc_polarisation, mc_randomseed, mc_minphotons, mc_maxscatters, mc_spectral_is, mc_delta_scaling, mc_rad_alpha, mc_backward_output, mc_forward_output, mc_backward_heat, mc_std, mc_jacobian, mc_progressbar, mc_surface_reflectalways, mc_spherical, mc_tenstream, mc_ipa, mc_tipa, mc_sensordirection, mc_sensorposition, mc_spherical3D_scene, mc_basename, mc_minscatters, mc_sun_angular_size.
Reference: libRadtran src_py/mc_options.py
- class pyradtran.models.mc.McConfig(*, photons: Annotated[int | None, Ge(ge=0)] = None, min_photons: Annotated[int | None, Ge(ge=0)] = None, backward: bool = False, backward_pixel_range: tuple[int, int, int, int] | None = None, escape: str | None = None, vroom: str | None = None, polarisation: bool = False, polarisation_state: Annotated[int | None, Ge(ge=-3), Le(le=4)] = None, random_seed: Annotated[int | None, Ge(ge=0), Le(le=1000000000000000)] = None, max_scatters: Annotated[int | None, Ge(ge=0)] = None, spectral_is: Annotated[float | None, Ge(ge=0), Le(le=1000000.0)] = None, delta_scaling_mucut: Annotated[float | None, Ge(ge=0.0), Le(le=1.0)] = None, delta_scaling_n_start: Annotated[int | None, Ge(ge=0)] = None, rad_alpha: Annotated[float | None, Ge(ge=0.0), Le(le=90.0)] = None, backward_output: str | None = None, backward_output_unit: str | None = None, forward_output: str | None = None, backward_heat: str | None = None, std: Annotated[float | None, Ge(ge=0.0)] = None, jacobian: str | None = None, jacobian_std: bool = False, progressbar: Annotated[int | None, Ge(ge=0), Le(le=3)] = None, surface_reflect_always: bool = False, photons_file: str | None = None, albedo_file: str | None = None, albedo_spectral_file: str | None = None, rossli_file: str | None = None, ambrals_spectral_file: str | None = None, rpv_spectral_file: str | None = None, bpdf: str | None = None, surface_parallel: bool = False, elevation_file: str | None = None, lidar_file: str | None = None, triangular_surface_file: str | None = None, spherical: str | None = None, tenstream: bool = False, ipa: bool = False, tipa: str | None = None, sensor_direction: tuple[float, float, float] | None = None, sensor_position: tuple[float, float, float] | None = None, spherical3d_scene: tuple[float, float, float, float] | None = None, basename: str | None = None, min_scatters: Annotated[int | None, Ge(ge=0)] = None, sun_angular_size: Annotated[float | None, Ge(ge=0.0), Le(le=10.0)] = None, relerr: Annotated[float | None, Ge(ge=0.0)] = None, coherent_backscatter: bool = False, nca: bool = False, aerosol_is: bool = False, bcond: str | None = None)[source]
Bases:
UvspecOptionMonte Carlo (MYSTIC) solver configuration.
- backward_pixel_range
Optional (ix_start, iy_start, ix_end, iy_end).
- spherical3d_scene
Spherical 3D scene bounds (lon_min, lat_min, lon_max, lat_max).
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- to_uvspec_items() list[tuple[int, str]][source]
Return (phase, keyword_line) pairs for priority-sorted output.
Subclasses may override to assign different phases to different keywords. Default phase is 9 (output section).
SSLidar
SSLidar (Single Scattering Lidar) configuration model.
Maps to uvspec keywords: sslidar, sslidar_nranges, sslidar_polarisation.
Reference: libRadtran src_py/geometry_options.py, src_py/solver_options.py
- class pyradtran.models.sslidar.SslidarConfig(*, area: Annotated[float | None, Ge(ge=0), Le(le=1000000.0)] = None, E0: Annotated[float | None, Ge(ge=0), Le(le=1000000.0)] = None, efficiency: Annotated[float | None, Ge(ge=0.0), Le(le=1.0)] = None, position: Annotated[float | None, Ge(ge=0), Le(le=1000000.0)] = None, range_bin: Annotated[float | None, Ge(ge=0), Le(le=1000000.0)] = None, n_ranges: Annotated[int | None, Ge(ge=1)] = None, polarisation: bool = False)[source]
Bases:
UvspecOptionSingle scattering lidar configuration.
Requires rte_solver sslidar.
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
3D Fields
3D atmosphere and cloud configuration model.
Maps to uvspec keywords: atmosphere_file (3D NetCDF fields).
Note: 3D cloud fields are specified via CloudConfig using wc_file=(“3D”, path) or ic_file=(“3D”, path), not through a separate keyword. The ipa_3d and output3D flags are set automatically by uvspec when tipa or MYSTIC is enabled.
Reference: libRadtran src/uvspec_lex.l (MYSTIC 3D options)
- class pyradtran.models.three_d.ThreeDConfig(*, atmosphere_file: str | None = None)[source]
Bases:
UvspecOption3D atmospheric field configuration.
Configures 3D atmospheric input fields for MYSTIC and dynamic tenstream solvers.
Note
3D cloud fields are specified through CloudConfig: scene.set_cloud(wc_file=(“3D”, “/path/to/cloud3d.nc”)) or scene.set_cloud(ic_file=(“3D”, “/path/to/ic3d.nc”)).
The ipa (independent pixel approximation) for 3D is enabled via McConfig.ipa=True or McConfig.tipa=”dir”/”dir3d”.
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
Advanced
Advanced options model.
Maps to uvspec keywords: fluorescence, fluorescence_file, raman.
Phase 3 scope. Phase 4 may add 3D, satellite geometry, dynamic solvers, etc.
Reference: libRadtran src_py/surface_options.py, src_py/solver_options.py
- class pyradtran.models.advanced.AdvancedConfig(*, fluorescence: Annotated[float | None, Ge(ge=0.0)] = None, fluorescence_file: str | None = None, raman: bool = False, raman_variant: str | None = None)[source]
Bases:
UvspecOptionAdvanced radiative transfer options.
- fluorescence_file
Path to wavelength-dependent fluorescence file. Mutually exclusive with fluorescence.
- Type:
str | None
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- to_uvspec_items() list[tuple[int, str]][source]
Return (phase, keyword_line) pairs for priority-sorted output.
Subclasses may override to assign different phases to different keywords. Default phase is 9 (output section).
- to_uvspec_lines() list[str][source]
Serialize this configuration to uvspec input file lines.
- Returns:
List of strings, each being one line of a uvspec input file.
- validate_advanced() AdvancedConfig[source]
Special
Special options model for scattering/absorption control and file includes.
Maps to uvspec keywords: no_absorption, no_scattering, no_scattering mol, include.
Reference: libRadtran src/uvspec_lex.l
- class pyradtran.models.special.SpecialConfig(*, no_absorption: bool = False, no_scattering: bool = False, no_scattering_mol: bool = False, include_files: list[str] = <factory>)[source]
Bases:
UvspecOptionSpecial options: scattering/absorption toggles and include files.
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- to_uvspec_lines() list[str][source]
Serialize this configuration to uvspec input file lines.
- Returns:
List of strings, each being one line of a uvspec input file.
- validate_scattering() SpecialConfig[source]
Aerosol Models
Standard Aerosol
Aerosol configuration models.
Provides a strict class hierarchy for aerosol configuration:
OpacPreset: OPAC preset mixture profiles (continental_average, maritime_clean, etc.)
OpacCustom: OPAC custom species profile files
Reference: libRadtran src/uvspec_lex.l (aerosol options) Reference: Hess et al. (1998), Bull. Amer. Meteor. Soc., 79, 831-844
- class pyradtran.models.aerosol.AerosolModel(*, modify: list[AerosolModifyEntry] = <factory>)[source]
Bases:
UvspecOptionAbstract base class for all aerosol configurations.
Subclasses implement mode-specific
to_uvspec_lines(). The commonmodifycapability is handled here.- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- modify: list[AerosolModifyEntry]
- class pyradtran.models.aerosol.AerosolModifyEntry(*, variable: str, action: str, value: float)[source]
Bases:
UvspecOptionA single aerosol_modify directive.
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- validate_entry() AerosolModifyEntry[source]
- class pyradtran.models.aerosol.OpacCustom(*, species_file: Annotated[str, MinLen(min_length=1)], rh_pct: float = 50.0, species_names: list[str] | None = None, data_path: str | None = None, n_legendre: int = 32)[source]
Bases:
BaseModelFactory: fold a user OPAC species profile file into
PlacedBlockpieces.Like
OpacPresetbut the mass-concentration profile is a user-supplied ASCII file (same format asstandard_aerosol_files).- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- to_composite(wavelength_grid_um, output_dir=None)[source]
Wrap
to_placed_blocks()in aCompositeAerosolon the profile grid.
- to_placed_blocks() list[source]
Return one
PlacedBlockper profile species with nonzero mass.
- validate_species() OpacCustom[source]
- class pyradtran.models.aerosol.OpacPreset(*, name: OpacPresetName, rh_pct: float = 50.0, species_names: list[str] | None = None, data_path: str | None = None, n_legendre: int = 32)[source]
Bases:
BaseModelFactory: fold an OPAC preset mixture into LEGO
PlacedBlockpieces.Each species with nonzero mass in the preset profile becomes one
MieSpecies(OPAC refractive index + OPAC lognormal atrh_pct) using the real Mie phase function, placed via its preset mass column. The pieces drop intoCompositeAerosol(pieces=...)– the same path as bulk/Mie blocks. No precomputed OPAC tables are read; libRadtran ships only the ingredients (refractive index, size distribution, mass profile).- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- name: OpacPresetName
- to_composite(wavelength_grid_um, output_dir=None)[source]
Wrap
to_placed_blocks()in aCompositeAerosolon the preset grid.
- to_placed_blocks() list[source]
Return one
PlacedBlockper preset species with nonzero mass.
- validate_species() OpacPreset[source]
- class pyradtran.models.aerosol.OpacPresetName(value)[source]
Bases:
StrEnumOPAC preset mixture profile names.
These correspond to files in data/aerosol/OPAC/standard_aerosol_files/.
- ANTARCTIC = 'antarctic'
- CONTINENTAL_AVERAGE = 'continental_average'
- CONTINENTAL_CLEAN = 'continental_clean'
- CONTINENTAL_POLLUTED = 'continental_polluted'
- DESERT = 'desert'
- DESERT_SPHEROIDS = 'desert_spheroids'
- MARITIME_CLEAN = 'maritime_clean'
- MARITIME_POLLUTED = 'maritime_polluted'
- MARITIME_TROPICAL = 'maritime_tropical'
- URBAN = 'urban'
Composite Aerosol
Composable aerosol optical-property models (Tier 1–4).
See design spec: docs/superpowers/specs/2026-04-27-composite-aerosol-design.md
- class pyradtran.models.aerosol_composite.BulkSpecies(*, bulk: Any, name: str = 'BulkSpecies')[source]
Bases:
BaseModelSpecies backed by an aerosol3D BulkAerosolOpticsData.
The size-distribution integration is already done in aerosol3D; this class only rescales cross-sections to per-mass, resamples wavelength, and selects the Legendre convention. Duck-typed: accepts any object exposing the BulkAerosolOpticsData attributes (no hard aerosol3D import).
- bulk: Any
- intensive(wl_um: ndarray, n_legendre: int = 32) SpeciesOptics[source]
- property mass_per_particle_kg: float
Volume-weighted per-particle mass from the bulk size distribution.
- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class pyradtran.models.aerosol_composite.CompositeAerosol(*, modify: list[~pyradtran.models.aerosol.AerosolModifyEntry] = <factory>, pieces: ~typing.Annotated[list, ~annotated_types.MinLen(min_length=1)], wavelength_grid_um: ~typing.Annotated[list[float], ~annotated_types.MinLen(min_length=1)], altitude_grid_km: ~typing.Annotated[list[float], ~annotated_types.MinLen(min_length=2)], n_legendre: int = 32, output_dir: ~pathlib.Path | None = None)[source]
Bases:
AerosolModelExternally mix any number of Piece blocks via a single explicit-file path.
Each item in
piecesis aPiece(e.g.PlacedBlockorDirectLayerOpticsBlock). They are combined with scattering-optical-depth weighting and written as one explicit.master/.LAYERset. The old mutual-exclusion rules and the single-source shortcut are gone: one path regardless of piece count or type.- evaluate(wl_um=None, z_km=None, n_legendre=None) LayerOptics[source]
Return the mixed (externally combined) LayerOptics without writing files.
- model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- to_uvspec_lines() list[str][source]
Single execution path: every Piece -> LayerOptics -> combine -> explicit file.
- validate_grids() CompositeAerosol[source]
- class pyradtran.models.aerosol_composite.IntegrationConfig(*, n_radius_grid: int = 200, radius_min_um: float = 0.001, radius_max_um: float = 100.0)[source]
Bases:
BaseModelConfiguration for size-distribution numerical integration.
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class pyradtran.models.aerosol_composite.LayerOptics(tau: ndarray[tuple[Any, ...], dtype[_ScalarT]], ssa: ndarray[tuple[Any, ...], dtype[_ScalarT]], g: ndarray[tuple[Any, ...], dtype[_ScalarT]], legendre_moments: ndarray[tuple[Any, ...], dtype[_ScalarT]])[source]
Bases:
objectExtensive optical properties per layer.
- class pyradtran.models.aerosol_composite.MieSpecies(*, refractive_index: ~pyradtran.models.aerosol_composite.RefractiveIndex, size_distribution: ~pyradtran.models.aerosol_composite.SizeDistribution, particle_density_kg_m3: ~typing.Annotated[float, ~annotated_types.Gt(gt=0)], integration_config: ~pyradtran.models.aerosol_composite.IntegrationConfig = <factory>, phase_function: ~typing.Literal['hg', 'mie'] = 'hg', name: str = 'MieSpecies')[source]
Bases:
BaseModelMie-computed species from refractive index + size distribution.
- integration_config: IntegrationConfig
- intensive(wl_um: ndarray, n_legendre: int = 32) SpeciesOptics[source]
Compute mass-normalized intensive optical properties.
- Parameters:
wl_um – Wavelengths in micrometers.
n_legendre – Number of Legendre moments to generate. When
phase_function='mie', moments are projected from the real Mie phase function (S1/S2 -> Legendre); the default'hg'derives them from the Henyey-Greenstein approximationg**l.
- Returns:
SpeciesOptics with beta_ext_per_mass, ssa, g, and legendre_moments.
- property mass_per_particle_kg: float
Average particle mass = density * mean volume over the size distribution.
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- phase_function: Literal['hg', 'mie']
- refractive_index: RefractiveIndex
- size_distribution: SizeDistribution
- class pyradtran.models.aerosol_composite.RefractiveIndex(*, wavelength_um: Annotated[list[float], MinLen(min_length=2)], n_real: list[float], k_imag: Annotated[list[float], MinLen(min_length=1)])[source]
Bases:
BaseModelWavelength-dependent complex refractive index.
Interpolation is log-linear in wavelength.
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- validate_lengths_and_sorted() RefractiveIndex[source]
- class pyradtran.models.aerosol_composite.SizeDistribution(*, kind: Literal['lognormal', 'modified_gamma', 'discrete', 'monodisperse'], params: dict, number_density_per_m3: float = 1.0)[source]
Bases:
BaseModelAerosol particle size distribution.
- kind: Literal['lognormal', 'modified_gamma', 'discrete', 'monodisperse']
- model_config = {'extra': 'forbid', 'frozen': True, 'populate_by_name': True, 'validate_by_alias': True, 'validate_by_name': True}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- validate_params() SizeDistribution[source]
- class pyradtran.models.aerosol_composite.SpeciesOptics(beta_ext_per_mass: ndarray[tuple[Any, ...], dtype[_ScalarT]], ssa: ndarray[tuple[Any, ...], dtype[_ScalarT]], g: ndarray[tuple[Any, ...], dtype[_ScalarT]], legendre_moments: ndarray[tuple[Any, ...], dtype[_ScalarT]] | None = None)[source]
Bases:
objectMass-normalized intensive optical properties of an aerosol species.
Aerosol Optics
Pure-NumPy Mie scattering (Bohren-Huffman algorithm).
No scipy dependency — uses only numpy for all computations.
- pyradtran.optics.mie.bhmie(x: float, m: complex, n_angles: int = 0) dict[source]
Compute Mie scattering for a single homogeneous sphere.
- Parameters:
x – Size parameter
2*pi*r/lambda.m – Complex refractive index relative to surrounding medium.
n_angles – Number of equally-spaced scattering angles between 0 and 180° for phase-function output. 0 = skip angular computation.
- Returns:
Qext: Extinction efficiency.Qsca: Scattering efficiency.Qback: Backscatter efficiency.g: Asymmetry parameter<cos(theta)>.S1,S2(if n_angles > 0): Complex amplitude functions.angles_deg(if n_angles > 0): Angle grid in degrees.
- Return type:
Dictionary with keys
- Reference:
Bohren & Huffman, Absorption and Scattering of Light by Small Particles, Wiley, 1983. Fortran code bhmie.f translated to Python/NumPy.
- pyradtran.optics.mie.integrate_size_distribution(*, wavelength_um: list[float], radius_um: list[float], Qext: ndarray, Qsca: ndarray, g: ndarray, legendre_moments: ndarray | None, size_distribution: SizeDistribution, particle_density_kg_m3: float, config: IntegrationConfig, n_legendre: int = 32) _SpeciesOptics[source]
Integrate Q-factors over size distribution to get intensive species optics.
- pyradtran.optics.mie.phase_function_to_legendre(s1: ndarray, s2: ndarray, angles_deg: ndarray, n_legendre: int) ndarray[source]
Project the unpolarised Mie phase function onto Legendre polynomials.
P(mu) ∝ |S1|^2 + |S2|^2, normalised so(1/2) ∫_{-1}^{1} P(mu) dmu = 1. Returnsbeta_l = (1/2) ∫_{-1}^{1} P(mu) P_l(mu) dmuforl = 0..n_legendre-1— the PMOM /g_lform (beta_0 = 1,beta_1= asymmetry parameter). Pure numpy (no scipy): Legendre polynomials via the Bonnet recurrence.
External mixing rules for aerosol optical properties.
- pyradtran.optics.mixing.combine_sources(sources: list, n_legendre: int) dict[source]
Externally mix N aerosol sources into a single LayerOptics-like dict.
- Parameters:
sources – List of LayerOptics objects.
n_legendre – Number of Legendre moments.
- Returns:
Dict with keys
tau,ssa,g,legendre_moments. All arrays have shape (n_wl, n_layer, …).
Writer for libRadtran aerosol_file explicit format.
- Produces:
master file: maps altitudes to .LAYER filenames
per-layer .LAYER files: wavelength_nm beta_ext_per_km ssa k_0 k_1 …
NULL.LAYER: zero-optical-depth placeholder
- pyradtran.optics.layer_writer.read_explicit_aerosol(master_path)[source]
Read a libRadtran explicit aerosol master + per-layer files.
Inverse of
write_explicit_aerosol(). Returns a 6-tuple(tau, ssa, g, legendre_moments, wavelength_um, altitude_km)wheretau/ssa/ghave shape(n_wl, n_layer)andlegendre_momentshas shape(n_wl, n_layer, n_legendre). The top NULL layer (zero optical thickness) is dropped.
- pyradtran.optics.layer_writer.write_explicit_aerosol(*, tau: ndarray, ssa: ndarray, g: ndarray, legendre_moments: ndarray, wavelength_um: ndarray, altitude_km: ndarray, output_dir: Path, source_signatures: list[str]) Path[source]
Write explicit aerosol files for libRadtran.
- Parameters:
tau – Optical depth per layer, shape (n_wl, n_layer).
ssa – Single-scattering albedo, shape (n_wl, n_layer).
g – Asymmetry parameter, shape (n_wl, n_layer).
legendre_moments – Legendre expansion coefficients, shape (n_wl, n_layer, n_legendre).
wavelength_um – Wavelength grid in um, shape (n_wl,).
altitude_km – Altitude boundaries in km, strictly descending, shape (n_layer+1,).
output_dir – Directory to write files.
source_signatures – Strings identifying sources (for hashing).
- Returns:
Path to the master file.
Readers for libRadtran OPAC ASCII ingredients.
OPAC ships only ingredients (no precomputed tables); libRadtran computes optics
at runtime via internal Mie. These parsers return pyRadtran data structures so
the existing MieSpecies path can fold OPAC species. Files live under
<data_root>/aerosol/OPAC/:
refractive_indices/<sp><rh>_refr.dat: 3-col (lambda_um n_real n_imag), 61 wl
size_distr.cfg: 7-col (no rh Rmin Rmax Rmod Rho Sigma)
standard_aerosol_files/<preset>.dat: z(km) x per-species mass columns (g/m^3)
- pyradtran.optics.opac.read_opac_preset_profile(name: str, *, data_path: str | Path | None = None) dict[str, tuple[ndarray, ndarray]][source]
Read
standard_aerosol_files/<name>.dat(wrapper over the file parser).
- pyradtran.optics.opac.read_opac_profile_file(path: str | Path) dict[str, tuple[ndarray, ndarray]][source]
Parse a standard aerosol profile file ->
{species: (z_km, mass_g_m3)}.The file is altitude (km) followed by one mass-concentration column (g/m^3) per OPAC species. A
#header line lists the species codes (after az(km)label); its species tokens map columns. If no header is found, the canonical 10-species order is assumed for the columns present. Altitude is returned in file order (standard presets are descending).
- pyradtran.optics.opac.read_opac_refractive_index(species: str, rh_pct: float = 50.0, *, data_path: str | Path | None = None) RefractiveIndex[source]
Read
<sp><rh>_refr.dat->RefractiveIndex.OPAC stores the imaginary part negative (its sign convention is
m = n - i*kappa); bhmie/Bohren-Huffman useIm(m) > 0for absorption, andRefractiveIndexrejectsk < 0. We therefore return the absolute value, soRefractiveIndex.at()yieldsm = n + i*k(k>0).
- pyradtran.optics.opac.read_opac_size_distribution(species: str, rh_pct: float = 50.0, *, data_path: str | Path | None = None) tuple[SizeDistribution, float][source]
Read the matching
size_distr.cfgrow.Columns:
no rh Rmin Rmax Rmod[um] Rho Sigma.Rhois treated as g/cm^3 (the values are physical densities; the cfg header label[g/m**3]is misleading) and returned as kg/m^3. Returns(lognormal SizeDistribution, density_kg_m3).
- pyradtran.optics.opac.snap_rh(species: str, rh_pct: float) int[source]
Snap a requested RH to the nearest available OPAC level for
species.Non-hygroscopic species only have RH=0 (the
00file); the request is ignored. Hygroscopic species snap to the nearest of the tabulated levels (ties round down to the lower level).
Presets
Site altitudes, standard atmosphere profiles, and common configurations.
Data Layer
Bundled libRadtran data + access layer.
Provides DataResolver for locating data files with a three-tier
priority (explicit path > environment variable > bundled subset) and an
optional bundled_only mode for reproducible runs.
- class pyradtran.data.Asset(category: str, name: str, uvspec_keyword: str, paths: tuple[str, ...])[source]
Bases:
objectA single bundled data asset.
- name
The user-facing reference value for the consuming uvspec keyword (e.g. “US-standard”, “kurudz_1.0nm.dat”, “reptran coarse”).
- Type:
- class pyradtran.data.DataResolver(*, data_root: str | PathLike | None = None, bundled_only: bool = False)[source]
Bases:
objectResolve logical data references to absolute paths under the data root.
- is_available(category: str, name: str) bool[source]
True if the asset is present on disk.
Unknown (category, name) – not in the bundled manifest – are treated as permissively available (assumed resolvable via an external data root).
- list_bundled(category: str | None = None) list[Asset][source]
List bundled assets, optionally filtered by category.
- resolve(category: str, name: str) Path[source]
Return the absolute path of an asset’s first file.
Raises FileNotFoundError if the (category, name) is unknown to the bundled manifest or its file is missing on disk.
- validate_scene(scene) list[ValidationIssue][source]
Check high-value data references in a Scene against available data.
Returns a list of ValidationIssue for references whose bundled-asset files are missing under the current data root. References absent from the bundled manifest are treated as permissively available (externally).
First batch covers: atmosphere profile, solar_flux_file, mol_abs_param, and OPAC aerosol library.
- class pyradtran.data.ValidationIssue(severity: str, category: str, name: str, message: str)[source]
Bases:
objectA single data-reference problem found when validating a Scene.
- pyradtran.data.get_data_root(*, bundled_only: bool = False)[source]
Return the effective data_files_path (convenience wrapper).
- pyradtran.data.list_bundled(category: str | None = None)[source]
List bundled assets (convenience wrapper).
- pyradtran.data.load_manifest() list[Asset][source]
Load bundled MANIFEST.toml into a list of Asset objects.
Returns an empty list when the manifest contains no
[[assets]]entries.
- pyradtran.data.resolve(category: str, name: str, *, bundled_only: bool = False)[source]
Resolve a logical reference to an absolute path (convenience wrapper).
DataResolver: locate libRadtran data files with tiered fallback.
- Resolution priority for the data root (
data_files_path): explicit
data_rootargument (user is most explicit)LIBRADTRAN_DATA_FILESenvironment variableLIBRADTRANDIRenvironment variable (itsdata/subdir)bundled subset at
pyradtran/data/assets
bundled_only=True overrides 1-3 and always uses the bundled root
(for reproducible runs / CI).
- class pyradtran.data.resolver.DataResolver(*, data_root: str | PathLike | None = None, bundled_only: bool = False)[source]
Bases:
objectResolve logical data references to absolute paths under the data root.
- is_available(category: str, name: str) bool[source]
True if the asset is present on disk.
Unknown (category, name) – not in the bundled manifest – are treated as permissively available (assumed resolvable via an external data root).
- list_bundled(category: str | None = None) list[Asset][source]
List bundled assets, optionally filtered by category.
- resolve(category: str, name: str) Path[source]
Return the absolute path of an asset’s first file.
Raises FileNotFoundError if the (category, name) is unknown to the bundled manifest or its file is missing on disk.
- validate_scene(scene) list[ValidationIssue][source]
Check high-value data references in a Scene against available data.
Returns a list of ValidationIssue for references whose bundled-asset files are missing under the current data root. References absent from the bundled manifest are treated as permissively available (externally).
First batch covers: atmosphere profile, solar_flux_file, mol_abs_param, and OPAC aerosol library.
Aerosol Building Blocks (LEGO)
LEGO aerosol blocks: unified interface for mixing any aerosol source.
Three-layer protocol (see spec 2026-06-18-lego-aerosol-blocks-design.md §4.2):
AerosolBlock—intensive(): the mass-normalized optical identity.
VerticalProfile— column placement (per-layer kg/m^3).
Piece—to_layer_optics(): the mixing contract (added in Task 3).
This module imports SpeciesOptics (and, from Task 3, LayerOptics)
from aerosol_composite; the reverse dependency is deferred (inside
CompositeAerosol methods) to avoid a circular import.
- class pyradtran.models.blocks.AerosolBlock(*args, **kwargs)[source]
Bases:
ProtocolA mass-normalized aerosol species that can report its intensive optics.
- intensive(wl_um: ndarray, n_legendre: int = 32) SpeciesOptics[source]
- class pyradtran.models.blocks.DirectLayerOpticsBlock(master_path: str, name: str = 'explicit_file')[source]
Bases:
objectDirect-route piece: a pre-computed explicit aerosol file set (.master + .LAYER).
The file already contains per-layer tau/ssa/pmom, so no
VerticalProfileis needed —to_layer_opticsparses the file directly. Wavelength resampling is not performed (v1): the requested grid must match the file’s grid.- to_layer_optics(wl_um: ndarray, altitude_km, n_legendre: int = 32) LayerOptics[source]
- class pyradtran.models.blocks.ExponentialProfile(rho0_kg_m3: float, scale_height_km: float)[source]
Bases:
objectrho(z) = rho0 * exp(-z / H), evaluated at the requested altitudes (km).
- class pyradtran.models.blocks.MassProfile(kg_m3_per_layer: tuple[float, ...])[source]
Bases:
objectExplicit per-layer mass concentration (kg/m^3).
Values are stored in descending-altitude layer order (matching the
altitude_grid_kmconvention used byCompositeAerosol).evaluatereturns them verbatim; the altitude argument is accepted only for interface compatibility withExponentialProfile.
- class pyradtran.models.blocks.Piece(*args, **kwargs)[source]
Bases:
ProtocolThe mixing contract: anything
CompositeAerosolaccepts produces per-layerLayerOpticson the shared (wavelength, altitude) grid.- to_layer_optics(wl_um: ndarray, altitude_km, n_legendre: int = 32) LayerOptics[source]
- class pyradtran.models.blocks.PlacedBlock(block: AerosolBlock, profile: VerticalProfile, modify: tuple[AerosolModifyEntry, ...] = ())[source]
Bases:
objectIntensity-route piece: a mass-normalized species placed in the column.
Ports the non-OPAC path of
LoadedSpecies.evaluate: the block’s intensive optics are weighted by the profile’s per-layer mass and the layer thickness to give extensive per-layer optical properties.- block: AerosolBlock
- modify: tuple[AerosolModifyEntry, ...] = ()
- profile: VerticalProfile
- to_layer_optics(wl_um: ndarray, altitude_km, n_legendre: int = 32) LayerOptics[source]
- class pyradtran.models.blocks.TabulatedProfile(z_km: tuple[float, ...], kg_m3: tuple[float, ...])[source]
Bases:
objectMass concentration (kg/m^3) tabulated vs altitude (km).
Linear interpolation in altitude; outside
[z_min, z_max]the value is clipped to the nearest table entry.z_kmmay be ascending or descending. Used to place OPAC preset mass columns, which come on the preset’s own grid.
- class pyradtran.models.blocks.VerticalProfile(*args, **kwargs)[source]
Bases:
ProtocolColumn placement: returns mass concentration (kg/m^3) at each altitude.
- pyradtran.models.blocks.od_to_mass_profile(block: AerosolBlock, tau_ref: float, ref_nm: float, altitude_km, scale_height_km: float) MassProfile[source]
Invert a target column optical depth into an exponential
MassProfile.The returned per-layer masses are chosen so that, evaluated on
altitude_kmwith the block’sbeta_ext_per_massatref_nm, they sum to exactlytau_ref:tau_ref = beta_ext_per_mass(ref) * sum_layers( rho_layer * dz )
This is the discrete, grid-exact inversion (the column OD the RT solver will actually see), replacing the example-side
compute_mass_profileglue.- Parameters:
block – An
AerosolBlockwith a positivebeta_ext_per_massat ref.tau_ref – Target column optical depth at
ref_nm(dimensionless).ref_nm – Reference wavelength in nm.
altitude_km – Layer-boundary altitudes in km, strictly descending.
scale_height_km – Exponential scale height H (km).
- Returns:
A
MassProfilewhose layers follow the exponential shape and whose column OD equalstau_ref.
Postprocessing
Pure dataset post-processing for RT outputs (no Runner / no libRadtran).
Transforms raw parsed flux datasets into physically meaningful quantities.
Kept separate from pyradtran.viz so the same derivations serve numeric
use (logging, NetCDF export, comparisons) without importing matplotlib.
- class pyradtran.core.postprocess.BudgetResult(transmittance: ndarray, reflectance: ndarray, absorptance: ndarray, wavelength: ndarray)[source]
Bases:
objectSpectral transmittance / reflectance / absorptance of the column.
- pyradtran.core.postprocess.add_budget_vars(ds: Dataset, *, f_incident: str = 'edir') Dataset[source]
Return a copy of
dswithtransmittance/reflectance/absorptance.Conventions:
T = (edir+edn)@surface / f_incident@TOA,R = eup@TOA / f_incident@TOA,A = 1 - T - R. Surface = lowest zout level, TOA = highest zout level.
- pyradtran.core.postprocess.compute_budget(ds: Dataset, *, f_incident: str = 'edir') BudgetResult[source]
Typed companion to
add_budget_vars()returning aBudgetResult.
- pyradtran.core.postprocess.evaluate_blocks_on_grid(comp, wl_um, z_km, n_legendre: int = 32) dict[str, Dataset][source]
Per-piece
(tau, rho)on the grid; one dataset per block name.taucomes from each piece’sto_layer_optics;rho_kg_m3is added only for pieces that carry aprofile(e.g.PlacedBlock).
- pyradtran.core.postprocess.evaluate_composite_on_grid(comp, wl_um, z_km, n_legendre: int = 32) Dataset[source]
Evaluate the mixed composite optics on a (wavelength, layer) grid.
Calls
comp.evaluate(...)(pure analytic mixing — no RT) and wraps the resultingLayerOpticsas anxarray.Datasetwith alayerdimension indexed by layer-center altitude.
Visualization
pyRadtran visualization layer (pure data-in -> fig-out; lazy matplotlib).
- pyradtran.viz.get_palette(n: int) list[str][source]
Return
ncolorblind-safe colors (cycling the Okabe-Ito set).
- pyradtran.viz.plot_block_profiles(per_block_ds_dict: dict[str, Dataset], *, quantity: str = 'tau', ax=None, save_path=None)[source]
Per-block τ(z) (spectrally summed over wavelength) or ρ(z) vs altitude.
The τ curve is
tau.sum(axis=0)— the per-layer sum over wavelength, a rough “spectral optical burden per layer” overview. For a physically meaningful τ(z) at a specific band, slice the block dataset to that wavelength before passing it in.
- pyradtran.viz.plot_budget(ds: Dataset, *, components=('transmittance', 'reflectance', 'absorptance'), ax=None, save_path=None)[source]
Stacked-area plot of T/R/A vs wavelength. Requires a budget-enriched dataset.
- pyradtran.viz.plot_component_attribution(result: AttributionLike, *, variable: str = 'edir', level='surface', ax=None, save_path=None)[source]
Plot per-block contributions (full - leave_one_out) plus the full curve.
- pyradtran.viz.plot_composite_optics(ds: Dataset, *, quantity: str = 'tau', ax=None, save_path=None)[source]
pcolormesh of τ / ssa / g over (wavelength, altitude) for the mixed composite.
- pyradtran.viz.plot_flux_profile(ds: Dataset, *, variable: str = 'edir', wavelength_nm: float = 550.0, ax=None, save_path=None)[source]
Plot a flux variable vs altitude (km) at the wavelength nearest
wavelength_nm.
- pyradtran.viz.plot_heating_rate(ds: Dataset, *, wavelength_nm: float | None = None, ax=None, save_path=None)[source]
Plot heating rate vs altitude (km).
If
wavelength_nmis None, plot all wavelengths as faint background lines; otherwise plot the nearest-wavelength line bold.
- pyradtran.viz.plot_rt_overview(ds: Dataset, *, wavelength_nm: float = 550.0)[source]
Convenience multi-panel: spectral (surface) + flux profile + budget.
- pyradtran.viz.plot_spectral(ds: Dataset, *, variables=('edir', 'edn', 'eup'), level='surface', ax=None, save_path=None)[source]
Plot selected flux variables vs wavelength at a single zout level.
For 2-D datasets,
level="surface"selects the lowest-altitude zout level.
Workflow
RT orchestration workflows (drive the Runner to produce structured results).
- class pyradtran.workflow.AttributionResult(full: Dataset, contributions: dict[str, Dataset])[source]
Bases:
objectFull-field run plus per-block contribution datasets.
- pyradtran.workflow.compute_component_attribution(build_scene: Callable, composite, execute_many: Callable[[list], list[Dataset]]) AttributionResult[source]
Compute per-block RT contributions by leave-one-out subtraction.
- Parameters:
build_scene – Callable mapping a (possibly leave-one-out) composite to a runnable
Scene.composite – A composite with
.piecesand.model_copy(update=...).execute_many – Callable running a list of scenes in parallel and returning the parsed datasets in the same order (e.g.
lambda scenes: Runner.execute_many(scenes, uvspec_exe=..., data_path=...)).
- Returns:
AttributionResultwhosecontributions[piece.name]isfull - leave_piece_out.