@@ -470,7 +470,9 @@ def __init__(self, filehandle, keep_full_data=False):
470470 "_atom_site.pdbx_formal_charge" : "charge" ,
471471 }
472472
473- HELIX_TARGET_COLS = {
473+ # full list of conf types: https://mmcif.wwpdb.org/dictionaries/mmcif_ma.dic/Items/_struct_conf_type.id.html;
474+ # mapping between file types: https://manpages.debian.org/unstable/dssp/mkdssp.1.en.html
475+ CONF_TARGET_COLS = {
474476 "_struct_conf.conf_type_id" : "conformation_type" ,
475477 "_struct_conf.id" : "id" ,
476478 # label_asym_id and label_seq_id are sufficient for merging to atom table;
@@ -508,11 +510,15 @@ def __init__(self, filehandle, keep_full_data=False):
508510 # decode information into dataframe with BioPython helper method; note this section may not be
509511 # present if no helices exist in the structure
510512 try :
511- self .helix_table = pd .DataFrame ({
512- name : _decode (data [source_column ]) for source_column , name in HELIX_TARGET_COLS .items ()
513- })
513+ self .conf_table = pd .DataFrame ({
514+ name : _decode (data [source_column ]) for source_column , name in CONF_TARGET_COLS .items ()
515+ }).query (
516+ # there are a handful of PDB entries that have (probably wrong) secondary structure assignments
517+ # extending over more than one segment (e.g. 2bp7, 2wjv), drop these rather than raising an error
518+ "beg_label_asym_id == end_label_asym_id"
519+ )
514520 except KeyError :
515- self .helix_table = None
521+ self .conf_table = None
516522
517523 # decode information into dataframe with BioPython helper method; note this section may not be
518524 # present if no sheets exist in the structure
@@ -526,16 +532,23 @@ def __init__(self, filehandle, keep_full_data=False):
526532 # create secondary structure table for merging to chain tables
527533 # (will only contain helix/H and strand/E, coil/C will need to be filled in)
528534 sse_raw = []
529- for sse_type , sse_table in [
530- ("H" , self .helix_table ),
531- ("E" , self .sheet_table )
535+ for sse_type , sse_table , sse_filter in [
536+ ("H" , self .conf_table , "HELX" ),
537+ ("E" , self .sheet_table , None ),
538+ # also retrieve beta strands/bridges from conf_table if available
539+ ("E" , self .conf_table , "STRN" ),
532540 ]:
533541 # skip if secondary structure element not present in PDB file at all
534542 if sse_table is None :
535543 continue
536544
545+ # filter table down to relevant entries for current secondary structure type
546+ if sse_filter is not None :
547+ sse_table = sse_table .query (
548+ f"conformation_type.str.startswith('{ sse_filter } ')"
549+ )
550+
537551 for _ , row in sse_table .iterrows ():
538- assert row .beg_label_asym_id == row .end_label_asym_id
539552 for seq_id in range (row .beg_label_seq_id , row .end_label_seq_id + 1 ):
540553 sse_raw .append ({
541554 "label_asym_id" : row .beg_label_asym_id ,
@@ -694,7 +707,7 @@ def get_chain(self, chain, model=0, is_author_id=True):
694707 # create coordinate ID from author residue ID + insertion code
695708 # (this should be unique and circumvents issues from 0 seqres values if selecting based on author chain ID)
696709 coord_id = lambda df : df .auth_seq_id .astype (str ) + df .insertion_code ,
697- seqres_id = lambda df : df .label_seq_id .astype (str ).replace ("0" , np . nan ),
710+ seqres_id = lambda df : df .label_seq_id .astype (str ).replace ("0" , pd . NA ). replace ( "" , pd . NA ),
698711 one_letter_code = lambda df : df .label_comp_id .map (AA3_to_AA1 , na_action = "ignore" ),
699712 # note that MSE will now be labeled as HETATM, which was not the case with MMTF
700713 hetatm = lambda df : df .record_type == "HETATM" ,
@@ -720,12 +733,13 @@ def get_chain(self, chain, model=0, is_author_id=True):
720733 how = "left"
721734 )
722735 else :
736+ # initialize to pd.NA instead of np.nan or warning about assigning str to float64 column appears
723737 res_sse = res .assign (
724- sec_struct_3state = np . nan
738+ sec_struct_3state = pd . NA
725739 )
726740
727741 res_sse .loc [
728- res_sse .sec_struct_3state .isnull () & ( res_sse .label_seq_id > 0 ),
742+ res_sse .sec_struct_3state .isnull () & res_sse .seqres_id . notnull ( ),
729743 "sec_struct_3state"
730744 ] = "C"
731745
0 commit comments