Source code for waterEntropy.analysis.shell_labels

"""
Label neighbours in a coordination shell based on what they are and what their
neighbours are.
"""

import waterEntropy.analysis.RAD as RADShell
from waterEntropy.analysis.shells import ShellCollection


[docs] def get_shell_labels(atom_idx: int, system, shell, shells: ShellCollection): """ Get the shell labels of an atoms shell based on the following: For a central UA, rank its coordination shell by proximity to that central UA's nearest non-like molecule UA. * '#_RESNAME' = RAD shell from same molecule type, when nearest nonlike resid is the same as the reference. * 'X_RESNAME' = when same molecule type has different nearest nonlike resid. * 'RESNAME' = when molecule of different type is in RAD shell. * '0_RESNAME' = closest different type molecule in RAD shell. (the one its assigned to, its nearest non-like!) :param atom_idx: atom index of central atom in coordination shell :param system: mdanalysis instance of atoms in a frame :param shell: shell instance of atom_idx :param shells: ShellCollection instance """ center = system.atoms[atom_idx] # 1. find the closest different UA in a shell # different = not the same resname nearest_nonlike_idx = get_nearest_nonlike(shell, system) # 2. only find labels if a solute is in the shell if nearest_nonlike_idx is not None: nearest_nonlike = system.atoms[nearest_nonlike_idx] shell_labels = [] N_w = 0 for n in shell.UA_shell: neighbour = system.atoms[n] # 3a. label nearest nonlike atom as "0_RESNAME" if neighbour.index == nearest_nonlike.index: shell_labels.append(f"0_{neighbour.resname}") # 3b. label other nonlike atoms as "RESNAME" if ( neighbour.index != nearest_nonlike.index and neighbour.resname != center.resname ): shell_labels.append(neighbour.resname) # 3c. find RAD shells for shell constituents with same resname # as central atom if ( neighbour.index != nearest_nonlike.index and neighbour.resname == center.resname ): N_w += 1 neighbour_shell = shells.find_shell(neighbour.index) if not neighbour_shell: neighbour_shell = RADShell.get_RAD_shell(neighbour, system, shells) # 3d. find nearest nonlike of neighbours with same resname # as central atom neighbour_nearest_nonlike_idx = get_nearest_nonlike( neighbour_shell, system ) # 3e. if neighbour has a pure shell, then it is in the second # shell of the nearest nonlike if neighbour_nearest_nonlike_idx is None: shell_labels.append(f"2_{neighbour.resname}") else: # 3f. if neighbours nearest nonlike is the same atom as # central atom, assume it is in the first shell # if neighbour_nearest_nonlike_idx == nearest_nonlike_idx: neighbour_nearest_nonlike = system.atoms[ neighbour_nearest_nonlike_idx ] # 3g. if neighbours nearest nonlike is in the same resid as # central atom, assume it is in the first shell if neighbour_nearest_nonlike.resid == nearest_nonlike.resid: shell_labels.append(f"1_{neighbour.resname}") else: # 3h. if neighbours nearest nonlike is not the same resid # as central nearest resid, it is in the first shell # of a different resid and labelled as "X_RESNAME" shell_labels.append(f"X_{neighbour.resname}") shell.labels = shell_labels # sorted(shell_labels) #don't sort yet shell.nearest_nonlike_idx = nearest_nonlike.index shell.N_w = N_w return shell
[docs] def get_nearest_nonlike(shell, system): """ For a given shell, find the closest neighbour that is not the same atom/molecule type as the central united atom. :param shell: shell instance of an atom :param system: mdanalysis instance of atoms in a frame """ nearest_nonlike_idx = None center = system.atoms[shell.atom_idx] for n in shell.UA_shell: neighbour = system.atoms[n] if neighbour.resname != center.resname and neighbour.type != center.type: nearest_nonlike_idx = n break return nearest_nonlike_idx