automol.util#

automol.util#

some words

Common utilities used by automol.

automol.util.breakby(lst, elem)#

Break a list by element, dropping the element itself. Analogous to ‘<char>’.split(‘<string>’) for strings. :type lst: Sequence :param lst: The list :type elem: :param elem: The element to break the list by, gets deleted :rtype: tuple[tuple, ...] :return:The chunks between the break points of the input list.

automol.util.equivalence_partition(iterable, relation, perfect=False)#

Partitions a set of objects into equivalence classes.

canned function taken from https://stackoverflow.com/a/38924631

Parameters:
  • iterable (Collection) – Collection of objects to be partitioned

  • relation (Callable[[Any, Any], bool]) – Equivalence relation. I.e. relation(o1,o2) evaluates to True if and only if o1 and o2 are equivalent

  • perfect (bool) – Is this a perfect equivalence relation, where a = c and b = c guarantees a = b? if not, an extra search is performed to make sure that a, b, and c still end up in the same class

Return type:

list

:returns:A sequence of sets. Each one is an equivalence class

automol.util.flatten(lst)#

Flatten an arbitrarily nested list of lists (iterator). Source: https://stackoverflow.com/a/2158532 . :type lst: Collection :param lst: An arbitrarily nested list or tuple :rtype: Iterator :return: An iterator over the flattened list of values.

automol.util.formula_from_symbols(symbs)#

Build a molecular formula from a list of atomic symbols.

(note: dummy atoms will be filtered out and cases will be standardized)

Parameters:

symbs (tuple[str]) – Atomic symbols

Return type:

str

automol.util.is_even_permutation(seq1, seq2, check=True)#

Determine whether a permutation of a sequence is even.

Parameters:
  • seq1 (Sequence) – The first sequence

  • seq2 (Sequence) – The second sequence, which must be a permuation of the first

Return type:

bool

Returns:

True if the permutation is even, False if it is odd

automol.util.is_odd_permutation(seq1, seq2)#

Determine whether a permutation of a sequence is odd.

Parameters:
  • seq1 (list) – The first sequence

  • seq2 (list) – The second sequence, which must be a permuation of the first

Return type:

bool

Returns:

True if the permutation is even, False if it is odd

automol.util.move_item_to_end(lst, item)#

Move an item to the end of a list.

Parameters:
  • lst (Sequence) – The list

  • item – The item, which must be in lst

Return type:

tuple

Returns:

The list, with the item moved to end

automol.util.move_item_to_front(lst, item)#

Move an item to the front of a list.

Parameters:
  • lst (Sequence) – The list

  • item – The item, which must be in lst

Return type:

tuple

Returns:

The list, with the item moved to front

automol.util.move_items_to_front(lst, items)#

Move an item to the front of a list.

Parameters:
  • lst (Sequence) – The list

  • item – The item, which must be in lst

Return type:

tuple

Returns:

The list, with the item moved to front

automol.util.partner(pair, item)#

Get the partner of an item in a pair.

The two items must be distinct

Parameters:
  • pair (Collection) – An iterable of length 2

  • item (Any) – One of two items

Return type:

Any

Returns:

The other item

automol.util.remove_duplicates_with_order(lst)#

Remove all duplicates of a list while not reordering the list. :type lst: Sequence :param lst: A list. :rtype: Sequence :return: A list, without duplicates. Note: To be deprecated and replaced with calls to more_itertools.unique_justseen.

automol.util.scale_iterable(iterable, scale_factor)#

Scale some type of iterable of floats by a scale factor. :type iterable: Collection[float] :param iterable: A list of numbers. :type scale_factor: float :param scale_factor: A factor to scale by. :rtype: Collection[float] :return: The scaled list of numbers.

automol.util.separate_negatives(lst)#

Seperate a list of numbers into negative and nonnegative (>= 0). :type lst: Sequence :param lst: The list :rtype: tuple[tuple, tuple] :return: Value for negatives and for non-negatives.

automol.util.sort_by_list(lst, ref_lst, include_missing=True)#

