def decryption_vigenere(keys: npt.ArrayLike, ct_numbers: npt.ArrayLike, current_interrupter: npt.ArrayLike) -> np.ndarray: mt = ct_numbers.copy() if len(mt.shape) == 1: mt = np.array([mt]) if len(keys.shape) == 1: keys = np.array([keys]) len_keys = keys.shape[1] indices = np.flatnonzero(np.logical_not(current_interrupter)) for s, t in enumerate(indices): mt[:, t] = (mt[:, t] - keys[:, s % len_keys]) return np.remainder(mt, 29)
def decryption_autokey(keys: npt.ArrayLike, ct_numbers: npt.ArrayLike, current_interrupter: npt.ArrayLike) -> np.ndarray: mt = ct_numbers.copy() len_keys = keys.shape[1] indices = np.flatnonzero(np.logical_not(current_interrupter)) mt[:, 0:len_keys] = np.remainder( mt[:, 0:len_keys] - keys[:, indices[0:len_keys]], 29) step_size = np.arange(len_keys, indices.shape[0], len_keys) if step_size[-1] != mt.shape[1]: step_size = np.concatenate(step_size, indices.shape[0]) diff_step_size = np.cumsum(np.concatenate(([0], np.diff(step_size)))) for index in range(step_size.shape[0] - 1): mt[:, indices[step_size[index]:step_size[index + 1]]] = \ np.remainder(mt[:, indices[step_size[index]:step_size[index + 1]]] - mt[:, diff_step_size[index]:diff_step_size[index + 1]], 29) return mt
def lipid_area(headgroup_coordinate: ArrayLike, neighbor_coordinates: ArrayLike, other_coordinates: Optional[ArrayLike]=None, box: Optional[ArrayLike]=None, plot: bool=False) -> float: """ Calculate the area of a lipid by projecting it onto a plane with neighboring coordinates and creating a Voronoi diagram. Parameters ---------- headgroup_coordinate: numpy.ndarray Coordinate array of shape (3,) or (n, 3) of the central lipid neighbor_coordinates: numpy.ndarray Coordinate array of shape (n, 3) of neighboring lipids to the central lipid. These coordinates are used to construct the plane of best fit. other_coordinates: numpy.ndarray (optional) Coordinate array of shape (n, 3) of neighboring atoms to the central lipid. These coordinates are *not* used to construct the plane of best fit, but are projected onto it. box: numpy.ndarray (optional) Box of minimum cell, used for unwrapping coordinates. plot: bool (optional) Whether to plot the resulting Voronoi diagram. Returns ------- area: float Area of the central lipid Raises ------ ValueError If a Voronoi cell cannot be constructed for the central lipid, usually because too few neighboring lipids have been given. """ from scipy.spatial import Voronoi # preprocess coordinates headgroup_coordinate = np.asarray(headgroup_coordinate) if len(headgroup_coordinate.shape) > 1: if box is not None: headgroup_coordinates = unwrap_around(headgroup_coordinate.copy(), headgroup_coordinate[0], box) headgroup_coordinate = headgroup_coordinates.mean(axis=0) if len(neighbor_coordinates) < 2: return np.nan if box is not None: neighbor_coordinates = unwrap_around(neighbor_coordinates.copy(), headgroup_coordinate, box) if other_coordinates is not None: other_coordinates = np.asarray(other_coordinates).copy() other_coordinates = unwrap_around(other_coordinates, headgroup_coordinate, box) points = np.concatenate([[headgroup_coordinate], neighbor_coordinates]) points -= headgroup_coordinate center = points.mean(axis=0) points -= center Mt_M = np.matmul(points.T, points) u, s, vh = np.linalg.linalg.svd(Mt_M) # project onto plane if other_coordinates is not None: points = np.r_[points, other_coordinates-center] xy = np.matmul(points, vh[:2].T) xy -= xy[0] # voronoi vor = Voronoi(xy) headgroup_cell_int = vor.point_region[0] headgroup_cell = vor.regions[headgroup_cell_int] if plot: from scipy.spatial import voronoi_plot_2d import matplotlib.pyplot as plt fig = voronoi_plot_2d(vor, show_vertices=False, line_alpha=0.6) plt.plot([vor.points[0][0]], [vor.points[0][1]], 'r+', markersize=12) plt.show() if not all(vertex != -1 for vertex in headgroup_cell): raise ValueError("headgroup not bounded by Voronoi cell points: " f"{headgroup_cell}. " "Try including more neighbor points") # x and y should be ordered clockwise x, y = np.array([vor.vertices[x] for x in headgroup_cell]).T area = np.dot(x[:-1], y[1:]) - np.dot(y[:-1], x[1:]) area += (x[-1] * y[0] - y[-1] * x[0]) lipid_area = 0.5 * np.abs(area) return lipid_area