A Collection of Utilities#
Math#
- pytools.levi_civita(tup: Tuple[int, ...]) int [source]#
Compute an entry of the Levi-Civita symbol for the indices tuple.
- pytools.perm(*args, **kwargs)#
- pytools.comb(*args, **kwargs)#
Assertive accessors#
- pytools.one(iterable: Iterable[pytools.T]) pytools.T [source]#
Return the first entry of iterable. Assert that iterable has only that one entry.
Memoization#
- pytools.memoize(*args: pytools.F, **kwargs: Any) pytools.F [source]#
Stores previously computed function values in a cache.
Two keyword-only arguments are supported:
- Parameters
use_kwargs β Allows the caller to use keyword arguments. Defaults to
False
. Setting this toTrue
has a non-negligible performance impact.key β A function receiving the same arguments as the decorated function which computes and returns the cache key.
- pytools.memoize_on_first_arg(function: pytools.F, cache_dict_name: Optional[str] = None) pytools.F [source]#
Like
memoize_method()
, but for functions that take the object in which do memoization information is stored as first argument.Supports cache deletion via
function_name.clear_cache(self)
.
- pytools.memoize_method(method: pytools.F) pytools.F [source]#
Supports cache deletion via
method_name.clear_cache(self)
.Changed in version 2021.2: Can memoize methods on classes that do not allow setting attributes (e.g. by overwritting
__setattr__
), e.g. frozendataclasses
.
- pytools.memoize_in(container: Any, identifier: Hashable) None [source]#
Adds a cache to the function it decorates. The cache is attached to container and must be uniquely specified by identifier (i.e. all functions using the same container and identifier will be using the same cache). The decorated function may only receive positional arguments.
Note
This function works well on nested functions, which do not have stable global identifiers.
Changed in version 2020.3: identifier no longer needs to be a
str
, but it needs to be hashable.Changed in version 2021.2.1: Can now use instances of classes as container that do not allow setting attributes (e.g. by overwritting
__setattr__
), e.g. frozendataclasses
.
- pytools.keyed_memoize_on_first_arg(key, cache_dict_name=None)[source]#
Like
memoize_method()
, but for functions that take the object in which memoization information is stored as first argument.Supports cache deletion via
function_name.clear_cache(self)
.- Parameters
key β A function receiving the same arguments as the decorated function which computes and returns the cache key.
cache_dict_name β The name of the dict attribute in the instance used to hold the cache.
New in version 2020.3.
- pytools.keyed_memoize_method(key, cache_dict_name=None)[source]#
Like
memoize_method
, but additionally uses a function key to compute the key under which the function result is stored.Supports cache deletion via
method_name.clear_cache(self)
.- Parameters
key β A function receiving the same arguments as the decorated function which computes and returns the cache key.
New in version 2020.3.
Changed in version 2021.2: Can memoize methods on classes that do not allow setting attributes (e.g. by overwritting
__setattr__
), e.g. frozendataclasses
.
- pytools.keyed_memoize_in(container, identifier, key)[source]#
Like
memoize_in
, but additionally uses a function key to compute the key under which the function result is memoized.- Parameters
key β A function receiving the same arguments as the decorated function which computes and returns the cache key.
New in version 2021.2.1.
Argmin/max#
Cartesian products#
Permutations, Tuples, Integer sequences#
- pytools.generate_nonnegative_integer_tuples_below(n, length=None, least=0)[source]#
n may be a sequence, in which case length must be None.
- pytools.generate_nonnegative_integer_tuples_summing_to_at_most(n, length)[source]#
Enumerate all non-negative integer tuples summing to at most n, exhausting the search space by varying the first entry fastest, and the last entry the slowest.
- pytools.generate_permutations(original)[source]#
Generate all permutations of the list original.
Nicked from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252178
Formatting#
- class pytools.Table(alignments: Optional[Tuple[str, ...]] = None)[source]#
An ASCII table generator.
- nrows#
- ncolumns#
- alignments#
A
tuple
of alignments of each column:"l"
,"c"
, or"r"
, for left, center, and right alignment, respectively). Columns which have no alignment specifier will use the last specified alignment. For example, withalignments=("l", "r")
, the third and all following columns will use right alignment.
- __str__() str [source]#
Returns a string representation of the table.
>>> tbl = Table(alignments=['l', 'r', 'l']) >>> tbl.add_row([1, '|']) >>> tbl.add_row([10, '20||']) >>> print(tbl) 1 | | ---+------ 10 | 20||
- github_markdown() str [source]#
Returns a string representation of the table formatted as GitHub-Flavored Markdown.
>>> tbl = Table(alignments=['l', 'r', 'l']) >>> tbl.add_row([1, '|']) >>> tbl.add_row([10, '20||']) >>> print(tbl.github_markdown()) 1 | \| :--|-------: 10 | 20\|\|
- csv(dialect: str = 'excel', csv_kwargs: Optional[Dict[str, Any]] = None) str [source]#
Returns a string containing a CSV representation of the table.
- Parameters
dialect β String passed to
csv.writer()
.csv_kwargs β Dict of arguments passed to
csv.writer()
.
>>> tbl = Table() >>> tbl.add_row([1, ","]) >>> tbl.add_row([10, 20]) >>> print(tbl.csv()) 1,"," 10,20
- latex(skip_lines: int = 0, hline_after: Optional[Tuple[int, ...]] = None) str [source]#
Returns a string containing the rows of a LaTeX representation of the table.
- Parameters
skip_lines β number of lines to skip at the start of the table.
hline_after β list of row indices after which to add an
hline
(the indices must subtract skip_lines, if non-zero).
>>> tbl = Table() >>> tbl.add_row([0, "skipped"]) >>> tbl.add_row([1, "apple"]) >>> tbl.add_row([2, "pear"]) >>> print(tbl.latex(skip_lines=1)) 1 & apple \\ 2 & pear \\
- pytools.merge_tables(*tables: pytools.Table, skip_columns: Optional[Tuple[int, ...]] = None) pytools.Table [source]#
- Parameters
skip_columns β a
tuple
of column indices to skip in all the tables except the first one.
Debugging#
Progress bars#
Name generation#
- pytools.generate_numbered_unique_names(prefix: str, num: Optional[int] = None) Iterable[Tuple[int, str]] [source]#
- class pytools.UniqueNameGenerator(existing_names: Optional[Set[str]] = None, forced_prefix: str = '')[source]#
-
- add_name(name: str, *, conflicting_ok: bool = False) None [source]#
- Parameters
conflicting_ok β A flag to dictate the behavior when name is conflicting with the set of existing names. If True, a conflict is silently passed. If False, a
ValueError
is raised on encountering a conflict.
Deprecation Warnings#
- pytools.deprecate_keyword(oldkey: str, newkey: Optional[str] = None, *, deadline: Optional[str] = None)[source]#
Decorator used to deprecate function keyword arguments.
- Parameters
oldkey β deprecated argument name.
newkey β new argument name that serves the same purpose, if any.
deadline β expected time frame for the removal of the deprecated argument.
Functions for dealing with (large) auxiliary files#
Helpers for numpy
#
- pytools.reshaped_view(a, newshape)[source]#
Create a new view object with shape
newshape
without copying the data ofa
. This function is different fromnumpy.reshape
by raising an exception when data copy is necessary.- Parameters
a β a
numpy.ndarray
object.newshape β an
int
object or a tuple ofint
objects.
New in version 2018.4.
Timing data#
Log utilities#
- class pytools.ProcessLogger(logger, description, silent_level=None, noisy_level=None, long_threshold_seconds=None)[source]#
Logs the completion time of a (presumably) lengthy process to
logging
. Only uses a high log level if the process took perceptible time.
Sorting in natural order#
- pytools.natorder(item)[source]#
Return a key for natural order string comparison.
See
natsorted()
.New in version 2020.1.
- pytools.natsorted(iterable, key=None, reverse=False)[source]#
Sort using natural order 1, as opposed to lexicographic order.
Example:
>>> sorted(["_10", "_1", "_9"]) == ["_1", "_10", "_9"] True >>> natsorted(["_10", "_1", "_9"]) == ["_1", "_9", "_10"] True
- Parameters
iterable β an iterable to be sorted. It must only have strings, unless key is specified.
key β if provided, a key function that returns strings for ordering using natural order.
reverse β if True, sorts in descending order.
- Returns
a sorted list
New in version 2020.1.
Backports of newer Python functionality#
- pytools.resolve_name(name)[source]#
A backport of
pkgutil.resolve_name()
(added in Python 3.9).New in version 2021.1.2.
Hashing#
- pytools.unordered_hash(hash_instance, iterable, hash_constructor=None)[source]#
Using a hash algorithm given by the parameter-less constructor hash_constructor, return a hash object whose internal state depends on the entries of iterable, but not their order. If hash is the instance returned by evaluating
hash_constructor()
, then the each entry i of the iterable must permithash.upate(i)
to succeed. An example of hash_constructor ishashlib.sha256
fromhashlib
.hash.digest_size
must also be defined. If hash_constructor is not provided,hash_instance.name
is used to deduce it.- Returns
the updated hash_instance.
Warning
The construction used in this function is likely not cryptographically secure. Do not use this function in a security-relevant context.
New in version 2021.2.
Sampling#
- pytools.sphere_sample_equidistant(npoints_approx: int, r: float = 1.0)[source]#
Generate points regularly distributed on a sphere based on https://www.cmu.edu/biolphys/deserno/pdf/sphere_equi.pdf.
- Returns
an
ndarray
of shape(3, npoints)
, wherenpoints
does not generally equal npoints_approx.
- pytools.sphere_sample_fibonacci(npoints: int, r: float = 1.0, *, optimize: Optional[str] = None)[source]#
Generate points on a sphere based on an offset Fibonacci lattice from 2.
- Parameters
optimize β takes the values: None to use the standard Fibonacci lattice,
"minimum"
to minimize the nearest neighbor distances in the lattice and"average"
to minimize the average distances in the lattice.- Returns
an
ndarray
of shape(3, npoints)
.
Type Variables Used#
- class pytools.T#
Any type.
- class pytools.F#
Any callable.
An in-memory relational database table#
- class pytools.datatable.DataTable(column_names, column_data=None)[source]#
An in-memory relational database table.
- __init__(column_names, column_data=None)[source]#
Construct a new table, with the given C{column_names}.
- Parameters
column_names β An indexable of column name strings.
column_data β None or a list of tuples of the same length as column_names indicating an initial set of data.
- copy()[source]#
Make a copy of the instance, but leave individual rows untouched.
If the rows are modified later, they will also be modified in the copy.
- deep_copy()[source]#
Make a copy of the instance down to the row level.
The copyβs rows may be modified independently from the original.
- join(column, other_column, other_table, outer=False)[source]#
Return a tabled joining this and the C{other_table} on C{column}.
The new table has the following columns: - C{column}, titled the same as in this table. - the columns of this table, minus C{column}. - the columns of C{other_table}, minus C{other_column}.
Assumes both tables are sorted ascendingly by the column by which they are joined.