SnapDimension

class PlasmaCalcs.dimensions.snaps.SnapDimension(*, u=None, **kw_super)

Bases: Dimension

snap dimension, representing current value AND list of all possible values.

Also has various helpful methods for working with this Dimension.
here, defines custom assign_coord & assign_coord_along,
because snap is associated with ‘t’ coord.
u: None or UnitsManager
used by assign_coord to determine units for t coord.
if None, will not assign t coord.
See help(Dimension) for more details.
— Dimension.__doc__ copied below: —
a single dimension, representing a current value AND a list of all possible values.
when creating a subclass, provide:
name: None or str
name of this dimension. E.g. ‘fluid’.
None –> this will not be a useable dimension.
(use None if creating a subclass which is intended to be subclassed again)
plural: None or str
name of this dimension, in plural form. E.g. ‘fluids’.
None –> use str(name)+’s’.
value_error_type: None or type
type for cls.dimension_value_error. E.g. FluidValueError
None –> use DimensionValueError
key_error_type: None or type
type for cls.dimension_key_error. E.g. FluidKeyError
None –> use DimensionKeyError
Note that docstrings for DIM_METHODS will be formatted using these names,
via docstring.format(dim=name, dims=plural), if name is provided.
when creating an instance (possibly an instance of a subclass), can provide:
v: None, DimensionValue, or DimensionValueList
current value of this dimension. Might be multiple values.
None –> use self.values instead.
note: when setting self.v = value, will attempt to match value(s) from self.values if possible:
if value is None, set self.v = None.
else, if self.values exists (and is not None), attempt self.v = self.values.get(v).
By default (if the previous cases fail or don’t hold), sets self.v = value.
values: UNSET, None, or DimensionValueList
all possible values of this dimension.
UNSET (or, del self.values) –> raise an AttributeError when trying to access.
None –> disables the AttributeError, but also disables the “smart” behavior of self.v,
where setting self.v tries to match value(s) from self.values.
on_set_v: None or callable of 1 argument.
if not None, call self.on_set_v(value) immediately after doing self.v = value.
— Example —
class FluidDimension(Dimension, name=’fluid’):
pass # no special methods for this example
@FluidDimension.setup_haver # setup FluidHaver by attaching various relevant properties & methods.
class FluidHaver(DimensionHaver, dimension=’fluid’):
pass # no special methods for this example
after the lines above, FluidHaver will “have” a fluid dimension, e.g.:
- fluid_haver.fluid_dim –> FluidDimension instance associated with this fluid_haver instance
- fluid_haver.fluid –> fluid_haver.fluid_dim.v
- fluid_haver.fluids –> fluid_haver.fluid_dim.values
- fluid_haver.current_n_fluid –> fluid_haver.fluid_dim.current_n
- fluid_haver.iter_fluids –> fluid_haver.fluid_dim.iter_values
- fluid_haver.take_fluid –> fluid_haver.fluid_dim.take
where fluid_haver is an instance of FluidHaver.
Note that FluidHaver has those attributes as well but they are properties or methods, e.g.:
FluidHaver.fluid = property(lambda self: self.fluid_dim.v) # roughly.
FluidHaver.iter_fluids = property(lambda self: self.fluid_dim.iter_values) # roughly.
For a complete list of all methods which will be attached, see Dimension.setup_haver and DIM_METHODS.

Methods

__init_subclass__(*[, name, plural, ...])

setup cls based on provided name and plural.

__repr__()

return repr for an instance of this class.

assign_coord(array[, value])

returns array.assign_coords(...), assigning 'snap' AND 't' coords.

assign_coord_along(array, dim[, value])

returns array.assign_coords(...), assigning 'snap' AND 't' coords.

current_n()

return number of values currently represented by self.v

current_n_existing_for(calculator)

return number of existing snaps, out of all snaps at self.v.

enumerate(*[, restore])

iterate through self.v.

enumerate_values(*[, restore])

iterate through self.values, seting self.v and yielding (i, v) for each v in self.values.

get_type(*[, check_all])

get type of single value in self.v.

is_iterable(*[, min_length])

return whether self.v represents multiple values.

iter(*[, restore, enumerate])

