Coverage for mddb_workflow/utils/mda_spells.py: 62%
48 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-29 15:48 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-29 15:48 +0000
1import json
2import numpy as np
3import pickle
5from mddb_workflow.utils.type_hints import *
6from mddb_workflow.utils.constants import GREY_HEADER, COLOR_END
7from mddb_workflow.utils.auxiliar import MISSING_CHARGES, MISSING_BONDS
9from MDAnalysis.topology.TPRParser import TPRParser
10#from MDAnalysis.topology.PDBParser import PDBParser # for class reference
11from MDAnalysis.core.universe import Universe
12from MDAnalysis.core.topology import Topology
13from MDAnalysis.core.topologyattrs import (
14 Atomnames,
15 Bonds,
16 ChainIDs,
17 Charges,
18 Elements,
19 Resids,
20 Resnames,
21 Resnums,
22 Segids
23)
25def to_MDAnalysis_topology(standard_topology_path : str) -> 'Topology':
26 """
27 Creates a MDAnalysis topology from a json topology file.
29 The json file should contain the following keys:
30 - atom_names
31 - atom_elements
32 - atom_charges
33 - atom_bonds (list of lists of atom indices)
34 - residue_names
35 - residue_numbers
36 - chain_names
37 - atom_residue_indices
38 - residue_chain_indices
40 :param topology: path to the json file
41 :returns: a MDAnalysis topology object
42 """
43 topology = json.load(open(standard_topology_path))
45 # transform bond to non redundant tuples
46 bonds = []
47 for bond_from, bond_tos in enumerate(topology['atom_bonds']):
48 for bond_to in bond_tos:
49 bond = tuple(sorted([bond_from, bond_to]))
50 bonds.append(bond)
51 # sorted(set(bonds)) if you want to check for duplicates
52 topology['bonds'] = set(bonds)
53 atom_2_chain = np.array(topology['residue_chain_indices'])[topology['atom_residue_indices']]
54 topology['chainIDs'] = np.array(topology['chain_names'])[atom_2_chain]
57 attrs = [Atomnames (topology['atom_names']),
58 Elements (topology['atom_elements']),
59 Charges (topology['atom_charges']),
60 Bonds (topology['bonds']),
61 Resnames (topology['residue_names']),
62 Resnums (topology['residue_numbers']),
63 ChainIDs (topology['chainIDs']),
64 Segids (topology['chain_names']),
65 Resids (np.arange(len(topology['residue_names']))),
66 ]
68 mda_top = Topology(n_atoms=len(topology['atom_names']),
69 n_res=len(topology['residue_names']),
70 n_seg=len(topology['chain_names']),
71 attrs=attrs,
72 atom_resindex=topology['atom_residue_indices'],
73 residue_segindex=topology['residue_chain_indices']
74 )
75 return mda_top
77def get_mda_universe_from_stopology (
78 standard_topology_path : str, coordinates_file : str) -> 'Universe':
79 """Create a MDAnalysis universe using data in the workflow.
81 Args:
82 standard_topology_path (str): Path to the standard topology file.
83 coordinates_file (str): Path to the coordinates file (e.g., PDB, XTC)."""
84 mda_topology = to_MDAnalysis_topology(standard_topology_path)
85 # Create a MDAnalysis topology from the standard topology file
86 return Universe(mda_topology, coordinates_file)
88def get_mda_universe (structure_file : 'File', # To load in MDAnalysis
89 trajectory_file : 'File', # To load in MDAnalysis
90 reference_bonds : list[list[int]], # To set the bonds
91 charges : list[float]) -> 'Universe': # To set the charges
92 """Create a MDAnalysis universe using data in the workflow."""
94 # Make MDAnalysis warnings and logs grey
95 print(GREY_HEADER, end='\r')
96 universe = Universe(structure_file.path, trajectory_file.path)
97 # Set the atom bonds
98 bonds = []
99 for bond_from, bond_tos in enumerate(reference_bonds):
100 if bond_tos == MISSING_BONDS: continue
101 for bond_to in bond_tos:
102 bond = tuple(sorted([bond_from, bond_to]))
103 bonds.append(bond)
104 universe.add_TopologyAttr('bonds', set(bonds))
106 # Set the charges
107 if charges and charges != MISSING_CHARGES and len(charges) > 0:
108 universe.add_TopologyAttr('charges', np.array(charges, dtype=np.float32))
109 print(COLOR_END, end='\r')
110 return universe
112# Get a cksum from a MDA universe for equality comparission
113def get_mda_universe_cksum (universe) -> str:
114 pickled = pickle.dumps(universe.atoms)
115 return sum(pickled)
117# Get TPR bonds using MDAnalysis
118# WARNING: Sometimes this function takes additional constrains as actual bonds
119# DANI: si miras los topology.bonds.values estos enlaces falsos van al final
120# DANI: Lo veo porque los índices están en orden ascendente y veulven a empezar
121# DANI: He pedido ayuda aquí https://github.com/MDAnalysis/mdanalysis/pull/463
122def get_tpr_bonds_mdanalysis (tpr_filepath : str) -> list[ tuple[int, int] ]:
123 parser = TPRParser(tpr_filepath)
124 topology = parser.parse()
125 bonds = list(topology.bonds.values)
126 return bonds