MhdRadiativeLoader

class PlasmaCalcs.mhd.mhd_radiative_loader.MhdRadiativeLoader

Bases: MhdBasesLoader

Loader for computing single-fluid MHD quantities related to radiative transfer.

This class extends MhdBasesLoader to provide specialized functionality for

radiative transfer calculations in magnetohydrodynamics (MHD) simulations,
including:
- **Emission Measure (EM)**: Calculations with optional TRAC (Transition Region
Adaptive Conduction) correction and opacity effects
- **Velocity-Differential Emission Measure (VDEM)**: Temperature and velocity
binning for spectral line analysis
- **Spectral Line Synthesis**: Full and partial spectra generation with instrument
profiles and multiple emission line support
- **Doppler Shifts**: Line-of-sight velocity analysis via Doppler shift calculations
- **Intensity Moments**: Computation of spectral line moments (intensity, mean
velocity, width)
Key Features
————
- Configurable emission measure modes (with/without TRAC, with/without opacity)
- Flexible temperature and velocity binning for VDEM calculations
- Multiple VDEM computation modes: interpolated, non-interpolated, and fully interpolated
- Support for photosphere masking in calculations
- Integration with MUSE instrument utilities and ChiantiPy for spectral synthesis
- Efficient handling of large datasets through xarray integration
Attributes
———-
emiss_mode : str
Emission measure calculation mode (‘notrac_noopa’, ‘trac_noopa’,
‘notrac_opa’, ‘trac_opa’)
emiss_trac : bool
Whether to include TRAC correction in emission measure calculations
emiss_opa : bool
Whether to include opacity effects in emission measure calculations
emiss_norm : float
Emission measure normalization factor (default: 1e27)
vdem_mode : str
VDEM calculation mode (‘interp’, ‘nointerp’, ‘allinterp’)
rcoords_logT : array-like
Log10(temperature [K]) values for binning
rcoords_vdop_kms : array-like
Velocity/Doppler shift values in km/s for binning
vdem_logT_min : float
Minimum log10(temperature [K]) threshold for VDEM calculations
See Also
——–
MhdBasesLoader : Parent class providing base MHD functionality

Methods

__call__(var, *args[, name, item, verbose])

returns value of var from self.

assert_single_fluid_mode([varname, mode])

asserts that self is in single fluid mode; else crash.

attach_extra_coords(arr)

attach any self.extra_coords to array arr but only if it is an xarray.DataArray or xarray.Dataset

cls_help([qstr, only, tree, modules, ...])

prints str for help with quants.

cls_var_tree(var, *[, missing_ok])

return QuantTree of MatchedQuantity objects from matching var and all dependencies,

copy()

returns a deep copy of self.

get_B()

magnetic field.

get_E()

electric field.

get_E_un0()

electric field in the u_neutral=0 frame.

get_Gofnt(var, *[, _match])

G(T,ne) from ChiantiPy and muse library for a given ion.

get_Gofnt_atmos(var, *[, _match])

Interpolated G(T) with temperature, for a given ion.

get_Gofnt_em(var, *[, _match])

Emission * G(T) for a given ion.

get_Gofnt_em_interp(var, *[, _match])

Emission * G(T) for a given ion.

get_Gofnt_em_nointerp(var, *[, _match])

Emission * G(T) for a given ion.

get_J()

current density (without displacement current).

get_Jf()

current density (associated with fluid).

get_P()

pressure ("isotropic/maxwellian").

get_T()

temperature.

get_T_neutral()

temperature of neutrals; T_n = T of SINGLE_FLUID.

get_Tjoule()

temperature ("isotropic/maxwellian"), in energy units.

get__vdem_ignores_photosphere_var(var, *[, ...])

_vdem_ignore_photosphere_var --> self(var) but possibly setting values at z<0 to 0,

get_absorption_h_he()

Absorption coefficient at wavelength=self.rcoords_wavelength_A,

get_behavior([keys])

return value of self.behavior.

get_chianti_opa1d_table([tabname])

Ionization state table from ChiantiPy.

get_ds()

vector(spatial scale), e.g. [dx, dy, dz].

get_e()

energy density.

get_emiss()

Emission measure (EM) based on the selected emission mode (self.emiss_mode).

get_emiss_for_vdem_loi(*[, _T_loi])

emiss_for_vdem_loi = emiss_loi, but with some adjustments for vdems:

get_emiss_notrac()

Emission measure in cgs without TRAC correction.

get_emiss_trac()

Emission measure in cgs with TRAC correction.

get_eperm()

internal energy (total, not density) per unit mass.

get_gamma()

adiabatic index.

get_ionfrac()

ionization fraction.

get_m()

abundance-weighted average fluid particle mass.

get_m_neutral()

mass, of a "single neutral particle".

get_moments(var, *[, _match])

First three moments of a var, e.g., vdem or spectra.

get_n()

number density.

get_n_neutral()

number density of neutrals.

get_ne()

electron number density

get_nq()

charge density.

get_nuns()

collision frequency.

get_nusj()

collision frequency.

get_nusn()

collision frequency.

get_opac_h()

H opacity at self.rcoords_wavelength_A.

get_opac_h_he([wavelength])

Opacities at wavelength=self.rcoords_wavelength_A.

get_opac_hei()

HeI opacity at self.rcoords_wavelength_A.

get_opac_heii()

HeII opacity at self.rcoords_wavelength_A.

get_p()

momentum density.

get_q()

charge, of a "single particle".

get_r()

mass density.

get_rcoords_Pe()

electron Pressure values for G(T) for fixed pressure, in [self.units] system,

get_rcoords_logD()

log(electron number density) values for VDEMs and G(T,ne), with ne in [self.units] system,

get_rcoords_logT()

log(Temperature) values used by some vars (e.g. vdems and G(T)), in [self.units] system,.

get_rcoords_vdop()

velocity (or, doppler shift) values used by some vars (e.g. vdems and spectra), in [self.units] system,.

get_set_or_cached(var)

returns var if found in self.setvars or self.cache, with compatible behavior_attrs.

get_single_fluid_var(var, *[, _match])

SF_{var} (or SINGLE_FLUID_{var}) --> {var}, definitely in single fluid mode.

get_spectra(var, *[, _match])

Synthetic spectra for a given ion.

get_tau()

Optical depth along line of integration (default: loi = line of sight),

get_tau_500([wavelength])

Computes the tau scale from H-bf opacity alone 500 nm.

get_u()

velocity.

get_u_neutral()

velocity of neutrals.

get_vars(vars, *args[, return_type, ...])

returns values of vars from self.

get_vdem()

VDEM (intergrated along an axis), as a function of temperature and velocity.

get_vdem_allinterp()

VDEM (intergrated along an axis), with interpolation (Matthias trick along T and u)

get_vdem_interp()

VDEM (intergrated along an axis), with interpolation (Matthias trick along T)

get_vdem_no_interp()

VDEM (intergrated along an axis), without interpolation.

get_vtherm_instr()

thermal velocity including instrumental broadening.

get_w_instrumental()

instrumental broadening for thermal velocity, in self.units system.

has_var(var)

return whether self can load var.

help([qstr, only, tree, modules, signature, ...])

prints str for help with quants.

help_call_options([search])

prints help for kw_call_options.

help_quants_str([qstr, only, tree, modules, ...])

returns str for help with quants.

help_str([qstr, only])

returns cls.help_quants_str(qstr=qstr, only=only, **kw).

interp_masked(array_or_var, bins[, dim, ...])

Compute interpolation masks and normalization factors for a variable (e.g., "T")

kw_call_options(*[, sorted])

returns list of kwarg names which can be used to set attrs self during self.__call__.

limb_vdem_pipeline(*[, iz0, snap, ...])

Execute a VDEM pipeline for limb observations using ray draping geometry.

load_direct(var, *args, **kw)

load var "directly", from some source which is not known by the main part of PlasmaCalcs.

load_fromfile(var, *args, **kw)

load var directly from a file.

maintaining_attrs(*attrs, **attrs_as_flags)

returns context manager which restores attrs of self to their original values, upon exit.

match_var(var, *[, check])

match var from cls.KNOWN_VARS or cls.KNOWN_PATTERNS, or raise FormulaMissingError.

match_var_loading_dims(var, **kw_loading_dims)

return dims for loading var across.

match_var_result_dims(var, **kw_result_dims)

return dims which result of cls(var) will vary across.

match_var_result_size(var, *[, maindims])

return size (number of elements) which self(var) will have.

match_var_tree([var])

return QuantTree of MatchedQuantity objects from matching var and all dependencies,

quant_tree([var])

return QuantTree of MatchedQuantity objects from matching var and all dependencies,

set_T_fromtable(value, **kw)

set T_fromtable to this value.

set_e(value, **kw)

set e to this value.

set_eperm(value, **kw)

set eperm to this value.

set_n(value, **kw)

set n to this value.

set_r(value, **kw)

set r to this value.

set_var(var, value[, behavior_attrs, ...])

set var in self.

set_var_internal(var, value, behavior_attrs)

set var in self.

tree([var])

return QuantTree of MatchedQuantity objects from matching var and all dependencies,

unset_var(var[, behavior_attrs, missing_ok])

remove var from self.setvars (but only at values stored with relevant behavior).

unset_var_internal(var, behavior_attrs[, ...])

unset var from self.setvars.

using_at_call_depth(depth, **attrs_and_values)

context manager for setting attrs_and_values but only while call_depth == depth.

using_at_next_call_depth(**attrs_and_values)

context manager for setting attrs_and_values but only while call_depth == self.call_depth + 1

using_attrs([attrs_as_dict, _unset_sentinel])

returns context manager which sets attrs of obj upon entry; restores original values upon exit.

vdem_pipeline(*[, los_dim, iz0, tg_percent, ...])

Execute a standard VDEM (Velocity-Differential Emission Measure) analysis pipeline.

_apply_toplevel_scale_coords(arr)

apply self.toplevel_scale_coords to arr, if nonempty, else return arr unchanged.

_battrs_for_set_var_internal(behavior_attrs)

returns behavior_attrs which will be used by set_var_internal, given these inputs.

_battrs_for_unset_var_internal(behavior_attrs)

returns behavior_attrs which will be used by unset_var_internal, given these inputs.

_call_hijacker(var, *args__None, **kw__None)

returns False or name of hijacker method to use instead of self(var) call.

_call_postprocess(result, *, var[, name, item])

postprocess result from self.__call__.

_call_postprocess_toplevel(result, *, var[, ...])

additional postprocessing for self.__call__ when call_depth=1.

_call_preprocess(result, *, var)

preprocessing during self.__call__.

_get_default_elements()

default value for elements.

_get_maybe_missing_var(var, *args[, ...])

return value of var, or None if FormulaMissingError and missing_vars 'ignore' or 'warn'.

_handle_typevar_nan(*[, errmsg])

crash with TypevarNanError if self.typevar_crash_if_nan, else return 'nan'.

_help_matches(qstr, k, v)

returns whether qstr matches k or v, and thus should be displayed during self.help(qstr).

_help_specialized_kw_call_options()

returns dict of docstrings for specialized kw call options for self.