Order the elements of the list by using the priorities given by some reference lst.

if include_missing: a=[q, a, e, x, f, t], ref=[x, a, q, e] -> sort_a=[x, a, q, e, f, t] if not include_missing: a=[q, a, e, x, f], ref=[x, a, q, e] -> sort_a=[x, a, q, e]

Note that any element in the original list not in original list is dropped if the user specifies not to include it.

Parameters:
  • lst (tuple) – List to sort

  • ref_lst (tuple) – List which sets the order of the previous list

Return type:

tuple

automol.util.translate(seq, trans_dct, drop=False, item_typ=<class 'numbers.Number'>)#

Translate items in a nested sequence or collection with a dictionary.

Parameters:
  • seq (Collection) – An arbitrarily nested sequence or collection

  • trans_dct (dict) – A translation dictionary

  • drop (bool) – Drop values missing from translation dictionary?, defaults to False

Return type:

Collection

Returns:

Translated version of collection

automol.util.value_similar_to(val, lst, thresh)#

Check if a value is close to any one of a list of values. :type val: float :param val: A number. :type lst: Sequence[float] :param lst: A collection of numbers to compare to. :type thresh: float :param thresh: The comparison threshold. :rtype: bool :return: ‘True’ if close, ‘False’ if not.

automol.util.heuristic#

Structural heuristics.

automol.util.heuristic.bond_distance(symb1, symb2, angstrom=True)#

The heuristic bond distance between two atoms, based on their symbols.

Returns whichever is smaller of (a.) the sum of covalent radii, and (b.) the average vdw radius.

Parameters:
  • symb1 (str) – The first atom symbol.

  • symb2 (str) – The second atom symbol.

  • angstrom (bool) – Return in angstroms intead of bohr, defaults to True

Return type:

float

Returns:

The heuristic distance

automol.util.heuristic.bond_distance_limit(symb1, symb2, dist_factor=None, angstrom=True)#

The heuristic bond distance limit (largest possible bond distance) between two atoms, based on their symbols.

Returns dist_factor times whichever is larger of of (a.) the sum of covalent radii, and (b.) the average vdw radius.

Parameters:
  • symb1 (str) – The first atom symbol

  • symb2 (str) – The second atom symbol

  • dist_factor (float, optional) – The multiplier on the distance limit, defaults to 1.05

  • angstrom (bool) – Return in angstroms intead of bohr?, defaults to True

Return type:

float

Returns:

The heuristic distance

automol.util.matrix#

some words

3D matrices.

automol.util.matrix.string(mat, val_format='{0:>8.3f}')#

Write a matrix to a string.

Parameters:
  • mat (Sequence[Sequence[float]]) – Matrix to form string with

  • val_format (str) – A number-formatting string, such as “{:.3f}”

Return type:

str

Returns:

Matrix as a string

automol.util.ring#

some words

Functions for dealing with a list of items encoding a ring.

automol.util.ring.cycle(items, count=1)#

Cycle ring items once.

Example: (1, 2, 3, 4) -> (2, 3, 4, 1)

Parameters:

items (Sequence[object]) – The ring items

Return type:

tuple[object]

Returns:

The ring items, cycled once

automol.util.ring.cycle_item_to_front(items, item, end_item=None)#

Cycle ring items until one is in front.

Optionally, request one adjacent item to be at the end, reversing the ring order if necessary.

Parameters:
Parm item:

The item to cycle to the font

Return type:

tuple[object, ...]

Returns:

The ring items with item cycled to the front and end_item to the end

automol.util.ring.cycle_items_to_back(items, back_items)#

Cycle ring items until a group of adjacent items is at the end of the list.

Parameters:

items (Sequence[object]) – The ring items

Parm back_items:

The item to cycle to the end

Return type:

tuple[object, ...]

Returns:

The ring items back_items cycled to the end

automol.util.ring.cycle_items_to_front(items, front_items)#

Cycle ring items until a group of adjacent items is at the front of the list.

