Skip to content

AeroViz.optical

Bulk optical properties, IMPROVE extinction, Mie theory (bulk, lognormal, multimodal, core-shell, angular), gas extinction, brown-carbon separation and refractive-index retrieval. Worked examples: Optical Closure; call-by-call summary: Post-Processing Functions. Theory: IMPROVE, Mie.

Input

df_sca.columns  ['sca_550', 'SAE']          # nephelometer reader output (lower-case)
df_abs.columns  ['abs_550', 'AAE', 'eBC']   # aethalometer reader output; abs_370 … abs_950 also available
df_mass.columns  ['AS', 'AN', 'OM', 'Soil', 'SS', 'EC']   # µg/m³, from reconstruct_mass(...)['mass']

Reading improve(...) results

df_RH must be a Series (e.g. met['RH']), not a one-column DataFrame. Each returned frame (dry, wet) carries the per-species columns plus a lower-case total; use dry['total'], never dry.sum(axis=1), which would count total twice.

Mixing modes for Mie: internal (volume-weighted mean refractive index), external (each species computed separately, then summed), core_shell (EC core with the remaining species as shell) and sensitivity. The first two are selected with mie(..., mixing=...); all four are available on SizeDist.to_extinction(method=...).

Functions

AeroViz.optical

Top-level optical-processing functions; convenience wrappers — see AeroViz.dataProcess.Optical.* for full algorithm details.

Attributes

__all__ module-attribute

__all__ = ['optical_basic', 'improve', 'gas_extinction', 'retrieve_ri', 'brown_carbon', 'mie', 'mie_lognormal', 'mie_multimodal', 'scattering_function', 'scattering_function_sd', 'phase_matrix', 'nephelometer_truncation_correction', 'mie_core_shell', 'mie_core_shell_sd', 'iterative_inversion', 'iterative_inversion_sd', 'contour_intersection']

Functions:

optical_basic

optical_basic(df_sca, df_abs, df_mass=None, df_no2=None, df_temp=None)

Compute basic optical properties (extinction, SSA, MEE/MSE/MAE, Ångström exponents) from measured scattering and absorption.

Parameters:

Name Type Description Default
df_sca DataFrame

Scattering coefficient (Mm⁻¹).

required
df_abs DataFrame

Absorption coefficient (Mm⁻¹).

required
df_mass DataFrame

PM mass concentration (μg/m³), used for mass efficiencies.

None
df_no2 DataFrame

NO2 concentration (ppb), used to subtract gas absorption.

None
df_temp DataFrame

Ambient temperature (°C), used in gas-extinction correction.

None

Returns:

Type Description
DataFrame

Derived optical properties.

improve

improve(df_mass, df_RH=None, method='revised', df_nh4_status=None, df_ext=None, oa_oc_ratio=1.8, upper_bounds=None)

Calculate extinction using the IMPROVE equation.

Parameters:

Name Type Description Default
df_mass DataFrame

Reconstructed mass concentrations. Required columns depend on method: - 'revised' / 'modified': AS, AN, OM, Soil, SS, EC - 'localized': AS, AN, POC, SOC, Soil, SS, EC

required
df_RH DataFrame

Relative humidity (%).

None
method ('revised', 'modified', 'localized')

IMPROVE variant.

'revised'
df_nh4_status DataFrame

NH4 status from chemistry reconstruction; rows flagged 'Deficiency' are excluded.

None
df_ext DataFrame

Measured extinction with 'Scattering' and 'Absorption' columns (Mm⁻¹). Required for method='localized'.

None
oa_oc_ratio float

OA/OC conversion ratio (method='localized' only).

1.8
upper_bounds dict

Upper bounds for MLR coefficients (method='localized' only).

None

Returns:

Type Description
dict

Keys include 'dry', 'wet', 'ALWC', 'fRH'; method='localized' adds 'coefficients' and 'regression'.

gas_extinction

gas_extinction(df_no2, df_temp)

Calculate gas contribution to extinction (Rayleigh + NO2 absorption).

Parameters:

Name Type Description Default
df_no2 DataFrame

NO2 concentration (ppb).

required
df_temp DataFrame

Ambient temperature (°C).

required

Returns:

Type Description
DataFrame

Columns: ScatteringByGas, AbsorptionByGas, ExtinctionByGas (Mm⁻¹).

retrieve_ri

retrieve_ri(df_optical, df_pnsd, dlogdp=0.014, wavelength=550)

Retrieve complex refractive index from co-located optical and PSD data.

Parameters:

Name Type Description Default
df_optical DataFrame

Optical data with Extinction, Scattering, and Absorption columns.

required
df_pnsd DataFrame

Particle number size distribution.

required
dlogdp float

Logarithmic bin width.

0.014
wavelength float

Wavelength in nm.

550

Returns:

Type Description
DataFrame

Retrieved RI with re_real and re_imaginary columns.

brown_carbon

brown_carbon(df_abs, wavelengths=None, ref_wavelength=880, aae_bc=1.0)

Separate BC and BrC absorption using the AAE approach.

Parameters:

Name Type Description Default
df_abs DataFrame

Absorption coefficients at multiple wavelengths (Mm⁻¹), with columns named like 'abs_370', 'abs_470', ..., 'abs_880'.

required
wavelengths list[int]

Wavelengths to compute BrC for. Default: [370, 470, 520, 590, 660].