_increment_call_depth()

context manager for incrementing call_depth.

_max_n_requires_float64()

returns whether max supported n, in self.units unit system, is too big for float32.

_pop_kw_call_options(kw)

pop all self.kw_call_options() from kw, returning dict of popped options.

_provided_val(var[, _val, _known_vals])

returns the value of var, either from _known_vals or _val.

_radiative_assert_single_component()

asserts self.current_n_component() == 1; raise ComponentValueError otherwise.

_specialized_kw_call_options(kw)

specialize popped kw_call_options, adjusting keys and/or values as needed,

_upcast_if_max_n_requires_float64(array)

if max n requires float64, upcast array to float64,

_vdem_multiply_then_sum_along(*arrays, dim)

multiply arrays then sum along dim, without making big intermediate array.

Attributes

GOFNT_INTERP_MODE_OPTIONS

GOFNT_MODE_OPTIONS

KNOWN_PATTERNS

KNOWN_SETTERS

KNOWN_VARS

VDEM_MODE_OPTIONS

assign_behavior_attrs

whether to assign self.behavior values as attrs of result when calling self.

assign_behavior_attrs_max_call_depth

max call_depth at which to assign_behavior_attrs to result,

assign_behavior_attrs_skip_xr

whether to use include_xr=False if self.assign_behavior_attrs,

behavior

dict of {attr: self.attr} for attr in self.behavior_attrs.

behavior_attrs

list of attrs in self which control behavior of self.

call_depth

depth of the current call to self.

call_depth_manager

stores the value of call_depth, and helps to manage attrs dependent on call_depth value.

cls_behavior_attrs

elements

ElementList of all elements in multifluid mixture assumed from single-fluid mhd.

emiss_mode

string telling emission measure mode.

emiss_norm

Emission Measure normalization factor.

emiss_opa

whether to include opacity in emission measure (self('emiss')).

emiss_trac

whether to include TRAC correction in emission measure (self('emiss')).

emiss_trac_coeff

TRAC coefficient for emiss_trac calculation.

enable_fromfile

bool: whether self.load_fromfile is enabled during self.load_direct.

extra_coords

dict of {coord_name: coord_value} to attach to outputs of self(var).

get

alias to __call__

gofnt_abundance

Abundance(?) to use for G(T) calculations.

gofnt_interp_mode

Selects the emission measure x G(T) calculation mode.

gofnt_mode

Selects the G(T) calculation mode.

gofnt_wavelength_range

Wavelength range (as [min, max]) (in [Angstrom] units) to use for G(T) calculations.

in_single_fluid_mode

whether self is in "single fluid mode".

known_pattern

known_setter

known_var

maintaining

alias to maintaining_attrs

nondim_behavior_attrs

list of attrs in self which control behavior of self, but which are NOT in self.dimensions.

rcoords_Pe_cgs

electron Pressure [cgs units] values, used by some MhdRadiativeLoader vars.

rcoords_logD_cgs

log10(electron number density [cgs units]) values, used by some MhdRadiativeLoader vars.

rcoords_logT

log10(Temperature [K]) values used by some MhdRadiativeLoader vars.

rcoords_vdop_kms

velocity [km/s] (or, doppler shift) values, used by some MhdRadiativeLoader vars.

rcoords_wavelength_A

Wavelength (in [Angstrom] units) used by some MhdRadiativeLoader vars.

set

alias to set_var

setvar

alias to set_var

setvars

VarCache of vars set via self.set_var().

toplevel_scale_coords

dict of {coord_name: coord_scaling} to apply to top-level outputs of self(var).

typevar_crash_if_nan

bool.

unset

alias to unset_var

using

alias to using_attrs

vdem_ignores_photosphere

Specifies how the photosphere is treated in VDEM calculations.

vdem_logT

(self.vdem_logT_min, self.rcoords_logT).

vdem_logT_min

Minimum log10(temperature [K]) to include in VDEM calculations.

vdem_loopdim

Tells which dimension to loop over during vdems.

vdem_los

tells which line of sight to integrate along for vdem calculations.

vdem_los_explicit

self.vdem_los, but if None convert to the explicit vdem_los to use.

vdem_mode

Selects the velocity-differential emission measure (VDEM) calculation mode.

vdem_varies_logD

tells whether vdems should also vary across logD (electron number density) dimension,

w_instrumental_si

instrumental broadening for thermal velocity, in SI units.

__call__(var, *args, name=UNSET, item=False, verbose=UNSET, **kw)

returns value of var from self.

result is probably an xarray.DataArray, but not guaranteed.
var: str or iterable of strs.
Name of the var(s) to load. E.g. ‘n’ for number density, or [‘n’, ‘u’] for number density & velocity.
If multiple vars: returns an xarray.Dataset of all vars, via self.get_vars.
Determine how to load each var, as follows:
- (caching) if var in self.cache, with matching self.behavior_attrs, use value from cache.
[TODO] - caching not yet implemented. May allow for better efficiency.
- (setvars) if var in self.setvars, with matching self.behavior_attrs, use value from setvars.
[TODO] - improve set_var functionality.
set_var will allow user to apply PlasmaCalcs calculations to arbitrary values,
not just values from one of the hookups. Useful for testing & quick calculations.
- (KNOWN_VARS) if var in self.KNOWN_VARS,
use the corresponding function to get it.
- (KNOWN_PATTERNS) if var matches a pattern from self.KNOWN_PATTERNS,
use the corresponding function to get it.
- (direct) attempt to load var “directly”, via self.load_direct.
load_direct will almost always end up loading values directly from a file (e.g., “data”).
This may include converting var to fromfile_var, i.e. match file naming conventions,
and/or dimensions being loaded. E.g. ‘b’ may become ‘bz’ when loading across ‘component’.
Then, check if fromfile_var in setvars and cache, returning relevant value if found.
Lastly, call self.load_fromfile(fromfile_var).
Those are checked in the order listed.
If none of those work, raise FormulaMissingError.
name: UNSET, None, or str
try to set result.name = name.
If can’t set result.name, but result.attrs exists, set result.attrs[‘name’] = name, instead.
UNSET –> use name = var.
item: bool
if True, convert result to single value (e.g., python float) via result.item().
This will cause crash if result is not a single value;
it will also cause all metadata stored in the result to be lost.
verbose: UNSET, bool, or int
set self.verbose during this call to self.
UNSET –> use self.verbose (unchanged)
kw may additionally contain any keys from self.kw_call_options().
if it does, pop those values, and temporarily set the corresponding attr.
E.g.: self(‘n’, units=’si’, fluid=1)
–> temporarily set units=’si’, fluid=1, while getting ‘n’.
See self.help_call_options() for more details.
[EFF] passes _match=re.fullmatch(pattern, var) to the getter function,
if the match is from KNOWN_PATTERNS (but not if it is from KNOWN_VARS).
misc note: if self._call_hijacker(…), instead return result from the corresponding method.
e.g. if it returns “_get_with_chunks” then return self._get_with_chunks(var, …).
Call hijacking occurs after setting behavior attrs (inside with self.using(...): block)
but before altering call depth (outside with self._increment_call_depth(): block).
_apply_toplevel_scale_coords(arr)

apply self.toplevel_scale_coords to arr, if nonempty, else return arr unchanged.

_battrs_for_set_var_internal(behavior_attrs, forall=[], *, ukey=None)

returns behavior_attrs which will be used by set_var_internal, given these inputs.

see help(self.set_var_internal) for details.
_battrs_for_unset_var_internal(behavior_attrs, forall=[], *, ukey=None)

returns behavior_attrs which will be used by unset_var_internal, given these inputs.

see help(self.unset_var_internal) for details.
_call_hijacker(var, *args__None, **kw__None)

returns False or name of hijacker method to use instead of self(var) call.

Here, just returns False, always. Subclass might override.
_call_postprocess(result, *, var, name=UNSET, item=UNSET)

postprocess result from self.__call__. Called during self.__call__.

(self.call_depth inside here will tell depth of the current call; depth=1 for top level.)
result: any value, probably an xarray.DataArray
result from self.__call__, before postprocessing.
var, name, item: UNSET or value
passed directly from self.__call__.
The implementation here does the following (subclasses might override / add to this):
(1) if self.verbose >= 4, print a message about getting var.
(2) result = self.attach_extra_coords(result).
(3) set result.name = name, or result.attrs[‘name’] = name, if possible.
(4) if self.assign_behavior_attrs at this call depth, do so now.
(5) if self.call_depth == 1, call self._call_postprocess_toplevel.
(6) if item, convert result to single value via result.item().
_call_postprocess_toplevel(result, *, var, name=UNSET, item=UNSET)

additional postprocessing for self.__call__ when call_depth=1.

called from self._call_postprocess, after doing other postprocessing, when call_depth=1.
result: any value, probably an xarray.DataArray
result from self.__call__, after other postprocessing (except item).
var, name, item: UNSET or value
passed directly from self.__call__.
Don’t need to handle these here because self._call_postprocess will handle it.
The implementation here does the following (subclasses might override / add to this):
(1) self._apply_toplevel_scale_coords (does nothing if self.toplevel_scale_coords is empty)
_call_preprocess(result, *, var)

preprocessing during self.__call__. Called during self.__call__.

(self.call_depth inside here will tell depth of the current call; depth=1 for top level.)
result: any value, probably RESULT_MISSING
result from self.__call__, before preprocessing. Usually RESULT_MISSING.
var: str
var being loaded. Passed directly from self.__call__.
The implementation here does the following (subclasses might override / add to this):
(1) if self.verbose >= 2 or DEFAULTS.DEBUG >= 7, print a message about getting var.
(2) return result, unchanged.
If the returned result is anything other than RESULT_MISSING,
self.__call__ will return it instead of loading var normally.
_get_default_elements()

default value for elements. here, just returns self.tabin.elements,

but raises a helpful error message if self.tabin not set.
_get_maybe_missing_var(var, *args, missing_vars=UNSET, **kw)

return value of var, or None if FormulaMissingError and missing_vars ‘ignore’ or ‘warn’.

missing_vars: UNSET, ‘ignore’, ‘warn’, or ‘raise’
what to do if any var causes FormulaMissingError.
UNSET –> use self.missing_vars if it exists, else ‘raise’.
‘ignore’ –> return None.
‘warn’ –> return None, but also print a warning.
‘raise’ –> raise FormulaMissingError.
_handle_typevar_nan(*, errmsg='')

crash with TypevarNanError if self.typevar_crash_if_nan, else return ‘nan’.

if crashing, use error message:
errmsg + “nTo return ‘nan’ instead of crashing, set self.typevar_crash_if_nan=False.”
classmethod _help_matches(qstr, k, v)

returns whether qstr matches k or v, and thus should be displayed during self.help(qstr).

qstr: str