iterate through self.v.

iter_partition(partition, *[, restore])

iterate through self.values.

iter_values(*[, restore, enumerate])

iterate through self.values.

join_along(arrays, *[, coords])

return arrays joined along the snap dimension.

list()

return self.v, but guaranteed to be a list.

maintaining(*attrs, **attrs_as_flags)

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

n_existing_for(calculator)

return number of snaps which exist for this calculator.

setup_haver(haver_cls)

setup haver_cls, so that it "has" this dimension,

take(array[, value, drop_labels, as_dict, ...])

take the array at array.{cls.name} == self.v (or at value, if provided).

take_along(array[, at, i, drop_labels, ...])

return a list of the array value for each {cls.name} in array.

using([attrs_as_dict, _unset_sentinel])

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

_as_single([val])

return the single value at self.v, or self.v corresponding to val if provided.

_dim_method([dim_methods])

return decorator(f) which returns f after putting {fmtname: f.__name__} into dim_methods

_get_first([val])

return first value from self.v, or self.v corresponding to val if provided.

Attributes

DIM_METHODS

NAN

loading

whether this dimension is currently being loaded across, via self.load_across().

name

plural

v

current value in self.

values

all possible values of this dimension.

classmethod __init_subclass__(*, name=None, plural=None, value_error_type=None, key_error_type=None, **kw_super)

setup cls based on provided name and plural.

name: None or str
if provided, does the following:
- sets cls.name
- sets cls.plural
- replace DIM_METHODS keys with key.format(dim=name, dims=plural).
plural: None or str
plural form of name. If None, use str(name)+’s’. (Only used if name is not None)
value_error_type: None or type
if provided, set cls.dimension_value_error = value_error_type
key_error_type: None or type
if provided, set cls.dimension_key_error = key_error_type
__repr__()

return repr for an instance of this class.

_as_single(val=None)

return the single value at self.v, or self.v corresponding to val if provided.

If result is not a single value, raise DimensionValueError.
_dim_method(dim_methods={'_as_single_{dim}': '_as_single', '_get_first_{dim}': '_get_first', 'assign_{dim}_along': 'assign_coord_along', 'assign_{dim}_coord': 'assign_coord', 'current_n_{dim}': 'current_n', 'enumerate_{dims}': 'enumerate_values', 'enumerate_{dim}': 'enumerate', 'iter_{dims}': 'iter_values', 'iter_{dims}_partition': 'iter_partition', 'iter_{dim}': 'iter', 'join_{dims}': 'join_along', 'take_{dims}': 'take_along', 'take_{dim}': 'take', '{dim}_is_iterable': 'is_iterable', '{dim}_list': 'list', '{dim}_type': 'get_type'})

return decorator(f) which returns f after putting {fmtname: f.__name__} into dim_methods

_get_first(val=None)

return first value from self.v, or self.v corresponding to val if provided.

If iterable, return self.v[0], else return self.v.
assign_coord(array, value=NO_VALUE, **kw_xarray_assign)

returns array.assign_coords(…), assigning ‘snap’ AND ‘t’ coords.

value: NO_VALUE, int, str, or Snap
if not NO_VALUE, assign snap coord as if self.snap = value.
(set self.snap=value, assign_snap_coord, then restore original self.snap)
requires not self.snap_is_iterable(), else raises SnapValueError.
if self.snap.t does not exist,
raise SnapValueError if DEFAULTS.DEBUG, else do not assign ‘t’ coord.
if ‘t’ coord is unexpectedly not being assigned, investigate via DEFAULTS.DEBUG = True.

Note: ‘t’ represents physical time, while ‘snap’ includes snap name information.

units for ‘t’ will be self.u(‘t’, alt=’coords’) units when this method is called.
assumes snap.t is in ‘raw’ units; will use:
t = snap.t * self.u(‘t’, alt=’coords’)
assign_coord_along(array, dim, value=NO_VALUE, **kw_assign_coords)

returns array.assign_coords(…), assigning ‘snap’ AND ‘t’ coords.

