ampworks.utils#

The utilities module provides a collection of helper functions and classes to simplify common tasks, such as timing specific portions of code, printing progress bars in the console, and more.

Classes#

ProgressBar

Progress bar.

RichResult

Dict-like results container.

RichTable

DataFrame-like results container.

Timer

Timer context manager.

Functions#

alphanum_sort(unsorted[, reverse])

Sort a list alphanumerically.

Package Contents#

class ampworks.utils.ProgressBar(iterable=None, manual=False, desc=None, ncols=80, total=None, **kwargs)[source]#

Progress bar.

Wraps tqdm with different defaults and enables a “manual” mode that is controlled using the set_progress() method.

Parameters:
  • iterable (Iterable or None, optional) – An iterable to automatically track progress across. Must be None if using the manual mode. The default is None. Set total when using a generator to make sure remaining time and the bar are displayed.

  • manual (bool, optional) – True enables a manual mode where the user controls progress updates. Must be False (default) if iterable is not None.

  • desc (str or None, optional) – Prefix description, by default None.

  • ncols (int, optional) – Terminal column width, by default 80. The special case of zero will display limited stats and time, with no progress bar.

  • total (int or None, optional) – Number of expected iterations. Use when iterable is a generator, otherwise estimated remaining time and the printed bar are skipped.

  • **kwargs (dict, optional) – Additional keyword arguments to pass through to tqdm.

Raises:

ValueError – Provide exactly one of iterable or manual, not both.

Examples

The following examples demonstrate both the automatic and manual modes of the progress bar. Note that set_progress() must be called manually to update the progress using values between [0, 1] in manual mode.

When assigning a progress bar to a variable, you should also call the close() method when finished using it to release resources. This is demonstrated for the manual mode below.

import time

from ampworks.utils import ProgressBar

# automatic mode with an iterable
for i in ProgressBar(range(5), desc='Iterable'):
    time.sleep(0.5)

# manual mode with custom progress updates
progbar = ProgressBar(manual=True, desc='Manual')

for i in range(5):
    time.sleep(0.5)
    progbar.set_progress((i + 1) / 5)

progbar.close()
close()[source]#

Closes the progress bar and releases resources. Should be called when finished with the progress bar, especially in manual mode.

reset()[source]#

Resets the iteration count to zero for repeated use. Only works for the manual mode. Create a new instance when using an iterable.

set_progress(progress)[source]#

Updates progress in manual mode. Should be called once per iteration.

Parameters:

progress (float) – Progress fraction in [0, 1].

class ampworks.utils.RichResult(**kwargs)[source]#

Dict-like results container.

A container class based off the _RichResult class in the scipy library. It combines a series of formatting functions to make the printed ‘repr’ easy to read. Use this class directly by passing in any number of keyword arguments, or use it as a base class to have custom classes for different result types.

Inheriting classes should define the class attribute _order_keys which is a list of strings that defines how output fields are sorted when an instance is printed.

Parameters:

**kwargs (dict, optional) – User-specified keyword arguments. Any number of arguments can be given as input. The class simply stores the key/value pairs, makes them accessible as attributes, and provides pretty printing.

Examples

The example below demonstrates how to define the _order_keys class attribute for custom sorting. If arguments are not in the list, they are placed at the end based on the order they were given. Note that _order_keys only provides sorting support and that no errors are raised if an argument is not present, e.g., third below.

from ampworks.utils import RichResult

class CustomResult(RichResult):
    _order_keys = ['first', 'second', 'third',]

result = CustomResult(second=None, last=None, first=None)

print(result)

RichResult can also be used directly, without any custom sorting. Arguments will print based on the order they were input. Instances will still have a fully formatted ‘repr’, including formatted arrays.

import numpy as np

from ampworks.utils import RichResult

t = np.linspace(0, 1, 1000)
y = np.random.rand(1000, 5)

y[0] = np.inf
y[-1] = np.nan

result = RichResult(message='Example.', status=0, t=t, y=y)

print(result)

After initialization, all key/value pairs are accessible as instance attributes.

