Common Utilities#
Common utility functions used throughout the project.
Timeout utilities are adapted from pnpnpn/timeout-decorator (MIT License) and from chaidiscovery/chai-lab
- exception atomworks.common.ChildProcessError[source]#
Bases:
ExceptionException raised when a child process dies unexpectedly.
- class atomworks.common.KeyToIntMapper[source]#
Bases:
objectMaps keys to unique integers based on the order of the first appearance of the key.
This is useful for mapping id’s such as chain_id, chain_entity, molecule_iid, etc. to integers.
Example
>>> chain_id_to_int = KeyToIntMapper() >>> chain_id_to_int("A") # 0 >>> chain_id_to_int("C") # 1 >>> chain_id_to_int("A") # 0 >>> chain_id_to_int("B") # 2
- atomworks.common.as_list(value: Any) list[source]#
Convert a value to a list.
- Handles various types using duck typing:
Iterable objects (lists, tuples, strings, etc.): converted to list
Single values: wrapped in a list
- Parameters:
value – The value to convert to a list.
- Returns:
A list containing the value(s).
- atomworks.common.default(obj: Any, default: Any) Any[source]#
Return obj if not None, otherwise return default.
- Parameters:
obj – The primary object to return.
default – The fallback value if obj is None.
- Returns:
obj if it is not None, otherwise default.
- atomworks.common.do_nothing(*args, **kwargs) Callable[source]#
A decorator that does nothing and simply returns the original function.
This decorator can be used as a placeholder or for testing purposes when you want to conditionally apply decorators without changing the code structure.
- Returns:
A decorator function that returns the original function unchanged.
Example
@do_nothing_decorator() def my_function(): return "Hello, World!" # or: do_nothing(bla=123, blub=456)(my_function)
- atomworks.common.exists(obj: Any) bool[source]#
Check that obj is not None.
- Parameters:
obj – The object to check.
- Returns:
True if obj is not None, False otherwise.
- atomworks.common.immutable_lru_cache(maxsize: int = 128, typed: bool = False, deepcopy: bool = True, copy_func: Callable | None = None) Callable[source]#
An immutable version of lru_cache for caching functions that return mutable objects.
- Parameters:
maxsize – Maximum number of items to cache.
typed – Whether to treat different types as separate cache entries.
deepcopy – Whether to use deep copy for immutable caching.
copy_func – Custom copy function to use. If provided, overrides deepcopy parameter. Should be a callable that takes the cached object and returns a copy.
- Returns:
A decorator that provides immutable caching functionality.
Example
>>> # Use biotite's fast copy for AtomArrays >>> @immutable_lru_cache(maxsize=200, copy_func=lambda x: x.copy()) >>> def get_template(code): ... return atom_array_from_ccd_code(code)
- atomworks.common.listmap(func: Callable, *iterables) list[source]#
Like map, but returns a list instead of an iterator.
- Parameters:
func – The function to apply.
*iterables – Variable number of iterables to map over.
- Returns:
A list containing the results of applying func to the iterables.
- atomworks.common.not_isin(element: ndarray, array: ndarray, **isin_kwargs) ndarray[source]#
Like ~np.isin, but more efficient.
- Parameters:
element – The array to test.
array – The array of values to test against.
**isin_kwargs – Additional keyword arguments for np.isin.
- Returns:
Boolean array indicating which elements are not in the array.
- atomworks.common.string_to_md5_hash(s: str, truncate: int = 32) str[source]#
Generate an MD5 hash of a string and return the first truncate characters.
- Parameters:
s – The string to hash.
truncate – Number of characters to return from the hash.
- Returns:
The truncated MD5 hash as a string.
- atomworks.common.sum_string_arrays(*objs: ndarray | str) ndarray[source]#
Sum a list of string arrays or strings into a single string array.
Concatenates the arrays and determines the shortest string length to set as dtype.
- Parameters:
*objs – Variable number of string arrays or strings to sum.
- Returns:
A single concatenated string array.
- atomworks.common.timeout(timeout: float | int | None = None, strategy: Literal['signal', 'subprocess'] = 'subprocess') Callable[source]#
Decorator to apply a timeout to a function.
The signal strategy is more efficient and slightly faster, but does not work in all contexts (e.g. with some C dependencies like RDKit, on certain operating systems). The subprocess strategy is always available, but slightly slower and with a higher overhead.
- atomworks.common.timeout_using_signal(timeout: float | int | None) Callable[source]#
Build a decorator that applies a timeout to a function using the signal module.
This decorator sets up a signal handler to raise a TimeoutError if the decorated function exceeds the specified timeout duration. It uses the SIGALRM signal to implement the timeout.
Use for example as:
`python result = timeout_using_signal(timeout=10.0)(my_function)(*args, **kwargs) `- Parameters:
timeout (float | int | None) – The timeout duration in seconds.
- Returns:
A decorator function that can be applied to other functions to add timeout functionality.
- Return type:
Callable
- atomworks.common.timeout_using_subprocess(timeout: float | int | None) Callable[source]#
Force function to timeout after specified time.
The returned decorator uses a subprocess to execute the function, allowing for timeout functionality even for CPU-bound operations that cannot be interrupted by signals.
- Parameters:
timeout (float | int | None) – The maximum time in seconds allowed for the function to execute.
- Returns:
A decorator that can be applied to a function.
- Return type:
Callable
- Raises:
TimeoutError – If the function does not return before the timeout.
ChildProcessException – If the child process dies unexpectedly.