Parameters:

items (Sequence[object]) – The ring items

Parm front_items:

The item to cycle to the font

Return type:

tuple[object, ...]

Returns:

The ring items with item cycled to the front and end_item to the end

automol.util.ring.cycle_to_optimal_split(items, split_pairs, back_items)#

Cycle to find an “optimum split” that puts a subset of items as close as possible to the end of the list.

Parameters:
Return type:

tuple[object, ...]

Returns:

The cycle with the optimal split

automol.util.ring.cycle_to_split(items, split_pair)#

Cycle to split a pair of adjacent items, putting one on each end of the list.

Parameters:
  • items (List[object]) – The ring items

  • split_pair (Tuple[object, object]) – The pair of items to split

Return type:

tuple[object, ...]

Returns:

The ring items with one item in the pair at the start and one at the end

automol.util.ring.distance(items, item1, item2, longest=False)#

Find the distance between two items in a ring.

By default, finds the shortest distance. Setting longest=True results in the longest distance.

Parameters:
  • items (Sequence[object]) – The ring items

  • item1 (object) – The item to start measuring distance from

  • item2 (object) – The item to measure distance to

  • longest (bool) – Return the longest distance?, defaults to False

Return type:

int

Returns:

The number of ring items between these two

automol.util.ring.edges(items)#

Get the edge pairs of a ring.

Example: (1, 2, 3, 4) -> ((1, 2), (2, 3), (3, 4), (4, 1))

Parameters:

items (Sequence[object]) – The ring items

Return type:

tuple[tuple[object, object], ...]

Returns:

The ring edge pairs

automol.util.ring.normalize(items)#

Normalize the ordering of items in a ring.

Parameters:

items (Sequence[object]) – The ring items

Return type:

tuple[object, ...]

Returns:

The ring items, in normalized order

automol.util.tensor#

I/O operations for higher dimension matrices of 3 or higher.

automol.util.tensor.build_full_array(mat_idxs, mat_vals, fill_perms=False)#

