Package: pdbx2df
pdbx2df: molecular structure data processing and analysis with DataFrameMany file formats are about different ways of integrating structured data blocks into a single file in that those blocks are related to each other in some way. ThePDBxormmCIFfile format organizes structural biology data intocategoriesand each category contains a structured data block which includes severalattributes, and each attribute contains the same number of elements within a category. Those characteristics make a PDBx/mmCIF file naturally to be representable as aPython dictofPandas DataFrames.Ourpdbx2dfpackage primarily parses a PDBx file (mmCIF file: <pdb_id>.cif) into a Python dict with PDBx category names as keys and contents belonging to the category as the corresponding values. Each category content is parsed as a Pandas DataFrame whose columns are the attribute names. On the other hand, we can write a dict of Pandas DataFrame(s) into a PDBx format in which the dict key(s) are used as category names, the DataFrame column names as attribute names, and the DataFrame row(s) as the corresponding record(s).The old stylePDBfile format is not very well structured compared to the new PDBx file format. However, we can makepdbx2dfsupport parsing a PDB file (pdb_id.pdb) into a Python dict of Pandas DataFrames similarly, although many 'blocks' need more post processing. As such, the lines starting withATOM,HETATM, andTERare read into a category named_atom_sitewhich corresponds to the same category in a mmCIF file. And for NMR models, allATOM,HETATM, andTERlines are read into a single DataFrame but atoms in a NMR model has the same value in thenmr_modelcolumn which is determined by the number in the correspondingMODELline.SEQRESlines are read into a category named_seq_res.TheTRIPOS MOL2file format is also supported for reading using the same keyword as the PDB and PDBx files about selecting file categories. Currently, theATOM,BOND, andMOLECULEare supported.For thePDBandMOL2formats, if any other categories are required in your workflow, please raise an issue or PR.RequirementsOnlyPandasis required since we need to export Pandas DataFrames. Python versions >= 3.9 in Linux, Windows, and MacOS are tested.Installpipinstallpdbx2dfUsage examples1. PDBx file1.1 If you want to read the 3D coordinates for PDB1viiinto a Pandas DataFrame, and you have downloaded the1vii.ciffile to your current working directory./, you can:frompdbx2dfimportread_pdbxpdbx_file='./1vii.cif'pdbx=read_pdbx(pdbx_file,category_names=['_atom_site'])atoms_df=pdbx['_atom_site']# 'atoms_df' is a Pandas DataFrame containing the '_atom_site' category which has the detailed 3D coordinates for each atom.1.2. If you want to read the FASTA sequence of1vii, you can:frompdbx2dfimportread_pdbxpdb_id='1vii'pdbx=read_pdbx(pdb_id=pdb_id,category_names=['_entity_poly'])fasta_df=pdbx['_entity_poly']fasta=fasta_df['pdbx_seq_one_letter_code_can'].to_list()[0]# 1vii only has one sequence# fasta == 'MLSDEDFKAVFGMTRSAFANLPLWKQQNLKKEKGLF'The file content of1VII.cifis fetched fromRCSBif onlypdb_idis provided.You can also put a Uniprot ID in thepdb_idkeyword to get the AlphaFold2 file fromalphafold.ebi.ac.uk.By default, the fetched content will be saved to a file named<pdb_id>.cifunder the directory given bypdbx_file_dir(which by default is your current working directory). You can choose not to save the file by settingsave_pdbx_file=Falsein theread_pdbxfunction calling.1.3. You can read them simutanously:frompdbx2dfimportread_pdbxpdbx_file='./1vii.cif'pdbx=read_pdbx(pdbx_file,category_names=['_entity_poly','_atom_site'])atoms_df=pdbx['_atom_site']fasta_df=pdbx['_entity_poly']Putting a list of category names tocategory_names, you will get them if they are in the PDBx file.1.4. You can parse the whole file by using 'all':frompdbx2dfimportread_pdbxpdbx_file='./1vii.cif'pdbx=read_pdbx(pdbx_file,category_names=['all'])atoms_df=pdbx['_atom_site']fasta_df=pdbx['_entity_poly']# and more1.5. Write back to a PDBx file:frompdbx2dfimportread_pdbx,write_pdbxpdbx_file='./1vii.cif'pdbx=read_pdbx(pdbx_file,category_names=['all'])keep=['_atom_site','_entity_poly']# suppose we only want to keep the FASTA sequence and 3D coordinates.pdbx_keep={k:vfork,vinpdbx.items()ifkinkeep}write_pdbx(pdbx_keep,'1vii_save.cif')2. PDB file2.1. For reading the atomic information in a PDB file1vii.pdb:frompdbx2dfimportread_pdbpdb_file='./1vii.pdb'pdb=read_pdb(pdb_file=pdb_file,category_names=['_atom_site'])# We use '_atom_site' here to mirror the mmCIF format and it is the defaultatoms_df=pdb['_atom_site']# 'atoms_df' is a Pandas DataFrame containing the '_atom_site' category which has the detailed 3D coordinates for each atom.2.2. Suppose we only want to keep the protein residue atoms in5u8l.pdb:frompdbx2dfimportread_pdb,write_pdbpdb_file='./5u8l.pdb'pdb=read_pdb(pdb_file=pdb_file,category_names=['_atom_site'])df=pdb['_atom_site']df=df[df.record_name=='ATOM']pdb['_atom_site']=dfwrite_pdb(pdb,'5u8l_nohetero.pdb')# The '5u8l_nohetero.pdb' file contains only the protein residues.Theread_pdbfunction can parse PDB files generated byChimeraby default. You can setallow_chimera=Falsein its input to fully follow the standard PDB format (although I don't see a use case).For using apdb_idor Uniprot ID (aspdb_id) to fetch a RCSB or AlphaFold2 PDB file, it is almost the same as the aboveread_pdbxexample, except that the keywords aresave_pdb_fileandpdb_file_dirfor saving the fetched content.Thewrite_pdbfunction can write PDB files that can be parsed byChimeraby settingallow_chimera=True.allow_chimera=Falseby default so that the output PDB files follow the standard PDB format strictly.Since our package can read from and write to PDB files containing NMR models, it is straightforward to read and write trajectory files saved as PDB files by molecular dynamics software, if different frames are surrounded by pairs ofMODELandENDMDLlines.3. MOL2 fileFor example, to read thetest.mol2file in thetests/test_filesfolder in this repository:frompdbx2dfimportread_mol2mol2_file='./tests/test_files/test.mol2'mol2=read_mol2(test_file)atoms_df=mol2['ATOM']# The 'ATOM' category as a DataFrame.bonds_df=mol2['BOND']# The 'BOND' category as a DataFrame.