Column observation¶
The column + averaging-kernel observation every transport tier shares: ColumnObservation turns a concentration field on the analysis grid (Tiers II and III) or per-receptor profiles (the Tier I plume, through coupled.column_response) into the column-mass enhancement a satellite sees. Tier I, reused by Tiers II–IV.
observation
¶
Column + averaging-kernel observation (implementation in plumax.gauss_plume._src.observation).
ColumnObservation
¶
Bases: Module
Averaging-kernel-weighted column at a set of receptors.
y_i = A_i Σ_k h_k c_{k,i}.
Attributes:
| Name | Type | Description |
|---|---|---|
layer_weights |
Float[Array, ' level']
|
Level weights h_k, the layer thicknesses [m] for a column integral. |
averaging_kernel |
Float[Array, ' obs'] | None
|
Per-receptor scalar averaging kernel A_i. |
receptor_index |
Int[Array, 'obs 2'] | None
|
|
Examples:
Two levels 10 m thick, every column of a uniform field:
>>> import jax.numpy as jnp
>>> observation = ColumnObservation(layer_weights=jnp.full(2, 10.0))
>>> observation.from_field(jnp.ones((2, 3, 4))).shape
(12,)
Two receptors with an averaging kernel:
>>> observation = ColumnObservation(
... layer_weights=jnp.full(2, 10.0),
... averaging_kernel=jnp.array([1.0, 0.5]),
... receptor_index=jnp.array([[0, 0], [2, 3]]),
... )
>>> observation.from_field(jnp.ones((2, 3, 4))).tolist()
[20.0, 10.0]
Trapezoid weights for profiles on irregular levels:
>>> levels = jnp.array([0.0, 10.0, 30.0])
>>> ColumnObservation.trapezoid(levels).layer_weights.tolist()
[5.0, 15.0, 10.0]
trapezoid
classmethod
¶
trapezoid(levels: Float[Array, ' level'], averaging_kernel: Float[Array, ' obs'] | None = None) -> ColumnObservation
Column over profiles on strictly increasing levels, trapezoid rule.
h_0 = Δz_0 / 2, h_k = (Δz_{k-1} + Δz_k) / 2, h_{K-1} = Δz_{K-2} / 2,
so Σ_k h_k c_k is jnp.trapezoid(c, x=levels).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
levels
|
Float[Array, ' level']
|
Level heights z_k [m]. |
required |
averaging_kernel
|
Float[Array, ' obs'] | None
|
Per-receptor scalar averaging kernel A_i. |
None
|
Returns:
| Type | Description |
|---|---|
ColumnObservation
|
The observation, with no receptor index (it takes profiles). |
Source code in src/plumax/gauss_plume/_src/observation.py
for_grid
classmethod
¶
for_grid(plume_grid: PlumeGrid3D, *, instrument: Instrument | None = None, receptor_index: Int[Array, 'obs 2'] | None = None) -> ColumnObservation
Column over a les_fvm analysis grid, midpoint rule (h_k = Δz).
An instrument places each receptor in the T-cell that contains it and
brings its averaging kernel. Without one, receptor_index (or every
column) is observed with the identity kernel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
plume_grid
|
PlumeGrid3D
|
The analysis grid the field lives on. |
required |
instrument
|
Instrument | None
|
Receptors |
None
|
receptor_index
|
Int[Array, 'obs 2'] | None
|
|
None
|
Returns:
| Type | Description |
|---|---|
ColumnObservation
|
The observation for interior fields of shape |
Raises:
| Type | Description |
|---|---|
DomainError
|
If a receptor lies outside the grid. |
ValueError
|
If both |
Source code in src/plumax/gauss_plume/_src/observation.py
column
¶
Apply the observation to per-receptor profiles c_{k,i}.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
profiles
|
Float[Array, 'obs level']
|
Concentration at each receptor and level. |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ' obs']
|
The observation y_i. |
Source code in src/plumax/gauss_plume/_src/observation.py
from_field
¶
Apply the observation to an interior field on the analysis grid.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
concentration
|
Float[Array, 'level y x']
|
Interior concentration c, ghost rings stripped. |
required |
Returns:
| Type | Description |
|---|---|
Float[Array, ' obs']
|
The observation y_i at each receptor. |