from ampworks.utils import RichResult

result = RichResult(a=10, b=20, c=30)

print(result.a*(result.b + result.c))
copy()[source]#

Returns a copy of the instance.

Returns:

result (Self) – A deep copy of the current instance. Does not share any memory with the original instance.

class ampworks.utils.RichTable(df)[source]#

DataFrame-like results container.

Provides a structured way to store data using a pd.DataFrame with additional validation and formatting features. Use this class directly by passing in a pd.DataFrame, or subclass it to define custom containers with required columns.

Inheriting classes should define the class attribute _required_cols which is a list of column names that must be present in the input. If any are missing, initialization will raise a ValueError.

Parameters:

df (pd.DataFrame) – The input dataframe to store. Columns are validated against the _required_cols attribute and then stored.

Notes

While this container is meant to act as a simplified dataframe, access to the full pd.DataFrame is provided via the df property. While the entire dataframe cannot be replaced, it can be manipulated in place through this property.

Examples

A minimal example using RichTable directly:

import pandas as pd

from ampworks.utils import RichTable

df = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]})
table = RichTable(df)

print(table)

Subclassing to enforce required columns:

import pandas as pd

from ampworks.utils import RichTable

class CustomTable(RichTable):
    _required_cols = ['Seconds', 'Volts']

df = pd.DataFrame({'Seconds': [0, 1], 'Volts': [3.8, 3.7]})
table = CustomTable(df)  # valid, no errors raised
copy()[source]#

Returns a copy of the instance.

Returns:

table (Self) – A deep copy of the instance. Does not share memory with original.

classmethod from_csv(path)[source]#

Create a new instance from a CSV file.

Parameters:

path (str or Path) – Path to the CSV file.

Returns:

table (Self) – A new instance initialized with data from the file.

to_csv(path)[source]#

Write the table to a CSV file.

Parameters:

path (str or Path) – Path to the output file.

property df: pandas.DataFrame#

The underlying DataFrame stored in the container.

class ampworks.utils.Timer(name='Elapsed time', units='s', display=True)[source]#

Timer context manager.

Records and prints the elapsed time between entering and exiting a context block.

Parameters:
  • name (str, optional) – Context block name used in print. The default is ‘Elapsed time’.

  • units (Literal['s', 'min', 'h'], optional) – Units to use when printing the elapsed time. The default is ‘s’.

  • display (bool, optional) – If True, print on exit. Otherwise, only stores the elapsed time.

Notes

If you want to print in additional units, you can convert and print the elapsed time using the elapsed_time property.

A timer instance can be reused across multiple context blocks; however, the elapsed_time property will only store values from the last block.

Examples

The Timer works as a context manager:

import time

from ampworks.utils import Timer

def function(sleep_time: float) -> None:
    time.sleep(sleep_time)

with Timer():
    function(2.)

If you want to silence printing, set display=False. You can then call print_elapsed at a later time, or access the elapsed_time property for custom printing:

with Timer(display=False) as timer:
    function(2.)

# print in all allowed units
for units in ['s', 'min', 'h']:
    timer.print_elapsed(units)

# custom printing, with higher precision
print(f"Elapsed time: {timer.elapsed_time:.10f} s")
print_elapsed(units='s')[source]#

Print the elapsed time.

Parameters:

units (Literal['s', 'min', 'h'], optional) – Units to use when printing the elapsed time. The default is ‘s’.

property elapsed_time: float#

Return the elapsed time in seconds.

Returns:

elapsed (float) – Time difference between entering and exiting a context block.

ampworks.utils.alphanum_sort(unsorted, reverse=False)[source]#

Sort a list alphanumerically.

This sorting function ensures that numerical substrings are compared based on their integer values. For example, “item2” comes before “item10”, unlike standard string sorting where “item10” would come before “item2”.

Parameters:
  • unsorted (list[str]) – Original unsorted list of strings.

  • reverse (bool, optional) – Flag to reverse the sorted list. The default is False.

Returns:

sorted (list[str]) – An alphanumerically sorted list of strings.