99
1010# Roland Dunbrack
1111# Fox Chase Cancer Center
12- # version 2
13- # February 21 , 2025
12+ # version 3
13+ # April 6 , 2025
1414# MIT license: script can be modified and redistributed for non-commercial and commercial use, as long as this information is reproduced.
1515
16+ # includes support for Boltz1 structures and structures with nucleic acids
17+
1618# It may be necessary to install numpy with the following command:
1719# pip install numpy
1820
@@ -392,17 +394,21 @@ def classify_chains(chains, residue_types):
392394 chain_pair_type [chain1 ][chain2 ]= 'nucleic_acid'
393395 else :
394396 chain_pair_type [chain1 ][chain2 ]= 'protein'
395- print (chain1 , chain2 , chain_dict [chain1 ], chain_dict [chain2 ], chain_pair_type [chain1 ][chain2 ])
396397
397398# Calculate distance matrix using NumPy broadcasting
398399distances = np .sqrt (((coordinates [:, np .newaxis , :] - coordinates [np .newaxis , :, :])** 2 ).sum (axis = 2 ))
399400
400401# Load AF2, AF3, or BOLTZ1 data and extract plddt and pae_matrix (and ptm_matrix if available)
401402if af2 :
402- if os .path .exists (pae_file_path ):
403- with open (pae_file_path , 'r' ) as file :
404- data = json .load (file )
403+
405404
405+ if os .path .exists (pae_file_path ):
406+ if pae_file_path .endswith ('.pkl' ):
407+ data = np .load (pae_file_path , allow_pickle = True )
408+ else :
409+ with open (pae_file_path , 'r' ) as file :
410+ data = json .load (file )
411+
406412 if 'iptm' in data : iptm_af2 = float (data ['iptm' ])
407413 else : iptm_af2 = - 1.0
408414 if 'ptm' in data : ptm_af2 = float (data ['ptm' ])
@@ -415,7 +421,11 @@ def classify_chains(chains, residue_types):
415421 plddt = np .zeros (numres )
416422 cb_plddt = np .zeros (numres )
417423
418- pae_matrix = np .array (data ['pae' ])
424+ if 'pae' in data :
425+ pae_matrix = np .array (data ['pae' ])
426+ elif 'predicted_aligned_error' in data :
427+ pae_matrix = np .array (data ['predicted_aligned_error' ])
428+
419429 else :
420430 print ("AF2 PAE file does not exist: " , pae_file_path )
421431 sys .exit ()
@@ -856,8 +866,8 @@ def classify_chains(chains, residue_types):
856866 'I' :'deepteal' , 'J' :'forest' , 'K' :'lightblue' , 'L' :'slate' ,
857867 'M' :'violet' , 'N' :'arsenic' , 'O' :'iodine' , 'P' :'silver' ,
858868 'Q' :'red' , 'R' :'sulfur' , 'S' :'purple' , 'T' :'olive' ,
859- 'U' :'palegreen' , 'V' :'gray90' , 'W' :'blue' , 'X' :'palecyan' ,
860- 'Y' :'yellow ' , 'Z' :'white ' }
869+ 'U' :'palegreen' , 'V' :'green' , 'W' :'blue' , 'X' :'palecyan' ,
870+ 'Y' :'limon ' , 'Z' :'chocolate ' }
861871
862872chainpairs = set ()
863873for chain1 in unique_chains :
@@ -956,5 +966,5 @@ def classify_chains(chains, residue_types):
956966 chain_pair = f'color_{ chain1 } _{ chain2 } '
957967 chain1_residues = f'chain { chain1 } and resi { contiguous_ranges (unique_residues_chain1 [chain1 ][chain2 ])} '
958968 chain2_residues = f'chain { chain2 } and resi { contiguous_ranges (unique_residues_chain2 [chain1 ][chain2 ])} '
959- PML .write (f'alias { chain_pair } , color { color1 } , { chain1_residues } ; color { color2 } , { chain2_residues } \n \n ' )
969+ PML .write (f'alias { chain_pair } , color gray80, all; color { color1 } , { chain1_residues } ; color { color2 } , { chain2_residues } \n \n ' )
960970 OUT .write ("\n " )
0 commit comments