None
ref_wavelength int

Reference wavelength assumed to be pure-BC absorption.

880
aae_bc float

AAE assumed for Black Carbon.

1.0

Returns:

Type Description
DataFrame

BC/BrC absorption, BrC fraction at each wavelength, and AAE_BrC.

_is_mixing_table

_is_mixing_table(ri: DataFrame) -> bool

Return True iff ri is a DataFrame with at least one *_volume_ratio column.

_mixing_table_to_complex_ri

_mixing_table_to_complex_ri(ri_table: DataFrame, wavelength: float) -> ndarray

Compute an effective complex RI per row by volume-weighted average of the species refractive indices for the given mixing table.

mie

mie(df_psd, ri, wavelength=550, mixing=None, distribution=False)

Compute Mie optical properties from a particle size distribution.

Parameters:

Name Type Description Default
df_psd DataFrame

PSD with rows = time, columns = diameters (nm).

required
ri Series of complex | DataFrame

Refractive index. EITHER: - Series of complex numbers, one per row → single-material Mie - DataFrame with columns ending in '_volume_ratio' → species mixing table (one column per species, values in [0, 1])

required
wavelength float

Wavelength in nm.

550
mixing ('internal', 'external', 'both')

Only used when ri is a mixing table. - 'internal' (default if not given): all species mixed within each particle - 'external': each species contributes independently - 'both': compute and return both

'internal'
distribution bool

False → return total ext/sca/abs (Mm⁻¹) per row. True → return per-bin dExt/dSca/dAbs (Mm⁻¹) distributions.

False

Returns:

Type Description
DataFrame | dict
  • mixing in (None/'internal'/'external'): DataFrame
  • mixing == 'both': dict {'internal': DataFrame, 'external': DataFrame}

mie_lognormal

mie_lognormal(refractive_index, wavelength=550, *, geo_mean=200, geo_std=2.0, total_number=1000000.0, n_bins=167, dp_range=(1, 2500))

One-shot Mie optics from a single lognormal PSD.

Convenience wrapper that builds the PSD internally then calls :func:Mie_SD. See :mod:AeroViz.dataProcess.Optical.mie for parameter details.

Returns:

Type Description
dict

Keys ext, sca, abs (Mm⁻¹).

mie_multimodal

mie_multimodal(refractive_index, wavelength=550, *, modes, n_bins=167, dp_range=(1, 2500))

Mie optics for a multi-modal lognormal PSD.

modes is a sequence of (geo_mean, geo_std, total_number) tuples; their lognormal distributions are summed onto a shared diameter grid before the Mie integration.

Returns:

Type Description
dict

Keys ext, sca, abs (Mm⁻¹).

scattering_function

scattering_function(m, wavelength, diameter, angles=None, space='theta')

Single-particle angular scattering pattern (Mie phase function).

Returns dict with angles, SL (parallel-polarised), SR (perpendicular), SU (unpolarised average).

scattering_function_sd

scattering_function_sd(m, wavelength, dp, ndp, angles=None, space='theta', psd_type='auto')

PSD-integrated angular scattering pattern.

Returns dict with the same keys as :func:scattering_function but PSD-integrated.

phase_matrix

phase_matrix(m, wavelength, diameter, mu=None)

Single-particle Mueller phase matrix (S₁₁, S₁₂, S₃₃, S₃₄).

Returns dict with keys mu, S11, S12, S33, S34.

nephelometer_truncation_correction

nephelometer_truncation_correction(sae, wavelength=550, instrument='NEPH')

Anderson & Ogren (1998) truncation correction for nephelometers.

Multiplicative factor to apply to uncorrected scattering for an integrating nephelometer (TSI 3563 default; Aurora 3000 also tabulated). sae is the scattering Ångström exponent.

mie_core_shell

mie_core_shell(m_core, m_shell, d_core, d_total, wavelength)

Aden-Kerker coated-sphere Mie efficiencies (single particle).

Returns dict with the same 7 keys as :func:calculate_mie_efficiencies: Q_ext, Q_sca, Q_abs, g, Q_pr, Q_back, Q_ratio.

mie_core_shell_sd

mie_core_shell_sd(m_core, m_shell, dp_core, dp_total, ndp, wavelength=550, psd_type='dNdlogDp')

PSD-integrated Aden-Kerker coated-sphere Mie.

Returns dict ext, sca, abs (Mm⁻¹) plus g_eff (scattering-weighted mean asymmetry parameter).

iterative_inversion

iterative_inversion(b_ext, b_sca, b_abs, lognormal_params, wavelength=550, n_initial=1.5, k_initial=0.01)

Newton-Raphson RI retrieval from measured (Bext, Bsca, Babs).

PSD is described by lognormal_params, a dict with keys geo_mean, geo_std, total_number.

Returns dict with n, k, iterations, converged, residuals.

iterative_inversion_sd

iterative_inversion_sd(b_ext, b_sca, b_abs, dp, ndp, wavelength=550, n_initial=1.5, k_initial=0.01)

Newton-Raphson RI retrieval with explicit PSD (dp, ndp arrays).

contour_intersection

contour_intersection(b_ext, b_sca, b_abs, lognormal_params, wavelength=550, n_range=(1.3, 2.0), k_range=(0, 0.5), grid=51)

Contour-intersection RI retrieval (Sumlin 2018 method).