the str to match; from self.help(qstr)
k: varname
the varname to test for matches.
key from self.KNOWN_VARS.keys(), or key.str from self.KNOWN_PATTERNS.keys().
v: LoadableQuantity
the LoadableQuantity to test for matches.
value from self.KNOWN_VARS.values() or self.KNOWN_PATTERNS.values().
matches if any of these are true:
qstr == ‘’
qstr in k.split(‘_’) # size limitation and split(‘_’) because, e.g. during help(‘n’),
len(qstr)>=3 and qstr in k # want vars related to number density, not all vars with the letter ‘n’.
qstr in module.split(‘.’) (where, module == v.get_f_module(cls))
‘.’ in qstr and qstr in module
len(qstr)>=3 and qstr in value from module.split(‘.’)
len(qstr)>=3 and qstr in v.fname
re.fullmatch(k, qstr) # if k is a Pattern
otherwise, does not match.
_help_specialized_kw_call_options()

returns dict of docstrings for specialized kw call options for self.

The implementation here just returns an empty dict, but subclass may override.
_increment_call_depth()

context manager for incrementing call_depth.

use “with self._increment_call_depth():” inside of __call__, e.g.:

def __call__(self, *args, **kw):
with self._increment_call_depth():
# do stuff; possibly including calling self again.
Equivalent to self.call_depth_manager.increment()
_max_n_requires_float64()

returns whether max supported n, in self.units unit system, is too big for float32.

max supported n, in SI units, is DEFAULTS.MHD_MAX_SAFE_N_SI
crash with ValueError if max supported n is too big for float64 as well.
without this check (and conversion to float64 if needed), some n values might become inf.
_pop_kw_call_options(kw)

pop all self.kw_call_options() from kw, returning dict of popped options.

_provided_val(var, _val=None, _known_vals={})

returns the value of var, either from _known_vals or _val.

if _val provided, return it; if ‘_{var}’ in _known_vals, return it;
if both provided, crash with InputConflictError (unless they are the same object),
else, return None.
Can use this internally to avoid redundant recalculations. (See e.g. VectorArithmeticLoader)
_radiative_assert_single_component()

asserts self.current_n_component() == 1; raise ComponentValueError otherwise.

The error message will be particularly helpful and give options for how to fix the error.
_specialized_kw_call_options(kw)

specialize popped kw_call_options, adjusting keys and/or values as needed,

to be suitable to pass to self.using(**kw).
kw may be edited IN PLACE.
Overriding this is discouraged, unless using property setters/getters is truly insufficient.
If overriding this method, consider also overriding self._help_specialized_kw_call_options,
to add documentation (inside self.help_call_options()) for any specialized kw call options.
self.__call__ uses this method as follows:
using=self._pop_kw_call_options(kw)
using = self._specialize_using_kw_call_options(using)
with self.using(**using):
# <– majority of self.__call__ functionality goes here.
The implementation here just returns kw, unchanged.
_upcast_if_max_n_requires_float64(array)

if max n requires float64, upcast array to float64,

unless array’s dtype was already float64 or larger (in which case, just return array).
see self._max_n_requires_float64 for details on when max n requires float64.
_vdem_multiply_then_sum_along(*arrays, dim)

multiply arrays then sum along dim, without making big intermediate array.

Like xarray_multiply_then_sum_along, but uses vdem-relevant defaults from self.
assert_single_fluid_mode(varname='var', *, mode='getting')

asserts that self is in single fluid mode; else crash.

varname: str
name of var to include in error message if crashing.
mode: str, ‘getting’ or ‘setting’
determines error type & error message if crashing.
‘getting’ –> FluidValueError, with error message starting like:
“{type(self)} getting {varname} requires self.in_single_fluid_mode…”
‘setting’ –> SetvarNotImplementedError, with error message starting like:
“var={varname}, when self not in_single_fluid_mode…”
Use for operations which directly assume single fluid mode (e.g. get_r implementation here).
Not necessary for operations which apply regardless of number of fluids,
E.g. n = r / m for any number of fluids, and B is always independent of fluid.
If unsure, err on the side of caution and use this function,
to require multifluid subclass to explicitly handle the situation else crash.
property assign_behavior_attrs

whether to assign self.behavior values as attrs of result when calling self.

