diff --git a/CodeEntropy/levels/axes.py b/CodeEntropy/levels/axes.py index 57ef8912..f1c8bb75 100644 --- a/CodeEntropy/levels/axes.py +++ b/CodeEntropy/levels/axes.py @@ -67,7 +67,7 @@ def get_residue_axes(self, data_container, index: int, residue=None): The translational and rotational axes at the residue level. - Identify the residue (either provided or selected by `resindex index`). - - Determine whether the residue is bonded to neighboring residues + - Determine whether the residue is bonded to neighbouring residues (previous/next in sequence) using MDAnalysis bonded selections. - If there are *no* bonds to other residues: * Use a custom principal axes, from a moment-of-inertia (MOI) tensor @@ -76,7 +76,10 @@ def get_residue_axes(self, data_container, index: int, residue=None): * Set translational axes equal to rotational axes (as per the original code convention). - If bonded to other residues: - * Use default axes and MOI (MDAnalysis principal axes / inertia). + Find edge heavy atoms (i.e. heavy atoms bonded to neighbour residues) + and find the shortest chain between them: the backbone. Edge + atoms + backbone COM are used to determine UA translational axes + (see get_residue_custom_axes) Args: data_container (MDAnalysis.Universe or AtomGroup): @@ -99,43 +102,89 @@ def get_residue_axes(self, data_container, index: int, residue=None): If the residue selection is empty. """ # TODO refine selection so that it will work for branched polymers + # match indexing to MDAnalysis indexing index_prev = index - 1 index_next = index + 1 - if residue is None: residue = data_container.select_atoms(f"resindex {index}") + # residue of interest if len(residue) == 0: raise ValueError(f"Empty residue selection for resindex={index}") - - center = residue.atoms.center_of_mass(unwrap=True) - atom_set = data_container.select_atoms( - f"(resindex {index_prev} or resindex {index_next}) and bonded resid {index}" + edge_atom_set = data_container.atoms.select_atoms( + f" resindex {index} and " + f"(bonded resindex {index_prev} or " + f"resindex {index_next})" ) - if len(atom_set) == 0: - # No bonds to other residues. + uas = residue.select_atoms("mass 2 to 999") + ua_masses = self.get_UA_masses(residue) + + if len(edge_atom_set) == 0: + # No UAS are bonded to other residues # Use a custom principal axes, from a MOI tensor that uses positions of # heavy atoms only, but including masses of heavy atom + bonded H. - uas = residue.select_atoms("mass 2 to 999") - ua_masses = self.get_UA_masses(residue) + moi_tensor = self.get_moment_of_inertia_tensor( - center_of_mass=center, + center_of_mass=np.array(residue.center_of_mass()), positions=uas.positions, masses=ua_masses, dimensions=data_container.dimensions[:3], ) rot_axes, moment_of_inertia = self.get_custom_principal_axes(moi_tensor) trans_axes = rot_axes # per original convention + rot_center = np.array(residue.center_of_mass()) else: - # If bonded to other residues, use default axes and MOI. + # If bonded to other residues, use local axes. make_whole(data_container.atoms) trans_axes = data_container.atoms.principal_axes() - rot_axes, moment_of_inertia = self.get_vanilla_axes(residue) - center = residue.center_of_mass(unwrap=True) - - return trans_axes, rot_axes, center, moment_of_inertia + residue = data_container.residues[index] + if len(edge_atom_set) == 1: + if index == 0: + # first residue + # use first heavy atom + edges = [residue.atoms[0], edge_atom_set[0]] + backbone = self.get_chain( + residue, residue.atoms[0], edge_atom_set[0] + ) + else: + # last residue + last_index = len(uas) - 1 + last = None + # look for last heavy atom + # with only one bond to another + while last_index > 0 and last is None: + heavy_atom = uas[last_index] + bonded_atoms = residue.atoms.select_atoms( + f"(mass 2 to 999) and bonded index {heavy_atom.index}" + ) + if len(bonded_atoms) == 1: + last = heavy_atom + else: + last_index -= 1 + edges = [edge_atom_set[0], last] + backbone = self.get_chain(residue, edge_atom_set[0], last) + else: + # residue has two bonds to other residues + edges = [edge_atom_set[0], edge_atom_set[1]] + backbone = self.get_chain(residue, edge_atom_set[0], edge_atom_set[1]) + # get edge atoms of the residue + # for terminal residues, this will include the C/N terminus + backbone_center = np.zeros(3) + for heavy_atom in backbone: + backbone_center += heavy_atom.position + backbone_center = backbone_center / len(backbone) + rot_center, rot_axes = self.get_residue_custom_axes(edges, backbone_center) + + moment_of_inertia = self.get_custom_residue_moment_of_inertia( + center_of_mass=rot_center, + positions=uas.positions, + masses=ua_masses, + custom_rot_axes=rot_axes, + dimensions=data_container.dimensions[:3], + ) + return trans_axes, rot_axes, rot_center, moment_of_inertia - def get_UA_axes(self, data_container, index: int): + def get_UA_axes(self, data_container, index: int, res_position): """Compute united-atom-level translational and rotational axes. The translational and rotational axes at the united-atom level. @@ -143,7 +192,12 @@ def get_UA_axes(self, data_container, index: int): This preserves the original behaviour and its rationale: - Translational axes: - Use the same custom principal-axes approach as residue level: + Use the same approach as residue level rotational. + Identify residue of interest and neighbours, then select + edge heavy atoms (i.e. heavy atoms bonded to neighbour residues) + and find the shortest chain between them: the backbone. Edge + atoms + backbone COM are used to determine UA translational axes + (see get_residue_custom_axes) compute a custom MOI tensor using heavy-atom coordinates but UA masses (heavy + bonded H masses), then compute the principal axes from it. @@ -158,7 +212,8 @@ def get_UA_axes(self, data_container, index: int): Molecule and trajectory data. index (int): Bead index (ordinal among heavy atoms). - + res_position: where the residue of interest is + in data_container Returns: Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: - trans_axes: Translational axes (3, 3). @@ -170,54 +225,173 @@ def get_UA_axes(self, data_container, index: int): IndexError: If `index` does not correspond to an existing heavy atom. ValueError: - If bonded-axis construction fails. + If axis construction fails. """ - index = int(index) # bead index - + heavy_atoms = data_container.select_atoms("mass 2 to 999") # use the same customPI trans axes as the residue level - heavy_atoms = data_container.select_atoms("prop mass > 1.1") if len(heavy_atoms) > 1: - UA_masses = self.get_UA_masses(data_container.atoms) - center = data_container.atoms.center_of_mass(unwrap=True) - moment_of_inertia_tensor = self.get_moment_of_inertia_tensor( - center, heavy_atoms.positions, UA_masses, data_container.dimensions[:3] - ) - trans_axes, _moment_of_inertia = self.get_custom_principal_axes( - moment_of_inertia_tensor + if len(data_container.residues) == 1: + # only the one residue => use principal axes + residue = data_container + trans_center = data_container.atoms.center_of_mass(unwrap=True) + trans_axes = data_container.atoms.principal_axes() + else: + # residue of interest has at least one neighbour + if res_position == -1: + residue = data_container.residues[0] + index_next = residue.resid + 1 + # the .resid attribute gives 1-indexing + # substract 1 to match indexing later + second_edge = data_container.select_atoms( + f"resindex {residue.resid - 1} and " + f"bonded resindex {index_next - 1}" + ) + edges = [residue.atoms[0], second_edge.atoms[0]] + backbone = self.get_chain( + residue, residue.atoms[0], second_edge.atoms[0] + ) + + elif res_position == 0: + # between 2 residues + residue = data_container.residues[1] + index_prev = residue.resid - 1 + index_next = residue.resid + 1 + edge_set = data_container.select_atoms( + f"resindex {residue.resid - 1} and " + f"(bonded resindex {index_next - 1} or " + f"resindex {index_prev - 1})" + ) + edges = [edge_set[0], edge_set[1]] + backbone = self.get_chain(residue, edge_set[0], edge_set[1]) + + else: + # last resid + residue = data_container.residues[1] + index_prev = residue.resid - 1 + first_edge = data_container.select_atoms( + f"resindex {residue.resid - 1} and " + f"bonded resindex {index_prev - 1}" + ) + last_index = len(heavy_atoms) - 1 + last = None + # look for last heavy atom + # with only one bond to another + while last_index > 0 and last is None: + heavy_atom = heavy_atoms[last_index] + bonded_atoms = residue.atoms.select_atoms( + f"(mass 2 to 999) and bonded index {heavy_atom.index}" + ) + if len(bonded_atoms) == 1: + last = heavy_atom + else: + last_index -= 1 + + edges = [first_edge.atoms[0], last] + backbone = self.get_chain(residue, first_edge.atoms[0], last) + + backbone_center = np.zeros(3) + for heavy_atom in backbone: + backbone_center += heavy_atom.position + backbone_center = backbone_center / len(backbone) + + trans_center, trans_axes = self.get_residue_custom_axes( + edges, backbone_center + ) + + residue_heavy_atoms = residue.atoms.select_atoms("mass 2 to 999") + # look for heavy atoms in residue of interest + heavy_atom_indices = [] + for atom in residue_heavy_atoms: + heavy_atom_indices.append(atom.index) + # we find the nth heavy atom + # where n is the bead index + heavy_atom_index = heavy_atom_indices[index] + heavy_atom = residue.atoms.select_atoms(f"index {heavy_atom_index}") + rot_center = heavy_atom.positions[0] + rot_axes, moment_of_inertia = self.get_bonded_axes( + system=data_container, + atom=heavy_atom[0], + dimensions=data_container.dimensions[:3], ) + else: - # use standard PA for UA not bonded to anything else - make_whole(data_container.atoms) - trans_axes = data_container.atoms.principal_axes() + # 1 heavy atom in the data_container + heavy_atom = heavy_atoms[0] + # trans and rot centres are centre of mass + rot_center = data_container.center_of_mass() + rot_axes, moment_of_inertia = self.get_bonded_axes( + system=data_container, + atom=heavy_atom, + dimensions=data_container.dimensions[:3], + ) + trans_center = rot_center + # principal axes + trans_axes = rot_axes + + if trans_axes is None: + raise ValueError("Unable to compute translation axes for UA bead.") - # look for heavy atoms in residue of interest - heavy_atom_indices = [] - for atom in heavy_atoms: - heavy_atom_indices.append(atom.index) - # we find the nth heavy atom - # where n is the bead index - heavy_atom_index = heavy_atom_indices[index] - heavy_atom = data_container.select_atoms(f"index {heavy_atom_index}") - - center = heavy_atom.positions[0] - rot_axes, moment_of_inertia = self.get_bonded_axes( - system=data_container, - atom=heavy_atom[0], - dimensions=data_container.dimensions[:3], - ) if rot_axes is None or moment_of_inertia is None: raise ValueError("Unable to compute bonded axes for UA bead.") - logger.debug(f"Translational Axes: {trans_axes}") - logger.debug(f"Rotational Axes: {rot_axes}") - logger.debug(f"Center: {center}") - logger.debug(f"Moment of Inertia: {moment_of_inertia}") + logger.debug("Translational Axes: %s", trans_axes) + logger.debug("Rotational Axes: %s", rot_axes) + logger.debug("Translational center: %s", trans_center) + logger.debug("Rotational center: %s", rot_center) + logger.debug("Moment of Inertia: %s", moment_of_inertia) + + return trans_axes, rot_axes, rot_center, moment_of_inertia + + def get_residue_custom_axes(self, edges, center): + """ + Compute rotation axes at the residue level, given + two edge atoms of the residue (E1+E2), + and the centre of geometry of backbone atoms + that are not edges (C). + x axis is O-E1 + y axis is O-C (perpendicular to O-E1 in the + same plane as E2) + z axis is perpendicular to the two other axes + + :: + + C + | + | + E1 ---- O --- E2 + + Args: + edges: (2,3) positions of two edge atoms + center: (3,) coordinates of the inner backbone + centre of geometry - return trans_axes, rot_axes, center, moment_of_inertia + Returns: + rot_center: (3,) rotation centre, + lies on the E1-E2 vector + rot_axes: (3,3) rotation axes of residue + """ + # x axis is O-E1 + E1C_vector = center - edges[0].position + # look for projection of E1-O onto E1-E2 (E1-C) + E1E2_vector = edges[1].position - edges[0].position + E1O_vector = ( + np.dot(E1E2_vector, E1C_vector) / (np.linalg.norm(E1E2_vector) ** 2) + ) * E1E2_vector + x_axis = -E1O_vector + # O-C = O-E1 + E1-C + OC_vector = -E1O_vector + E1C_vector + y_axis = OC_vector + z_axis = np.cross(x_axis, y_axis) + x_axis /= np.linalg.norm(x_axis) + y_axis /= np.linalg.norm(y_axis) + z_axis /= np.linalg.norm(z_axis) + rot_axes = np.array([x_axis, y_axis, z_axis]) + rot_center = E1O_vector + edges[0].position + return rot_center, rot_axes def get_bonded_axes(self, system, atom, dimensions: np.ndarray): - r"""Compute UA rotational axes from bonded topology around a heavy atom. + """Compute UA rotational axes from bonded topology around a heavy atom. For a given heavy atom, use its bonded atoms to get the axes for rotating forces around. Few cases for choosing united atom axes, which are dependent @@ -446,6 +620,41 @@ def get_custom_axes( scaled_custom_axes = unscaled_custom_axes / mod[:, np.newaxis] return scaled_custom_axes + def get_custom_residue_moment_of_inertia( + self, + center_of_mass: np.ndarray, + positions: np.ndarray, + masses: np.ndarray, + custom_rot_axes: np.ndarray, + dimensions: np.ndarray, + ): + """ + Compute moment of inertia around custom axes for a bead + formed of multiple UAs. + + Args: + center_of_mass: (3, ) COM for bead + positions: (N,3) positions of the UAs in the bead + masses: (N,) masses of the UAs in the bead + custom_rot_axes: (3,3) array of residue rotation axes + dimensions: (3,) simulation_box_dimensions + + Returns: + np.ndarray: (3,) moment of inertia array. + + """ + + translated_coords = self.get_vector(center_of_mass, positions, dimensions) + custom_moment_of_inertia = np.zeros(3, dtype=float) + + for coord, mass in zip(translated_coords, masses, strict=True): + axis_component = np.sum( + np.cross(custom_rot_axes, coord) ** 2 * mass, axis=1 + ) + custom_moment_of_inertia += axis_component + + return custom_moment_of_inertia + def get_custom_moment_of_inertia( self, UA, @@ -567,7 +776,6 @@ def get_moment_of_inertia_tensor( """ r = self.get_vector(center_of_mass, positions, dimensions) r2 = np.sum(r**2, axis=1) - masses_arr = np.asarray(list(masses), dtype=float) moment_of_inertia_tensor = np.eye(3) * np.sum(masses_arr * r2) moment_of_inertia_tensor -= np.einsum("i,ij,ik->jk", masses_arr, r, r) @@ -599,6 +807,7 @@ def get_custom_principal_axes( - principal_axes: (3, 3) principal axes (rows). - moment_of_inertia: (3,) principal moments. """ + eigenvalues, eigenvectors = np.linalg.eig(moment_of_inertia_tensor) order = np.abs(eigenvalues).argsort()[::-1] # descending order transposed = np.transpose(eigenvectors) # columns -> rows @@ -636,3 +845,78 @@ def get_UA_masses(self, molecule) -> list[float]: ua_mass += float(h.mass) ua_masses.append(ua_mass) return ua_masses + + def get_chain(self, residue, first, last): + """ + For a given MDAnalysis AtomGroup and two given heavy atoms + within that AtomGroup, return the + shortest path between the two atoms. + + Args: + residue: MDAnalysis AtomGroup representing + the residue/monomer of interest. + first: First heavy atom in the chain + last: Last heavy atom in the chain + + Returns: + chain: MDAnalysis AtomGroup containing chain atoms. + """ + chain = [] + chain_indices = [] + # at the beggining we've only visited the first atom + visited_dict = {first: True} + # keep the previous atom to trace back the path + prev = {} + # queue of next heavy atoms to visit + next_to_visit = [first] + # all others heavy atoms in the residue, we have not yet visited + remaining_heavy_atoms = residue.atoms.select_atoms( + f"(mass 2 to 999) and not index {first.index}" + ) + for atom in remaining_heavy_atoms: + visited_dict[atom] = False + current = first + while not visited_dict[last]: + # we haven't found a path to the last residue + next_to_visit.pop(0) + # we're visiting the current atom => we remove it from the queue + bonded_atoms = residue.atoms.select_atoms( + f"(mass 2 to 999) and bonded index {current.index}" + ) + if last in bonded_atoms: + # we found a path to the last atom + visited_dict[last] = True + chain.append(last) + prev[last] = current + else: + for bonded_atom in bonded_atoms: + # look for unvisited bonded atoms to the current atom we're visiting + if not visited_dict[bonded_atom]: + # we're going to want to visit the atoms + next_to_visit.append(bonded_atom) + prev[bonded_atom] = current + # we visit the next atom in the queue + current = next_to_visit[0] + visited_dict[current] = True + + # we track the previous atom back to the first atom now + current = last + chain = [last] + # subtract index of first atom in resid + # most likely will coincide with first + # but this will work even if it doesn't + # accout for in-residue index + chain_indices = [last.index - residue.atoms.indices[0]] + # start from last atom in chain + while chain[-1] != first: + # we haven't yet returned to the first atom + current = prev[current] + chain.append(current) + chain_indices.append(current.index - residue.atoms.indices[0]) + chain_indices = np.flip(chain_indices) + # only get in between residues + chain_indices = chain_indices[1:-1] + # accout for in-residue index + chain_AtomGroup = residue.atoms[chain_indices] + chain = chain_AtomGroup.atoms.select_atoms("all") + return chain diff --git a/CodeEntropy/levels/nodes/covariance.py b/CodeEntropy/levels/nodes/covariance.py index 4331cc6a..38ec3d1c 100644 --- a/CodeEntropy/levels/nodes/covariance.py +++ b/CodeEntropy/levels/nodes/covariance.py @@ -197,7 +197,30 @@ def _process_united_atom( out_torque: Frame-local torque second-moment accumulator, mutated in place. molcount: Per-residue group sample counters, mutated in place. """ + for local_res_i, res in enumerate(mol.residues): + if len(mol.residues) > 1: + # there are multiple residues in the molecule + # build residue group here + if local_res_i == 0: + # first residue + res_position = -1 + res_next = mol.residues[1] + residue_group = res + res_next + elif local_res_i == len(mol.residues) - 1: + # last residue + res_position = 1 + res_prev = mol.residues[-2] + residue_group = res + res_prev + else: + res_position = 0 + res_prev = mol.residues[local_res_i - 1] + res_next = mol.residues[local_res_i + 1] + residue_group = res_prev + res + res_next + else: + # only one residue + res_position = None + residue_group = res bead_key = (mol_id, "united_atom", local_res_i) bead_idx_list = beads.get(bead_key, []) if not bead_idx_list: @@ -208,13 +231,14 @@ def _process_united_atom( continue force_vecs, torque_vecs = self._build_ua_vectors( - residue_atoms=res.atoms, + residue_group=residue_group.atoms, bead_groups=bead_groups, axes_manager=axes_manager, box=box, force_partitioning=force_partitioning, customised_axes=customised_axes, is_highest=is_highest, + res_position=res_position, ) F, T = self._ft.compute_frame_covariance(force_vecs, torque_vecs) @@ -389,23 +413,26 @@ def _build_ua_vectors( self, *, bead_groups: list[Any], - residue_atoms: Any, + residue_group: Any, axes_manager: Any, box: np.ndarray | None, force_partitioning: float, customised_axes: bool, is_highest: bool, + res_position: int, ) -> tuple[list[np.ndarray], list[np.ndarray]]: """Build force and torque vectors for united-atom beads. Args: - bead_groups: Atom groups representing UA beads in a residue. - residue_atoms: Atom group for the parent residue. - axes_manager: Axes helper used to select axes, centres, and moments. - box: Optional periodic box vector. - force_partitioning: Force partitioning factor for highest-level vectors. - customised_axes: Whether customised UA axes should be used. - is_highest: Whether UA is the highest active level. + bead_groups: List of UA bead AtomGroups for the residue. + residue_group: AtomGroup for the residue group atoms. + axes_manager: Axes manager used to determine axes/centers/MOI. + box: Optional box vector used for PBC-aware displacements. + force_partitioning: Force scaling factor applied at highest level. + customised_axes: Whether to use customised axes methods when available. + is_highest: Whether UA level is the highest level for the molecule. + res_position: Where the residue is in the residue group + Returns: A tuple containing lists of force vectors and torque vectors. @@ -416,13 +443,21 @@ def _build_ua_vectors( for ua_i, bead in enumerate(bead_groups): if customised_axes: trans_axes, rot_axes, center, moi = axes_manager.get_UA_axes( - residue_atoms, ua_i + residue_group, ua_i, res_position ) else: - make_whole(residue_atoms) + make_whole(residue_group) make_whole(bead) - - trans_axes = residue_atoms.principal_axes() + if res_position == -1: + # first residue in group + residue = residue_group.residues[0] + elif res_position == 0 or res_position == 1: + # middle or last residue => second in group + residue = residue_group.residues[1] + else: + # res_position is None bc there is only one residue + residue = residue_group + trans_axes = residue.atoms.principal_axes() rot_axes, moi = axes_manager.get_vanilla_axes(bead) center = bead.center_of_mass(unwrap=True) diff --git a/tests/regression/baselines/benzaldehyde/combined_forcetorque_false.json b/tests/regression/baselines/benzaldehyde/combined_forcetorque_false.json index a5d1af0e..27025e62 100644 --- a/tests/regression/baselines/benzaldehyde/combined_forcetorque_false.json +++ b/tests/regression/baselines/benzaldehyde/combined_forcetorque_false.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 0.07119323721997475, + "united_atom:Transvibrational": 0.08982962903796131, "united_atom:Rovibrational": 49.68669738152346, "residue:Transvibrational": 69.48692941204929, "residue:Rovibrational": 68.46147102540942, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 20.481571492615355 }, - "total": 208.1878625488175 + "total": 208.2064989406355 } } } diff --git a/tests/regression/baselines/benzaldehyde/default.json b/tests/regression/baselines/benzaldehyde/default.json index c99a2d15..1ed1a4e7 100644 --- a/tests/regression/baselines/benzaldehyde/default.json +++ b/tests/regression/baselines/benzaldehyde/default.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 24.88518233240474, + "united_atom:Transvibrational": 24.869562693152986, "united_atom:Rovibrational": 27.950376507672583, "residue:FTmat-Transvibrational": 71.03412922724692, "residue:FTmat-Rovibrational": 59.44169664956799, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 59.43920971558428 }, - "total": 250.27323833217878 + "total": 250.25761869292705 } } } diff --git a/tests/regression/baselines/benzaldehyde/frame_window.json b/tests/regression/baselines/benzaldehyde/frame_window.json index 70bb2766..27225723 100644 --- a/tests/regression/baselines/benzaldehyde/frame_window.json +++ b/tests/regression/baselines/benzaldehyde/frame_window.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 40.30267601961045, + "united_atom:Transvibrational": 41.75648599130188, "united_atom:Rovibrational": 38.21906858443615, "residue:FTmat-Transvibrational": 73.41098578352612, "residue:FTmat-Rovibrational": 57.881504393660364, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 20.481571492615355 }, - "total": 230.29580627384846 + "total": 231.74961624553984 } } } diff --git a/tests/regression/baselines/benzaldehyde/rad.json b/tests/regression/baselines/benzaldehyde/rad.json index 8e39e21b..02d56d59 100644 --- a/tests/regression/baselines/benzaldehyde/rad.json +++ b/tests/regression/baselines/benzaldehyde/rad.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 24.88518233240474, + "united_atom:Transvibrational": 24.869562693152986, "united_atom:Rovibrational": 27.950376507672583, "residue:FTmat-Transvibrational": 71.03412922724692, "residue:FTmat-Rovibrational": 59.44169664956799, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 25.502722133228936 }, - "total": 216.33675074982344 + "total": 216.32113111057168 } } } diff --git a/tests/regression/baselines/benzaldehyde/selection_subset.json b/tests/regression/baselines/benzaldehyde/selection_subset.json index 6d50b1a7..c7750ebb 100644 --- a/tests/regression/baselines/benzaldehyde/selection_subset.json +++ b/tests/regression/baselines/benzaldehyde/selection_subset.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 0.07119323721997475, + "united_atom:Transvibrational": 0.08982962903796131, "united_atom:Rovibrational": 49.68669738152346, "residue:FTmat-Transvibrational": 87.43527331108173, "residue:FTmat-Rovibrational": 61.67126452972779, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 20.481571492615355 }, - "total": 219.34599995216834 + "total": 219.3646363439863 } } } diff --git a/tests/regression/baselines/benzene/combined_forcetorque_off.json b/tests/regression/baselines/benzene/combined_forcetorque_off.json index 16b5e375..ee2c41fc 100644 --- a/tests/regression/baselines/benzene/combined_forcetorque_off.json +++ b/tests/regression/baselines/benzene/combined_forcetorque_off.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 0.16311383522946216, + "united_atom:Transvibrational": 0.17824017761231503, "united_atom:Rovibrational": 40.695812407899396, "residue:Transvibrational": 57.59675197041957, "residue:Rovibrational": 52.85496348419672, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 0.0 }, - "total": 151.31064169774515 + "total": 151.325768040128 } } } diff --git a/tests/regression/baselines/benzene/default.json b/tests/regression/baselines/benzene/default.json index 86ae25d0..de6eebc0 100644 --- a/tests/regression/baselines/benzene/default.json +++ b/tests/regression/baselines/benzene/default.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 9.081853431559052, + "united_atom:Transvibrational": 9.050489789631982, "united_atom:Rovibrational": 27.534380126250227, "residue:FTmat-Transvibrational": 72.66211800013413, "residue:FTmat-Rovibrational": 59.93761874375924, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 41.58427729275938 }, - "total": 210.800247594462 + "total": 210.76888395253496 } } } diff --git a/tests/regression/baselines/benzene/frame_window.json b/tests/regression/baselines/benzene/frame_window.json index c1ffd000..0f692cbb 100644 --- a/tests/regression/baselines/benzene/frame_window.json +++ b/tests/regression/baselines/benzene/frame_window.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 11.46552036084548, + "united_atom:Transvibrational": 11.552833417413368, "united_atom:Rovibrational": 34.98492056748493, "residue:FTmat-Transvibrational": 71.83491878606151, "residue:FTmat-Rovibrational": 55.6098400281744, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 0.0 }, - "total": 173.89519974256632 + "total": 173.9825127991342 } } } diff --git a/tests/regression/baselines/benzene/rad.json b/tests/regression/baselines/benzene/rad.json index c4aca55f..2ccf3306 100644 --- a/tests/regression/baselines/benzene/rad.json +++ b/tests/regression/baselines/benzene/rad.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 9.081853431559052, + "united_atom:Transvibrational": 9.050489789631982, "united_atom:Rovibrational": 27.534380126250227, "residue:FTmat-Transvibrational": 72.66211800013413, "residue:FTmat-Rovibrational": 59.93761874375924, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 12.386543820026672 }, - "total": 181.6025141217293 + "total": 181.57115047980224 } } } diff --git a/tests/regression/baselines/benzene/selection_subset.json b/tests/regression/baselines/benzene/selection_subset.json index ff2d09b5..807d8c05 100644 --- a/tests/regression/baselines/benzene/selection_subset.json +++ b/tests/regression/baselines/benzene/selection_subset.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 0.16311383522946216, + "united_atom:Transvibrational": 0.17824017761231503, "united_atom:Rovibrational": 40.695812407899396, "residue:FTmat-Transvibrational": 71.15771063929333, "residue:FTmat-Rovibrational": 47.26253953880574, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 0.0 }, - "total": 159.27917642122793 + "total": 159.2943027636108 } } } diff --git a/tests/regression/baselines/cyclohexane/combined_forcetorque_off.json b/tests/regression/baselines/cyclohexane/combined_forcetorque_off.json index a548349d..56de2915 100644 --- a/tests/regression/baselines/cyclohexane/combined_forcetorque_off.json +++ b/tests/regression/baselines/cyclohexane/combined_forcetorque_off.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 0.5949308536734588, + "united_atom:Transvibrational": 0.6825851535582973, "united_atom:Rovibrational": 24.234154676578637, "residue:Transvibrational": 69.9872567772153, "residue:Rovibrational": 68.68521019685565, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 0.0 }, - "total": 163.50155250432303 + "total": 163.5892068042079 } } } diff --git a/tests/regression/baselines/cyclohexane/default.json b/tests/regression/baselines/cyclohexane/default.json index c0233178..e7867e50 100644 --- a/tests/regression/baselines/cyclohexane/default.json +++ b/tests/regression/baselines/cyclohexane/default.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 11.726471858700231, + "united_atom:Transvibrational": 11.65610486557721, "united_atom:Rovibrational": 47.71088602161552, "residue:FTmat-Transvibrational": 70.3922327806972, "residue:FTmat-Rovibrational": 63.44920824648768, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 47.54362774624537 }, - "total": 242.11130586044152 + "total": 242.0409388673185 } } } diff --git a/tests/regression/baselines/cyclohexane/frame_window.json b/tests/regression/baselines/cyclohexane/frame_window.json index d21d437d..dd423267 100644 --- a/tests/regression/baselines/cyclohexane/frame_window.json +++ b/tests/regression/baselines/cyclohexane/frame_window.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 17.398382397359153, + "united_atom:Transvibrational": 16.605273867798914, "united_atom:Rovibrational": 73.96792995794405, "residue:FTmat-Transvibrational": 76.4267996157354, "residue:FTmat-Rovibrational": 63.30469126284744, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 0.0 }, - "total": 231.09780323388605 + "total": 230.3046947043258 } } } diff --git a/tests/regression/baselines/cyclohexane/rad.json b/tests/regression/baselines/cyclohexane/rad.json index f65d9a4c..8de06e5b 100644 --- a/tests/regression/baselines/cyclohexane/rad.json +++ b/tests/regression/baselines/cyclohexane/rad.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 11.726471858700231, + "united_atom:Transvibrational": 11.65610486557721, "united_atom:Rovibrational": 47.71088602161552, "residue:FTmat-Transvibrational": 70.3922327806972, "residue:FTmat-Rovibrational": 63.44920824648768, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 14.049324060636614 }, - "total": 208.61700217483278 + "total": 208.54663518170975 } } } diff --git a/tests/regression/baselines/cyclohexane/selection_subset.json b/tests/regression/baselines/cyclohexane/selection_subset.json index b1a14443..a1a37145 100644 --- a/tests/regression/baselines/cyclohexane/selection_subset.json +++ b/tests/regression/baselines/cyclohexane/selection_subset.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 0.5949308536734588, + "united_atom:Transvibrational": 0.6825851535582973, "united_atom:Rovibrational": 24.234154676578637, "residue:FTmat-Transvibrational": 84.37184730911717, "residue:FTmat-Rovibrational": 59.52377096811085, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 0.0 }, - "total": 168.72470380748013 + "total": 168.81235810736496 } } } diff --git a/tests/regression/baselines/dna/combined_forcetorque_off.json b/tests/regression/baselines/dna/combined_forcetorque_off.json index e867cee1..5e724622 100644 --- a/tests/regression/baselines/dna/combined_forcetorque_off.json +++ b/tests/regression/baselines/dna/combined_forcetorque_off.json @@ -2,17 +2,17 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 0.0, + "united_atom:Transvibrational": 4.762281610623415e-20, "united_atom:Rovibrational": 0.002160679012128457, "residue:Transvibrational": 0.0, - "residue:Rovibrational": 3.376800684085249, + "residue:Rovibrational": 6.633599673254765, "polymer:Transvibrational": 21.18266215491188, "polymer:Rovibrational": 12.837576042626923, "united_atom:Conformational": 0.0, "residue:Conformational": 0.0, "polymer:Orientational": 4.758905336627712 }, - "total": 42.1581048972639 + "total": 45.41490388643341 }, "1": { "components": { diff --git a/tests/regression/baselines/dna/default.json b/tests/regression/baselines/dna/default.json index 2cbef740..7a2b6c3a 100644 --- a/tests/regression/baselines/dna/default.json +++ b/tests/regression/baselines/dna/default.json @@ -2,17 +2,17 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 0.0, + "united_atom:Transvibrational": 4.762281610623415e-20, "united_atom:Rovibrational": 0.002160679012128457, "residue:Transvibrational": 0.0, - "residue:Rovibrational": 3.376800684085249, + "residue:Rovibrational": 6.633599673254765, "polymer:FTmat-Transvibrational": 12.341104347192612, "polymer:FTmat-Rovibrational": 0.0, "united_atom:Conformational": 0.0, "residue:Conformational": 0.0, "polymer:Orientational": 4.758905336627712 }, - "total": 20.478971046917703 + "total": 23.735770036087217 }, "1": { "components": { diff --git a/tests/regression/baselines/dna/frame_window.json b/tests/regression/baselines/dna/frame_window.json index c35d2211..fd24e0e2 100644 --- a/tests/regression/baselines/dna/frame_window.json +++ b/tests/regression/baselines/dna/frame_window.json @@ -5,18 +5,18 @@ "united_atom:Transvibrational": 0.0, "united_atom:Rovibrational": 1.5821720528374943, "residue:Transvibrational": 0.0, - "residue:Rovibrational": 27.397449238560412, + "residue:Rovibrational": 35.89784662172834, "polymer:FTmat-Transvibrational": 48.62026970762269, "polymer:FTmat-Rovibrational": 0.0, "united_atom:Conformational": 10.584542990557836, "residue:Conformational": 0.0, "polymer:Orientational": 4.758905336627712 }, - "total": 92.94333932620614 + "total": 101.44373670937406 }, "1": { "components": { - "united_atom:Transvibrational": 0.0, + "united_atom:Transvibrational": 5.359713875687138e-10, "united_atom:Rovibrational": 2.5277936366208014, "residue:Transvibrational": 0.0, "residue:Rovibrational": 24.80670067454149, @@ -26,7 +26,7 @@ "residue:Conformational": 0.0, "polymer:Orientational": 4.758905336627712 }, - "total": 97.85965049646045 + "total": 97.85965049699642 } } } diff --git a/tests/regression/baselines/dna/grouping_each.json b/tests/regression/baselines/dna/grouping_each.json index 2cbef740..7a2b6c3a 100644 --- a/tests/regression/baselines/dna/grouping_each.json +++ b/tests/regression/baselines/dna/grouping_each.json @@ -2,17 +2,17 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 0.0, + "united_atom:Transvibrational": 4.762281610623415e-20, "united_atom:Rovibrational": 0.002160679012128457, "residue:Transvibrational": 0.0, - "residue:Rovibrational": 3.376800684085249, + "residue:Rovibrational": 6.633599673254765, "polymer:FTmat-Transvibrational": 12.341104347192612, "polymer:FTmat-Rovibrational": 0.0, "united_atom:Conformational": 0.0, "residue:Conformational": 0.0, "polymer:Orientational": 4.758905336627712 }, - "total": 20.478971046917703 + "total": 23.735770036087217 }, "1": { "components": { diff --git a/tests/regression/baselines/dna/selection_subset.json b/tests/regression/baselines/dna/selection_subset.json index 2cbef740..7a2b6c3a 100644 --- a/tests/regression/baselines/dna/selection_subset.json +++ b/tests/regression/baselines/dna/selection_subset.json @@ -2,17 +2,17 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 0.0, + "united_atom:Transvibrational": 4.762281610623415e-20, "united_atom:Rovibrational": 0.002160679012128457, "residue:Transvibrational": 0.0, - "residue:Rovibrational": 3.376800684085249, + "residue:Rovibrational": 6.633599673254765, "polymer:FTmat-Transvibrational": 12.341104347192612, "polymer:FTmat-Rovibrational": 0.0, "united_atom:Conformational": 0.0, "residue:Conformational": 0.0, "polymer:Orientational": 4.758905336627712 }, - "total": 20.478971046917703 + "total": 23.735770036087217 }, "1": { "components": { diff --git a/tests/regression/baselines/ethyl-acetate/combined_forcetorque_off.json b/tests/regression/baselines/ethyl-acetate/combined_forcetorque_off.json index 8c68cce7..499fca4c 100644 --- a/tests/regression/baselines/ethyl-acetate/combined_forcetorque_off.json +++ b/tests/regression/baselines/ethyl-acetate/combined_forcetorque_off.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 1.196367074472673, + "united_atom:Transvibrational": 0.8081103094129065, "united_atom:Rovibrational": 82.36455154278131, "residue:Transvibrational": 64.68750154134017, "residue:Rovibrational": 58.903938937880085, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 0.0 }, - "total": 215.05334534012698 + "total": 214.6650885750672 } } } diff --git a/tests/regression/baselines/ethyl-acetate/default.json b/tests/regression/baselines/ethyl-acetate/default.json index 077cdbe3..a98d4af8 100644 --- a/tests/regression/baselines/ethyl-acetate/default.json +++ b/tests/regression/baselines/ethyl-acetate/default.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 19.703248485425714, + "united_atom:Transvibrational": 19.67356252280246, "united_atom:Rovibrational": 49.35007067210558, "residue:FTmat-Transvibrational": 67.91350627765567, "residue:FTmat-Rovibrational": 60.042233035077246, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 65.33877737416202 }, - "total": 270.52337372549465 + "total": 270.4936877628714 } } } diff --git a/tests/regression/baselines/ethyl-acetate/frame_window.json b/tests/regression/baselines/ethyl-acetate/frame_window.json index be566d07..911a2667 100644 --- a/tests/regression/baselines/ethyl-acetate/frame_window.json +++ b/tests/regression/baselines/ethyl-acetate/frame_window.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 28.312711247966337, + "united_atom:Transvibrational": 29.222699118677973, "united_atom:Rovibrational": 51.99036142818903, "residue:FTmat-Transvibrational": 67.80560626717748, "residue:FTmat-Rovibrational": 55.1631201009248, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 3.8984476469128193 }, - "total": 215.80571814986257 + "total": 216.7157060205742 } } } diff --git a/tests/regression/baselines/ethyl-acetate/rad.json b/tests/regression/baselines/ethyl-acetate/rad.json index ee7df624..51bed453 100644 --- a/tests/regression/baselines/ethyl-acetate/rad.json +++ b/tests/regression/baselines/ethyl-acetate/rad.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 19.703248485425714, + "united_atom:Transvibrational": 19.67356252280246, "united_atom:Rovibrational": 49.35007067210558, "residue:FTmat-Transvibrational": 67.91350627765567, "residue:FTmat-Rovibrational": 60.042233035077246, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 30.739736508673403 }, - "total": 235.92433286000602 + "total": 235.89464689738276 } } } diff --git a/tests/regression/baselines/ethyl-acetate/selection_subset.json b/tests/regression/baselines/ethyl-acetate/selection_subset.json index 270dbbd5..dd0f2695 100644 --- a/tests/regression/baselines/ethyl-acetate/selection_subset.json +++ b/tests/regression/baselines/ethyl-acetate/selection_subset.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 1.196367074472673, + "united_atom:Transvibrational": 0.8081103094129065, "united_atom:Rovibrational": 82.36455154278131, "residue:FTmat-Transvibrational": 74.5939232239247, "residue:FTmat-Rovibrational": 55.42964192531005, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 0.0 }, - "total": 221.48547001014148 + "total": 221.09721324508172 } } } diff --git a/tests/regression/baselines/methane/combined_forcetorque_off.json b/tests/regression/baselines/methane/combined_forcetorque_off.json index 318c30c6..70be3cef 100644 --- a/tests/regression/baselines/methane/combined_forcetorque_off.json +++ b/tests/regression/baselines/methane/combined_forcetorque_off.json @@ -2,12 +2,12 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 42.51619525142699, - "united_atom:Rovibrational": 34.651932322640015, + "united_atom:Transvibrational": 42.516195251426986, + "united_atom:Rovibrational": 34.69255616696802, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 77.168127574067 + "total": 77.208751418395 } } } diff --git a/tests/regression/baselines/methane/default.json b/tests/regression/baselines/methane/default.json index d08ac60f..c6716b00 100644 --- a/tests/regression/baselines/methane/default.json +++ b/tests/regression/baselines/methane/default.json @@ -2,12 +2,12 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 40.3239711717637, - "united_atom:Rovibrational": 33.60582165153992, + "united_atom:Transvibrational": 40.32397117176369, + "united_atom:Rovibrational": 33.617646190915714, "united_atom:Conformational": 0.0, "united_atom:Orientational": 3.596676624528629 }, - "total": 77.52646944783224 + "total": 77.53829398720804 } } } diff --git a/tests/regression/baselines/methane/frame_window.json b/tests/regression/baselines/methane/frame_window.json index 9a45dc98..0f70346d 100644 --- a/tests/regression/baselines/methane/frame_window.json +++ b/tests/regression/baselines/methane/frame_window.json @@ -3,11 +3,11 @@ "0": { "components": { "united_atom:Transvibrational": 40.70376001258969, - "united_atom:Rovibrational": 33.778792396823484, + "united_atom:Rovibrational": 33.83818524319629, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 74.48255240941317 + "total": 74.54194525578598 } } } diff --git a/tests/regression/baselines/methane/grouping_each.json b/tests/regression/baselines/methane/grouping_each.json index 3b31963b..e5f74df8 100644 --- a/tests/regression/baselines/methane/grouping_each.json +++ b/tests/regression/baselines/methane/grouping_each.json @@ -3,92 +3,92 @@ "0": { "components": { "united_atom:Transvibrational": 24.315699188266926, - "united_atom:Rovibrational": 21.0483901242056, + "united_atom:Rovibrational": 21.06129596642336, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 45.36408931247253 + "total": 45.376995154690285 }, "1": { "components": { "united_atom:Transvibrational": 23.76608267046309, - "united_atom:Rovibrational": 16.769636839671296, + "united_atom:Rovibrational": 16.800440306419098, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 40.535719510134385 + "total": 40.56652297688218 }, "2": { "components": { "united_atom:Transvibrational": 24.833896219788347, - "united_atom:Rovibrational": 16.996392060962357, + "united_atom:Rovibrational": 17.0032604785275, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 41.83028828075071 + "total": 41.83715669831585 }, "3": { "components": { "united_atom:Transvibrational": 6.6723857079283215, - "united_atom:Rovibrational": 4.986376282798274, + "united_atom:Rovibrational": 4.958640584432368, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 11.658761990726596 + "total": 11.63102629236069 }, "4": { "components": { - "united_atom:Transvibrational": 6.880461178899526, - "united_atom:Rovibrational": 4.441585994100298, + "united_atom:Transvibrational": 6.880461178899524, + "united_atom:Rovibrational": 4.47005523879151, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 11.322047172999824 + "total": 11.350516417691033 }, "5": { "components": { "united_atom:Transvibrational": 15.473092273577388, - "united_atom:Rovibrational": 7.777083478334702, + "united_atom:Rovibrational": 7.7776511992146515, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 23.25017575191209 + "total": 23.25074347279204 }, "6": { "components": { "united_atom:Transvibrational": 25.694168010993888, - "united_atom:Rovibrational": 6.731392483940261, + "united_atom:Rovibrational": 6.727950082765358, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 32.425560494934146 + "total": 32.422118093759245 }, "7": { "components": { - "united_atom:Transvibrational": 10.533257828925997, - "united_atom:Rovibrational": 8.97563913301586, + "united_atom:Transvibrational": 10.533257828925999, + "united_atom:Rovibrational": 9.059251947808503, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 19.508896961941858 + "total": 19.592509776734502 }, "8": { "components": { "united_atom:Transvibrational": 7.332978272264879, - "united_atom:Rovibrational": 3.0418502362906086, + "united_atom:Rovibrational": 3.084945359076361, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 10.374828508555488 + "total": 10.417923631341239 }, "9": { "components": { "united_atom:Transvibrational": 4.023932761002867, - "united_atom:Rovibrational": 8.289324383636089, + "united_atom:Rovibrational": 8.271395156034108, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 12.313257144638957 + "total": 12.295327917036975 } } } diff --git a/tests/regression/baselines/methane/rad.json b/tests/regression/baselines/methane/rad.json index df8fbbd7..2b506858 100644 --- a/tests/regression/baselines/methane/rad.json +++ b/tests/regression/baselines/methane/rad.json @@ -2,12 +2,12 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 40.3239711717637, - "united_atom:Rovibrational": 33.60582165153992, + "united_atom:Transvibrational": 40.32397117176369, + "united_atom:Rovibrational": 33.617646190915714, "united_atom:Conformational": 0.0, "united_atom:Orientational": 6.667209510980459 }, - "total": 80.59700233428407 + "total": 80.60882687365986 } } } diff --git a/tests/regression/baselines/methane/selection_subset.json b/tests/regression/baselines/methane/selection_subset.json index 318c30c6..70be3cef 100644 --- a/tests/regression/baselines/methane/selection_subset.json +++ b/tests/regression/baselines/methane/selection_subset.json @@ -2,12 +2,12 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 42.51619525142699, - "united_atom:Rovibrational": 34.651932322640015, + "united_atom:Transvibrational": 42.516195251426986, + "united_atom:Rovibrational": 34.69255616696802, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 77.168127574067 + "total": 77.208751418395 } } } diff --git a/tests/regression/baselines/octonol/combined_forcetorque_off.json b/tests/regression/baselines/octonol/combined_forcetorque_off.json index 920589a7..362cd1c2 100644 --- a/tests/regression/baselines/octonol/combined_forcetorque_off.json +++ b/tests/regression/baselines/octonol/combined_forcetorque_off.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 0.34382967782781193, + "united_atom:Transvibrational": 0.2907129992470817, "united_atom:Rovibrational": 19.154228264604278, "residue:Transvibrational": 74.72816183790984, "residue:Rovibrational": 60.84390144550801, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 25.79114991860739 }, - "total": 197.70076468713353 + "total": 197.64764800855278 } } } diff --git a/tests/regression/baselines/octonol/default.json b/tests/regression/baselines/octonol/default.json index fdd22382..76b4b259 100644 --- a/tests/regression/baselines/octonol/default.json +++ b/tests/regression/baselines/octonol/default.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 37.860034170693694, + "united_atom:Transvibrational": 37.90014130683313, "united_atom:Rovibrational": 84.2608785308744, "residue:FTmat-Transvibrational": 66.13571365167344, "residue:FTmat-Rovibrational": 57.090651827515686, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 74.78356386019003 }, - "total": 354.36024401601327 + "total": 354.4003511521527 } } } diff --git a/tests/regression/baselines/octonol/frame_window.json b/tests/regression/baselines/octonol/frame_window.json index 5c07dcc2..3fcdaef3 100644 --- a/tests/regression/baselines/octonol/frame_window.json +++ b/tests/regression/baselines/octonol/frame_window.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 65.86600728016141, + "united_atom:Transvibrational": 68.20033834493445, "united_atom:Rovibrational": 162.26463085986236, "residue:FTmat-Transvibrational": 74.84326467422125, "residue:FTmat-Rovibrational": 60.95710412746361, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 25.79114991860739 }, - "total": 406.37330124036134 + "total": 408.7076323051344 } } } diff --git a/tests/regression/baselines/octonol/rad.json b/tests/regression/baselines/octonol/rad.json index c2c20839..1d294585 100644 --- a/tests/regression/baselines/octonol/rad.json +++ b/tests/regression/baselines/octonol/rad.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 37.860034170693694, + "united_atom:Transvibrational": 37.90014130683313, "united_atom:Rovibrational": 84.2608785308744, "residue:FTmat-Transvibrational": 66.13571365167344, "residue:FTmat-Rovibrational": 57.090651827515686, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 28.084239413273323 }, - "total": 307.66091956909656 + "total": 307.701026705236 } } } diff --git a/tests/regression/baselines/octonol/selection_subset.json b/tests/regression/baselines/octonol/selection_subset.json index 5f9d18f1..e15b9555 100644 --- a/tests/regression/baselines/octonol/selection_subset.json +++ b/tests/regression/baselines/octonol/selection_subset.json @@ -2,7 +2,7 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 0.34382967782781193, + "united_atom:Transvibrational": 0.2907129992470817, "united_atom:Rovibrational": 19.154228264604278, "residue:FTmat-Transvibrational": 83.17889385114952, "residue:FTmat-Rovibrational": 57.480841206687685, @@ -10,7 +10,7 @@ "residue:Conformational": 0.0, "residue:Orientational": 25.79114991860739 }, - "total": 202.78843646155286 + "total": 202.73531978297217 } } } diff --git a/tests/regression/baselines/water/combined_forcetorque_off.json b/tests/regression/baselines/water/combined_forcetorque_off.json index 2e632568..b92ef4e3 100644 --- a/tests/regression/baselines/water/combined_forcetorque_off.json +++ b/tests/regression/baselines/water/combined_forcetorque_off.json @@ -2,12 +2,12 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 51.22145722965398, - "united_atom:Rovibrational": 17.232634718413053, + "united_atom:Transvibrational": 51.22145722965397, + "united_atom:Rovibrational": 17.307840626636313, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 68.45409194806703 + "total": 68.52929785629028 } } } diff --git a/tests/regression/baselines/water/default.json b/tests/regression/baselines/water/default.json index c98bc3eb..7f5baa09 100644 --- a/tests/regression/baselines/water/default.json +++ b/tests/regression/baselines/water/default.json @@ -3,11 +3,11 @@ "0": { "components": { "united_atom:Transvibrational": 43.725393337304425, - "united_atom:Rovibrational": 17.28911070147887, + "united_atom:Rovibrational": 17.42448032148262, "united_atom:Conformational": 0.0, "united_atom:Orientational": 32.193445593362114 }, - "total": 93.20794963214541 + "total": 93.34331925214916 } } } diff --git a/tests/regression/baselines/water/frame_window.json b/tests/regression/baselines/water/frame_window.json index c6ae550d..8b368026 100644 --- a/tests/regression/baselines/water/frame_window.json +++ b/tests/regression/baselines/water/frame_window.json @@ -3,11 +3,11 @@ "0": { "components": { "united_atom:Transvibrational": 46.684099714230925, - "united_atom:Rovibrational": 17.694014405444744, + "united_atom:Rovibrational": 17.66359738549709, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 64.37811411967567 + "total": 64.34769709972801 } } } diff --git a/tests/regression/baselines/water/grouping_each.json b/tests/regression/baselines/water/grouping_each.json index acccd86b..676010dd 100644 --- a/tests/regression/baselines/water/grouping_each.json +++ b/tests/regression/baselines/water/grouping_each.json @@ -3,92 +3,92 @@ "0": { "components": { "united_atom:Transvibrational": 14.945907953805552, - "united_atom:Rovibrational": 1.8947243953648254, + "united_atom:Rovibrational": 1.94076792014105, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 16.840632349170377 + "total": 16.8866758739466 }, "1": { "components": { - "united_atom:Transvibrational": 8.111522208287779, - "united_atom:Rovibrational": 0.9607747968334215, + "united_atom:Transvibrational": 8.11152220828778, + "united_atom:Rovibrational": 0.9798912337680555, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 9.0722970051212 + "total": 9.091413442055837 }, "2": { "components": { - "united_atom:Transvibrational": 15.79497347968759, - "united_atom:Rovibrational": 4.606072530590255, + "united_atom:Transvibrational": 15.794973479687599, + "united_atom:Rovibrational": 4.4692860930919585, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 20.401046010277845 + "total": 20.264259572779558 }, "3": { "components": { "united_atom:Transvibrational": 9.462487265119448, - "united_atom:Rovibrational": 1.6509513986984767, + "united_atom:Rovibrational": 1.6054615846390614, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 11.113438663817924 + "total": 11.067948849758508 }, "4": { "components": { "united_atom:Transvibrational": 16.254161245740693, - "united_atom:Rovibrational": 1.367597374110767, + "united_atom:Rovibrational": 1.448700454979353, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 17.62175861985146 + "total": 17.702861700720046 }, "5": { "components": { "united_atom:Transvibrational": 11.57779876203329, - "united_atom:Rovibrational": 7.351163568004953, + "united_atom:Rovibrational": 7.23849459157533, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 18.928962330038242 + "total": 18.81629335360862 }, "6": { "components": { "united_atom:Transvibrational": 10.172061262201801, - "united_atom:Rovibrational": 3.671537296888502, + "united_atom:Rovibrational": 4.086982297438225, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 13.843598559090303 + "total": 14.259043559640027 }, "7": { "components": { - "united_atom:Transvibrational": 13.49951045186194, - "united_atom:Rovibrational": 1.7029491215274863, + "united_atom:Transvibrational": 13.499510451861939, + "united_atom:Rovibrational": 1.6178142656646386, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 15.202459573389428 + "total": 15.117324717526577 }, "8": { "components": { "united_atom:Transvibrational": 16.597759171924583, - "united_atom:Rovibrational": 1.6190289365617598, + "united_atom:Rovibrational": 1.6676178150275727, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 18.21678810848634 + "total": 18.265376986952155 }, "9": { "components": { "united_atom:Transvibrational": 13.731375187064538, - "united_atom:Rovibrational": 5.650620990305761, + "united_atom:Rovibrational": 5.161816204002109, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 19.381996177370297 + "total": 18.893191391066647 } } } diff --git a/tests/regression/baselines/water/rad.json b/tests/regression/baselines/water/rad.json index cbda37a9..cf8510e3 100644 --- a/tests/regression/baselines/water/rad.json +++ b/tests/regression/baselines/water/rad.json @@ -2,12 +2,12 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 79.20298312418278, - "united_atom:Rovibrational": 50.90260688502127, + "united_atom:Transvibrational": 79.2029831241828, + "united_atom:Rovibrational": 51.07316520629525, "united_atom:Conformational": 0.0, "united_atom:Orientational": 22.760377489372107 }, - "total": 152.86596749857614 + "total": 153.03652581985014 } } } diff --git a/tests/regression/baselines/water/selection_subset.json b/tests/regression/baselines/water/selection_subset.json index 2e632568..b92ef4e3 100644 --- a/tests/regression/baselines/water/selection_subset.json +++ b/tests/regression/baselines/water/selection_subset.json @@ -2,12 +2,12 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 51.22145722965398, - "united_atom:Rovibrational": 17.232634718413053, + "united_atom:Transvibrational": 51.22145722965397, + "united_atom:Rovibrational": 17.307840626636313, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 68.45409194806703 + "total": 68.52929785629028 } } } diff --git a/tests/regression/baselines/water/water_off.json b/tests/regression/baselines/water/water_off.json index 2e632568..b92ef4e3 100644 --- a/tests/regression/baselines/water/water_off.json +++ b/tests/regression/baselines/water/water_off.json @@ -2,12 +2,12 @@ "groups": { "0": { "components": { - "united_atom:Transvibrational": 51.22145722965398, - "united_atom:Rovibrational": 17.232634718413053, + "united_atom:Transvibrational": 51.22145722965397, + "united_atom:Rovibrational": 17.307840626636313, "united_atom:Conformational": 0.0, "united_atom:Orientational": 0.0 }, - "total": 68.45409194806703 + "total": 68.52929785629028 } } } diff --git a/tests/unit/CodeEntropy/levels/nodes/test_covariance_node.py b/tests/unit/CodeEntropy/levels/nodes/test_covariance_node.py index 8398113c..d989069f 100644 --- a/tests/unit/CodeEntropy/levels/nodes/test_covariance_node.py +++ b/tests/unit/CodeEntropy/levels/nodes/test_covariance_node.py @@ -415,12 +415,13 @@ def test_build_ua_vectors_uses_customised_axes(): force_vecs, torque_vecs = node._build_ua_vectors( bead_groups=[FakeAtomGroup("ua")], - residue_atoms=FakeAtomGroup("res"), + residue_group=FakeAtomGroup("res"), axes_manager=axes_manager, box=None, force_partitioning=0.5, customised_axes=True, is_highest=True, + res_position=None, ) assert len(force_vecs) == 1 @@ -435,18 +436,22 @@ def test_build_ua_vectors_uses_vanilla_axes_when_not_customised(): np.eye(3), np.array([1.0, 2.0, 3.0]), ) + FakeAtomGroup_Atoms = MagicMock(positions=np.zeros((2, 3))) + FakeAtomGroup.atoms = FakeAtomGroup_Atoms + axes_manager.principal_axes.return_value = np.eye(3) node._ft.get_weighted_forces = MagicMock(return_value=np.array([1.0, 0.0, 0.0])) node._ft.get_weighted_torques = MagicMock(return_value=np.array([0.0, 1.0, 0.0])) with patch("CodeEntropy.levels.nodes.covariance.make_whole") as make_whole: node._build_ua_vectors( bead_groups=[FakeAtomGroup("ua")], - residue_atoms=FakeAtomGroup("res"), + residue_group=FakeAtomGroup("res"), axes_manager=axes_manager, box=None, force_partitioning=0.5, customised_axes=False, is_highest=False, + res_position=None, ) assert make_whole.call_count == 2 diff --git a/tests/unit/CodeEntropy/levels/test_axes.py b/tests/unit/CodeEntropy/levels/test_axes.py index d6d0093f..4c4a894a 100644 --- a/tests/unit/CodeEntropy/levels/test_axes.py +++ b/tests/unit/CodeEntropy/levels/test_axes.py @@ -117,13 +117,17 @@ def _select_atoms(q): assert np.allclose(moi, np.array([3.0, 2.0, 1.0])) -def test_get_residue_axes_with_bonds_uses_vanilla_axes(monkeypatch): +def test_get_residue_axes_uses_vanilla_axes(monkeypatch): ax = AxesCalculator() residue = MagicMock() residue.__len__.return_value = 1 residue.atoms.center_of_mass.return_value = np.array([1.0, 2.0, 3.0]) residue.center_of_mass.return_value = np.array([1.0, 2.0, 3.0]) + residue.select_atoms.return_value = MagicMock( + positions=[[1.0, 2.0, 3.0], [3.0, 2.0, 1.0]] + ) + uas = MagicMock(positions=np.zeros((2, 3))) u = MagicMock() u.dimensions = np.array([10.0, 10.0, 10.0, 90, 90, 90]) @@ -135,20 +139,25 @@ def _select_atoms(q): return [1] # non-empty if q.startswith("resindex "): return residue + if q == "mass 2 to 999": + return uas return [] + monkeypatch.setattr(ax, "get_UA_masses", lambda mol: [10.0, 12.0]) u.select_atoms.side_effect = _select_atoms + residue = u.select_atoms("resindex 10") monkeypatch.setattr("CodeEntropy.levels.axes.make_whole", lambda _ag: None) - monkeypatch.setattr( - ax, "get_vanilla_axes", lambda mol: (np.eye(3) * 2, np.array([9.0, 8.0, 7.0])) - ) + eigenvalues, eigenvectors = np.linalg.eig([[48, 0, 48], [0, 96, 0], [48, 0, 48]]) + transposed = np.transpose(eigenvectors) + axes = transposed[[2, 0, 1]] + axes[2] = -axes[2] - trans, rot, center, moi = ax.get_residue_axes(u, index=10) + trans, rot, center, moi = ax.get_residue_axes(u, index=10, residue=residue) - assert np.allclose(trans, np.eye(3)) - assert np.allclose(rot, np.eye(3) * 2) - assert np.allclose(moi, np.array([9.0, 8.0, 7.0])) + assert np.allclose(trans, axes) + assert np.allclose(rot, axes) + assert np.allclose(moi, np.array([96.0, 96.0, 0.0])) def test_get_UA_axes_uses_principal_axes_when_single_heavy(monkeypatch): @@ -157,13 +166,15 @@ def test_get_UA_axes_uses_principal_axes_when_single_heavy(monkeypatch): u = MagicMock() u.dimensions = np.array([10.0, 10.0, 10.0, 90, 90, 90]) u.atoms.principal_axes.return_value = np.eye(3) + u.center_of_mass.return_value = np.array([[4.0, 0.0, 0.0]]) # heavy_atoms length <= 1 => principal_axes path - heavy_atom = MagicMock(index=5) + heavy_atom = MagicMock(index=5, position=np.array([4.0, 0.0, 0.0])) heavy_atoms = [heavy_atom] def _sel(q): - if q == "prop mass > 1.1": + if q == "mass 2 to 999": + # return heavy atoms group return heavy_atoms if q.startswith("index "): # return atom group with positions @@ -172,6 +183,7 @@ def _sel(q): ag.__getitem__.return_value = MagicMock( mass=12.0, position=np.array([4.0, 0.0, 0.0]), index=5 ) + return ag return [] @@ -184,7 +196,7 @@ def _sel(q): lambda system, atom, dimensions: (np.eye(3), np.array([1.0, 2.0, 3.0])), ) - trans, rot, center, moi = ax.get_UA_axes(u, index=0) + trans, rot, center, moi = ax.get_UA_axes(u, index=0, res_position=None) assert np.allclose(trans, np.eye(3)) assert np.allclose(rot, np.eye(3)) @@ -201,7 +213,7 @@ def test_get_UA_axes_raises_when_bonded_axes_fail(monkeypatch): heavy_atoms = [heavy_atom] def _sel(q): - if q == "prop mass > 1.1": + if q == "mass 2 to 999": return heavy_atoms if q.startswith("index "): ag = MagicMock() @@ -217,7 +229,7 @@ def _sel(q): monkeypatch.setattr(ax, "get_bonded_axes", lambda **kwargs: (None, None)) with pytest.raises(ValueError): - ax.get_UA_axes(u, index=0) + ax.get_UA_axes(u, index=5, res_position=None) def test_get_custom_axes_degenerate_axis1_raises(): @@ -504,18 +516,16 @@ def _select_atoms(q): assert np.allclose(moi, np.array([3.0, 2.0, 1.0])) -def test_get_residue_axes_with_bonds_vanilla_path(monkeypatch): +def test_get_residue_axes_vanilla_path(monkeypatch): ax = AxesCalculator() - residue = MagicMock() residue.__len__.return_value = 1 - residue.atoms.principal_axes.return_value = np.eye(3) * 2 residue.atoms.center_of_mass.return_value = np.array([1.0, 2.0, 3.0]) residue.center_of_mass.return_value = np.array([1.0, 2.0, 3.0]) + residue.select_atoms.return_value = MagicMock(positions=np.zeros((1, 3))) u = MagicMock() u.dimensions = np.array([10.0, 10.0, 10.0, 90, 90, 90]) - u.atoms.principal_axes.return_value = np.eye(3) * 2 def _select_atoms(q): if q.startswith("(resindex"): @@ -528,10 +538,12 @@ def _select_atoms(q): monkeypatch.setattr("CodeEntropy.levels.axes.make_whole", lambda _ag: None) monkeypatch.setattr( - ax, "get_vanilla_axes", lambda mol: (np.eye(3) * 2, np.array([9.0, 8.0, 7.0])) + ax, + "get_custom_principal_axes", + lambda mol: (np.eye(3) * 2, np.array([9.0, 8.0, 7.0])), ) - trans, rot, center, moi = ax.get_residue_axes(u, index=10) + trans, rot, center, moi = ax.get_residue_axes(u, index=10, residue=residue) assert np.allclose(trans, np.eye(3) * 2) assert np.allclose(rot, np.eye(3) * 2) @@ -638,12 +650,23 @@ def center_of_mass(self, *args, **kwargs): def __getitem__(self, idx): return system_atom + def principal_axes(self, *args, **kwargs): + return np.eye(3) + + def select_atoms(self, q): + if q == "mass 2 to 999": + return heavy_atoms + if q.startswith("index "): + return heavy_atom_selection + data_container = MagicMock() data_container.atoms = _Atoms() + data_container.residues.__len__.return_value = 1 data_container.dimensions = np.array([10.0, 10.0, 10.0, 90, 90, 90], dtype=float) + _FakeAtomGroup.atoms = heavy_atom_selection def _select_atoms(q): - if q == "prop mass > 1.1": + if q == "mass 2 to 999": return heavy_atoms if q.startswith("index "): return heavy_atom_selection @@ -658,20 +681,14 @@ def _select_atoms(q): ) monkeypatch.setattr(ax, "get_UA_masses", lambda _ag: [12.0, 12.0]) - got_tensor = MagicMock(return_value=np.eye(3)) - monkeypatch.setattr(ax, "get_moment_of_inertia_tensor", got_tensor) - - got_custom_axes = MagicMock(return_value=(np.eye(3), np.array([3.0, 2.0, 1.0]))) - monkeypatch.setattr(ax, "get_custom_principal_axes", got_custom_axes) - - trans_axes, rot_axes, center, moi = ax.get_UA_axes(data_container, index=0) + trans_axes, rot_axes, center, moi = ax.get_UA_axes( + data_container, index=0, res_position=None + ) assert trans_axes.shape == (3, 3) assert rot_axes.shape == (3, 3) assert np.allclose(center, np.array([0.0, 0.0, 0.0])) assert moi.shape == (3,) - got_tensor.assert_called_once() - got_custom_axes.assert_called_once() def test_get_bonded_axes_returns_none_none_if_custom_axes_none(monkeypatch):