Source code for haddock.gear.haddockmodel

"""Represent an Haddock model."""

from haddock.core.typing import FilePath


[docs] class HaddockModel: """Represent HADDOCK model.""" def __init__(self, pdb_f: FilePath) -> None: remarks = self._load_remarks(pdb_f) self.energies = self._load_energies(remarks) self.interface_energies = self._load_per_interface_energies(remarks) @staticmethod def _load_remarks(pdb_f: FilePath) -> list[str]: """Load remark lines from PDB file Parameters ---------- pdb_f : FilePath Path to a PDB file Returns ------- remarks : list[str] List of PDB lines containing remarks. """ remarks: list[str] = [] with open(pdb_f) as fh: for line in fh.readlines(): if line.startswith('REMARK'): remarks.append(line) return remarks @staticmethod def _load_energies(remarks: list[str]) -> dict[str, float]: """Load HADDOCK energy terms from PDB remarks. Parameters ---------- remarks : list[str] List of PDB lines containing remarks. Returns ------- energy_dic : dict[str, float] Dictionary of energy terms with their values """ energy_dic: dict[str, float] = {} for line in remarks: # TODO: use regex to do this if 'energies' in line: energy_values = map( float, line.rstrip().split(':')[-1].split(',') ) total, bonds, angles, improper, dihe, vdw, elec, air, cdih, coup, rdcs, vean, dani, xpcs, rg = energy_values # noqa: E501 energy_dic['total'] = total energy_dic['bonds'] = bonds energy_dic['angles'] = angles energy_dic['improper'] = improper energy_dic['dihe'] = dihe energy_dic['vdw'] = vdw energy_dic['elec'] = elec energy_dic['air'] = air energy_dic['cdih'] = cdih energy_dic['coup'] = coup energy_dic['rdcs'] = rdcs energy_dic['vean'] = vean energy_dic['dani'] = dani energy_dic['xpcs'] = xpcs energy_dic['rg'] = rg if 'buried surface area' in line: bsa = float(line.rstrip().split(':')[-1]) energy_dic['bsa'] = bsa if 'Desolvation energy' in line: desolv = float(line.rstrip().split(':')[-1]) energy_dic['desolv'] = desolv if 'Symmetry energy' in line: sym = float(line.rstrip().split(':')[-1]) energy_dic['sym'] = sym return energy_dic @staticmethod def _load_per_interface_energies( remarks: list[str], ) -> dict[str, dict[str, float]]: """Read a pdb file and parse per interface scores. Parameters ---------- remarks : list[str] List of PDB lines containing remarks. Returns ------- interfaces_scores : dict[str, dict[str, float]] Dictionary holding per interfaces scores. """ header = None interfaces_scores: dict[str, dict[str, float]] = {} for _ in remarks: if _.startswith("REMARK Interface"): s_ = _.strip().split()[2:] # Extract header if not header: header = s_ # Extract data else: chain1 = s_[header.index("Chain1")] chain2 = s_[header.index("Chain2")] haddockscore = float(s_[header.index("HADDOCKscore")]) evdw = float(s_[header.index("Evdw")]) eelec = float(s_[header.index("Eelec")]) edesol = float(s_[header.index("Edesol")]) bsa = float(s_[header.index("BSA")]) # Combine chains together chains_key = f"{chain1}_{chain2}" # Hold data interfaces_scores[chains_key] = { "HADDOCKscore": haddockscore, "vdw": evdw, "elec": eelec, "desolv": edesol, "bsa": bsa, } return interfaces_scores
[docs] def calc_haddock_score(self, **weights: float) -> float: """Calculate the haddock score based on the weights and energies.""" return self.calc_score(self.energies, **weights)
[docs] @staticmethod def calc_score(energies: dict[str, float], **weights: float) -> float: """Compute sum of weighted energy terms. Parameters ---------- energies : dict[str, float] Dict of energy values for each energy term Returns ------- weighted_score : float Sum of weighted energy terms """ weighted_score: float = 0.0 for weight_name, weight_value in weights.items(): component_id = weight_name.split("_")[1] try: weighted_score += energies[component_id] * weight_value except KeyError: continue return weighted_score