False –> don’t use self.behavior code architecture to assign attrs.
True –> equivalent to ‘nondefault’
‘nondefault’ –> self.behavior.assign_nondefault_attrs(result)
(for brevity, it does not assign behavior attrs with “default” value.)
‘all’ –> self.behavior.assign_attrs(result).
[EFF] only assigns attrs at call_depth >= self.assign_behavior_attrs_max_call_depth.
(default: only assigns attrs at call_depth=1, i.e. at top level.
property assign_behavior_attrs_max_call_depth

max call_depth at which to assign_behavior_attrs to result,

if self.assign_behavior_attrs indicates to assign behavior attrs.
default 1, i.e. only assign if at top level.
Use None to indicate “no max depth”.
property assign_behavior_attrs_skip_xr

whether to use include_xr=False if self.assign_behavior_attrs,

during self.behavior.assign_nondefault_attrs.
Use this if you want to assign behavior attrs EXCEPT array-valued behavior attrs.
attach_extra_coords(arr)

attach any self.extra_coords to array arr but only if it is an xarray.DataArray or xarray.Dataset

property behavior

dict of {attr: self.attr} for attr in self.behavior_attrs. Note dims are separate;

dims go in behavior.dims. E.g. Behavior({‘units’:’si’,…}, dims={‘snap’:0,…}).
property behavior_attrs

list of attrs in self which control behavior of self.

Here, returns self.cls_behavior_attrs.
Subclasses could override if any behavior attrs are not known at the class-level,
e.g. if MySubclass’s list of behavior attrs varies between instances of MySubclass.
property call_depth

depth of the current call to self. depth = number of calls to self from within self.

E.g., call_depth while calculating gyrofrequency:

# call_depth == 0, for any code run here (outside any call to self).
self(‘gyrof’)
# call_depth == 1, for any code run here (inside ‘gyrof’ call but not inside deeper calls).
q = self(‘q’)
# call_depth == 2, for code inside ‘q’ call.
mod_B = self(‘mod_B’)
# call_depth == 2, for code inside ‘mod_B’ call.
self(‘B’)
# call_depth == 3, for code inside ‘B’ call.
m = self(‘m’)
# call_depth == 2, for code inside ‘m’ call.
result = q * mod_B / m
Cannot be set directly; can only be manipulated via self.call_depth_manager.
property call_depth_manager

stores the value of call_depth, and helps to manage attrs dependent on call_depth value.

classmethod cls_help(qstr=None, only=None, *, tree=None, modules=False, signature=False, doc=True, dense=False, print=True, **kw)

prints str for help with quants. Fails for any quants which depend on present values of a cls instance.

qstr: None or str

None –> tells info about this class & how to use this function.
in particular, tells that quants are stored cls.KNOWN_VARS and cls.KNOWN_PATTERNS,
and describes behavior of calling help with a string.
str –> return str for help with all quants related to str.
use empty str to get help for all quants.
only: None or str
If provided, only get help for a subset of relevant quantities.
None –> get help with all quantities related to qstr.
‘VARS’ –> only get help with KNOWN_VARS.
‘PATTERNS’ –> only get help with KNOWN_PATTERNS.
‘TREE’ –> only get help with quantities in cls.cls_var_tree(str).
‘EXACT’ –> only get help for the KNOWN_VAR exactly matching qstr.
if provided when qstr is None, treat qstr as ‘’ instead.
tree: None or bool
How much help to give for quantities in cls.cls_var_tree(qstr).
False –> don’t even check cls.cls_var_tree(qstr).
True –> help for all quantities in cls.cls_var_tree.
None –> help for quantities in cls.cls_var_tree(qstr).flat_branches_until_vars()
i.e. patterns & vars in tree but ignore any nodes with LoadableVar ancestors.
e.g. qstr=’mean_mod_beta’ –> help with ‘mean_(.+)’, ‘mod_(.+)’, and ‘beta’,
but no help with dependencies of ‘beta’ (‘q’, ‘mod_B’, ‘m’).
modules: bool
Whether to include modules in result.
If True, result will be grouped into sections with modules written at top.
signature: signature: bool
whether to include line with signature in help string.
e.g. “help_str(f, *, module=True, signature=True, indent=None)”
doc: doc: bool
whether to include lines with docstring in help string.
e.g. “return str for help(f).” … and all the other docs in here.
dense: bool
Whether to reduce whitespace in result.
E.g. True –> no newlines between functions. False –> one newline between functions.
print: bool
whether to print the result. If False, return the result instead of printing.
classmethod cls_var_tree(var, *, missing_ok=False)

return QuantTree of MatchedQuantity objects from matching var and all dependencies,

using self.KNOWN_VARS and self.KNOWN_PATTERNS when searching for matches.
missing_ok: bool
whether to be lenient sometimes when missing details that would allow to fully determine deps.
see help(MatchedQuantity.dep_vars) for more details.
copy()

returns a deep copy of self.

[TODO] implement something less hacky than using the pickle module?
property elements

ElementList of all elements in multifluid mixture assumed from single-fluid mhd.

Used to infer SINGLE_FLUID m.
property emiss_mode

string telling emission measure mode.

Depends on (and can be used to set) emiss_trac and emiss_opa.
‘notrac_noopa’ <–> emiss_trac=False, emiss_opa=False
‘trac_noopa’ <–> emiss_trac=True, emiss_opa=False
‘notrac_opa’ <–> emiss_trac=False, emiss_opa=True
‘trac_opa’ <–> emiss_trac=True, emiss_opa=True
Setting string sets emiss_trac and emiss_opa accordingly.
Getting string returns result according to emiss_trac and emiss_opa.
(Currently included for backwards compatibility, might be removed eventually.)
property emiss_norm

Emission Measure normalization factor. Used in self(‘emiss’)

and related vars. emiss = unnormed_emiss / emiss_norm.
property emiss_opa

whether to include opacity in emission measure (self(‘emiss’)).

property emiss_trac

whether to include TRAC correction in emission measure (self(‘emiss’)).

property emiss_trac_coeff

TRAC coefficient for emiss_trac calculation.

transition region using an adaptive conduction coefficient (Johnston et al. 2020).
property enable_fromfile

bool: whether self.load_fromfile is enabled during self.load_direct.

If False, raise QuantCalcError if load_direct can’t get value without load_fromfile().
property extra_coords

dict of {coord_name: coord_value} to attach to outputs of self(var).

Useful if planning to join the output of self(var) with output from a different QuantityLoader.
E.g. self.extra_coords={‘run’: ‘run 0’} and other.extra_coords={‘run’: ‘run 1’},
then xr.concat([self(‘n’), other(‘n’)], ‘run’) gives ‘n’ from self AND other.
(this is nice if self and other have same values for dims. Otherwise, might struggle.)
property get

alias to __call__

get_B()

magnetic field.

[Not implemented for this class]
get_E()

electric field.

[Not implemented for this class]
get_E_un0()

electric field in the u_neutral=0 frame.

Here, asserts all of self(‘u_n’)==0, then returns self(‘E’).
if the assertion fails, raise NotImplementedError (expect subclass to handle it).
get_Gofnt(var, *, _match=None)

G(T,ne) from ChiantiPy and muse library for a given ion. E.g., GofT_fe_9_ion

Always in [cgs] (erg*cm^3/s/sr) regardless of self.units.
ion string (like ‘fe_9’) is passed into muse.instr.utils.chianti_gofnt_linelist,
via ionList = [ionstr]. See that function for more details about available ions.
“returns G(T,ne) and spectral line properties, including wavelength and transition probabilities.”
[TODO] what does that mean?
CAUTION: directly adjusts the value of self.rcoords_wavelength_A, based on result.
get_Gofnt_atmos(var, *, _match=None)

Interpolated G(T) with temperature, for a given ion.

Always in [cgs] (erg*cm^3/s/sr) regardless of self.units.
For details about available ions, see muse.instr.utils.chianti_gofnt_linelist
get_Gofnt_em(var, *, _match=None)

Emission * G(T) for a given ion. Results always in [cgs] (erg/cm^2/s/sr).

For details about available ions, see muse.instr.utils.chianti_gofnt_linelist
get_Gofnt_em_interp(var, *, _match=None)

Emission * G(T) for a given ion. Results always in [cgs] (erg/cm^2/s/sr).

For details about available ions, see muse.instr.utils.chianti_gofnt_linelist
get_Gofnt_em_nointerp(var, *, _match=None)

Emission * G(T) for a given ion. Results always in [cgs] (erg/cm^2/s/sr).

For details about available ions, see muse.instr.utils.chianti_gofnt_linelist
get_J()

current density (without displacement current). J = curl(B) / mu0.

Per unit area, e.g. the SI units would be Amperes / meter^2.
get_Jf()

current density (associated with fluid). Jf = (nq * u) = (charge density * velocity)

This is per unit area, e.g. the SI units would be Amperes / meter^2.
(If self is not a FluidHaver, this will equal the total current density.)
get_P()

pressure (“isotropic/maxwellian”). P = (n * Tjoule) = (number density * T [energy units])

get_T()

temperature. “maxwellian” temperature (classical T in thermodynamics).

[Not implemented for this class]
get_T_neutral()

temperature of neutrals; T_n = T of SINGLE_FLUID.

(subclass might implement better T, but here assumes T_n equivalent to SF_T.)
get_Tjoule()

temperature (“isotropic/maxwellian”), in energy units. Tjoule = kB * T.

self(‘Tjoule’) == self(‘kB*T’) == kB * T. (If using SI units, result will be in Joules.)
get__vdem_ignores_photosphere_var(var, *, _match=None)

_vdem_ignore_photosphere_var –> self(var) but possibly setting values at z<0 to 0,

depending on self.vdem_ignores_photosphere.
get_absorption_h_he()

Absorption coefficient at wavelength=self.rcoords_wavelength_A,

considering only H, HeI, and HeII contributions.
Result is always in [cgs] units, regardless of self.units.
See Anzer & Heinzel, 2005 for details.
absorption_h_he = (opacity from h and he) * (single-fluid mass density) / grph,
where grph = mean molecular mass (same unit system as other terms in expression).
Assuming photopsheric abundances, grph is roughly 1.3 to 1.5 amu, depending on
exact abundances model (but constant in space & time; it just depends on self.elements).
get_behavior(keys=None)

return value of self.behavior.

keys: None or iterable
if provided, only include these attrs.
from nondim_behavior_attrs, or dims.
get_chianti_opa1d_table(tabname='chianti')

Ionization state table from ChiantiPy.

result is an xr.Dataset with data_vars ‘h’, ‘he’, ‘hei’,
telling the H, HeI, and HeII ionization fractions, respectively.
get_ds()

vector(spatial scale), e.g. [dx, dy, dz].

This is the spatial scale for the underlying grid
(ignoring self.slices, even if self.slices exists).
[Not implemented for this class]
get_e()

energy density. e = P / (gamma - 1) = pressure / (adiabatic index - 1)

get_emiss()

Emission measure (EM) based on the selected emission mode (self.emiss_mode).

Depends on self.emiss_mode; see self.EMISS_MODE_OPTIONS for details.
Result is always in cgs, regardless of self.units.
get_emiss_for_vdem_loi(*, _T_loi=None)

emiss_for_vdem_loi = emiss_loi, but with some adjustments for vdems:

- ignores emiss contributions from very cold regions (log10(T) < self.vdem_logT_min).
- depending on self.vdem_ignores_photosphere, might set to 0 below z=0
[EFF] for efficiency, can provide _T_loi if known.
get_emiss_notrac()

Emission measure in cgs without TRAC correction.

Result is always in [cgs], regardless of self.units.
nh = r / (n_per_nh * mh)
emiss_notrac = ne * nh / self.emiss_norm [1/cm^6]
get_emiss_trac()

Emission measure in cgs with TRAC correction.

Result is always in [cgs], regardless of self.units.
nh = r / (n_per_nh * mh)
emiss_trac = ne * nh * trac_correction / normalization
self.emiss_trac_coeff tells the TRAC coefficient (default 3)
get_eperm()

internal energy (total, not density) per unit mass. eperm = e / r.

get_gamma()

adiabatic index.

[Not implemented for this class]
get_ionfrac()

ionization fraction. ionfrac = ne / n (from single fluid).

Assumes quasineutrality, and that only once-ionized ions are relevant.
get_m()

abundance-weighted average fluid particle mass.

m = self.elements.mtot() * (mass of 1 atomic mass unit).
The “abundance-weighting” is as follows:
m = sum_x(mx ax) / sum_x(ax), where ax = nx / nH, and x is any elem from self.elements.
note: ax is related to abundance Ax via Ax = 12 + log10(ax).
see help(self.elements.mtot) for more details, including a proof that mtot = rtot / ntot.
(if self.elements does not exist, this method will crash with LoadingNotImplementedError)
get_m_neutral()

mass, of a “single neutral particle”. For Hydrogen, ~= +1 atomic mass unit.

[Uses self.get_neutral(‘m’) if possible, else crash. Subclass may override.]
get_moments(var, *, _match=None)

First three moments of a var, e.g., vdem or spectra.

I0 = (int(I du)) [erg/cm^2/s/sr]
I1 = (int(I u du))/I0 [km/s]
I2 = (int(I u^2 du))/I0-I1^2 [km/s]
dim_moments_var –> self(var).pc.moments(dim=dim).
e.g., vdop_moments_vdem –> self(‘vdem’).pc.moments(dim=’vdop’)
result is a Dataset with data_vars ‘moment_0’, ‘moment_1’, ‘moment_2’.
get_n()

number density. n = (r / m) = (mass density / mass)

(Note: for single-fluid, this excludes electron number density.)
get_n_neutral()

number density of neutrals.

[Uses self.get_neutral(‘n’) if possible, else crash. Subclass may override.]
get_ne()

electron number density

[Not implemented for this class]
get_nq()

charge density. nq = (n * q) = (number density * charge)

get_nuns()

collision frequency. for a single neutral particle to collide with any s.

nuns = nusn * (m / m_neutral) * (n / n_neutral).
(from conservation of momentum, and summing collisional momentum transfer between species)
get_nusj()

collision frequency. for a single particle of s to collide with any of j.

[Not implemented for this class]
get_nusn()

collision frequency. for a single particle of s to collide with any neutral.

Computed as self(‘nusj’, jfluid=self.jfluids.get_neutral()).
get_opac_h()

H opacity at self.rcoords_wavelength_A.

See Anzer & Heinzel, 2005 for details.
get_opac_h_he(wavelength=None)

Opacities at wavelength=self.rcoords_wavelength_A.

from hydrogen and helium bound free absorption (Anzer & Heinzel, 2005)
get_opac_hei()

HeI opacity at self.rcoords_wavelength_A.

See Anzer & Heinzel, 2005 for details.
get_opac_heii()

HeII opacity at self.rcoords_wavelength_A.

See Anzer & Heinzel, 2005 for details.
get_p()

momentum density. p = (u * r) = (velocity * mass density).

get_q()

charge, of a “single particle”. for protons, == +1 elementary charge.

[Not implemented for this class]
get_r()

mass density. r = (n * m) = (number density * mass)

get_rcoords_Pe()

electron Pressure values for G(T) for fixed pressure, in [self.units] system,

along dimension ‘P’, with coords always in [cgs] units regardless of self.units.
Determined by self.rcoords_Pe_cgs (which can be set directly), converted to [self.units].
get_rcoords_logD()

log(electron number density) values for VDEMs and G(T,ne), with ne in [self.units] system,

along dimension ‘logD’, with coords always telling log10(ne [cgs]) regardless of self.units.
Determined by self.rcoords_logD_cgs (which can be set directly), converted to [self.units].
Getting self(‘rcoords_logD’) will crash if self.rcoords_logD_cgs is None, with a helpful error message.
get_rcoords_logT()

log(Temperature) values used by some vars (e.g. vdems and G(T)), in [self.units] system,

along dimension ‘logT’, with coords always telling log(T [K]) regardless of self.units.
Determined by self.rcoords_logT (which can be set directly), converted to [self.units].
get_rcoords_vdop()

velocity (or, doppler shift) values used by some vars (e.g. vdems and spectra), in [self.units] system,

along dimension ‘vdop’, with coords always in km/s regardless of self.units.
Determined by self.rcoords_vdop_kms (which can be set directly), converted to [self.units].
get_set_or_cached(var)

returns var if found in self.setvars or self.cache, with compatible behavior_attrs.

otherwise, raise CacheNotApplicableError.
if var is found in self.setvars and has relevant, but not matching behavior_attrs,
self.load_across_dims will be used to load the value.
get_single_fluid_var(var, *, _match=None)

SF_{var} (or SINGLE_FLUID_{var}) –> {var}, definitely in single fluid mode.

crashes with FluidValueError if not self.in_single_fluid_mode.
The implementation here just does self.assert_single_fluid_mode(),
then returns self(var) (var from SF_var or SINGLE_FLUID_var string).
Subclass might override to also set self.fluid = SINGLE_FLUID.
get_spectra(var, *, _match=None)

Synthetic spectra for a given ion. Always in [cgs] units, regardless of self.units.

Units erg/cm^2/s/sr/Angs
Result depends on self.rcoords_vdop_kms and self.rcoords_wavelength_A, which can be set directly.
Result varies along the ‘vdop’ dimension which indicates doppler velocity (in km/s).
[TODO] formula/details
get_tau()

Optical depth along line of integration (default: loi = line of sight),

at wavelength=self.rcoords_wavelength_A, and considering only H, HeI, and HeII contributions.
Result is always in [cgs] units, regardless of self.units.
loi determined by self.loi (see help(type(self).loi) for details),
when using self.los = self.vdem_los_explicit (see help(type(self).vdem_los) for details).
tau(l) = integral(absorption * dl, from 0th l value to l); use self.loi instead of l.
(in python terms, this is represented by a cumsum.)
To reverse direction (i.e. “start from the other end”), edit self.loi or self.vdem_los.
E.g. when self.loi=’los’, swapping from self.vdem_los=’-x’ to self.vdem_los=’x’ swaps direction.
get_tau_500(wavelength=None)

Computes the tau scale from H-bf opacity alone 500 nm.

Assume all hydrogen to be neutral
get_u()

velocity. vector quantity (result depends on self.component)

[Not implemented for this class]
get_u_neutral()

velocity of neutrals. vector quantity (result depends on self.component)

[Uses self.get_neutral(‘u’) if possible, else crash. Subclass may override.]
get_vars(vars, *args, return_type='dataset', missing_vars=UNSET, **kw)

returns values of vars from self.

result is probably an xarray.Dataset, but not guaranteed; also depends on return_type.
Equivalent to self(vars, *args, return_type=’dataset’, **kw).
(Actually, self(vars, …) will call self.get_vars(vars, …).)
vars: iterable of strs
Names of the vars to load. [‘n’, ‘u’] for number density & velocity.
if any of these vars returns a return_type object, expand its keys,
e.g. if ‘myDSvar’ returns dataset with ‘myvar1’, ‘myvar2’,
then [‘n’, ‘myDSvar’] gives dataset with ‘n’, ‘myvar1’, ‘myvar2’.
return_type: ‘dataset’ or ‘dict’
if ‘dataset’, return result as xarray.Dataset.
the data_var names will be the same as the var names.
if ‘dict’, return result as dict of {var: value}.
missing_vars: UNSET, ‘ignore’, ‘warn’, or ‘raise’
what to do if any vars cause FormulaMissingError at any point in the error stack.
UNSET –> use self.missing_vars if it exists, else ‘raise’.
‘ignore’ –> ignore missing vars, and don’t include them in the result.
‘warn’ –> ignore missing vars, but print a warning.
‘raise’ –> raise FormulaMissingError if any vars are missing.
additional args & kwargs are passed to self(…).
get_vdem()

VDEM (intergrated along an axis), as a function of temperature and velocity.

If
Result depends on self.vdem_mode; see self.VDEM_MODE_OPTIONS for details.
See also: self.interp_masked
Regardless of self.vdem_mode, the following always apply:
temperature and velocity are determined by self.rcoords_logT and self.rcoords_vdop_kms,
which can be set directly.
Result is always in [cgs] units, regardless of self.units.
(Result’s coords’ units will still be self.units, or self.coords_units if not None.)
Might ignore photosphere, depending on self.vdem_ignores_photosphere;
see help(type(self).vdem_ignores_photosphere) for details.
Result is along line of sight corresponding to self.component (must be a single value).
Can set via, e.g., self.component=’x’, or self(‘vdem_y’), or self(var, component=’z’).
Ignores emiss contributions from very cold regions (log10(T) < self.vdem_logT_min).
get_vdem_allinterp()

VDEM (intergrated along an axis), with interpolation (Matthias trick along T and u)

See self.help(‘vdem’) or help(self.get_vdem) for more details about vdems.
Equivalent: self(‘vdem’, vdem_mode=’allinterp’).
get_vdem_interp()

VDEM (intergrated along an axis), with interpolation (Matthias trick along T)

See self.help(‘vdem’) or help(self.get_vdem) for more details about vdems.
Equivalent: self(‘vdem’, vdem_mode=’interp’).
get_vdem_no_interp()

VDEM (intergrated along an axis), without interpolation.

See self.help(‘vdem’) or help(self.get_vdem) for more details about vdems.
Equivalent: self(‘vdem’, vdem_mode=’nointerp’).
get_vtherm_instr()

thermal velocity including instrumental broadening.

vtherm_instr = sqrt((kB T / m) + w_instrumental^2)
w_instrumental can be set via self.w_instrumental_si = value.
get_w_instrumental()

instrumental broadening for thermal velocity, in self.units system.

w_instrumental = self.w_instrumental_si, converted to self.units system.
See also: vtherm_instr
property gofnt_abundance

Abundance(?) to use for G(T) calculations.

Passed directly to muse.instr.utils.chianti_gofnt_linelist via “abundance” kwarg.
property gofnt_interp_mode

Selects the emission measure x G(T) calculation mode.

See self.GOFNT_INTERP_MODE_OPTIONS for options.
property gofnt_mode

Selects the G(T) calculation mode. See self.GOFNT_MODE_OPTIONS for options.

property gofnt_wavelength_range

Wavelength range (as [min, max]) (in [Angstrom] units) to use for G(T) calculations.

Passed directly to muse.instr.utils.chianti_gofnt_linelist via “wavelength_range” kwarg.
has_var(var)

return whether self can load var. True if self.match_var(var) is found, else False.

Subclasses might override, to include checks for whether var can be loaded from data.
[TODO] also check if var in self.cache or self.setvars.
help(qstr=None, only=None, *, tree=None, modules=False, signature=False, doc=True, dense=False, print=True)

prints str for help with quants.

qstr: None or str

None –> tells info about this class & how to use this function.
in particular, tells that quants are stored cls.KNOWN_VARS and cls.KNOWN_PATTERNS,
and describes behavior of calling help with a string.
str –> return str for help with all quants related to str.
use empty str to get help for all quants.
only: None or str
If provided, only get help for a subset of relevant quantities.
None –> get help with all quantities related to qstr.
‘VARS’ –> only get help with KNOWN_VARS.
‘PATTERNS’ –> only get help with KNOWN_PATTERNS.
‘TREE’ –> only get help with quantities in cls.cls_var_tree(str).
‘EXACT’ –> only get help for the KNOWN_VAR exactly matching qstr.
if provided when qstr is None, treat qstr as ‘’ instead.
tree: None or bool
How much help to give for quantities in cls.cls_var_tree(qstr).
False –> don’t even check cls.cls_var_tree(qstr).
True –> help for all quantities in cls.cls_var_tree.
None –> help for quantities in cls.cls_var_tree(qstr).flat_branches_until_vars()
i.e. patterns & vars in tree but ignore any nodes with LoadableVar ancestors.
e.g. qstr=’mean_mod_beta’ –> help with ‘mean_(.+)’, ‘mod_(.+)’, and ‘beta’,
but no help with dependencies of ‘beta’ (‘q’, ‘mod_B’, ‘m’).
modules: bool
Whether to include modules in result.
If True, result will be grouped into sections with modules written at top.
signature: signature: bool
whether to include line with signature in help string.
e.g. “help_str(f, *, module=True, signature=True, indent=None)”
doc: doc: bool
whether to include lines with docstring in help string.
e.g. “return str for help(f).” … and all the other docs in here.
dense: bool
Whether to reduce whitespace in result.
E.g. True –> no newlines between functions. False –> one newline between functions.
help_call_options(search=None)

prints help for kw_call_options.

if search is provided, only print help for keys containing search.
classmethod help_quants_str(qstr=None, only=None, *, tree=None, modules=True, signature=False, doc=True, dense=False, _instance=None)

returns str for help with quants.

qstr: None or str

None –> tells info about this class & how to use this function.
in particular, tells that quants are stored cls.KNOWN_VARS and cls.KNOWN_PATTERNS,
and describes behavior of calling help with a string.
str –> return str for help with all quants related to str.
use empty str to get help for all quants.
only: None or str
If provided, only get help for a subset of relevant quantities.
None –> get help with all quantities related to qstr.
‘VARS’ –> only get help with KNOWN_VARS.
‘PATTERNS’ –> only get help with KNOWN_PATTERNS.
‘TREE’ –> only get help with quantities in cls.cls_var_tree(str).
‘EXACT’ –> only get help for the KNOWN_VAR exactly matching qstr.
if provided when qstr is None, treat qstr as ‘’ instead.
tree: None or bool
How much help to give for quantities in cls.cls_var_tree(qstr).
False –> don’t even check cls.cls_var_tree(qstr).
True –> help for all quantities in cls.cls_var_tree.
None –> help for quantities in cls.cls_var_tree(qstr).flat_branches_until_vars()
i.e. patterns & vars in tree but ignore any nodes with LoadableVar ancestors.
e.g. qstr=’mean_mod_beta’ –> help with ‘mean_(.+)’, ‘mod_(.+)’, and ‘beta’,
but no help with dependencies of ‘beta’ (‘q’, ‘mod_B’, ‘m’).
modules: bool
Whether to include modules in result.
If True, result will be grouped into sections with modules written at top.
signature: signature: bool
whether to include line with signature in help string.
e.g. “help_str(f, *, module=True, signature=True, indent=None)”
doc: doc: bool
whether to include lines with docstring in help string.
e.g. “return str for help(f).” … and all the other docs in here.
dense: bool
Whether to reduce whitespace in result.
E.g. True –> no newlines between functions. False –> one newline between functions.
_instance: None or QuantityLoader instance
if provided, use _instance.match_var_tree() instead of cls.cls_var_tree().
classmethod help_str(qstr=None, only=None, **kw)

returns cls.help_quants_str(qstr=qstr, only=only, **kw).

cls.help() calls help_str.
subclasses might overwrite help_str, but probably won’t touch help_quants_str.
property in_single_fluid_mode

whether self is in “single fluid mode”.

MhdCalculator is always in single-fluid mode… but subclass might not be.
Some vars (bases especially) assume single-fluid mode, so it is good to check.
E.g. this ensures multifluid subclasses don’t do weird things by accident.
interp_masked(array_or_var, bins, dim=None, *, mode='correct', return_weights=False)

Compute interpolation masks and normalization factors for a variable (e.g., “T”)

for use in DEM/VDEM binning with or without logarithmic scaling.
Works just like the “static” method (not attached to this class),
but with a few extra convenient features here:
(1) first arg can be array (as in static method), OR a var.
if it is a var (i.e., a str), use array=self(var)
(2) dim does not need to be provided;
if not provided, use dim=str(self.component).
Docstring from “static” method copied below, for convenience.
————————————————————-
Array masked to bins, possibly with interpolation correction and normalization factors,
for use in (Velocity) Differential Emission Measure ((V)DEM) binning.
The result has array dims plus bins dim, with values from 0 to 1.
Conceptually - basically, this just tells whether array overlaps with each bin.
E.g. result.isel(x=i, y=j, bindim=k) tells whether the (i,j)th x,y point overlaps with bin k.
Actually - it may include an interpolation correction factor,
accounting for adjacent cell values, and any jumps larger than bin widths.
E.g. result.isel(x=i, bindim=k) tells how much of bin k is covered from the ith to (i+1)th x.
Additionally - if return_weights, this method also returns xn, which can be applied to a value,
to properly account for interpolation between adjacent cells.
See Rempel et al. (2017) for details.
(Note - Rempel+2017 formulas are slightly different than those here,
because those formulas solve a slightly different problem.
Testing those formulas here led to more numerical artifacts.)
If binning multiple quantities (e.g., temperature and velocity), the canonical pattern to use is:
mask1, xn = self.interp_masked(quantity1, bins1, return_weights=’exp’)
mask2 = self.interp_masked(quantity2, bins2)
mask3 = self.interp_masked(quantity3, bins3)
… # etc. i.e., only the first call computes interpolation weights.
emiss_interped = emiss * (1.0 - xn) + emiss.roll({x:1}) * xn
Note - the result’s first value along dim may be unreliable (if non-periodic array),
as it relies on array.roll({dim:1}).
Parameters
———-
array : xarray.DataArray
variable to be interp-masked. E.g., array of log10(temperature) values.
bins : xarray.DataArray
1D array of (evenly-spaced) bin centers (internally, assumes bin width = (bins[1]-bins[0])/2).
dim : str
apply the correction along this dimension of array.
For VDEMS, this is the dimension along which the LOS integration will be performed.
mode: ‘correct’ or ‘simple’
tells how to compute the result.
‘correct’ –> includes correction factor.
‘simple’ –> exclude correction factor, just tells whether each point falls within each bin.
Equivalent to: result = (bins - delta <= array) & (array < bins + delta),
where delta = (bins[1] - bins[0]) / 2 == bin width.
This can be much faster than mode=’correct’, but produces noisier results.
(Also, only allowed if return_weights=False).
return_weights : False, True, or ‘exp’
whether to also return interpolation weights xn for each bin.
False –> returns masked
True –> returns (masked, xn)
‘exp’ –> returns (masked, xn) but compute xn using (10**value, 10**bins) not (value, bins).
Returns
——-
masked : xarray.DataArray
array of fn * overlaps, where overlaps = whether each cell overlaps with each bin,
and fn = normalization factor for each bin, clipped to [0, 1].
(Or, if mode==’simple’, this is just (bins - delta <= array) & (array < bins + delta).)
xn : xarray.DataArray
Interpolation weight for each bin, with values clipped to [0, 1].
(Only returned if return_weights.)
kw_call_options(*, sorted=True)

returns list of kwarg names which can be used to set attrs self during self.__call__.

(see self.__call__ for more details).
Here, returns list(self.behavior_attrs) + list(self._extra_kw_for_quantity_loader_call)
limb_vdem_pipeline(*, iz0=50, snap=None, tile_snaps=None, tile_snaps_fov=UNSET, fov_method='standard', Abox_x_NXEXT=0, Nx_times=1, Ny_times=1, Nz_times=1, Asph_theta=1.5707963267948966, Asph_phi=0, rays_debug_fov=False, rays_debug_all_tiles=False, tg_percent=0.1, dlogT=0.1, mintg_cut=4.6, maxtg_cut=7.7, tg_bins=60, ulos_bin=60, vel_percent=0.1, dvdop=10, minvel_cut=-3000, maxvel_cut=3000, emiss_norm=1e+27, modelname='', nslicer=46, zarr_version=2, dst='pc_limb_vdem_pipeline', author)

Execute a VDEM pipeline for limb observations using ray draping geometry.

This specialized pipeline performs VDEM analysis for solar limb observations where

the line-of-sight follows curved ray paths through the simulation domain. It uses
ray draping to simulate realistic observing geometries and supports tiling multiple
snapshots for extended spatial coverage.
The pipeline handles large datasets by computing VDEM in slices, performs both
full-disk and photosphere-cutoff analyses, and generates diagnostic plots with
proper coordinate transformations for limb viewing geometry.
Parameters
———-
iz0 : int, default=50
Index along z-dimension marking the photosphere boundary. Used for
photosphere cutoff analysis.
snap : int or None, optional
Snapshot number to analyze. If None, uses current snapshot.
tile_snaps : array-like or None, optional
Array of snapshot indices to tile along x-dimension for extended coverage.
E.g., [0, 1, 2, ‘current’] tiles three consecutive snapshots, before the current snapshot.
(‘current’ or ‘here’ must appear in tile_snaps exactly once.)
Note that the full (tiled) extent will be repeated periodically as needed to cover rays.
None –> no tiling, equivalent to tile_snaps = [‘current’]
(i.e. the single current snapshot would be repeated periodically as needed).
tile_snaps_fov: UNSET, None, or array-like, optional
default fov includes all rays needed to cover tile_snaps_fov.
UNSET –> equivalent to tile_snaps_fov = tile_snaps.
None –> no tiling, i.e. default fov only includes the rays needed to cover the current snap.
E.g., to make FOV roughly “half-at-limb, half-on-disk”, and buffer with snap 0, could do:
tile_snaps_fov = [‘current’, 0], tile_snaps = [‘current’, 0, 0, 0].
fov_method : str, default=’standard’
Field-of-view generation method. Options depend on ray draping implementation.
Abox_x_NXEXT : float, default=0
X-offset for ray draping box in units of simulation XEXT (domain extent).
Allows shifting the observing geometry along x.
Nx_times : float, default=1
Multiplier for number of FOV pixels in x-direction relative to simulation Nx.
Ny_times : float, default=1
Multiplier for number of FOV pixels in y-direction relative to simulation Ny.
Nz_times : float, default=1
Multiplier for number of ray integration points relative to simulation Nz.
Asph_theta : float, default=np.pi/2
Spherical coordinate theta (colatitude) angle in radians for viewing geometry.
pi/2 corresponds to equatorial view.
Asph_phi : float, default=0
Spherical coordinate phi (azimuthal) angle in radians for viewing geometry.
rays_debug_fov: bool, default=False
if enabled, halt immediately after producing plot showing ray paths through tile_snaps_fov box.
rays_debug_all_tiles: bool, default=False
if enabled, halt immediately after producing plot showing ray paths through tile_snaps box.
This check occurs after rays_debug_fov; it is fast to produce both plots, so
it is recommended to use this flag to double-check the rays look correct,
before running full pipeline, especially for a large simulation.
tg_percent : float, default=0.1
Percentage threshold for automatic temperature range determination from histogram.
dlogT : float, default=0.1
Temperature bin width in log10(T [K]) units.
mintg_cut : float or None, default=4.6
Minimum log10(temperature [K]) cutoff. Overrides automatic determination.
maxtg_cut : float or None, default=7.7
Maximum log10(temperature [K]) cutoff. Overrides automatic determination.
tg_bins : int, default=60
Number of bins for temperature histogram analysis.
ulos_bin : int, default=60
Number of bins for velocity histogram analysis.
vel_percent : float, default=0.1
Percentage threshold for automatic velocity range determination from histogram.
dvdop : float, default=10
Velocity bin width in km/s.
minvel_cut : float or None, default=-3000
Minimum velocity cutoff in km/s. Overrides automatic determination.
maxvel_cut : float or None, default=3000
Maximum velocity cutoff in km/s. Overrides automatic determination.
emiss_norm : float, default=1e27
Emission measure normalization factor.
modelname : str, default=’’
Model identifier string used in output filenames.
nslicer : int, default=46
Number of slices for dividing FOV computation. Higher values reduce memory
usage but increase I/O overhead.
zarr_version : int, default=2
Zarr format version for output files (2 or 3).
dst : str, default=’pc_limb_vdem_pipeline’
Destination directory for output files.
author : str, required
Author name/identifier for output filenames and metadata.
Returns
——-
vdem0 : xarray.Dataset
Processed VDEM dataset with limb observation coordinates and complete metadata.
Contains ‘vdem’ data variable with dimensions (logT, vdop, x, y) where x and y
represent FOV coordinates.
Notes
—–
**Copy of self**: This pipeline uses self.copy() instead of using self directly,
to avoid editing self in-place. Self will not be changed by this pipeline.
**Temporary Directories**: This pipeline creates and DELETES temporary directories:
- ‘_pc_temp_fov_lib_vdem/’: For storing partial VDEM computations
- ‘_pc_temp_fov_lib_vdem_ph/’: For photosphere-cutoff VDEM computations
These directories will be destroyed via shutil.rmtree() during pipeline execution.
**Ray Draping Setup**: The pipeline configures ray draping with:
- R0 = Solar radius (from DEFAULTS.PHYSICAL.CONSTANTS_SI)
- T = 1 AU (observer distance)
- Integration points scaled by Nz_times
- FOV dimensions scaled by Nx_times
- Spherical viewing angles (Asph_theta, Asph_phi)
**Output Files**:
- Temperature/velocity histograms:
‘T_ulos_hist_{code}_{modelname}_{author}_{date}_{snap}.png’
- VDEM moments (full):
‘vdem_moment_{code}_{modelname}_{author}_{date}_{snap}.png’
- VDEM moments (photosphere):
‘vdem_moment_ph_{code}_{modelname}_{author}_{date}_{snap}.png’
- VDEM Zarr dataset:
‘vdem_{code}_{modelname}_limb_{author}_{date}_snaps_{tiles}.zarr’
**Processing Steps**:
1. Configure ray draping geometry with spherical coordinates
2. Enable snapshot tiling if tile_snaps provided
3. Compute histograms to determine optimal T and velocity ranges
4. Compute VDEM in FOV slices to manage memory
5. Merge slices and compute moments for full domain
6. Repeat with photosphere cutoff (z < iz0-15)
7. Generate diagnostic plots with proper scaling
8. Save with complete metadata and coordinate attributes
Examples
——–
>>> # Standard limb observation at solar equator
>>> result = calc.limb_vdem_pipeline(
… snap=100,
… tile_snaps=[99, ‘current’, 101],
… author=’scientist_name’
… )
>>> # High-resolution polar limb observation
>>> result = calc.limb_vdem_pipeline(
… Asph_phi=-np.pi/2, # North pole view
… Nx_times=2, # Double resolution
… dlogT=0.05, # Finer temperature bins
… nslicer=92, # More slices for memory
… author=’scientist_name’
… )
>>> # Limb observation with shifted viewpoint
>>> result = calc.limb_vdem_pipeline(
… Abox_x_NXEXT=0.5, # Shift by half domain width
… Asph_phi=np.pi/4, # 45-degree azimuthal angle
… author=’scientist_name’
… )
See Also
——–
vdem_pipeline : Standard VDEM pipeline without ray draping
get_vdem : Core VDEM computation method
ray_draper : Ray draping geometry handler
load_direct(var, *args, **kw)

load var “directly”, from some source which is not known by the main part of PlasmaCalcs.

The implementation here just returns self.load_fromfile() (or crashes if not self.enable_fromfile),
but subclasses may override to include more checks. (see DirectLoader)
(Here also sets self._load_direct_used_override = None to indicate no override was used,
i.e. result is from load_fromfile, not from something like setvars nor cache.)
return the result (probably a numpy array, but not guaranteed).
load_fromfile(var, *args, **kw)

load var directly from a file. Other methods should usually use load_direct, instead.

the implementation here just raises LoadingNotImplementedError;
subclasses should implement this method in order to load any values from files.
property maintaining

alias to maintaining_attrs

maintaining_attrs(*attrs, **attrs_as_flags)

returns context manager which restores attrs of self to their original values, upon exit.

E.g. maintaining_attrs(obj, ‘attr1’, ‘attr2’, attr3=True, attr4=False)
–> will restore upon exit, original values of obj.attr1, attr2, and attr3, but not attr4.
classmethod match_var(var, *, check=['KNOWN_VARS', 'KNOWN_PATTERNS'])

match var from cls.KNOWN_VARS or cls.KNOWN_PATTERNS, or raise FormulaMissingError.

returns result=MatchedQuantity(var, loadable, _match=_match) where:

loadable is the LoadableQuantity associated with this var,
_match is:
None, if var in cls.KNOWN_VARS;
re.fullmatch(pattern, var), if var matches any pattern in cls.KNOWN_PATTERNS.
if var matches multiple patterns, only the first matching pattern is used.
Uses MatchedVar if match from KNOWN_VARS, MatchedPattern if from KNOWN_PATTERNS.
(note that both MatchedVar and MatchedPattern subclass MatchedQuantity.)
check: str or list of str from [‘KNOWN_VARS’, ‘KNOWN_PATTERNS’]
where to check for matches. Default is to check KNOWN_VARS and KNOWN_PATTERNS.
E.g. to only check KNOWN_PATTERNS, use check=[‘KNOWN_PATTERNS’].
loadable and _match can be retrieved via result.loadable and result._match.
match_var_loading_dims(var, **kw_loading_dims)

return dims for loading var across.

Result will probably vary across these dims (but not guaranteed, if any dependency uses reduces_dims.)
These are all Dimension dims, not maindims. (E.g. ‘fluid’ and ‘snap’, but not ‘x’, ‘y’, ‘z’).
Equivalent: self.match_var_tree(var).loading_dims(**kw_loading_dims)
match_var_result_dims(var, **kw_result_dims)

return dims which result of cls(var) will vary across.

These are all Dimension dims, not maindims. (E.g. ‘fluid’ and ‘snap’, but not ‘x’, ‘y’, ‘z’).
Equivalent: cls.match_var_tree(var).result_dims(**kw_result_dims)
match_var_result_size(var, *, maindims=True, **kw_result_dims)

return size (number of elements) which self(var) will have.

(Efficient; doesn’t actually get self(var).)
Depends on current values of relevant dims. (E.g., self.fluid, not self.fluids)
maindims: bool
if True, include maindims_shape when calculating size.
match_var_tree(var=UNSET, **kw_quant_tree_from_quantity_loader)

return QuantTree of MatchedQuantity objects from matching var and all dependencies,

using self.KNOWN_VARS and self.KNOWN_PATTERNS when searching for matches.
var must be provided; var=UNSET will raise an error (helpful if tried calling this as a classmethod).
See also: type(self).cls_var_tree, for the classmethod version of this function.
Most of the time it is possible to get tree without any details from self,
but sometimes not. e.g. when getting collision frequencies, self.fluid affects deps.
additional kwargs will be passed to QuantTree.from_quantity_loader(…),
which passes kwargs from self.kw_call_options() into self.using(**kw) while getting deps.
matched_pattern_cls

alias of MatchedPattern

matched_var_cls

alias of MatchedVar

property nondim_behavior_attrs

list of attrs in self which control behavior of self, but which are NOT in self.dimensions.

quant_tree(var=UNSET, **kw_quant_tree_from_quantity_loader)

return QuantTree of MatchedQuantity objects from matching var and all dependencies,

using self.KNOWN_VARS and self.KNOWN_PATTERNS when searching for matches.
var must be provided; var=UNSET will raise an error (helpful if tried calling this as a classmethod).
See also: type(self).cls_var_tree, for the classmethod version of this function.
Most of the time it is possible to get tree without any details from self,
but sometimes not. e.g. when getting collision frequencies, self.fluid affects deps.
additional kwargs will be passed to QuantTree.from_quantity_loader(…),
which passes kwargs from self.kw_call_options() into self.using(**kw) while getting deps.
quant_tree_cls

alias of QuantTree

property rcoords_Pe_cgs

electron Pressure [cgs units] values, used by some MhdRadiativeLoader vars.

E.g., used by G(T) when self.gofnt_mode==’pressure’.
Can be a scalar, a 1D list or numpy array, or 1D xr.DataArray with dimension ‘Pe’.
property rcoords_logD_cgs

log10(electron number density [cgs units]) values, used by some MhdRadiativeLoader vars.

E.g., used in vdems and used by G(T,ne) when self.gofnt_mode==’density’.
Can be a scalar, a 1D list or numpy array, or 1D xr.DataArray with dimension ‘logD’.
property rcoords_logT

log10(Temperature [K]) values used by some MhdRadiativeLoader vars.

E.g., used in VDEMs and in G(T) lookup tables.
Can be a scalar, a 1D list or numpy array, or 1D xr.DataArray with dimension ‘logT’.
Note: rcoords_logT minimum value can never be less than self.vdem_logT_min.
(attempting to set bad value will cause crash & helpful error message.)
property rcoords_vdop_kms

velocity [km/s] (or, doppler shift) values, used by some MhdRadiativeLoader vars.

E.g., used in VDEMs and in getting spectra.
Can be a scalar, a 1D list or numpy array, or 1D xr.DataArray with dimension ‘vdop’.
property rcoords_wavelength_A

Wavelength (in [Angstrom] units) used by some MhdRadiativeLoader vars.

E.g., used in get_spectra().
[TODO] can it be a 1D list/array, or is it required to be a scalar?
property set

alias to set_var

set_T_fromtable(value, **kw)

set T_fromtable to this value. T_fromtable = single fluid temperature, from er table.

Depends on the current value of r; if also setting r be sure to set r first.
(internally, sets eperm such that T is the given value when doing lookups.)
set_e(value, **kw)

set e to this value. e = energy density.

set_eperm(value, **kw)

set eperm to this value. eperm = internal energy per unit mass == e / r.

Depends on the current value of r; if also setting r be sure to set r first.
set_n(value, **kw)

set n to this value. n = number density == r / m.

set_r(value, **kw)

set r to this value. r = mass density.

set_var(var, value, behavior_attrs=None, forall=[], *, ukey=None, forced=False, **kw_using)

set var in self. When later doing self(var) to get var, return the set value,

but only if self.behavior is compatible with the relevant parts of self.behavior when var was set.
This function will use, if it exists:
self.KNOWN_SETTERS[var](self, value, behavior_attrs, forall=forall)
Otherwise, calls:
self.set_var_internal(var, value, self.behavior_attrs, forall=forall)
var: str
the var to set in self.
value: number, xarray, iterable or 1D array, array with shape matching self.maindims_shape.
the value to set var to.
number –> set var to this number.
xarray –> set var to this xarray.
[TODO](not yet implemented) iterable or 1D array –> set var to these values along dim=’testing’.
[TODO](not yet implemented) array with shape matching self.maindims_shape –> set var to this array.
behavior_attrs: None or list
tells which attrs from self control behavior of the set var.
The set var will only be retrieved when behavior_attrs of self are compatible.
E.g. set_var(‘n’, [‘fluid’, ‘snap’]) –> saves ‘n’ in cache with current fluid & snap.
Will only load ‘n’ if self.fluid and self.snap == cached fluid and snap for ‘n’.
if var in self.KNOWN_SETTERS, cannot provide behavior_attrs here.
else, use self.behavior_attrs if None.
forall: list of strings
if provided, tells which attrs of self do NOT control the behavior of the set var.
E.g. forall=[‘snap’] –> ‘snap’ will NOT be included in behavior_attrs.
(anything in behavior_attrs AND forall will be removed from the final behavior_attrs)
ukey: None or str
if provided, tells string to give to UnitsManager when converting value’s units.
When ukey is known, setting value in any unit system will enable to read it in all unit systems.
E.g. set_var(‘n’, 1e10, …, ukey=’n’, units=’si’)
–> self(‘n’, units=’raw’) == self(‘n’, units=’si’) * self.u(‘u’, ‘raw’, convert_from=’si’)
if not provided, value will be associated with current unit system;
attempted to read value in any other unit system will not used the cached value set here.
E.g. set_var(‘u’, 1e10, …, units=’si’) # ukey not provided
–> self(‘u’, units=’raw’) –> uses self’s other logic for getting ‘u’, not from setvars.
note: if provided, ‘units’ will be added to behavior_attrs if not already in there.
forced: bool, default True
handles the case where self.KNOWN_SETTERS[var] doesn’t exist. In that case…
True –> set var in self, anyway.
False –> crash; raise FormulaMissingError
additional kwargs, if provided, go to self.using(**kw) during the operation.
returns list of set quantities.
set_var_internal(var, value, behavior_attrs, forall=[], *, ukey=None)

set var in self. KNOWN_SETTERS functions may wish to use this method.

(KNOWN_SETTERS functions should NOT use self.set_var, to avoid recursion issue.)
This function has the internal logic for self.set_var;
set_var calls set_var_internal when self.KNOWN_SETTERS[var] not provided.
var: str
the var to set in self.
value: number, xarray, iterable or 1D array, array with shape matching self.maindims_shape.
the value to set var to. See help(self.set_var) for more info.
behavior_attrs: list of strings
the behavior attrs relevant to setting this var;
getting var only gives value when current behavior attrs values are compatible with the cached ones.
forall: list of strings
if provided, tells which behavior attrs do NOT control the behavior of the set var.
e.g. behavior_attrs=[‘snap’, ‘fluid’], forall=[‘snap’] –> use [‘fluid’], only.
ukey: None or str
if provided, tells string to give to UnitsManager when converting value’s units;
when ukey is provided, can retrieve value in any unit system (probably ‘si’ or ‘raw’).
when ukey not provided, if ‘units’ in used behavior attrs, can only retrieve value in that unit system.
property setvar

alias to set_var

property setvars

VarCache of vars set via self.set_var(). Returns these values when appropriate,

i.e. whenever self.behavior is compatible with the behavior in the cache.
To empty the cache, use self.setvars.clear() to empty the cache.
property toplevel_scale_coords

dict of {coord_name: coord_scaling} to apply to top-level outputs of self(var).

(Never applies to internal calls of self(var), only applies at self.call_depth==1.)
Useful if making plots and want to scale coords by some factor.
E.g., self.toplevel_scale_coords = {‘t’: 1000} to convert s to ms.
CAUTION: coord units labels will remain unaffected.
tree(var=UNSET, **kw_quant_tree_from_quantity_loader)

return QuantTree of MatchedQuantity objects from matching var and all dependencies,

using self.KNOWN_VARS and self.KNOWN_PATTERNS when searching for matches.
var must be provided; var=UNSET will raise an error (helpful if tried calling this as a classmethod).
See also: type(self).cls_var_tree, for the classmethod version of this function.
Most of the time it is possible to get tree without any details from self,
but sometimes not. e.g. when getting collision frequencies, self.fluid affects deps.
additional kwargs will be passed to QuantTree.from_quantity_loader(…),
which passes kwargs from self.kw_call_options() into self.using(**kw) while getting deps.
property typevar_crash_if_nan

bool. whether to crash methods if typevar output would be ‘nan’.

False –> return NaN when typevar gives ‘nan’, instead of crashing.
“typevar” here refers to any var used for checking which formula to use, from various options,
e.g. ‘ntype’ in MhdMultifluidLoader or ‘ionfrac_type’ in MhdIonizationLoader.
The relevant methods can check if self.typevar_crash_if_nan before returning a ‘nan’ result.
property unset

alias to unset_var

unset_var(var, behavior_attrs=[], *, missing_ok=True, **kw_using)

remove var from self.setvars (but only at values stored with relevant behavior).

[TODO] define rules for which vars unset which other vars…
e.g. for eppic right now, set_var(‘n’) sets ‘den’ but not ‘n’;
unset_var(‘n’) unsets nothing… but should probably alias to unset_var(‘den’).
behavior_attrs: list of strings
only remove cached values where self.behavior matches cached behavior for these attrs.
if empty, remove all cached values for var, regardless of associated behavior.
missing_ok: bool
whether it is okay for there to be zero matching cached values for var.
raise CacheNotApplicableError if missing_ok=False when there are no matching cached values.
additional kwargs, if provided, go to self.using(**kw) during the operation.
return list of CachedQuantity objects which were removed from self.setvars.
unset_var_internal(var, behavior_attrs, forall=[], *, ukey=None, missing_ok=True)

unset var from self.setvars.

KNOWN_SETTERS functions may wish to use this method, to unset dependent values.
E.g. if u depends on n, and n is changed, may wish to unset the value of u.
behavior_attrs: list of strings
the behavior attrs relevant to setting this var.
forall: list of strings
if provided, tells which behavior attrs to ignore when unsetting the var.
ukey: None or string
if provided, ignore ‘units’ behavior attr when unsetting the var
(due to assuming that ukey was provided when setting the var,
hence that the set var could be retrieved in any units system)
missing_ok: bool
whether it is okay for there to be zero matching cached values for var.
raise CacheNotApplicableError if missing_ok=False when there are no matching cached values.
return list of CachedQuantity objects which were removed from self.setvars.
property using

alias to using_attrs

using_at_call_depth(depth, **attrs_and_values)

context manager for setting attrs_and_values but only while call_depth == depth.

E.g.:

with self.using_at_call_depth(3, verbose=3):
self(‘sgyrof’)
# while self.call_depth == 3 inside of this ‘with’ block, uses self.verbose=3.
# but everywhere else, uses original value of verbose.
# assuming originally verbose=False (or unset), this example will print:
| | (call_depth=2) get var=’q’
| | (call_depth=2) get var=’mod_B’
| | (call_depth=2) get var=’m’
# compare this to simply using self.verbose=3, which would print:
| (call_depth=1) get var=’sgyrof’
| | (call_depth=2) get var=’q’
| | (call_depth=2) get var=’mod_B’
| | | (call_depth=3) get var=’B_dot_B’
| | | | (call_depth=4) get var=’B_xyz’
| | | | | (call_depth=5) get var=’B’
| | (call_depth=2) get var=’m’
Equivalent to self.call_depth_manager.using_obj_attrs_at(depth, **attrs_and_values)
using_at_next_call_depth(**attrs_and_values)

context manager for setting attrs_and_values but only while call_depth == self.call_depth + 1

Equivalent to self.using_at_call_depth(self.call_depth + 1, **attrs_and_values).

(Also equivalent to self.call_depth_manager.using_obj_attrs_at_next(**attrs_and_values).)
using_attrs(attrs_as_dict={}, _unset_sentinel=ATTR_UNSET, **attrs_and_values)

returns context manager which sets attrs of obj upon entry; restores original values upon exit.

_unset_sentinel: any value, default ATTR_UNSET
upon entry, delete any attrs with value _unset_sentinel (compared via ‘is’).
E.g. using_attrs(obj, _unset_sentinel=None, x=None) –> del obj.x upon entry.
property vdem_ignores_photosphere

Specifies how the photosphere is treated in VDEM calculations.

Options include:
‘z=0’ –> account for photosphere by ignoring all values at z < 0.
False –> do not worry about photosphere.
property vdem_logT

(self.vdem_logT_min, self.rcoords_logT).

Can set both at once via self.vdem_logT = (desired_min, desired_coords)
property vdem_logT_min

Minimum log10(temperature [K]) to include in VDEM calculations.

some VDEMs ignore emiss contributions from very cold regions (T < self.vdem_logT_min).
Note: vdem_logT_min can never be more than minimum value of self.rcoords_logT.
(attempting to set bad value will cause crash & helpful error message.)
property vdem_loopdim

Tells which dimension to loop over during vdems.

Passed as “loop” kwarg to xarray_multiply_then_sum_along. Docs for that parameter copied below:
None, str, or (str, int, mode).
Indicates looping instructions (if any) to use during xarray_multiply_then_sum_along.
None –> no looping; simply multiply all arrays, then sum along dim.
Conceptually simplest. But, internally builds unnecessarily large array,
which might be larger than DEFAULTS.RESULT_ARRAY_GBYTES_MAX and thus trigger MemorySizeError.
str –> loop over each point along the indicated dimension.
If loop != dim, sum at each point and then concatenate final result.
If loop == dim, keep a running sum during the loop; no need to concatenate final result.
‘int’ or ‘sum’ –> equivalent to using loop == dim.
(str, integer, mode) –> (loop dimension, chunk size, chunk size mode)
loop over the indicated dimension in chunks of the indicated size,
instead of only one point at a time. This is usually the most efficient option. Mode can be:
‘GB’ –> size of chunk arrays in GB (approximately)
E.g., (‘logT’, 5, ‘GB’) picks chunk size for logT such that each chunk is 5 GB or less.
‘size’ –> number of points in the dimension.
E.g., (‘x’, 5, ‘size’) does first 5 points along x, then next 5, etc.
‘n’ –> number of chunks (roughly)
E.g., (‘x’, 5, ‘n’) does first 1/5 of n points, then next 1/5, etc.
Not guaranteed to be exactly 5 chunks, due to rounding.
property vdem_los

tells which line of sight to integrate along for vdem calculations.

if None, vdems will use self.los if provided, else self._DEFAULT_VDEM_LOS (default: ‘-component’).
(see self.LOS_OPTIONS for more details about the available shorthand options.
Another option is to use an xr.DataArray with ‘component’ dimension.)
The default (‘-component’) means the opposite direction implied by self.component,
e.g. if self.component==’z’, then vdem_los is ‘-z’ (corresponding to paths
which start at top of box and proceed downwards along z).
Use self.vdem_los_explicit to get the actual value that will be used
(filling in default or value from self.los as appropriate).
property vdem_los_explicit

self.vdem_los, but if None convert to the explicit vdem_los to use.

property vdem_mode

Selects the velocity-differential emission measure (VDEM) calculation mode.

See self.VDEM_MODE_OPTIONS for options.
vdem_pipeline(*, los_dim='z', iz0=50, tg_percent=0.1, dlogT=0.1, mintg_cut=4.6, maxtg_cut=7.7, tg_bins=60, ulos_bin=60, vel_percent=0.1, dvdop=10, minvel_cut=-3000, maxvel_cut=3000, emiss_norm=1e+27, modelname='', zarr_version=2, chunks=256, ncpu=12, dst='pc_vdem_pipeline', author)

Execute a standard VDEM (Velocity-Differential Emission Measure) analysis pipeline.

This pipeline performs a complete VDEM analysis including:

1. Automatic determination of temperature and velocity ranges from data histograms
2. Computation of VDEM with configurable binning
3. Generation of moment plots (intensity, mean velocity, width)
4. Photosphere region analysis with separate plots
5. Saving results to Zarr format with complete metadata
The pipeline automatically determines optimal temperature and velocity bins based on
histogram analysis, applies user-specified cutoffs, computes VDEM along the specified
line-of-sight dimension, and generates diagnostic plots.
Parameters
———-
los_dim : str, default=’z’
Line-of-sight dimension for VDEM integration (‘x’, ‘y’, or ‘z’).
iz0 : int, default=50
Index along z-dimension marking the photosphere boundary. Used to define
integration limits and photosphere cutoff analysis.
tg_percent : float, default=0.1
Percentage threshold for automatic temperature range determination.
Histogram bins with density > tg_percent% of maximum are included.
dlogT : float, default=0.1
Temperature bin width in log10(T [K]) units.
mintg_cut : float or None, default=4.6
Minimum log10(temperature [K]) cutoff. Overrides automatic determination
if specified.
maxtg_cut : float or None, default=7.7
Maximum log10(temperature [K]) cutoff. Overrides automatic determination
if specified.
tg_bins : int, default=60
Number of bins for temperature histogram analysis.
ulos_bin : int, default=60
Number of bins for velocity histogram analysis.
vel_percent : float, default=0.1
Percentage threshold for automatic velocity range determination.
Histogram bins with density > vel_percent% of maximum are included.
dvdop : float, default=10
Velocity bin width in km/s.
minvel_cut : float or None, default=-3000
Minimum velocity cutoff in km/s. Overrides automatic determination if specified.
maxvel_cut : float or None, default=3000
Maximum velocity cutoff in km/s. Overrides automatic determination if specified.
emiss_norm : float, default=1e27
Emission measure normalization factor.
modelname : str, default=’’
Model identifier string used in output filenames.
zarr_version : int, default=2
Zarr format version for output files (2 or 3).
chunks : int, default=256
Chunk size for parallel computation along spatial dimensions.
ncpu : int, default=12
Number of CPU cores to use for parallel computation.
dst : str, default=’pc_vdem_pipeline’
Destination directory for output files.
author : str, required
Author name/identifier for output filenames and metadata.
Returns
——-
vdem0 : xarray.Dataset
Processed VDEM dataset with coordinates and attributes set for the full domain.
Contains ‘vdem’ data variable with dimensions (logT, vdop, x, y).
Notes
—–
The pipeline generates the following outputs:
- Temperature and velocity histogram plot:
‘T_ulos_hist_{code}_{modelname}_{author}_{date}_{snap}.png’
- VDEM moments plot (full domain):
‘vdem_moment_{code}_{modelname}_{author}_{date}_{snap}.png’
- VDEM moments plot (photosphere):
‘vdem_moment_ph_{code}_{modelname}_{author}_{date}_{snap}.png’
- VDEM Zarr dataset:
‘vdem_{code}_{modelname}_los{los_dim}_{author}_{date}_{snap}.zarr’
The pipeline automatically:
- Sets units to CGS
- Determines integration slice from iz0 to top of domain
- Computes histograms to find optimal binning
- Applies both automatic and manual cutoffs for T and velocity ranges
- Computes VDEM with multiprocessing support
- Generates moment plots with logarithmic scaling for intensity
- Performs separate photosphere analysis (iz0 to iz0+5)
- Adds complete history and metadata to output
Examples
——–
>>> # Standard VDEM pipeline with default settings
>>> result = calc.vdem_pipeline(author=’scientist_name’)
>>> # Custom temperature and velocity ranges
>>> result = calc.vdem_pipeline(
… mintg_cut=5.0,
… maxtg_cut=7.0,
… minvel_cut=-1000,
… maxvel_cut=1000,
… author=’scientist_name’
… )
>>> # High-resolution analysis with more CPU cores
>>> result = calc.vdem_pipeline(
… dlogT=0.05,
… dvdop=5,
… chunks=128,
… ncpu=24,
… author=’scientist_name’
… )
See Also
——–
limb_vdem_pipeline : Pipeline for limb observations with ray draping
get_vdem : Core VDEM computation method
property vdem_varies_logD

tells whether vdems should also vary across logD (electron number density) dimension,

in addition to temperature (logT) and velocity (vdop) dimensions.
Currently, equivalent to: (self.rcoords_logD_cgs is not None).
(Eventually, might allow to edit this property directly, instead.)
property w_instrumental_si

instrumental broadening for thermal velocity, in SI units.

vtherm_instr = sqrt((kB T / m) + self.w_instrumental_si^2)