A Collection of Utilities

Math

pytools.levi_civita(tup)[source]

Compute an entry of the Levi-Civita tensor for the indices tuple.

pytools.perm(n, k)[source]

Return P(n, k), the number of permutations of length k drawn from n choices.

pytools.comb(n, k)[source]

Return C(n, k), the number of combinations (subsets) of length k drawn from n choices.

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.

pytools.is_single_valued(iterable: Iterable[pytools.T], equality_pred: Callable[[pytools.T, pytools.T], bool] = <built-in function eq>) bool[source]
pytools.all_roughly_equal(iterable, threshold)[source]
pytools.single_valued(iterable: Iterable[pytools.T], equality_pred: Callable[[pytools.T, pytools.T], bool] = <built-in function eq>) pytools.T[source]

Return the first entry of iterable; Assert that other entries are the same with the first entry of iterable.

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 to True 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, cache_dict_name=None)[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. frozen dataclasses.

pytools.memoize_in(container, identifier)[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. frozen dataclasses.

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. frozen dataclasses.

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

pytools.argmin2(iterable, return_value=False)[source]
pytools.argmax2(iterable, return_value=False)[source]
pytools.argmin(iterable)[source]
pytools.argmax(iterable)[source]

Cartesian products

pytools.cartesian_product(*args)[source]
pytools.distinct_pairs(list1, list2)[source]

Permutations, Tuples, Integer sequences

pytools.wandering_element(length, wanderer=1, landscape=0)[source]
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_all_integer_tuples_below(n, length, least_abs=0)[source]
pytools.generate_permutations(original)[source]

Generate all permutations of the list original.

Nicked from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252178

pytools.generate_unique_permutations(original)[source]

Generate all unique permutations of the list original.

Formatting

class pytools.Table(alignments=None)[source]

An ASCII table generator.

Parameters

alignments – List 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, with alignments=[‘l’, ‘r’], the third and all following columns will use ‘r’ alignment.

add_row(row)[source]
__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()[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='excel', csv_kwargs=None)[source]

Returns a string containing a CSV representation of the table.

Parameters
>>> tbl = Table()
>>> tbl.add_row([1, ","])
>>> tbl.add_row([10, 20])
>>> print(tbl.csv())
1,","
10,20
latex(skip_lines=0, hline_after=None)[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.string_histogram(iterable, min_value=None, max_value=None, bin_count=20, width=70, bin_starts=None, use_unicode=True)[source]
pytools.word_wrap(text, width, wrap_using='\n')[source]

A word-wrap function that preserves existing line breaks and most spaces in the text. Expects that existing line breaks are posix newlines (\n).

Debugging

pytools.typedump(val, max_seq=5, special_handlers=None)[source]
pytools.invoke_editor(s, filename='edit.txt', descr='the file')[source]

Progress bars

class pytools.ProgressBar(descr, total, initial=0, length=40)[source]
draw()[source]
progress(steps=1)[source]
set_progress(done)[source]
finished()[source]
__enter__()[source]
__exit__(exc_type, exc_val, exc_tb)[source]

Name generation

pytools.generate_unique_names(prefix)[source]
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]
is_name_conflicting(name: str) bool[source]
add_name(name: str) None[source]
add_names(names: Iterable[str]) None[source]
__call__(based_on: str = 'id') str[source]

Call self as a function.

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

pytools.download_from_web_if_not_present(url, local_name=None)[source]

New in version 2017.5.

Helpers for numpy

pytools.reshaped_view(a, newshape)[source]

Create a new view object with shape newshape without copying the data of a. This function is different from numpy.reshape by raising an exception when data copy is necessary.

Parameters
  • a – a numpy.ndarray object.

  • newshape – an int object or a tuple of int objects.

New in version 2018.4.

Timing data

class pytools.ProcessTimer[source]

Measures elapsed wall time and process time.

__enter__()[source]
__exit__(exc_type, exc_val, exc_tb)[source]
done()[source]

Timing data attributes:

wall_elapsed
process_elapsed

New in version 2018.5.

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.

__init__(logger, description, silent_level=None, noisy_level=None, long_threshold_seconds=None)[source]
done(extra_msg=None, *extra_fmt_args)[source]
__enter__()[source]
__exit__(exc_type, exc_val, exc_tb)[source]
class pytools.DebugProcessLogger(logger, description, silent_level=None, noisy_level=None, long_threshold_seconds=None)[source]
class pytools.log_process(logger, description=None)[source]

A decorator that uses ProcessLogger to log data about calls to the wrapped function.

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

1

https://en.wikipedia.org/wiki/Natural_sort_order

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 permit hash.upate(i) to succeed. An example of hash_constructor is hashlib.sha256 from hashlib. 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), where npoints 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.

2

http://extremelearning.com.au/how-to-evenly-distribute-points-on-a-sphere-more-effectively-than-the-canonical-fibonacci-lattice/

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.