value: NO_VALUE, None, or iterable indicating which snaps to use.
if not NO_VALUE, assign snap coord as if self.snap = value.
(set self.snap=value, assign_snap_coord, then restore original self.snap)
requires self.snap_is_iterable(), else raises SnapValueError.
if self.snap.t does not exist,
raise SnapValueError if DEFAULTS.DEBUG, else do not assign ‘t’ coord.
if ‘t’ coord is unexpectedly not being assigned, investigate via DEFAULTS.DEBUG.

Note: ‘t’ represents physical time, while ‘snap’ includes snap name information.

units for ‘t’ will be self.units when this method is called.
assumes snap.t is in ‘raw’ units; will use:
t = snap.t * self.u(‘t’, self.units, convert_from=’raw’)
current_n()

return number of values currently represented by self.v

0 if None, else len(self.v) if possible, else 1.
current_n_existing_for(calculator)

return number of existing snaps, out of all snaps at self.v.

Equivalent to self.v.exists_for(calculator).
dimension_key_error

alias of SnapKeyError

dimension_value_error

alias of SnapValueError

enumerate(*, restore=True)

iterate through self.v. sets self.v and yields (i, v), for each value in self.v when iteration began.

i corresponds to position of value in original self.v (not necessarily self.values).
Equivalent to self.iter(restore=restore, enumerate=True).
enumerate_values(*, restore=True)

iterate through self.values, seting self.v and yielding (i, v) for each v in self.values.

Equivalent to self.iter_values(restore=restore, enumerate=True).
get_type(*, check_all=False)

get type of single value in self.v.

check_all: bool, default False
if True, check all values in self.v to ensure they are all the same type.
is_iterable(*, min_length=None)

return whether self.v represents multiple values.

False if self.v represents only one value.
if min_length is provided, return bool((result) and (len(self.v) >= min_length)).
iter(*, restore=True, enumerate=False)

iterate through self.v. sets AND yields self.v, for each value in self.v when iteration began.

Note the difference between this method and iter_values;

this method uses self.v when called, to determine which values to iterate through,
while iter_values instead uses self.values to determine which values to iterate through.
if self.v is not iterable, yield self.v once and do not change its value.
restore: bool, default True
whether to restore original self.v after iteration.
enumerate: bool, default False
whether to yield indices too, i.e. (i, v) instead of just v.
if True, indices correspond to position of value in the original self.v (not necessarily self.values!)
iter_partition(partition, *, restore=True)

iterate through self.values. setting self.v=vlist, yielding (partkey, self.v) from partition.items()

partition: dict-like of {partkey: vlist}
use to partition values into groups.
Note: iter_partition doesn’t return vlist directly, but instead sets self.v = vlist,
then returns self.v. If vlist is a list of v-specifiers, the actual v will be returned.
E.g. if vlist = [0,3,4], result has self.values.get([0,3,4]), not [0,3,4].
restore: bool, default True
whether to restore original self.v after iteration.
E.g. partition = {‘a’: [‘v0’, ‘v1’, ‘v4’], ‘b’: [‘v2’, ‘v3’], ‘c’: [‘v5’]}
–> yields (‘a’, [‘v0’, ‘v1’, ‘v4’]), then (‘b’, [‘v2’, ‘v3’]), then (‘c’, [‘v5’]),
setting self.v=[‘v0’, ‘v1’, ‘v4’], then self.v=[‘v2’, ‘v3’], then self.v=[‘v5’].
iter_values(*, restore=True, enumerate=False)

iterate through self.values. sets AND yields self.v, for each value in self.values.

restore: bool, default True
whether to restore original self.v after iteration.
enumerate: bool, default False
whether to yield indices too, i.e. (i, v) instead of just v.
if True, indices correspond to position of value in self.values.
join_along(arrays, *, coords=['t'], **kw_super)

return arrays joined along the snap dimension.

by default, joins ‘t’ coords as well.
coords: str or list of str
names of coords to join along with snap.
default = [‘t’] –> join ‘t’ coords as well.
str –> rule, e.g. ‘different’ or ‘minimal’; see help(xr.concat) for details.
list()

return self.v, but guaranteed to be a list.

if self.v is iterable, return self.v, unchanged;
else, return [self.v].
property loading

whether this dimension is currently being loaded across, via self.load_across().

