Download model/boltzgen/data/write/pdb.py from OneScience-Group/BoltzGen: direct link, hf CLI and curl.
- Browser
- Download file 4.55 kB
-
https://huggingface.co/OneScience-Group/BoltzGen/resolve/main/model/boltzgen/data/write/pdb.py
- Command line
-
hf download hf://OneScience-Group/BoltzGen/model/boltzgen/data/write/pdb.py
-
curl -L -o pdb.py https://huggingface.co/OneScience-Group/BoltzGen/resolve/main/model/boltzgen/data/write/pdb.py
4.55 kB
| import re | |
| import string | |
| from typing import Iterator | |
| from boltzgen.data import const | |
| from boltzgen.data.data import Structure | |
| def generate_tags() -> Iterator[str]: | |
| """Generate chain tags. | |
| Yields | |
| ------ | |
| str | |
| The next chain tag | |
| """ | |
| for i in range(1, 4): | |
| for j in range(len(string.ascii_uppercase) ** i): | |
| tag = "" | |
| for k in range(i): | |
| tag += string.ascii_uppercase[ | |
| j | |
| // (len(string.ascii_uppercase) ** k) | |
| % len(string.ascii_uppercase) | |
| ] | |
| yield tag | |
| def to_pdb(structure: Structure) -> str: # noqa: PLR0915 | |
| """Write a structure into a PDB file. | |
| Parameters | |
| ---------- | |
| structure : Structure | |
| The input structure | |
| Returns | |
| ------- | |
| str | |
| the output PDB file | |
| """ | |
| pdb_lines = [] | |
| atom_index = 1 | |
| atom_reindex_ter = [] | |
| chain_tags = generate_tags() | |
| # Add all atom sites. | |
| for chain in structure.chains: | |
| # We rename the chains in alphabetical order | |
| chain_idx = chain["asym_id"] | |
| chain_tag = next(chain_tags) | |
| res_start = chain["res_idx"] | |
| res_end = chain["res_idx"] + chain["res_num"] | |
| residues = structure.residues[res_start:res_end] | |
| for residue in residues: | |
| atom_start = residue["atom_idx"] | |
| atom_end = residue["atom_idx"] + residue["atom_num"] | |
| atoms = structure.atoms[atom_start:atom_end] | |
| atom_coords = atoms["coords"] | |
| res_name = residue["name"] | |
| for i, atom in enumerate(atoms): | |
| atom_reindex_ter.append(atom_index) | |
| # This should not happen on predictions, but just in case. | |
| if not atom["is_present"]: | |
| continue | |
| record_type = ( | |
| "ATOM" | |
| if chain["mol_type"] != const.chain_type_ids["NONPOLYMER"] | |
| else "HETATM" | |
| ) | |
| atom_name = atom["name"] | |
| alt_loc = "" | |
| insertion_code = "" | |
| occupancy = 1.00 | |
| atom_key = re.sub(r"\d", "", atom_name) | |
| if atom_key in const.ambiguous_atoms: | |
| if isinstance(const.ambiguous_atoms[atom_key], str): | |
| element = const.ambiguous_atoms[atom_key] | |
| elif res_name in const.ambiguous_atoms[atom_key]: | |
| element = const.ambiguous_atoms[atom_key][res_name] | |
| else: | |
| element = const.ambiguous_atoms[atom_key]["*"] | |
| else: | |
| element = atom_key[0] | |
| charge = "" | |
| residue_index = residue["res_idx"] + 1 | |
| pos = atom_coords[i] | |
| res_name_3 = "LIG" if record_type == "HETATM" else res_name | |
| b_factor = 1.00 | |
| # PDB is a columnar format, every space matters here! | |
| atom_line = ( | |
| f"{record_type:<6}{atom_index:>5} {atom_name:<4}{alt_loc:>1}" | |
| f"{res_name_3:>3} {chain_tag:>1}" | |
| f"{residue_index:>4}{insertion_code:>1} " | |
| f"{pos[0]:>8.3f}{pos[1]:>8.3f}{pos[2]:>8.3f}" | |
| f"{occupancy:>6.2f}{b_factor:>6.2f} " | |
| f"{element:>2}{charge:>2}" | |
| ) | |
| pdb_lines.append(atom_line) | |
| atom_index += 1 | |
| should_terminate = chain_idx < (len(structure.chains) - 1) | |
| if should_terminate: | |
| # Close the chain. | |
| chain_end = "TER" | |
| chain_termination_line = ( | |
| f"{chain_end:<6}{atom_index:>5} " | |
| f"{res_name_3:>3} " | |
| f"{chain_tag:>1}{residue_index:>4}" | |
| ) | |
| pdb_lines.append(chain_termination_line) | |
| atom_index += 1 | |
| # Dump CONECT records. | |
| for bond in structure.bonds: | |
| atom1 = structure.atoms[bond["atom_1"]] | |
| atom2 = structure.atoms[bond["atom_2"]] | |
| if not atom1["is_present"] or not atom2["is_present"]: | |
| continue | |
| atom1_idx = atom_reindex_ter[bond["atom_1"]] | |
| atom2_idx = atom_reindex_ter[bond["atom_2"]] | |
| conect_line = f"CONECT{atom1_idx:>5}{atom2_idx:>5}" | |
| pdb_lines.append(conect_line) | |
| pdb_lines.append("END") | |
| pdb_lines.append("") | |
| pdb_lines = [line.ljust(80) for line in pdb_lines] | |
| return "\n".join(pdb_lines) | |