Function to fill out the array with avail caps: (

((idx1, idx2, …, idxn), val1), ((idx1, idx2, …, idxn), val2), …, ((idx1, idx2, …, idxn), valn),.

Parameters:
Return type:

ndarray

Returns:

Array.

automol.util.tensor.from_string(arr_str, fill_perms=False)#

Write a higher dimensional array (3 or more) to a string.

Parameters:

arr_str (str) – string containing higher dimensions matrix

Return type:

ndarray

Returns:

Array of high dimension matrix

Format of input string:

idx1 idx2 .. idxn val1 idx1 idx2 .. idxn valn

automol.util.tensor.string(arr, include_zeros=False, include_perms=False, val_format='{0:>16.8f}')#

Write a higher dimensional array (3 or more) to a string.

Parameters:

arr (ndarray) – higher dimensions matrix

Return type:

str

Returns:

Numbers in a string

Format of output string:

idx1 idx2 .. idxn val1 idx1 idx2 .. idxn valn

automol.util.tensor.string_submat_3d(arr)#

Writes a 3-dimensional matrix to a unique string format. :type arr: ndarray :param arr:higher dimensions matrix :rtype: str :return: Numbers in a string idx1

2d submat1

idx2

2d submat2

idxn

2d submatn.

automol.util.tensor.string_submat_4d(arr)#

Writes a 4-dimensional matrix to a unique string format. :type arr: ndarray :param arr:higher dimensions matrix :rtype: str :return: Numbers in a string idx1

2d submat1

idx2

2d submat2

idxn

2d submatn.

automol.util.vector#

vector functions.

automol.util.vector.angle(xyz1, xyz2, orig_xyz=(0.0, 0.0, 0.0))#

Measure the angle inscribed by three atoms.

Parameters:
Return type:

float

Returns:

Angle between three atoms

automol.util.vector.arbitrary_unit_perpendicular(xyz, orig_xyz=(0.0, 0.0, 0.0))#

Determine an arbitrary perpendicular vector.

Return type:

ndarray

automol.util.vector.are_parallel(xyz1, xyz2, orig_xyz=(0.0, 0.0, 0.0), anti=False, tol=0.001)#

Assess if two vectors are parallel to each other.

Parameters:
Return type:

bool

Returns:

True if vectors are parallel, false if not

automol.util.vector.best_unit_perpendicular(xyzs)#

Find a vector that is perpendicular to a series of points as much as possible.

For 1 point, this is an arbitrary vector. For 2 points, this is an arbitrary perpendicular vector. For 3 points, this is the exact normal to the plane. For 4+ points, this is the normal to the best-fit plane.

Solution to the last problem was found here: https://stackoverflow.com/a/51132260

Parameters:

xyzs (Sequence[Sequence | ndarray]) – The points

Return type:

ndarray

Returns:

New vector

automol.util.vector.central_angle(xyz1, xyz2, xyz3)#

Measure the angle inscribed by three atoms.

Parameters:
Return type:

float

Returns:

Angle inscribed by three atoms

automol.util.vector.dihedral_angle(xyz1, xyz2, xyz3, xyz4)#

Measure the dihedral angle defined by four atoms.

Parameters:
Return type:

float

Returns:

Dihedral angle of four atoms

automol.util.vector.distance(xyz1, xyz2)#

Measure the distance between points.

Parameters:
Return type:

float

Returns:

Distance

automol.util.vector.flip_if_left_handed(xvec, yvec, zvec)#

Given three vectors, flips the third one, if necessary, to make a right-handed coordinate system.

The vectors need not be orthogonal, but they must be linearly independent for this to work. Does not change direction – only flips the sign, if necessary.

Parameters:
Return type:

ndarray

Returns:

zvec or, if they made a left-handed system, -zvec

automol.util.vector.from_internals(dist=0.0, xyz1=(0.0, 0.0, 0.0), ang=0.0, xyz2=(0.0, 0.0, 1.0), dih=0.0, xyz3=(0.0, 1.0, 0.0))#

Determine the position of a point (xyz4) in Cartesian coordinates whose position is related to three other points (xyz1, xyz2, xyz3) via a set of internal coordinates.

Parameters:
  • dist (float) – Distance between xyz1 and xyz2 (in bohr)

  • angle – Angle between xyz1, xyz2, xyz3 (in radians)

  • xyz2 (Sequence | ndarray) – 3D vector to point 2

  • dih (float) – Dihedral from xyz1, xyz2, xyz3 to xyz4 (in radians)

  • xyz3 (Sequence | ndarray) – 3D vector to point 2

Return type:

ndarray

Returns:

New point ‘xyz4’

automol.util.vector.is_vector_like(obj)#

Check if an object has the right shape and dtype to be a vector.

Parameters:

obj (Sequence | ndarray) – The object

Return type:

bool

Returns:

True if it does, False if it doesn’t

automol.util.vector.orthogonalize(xyz1, xyz2, normalize=False)#

Orthogonalize xyz2 against xyz1. :type xyz1: Sequence | ndarray :param xyz1: 3D vector :type xyz2: Sequence | ndarray :param xyz2: 3D vector :type normalize: bool :param normalize: Whether to normalize the result :rtype: ndarray :return: The orthoganol component.

automol.util.vector.projected_central_angle(xyz1, xyz2, xyz3)#

Measure the angle inscribed by three atoms, projected onto the normal plane of the central atom.

Parameters:
Return type:

float

Returns:

Angle projected on normal plane

automol.util.vector.require_vector_like(obj)#

Require an object to have the right shape and dtype to be a vector.

Parameters:

obj (Sequence | ndarray) – The object

Raises:

Raises an AssertionError if the object is not vector-like

automol.util.vector.rotator(axis, ang, degree=False, orig_xyz=(0.0, 0.0, 0.0))#

Get a function for axis-angle rotations, optionally specifying the origin.

Parameters:
  • axis (ndarray) – Rotational axis (norm is ignored)

  • ang (float) – Rotational angle

  • degree (bool) – _description_, defaults to False

Return type:

Callable[[ndarray], ndarray]

Returns:

_description_

automol.util.vector.string(vec, num_per_row=None, val_format='{0:>8.3f}')#

Write a vector to a string.

Parameters:
  • vec (Sequence | ndarray) – vector to form string with

  • num_per_row (Optional[int]) – number of vector elements to write to a row

Return type:

str

Returns:

String

automol.util.vector.unit_bisector(xyz1, xyz2, orig_xyz=(0.0, 0.0, 0.0), outer=False)#

Calculate a unit bisector.

Parameters:
  • xyz1 (Sequence | ndarray) – 3D vector

  • xyz2 (Sequence | ndarray) – 3D vector

  • orig_xyz (Sequence | ndarray) – Origin of coordinate system xyz1 and xyz2 are in

  • outer (bool) – Get the outer, instead of the inner bisector?, defaults to False

Return type:

ndarray

Returns:

Unit bisector

automol.util.vector.unit_direction(xyz1, xyz2)#

Calculate a unit direction vector from xyz1 to xyz2.

Parameters:
Return type:

ndarray

Returns:

Unit direction vector from two vectors

automol.util.vector.unit_norm(xyz)#

Normalize a vector (xyz) to 1.0.

Does nothing to null vectors

:param xyz:3D Vector :rtype: ndarray :return: Numbers in the vector

automol.util.vector.unit_perpendicular(xyz1, xyz2, orig_xyz=(0.0, 0.0, 0.0), value_if_parallel=(0.0, 0.0, 0.0))#

Calculate a unit perpendicular on xyz1 and xyz2.

Parameters:
Return type:

ndarray

Returns:

Unit vector perpendicular to xyz1 and xyz2.

automol.util.dict_#

dictionary helpers

automol.util.dict_.by_key(dct, keys, fill=True, fill_val=None)#

Dictionary on a set of keys, filling missing entries.

Parameters:
  • fill (bool) – Fill in missing values

  • keys (object) – Keys for missing values

  • fill_val (Optional[bool]) – If fill is True, fill missing entries with this value.

Return type:

dict[object, object]

Returns:

‘fill; or dictionary with filled values

automol.util.dict_.by_value(dct, func=<function <lambda>>)#

Dictionary on a set of values, determined by a function. :type dct: dict[object, object] :param dct: Dictionary of values :type func: Callable :param func: Function :return: Dictionary with keys.

automol.util.dict_.compose(dct1, dct2)#

Get the composition of dct1 with dct2.

That is, dct[k] = dct1[dct2[k]]

Parameters:
Return type:

dict[object, object]

Returns:

The composed dictionary

automol.util.dict_.empty_if_none(obj)#

Returns an empty dictionary if input object is None, otherwise return the object. :type obj: object :param obj: Generic object :return: Object of none if none.

automol.util.dict_.filter_by_key(dct, func=<function <lambda>>)#

Filter dictionary entries by their values. :type dct: dict[object, object] :param dct: Dictionary :type func: Callable :param func: Callable function :return:Dictionary with sorted values.

automol.util.dict_.filter_by_value(dct, func=<function <lambda>>)#

Filter dictionary entries by their values. :type dct: dict[object, object] :param dct: Dictionary :type func: Callable :param func: Callable function :return:Dictionary with sorted values.

automol.util.dict_.filter_keys(dct_1, dct_2)#

Given two dictionaries (dct1 bigger dct2), filter out from 1 all the entries present in 2.

Parameters:
  • dct1 – First dictionary

  • dct2 – Second dictionary

Return type:

dict[object, object]

Returns:

filtered dct1

automol.util.dict_.invert(dct)#

Transposes the keys and values in a dictionary.

Parameters:

dct (dict[object, object]) – Dictionary to transpose

Return type:

dict[object, object]

Returns:

Transposed dictionary

automol.util.dict_.keys_by_value(dct, func=<function <lambda>>)#

Return dictionary keys for specific values. :param dict: Dictionary :type func: Callable :param func: Callable Function :return: Key that was called based on value.

automol.util.dict_.keys_sorted_by_value(dct)#

Dictionary keys sorted by their associated values. :type dct: dict[object, object] :param dct: Dictionary :param func: Callable function :return:Dictionary with sorted values.

automol.util.dict_.merge_sequence(dcts)#

Merge a sequence of dictionaries. :type dcts: Sequence[dict[object, object]] :param dcts: Dictionary to merge :return: Merged dictionaries.

automol.util.dict_.sort_value_(dct, allow_missing=True, missing_val=None)#

Generate a sort value function from a dictionary.

Parameters:
  • dct (dict[object, object]) – A dictionary

  • allow_missing (bool) – Allow missing values?, defaults to True

Returns:

automol.util.dict_.transform_items_to_values(dct, func=<function <lambda>>)#

Apply a function to each value. :type dct: dict[object, object] :param dct: Dictionary :type func: Callable :param func: Callable function :return: Dictionary with new values.

automol.util.dict_.transform_keys(dct, func=<function <lambda>>)#

Apply a function to each key. :type dct: dict[object, object] :param dct: Dictionary :type func: Callable :param func: Callable function :return: Dictionary and new values.

automol.util.dict_.transform_values(dct, func=<function <lambda>>)#

Apply a function to each value. :type dct: dict[object, object] :param dct: Dictionary :type func: Callable :param func: Callable function :return: New values in a dictionary.

automol.util.dict_.value_by_unordered_key(dct, key, fill_val=None)#

Return the first value matching a tuple key in any order. :type dct: dict[object, object] :param dct: Dictionary of values :param keys: Keys for entries :type fill_val: :param fill_val: Values to fill the missing keys :return: Dictionary with new keys in order.

automol.util.dict_.value_in_floatkey_dct(dct, key, tol=1e-05)#

Access value in a dictionary that may have floats with large numbers of decimal places or strings. :type dct: dict[object, object] :param dct: Dictionary of values :param keys: Keys for entries :type tol: :param tol: Tolerance 1.0e-5 :return: Dictionary with new values.

automol.util.dict_.values_by_key(dct, keys, fill_val=None)#

Return dictionary values for specific keys, filling missing entries. :type dct: dict[object, object] :param dct: Dictionary of values :type keys: object :param keys: Keys for entries :type fill_val: Optional[object] :param fill_val: Fill where value is none :return: Dictionary with new keys.

automol.util.dict_.values_in_multilevel_dct(dct, key1, key2, fill_val=None)#

Obtain a dictionary value where dct[key1][key2]. :param dict: Dictionary with two objects :type key1: object :param key1: First key :type key2: object :param key2: Second key :return: Value of the second entry.

automol.util.dict_.values_sorted_by_key(dct)#

Dictionary values sorted by their associated keys. :type dct: dict[object, object] :param dct: Dictionary :return: Dictionary with sorted values.

automol.util.dict_.multi#

multi-valued dictionary helpers.

dictionary values must all be tuples of the same length

automol.util.dict_.multi.by_key_by_position(mdct, keys, pos)#

Position values, as a dictionary with these keys. :type mdct: dict[object, tuple[object, ...]] :param mdct: Multi-valued dictionary :type keys: object :param keys: Keys for sorting :type pos: int :param pos: Position to select column for dictionary.

Return type:

dict[object, object]

automol.util.dict_.multi.is_multidict(mdct)#

Is this a multi-valued dictionary?. :param mdict: Dictionary :rtype: bool :return: True if it is a multi-valued dictionary, False if not.

automol.util.dict_.multi.set_by_key_by_position(mdct, dct, pos)#

Set values by position and key. :type mdct: dict[object, tuple[object, ...]] :param mdct: Multi-valued dictionary :type dct: dict :param dct: Dictionary :type pos: int :param pos:Position to select column for dictionary. :rtype: dict[object, tuple[object, ...]] :return: New multi-valued dictionary set by key and position.