Top-level classes and functions¶
|
Class for describing and executing computations. |
|
A hashable key for a quantity that includes its dimensionality. |
|
A collection of |
alias of |
|
|
Assert that each of args is a Quantity object. |
|
Configure |
Get the current |
|
|
Set the |
Also:
ComputationError,
KeyExistsError,
MissingKeyError,
Operator,
literal(),
quote().
- class genno.Computer(**kwargs)[source]¶
Class for describing and executing computations.
- Parameters:
kwargs – Passed to
configure().
A Computer is used to prepare (
add()and related methods) and then execute (get()and related methods) computations stored in agraph. Advanced users may manipulate the graph directly; but most computations can be prepared using the methods of Computer.Instance attributes:
The default key to
get()with no argument.keys()Return the keys of
graph.List of modules containing operators.
The
pint.UnitRegistryused by the Computer.General-purpose methods for preparing computations and tasks:
add(data, *args, **kwargs)General-purpose method to add computations.
add_queue(queue[, max_tries, fail])Add tasks from a list or queue.
add_single(key, *computation[, strict, index])Add a single computation at key.
aggregate(qty, tag, dims_or_groups[, ...])Deprecated.
apply(generator, *keys, **kwargs)Add computations by applying generator to keys.
cache(func)Decorate func so that its return value is cached.
describe([key, quiet])Return a string describing the computations that produce key.
duplicate(key, tag)Duplicate the task at key and all of its inputs.
eval(expr)Evaluate expr to add tasks and keys.
insert(key, *args[, tag])Insert a task before key, using args, kwargs.
visualize(filename[, key, optimize_graph])Generate an image describing the Computer structure.
Executing computations:
get([key])Execute and return the result of the computation key.
write(key, path, **kwargs)Compute key and write the result directly to path.
Utility and configuration methods:
check_keys(*keys[, predicate, action])Check that keys are in the Computer.
configure([path, fail, config])Configure the Computer.
full_key(name_or_key)Return the full-dimensionality key for name_or_key.
get_operator(name)Return a function,
Operator, or callable for use in a task.infer_keys(key_or_keys[, dims])Infer complete key_or_keys.
require_compat(pkg)Register a module for
get_operator().Deprecated:
add_file(*args, **kwargs)Deprecated.
add_product(*args, **kwargs)Deprecated.
convert_pyam(*args, **kwargs)Deprecated.
disaggregate(qty, new_dim[, method, args])Deprecated.
- graph: genno.core.graph.Graph = {'config': {}}¶
A dask-format graph (see 1, 2).
Dictionary keys are either
Key,str, or any other hashable value.Dictionary values are computations, one of:
Any other, existing key in the Computer. This functions as an alias.
Any other literal value or constant, to be returned directly.
A task
tuple: a callable (such as a function or any object with a__call__()method), followed by zero or more keys (referring to the output of other computations), or computations directly.A
listcontaining zero or more of (1), (2), and/or (3).
gennoreserves some keys for special usage:"config"A
dictstoring configuration settings. See Configuration. Because this information is stored in thegraph, it can be used as one input to other operators.
Some inputs to tasks may be confused for (1) or (4), above. The recommended way to protect these is:
Literal
strinputs to tasks: usefunctools.partial()on the function that is the first element of the task tuple.
- add(data, *args, **kwargs) KeyLike | tuple[KeyLike, ...][source]¶
General-purpose method to add computations.
add()can be called in several ways; its behaviour depends on data; see below. It chains to methods such asadd_single(),add_queue(), and/orapply(); each can also be called directly.See also
The data argument may be:
listA list of computations, like
[(list(args1), dict(kwargs1)), (list(args2), dict(kwargs2)), ...]→ passed toadd_queue().strnaming an operatore.g. “select”, retrievable with
get_operator().add_single()is called with(key=args[0], data, *args[1], **kwargs), that is, applying the named operator to the other parameters.Keyor otherstr:Passed to
add_single().
add()may be used to:Provide an alias from one key to another:
>>> from genno import Computer >>> c = Computer() # Create a new Computer object >>> c.add('aliased name', 'original name')
Define an arbitrarily complex operator in a Python function that operates directly on the
ixmp.Scenario:>>> def my_func(scenario): >>> # many lines of code >>> return 'foo' >>> c.add('my report', my_func, 'scenario') >>> c.finalize(scenario) >>> c.get('my report') foo
- add_queue(queue: Iterable[tuple], max_tries: int = 1, fail: str | int | None = None) tuple[KeyLike, ...][source]¶
Add tasks from a list or queue.
- Parameters:
queue (
collections.abc.Iterableoftuple) – Each item is either a N-tupleof positional arguments toadd(), or a 2-tupleof (tupleof positional arguments,dictof keyword arguments).max_tries (
int, optional) – Retry adding elements up to this many times.fail (
"raise"orstrorlogginglevel, optional) – Action to take when a computation from queue cannot be added after max_tries: “raise” an exception, or log messages on the indicated level and continue.
This method allows to add many computations at once by, in effect, calling
add()repeatedly with sets of positional and (optionally) keyword arguments taken from the queue. The argument may be:A prepared/static data structure, like a
list, where each item is either a 2-tupleof(args, kwargs)or only a tuple ofargsthat can be passed toadd().A generator that yields items of the same type(s).
Given this initial sequence of items,
add_queue()will…Pass each item in turn to
add();If an item fails to be added—for instance, with
MissingKeyErroron one of its inputs—and max_tries > 1: re-append that item to the queue so that it can be attempted again;If an item fails to be added at least max_tries times: take an action according to fail.
This behaviour makes
add_queue()tolerant of entries in queue that are out-of-order: individual items may fail in calls toadd()on initial passes through the queue, but eventually succeed once their inputs are available.
- apply(generator: Callable, *keys, **kwargs) KeyLike | tuple[KeyLike, ...][source]¶
Add computations by applying generator to keys.
- Parameters:
generator (
typing.Callable) –Function to apply to keys. This function may take a first positional argument annotated with
Computeror a subtype; if so, then it is provided with a reference to self.The function may:
yieldor return an iterable of (key, computation). These are used to directly update thegraph, and thenapply()returns the added keys.If it is provided with a reference to the Computer, call
add()or any other method to update the graph. In this case, it shouldreturnaKeyor sequence of keys, indicating what was added; these are in turn returned byapply().
keys (
Hashable) – The starting key(s). These are provided as positional arguments to generator.kwargs – Keyword arguments to generator.
The generator may have a type annotation for Computer on its first positional argument. In this case, a reference to the Computer is supplied, and generator can use the Computer methods to add many keys and computations:
def my_gen0(c: genno.Computer, **kwargs): c.load_file("file0.txt", **kwargs) c.load_file("file1.txt", **kwargs) # Use the generator to add several computations c.apply(my_gen0, units="kg")
Or, generator may
yielda sequence (0 or more) of (key, computation), which are added to thegraph:def my_gen1(**kwargs): op = partial(operator.load_file, **kwargs) yield from (f"file:{i}", (op, "file{i}.txt")) for i in range(2) c.apply(my_gen1, units="kg")
- eval(expr: str) tuple[Key, ...][source]¶
Evaluate expr to add tasks and keys.
Parse a statement or block of statements using
astfrom the Python standard library. expr may include:Constants.
References to existing keys in the Computer by their name; these are expanded using
full_key().Multiple statements on separate lines or separated by “;”.
Python arithmetic operators including
+,-,*,/,**; these are mapped to the correspondingoperator.Function calls, also mapped to the corresponding
operatorviaget_operator(). These may include simple positional (constants or key references) or keyword (constants only) arguments.
- Parameters:
expr (
str) – Expression to be evaluated.- Returns:
One key for the left-hand side of each expression.
- Return type:
- Raises:
NotImplementedError – For complex expressions not supported; if any of the statements is anything other than a simple assignment.
NameError – If a function call references a non-existent computation.
Examples
Parse a multi-line string and add tasks to compute z, a, b, d, and e. The dimensions of each are automatically inferred given the dimension of the existing operand, x.
>>> c = Computer() >>> # (Here, add tasks to compute a quantity like "x:t-y") >>> added = c.eval( ... """ ... z = - (0.5 / (x ** 3)) ... a = x ** 3 + z ... b = a + a ... d = assign_units(b, "km") ... e = index_to(d, dim="t", label="foo1") ... """ ... ) >>> added[-1] <e:t-y>
- add_aggregate(qty: KeyLike, tag: str, dims_or_groups: Mapping | str | Sequence[str], weights: DataArray | None = None, keep: bool = True, sums: bool = False, fail: str | int | None = None)¶
Deprecated.
Add a computation that aggregates qty.
Deprecated since version 1.18.0: Instead, for a mapping/
dictdims_or_groups, use:c.add(qty, "aggregate", groups=dims_or_groups, keep=keep, ...)
Or, for
stror sequence ofstrdims_or_groups, use:c.add(None, "sum", qty, dimensions=dims_or_groups, ...)
- Parameters:
tag (
str) – Additional string to add to the end the key for the aggregated quantity.dims_or_groups (
strorcollections.abc.Iterableofstrordict) – Name(s) of the dimension(s) to sum over, or nested dict.weights (
xarray.DataArray, optional) – Weights for weighted aggregation.keep (
bool, optional) – Passed tooperator.aggregate.fail (
strorint, optional) – Passed toadd_queue()viaadd().
- Returns:
The key of the newly-added node.
- Return type:
- add_file(*args, **kwargs)[source]¶
Deprecated.
Deprecated since version 1.18.0: Instead use
add_load_file()via:c.add(..., "load_file", ...)
- add_product(*args, **kwargs)[source]¶
Deprecated.
Deprecated since version 1.18.0: Instead use
add_binop()via:c.add(..., "mul", ...)
- add_single(key: KeyLike, *computation, strict=False, index=False) KeyLike[source]¶
Add a single computation at key.
- Parameters:
key (
strorKeyorcollections.abc.Hashable) – A string, Key, or other value identifying the output of computation.strict (
bool, optional) – If True, key must not already exist in the Computer, and any keys referred to by computation must exist.index (
bool, optional) – If True, key is added to the index as a full-resolution key, so it can be later retrieved withfull_key().
- Raises:
KeyExistsError – If strict is
Trueand either (a) key already exists; or (b) sums isTrueand the key for one of the partial sums of key already exists.MissingKeyError – If strict is
Trueand any key referred to by computation does not exist.
- aggregate(qty: KeyLike, tag: str, dims_or_groups: Mapping | str | Sequence[str], weights: DataArray | None = None, keep: bool = True, sums: bool = False, fail: str | int | None = None)[source]¶
Deprecated.
Add a computation that aggregates qty.
Deprecated since version 1.18.0: Instead, for a mapping/
dictdims_or_groups, use:c.add(qty, "aggregate", groups=dims_or_groups, keep=keep, ...)
Or, for
stror sequence ofstrdims_or_groups, use:c.add(None, "sum", qty, dimensions=dims_or_groups, ...)
- Parameters:
tag (
str) – Additional string to add to the end the key for the aggregated quantity.dims_or_groups (
strorcollections.abc.Iterableofstrordict) – Name(s) of the dimension(s) to sum over, or nested dict.weights (
xarray.DataArray, optional) – Weights for weighted aggregation.keep (
bool, optional) – Passed tooperator.aggregate.fail (
strorint, optional) – Passed toadd_queue()viaadd().
- Returns:
The key of the newly-added node.
- Return type:
- check_keys(*keys: str | Key, predicate=None, action='raise') list[KeyLike][source]¶
Check that keys are in the Computer.
- Parameters:
- Returns:
One item for each item
kin keys:kitself, unchanged, if predicate is given andpredicate(k)returnsTrue.Graph.unsorted_key(), that is,kbut with its dimensions in a specific order that already appears ingraph.Graph.full_key(), that is, an existing key with the namekwith its full dimensionality.Noneotherwise.
- Return type:
- Raises:
MissingKeyError – If action is “raise” and 1 or more of keys do not appear (either in different dimension order, or full dimensionality) in the
graph.
- configure(path: Path | str | None = None, fail: str | int = 'raise', config: Mapping[str, Any] | None = None, **config_kw)[source]¶
Configure the Computer.
Accepts a path to a configuration file and/or keyword arguments. Configuration keys loaded from file are superseded by keyword arguments. Messages are logged at level
logging.INFOif config contains unhandled sections.See Configuration for a list of all configuration sections and keys, and details of the configuration file format.
- Parameters:
path (
pathlib.Path, optional) – Path to a configuration file in JSON or YAML format.fail (
"raise"orstrorlogginglevel, optional) – Passed toadd_queue(). If not “raise”, then log messages are generated for config handlers that fail. The Computer may be only partially configured.config – Configuration keys/sections and values, as a mapping. Use this if any of the keys/sections are not valid Python names, for instance if they contain “-” or “ “.
**config_kw – Configuration keys/sections and values, as keyword arguments.
- convert_pyam(*args, **kwargs)[source]¶
Deprecated.
Deprecated since version 1.18.0: Instead use
add_as_pyam()via:c.require_compat("pyam") c.add(..., "as_pyam", ...)
- describe(key=None, quiet=True)[source]¶
Return a string describing the computations that produce key.
If key is not provided, all keys in the Computer are described.
Unless quiet, the string is also printed to the console.
- disaggregate(qty, new_dim, method='shares', args=[])[source]¶
Deprecated.
Deprecated since version 1.18.0: Instead, for method = “disaggregate_shares”, use:
c = Computer() c.add(qty.append(new_dim), "mul", qty, ..., strict=True)
Or for a
callable()method, use:c.add(qty.append(new_dim), method, qty, ..., strict=True)
- duplicate(key: TKeyLike, tag: str) TKeyLike[source]¶
Duplicate the task at key and all of its inputs.
Re
- Parameters:
key – Starting key to duplicate.
tag –
tagto add to duplicated keys.
- full_key(name_or_key: KeyLike) KeyLike[source]¶
Return the full-dimensionality key for name_or_key.
An quantity ‘foo’ with dimensions (a, c, n, q, x) is available in the Computer as
'foo:a-c-n-q-x'. ThisKeycan be retrieved with:c.full_key("foo") c.full_key("foo:c") # etc.
- Raises:
KeyError – if name_or_key is not in the graph.
- get(key=None)[source]¶
Execute and return the result of the computation key.
Only key and its dependencies are computed.
- Parameters:
key (
str, optional) – If not provided,default_keyis used.- Raises:
ValueError – If key and
default_keyare bothNone.
- get_comp(name) Callable | None¶
Alias of
get_operator().
- get_operator(name) Callable | None[source]¶
Return a function,
Operator, or callable for use in a task.get_operator()checks each of themodulesfor a callable with the given name. Modules at the end of the list take precedence over those earlier in the list.
- infer_keys(key_or_keys: KeyLike | Iterable[KeyLike], dims: Iterable[str] = [])[source]¶
Infer complete key_or_keys.
Each return value is one of:
a
Keywith eitherdimensions dims, if any are given, otherwise
its full dimensionality (cf.
full_key())
str, the same as input, if the key is not defined in the Computer.
- insert(key: KeyLike, *args, tag: str = 'pre', **kwargs) None[source]¶
Insert a task before key, using args, kwargs.
The existing task at key is moved to
key + tag. The args and kwargs are passed toadd()to insert a new task at key. The args must include at least 2 items:the new
callableorOperator, andthe
.Ellipsis(...), which is replaced by the shiftedkey + tag.
If there are more than 2 items, each instance of the
Ellipsisis replaced per (2); all other items (and kwargs) are passed on as-is.The effect is that all existing tasks to which key are input will receive, instead, the output of the added task.
One way to use
insert()is with a ‘pass-through’ operation that, for instance, performs logging, assertions, or other steps, then returns its input unchanged. It is also possible to insert a new task that mutates its input in certain ways.
- modules: MutableSequence[ModuleType] = []¶
List of modules containing operators.
By default, this includes the
gennobuilt-in operators ingenno.operator.require_compat()appends additional modules, for instancegenno.compat.plotnine, to this list. User code may also add modules to this list directly.
- require_compat(pkg: str | ModuleType)[source]¶
Register a module for
get_operator().The specified module is appended to
modules.- Parameters:
pkg (
strormodule) –One of:
the name of a package (for instance “plotnine”), corresponding to a submodule of
genno.compat(genno.compat.plotnine).genno.compat.{pkg}.operatoris added.the name of any importable module, for instance “foo.bar”.
a module object that has already been imported.
- Raises:
ModuleNotFoundError – If the required packages are missing.
Examples
Operators packaged with genno for compatibility:
>>> c = Computer() >>> c.require_compat("pyam")
Operators in another module, using the module name:
>>> c.require_compat("ixmp.reporting.computations")
or using imported module object directly:
>>> import ixmp.reporting.computations as mod >>> c.require_compat(mod)
- property unit_registry¶
The
pint.UnitRegistryused by the Computer.
- update(other: Computer) None[source]¶
Update Computer with the contents of other.
The operators
|and|=invoke this method.Examples
>>> c1 = Computer() >>> c2 = Computer() ### Create a new Computer containing all tasks from both c1 and c2 >>> c3 = c1 | c2 ### Add all tasks from c2 to c1 >>> c1.update(c2) ### Same as above >>> c1 |= c2
- Raises:
RuntimeError – if any key is present in both the Computer and other with a different task.
- visualize(filename, key=None, optimize_graph=False, **kwargs)[source]¶
Generate an image describing the Computer structure.
This is similar to
dask.visualize(); seecompat.graphviz.visualize(). Requires graphviz.
- class genno.Key(name_or_value: str | Key | AnyQuantity, dims: Iterable[str] = [], tag: str | None = None, _fast: bool = False)[source]¶
A hashable key for a quantity that includes its dimensionality.
Quantities are indexed by 0 or more dimensions. A Key refers to a quantity using three components:
For example, for a quantity \(\text{foo}\) with with three dimensions \(a, b, c\):
\[\text{foo}^{abc}\]…Key allows a specific, explicit reference to various forms of “foo”:
in its full resolution; that is, indexed by a, b, and c:
>>> k1 = Key("foo", ["a", "b", "c"]) >>> k1 <foo:a-b-c>
in a partial sum over one dimension, for instance summed across dimension c, with remaining dimensions a and b:
>>> k2 = k1 / "c" >>> k2 == "foo:a-b" True
in a partial sum over multiple dimensions, etc.:
>>> k1.drop("a", "c") == k1 / ("a", "c") == k2 / "a" == "foo:b" True
after it has been manipulated by other computations, e.g.
>>> k3 = k1.add_tag(""normalized") >>> k3 <foo:a-b-c:normalized> >>> k4 = k3 + "rescaled" >>> k4 <foo:a-b-c:normalized+rescaled>
Key comparison.
Keys with the same name, dimensions, and tag compare and
hash()equal—even if the dimensions are in a different order.A key compares (but does not
hash()) equal to astrwith the same name, dimensions (in any order) and tag.
repr(key)prints the Key in angle brackets (‘<>’) to signify that it is a Key object.>>> str(k1) 'foo:a-b-c' >>> repr(k1) '<foo:a-b-c>' >>> hash(k1) == hash("foo:a-b-c") True >>> k1 == "foo:c-b-a" True
Keys are immutable: the properties
name,dims, andtagare read-only, and the methodsappend(),drop(), andadd_tag()return new Key objects.Keys may be generated concisely by defining a convenience method:
>>> def foo(dims): >>> return Key('foo', dims.split()) >>> foo('a b c') <foo:a-b-c>
Key arithmetic. Keys can be manipulated using some of the Python arithmetic operators:
+: and-: manipulatetag, same asadd_tag()andremove_tag()respectively:>>> k1 = Key("foo", "abc", "bar+baz+qux") >>> k1 <foo:a-b-c:bar+baz+qux> >>> k2 + "newtag" <foo:a-b-c:bar+baz+qux+newtag> >>> k1 - "baz" <foo:a-b-c:bar+qux> >>> k1 - ("bar", "baz") <foo:a-b-c:qux>
*and/: manipulatedims, similar toappend()/productanddrop, respectively:>>> k1 * "d" <foo:a-b-c-d> >>> k1 * ("e", "f") <foo:a-b-c-e-f> >>> k1 * Key("bar", "ghi") <foo:a-b-c-g-h-i>
>>> k1 / "a" <foo:b-c> >>> k1 / ("a", "c") <foo:b> >>> k1 / Key("baz", "cde") <foo:a-b>
Key generation and derivation. When preparing chains or complicated graphs of computations, it can be useful to use a sequence or set of similar keys to refer to the intermediate steps. Python item-access syntax (
[...]) and the built-in functionnext()can be used to generate or derive keys from an original one, in any order:>>> k1 = Key("foo:a-b-c") >>> k[0] <foo:a-b-c:0> >>> k[1] <foo:a-b-c:1> >>> k["bar"] <foo:a-b-c:bar> >>> k[99] <foo:a-b-c:99>
next()always returns the next key in a sequence of integers, starting with0and continuing from the highest previously created tag/Key:>>> next(k) <foo:a-b-c:100> # Same
A Key is callable, with any value that has a
strrepresentation:>>> k() <foo:a-b-c:101> # Same as item-access syntax >>> k("baz") <foo:a-b-c:baz>
The attributes
lastandgeneratedallow to inspect one or all of the keys that have been derived from an original:>>> k.last <foo:a-b-c:baz> >>> k.generated (<foo:a-b-c:0>, <foo:a-b-c:1>, <foo:a-b-c:bar>, <foo:a-b-c:99>, <foo:a-b-c:100>, <foo:a-b-c:101>, <foo:a-b-c:baz>)
- classmethod bare_name(value) str | None[source]¶
If value is a bare name (no dims or tags), return it; else
None.
- classmethod from_str_or_key(value: str | Key | AnyQuantity, drop: Iterable[str] | bool = [], append: Iterable[str] = [], tag: str | None = None) Key[source]¶
Return a new Key from value.
Changed in version 1.18.0: Calling
from_str_or_key()with a single argument is no longer necessary; simply give the same value as an argument toKey.The class method is retained for convenience when calling with multiple arguments. However, the following are equivalent and may be more readable:
k1 = Key("foo:a-b-c:t1", drop="b", append="d", tag="t2") k2 = Key("foo:a-b-c:t1").drop("b").append("d)"
- Parameters:
drop (
listofstrorTrue, optional) – Existing dimensions of value to drop. Seedrop().append (
listofstr, optional) – New dimensions to append to the returned Key. Seeappend().tag (
str, optional) – Tag for returned Key. If value has a tag, the two are joined using a ‘+’ character. Seeadd_tag().
- Return type:
- iter_sums() Generator[tuple[Key, Callable, Key], None, None][source]¶
Generate (key, task) for all possible partial sums of the Key.
- classmethod product(new_name: str, *keys, tag: str | None = None) Key[source]¶
Return a new Key that has the union of dimensions on keys.
Dimensions are ordered by their first appearance:
First, the dimensions of the first of the keys.
Next, any additional dimensions in the second of the keys that were not already added in step 1.
etc.
- remove_tag(*tags: str) Key[source]¶
Return a key with any of tags dropped.
- Raises:
ValueError – If none of tags are in
tags.
- class genno.Keys(**kwargs: Key | str)[source]¶
A collection of
Key.This is essentially the same as
types.SimpleNamespace, except every attribute is aKey.>>> k = Keys(foo="X:a-b-c-d-e-f", bar="Y:a-b-c:long+sequence+of+tags") >>> k.baz = "Z:a-b-c-e-f"
- class genno.KeySeq(*args, **kwargs)[source]¶
Utility class for generating similar
Keys.Note
As of genno 1.28.0,
Keyprovides most of the conveniences and shorthand that were previously provided by KeySeq. User could should prefer use of Key and Keys. KeySeq may eventually be deprecated and removed.KeySeq supports several ways to create related keys starting from a base key:
>>> ks = KeySeq("foo:x-y-z:bar")
Access the most recently generated item:
>>> ks.prev <foo:x-y-z:bar+7>
Access the base Key or its properties:
>>> ks.base <foo:x-y-z:bar> >>> ks.name "foo"
Access a
dictof all previously-created keys. Becausedictis order-preserving, the order of keys and values reflects the order in which they were created:>>> tuple(ks.keys) ("a", "b", 0, 5, 6, "a", 7)
The same Python arithmetic operators usable with Key are usable with KeySeq; they return a new KeySeq with a different
base:>>> ks * "w" <KeySeq from 'foo:x-y-z-w:bar'> >>> ks / ("x", "z") <KeySeq from 'foo:z:bar'>
- genno.Quantity¶
alias of
AttrSeries
The Quantity constructor converts its arguments to an internal, xarray.DataArray-like data format:
# Existing data
data = pd.Series(...)
# Convert to a Quantity for use in genno calculations
qty = Quantity(data, name="Quantity name", units="kg")
c.add("new_qty", qty)
Common genno usage, e.g. in message_ix, creates large, sparse data frames (billions of possible elements, but <1% populated); DataArray’s default, ‘dense’ storage format would be too large for available memory.
Currently, Quantity implemented as is
AttrSeries, a wrappedpandas.Seriesthat behaves like aDataArray.In the future,
gennowill useSparseDataArray, and eventually directlyDataArraybacked by sparse data.
The goal is that all genno-based code, including built-in and user functions, can treat quantity arguments as if they were DataArray.
Quantity has a units attribute, which can be set using either str or pint.Unit.
Quantity supports the standard binary operations with unit-aware behaviour:
__add__(),
__radd__(),
__mul__(),
__rmul__(),
__pow__(),
__rpow__(),
__sub__(),
__radd__(),
__truediv__(), and
__rtruediv__().
This means that correct units are derived from the units of operands and attached to the resulting Quantity.
Quantity has the following methods and attributes that exactly mirror the signatures and types of the corresponding xarray.DataArray items.
|
|
|
Like |
|
Like |
Like |
|
|
|
|
|
Like |
|
|
Like |
|
|
|
|
|
Like |
|
|
|
Like |
|
|
|
Like |
Like |
|
|
Like |
|
|
|
Like |
|
|
|
|
|
Like |
- genno.configure(path: Path | str | None = None, **config)[source]
Configure
gennoglobally.Modifies global variables that affect the behaviour of all Computers and operators. Configuration keys loaded from file are superseded by keyword arguments. Messages are logged at level
logging.INFOif config contains unhandled sections.- Parameters:
path (
pathlib.Path, optional) – Path to a configuration file in JSON or YAML format.**config – Configuration keys/sections and values.
- exception genno.ComputationError(exc)[source]¶
Wrapper to print intelligible exception information for
Computer.get().In order to aid in debugging, this helper:
Omits the parts of the stack trace that are internal to
Dask, andGives the key in the
Computer.graphand the computation/task that caused the exception.
- exception genno.KeyExistsError[source]¶
Raised by
Computer.add()when the target key exists.
- exception genno.MissingKeyError[source]¶
Raised by
Computer.add()when a required input key is missing.
- class genno.Operator[source]¶
Base class for a callable with convenience methods.
Example
>>> from genno import Operator >>> >>> @Operator.define() ... def myfunc(q1: Quantity, q2: Quantity) -> Quantity: ... # Operator code >>> >>> @myfunc.helper ... def add_myfunc(f, computer, *args, **kwargs): ... # Custom code to add tasks to `computer` ... # Perform checks or handle `args` and `kwargs`.
Or:
>>> from genno import Operator >>> >>> def add_myfunc(f, computer, *args, **kwargs): ... # ... as above >>> >>> @Operator.define(helper=add_myfunc) ... def myfunc(q1: Quantity, q2: Quantity) -> Quantity: ... # ... as above
- add_tasks(c: Computer, *args, **kwargs) tuple[Key | str, ...][source]¶
Invoke
_add_taskto add tasks to c.
- genno.assert_quantity(*args)[source]¶
Assert that each of args is a Quantity object.
- Raises:
TypeError – with a indicative message.
- genno.get_class() Type[AttrSeries | SparseDataArray][source]¶
Get the current
Quantityimplementation in use.Returns one of the classes
AttrSeriesorSparseDataArray.
- class genno.literal(data)[source]¶
A small serializable object to wrap literal values without copying
- genno.quote(x)[source]¶
Ensure that this value remains this value in a dask graph
Some values in dask graph take on special meaning. Sometimes we want to ensure that our data is not interpreted but remains literal.
>>> add = lambda x, y: x + y >>> quote((add, 1, 2)) (literal<type=tuple>,)
- genno.set_class(name: Literal['AttrSeries', 'SparseDataArray'] = 'AttrSeries') Type[AttrSeries | SparseDataArray][source]¶
Set the
Quantityimplementation to be used.This also updates
genno.Quantityandgenno.quantity.Quantityto refer to the selected class. It does not update previously-imported references to one class or the other; code that usesset_class()should refer to one of those two locations:import genno from genno import Quantity # AttrSeries, by default Quantity() # AttrSeries genno.Quantity() # AttrSeries genno.set_class("SparseDataArray") Quantity() # AttrSeries genno.Quantity() # SparseDataArray
Another approach is to update the local reference with the return value of the function:
from genno import Quantity, set_class Quantity() # AttrSeries Quantity = set_class("SparseDataArray") Quantity() # SparseDataArray
In code that does not use
set_class(),from genno import Quantityis safe.See also