From a16befa602870a34b2df899db8f43071a644c0a4 Mon Sep 17 00:00:00 2001 From: paulinaCabral Date: Sat, 1 Aug 2026 22:48:33 -0700 Subject: [PATCH 1/5] - Added inner function to perform_multiple_alignment called get_gap_letter - added more identifiers in gap_letter (a,b..AA, AB.. - Added warning message for when a structure has to get additional identifiers (AA, AB) --- src/pdbcleanresiduestandardizationutils.py | 51 ++++++++++++++++++++-- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/src/pdbcleanresiduestandardizationutils.py b/src/pdbcleanresiduestandardizationutils.py index 699d737..091e8a4 100644 --- a/src/pdbcleanresiduestandardizationutils.py +++ b/src/pdbcleanresiduestandardizationutils.py @@ -3,6 +3,8 @@ from Bio.PDB.MMCIFParser import FastMMCIFParser from PDBClean.alignmentutils import * from PDBClean.listutils import * +import string + # #################### @@ -104,9 +106,39 @@ def perform_multiple_alignment(Structure_Sequences, ChID_ResiNum_Vector, structi check : str Updated string representing the state of the main menu, set to '1' to indicate a state change. """ + + def get_gap_letter(n): + """ + Convert a 0-based index into a spreadsheet-style alphabet label. + + Cycles through all single uppercase letters (A-Z) and lowercase letters + (a-z) before moving into multi-letter combinations (AA, AB, ..., zz, AAA...). + + Parameters: + ----------- + n : int + The 0-based index to convert. + + Returns: + -------- + label : str + The corresponding alphabetic label. + """ + alphabet = string.ascii_uppercase + string.ascii_lowercase + + label = "" + n += 1 + while n > 0: + n, remainder = divmod(n - 1, 52) + label = alphabet[remainder] + label + + return label + Structure_Sequences_Aligned = {} Structure_ConversionTemplate = {} Structure_Sequences_GAPS = {} + big_structures_warning = set() + input_submenu = "" while(input_submenu != "QUIT"): print(" Perform multiple alignments to identify residues", @@ -147,6 +179,7 @@ def perform_multiple_alignment(Structure_Sequences, ChID_ResiNum_Vector, structi key = str(structid_list[I]) + "_" + chid if key in Structure_Sequences: #Structure_Sequences_Aligned[key] = this_chainsseq_aligned_list[i] + Structure_Sequences_Aligned[key] = this_chainsseq_aligned_list_map[str(structid_list[I])] Structure_Sequences_GAPS[key] = this_chainseq_gap_percentages #FAPA i += 1 @@ -189,12 +222,13 @@ def perform_multiple_alignment(Structure_Sequences, ChID_ResiNum_Vector, structi new_res_num=[] freq_tracker=1 gap_tracker=0 - gap_letter=['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'] - for freq in gaps: + for freq in gaps: # accepted gap percentage based on user defined occupancy threshold + + # Changing the functionality of gap_letter #freq_tracker = 1 #gap_tracker = 0 #print(freq) - if freq < 100-user_gap: # accepted gap percentage based on user defined occupancy threshold + if freq < 100-user_gap: new_res_num.append(counter) counter += 1 freq_tracker=freq @@ -203,7 +237,10 @@ def perform_multiple_alignment(Structure_Sequences, ChID_ResiNum_Vector, structi else: #print(gap_tracker) #new_res_num.append(str(counter)+"_"+str(gap_tracker)) - new_res_num.append(str(counter-1) +" "+str(gap_letter[gap_tracker])) + new_res_num.append(str(counter-1) +" "+str(get_gap_letter(gap_tracker))) + + if gap_tracker == 52: + big_structures_warning.add(structid_list[I].split("/")[-1]) gap_tracker+=1 freq_tracker=freq @@ -266,6 +303,12 @@ def perform_multiple_alignment(Structure_Sequences, ChID_ResiNum_Vector, structi check = "1" input_submenu = "QUIT" + + if len(big_structures_warning) > 0: + print(f"\nWARNING: The following structures were affected by large gaps in most of the MSA (>62 positions), " + f"resulting in residue renumbering that requires two-character alternate identifiers. This may lead " + f"to problems when opening the structure with molecular visualization software. {big_structures_warning}\n") + return Structure_Sequences_Aligned, Structure_ConversionTemplate, chid_list, check def show_conversiontemplate(Structure_ConversionTemplate): From eb5ad8133130be0b96b8eb17722561a536d9dcda Mon Sep 17 00:00:00 2001 From: paulinaCabral Date: Sat, 8 Aug 2026 22:36:09 -0700 Subject: [PATCH 2/5] Updated 'perform_multiple_alignment' to output a csv formatted file that includes information about problematic chains in a structure --- src/pdbcleanresiduestandardizationutils.py | 33 +++++++++++++--------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/pdbcleanresiduestandardizationutils.py b/src/pdbcleanresiduestandardizationutils.py index 091e8a4..f1cf8b7 100644 --- a/src/pdbcleanresiduestandardizationutils.py +++ b/src/pdbcleanresiduestandardizationutils.py @@ -109,20 +109,16 @@ def perform_multiple_alignment(Structure_Sequences, ChID_ResiNum_Vector, structi def get_gap_letter(n): """ - Convert a 0-based index into a spreadsheet-style alphabet label. + Convert a 0-based index into a spreadsheet-style alphabet label. - Cycles through all single uppercase letters (A-Z) and lowercase letters - (a-z) before moving into multi-letter combinations (AA, AB, ..., zz, AAA...). + Cycles through all single uppercase letters (A-Z) and lowercase letters + (a-z) before moving into multi-letter combinations (AA, AB, ..., zz, AAA...). Parameters: - ----------- - n : int - The 0-based index to convert. + n (int): The 0-based index to convert. Returns: - -------- - label : str - The corresponding alphabetic label. + str: The corresponding alphabetic label. """ alphabet = string.ascii_uppercase + string.ascii_lowercase @@ -137,7 +133,7 @@ def get_gap_letter(n): Structure_Sequences_Aligned = {} Structure_ConversionTemplate = {} Structure_Sequences_GAPS = {} - big_structures_warning = set() + big_structures_warning = {} input_submenu = "" while(input_submenu != "QUIT"): @@ -177,6 +173,7 @@ def get_gap_letter(n): i = 0 for I in range(len(structid_list)): key = str(structid_list[I]) + "_" + chid + if key in Structure_Sequences: #Structure_Sequences_Aligned[key] = this_chainsseq_aligned_list[i] @@ -240,7 +237,8 @@ def get_gap_letter(n): new_res_num.append(str(counter-1) +" "+str(get_gap_letter(gap_tracker))) if gap_tracker == 52: - big_structures_warning.add(structid_list[I].split("/")[-1]) + structure = (structid_list[I].split("/")[-1]) + big_structures_warning.setdefault(structure, []).append(chain) gap_tracker+=1 freq_tracker=freq @@ -305,10 +303,17 @@ def get_gap_letter(n): input_submenu = "QUIT" if len(big_structures_warning) > 0: - print(f"\nWARNING: The following structures were affected by large gaps in most of the MSA (>62 positions), " + print(f"\nWARNING: Some structures were affected by large gaps in most of the MSA (>62 positions), " f"resulting in residue renumbering that requires two-character alternate identifiers. This may lead " - f"to problems when opening the structure with molecular visualization software. {big_structures_warning}\n") - + f"to problems when opening the structure with molecular visualization software. These structures " + f"will be saved in residue_warning_structures.txt in the format 'structure:chain'\n") + + with open(f"residue_warning_structures.txt", "w+") as f: + f.write("structure:chain\n") + for structure in big_structures_warning: + for chain in big_structures_warning[structure]: + f.write(f"{structure}:{chain}\n") + return Structure_Sequences_Aligned, Structure_ConversionTemplate, chid_list, check def show_conversiontemplate(Structure_ConversionTemplate): From 301dce4b018dfdc4699b832c5f767cf226f40214 Mon Sep 17 00:00:00 2001 From: Paulina Cabral <137828909+gdkwxn@users.noreply.github.com> Date: Mon, 10 Aug 2026 16:31:10 -0700 Subject: [PATCH 3/5] co-pilot suggestion #2 Changed output file type from txt -> csv Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/pdbcleanresiduestandardizationutils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pdbcleanresiduestandardizationutils.py b/src/pdbcleanresiduestandardizationutils.py index f1cf8b7..dad3104 100644 --- a/src/pdbcleanresiduestandardizationutils.py +++ b/src/pdbcleanresiduestandardizationutils.py @@ -306,9 +306,9 @@ def get_gap_letter(n): print(f"\nWARNING: Some structures were affected by large gaps in most of the MSA (>62 positions), " f"resulting in residue renumbering that requires two-character alternate identifiers. This may lead " f"to problems when opening the structure with molecular visualization software. These structures " - f"will be saved in residue_warning_structures.txt in the format 'structure:chain'\n") + f"will be saved in residue_warning_structures.csv in the format 'structure:chain'\n") - with open(f"residue_warning_structures.txt", "w+") as f: + with open("residue_warning_structures.csv", "w") as f: f.write("structure:chain\n") for structure in big_structures_warning: for chain in big_structures_warning[structure]: From 38849656b64e9d6c771d9ecb288b1d104be09987 Mon Sep 17 00:00:00 2001 From: Paulina Cabral <137828909+gdkwxn@users.noreply.github.com> Date: Mon, 10 Aug 2026 16:59:17 -0700 Subject: [PATCH 4/5] co-pilot suggestion #1 updated the logic behind the assignment of function get_gap_letter(n) Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/pdbcleanresiduestandardizationutils.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/pdbcleanresiduestandardizationutils.py b/src/pdbcleanresiduestandardizationutils.py index dad3104..49d0405 100644 --- a/src/pdbcleanresiduestandardizationutils.py +++ b/src/pdbcleanresiduestandardizationutils.py @@ -109,23 +109,24 @@ def perform_multiple_alignment(Structure_Sequences, ChID_ResiNum_Vector, structi def get_gap_letter(n): """ - Convert a 0-based index into a spreadsheet-style alphabet label. + Convert a 0-based index into a spreadsheet-style alphanumeric label. - Cycles through all single uppercase letters (A-Z) and lowercase letters - (a-z) before moving into multi-letter combinations (AA, AB, ..., zz, AAA...). + Cycles through all single uppercase letters (A-Z), lowercase letters (a-z), and digits (0-9) + before moving into multi-letter combinations (AA, AB, ..., 99, AAA...). Parameters: n (int): The 0-based index to convert. Returns: - str: The corresponding alphabetic label. + str: The corresponding label. """ - alphabet = string.ascii_uppercase + string.ascii_lowercase + alphabet = string.ascii_uppercase + string.ascii_lowercase + string.digits + base = len(alphabet) label = "" n += 1 while n > 0: - n, remainder = divmod(n - 1, 52) + n, remainder = divmod(n - 1, base) label = alphabet[remainder] + label return label From 486f9c4980f6267350d4563075e9670934586a7e Mon Sep 17 00:00:00 2001 From: Paulina Cabral <137828909+gdkwxn@users.noreply.github.com> Date: Mon, 10 Aug 2026 17:03:45 -0700 Subject: [PATCH 5/5] Fix gap_tracker condition from 52 to 62 This takes into consideration the 0-9 identifiers that we included into gap_letter --- src/pdbcleanresiduestandardizationutils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pdbcleanresiduestandardizationutils.py b/src/pdbcleanresiduestandardizationutils.py index 49d0405..cddd851 100644 --- a/src/pdbcleanresiduestandardizationutils.py +++ b/src/pdbcleanresiduestandardizationutils.py @@ -237,7 +237,7 @@ def get_gap_letter(n): #new_res_num.append(str(counter)+"_"+str(gap_tracker)) new_res_num.append(str(counter-1) +" "+str(get_gap_letter(gap_tracker))) - if gap_tracker == 52: + if gap_tracker == 62: structure = (structid_list[I].split("/")[-1]) big_structures_warning.setdefault(structure, []).append(chain) gap_tracker+=1 @@ -538,4 +538,4 @@ def conversiontemplate_to_pdb_FAPA(filelist, Structure_ConversionTemplate, targe else: newciffile.write(line) -# FAPA MAY 2024 TEST ENDS \ No newline at end of file +# FAPA MAY 2024 TEST ENDS