maintaining(*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.
n_existing_for(calculator)

return number of snaps which exist for this calculator.

Equivalent to (self.values.exists_for(calculator)).sum()
classmethod setup_haver(haver_cls)

setup haver_cls, so that it “has” this dimension,

in the sense that the following are defined (replacing “fluid” with cls.name):
- h = haver_cls
- plural = cls.plural
- h.fluid_dim_cls = cls
- h.fluid_dim = alias to the instance of cls associated with an instance of h
- h.fluid = alias to h.fluid_dim.v
- h.{plural} = alias to h.fluid_dim.values
- h._loading_fluid = alias to h.fluid_dim.loading
- for (key, method) in cls.DIM_METHODS.items():
# assert that h.{key} doesn’t exist yet, then define:
h.{key} = alias to h.fluid_dim.{method}
# (e.g., h.assign_snap_coord = alias to h.snap_dim.assign_coord)
Also, call haver_cls.__setup_haver__(cls) if it exists.
returns haver_cls, so that this function may be used as a class decorator.
take(array, value=UNSET, *, drop_labels=False, as_dict=False, squeeze=True, item=False, **kw__take_along)

take the array at array.{cls.name} == self.v (or at value, if provided).

if self.is_iterable(), return [array at array.{cls.name}==val for val in self.v].
otherwise, return a single array: array at array.{cls.name}==self.v.
array: xarray.DataArray
array to take from.
E.g., self.v==’e’, cls.name==’fluid’, array has coord ‘fluid’ with one value equal to ‘e’
–> take(array) gives array value at fluid==’e’.
value: UNSET or value
if provided, temporarily set self.v = value, then restore it afterwards.
This means value can be “shorthand” for actual values,
e.g. value = 0 –> self.v = self.values.get(0)
value = None –> self.v = None, so self.v gives self.values.
See help(type(self).v) for more info.
drop_labels: bool, default False
whether to remove this dimension from arr.coords for arr in result.
as_dict: bool, default False
if True, return dict of {dim value: array value at this dim} instead.
squeeze: bool, default True
if False, always return list (with length==1 if not self.is_iterable()),
unless as_dict=True. (Ignore squeeze if as_dict.)
item: bool
if True, convert arrays to single values via array.item().
classmethod take_along(array, at=None, *, i=None, drop_labels=False, as_dict=False, item=False, **kw__take_along_dimension)

return a list of the array value for each {cls.name} in array.

array: xarray.DataArray
array to take from.
E.g., array with coords fluid [‘e’, ‘H+’, ‘C+’], cls.name==’fluid’
–> take_along(array) gives [array value for ‘e’, value for ‘H+’, value for ‘C+’].
at: None or list-like of values in this dimension
take at these values. None –> use values from array.coords[this dimension]
i: None or indices
(if provided) take only at these indices; use isel.
drop_labels: bool, default False
whether to remove this dimension from arr.coords for arr in result.
as_dict: bool, default False
if True, return dict of {dim value: array value at this dim} instead of list.
item: bool
if True, convert arrays to single values via array.item().
additional kwargs go to tools.take_along_dimension
using(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 v

current value in self.

Getting self.v:
Return self._v if it exists (and is not None), else return self.values.
Setting self.v = value:
Attempt to match value from self.values if possible:
if value is None, set self.v = None
if value is a DimensionSpecialValueSpecifier, call value.value_to_set(self).
else, if self.values exists (and is not None), attempt self.v = self.values.get(value).
By default (if the previous cases fail or don’t hold), sets self.v = value.
Afterwards, call self.on_set_v(value), if self.on_set_v is not None.
property values

all possible values of this dimension.

If values does not exist, raise an AttributeError with a helpful message.
(the message is most helpful at “high level”, when using DimensionHaver,
so it uses the dimension’s name instead of ‘v’ and ‘values’.)
If you want to avoid using DimensionValueList (at the cost of not using its smart behavior..)
you can use self.values=None, to disable that error message.
You can del self.values to re-enable that error message.
(del self.values will do nothing if self.values doesn’t exist, as opposed to crashing.)
Settings self.values will also reset self.v to None afterwards.