From eb1577a8958fff190d09e8400a7b6a5db6803364 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 3 Mar 2023 12:31:21 +0100 Subject: [PATCH 001/173] load structures first thing --- DockQ.py | 197 ++++++++++++++++--------------------------------------- 1 file changed, 58 insertions(+), 139 deletions(-) diff --git a/DockQ.py b/DockQ.py index 70ad789..f2987b1 100755 --- a/DockQ.py +++ b/DockQ.py @@ -1,19 +1,49 @@ #!/usr/bin/env python -import Bio.PDB -import warnings -from Bio import BiopythonWarning -warnings.simplefilter('ignore', BiopythonWarning) import sys import os import re +import warnings import tempfile +import itertools +import subprocess import numpy as np -from Bio.SVDSuperimposer import SVDSuperimposer from math import sqrt from argparse import ArgumentParser -import itertools -import subprocess +import Bio.PDB +from Bio import pairwise2 +from Bio import BiopythonWarning +from Bio.SVDSuperimposer import SVDSuperimposer +warnings.simplefilter('ignore', BiopythonWarning) + +def align_sequence_features(model_sequence, native_sequence, native_numbering): + """Realigns sequence-specific features between PDB structures and antigen sequences + For example, if from_sequence (the sequence for which features have + been calculated) is missing an amino acid but contains more amino acids + at the C terminal than the to_sequence, the features will be assigned + as in this schematic: + + native_numbering 23456789 + native_sequence_aligned -WEKLAPTG + model_sequence_aligned DWEKLAPT- + model_numbering 12345678-1 + Wherever it is not possible to assign features (missing AA in native_sequence) + a pseudovalue of -1 will be assigned instead + """ + alignment = pairwise2.align.localms( + model_sequence, native_sequence, match=5, mismatch=0, open=-10, extend=-1 + )[0] + model_sequence_aligned = np.array(list(alignment.seqA)) + native_sequence_aligned = np.array(list(alignment.seqB)) + + model_indexes = np.where(model_sequence_aligned != "-")[0] + native_indexes = np.where(native_sequence_aligned != "-")[0] + alignment_length = np.sum((model_sequence_aligned != "-") & (native_sequence_aligned != "-")) + + aligned_numbering = np.zeros(len(model_indexes)) - 1 + aligned_numbering[native_indexes[:alignment_length]] = native_numbering[model_indexes[:alignment_length]] + aligned_numbering = aligned_numbering.tolist() + return aligned_numbering def parse_fnat(fnat_out): fnat=-1; @@ -24,7 +54,6 @@ def parse_fnat(fnat_out): model_total=-1 inter=[] for line in fnat_out.split("\n"): -# print line line=line.rstrip('\n') match=re.search(r'NATIVE: (\d+)(\w) (\d+)(\w)',line) if(re.search(r'^Fnat',line)): @@ -38,12 +67,10 @@ def parse_fnat(fnat_out): nonnat_count=int(list[1]) model_total=int(list[2]) elif(match): - #print line res1=match.group(1) chain1=match.group(2) res2=match.group(3) chain2=match.group(4) - # print res1 + ' ' + chain1 + ' ' + res2 + ' ' + chain2 inter.append(res1 + chain1) inter.append(res2 + chain2) return (fnat,nat_correct,nat_total,fnonnat,nonnat_count,model_total,inter) @@ -97,7 +124,6 @@ def capri_class_DockQ(DockQ,capri_peptide=False): def calc_DockQ(model,native,use_CA_only=False,capri_peptide=False): -# exec_path=os.path.dirname(os.path.abspath(sys.argv[0])) exec_path=os.path.dirname(os.path.abspath(__file__)) atom_for_sup=['CA','C','N','O'] if(use_CA_only): @@ -113,22 +139,13 @@ def calc_DockQ(model,native,use_CA_only=False,capri_peptide=False): fnat_out = os.popen(cmd_fnat).read() - #fnat_out = subprocess.getoutput(cmd_fnat) - #print(fnat_out) - # sys.exit() (fnat,nat_correct,nat_total,fnonnat,nonnat_count,model_total,interface5A)=parse_fnat(fnat_out) assert fnat!=-1, "Error running cmd: %s\n" % (cmd_fnat) inter_out = os.popen(cmd_interface).read() -# inter_out = subprocess.getoutput(cmd_interface) (fnat_bb,nat_correct_bb,nat_total_bb,fnonnat_bb,nonnat_count_bb,model_total_bb,interface)=parse_fnat(inter_out) assert fnat_bb!=-1, "Error running cmd: %s\n" % (cmd_interface) - #print fnat - #Use same interface as for fnat for iRMS - #interface=interface5A - - # Start the parser pdb_parser = Bio.PDB.PDBParser(QUIET = True) @@ -156,11 +173,8 @@ def calc_DockQ(model,native,use_CA_only=False,capri_peptide=False): atoms_def_in_both=[] #first read in sample for sample_chain in sample_model: -# print sample_chain chain=sample_chain.id -# print chain for sample_res in sample_chain: - # print sample_res if sample_res.get_id()[0] != ' ': #Skip hetatm. continue resname=sample_res.get_id()[1] @@ -176,9 +190,7 @@ def calc_DockQ(model,native,use_CA_only=False,capri_peptide=False): for ref_chain in ref_model: chain=ref_chain.id for ref_res in ref_chain: - #print ref_res if ref_res.get_id()[0] != ' ': #Skip hetatm. -# print ref_res.get_id() continue resname=ref_res.get_id()[1] key=str(resname) + chain @@ -190,7 +202,6 @@ def calc_DockQ(model,native,use_CA_only=False,capri_peptide=False): atoms_def_in_both.append(atom_key) -# print atoms_def_in_both for sample_chain in sample_model: chain=sample_chain.id if chain not in list(chain_res.keys()): @@ -208,8 +219,6 @@ def calc_DockQ(model,native,use_CA_only=False,capri_peptide=False): sample_atoms.append(sample_res[a]) common_interface.append(key) - #print inter_pairs - chain_ref={} common_residues=[] @@ -218,7 +227,6 @@ def calc_DockQ(model,native,use_CA_only=False,capri_peptide=False): # Iterate of all chains in the model in order to find all residues for ref_chain in ref_model: # Iterate of all residues in each model in order to find proper atoms - # print dir(ref_chain) chain=ref_chain.id if chain not in list(chain_ref.keys()): chain_ref[chain]=[] @@ -228,9 +236,6 @@ def calc_DockQ(model,native,use_CA_only=False,capri_peptide=False): resname=ref_res.get_id()[1] key=str(resname) + chain - #print ref_res - # print key - # print chain_res.values() if key in chain_res[chain]: # if key is present in sample #print key for a in atom_for_sup: @@ -238,18 +243,15 @@ def calc_DockQ(model,native,use_CA_only=False,capri_peptide=False): if a in ref_res and atom_key in atoms_def_in_both: chain_ref[chain].append(ref_res[a]) common_residues.append(key) - #chain_sample.append((ref_res['CA']) if key in common_interface: # Check if residue number ( .get_id() ) is in the list # Append CA atom to list - #print key for a in atom_for_sup: atom_key=key + '.' + a - #print atom_key if a in ref_res and atom_key in atoms_def_in_both: ref_atoms.append(ref_res[a]) - + print(np.asarray([r.get_coord() for r in ref_atoms]).shape) #get the ones that are present in native chain_sample={} @@ -267,12 +269,6 @@ def calc_DockQ(model,native,use_CA_only=False,capri_peptide=False): atom_key=key + '.' + a if a in sample_res and atom_key in atoms_def_in_both: chain_sample[chain].append(sample_res[a]) - - #if key in common_residues: - # print key - #sample_atoms.append(sample_res['CA']) - #common_interface.append(key) - assert len(ref_atoms)!=0, "length of native is zero" assert len(sample_atoms)!=0, "length of model is zero" @@ -282,7 +278,6 @@ def calc_DockQ(model,native,use_CA_only=False,capri_peptide=False): super_imposer.set_atoms(ref_atoms, sample_atoms) super_imposer.apply(sample_model.get_atoms()) - # Print RMSD: irms=super_imposer.rms (chain1,chain2)=list(chain_sample.keys()) @@ -303,33 +298,12 @@ def calc_DockQ(model,native,use_CA_only=False,capri_peptide=False): class1='receptor' class2='ligand' - - - #print len1 - #print len2 - #print chain_sample.keys() - #Set to align on receptor assert len(chain_ref[receptor_chain])==len(chain_sample[receptor_chain]), "Different number of atoms in native and model receptor (chain %c) %d %d\n" % (receptor_chain,len(chain_ref[receptor_chain]),len(chain_sample[receptor_chain])) super_imposer.set_atoms(chain_ref[receptor_chain], chain_sample[receptor_chain]) super_imposer.apply(sample_model.get_atoms()) receptor_chain_rms=super_imposer.rms - #print receptor_chain_rms - #print dir(super_imposer) - #print chain1_rms - - #Grep out the transformed ligand coords - - #print ligand_chain - - #print chain_ref[ligand_chain] - #print chain_sample[ligand_chain] - #l1=len(chain_ref[ligand_chain]) - #l2=len(chain_sample[ligand_chain]) - - - assert len(chain_ref[ligand_chain])!=0 or len(chain_sample[ligand_chain])!=0, "Zero number of equivalent atoms in native and model ligand (chain %s) %d %d.\nCheck that the residue numbers in model and native is consistent\n" % (ligand_chain,len(chain_ref[ligand_chain]),len(chain_sample[ligand_chain])) @@ -339,27 +313,9 @@ def calc_DockQ(model,native,use_CA_only=False,capri_peptide=False): coord1=np.array([atom.coord for atom in chain_ref[ligand_chain]]) coord2=np.array([atom.coord for atom in chain_sample[ligand_chain]]) - #coord1=np.array([atom.coord for atom in chain_ref[receptor_chain]]) - #coord2=np.array([atom.coord for atom in chain_sample[receptor_chain]]) - - #print len(coord1) - #print len(coord2) - sup=SVDSuperimposer() Lrms = sup._rms(coord1,coord2) #using the private _rms function which does not superimpose - - #super_imposer.set_atoms(chain_ref[ligand_chain], chain_sample[ligand_chain]) - #super_imposer.apply(sample_model.get_atoms()) - #coord1=np.array([atom.coord for atom in chain_ref[receptor_chain]]) - #coord2=np.array([atom.coord for atom in chain_sample[receptor_chain]]) - #Rrms= sup._rms(coord1,coord2) - #should give same result as above line - #diff = coord1-coord2 - #l = len(diff) #number of atoms - #from math import sqrt - #print sqrt(sum(sum(diff*diff))/l) - #print np.sqrt(np.sum(diff**2)/l) DockQ=(float(fnat) + 1/(1+(irms/1.5)*(irms/1.5)) + 1/(1+(Lrms/8.5)*(Lrms/8.5)))/3 info={} info['DockQ']=DockQ @@ -432,14 +388,8 @@ def make_two_chain_pdb_perm(pdb,group1,group2): #not yet ready if chain not in pdb_chains: pdb_chains[chain]=[] pdb_chains[chain].append(line) - # print line - # s[21]='B' - # print "".join(s) -# print chain - f.close() - #sys.exit() (code,outfile)=tempfile.mkstemp() f=open(outfile,'w') for c in group1: @@ -449,7 +399,6 @@ def make_two_chain_pdb_perm(pdb,group1,group2): #not yet ready for c in group2: f.write(change_chain(pdb_chains[c],"B")) f.close(); - #print outfile exec_path=os.path.dirname(os.path.abspath(sys.argv[0])) cmd=exec_path + '/scripts/renumber_pdb.pl ' + outfile os.system(cmd) @@ -470,48 +419,41 @@ def main(): parser.add_argument('-no_needle',default=False,action='store_true',help='do not use global alignment to fix residue numbering between native and model during chain permutation (use only in case needle is not installed, and the residues between the chains are identical') parser.add_argument('-perm1',default=False,action='store_true',help='use all chain1 permutations to find maximum DockQ (number of comparisons is n! = 24, if combined with -perm2 there will be n!*m! combinations') parser.add_argument('-perm2',default=False,action='store_true',help='use all chain2 permutations to find maximum DockQ (number of comparisons is n! = 24, if combined with -perm1 there will be n!*m! combinations') -# parser.add_argument('-comb',default=False,action='store_true',help='use all cyclicchain permutations to find maximum DockQ (number of comparisons is n!*m! = 24*24 = 576 for two tetramers interacting') parser.add_argument('-model_chain1',metavar='model_chain1', type=str,nargs='+', help='pdb chain order to group together partner 1') parser.add_argument('-model_chain2',metavar='model_chain2', type=str,nargs='+', help='pdb chain order to group together partner 2 (complement to partner 1 if undef)') parser.add_argument('-native_chain1',metavar='native_chain1', type=str,nargs='+', help='pdb chain order to group together from native partner 1') parser.add_argument('-native_chain2',metavar='native_chain2', type=str,nargs='+', help='pdb chain order to group together from native partner 2 (complement to partner 1 if undef)') - args = parser.parse_args() - #bio_ver=1.64 + bio_ver=1.61 if(float(Bio.__version__) < bio_ver): print("Biopython version (%s) is too old need at least >=%.2f" % (Bio.__version__,bio_ver)) sys.exit() -# if(len(sys.argv)!=3): -# print "Usage: ./Dock.py " -# sys.exit() - -# print args -# print args.model[0] -# sys.exit() -# model=sys.argv[1] -# native=sys.argv[2] - exec_path=os.path.dirname(os.path.abspath(sys.argv[0])) fix_numbering=exec_path + '/scripts/fix_numbering.pl' model=args.model[0] - model_in=model native=args.native[0] - native_in=native use_CA_only=args.useCA capri_peptide=args.capri_peptide + + # Start the parser + pdb_parser = Bio.PDB.PDBParser(QUIET = True) + + # Get the structures + native_structure = pdb_parser.get_structure("reference", native)[0] + model_structure = pdb_parser.get_structure("model", model)[0] + model_chains=[] native_chains=[] best_info='' if(not args.skip_check): - model_chains=get_pdb_chains(model) - native_chains=get_pdb_chains(native) + model_chains = [c.id for c in model_structure] + native_chains = [c.id for c in native_structure] files_to_clean=[] -# print native_chains if((len(model_chains) > 2 or len(native_chains) > 2) and (args.model_chain1 == None and args.native_chain1 == None)): print("Multi-chain model need sets of chains to group\nuse -native_chain1 and/or -model_chain1 if you want a different mapping than 1-1") @@ -557,12 +499,6 @@ def main(): group1=nat_group1 group2=nat_group2 - #print group1 - #print group2 - - #print "native" - #print nat_group1 - #print nat_group2 if(args.verbose): print('Merging ' + ''.join(group1) + ' -> ' + ''.join(nat_group1) + ' to chain A') print('Merging ' + ''.join(group2) + ' -> ' + ''.join(nat_group2) + ' to chain B') @@ -591,24 +527,18 @@ def main(): for g1 in combos1: for g2 in combos2: pe=pe+1 - # print str(g1)+' '+str(g2) -# print pe -# print group1 -# print group2 pe_tot=pe pe=1 - #sys.exit() if args.verbose: print('Starting chain order permutation search (number of permutations: ' + str(pe_tot) + ')') for g1 in combos1: for g2 in combos2: - #g2=group2 model_renum=make_two_chain_pdb_perm(model_in,g1,g2) model_fixed=model_renum if not args.no_needle: + fix_numbering_cmd=fix_numbering + ' ' + model_renum + ' ' + native + ' > /dev/null' model_fixed=model_renum + ".fixed" - # print fix_numbering_cmd os.system(fix_numbering_cmd) os.remove(model_renum) if not os.path.exists(model_fixed): @@ -632,14 +562,12 @@ def main(): pe=pe+1 if not args.quiet: print(best_info) -# print 'Best score ( ' + str(best_DockQ) +' ) found for ' + str(best_g1) + ' ' + str(best_g2) else: model_renum=make_two_chain_pdb_perm(model,group1,group2) model_fixed=model_renum if not args.no_needle: fix_numbering_cmd=fix_numbering + ' ' + model_renum + ' ' + native + ' > /dev/null' model_fixed=model_renum + ".fixed" -# print fix_numbering_cmd os.system(fix_numbering_cmd) os.remove(model_renum) if not os.path.exists(model_fixed): @@ -647,18 +575,11 @@ def main(): sys.exit() info=calc_DockQ(model_fixed,native,use_CA_only) - #os.system('cp ' + native + ' native_multichain.pdb') - #os.system('cp ' + model_fixed + ' .') + os.remove(model_fixed) -# files_to_clean.append(model) -# files_to_clean.append(model_fixed) - # sys.exit() - - # print native - # print model + else: info=calc_DockQ(model,native,use_CA_only=use_CA_only,capri_peptide=capri_peptide) #False): -# info=calc_DockQ(model,native,use_CA_only=) irms=info['irms'] Lrms=info['Lrms'] @@ -668,9 +589,9 @@ def main(): if(args.short): if capri_peptide: - print(("DockQ-capri_peptide %.3f Fnat %.3f iRMS %.3f LRMS %.3f Fnonnat %.3f %s %s %s" % (DockQ,fnat,irms,Lrms,fnonnat,model_in,native_in,best_info))) + print(("DockQ-capri_peptide %.3f Fnat %.3f iRMS %.3f LRMS %.3f Fnonnat %.3f %s %s %s" % (DockQ,fnat,irms,Lrms,fnonnat,model,native_in,best_info))) else: - print(("DockQ %.3f Fnat %.3f iRMS %.3f LRMS %.3f Fnonnat %.3f %s %s %s" % (DockQ,fnat,irms,Lrms,fnonnat,model_in,native_in,best_info))) + print(("DockQ %.3f Fnat %.3f iRMS %.3f LRMS %.3f Fnonnat %.3f %s %s %s" % (DockQ,fnat,irms,Lrms,fnonnat,model_in,native,best_info))) else: if capri_peptide: @@ -703,8 +624,8 @@ def main(): print('* For comments, please email: bjorn.wallner@.liu.se *') print('* *') print('****************************************************************') - print(("Model : %s" % model_in)) - print(("Native : %s" % native_in)) + print(("Model : %s" % model)) + print(("Native : %s" % native)) if len(best_info): print(best_info) print('Number of equivalent residues in chain ' + info['chain1'] + ' ' + str(info['len1']) + ' (' + info['class1'] + ')') @@ -713,13 +634,10 @@ def main(): print(("Fnonnat %.3f %d non-native of %d model contacts" % (info['fnonnat'],info['nonnat_count'],info['model_total']))) print(("iRMS %.3f" % irms)) print(("LRMS %.3f" % Lrms)) - # print 'CAPRI ' + capri_class(fnat,irms,Lrms,capri_peptide=capri_peptide) peptide_suffix='' if capri_peptide: peptide_suffix='_peptide' - #print('CAPRI use DockQ instead.') - #print(('CAPRI{} {}'.format(peptide_suffix,capri_class(fnat,irms,Lrms,capri_peptide=capri_peptide)))) - #print('DockQ_CAPRI ' + capri_class_DockQ(DockQ,capri_peptide=capri_peptide)) + peptide_disclaimer='' if capri_peptide: peptide_disclaimer='DockQ not reoptimized for CAPRI peptide evaluation' @@ -730,3 +648,4 @@ def main(): if __name__ == '__main__': main() + \ No newline at end of file From 742b8eaa7048de152fbea8271e44255ad026ca63 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 3 Mar 2023 12:36:02 +0100 Subject: [PATCH 002/173] model_in is not used --- DockQ.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/DockQ.py b/DockQ.py index f2987b1..be03bee 100755 --- a/DockQ.py +++ b/DockQ.py @@ -533,7 +533,7 @@ def main(): print('Starting chain order permutation search (number of permutations: ' + str(pe_tot) + ')') for g1 in combos1: for g2 in combos2: - model_renum=make_two_chain_pdb_perm(model_in,g1,g2) + model_renum=make_two_chain_pdb_perm(model,g1,g2) model_fixed=model_renum if not args.no_needle: @@ -591,7 +591,7 @@ def main(): if capri_peptide: print(("DockQ-capri_peptide %.3f Fnat %.3f iRMS %.3f LRMS %.3f Fnonnat %.3f %s %s %s" % (DockQ,fnat,irms,Lrms,fnonnat,model,native_in,best_info))) else: - print(("DockQ %.3f Fnat %.3f iRMS %.3f LRMS %.3f Fnonnat %.3f %s %s %s" % (DockQ,fnat,irms,Lrms,fnonnat,model_in,native,best_info))) + print(("DockQ %.3f Fnat %.3f iRMS %.3f LRMS %.3f Fnonnat %.3f %s %s %s" % (DockQ,fnat,irms,Lrms,fnonnat,model,native,best_info))) else: if capri_peptide: @@ -648,4 +648,3 @@ def main(): if __name__ == '__main__': main() - \ No newline at end of file From a197ba6d294998c338f2abcecb1db3667804967f Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 3 Mar 2023 15:35:39 +0100 Subject: [PATCH 003/173] blacken, alignment functions --- DockQ.py | 1056 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 671 insertions(+), 385 deletions(-) diff --git a/DockQ.py b/DockQ.py index be03bee..48ef547 100755 --- a/DockQ.py +++ b/DockQ.py @@ -13,8 +13,11 @@ import Bio.PDB from Bio import pairwise2 from Bio import BiopythonWarning +from Bio.SeqUtils import seq1 from Bio.SVDSuperimposer import SVDSuperimposer -warnings.simplefilter('ignore', BiopythonWarning) + +warnings.simplefilter("ignore", BiopythonWarning) + def align_sequence_features(model_sequence, native_sequence, native_numbering): """Realigns sequence-specific features between PDB structures and antigen sequences @@ -38,116 +41,154 @@ def align_sequence_features(model_sequence, native_sequence, native_numbering): model_indexes = np.where(model_sequence_aligned != "-")[0] native_indexes = np.where(native_sequence_aligned != "-")[0] - alignment_length = np.sum((model_sequence_aligned != "-") & (native_sequence_aligned != "-")) + alignment_length = np.sum( + (model_sequence_aligned != "-") & (native_sequence_aligned != "-") + ) + + aligned_numbering = np.empty(len(model_indexes), dtype=object) + for i in range(len(model_indexes)): + aligned_numbering[i] = ("-", -1) + aligned_numbering[native_indexes[:alignment_length]] = native_numbering[ + model_indexes[:alignment_length] + ] - aligned_numbering = np.zeros(len(model_indexes)) - 1 - aligned_numbering[native_indexes[:alignment_length]] = native_numbering[model_indexes[:alignment_length]] - aligned_numbering = aligned_numbering.tolist() return aligned_numbering + def parse_fnat(fnat_out): - fnat=-1; - nat_correct=-1 - nat_total=-1 - fnonnat=-1 - nonnat_count=-1 - model_total=-1 - inter=[] + fnat = -1 + nat_correct = -1 + nat_total = -1 + fnonnat = -1 + nonnat_count = -1 + model_total = -1 + inter = [] for line in fnat_out.split("\n"): - line=line.rstrip('\n') - match=re.search(r'NATIVE: (\d+)(\w) (\d+)(\w)',line) - if(re.search(r'^Fnat',line)): - list=line.split(' ') - fnat=float(list[3]) - nat_correct=int(list[1]) - nat_total=int(list[2]) - elif(re.search(r'^Fnonnat',line)): - list=line.split(' ') - fnonnat=float(list[3]) - nonnat_count=int(list[1]) - model_total=int(list[2]) - elif(match): - res1=match.group(1) - chain1=match.group(2) - res2=match.group(3) - chain2=match.group(4) + line = line.rstrip("\n") + match = re.search(r"NATIVE: (\d+)(\w) (\d+)(\w)", line) + if re.search(r"^Fnat", line): + list = line.split(" ") + fnat = float(list[3]) + nat_correct = int(list[1]) + nat_total = int(list[2]) + elif re.search(r"^Fnonnat", line): + list = line.split(" ") + fnonnat = float(list[3]) + nonnat_count = int(list[1]) + model_total = int(list[2]) + elif match: + res1 = match.group(1) + chain1 = match.group(2) + res2 = match.group(3) + chain2 = match.group(4) inter.append(res1 + chain1) inter.append(res2 + chain2) - return (fnat,nat_correct,nat_total,fnonnat,nonnat_count,model_total,inter) + return (fnat, nat_correct, nat_total, fnonnat, nonnat_count, model_total, inter) -def capri_class(fnat,iRMS,LRMS,capri_peptide=False): +def capri_class(fnat, iRMS, LRMS, capri_peptide=False): if capri_peptide: - - if(fnat < 0.2 or (LRMS > 5.0 and iRMS > 2.0)): - return 'Incorrect' - elif((fnat >= 0.2 and fnat < 0.5) and (LRMS <= 5.0 or iRMS <= 2.0) or (fnat >= 0.5 and LRMS > 2.0 and iRMS > 1.0)): - return 'Acceptable' - elif((fnat >= 0.5 and fnat < 0.8) and (LRMS <= 2.0 or iRMS <= 1.0) or (fnat >= 0.8 and LRMS > 1.0 and iRMS > 0.5)): - return 'Medium' - elif(fnat >= 0.8 and (LRMS <= 1.0 or iRMS <= 0.5)): - return 'High' + + if fnat < 0.2 or (LRMS > 5.0 and iRMS > 2.0): + return "Incorrect" + elif ( + (fnat >= 0.2 and fnat < 0.5) + and (LRMS <= 5.0 or iRMS <= 2.0) + or (fnat >= 0.5 and LRMS > 2.0 and iRMS > 1.0) + ): + return "Acceptable" + elif ( + (fnat >= 0.5 and fnat < 0.8) + and (LRMS <= 2.0 or iRMS <= 1.0) + or (fnat >= 0.8 and LRMS > 1.0 and iRMS > 0.5) + ): + return "Medium" + elif fnat >= 0.8 and (LRMS <= 1.0 or iRMS <= 0.5): + return "High" else: - return 'Undef' + return "Undef" else: - if(fnat < 0.1 or (LRMS > 10.0 and iRMS > 4.0)): - return 'Incorrect' - elif((fnat >= 0.1 and fnat < 0.3) and (LRMS <= 10.0 or iRMS <= 4.0) or (fnat >= 0.3 and LRMS > 5.0 and iRMS > 2.0)): - return 'Acceptable' - elif((fnat >= 0.3 and fnat < 0.5) and (LRMS <= 5.0 or iRMS <= 2.0) or (fnat >= 0.5 and LRMS > 1.0 and iRMS > 1.0)): - return 'Medium' - elif(fnat >= 0.5 and (LRMS <= 1.0 or iRMS <= 1.0)): - return 'High' + if fnat < 0.1 or (LRMS > 10.0 and iRMS > 4.0): + return "Incorrect" + elif ( + (fnat >= 0.1 and fnat < 0.3) + and (LRMS <= 10.0 or iRMS <= 4.0) + or (fnat >= 0.3 and LRMS > 5.0 and iRMS > 2.0) + ): + return "Acceptable" + elif ( + (fnat >= 0.3 and fnat < 0.5) + and (LRMS <= 5.0 or iRMS <= 2.0) + or (fnat >= 0.5 and LRMS > 1.0 and iRMS > 1.0) + ): + return "Medium" + elif fnat >= 0.5 and (LRMS <= 1.0 or iRMS <= 1.0): + return "High" else: - return 'Undef' + return "Undef" -def capri_class_DockQ(DockQ,capri_peptide=False): +def capri_class_DockQ(DockQ, capri_peptide=False): if capri_peptide: - return 'Undef for capri_peptides' - - (c1,c2,c3)=(0.23,0.49,0.80) - if(DockQ < c1): - return 'Incorrect' - elif(DockQ >= c1 and DockQ < c2): - return 'Acceptable' - elif(DockQ >= c2 and DockQ < c3): - return 'Medium' - elif(DockQ >= c3): - return 'High' + return "Undef for capri_peptides" + + (c1, c2, c3) = (0.23, 0.49, 0.80) + if DockQ < c1: + return "Incorrect" + elif DockQ >= c1 and DockQ < c2: + return "Acceptable" + elif DockQ >= c2 and DockQ < c3: + return "Medium" + elif DockQ >= c3: + return "High" else: - return 'Undef' + return "Undef" -def calc_DockQ(model,native,use_CA_only=False,capri_peptide=False): - - exec_path=os.path.dirname(os.path.abspath(__file__)) - atom_for_sup=['CA','C','N','O'] - if(use_CA_only): - atom_for_sup=['CA'] +def calc_DockQ(model, native, use_CA_only=False, capri_peptide=False): + exec_path = os.path.dirname(os.path.abspath(__file__)) + atom_for_sup = ["CA", "C", "N", "O"] + if use_CA_only: + atom_for_sup = ["CA"] - cmd_fnat=exec_path + '/fnat ' + model + ' ' + native + ' 5 -all' - cmd_interface=exec_path + '/fnat ' + model + ' ' + native + ' 10 -all' + cmd_fnat = exec_path + "/fnat " + model + " " + native + " 5 -all" + cmd_interface = exec_path + "/fnat " + model + " " + native + " 10 -all" if capri_peptide: - cmd_fnat=exec_path + '/fnat ' + model + ' ' + native + ' 4 -all' - cmd_interface=exec_path + '/fnat ' + model + ' ' + native + ' 8 -cb' + cmd_fnat = exec_path + "/fnat " + model + " " + native + " 4 -all" + cmd_interface = exec_path + "/fnat " + model + " " + native + " 8 -cb" fnat_out = os.popen(cmd_fnat).read() - (fnat,nat_correct,nat_total,fnonnat,nonnat_count,model_total,interface5A)=parse_fnat(fnat_out) - assert fnat!=-1, "Error running cmd: %s\n" % (cmd_fnat) + ( + fnat, + nat_correct, + nat_total, + fnonnat, + nonnat_count, + model_total, + interface5A, + ) = parse_fnat(fnat_out) + assert fnat != -1, "Error running cmd: %s\n" % (cmd_fnat) inter_out = os.popen(cmd_interface).read() - - (fnat_bb,nat_correct_bb,nat_total_bb,fnonnat_bb,nonnat_count_bb,model_total_bb,interface)=parse_fnat(inter_out) - assert fnat_bb!=-1, "Error running cmd: %s\n" % (cmd_interface) + + ( + fnat_bb, + nat_correct_bb, + nat_total_bb, + fnonnat_bb, + nonnat_count_bb, + model_total_bb, + interface, + ) = parse_fnat(inter_out) + assert fnat_bb != -1, "Error running cmd: %s\n" % (cmd_interface) # Start the parser - pdb_parser = Bio.PDB.PDBParser(QUIET = True) + pdb_parser = Bio.PDB.PDBParser(QUIET=True) # Get the structures ref_structure = pdb_parser.get_structure("reference", native) @@ -155,7 +196,7 @@ def calc_DockQ(model,native,use_CA_only=False,capri_peptide=False): # Use the first model in the pdb-files for alignment # Change the number 0 if you want to align to another structure - ref_model = ref_structure[0] + ref_model = ref_structure[0] sample_model = sample_structure[0] # Make a list of the atoms (in the structures) you wish to align. @@ -163,488 +204,733 @@ def calc_DockQ(model,native,use_CA_only=False,capri_peptide=False): ref_atoms = [] sample_atoms = [] - common_interface=[] + common_interface = [] - chain_res={} + chain_res = {} - - #find atoms common in both sample and native - atoms_def_sample=[] - atoms_def_in_both=[] - #first read in sample + # find atoms common in both sample and native + atoms_def_sample = [] + atoms_def_in_both = [] + # first read in sample for sample_chain in sample_model: - chain=sample_chain.id + chain = sample_chain.id for sample_res in sample_chain: - if sample_res.get_id()[0] != ' ': #Skip hetatm. + if sample_res.get_id()[0] != " ": # Skip hetatm. continue - resname=sample_res.get_id()[1] - key=str(resname) + chain + resname = sample_res.get_id()[1] + key = str(resname) + chain for a in atom_for_sup: - atom_key=key + '.' + a + atom_key = key + "." + a if a in sample_res: if atom_key in atoms_def_sample: - print(atom_key + ' already added (MODEL)!!!') + print(atom_key + " already added (MODEL)!!!") atoms_def_sample.append(atom_key) - #then read in native also present in sample + # then read in native also present in sample for ref_chain in ref_model: - chain=ref_chain.id + chain = ref_chain.id for ref_res in ref_chain: - if ref_res.get_id()[0] != ' ': #Skip hetatm. + if ref_res.get_id()[0] != " ": # Skip hetatm. continue - resname=ref_res.get_id()[1] - key=str(resname) + chain + resname = ref_res.get_id()[1] + key = str(resname) + chain for a in atom_for_sup: - atom_key=key + '.' + a + atom_key = key + "." + a if a in ref_res and atom_key in atoms_def_sample: if atom_key in atoms_def_in_both: - print(atom_key + ' already added (Native)!!!') + print(atom_key + " already added (Native)!!!") atoms_def_in_both.append(atom_key) - for sample_chain in sample_model: - chain=sample_chain.id + chain = sample_chain.id if chain not in list(chain_res.keys()): - chain_res[chain]=[] + chain_res[chain] = [] for sample_res in sample_chain: - if sample_res.get_id()[0] != ' ': #Skip hetatm. + if sample_res.get_id()[0] != " ": # Skip hetatm. continue - resname=sample_res.get_id()[1] - key=str(resname) + chain + resname = sample_res.get_id()[1] + key = str(resname) + chain chain_res[chain].append(key) if key in interface: for a in atom_for_sup: - atom_key=key + '.' + a + atom_key = key + "." + a if a in sample_res and atom_key in atoms_def_in_both: sample_atoms.append(sample_res[a]) common_interface.append(key) - chain_ref={} - common_residues=[] - - + chain_ref = {} + common_residues = [] # Iterate of all chains in the model in order to find all residues for ref_chain in ref_model: # Iterate of all residues in each model in order to find proper atoms - chain=ref_chain.id + chain = ref_chain.id if chain not in list(chain_ref.keys()): - chain_ref[chain]=[] + chain_ref[chain] = [] for ref_res in ref_chain: - if ref_res.get_id()[0] != ' ': #Skip hetatm. + if ref_res.get_id()[0] != " ": # Skip hetatm. continue - resname=ref_res.get_id()[1] - key=str(resname) + chain + resname = ref_res.get_id()[1] + key = str(resname) + chain - if key in chain_res[chain]: # if key is present in sample - #print key + if key in chain_res[chain]: # if key is present in sample + # print key for a in atom_for_sup: - atom_key=key + '.' + a + atom_key = key + "." + a if a in ref_res and atom_key in atoms_def_in_both: chain_ref[chain].append(ref_res[a]) common_residues.append(key) if key in common_interface: - # Check if residue number ( .get_id() ) is in the list - # Append CA atom to list + # Check if residue number ( .get_id() ) is in the list + # Append CA atom to list for a in atom_for_sup: - atom_key=key + '.' + a + atom_key = key + "." + a if a in ref_res and atom_key in atoms_def_in_both: ref_atoms.append(ref_res[a]) print(np.asarray([r.get_coord() for r in ref_atoms]).shape) - #get the ones that are present in native - chain_sample={} + # get the ones that are present in native + chain_sample = {} for sample_chain in sample_model: - chain=sample_chain.id + chain = sample_chain.id if chain not in list(chain_sample.keys()): - chain_sample[chain]=[] + chain_sample[chain] = [] for sample_res in sample_chain: - if sample_res.get_id()[0] != ' ': #Skip hetatm. + if sample_res.get_id()[0] != " ": # Skip hetatm. continue - resname=sample_res.get_id()[1] - key=str(resname) + chain + resname = sample_res.get_id()[1] + key = str(resname) + chain if key in common_residues: for a in atom_for_sup: - atom_key=key + '.' + a + atom_key = key + "." + a if a in sample_res and atom_key in atoms_def_in_both: chain_sample[chain].append(sample_res[a]) - - assert len(ref_atoms)!=0, "length of native is zero" - assert len(sample_atoms)!=0, "length of model is zero" - assert len(ref_atoms)==len(sample_atoms), "Different number of atoms in native and model %d %d\n" % (len(ref_atoms),len(sample_atoms)) + + assert len(ref_atoms) != 0, "length of native is zero" + assert len(sample_atoms) != 0, "length of model is zero" + assert len(ref_atoms) == len(sample_atoms), ( + "Different number of atoms in native and model %d %d\n" + % (len(ref_atoms), len(sample_atoms)) + ) super_imposer = Bio.PDB.Superimposer() super_imposer.set_atoms(ref_atoms, sample_atoms) super_imposer.apply(sample_model.get_atoms()) - irms=super_imposer.rms + irms = super_imposer.rms - (chain1,chain2)=list(chain_sample.keys()) + (chain1, chain2) = list(chain_sample.keys()) - ligand_chain=chain1 - receptor_chain=chain2 - len1=len(chain_res[chain1]) - len2=len(chain_res[chain2]) + ligand_chain = chain1 + receptor_chain = chain2 + len1 = len(chain_res[chain1]) + len2 = len(chain_res[chain2]) - assert len1!=0, "%s chain has zero length!\n" % chain1 - assert len2!=0, "%s chain has zero length!\n" % chain2 + assert len1 != 0, "%s chain has zero length!\n" % chain1 + assert len2 != 0, "%s chain has zero length!\n" % chain2 - class1='ligand' - class2='receptor' - if(len(chain_sample[chain1]) > len(chain_sample[chain2])): - receptor_chain=chain1 - ligand_chain=chain2 - class1='receptor' - class2='ligand' + class1 = "ligand" + class2 = "receptor" + if len(chain_sample[chain1]) > len(chain_sample[chain2]): + receptor_chain = chain1 + ligand_chain = chain2 + class1 = "receptor" + class2 = "ligand" - #Set to align on receptor - assert len(chain_ref[receptor_chain])==len(chain_sample[receptor_chain]), "Different number of atoms in native and model receptor (chain %c) %d %d\n" % (receptor_chain,len(chain_ref[receptor_chain]),len(chain_sample[receptor_chain])) + # Set to align on receptor + assert len(chain_ref[receptor_chain]) == len(chain_sample[receptor_chain]), ( + "Different number of atoms in native and model receptor (chain %c) %d %d\n" + % ( + receptor_chain, + len(chain_ref[receptor_chain]), + len(chain_sample[receptor_chain]), + ) + ) super_imposer.set_atoms(chain_ref[receptor_chain], chain_sample[receptor_chain]) super_imposer.apply(sample_model.get_atoms()) - receptor_chain_rms=super_imposer.rms + receptor_chain_rms = super_imposer.rms + + assert len(chain_ref[ligand_chain]) != 0 or len(chain_sample[ligand_chain]) != 0, ( + "Zero number of equivalent atoms in native and model ligand (chain %s) %d %d.\nCheck that the residue numbers in model and native is consistent\n" + % (ligand_chain, len(chain_ref[ligand_chain]), len(chain_sample[ligand_chain])) + ) + + assert len(chain_ref[ligand_chain]) == len(chain_sample[ligand_chain]), ( + "Different number of atoms in native and model ligand (chain %c) %d %d\n" + % (ligand_chain, len(chain_ref[ligand_chain]), len(chain_sample[ligand_chain])) + ) + + coord1 = np.array([atom.coord for atom in chain_ref[ligand_chain]]) + coord2 = np.array([atom.coord for atom in chain_sample[ligand_chain]]) + + sup = SVDSuperimposer() + Lrms = sup._rms( + coord1, coord2 + ) # using the private _rms function which does not superimpose + + DockQ = ( + float(fnat) + + 1 / (1 + (irms / 1.5) * (irms / 1.5)) + + 1 / (1 + (Lrms / 8.5) * (Lrms / 8.5)) + ) / 3 + info = {} + info["DockQ"] = DockQ + info["irms"] = irms + info["Lrms"] = Lrms + info["fnat"] = fnat + info["nat_correct"] = nat_correct + info["nat_total"] = nat_total + + info["fnonnat"] = fnonnat + info["nonnat_count"] = nonnat_count + info["model_total"] = model_total + + info["chain1"] = chain1 + info["chain2"] = chain2 + info["len1"] = len1 + info["len2"] = len2 + info["class1"] = class1 + info["class2"] = class2 - assert len(chain_ref[ligand_chain])!=0 or len(chain_sample[ligand_chain])!=0, "Zero number of equivalent atoms in native and model ligand (chain %s) %d %d.\nCheck that the residue numbers in model and native is consistent\n" % (ligand_chain,len(chain_ref[ligand_chain]),len(chain_sample[ligand_chain])) - - - assert len(chain_ref[ligand_chain])==len(chain_sample[ligand_chain]), "Different number of atoms in native and model ligand (chain %c) %d %d\n" % (ligand_chain,len(chain_ref[ligand_chain]),len(chain_sample[ligand_chain])) - - coord1=np.array([atom.coord for atom in chain_ref[ligand_chain]]) - coord2=np.array([atom.coord for atom in chain_sample[ligand_chain]]) - - sup=SVDSuperimposer() - Lrms = sup._rms(coord1,coord2) #using the private _rms function which does not superimpose - - DockQ=(float(fnat) + 1/(1+(irms/1.5)*(irms/1.5)) + 1/(1+(Lrms/8.5)*(Lrms/8.5)))/3 - info={} - info['DockQ']=DockQ - info['irms']=irms - info['Lrms']=Lrms - info['fnat']=fnat - info['nat_correct']=nat_correct - info['nat_total']=nat_total - - info['fnonnat']=fnonnat - info['nonnat_count']=nonnat_count - info['model_total']=model_total - - info['chain1']=chain1 - info['chain2']=chain2 - info['len1']=len1 - info['len2']=len2 - info['class1']=class1 - info['class2']=class2 - return info + def get_pdb_chains(pdb): - pdb_parser = Bio.PDB.PDBParser(QUIET = True) + pdb_parser = Bio.PDB.PDBParser(QUIET=True) pdb_struct = pdb_parser.get_structure("reference", pdb)[0] - chain=[] + chain = [] for c in pdb_struct: chain.append(c.id) return chain -#ATOM 3312 CA -#ATOM 3315 CB ALA H 126 -21.802 31.674 73.597 1.00 58.05 C -def make_two_chain_pdb(pdb,group1,group2): #renumber from 1 - pdb_parser = Bio.PDB.PDBParser(QUIET = True) + +# ATOM 3312 CA +# ATOM 3315 CB ALA H 126 -21.802 31.674 73.597 1.00 58.05 C + + +def make_two_chain_pdb(pdb, group1, group2): # renumber from 1 + pdb_parser = Bio.PDB.PDBParser(QUIET=True) pdb_struct = pdb_parser.get_structure("reference", pdb)[0] for c in pdb_struct: if c.id in group1: - c.id='A' + c.id = "A" if c.id in group2: - c.id='B' - (code,outfile)=tempfile.mkstemp() - io=Bio.PDB.PDBIO() + c.id = "B" + (code, outfile) = tempfile.mkstemp() + io = Bio.PDB.PDBIO() io.set_structure(pdb_struct) io.save(outfile) - exec_path=os.path.dirname(os.path.abspath(sys.argv[0])) - cmd=exec_path + '/scripts/renumber_pdb.pl ' + outfile + exec_path = os.path.dirname(os.path.abspath(sys.argv[0])) + cmd = exec_path + "/scripts/renumber_pdb.pl " + outfile os.system(cmd) os.remove(outfile) - return outfile +'.renum' + return outfile + ".renum" + -def change_chain(pdb_string,chain): - new_str=[]; +def change_chain(pdb_string, chain): + new_str = [] for line in pdb_string: - s=list(line); - s[21]=chain; - new_str.append("".join(s)); - return "\n".join(new_str); - -def make_two_chain_pdb_perm(pdb,group1,group2): #not yet ready - pdb_chains={} - f=open(pdb); + s = list(line) + s[21] = chain + new_str.append("".join(s)) + return "\n".join(new_str) + + +def make_two_chain_pdb_perm(pdb, group1, group2): # not yet ready + pdb_chains = {} + f = open(pdb) for line in f.readlines(): if line[0:4] == "ATOM": # s=list(line); - #print line - chain=line[21] - atom=line[13:16] - resnum=int(line[22:26]) + # print line + chain = line[21] + atom = line[13:16] + resnum = int(line[22:26]) # print atom + ':' + str(resnum) +':' if chain not in pdb_chains: - pdb_chains[chain]=[] + pdb_chains[chain] = [] pdb_chains[chain].append(line) f.close() - (code,outfile)=tempfile.mkstemp() - f=open(outfile,'w') + (code, outfile) = tempfile.mkstemp() + f = open(outfile, "w") for c in group1: - # print pdb_chains[c] - f.write(change_chain(pdb_chains[c],"A")) - f.write("TER\n"); + # print pdb_chains[c] + f.write(change_chain(pdb_chains[c], "A")) + f.write("TER\n") for c in group2: - f.write(change_chain(pdb_chains[c],"B")) - f.close(); - exec_path=os.path.dirname(os.path.abspath(sys.argv[0])) - cmd=exec_path + '/scripts/renumber_pdb.pl ' + outfile + f.write(change_chain(pdb_chains[c], "B")) + f.close() + exec_path = os.path.dirname(os.path.abspath(sys.argv[0])) + cmd = exec_path + "/scripts/renumber_pdb.pl " + outfile os.system(cmd) os.remove(outfile) - return outfile +'.renum' - + return outfile + ".renum" + + def main(): - parser=ArgumentParser(description="DockQ - Quality measure for protein-protein docking models") - parser.add_argument('model',metavar='',type=str,nargs=1,help='path to model file') - parser.add_argument('native',metavar='',type=str,nargs=1,help='path to native file') - parser.add_argument('-capri_peptide',default=False,action='store_true',help='use version for capri_peptide (DockQ cannot not be trusted for this setting)') - parser.add_argument('-short',default=False,action='store_true',help='short output') - parser.add_argument('-verbose',default=False,action='store_true',help='talk a lot!') - parser.add_argument('-quiet',default=False,action='store_true',help='keep quiet!') - parser.add_argument('-useCA',default=False,action='store_true',help='use CA instead of backbone') - parser.add_argument('-skip_check',default=False,action='store_true',help='skip initial check fo speed up on two chain examples') - parser.add_argument('-no_needle',default=False,action='store_true',help='do not use global alignment to fix residue numbering between native and model during chain permutation (use only in case needle is not installed, and the residues between the chains are identical') - parser.add_argument('-perm1',default=False,action='store_true',help='use all chain1 permutations to find maximum DockQ (number of comparisons is n! = 24, if combined with -perm2 there will be n!*m! combinations') - parser.add_argument('-perm2',default=False,action='store_true',help='use all chain2 permutations to find maximum DockQ (number of comparisons is n! = 24, if combined with -perm1 there will be n!*m! combinations') - parser.add_argument('-model_chain1',metavar='model_chain1', type=str,nargs='+', help='pdb chain order to group together partner 1') - parser.add_argument('-model_chain2',metavar='model_chain2', type=str,nargs='+', help='pdb chain order to group together partner 2 (complement to partner 1 if undef)') - parser.add_argument('-native_chain1',metavar='native_chain1', type=str,nargs='+', help='pdb chain order to group together from native partner 1') - parser.add_argument('-native_chain2',metavar='native_chain2', type=str,nargs='+', help='pdb chain order to group together from native partner 2 (complement to partner 1 if undef)') + parser = ArgumentParser( + description="DockQ - Quality measure for protein-protein docking models" + ) + parser.add_argument( + "model", metavar="", type=str, nargs=1, help="path to model file" + ) + parser.add_argument( + "native", metavar="", type=str, nargs=1, help="path to native file" + ) + parser.add_argument( + "-capri_peptide", + default=False, + action="store_true", + help="use version for capri_peptide (DockQ cannot not be trusted for this setting)", + ) + parser.add_argument( + "-short", default=False, action="store_true", help="short output" + ) + parser.add_argument( + "-verbose", default=False, action="store_true", help="talk a lot!" + ) + parser.add_argument( + "-quiet", default=False, action="store_true", help="keep quiet!" + ) + parser.add_argument( + "-useCA", default=False, action="store_true", help="use CA instead of backbone" + ) + parser.add_argument( + "-skip_check", + default=False, + action="store_true", + help="skip initial check fo speed up on two chain examples", + ) + parser.add_argument( + "-no_needle", + default=False, + action="store_true", + help="do not use global alignment to fix residue numbering between native and model during chain permutation (use only in case needle is not installed, and the residues between the chains are identical", + ) + parser.add_argument( + "-perm1", + default=False, + action="store_true", + help="use all chain1 permutations to find maximum DockQ (number of comparisons is n! = 24, if combined with -perm2 there will be n!*m! combinations", + ) + parser.add_argument( + "-perm2", + default=False, + action="store_true", + help="use all chain2 permutations to find maximum DockQ (number of comparisons is n! = 24, if combined with -perm1 there will be n!*m! combinations", + ) + parser.add_argument( + "-model_chain1", + metavar="model_chain1", + type=str, + nargs="+", + help="pdb chain order to group together partner 1", + ) + parser.add_argument( + "-model_chain2", + metavar="model_chain2", + type=str, + nargs="+", + help="pdb chain order to group together partner 2 (complement to partner 1 if undef)", + ) + parser.add_argument( + "-native_chain1", + metavar="native_chain1", + type=str, + nargs="+", + help="pdb chain order to group together from native partner 1", + ) + parser.add_argument( + "-native_chain2", + metavar="native_chain2", + type=str, + nargs="+", + help="pdb chain order to group together from native partner 2 (complement to partner 1 if undef)", + ) args = parser.parse_args() - - bio_ver=1.61 - if(float(Bio.__version__) < bio_ver): - print("Biopython version (%s) is too old need at least >=%.2f" % (Bio.__version__,bio_ver)) - sys.exit() - exec_path=os.path.dirname(os.path.abspath(sys.argv[0])) - fix_numbering=exec_path + '/scripts/fix_numbering.pl' - model=args.model[0] - native=args.native[0] - use_CA_only=args.useCA - capri_peptide=args.capri_peptide + bio_ver = 1.61 + if float(Bio.__version__) < bio_ver: + print( + "Biopython version (%s) is too old need at least >=%.2f" + % (Bio.__version__, bio_ver) + ) + sys.exit() + exec_path = os.path.dirname(os.path.abspath(sys.argv[0])) + fix_numbering = exec_path + "/scripts/fix_numbering.pl" + model = args.model[0] + native = args.native[0] + use_CA_only = args.useCA + capri_peptide = args.capri_peptide # Start the parser - pdb_parser = Bio.PDB.PDBParser(QUIET = True) + pdb_parser = Bio.PDB.PDBParser(QUIET=True) # Get the structures native_structure = pdb_parser.get_structure("reference", native)[0] model_structure = pdb_parser.get_structure("model", model)[0] - - model_chains=[] - native_chains=[] - best_info='' - if(not args.skip_check): - model_chains = [c.id for c in model_structure] + + model_chains = [] + native_chains = [] + best_info = "" + if not args.skip_check: native_chains = [c.id for c in native_structure] - files_to_clean=[] + model_chains = [c.id for c in model_structure] + + files_to_clean = [] - if((len(model_chains) > 2 or len(native_chains) > 2) and - (args.model_chain1 == None and args.native_chain1 == None)): - print("Multi-chain model need sets of chains to group\nuse -native_chain1 and/or -model_chain1 if you want a different mapping than 1-1") + if (len(model_chains) > 2 or len(native_chains) > 2) and ( + args.model_chain1 == None and args.native_chain1 == None + ): + print( + "Multi-chain model need sets of chains to group\nuse -native_chain1 and/or -model_chain1 if you want a different mapping than 1-1" + ) print("Model chains : " + str(model_chains)) print("Native chains : " + str(native_chains)) sys.exit() - if not args.skip_check and (len(model_chains) < 2 or len(native_chains)< 2): - print("Need at least two chains in the two inputs\n"); + if not args.skip_check and (len(model_chains) < 2 or len(native_chains) < 2): + print("Need at least two chains in the two inputs\n") sys.exit() - - if len(model_chains) > 2 or len(native_chains)> 2: - group1=model_chains[0] - group2=model_chains[1] - nat_group1=native_chains[0] - nat_group2=native_chains[1] - if(args.model_chain1 != None): - group1=args.model_chain1 - nat_group1=group1 - if(args.model_chain2 != None): - group2=args.model_chain2 + + if len(model_chains) > 2 or len(native_chains) > 2: + group1 = model_chains[0] + group2 = model_chains[1] + nat_group1 = native_chains[0] + nat_group2 = native_chains[1] + if args.model_chain1 != None: + group1 = args.model_chain1 + nat_group1 = group1 + if args.model_chain2 != None: + group2 = args.model_chain2 else: - #will use the complement from group1 - group2=[] + # will use the complement from group1 + group2 = [] for c in model_chains: if c not in group1: group2.append(c) - nat_group1=group1 - nat_group2=group2 - - - if(args.native_chain1 != None): - nat_group1=args.native_chain1 - if(args.native_chain2 != None): - nat_group2=args.native_chain2 + nat_group1 = group1 + nat_group2 = group2 + + if args.native_chain1 != None: + nat_group1 = args.native_chain1 + if args.native_chain2 != None: + nat_group2 = args.native_chain2 else: - #will use the complement from group1 - nat_group2=[] + # will use the complement from group1 + nat_group2 = [] for c in native_chains: if c not in nat_group1: nat_group2.append(c) - - if(args.model_chain1 == None): - group1=nat_group1 - group2=nat_group2 - - if(args.verbose): - print('Merging ' + ''.join(group1) + ' -> ' + ''.join(nat_group1) + ' to chain A') - print('Merging ' + ''.join(group2) + ' -> ' + ''.join(nat_group2) + ' to chain B') - native=make_two_chain_pdb_perm(native,nat_group1,nat_group2) + + if args.model_chain1 == None: + group1 = nat_group1 + group2 = nat_group2 + + nat_group1_info = {} + nat_group2_info = {} + native_sequence1 = "" + native_sequence2 = "" + for chain in nat_group1: + for residue in native_structure[chain].get_residues(): + nat_group1_info[(chain, residue.id[1])] = len( + residue.get_unpacked_list() + ) + native_sequence1 = native_sequence1 + seq1(residue.get_resname()) + + for chain in nat_group2: + for residue in native_structure[chain].get_residues(): + nat_group2_info[(chain, residue.id[1])] = len( + residue.get_unpacked_list() + ) + native_sequence2 = native_sequence2 + seq1(residue.get_resname()) + + model_sequence1 = "".join( + seq1(residue.get_resname()) + for chain in group1 + for residue in model_structure[chain].get_residues() + ) + model_sequence2 = "".join( + seq1(residue.get_resname()) + for chain in group2 + for residue in model_structure[chain].get_residues() + ) + + native_numbering1 = np.array( + list(nat_group1_info.keys()), dtype=np.dtype("U10, int") + ) + native_numbering2 = np.array( + list(nat_group2_info.keys()), dtype=np.dtype("U10, int") + ) + + aligned_model_sequence1 = align_sequence_features( + model_sequence1, native_sequence1, native_numbering1 + ) + aligned_model_sequence2 = align_sequence_features( + model_sequence2, native_sequence2, native_numbering2 + ) + + aligned_model_sequences = list(aligned_model_sequence1) + list( + aligned_model_sequence2 + ) + for chain in model_chains: + if chain not in group1 and chain not in group2: + model_structure.detach_child(chain) + + residues_to_delete = [] + for residue, aligned_element in zip( + model_structure.get_residues(), aligned_model_sequences + ): + if aligned_element[0] == "-": + residues_to_delete.append(residue.get_full_id()) + else: + residue.id = (" ", aligned_element[1], " ") + + for chain in model_structure: + for full_id in residues_to_delete: + if full_id[2] == chain: + id = full_id[3] + chain.detach_child(id) + + if args.verbose: + print( + "Merging " + + "".join(group1) + + " -> " + + "".join(nat_group1) + + " to chain A" + ) + print( + "Merging " + + "".join(group2) + + " -> " + + "".join(nat_group2) + + " to chain B" + ) + native = make_two_chain_pdb_perm(native, nat_group1, nat_group2) files_to_clean.append(native) - pe=0 + pe = 0 if args.perm1 or args.perm2: - best_DockQ=-1; - best_g1=[] - best_g2=[] - - iter_perm1=itertools.combinations(group1,len(group1)) - iter_perm2=itertools.combinations(group2,len(group2)) + best_DockQ = -1 + best_g1 = [] + best_g2 = [] + + iter_perm1 = itertools.combinations(group1, len(group1)) + iter_perm2 = itertools.combinations(group2, len(group2)) if args.perm1: - iter_perm1=itertools.permutations(group1) + iter_perm1 = itertools.permutations(group1) if args.perm2: - iter_perm2=itertools.permutations(group2) - - combos1=[]; - combos2=[]; - for g1 in iter_perm1:#_temp: + iter_perm2 = itertools.permutations(group2) + + combos1 = [] + combos2 = [] + for g1 in iter_perm1: # _temp: combos1.append(g1) for g2 in iter_perm2: combos2.append(g2) for g1 in combos1: for g2 in combos2: - pe=pe+1 - pe_tot=pe - pe=1 + pe = pe + 1 + pe_tot = pe + pe = 1 if args.verbose: - print('Starting chain order permutation search (number of permutations: ' + str(pe_tot) + ')') + print( + "Starting chain order permutation search (number of permutations: " + + str(pe_tot) + + ")" + ) for g1 in combos1: for g2 in combos2: - model_renum=make_two_chain_pdb_perm(model,g1,g2) - model_fixed=model_renum + model_renum = make_two_chain_pdb_perm(model, g1, g2) + model_fixed = model_renum if not args.no_needle: - fix_numbering_cmd=fix_numbering + ' ' + model_renum + ' ' + native + ' > /dev/null' - model_fixed=model_renum + ".fixed" + fix_numbering_cmd = ( + fix_numbering + + " " + + model_renum + + " " + + native + + " > /dev/null" + ) + model_fixed = model_renum + ".fixed" os.system(fix_numbering_cmd) os.remove(model_renum) if not os.path.exists(model_fixed): - print('If you are sure the residues are identical you can use the options -no_needle') + print( + "If you are sure the residues are identical you can use the options -no_needle" + ) sys.exit() - test_dict=calc_DockQ(model_fixed,native,use_CA_only) + test_dict = calc_DockQ(model_fixed, native, use_CA_only) os.remove(model_fixed) if not args.quiet: - print(str(pe)+'/'+str(pe_tot) + ' ' + ''.join(g1) + ' -> ' + ''.join(g2) + ' ' + str(test_dict['DockQ'])) - if(test_dict['DockQ'] > best_DockQ): - best_DockQ=test_dict['DockQ']; - info=test_dict - best_g1=g1 - best_g2=g2 - best_info='Best score ( ' + str(best_DockQ) +' ) found for model -> native, chain1:' + ''.join(best_g1) + ' -> ' + ''.join(nat_group1) + ' chain2:' + ''.join(best_g2) + ' -> ' + ''.join(nat_group2) - + print( + str(pe) + + "/" + + str(pe_tot) + + " " + + "".join(g1) + + " -> " + + "".join(g2) + + " " + + str(test_dict["DockQ"]) + ) + if test_dict["DockQ"] > best_DockQ: + best_DockQ = test_dict["DockQ"] + info = test_dict + best_g1 = g1 + best_g2 = g2 + best_info = ( + "Best score ( " + + str(best_DockQ) + + " ) found for model -> native, chain1:" + + "".join(best_g1) + + " -> " + + "".join(nat_group1) + + " chain2:" + + "".join(best_g2) + + " -> " + + "".join(nat_group2) + ) + if args.verbose: print(best_info) - if not args.quiet: + if not args.quiet: print("Current best " + str(best_DockQ)) - pe=pe+1 + pe = pe + 1 if not args.quiet: - print(best_info) + print(best_info) else: - model_renum=make_two_chain_pdb_perm(model,group1,group2) - model_fixed=model_renum + model_renum = make_two_chain_pdb_perm(model, group1, group2) + model_fixed = model_renum if not args.no_needle: - fix_numbering_cmd=fix_numbering + ' ' + model_renum + ' ' + native + ' > /dev/null' - model_fixed=model_renum + ".fixed" + fix_numbering_cmd = ( + fix_numbering + " " + model_renum + " " + native + " > /dev/null" + ) + model_fixed = model_renum + ".fixed" os.system(fix_numbering_cmd) os.remove(model_renum) if not os.path.exists(model_fixed): - print('If you are sure the residues are identical you can use the options -no_needle') + print( + "If you are sure the residues are identical you can use the options -no_needle" + ) sys.exit() - info=calc_DockQ(model_fixed,native,use_CA_only) - + info = calc_DockQ(model_fixed, native, use_CA_only) os.remove(model_fixed) else: - info=calc_DockQ(model,native,use_CA_only=use_CA_only,capri_peptide=capri_peptide) #False): - - irms=info['irms'] - Lrms=info['Lrms'] - fnat=info['fnat'] - DockQ=info['DockQ'] - fnonnat=info['fnonnat'] - - if(args.short): + info = calc_DockQ( + model, native, use_CA_only=use_CA_only, capri_peptide=capri_peptide + ) # False): + + irms = info["irms"] + Lrms = info["Lrms"] + fnat = info["fnat"] + DockQ = info["DockQ"] + fnonnat = info["fnonnat"] + + if args.short: if capri_peptide: - print(("DockQ-capri_peptide %.3f Fnat %.3f iRMS %.3f LRMS %.3f Fnonnat %.3f %s %s %s" % (DockQ,fnat,irms,Lrms,fnonnat,model,native_in,best_info))) + print( + ( + "DockQ-capri_peptide %.3f Fnat %.3f iRMS %.3f LRMS %.3f Fnonnat %.3f %s %s %s" + % (DockQ, fnat, irms, Lrms, fnonnat, model, native_in, best_info) + ) + ) else: - print(("DockQ %.3f Fnat %.3f iRMS %.3f LRMS %.3f Fnonnat %.3f %s %s %s" % (DockQ,fnat,irms,Lrms,fnonnat,model,native,best_info))) + print( + ( + "DockQ %.3f Fnat %.3f iRMS %.3f LRMS %.3f Fnonnat %.3f %s %s %s" + % (DockQ, fnat, irms, Lrms, fnonnat, model, native, best_info) + ) + ) else: if capri_peptide: - print('****************************************************************') - print('* DockQ-CAPRI peptide *') - print('* Do not trust any thing you read.... *') - print('* OBS THE DEFINITION OF Fnat and iRMS are different for *') - print('* peptides in CAPRI *') - print('* *') - print('* For the record: *') - print('* Definition of contact <4A all heavy atoms (Fnat) *') - print('* Definition of interface <8A CB (iRMS) *') - print('* For comments, please email: bjorn.wallner@.liu.se *') - print('****************************************************************') + print("****************************************************************") + print("* DockQ-CAPRI peptide *") + print("* Do not trust any thing you read.... *") + print("* OBS THE DEFINITION OF Fnat and iRMS are different for *") + print("* peptides in CAPRI *") + print("* *") + print("* For the record: *") + print("* Definition of contact <4A all heavy atoms (Fnat) *") + print("* Definition of interface <8A CB (iRMS) *") + print("* For comments, please email: bjorn.wallner@.liu.se *") + print("****************************************************************") else: - print('****************************************************************') - print('* DockQ *') - print('* Scoring function for protein-protein docking models *') - print('* Statistics on CAPRI data: *') - print('* 0.00 <= DockQ < 0.23 - Incorrect *') - print('* 0.23 <= DockQ < 0.49 - Acceptable quality *') - print('* 0.49 <= DockQ < 0.80 - Medium quality *') - print('* DockQ >= 0.80 - High quality *') - print('* Reference: Sankar Basu and Bjorn Wallner, DockQ: A quality *') - print('* measure for protein-protein docking models, submitted *') - print('* *') - print('* For the record: *') - print('* Definition of contact <5A (Fnat) *') - print('* Definition of interface <10A all heavy atoms (iRMS) *') - print('* For comments, please email: bjorn.wallner@.liu.se *') - print('* *') - print('****************************************************************') + print("****************************************************************") + print("* DockQ *") + print("* Scoring function for protein-protein docking models *") + print("* Statistics on CAPRI data: *") + print("* 0.00 <= DockQ < 0.23 - Incorrect *") + print("* 0.23 <= DockQ < 0.49 - Acceptable quality *") + print("* 0.49 <= DockQ < 0.80 - Medium quality *") + print("* DockQ >= 0.80 - High quality *") + print("* Reference: Sankar Basu and Bjorn Wallner, DockQ: A quality *") + print("* measure for protein-protein docking models, submitted *") + print("* *") + print("* For the record: *") + print("* Definition of contact <5A (Fnat) *") + print("* Definition of interface <10A all heavy atoms (iRMS) *") + print("* For comments, please email: bjorn.wallner@.liu.se *") + print("* *") + print("****************************************************************") print(("Model : %s" % model)) print(("Native : %s" % native)) if len(best_info): print(best_info) - print('Number of equivalent residues in chain ' + info['chain1'] + ' ' + str(info['len1']) + ' (' + info['class1'] + ')') - print('Number of equivalent residues in chain ' + info['chain2'] + ' ' + str(info['len2']) + ' (' + info['class2'] + ')') - print(("Fnat %.3f %d correct of %d native contacts" % (info['fnat'],info['nat_correct'],info['nat_total']))) - print(("Fnonnat %.3f %d non-native of %d model contacts" % (info['fnonnat'],info['nonnat_count'],info['model_total']))) + print( + "Number of equivalent residues in chain " + + info["chain1"] + + " " + + str(info["len1"]) + + " (" + + info["class1"] + + ")" + ) + print( + "Number of equivalent residues in chain " + + info["chain2"] + + " " + + str(info["len2"]) + + " (" + + info["class2"] + + ")" + ) + print( + ( + "Fnat %.3f %d correct of %d native contacts" + % (info["fnat"], info["nat_correct"], info["nat_total"]) + ) + ) + print( + ( + "Fnonnat %.3f %d non-native of %d model contacts" + % (info["fnonnat"], info["nonnat_count"], info["model_total"]) + ) + ) print(("iRMS %.3f" % irms)) print(("LRMS %.3f" % Lrms)) - peptide_suffix='' + peptide_suffix = "" if capri_peptide: - peptide_suffix='_peptide' + peptide_suffix = "_peptide" - peptide_disclaimer='' + peptide_disclaimer = "" if capri_peptide: - peptide_disclaimer='DockQ not reoptimized for CAPRI peptide evaluation' - print(("DockQ {:.3f} {}".format(DockQ,peptide_disclaimer))) + peptide_disclaimer = "DockQ not reoptimized for CAPRI peptide evaluation" + print(("DockQ {:.3f} {}".format(DockQ, peptide_disclaimer))) for f in files_to_clean: os.remove(f) -if __name__ == '__main__': - main() + +if __name__ == "__main__": + main() From 23bb5228fd6b225619e59d4f9e3b7e06e8d1b35f Mon Sep 17 00:00:00 2001 From: clami66 Date: Sat, 4 Mar 2023 17:29:38 +0100 Subject: [PATCH 004/173] atom selection for irmsd --- DockQ.py | 541 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 304 insertions(+), 237 deletions(-) diff --git a/DockQ.py b/DockQ.py index 48ef547..a0b0be9 100755 --- a/DockQ.py +++ b/DockQ.py @@ -19,40 +19,88 @@ warnings.simplefilter("ignore", BiopythonWarning) -def align_sequence_features(model_sequence, native_sequence, native_numbering): - """Realigns sequence-specific features between PDB structures and antigen sequences - For example, if from_sequence (the sequence for which features have - been calculated) is missing an amino acid but contains more amino acids - at the C terminal than the to_sequence, the features will be assigned - as in this schematic: - - native_numbering 23456789 - native_sequence_aligned -WEKLAPTG - model_sequence_aligned DWEKLAPT- - model_numbering 12345678-1 - Wherever it is not possible to assign features (missing AA in native_sequence) - a pseudovalue of -1 will be assigned instead - """ - alignment = pairwise2.align.localms( - model_sequence, native_sequence, match=5, mismatch=0, open=-10, extend=-1 - )[0] - model_sequence_aligned = np.array(list(alignment.seqA)) - native_sequence_aligned = np.array(list(alignment.seqB)) - - model_indexes = np.where(model_sequence_aligned != "-")[0] - native_indexes = np.where(native_sequence_aligned != "-")[0] - alignment_length = np.sum( - (model_sequence_aligned != "-") & (native_sequence_aligned != "-") +def parse_args(): + parser = ArgumentParser( + description="DockQ - Quality measure for protein-protein docking models" + ) + parser.add_argument( + "model", metavar="", type=str, help="path to model file" + ) + parser.add_argument( + "native", metavar="", type=str, help="path to native file" + ) + parser.add_argument( + "-capri_peptide", + default=False, + action="store_true", + help="use version for capri_peptide (DockQ cannot not be trusted for this setting)", + ) + parser.add_argument( + "-short", default=False, action="store_true", help="short output" + ) + parser.add_argument( + "-verbose", default=False, action="store_true", help="talk a lot!" + ) + parser.add_argument( + "-quiet", default=False, action="store_true", help="keep quiet!" + ) + parser.add_argument( + "-useCA", default=False, action="store_true", help="use CA instead of backbone" + ) + parser.add_argument( + "-skip_check", + default=False, + action="store_true", + help="skip initial check fo speed up on two chain examples", + ) + parser.add_argument( + "-no_needle", + default=False, + action="store_true", + help="do not use global alignment to fix residue numbering between native and model during chain permutation (use only in case needle is not installed, and the residues between the chains are identical", + ) + parser.add_argument( + "-perm1", + default=False, + action="store_true", + help="use all chain1 permutations to find maximum DockQ (number of comparisons is n! = 24, if combined with -perm2 there will be n!*m! combinations", + ) + parser.add_argument( + "-perm2", + default=False, + action="store_true", + help="use all chain2 permutations to find maximum DockQ (number of comparisons is n! = 24, if combined with -perm1 there will be n!*m! combinations", + ) + parser.add_argument( + "-model_chain1", + metavar="model_chain1", + type=str, + nargs="+", + help="pdb chain order to group together partner 1", + ) + parser.add_argument( + "-model_chain2", + metavar="model_chain2", + type=str, + nargs="+", + help="pdb chain order to group together partner 2 (complement to partner 1 if undef)", + ) + parser.add_argument( + "-native_chain1", + metavar="native_chain1", + type=str, + nargs="+", + help="pdb chain order to group together from native partner 1", + ) + parser.add_argument( + "-native_chain2", + metavar="native_chain2", + type=str, + nargs="+", + help="pdb chain order to group together from native partner 2 (complement to partner 1 if undef)", ) - aligned_numbering = np.empty(len(model_indexes), dtype=object) - for i in range(len(model_indexes)): - aligned_numbering[i] = ("-", -1) - aligned_numbering[native_indexes[:alignment_length]] = native_numbering[ - model_indexes[:alignment_length] - ] - - return aligned_numbering + return parser.parse_args() def parse_fnat(fnat_out): @@ -87,7 +135,6 @@ def parse_fnat(fnat_out): def capri_class(fnat, iRMS, LRMS, capri_peptide=False): - if capri_peptide: if fnat < 0.2 or (LRMS > 5.0 and iRMS > 2.0): @@ -131,7 +178,6 @@ def capri_class(fnat, iRMS, LRMS, capri_peptide=False): def capri_class_DockQ(DockQ, capri_peptide=False): - if capri_peptide: return "Undef for capri_peptides" @@ -148,56 +194,63 @@ def capri_class_DockQ(DockQ, capri_peptide=False): return "Undef" -def calc_DockQ(model, native, use_CA_only=False, capri_peptide=False): +def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, use_CA_only=False, capri_peptide=False): - exec_path = os.path.dirname(os.path.abspath(__file__)) + #exec_path = os.path.dirname(os.path.abspath(__file__)) atom_for_sup = ["CA", "C", "N", "O"] if use_CA_only: atom_for_sup = ["CA"] - cmd_fnat = exec_path + "/fnat " + model + " " + native + " 5 -all" - cmd_interface = exec_path + "/fnat " + model + " " + native + " 10 -all" + #cmd_fnat = exec_path + "/fnat " + model + " " + native + " 5 -all" + #cmd_interface = exec_path + "/fnat " + model + " " + native + " 10 -all" - if capri_peptide: - cmd_fnat = exec_path + "/fnat " + model + " " + native + " 4 -all" - cmd_interface = exec_path + "/fnat " + model + " " + native + " 8 -cb" - - fnat_out = os.popen(cmd_fnat).read() - - ( - fnat, - nat_correct, - nat_total, - fnonnat, - nonnat_count, - model_total, - interface5A, - ) = parse_fnat(fnat_out) - assert fnat != -1, "Error running cmd: %s\n" % (cmd_fnat) - inter_out = os.popen(cmd_interface).read() - - ( - fnat_bb, - nat_correct_bb, - nat_total_bb, - fnonnat_bb, - nonnat_count_bb, - model_total_bb, - interface, - ) = parse_fnat(inter_out) - assert fnat_bb != -1, "Error running cmd: %s\n" % (cmd_interface) + threshold = 4.0 if capri_peptide else 5.0 + interface_threshold = 8.0 if capri_peptide else 10.0 + all_atom = not capri_peptide + #cmd_fnat = exec_path + "/fnat " + model + " " + native + " 4 -all" + #cmd_interface = exec_path + "/fnat " + model + " " + native + " 8 -cb" + + nat_correct, nonnat_count, nat_total, model_total = get_fnat(sample_model, ref_model, group1, group2, nat_group1, nat_group2, thr=threshold) + fnat = nat_correct / nat_total + fnonnat = nonnat_count / model_total + sample_interface, ref_interface = get_interface(sample_model, ref_model, group1, group2, nat_group1, nat_group2, thr=interface_threshold, all_atom=all_atom) + #fnat_out = os.popen(cmd_fnat).read() + + #( + #fnat, + #nat_correct, + #nat_total, + #fnonnat, + #nonnat_count, + #model_total, + #interface5A, + #) = parse_fnat(fnat_out) + #assert fnat != -1, "Error running cmd: %s\n" % (cmd_fnat) + #inter_out = os.popen(cmd_interface).read() + + #( + #fnat_bb, + #nat_correct_bb, + #nat_total_bb, + #fnonnat_bb, + #nonnat_count_bb, + #model_total_bb, + #interface, + #) = parse_fnat(inter_out) + #assert fnat_bb != -1, "Error running cmd: %s\n" % (cmd_interface) + # Start the parser - pdb_parser = Bio.PDB.PDBParser(QUIET=True) + #pdb_parser = Bio.PDB.PDBParser(QUIET=True) # Get the structures - ref_structure = pdb_parser.get_structure("reference", native) - sample_structure = pdb_parser.get_structure("model", model) + #ref_structure = pdb_parser.get_structure("reference", native) + #sample_structure = pdb_parser.get_structure("model", model) # Use the first model in the pdb-files for alignment # Change the number 0 if you want to align to another structure - ref_model = ref_structure[0] - sample_model = sample_structure[0] + #ref_model = ref_structure[0] + #sample_model = sample_structure[0] # Make a list of the atoms (in the structures) you wish to align. # In this case we use CA atoms whose index is in the specified range @@ -207,7 +260,7 @@ def calc_DockQ(model, native, use_CA_only=False, capri_peptide=False): common_interface = [] chain_res = {} - + """ # find atoms common in both sample and native atoms_def_sample = [] atoms_def_in_both = [] @@ -288,8 +341,6 @@ def calc_DockQ(model, native, use_CA_only=False, capri_peptide=False): if a in ref_res and atom_key in atoms_def_in_both: ref_atoms.append(ref_res[a]) - print(np.asarray([r.get_coord() for r in ref_atoms]).shape) - # get the ones that are present in native chain_sample = {} for sample_chain in sample_model: @@ -313,13 +364,15 @@ def calc_DockQ(model, native, use_CA_only=False, capri_peptide=False): "Different number of atoms in native and model %d %d\n" % (len(ref_atoms), len(sample_atoms)) ) - + """ + ref_atoms = [atom for ref_res in ref_interface for atom in ref_res.get_atoms() if atom.id in atom_for_sup] + sample_atoms = [atom for sample_res in sample_interface for atom in sample_res.get_atoms() if atom.id in atom_for_sup] super_imposer = Bio.PDB.Superimposer() super_imposer.set_atoms(ref_atoms, sample_atoms) super_imposer.apply(sample_model.get_atoms()) irms = super_imposer.rms - + print(irms) (chain1, chain2) = list(chain_sample.keys()) ligand_chain = chain1 @@ -470,89 +523,168 @@ def make_two_chain_pdb_perm(pdb, group1, group2): # not yet ready return outfile + ".renum" -def main(): +def get_group_dictionary(model, group): + n_atoms_per_residue = {} + for chain in group: + for residue in model[chain].get_residues(): + n_atoms_per_residue[(chain, residue.id[1])] = len( + residue.get_unpacked_list() + ) + return n_atoms_per_residue - parser = ArgumentParser( - description="DockQ - Quality measure for protein-protein docking models" - ) - parser.add_argument( - "model", metavar="", type=str, nargs=1, help="path to model file" - ) - parser.add_argument( - "native", metavar="", type=str, nargs=1, help="path to native file" - ) - parser.add_argument( - "-capri_peptide", - default=False, - action="store_true", - help="use version for capri_peptide (DockQ cannot not be trusted for this setting)", - ) - parser.add_argument( - "-short", default=False, action="store_true", help="short output" - ) - parser.add_argument( - "-verbose", default=False, action="store_true", help="talk a lot!" - ) - parser.add_argument( - "-quiet", default=False, action="store_true", help="keep quiet!" - ) - parser.add_argument( - "-useCA", default=False, action="store_true", help="use CA instead of backbone" - ) - parser.add_argument( - "-skip_check", - default=False, - action="store_true", - help="skip initial check fo speed up on two chain examples", - ) - parser.add_argument( - "-no_needle", - default=False, - action="store_true", - help="do not use global alignment to fix residue numbering between native and model during chain permutation (use only in case needle is not installed, and the residues between the chains are identical", - ) - parser.add_argument( - "-perm1", - default=False, - action="store_true", - help="use all chain1 permutations to find maximum DockQ (number of comparisons is n! = 24, if combined with -perm2 there will be n!*m! combinations", - ) - parser.add_argument( - "-perm2", - default=False, - action="store_true", - help="use all chain2 permutations to find maximum DockQ (number of comparisons is n! = 24, if combined with -perm1 there will be n!*m! combinations", + +def align_model_to_native(model_structure, native_structure, model_chain, native_chain): + model_sequence = "".join( + seq1(residue.get_resname()) for residue in model_structure[model_chain].get_residues() ) - parser.add_argument( - "-model_chain1", - metavar="model_chain1", - type=str, - nargs="+", - help="pdb chain order to group together partner 1", + + native_sequence = "".join( + seq1(residue.get_resname()) for residue in native_structure[native_chain].get_residues() ) - parser.add_argument( - "-model_chain2", - metavar="model_chain2", - type=str, - nargs="+", - help="pdb chain order to group together partner 2 (complement to partner 1 if undef)", + + native_numbering = np.array( + [residue.id[1] for residue in native_structure[native_chain].get_residues()] ) - parser.add_argument( - "-native_chain1", - metavar="native_chain1", - type=str, - nargs="+", - help="pdb chain order to group together from native partner 1", + aligned_model_sequence = align_sequence_features( + model_sequence, native_sequence, native_numbering ) - parser.add_argument( - "-native_chain2", - metavar="native_chain2", - type=str, - nargs="+", - help="pdb chain order to group together from native partner 2 (complement to partner 1 if undef)", + + return list(aligned_model_sequence) + + +def remove_extra_chains(model, chains_to_keep): + for chain in model.get_chains(): + if chain.id not in chains_to_keep: + model.detach_child(chain.id) + return model + + +def fix_chain_residues(model, chain, aligned_chain_sequence): + residues_to_delete = [] + + for residue, aligned_residue in zip(model[chain].get_residues(), aligned_chain_sequence): + if aligned_residue == -1: # gap residue: remove from structure + residues_to_delete.append(residue.get_full_id()) + else: + residue.id = (" ", aligned_residue, " ") + + for _, _, _, res in residues_to_delete: + model[chain].detach_child(res) + + +def align_sequence_features(model_sequence, native_sequence, native_numbering): + """Realigns sequence-specific features between PDB structures and antigen sequences + For example, if from_sequence (the sequence for which features have + been calculated) is missing an amino acid but contains more amino acids + at the C terminal than the to_sequence, the features will be assigned + as in this schematic: + + native_numbering 23456789 + native_sequence_aligned -WEKLAPTG + model_sequence_aligned DWEKLAPT- + model_numbering 12345678-1 + Wherever it is not possible to assign features (missing AA in native_sequence) + a pseudovalue of -1 will be assigned instead + """ + alignment = pairwise2.align.localms( + model_sequence, native_sequence, match=5, mismatch=0, open=-10, extend=-1 + )[0] + model_sequence_aligned = np.array(list(alignment.seqA)) + native_sequence_aligned = np.array(list(alignment.seqB)) + + model_indexes = np.where(model_sequence_aligned != "-")[0] + native_indexes = np.where(native_sequence_aligned != "-")[0] + alignment_length = np.sum( + (model_sequence_aligned != "-") & (native_sequence_aligned != "-") ) - args = parser.parse_args() + aligned_numbering = np.zeros(len(model_indexes), dtype=int) - 1 + + aligned_numbering[native_indexes[:alignment_length]] = native_numbering[ + model_indexes[:alignment_length] + ] + + return aligned_numbering + + +def get_distances_across_chains(model, group1, group2, all_atom=True): + + if all_atom: + model_A_atoms = np.asarray([atom.get_coord() for chain in group1 for res in model[chain].get_residues() for atom in res.get_atoms()]) + model_B_atoms = np.asarray([atom.get_coord() for chain in group2 for res in model[chain].get_residues() for atom in res.get_atoms()]) + else: + model_A_atoms = np.asarray([res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() for chain in group1 for res in model[chain].get_residues()]) + model_B_atoms = np.asarray([res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() for chain in group2 for res in model[chain].get_residues()]) + + distances = np.sqrt(((model_A_atoms[:, None] - model_B_atoms[None, :]) ** 2).sum(-1)) + return distances + +def group_atom_into_res_distances(atom_distances, group_dic1, group_dic2): + res_distances = np.zeros((len(group_dic1), len(group_dic2))) + + cum_i_atoms = 0 + for i, key1 in enumerate(group_dic1.keys()): + i_atoms = group_dic1[key1] + cum_j_atoms = 0 + for j, key2 in enumerate(group_dic2.keys()): + j_atoms = group_dic2[key2] + res_distances[i, j] = np.min(atom_distances[cum_i_atoms:cum_i_atoms+i_atoms, cum_j_atoms:cum_j_atoms+j_atoms]) + cum_j_atoms += j_atoms + cum_i_atoms += i_atoms + return res_distances + + +def get_fnat(model_structure, native_structure, group1, group2, nat_group1, nat_group2, thr=5.0): + # get information about how many atoms correspond to each amino acid in each group of chains + model_group_dic1 = get_group_dictionary(model_structure, group1) + model_group_dic2 = get_group_dictionary(model_structure, group2) + native_group_dic1 = get_group_dictionary(native_structure, nat_group1) + native_group_dic2 = get_group_dictionary(native_structure, nat_group2) + + model_atom_distances = get_distances_across_chains(model_structure, group1, group2) + native_atom_distances = get_distances_across_chains(native_structure, nat_group1, nat_group2) + + model_res_distances = group_atom_into_res_distances(model_atom_distances, model_group_dic1, model_group_dic2) + native_res_distances = group_atom_into_res_distances(native_atom_distances, native_group_dic1, native_group_dic2) + + native_contacts = native_res_distances < thr + model_contacts = model_res_distances < thr + n_native_contacts = np.sum(native_contacts) + n_model_contacts = np.sum(model_contacts) + n_shared_contacts = np.sum(model_contacts * native_contacts) + n_non_native_contacts = np.sum(model_contacts * (1 - native_contacts)) + return (n_shared_contacts, n_non_native_contacts, n_native_contacts, n_model_contacts) + + +def get_interface(model_structure, ref_structure, model_group1, model_group2, ref_group1, ref_group2, thr=0.5, all_atom=True): + ref_interface = [] + model_interface = [] + atom_distances = get_distances_across_chains(ref_structure, ref_group1, ref_group2, all_atom) + if all_atom: + group_dic1 = get_group_dictionary(ref_structure, ref_group1) + group_dic2 = get_group_dictionary(ref_structure, ref_group2) + model_res_distances = group_atom_into_res_distances(atom_distances, group_dic1, group_dic2) + else: + model_res_distances = atom_distances + + positive_pairs = np.where(model_res_distances < thr) + ref_residues_group1 = [res for chain in ref_group1 for res in ref_structure[chain].get_residues()] + ref_residues_group2 = [res for chain in ref_group2 for res in ref_structure[chain].get_residues()] + + model_residues_group1 = [res for chain in model_group1 for res in model_structure[chain].get_residues()] + model_residues_group2 = [res for chain in model_group2 for res in model_structure[chain].get_residues()] + for pair in zip(positive_pairs[0], positive_pairs[1]): + ref_interface.append(ref_residues_group1[pair[0]]) + ref_interface.append(ref_residues_group2[pair[1]]) + + model_interface.append(model_residues_group1[pair[0]]) + model_interface.append(model_residues_group2[pair[1]]) + return model_interface, ref_interface + + +def main(): + + args = parse_args() bio_ver = 1.61 if float(Bio.__version__) < bio_ver: @@ -564,8 +696,8 @@ def main(): exec_path = os.path.dirname(os.path.abspath(sys.argv[0])) fix_numbering = exec_path + "/scripts/fix_numbering.pl" - model = args.model[0] - native = args.native[0] + model = args.model + native = args.native use_CA_only = args.useCA capri_peptide = args.capri_peptide @@ -632,88 +764,23 @@ def main(): group1 = nat_group1 group2 = nat_group2 - nat_group1_info = {} - nat_group2_info = {} - native_sequence1 = "" - native_sequence2 = "" - for chain in nat_group1: - for residue in native_structure[chain].get_residues(): - nat_group1_info[(chain, residue.id[1])] = len( - residue.get_unpacked_list() - ) - native_sequence1 = native_sequence1 + seq1(residue.get_resname()) - - for chain in nat_group2: - for residue in native_structure[chain].get_residues(): - nat_group2_info[(chain, residue.id[1])] = len( - residue.get_unpacked_list() - ) - native_sequence2 = native_sequence2 + seq1(residue.get_resname()) - - model_sequence1 = "".join( - seq1(residue.get_resname()) - for chain in group1 - for residue in model_structure[chain].get_residues() - ) - model_sequence2 = "".join( - seq1(residue.get_resname()) - for chain in group2 - for residue in model_structure[chain].get_residues() - ) - native_numbering1 = np.array( - list(nat_group1_info.keys()), dtype=np.dtype("U10, int") - ) - native_numbering2 = np.array( - list(nat_group2_info.keys()), dtype=np.dtype("U10, int") - ) - - aligned_model_sequence1 = align_sequence_features( - model_sequence1, native_sequence1, native_numbering1 - ) - aligned_model_sequence2 = align_sequence_features( - model_sequence2, native_sequence2, native_numbering2 - ) - - aligned_model_sequences = list(aligned_model_sequence1) + list( - aligned_model_sequence2 - ) - for chain in model_chains: - if chain not in group1 and chain not in group2: - model_structure.detach_child(chain) - - residues_to_delete = [] - for residue, aligned_element in zip( - model_structure.get_residues(), aligned_model_sequences - ): - if aligned_element[0] == "-": - residues_to_delete.append(residue.get_full_id()) - else: - residue.id = (" ", aligned_element[1], " ") - - for chain in model_structure: - for full_id in residues_to_delete: - if full_id[2] == chain: - id = full_id[3] - chain.detach_child(id) - - if args.verbose: - print( - "Merging " - + "".join(group1) - + " -> " - + "".join(nat_group1) - + " to chain A" - ) - print( - "Merging " - + "".join(group2) - + " -> " - + "".join(nat_group2) - + " to chain B" - ) - native = make_two_chain_pdb_perm(native, nat_group1, nat_group2) - files_to_clean.append(native) + model_structure = remove_extra_chains(model_structure, chains_to_keep=group1 + group2) + native_structure = remove_extra_chains(native_structure, chains_to_keep=nat_group1 + nat_group2) + + # realign each model chain against the corresponding native chain + for model_chain, native_chain in zip(group1 + group2, nat_group1 + nat_group2): + aligned_model_sequence = align_model_to_native(model_structure, native_structure, model_chain, native_chain) + fix_chain_residues(model_structure, model_chain, aligned_model_sequence) + + #io = Bio.PDB.PDBIO() + #io.set_structure(model_structure) + #io.save("model_structure.pdb") + #io.set_structure(native_structure) + #io.save("native_structure.pdb") + + #native = make_two_chain_pdb_perm(native, nat_group1, nat_group2) + #files_to_clean.append(native) pe = 0 if args.perm1 or args.perm2: best_DockQ = -1 @@ -767,7 +834,7 @@ def main(): "If you are sure the residues are identical you can use the options -no_needle" ) sys.exit() - test_dict = calc_DockQ(model_fixed, native, use_CA_only) + test_dict = calc_DockQ(model_structure, native_structure, group1, group2, nat_group1, nat_group2, use_CA_only) os.remove(model_fixed) if not args.quiet: print( @@ -821,7 +888,7 @@ def main(): "If you are sure the residues are identical you can use the options -no_needle" ) sys.exit() - info = calc_DockQ(model_fixed, native, use_CA_only) + info = calc_DockQ(model_structure, native_structure, group1, group2, nat_group1, nat_group2, use_CA_only) os.remove(model_fixed) From 659132aa6dbe76855e58a0adfd86c7f08f1e25a4 Mon Sep 17 00:00:00 2001 From: clami66 Date: Sat, 4 Mar 2023 18:48:50 +0100 Subject: [PATCH 005/173] working irms --- DockQ.py | 213 ++++++++++++------------------------------------------- 1 file changed, 47 insertions(+), 166 deletions(-) diff --git a/DockQ.py b/DockQ.py index a0b0be9..a5136ea 100755 --- a/DockQ.py +++ b/DockQ.py @@ -213,162 +213,21 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, nat_correct, nonnat_count, nat_total, model_total = get_fnat(sample_model, ref_model, group1, group2, nat_group1, nat_group2, thr=threshold) fnat = nat_correct / nat_total fnonnat = nonnat_count / model_total - sample_interface, ref_interface = get_interface(sample_model, ref_model, group1, group2, nat_group1, nat_group2, thr=interface_threshold, all_atom=all_atom) - #fnat_out = os.popen(cmd_fnat).read() - - #( - #fnat, - #nat_correct, - #nat_total, - #fnonnat, - #nonnat_count, - #model_total, - #interface5A, - #) = parse_fnat(fnat_out) - #assert fnat != -1, "Error running cmd: %s\n" % (cmd_fnat) - #inter_out = os.popen(cmd_interface).read() - - #( - #fnat_bb, - #nat_correct_bb, - #nat_total_bb, - #fnonnat_bb, - #nonnat_count_bb, - #model_total_bb, - #interface, - #) = parse_fnat(inter_out) - #assert fnat_bb != -1, "Error running cmd: %s\n" % (cmd_interface) - - - # Start the parser - #pdb_parser = Bio.PDB.PDBParser(QUIET=True) - - # Get the structures - #ref_structure = pdb_parser.get_structure("reference", native) - #sample_structure = pdb_parser.get_structure("model", model) - - # Use the first model in the pdb-files for alignment - # Change the number 0 if you want to align to another structure - #ref_model = ref_structure[0] - #sample_model = sample_structure[0] + sample_interface_atoms, ref_interface_atoms = get_interface_atoms(sample_model, ref_model, group1, group2, nat_group1, nat_group2, thr=interface_threshold, atom_types=atom_for_sup) # Make a list of the atoms (in the structures) you wish to align. # In this case we use CA atoms whose index is in the specified range - ref_atoms = [] - sample_atoms = [] + #ref_atoms = [] + #sample_atoms = [] common_interface = [] chain_res = {} - """ - # find atoms common in both sample and native - atoms_def_sample = [] - atoms_def_in_both = [] - # first read in sample - for sample_chain in sample_model: - chain = sample_chain.id - for sample_res in sample_chain: - if sample_res.get_id()[0] != " ": # Skip hetatm. - continue - resname = sample_res.get_id()[1] - key = str(resname) + chain - for a in atom_for_sup: - atom_key = key + "." + a - if a in sample_res: - if atom_key in atoms_def_sample: - print(atom_key + " already added (MODEL)!!!") - atoms_def_sample.append(atom_key) - - # then read in native also present in sample - for ref_chain in ref_model: - chain = ref_chain.id - for ref_res in ref_chain: - if ref_res.get_id()[0] != " ": # Skip hetatm. - continue - resname = ref_res.get_id()[1] - key = str(resname) + chain - for a in atom_for_sup: - atom_key = key + "." + a - if a in ref_res and atom_key in atoms_def_sample: - if atom_key in atoms_def_in_both: - print(atom_key + " already added (Native)!!!") - atoms_def_in_both.append(atom_key) - - for sample_chain in sample_model: - chain = sample_chain.id - if chain not in list(chain_res.keys()): - chain_res[chain] = [] - for sample_res in sample_chain: - if sample_res.get_id()[0] != " ": # Skip hetatm. - continue - resname = sample_res.get_id()[1] - key = str(resname) + chain - chain_res[chain].append(key) - if key in interface: - for a in atom_for_sup: - atom_key = key + "." + a - if a in sample_res and atom_key in atoms_def_in_both: - sample_atoms.append(sample_res[a]) - common_interface.append(key) - - chain_ref = {} - common_residues = [] - - # Iterate of all chains in the model in order to find all residues - for ref_chain in ref_model: - # Iterate of all residues in each model in order to find proper atoms - chain = ref_chain.id - if chain not in list(chain_ref.keys()): - chain_ref[chain] = [] - for ref_res in ref_chain: - if ref_res.get_id()[0] != " ": # Skip hetatm. - continue - resname = ref_res.get_id()[1] - key = str(resname) + chain - - if key in chain_res[chain]: # if key is present in sample - # print key - for a in atom_for_sup: - atom_key = key + "." + a - if a in ref_res and atom_key in atoms_def_in_both: - chain_ref[chain].append(ref_res[a]) - common_residues.append(key) - if key in common_interface: - # Check if residue number ( .get_id() ) is in the list - # Append CA atom to list - for a in atom_for_sup: - atom_key = key + "." + a - if a in ref_res and atom_key in atoms_def_in_both: - ref_atoms.append(ref_res[a]) - - # get the ones that are present in native - chain_sample = {} - for sample_chain in sample_model: - chain = sample_chain.id - if chain not in list(chain_sample.keys()): - chain_sample[chain] = [] - for sample_res in sample_chain: - if sample_res.get_id()[0] != " ": # Skip hetatm. - continue - resname = sample_res.get_id()[1] - key = str(resname) + chain - if key in common_residues: - for a in atom_for_sup: - atom_key = key + "." + a - if a in sample_res and atom_key in atoms_def_in_both: - chain_sample[chain].append(sample_res[a]) - - assert len(ref_atoms) != 0, "length of native is zero" - assert len(sample_atoms) != 0, "length of model is zero" - assert len(ref_atoms) == len(sample_atoms), ( - "Different number of atoms in native and model %d %d\n" - % (len(ref_atoms), len(sample_atoms)) - ) - """ - ref_atoms = [atom for ref_res in ref_interface for atom in ref_res.get_atoms() if atom.id in atom_for_sup] - sample_atoms = [atom for sample_res in sample_interface for atom in sample_res.get_atoms() if atom.id in atom_for_sup] + + #ref_atoms = [atom for ref_res in ref_interface for atom in ref_res.get_atoms() if atom.id in atom_for_sup] + #sample_atoms = [atom for sample_res in sample_interface for atom in sample_res.get_atoms() if atom.id in atom_for_sup] super_imposer = Bio.PDB.Superimposer() - super_imposer.set_atoms(ref_atoms, sample_atoms) + super_imposer.set_atoms(ref_interface_atoms, sample_interface_atoms) super_imposer.apply(sample_model.get_atoms()) irms = super_imposer.rms @@ -656,30 +515,52 @@ def get_fnat(model_structure, native_structure, group1, group2, nat_group1, nat_ return (n_shared_contacts, n_non_native_contacts, n_native_contacts, n_model_contacts) -def get_interface(model_structure, ref_structure, model_group1, model_group2, ref_group1, ref_group2, thr=0.5, all_atom=True): +def get_interface_atoms(model_structure, ref_structure, model_group1, model_group2, ref_group1, ref_group2, thr=0.5, atom_types=["CA", "C", "N", "O"]): ref_interface = [] - model_interface = [] - atom_distances = get_distances_across_chains(ref_structure, ref_group1, ref_group2, all_atom) - if all_atom: - group_dic1 = get_group_dictionary(ref_structure, ref_group1) - group_dic2 = get_group_dictionary(ref_structure, ref_group2) - model_res_distances = group_atom_into_res_distances(atom_distances, group_dic1, group_dic2) - else: - model_res_distances = atom_distances + mod_interface = [] + atom_distances = get_distances_across_chains(ref_structure, ref_group1, ref_group2) + group_dic1 = get_group_dictionary(ref_structure, ref_group1) + group_dic2 = get_group_dictionary(ref_structure, ref_group2) + model_res_distances = group_atom_into_res_distances(atom_distances, group_dic1, group_dic2) - positive_pairs = np.where(model_res_distances < thr) + interacting_pairs = np.where(model_res_distances < thr) ref_residues_group1 = [res for chain in ref_group1 for res in ref_structure[chain].get_residues()] ref_residues_group2 = [res for chain in ref_group2 for res in ref_structure[chain].get_residues()] - model_residues_group1 = [res for chain in model_group1 for res in model_structure[chain].get_residues()] - model_residues_group2 = [res for chain in model_group2 for res in model_structure[chain].get_residues()] - for pair in zip(positive_pairs[0], positive_pairs[1]): - ref_interface.append(ref_residues_group1[pair[0]]) - ref_interface.append(ref_residues_group2[pair[1]]) + mod_residues_group1 = [res for chain in model_group1 for res in model_structure[chain].get_residues()] + mod_residues_group2 = [res for chain in model_group2 for res in model_structure[chain].get_residues()] + + # get the native interfacial residues, along with the corresponding model residues, and select common backbone atoms + for i, j in zip(interacting_pairs[0], interacting_pairs[1]): + ref_res1_atoms = [atom for atom in ref_residues_group1[i].get_atoms()] + mod_res1_atoms = [atom for atom in mod_residues_group1[i].get_atoms()] + + ref_res2_atoms = [atom for atom in ref_residues_group2[j].get_atoms()] + mod_res2_atoms = [atom for atom in mod_residues_group2[j].get_atoms()] + + atom_ids_in_ref_res1 = [atm.id for atm in ref_res1_atoms] + atom_ids_in_mod_res1 = [atm.id for atm in mod_res1_atoms] + + atom_ids_in_ref_res2 = [atm.id for atm in ref_res2_atoms] + atom_ids_in_mod_res2 = [atm.id for atm in mod_res2_atoms] + + # find which atoms are in both interfacial residues, and also in atom_types + atom_ids_in_ref_and_mod_res1 = set(atom_ids_in_ref_res1).intersection(atom_types).intersection(atom_ids_in_mod_res1) + indices_ref_res1 = [atom_ids_in_ref_res1.index(atm_id) for atm_id in atom_ids_in_ref_and_mod_res1] + indices_mod_res1 = [atom_ids_in_mod_res1.index(atm_id) for atm_id in atom_ids_in_ref_and_mod_res1] + + atom_ids_in_ref_and_mod_res2 = set(atom_ids_in_ref_res2).intersection(atom_types).intersection(atom_ids_in_mod_res2) + indices_ref_res2 = [atom_ids_in_ref_res2.index(atm_id) for atm_id in atom_ids_in_ref_and_mod_res2] + indices_mod_res2 = [atom_ids_in_mod_res2.index(atm_id) for atm_id in atom_ids_in_ref_and_mod_res2] - model_interface.append(model_residues_group1[pair[0]]) - model_interface.append(model_residues_group2[pair[1]]) - return model_interface, ref_interface + for atom1, atom2 in zip(indices_ref_res1, indices_mod_res1): + ref_interface.append(ref_res1_atoms[atom1]) + mod_interface.append(mod_res1_atoms[atom2]) + for atom1, atom2 in zip(indices_ref_res2, indices_mod_res2): + ref_interface.append(ref_res2_atoms[atom1]) + mod_interface.append(mod_res2_atoms[atom2]) + + return mod_interface, ref_interface def main(): From d544cf2e18a8a87a6514b1631b2f46d92d010a2b Mon Sep 17 00:00:00 2001 From: clami66 Date: Sat, 4 Mar 2023 20:12:18 +0100 Subject: [PATCH 006/173] backbone atoms selection --- DockQ.py | 148 ++++++++++++++++++++++++++----------------------------- 1 file changed, 71 insertions(+), 77 deletions(-) diff --git a/DockQ.py b/DockQ.py index a5136ea..5486801 100755 --- a/DockQ.py +++ b/DockQ.py @@ -3,6 +3,7 @@ import sys import os import re +import copy import warnings import tempfile import itertools @@ -200,66 +201,44 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, atom_for_sup = ["CA", "C", "N", "O"] if use_CA_only: atom_for_sup = ["CA"] - - #cmd_fnat = exec_path + "/fnat " + model + " " + native + " 5 -all" - #cmd_interface = exec_path + "/fnat " + model + " " + native + " 10 -all" - + threshold = 4.0 if capri_peptide else 5.0 interface_threshold = 8.0 if capri_peptide else 10.0 all_atom = not capri_peptide - #cmd_fnat = exec_path + "/fnat " + model + " " + native + " 4 -all" - #cmd_interface = exec_path + "/fnat " + model + " " + native + " 8 -cb" nat_correct, nonnat_count, nat_total, model_total = get_fnat(sample_model, ref_model, group1, group2, nat_group1, nat_group2, thr=threshold) fnat = nat_correct / nat_total fnonnat = nonnat_count / model_total - sample_interface_atoms, ref_interface_atoms = get_interface_atoms(sample_model, ref_model, group1, group2, nat_group1, nat_group2, thr=interface_threshold, atom_types=atom_for_sup) - - # Make a list of the atoms (in the structures) you wish to align. - # In this case we use CA atoms whose index is in the specified range - #ref_atoms = [] - #sample_atoms = [] - common_interface = [] - - chain_res = {} + # get a copy of each structure containing shared backbone atoms + sample_model_backbone = copy.deepcopy(sample_model) + ref_model_backbone = copy.deepcopy(ref_model) + set_common_backbone_atoms(sample_model_backbone, ref_model_backbone, atom_types=atom_for_sup) + + # Get interfacial atoms from reference, and corresponding atoms from sample + interacting_pairs = get_interacting_pairs(ref_model, nat_group1, nat_group2, thr=interface_threshold) + sample_interface_atoms, ref_interface_atoms = get_interface_atoms(interacting_pairs, + sample_model_backbone, + ref_model_backbone, + group1, + group2, + nat_group1, + nat_group2) - #ref_atoms = [atom for ref_res in ref_interface for atom in ref_res.get_atoms() if atom.id in atom_for_sup] - #sample_atoms = [atom for sample_res in sample_interface for atom in sample_res.get_atoms() if atom.id in atom_for_sup] super_imposer = Bio.PDB.Superimposer() super_imposer.set_atoms(ref_interface_atoms, sample_interface_atoms) super_imposer.apply(sample_model.get_atoms()) irms = super_imposer.rms print(irms) - (chain1, chain2) = list(chain_sample.keys()) - - ligand_chain = chain1 - receptor_chain = chain2 - len1 = len(chain_res[chain1]) - len2 = len(chain_res[chain2]) - - assert len1 != 0, "%s chain has zero length!\n" % chain1 - assert len2 != 0, "%s chain has zero length!\n" % chain2 - - class1 = "ligand" - class2 = "receptor" - if len(chain_sample[chain1]) > len(chain_sample[chain2]): - receptor_chain = chain1 - ligand_chain = chain2 - class1 = "receptor" - class2 = "ligand" + + ref_group1_size = np.sum([len(ref_model[chain]) for chain in nat_group1]) + ref_group2_size = np.sum([len(ref_model[chain]) for chain in nat_group2]) + class1 = "receptor" if ref_group1_size > ref_group2_size else "ligand" + class2 = "ligand" if class1 == "receptor" else "receptor" + # Set to align on receptor - assert len(chain_ref[receptor_chain]) == len(chain_sample[receptor_chain]), ( - "Different number of atoms in native and model receptor (chain %c) %d %d\n" - % ( - receptor_chain, - len(chain_ref[receptor_chain]), - len(chain_sample[receptor_chain]), - ) - ) - super_imposer.set_atoms(chain_ref[receptor_chain], chain_sample[receptor_chain]) super_imposer.apply(sample_model.get_atoms()) receptor_chain_rms = super_imposer.rms @@ -515,52 +494,61 @@ def get_fnat(model_structure, native_structure, group1, group2, nat_group1, nat_ return (n_shared_contacts, n_non_native_contacts, n_native_contacts, n_model_contacts) -def get_interface_atoms(model_structure, ref_structure, model_group1, model_group2, ref_group1, ref_group2, thr=0.5, atom_types=["CA", "C", "N", "O"]): +def get_interacting_pairs(model, group1, group2, thr=0.5): + atom_distances = get_distances_across_chains(model, group1, group2) + group_dic1 = get_group_dictionary(model, group1) + group_dic2 = get_group_dictionary(model, group2) + model_res_distances = group_atom_into_res_distances(atom_distances, group_dic1, group_dic2) + interacting_pairs = np.where(model_res_distances < thr) + + return interacting_pairs + +def get_interface_atoms(interacting_pairs, model_backbone, ref_backbone, model_group1, model_group2, ref_group1, ref_group2): ref_interface = [] mod_interface = [] - atom_distances = get_distances_across_chains(ref_structure, ref_group1, ref_group2) - group_dic1 = get_group_dictionary(ref_structure, ref_group1) - group_dic2 = get_group_dictionary(ref_structure, ref_group2) - model_res_distances = group_atom_into_res_distances(atom_distances, group_dic1, group_dic2) - interacting_pairs = np.where(model_res_distances < thr) - ref_residues_group1 = [res for chain in ref_group1 for res in ref_structure[chain].get_residues()] - ref_residues_group2 = [res for chain in ref_group2 for res in ref_structure[chain].get_residues()] + ref_residues_group1 = [res for chain in ref_group1 for res in ref_backbone[chain].get_residues()] + ref_residues_group2 = [res for chain in ref_group2 for res in ref_backbone[chain].get_residues()] - mod_residues_group1 = [res for chain in model_group1 for res in model_structure[chain].get_residues()] - mod_residues_group2 = [res for chain in model_group2 for res in model_structure[chain].get_residues()] + mod_residues_group1 = [res for chain in model_group1 for res in model_backbone[chain].get_residues()] + mod_residues_group2 = [res for chain in model_group2 for res in model_backbone[chain].get_residues()] # get the native interfacial residues, along with the corresponding model residues, and select common backbone atoms for i, j in zip(interacting_pairs[0], interacting_pairs[1]): - ref_res1_atoms = [atom for atom in ref_residues_group1[i].get_atoms()] - mod_res1_atoms = [atom for atom in mod_residues_group1[i].get_atoms()] + ref_res1_atoms = ref_residues_group1[i].get_atoms() + mod_res1_atoms = mod_residues_group1[i].get_atoms() - ref_res2_atoms = [atom for atom in ref_residues_group2[j].get_atoms()] - mod_res2_atoms = [atom for atom in mod_residues_group2[j].get_atoms()] + ref_res2_atoms = ref_residues_group1[j].get_atoms() + mod_res2_atoms = mod_residues_group1[j].get_atoms() - atom_ids_in_ref_res1 = [atm.id for atm in ref_res1_atoms] - atom_ids_in_mod_res1 = [atm.id for atm in mod_res1_atoms] + for atom1, atom2 in zip(ref_res1_atoms, mod_res1_atoms): + ref_interface.append(atom1) + mod_interface.append(atom2) + + for atom1, atom2 in zip(ref_res2_atoms, mod_res2_atoms): + ref_interface.append(atom1) + mod_interface.append(atom2) + + return mod_interface, ref_interface + + +def set_common_backbone_atoms(model, reference, atom_types=["CA", "C", "N", "O"]): + # model and reference should have the same number of amino acids and be aligned + for mod_res, ref_res in zip(model.get_residues(), reference.get_residues()): + mod_atoms = [atom for atom in mod_res.get_atoms()] + ref_atoms = [atom for atom in ref_res.get_atoms()] - atom_ids_in_ref_res2 = [atm.id for atm in ref_res2_atoms] - atom_ids_in_mod_res2 = [atm.id for atm in mod_res2_atoms] + atom_ids_in_mod_res = [atm.id for atm in mod_atoms] + atom_ids_in_ref_res = [atm.id for atm in ref_atoms] - # find which atoms are in both interfacial residues, and also in atom_types - atom_ids_in_ref_and_mod_res1 = set(atom_ids_in_ref_res1).intersection(atom_types).intersection(atom_ids_in_mod_res1) - indices_ref_res1 = [atom_ids_in_ref_res1.index(atm_id) for atm_id in atom_ids_in_ref_and_mod_res1] - indices_mod_res1 = [atom_ids_in_mod_res1.index(atm_id) for atm_id in atom_ids_in_ref_and_mod_res1] + atom_ids_in_ref_and_mod_res = set(atom_ids_in_mod_res).intersection(atom_types).intersection(atom_ids_in_ref_res) - atom_ids_in_ref_and_mod_res2 = set(atom_ids_in_ref_res2).intersection(atom_types).intersection(atom_ids_in_mod_res2) - indices_ref_res2 = [atom_ids_in_ref_res2.index(atm_id) for atm_id in atom_ids_in_ref_and_mod_res2] - indices_mod_res2 = [atom_ids_in_mod_res2.index(atm_id) for atm_id in atom_ids_in_ref_and_mod_res2] + # whatever atom is not in the shared list, remove it from the both structures + for atom_id in set(atom_ids_in_mod_res).difference(atom_ids_in_ref_and_mod_res): + mod_res.detach_child(atom_id) - for atom1, atom2 in zip(indices_ref_res1, indices_mod_res1): - ref_interface.append(ref_res1_atoms[atom1]) - mod_interface.append(mod_res1_atoms[atom2]) - for atom1, atom2 in zip(indices_ref_res2, indices_mod_res2): - ref_interface.append(ref_res2_atoms[atom1]) - mod_interface.append(mod_res2_atoms[atom2]) - - return mod_interface, ref_interface + for atom_id in set(atom_ids_in_ref_res).difference(atom_ids_in_ref_and_mod_res): + ref_res.detach_child(atom_id) def main(): @@ -654,11 +642,17 @@ def main(): aligned_model_sequence = align_model_to_native(model_structure, native_structure, model_chain, native_chain) fix_chain_residues(model_structure, model_chain, aligned_model_sequence) + + #io = Bio.PDB.PDBIO() #io.set_structure(model_structure) #io.save("model_structure.pdb") - #io.set_structure(native_structure) + #io.set_structure(model_structure) #io.save("native_structure.pdb") + #io.set_structure(model_structure_backbone) + #io.save("model_structure_backbone.pdb") + #io.set_structure(model_structure_backbone) + #io.save("native_structure_backbone.pdb") #native = make_two_chain_pdb_perm(native, nat_group1, nat_group2) #files_to_clean.append(native) From e9cfc1f1616031e0fd3a63d776ea4efcb5e8b7fd Mon Sep 17 00:00:00 2001 From: clami66 Date: Sat, 4 Mar 2023 21:09:19 +0100 Subject: [PATCH 007/173] lrms calculation --- DockQ.py | 40 +++++++++++++++++----------------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/DockQ.py b/DockQ.py index 5486801..d4796dc 100755 --- a/DockQ.py +++ b/DockQ.py @@ -227,40 +227,34 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, super_imposer = Bio.PDB.Superimposer() super_imposer.set_atoms(ref_interface_atoms, sample_interface_atoms) - super_imposer.apply(sample_model.get_atoms()) + super_imposer.apply(sample_model_backbone.get_atoms()) irms = super_imposer.rms - print(irms) + #print(irms) ref_group1_size = np.sum([len(ref_model[chain]) for chain in nat_group1]) ref_group2_size = np.sum([len(ref_model[chain]) for chain in nat_group2]) - class1 = "receptor" if ref_group1_size > ref_group2_size else "ligand" - class2 = "ligand" if class1 == "receptor" else "receptor" + receptor_chains = (nat_group1, group1) if ref_group1_size > ref_group2_size else (nat_group2, group2) + ligand_chains = (nat_group1, group1) if ref_group1_size <= ref_group2_size else (nat_group2, group2) + class1, class2 = ("receptor", "ligand") if ref_group1_size > ref_group2_size else ("ligand", "receptor") + + receptor_atoms_native = [atom for chain in receptor_chains[0] for atom in ref_model_backbone[chain].get_atoms()] + receptor_atoms_sample = [atom for chain in receptor_chains[1] for atom in sample_model_backbone[chain].get_atoms()] # Set to align on receptor - super_imposer.set_atoms(chain_ref[receptor_chain], chain_sample[receptor_chain]) - super_imposer.apply(sample_model.get_atoms()) + super_imposer.set_atoms(receptor_atoms_native, receptor_atoms_sample) + super_imposer.apply(sample_model_backbone.get_atoms()) receptor_chain_rms = super_imposer.rms - assert len(chain_ref[ligand_chain]) != 0 or len(chain_sample[ligand_chain]) != 0, ( - "Zero number of equivalent atoms in native and model ligand (chain %s) %d %d.\nCheck that the residue numbers in model and native is consistent\n" - % (ligand_chain, len(chain_ref[ligand_chain]), len(chain_sample[ligand_chain])) - ) - - assert len(chain_ref[ligand_chain]) == len(chain_sample[ligand_chain]), ( - "Different number of atoms in native and model ligand (chain %c) %d %d\n" - % (ligand_chain, len(chain_ref[ligand_chain]), len(chain_sample[ligand_chain])) - ) - - coord1 = np.array([atom.coord for atom in chain_ref[ligand_chain]]) - coord2 = np.array([atom.coord for atom in chain_sample[ligand_chain]]) + coord1 = np.array([atom.coord for chain in ligand_chains[0] for atom in ref_model_backbone[chain].get_atoms()]) + coord2 = np.array([atom.coord for chain in ligand_chains[1] for atom in sample_model_backbone[chain].get_atoms()]) sup = SVDSuperimposer() Lrms = sup._rms( coord1, coord2 ) # using the private _rms function which does not superimpose - + #print(Lrms) DockQ = ( float(fnat) + 1 / (1 + (irms / 1.5) * (irms / 1.5)) @@ -278,10 +272,10 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, info["nonnat_count"] = nonnat_count info["model_total"] = model_total - info["chain1"] = chain1 - info["chain2"] = chain2 - info["len1"] = len1 - info["len2"] = len2 + info["chain1"] = " ".join(group1) + info["chain2"] = " ".join(group2) + info["len1"] = ref_group1_size + info["len2"] = ref_group2_size info["class1"] = class1 info["class2"] = class2 From 1689247dbbde4a6091bfb7925a316363c55abd8c Mon Sep 17 00:00:00 2001 From: clami66 Date: Sat, 4 Mar 2023 21:48:44 +0100 Subject: [PATCH 008/173] remove old stuff --- DockQ.py | 141 ++----------------------------------------------------- 1 file changed, 3 insertions(+), 138 deletions(-) diff --git a/DockQ.py b/DockQ.py index d4796dc..552939c 100755 --- a/DockQ.py +++ b/DockQ.py @@ -104,37 +104,6 @@ def parse_args(): return parser.parse_args() -def parse_fnat(fnat_out): - fnat = -1 - nat_correct = -1 - nat_total = -1 - fnonnat = -1 - nonnat_count = -1 - model_total = -1 - inter = [] - for line in fnat_out.split("\n"): - line = line.rstrip("\n") - match = re.search(r"NATIVE: (\d+)(\w) (\d+)(\w)", line) - if re.search(r"^Fnat", line): - list = line.split(" ") - fnat = float(list[3]) - nat_correct = int(list[1]) - nat_total = int(list[2]) - elif re.search(r"^Fnonnat", line): - list = line.split(" ") - fnonnat = float(list[3]) - nonnat_count = int(list[1]) - model_total = int(list[2]) - elif match: - res1 = match.group(1) - chain1 = match.group(2) - res2 = match.group(3) - chain2 = match.group(4) - inter.append(res1 + chain1) - inter.append(res2 + chain2) - return (fnat, nat_correct, nat_total, fnonnat, nonnat_count, model_total, inter) - - def capri_class(fnat, iRMS, LRMS, capri_peptide=False): if capri_peptide: @@ -196,7 +165,6 @@ def capri_class_DockQ(DockQ, capri_peptide=False): def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, use_CA_only=False, capri_peptide=False): - #exec_path = os.path.dirname(os.path.abspath(__file__)) atom_for_sup = ["CA", "C", "N", "O"] if use_CA_only: @@ -230,14 +198,14 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, super_imposer.apply(sample_model_backbone.get_atoms()) irms = super_imposer.rms - #print(irms) + print(fnat, irms) ref_group1_size = np.sum([len(ref_model[chain]) for chain in nat_group1]) ref_group2_size = np.sum([len(ref_model[chain]) for chain in nat_group2]) receptor_chains = (nat_group1, group1) if ref_group1_size > ref_group2_size else (nat_group2, group2) ligand_chains = (nat_group1, group1) if ref_group1_size <= ref_group2_size else (nat_group2, group2) - + print(ligand_chains) class1, class2 = ("receptor", "ligand") if ref_group1_size > ref_group2_size else ("ligand", "receptor") receptor_atoms_native = [atom for chain in receptor_chains[0] for atom in ref_model_backbone[chain].get_atoms()] @@ -282,79 +250,6 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, return info -def get_pdb_chains(pdb): - pdb_parser = Bio.PDB.PDBParser(QUIET=True) - pdb_struct = pdb_parser.get_structure("reference", pdb)[0] - chain = [] - for c in pdb_struct: - chain.append(c.id) - return chain - - -# ATOM 3312 CA -# ATOM 3315 CB ALA H 126 -21.802 31.674 73.597 1.00 58.05 C - - -def make_two_chain_pdb(pdb, group1, group2): # renumber from 1 - pdb_parser = Bio.PDB.PDBParser(QUIET=True) - pdb_struct = pdb_parser.get_structure("reference", pdb)[0] - for c in pdb_struct: - if c.id in group1: - c.id = "A" - if c.id in group2: - c.id = "B" - (code, outfile) = tempfile.mkstemp() - io = Bio.PDB.PDBIO() - io.set_structure(pdb_struct) - io.save(outfile) - exec_path = os.path.dirname(os.path.abspath(sys.argv[0])) - cmd = exec_path + "/scripts/renumber_pdb.pl " + outfile - os.system(cmd) - os.remove(outfile) - return outfile + ".renum" - - -def change_chain(pdb_string, chain): - new_str = [] - for line in pdb_string: - s = list(line) - s[21] = chain - new_str.append("".join(s)) - return "\n".join(new_str) - - -def make_two_chain_pdb_perm(pdb, group1, group2): # not yet ready - pdb_chains = {} - f = open(pdb) - for line in f.readlines(): - if line[0:4] == "ATOM": - # s=list(line); - # print line - chain = line[21] - atom = line[13:16] - resnum = int(line[22:26]) - # print atom + ':' + str(resnum) +':' - if chain not in pdb_chains: - pdb_chains[chain] = [] - pdb_chains[chain].append(line) - - f.close() - (code, outfile) = tempfile.mkstemp() - f = open(outfile, "w") - for c in group1: - # print pdb_chains[c] - f.write(change_chain(pdb_chains[c], "A")) - f.write("TER\n") - for c in group2: - f.write(change_chain(pdb_chains[c], "B")) - f.close() - exec_path = os.path.dirname(os.path.abspath(sys.argv[0])) - cmd = exec_path + "/scripts/renumber_pdb.pl " + outfile - os.system(cmd) - os.remove(outfile) - return outfile + ".renum" - - def get_group_dictionary(model, group): n_atoms_per_residue = {} for chain in group: @@ -546,7 +441,6 @@ def set_common_backbone_atoms(model, reference, atom_types=["CA", "C", "N", "O"] def main(): - args = parse_args() bio_ver = 1.61 @@ -636,20 +530,6 @@ def main(): aligned_model_sequence = align_model_to_native(model_structure, native_structure, model_chain, native_chain) fix_chain_residues(model_structure, model_chain, aligned_model_sequence) - - - #io = Bio.PDB.PDBIO() - #io.set_structure(model_structure) - #io.save("model_structure.pdb") - #io.set_structure(model_structure) - #io.save("native_structure.pdb") - #io.set_structure(model_structure_backbone) - #io.save("model_structure_backbone.pdb") - #io.set_structure(model_structure_backbone) - #io.save("native_structure_backbone.pdb") - - #native = make_two_chain_pdb_perm(native, nat_group1, nat_group2) - #files_to_clean.append(native) pe = 0 if args.perm1 or args.perm2: best_DockQ = -1 @@ -743,23 +623,8 @@ def main(): if not args.quiet: print(best_info) else: - model_renum = make_two_chain_pdb_perm(model, group1, group2) - model_fixed = model_renum - if not args.no_needle: - fix_numbering_cmd = ( - fix_numbering + " " + model_renum + " " + native + " > /dev/null" - ) - model_fixed = model_renum + ".fixed" - os.system(fix_numbering_cmd) - os.remove(model_renum) - if not os.path.exists(model_fixed): - print( - "If you are sure the residues are identical you can use the options -no_needle" - ) - sys.exit() - info = calc_DockQ(model_structure, native_structure, group1, group2, nat_group1, nat_group2, use_CA_only) - os.remove(model_fixed) + info = calc_DockQ(model_structure, native_structure, group1, group2, nat_group1, nat_group2, use_CA_only) else: info = calc_DockQ( From 204dd0fda5b7df5b107a945f639db9cbd4442888 Mon Sep 17 00:00:00 2001 From: clami66 Date: Sat, 4 Mar 2023 22:39:33 +0100 Subject: [PATCH 009/173] optimization --- DockQ.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/DockQ.py b/DockQ.py index 552939c..75be7a9 100755 --- a/DockQ.py +++ b/DockQ.py @@ -198,14 +198,13 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, super_imposer.apply(sample_model_backbone.get_atoms()) irms = super_imposer.rms - print(fnat, irms) ref_group1_size = np.sum([len(ref_model[chain]) for chain in nat_group1]) ref_group2_size = np.sum([len(ref_model[chain]) for chain in nat_group2]) receptor_chains = (nat_group1, group1) if ref_group1_size > ref_group2_size else (nat_group2, group2) ligand_chains = (nat_group1, group1) if ref_group1_size <= ref_group2_size else (nat_group2, group2) - print(ligand_chains) + class1, class2 = ("receptor", "ligand") if ref_group1_size > ref_group2_size else ("ligand", "receptor") receptor_atoms_native = [atom for chain in receptor_chains[0] for atom in ref_model_backbone[chain].get_atoms()] @@ -346,6 +345,7 @@ def get_distances_across_chains(model, group1, group2, all_atom=True): distances = np.sqrt(((model_A_atoms[:, None] - model_B_atoms[None, :]) ** 2).sum(-1)) return distances + def group_atom_into_res_distances(atom_distances, group_dic1, group_dic2): res_distances = np.zeros((len(group_dic1), len(group_dic2))) @@ -355,7 +355,7 @@ def group_atom_into_res_distances(atom_distances, group_dic1, group_dic2): cum_j_atoms = 0 for j, key2 in enumerate(group_dic2.keys()): j_atoms = group_dic2[key2] - res_distances[i, j] = np.min(atom_distances[cum_i_atoms:cum_i_atoms+i_atoms, cum_j_atoms:cum_j_atoms+j_atoms]) + res_distances[i, j] = atom_distances[cum_i_atoms:cum_i_atoms+i_atoms, cum_j_atoms:cum_j_atoms+j_atoms].min() cum_j_atoms += j_atoms cum_i_atoms += i_atoms return res_distances @@ -391,7 +391,8 @@ def get_interacting_pairs(model, group1, group2, thr=0.5): interacting_pairs = np.where(model_res_distances < thr) return interacting_pairs - + + def get_interface_atoms(interacting_pairs, model_backbone, ref_backbone, model_group1, model_group2, ref_group1, ref_group2): ref_interface = [] mod_interface = [] @@ -521,15 +522,6 @@ def main(): group1 = nat_group1 group2 = nat_group2 - - model_structure = remove_extra_chains(model_structure, chains_to_keep=group1 + group2) - native_structure = remove_extra_chains(native_structure, chains_to_keep=nat_group1 + nat_group2) - - # realign each model chain against the corresponding native chain - for model_chain, native_chain in zip(group1 + group2, nat_group1 + nat_group2): - aligned_model_sequence = align_model_to_native(model_structure, native_structure, model_chain, native_chain) - fix_chain_residues(model_structure, model_chain, aligned_model_sequence) - pe = 0 if args.perm1 or args.perm2: best_DockQ = -1 @@ -624,12 +616,19 @@ def main(): print(best_info) else: + model_structure = remove_extra_chains(model_structure, chains_to_keep=group1 + group2) + native_structure = remove_extra_chains(native_structure, chains_to_keep=nat_group1 + nat_group2) + + # realign each model chain against the corresponding native chain + for model_chain, native_chain in zip(group1 + group2, nat_group1 + nat_group2): + aligned_model_sequence = align_model_to_native(model_structure, native_structure, model_chain, native_chain) + fix_chain_residues(model_structure, model_chain, aligned_model_sequence) info = calc_DockQ(model_structure, native_structure, group1, group2, nat_group1, nat_group2, use_CA_only) else: info = calc_DockQ( model, native, use_CA_only=use_CA_only, capri_peptide=capri_peptide - ) # False): + ) irms = info["irms"] Lrms = info["Lrms"] From b6fbb5bef50c094eef8ff980591db9ad00262ace Mon Sep 17 00:00:00 2001 From: clami66 Date: Sat, 4 Mar 2023 23:09:44 +0100 Subject: [PATCH 010/173] faster deep copy --- DockQ.py | 51 ++++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/DockQ.py b/DockQ.py index 75be7a9..68337bf 100755 --- a/DockQ.py +++ b/DockQ.py @@ -4,6 +4,7 @@ import os import re import copy +import pickle import warnings import tempfile import itertools @@ -163,9 +164,8 @@ def capri_class_DockQ(DockQ, capri_peptide=False): else: return "Undef" - +#@profile def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, use_CA_only=False, capri_peptide=False): - #exec_path = os.path.dirname(os.path.abspath(__file__)) atom_for_sup = ["CA", "C", "N", "O"] if use_CA_only: atom_for_sup = ["CA"] @@ -174,17 +174,20 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, interface_threshold = 8.0 if capri_peptide else 10.0 all_atom = not capri_peptide - nat_correct, nonnat_count, nat_total, model_total = get_fnat(sample_model, ref_model, group1, group2, nat_group1, nat_group2, thr=threshold) + sample_res_distances = get_residue_distances(sample_model, group1, group2) + ref_res_distances = get_residue_distances(ref_model, nat_group1, nat_group2) + + nat_correct, nonnat_count, nat_total, model_total = get_fnat(sample_res_distances, ref_res_distances, thr=threshold) fnat = nat_correct / nat_total fnonnat = nonnat_count / model_total # get a copy of each structure containing shared backbone atoms - sample_model_backbone = copy.deepcopy(sample_model) - ref_model_backbone = copy.deepcopy(ref_model) + sample_model_backbone = pickle.loads(pickle.dumps(sample_model, -1)) #copy.deepcopy(sample_model) + ref_model_backbone = pickle.loads(pickle.dumps(ref_model, -1)) #copy.deepcopy(ref_model) set_common_backbone_atoms(sample_model_backbone, ref_model_backbone, atom_types=atom_for_sup) # Get interfacial atoms from reference, and corresponding atoms from sample - interacting_pairs = get_interacting_pairs(ref_model, nat_group1, nat_group2, thr=interface_threshold) + interacting_pairs = get_interacting_pairs(ref_res_distances, thr=interface_threshold) sample_interface_atoms, ref_interface_atoms = get_interface_atoms(interacting_pairs, sample_model_backbone, ref_model_backbone, @@ -361,18 +364,18 @@ def group_atom_into_res_distances(atom_distances, group_dic1, group_dic2): return res_distances -def get_fnat(model_structure, native_structure, group1, group2, nat_group1, nat_group2, thr=5.0): - # get information about how many atoms correspond to each amino acid in each group of chains - model_group_dic1 = get_group_dictionary(model_structure, group1) - model_group_dic2 = get_group_dictionary(model_structure, group2) - native_group_dic1 = get_group_dictionary(native_structure, nat_group1) - native_group_dic2 = get_group_dictionary(native_structure, nat_group2) +def get_residue_distances(structure, group1, group2): + # get information about how many atoms correspond to each amino acid in each group of chains + model_group_dic1 = get_group_dictionary(structure, group1) + model_group_dic2 = get_group_dictionary(structure, group2) + + model_atom_distances = get_distances_across_chains(structure, group1, group2) - model_atom_distances = get_distances_across_chains(model_structure, group1, group2) - native_atom_distances = get_distances_across_chains(native_structure, nat_group1, nat_group2) - model_res_distances = group_atom_into_res_distances(model_atom_distances, model_group_dic1, model_group_dic2) - native_res_distances = group_atom_into_res_distances(native_atom_distances, native_group_dic1, native_group_dic2) + return model_res_distances + + +def get_fnat(model_res_distances, native_res_distances, thr=5.0): native_contacts = native_res_distances < thr model_contacts = model_res_distances < thr @@ -383,14 +386,12 @@ def get_fnat(model_structure, native_structure, group1, group2, nat_group1, nat_ return (n_shared_contacts, n_non_native_contacts, n_native_contacts, n_model_contacts) -def get_interacting_pairs(model, group1, group2, thr=0.5): - atom_distances = get_distances_across_chains(model, group1, group2) - group_dic1 = get_group_dictionary(model, group1) - group_dic2 = get_group_dictionary(model, group2) - model_res_distances = group_atom_into_res_distances(atom_distances, group_dic1, group_dic2) - interacting_pairs = np.where(model_res_distances < thr) - - return interacting_pairs +def get_interacting_pairs(distances, thr=0.5): + #atom_distances = get_distances_across_chains(model, group1, group2) + #group_dic1 = get_group_dictionary(model, group1) + #group_dic2 = get_group_dictionary(model, group2) + #model_res_distances = group_atom_into_res_distances(atom_distances, group_dic1, group_dic2) + return np.where(distances < thr) def get_interface_atoms(interacting_pairs, model_backbone, ref_backbone, model_group1, model_group2, ref_group1, ref_group2): @@ -440,7 +441,7 @@ def set_common_backbone_atoms(model, reference, atom_types=["CA", "C", "N", "O"] for atom_id in set(atom_ids_in_ref_res).difference(atom_ids_in_ref_and_mod_res): ref_res.detach_child(atom_id) - +#@profile def main(): args = parse_args() From 912e70c29db02872eae7b124bf828e562b968de7 Mon Sep 17 00:00:00 2001 From: clami66 Date: Sun, 5 Mar 2023 12:31:29 +0100 Subject: [PATCH 011/173] fix reverse alignments --- DockQ.py | 135 +++++++++++++++++++++++++------------------------------ 1 file changed, 60 insertions(+), 75 deletions(-) diff --git a/DockQ.py b/DockQ.py index 68337bf..197b6bb 100755 --- a/DockQ.py +++ b/DockQ.py @@ -2,24 +2,15 @@ import sys import os -import re -import copy import pickle -import warnings -import tempfile import itertools -import subprocess import numpy as np -from math import sqrt from argparse import ArgumentParser import Bio.PDB from Bio import pairwise2 -from Bio import BiopythonWarning from Bio.SeqUtils import seq1 from Bio.SVDSuperimposer import SVDSuperimposer -warnings.simplefilter("ignore", BiopythonWarning) - def parse_args(): parser = ArgumentParser( @@ -224,7 +215,7 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, Lrms = sup._rms( coord1, coord2 ) # using the private _rms function which does not superimpose - #print(Lrms) + DockQ = ( float(fnat) + 1 / (1 + (irms / 1.5) * (irms / 1.5)) @@ -252,55 +243,6 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, return info -def get_group_dictionary(model, group): - n_atoms_per_residue = {} - for chain in group: - for residue in model[chain].get_residues(): - n_atoms_per_residue[(chain, residue.id[1])] = len( - residue.get_unpacked_list() - ) - return n_atoms_per_residue - - -def align_model_to_native(model_structure, native_structure, model_chain, native_chain): - model_sequence = "".join( - seq1(residue.get_resname()) for residue in model_structure[model_chain].get_residues() - ) - - native_sequence = "".join( - seq1(residue.get_resname()) for residue in native_structure[native_chain].get_residues() - ) - - native_numbering = np.array( - [residue.id[1] for residue in native_structure[native_chain].get_residues()] - ) - aligned_model_sequence = align_sequence_features( - model_sequence, native_sequence, native_numbering - ) - - return list(aligned_model_sequence) - - -def remove_extra_chains(model, chains_to_keep): - for chain in model.get_chains(): - if chain.id not in chains_to_keep: - model.detach_child(chain.id) - return model - - -def fix_chain_residues(model, chain, aligned_chain_sequence): - residues_to_delete = [] - - for residue, aligned_residue in zip(model[chain].get_residues(), aligned_chain_sequence): - if aligned_residue == -1: # gap residue: remove from structure - residues_to_delete.append(residue.get_full_id()) - else: - residue.id = (" ", aligned_residue, " ") - - for _, _, _, res in residues_to_delete: - model[chain].detach_child(res) - - def align_sequence_features(model_sequence, native_sequence, native_numbering): """Realigns sequence-specific features between PDB structures and antigen sequences For example, if from_sequence (the sequence for which features have @@ -335,6 +277,44 @@ def align_sequence_features(model_sequence, native_sequence, native_numbering): return aligned_numbering +def align_model_to_native(model_structure, native_structure, model_chain, native_chain): + model_sequence = "".join( + seq1(residue.get_resname()) for residue in model_structure[model_chain].get_residues() + ) + + native_sequence = "".join( + seq1(residue.get_resname()) for residue in native_structure[native_chain].get_residues() + ) + + alignment = pairwise2.align.localms( + model_sequence, native_sequence, match=5, mismatch=0, open=-10, extend=-1 + )[0] + + return alignment + + +def remove_extra_chains(model, chains_to_keep): + for chain in model.get_chains(): + if chain.id not in chains_to_keep: + model.detach_child(chain.id) + return model + + +def fix_chain_residues(model, chain, alignment, invert=False): + residues = model[chain].get_residues() + residues_to_delete = [] + start = False + seqA = alignment.seqA if not invert else alignment.seqB + seqB = alignment.seqB if not invert else alignment.seqA + for (aligned_residue_A, aligned_residue_B) in zip(seqA, seqB): + if aligned_residue_A != "-": + residue = next(residues) + if aligned_residue_B == "-": # gap residue: remove from structure + residues_to_delete.append(residue.get_full_id()) + + for _, _, _, res in residues_to_delete: + model[chain].detach_child(res) + def get_distances_across_chains(model, group1, group2, all_atom=True): @@ -348,24 +328,31 @@ def get_distances_across_chains(model, group1, group2, all_atom=True): distances = np.sqrt(((model_A_atoms[:, None] - model_B_atoms[None, :]) ** 2).sum(-1)) return distances - +#@profile def group_atom_into_res_distances(atom_distances, group_dic1, group_dic2): res_distances = np.zeros((len(group_dic1), len(group_dic2))) cum_i_atoms = 0 - for i, key1 in enumerate(group_dic1.keys()): - i_atoms = group_dic1[key1] + for i, i_atoms in enumerate(group_dic1): cum_j_atoms = 0 - for j, key2 in enumerate(group_dic2.keys()): - j_atoms = group_dic2[key2] + for j, j_atoms in enumerate(group_dic2): res_distances[i, j] = atom_distances[cum_i_atoms:cum_i_atoms+i_atoms, cum_j_atoms:cum_j_atoms+j_atoms].min() cum_j_atoms += j_atoms cum_i_atoms += i_atoms return res_distances +def get_group_dictionary(model, group): + n_atoms_per_residue = [] + for chain in group: + for residue in model[chain].get_residues(): + n_atoms_per_residue.append(len(residue.get_unpacked_list())) + return n_atoms_per_residue + + +#@profile def get_residue_distances(structure, group1, group2): - # get information about how many atoms correspond to each amino acid in each group of chains + # get information about how many atoms correspond to each amino acid in each group of chains model_group_dic1 = get_group_dictionary(structure, group1) model_group_dic2 = get_group_dictionary(structure, group2) @@ -387,10 +374,6 @@ def get_fnat(model_res_distances, native_res_distances, thr=5.0): def get_interacting_pairs(distances, thr=0.5): - #atom_distances = get_distances_across_chains(model, group1, group2) - #group_dic1 = get_group_dictionary(model, group1) - #group_dic2 = get_group_dictionary(model, group2) - #model_res_distances = group_atom_into_res_distances(atom_distances, group_dic1, group_dic2) return np.where(distances < thr) @@ -488,10 +471,11 @@ def main(): if not args.skip_check and (len(model_chains) < 2 or len(native_chains) < 2): print("Need at least two chains in the two inputs\n") sys.exit() - + + group1 = model_chains[0] + group2 = model_chains[1] + if len(model_chains) > 2 or len(native_chains) > 2: - group1 = model_chains[0] - group2 = model_chains[1] nat_group1 = native_chains[0] nat_group2 = native_chains[1] if args.model_chain1 != None: @@ -622,9 +606,10 @@ def main(): # realign each model chain against the corresponding native chain for model_chain, native_chain in zip(group1 + group2, nat_group1 + nat_group2): - aligned_model_sequence = align_model_to_native(model_structure, native_structure, model_chain, native_chain) - fix_chain_residues(model_structure, model_chain, aligned_model_sequence) - info = calc_DockQ(model_structure, native_structure, group1, group2, nat_group1, nat_group2, use_CA_only) + alignment = align_model_to_native(model_structure, native_structure, model_chain, native_chain) + fix_chain_residues(model_structure, model_chain, alignment) + fix_chain_residues(native_structure, native_chain, alignment, invert=True) + info = calc_DockQ(model_structure, native_structure, group1, group2, nat_group1, nat_group2, use_CA_only=use_CA_only, capri_peptide=capri_peptide) else: info = calc_DockQ( From ab03680f0508b3e1bf485513fd9892c3b1e2ef80 Mon Sep 17 00:00:00 2001 From: clami66 Date: Sun, 5 Mar 2023 12:37:59 +0100 Subject: [PATCH 012/173] 2-chain case --- DockQ.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/DockQ.py b/DockQ.py index 197b6bb..9c0ee6f 100755 --- a/DockQ.py +++ b/DockQ.py @@ -475,9 +475,9 @@ def main(): group1 = model_chains[0] group2 = model_chains[1] + nat_group1 = native_chains[0] + nat_group2 = native_chains[1] if len(model_chains) > 2 or len(native_chains) > 2: - nat_group1 = native_chains[0] - nat_group2 = native_chains[1] if args.model_chain1 != None: group1 = args.model_chain1 nat_group1 = group1 @@ -612,9 +612,15 @@ def main(): info = calc_DockQ(model_structure, native_structure, group1, group2, nat_group1, nat_group2, use_CA_only=use_CA_only, capri_peptide=capri_peptide) else: - info = calc_DockQ( - model, native, use_CA_only=use_CA_only, capri_peptide=capri_peptide - ) + model_structure = remove_extra_chains(model_structure, chains_to_keep=group1 + group2) + native_structure = remove_extra_chains(native_structure, chains_to_keep=nat_group1 + nat_group2) + + # realign each model chain against the corresponding native chain + for model_chain, native_chain in zip(group1 + group2, nat_group1 + nat_group2): + alignment = align_model_to_native(model_structure, native_structure, model_chain, native_chain) + fix_chain_residues(model_structure, model_chain, alignment) + fix_chain_residues(native_structure, native_chain, alignment, invert=True) + info = calc_DockQ(model_structure, native_structure, group1, group2, nat_group1, nat_group2, use_CA_only=use_CA_only, capri_peptide=capri_peptide) irms = info["irms"] Lrms = info["Lrms"] From fca022b5321e3fcc492a1b0844f5cce1ef56320b Mon Sep 17 00:00:00 2001 From: clami66 Date: Sun, 5 Mar 2023 13:03:02 +0100 Subject: [PATCH 013/173] bugfix in interface atom getter --- DockQ.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/DockQ.py b/DockQ.py index 9c0ee6f..fc788c2 100755 --- a/DockQ.py +++ b/DockQ.py @@ -188,7 +188,10 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, nat_group2) super_imposer = Bio.PDB.Superimposer() - super_imposer.set_atoms(ref_interface_atoms, sample_interface_atoms) + print(len(sample_interface_atoms), len(ref_interface_atoms)) + #print(np.array([atom.coord for atom in sample_interface_atoms]).shape) + super_imposer.set_atoms(sample_interface_atoms, ref_interface_atoms) + print(super_imposer.rms) super_imposer.apply(sample_model_backbone.get_atoms()) irms = super_imposer.rms @@ -374,7 +377,7 @@ def get_fnat(model_res_distances, native_res_distances, thr=5.0): def get_interacting_pairs(distances, thr=0.5): - return np.where(distances < thr) + return np.nonzero(distances < thr) def get_interface_atoms(interacting_pairs, model_backbone, ref_backbone, model_group1, model_group2, ref_group1, ref_group2): @@ -392,8 +395,8 @@ def get_interface_atoms(interacting_pairs, model_backbone, ref_backbone, model_g ref_res1_atoms = ref_residues_group1[i].get_atoms() mod_res1_atoms = mod_residues_group1[i].get_atoms() - ref_res2_atoms = ref_residues_group1[j].get_atoms() - mod_res2_atoms = mod_residues_group1[j].get_atoms() + ref_res2_atoms = ref_residues_group2[j].get_atoms() + mod_res2_atoms = mod_residues_group2[j].get_atoms() for atom1, atom2 in zip(ref_res1_atoms, mod_res1_atoms): ref_interface.append(atom1) From 858db4b2323b80535a127146372ca66eefa1c96b Mon Sep 17 00:00:00 2001 From: clami66 Date: Sun, 5 Mar 2023 13:05:37 +0100 Subject: [PATCH 014/173] remove prints --- DockQ.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/DockQ.py b/DockQ.py index fc788c2..b859da7 100755 --- a/DockQ.py +++ b/DockQ.py @@ -189,10 +189,9 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, super_imposer = Bio.PDB.Superimposer() print(len(sample_interface_atoms), len(ref_interface_atoms)) - #print(np.array([atom.coord for atom in sample_interface_atoms]).shape) + super_imposer.set_atoms(sample_interface_atoms, ref_interface_atoms) - print(super_imposer.rms) - super_imposer.apply(sample_model_backbone.get_atoms()) + #super_imposer.apply(sample_model_backbone.get_atoms()) irms = super_imposer.rms From 197ed544e93147d704450c58f8b6c5f1b7e13575 Mon Sep 17 00:00:00 2001 From: clami66 Date: Sun, 5 Mar 2023 13:40:53 +0100 Subject: [PATCH 015/173] simplify --- DockQ.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/DockQ.py b/DockQ.py index b859da7..4718368 100755 --- a/DockQ.py +++ b/DockQ.py @@ -157,10 +157,7 @@ def capri_class_DockQ(DockQ, capri_peptide=False): #@profile def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, use_CA_only=False, capri_peptide=False): - atom_for_sup = ["CA", "C", "N", "O"] - if use_CA_only: - atom_for_sup = ["CA"] - + atom_for_sup = ["CA", "C", "N", "O"] if not use_CA_only else ["CA"] threshold = 4.0 if capri_peptide else 5.0 interface_threshold = 8.0 if capri_peptide else 10.0 all_atom = not capri_peptide @@ -173,8 +170,8 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, fnonnat = nonnat_count / model_total # get a copy of each structure containing shared backbone atoms - sample_model_backbone = pickle.loads(pickle.dumps(sample_model, -1)) #copy.deepcopy(sample_model) - ref_model_backbone = pickle.loads(pickle.dumps(ref_model, -1)) #copy.deepcopy(ref_model) + sample_model_backbone = pickle.loads(pickle.dumps(sample_model, -1)) + ref_model_backbone = pickle.loads(pickle.dumps(ref_model, -1)) set_common_backbone_atoms(sample_model_backbone, ref_model_backbone, atom_types=atom_for_sup) # Get interfacial atoms from reference, and corresponding atoms from sample @@ -188,8 +185,6 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, nat_group2) super_imposer = Bio.PDB.Superimposer() - print(len(sample_interface_atoms), len(ref_interface_atoms)) - super_imposer.set_atoms(sample_interface_atoms, ref_interface_atoms) #super_imposer.apply(sample_model_backbone.get_atoms()) From 8f67b14faafde02b40aed9464505c4cdcf46fddc Mon Sep 17 00:00:00 2001 From: clami66 Date: Sun, 5 Mar 2023 14:52:15 +0100 Subject: [PATCH 016/173] avoid duplicate atoms in set --- DockQ.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/DockQ.py b/DockQ.py index 4718368..70adbfa 100755 --- a/DockQ.py +++ b/DockQ.py @@ -185,6 +185,7 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, nat_group2) super_imposer = Bio.PDB.Superimposer() + #print([atom.coord for atom in ref_interface_atoms]) super_imposer.set_atoms(sample_interface_atoms, ref_interface_atoms) #super_imposer.apply(sample_model_backbone.get_atoms()) @@ -393,14 +394,18 @@ def get_interface_atoms(interacting_pairs, model_backbone, ref_backbone, model_g mod_res2_atoms = mod_residues_group2[j].get_atoms() for atom1, atom2 in zip(ref_res1_atoms, mod_res1_atoms): - ref_interface.append(atom1) - mod_interface.append(atom2) + if atom1 not in ref_interface: + ref_interface.append(atom1) + if atom2 not in mod_interface: + mod_interface.append(atom2) for atom1, atom2 in zip(ref_res2_atoms, mod_res2_atoms): - ref_interface.append(atom1) - mod_interface.append(atom2) + if atom1 not in ref_interface: + ref_interface.append(atom1) + if atom2 not in mod_interface: + mod_interface.append(atom2) - return mod_interface, ref_interface + return list(mod_interface), list(ref_interface) def set_common_backbone_atoms(model, reference, atom_types=["CA", "C", "N", "O"]): From 6965410d36f832d8d1ba166f820b2d4555822c1e Mon Sep 17 00:00:00 2001 From: clami66 Date: Sun, 5 Mar 2023 15:37:18 +0100 Subject: [PATCH 017/173] fix capri peptide --- DockQ.py | 100 ++++++++++++++++--------------------------------------- 1 file changed, 29 insertions(+), 71 deletions(-) diff --git a/DockQ.py b/DockQ.py index 70adbfa..0ecd109 100755 --- a/DockQ.py +++ b/DockQ.py @@ -160,20 +160,21 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, atom_for_sup = ["CA", "C", "N", "O"] if not use_CA_only else ["CA"] threshold = 4.0 if capri_peptide else 5.0 interface_threshold = 8.0 if capri_peptide else 10.0 - all_atom = not capri_peptide sample_res_distances = get_residue_distances(sample_model, group1, group2) ref_res_distances = get_residue_distances(ref_model, nat_group1, nat_group2) - + nat_correct, nonnat_count, nat_total, model_total = get_fnat(sample_res_distances, ref_res_distances, thr=threshold) fnat = nat_correct / nat_total fnonnat = nonnat_count / model_total - # get a copy of each structure containing shared backbone atoms + # get a copy of each structure, then only keep backbone atoms. This is faster than copy.deepcopy() sample_model_backbone = pickle.loads(pickle.dumps(sample_model, -1)) ref_model_backbone = pickle.loads(pickle.dumps(ref_model, -1)) set_common_backbone_atoms(sample_model_backbone, ref_model_backbone, atom_types=atom_for_sup) + if capri_peptide: + ref_res_distances = get_residue_distances(ref_model, nat_group1, nat_group2, all_atom=False) # Get interfacial atoms from reference, and corresponding atoms from sample interacting_pairs = get_interacting_pairs(ref_res_distances, thr=interface_threshold) sample_interface_atoms, ref_interface_atoms = get_interface_atoms(interacting_pairs, @@ -185,22 +186,19 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, nat_group2) super_imposer = Bio.PDB.Superimposer() - #print([atom.coord for atom in ref_interface_atoms]) super_imposer.set_atoms(sample_interface_atoms, ref_interface_atoms) - #super_imposer.apply(sample_model_backbone.get_atoms()) irms = super_imposer.rms + # assign which group of chains constitutes the receptor, then the other is the ligand ref_group1_size = np.sum([len(ref_model[chain]) for chain in nat_group1]) ref_group2_size = np.sum([len(ref_model[chain]) for chain in nat_group2]) - receptor_chains = (nat_group1, group1) if ref_group1_size > ref_group2_size else (nat_group2, group2) ligand_chains = (nat_group1, group1) if ref_group1_size <= ref_group2_size else (nat_group2, group2) - - class1, class2 = ("receptor", "ligand") if ref_group1_size > ref_group2_size else ("ligand", "receptor") - + class1, class2 = ("receptor", "ligand") if ref_group1_size > ref_group2_size else ("ligand", "receptor") receptor_atoms_native = [atom for chain in receptor_chains[0] for atom in ref_model_backbone[chain].get_atoms()] receptor_atoms_sample = [atom for chain in receptor_chains[1] for atom in sample_model_backbone[chain].get_atoms()] + # Set to align on receptor super_imposer.set_atoms(receptor_atoms_native, receptor_atoms_sample) super_imposer.apply(sample_model_backbone.get_atoms()) @@ -241,40 +239,6 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, return info -def align_sequence_features(model_sequence, native_sequence, native_numbering): - """Realigns sequence-specific features between PDB structures and antigen sequences - For example, if from_sequence (the sequence for which features have - been calculated) is missing an amino acid but contains more amino acids - at the C terminal than the to_sequence, the features will be assigned - as in this schematic: - - native_numbering 23456789 - native_sequence_aligned -WEKLAPTG - model_sequence_aligned DWEKLAPT- - model_numbering 12345678-1 - Wherever it is not possible to assign features (missing AA in native_sequence) - a pseudovalue of -1 will be assigned instead - """ - alignment = pairwise2.align.localms( - model_sequence, native_sequence, match=5, mismatch=0, open=-10, extend=-1 - )[0] - model_sequence_aligned = np.array(list(alignment.seqA)) - native_sequence_aligned = np.array(list(alignment.seqB)) - - model_indexes = np.where(model_sequence_aligned != "-")[0] - native_indexes = np.where(native_sequence_aligned != "-")[0] - alignment_length = np.sum( - (model_sequence_aligned != "-") & (native_sequence_aligned != "-") - ) - - aligned_numbering = np.zeros(len(model_indexes), dtype=int) - 1 - - aligned_numbering[native_indexes[:alignment_length]] = native_numbering[ - model_indexes[:alignment_length] - ] - - return aligned_numbering - def align_model_to_native(model_structure, native_structure, model_chain, native_chain): model_sequence = "".join( seq1(residue.get_resname()) for residue in model_structure[model_chain].get_residues() @@ -314,8 +278,7 @@ def fix_chain_residues(model, chain, alignment, invert=False): model[chain].detach_child(res) -def get_distances_across_chains(model, group1, group2, all_atom=True): - +def get_distances_across_chains(model, group1, group2, all_atom=True): if all_atom: model_A_atoms = np.asarray([atom.get_coord() for chain in group1 for res in model[chain].get_residues() for atom in res.get_atoms()]) model_B_atoms = np.asarray([atom.get_coord() for chain in group2 for res in model[chain].get_residues() for atom in res.get_atoms()]) @@ -349,14 +312,17 @@ def get_group_dictionary(model, group): #@profile -def get_residue_distances(structure, group1, group2): +def get_residue_distances(structure, group1, group2, all_atom=True): # get information about how many atoms correspond to each amino acid in each group of chains model_group_dic1 = get_group_dictionary(structure, group1) model_group_dic2 = get_group_dictionary(structure, group2) - model_atom_distances = get_distances_across_chains(structure, group1, group2) + model_atom_distances = get_distances_across_chains(structure, group1, group2, all_atom=all_atom) - model_res_distances = group_atom_into_res_distances(model_atom_distances, model_group_dic1, model_group_dic2) + if all_atom: + model_res_distances = group_atom_into_res_distances(model_atom_distances, model_group_dic1, model_group_dic2) + else: + model_res_distances = model_atom_distances return model_res_distances @@ -371,10 +337,10 @@ def get_fnat(model_res_distances, native_res_distances, thr=5.0): return (n_shared_contacts, n_non_native_contacts, n_native_contacts, n_model_contacts) -def get_interacting_pairs(distances, thr=0.5): +def get_interacting_pairs(distances, thr=5.0): return np.nonzero(distances < thr) - +#@profile def get_interface_atoms(interacting_pairs, model_backbone, ref_backbone, model_group1, model_group2, ref_group1, ref_group2): ref_interface = [] mod_interface = [] @@ -385,27 +351,19 @@ def get_interface_atoms(interacting_pairs, model_backbone, ref_backbone, model_g mod_residues_group1 = [res for chain in model_group1 for res in model_backbone[chain].get_residues()] mod_residues_group2 = [res for chain in model_group2 for res in model_backbone[chain].get_residues()] - # get the native interfacial residues, along with the corresponding model residues, and select common backbone atoms - for i, j in zip(interacting_pairs[0], interacting_pairs[1]): - ref_res1_atoms = ref_residues_group1[i].get_atoms() - mod_res1_atoms = mod_residues_group1[i].get_atoms() - - ref_res2_atoms = ref_residues_group2[j].get_atoms() - mod_res2_atoms = mod_residues_group2[j].get_atoms() - - for atom1, atom2 in zip(ref_res1_atoms, mod_res1_atoms): - if atom1 not in ref_interface: - ref_interface.append(atom1) - if atom2 not in mod_interface: - mod_interface.append(atom2) - - for atom1, atom2 in zip(ref_res2_atoms, mod_res2_atoms): - if atom1 not in ref_interface: - ref_interface.append(atom1) - if atom2 not in mod_interface: - mod_interface.append(atom2) - - return list(mod_interface), list(ref_interface) + # remove duplicate residues + interface_residues_group1 = set(interacting_pairs[0]) + interface_residues_group2 = set(interacting_pairs[1]) + + for i in interface_residues_group1: + ref_interface += [atom for atom in ref_residues_group1[i].get_atoms()] + mod_interface += [atom for atom in mod_residues_group1[i].get_atoms()] + + for j in interface_residues_group2: + ref_interface += [atom for atom in ref_residues_group2[j].get_atoms()] + mod_interface += [atom for atom in mod_residues_group2[j].get_atoms()] + + return mod_interface, ref_interface def set_common_backbone_atoms(model, reference, atom_types=["CA", "C", "N", "O"]): From d523121d9769e1304b9d55f643d48994cf698268 Mon Sep 17 00:00:00 2001 From: clami66 Date: Sun, 5 Mar 2023 15:54:17 +0100 Subject: [PATCH 018/173] better flag name --- DockQ.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/DockQ.py b/DockQ.py index 0ecd109..e555f7d 100755 --- a/DockQ.py +++ b/DockQ.py @@ -158,13 +158,13 @@ def capri_class_DockQ(DockQ, capri_peptide=False): #@profile def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, use_CA_only=False, capri_peptide=False): atom_for_sup = ["CA", "C", "N", "O"] if not use_CA_only else ["CA"] - threshold = 4.0 if capri_peptide else 5.0 + fnat_threshold = 4.0 if capri_peptide else 5.0 interface_threshold = 8.0 if capri_peptide else 10.0 sample_res_distances = get_residue_distances(sample_model, group1, group2) ref_res_distances = get_residue_distances(ref_model, nat_group1, nat_group2) - nat_correct, nonnat_count, nat_total, model_total = get_fnat(sample_res_distances, ref_res_distances, thr=threshold) + nat_correct, nonnat_count, nat_total, model_total = get_fnat(sample_res_distances, ref_res_distances, thr=fnat_threshold) fnat = nat_correct / nat_total fnonnat = nonnat_count / model_total @@ -327,7 +327,6 @@ def get_residue_distances(structure, group1, group2, all_atom=True): def get_fnat(model_res_distances, native_res_distances, thr=5.0): - native_contacts = native_res_distances < thr model_contacts = model_res_distances < thr n_native_contacts = np.sum(native_contacts) From 5117cc082fd13bf6dd0e10ef45a8ea6822ae921e Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 6 Mar 2023 11:38:21 +0100 Subject: [PATCH 019/173] printing, no-needle --- DockQ.py | 215 +++++++++++++++++++++++++++---------------------------- 1 file changed, 106 insertions(+), 109 deletions(-) diff --git a/DockQ.py b/DockQ.py index e555f7d..77e48ab 100755 --- a/DockQ.py +++ b/DockQ.py @@ -164,7 +164,7 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, sample_res_distances = get_residue_distances(sample_model, group1, group2) ref_res_distances = get_residue_distances(ref_model, nat_group1, nat_group2) - nat_correct, nonnat_count, nat_total, model_total = get_fnat(sample_res_distances, ref_res_distances, thr=fnat_threshold) + nat_correct, nonnat_count, nat_total, model_total = get_fnat_stats(sample_res_distances, ref_res_distances, thr=fnat_threshold) fnat = nat_correct / nat_total fnonnat = nonnat_count / model_total @@ -239,7 +239,7 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, return info -def align_model_to_native(model_structure, native_structure, model_chain, native_chain): +def align_model_to_native(model_structure, native_structure, model_chain, native_chain, use_numbering=False): model_sequence = "".join( seq1(residue.get_resname()) for residue in model_structure[model_chain].get_residues() ) @@ -247,11 +247,50 @@ def align_model_to_native(model_structure, native_structure, model_chain, native native_sequence = "".join( seq1(residue.get_resname()) for residue in native_structure[native_chain].get_residues() ) + alignment = {} + if use_numbering: + model_numbering = [] + native_numbering = [] + + for residue in model_structure[model_chain].get_residues(): + resn = int(residue.id[1]) + model_numbering.append(resn) - alignment = pairwise2.align.localms( - model_sequence, native_sequence, match=5, mismatch=0, open=-10, extend=-1 - )[0] + for residue in native_structure[native_chain].get_residues(): + resn = int(residue.id[1]) + native_numbering.append(resn) + + start = min(native_numbering + model_numbering) + end = max(native_numbering + model_numbering) + alignment["seqA"] = [] + alignment["seqB"] = [] + model_sequence = iter(model_sequence) + native_sequence = iter(native_sequence) + + for i in range(start, end+1): + if i in model_numbering: + next_model_res = "A" + else: + next_model_res = "-" + if i in native_numbering: + next_native_res = "A" + else: + next_native_res = "-" + + if next_model_res != "-" or next_native_res != "-": + alignment["seqA"].append(next_model_res) + alignment["seqB"].append(next_native_res) + + else: + aln = pairwise2.align.localms( + model_sequence, native_sequence, match=5, mismatch=0, open=-10, extend=-1 + )[0] + alignment["seqA"] = aln.seqA + alignment["seqB"] = aln.seqB + + print("".join(alignment["seqA"])) + print("".join(alignment["seqB"])) return alignment @@ -266,8 +305,8 @@ def fix_chain_residues(model, chain, alignment, invert=False): residues = model[chain].get_residues() residues_to_delete = [] start = False - seqA = alignment.seqA if not invert else alignment.seqB - seqB = alignment.seqB if not invert else alignment.seqA + seqA = alignment["seqA"] if not invert else alignment["seqB"] + seqB = alignment["seqB"] if not invert else alignment["seqA"] for (aligned_residue_A, aligned_residue_B) in zip(seqA, seqB): if aligned_residue_A != "-": residue = next(residues) @@ -290,7 +329,7 @@ def get_distances_across_chains(model, group1, group2, all_atom=True): return distances #@profile -def group_atom_into_res_distances(atom_distances, group_dic1, group_dic2): +def atom_distances_to_residue_distances(atom_distances, group_dic1, group_dic2): res_distances = np.zeros((len(group_dic1), len(group_dic2))) cum_i_atoms = 0 @@ -303,7 +342,7 @@ def group_atom_into_res_distances(atom_distances, group_dic1, group_dic2): return res_distances -def get_group_dictionary(model, group): +def list_atoms_per_residue(model, group): n_atoms_per_residue = [] for chain in group: for residue in model[chain].get_residues(): @@ -314,19 +353,19 @@ def get_group_dictionary(model, group): #@profile def get_residue_distances(structure, group1, group2, all_atom=True): # get information about how many atoms correspond to each amino acid in each group of chains - model_group_dic1 = get_group_dictionary(structure, group1) - model_group_dic2 = get_group_dictionary(structure, group2) + n_atoms_per_res_group1 = list_atoms_per_residue(structure, group1) + n_atoms_per_res_group2 = list_atoms_per_residue(structure, group2) model_atom_distances = get_distances_across_chains(structure, group1, group2, all_atom=all_atom) if all_atom: - model_res_distances = group_atom_into_res_distances(model_atom_distances, model_group_dic1, model_group_dic2) - else: + model_res_distances = atom_distances_to_residue_distances(model_atom_distances, n_atoms_per_res_group1, n_atoms_per_res_group2) + else: # distances were already between CBs only model_res_distances = model_atom_distances return model_res_distances -def get_fnat(model_res_distances, native_res_distances, thr=5.0): +def get_fnat_stats(model_res_distances, native_res_distances, thr=5.0): native_contacts = native_res_distances < thr model_contacts = model_res_distances < thr n_native_contacts = np.sum(native_contacts) @@ -395,19 +434,12 @@ def main(): ) sys.exit() - exec_path = os.path.dirname(os.path.abspath(sys.argv[0])) - fix_numbering = exec_path + "/scripts/fix_numbering.pl" - model = args.model - native = args.native - use_CA_only = args.useCA - capri_peptide = args.capri_peptide - # Start the parser pdb_parser = Bio.PDB.PDBParser(QUIET=True) # Get the structures - native_structure = pdb_parser.get_structure("reference", native)[0] - model_structure = pdb_parser.get_structure("model", model)[0] + native_structure = pdb_parser.get_structure("reference", args.native)[0] + model_structure = pdb_parser.get_structure("model", args.model)[0] model_chains = [] native_chains = [] @@ -437,10 +469,10 @@ def main(): nat_group1 = native_chains[0] nat_group2 = native_chains[1] if len(model_chains) > 2 or len(native_chains) > 2: - if args.model_chain1 != None: + if args.model_chain1: group1 = args.model_chain1 nat_group1 = group1 - if args.model_chain2 != None: + if args.model_chain2: group2 = args.model_chain2 else: # will use the complement from group1 @@ -448,12 +480,12 @@ def main(): for c in model_chains: if c not in group1: group2.append(c) - nat_group1 = group1 - nat_group2 = group2 + nat_group1 = native_chains[:len(group1)] + nat_group2 = native_chains[len(group1):] - if args.native_chain1 != None: + if args.native_chain1: nat_group1 = args.native_chain1 - if args.native_chain2 != None: + if args.native_chain2: nat_group2 = args.native_chain2 else: # will use the complement from group1 @@ -462,9 +494,9 @@ def main(): if c not in nat_group1: nat_group2.append(c) - if args.model_chain1 == None: - group1 = nat_group1 - group2 = nat_group2 + if not args.model_chain1: + group1 = model_chains[:len(nat_group1)] + group2 = model_chains[len(nat_group1):] pe = 0 if args.perm1 or args.perm2: @@ -497,33 +529,23 @@ def main(): + str(pe_tot) + ")" ) + for g1 in combos1: for g2 in combos2: - model_renum = make_two_chain_pdb_perm(model, g1, g2) - model_fixed = model_renum - if not args.no_needle: + + model_structure_this = pickle.loads(pickle.dumps(model_structure, -1)) + model_structure_this = remove_extra_chains(model_structure_this, chains_to_keep=g1 + g2) + + # realign each model chain against the corresponding native chain + for model_chain, native_chain in zip(g1 + g2, nat_group1 + nat_group2): + alignment = align_model_to_native(model_structure, native_structure, model_chain, native_chain, use_numbering=args.no_needle) + fix_chain_residues(model_structure_this, model_chain, alignment) + fix_chain_residues(native_structure, native_chain, alignment, invert=True) + + test_dict = calc_DockQ(model_structure_this, native_structure, g1, g2, nat_group1, nat_group2, use_CA_only=args.useCA, capri_peptide=args.capri_peptide) - fix_numbering_cmd = ( - fix_numbering - + " " - + model_renum - + " " - + native - + " > /dev/null" - ) - model_fixed = model_renum + ".fixed" - os.system(fix_numbering_cmd) - os.remove(model_renum) - if not os.path.exists(model_fixed): - print( - "If you are sure the residues are identical you can use the options -no_needle" - ) - sys.exit() - test_dict = calc_DockQ(model_structure, native_structure, group1, group2, nat_group1, nat_group2, use_CA_only) - os.remove(model_fixed) if not args.quiet: - print( - str(pe) + print(str(pe) + "/" + str(pe_tot) + " " @@ -565,43 +587,37 @@ def main(): # realign each model chain against the corresponding native chain for model_chain, native_chain in zip(group1 + group2, nat_group1 + nat_group2): - alignment = align_model_to_native(model_structure, native_structure, model_chain, native_chain) + alignment = align_model_to_native(model_structure, native_structure, model_chain, native_chain, use_numbering=args.no_needle) fix_chain_residues(model_structure, model_chain, alignment) fix_chain_residues(native_structure, native_chain, alignment, invert=True) - info = calc_DockQ(model_structure, native_structure, group1, group2, nat_group1, nat_group2, use_CA_only=use_CA_only, capri_peptide=capri_peptide) + info = calc_DockQ(model_structure, native_structure, group1, group2, nat_group1, nat_group2, use_CA_only=args.useCA, capri_peptide=args.capri_peptide) else: model_structure = remove_extra_chains(model_structure, chains_to_keep=group1 + group2) native_structure = remove_extra_chains(native_structure, chains_to_keep=nat_group1 + nat_group2) + # realign each model chain against the corresponding native chain for model_chain, native_chain in zip(group1 + group2, nat_group1 + nat_group2): - alignment = align_model_to_native(model_structure, native_structure, model_chain, native_chain) + alignment = align_model_to_native(model_structure, native_structure, model_chain, native_chain, use_numbering=args.no_needle) fix_chain_residues(model_structure, model_chain, alignment) fix_chain_residues(native_structure, native_chain, alignment, invert=True) - info = calc_DockQ(model_structure, native_structure, group1, group2, nat_group1, nat_group2, use_CA_only=use_CA_only, capri_peptide=capri_peptide) + info = calc_DockQ(model_structure, native_structure, group1, group2, nat_group1, nat_group2, use_CA_only=args.useCA, capri_peptide=args.capri_peptide) - irms = info["irms"] - Lrms = info["Lrms"] - fnat = info["fnat"] - DockQ = info["DockQ"] - fnonnat = info["fnonnat"] + info["model"] = args.model + info["native"] = args.native + info["best"] = best_info + print_results(info, args.short, args.capri_peptide) - if args.short: - if capri_peptide: - print( - ( - "DockQ-capri_peptide %.3f Fnat %.3f iRMS %.3f LRMS %.3f Fnonnat %.3f %s %s %s" - % (DockQ, fnat, irms, Lrms, fnonnat, model, native_in, best_info) - ) - ) - else: - print( - ( - "DockQ %.3f Fnat %.3f iRMS %.3f LRMS %.3f Fnonnat %.3f %s %s %s" - % (DockQ, fnat, irms, Lrms, fnonnat, model, native, best_info) - ) +def print_results(info, short=False, capri_peptide=False): + if short: + capri_peptide_str = "-capri_peptide" if capri_peptide else "" + print( + ( + f"DockQ{capri_peptide_str} {info['DockQ']:.3f} Fnat {info['fnat']:.3f} iRMS {info['irms']:.3f} LRMS {info['Lrms']:.3f} Fnonnat {info['fnonnat']:.3f} {info['model']} {info['native']} {info['best']}" ) + ) + else: if capri_peptide: @@ -634,53 +650,34 @@ def main(): print("* For comments, please email: bjorn.wallner@.liu.se *") print("* *") print("****************************************************************") - print(("Model : %s" % model)) - print(("Native : %s" % native)) - if len(best_info): - print(best_info) + print(f"Model : {info['model']}") + print(f"Native : {info['native']}") + if "best" in info: + print(info["best"]) print( - "Number of equivalent residues in chain " - + info["chain1"] - + " " - + str(info["len1"]) - + " (" - + info["class1"] - + ")" + f"Number of equivalent residues in chain {info['chain1']} {info['len1']} ({info['class1']})" ) print( - "Number of equivalent residues in chain " - + info["chain2"] - + " " - + str(info["len2"]) - + " (" - + info["class2"] - + ")" + f"Number of equivalent residues in chain {info['chain2']} {info['len2']} ({info['class2']})" ) print( ( - "Fnat %.3f %d correct of %d native contacts" - % (info["fnat"], info["nat_correct"], info["nat_total"]) + f"Fnat {info['fnat']:.3f} {info['nat_correct']} correct of {info['nat_total']} native contacts" ) ) print( ( - "Fnonnat %.3f %d non-native of %d model contacts" - % (info["fnonnat"], info["nonnat_count"], info["model_total"]) + f"Fnonnat {info['fnonnat']:.3f} {info['nonnat_count']} non-native of {info['model_total']} model contacts" ) ) - print(("iRMS %.3f" % irms)) - print(("LRMS %.3f" % Lrms)) + print(f"iRMS {info['irms']:.3f}") + print(f"LRMS {info['Lrms']:.3f}") peptide_suffix = "" if capri_peptide: peptide_suffix = "_peptide" - peptide_disclaimer = "" - if capri_peptide: - peptide_disclaimer = "DockQ not reoptimized for CAPRI peptide evaluation" - print(("DockQ {:.3f} {}".format(DockQ, peptide_disclaimer))) - - for f in files_to_clean: - os.remove(f) + peptide_disclaimer = " DockQ not reoptimized for CAPRI peptide evaluation" if capri_peptide else "" + print(f"DockQ {info['DockQ']:.3f}{peptide_disclaimer}") if __name__ == "__main__": From 5979cb45b386a6f403959000eaae95cbf0f81bd1 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 6 Mar 2023 14:28:44 +0100 Subject: [PATCH 020/173] no needle fixed --- DockQ.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/DockQ.py b/DockQ.py index 77e48ab..43fa3be 100755 --- a/DockQ.py +++ b/DockQ.py @@ -269,12 +269,12 @@ def align_model_to_native(model_structure, native_structure, model_chain, native for i in range(start, end+1): if i in model_numbering: - next_model_res = "A" + next_model_res = next(model_sequence) else: next_model_res = "-" if i in native_numbering: - next_native_res = "A" + next_native_res = next(native_sequence) else: next_native_res = "-" @@ -288,9 +288,7 @@ def align_model_to_native(model_structure, native_structure, model_chain, native )[0] alignment["seqA"] = aln.seqA alignment["seqB"] = aln.seqB - - print("".join(alignment["seqA"])) - print("".join(alignment["seqB"])) + return alignment From caff9e7c1157daa77363397dd65dfeb2317459c5 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 6 Mar 2023 14:31:02 +0100 Subject: [PATCH 021/173] remove external scripts --- scripts/.renum | 0 scripts/README.numbering | 23 -- scripts/fix_numbering.pl | 300 ----------------- scripts/renumber_pdb.pl | 69 ---- src/fnat.c | 261 --------------- src/molecule.c | 677 --------------------------------------- src/molecule.h | 84 ----- 7 files changed, 1414 deletions(-) delete mode 100644 scripts/.renum delete mode 100644 scripts/README.numbering delete mode 100755 scripts/fix_numbering.pl delete mode 100755 scripts/renumber_pdb.pl delete mode 100644 src/fnat.c delete mode 100644 src/molecule.c delete mode 100644 src/molecule.h diff --git a/scripts/.renum b/scripts/.renum deleted file mode 100644 index e69de29..0000000 diff --git a/scripts/README.numbering b/scripts/README.numbering deleted file mode 100644 index bd7fd5c..0000000 --- a/scripts/README.numbering +++ /dev/null @@ -1,23 +0,0 @@ - - -# fix_numbering performs a sequence alignment between the model and the native based on the "Needleman–Wunsch algorithm" and slides the unaligned residues appropreately in both structure. - -usage: ./fix_numbering.pl - OUTFILE: model.fixed - -e.g., ./fix_numbering.pl model_unfixed.pdb native_unfixed.pdb - ->MODEL: -SVIHPLQNLLTSRDGSLVFAIIKNCILSFKYQSPNHWEFAGKWSDDFPIYSYIRNLRLTSDESRLIACADSDKSLLVFDVDKTSKNVLKLRKRFCFSKRPNAISIAEDDTTVIIADKFGDVYSIDINSIPEEKFTQEPILGHVSMLTDVHLIKDSDGHQFIITSDRDEHIKISHYPQCFIVDKWLFGHKHFVSSICCGKDYLLLSAGGDDKIFAWDWKTGKNLSTFDYNSLIKPYLNDQHLA-PIIEFAVSKIIKSKNLPFVAFFVEATKCIIILEMSEKQKGDLALKQIITFPYNVISLSAHNDEFQVTLDNKESSGVQKNFAKFIEYNLNENSFVVNNEKSNEFDSAIIQSVQGDSNLVTKKEEIYPLYNVSSL-------PQDMDWSKLYPYYK-----QMTKKVTIADIGCGFGGLMIDLSPAFPEDLILGMEIRVQVTNYVEDRIIALRNNTASKHGFQNINVLRGNAMKFLPNFFEKGQLSKMFFCFPDPHKARIITNTLLSEYAYVLKEGGVVYTITDVKDLHEWMVKHLEEHPLFERLSKEWEENDECVKIMRNATEEGKKVERKKGDKFVACFTRLPTPAIL - ->NATIVE: -SVIHPLQNLLTSRDGSLVFAIIKNCILSFKYQSPNHWEFAGKWSDDFPIYSYIRNLRLTSDESRLIACADSDKSLLVFDVDKTSKNVLKLRKRFCFSKRPNAISIAEDDTTVIIADKFGDVYSIDINSIPEEKFTQEPILGHVSMLTDVHLIKDSDGHQFIITSDRDEHIKISHYPQCFIVDKWLFGHKHFVSSICCGKDYLLLSAGGDDKIFAWDWKTGKNLSTFDYNSLIKPYLNDQHLAPPIIEFAVSKIIKSKNLPFVAFFVEATKCIIILEMSEKQKGDLALKQIITFPYNVISLSAHNDEFQVTLDNKESSGVQKNFAKFIEYNLNENSFVVNNEKSNEFDSAIIQSVQGDSNLVTKKEEIYPLYNVSSLQLEYPVSPQDMDWSKLYPYYKNAENGQMTKKVTIADIGCGFGGLMIDLSPAFPEDLILGMEIRVQVTNYVEDRIIALRNNTASKHGFQNINVLRGNAMKFLPNFFEKGQLSKMFFCFPDP---RIITNTLLSEYAYVLKEGGVVYTITDVKDLHEWMVKHLEEHPLFERLSKEWEENDECVKIMRNAT-----------DKFVACFTRLPTPAIL - -YOU NEED TO HAVE 'needle' INSTALLED AS PART OF THE EMBOS PACKAGE: http://emboss.sourceforge.net/apps/release/6.6/emboss/apps/needle.html - -# renumber_pdb.pl renumbers residues from 1 for each of the two chains in a complex PDB file containing multiple chains for either the receptor or the ligand or both. - -usage: ./renumbering.pl - OUTFILE: PDB.renum - - diff --git a/scripts/fix_numbering.pl b/scripts/fix_numbering.pl deleted file mode 100755 index 223e811..0000000 --- a/scripts/fix_numbering.pl +++ /dev/null @@ -1,300 +0,0 @@ -#!/usr/bin/perl -use File::Temp qw/ tempfile /; - - -if(scalar(@ARGV)==0) { - print STDERR "\nusage: ./fix_numbering.pl \n OUTFILE: model.fixed\n\n "; - - $chneedle=`which needle`; - print $chneedle,"\n"; - if ($chneedle =~ m/needle/) - { - print "needle found to be installed in the path\n"; - } - else - { - print "needle NOT found in the path\n"; - print "YOU NEED TO HAVE 'needle' INSTALLED AS PART OF THE EMBOSS PACKAGE: http://emboss.sourceforge.net/apps/release/6.6/emboss/apps/needle.html\n"; - } - exit; -} - - - - - - -$pdb_model=$ARGV[0]; -$pdb_template=$ARGV[1]; -$use_CA=1; #to get sequence -if(defined($ARGV[2])) { - $use_CA=0; -} -$a=0; -if($use_CA) { - ($seq_model,$resnum_model)=aa321_resnum($pdb_model); -} else { - ($seq_model,$resnum_model)=aa321_resnumANY($pdb_model); -} -$a=1 if(defined($resnum_model)); - -if($use_CA) { - ($seq_template,$resnum_template)=aa321_resnum($pdb_template); -} else { - ($seq_template,$resnum_template)=aa321_resnumANY($pdb_template); - -} -($ali_model,$ali_template)=align($seq_model,$seq_template); -if(length($ali_model)==0) { - - exit; -} -@ali_model=split(//,$ali_model); -@ali_template=split(//,$ali_template); -@ali_resnum_model=(); -my $pos=0; -my $insert_num=9000; -for(my $i=0;$i"$pdb_model.num"); -print ">MODEL:\n$ali_model\n\n>NATIVE:\n$ali_template\n"; -#print STDERR ">MODEL:\n$ali_model\n\n>NATIVE:\n$ali_template\n"; -#exit; -my $old_resnum="whatever"; -$pos=-1; -#ATOM 1226 N GLY A 188A 20.672 19.160 17.606 1.00 26.27 -open(MODEL,$pdb_model); -open(OUT,">$pdb_model.fixed"); -while() { - # print "A: "; - # print; - if(/^ATOM/) { -# my $atomno=substr($_, 7, 4); -# my $atomtypeq=substr($_, 13, 3); - my $resnum=substr($_,22,5); - $resnum=~s/\s+//g; - #print "$resnum $old_resnum $atomtype\n"; - if($old_resnum ne $resnum) - { - $pos++; -# print "POS $ali_resnum_model[$pos] $_"; - } - $old_resnum=$resnum; - #print $pos."\n"; - if($ali_resnum_model[$pos]=~/X/) { - substr($_,22,5)=sprintf("%-5s",$ali_resnum_model[$pos]); - } else { - substr($_,22,5)=sprintf("%5s",$ali_resnum_model[$pos]); - } - - } -# print "B: "; - print OUT; -} - - - -sub align # Takes two strings removes all dashes and returns the alignment. -{ - my ($seq1,$seq2)=@_; - my $needle_linux="/usr/bin/needle"; - my $needle_mac="/opt/local/bin/needle"; - my $osname = $^O; - my $input1=$seq1; - my $input2=$seq2; - $seq1=~s/-//g; - $seq2=~s/-//g; - #$seq1=remove_dashes($seq1); - #$seq2=remove_dashes($seq2); - $seq1=~s/\n//g; - $seq2=~s/\n//g; - $seq1=~s/\s+//g; - $seq2=~s/\s+//g; - - my ($fh1,$file1)=tempfile("/tmp/seq.XXXXXXXX"); - my ($fh2,$file2)=tempfile("/tmp/seq.XXXXXXXX"); - my ($fh3,$file3)=tempfile("/tmp/ali.XXXXXXXX"); - close($fh3); - print $fh1 ">seq1\n$seq1\n"; - close($fh1); - print $fh2 ">seq2\n$seq2\n"; - close($fh2); - - if($osname eq "linux" && -e $needle_linux) { - $needle=$needle_linux; - } - if($osname eq "darwin" && -e $needle_mac) { - $needle=$needle_mac; - } - - #print "needle -aseq $file1 -bseq $file2 -gapopen 10 -gapextend 0.5 -outfile $file3\n"; - `needle -aseq $file1 -bseq $file2 -gapopen 1 -gapextend 0.5 -outfile $file3 > /dev/null 2>&1`; - #print $file3."\n"; - ($ali_return1,$ali_return2)=parse_needle_output($file3); - `rm $file1 $file2 $file3`; - - - return ($ali_return1,$ali_return2); - -} - -sub parse_needle_output -{ - my $file=shift; - my $seq1=""; - my $seq2=""; - my $header1=""; - my $header2=""; - - my $isFirst=1; - open(FILE,$file); - while(){ - next if (/^#/); - if(/^(.{13})(.{6}\d)\ ([\w\-]+)/){ - # print "header:$1, seqnro:$2, seq:$3|\n"; - my $header = $1; - my $seq = $3; - if ($isFirst){ - $seq1.=$seq; - $header1 = $header; - $isFirst=0; - } - else { - $seq2.=$seq; - $header2 = $header; - $isFirst=1; - } - } - - } - close(FILE); - if(length($seq1) == 0) { - - print STDERR "needle from the EMBOSS package needs to be installed.\n"; - } - return($seq1,$seq2); -} -sub aa321_resnum -{ - my $file=shift; - my $seq=""; - my $old_resnum="whatever"; - my @resnum=(); - open(PDB,"$file"); - while() - { - if(/^ATOM\s/) - { - my $atomno=substr($_, 7, 4); - my $atomtype=substr($_, 12, 4); - my $resnum=substr($_,22,5); -# $resnum=~s/\s+//g; - #print "$resnum $old_resnum $atomtype\n"; - if($atomtype=~/CA/ && $old_resnum ne $resnum) - { - $res=substr($_,17, 3); - $seq.=aa321($res); - # print $table{$res}; - push(@resnum,$resnum); - $old_resnum=$resnum; - } - } - - last if(/^ENDMDL/); - } - close(PDB); - if(scalar(@resnum)==0) { #read sequence - $seq=`grep -v '>' $file`; - $seq=~s/\n//g; - my @seq=split(//,$seq); - for(my $i=0;$i) - { - if(/^ATOM/) - { - my $atomno=substr($_, 7, 4); - my $atomtype=substr($_, 12, 4); - my $resnum=substr($_,22,5); -# $resnum=~s/\s+//g; - #print "$resnum $old_resnum $atomtype\n"; - if($old_resnum ne $resnum) - { - $res=substr($_,17, 3); - $seq.=aa321($res); - # print $table{$res}; - push(@resnum,$resnum); - $old_resnum=$resnum; - } - } - - last if(/^ENDMDL/); - } - close(PDB); - # print "\n"; - return ($seq,\@resnum); -} -sub aa321 -{ - my $aa=shift; - my %aa321=('ALA', 'A', - 'ARG', 'R', - 'ASN', 'N', - 'ASP', 'D', - 'CYS', 'C', - 'GLN', 'Q', - 'GLU', 'E', - 'GLY', 'G', - 'HIS', 'H', - 'ILE', 'I', - 'LEU', 'L', - 'LYS', 'K', - 'MET', 'M', - 'PHE', 'F', - 'PRO', 'P', - 'SER', 'S', - 'THR', 'T', - 'TRP', 'W', - 'TYR', 'Y', - 'VAL', 'V', - 'ASX', 'B', - 'GLX', 'Z', - 'XXX', 'A', - 'MSE', 'M', - 'FME', 'M', - 'PCA', 'E', - '5HP', 'E', - 'SAC', 'S', - 'CCS', 'C'); - my $aa1=0; - $aa1=$aa321{$aa} if(defined($aa321{$aa})); - return($aa1); - -} diff --git a/scripts/renumber_pdb.pl b/scripts/renumber_pdb.pl deleted file mode 100755 index d0dca36..0000000 --- a/scripts/renumber_pdb.pl +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/perl -w -#require 'bjornlib.pl'; - -if(scalar(@ARGV)==0) { - print STDERR "\nusage: ./renumber_pdb.pl \n OUTFILE: PDB.renum\n\n"; - exit; - -} - -$diff=1; -if(defined($ARGV[1])) { - $diff=$ARGV[1]; -} -#$file=number_pdb($ARGV[0],205+20); -$file=number_pdb($ARGV[0],$diff); -$outfile=$ARGV[0].'.renum'; -open (OUT,">$outfile"); -print OUT $file; - - -sub number_pdb #Takes a pdbfile and a number to start with, and starts renumbering the file from there -{ - my($file,$number)=@_; - my $in_number=$number; - # $number--; - my $oldresno=""; - my $old_chain=" "; - my $temp=""; - my $new_file=""; - my $atomcount=1; - my $c="A"; -# my $c=" "; - open(PDB,"$file"); - while() - { - my $line=$_; - if($line=~/^ATOM/) - { - my $chain=substr($line,21,1); - my $resno=substr($line, 22, 4); - if($oldresno ne $resno) - { - $number++; - if($old_chain ne $chain) { - $number=$in_number; - $new_file.="TER\n" if(length($new_file)>0); - } - $temp=sprintf("%4d",$number); - } - substr($line,6,5)=sprintf("%5d",$atomcount); - $atomcount++; - substr($line, 22, 4)=$temp; - - substr($line, 26, 1)=" "; - #substr($line, 21, 1)="$c"; - $oldresno=$resno; - $old_chain=$chain; - $new_file.=$line; - } - if(/ENDMDL|^TER/) { - # $number=$in_number; - #$c="B"; - - - } - - } - return $new_file; -} diff --git a/src/fnat.c b/src/fnat.c deleted file mode 100644 index cc8b442..0000000 --- a/src/fnat.c +++ /dev/null @@ -1,261 +0,0 @@ -#include -#include -#include -#include -#include "molecule.h" - -// -// Any comments and suggestion may be sent to: -// Author: Björn Wallner -// E-mail: bjorn.wallner@liu.se -// -// - - - -int main(int argc,char *argv[]) /* Main routine */ -{ - molecule m[1]; - molecule model[1]; - int i,j,k; - double d; - double mean=0; - int atoms=0; - int residues=0,residues2=0; - // int contacts[MAXRES][MAXRES]={{}}; - /* int **contacts,**contacts2; - double **dist,**dist2;*/ - - // int res_contacts[20][20]={{}}; - // int restype[20]={}; - // int tot_res_contacts=0; - /// int type_i,type_j; - int current_res_i=0; - int current_res_j=0; - long selected_resnum; - int first=0; - double cutoff=0; - FILE *fp; - int error=0,error2=0; - double temp; - int tmp=0; - int binary=1; - char chain_name; - int nativeA[5000]; - int nativeB[5000]; - int modelA[5000]; - int modelB[5000]; - char chainA,chainB,chainA2,chainB2; - int interface_contacts=0; - int interface_contacts_model=0; - int verbose=0; - char set='a'; - char set_switch[100]; - char arg[100]; - //float sum=0; - /* Parse command line for PDB filename */ - - if(argc>=4) - { - strcpy(model[0].filename,argv[1]); - strcpy(m[0].filename,argv[2]); - cutoff=strtod(argv[3],NULL); - cutoff=cutoff*cutoff; - for(i=4; i5) - // verbose=1; - } - else - { - printf("Usage: fnat [pdb_file] [native] cutoff [set default all-atom] [verbose (default off)]]\n"); - exit(1); - } - - - error=read_molecules(m,set); - - if(error==0) - { - residues=m[0].residues; - /* - contacts = malloc(residues*sizeof(int *)); - dist = malloc(residues*sizeof(double *)); - for(i=0;i5 && - if(strcmp(m[0].atm[j].chain,m[0].atm[i].chain)!=0) { - // printf("HEJ %d %d %d %d %f %f\n",current_res_j,current_res_i,i,j,crd(m,i,j),crd(m,j,i)); - d=crd(m,i,j); - // printf("%d %d %d %d %s %s %f\n",m[0].atm[j].resnum,m[0].atm[i].resnum,i,j,m[0].atm[j].chain,m[0].atm[i].chain,d); - if(verbose) - printf("ALLNATIVE: %d%s %d%s %f %d %d\n",m[0].atm[i].resnum,m[0].atm[i].chain,m[0].atm[j].resnum,m[0].atm[j].chain,sqrt(d),current_res_i,current_res_j); //,contacts[current_res_i][current_res_j]); - chainA=m[0].atm[i].chain[0]; - chainB=m[0].atm[j].chain[0]; - if(/*contacts[current_res_i][current_res_j]==0 && */crd(m,i,j)<=cutoff) - { - nativeA[interface_contacts]=m[0].atm[i].resnum; - nativeB[interface_contacts]=m[0].atm[j].resnum; - interface_contacts++; - - d=crd(m,i,j); - printf("NATIVE: %d%s %d%s %f\n",m[0].atm[i].resnum,m[0].atm[i].chain,m[0].atm[j].resnum,m[0].atm[j].chain,sqrt(d)); - - /*contacts[current_res_i][current_res_j]=1; - contacts[current_res_j][current_res_i]=1;*/ - - //res_contacts[get_res(m[0].atm[i].residue)][get_res(m[0].atm[j].residue)]++; - //tot_res_contacts++; - } - /*dist[current_res_i][current_res_j]=d; - dist[current_res_j][current_res_i]=d;*/ - } - current_res_j++; - } - } - current_res_i++; - } - } - //chain_name=m[0].atm[m[0].CA_ref[i]].chain[0]; - } - - - error2=read_molecules(model,set); - if(error2==0) - { - - residues2=model[0].residues; - /* - contacts2 = malloc(residues2*sizeof(int *)); - for(i=0;i5 && - if(strcmp(model[0].atm[j].chain,model[0].atm[i].chain)!=0) { - - //printf("HEJ %d %d %d %d %f %f\n",current_res_j,current_res_i,i,j,crd(m,i,j),crd(m,j,i)); - //d=crd(m,i,j); - //printf("%d %d %d %d %s %s %f\n",model[0].atm[j].resnum,model[0].atm[i].resnum,i,j,model[0].atm[j].chain,model[0].atm[i].chain,d); - //d=crd(model,i,j); - //printf("ALLMODEL: %d%s %d%s %f %d %d\n",model[0].atm[i].resnum,model[0].atm[i].chain,model[0].atm[j].resnum,model[0].atm[j].chain,sqrt(d),current_res_i,current_res_j); - - chainA2=model[0].atm[i].chain[0]; - chainB2=model[0].atm[j].chain[0]; - if(/*contacts2[current_res_i][current_res_j]==0 &&*/ crd(model,i,j)<=cutoff) - { - //printf("%d %d %d %d %d %d %d\n", residues2,model[0].atm[i].resnum,model[0].atm[j].resnum,model[0].atm[i].rescount,model[0].atm[j].rescount,current_res_i,current_res_j); - modelA[interface_contacts_model]=model[0].atm[i].resnum; - modelB[interface_contacts_model]=model[0].atm[j].resnum; - interface_contacts_model++; - - if(verbose) { - d=crd(model,i,j); - printf("MODEL: %d%s %d%s %f %d %d\n",model[0].atm[i].resnum,model[0].atm[i].chain,model[0].atm[j].resnum,model[0].atm[j].chain,sqrt(d),current_res_i,current_res_j); - } - /*contacts2[current_res_i][current_res_j]=1; - contacts2[current_res_j][current_res_i]=1;*/ - //res_contacts[get_res(model[0].atm[i].residue)][get_res(model[0].atm[j].residue)]++; - //tot_res_contacts++; - } - } - current_res_j++; - } - } - current_res_i++; - } - } - //chain_name=model[0].atm[model[0].CA_ref[i]].chain[0]; - } - - int matches=0; - if(chainA!= chainA2 || chainB != chainB2) { - fprintf(stderr,"chain mismatch %c %c %c %c",chainA,chainA2,chainB,chainB2); - } else { - - - // find matches in nativeA-nativeB modelA-modelB - for(i=0;i -#include -#include -#include -#include "molecule.h" -//#include "nr.h" -//#include "nrutil.h" -//#include "nets.h" - - -/* changed input to (molecule *m,char atomflag) - atomflag == a -> read all atoms (except H) - atomflag == c -> CA atoms - atomflag == b -> backbone CA,C,N,O atoms -*/ - -int read_molecules(molecule *m,char atomflag) /* Reads in molecules to be superimposed */ -{ - int i,j,k,atoms,residues; /* Counter variables */ - char buff[1200]; /* Input string */ - char temp[1000]; /* Throwaway string */ - char line_flag[11]; /* PDB file line mode */ - char desc_flag[20]; - char residue[4]; /* PDB atom info for output */ - char name[4]; - int resnum; - char resname[9]; - char old_resname[9]="noname"; - char alt_loc_check[2]=" "; - char x_temp[11]; - char y_temp[11]; - char z_temp[11]; - //char number[8]; - int number; - char chain[2]; - char inscode[2]=" "; - char alt_loc[2]=" "; - double x,y,z; /* Temporary coordinates values */ - FILE *fp; - double bfactor=9.99; - char temp_number[11]; - char temp_resnum[11]; - char temp_bfactor[11]; - int ss_flag=0; - - i=0; /* It is only one molecule to be read this was done for the moment instead of changing all "i" to 0 */ - - - //for (i=0;i<2;i++) - //{ - //#ifdef NOZLIB*/ - //fp=fopen(m[i].filename,"r"); /* Does file exist? */ - //#else - //fp=gzopen(m[i].filename,"r"); /* Does file exist? */ - //#endif - //printf("%s\n",m[0].filename); - strcpy(m[0].method,"undef"); - m[0].rank=-1; - m[0].score=-9999; - - fp=fopen(m[0].filename,"r"); /* Does file exist? */ - if (fp!=NULL) /* If yes, read in coordinates */ - { - /* Initialize things */ - //m[0].xcen=m[0].ycen=m[0].zcen=0; - atoms=0; - residues=0; - //#ifdef NOZLIB - //while(fgets(buff,255,fp)!=NULL) - //#else - //while(gzgets(fp,buff,255)!=NULL) - //#endif - while(fgets(buff,1000,fp)!=NULL) - { - //sscanf(buff,"%-6s %4d %-3s%1s%3s %1s%5s %7.3lf %7.3lf %7.3lf",line_flag,&number,name,residue,chain,&resnum,inscode,&x,&y,&z); - //sscanf(buff,"%s %d %s %s %s",line_flag,&number,name,residue,resname); - strcpy(line_flag,"undef"); - sscanf(buff,"%s",line_flag); - //printf("%s %s %s",m[0].filename,line_flag,&buff); - if(strcmp("REMARK",line_flag)==0) - { - sscanf(buff,"%s %s %s",line_flag,desc_flag,temp); - if(strcmp("SS",desc_flag)==0) - { - strcpy(m[0].ss,temp); - ss_flag=1; - //printf("%s\n",m[0].ss); - } - if(strcmp("METHOD",desc_flag)==0) - { - strcpy(m[0].method,temp); - //printf("%s\n",m[0].method); - } - if(strcmp("SCORE",desc_flag)==0) - { - m[0].score=atof(temp); - //strcpy(m[0].method,temp); - //printf("%lf\n",m[0].score); - } - } - if(strcmp("MODEL",line_flag)==0) - { - sscanf(buff,"%s %s",line_flag,temp); - m[0].rank=atoi(temp); - } - - //ATOM 5307 3HD1 ILE 340 -27.009 -9.984 11.751 1.00 0.00 - if(strcmp("ATOM",line_flag)==0 && buff[12] != 'H' && buff[13] != 'H') /* Is it an ATOM entry? */ - { - //printf("Heja: %s %s",m[0].filename,&buff); - strncpy_NULL(temp_number,&buff[6],5); - strncpy_NULL(name,&buff[13],3); - strncpy_NULL(residue,&buff[17],3); - if(atomflag == 'a' || - (atomflag == 'c' && strcmp("CB ",name) == 0) || - (atomflag == 'c' && strcmp("GLY",residue) == 0 && strcmp("CA ",name) == 0) || - (atomflag == 'b' && (strcmp("CA ",name) == 0 || strcmp("C ",name) == 0 || strcmp("O ",name) == 0 || strcmp("N ",name) ==0))) - { - //printf("%s",buff); - // printf("%s %c %c %c %s\n",name,buff[12],buff[13],buff[24],buff); - strncpy_NULL(alt_loc,&buff[16],1); - strncpy_NULL(chain,&buff[21],1); - strncpy_NULL(temp_resnum,&buff[22],4); - strncpy_NULL(resname,&buff[22],5); - strncpy_NULL(x_temp,&buff[30],8); - strncpy_NULL(y_temp,&buff[38],8); - strncpy_NULL(z_temp,&buff[46],8); - - number=atoi(temp_number); - resnum=atoi(temp_resnum); - if(strlen(buff)>=66) - { - - strncpy_NULL(temp_bfactor,&buff[60],6); - bfactor=atof(temp_bfactor); - // printf("%lf\n",bfactor); - } - - x=atof(x_temp); - y=atof(y_temp); - z=atof(z_temp); - //printf("test: %s %d %s %s %s %s %d %s %lf %lf %lf\n",line_flag,number,name,alt_loc,residue,chain,resnum,resname,x,y,z); - // printf("test: %s %d %s %s %s %s %d %s %lf %lf %lf\n",line_flag,number,name,alt_loc,residue,chain,resnum,resname,x,y,z); - //if (strcmp("N",name)==0) /* Is it an N atom => new residue? */ - //printf("%s %s\n",old_resname,resname); - if(strcmp(old_resname,resname)!=0) - { - m[0].sequence[residues]=aa321(residue); - residues++; - strcpy(alt_loc_check,alt_loc); - //printf("%s %s\n",resname,residue); - } - //sscanf(&buff[22],"%d %lf %lf %lf",&resnum,&x,&y,&z); - //printf("test %d %s %s %d %lf %lf %lf\n",number,name,residue,resnum,x,y,z); - if(strcmp(alt_loc_check,alt_loc)==0) - { - m[0].atm[atoms].x=x; - m[0].atm[atoms].y=y; - m[0].atm[atoms].z=z; - m[0].atm[atoms].bfactor=bfactor; - m[0].atm[atoms].resnum=resnum; - m[0].atm[atoms].number=number; //atoi(number); - m[0].atm[atoms].rescount=residues; - m[0].atm[atoms].selected=TRUE; - m[0].atm[atoms].deleted=FALSE; - strcpy(m[0].atm[atoms].name,name); - strcpy(m[0].atm[atoms].residue,residue); - strcpy(m[0].atm[atoms].resname,resname); - strcpy(m[0].atm[atoms].chain,chain); - - if(strcmp("CA ",name) == 0) - { - //printf("%s %s %s %s %d\n",m[0].filename,resname,residue,alt_loc,residues); - m[0].CA_ref[residues-1]=atoms; - } - //if(strcmp(old_resname,resname)!=0) - // { - // m[0].sequence[residues-1]=aa321(residue); - // } - - m[0].xcen+=x; - m[0].ycen+=y; - m[0].zcen+=z; - atoms++; - strcpy(old_resname,resname); - } - } - } - } - m[0].sequence[residues]='\0'; - m[0].atoms=atoms; - m[0].residues=residues; - m[0].xcen=m[0].xcen/atoms; - m[0].ycen=m[0].ycen/atoms; - m[0].zcen=m[0].zcen/atoms; - if(ss_flag == 0) - { - //fprintf(stderr,"No secondary structure information in file!\n"); - } - - fclose(fp); - //#ifdef NOZLIB - // fclose(fp); - //#else - // gzclose(fp); - //#endif - // if (atoms!=m[0].atoms) /* Are file sizes indentical? */ - //{ - // printf("Inconsistent number of atoms in file %s\n",m[0].filename); - // return(1); - //} - - } - else - { - printf("Couldn't open file \"%s\"\n",m[0].filename); - exit(1); - } - return(0); -} - -int read_molecules_ca(molecule *m) /* Reads in molecules to be superimposed */ -{ - int i,j,k,atoms,residues; /* Counter variables */ - char buff[1200]; /* Input string */ - char temp[1000]; /* Throwaway string */ - char line_flag[11]; /* PDB file line mode */ - char desc_flag[20]; - char residue[4]; /* PDB atom info for output */ - char name[4]; - int resnum; - char resname[9]; - char old_resname[9]="noname"; - char alt_loc_check[2]=" "; - char x_temp[11]; - char y_temp[11]; - char z_temp[11]; - //char number[8]; - int number; - char chain[2]; - char inscode[2]=" "; - char alt_loc[2]=" "; - double x,y,z; /* Temporary coordinates values */ - FILE *fp; - char temp_number[11]; - char temp_resnum[11]; - - i=0; /* It is only one molecule to be read this was done for the moment instead of changing all "i" to 0 */ - - - //for (i=0;i<2;i++) - //{ - //#ifdef NOZLIB*/ - //fp=fopen(m[i].filename,"r"); /* Does file exist? */ - //#else - //fp=gzopen(m[i].filename,"r"); /* Does file exist? */ - //#endif - //printf("%s\n",m[0].filename); - strcpy(m[0].method,"undef"); - m[0].rank=-1; - m[0].score=-9999; - fp=fopen(m[0].filename,"r"); /* Does file exist? */ - if (fp!=NULL) /* If yes, read in coordinates */ - { - /* Initialize things */ - //m[0].xcen=m[0].ycen=m[0].zcen=0; - atoms=0; - residues=0; - //#ifdef NOZLIB - //while(fgets(buff,255,fp)!=NULL) - //#else - //while(gzgets(fp,buff,255)!=NULL) - //#endif - while(fgets(buff,1000,fp)!=NULL) - { - //sscanf(buff,"%-6s %4d %-3s%1s%3s %1s%5s %7.3lf %7.3lf %7.3lf",line_flag,&number,name,residue,chain,&resnum,inscode,&x,&y,&z); - //sscanf(buff,"%s %d %s %s %s",line_flag,&number,name,residue,resname); - sscanf(buff,"%s",line_flag); - if(strcmp("REMARK",line_flag)==0) - { - //printf("%s",buff); - sscanf(buff,"%s %s %s",line_flag,desc_flag,temp); - if(strcmp("SS",desc_flag)==0) - { - //printf("%s\n%d\n\n",buff,strlen(buff)); - strcpy(m[0].ss,temp); - //printf("%s\n%d\n",m[0].ss,strlen(m[0].ss)); - } - if(strcmp("METHOD",desc_flag)==0) - { - strcpy(m[0].method,temp); - //printf("%s\n",m[0].method); - } - if(strcmp("SCORE",desc_flag)==0) - { - m[0].score=atof(temp); - //strcpy(m[0].method,temp); - //printf("%lf\n",m[0].score); - } - - } - if(strcmp("MODEL",line_flag)==0) - { - sscanf(buff,"%s %s",line_flag,temp); - m[0].rank=atoi(temp); - } - - if (strcmp("ATOM",line_flag)==0 && buff[13] != 'H') /* Is it an ATOM entry? */ - { - strncpy_NULL(temp_number,&buff[6],5); - strncpy_NULL(name,&buff[13],3); - //printf("%s",&buff[6]); - if(strcmp("CA ",name) == 0) - { - //printf("%s",&buff[6]); - strncpy_NULL(alt_loc,&buff[16],1); - strncpy_NULL(residue,&buff[17],3); - strncpy_NULL(chain,&buff[21],1); - strncpy_NULL(temp_resnum,&buff[22],4); - strncpy_NULL(resname,&buff[22],5); - strncpy_NULL(x_temp,&buff[30],8); - strncpy_NULL(y_temp,&buff[38],8); - strncpy_NULL(z_temp,&buff[46],8); - - number=atoi(temp_number); - resnum=atoi(temp_resnum); - x=atof(x_temp); - y=atof(y_temp); - z=atof(z_temp); - - - //printf("test: %s %d %s %s %s %s %d %s %lf %lf %lf\n",line_flag,number,name,alt_loc,residue,chain,resnum,resname,x,y,z); - //if (strcmp("N",name)==0) /* Is it an N atom => new residue? */ - //printf("%s %s\n",old_resname,resname); - if(strcmp(old_resname,resname)!=0) - { - m[0].sequence[residues]=aa321(residue); - residues++; - strcpy(alt_loc_check,alt_loc); - //printf("%s %s\n",resname,residue); - } - //sscanf(&buff[22],"%d %lf %lf %lf",&resnum,&x,&y,&z); - //printf("test %d %s %s %d %lf %lf %lf\n",number,name,residue,resnum,x,y,z); - if(strcmp(alt_loc_check,alt_loc)==0) - { - m[0].atm[atoms].x=x; - m[0].atm[atoms].y=y; - m[0].atm[atoms].z=z; - m[0].atm[atoms].resnum=resnum; - m[0].atm[atoms].number=number; //atoi(number); - m[0].atm[atoms].rescount=residues; - m[0].atm[atoms].selected=TRUE; - strcpy(m[0].atm[atoms].name,name); - strcpy(m[0].atm[atoms].residue,residue); - //if(strcmp(old_resname,resname)!=0) - // { - // m[0].sequence[residues-1]=aa321(residue); - // } - - m[0].xcen+=x; - m[0].ycen+=y; - m[0].zcen+=z; - atoms++; - strcpy(old_resname,resname); - } - } - } - } - m[0].sequence[residues]='\0'; - m[0].atoms=atoms; - m[0].residues=residues; - m[0].xcen=m[0].xcen/atoms; - m[0].ycen=m[0].ycen/atoms; - m[0].zcen=m[0].zcen/atoms; - fclose(fp); - //#ifdef NOZLIB - // fclose(fp); - //#else - // gzclose(fp); - //#endif - // if (atoms!=m[0].atoms) /* Are file sizes indentical? */ - //{ - // printf("Inconsistent number of atoms in file %s\n",m[0].filename); - // return(1); - //} - - } - else - { - printf("Couldn't open file \"%s\"\n",m[0].filename); - exit(1); - } - return(0); -} - - -int read_molecules_backbone(molecule *m) /* Reads in molecules to be superimposed */ -{ - int i,j,k,atoms,residues; /* Counter variables */ - char buff[1200]; /* Input string */ - char temp[1000]; /* Throwaway string */ - char line_flag[11]; /* PDB file line mode */ - char desc_flag[20]; - char residue[4]; /* PDB atom info for output */ - char name[4]; - int resnum; - char resname[9]; - char old_resname[9]="noname"; - char x_temp[11]; - char y_temp[11]; - char z_temp[11]; - //char number[8]; - int number; - char chain[2]; - char inscode[2]=" "; - char alt_loc[2]=" "; - double x,y,z; /* Temporary coordinates values */ - FILE *fp; - char temp_number[11]; - char temp_resnum[11]; - i=0; /* It is only one molecule to be read this was done for the moment instead of changing all "i" to 0 */ - //printf("%s\n",m[0].filename); - strcpy(m[0].method,"undef"); - m[0].rank=-1; - m[0].score=-9999; - - fp=fopen(m[0].filename,"r"); /* Does file exist? */ - if (fp!=NULL) /* If yes, read in coordinates */ - { - /* Initialize things */ - atoms=0; - residues=0; - while(fgets(buff,1000,fp)!=NULL) - { - //sscanf(buff,"%-6s %4d %-3s%1s%3s %1s%5s %7.3lf %7.3lf %7.3lf",line_flag,&number,name,residue,chain,&resnum,inscode,&x,&y,&z); - //sscanf(buff,"%s %d %s %s %s",line_flag,&number,name,residue,resname); - sscanf(buff,"%s",line_flag); - if(strcmp("REMARK",line_flag)==0) - { - sscanf(buff,"%s %s %s",line_flag,desc_flag,temp); - if(strcmp("SS",desc_flag)==0) - { - //strcpy(m[0].ss,temp); - strncpy_NULL(m[0].ss,temp,strlen(temp)); - // printf("%s\n",m[0].ss); - } - if(strcmp("METHOD",desc_flag)==0) - { - //strcpy(m[0].method,temp); - strncpy_NULL(m[0].method,temp,strlen(temp)); - //printf("%s\n",m[0].method); - } - if(strcmp("SCORE",desc_flag)==0) - { - m[0].score=atof(temp); - //strcpy(m[0].method,temp); - //printf("%lf\n",m[0].score); - } - - } - if(strcmp("MODEL",line_flag)==0) - { - sscanf(buff,"%s %s",line_flag,temp); - m[0].rank=atoi(temp); - } - if(strcmp("ATOM",line_flag)==0) /* Is it an ATOM entry? */ - { - //printf("%s",&buff[6]); - strncpy_NULL(temp_number,&buff[6],5); - strncpy_NULL(name,&buff[13],3); - //printf("%s",&buff[6]); - if(strcmp("CA ",name) == 0 || - strcmp("C ",name) == 0 || - strcmp("O ",name) == 0 || - strcmp("N ",name) ==0) - { - //printf("%d %s",2,&buff[6]); - strncpy_NULL(alt_loc,&buff[16],1); - strncpy_NULL(residue,&buff[17],3); - strncpy_NULL(chain,&buff[21],1); - strncpy_NULL(temp_resnum,&buff[22],4); - strncpy_NULL(resname,&buff[22],5); - strncpy_NULL(x_temp,&buff[30],8); - strncpy_NULL(y_temp,&buff[38],8); - strncpy_NULL(z_temp,&buff[46],8); - - - //(strcmp("CA ",name) !=0) - // - number=atoi(temp_number); - resnum=atoi(temp_resnum); - x=atof(x_temp); - y=atof(y_temp); - z=atof(z_temp); - - //printf("test: %s %d %s %s %s %s %d %s %lf %lf %lf\n",line_flag,number,name,alt_loc,residue,chain,resnum,resname,x,y,z); - //if (strcmp("N",name)==0) /* Is it an N atom => new residue? */ - //printf("%s %s\n",old_resname,resname); - if(strcmp(old_resname,resname)!=0) - { - m[0].sequence[residues]=aa321(residue); - m[0].res_ref[residues]=atoms; - residues++; - //printf("%s %s\n",resname,residue); - } - //printf("%s %s\n",resname,residue); - // } - //sscanf(&buff[22],"%d %lf %lf %lf",&resnum,&x,&y,&z); - //printf("test %d %s %s %d %lf %lf %lf\n",number,name,residue,resnum,x,y,z); - m[0].atm[atoms].x=x; - m[0].atm[atoms].y=y; - m[0].atm[atoms].z=z; - m[0].atm[atoms].resnum=resnum; - //printf("%d\n",m[0].atm[atoms].resnum); - m[0].atm[atoms].number=number; //atoi(number); - m[0].atm[atoms].rescount=residues; - m[0].atm[atoms].selected=TRUE; - strcpy(m[0].atm[atoms].name,name); - strcpy(m[0].atm[atoms].residue,residue); - if(strcmp("CA ",name) == 0) - { - //printf("%s %s %s %d\n",resname,residue,alt_loc,residues); - m[0].CA_ref[residues-1]=atoms; - } - - // if(strcmp(old_resname,resname)!=0) - // { - // m[0].sequence[residues-1]=aa321(residue); - // } - - m[0].xcen+=x; - m[0].ycen+=y; - m[0].zcen+=z; - atoms++; - strcpy(old_resname,resname); - //} - } - } - } - m[0].sequence[residues]='\0'; - m[0].atoms=atoms; - m[0].residues=residues; - m[0].xcen=m[0].xcen/atoms; - m[0].ycen=m[0].ycen/atoms; - m[0].zcen=m[0].zcen/atoms; - - - fclose(fp); - //#ifdef NOZLIB - // fclose(fp); - //#else - // gzclose(fp); - //#endif - // if (atoms!=m[0].atoms) /* Are file sizes indentical? */ - //{ - // printf("Inconsistent number of atoms in file %s\n",m[0].filename); - // return(1); - //} - - } - else - { - printf("Couldn't open file \"%s\"\n",m[0].filename); - exit(1); - } - return(0); -} - - -void strncpy_NULL(char *dest, char *src, size_t n) -{ - strncpy(dest, src, n); - dest[n]='\0'; -} - - - - - - -double crd(molecule *m,int atomno1, int atomno2) /* atomnoX is the first atom of the residue */ -{ - int i,j; - double dist,lowest_dist; - lowest_dist=999999; - //printf("crd i: %d, j; %d\n",atomno1,atomno2); - for(i=atomno1;m[0].atm[i].rescount == m[0].atm[atomno1].rescount;i++) - { - // if(strcmp("C ",m[0].atm[i].name)!=0 && - // strcmp("O ",m[0].atm[i].name)!=0 && - // strcmp("N ",m[0].atm[i].name)!=0) - { - for(j=atomno2;m[0].atm[j].rescount == m[0].atm[atomno2].rescount;j++) - { - // if(strcmp("C ",m[0].atm[j].name)!=0 && - // strcmp("O ",m[0].atm[j].name)!=0 && - // strcmp("N ",m[0].atm[j].name)!=0) - { - dist=distance(m,i,j); - //printf("%f ",dist); - if(dist (b) ? (a) : (b)) -#undef min -#define min(a,b) ((a) < (b) ? (a) : (b)) - -//#define SIZE (sizeof(a) / sizeof(a[0])) - -typedef struct - { - double x,y,z; /* Atomic coordinates */ - double rms; /* RMS deviation */ - char residue[8]; /* PDB info for output */ - char name[8]; - int number; - int resnum; - char resname[8]; - int rescount; - int selected; - int deleted; - double bfactor; - char chain[2]; - } atm; - -typedef struct { - atm atm[MAXATMS]; - int CA_ref[MAXRES]; - int res_ref[MAXRES]; - double xcen,ycen,zcen; - int atoms; /* Current # of atoms */ - int residues; - char sequence[MAXRES]; - char ss[MAXRES]; - double score; - char method[200]; - int rank; - char filename[1000]; /* filename to read molecule from */ - -} molecule; - -typedef struct -{ - double x,y,z; -}my_vector; - - -/* OBS!!!!!!!!! - To relace *_ca and _backbone with one routine I - changed input to read_molecules(molecule *m,char atomflag) - atomflag == a -> read all atoms (except H) - atomflag == c -> CA atoms - atomflag == b -> backbone CA,C,N,O atoms -*/ - -enum aacodes -{ - ALA, ARG, ASN, ASP, CYS, - GLN, GLU, GLY, HIS, ILE, - LEU, LYS, MET, PHE, PRO, - SER, THR, TRP, TYR, VAL, - UNK -}; - - -int read_molecules(molecule *m,char atomflag); -int read_molecules_ca(molecule *m); -int read_molecules_backbone(molecule *m); - -void strncpy_NULL(char *dest, char *src, size_t n); - -double distance(molecule *m,int atomno1, int atomno2); -double crd(molecule *m,int atomno1, int atomno2); /*closest residue distance */ -char aa321(char *name); - - -#endif From 3f3ef96f79029577afe7d9318c38a41d158b6e38 Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 7 Mar 2023 09:03:49 +0100 Subject: [PATCH 022/173] duplicate atoms bug --- DockQ.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/DockQ.py b/DockQ.py index 43fa3be..1e2910e 100755 --- a/DockQ.py +++ b/DockQ.py @@ -344,7 +344,9 @@ def list_atoms_per_residue(model, group): n_atoms_per_residue = [] for chain in group: for residue in model[chain].get_residues(): - n_atoms_per_residue.append(len(residue.get_unpacked_list())) + # important to remove duplicate atoms (e.g. alternates) at this stage + atom_ids = set([a.id for a in residue.get_unpacked_list()]) + n_atoms_per_residue.append(len(atom_ids)) return n_atoms_per_residue From 7def6d9bb67cbd8a205911899a675dc33269f171 Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 7 Mar 2023 10:31:24 +0100 Subject: [PATCH 023/173] fix readme --- Makefile | 19 ------------------- README.md | 19 ++++++++----------- 2 files changed, 8 insertions(+), 30 deletions(-) delete mode 100644 Makefile diff --git a/Makefile b/Makefile deleted file mode 100644 index 8fb078f..0000000 --- a/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -FNAT=molecule.o fnat.o - -#CCFLAG=-static -static-libgcc -#CCFLAG=-w -LFLAG=-O3 -funroll-loops -Isrc/ - - -fnat: $(FNAT) - $(CC) $(LFLAG) $(CCFLAG) -o fnat $(FNAT) -lm - -fnat.o: src/fnat.c - $(CC) $(LFLAG) $(CCFLAG) -c src/fnat.c -lm -molecule.o: src/molecule.c src/molecule.h - $(CC) $(LFLAG) $(CCFLAG) -c src/molecule.c -lm - -.c.o: - $(CC) -c $(LFLAG) $(CCFLAG) $*.c -lm - - diff --git a/README.md b/README.md index baf5d7a..89dfb25 100644 --- a/README.md +++ b/README.md @@ -2,26 +2,23 @@ Requires python packages: `numpy` and `Biopython` Installation + +Just clone the repository, the main script `DockQ.py` is in the cloned folder: + ``` git clone https://github.com/bjornwallner/DockQ/ -cd DockQ -make ``` + Install (i) `numpy` (a prerequisite to install 'Biopython') and (ii) `Biopython` - Numpy: http://www.scipy.org/install.html -- Biopython version >=1.64: http://biopython.org/wiki/Download#Installation_Instructions - -Quick start for two interacting partners (two-chain-models) run with +- Biopython: http://biopython.org/wiki/Download#Installation_Instructions -`./DockQ.py ` - -To fix the residue numbering, in case there are inconsistencies, missing residues or small sequence differences between `model` and `native` +This version of DockQ has been tested with numpy v1.21.6 and biopython v1.79. -`scripts/fix_numbering.pl model.pdb native.pdb` - -will output a file, `model.pdb.fixed`, with a residue numbering corresponding to the that in the `native.pdb` based on the sequences from the two pdb files. +Quick start for two interacting partners (two-chain-models) run with: +`./DockQ.py ` Example From 850d624045c4fa9c6291f60eed331f33c35fb899 Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 7 Mar 2023 10:32:28 +0100 Subject: [PATCH 024/173] useless file --- clean.bash | 5 ----- 1 file changed, 5 deletions(-) delete mode 100755 clean.bash diff --git a/clean.bash b/clean.bash deleted file mode 100755 index ae01c05..0000000 --- a/clean.bash +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -rm molecule.o -rm fnat.o -rm fnat From e72c3888e3918facf24cf825fc1f98a12ccedd7d Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 7 Mar 2023 10:47:55 +0100 Subject: [PATCH 025/173] f-string everything --- DockQ.py | 421 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 292 insertions(+), 129 deletions(-) diff --git a/DockQ.py b/DockQ.py index 1e2910e..10759e4 100755 --- a/DockQ.py +++ b/DockQ.py @@ -16,9 +16,7 @@ def parse_args(): parser = ArgumentParser( description="DockQ - Quality measure for protein-protein docking models" ) - parser.add_argument( - "model", metavar="", type=str, help="path to model file" - ) + parser.add_argument("model", metavar="", type=str, help="path to model file") parser.add_argument( "native", metavar="", type=str, help="path to native file" ) @@ -155,57 +153,109 @@ def capri_class_DockQ(DockQ, capri_peptide=False): else: return "Undef" -#@profile -def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, use_CA_only=False, capri_peptide=False): + +# @profile +def calc_DockQ( + sample_model, + ref_model, + group1, + group2, + nat_group1, + nat_group2, + use_CA_only=False, + capri_peptide=False, +): atom_for_sup = ["CA", "C", "N", "O"] if not use_CA_only else ["CA"] fnat_threshold = 4.0 if capri_peptide else 5.0 interface_threshold = 8.0 if capri_peptide else 10.0 - + sample_res_distances = get_residue_distances(sample_model, group1, group2) ref_res_distances = get_residue_distances(ref_model, nat_group1, nat_group2) - - nat_correct, nonnat_count, nat_total, model_total = get_fnat_stats(sample_res_distances, ref_res_distances, thr=fnat_threshold) + + nat_correct, nonnat_count, nat_total, model_total = get_fnat_stats( + sample_res_distances, ref_res_distances, thr=fnat_threshold + ) fnat = nat_correct / nat_total fnonnat = nonnat_count / model_total # get a copy of each structure, then only keep backbone atoms. This is faster than copy.deepcopy() sample_model_backbone = pickle.loads(pickle.dumps(sample_model, -1)) ref_model_backbone = pickle.loads(pickle.dumps(ref_model, -1)) - set_common_backbone_atoms(sample_model_backbone, ref_model_backbone, atom_types=atom_for_sup) + set_common_backbone_atoms( + sample_model_backbone, ref_model_backbone, atom_types=atom_for_sup + ) if capri_peptide: - ref_res_distances = get_residue_distances(ref_model, nat_group1, nat_group2, all_atom=False) + ref_res_distances = get_residue_distances( + ref_model, nat_group1, nat_group2, all_atom=False + ) # Get interfacial atoms from reference, and corresponding atoms from sample - interacting_pairs = get_interacting_pairs(ref_res_distances, thr=interface_threshold) - sample_interface_atoms, ref_interface_atoms = get_interface_atoms(interacting_pairs, - sample_model_backbone, - ref_model_backbone, - group1, - group2, - nat_group1, - nat_group2) - + interacting_pairs = get_interacting_pairs( + ref_res_distances, thr=interface_threshold + ) + sample_interface_atoms, ref_interface_atoms = get_interface_atoms( + interacting_pairs, + sample_model_backbone, + ref_model_backbone, + group1, + group2, + nat_group1, + nat_group2, + ) + super_imposer = Bio.PDB.Superimposer() super_imposer.set_atoms(sample_interface_atoms, ref_interface_atoms) irms = super_imposer.rms - + # assign which group of chains constitutes the receptor, then the other is the ligand ref_group1_size = np.sum([len(ref_model[chain]) for chain in nat_group1]) ref_group2_size = np.sum([len(ref_model[chain]) for chain in nat_group2]) - receptor_chains = (nat_group1, group1) if ref_group1_size > ref_group2_size else (nat_group2, group2) - ligand_chains = (nat_group1, group1) if ref_group1_size <= ref_group2_size else (nat_group2, group2) - class1, class2 = ("receptor", "ligand") if ref_group1_size > ref_group2_size else ("ligand", "receptor") - receptor_atoms_native = [atom for chain in receptor_chains[0] for atom in ref_model_backbone[chain].get_atoms()] - receptor_atoms_sample = [atom for chain in receptor_chains[1] for atom in sample_model_backbone[chain].get_atoms()] - + receptor_chains = ( + (nat_group1, group1) + if ref_group1_size > ref_group2_size + else (nat_group2, group2) + ) + ligand_chains = ( + (nat_group1, group1) + if ref_group1_size <= ref_group2_size + else (nat_group2, group2) + ) + class1, class2 = ( + ("receptor", "ligand") + if ref_group1_size > ref_group2_size + else ("ligand", "receptor") + ) + receptor_atoms_native = [ + atom + for chain in receptor_chains[0] + for atom in ref_model_backbone[chain].get_atoms() + ] + receptor_atoms_sample = [ + atom + for chain in receptor_chains[1] + for atom in sample_model_backbone[chain].get_atoms() + ] + # Set to align on receptor super_imposer.set_atoms(receptor_atoms_native, receptor_atoms_sample) super_imposer.apply(sample_model_backbone.get_atoms()) receptor_chain_rms = super_imposer.rms - coord1 = np.array([atom.coord for chain in ligand_chains[0] for atom in ref_model_backbone[chain].get_atoms()]) - coord2 = np.array([atom.coord for chain in ligand_chains[1] for atom in sample_model_backbone[chain].get_atoms()]) + coord1 = np.array( + [ + atom.coord + for chain in ligand_chains[0] + for atom in ref_model_backbone[chain].get_atoms() + ] + ) + coord2 = np.array( + [ + atom.coord + for chain in ligand_chains[1] + for atom in sample_model_backbone[chain].get_atoms() + ] + ) sup = SVDSuperimposer() Lrms = sup._rms( @@ -239,19 +289,23 @@ def calc_DockQ(sample_model, ref_model, group1, group2, nat_group1, nat_group2, return info -def align_model_to_native(model_structure, native_structure, model_chain, native_chain, use_numbering=False): +def align_model_to_native( + model_structure, native_structure, model_chain, native_chain, use_numbering=False +): model_sequence = "".join( - seq1(residue.get_resname()) for residue in model_structure[model_chain].get_residues() + seq1(residue.get_resname()) + for residue in model_structure[model_chain].get_residues() ) - + native_sequence = "".join( - seq1(residue.get_resname()) for residue in native_structure[native_chain].get_residues() + seq1(residue.get_resname()) + for residue in native_structure[native_chain].get_residues() ) alignment = {} if use_numbering: model_numbering = [] native_numbering = [] - + for residue in model_structure[model_chain].get_residues(): resn = int(residue.id[1]) model_numbering.append(resn) @@ -259,7 +313,7 @@ def align_model_to_native(model_structure, native_structure, model_chain, native for residue in native_structure[native_chain].get_residues(): resn = int(residue.id[1]) native_numbering.append(resn) - + start = min(native_numbering + model_numbering) end = max(native_numbering + model_numbering) alignment["seqA"] = [] @@ -267,7 +321,7 @@ def align_model_to_native(model_structure, native_structure, model_chain, native model_sequence = iter(model_sequence) native_sequence = iter(native_sequence) - for i in range(start, end+1): + for i in range(start, end + 1): if i in model_numbering: next_model_res = next(model_sequence) else: @@ -277,7 +331,7 @@ def align_model_to_native(model_structure, native_structure, model_chain, native next_native_res = next(native_sequence) else: next_native_res = "-" - + if next_model_res != "-" or next_native_res != "-": alignment["seqA"].append(next_model_res) alignment["seqB"].append(next_native_res) @@ -308,34 +362,65 @@ def fix_chain_residues(model, chain, alignment, invert=False): for (aligned_residue_A, aligned_residue_B) in zip(seqA, seqB): if aligned_residue_A != "-": residue = next(residues) - if aligned_residue_B == "-": # gap residue: remove from structure + if aligned_residue_B == "-": # gap residue: remove from structure residues_to_delete.append(residue.get_full_id()) for _, _, _, res in residues_to_delete: model[chain].detach_child(res) -def get_distances_across_chains(model, group1, group2, all_atom=True): +def get_distances_across_chains(model, group1, group2, all_atom=True): if all_atom: - model_A_atoms = np.asarray([atom.get_coord() for chain in group1 for res in model[chain].get_residues() for atom in res.get_atoms()]) - model_B_atoms = np.asarray([atom.get_coord() for chain in group2 for res in model[chain].get_residues() for atom in res.get_atoms()]) + model_A_atoms = np.asarray( + [ + atom.get_coord() + for chain in group1 + for res in model[chain].get_residues() + for atom in res.get_atoms() + ] + ) + model_B_atoms = np.asarray( + [ + atom.get_coord() + for chain in group2 + for res in model[chain].get_residues() + for atom in res.get_atoms() + ] + ) else: - model_A_atoms = np.asarray([res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() for chain in group1 for res in model[chain].get_residues()]) - model_B_atoms = np.asarray([res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() for chain in group2 for res in model[chain].get_residues()]) + model_A_atoms = np.asarray( + [ + res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() + for chain in group1 + for res in model[chain].get_residues() + ] + ) + model_B_atoms = np.asarray( + [ + res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() + for chain in group2 + for res in model[chain].get_residues() + ] + ) - distances = np.sqrt(((model_A_atoms[:, None] - model_B_atoms[None, :]) ** 2).sum(-1)) + distances = np.sqrt( + ((model_A_atoms[:, None] - model_B_atoms[None, :]) ** 2).sum(-1) + ) return distances -#@profile + +# @profile def atom_distances_to_residue_distances(atom_distances, group_dic1, group_dic2): res_distances = np.zeros((len(group_dic1), len(group_dic2))) - + cum_i_atoms = 0 for i, i_atoms in enumerate(group_dic1): cum_j_atoms = 0 for j, j_atoms in enumerate(group_dic2): - res_distances[i, j] = atom_distances[cum_i_atoms:cum_i_atoms+i_atoms, cum_j_atoms:cum_j_atoms+j_atoms].min() - cum_j_atoms += j_atoms + res_distances[i, j] = atom_distances[ + cum_i_atoms : cum_i_atoms + i_atoms, cum_j_atoms : cum_j_atoms + j_atoms + ].min() + cum_j_atoms += j_atoms cum_i_atoms += i_atoms return res_distances @@ -350,17 +435,21 @@ def list_atoms_per_residue(model, group): return n_atoms_per_residue -#@profile +# @profile def get_residue_distances(structure, group1, group2, all_atom=True): # get information about how many atoms correspond to each amino acid in each group of chains n_atoms_per_res_group1 = list_atoms_per_residue(structure, group1) n_atoms_per_res_group2 = list_atoms_per_residue(structure, group2) - - model_atom_distances = get_distances_across_chains(structure, group1, group2, all_atom=all_atom) - + + model_atom_distances = get_distances_across_chains( + structure, group1, group2, all_atom=all_atom + ) + if all_atom: - model_res_distances = atom_distances_to_residue_distances(model_atom_distances, n_atoms_per_res_group1, n_atoms_per_res_group2) - else: # distances were already between CBs only + model_res_distances = atom_distances_to_residue_distances( + model_atom_distances, n_atoms_per_res_group1, n_atoms_per_res_group2 + ) + else: # distances were already between CBs only model_res_distances = model_atom_distances return model_res_distances @@ -372,31 +461,53 @@ def get_fnat_stats(model_res_distances, native_res_distances, thr=5.0): n_model_contacts = np.sum(model_contacts) n_shared_contacts = np.sum(model_contacts * native_contacts) n_non_native_contacts = np.sum(model_contacts * (1 - native_contacts)) - return (n_shared_contacts, n_non_native_contacts, n_native_contacts, n_model_contacts) + return ( + n_shared_contacts, + n_non_native_contacts, + n_native_contacts, + n_model_contacts, + ) def get_interacting_pairs(distances, thr=5.0): return np.nonzero(distances < thr) -#@profile -def get_interface_atoms(interacting_pairs, model_backbone, ref_backbone, model_group1, model_group2, ref_group1, ref_group2): + +# @profile +def get_interface_atoms( + interacting_pairs, + model_backbone, + ref_backbone, + model_group1, + model_group2, + ref_group1, + ref_group2, +): ref_interface = [] mod_interface = [] - ref_residues_group1 = [res for chain in ref_group1 for res in ref_backbone[chain].get_residues()] - ref_residues_group2 = [res for chain in ref_group2 for res in ref_backbone[chain].get_residues()] - - mod_residues_group1 = [res for chain in model_group1 for res in model_backbone[chain].get_residues()] - mod_residues_group2 = [res for chain in model_group2 for res in model_backbone[chain].get_residues()] - + ref_residues_group1 = [ + res for chain in ref_group1 for res in ref_backbone[chain].get_residues() + ] + ref_residues_group2 = [ + res for chain in ref_group2 for res in ref_backbone[chain].get_residues() + ] + + mod_residues_group1 = [ + res for chain in model_group1 for res in model_backbone[chain].get_residues() + ] + mod_residues_group2 = [ + res for chain in model_group2 for res in model_backbone[chain].get_residues() + ] + # remove duplicate residues interface_residues_group1 = set(interacting_pairs[0]) interface_residues_group2 = set(interacting_pairs[1]) - + for i in interface_residues_group1: ref_interface += [atom for atom in ref_residues_group1[i].get_atoms()] mod_interface += [atom for atom in mod_residues_group1[i].get_atoms()] - + for j in interface_residues_group2: ref_interface += [atom for atom in ref_residues_group2[j].get_atoms()] mod_interface += [atom for atom in mod_residues_group2[j].get_atoms()] @@ -409,30 +520,33 @@ def set_common_backbone_atoms(model, reference, atom_types=["CA", "C", "N", "O"] for mod_res, ref_res in zip(model.get_residues(), reference.get_residues()): mod_atoms = [atom for atom in mod_res.get_atoms()] ref_atoms = [atom for atom in ref_res.get_atoms()] - + atom_ids_in_mod_res = [atm.id for atm in mod_atoms] atom_ids_in_ref_res = [atm.id for atm in ref_atoms] - - atom_ids_in_ref_and_mod_res = set(atom_ids_in_mod_res).intersection(atom_types).intersection(atom_ids_in_ref_res) - + + atom_ids_in_ref_and_mod_res = ( + set(atom_ids_in_mod_res) + .intersection(atom_types) + .intersection(atom_ids_in_ref_res) + ) + # whatever atom is not in the shared list, remove it from the both structures for atom_id in set(atom_ids_in_mod_res).difference(atom_ids_in_ref_and_mod_res): mod_res.detach_child(atom_id) - + for atom_id in set(atom_ids_in_ref_res).difference(atom_ids_in_ref_and_mod_res): ref_res.detach_child(atom_id) -#@profile + +# @profile def main(): args = parse_args() - bio_ver = 1.61 + bio_ver = 1.79 if float(Bio.__version__) < bio_ver: print( - "Biopython version (%s) is too old need at least >=%.2f" - % (Bio.__version__, bio_ver) + f"WARNING: Biopython version {Bio.__version__} is older than the recommended version {bio_ver}" ) - sys.exit() # Start the parser pdb_parser = Bio.PDB.PDBParser(QUIET=True) @@ -462,10 +576,10 @@ def main(): if not args.skip_check and (len(model_chains) < 2 or len(native_chains) < 2): print("Need at least two chains in the two inputs\n") sys.exit() - + group1 = model_chains[0] group2 = model_chains[1] - + nat_group1 = native_chains[0] nat_group2 = native_chains[1] if len(model_chains) > 2 or len(native_chains) > 2: @@ -480,8 +594,8 @@ def main(): for c in model_chains: if c not in group1: group2.append(c) - nat_group1 = native_chains[:len(group1)] - nat_group2 = native_chains[len(group1):] + nat_group1 = native_chains[: len(group1)] + nat_group2 = native_chains[len(group1) :] if args.native_chain1: nat_group1 = args.native_chain1 @@ -495,8 +609,8 @@ def main(): nat_group2.append(c) if not args.model_chain1: - group1 = model_chains[:len(nat_group1)] - group2 = model_chains[len(nat_group1):] + group1 = model_chains[: len(nat_group1)] + group2 = model_chains[len(nat_group1) :] pe = 0 if args.perm1 or args.perm2: @@ -525,100 +639,145 @@ def main(): pe = 1 if args.verbose: print( - "Starting chain order permutation search (number of permutations: " - + str(pe_tot) - + ")" + f"Starting chain order permutation search (number of permutations: {pe_tot})" ) for g1 in combos1: for g2 in combos2: - - model_structure_this = pickle.loads(pickle.dumps(model_structure, -1)) - model_structure_this = remove_extra_chains(model_structure_this, chains_to_keep=g1 + g2) + + model_structure_this = pickle.loads( + pickle.dumps(model_structure, -1) + ) + model_structure_this = remove_extra_chains( + model_structure_this, chains_to_keep=g1 + g2 + ) # realign each model chain against the corresponding native chain - for model_chain, native_chain in zip(g1 + g2, nat_group1 + nat_group2): - alignment = align_model_to_native(model_structure, native_structure, model_chain, native_chain, use_numbering=args.no_needle) + for model_chain, native_chain in zip( + g1 + g2, nat_group1 + nat_group2 + ): + alignment = align_model_to_native( + model_structure, + native_structure, + model_chain, + native_chain, + use_numbering=args.no_needle, + ) fix_chain_residues(model_structure_this, model_chain, alignment) - fix_chain_residues(native_structure, native_chain, alignment, invert=True) - - test_dict = calc_DockQ(model_structure_this, native_structure, g1, g2, nat_group1, nat_group2, use_CA_only=args.useCA, capri_peptide=args.capri_peptide) + fix_chain_residues( + native_structure, native_chain, alignment, invert=True + ) + + test_dict = calc_DockQ( + model_structure_this, + native_structure, + g1, + g2, + nat_group1, + nat_group2, + use_CA_only=args.useCA, + capri_peptide=args.capri_peptide, + ) if not args.quiet: - print(str(pe) - + "/" - + str(pe_tot) - + " " - + "".join(g1) - + " -> " - + "".join(g2) - + " " - + str(test_dict["DockQ"]) + print( + f"{pe}/{pe_tot} {''.join(g1)} -> {''.join(g2)} {test_dict['DockQ']}" ) + if test_dict["DockQ"] > best_DockQ: best_DockQ = test_dict["DockQ"] info = test_dict best_g1 = g1 best_g2 = g2 - best_info = ( - "Best score ( " - + str(best_DockQ) - + " ) found for model -> native, chain1:" - + "".join(best_g1) - + " -> " - + "".join(nat_group1) - + " chain2:" - + "".join(best_g2) - + " -> " - + "".join(nat_group2) - ) + best_info = f"Best score ({best_DockQ}) found for model -> native, chain1: {''.join(best_g1)} -> {''.join(nat_group1)} chain2: {''.join(best_g2)} -> {''.join(nat_group2)}" if args.verbose: print(best_info) if not args.quiet: - print("Current best " + str(best_DockQ)) + print(f"Current best: {best_DockQ}") pe = pe + 1 if not args.quiet: print(best_info) else: - model_structure = remove_extra_chains(model_structure, chains_to_keep=group1 + group2) - native_structure = remove_extra_chains(native_structure, chains_to_keep=nat_group1 + nat_group2) - + model_structure = remove_extra_chains( + model_structure, chains_to_keep=group1 + group2 + ) + native_structure = remove_extra_chains( + native_structure, chains_to_keep=nat_group1 + nat_group2 + ) + # realign each model chain against the corresponding native chain - for model_chain, native_chain in zip(group1 + group2, nat_group1 + nat_group2): - alignment = align_model_to_native(model_structure, native_structure, model_chain, native_chain, use_numbering=args.no_needle) + for model_chain, native_chain in zip( + group1 + group2, nat_group1 + nat_group2 + ): + alignment = align_model_to_native( + model_structure, + native_structure, + model_chain, + native_chain, + use_numbering=args.no_needle, + ) fix_chain_residues(model_structure, model_chain, alignment) - fix_chain_residues(native_structure, native_chain, alignment, invert=True) - info = calc_DockQ(model_structure, native_structure, group1, group2, nat_group1, nat_group2, use_CA_only=args.useCA, capri_peptide=args.capri_peptide) + fix_chain_residues( + native_structure, native_chain, alignment, invert=True + ) + info = calc_DockQ( + model_structure, + native_structure, + group1, + group2, + nat_group1, + nat_group2, + use_CA_only=args.useCA, + capri_peptide=args.capri_peptide, + ) else: - model_structure = remove_extra_chains(model_structure, chains_to_keep=group1 + group2) - native_structure = remove_extra_chains(native_structure, chains_to_keep=nat_group1 + nat_group2) - - + model_structure = remove_extra_chains( + model_structure, chains_to_keep=group1 + group2 + ) + native_structure = remove_extra_chains( + native_structure, chains_to_keep=nat_group1 + nat_group2 + ) + # realign each model chain against the corresponding native chain for model_chain, native_chain in zip(group1 + group2, nat_group1 + nat_group2): - alignment = align_model_to_native(model_structure, native_structure, model_chain, native_chain, use_numbering=args.no_needle) + alignment = align_model_to_native( + model_structure, + native_structure, + model_chain, + native_chain, + use_numbering=args.no_needle, + ) fix_chain_residues(model_structure, model_chain, alignment) fix_chain_residues(native_structure, native_chain, alignment, invert=True) - info = calc_DockQ(model_structure, native_structure, group1, group2, nat_group1, nat_group2, use_CA_only=args.useCA, capri_peptide=args.capri_peptide) + info = calc_DockQ( + model_structure, + native_structure, + group1, + group2, + nat_group1, + nat_group2, + use_CA_only=args.useCA, + capri_peptide=args.capri_peptide, + ) info["model"] = args.model info["native"] = args.native info["best"] = best_info print_results(info, args.short, args.capri_peptide) + def print_results(info, short=False, capri_peptide=False): if short: - capri_peptide_str = "-capri_peptide" if capri_peptide else "" + capri_peptide_str = "-capri_peptide" if capri_peptide else "" print( ( f"DockQ{capri_peptide_str} {info['DockQ']:.3f} Fnat {info['fnat']:.3f} iRMS {info['irms']:.3f} LRMS {info['Lrms']:.3f} Fnonnat {info['fnonnat']:.3f} {info['model']} {info['native']} {info['best']}" ) ) - else: if capri_peptide: print("****************************************************************") @@ -676,7 +835,11 @@ def print_results(info, short=False, capri_peptide=False): if capri_peptide: peptide_suffix = "_peptide" - peptide_disclaimer = " DockQ not reoptimized for CAPRI peptide evaluation" if capri_peptide else "" + peptide_disclaimer = ( + " DockQ not reoptimized for CAPRI peptide evaluation" + if capri_peptide + else "" + ) print(f"DockQ {info['DockQ']:.3f}{peptide_disclaimer}") From e9447a7daa43812ae5516ee07b7beb0e2dd96b29 Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 7 Mar 2023 10:56:49 +0100 Subject: [PATCH 026/173] unused variables --- DockQ.py | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/DockQ.py b/DockQ.py index 10759e4..f746293 100755 --- a/DockQ.py +++ b/DockQ.py @@ -38,12 +38,6 @@ def parse_args(): parser.add_argument( "-useCA", default=False, action="store_true", help="use CA instead of backbone" ) - parser.add_argument( - "-skip_check", - default=False, - action="store_true", - help="skip initial check fo speed up on two chain examples", - ) parser.add_argument( "-no_needle", default=False, @@ -555,14 +549,10 @@ def main(): native_structure = pdb_parser.get_structure("reference", args.native)[0] model_structure = pdb_parser.get_structure("model", args.model)[0] - model_chains = [] - native_chains = [] best_info = "" - if not args.skip_check: - native_chains = [c.id for c in native_structure] - model_chains = [c.id for c in model_structure] - files_to_clean = [] + model_chains = [c.id for c in model_structure] + native_chains = [c.id for c in native_structure] if (len(model_chains) > 2 or len(native_chains) > 2) and ( args.model_chain1 == None and args.native_chain1 == None @@ -570,10 +560,10 @@ def main(): print( "Multi-chain model need sets of chains to group\nuse -native_chain1 and/or -model_chain1 if you want a different mapping than 1-1" ) - print("Model chains : " + str(model_chains)) - print("Native chains : " + str(native_chains)) + print(f"Model chains: {' '.join(model_chains)}") + print(f"Native chains: {' '.join(native_chains)}") sys.exit() - if not args.skip_check and (len(model_chains) < 2 or len(native_chains) < 2): + if len(model_chains) < 2 or len(native_chains) < 2: print("Need at least two chains in the two inputs\n") sys.exit() From d7b5742ce91589cf38ae43cd053db638433cec91 Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 7 Mar 2023 11:05:40 +0100 Subject: [PATCH 027/173] blacken --- DockQ.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/DockQ.py b/DockQ.py index f746293..8766342 100755 --- a/DockQ.py +++ b/DockQ.py @@ -551,7 +551,7 @@ def main(): best_info = "" - model_chains = [c.id for c in model_structure] + model_chains = [c.id for c in model_structure] native_chains = [c.id for c in native_structure] if (len(model_chains) > 2 or len(native_chains) > 2) and ( @@ -763,9 +763,7 @@ def print_results(info, short=False, capri_peptide=False): if short: capri_peptide_str = "-capri_peptide" if capri_peptide else "" print( - ( - f"DockQ{capri_peptide_str} {info['DockQ']:.3f} Fnat {info['fnat']:.3f} iRMS {info['irms']:.3f} LRMS {info['Lrms']:.3f} Fnonnat {info['fnonnat']:.3f} {info['model']} {info['native']} {info['best']}" - ) + f"DockQ{capri_peptide_str} {info['DockQ']:.3f} Fnat {info['fnat']:.3f} iRMS {info['irms']:.3f} LRMS {info['Lrms']:.3f} Fnonnat {info['fnonnat']:.3f} {info['model']} {info['native']} {info['best']}" ) else: @@ -810,14 +808,10 @@ def print_results(info, short=False, capri_peptide=False): f"Number of equivalent residues in chain {info['chain2']} {info['len2']} ({info['class2']})" ) print( - ( - f"Fnat {info['fnat']:.3f} {info['nat_correct']} correct of {info['nat_total']} native contacts" - ) + f"Fnat {info['fnat']:.3f} {info['nat_correct']} correct of {info['nat_total']} native contacts" ) print( - ( - f"Fnonnat {info['fnonnat']:.3f} {info['nonnat_count']} non-native of {info['model_total']} model contacts" - ) + f"Fnonnat {info['fnonnat']:.3f} {info['nonnat_count']} non-native of {info['model_total']} model contacts" ) print(f"iRMS {info['irms']:.3f}") print(f"LRMS {info['Lrms']:.3f}") From d0075e8f4e9a865763dac83a8c9b6edb928f4aef Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 7 Mar 2023 13:25:05 +0100 Subject: [PATCH 028/173] doi --- DockQ.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DockQ.py b/DockQ.py index 8766342..866cb4e 100755 --- a/DockQ.py +++ b/DockQ.py @@ -788,9 +788,9 @@ def print_results(info, short=False, capri_peptide=False): print("* 0.23 <= DockQ < 0.49 - Acceptable quality *") print("* 0.49 <= DockQ < 0.80 - Medium quality *") print("* DockQ >= 0.80 - High quality *") - print("* Reference: Sankar Basu and Bjorn Wallner, DockQ: A quality *") - print("* measure for protein-protein docking models, submitted *") - print("* *") + print("* Ref: S. Basu and B. Wallner, DockQ: A quality measure for *") + print("* protein-protein docking models *") + print("* doi:10.1371/journal.pone.0161879 *") print("* For the record: *") print("* Definition of contact <5A (Fnat) *") print("* Definition of interface <10A all heavy atoms (iRMS) *") From 75efd6bdc7e5bc444c1d707d894618d03fcb40c0 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 8 Mar 2023 08:52:42 +0100 Subject: [PATCH 029/173] nicer chain grouping --- DockQ.py | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/DockQ.py b/DockQ.py index 866cb4e..683ddaa 100755 --- a/DockQ.py +++ b/DockQ.py @@ -148,7 +148,7 @@ def capri_class_DockQ(DockQ, capri_peptide=False): return "Undef" -# @profile +#@profile def calc_DockQ( sample_model, ref_model, @@ -532,7 +532,7 @@ def set_common_backbone_atoms(model, reference, atom_types=["CA", "C", "N", "O"] ref_res.detach_child(atom_id) -# @profile +#@profile def main(): args = parse_args() @@ -575,17 +575,18 @@ def main(): if len(model_chains) > 2 or len(native_chains) > 2: if args.model_chain1: group1 = args.model_chain1 - nat_group1 = group1 if args.model_chain2: group2 = args.model_chain2 else: # will use the complement from group1 - group2 = [] - for c in model_chains: - if c not in group1: - group2.append(c) - nat_group1 = native_chains[: len(group1)] - nat_group2 = native_chains[len(group1) :] + group2 = [chain for chain in model_chains if chain not in group1] + # temporarily set native chains to follow same mapping as model chains + if model_chains == native_chains: + nat_group1 = group1 + nat_group2 = group2 + else: + nat_group1 = native_chains[: len(group1)] + nat_group2 = native_chains[len(group1) :] if args.native_chain1: nat_group1 = args.native_chain1 @@ -593,14 +594,15 @@ def main(): nat_group2 = args.native_chain2 else: # will use the complement from group1 - nat_group2 = [] - for c in native_chains: - if c not in nat_group1: - nat_group2.append(c) - - if not args.model_chain1: - group1 = model_chains[: len(nat_group1)] - group2 = model_chains[len(nat_group1) :] + nat_group2 = [chain for chain in native_chains if chain not in nat_group1] + # if only native chains have been set, then assume model chains follow the same mapping + if not args.model_chain1: + if model_chains == native_chains: + group1 = nat_group1 + group2 = nat_group2 + else: # worst case scenario, group chains by whatever order they come from + group1 = model_chains[: len(nat_group1)] + group2 = model_chains[len(nat_group1) :] pe = 0 if args.perm1 or args.perm2: From cb54621318065970e324b822edcfc7fb9180344f Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 8 Mar 2023 09:33:05 +0100 Subject: [PATCH 030/173] refactor main --- DockQ.py | 300 ++++++++++++++++++++++--------------------------------- 1 file changed, 120 insertions(+), 180 deletions(-) diff --git a/DockQ.py b/DockQ.py index 683ddaa..4b9c3fc 100755 --- a/DockQ.py +++ b/DockQ.py @@ -532,6 +532,42 @@ def set_common_backbone_atoms(model, reference, atom_types=["CA", "C", "N", "O"] ref_res.detach_child(atom_id) +def run_on_groups(model_structure, native_structure, group1, group2, nat_group1, nat_group2, no_needle=False, use_CA_only=False, capri_peptide=False): + model_structure = remove_extra_chains( + model_structure, chains_to_keep=group1 + group2 + ) + native_structure = remove_extra_chains( + native_structure, chains_to_keep=nat_group1 + nat_group2 + ) + + # realign each model chain against the corresponding native chain + for model_chain, native_chain in zip( + group1 + group2, nat_group1 + nat_group2 + ): + alignment = align_model_to_native( + model_structure, + native_structure, + model_chain, + native_chain, + use_numbering=no_needle, + ) + fix_chain_residues(model_structure, model_chain, alignment) + fix_chain_residues( + native_structure, native_chain, alignment, invert=True + ) + info = calc_DockQ( + model_structure, + native_structure, + group1, + group2, + nat_group1, + nat_group2, + use_CA_only=use_CA_only, + capri_peptide=capri_peptide, + ) + return info + + #@profile def main(): args = parse_args() @@ -555,7 +591,7 @@ def main(): native_chains = [c.id for c in native_structure] if (len(model_chains) > 2 or len(native_chains) > 2) and ( - args.model_chain1 == None and args.native_chain1 == None + not args.model_chain1 and not args.native_chain1 ): print( "Multi-chain model need sets of chains to group\nuse -native_chain1 and/or -model_chain1 if you want a different mapping than 1-1" @@ -567,193 +603,97 @@ def main(): print("Need at least two chains in the two inputs\n") sys.exit() - group1 = model_chains[0] - group2 = model_chains[1] - - nat_group1 = native_chains[0] - nat_group2 = native_chains[1] - if len(model_chains) > 2 or len(native_chains) > 2: - if args.model_chain1: - group1 = args.model_chain1 - if args.model_chain2: - group2 = args.model_chain2 - else: - # will use the complement from group1 - group2 = [chain for chain in model_chains if chain not in group1] - # temporarily set native chains to follow same mapping as model chains - if model_chains == native_chains: - nat_group1 = group1 - nat_group2 = group2 - else: - nat_group1 = native_chains[: len(group1)] - nat_group2 = native_chains[len(group1) :] + # Some of these might be None + group1 = [model_chains[0]] if len(model_chains) == 2 else args.model_chain1 + group2 = args.model_chain2 + nat_group1 = args.native_chain1 + nat_group2 = args.native_chain2 + + # at this stage either group1 or nat_group1 are not None + if not nat_group1: # then the user has set group1. Try to follow the same mapping + if model_chains == native_chains: # easier case: the chains have the same naming between native/model, so just copy them + nat_group1 = group1 + # use complement to nat_group1 if group2 hasn't been decided yet + nat_group2 = group2 + else: # otherwise, group the chains by however many where in either model group + nat_group1 = native_chains[: len(group1)] + nat_group2 = native_chains[len(group1) :] + + if not group1: # viceversa, the user has set nat_group1 + if model_chains == native_chains: + group1 = nat_group1 + group2 = nat_group2 + else: + group1 = model_chains[: len(nat_group1)] + group2 = model_chains[len(nat_group1) :] + + if not group2: # no group2 set yet, use the complement to group1 + group2 = [chain for chain in model_chains if chain not in group1] + if not nat_group2: + nat_group2 = [chain for chain in native_chains if chain not in nat_group1] + + if not args.perm1 and not args.perm2: + info = run_on_groups(model_structure, native_structure, group1, group2, nat_group1, nat_group2, args.no_needle, args.useCA, args.capri_peptide) + else: # permute chains and run on a for loop + pe = 0 + best_DockQ = -1 + best_g1 = [] + best_g2 = [] + + iter_perm1 = itertools.combinations(group1, len(group1)) + iter_perm2 = itertools.combinations(group2, len(group2)) + if args.perm1: + iter_perm1 = itertools.permutations(group1) + if args.perm2: + iter_perm2 = itertools.permutations(group2) + + combos1 = [] + combos2 = [] + for g1 in iter_perm1: # _temp: + combos1.append(g1) + for g2 in iter_perm2: + combos2.append(g2) + + for g1 in combos1: + for g2 in combos2: + pe = pe + 1 + pe_tot = pe + pe = 1 + if args.verbose: + print( + f"Starting chain order permutation search (number of permutations: {pe_tot})" + ) - if args.native_chain1: - nat_group1 = args.native_chain1 - if args.native_chain2: - nat_group2 = args.native_chain2 - else: - # will use the complement from group1 - nat_group2 = [chain for chain in native_chains if chain not in nat_group1] - # if only native chains have been set, then assume model chains follow the same mapping - if not args.model_chain1: - if model_chains == native_chains: - group1 = nat_group1 - group2 = nat_group2 - else: # worst case scenario, group chains by whatever order they come from - group1 = model_chains[: len(nat_group1)] - group2 = model_chains[len(nat_group1) :] + for g1 in combos1: + for g2 in combos2: - pe = 0 - if args.perm1 or args.perm2: - best_DockQ = -1 - best_g1 = [] - best_g2 = [] - - iter_perm1 = itertools.combinations(group1, len(group1)) - iter_perm2 = itertools.combinations(group2, len(group2)) - if args.perm1: - iter_perm1 = itertools.permutations(group1) - if args.perm2: - iter_perm2 = itertools.permutations(group2) - - combos1 = [] - combos2 = [] - for g1 in iter_perm1: # _temp: - combos1.append(g1) - for g2 in iter_perm2: - combos2.append(g2) - - for g1 in combos1: - for g2 in combos2: - pe = pe + 1 - pe_tot = pe - pe = 1 - if args.verbose: - print( - f"Starting chain order permutation search (number of permutations: {pe_tot})" + model_structure_this = pickle.loads( + pickle.dumps(model_structure, -1) ) + model_structure_this = remove_extra_chains( + model_structure_this, chains_to_keep=g1 + g2 + ) + test_info = run_on_groups(model_structure_this, native_structure, g1, g2, nat_group1, nat_group2, args.no_needle, args.useCA, args.capri_peptide) - for g1 in combos1: - for g2 in combos2: - - model_structure_this = pickle.loads( - pickle.dumps(model_structure, -1) - ) - model_structure_this = remove_extra_chains( - model_structure_this, chains_to_keep=g1 + g2 + if not args.quiet: + print( + f"{pe}/{pe_tot} {''.join(g1)} -> {''.join(g2)} {test_info['DockQ']}" ) - # realign each model chain against the corresponding native chain - for model_chain, native_chain in zip( - g1 + g2, nat_group1 + nat_group2 - ): - alignment = align_model_to_native( - model_structure, - native_structure, - model_chain, - native_chain, - use_numbering=args.no_needle, - ) - fix_chain_residues(model_structure_this, model_chain, alignment) - fix_chain_residues( - native_structure, native_chain, alignment, invert=True - ) - - test_dict = calc_DockQ( - model_structure_this, - native_structure, - g1, - g2, - nat_group1, - nat_group2, - use_CA_only=args.useCA, - capri_peptide=args.capri_peptide, - ) + if test_info["DockQ"] > best_DockQ: + best_DockQ = test_info["DockQ"] + info = test_info + best_g1 = g1 + best_g2 = g2 + best_info = f"Best score ({best_DockQ}) found for model -> native, chain1: {''.join(best_g1)} -> {''.join(nat_group1)} chain2: {''.join(best_g2)} -> {''.join(nat_group2)}" + if args.verbose: + print(best_info) if not args.quiet: - print( - f"{pe}/{pe_tot} {''.join(g1)} -> {''.join(g2)} {test_dict['DockQ']}" - ) - - if test_dict["DockQ"] > best_DockQ: - best_DockQ = test_dict["DockQ"] - info = test_dict - best_g1 = g1 - best_g2 = g2 - best_info = f"Best score ({best_DockQ}) found for model -> native, chain1: {''.join(best_g1)} -> {''.join(nat_group1)} chain2: {''.join(best_g2)} -> {''.join(nat_group2)}" - - if args.verbose: - print(best_info) - if not args.quiet: - print(f"Current best: {best_DockQ}") - pe = pe + 1 - if not args.quiet: - print(best_info) - else: - - model_structure = remove_extra_chains( - model_structure, chains_to_keep=group1 + group2 - ) - native_structure = remove_extra_chains( - native_structure, chains_to_keep=nat_group1 + nat_group2 - ) - - # realign each model chain against the corresponding native chain - for model_chain, native_chain in zip( - group1 + group2, nat_group1 + nat_group2 - ): - alignment = align_model_to_native( - model_structure, - native_structure, - model_chain, - native_chain, - use_numbering=args.no_needle, - ) - fix_chain_residues(model_structure, model_chain, alignment) - fix_chain_residues( - native_structure, native_chain, alignment, invert=True - ) - info = calc_DockQ( - model_structure, - native_structure, - group1, - group2, - nat_group1, - nat_group2, - use_CA_only=args.useCA, - capri_peptide=args.capri_peptide, - ) - - else: - model_structure = remove_extra_chains( - model_structure, chains_to_keep=group1 + group2 - ) - native_structure = remove_extra_chains( - native_structure, chains_to_keep=nat_group1 + nat_group2 - ) - - # realign each model chain against the corresponding native chain - for model_chain, native_chain in zip(group1 + group2, nat_group1 + nat_group2): - alignment = align_model_to_native( - model_structure, - native_structure, - model_chain, - native_chain, - use_numbering=args.no_needle, - ) - fix_chain_residues(model_structure, model_chain, alignment) - fix_chain_residues(native_structure, native_chain, alignment, invert=True) - info = calc_DockQ( - model_structure, - native_structure, - group1, - group2, - nat_group1, - nat_group2, - use_CA_only=args.useCA, - capri_peptide=args.capri_peptide, - ) + print(f"Current best: {best_DockQ}") + pe = pe + 1 + if not args.quiet: + print(best_info) info["model"] = args.model info["native"] = args.native From 58fdbd76d30b0dec8cb024223cae7db009d993ed Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 8 Mar 2023 11:00:33 +0100 Subject: [PATCH 031/173] mmcif support --- DockQ.py | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/DockQ.py b/DockQ.py index 4b9c3fc..59e2aad 100755 --- a/DockQ.py +++ b/DockQ.py @@ -38,6 +38,12 @@ def parse_args(): parser.add_argument( "-useCA", default=False, action="store_true", help="use CA instead of backbone" ) + parser.add_argument( + "-mmcif_model", default=False, action="store_true", help="The model is in mmCIF format" + ) + parser.add_argument( + "-mmcif_native", default=False, action="store_true", help="The native is in mmCIF format" + ) parser.add_argument( "-no_needle", default=False, @@ -568,6 +574,20 @@ def run_on_groups(model_structure, native_structure, group1, group2, nat_group1, return info +def load_PDB(path, n_model=0, is_mmcif=False): + + if not is_mmcif: + pdb_parser = Bio.PDB.PDBParser(QUIET=True) + else: + pdb_parser = Bio.PDB.MMCIFParser(QUIET=True) + + try: + structure = pdb_parser.get_structure("-", path) + model = structure[n_model] + except Exception as e: + print(e) + return model + #@profile def main(): args = parse_args() @@ -578,12 +598,8 @@ def main(): f"WARNING: Biopython version {Bio.__version__} is older than the recommended version {bio_ver}" ) - # Start the parser - pdb_parser = Bio.PDB.PDBParser(QUIET=True) - - # Get the structures - native_structure = pdb_parser.get_structure("reference", args.native)[0] - model_structure = pdb_parser.get_structure("model", args.model)[0] + native_structure = load_PDB(args.native, is_mmcif=args.mmcif_native) + model_structure = load_PDB(args.model, is_mmcif=args.mmcif_model) best_info = "" From 356a75f6eb77e54facb1b2afeaaf4ca54af7c0c4 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 8 Mar 2023 11:22:16 +0100 Subject: [PATCH 032/173] better error handling --- DockQ.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/DockQ.py b/DockQ.py index 59e2aad..e20c9a5 100755 --- a/DockQ.py +++ b/DockQ.py @@ -3,6 +3,7 @@ import sys import os import pickle +import traceback import itertools import numpy as np from argparse import ArgumentParser @@ -585,7 +586,11 @@ def load_PDB(path, n_model=0, is_mmcif=False): structure = pdb_parser.get_structure("-", path) model = structure[n_model] except Exception as e: - print(e) + print("ERROR: is the file in the correct format? (.pdb, .mmcif)") + if not is_mmcif: + print(" (use -mmcif_model or -mmcif_native if either is in mmCIF format)") + print(traceback.format_exc()) + sys.exit(1) return model #@profile From de7888ee5ab27433f5f30a757f3754bf6e01c473 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 8 Mar 2023 11:26:47 +0100 Subject: [PATCH 033/173] fix help --- DockQ.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DockQ.py b/DockQ.py index e20c9a5..1219728 100755 --- a/DockQ.py +++ b/DockQ.py @@ -49,7 +49,7 @@ def parse_args(): "-no_needle", default=False, action="store_true", - help="do not use global alignment to fix residue numbering between native and model during chain permutation (use only in case needle is not installed, and the residues between the chains are identical", + help="Do not align native and model using sequence alignments, but use the numbering of residues instead", ) parser.add_argument( "-perm1", @@ -588,7 +588,7 @@ def load_PDB(path, n_model=0, is_mmcif=False): except Exception as e: print("ERROR: is the file in the correct format? (.pdb, .mmcif)") if not is_mmcif: - print(" (use -mmcif_model or -mmcif_native if either is in mmCIF format)") + print(" (use -mmcif_model or -mmcif_native with mmCIF inputs)") print(traceback.format_exc()) sys.exit(1) return model From 7079cc899c295943cd27f0a0f838efeb8897e6ba Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 8 Mar 2023 12:04:22 +0100 Subject: [PATCH 034/173] ignore hydrogens --- DockQ.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/DockQ.py b/DockQ.py index 1219728..1614f94 100755 --- a/DockQ.py +++ b/DockQ.py @@ -378,6 +378,7 @@ def get_distances_across_chains(model, group1, group2, all_atom=True): for chain in group1 for res in model[chain].get_residues() for atom in res.get_atoms() + if atom.element != "H" ] ) model_B_atoms = np.asarray( @@ -386,6 +387,7 @@ def get_distances_across_chains(model, group1, group2, all_atom=True): for chain in group2 for res in model[chain].get_residues() for atom in res.get_atoms() + if atom.element != "H" ] ) else: @@ -430,8 +432,8 @@ def list_atoms_per_residue(model, group): n_atoms_per_residue = [] for chain in group: for residue in model[chain].get_residues(): - # important to remove duplicate atoms (e.g. alternates) at this stage - atom_ids = set([a.id for a in residue.get_unpacked_list()]) + # important to remove duplicate atoms (e.g. alternates) at this stage, remove also hydrogens + atom_ids = set([a.id for a in residue.get_unpacked_list() if a.element != "H"]) n_atoms_per_residue.append(len(atom_ids)) return n_atoms_per_residue From ab3780ab2c8131a218d1037b8c1d933f32b8fbf2 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 8 Mar 2023 13:08:22 +0100 Subject: [PATCH 035/173] simplify --- DockQ.py | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/DockQ.py b/DockQ.py index 1614f94..2d40409 100755 --- a/DockQ.py +++ b/DockQ.py @@ -658,10 +658,7 @@ def main(): if not args.perm1 and not args.perm2: info = run_on_groups(model_structure, native_structure, group1, group2, nat_group1, nat_group2, args.no_needle, args.useCA, args.capri_peptide) else: # permute chains and run on a for loop - pe = 0 best_DockQ = -1 - best_g1 = [] - best_g2 = [] iter_perm1 = itertools.combinations(group1, len(group1)) iter_perm2 = itertools.combinations(group2, len(group2)) @@ -670,17 +667,10 @@ def main(): if args.perm2: iter_perm2 = itertools.permutations(group2) - combos1 = [] - combos2 = [] - for g1 in iter_perm1: # _temp: - combos1.append(g1) - for g2 in iter_perm2: - combos2.append(g2) + combos1 = [g1 for g1 in iter_perm1] + combos2 = [g2 for g2 in iter_perm2] - for g1 in combos1: - for g2 in combos2: - pe = pe + 1 - pe_tot = pe + pe_tot = len(combos1) * len(combos2) pe = 1 if args.verbose: print( @@ -706,9 +696,7 @@ def main(): if test_info["DockQ"] > best_DockQ: best_DockQ = test_info["DockQ"] info = test_info - best_g1 = g1 - best_g2 = g2 - best_info = f"Best score ({best_DockQ}) found for model -> native, chain1: {''.join(best_g1)} -> {''.join(nat_group1)} chain2: {''.join(best_g2)} -> {''.join(nat_group2)}" + best_info = f"Best score ({best_DockQ}) found for model -> native, chain1: {''.join(g1)} -> {''.join(nat_group1)} chain2: {''.join(g2)} -> {''.join(nat_group2)}" if args.verbose: print(best_info) From 156ca88eafa804c74aa276956ccb46fc440ab5c6 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 9 Mar 2023 10:43:10 +0100 Subject: [PATCH 036/173] simplify --- DockQ.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DockQ.py b/DockQ.py index 2d40409..340cc7e 100755 --- a/DockQ.py +++ b/DockQ.py @@ -667,8 +667,8 @@ def main(): if args.perm2: iter_perm2 = itertools.permutations(group2) - combos1 = [g1 for g1 in iter_perm1] - combos2 = [g2 for g2 in iter_perm2] + combos1 = list(iter_perm1) + combos2 = list(iter_perm2) pe_tot = len(combos1) * len(combos2) pe = 1 From f98d143c1dd82d46af49828d5eda854686ac86e6 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 9 Mar 2023 10:45:36 +0100 Subject: [PATCH 037/173] fix naming --- DockQ.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DockQ.py b/DockQ.py index 340cc7e..2ed2ca0 100755 --- a/DockQ.py +++ b/DockQ.py @@ -413,13 +413,13 @@ def get_distances_across_chains(model, group1, group2, all_atom=True): # @profile -def atom_distances_to_residue_distances(atom_distances, group_dic1, group_dic2): - res_distances = np.zeros((len(group_dic1), len(group_dic2))) +def atom_distances_to_residue_distances(atom_distances, atoms_per_res1, atoms_per_res2): + res_distances = np.zeros((len(atoms_per_res1), len(atoms_per_res2))) cum_i_atoms = 0 - for i, i_atoms in enumerate(group_dic1): + for i, i_atoms in enumerate(atoms_per_res1): cum_j_atoms = 0 - for j, j_atoms in enumerate(group_dic2): + for j, j_atoms in enumerate(atoms_per_res2): res_distances[i, j] = atom_distances[ cum_i_atoms : cum_i_atoms + i_atoms, cum_j_atoms : cum_j_atoms + j_atoms ].min() From aeecfb2aeb62f169fc32ab3a85fe2103d10497a3 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 9 Mar 2023 10:49:22 +0100 Subject: [PATCH 038/173] redundant command --- DockQ.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/DockQ.py b/DockQ.py index 2ed2ca0..daa7b26 100755 --- a/DockQ.py +++ b/DockQ.py @@ -683,9 +683,6 @@ def main(): model_structure_this = pickle.loads( pickle.dumps(model_structure, -1) ) - model_structure_this = remove_extra_chains( - model_structure_this, chains_to_keep=g1 + g2 - ) test_info = run_on_groups(model_structure_this, native_structure, g1, g2, nat_group1, nat_group2, args.no_needle, args.useCA, args.capri_peptide) if not args.quiet: From f80c0c4074dda88a6c6009fbc1f0758e84f96c64 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 9 Mar 2023 10:54:21 +0100 Subject: [PATCH 039/173] superfluous variable --- DockQ.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/DockQ.py b/DockQ.py index daa7b26..a434d79 100755 --- a/DockQ.py +++ b/DockQ.py @@ -765,9 +765,6 @@ def print_results(info, short=False, capri_peptide=False): ) print(f"iRMS {info['irms']:.3f}") print(f"LRMS {info['Lrms']:.3f}") - peptide_suffix = "" - if capri_peptide: - peptide_suffix = "_peptide" peptide_disclaimer = ( " DockQ not reoptimized for CAPRI peptide evaluation" From bc9ab81157a4e87824b74bb91430e2538f4be10f Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 9 Mar 2023 14:10:35 +0100 Subject: [PATCH 040/173] fancy division --- DockQ.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/DockQ.py b/DockQ.py index a434d79..c1773a5 100755 --- a/DockQ.py +++ b/DockQ.py @@ -176,8 +176,9 @@ def calc_DockQ( nat_correct, nonnat_count, nat_total, model_total = get_fnat_stats( sample_res_distances, ref_res_distances, thr=fnat_threshold ) - fnat = nat_correct / nat_total - fnonnat = nonnat_count / model_total + # avoids divide by 0 errors + fnat = nat_total and nat_correct / nat_total or 0 + fnonnat = model_total and nonnat_count / model_total or 0 # get a copy of each structure, then only keep backbone atoms. This is faster than copy.deepcopy() sample_model_backbone = pickle.loads(pickle.dumps(sample_model, -1)) From 3d60a5445fe62badce03d156cf28a523d364f995 Mon Sep 17 00:00:00 2001 From: Claudio Date: Thu, 9 Mar 2023 21:41:18 +0100 Subject: [PATCH 041/173] move functions to cython --- pyproject.toml | 4 +++ setup.cfg | 18 ++++++++++ setup.py | 10 ++++++ DockQ.py => src/DockQ/DockQ.py | 22 ++++++------ src/DockQ/__init__.py | 0 src/DockQ/__main__.py | 5 +++ src/DockQ/operations.pyx | 65 ++++++++++++++++++++++++++++++++++ 7 files changed, 114 insertions(+), 10 deletions(-) create mode 100644 pyproject.toml create mode 100644 setup.cfg create mode 100644 setup.py rename DockQ.py => src/DockQ/DockQ.py (97%) create mode 100644 src/DockQ/__init__.py create mode 100644 src/DockQ/__main__.py create mode 100644 src/DockQ/operations.pyx diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..eda92d7 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,4 @@ +[build-system] +requires = ["setuptools", "cython"] +build-backend = "setuptools.build_meta" + diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..9a324ea --- /dev/null +++ b/setup.cfg @@ -0,0 +1,18 @@ +[metadata] +name = DockQ + +[options] +package_dir = + =src +packages = find: +install_requires = + numpy + biopython>=1.78 + +[options.packages.find] +where=src + +[options.entry_points] +console_scripts = + DockQ = DockQ.__main__:main + diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..9efc4fe --- /dev/null +++ b/setup.py @@ -0,0 +1,10 @@ +from setuptools import setup, Extension + +setup( + ext_modules=[ + Extension( + "DockQ.operations", sources=["src/DockQ/operations.pyx"], + ), + ], +) + diff --git a/DockQ.py b/src/DockQ/DockQ.py similarity index 97% rename from DockQ.py rename to src/DockQ/DockQ.py index c1773a5..a226275 100755 --- a/DockQ.py +++ b/src/DockQ/DockQ.py @@ -11,6 +11,7 @@ from Bio import pairwise2 from Bio.SeqUtils import seq1 from Bio.SVDSuperimposer import SVDSuperimposer +from .operations import residue_distances, get_fnat_stats def parse_args(): @@ -174,7 +175,7 @@ def calc_DockQ( ref_res_distances = get_residue_distances(ref_model, nat_group1, nat_group2) nat_correct, nonnat_count, nat_total, model_total = get_fnat_stats( - sample_res_distances, ref_res_distances, thr=fnat_threshold + sample_res_distances, ref_res_distances, threshold=fnat_threshold ) # avoids divide by 0 errors fnat = nat_total and nat_correct / nat_total or 0 @@ -436,7 +437,7 @@ def list_atoms_per_residue(model, group): # important to remove duplicate atoms (e.g. alternates) at this stage, remove also hydrogens atom_ids = set([a.id for a in residue.get_unpacked_list() if a.element != "H"]) n_atoms_per_residue.append(len(atom_ids)) - return n_atoms_per_residue + return np.cumsum(n_atoms_per_residue).astype(int) # @profile @@ -445,20 +446,21 @@ def get_residue_distances(structure, group1, group2, all_atom=True): n_atoms_per_res_group1 = list_atoms_per_residue(structure, group1) n_atoms_per_res_group2 = list_atoms_per_residue(structure, group2) - model_atom_distances = get_distances_across_chains( - structure, group1, group2, all_atom=all_atom - ) + if all_atom: - model_res_distances = atom_distances_to_residue_distances( - model_atom_distances, n_atoms_per_res_group1, n_atoms_per_res_group2 + atom_coordinates = np.array([atom.coord for atom in structure.get_atoms()]) + model_res_distances = residue_distances( + atom_coordinates, n_atoms_per_res_group1, n_atoms_per_res_group2 ) else: # distances were already between CBs only - model_res_distances = model_atom_distances + model_res_distances = get_distances_across_chains( + structure, group1, group2, all_atom=all_atom + ) return model_res_distances -def get_fnat_stats(model_res_distances, native_res_distances, thr=5.0): +def get_fnat_stats2(model_res_distances, native_res_distances, thr=5.0): native_contacts = native_res_distances < thr model_contacts = model_res_distances < thr n_native_contacts = np.sum(native_contacts) @@ -474,7 +476,7 @@ def get_fnat_stats(model_res_distances, native_res_distances, thr=5.0): def get_interacting_pairs(distances, thr=5.0): - return np.nonzero(distances < thr) + return np.nonzero(np.asarray(distances) < thr) # @profile diff --git a/src/DockQ/__init__.py b/src/DockQ/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/DockQ/__main__.py b/src/DockQ/__main__.py new file mode 100644 index 0000000..c37fe97 --- /dev/null +++ b/src/DockQ/__main__.py @@ -0,0 +1,5 @@ +from .DockQ import main + +if __name__ == "__main__": + main() + diff --git a/src/DockQ/operations.pyx b/src/DockQ/operations.pyx new file mode 100644 index 0000000..918fb1e --- /dev/null +++ b/src/DockQ/operations.pyx @@ -0,0 +1,65 @@ +#cython: language_level=3 +import numpy as np +cimport numpy as np +import cython +from libc.math cimport sqrt + + +def residue_distances(float [:,:] atom_coordinates, long [:] atoms_per_res1, long [:] atoms_per_res2, float threshold=5.0): + cdef: + int i, j, x, y + int n_res_i = len(atoms_per_res1) + int n_res_j = len(atoms_per_res2) + float min_d = 100.0 + float this_d + float [:,:] res_distances = np.zeros((n_res_i, n_res_j), dtype=np.float32) + + + for i in range(n_res_i): + n_atoms_res_i = atoms_per_res1[i] + for j in range(n_res_j): + n_atoms_res_j = atoms_per_res2[j] + + for x in range(n_atoms_res_i): + for y in range(n_atoms_res_j): + this_d = sqrt((atom_coordinates[x][0] - atom_coordinates[y][0])**2 + (atom_coordinates[x][1] - atom_coordinates[y][1])**2 + (atom_coordinates[x][2] - atom_coordinates[y][2])**2) + if this_d < min_d: + min_d = this_d + if min_d < threshold: + break + res_distances[i, j] = min_d + + return res_distances + + +def get_fnat_stats(float [:,:] model_res_distances, float [:,:] native_res_distances, float threshold=5.0): + cdef: + int model_shape_0 = model_res_distances.shape[0] + int model_shape_1 = model_res_distances.shape[1] + int native_shape_0 = native_res_distances.shape[0] + int native_shape_1 = native_res_distances.shape[1] + int i, j + int n_native_contacts = 0 + int n_model_contacts = 0 + int n_shared_contacts = 0 + int n_non_native_contacts = 0 + #unsigned char [:,:] model_contacts = np.zeros((model_shape_0, model_shape_1), dtype=np.uint8) + #unsigned char [:,:] native_contacts = np.zeros((native_shape_0, native_shape_1), dtype=np.uint8) + + for i in range(native_shape_0): + for j in range(native_shape_1): + if native_res_distances[i, j] < threshold: + n_native_contacts += 1 + if model_res_distances[i, j] < threshold: + n_shared_contacts += 1 + if model_res_distances[i, j] < threshold: + n_model_contacts += 1 + if native_res_distances[i, j] >= threshold: + n_non_native_contacts += 1 + + return ( + n_shared_contacts, + n_non_native_contacts, + n_native_contacts, + n_model_contacts, + ) From 58aadef9e488e44b9c229b8bc204431dc03ffb37 Mon Sep 17 00:00:00 2001 From: Claudio Date: Thu, 9 Mar 2023 22:28:38 +0100 Subject: [PATCH 042/173] bugfix --- src/DockQ/DockQ.py | 33 ++++++++++++++++++++++++--------- src/DockQ/operations.pyx | 35 ++++++++++++++++++----------------- 2 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index a226275..319e5bb 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -437,25 +437,40 @@ def list_atoms_per_residue(model, group): # important to remove duplicate atoms (e.g. alternates) at this stage, remove also hydrogens atom_ids = set([a.id for a in residue.get_unpacked_list() if a.element != "H"]) n_atoms_per_residue.append(len(atom_ids)) - return np.cumsum(n_atoms_per_residue).astype(int) + return np.array(n_atoms_per_residue).astype(int) # @profile -def get_residue_distances(structure, group1, group2, all_atom=True): +def get_residue_distances(model, group1, group2, all_atom=True): # get information about how many atoms correspond to each amino acid in each group of chains - n_atoms_per_res_group1 = list_atoms_per_residue(structure, group1) - n_atoms_per_res_group2 = list_atoms_per_residue(structure, group2) - - + n_atoms_per_res_group1 = list_atoms_per_residue(model, group1) + n_atoms_per_res_group2 = list_atoms_per_residue(model, group2) if all_atom: - atom_coordinates = np.array([atom.coord for atom in structure.get_atoms()]) + model_A_atoms = np.asarray( + [ + atom.get_coord() + for chain in group1 + for res in model[chain].get_residues() + for atom in res.get_atoms() + if atom.element != "H" + ] + ) + model_B_atoms = np.asarray( + [ + atom.get_coord() + for chain in group2 + for res in model[chain].get_residues() + for atom in res.get_atoms() + if atom.element != "H" + ] + ) model_res_distances = residue_distances( - atom_coordinates, n_atoms_per_res_group1, n_atoms_per_res_group2 + model_A_atoms, model_B_atoms, n_atoms_per_res_group1, n_atoms_per_res_group2 ) else: # distances were already between CBs only model_res_distances = get_distances_across_chains( - structure, group1, group2, all_atom=all_atom + model, group1, group2, all_atom=all_atom ) return model_res_distances diff --git a/src/DockQ/operations.pyx b/src/DockQ/operations.pyx index 918fb1e..147f395 100644 --- a/src/DockQ/operations.pyx +++ b/src/DockQ/operations.pyx @@ -5,29 +5,29 @@ import cython from libc.math cimport sqrt -def residue_distances(float [:,:] atom_coordinates, long [:] atoms_per_res1, long [:] atoms_per_res2, float threshold=5.0): +def residue_distances(float [:,:] atom_coordinates1, float [:,:] atom_coordinates2, long [:] atoms_per_res1, long [:] atoms_per_res2): cdef: - int i, j, x, y + int i, j, x, y, cum_i_atoms, cum_j_atoms int n_res_i = len(atoms_per_res1) int n_res_j = len(atoms_per_res2) - float min_d = 100.0 - float this_d - float [:,:] res_distances = np.zeros((n_res_i, n_res_j), dtype=np.float32) + float this_d, min_d + float [:,:] res_distances = np.zeros((n_res_i, n_res_j), dtype=np.float32) - - for i in range(n_res_i): - n_atoms_res_i = atoms_per_res1[i] - for j in range(n_res_j): - n_atoms_res_j = atoms_per_res2[j] - - for x in range(n_atoms_res_i): - for y in range(n_atoms_res_j): - this_d = sqrt((atom_coordinates[x][0] - atom_coordinates[y][0])**2 + (atom_coordinates[x][1] - atom_coordinates[y][1])**2 + (atom_coordinates[x][2] - atom_coordinates[y][2])**2) + cum_i_atoms = 0 + for i, i_atoms in enumerate(atoms_per_res1): + cum_j_atoms = 0 + for j, j_atoms in enumerate(atoms_per_res2): + min_d = 100.0 + for x in range(cum_i_atoms, cum_i_atoms + i_atoms): + for y in range(cum_j_atoms, cum_j_atoms + j_atoms): + this_d = sqrt((atom_coordinates1[x][0] - atom_coordinates2[y][0])**2 + (atom_coordinates1[x][1] - atom_coordinates2[y][1])**2 + (atom_coordinates1[x][2] - atom_coordinates2[y][2])**2) if this_d < min_d: min_d = this_d - if min_d < threshold: - break - res_distances[i, j] = min_d + res_distances[i, j] = min_d + cum_j_atoms += j_atoms + #print(i, j, min_d) + cum_i_atoms += i_atoms + return res_distances @@ -43,6 +43,7 @@ def get_fnat_stats(float [:,:] model_res_distances, float [:,:] native_res_dista int n_model_contacts = 0 int n_shared_contacts = 0 int n_non_native_contacts = 0 + float threshold_squared = threshold**2 #unsigned char [:,:] model_contacts = np.zeros((model_shape_0, model_shape_1), dtype=np.uint8) #unsigned char [:,:] native_contacts = np.zeros((native_shape_0, native_shape_1), dtype=np.uint8) From 2cbda3b67201c8ed3fc68230d8e9d0f923e7eca2 Mon Sep 17 00:00:00 2001 From: Claudio Date: Thu, 9 Mar 2023 23:05:36 +0100 Subject: [PATCH 043/173] optimization --- src/DockQ/DockQ.py | 19 +++++++++------- src/DockQ/operations.pyx | 49 +++++++++++++++++++++------------------- 2 files changed, 37 insertions(+), 31 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 319e5bb..d68f944 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -181,21 +181,24 @@ def calc_DockQ( fnat = nat_total and nat_correct / nat_total or 0 fnonnat = model_total and nonnat_count / model_total or 0 - # get a copy of each structure, then only keep backbone atoms. This is faster than copy.deepcopy() - sample_model_backbone = pickle.loads(pickle.dumps(sample_model, -1)) - ref_model_backbone = pickle.loads(pickle.dumps(ref_model, -1)) - set_common_backbone_atoms( - sample_model_backbone, ref_model_backbone, atom_types=atom_for_sup - ) - if capri_peptide: ref_res_distances = get_residue_distances( ref_model, nat_group1, nat_group2, all_atom=False ) # Get interfacial atoms from reference, and corresponding atoms from sample interacting_pairs = get_interacting_pairs( - ref_res_distances, thr=interface_threshold + ref_res_distances, thr=interface_threshold**2 + ) + + # get a copy of each structure, then only keep backbone atoms. This is faster than copy.deepcopy() + #sample_model_backbone = pickle.loads(pickle.dumps(sample_model, -1)) + #ref_model_backbone = pickle.loads(pickle.dumps(ref_model, -1)) + sample_model_backbone = sample_model + ref_model_backbone = ref_model + set_common_backbone_atoms( + sample_model_backbone, ref_model_backbone, atom_types=atom_for_sup ) + sample_interface_atoms, ref_interface_atoms = get_interface_atoms( interacting_pairs, sample_model_backbone, diff --git a/src/DockQ/operations.pyx b/src/DockQ/operations.pyx index 147f395..a858d5a 100644 --- a/src/DockQ/operations.pyx +++ b/src/DockQ/operations.pyx @@ -4,38 +4,42 @@ cimport numpy as np import cython from libc.math cimport sqrt - +@cython.boundscheck(False) +@cython.wraparound(False) def residue_distances(float [:,:] atom_coordinates1, float [:,:] atom_coordinates2, long [:] atoms_per_res1, long [:] atoms_per_res2): cdef: - int i, j, x, y, cum_i_atoms, cum_j_atoms - int n_res_i = len(atoms_per_res1) - int n_res_j = len(atoms_per_res2) + int i, j, x, y, i_atoms, j_atoms, cum_i_atoms, cum_j_atoms, cum_i_atoms_end, cum_j_atoms_end + int n_res_i = atoms_per_res1.shape[0] + int n_res_j = atoms_per_res2.shape[0] float this_d, min_d float [:,:] res_distances = np.zeros((n_res_i, n_res_j), dtype=np.float32) cum_i_atoms = 0 - for i, i_atoms in enumerate(atoms_per_res1): + + for i in range(n_res_i): + i_atoms = atoms_per_res1[i] + cum_i_atoms_end = cum_i_atoms + i_atoms cum_j_atoms = 0 - for j, j_atoms in enumerate(atoms_per_res2): - min_d = 100.0 - for x in range(cum_i_atoms, cum_i_atoms + i_atoms): - for y in range(cum_j_atoms, cum_j_atoms + j_atoms): - this_d = sqrt((atom_coordinates1[x][0] - atom_coordinates2[y][0])**2 + (atom_coordinates1[x][1] - atom_coordinates2[y][1])**2 + (atom_coordinates1[x][2] - atom_coordinates2[y][2])**2) + for j in range(n_res_j): + j_atoms = atoms_per_res2[j] + min_d = 100000.0 + cum_j_atoms_end = cum_j_atoms + j_atoms + for x in range(cum_i_atoms, cum_i_atoms_end): + for y in range(cum_j_atoms, cum_j_atoms_end): + this_d = (atom_coordinates1[x][0] - atom_coordinates2[y][0])**2 + (atom_coordinates1[x][1] - atom_coordinates2[y][1])**2 + (atom_coordinates1[x][2] - atom_coordinates2[y][2])**2 if this_d < min_d: min_d = this_d res_distances[i, j] = min_d - cum_j_atoms += j_atoms - #print(i, j, min_d) - cum_i_atoms += i_atoms + cum_j_atoms = cum_j_atoms + j_atoms + cum_i_atoms = cum_i_atoms + i_atoms return res_distances - +@cython.boundscheck(False) +@cython.wraparound(False) def get_fnat_stats(float [:,:] model_res_distances, float [:,:] native_res_distances, float threshold=5.0): cdef: - int model_shape_0 = model_res_distances.shape[0] - int model_shape_1 = model_res_distances.shape[1] int native_shape_0 = native_res_distances.shape[0] int native_shape_1 = native_res_distances.shape[1] int i, j @@ -43,19 +47,18 @@ def get_fnat_stats(float [:,:] model_res_distances, float [:,:] native_res_dista int n_model_contacts = 0 int n_shared_contacts = 0 int n_non_native_contacts = 0 - float threshold_squared = threshold**2 - #unsigned char [:,:] model_contacts = np.zeros((model_shape_0, model_shape_1), dtype=np.uint8) - #unsigned char [:,:] native_contacts = np.zeros((native_shape_0, native_shape_1), dtype=np.uint8) + float threshold_squared + threshold_squared = threshold * threshold for i in range(native_shape_0): for j in range(native_shape_1): - if native_res_distances[i, j] < threshold: + if native_res_distances[i, j] < threshold_squared: n_native_contacts += 1 - if model_res_distances[i, j] < threshold: + if model_res_distances[i, j] < threshold_squared: n_shared_contacts += 1 - if model_res_distances[i, j] < threshold: + if model_res_distances[i, j] < threshold_squared: n_model_contacts += 1 - if native_res_distances[i, j] >= threshold: + if native_res_distances[i, j] >= threshold_squared: n_non_native_contacts += 1 return ( From 58f51bd01fe4ee4dc17e224ddf5e9e0da2e86302 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 10 Mar 2023 10:49:22 +0100 Subject: [PATCH 044/173] fix capri peptide bug --- src/DockQ/DockQ.py | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index d68f944..5a047cd 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -156,7 +156,6 @@ def capri_class_DockQ(DockQ, capri_peptide=False): return "Undef" -#@profile def calc_DockQ( sample_model, ref_model, @@ -187,12 +186,11 @@ def calc_DockQ( ) # Get interfacial atoms from reference, and corresponding atoms from sample interacting_pairs = get_interacting_pairs( - ref_res_distances, thr=interface_threshold**2 + # working with squared thresholds to avoid using sqrt in distance calculations + ref_res_distances, threshold=interface_threshold**2 ) # get a copy of each structure, then only keep backbone atoms. This is faster than copy.deepcopy() - #sample_model_backbone = pickle.loads(pickle.dumps(sample_model, -1)) - #ref_model_backbone = pickle.loads(pickle.dumps(ref_model, -1)) sample_model_backbone = sample_model ref_model_backbone = ref_model set_common_backbone_atoms( @@ -445,11 +443,11 @@ def list_atoms_per_residue(model, group): # @profile def get_residue_distances(model, group1, group2, all_atom=True): - # get information about how many atoms correspond to each amino acid in each group of chains - n_atoms_per_res_group1 = list_atoms_per_residue(model, group1) - n_atoms_per_res_group2 = list_atoms_per_residue(model, group2) if all_atom: + # get information about how many atoms correspond to each amino acid in each group of chains + n_atoms_per_res_group1 = list_atoms_per_residue(model, group1) + n_atoms_per_res_group2 = list_atoms_per_residue(model, group2) model_A_atoms = np.asarray( [ atom.get_coord() @@ -468,13 +466,29 @@ def get_residue_distances(model, group1, group2, all_atom=True): if atom.element != "H" ] ) - model_res_distances = residue_distances( - model_A_atoms, model_B_atoms, n_atoms_per_res_group1, n_atoms_per_res_group2 - ) + else: # distances were already between CBs only - model_res_distances = get_distances_across_chains( - model, group1, group2, all_atom=all_atom + model_A_atoms = np.asarray( + [ + res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() + for chain in group1 + for res in model[chain].get_residues() + ] + ) + model_B_atoms = np.asarray( + [ + res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() + for chain in group2 + for res in model[chain].get_residues() + ] ) + + n_atoms_per_res_group1 = np.ones(model_A_atoms.shape[0]).astype(int) + n_atoms_per_res_group2 = np.ones(model_B_atoms.shape[0]).astype(int) + + model_res_distances = residue_distances( + model_A_atoms, model_B_atoms, n_atoms_per_res_group1, n_atoms_per_res_group2 + ) return model_res_distances @@ -493,8 +507,8 @@ def get_fnat_stats2(model_res_distances, native_res_distances, thr=5.0): ) -def get_interacting_pairs(distances, thr=5.0): - return np.nonzero(np.asarray(distances) < thr) +def get_interacting_pairs(distances, threshold): + return np.nonzero(np.asarray(distances) < threshold) # @profile From b3462bab7e7ca233f39289ee541375879bf59093 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 10 Mar 2023 10:52:14 +0100 Subject: [PATCH 045/173] unused functions --- src/DockQ/DockQ.py | 73 ---------------------------------------------- 1 file changed, 73 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 5a047cd..52a51e1 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -373,64 +373,6 @@ def fix_chain_residues(model, chain, alignment, invert=False): model[chain].detach_child(res) -def get_distances_across_chains(model, group1, group2, all_atom=True): - if all_atom: - model_A_atoms = np.asarray( - [ - atom.get_coord() - for chain in group1 - for res in model[chain].get_residues() - for atom in res.get_atoms() - if atom.element != "H" - ] - ) - model_B_atoms = np.asarray( - [ - atom.get_coord() - for chain in group2 - for res in model[chain].get_residues() - for atom in res.get_atoms() - if atom.element != "H" - ] - ) - else: - model_A_atoms = np.asarray( - [ - res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() - for chain in group1 - for res in model[chain].get_residues() - ] - ) - model_B_atoms = np.asarray( - [ - res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() - for chain in group2 - for res in model[chain].get_residues() - ] - ) - - distances = np.sqrt( - ((model_A_atoms[:, None] - model_B_atoms[None, :]) ** 2).sum(-1) - ) - return distances - - -# @profile -def atom_distances_to_residue_distances(atom_distances, atoms_per_res1, atoms_per_res2): - res_distances = np.zeros((len(atoms_per_res1), len(atoms_per_res2))) - - cum_i_atoms = 0 - for i, i_atoms in enumerate(atoms_per_res1): - cum_j_atoms = 0 - for j, j_atoms in enumerate(atoms_per_res2): - res_distances[i, j] = atom_distances[ - cum_i_atoms : cum_i_atoms + i_atoms, cum_j_atoms : cum_j_atoms + j_atoms - ].min() - cum_j_atoms += j_atoms - cum_i_atoms += i_atoms - return res_distances - - def list_atoms_per_residue(model, group): n_atoms_per_residue = [] for chain in group: @@ -492,21 +434,6 @@ def get_residue_distances(model, group1, group2, all_atom=True): return model_res_distances -def get_fnat_stats2(model_res_distances, native_res_distances, thr=5.0): - native_contacts = native_res_distances < thr - model_contacts = model_res_distances < thr - n_native_contacts = np.sum(native_contacts) - n_model_contacts = np.sum(model_contacts) - n_shared_contacts = np.sum(model_contacts * native_contacts) - n_non_native_contacts = np.sum(model_contacts * (1 - native_contacts)) - return ( - n_shared_contacts, - n_non_native_contacts, - n_native_contacts, - n_model_contacts, - ) - - def get_interacting_pairs(distances, threshold): return np.nonzero(np.asarray(distances) < threshold) From ca9303f6d38b0bc6ffdb1ada524ea3f68b4c4df7 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 10 Mar 2023 11:55:11 +0100 Subject: [PATCH 046/173] fix install bug --- pyproject.toml | 2 +- setup.py | 11 ++++++++--- src/DockQ/operations.pyx | 8 +++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index eda92d7..4e8b8c8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,4 +1,4 @@ [build-system] -requires = ["setuptools", "cython"] +requires = ["setuptools", "cython", "numpy"] build-backend = "setuptools.build_meta" diff --git a/setup.py b/setup.py index 9efc4fe..e84146c 100644 --- a/setup.py +++ b/setup.py @@ -1,10 +1,15 @@ from setuptools import setup, Extension +from Cython.Build import cythonize +import numpy -setup( - ext_modules=[ +extensions = [ Extension( "DockQ.operations", sources=["src/DockQ/operations.pyx"], + include_dirs = [numpy.get_include()], ), - ], + ] + +setup( + ext_modules=cythonize(extensions) ) diff --git a/src/DockQ/operations.pyx b/src/DockQ/operations.pyx index a858d5a..5df7956 100644 --- a/src/DockQ/operations.pyx +++ b/src/DockQ/operations.pyx @@ -15,7 +15,6 @@ def residue_distances(float [:,:] atom_coordinates1, float [:,:] atom_coordinate float [:,:] res_distances = np.zeros((n_res_i, n_res_j), dtype=np.float32) cum_i_atoms = 0 - for i in range(n_res_i): i_atoms = atoms_per_res1[i] cum_i_atoms_end = cum_i_atoms + i_atoms @@ -29,11 +28,10 @@ def residue_distances(float [:,:] atom_coordinates1, float [:,:] atom_coordinate this_d = (atom_coordinates1[x][0] - atom_coordinates2[y][0])**2 + (atom_coordinates1[x][1] - atom_coordinates2[y][1])**2 + (atom_coordinates1[x][2] - atom_coordinates2[y][2])**2 if this_d < min_d: min_d = this_d - res_distances[i, j] = min_d + res_distances[i, j] = min_d cum_j_atoms = cum_j_atoms + j_atoms cum_i_atoms = cum_i_atoms + i_atoms - - + return res_distances @cython.boundscheck(False) @@ -48,7 +46,7 @@ def get_fnat_stats(float [:,:] model_res_distances, float [:,:] native_res_dista int n_shared_contacts = 0 int n_non_native_contacts = 0 float threshold_squared - + threshold_squared = threshold * threshold for i in range(native_shape_0): for j in range(native_shape_1): From 1972d1656f14104c1339e78626f3572561ccc095 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 10 Mar 2023 15:35:31 +0100 Subject: [PATCH 047/173] native contacts before subsetting --- src/DockQ/DockQ.py | 82 +++++++++------------------------------------- 1 file changed, 16 insertions(+), 66 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 52a51e1..ec53645 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -96,69 +96,10 @@ def parse_args(): return parser.parse_args() -def capri_class(fnat, iRMS, LRMS, capri_peptide=False): - if capri_peptide: - - if fnat < 0.2 or (LRMS > 5.0 and iRMS > 2.0): - return "Incorrect" - elif ( - (fnat >= 0.2 and fnat < 0.5) - and (LRMS <= 5.0 or iRMS <= 2.0) - or (fnat >= 0.5 and LRMS > 2.0 and iRMS > 1.0) - ): - return "Acceptable" - elif ( - (fnat >= 0.5 and fnat < 0.8) - and (LRMS <= 2.0 or iRMS <= 1.0) - or (fnat >= 0.8 and LRMS > 1.0 and iRMS > 0.5) - ): - return "Medium" - elif fnat >= 0.8 and (LRMS <= 1.0 or iRMS <= 0.5): - return "High" - else: - return "Undef" - else: - - if fnat < 0.1 or (LRMS > 10.0 and iRMS > 4.0): - return "Incorrect" - elif ( - (fnat >= 0.1 and fnat < 0.3) - and (LRMS <= 10.0 or iRMS <= 4.0) - or (fnat >= 0.3 and LRMS > 5.0 and iRMS > 2.0) - ): - return "Acceptable" - elif ( - (fnat >= 0.3 and fnat < 0.5) - and (LRMS <= 5.0 or iRMS <= 2.0) - or (fnat >= 0.5 and LRMS > 1.0 and iRMS > 1.0) - ): - return "Medium" - elif fnat >= 0.5 and (LRMS <= 1.0 or iRMS <= 1.0): - return "High" - else: - return "Undef" - - -def capri_class_DockQ(DockQ, capri_peptide=False): - if capri_peptide: - return "Undef for capri_peptides" - - (c1, c2, c3) = (0.23, 0.49, 0.80) - if DockQ < c1: - return "Incorrect" - elif DockQ >= c1 and DockQ < c2: - return "Acceptable" - elif DockQ >= c2 and DockQ < c3: - return "Medium" - elif DockQ >= c3: - return "High" - else: - return "Undef" - - def calc_DockQ( sample_model, ref_model, + ref_model_original, group1, group2, nat_group1, @@ -170,10 +111,14 @@ def calc_DockQ( fnat_threshold = 4.0 if capri_peptide else 5.0 interface_threshold = 8.0 if capri_peptide else 10.0 + # total number of native contacts is calculated on untouched native structure + ref_res_distances = get_residue_distances(ref_model_original, nat_group1, nat_group2) + nat_total = np.nonzero(np.asarray(ref_res_distances) < fnat_threshold**2)[0].shape[0] + sample_res_distances = get_residue_distances(sample_model, group1, group2) ref_res_distances = get_residue_distances(ref_model, nat_group1, nat_group2) - nat_correct, nonnat_count, nat_total, model_total = get_fnat_stats( + nat_correct, nonnat_count, _, model_total = get_fnat_stats( sample_res_distances, ref_res_distances, threshold=fnat_threshold ) # avoids divide by 0 errors @@ -213,21 +158,21 @@ def calc_DockQ( irms = super_imposer.rms # assign which group of chains constitutes the receptor, then the other is the ligand - ref_group1_size = np.sum([len(ref_model[chain]) for chain in nat_group1]) - ref_group2_size = np.sum([len(ref_model[chain]) for chain in nat_group2]) + ref_group1_size = np.sum([len(ref_model_original[chain]) for chain in nat_group1]) + ref_group2_size = np.sum([len(ref_model_original[chain]) for chain in nat_group2]) receptor_chains = ( (nat_group1, group1) - if ref_group1_size > ref_group2_size + if ref_group1_size >= ref_group2_size else (nat_group2, group2) ) ligand_chains = ( (nat_group1, group1) - if ref_group1_size <= ref_group2_size + if ref_group1_size < ref_group2_size else (nat_group2, group2) ) class1, class2 = ( ("receptor", "ligand") - if ref_group1_size > ref_group2_size + if ref_group1_size >= ref_group2_size else ("ligand", "receptor") ) receptor_atoms_native = [ @@ -511,6 +456,10 @@ def run_on_groups(model_structure, native_structure, group1, group2, nat_group1, native_structure, chains_to_keep=nat_group1 + nat_group2 ) + native_structure_original = pickle.loads( + pickle.dumps(native_structure, -1) + ) + # realign each model chain against the corresponding native chain for model_chain, native_chain in zip( group1 + group2, nat_group1 + nat_group2 @@ -529,6 +478,7 @@ def run_on_groups(model_structure, native_structure, group1, group2, nat_group1, info = calc_DockQ( model_structure, native_structure, + native_structure_original, group1, group2, nat_group1, From 8f899ac0aeb36981657b5625bf5037a200c7f197 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 10 Mar 2023 15:36:00 +0100 Subject: [PATCH 048/173] unused import --- pyproject.toml | 2 ++ src/DockQ/operations.pyx | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 4e8b8c8..df7b3a3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,4 +1,6 @@ [build-system] +name = "DockQ" +version = 2.0 requires = ["setuptools", "cython", "numpy"] build-backend = "setuptools.build_meta" diff --git a/src/DockQ/operations.pyx b/src/DockQ/operations.pyx index 5df7956..f95b2b6 100644 --- a/src/DockQ/operations.pyx +++ b/src/DockQ/operations.pyx @@ -2,7 +2,6 @@ import numpy as np cimport numpy as np import cython -from libc.math cimport sqrt @cython.boundscheck(False) @cython.wraparound(False) From d4d4556ad6d5b2a6fbd6121cb34fd41008d966fe Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 14 Mar 2023 14:01:18 +0100 Subject: [PATCH 049/173] chain handling bug --- src/DockQ/DockQ.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index ec53645..eee434b 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -135,7 +135,7 @@ def calc_DockQ( ref_res_distances, threshold=interface_threshold**2 ) - # get a copy of each structure, then only keep backbone atoms. This is faster than copy.deepcopy() + # get a copy of each structure, then only keep backbone atoms sample_model_backbone = sample_model ref_model_backbone = ref_model set_common_backbone_atoms( @@ -296,10 +296,11 @@ def align_model_to_native( def remove_extra_chains(model, chains_to_keep): - for chain in model.get_chains(): - if chain.id not in chains_to_keep: - model.detach_child(chain.id) - return model + chains = [chain.id for chain in model.get_chains()] + + chains_to_remove = set(chains).difference(set(chains_to_keep)) + for chain in chains_to_remove: + model.detach_child(chain) def fix_chain_residues(model, chain, alignment, invert=False): @@ -439,7 +440,6 @@ def set_common_backbone_atoms(model, reference, atom_types=["CA", "C", "N", "O"] .intersection(atom_types) .intersection(atom_ids_in_ref_res) ) - # whatever atom is not in the shared list, remove it from the both structures for atom_id in set(atom_ids_in_mod_res).difference(atom_ids_in_ref_and_mod_res): mod_res.detach_child(atom_id) @@ -449,10 +449,10 @@ def set_common_backbone_atoms(model, reference, atom_types=["CA", "C", "N", "O"] def run_on_groups(model_structure, native_structure, group1, group2, nat_group1, nat_group2, no_needle=False, use_CA_only=False, capri_peptide=False): - model_structure = remove_extra_chains( + remove_extra_chains( model_structure, chains_to_keep=group1 + group2 ) - native_structure = remove_extra_chains( + remove_extra_chains( native_structure, chains_to_keep=nat_group1 + nat_group2 ) @@ -475,6 +475,7 @@ def run_on_groups(model_structure, native_structure, group1, group2, nat_group1, fix_chain_residues( native_structure, native_chain, alignment, invert=True ) + info = calc_DockQ( model_structure, native_structure, From 7d2a3ced93cec056db342bbe17b114ebda0262c3 Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 14 Mar 2023 16:06:45 +0100 Subject: [PATCH 050/173] run all interfaces --- src/DockQ/DockQ.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index eee434b..a453906 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -331,7 +331,6 @@ def list_atoms_per_residue(model, group): # @profile def get_residue_distances(model, group1, group2, all_atom=True): - if all_atom: # get information about how many atoms correspond to each amino acid in each group of chains n_atoms_per_res_group1 = list_atoms_per_residue(model, group1) @@ -490,6 +489,32 @@ def run_on_groups(model_structure, native_structure, group1, group2, nat_group1, return info +def run_on_all_native_interfaces(model_structure, native_structure, chain_map={"A":"A", "B":"B"}, no_needle=False, use_CA_only=False, capri_peptide=False): + """ Given a native-model chain map, finds all non-null native interfaces and runs DockQ for each native-model pair of interfaces """ + interface_dic = {} + results_dic = {} + native_chains = [c.id for c in native_structure] + for chain_pair in itertools.combinations(native_chains, 2): + n_contacts = np.sum(np.asarray(get_residue_distances(native_structure, [chain_pair[0]], [chain_pair[1]])) < 25.0) + interface_dic[chain_pair] = n_contacts + + for chain_pair, interface_size in interface_dic.items(): + if interface_size > 0 and chain_pair[0] in chain_map and chain_pair[1] in chain_map: + model_structure_this = pickle.loads(pickle.dumps(model_structure, -1)) + native_structure_this = pickle.loads(pickle.dumps(native_structure, -1)) + info = run_on_groups(model_structure_this, native_structure_this, [chain_pair[0]], [chain_pair[1]], [chain_map[chain_pair[0]]], [chain_map[chain_pair[1]]]) + results_dic[chain_pair] = info + + return results_dic + + +def run_DockQ(path_to_model, path_to_native, group1=["A"], group2=["B"], nat_group1=["A"], nat_group2=["B"], model_is_mmcif=False, native_is_mmcif=False, no_needle=False, use_CA_only=False, capri_peptide=False): + model = load_PDB(path_to_model, is_mmcif=model_is_mmcif) + native = load_PDB(path_to_native, is_mmcif=native_is_mmcif) + + return run_on_groups(model, native, group1, group2, nat_group1, nat_group2, no_needle, use_CA_only, capri_peptide) + + def load_PDB(path, n_model=0, is_mmcif=False): if not is_mmcif: From fe4c4f96301f5b6e91166cab45cf5cbe2f1841d0 Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 14 Mar 2023 16:52:42 +0100 Subject: [PATCH 051/173] arg parsing bug --- src/DockQ/DockQ.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index a453906..96af0d7 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -141,7 +141,7 @@ def calc_DockQ( set_common_backbone_atoms( sample_model_backbone, ref_model_backbone, atom_types=atom_for_sup ) - + sample_interface_atoms, ref_interface_atoms = get_interface_atoms( interacting_pairs, sample_model_backbone, @@ -474,7 +474,6 @@ def run_on_groups(model_structure, native_structure, group1, group2, nat_group1, fix_chain_residues( native_structure, native_chain, alignment, invert=True ) - info = calc_DockQ( model_structure, native_structure, @@ -550,7 +549,7 @@ def main(): model_chains = [c.id for c in model_structure] native_chains = [c.id for c in native_structure] - + print(model_chains, native_chains) if (len(model_chains) > 2 or len(native_chains) > 2) and ( not args.model_chain1 and not args.native_chain1 ): @@ -578,7 +577,7 @@ def main(): nat_group2 = group2 else: # otherwise, group the chains by however many where in either model group nat_group1 = native_chains[: len(group1)] - nat_group2 = native_chains[len(group1) :] + nat_group2 = native_chains[len(group1) : len(group1) + len(group2)] if group2 else None if not group1: # viceversa, the user has set nat_group1 if model_chains == native_chains: @@ -586,7 +585,7 @@ def main(): group2 = nat_group2 else: group1 = model_chains[: len(nat_group1)] - group2 = model_chains[len(nat_group1) :] + group2 = model_chains[len(nat_group1) : len(nat_group1) + len(nat_group2)] if nat_group2 else None if not group2: # no group2 set yet, use the complement to group1 group2 = [chain for chain in model_chains if chain not in group1] From fbc5536d506ac8eb6ee98566fb52145c541fa033 Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 14 Mar 2023 21:39:28 +0100 Subject: [PATCH 052/173] better alignments by numbering --- src/DockQ/DockQ.py | 57 ++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 35 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 96af0d7..c7af489 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -241,56 +241,43 @@ def calc_DockQ( def align_model_to_native( model_structure, native_structure, model_chain, native_chain, use_numbering=False ): - model_sequence = "".join( - seq1(residue.get_resname()) - for residue in model_structure[model_chain].get_residues() - ) - native_sequence = "".join( - seq1(residue.get_resname()) - for residue in native_structure[native_chain].get_residues() - ) alignment = {} if use_numbering: model_numbering = [] native_numbering = [] + model_sequence = "" + native_sequence = "" for residue in model_structure[model_chain].get_residues(): resn = int(residue.id[1]) model_numbering.append(resn) + model_sequence += chr(resn) for residue in native_structure[native_chain].get_residues(): resn = int(residue.id[1]) native_numbering.append(resn) + # if the samllest resn is negative, it will be used to shift all numbers so they start from 0 + min_resn = max(0, -min(model_numbering + native_numbering)) - start = min(native_numbering + model_numbering) - end = max(native_numbering + model_numbering) - alignment["seqA"] = [] - alignment["seqB"] = [] - model_sequence = iter(model_sequence) - native_sequence = iter(native_sequence) - - for i in range(start, end + 1): - if i in model_numbering: - next_model_res = next(model_sequence) - else: - next_model_res = "-" - - if i in native_numbering: - next_native_res = next(native_sequence) - else: - next_native_res = "-" - - if next_model_res != "-" or next_native_res != "-": - alignment["seqA"].append(next_model_res) - alignment["seqB"].append(next_native_res) + model_sequence = "".join([chr(resn + min_resn) for resn in model_numbering]) + native_sequence = "".join([chr(resn + min_resn) for resn in native_numbering]) else: - aln = pairwise2.align.localms( - model_sequence, native_sequence, match=5, mismatch=0, open=-10, extend=-1 - )[0] - alignment["seqA"] = aln.seqA - alignment["seqB"] = aln.seqB + model_sequence = "".join( + seq1(residue.get_resname()) + for residue in model_structure[model_chain].get_residues() + ) + + native_sequence = "".join( + seq1(residue.get_resname()) + for residue in native_structure[native_chain].get_residues() + ) + aln = pairwise2.align.localms( + model_sequence, native_sequence, match=5, mismatch=0, open=-10, extend=-1 + )[0] + alignment["seqA"] = aln.seqA + alignment["seqB"] = aln.seqB return alignment @@ -549,7 +536,7 @@ def main(): model_chains = [c.id for c in model_structure] native_chains = [c.id for c in native_structure] - print(model_chains, native_chains) + if (len(model_chains) > 2 or len(native_chains) > 2) and ( not args.model_chain1 and not args.native_chain1 ): From a1e0b0c95e9f3880158a85891601093062d6b80e Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 14 Mar 2023 22:02:23 +0100 Subject: [PATCH 053/173] small fixes --- src/DockQ/DockQ.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index c7af489..8846f0d 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -134,7 +134,7 @@ def calc_DockQ( # working with squared thresholds to avoid using sqrt in distance calculations ref_res_distances, threshold=interface_threshold**2 ) - + # get a copy of each structure, then only keep backbone atoms sample_model_backbone = sample_model ref_model_backbone = ref_model @@ -189,7 +189,6 @@ def calc_DockQ( # Set to align on receptor super_imposer.set_atoms(receptor_atoms_native, receptor_atoms_sample) super_imposer.apply(sample_model_backbone.get_atoms()) - receptor_chain_rms = super_imposer.rms coord1 = np.array( [ @@ -246,13 +245,10 @@ def align_model_to_native( if use_numbering: model_numbering = [] native_numbering = [] - model_sequence = "" - native_sequence = "" for residue in model_structure[model_chain].get_residues(): resn = int(residue.id[1]) model_numbering.append(resn) - model_sequence += chr(resn) for residue in native_structure[native_chain].get_residues(): resn = int(residue.id[1]) @@ -293,7 +289,7 @@ def remove_extra_chains(model, chains_to_keep): def fix_chain_residues(model, chain, alignment, invert=False): residues = model[chain].get_residues() residues_to_delete = [] - start = False + seqA = alignment["seqA"] if not invert else alignment["seqB"] seqB = alignment["seqB"] if not invert else alignment["seqA"] for (aligned_residue_A, aligned_residue_B) in zip(seqA, seqB): @@ -340,7 +336,7 @@ def get_residue_distances(model, group1, group2, all_atom=True): if atom.element != "H" ] ) - + else: # distances were already between CBs only model_A_atoms = np.asarray( [ @@ -483,7 +479,7 @@ def run_on_all_native_interfaces(model_structure, native_structure, chain_map={" for chain_pair in itertools.combinations(native_chains, 2): n_contacts = np.sum(np.asarray(get_residue_distances(native_structure, [chain_pair[0]], [chain_pair[1]])) < 25.0) interface_dic[chain_pair] = n_contacts - + for chain_pair, interface_size in interface_dic.items(): if interface_size > 0 and chain_pair[0] in chain_map and chain_pair[1] in chain_map: model_structure_this = pickle.loads(pickle.dumps(model_structure, -1)) @@ -497,7 +493,7 @@ def run_on_all_native_interfaces(model_structure, native_structure, chain_map={" def run_DockQ(path_to_model, path_to_native, group1=["A"], group2=["B"], nat_group1=["A"], nat_group2=["B"], model_is_mmcif=False, native_is_mmcif=False, no_needle=False, use_CA_only=False, capri_peptide=False): model = load_PDB(path_to_model, is_mmcif=model_is_mmcif) native = load_PDB(path_to_native, is_mmcif=native_is_mmcif) - + return run_on_groups(model, native, group1, group2, nat_group1, nat_group2, no_needle, use_CA_only, capri_peptide) From 7abbd33e3ee6e7b0194f836cb903a81263e1d089 Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 14 Mar 2023 22:07:08 +0100 Subject: [PATCH 054/173] simplify --- src/DockQ/DockQ.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 8846f0d..22c34a3 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -473,14 +473,11 @@ def run_on_groups(model_structure, native_structure, group1, group2, nat_group1, def run_on_all_native_interfaces(model_structure, native_structure, chain_map={"A":"A", "B":"B"}, no_needle=False, use_CA_only=False, capri_peptide=False): """ Given a native-model chain map, finds all non-null native interfaces and runs DockQ for each native-model pair of interfaces """ - interface_dic = {} results_dic = {} native_chains = [c.id for c in native_structure] for chain_pair in itertools.combinations(native_chains, 2): - n_contacts = np.sum(np.asarray(get_residue_distances(native_structure, [chain_pair[0]], [chain_pair[1]])) < 25.0) - interface_dic[chain_pair] = n_contacts + interface_size = np.sum(np.asarray(get_residue_distances(native_structure, [chain_pair[0]], [chain_pair[1]])) < 25.0) - for chain_pair, interface_size in interface_dic.items(): if interface_size > 0 and chain_pair[0] in chain_map and chain_pair[1] in chain_map: model_structure_this = pickle.loads(pickle.dumps(model_structure, -1)) native_structure_this = pickle.loads(pickle.dumps(native_structure, -1)) From 583c5b7eea23b4f2ef72a40fd99dbd90cf8caaf6 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 15 Mar 2023 11:08:26 +0100 Subject: [PATCH 055/173] fix bug in no_needle align --- src/DockQ/DockQ.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 22c34a3..b8f1ed4 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -254,7 +254,7 @@ def align_model_to_native( resn = int(residue.id[1]) native_numbering.append(resn) # if the samllest resn is negative, it will be used to shift all numbers so they start from 0 - min_resn = max(0, -min(model_numbering + native_numbering)) + min_resn = max(45, -min(model_numbering + native_numbering)) model_sequence = "".join([chr(resn + min_resn) for resn in model_numbering]) native_sequence = "".join([chr(resn + min_resn) for resn in native_numbering]) @@ -274,7 +274,6 @@ def align_model_to_native( )[0] alignment["seqA"] = aln.seqA alignment["seqB"] = aln.seqB - return alignment From 45b02c8e15becb8f2e05150e460443714248cbf5 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 16 Mar 2023 09:05:07 +0100 Subject: [PATCH 056/173] assert --- src/DockQ/DockQ.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index b8f1ed4..1a85b53 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -118,6 +118,8 @@ def calc_DockQ( sample_res_distances = get_residue_distances(sample_model, group1, group2) ref_res_distances = get_residue_distances(ref_model, nat_group1, nat_group2) + assert sample_res_distances.shape == ref_res_distances.shape, "Interfaces have different shapes" + nat_correct, nonnat_count, _, model_total = get_fnat_stats( sample_res_distances, ref_res_distances, threshold=fnat_threshold ) @@ -254,6 +256,7 @@ def align_model_to_native( resn = int(residue.id[1]) native_numbering.append(resn) # if the samllest resn is negative, it will be used to shift all numbers so they start from 0 + # the minimum offset is 45 to avoid including the "-" character that is reserved for gaps min_resn = max(45, -min(model_numbering + native_numbering)) model_sequence = "".join([chr(resn + min_resn) for resn in model_numbering]) From c24d8627edddf1a35c72dd38cab44812345738d5 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 16 Mar 2023 09:16:41 +0100 Subject: [PATCH 057/173] ligand/receptor switch when same size --- src/DockQ/DockQ.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 1a85b53..e8cfdd5 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -164,17 +164,17 @@ def calc_DockQ( ref_group2_size = np.sum([len(ref_model_original[chain]) for chain in nat_group2]) receptor_chains = ( (nat_group1, group1) - if ref_group1_size >= ref_group2_size + if ref_group1_size > ref_group2_size else (nat_group2, group2) ) ligand_chains = ( (nat_group1, group1) - if ref_group1_size < ref_group2_size + if ref_group1_size <= ref_group2_size else (nat_group2, group2) ) class1, class2 = ( ("receptor", "ligand") - if ref_group1_size >= ref_group2_size + if ref_group1_size > ref_group2_size else ("ligand", "receptor") ) receptor_atoms_native = [ From 66e447bd1be5cb607aca137c5513e329f22e82a1 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 16 Mar 2023 09:30:44 +0100 Subject: [PATCH 058/173] remove hetatms --- src/DockQ/DockQ.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index e8cfdd5..09a9c72 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -288,6 +288,20 @@ def remove_extra_chains(model, chains_to_keep): model.detach_child(chain) +def remove_hetatms(model): + chains = [chain.id for chain in model.get_chains()] + residues_to_delete = [] + + for chain in chains: + residues = model[chain].get_residues() + + for res in residues: + if res.id[0] != " ": + residues_to_delete.append(res.get_full_id()) + for _, _, chain, res in residues_to_delete: + model[chain].detach_child(res) + + def fix_chain_residues(model, chain, alignment, invert=False): residues = model[chain].get_residues() residues_to_delete = [] @@ -526,6 +540,8 @@ def main(): native_structure = load_PDB(args.native, is_mmcif=args.mmcif_native) model_structure = load_PDB(args.model, is_mmcif=args.mmcif_model) + remove_hetatms(native_structure) + remove_hetatms(model_structure) best_info = "" From 57509d0f9340069b59ab8c3f89ee14c73e392aef Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 16 Mar 2023 11:05:14 +0100 Subject: [PATCH 059/173] nocython option --- src/DockQ/DockQ.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 09a9c72..d29aa4a 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -11,7 +11,12 @@ from Bio import pairwise2 from Bio.SeqUtils import seq1 from Bio.SVDSuperimposer import SVDSuperimposer -from .operations import residue_distances, get_fnat_stats +# fallback in case the cython version doesn't work, though it will be slower +try: + from .operations import residue_distances, get_fnat_stats +except: + print("WARNING: It looks like cython is not working, falling back on native python. This will make DockQ slower") + from operations_nocy import residue_distances, get_fnat_stats def parse_args(): @@ -328,7 +333,6 @@ def list_atoms_per_residue(model, group): return np.array(n_atoms_per_residue).astype(int) -# @profile def get_residue_distances(model, group1, group2, all_atom=True): if all_atom: # get information about how many atoms correspond to each amino acid in each group of chains From ff8bfeaa838ff2bbf2767fd43cb2455172236fb2 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 16 Mar 2023 11:14:39 +0100 Subject: [PATCH 060/173] blacken --- src/DockQ/DockQ.py | 192 ++++++++++++++++++++++++++--------- src/DockQ/operations_nocy.py | 49 +++++++++ 2 files changed, 192 insertions(+), 49 deletions(-) create mode 100644 src/DockQ/operations_nocy.py diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index d29aa4a..b72bb06 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -11,11 +11,14 @@ from Bio import pairwise2 from Bio.SeqUtils import seq1 from Bio.SVDSuperimposer import SVDSuperimposer + # fallback in case the cython version doesn't work, though it will be slower try: from .operations import residue_distances, get_fnat_stats except: - print("WARNING: It looks like cython is not working, falling back on native python. This will make DockQ slower") + print( + "WARNING: It looks like cython is not working, falling back on native python. This will make DockQ slower" + ) from operations_nocy import residue_distances, get_fnat_stats @@ -46,10 +49,16 @@ def parse_args(): "-useCA", default=False, action="store_true", help="use CA instead of backbone" ) parser.add_argument( - "-mmcif_model", default=False, action="store_true", help="The model is in mmCIF format" + "-mmcif_model", + default=False, + action="store_true", + help="The model is in mmCIF format", ) parser.add_argument( - "-mmcif_native", default=False, action="store_true", help="The native is in mmCIF format" + "-mmcif_native", + default=False, + action="store_true", + help="The native is in mmCIF format", ) parser.add_argument( "-no_needle", @@ -117,13 +126,19 @@ def calc_DockQ( interface_threshold = 8.0 if capri_peptide else 10.0 # total number of native contacts is calculated on untouched native structure - ref_res_distances = get_residue_distances(ref_model_original, nat_group1, nat_group2) - nat_total = np.nonzero(np.asarray(ref_res_distances) < fnat_threshold**2)[0].shape[0] + ref_res_distances = get_residue_distances( + ref_model_original, nat_group1, nat_group2 + ) + nat_total = np.nonzero(np.asarray(ref_res_distances) < fnat_threshold**2)[ + 0 + ].shape[0] sample_res_distances = get_residue_distances(sample_model, group1, group2) ref_res_distances = get_residue_distances(ref_model, nat_group1, nat_group2) - assert sample_res_distances.shape == ref_res_distances.shape, "Interfaces have different shapes" + assert ( + sample_res_distances.shape == ref_res_distances.shape + ), "Interfaces have different shapes" nat_correct, nonnat_count, _, model_total = get_fnat_stats( sample_res_distances, ref_res_distances, threshold=fnat_threshold @@ -139,7 +154,8 @@ def calc_DockQ( # Get interfacial atoms from reference, and corresponding atoms from sample interacting_pairs = get_interacting_pairs( # working with squared thresholds to avoid using sqrt in distance calculations - ref_res_distances, threshold=interface_threshold**2 + ref_res_distances, + threshold=interface_threshold**2, ) # get a copy of each structure, then only keep backbone atoms @@ -296,7 +312,7 @@ def remove_extra_chains(model, chains_to_keep): def remove_hetatms(model): chains = [chain.id for chain in model.get_chains()] residues_to_delete = [] - + for chain in chains: residues = model[chain].get_residues() @@ -328,7 +344,9 @@ def list_atoms_per_residue(model, group): for chain in group: for residue in model[chain].get_residues(): # important to remove duplicate atoms (e.g. alternates) at this stage, remove also hydrogens - atom_ids = set([a.id for a in residue.get_unpacked_list() if a.element != "H"]) + atom_ids = set( + [a.id for a in residue.get_unpacked_list() if a.element != "H"] + ) n_atoms_per_residue.append(len(atom_ids)) return np.array(n_atoms_per_residue).astype(int) @@ -377,7 +395,7 @@ def get_residue_distances(model, group1, group2, all_atom=True): n_atoms_per_res_group2 = np.ones(model_B_atoms.shape[0]).astype(int) model_res_distances = residue_distances( - model_A_atoms, model_B_atoms, n_atoms_per_res_group1, n_atoms_per_res_group2 + model_A_atoms, model_B_atoms, n_atoms_per_res_group1, n_atoms_per_res_group2 ) return model_res_distances @@ -450,22 +468,24 @@ def set_common_backbone_atoms(model, reference, atom_types=["CA", "C", "N", "O"] ref_res.detach_child(atom_id) -def run_on_groups(model_structure, native_structure, group1, group2, nat_group1, nat_group2, no_needle=False, use_CA_only=False, capri_peptide=False): - remove_extra_chains( - model_structure, chains_to_keep=group1 + group2 - ) - remove_extra_chains( - native_structure, chains_to_keep=nat_group1 + nat_group2 - ) +def run_on_groups( + model_structure, + native_structure, + group1, + group2, + nat_group1, + nat_group2, + no_needle=False, + use_CA_only=False, + capri_peptide=False, +): + remove_extra_chains(model_structure, chains_to_keep=group1 + group2) + remove_extra_chains(native_structure, chains_to_keep=nat_group1 + nat_group2) - native_structure_original = pickle.loads( - pickle.dumps(native_structure, -1) - ) + native_structure_original = pickle.loads(pickle.dumps(native_structure, -1)) # realign each model chain against the corresponding native chain - for model_chain, native_chain in zip( - group1 + group2, nat_group1 + nat_group2 - ): + for model_chain, native_chain in zip(group1 + group2, nat_group1 + nat_group2): alignment = align_model_to_native( model_structure, native_structure, @@ -474,9 +494,7 @@ def run_on_groups(model_structure, native_structure, group1, group2, nat_group1, use_numbering=no_needle, ) fix_chain_residues(model_structure, model_chain, alignment) - fix_chain_residues( - native_structure, native_chain, alignment, invert=True - ) + fix_chain_residues(native_structure, native_chain, alignment, invert=True) info = calc_DockQ( model_structure, native_structure, @@ -491,27 +509,74 @@ def run_on_groups(model_structure, native_structure, group1, group2, nat_group1, return info -def run_on_all_native_interfaces(model_structure, native_structure, chain_map={"A":"A", "B":"B"}, no_needle=False, use_CA_only=False, capri_peptide=False): - """ Given a native-model chain map, finds all non-null native interfaces and runs DockQ for each native-model pair of interfaces """ +def run_on_all_native_interfaces( + model_structure, + native_structure, + chain_map={"A": "A", "B": "B"}, + no_needle=False, + use_CA_only=False, + capri_peptide=False, +): + """Given a native-model chain map, finds all non-null native interfaces and runs DockQ for each native-model pair of interfaces""" results_dic = {} native_chains = [c.id for c in native_structure] for chain_pair in itertools.combinations(native_chains, 2): - interface_size = np.sum(np.asarray(get_residue_distances(native_structure, [chain_pair[0]], [chain_pair[1]])) < 25.0) + interface_size = np.sum( + np.asarray( + get_residue_distances( + native_structure, [chain_pair[0]], [chain_pair[1]] + ) + ) + < 25.0 + ) - if interface_size > 0 and chain_pair[0] in chain_map and chain_pair[1] in chain_map: + if ( + interface_size > 0 + and chain_pair[0] in chain_map + and chain_pair[1] in chain_map + ): model_structure_this = pickle.loads(pickle.dumps(model_structure, -1)) native_structure_this = pickle.loads(pickle.dumps(native_structure, -1)) - info = run_on_groups(model_structure_this, native_structure_this, [chain_pair[0]], [chain_pair[1]], [chain_map[chain_pair[0]]], [chain_map[chain_pair[1]]]) + info = run_on_groups( + model_structure_this, + native_structure_this, + [chain_pair[0]], + [chain_pair[1]], + [chain_map[chain_pair[0]]], + [chain_map[chain_pair[1]]], + ) results_dic[chain_pair] = info return results_dic -def run_DockQ(path_to_model, path_to_native, group1=["A"], group2=["B"], nat_group1=["A"], nat_group2=["B"], model_is_mmcif=False, native_is_mmcif=False, no_needle=False, use_CA_only=False, capri_peptide=False): +def run_DockQ( + path_to_model, + path_to_native, + group1=["A"], + group2=["B"], + nat_group1=["A"], + nat_group2=["B"], + model_is_mmcif=False, + native_is_mmcif=False, + no_needle=False, + use_CA_only=False, + capri_peptide=False, +): model = load_PDB(path_to_model, is_mmcif=model_is_mmcif) native = load_PDB(path_to_native, is_mmcif=native_is_mmcif) - return run_on_groups(model, native, group1, group2, nat_group1, nat_group2, no_needle, use_CA_only, capri_peptide) + return run_on_groups( + model, + native, + group1, + group2, + nat_group1, + nat_group2, + no_needle, + use_CA_only, + capri_peptide, + ) def load_PDB(path, n_model=0, is_mmcif=False): @@ -532,7 +597,8 @@ def load_PDB(path, n_model=0, is_mmcif=False): sys.exit(1) return model -#@profile + +# @profile def main(): args = parse_args() @@ -572,31 +638,51 @@ def main(): nat_group2 = args.native_chain2 # at this stage either group1 or nat_group1 are not None - if not nat_group1: # then the user has set group1. Try to follow the same mapping - if model_chains == native_chains: # easier case: the chains have the same naming between native/model, so just copy them + if not nat_group1: # then the user has set group1. Try to follow the same mapping + if ( + model_chains == native_chains + ): # easier case: the chains have the same naming between native/model, so just copy them nat_group1 = group1 # use complement to nat_group1 if group2 hasn't been decided yet nat_group2 = group2 - else: # otherwise, group the chains by however many where in either model group + else: # otherwise, group the chains by however many where in either model group nat_group1 = native_chains[: len(group1)] - nat_group2 = native_chains[len(group1) : len(group1) + len(group2)] if group2 else None - - if not group1: # viceversa, the user has set nat_group1 + nat_group2 = ( + native_chains[len(group1) : len(group1) + len(group2)] + if group2 + else None + ) + + if not group1: # viceversa, the user has set nat_group1 if model_chains == native_chains: group1 = nat_group1 group2 = nat_group2 else: group1 = model_chains[: len(nat_group1)] - group2 = model_chains[len(nat_group1) : len(nat_group1) + len(nat_group2)] if nat_group2 else None - - if not group2: # no group2 set yet, use the complement to group1 + group2 = ( + model_chains[len(nat_group1) : len(nat_group1) + len(nat_group2)] + if nat_group2 + else None + ) + + if not group2: # no group2 set yet, use the complement to group1 group2 = [chain for chain in model_chains if chain not in group1] if not nat_group2: nat_group2 = [chain for chain in native_chains if chain not in nat_group1] - + if not args.perm1 and not args.perm2: - info = run_on_groups(model_structure, native_structure, group1, group2, nat_group1, nat_group2, args.no_needle, args.useCA, args.capri_peptide) - else: # permute chains and run on a for loop + info = run_on_groups( + model_structure, + native_structure, + group1, + group2, + nat_group1, + nat_group2, + args.no_needle, + args.useCA, + args.capri_peptide, + ) + else: # permute chains and run on a for loop best_DockQ = -1 iter_perm1 = itertools.combinations(group1, len(group1)) @@ -619,10 +705,18 @@ def main(): for g1 in combos1: for g2 in combos2: - model_structure_this = pickle.loads( - pickle.dumps(model_structure, -1) + model_structure_this = pickle.loads(pickle.dumps(model_structure, -1)) + test_info = run_on_groups( + model_structure_this, + native_structure, + g1, + g2, + nat_group1, + nat_group2, + args.no_needle, + args.useCA, + args.capri_peptide, ) - test_info = run_on_groups(model_structure_this, native_structure, g1, g2, nat_group1, nat_group2, args.no_needle, args.useCA, args.capri_peptide) if not args.quiet: print( diff --git a/src/DockQ/operations_nocy.py b/src/DockQ/operations_nocy.py new file mode 100644 index 0000000..6edb480 --- /dev/null +++ b/src/DockQ/operations_nocy.py @@ -0,0 +1,49 @@ +import numpy as np + + +def get_distances_across_chains(model_A_atoms, model_B_atoms): + + distances = ((model_A_atoms[:, None] - model_B_atoms[None, :]) ** 2).sum(-1) + + return distances + + +def atom_distances_to_residue_distances(atom_distances, atoms_per_res1, atoms_per_res2): + res_distances = np.zeros((len(atoms_per_res1), len(atoms_per_res2))) + + cum_i_atoms = 0 + for i, i_atoms in enumerate(atoms_per_res1): + cum_j_atoms = 0 + for j, j_atoms in enumerate(atoms_per_res2): + res_distances[i, j] = atom_distances[ + cum_i_atoms : cum_i_atoms + i_atoms, cum_j_atoms : cum_j_atoms + j_atoms + ].min() + cum_j_atoms += j_atoms + cum_i_atoms += i_atoms + return res_distances + + +def residue_distances( + atom_coordinates1, atom_coordinates2, atoms_per_res1, atoms_per_res2 +): + atom_distances = get_distances_across_chains(atom_coordinates1, atom_coordinates2) + res_distances = atom_distances_to_residue_distances( + atom_distances, atoms_per_res1, atoms_per_res2 + ) + + return res_distances + + +def get_fnat_stats(model_res_distances, native_res_distances, threshold=5.0): + native_contacts = native_res_distances < threshold**2 + model_contacts = model_res_distances < threshold**2 + n_native_contacts = np.sum(native_contacts) + n_model_contacts = np.sum(model_contacts) + n_shared_contacts = np.sum(model_contacts * native_contacts) + n_non_native_contacts = np.sum(model_contacts * (1 - native_contacts)) + return ( + n_shared_contacts, + n_non_native_contacts, + n_native_contacts, + n_model_contacts, + ) From 7a1be3b11ab8f70616efd78703905c469de084db Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 16 Mar 2023 13:22:33 +0100 Subject: [PATCH 061/173] new alignment method --- src/DockQ/DockQ.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index b72bb06..e7702c4 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -8,7 +8,8 @@ import numpy as np from argparse import ArgumentParser import Bio.PDB -from Bio import pairwise2 +#from Bio import pairwise2 +from Bio import Align from Bio.SeqUtils import seq1 from Bio.SVDSuperimposer import SVDSuperimposer @@ -263,7 +264,12 @@ def calc_DockQ( def align_model_to_native( model_structure, native_structure, model_chain, native_chain, use_numbering=False ): - + """ + Function to align two PDB structures. This can be done by sequence (default) or by + numbering. If the numbering is used, then each residue number from the pdb structure + is converted to a unique character. Then the two vectors of character are aligned + as if they were two sequences + """ alignment = {} if use_numbering: model_numbering = [] @@ -293,11 +299,17 @@ def align_model_to_native( seq1(residue.get_resname()) for residue in native_structure[native_chain].get_residues() ) - aln = pairwise2.align.localms( - model_sequence, native_sequence, match=5, mismatch=0, open=-10, extend=-1 - )[0] - alignment["seqA"] = aln.seqA - alignment["seqB"] = aln.seqB + #aln = pairwise2.align.localms( + # model_sequence, native_sequence, match=5, mismatch=0, open=-10, extend=-1 + #)[0] + aligner = Align.PairwiseAligner() + aligner.match = 5 + aligner.mismatch = 0 + aligner.open_gap_score = -10 + aligner.extend_gap_score = -0.5 + aln = Align.PairwiseAligner().align(model_sequence, native_sequence)[0] + alignment["seqA"] = aln.format().split("\n")[0] #aln.seqA + alignment["seqB"] = aln.format().split("\n")[2] #aln.seqB return alignment From 01f97033ffee5a3e335e8f9bc1032676056a8288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wallner?= Date: Tue, 16 May 2023 14:52:05 +0200 Subject: [PATCH 062/173] added file test --- test | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test diff --git a/test b/test new file mode 100644 index 0000000..e69de29 From addb329ef1ae19206f92cfac7a16f02c947872ce Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 1 Mar 2024 11:43:24 +0100 Subject: [PATCH 063/173] group models based on native sequences, bugfixes, simplify code --- src/DockQ/DockQ.py | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index e7702c4..679d91d 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -299,17 +299,15 @@ def align_model_to_native( seq1(residue.get_resname()) for residue in native_structure[native_chain].get_residues() ) - #aln = pairwise2.align.localms( - # model_sequence, native_sequence, match=5, mismatch=0, open=-10, extend=-1 - #)[0] + aligner = Align.PairwiseAligner() aligner.match = 5 aligner.mismatch = 0 aligner.open_gap_score = -10 aligner.extend_gap_score = -0.5 - aln = Align.PairwiseAligner().align(model_sequence, native_sequence)[0] - alignment["seqA"] = aln.format().split("\n")[0] #aln.seqA - alignment["seqB"] = aln.format().split("\n")[2] #aln.seqB + aln = aligner.align(model_sequence, native_sequence)[0] + alignment["seqA"] = aln.format().split("\n")[0] + alignment["seqB"] = aln.format().split("\n")[2] return alignment @@ -610,6 +608,16 @@ def load_PDB(path, n_model=0, is_mmcif=False): return model +def group_model_chains(model_structure, native_structure, model_chains, native_chains): + alignment_targets = itertools.product(model_chains, native_chains) + native_chain_clusters = {chain:[] for chain in native_chains} + + for model_chain, native_chain in alignment_targets: + model_aln = align_model_to_native(model_structure, native_structure, model_chain, native_chain)["seqA"] + if "-" not in model_aln: # 100% sequence identity, 100% coverage of native sequence in model sequence + native_chain_clusters[native_chain].append(model_chain) + return native_chain_clusters + # @profile def main(): args = parse_args() @@ -648,7 +656,7 @@ def main(): group2 = args.model_chain2 nat_group1 = args.native_chain1 nat_group2 = args.native_chain2 - + # at this stage either group1 or nat_group1 are not None if not nat_group1: # then the user has set group1. Try to follow the same mapping if ( @@ -664,6 +672,7 @@ def main(): if group2 else None ) + print(group1, group2, nat_group1, nat_group2) if not group1: # viceversa, the user has set nat_group1 if model_chains == native_chains: @@ -697,16 +706,13 @@ def main(): else: # permute chains and run on a for loop best_DockQ = -1 - iter_perm1 = itertools.combinations(group1, len(group1)) - iter_perm2 = itertools.combinations(group2, len(group2)) - if args.perm1: - iter_perm1 = itertools.permutations(group1) - if args.perm2: - iter_perm2 = itertools.permutations(group2) + native_chain_clusters = group_model_chains(model_structure, native_structure, model_chains, native_chains) + print(native_chain_clusters) - combos1 = list(iter_perm1) - combos2 = list(iter_perm2) + combos1 = list(itertools.permutations(group1)) if args.perm1 else group1 + combos2 = list(itertools.permutations(group2)) if args.perm2 else group2 + print(combos1, combos2) pe_tot = len(combos1) * len(combos2) pe = 1 if args.verbose: From 663522f7d67080babbca560776244d3d7c403aa9 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 1 Mar 2024 13:49:51 +0100 Subject: [PATCH 064/173] draft of chain mapping engine --- src/DockQ/DockQ.py | 177 ++++++++++++++++++++++----------------------- 1 file changed, 88 insertions(+), 89 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 679d91d..89e8ecf 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -5,10 +5,11 @@ import pickle import traceback import itertools -import numpy as np +from functools import lru_cache from argparse import ArgumentParser + import Bio.PDB -#from Bio import pairwise2 +import numpy as np from Bio import Align from Bio.SeqUtils import seq1 from Bio.SVDSuperimposer import SVDSuperimposer @@ -133,13 +134,19 @@ def calc_DockQ( nat_total = np.nonzero(np.asarray(ref_res_distances) < fnat_threshold**2)[ 0 ].shape[0] + + if nat_total == 0: + # if the native has no interface between the two chain groups + # nothing to do here + print(nat_group1, nat_group2) + return None sample_res_distances = get_residue_distances(sample_model, group1, group2) ref_res_distances = get_residue_distances(ref_model, nat_group1, nat_group2) assert ( sample_res_distances.shape == ref_res_distances.shape - ), "Interfaces have different shapes" + ), f"Native and model have incompatible sizes ({sample_res_distances.shape} != {ref_res_distances.shape})" nat_correct, nonnat_count, _, model_total = get_fnat_stats( sample_res_distances, ref_res_distances, threshold=fnat_threshold @@ -270,7 +277,7 @@ def align_model_to_native( is converted to a unique character. Then the two vectors of character are aligned as if they were two sequences """ - alignment = {} + if use_numbering: model_numbering = [] native_numbering = [] @@ -306,8 +313,15 @@ def align_model_to_native( aligner.open_gap_score = -10 aligner.extend_gap_score = -0.5 aln = aligner.align(model_sequence, native_sequence)[0] - alignment["seqA"] = aln.format().split("\n")[0] - alignment["seqB"] = aln.format().split("\n")[2] + return aln + + +def format_alignment(aln): + alignment = {} + formatted_aln = aln.format().split("\n") + alignment["seqA"] = formatted_aln[0] + alignment["matches"] = formatted_aln[1] + alignment["seqB"] = formatted_aln[2] return alignment @@ -361,6 +375,7 @@ def list_atoms_per_residue(model, group): return np.array(n_atoms_per_residue).astype(int) +#@lru_cache def get_residue_distances(model, group1, group2, all_atom=True): if all_atom: # get information about how many atoms correspond to each amino acid in each group of chains @@ -478,6 +493,7 @@ def set_common_backbone_atoms(model, reference, atom_types=["CA", "C", "N", "O"] ref_res.detach_child(atom_id) +#@lru_cache def run_on_groups( model_structure, native_structure, @@ -490,19 +506,19 @@ def run_on_groups( capri_peptide=False, ): remove_extra_chains(model_structure, chains_to_keep=group1 + group2) - remove_extra_chains(native_structure, chains_to_keep=nat_group1 + nat_group2) - native_structure_original = pickle.loads(pickle.dumps(native_structure, -1)) + remove_extra_chains(native_structure, chains_to_keep=nat_group1 + nat_group2) # realign each model chain against the corresponding native chain for model_chain, native_chain in zip(group1 + group2, nat_group1 + nat_group2): - alignment = align_model_to_native( + aln = align_model_to_native( model_structure, native_structure, model_chain, native_chain, use_numbering=no_needle, ) + alignment = format_alignment(aln) fix_chain_residues(model_structure, model_chain, alignment) fix_chain_residues(native_structure, native_chain, alignment, invert=True) info = calc_DockQ( @@ -534,7 +550,7 @@ def run_on_all_native_interfaces( interface_size = np.sum( np.asarray( get_residue_distances( - native_structure, [chain_pair[0]], [chain_pair[1]] + native_structure, (chain_pair[0]), (chain_pair[1]) ) ) < 25.0 @@ -550,10 +566,10 @@ def run_on_all_native_interfaces( info = run_on_groups( model_structure_this, native_structure_this, - [chain_pair[0]], - [chain_pair[1]], - [chain_map[chain_pair[0]]], - [chain_map[chain_pair[1]]], + (chain_map[chain_pair[0]]), + (chain_map[chain_pair[1]]), + (chain_pair[0]), + (chain_pair[1]), ) results_dic[chain_pair] = info @@ -613,8 +629,10 @@ def group_model_chains(model_structure, native_structure, model_chains, native_c native_chain_clusters = {chain:[] for chain in native_chains} for model_chain, native_chain in alignment_targets: - model_aln = align_model_to_native(model_structure, native_structure, model_chain, native_chain)["seqA"] - if "-" not in model_aln: # 100% sequence identity, 100% coverage of native sequence in model sequence + aln = align_model_to_native(model_structure, native_structure, model_chain, native_chain) + alignment = format_alignment(aln) + if "." not in alignment["matches"] and ("-" not in alignment["seqA"] or "-" not in alignment["seqB"]): + # 100% sequence identity, 100% coverage of native sequence in model sequence native_chain_clusters[native_chain].append(model_chain) return native_chain_clusters @@ -634,7 +652,7 @@ def main(): remove_hetatms(model_structure) best_info = "" - + info = {} model_chains = [c.id for c in model_structure] native_chains = [c.id for c in native_structure] @@ -672,7 +690,6 @@ def main(): if group2 else None ) - print(group1, group2, nat_group1, nat_group2) if not group1: # viceversa, the user has set nat_group1 if model_chains == native_chains: @@ -704,59 +721,39 @@ def main(): args.capri_peptide, ) else: # permute chains and run on a for loop - best_DockQ = -1 + best_dockq = -1 + best_mapping = None native_chain_clusters = group_model_chains(model_structure, native_structure, model_chains, native_chains) - print(native_chain_clusters) - - combos1 = list(itertools.permutations(group1)) if args.perm1 else group1 - combos2 = list(itertools.permutations(group2)) if args.perm2 else group2 - - print(combos1, combos2) - pe_tot = len(combos1) * len(combos2) - pe = 1 - if args.verbose: - print( - f"Starting chain order permutation search (number of permutations: {pe_tot})" + all_mappings = itertools.product(*native_chain_clusters.values()) + + # remove mappings where the same model chain is present more than once + all_mappings = [element for element in all_mappings if len(set(element)) == len(element)] + combo_dockq = -1 + for mapping in all_mappings: + chain_map = {native_chain:mapping[i] for i, native_chain in enumerate(native_chains)} + + result_this_mapping = run_on_all_native_interfaces( + model_structure, + native_structure, + chain_map=chain_map, + no_needle=args.no_needle, + use_CA_only=args.useCA, + capri_peptide=args.capri_peptide, ) + #print(chain_map) + #print(result_this_mapping.values()) + total_dockq = sum([result["DockQ"] for result in result_this_mapping.values()]) + print(result_this_mapping, total_dockq) + if total_dockq > best_dockq: + best_dockq = total_dockq + best_result = result_this_mapping + + info["model"] = args.model + info["native"] = args.native + info["best_dockq"] = best_dockq + info["best_result"] = best_result - for g1 in combos1: - for g2 in combos2: - - model_structure_this = pickle.loads(pickle.dumps(model_structure, -1)) - test_info = run_on_groups( - model_structure_this, - native_structure, - g1, - g2, - nat_group1, - nat_group2, - args.no_needle, - args.useCA, - args.capri_peptide, - ) - - if not args.quiet: - print( - f"{pe}/{pe_tot} {''.join(g1)} -> {''.join(g2)} {test_info['DockQ']}" - ) - - if test_info["DockQ"] > best_DockQ: - best_DockQ = test_info["DockQ"] - info = test_info - best_info = f"Best score ({best_DockQ}) found for model -> native, chain1: {''.join(g1)} -> {''.join(nat_group1)} chain2: {''.join(g2)} -> {''.join(nat_group2)}" - - if args.verbose: - print(best_info) - if not args.quiet: - print(f"Current best: {best_DockQ}") - pe = pe + 1 - if not args.quiet: - print(best_info) - - info["model"] = args.model - info["native"] = args.native - info["best"] = best_info print_results(info, args.short, args.capri_peptide) @@ -800,29 +797,31 @@ def print_results(info, short=False, capri_peptide=False): print("****************************************************************") print(f"Model : {info['model']}") print(f"Native : {info['native']}") - if "best" in info: - print(info["best"]) - print( - f"Number of equivalent residues in chain {info['chain1']} {info['len1']} ({info['class1']})" - ) - print( - f"Number of equivalent residues in chain {info['chain2']} {info['len2']} ({info['class2']})" - ) - print( - f"Fnat {info['fnat']:.3f} {info['nat_correct']} correct of {info['nat_total']} native contacts" - ) - print( - f"Fnonnat {info['fnonnat']:.3f} {info['nonnat_count']} non-native of {info['model_total']} model contacts" - ) - print(f"iRMS {info['irms']:.3f}") - print(f"LRMS {info['Lrms']:.3f}") + if "best_dockq" in info: + print(info["best_result"]) + print(info["best_dockq"]) + else: + print( + f"Number of equivalent residues in chain {info['chain1']} {info['len1']} ({info['class1']})" + ) + print( + f"Number of equivalent residues in chain {info['chain2']} {info['len2']} ({info['class2']})" + ) + print( + f"Fnat {info['fnat']:.3f} {info['nat_correct']} correct of {info['nat_total']} native contacts" + ) + print( + f"Fnonnat {info['fnonnat']:.3f} {info['nonnat_count']} non-native of {info['model_total']} model contacts" + ) + print(f"iRMS {info['irms']:.3f}") + print(f"LRMS {info['Lrms']:.3f}") - peptide_disclaimer = ( - " DockQ not reoptimized for CAPRI peptide evaluation" - if capri_peptide - else "" - ) - print(f"DockQ {info['DockQ']:.3f}{peptide_disclaimer}") + peptide_disclaimer = ( + " DockQ not reoptimized for CAPRI peptide evaluation" + if capri_peptide + else "" + ) + print(f"DockQ {info['DockQ']:.3f}{peptide_disclaimer}") if __name__ == "__main__": From 54f2690b63f7e9e968ffc4a8c0485f6a24d2cf47 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 1 Mar 2024 14:27:34 +0100 Subject: [PATCH 065/173] mapping engine draft --- src/DockQ/DockQ.py | 118 ++++++++++++++++++++++----------------------- 1 file changed, 57 insertions(+), 61 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 89e8ecf..c7ee44f 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -69,16 +69,10 @@ def parse_args(): help="Do not align native and model using sequence alignments, but use the numbering of residues instead", ) parser.add_argument( - "-perm1", - default=False, - action="store_true", - help="use all chain1 permutations to find maximum DockQ (number of comparisons is n! = 24, if combined with -perm2 there will be n!*m! combinations", - ) - parser.add_argument( - "-perm2", - default=False, + "-auto_map", + default=True, action="store_true", - help="use all chain2 permutations to find maximum DockQ (number of comparisons is n! = 24, if combined with -perm1 there will be n!*m! combinations", + help="automatically calculate chain mapping between model and native to maximize total DockQ (sum DockQ for all native interfaces)", ) parser.add_argument( "-model_chain1", @@ -535,6 +529,7 @@ def run_on_groups( return info +#@profile def run_on_all_native_interfaces( model_structure, native_structure, @@ -547,14 +542,14 @@ def run_on_all_native_interfaces( results_dic = {} native_chains = [c.id for c in native_structure] for chain_pair in itertools.combinations(native_chains, 2): - interface_size = np.sum( - np.asarray( - get_residue_distances( - native_structure, (chain_pair[0]), (chain_pair[1]) - ) - ) - < 25.0 + + # total number of native contacts is calculated on untouched native structure + ref_res_distances = get_residue_distances( + native_structure, (chain_pair[0]), (chain_pair[1]) ) + interface_size = np.nonzero(np.asarray(ref_res_distances) < 25.0)[ + 0 + ].shape[0] if ( interface_size > 0 @@ -636,7 +631,7 @@ def group_model_chains(model_structure, native_structure, model_chains, native_c native_chain_clusters[native_chain].append(model_chain) return native_chain_clusters -# @profile +#@profile def main(): args = parse_args() @@ -656,6 +651,7 @@ def main(): model_chains = [c.id for c in model_structure] native_chains = [c.id for c in native_structure] + """ if (len(model_chains) > 2 or len(native_chains) > 2) and ( not args.model_chain1 and not args.native_chain1 ): @@ -665,50 +661,51 @@ def main(): print(f"Model chains: {' '.join(model_chains)}") print(f"Native chains: {' '.join(native_chains)}") sys.exit() + """ if len(model_chains) < 2 or len(native_chains) < 2: print("Need at least two chains in the two inputs\n") sys.exit() - # Some of these might be None - group1 = [model_chains[0]] if len(model_chains) == 2 else args.model_chain1 - group2 = args.model_chain2 - nat_group1 = args.native_chain1 - nat_group2 = args.native_chain2 - - # at this stage either group1 or nat_group1 are not None - if not nat_group1: # then the user has set group1. Try to follow the same mapping - if ( - model_chains == native_chains - ): # easier case: the chains have the same naming between native/model, so just copy them - nat_group1 = group1 - # use complement to nat_group1 if group2 hasn't been decided yet - nat_group2 = group2 - else: # otherwise, group the chains by however many where in either model group - nat_group1 = native_chains[: len(group1)] - nat_group2 = ( - native_chains[len(group1) : len(group1) + len(group2)] - if group2 - else None - ) + if not args.auto_map: + # Some of these might be None + group1 = [model_chains[0]] if len(model_chains) == 2 else args.model_chain1 + group2 = args.model_chain2 + nat_group1 = args.native_chain1 + nat_group2 = args.native_chain2 + + # at this stage either group1 or nat_group1 are not None + if not nat_group1: # then the user has set group1. Try to follow the same mapping + if ( + model_chains == native_chains + ): # easier case: the chains have the same naming between native/model, so just copy them + nat_group1 = group1 + # use complement to nat_group1 if group2 hasn't been decided yet + nat_group2 = group2 + else: # otherwise, group the chains by however many where in either model group + nat_group1 = native_chains[: len(group1)] + nat_group2 = ( + native_chains[len(group1) : len(group1) + len(group2)] + if group2 + else None + ) - if not group1: # viceversa, the user has set nat_group1 - if model_chains == native_chains: - group1 = nat_group1 - group2 = nat_group2 - else: - group1 = model_chains[: len(nat_group1)] - group2 = ( - model_chains[len(nat_group1) : len(nat_group1) + len(nat_group2)] - if nat_group2 - else None - ) + if not group1: # viceversa, the user has set nat_group1 + if model_chains == native_chains: + group1 = nat_group1 + group2 = nat_group2 + else: + group1 = model_chains[: len(nat_group1)] + group2 = ( + model_chains[len(nat_group1) : len(nat_group1) + len(nat_group2)] + if nat_group2 + else None + ) - if not group2: # no group2 set yet, use the complement to group1 - group2 = [chain for chain in model_chains if chain not in group1] - if not nat_group2: - nat_group2 = [chain for chain in native_chains if chain not in nat_group1] + if not group2: # no group2 set yet, use the complement to group1 + group2 = [chain for chain in model_chains if chain not in group1] + if not nat_group2: + nat_group2 = [chain for chain in native_chains if chain not in nat_group1] - if not args.perm1 and not args.perm2: info = run_on_groups( model_structure, native_structure, @@ -722,17 +719,18 @@ def main(): ) else: # permute chains and run on a for loop best_dockq = -1 - best_mapping = None + best_result = None native_chain_clusters = group_model_chains(model_structure, native_structure, model_chains, native_chains) all_mappings = itertools.product(*native_chain_clusters.values()) - + #print(native_chain_clusters, list(all_mappings)) # remove mappings where the same model chain is present more than once - all_mappings = [element for element in all_mappings if len(set(element)) == len(element)] + #all_mappings = [element for element in all_mappings if len(set(element)) == len(element)] combo_dockq = -1 + for mapping in all_mappings: chain_map = {native_chain:mapping[i] for i, native_chain in enumerate(native_chains)} - + print(chain_map) result_this_mapping = run_on_all_native_interfaces( model_structure, native_structure, @@ -741,10 +739,8 @@ def main(): use_CA_only=args.useCA, capri_peptide=args.capri_peptide, ) - #print(chain_map) - #print(result_this_mapping.values()) + total_dockq = sum([result["DockQ"] for result in result_this_mapping.values()]) - print(result_this_mapping, total_dockq) if total_dockq > best_dockq: best_dockq = total_dockq best_result = result_this_mapping From 1288e7a6356b3a6aef3344fae5eb2b1b5131ea64 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 4 Mar 2024 09:46:15 +0100 Subject: [PATCH 066/173] debug --- src/DockQ/DockQ.py | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index c7ee44f..2d03d9e 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -651,17 +651,6 @@ def main(): model_chains = [c.id for c in model_structure] native_chains = [c.id for c in native_structure] - """ - if (len(model_chains) > 2 or len(native_chains) > 2) and ( - not args.model_chain1 and not args.native_chain1 - ): - print( - "Multi-chain model need sets of chains to group\nuse -native_chain1 and/or -model_chain1 if you want a different mapping than 1-1" - ) - print(f"Model chains: {' '.join(model_chains)}") - print(f"Native chains: {' '.join(native_chains)}") - sys.exit() - """ if len(model_chains) < 2 or len(native_chains) < 2: print("Need at least two chains in the two inputs\n") sys.exit() @@ -723,9 +712,8 @@ def main(): native_chain_clusters = group_model_chains(model_structure, native_structure, model_chains, native_chains) all_mappings = itertools.product(*native_chain_clusters.values()) - #print(native_chain_clusters, list(all_mappings)) # remove mappings where the same model chain is present more than once - #all_mappings = [element for element in all_mappings if len(set(element)) == len(element)] + all_mappings = [element for element in all_mappings if len(set(element)) == len(element)] combo_dockq = -1 for mapping in all_mappings: From eb0c87172d462e7fb25f2392df19f5e3f0c32eb0 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 4 Mar 2024 13:01:19 +0100 Subject: [PATCH 067/173] slightly more efficient pickling --- pyproject.toml | 4 +- src/DockQ/DockQ.py | 406 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 389 insertions(+), 21 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index df7b3a3..fa680af 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [build-system] name = "DockQ" -version = 2.0 -requires = ["setuptools", "cython", "numpy"] +version = "2.0" +requires = ["setuptools", "cython", "numpy ~= 1.21", "biopython == 1.79"] build-backend = "setuptools.build_meta" diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 2d03d9e..ca48d13 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -1,7 +1,8 @@ #!/usr/bin/env python -import sys import os +import sys +import time import pickle import traceback import itertools @@ -262,6 +263,153 @@ def calc_DockQ( return info +def calc_DockQ( + sample_chains, + ref_chains, + ref_chains_original, + use_CA_only=False, + capri_peptide=False, +): + atom_for_sup = ["CA", "C", "N", "O"] if not use_CA_only else ["CA"] + fnat_threshold = 4.0 if capri_peptide else 5.0 + interface_threshold = 8.0 if capri_peptide else 10.0 + + # total number of native contacts is calculated on untouched native structure + ref_res_distances = get_residue_distances( + ref_chains_original[0], ref_chains_original[1] + ) + nat_total = np.nonzero(np.asarray(ref_res_distances) < fnat_threshold**2)[ + 0 + ].shape[0] + + if nat_total == 0: + # if the native has no interface between the two chain groups + # nothing to do here + print(nat_group1, nat_group2) + return None + + sample_res_distances = get_residue_distances(sample_chains[0], sample_chains[1]) + ref_res_distances = get_residue_distances(ref_chains[0], ref_chains[1]) + + assert ( + sample_res_distances.shape == ref_res_distances.shape + ), f"Native and model have incompatible sizes ({sample_res_distances.shape} != {ref_res_distances.shape})" + + nat_correct, nonnat_count, _, model_total = get_fnat_stats( + sample_res_distances, ref_res_distances, threshold=fnat_threshold + ) + # avoids divide by 0 errors + fnat = nat_total and nat_correct / nat_total or 0 + fnonnat = model_total and nonnat_count / model_total or 0 + + if capri_peptide: + ref_res_distances = get_residue_distances( + ref_chains[0], ref_chains[1], all_atom=False + ) + # Get interfacial atoms from reference, and corresponding atoms from sample + interacting_pairs = get_interacting_pairs( + # working with squared thresholds to avoid using sqrt in distance calculations + ref_res_distances, + threshold=interface_threshold**2, + ) + + # get a copy of each structure, then only keep backbone atoms + sample_chains_backbone = sample_chains + ref_chains_backbone = ref_chains + set_common_backbone_atoms( + sample_chains_backbone[0], ref_chains_backbone[0], atom_types=atom_for_sup + ) + set_common_backbone_atoms( + sample_chains_backbone[1], ref_chains_backbone[1], atom_types=atom_for_sup + ) + + sample_interface_atoms, ref_interface_atoms = get_interface_atoms( + interacting_pairs, + sample_chains_backbone, + ref_chains_backbone, + ) + + super_imposer = Bio.PDB.Superimposer() + super_imposer.set_atoms(sample_interface_atoms, ref_interface_atoms) + + irms = super_imposer.rms + + # assign which group of chains constitutes the receptor, then the other is the ligand + ref_group1_size = len(ref_chains[0]) + ref_group2_size = len(ref_chains[1]) + receptor_chains = ( + (ref_chains[0], sample_chains[0]) + if ref_group1_size > ref_group2_size + else (ref_chains[1], sample_chains[1]) + ) + ligand_chains = ( + (ref_chains[1], sample_chains[1]) + if ref_group1_size <= ref_group2_size + else (ref_chains[0], sample_chains[0]) + ) + class1, class2 = ( + ("receptor", "ligand") + if ref_group1_size > ref_group2_size + else ("ligand", "receptor") + ) + receptor_atoms_native = [ + atom + for atom in receptor_chains[0].get_atoms() + ] + receptor_atoms_sample = [ + atom + for atom in receptor_chains[1].get_atoms() + ] + + # Set to align on receptor + super_imposer.set_atoms(receptor_atoms_native, receptor_atoms_sample) + super_imposer.apply([atom for backbone in sample_chains_backbone for atom in backbone.get_atoms()]) + + coord1 = np.array( + [ + atom.coord + for atom in ligand_chains[0].get_atoms() + ] + ) + coord2 = np.array( + [ + atom.coord + for atom in ligand_chains[1].get_atoms() + ] + ) + + sup = SVDSuperimposer() + Lrms = sup._rms( + coord1, coord2 + ) # using the private _rms function which does not superimpose + + DockQ = ( + float(fnat) + + 1 / (1 + (irms / 1.5) * (irms / 1.5)) + + 1 / (1 + (Lrms / 8.5) * (Lrms / 8.5)) + ) / 3 + info = {} + info["DockQ"] = DockQ + info["irms"] = irms + info["Lrms"] = Lrms + info["fnat"] = fnat + info["nat_correct"] = nat_correct + info["nat_total"] = nat_total + + info["fnonnat"] = fnonnat + info["nonnat_count"] = nonnat_count + info["model_total"] = model_total + + info["chain1"] = "A" #" ".join(group1) + info["chain2"] = "B" #" ".join(group2) + info["len1"] = ref_group1_size + info["len2"] = ref_group2_size + info["class1"] = class1 + info["class2"] = class2 + + return info + + def align_model_to_native( model_structure, native_structure, model_chain, native_chain, use_numbering=False ): @@ -310,6 +458,54 @@ def align_model_to_native( return aln +def align_chains( + model_chain, native_chain, use_numbering=False +): + """ + Function to align two PDB structures. This can be done by sequence (default) or by + numbering. If the numbering is used, then each residue number from the pdb structure + is converted to a unique character. Then the two vectors of character are aligned + as if they were two sequences + """ + + if use_numbering: + model_numbering = [] + native_numbering = [] + + for residue in model_chain.get_residues(): + resn = int(residue.id[1]) + model_numbering.append(resn) + + for residue in native_chain.get_residues(): + resn = int(residue.id[1]) + native_numbering.append(resn) + # if the samllest resn is negative, it will be used to shift all numbers so they start from 0 + # the minimum offset is 45 to avoid including the "-" character that is reserved for gaps + min_resn = max(45, -min(model_numbering + native_numbering)) + + model_sequence = "".join([chr(resn + min_resn) for resn in model_numbering]) + native_sequence = "".join([chr(resn + min_resn) for resn in native_numbering]) + + else: + model_sequence = "".join( + seq1(residue.get_resname()) + for residue in model_chain.get_residues() + ) + + native_sequence = "".join( + seq1(residue.get_resname()) + for residue in native_chain.get_residues() + ) + + aligner = Align.PairwiseAligner() + aligner.match = 5 + aligner.mismatch = 0 + aligner.open_gap_score = -10 + aligner.extend_gap_score = -0.5 + aln = aligner.align(model_sequence, native_sequence)[0] + return aln + + def format_alignment(aln): alignment = {} formatted_aln = aln.format().split("\n") @@ -341,6 +537,20 @@ def remove_hetatms(model): model[chain].detach_child(res) +def remove_h(model): + chains = [chain.id for chain in model.get_chains()] + atoms_to_delete = [] + + for chain in chains: + residues = model[chain].get_residues() + for residue in residues: + for atom in residue.get_atoms(): + if atom.element == "H": + atoms_to_delete.append(atom.get_full_id()) + + for _, _, chain, res, atom in atoms_to_delete: + model[chain][res].detach_child(atom[0]) + def fix_chain_residues(model, chain, alignment, invert=False): residues = model[chain].get_residues() residues_to_delete = [] @@ -357,6 +567,22 @@ def fix_chain_residues(model, chain, alignment, invert=False): model[chain].detach_child(res) +def fix_chain_residues(chain, alignment, invert=False): + residues = chain.get_residues() + residues_to_delete = [] + + seqA = alignment["seqA"] if not invert else alignment["seqB"] + seqB = alignment["seqB"] if not invert else alignment["seqA"] + for (aligned_residue_A, aligned_residue_B) in zip(seqA, seqB): + if aligned_residue_A != "-": + residue = next(residues) + if aligned_residue_B == "-": # gap residue: remove from structure + residues_to_delete.append(residue.get_full_id()) + + for _, _, _, res in residues_to_delete: + chain.detach_child(res) + + def list_atoms_per_residue(model, group): n_atoms_per_residue = [] for chain in group: @@ -369,7 +595,7 @@ def list_atoms_per_residue(model, group): return np.array(n_atoms_per_residue).astype(int) -#@lru_cache +@lru_cache def get_residue_distances(model, group1, group2, all_atom=True): if all_atom: # get information about how many atoms correspond to each amino acid in each group of chains @@ -419,6 +645,67 @@ def get_residue_distances(model, group1, group2, all_atom=True): return model_res_distances +@lru_cache +def get_residue_distances(chain1, chain2, all_atom=True): + if all_atom: + # get information about how many atoms correspond to each amino acid in each group of chains + n_atoms_per_res_chain1 = list_atoms_per_residue(chain1) + n_atoms_per_res_chain2 = list_atoms_per_residue(chain2) + model_A_atoms = np.asarray( + [ + atom.get_coord() + for res in chain1.get_residues() + for atom in res.get_atoms() + if atom.element != "H" + ] + ) + model_B_atoms = np.asarray( + [ + atom.get_coord() + for res in chain2.get_residues() + for atom in res.get_atoms() + if atom.element != "H" + ] + ) + + else: # distances were already between CBs only + model_A_atoms = np.asarray( + [ + res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() + for res in chain1.get_residues() + ] + ) + model_B_atoms = np.asarray( + [ + res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() + for res in chain2.get_residues() + ] + ) + + n_atoms_per_res_chain1 = np.ones(model_A_atoms.shape[0]).astype(int) + n_atoms_per_res_chain2 = np.ones(model_B_atoms.shape[0]).astype(int) + + model_res_distances = residue_distances( + model_A_atoms, model_B_atoms, n_atoms_per_res_chain1, n_atoms_per_res_chain2 + ) + return model_res_distances + + +def list_atoms_per_residue(chain): + n_atoms_per_residue = [] + + for residue in chain.get_residues(): + # important to remove duplicate atoms (e.g. alternates) at this stage, remove also hydrogens + atom_ids = set( + [a.id for a in residue.get_unpacked_list() if a.element != "H"] + ) + n_atoms_per_residue.append(len(atom_ids)) + return np.array(n_atoms_per_residue).astype(int) + + + + + def get_interacting_pairs(distances, threshold): return np.nonzero(np.asarray(distances) < threshold) @@ -465,6 +752,47 @@ def get_interface_atoms( return mod_interface, ref_interface +def get_interface_atoms( + interacting_pairs, + model_chains, + ref_chains, +): + ref_interface = [] + mod_interface = [] + + ref_residues_group1 = [ + #res for chain in ref_group1 for res in ref_backbone[chain].get_residues() + res for res in ref_chains[0].get_residues() + ] + ref_residues_group2 = [ + #res for chain in ref_group2 for res in ref_backbone[chain].get_residues() + res for res in ref_chains[1].get_residues() + ] + + mod_residues_group1 = [ + #res for chain in model_group1 for res in model_backbone[chain].get_residues() + res for res in model_chains[0].get_residues() + ] + mod_residues_group2 = [ + #res for chain in model_group2 for res in model_backbone[chain].get_residues() + res for res in model_chains[1].get_residues() + ] + + # remove duplicate residues + interface_residues_group1 = set(interacting_pairs[0]) + interface_residues_group2 = set(interacting_pairs[1]) + + for i in interface_residues_group1: + ref_interface += [atom for atom in ref_residues_group1[i].get_atoms()] + mod_interface += [atom for atom in mod_residues_group1[i].get_atoms()] + + for j in interface_residues_group2: + ref_interface += [atom for atom in ref_residues_group2[j].get_atoms()] + mod_interface += [atom for atom in mod_residues_group2[j].get_atoms()] + + return mod_interface, ref_interface + + def set_common_backbone_atoms(model, reference, atom_types=["CA", "C", "N", "O"]): # model and reference should have the same number of amino acids and be aligned for mod_res, ref_res in zip(model.get_residues(), reference.get_residues()): @@ -486,11 +814,16 @@ def set_common_backbone_atoms(model, reference, atom_types=["CA", "C", "N", "O"] for atom_id in set(atom_ids_in_ref_res).difference(atom_ids_in_ref_and_mod_res): ref_res.detach_child(atom_id) - #@lru_cache +def copy(structure): + return pickle.loads(pickle.dumps(structure, protocol=4)) + + +@lru_cache def run_on_groups( model_structure, native_structure, + native_structure_original, group1, group2, nat_group1, @@ -500,7 +833,6 @@ def run_on_groups( capri_peptide=False, ): remove_extra_chains(model_structure, chains_to_keep=group1 + group2) - native_structure_original = pickle.loads(pickle.dumps(native_structure, -1)) remove_extra_chains(native_structure, chains_to_keep=nat_group1 + nat_group2) # realign each model chain against the corresponding native chain @@ -528,8 +860,38 @@ def run_on_groups( ) return info +@lru_cache +def run_on_chains( + model_chains, + native_chains, + no_needle=False, + use_CA_only=False, + capri_peptide=False, +): + #remove_extra_chains(model_structure, chains_to_keep=group1 + group2) + #remove_extra_chains(native_structure, chains_to_keep=nat_group1 + nat_group2) -#@profile + # realign each model chain against the corresponding native chain + for model_chain, native_chain in zip(model_chains, native_chains): + aln = align_chains( + model_chain, + native_chain, + use_numbering=no_needle, + ) + alignment = format_alignment(aln) + fix_chain_residues(model_chain, alignment) + fix_chain_residues(native_chain, alignment, invert=True) + info = calc_DockQ( + model_chains, + native_chains, + native_chains, #### + use_CA_only=use_CA_only, + capri_peptide=capri_peptide, + ) + return info + + +@profile def run_on_all_native_interfaces( model_structure, native_structure, @@ -540,12 +902,15 @@ def run_on_all_native_interfaces( ): """Given a native-model chain map, finds all non-null native interfaces and runs DockQ for each native-model pair of interfaces""" results_dic = {} - native_chains = [c.id for c in native_structure] - for chain_pair in itertools.combinations(native_chains, 2): + native_chain_ids = [c.id for c in native_structure] + + for chain_pair in itertools.combinations(native_chain_ids, 2): + native_chains = tuple([native_structure[chain] for chain in chain_pair]) + model_chains = tuple([model_structure[chain] for chain in [chain_map[chain_pair[0]], chain_map[chain_pair[1]]]]) # total number of native contacts is calculated on untouched native structure ref_res_distances = get_residue_distances( - native_structure, (chain_pair[0]), (chain_pair[1]) + native_chains[0], native_chains[1] ) interface_size = np.nonzero(np.asarray(ref_res_distances) < 25.0)[ 0 @@ -556,16 +921,13 @@ def run_on_all_native_interfaces( and chain_pair[0] in chain_map and chain_pair[1] in chain_map ): - model_structure_this = pickle.loads(pickle.dumps(model_structure, -1)) - native_structure_this = pickle.loads(pickle.dumps(native_structure, -1)) - info = run_on_groups( - model_structure_this, - native_structure_this, - (chain_map[chain_pair[0]]), - (chain_map[chain_pair[1]]), - (chain_pair[0]), - (chain_pair[1]), + model_chains_this = copy(model_chains) + native_chains_this = copy(native_chains) + info = run_on_chains( + model_chains_this, + native_chains_this, ) + results_dic[chain_pair] = info return results_dic @@ -590,6 +952,7 @@ def run_DockQ( return run_on_groups( model, native, + copy(native), group1, group2, nat_group1, @@ -645,6 +1008,8 @@ def main(): model_structure = load_PDB(args.model, is_mmcif=args.mmcif_model) remove_hetatms(native_structure) remove_hetatms(model_structure) + remove_h(model_structure) + remove_h(native_structure) best_info = "" info = {} @@ -715,8 +1080,9 @@ def main(): # remove mappings where the same model chain is present more than once all_mappings = [element for element in all_mappings if len(set(element)) == len(element)] combo_dockq = -1 - - for mapping in all_mappings: + + for mapping in all_mappings[:5]: + start = time.time() chain_map = {native_chain:mapping[i] for i, native_chain in enumerate(native_chains)} print(chain_map) result_this_mapping = run_on_all_native_interfaces( @@ -732,6 +1098,8 @@ def main(): if total_dockq > best_dockq: best_dockq = total_dockq best_result = result_this_mapping + stop = time.time() + print(stop-start) info["model"] = args.model info["native"] = args.native From e3d95eb58d4a11c1f503dcbddcc51ea641dc246a Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 4 Mar 2024 14:25:52 +0100 Subject: [PATCH 068/173] use alignments instead of dropping residues from structures --- src/DockQ/DockQ.py | 125 ++++++++++++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 47 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index ca48d13..504fe2a 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -266,7 +266,7 @@ def calc_DockQ( def calc_DockQ( sample_chains, ref_chains, - ref_chains_original, + alignments=[], use_CA_only=False, capri_peptide=False, ): @@ -276,7 +276,7 @@ def calc_DockQ( # total number of native contacts is calculated on untouched native structure ref_res_distances = get_residue_distances( - ref_chains_original[0], ref_chains_original[1] + ref_chains[0], ref_chains[1] ) nat_total = np.nonzero(np.asarray(ref_res_distances) < fnat_threshold**2)[ 0 @@ -288,13 +288,14 @@ def calc_DockQ( print(nat_group1, nat_group2) return None - sample_res_distances = get_residue_distances(sample_chains[0], sample_chains[1]) - ref_res_distances = get_residue_distances(ref_chains[0], ref_chains[1]) + sample_res_distances = get_residue_distances(sample_chains[0], sample_chains[1], alignments=alignments) + ref_res_distances = get_residue_distances(ref_chains[0], ref_chains[1], alignments=alignments) assert ( sample_res_distances.shape == ref_res_distances.shape ), f"Native and model have incompatible sizes ({sample_res_distances.shape} != {ref_res_distances.shape})" + print(f"Native and model have compatible sizes ({sample_res_distances.shape} == {ref_res_distances.shape})") nat_correct, nonnat_count, _, model_total = get_fnat_stats( sample_res_distances, ref_res_distances, threshold=fnat_threshold ) @@ -361,6 +362,7 @@ def calc_DockQ( for atom in receptor_chains[1].get_atoms() ] + print(len(receptor_atoms_native), len(receptor_atoms_sample)) # Set to align on receptor super_imposer.set_atoms(receptor_atoms_native, receptor_atoms_sample) super_imposer.apply([atom for backbone in sample_chains_backbone for atom in backbone.get_atoms()]) @@ -581,6 +583,7 @@ def fix_chain_residues(chain, alignment, invert=False): for _, _, _, res in residues_to_delete: chain.detach_child(res) + return chain def list_atoms_per_residue(model, group): @@ -595,7 +598,7 @@ def list_atoms_per_residue(model, group): return np.array(n_atoms_per_residue).astype(int) -@lru_cache +#@lru_cache def get_residue_distances(model, group1, group2, all_atom=True): if all_atom: # get information about how many atoms correspond to each amino acid in each group of chains @@ -645,40 +648,61 @@ def get_residue_distances(model, group1, group2, all_atom=True): return model_res_distances -@lru_cache -def get_residue_distances(chain1, chain2, all_atom=True): +#@lru_cache +def get_residue_distances(chain1, chain2, alignments=[], all_atom=True): if all_atom: # get information about how many atoms correspond to each amino acid in each group of chains - n_atoms_per_res_chain1 = list_atoms_per_residue(chain1) - n_atoms_per_res_chain2 = list_atoms_per_residue(chain2) - model_A_atoms = np.asarray( - [ - atom.get_coord() - for res in chain1.get_residues() - for atom in res.get_atoms() - if atom.element != "H" - ] - ) - model_B_atoms = np.asarray( - [ - atom.get_coord() - for res in chain2.get_residues() - for atom in res.get_atoms() - if atom.element != "H" - ] - ) + n_atoms_per_res_chain1 = list_atoms_per_residue(chain1, alignment=alignments[0] if alignments else "") + n_atoms_per_res_chain2 = list_atoms_per_residue(chain2, alignment=alignments[1] if alignments else "") + + if not alignments: + model_A_atoms = np.asarray( + [ + atom.get_coord() + for i, res in enumerate(chain1.get_residues()) + for atom in res.get_atoms() + if atom.element != "H" + ] + ) + model_B_atoms = np.asarray( + [ + atom.get_coord() + for i, res in enumerate(chain2.get_residues()) + for atom in res.get_atoms() + if atom.element != "H" + ] + ) + else: + model_A_atoms = [] + model_B_atoms = [] + res_chain1 = chain1.get_residues() + res_chain2 = chain2.get_residues() + for match in alignments[0]: + if match == "|": + res1 = next(res_chain1) + + model_A_atoms.extend([atom.get_coord() for atom in res1.get_atoms()]) + + for match in alignments[1]: + if match == "|": + res2 = next(res_chain2) + model_B_atoms.extend([atom.get_coord() for atom in res2.get_atoms()]) + model_A_atoms = np.asarray(model_A_atoms) + model_B_atoms = np.asarray(model_B_atoms) else: # distances were already between CBs only model_A_atoms = np.asarray( [ res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() - for res in chain1.get_residues() + for i, res in enumerate(chain1.get_residues()) + if (alignments[0][i] == "|" if alignments else True) ] ) model_B_atoms = np.asarray( [ res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() - for res in chain2.get_residues() + for i, res in enumerate(chain2.get_residues()) + if (alignments[1][i] == "|" if alignments else True) ] ) @@ -691,21 +715,28 @@ def get_residue_distances(chain1, chain2, all_atom=True): return model_res_distances -def list_atoms_per_residue(chain): +def list_atoms_per_residue(chain, alignment=""): n_atoms_per_residue = [] - - for residue in chain.get_residues(): - # important to remove duplicate atoms (e.g. alternates) at this stage, remove also hydrogens - atom_ids = set( - [a.id for a in residue.get_unpacked_list() if a.element != "H"] - ) - n_atoms_per_residue.append(len(atom_ids)) + residues = chain.get_residues() + + if alignment: + for match in alignment: + if match == "|": + residue = next(residues) + atom_ids = set( + [a.id for a in residue.get_unpacked_list()] + ) + n_atoms_per_residue.append(len(atom_ids)) + else: + for residue in residues: + # important to remove duplicate atoms (e.g. alternates) at this stage, remove also hydrogens + atom_ids = set( + [a.id for a in residue.get_unpacked_list()] + ) + n_atoms_per_residue.append(len(atom_ids)) return np.array(n_atoms_per_residue).astype(int) - - - def get_interacting_pairs(distances, threshold): return np.nonzero(np.asarray(distances) < threshold) @@ -868,10 +899,8 @@ def run_on_chains( use_CA_only=False, capri_peptide=False, ): - #remove_extra_chains(model_structure, chains_to_keep=group1 + group2) - #remove_extra_chains(native_structure, chains_to_keep=nat_group1 + nat_group2) - # realign each model chain against the corresponding native chain + alignments = [] for model_chain, native_chain in zip(model_chains, native_chains): aln = align_chains( model_chain, @@ -879,19 +908,21 @@ def run_on_chains( use_numbering=no_needle, ) alignment = format_alignment(aln) - fix_chain_residues(model_chain, alignment) - fix_chain_residues(native_chain, alignment, invert=True) + #fix_chain_residues(model_chain, alignment) + #fix_chain_residues(native_chain, alignment, invert=True) + alignments.append(alignment["matches"]) + info = calc_DockQ( model_chains, native_chains, - native_chains, #### + alignments=alignments, use_CA_only=use_CA_only, capri_peptide=capri_peptide, ) return info -@profile +#@profile def run_on_all_native_interfaces( model_structure, native_structure, @@ -923,6 +954,7 @@ def run_on_all_native_interfaces( ): model_chains_this = copy(model_chains) native_chains_this = copy(native_chains) + print(chain_pair) info = run_on_chains( model_chains_this, native_chains_this, @@ -1084,7 +1116,6 @@ def main(): for mapping in all_mappings[:5]: start = time.time() chain_map = {native_chain:mapping[i] for i, native_chain in enumerate(native_chains)} - print(chain_map) result_this_mapping = run_on_all_native_interfaces( model_structure, native_structure, @@ -1099,7 +1130,7 @@ def main(): best_dockq = total_dockq best_result = result_this_mapping stop = time.time() - print(stop-start) + print(f"Time (s): {stop-start}") info["model"] = args.model info["native"] = args.native From 4bdb20c51f32f3fbdb8796001fe5e912f0023cbb Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 4 Mar 2024 16:17:47 +0100 Subject: [PATCH 069/173] do not modify Bio.PDB objects, F1 --- src/DockQ/DockQ.py | 627 ++++++++------------------------------------- 1 file changed, 108 insertions(+), 519 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 504fe2a..e81c0fa 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -107,162 +107,26 @@ def parse_args(): return parser.parse_args() -def calc_DockQ( - sample_model, - ref_model, - ref_model_original, - group1, - group2, - nat_group1, - nat_group2, - use_CA_only=False, - capri_peptide=False, -): - atom_for_sup = ["CA", "C", "N", "O"] if not use_CA_only else ["CA"] - fnat_threshold = 4.0 if capri_peptide else 5.0 - interface_threshold = 8.0 if capri_peptide else 10.0 - - # total number of native contacts is calculated on untouched native structure - ref_res_distances = get_residue_distances( - ref_model_original, nat_group1, nat_group2 - ) - nat_total = np.nonzero(np.asarray(ref_res_distances) < fnat_threshold**2)[ - 0 - ].shape[0] +def get_aligned_residues(chainA, chainB, alignment): + aligned_resA = [] + aligned_resB = [] + resA = chainA.get_residues() + resB = chainB.get_residues() + + for A, match, B in zip(*alignment): + if A != "-": + rA = next(resA) + if B != "-": + rB = next(resB) + + if match == "|": + aligned_resA.append(rA) + aligned_resB.append(rB) + + return aligned_resA, aligned_resB - if nat_total == 0: - # if the native has no interface between the two chain groups - # nothing to do here - print(nat_group1, nat_group2) - return None - - sample_res_distances = get_residue_distances(sample_model, group1, group2) - ref_res_distances = get_residue_distances(ref_model, nat_group1, nat_group2) - - assert ( - sample_res_distances.shape == ref_res_distances.shape - ), f"Native and model have incompatible sizes ({sample_res_distances.shape} != {ref_res_distances.shape})" - - nat_correct, nonnat_count, _, model_total = get_fnat_stats( - sample_res_distances, ref_res_distances, threshold=fnat_threshold - ) - # avoids divide by 0 errors - fnat = nat_total and nat_correct / nat_total or 0 - fnonnat = model_total and nonnat_count / model_total or 0 - - if capri_peptide: - ref_res_distances = get_residue_distances( - ref_model, nat_group1, nat_group2, all_atom=False - ) - # Get interfacial atoms from reference, and corresponding atoms from sample - interacting_pairs = get_interacting_pairs( - # working with squared thresholds to avoid using sqrt in distance calculations - ref_res_distances, - threshold=interface_threshold**2, - ) - - # get a copy of each structure, then only keep backbone atoms - sample_model_backbone = sample_model - ref_model_backbone = ref_model - set_common_backbone_atoms( - sample_model_backbone, ref_model_backbone, atom_types=atom_for_sup - ) - - sample_interface_atoms, ref_interface_atoms = get_interface_atoms( - interacting_pairs, - sample_model_backbone, - ref_model_backbone, - group1, - group2, - nat_group1, - nat_group2, - ) - - super_imposer = Bio.PDB.Superimposer() - super_imposer.set_atoms(sample_interface_atoms, ref_interface_atoms) - - irms = super_imposer.rms - - # assign which group of chains constitutes the receptor, then the other is the ligand - ref_group1_size = np.sum([len(ref_model_original[chain]) for chain in nat_group1]) - ref_group2_size = np.sum([len(ref_model_original[chain]) for chain in nat_group2]) - receptor_chains = ( - (nat_group1, group1) - if ref_group1_size > ref_group2_size - else (nat_group2, group2) - ) - ligand_chains = ( - (nat_group1, group1) - if ref_group1_size <= ref_group2_size - else (nat_group2, group2) - ) - class1, class2 = ( - ("receptor", "ligand") - if ref_group1_size > ref_group2_size - else ("ligand", "receptor") - ) - receptor_atoms_native = [ - atom - for chain in receptor_chains[0] - for atom in ref_model_backbone[chain].get_atoms() - ] - receptor_atoms_sample = [ - atom - for chain in receptor_chains[1] - for atom in sample_model_backbone[chain].get_atoms() - ] - - # Set to align on receptor - super_imposer.set_atoms(receptor_atoms_native, receptor_atoms_sample) - super_imposer.apply(sample_model_backbone.get_atoms()) - - coord1 = np.array( - [ - atom.coord - for chain in ligand_chains[0] - for atom in ref_model_backbone[chain].get_atoms() - ] - ) - coord2 = np.array( - [ - atom.coord - for chain in ligand_chains[1] - for atom in sample_model_backbone[chain].get_atoms() - ] - ) - - sup = SVDSuperimposer() - Lrms = sup._rms( - coord1, coord2 - ) # using the private _rms function which does not superimpose - - DockQ = ( - float(fnat) - + 1 / (1 + (irms / 1.5) * (irms / 1.5)) - + 1 / (1 + (Lrms / 8.5) * (Lrms / 8.5)) - ) / 3 - info = {} - info["DockQ"] = DockQ - info["irms"] = irms - info["Lrms"] = Lrms - info["fnat"] = fnat - info["nat_correct"] = nat_correct - info["nat_total"] = nat_total - - info["fnonnat"] = fnonnat - info["nonnat_count"] = nonnat_count - info["model_total"] = model_total - - info["chain1"] = " ".join(group1) - info["chain2"] = " ".join(group2) - info["len1"] = ref_group1_size - info["len2"] = ref_group2_size - info["class1"] = class1 - info["class2"] = class2 - - return info - +@profile def calc_DockQ( sample_chains, ref_chains, @@ -285,20 +149,22 @@ def calc_DockQ( if nat_total == 0: # if the native has no interface between the two chain groups # nothing to do here - print(nat_group1, nat_group2) return None - sample_res_distances = get_residue_distances(sample_chains[0], sample_chains[1], alignments=alignments) - ref_res_distances = get_residue_distances(ref_chains[0], ref_chains[1], alignments=alignments) + aligned_sample_1, aligned_ref_1 = get_aligned_residues(sample_chains[0], ref_chains[0], alignments[0]) + aligned_sample_2, aligned_ref_2 = get_aligned_residues(sample_chains[1], ref_chains[1], alignments[1]) + + sample_res_distances = get_residue_distances(aligned_sample_1, aligned_sample_2) + ref_res_distances = get_residue_distances(aligned_ref_1, aligned_ref_2) assert ( sample_res_distances.shape == ref_res_distances.shape ), f"Native and model have incompatible sizes ({sample_res_distances.shape} != {ref_res_distances.shape})" - print(f"Native and model have compatible sizes ({sample_res_distances.shape} == {ref_res_distances.shape})") nat_correct, nonnat_count, _, model_total = get_fnat_stats( sample_res_distances, ref_res_distances, threshold=fnat_threshold ) + # avoids divide by 0 errors fnat = nat_total and nat_correct / nat_total or 0 fnonnat = model_total and nonnat_count / model_total or 0 @@ -315,19 +181,11 @@ def calc_DockQ( ) # get a copy of each structure, then only keep backbone atoms - sample_chains_backbone = sample_chains - ref_chains_backbone = ref_chains - set_common_backbone_atoms( - sample_chains_backbone[0], ref_chains_backbone[0], atom_types=atom_for_sup - ) - set_common_backbone_atoms( - sample_chains_backbone[1], ref_chains_backbone[1], atom_types=atom_for_sup - ) - sample_interface_atoms, ref_interface_atoms = get_interface_atoms( interacting_pairs, - sample_chains_backbone, - ref_chains_backbone, + [aligned_sample_1, aligned_sample_2], + [aligned_ref_1, aligned_ref_2], + atom_types=["CA", "C", "N", "O"], ) super_imposer = Bio.PDB.Superimposer() @@ -339,59 +197,40 @@ def calc_DockQ( ref_group1_size = len(ref_chains[0]) ref_group2_size = len(ref_chains[1]) receptor_chains = ( - (ref_chains[0], sample_chains[0]) + (aligned_ref_1, aligned_sample_1) if ref_group1_size > ref_group2_size - else (ref_chains[1], sample_chains[1]) + else (aligned_ref_2, aligned_sample_2) ) ligand_chains = ( - (ref_chains[1], sample_chains[1]) + (aligned_ref_2, aligned_sample_2) if ref_group1_size <= ref_group2_size - else (ref_chains[0], sample_chains[0]) + else (aligned_ref_1, aligned_sample_1) ) class1, class2 = ( ("receptor", "ligand") if ref_group1_size > ref_group2_size else ("ligand", "receptor") ) - receptor_atoms_native = [ - atom - for atom in receptor_chains[0].get_atoms() - ] - receptor_atoms_sample = [ - atom - for atom in receptor_chains[1].get_atoms() - ] - print(len(receptor_atoms_native), len(receptor_atoms_sample)) + receptor_atoms_native = get_atoms_per_residue(receptor_chains[0]) + receptor_atoms_sample = get_atoms_per_residue(receptor_chains[1]) + + ligand_atoms_native = np.asarray(get_atoms_per_residue(ligand_chains[0], coords=True)) + ligand_atoms_sample = np.asarray(get_atoms_per_residue(ligand_chains[1], coords=True)) + # Set to align on receptor super_imposer.set_atoms(receptor_atoms_native, receptor_atoms_sample) - super_imposer.apply([atom for backbone in sample_chains_backbone for atom in backbone.get_atoms()]) - - coord1 = np.array( - [ - atom.coord - for atom in ligand_chains[0].get_atoms() - ] - ) - coord2 = np.array( - [ - atom.coord - for atom in ligand_chains[1].get_atoms() - ] - ) + super_imposer.apply([atom for chain in sample_chains for atom in chain.get_atoms()]) sup = SVDSuperimposer() Lrms = sup._rms( - coord1, coord2 + ligand_atoms_native, ligand_atoms_sample ) # using the private _rms function which does not superimpose - DockQ = ( - float(fnat) - + 1 / (1 + (irms / 1.5) * (irms / 1.5)) - + 1 / (1 + (Lrms / 8.5) * (Lrms / 8.5)) - ) / 3 info = {} - info["DockQ"] = DockQ + + info["F1"] = f1_formula(nat_correct, nonnat_count, nat_total) + info["DockQ"] = dockq_formula(fnat, irms, Lrms) info["irms"] = irms info["Lrms"] = Lrms info["fnat"] = fnat @@ -402,8 +241,6 @@ def calc_DockQ( info["nonnat_count"] = nonnat_count info["model_total"] = model_total - info["chain1"] = "A" #" ".join(group1) - info["chain2"] = "B" #" ".join(group2) info["len1"] = ref_group1_size info["len2"] = ref_group2_size info["class1"] = class1 @@ -412,52 +249,20 @@ def calc_DockQ( return info -def align_model_to_native( - model_structure, native_structure, model_chain, native_chain, use_numbering=False -): - """ - Function to align two PDB structures. This can be done by sequence (default) or by - numbering. If the numbering is used, then each residue number from the pdb structure - is converted to a unique character. Then the two vectors of character are aligned - as if they were two sequences - """ - - if use_numbering: - model_numbering = [] - native_numbering = [] - - for residue in model_structure[model_chain].get_residues(): - resn = int(residue.id[1]) - model_numbering.append(resn) - - for residue in native_structure[native_chain].get_residues(): - resn = int(residue.id[1]) - native_numbering.append(resn) - # if the samllest resn is negative, it will be used to shift all numbers so they start from 0 - # the minimum offset is 45 to avoid including the "-" character that is reserved for gaps - min_resn = max(45, -min(model_numbering + native_numbering)) - - model_sequence = "".join([chr(resn + min_resn) for resn in model_numbering]) - native_sequence = "".join([chr(resn + min_resn) for resn in native_numbering]) - - else: - model_sequence = "".join( - seq1(residue.get_resname()) - for residue in model_structure[model_chain].get_residues() - ) +def f1(tp, fp, p): + precision = tp / tp + fp + recall = tp / p + return 2 * (precision * recall) / (precision + recall) - native_sequence = "".join( - seq1(residue.get_resname()) - for residue in native_structure[native_chain].get_residues() - ) - aligner = Align.PairwiseAligner() - aligner.match = 5 - aligner.mismatch = 0 - aligner.open_gap_score = -10 - aligner.extend_gap_score = -0.5 - aln = aligner.align(model_sequence, native_sequence)[0] - return aln +def dockq_formula(fnat, irms, Lrms): + # fnat is recall + # precision is num + dockq = ( + float(fnat) + + 1 / (1 + (irms / 1.5) * (irms / 1.5)) + + 1 / (1 + (Lrms / 8.5) * (Lrms / 8.5)) + ) / 3 def align_chains( @@ -553,21 +358,6 @@ def remove_h(model): for _, _, chain, res, atom in atoms_to_delete: model[chain][res].detach_child(atom[0]) -def fix_chain_residues(model, chain, alignment, invert=False): - residues = model[chain].get_residues() - residues_to_delete = [] - - seqA = alignment["seqA"] if not invert else alignment["seqB"] - seqB = alignment["seqB"] if not invert else alignment["seqA"] - for (aligned_residue_A, aligned_residue_B) in zip(seqA, seqB): - if aligned_residue_A != "-": - residue = next(residues) - if aligned_residue_B == "-": # gap residue: remove from structure - residues_to_delete.append(residue.get_full_id()) - - for _, _, _, res in residues_to_delete: - model[chain].detach_child(res) - def fix_chain_residues(chain, alignment, invert=False): residues = chain.get_residues() @@ -586,29 +376,18 @@ def fix_chain_residues(chain, alignment, invert=False): return chain -def list_atoms_per_residue(model, group): - n_atoms_per_residue = [] - for chain in group: - for residue in model[chain].get_residues(): - # important to remove duplicate atoms (e.g. alternates) at this stage, remove also hydrogens - atom_ids = set( - [a.id for a in residue.get_unpacked_list() if a.element != "H"] - ) - n_atoms_per_residue.append(len(atom_ids)) - return np.array(n_atoms_per_residue).astype(int) - #@lru_cache -def get_residue_distances(model, group1, group2, all_atom=True): +def get_residue_distances(chain1, chain2, alignments=[], all_atom=True): if all_atom: # get information about how many atoms correspond to each amino acid in each group of chains - n_atoms_per_res_group1 = list_atoms_per_residue(model, group1) - n_atoms_per_res_group2 = list_atoms_per_residue(model, group2) + n_atoms_per_res_chain1 = list_atoms_per_residue(chain1) + n_atoms_per_res_chain2 = list_atoms_per_residue(chain2) + model_A_atoms = np.asarray( [ atom.get_coord() - for chain in group1 - for res in model[chain].get_residues() + for i, res in enumerate(chain1) for atom in res.get_atoms() if atom.element != "H" ] @@ -616,8 +395,7 @@ def get_residue_distances(model, group1, group2, all_atom=True): model_B_atoms = np.asarray( [ atom.get_coord() - for chain in group2 - for res in model[chain].get_residues() + for i, res in enumerate(chain2) for atom in res.get_atoms() if atom.element != "H" ] @@ -627,82 +405,13 @@ def get_residue_distances(model, group1, group2, all_atom=True): model_A_atoms = np.asarray( [ res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() - for chain in group1 - for res in model[chain].get_residues() - ] - ) - model_B_atoms = np.asarray( - [ - res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() - for chain in group2 - for res in model[chain].get_residues() - ] - ) - - n_atoms_per_res_group1 = np.ones(model_A_atoms.shape[0]).astype(int) - n_atoms_per_res_group2 = np.ones(model_B_atoms.shape[0]).astype(int) - - model_res_distances = residue_distances( - model_A_atoms, model_B_atoms, n_atoms_per_res_group1, n_atoms_per_res_group2 - ) - return model_res_distances - - -#@lru_cache -def get_residue_distances(chain1, chain2, alignments=[], all_atom=True): - if all_atom: - # get information about how many atoms correspond to each amino acid in each group of chains - n_atoms_per_res_chain1 = list_atoms_per_residue(chain1, alignment=alignments[0] if alignments else "") - n_atoms_per_res_chain2 = list_atoms_per_residue(chain2, alignment=alignments[1] if alignments else "") - - if not alignments: - model_A_atoms = np.asarray( - [ - atom.get_coord() - for i, res in enumerate(chain1.get_residues()) - for atom in res.get_atoms() - if atom.element != "H" - ] - ) - model_B_atoms = np.asarray( - [ - atom.get_coord() - for i, res in enumerate(chain2.get_residues()) - for atom in res.get_atoms() - if atom.element != "H" - ] - ) - else: - model_A_atoms = [] - model_B_atoms = [] - res_chain1 = chain1.get_residues() - res_chain2 = chain2.get_residues() - for match in alignments[0]: - if match == "|": - res1 = next(res_chain1) - - model_A_atoms.extend([atom.get_coord() for atom in res1.get_atoms()]) - - for match in alignments[1]: - if match == "|": - res2 = next(res_chain2) - model_B_atoms.extend([atom.get_coord() for atom in res2.get_atoms()]) - model_A_atoms = np.asarray(model_A_atoms) - model_B_atoms = np.asarray(model_B_atoms) - - else: # distances were already between CBs only - model_A_atoms = np.asarray( - [ - res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() - for i, res in enumerate(chain1.get_residues()) - if (alignments[0][i] == "|" if alignments else True) + for i, res in enumerate(chain1) ] ) model_B_atoms = np.asarray( [ res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() - for i, res in enumerate(chain2.get_residues()) - if (alignments[1][i] == "|" if alignments else True) + for i, res in enumerate(chain2) ] ) @@ -715,111 +424,73 @@ def get_residue_distances(chain1, chain2, alignments=[], all_atom=True): return model_res_distances -def list_atoms_per_residue(chain, alignment=""): +def list_atoms_per_residue(chain): n_atoms_per_residue = [] - residues = chain.get_residues() + residues = [r for r in chain] - if alignment: - for match in alignment: - if match == "|": - residue = next(residues) - atom_ids = set( - [a.id for a in residue.get_unpacked_list()] - ) - n_atoms_per_residue.append(len(atom_ids)) - else: - for residue in residues: - # important to remove duplicate atoms (e.g. alternates) at this stage, remove also hydrogens - atom_ids = set( - [a.id for a in residue.get_unpacked_list()] - ) - n_atoms_per_residue.append(len(atom_ids)) + for residue in residues: + # important to remove duplicate atoms (e.g. alternates) at this stage, remove also hydrogens + atom_ids = set( + [a.id for a in residue.get_unpacked_list()] + ) + n_atoms_per_residue.append(len(atom_ids)) return np.array(n_atoms_per_residue).astype(int) -def get_interacting_pairs(distances, threshold): - return np.nonzero(np.asarray(distances) < threshold) - - -# @profile -def get_interface_atoms( - interacting_pairs, - model_backbone, - ref_backbone, - model_group1, - model_group2, - ref_group1, - ref_group2, -): - ref_interface = [] - mod_interface = [] - - ref_residues_group1 = [ - res for chain in ref_group1 for res in ref_backbone[chain].get_residues() - ] - ref_residues_group2 = [ - res for chain in ref_group2 for res in ref_backbone[chain].get_residues() - ] - - mod_residues_group1 = [ - res for chain in model_group1 for res in model_backbone[chain].get_residues() - ] - mod_residues_group2 = [ - res for chain in model_group2 for res in model_backbone[chain].get_residues() - ] - - # remove duplicate residues - interface_residues_group1 = set(interacting_pairs[0]) - interface_residues_group2 = set(interacting_pairs[1]) +def get_atoms_per_residue(chain, coords=False, atom_types=["CA", "C", "N", "O"],): + residues = chain + atoms = [] - for i in interface_residues_group1: - ref_interface += [atom for atom in ref_residues_group1[i].get_atoms()] - mod_interface += [atom for atom in mod_residues_group1[i].get_atoms()] + for residue in residues: + atoms.extend([atom.coord if coords else atom for atom in residue.get_atoms() if atom.id in atom_types]) + return atoms - for j in interface_residues_group2: - ref_interface += [atom for atom in ref_residues_group2[j].get_atoms()] - mod_interface += [atom for atom in mod_residues_group2[j].get_atoms()] - return mod_interface, ref_interface +def get_interacting_pairs(distances, threshold): + return np.nonzero(np.asarray(distances) < threshold) def get_interface_atoms( interacting_pairs, model_chains, ref_chains, + atom_types=[], ): ref_interface = [] mod_interface = [] ref_residues_group1 = [ - #res for chain in ref_group1 for res in ref_backbone[chain].get_residues() - res for res in ref_chains[0].get_residues() + res for res in ref_chains[0] ] ref_residues_group2 = [ - #res for chain in ref_group2 for res in ref_backbone[chain].get_residues() - res for res in ref_chains[1].get_residues() + res for res in ref_chains[1] ] mod_residues_group1 = [ - #res for chain in model_group1 for res in model_backbone[chain].get_residues() - res for res in model_chains[0].get_residues() + res for res in model_chains[0] ] mod_residues_group2 = [ - #res for chain in model_group2 for res in model_backbone[chain].get_residues() - res for res in model_chains[1].get_residues() + res for res in model_chains[1] ] - # remove duplicate residues interface_residues_group1 = set(interacting_pairs[0]) interface_residues_group2 = set(interacting_pairs[1]) for i in interface_residues_group1: - ref_interface += [atom for atom in ref_residues_group1[i].get_atoms()] - mod_interface += [atom for atom in mod_residues_group1[i].get_atoms()] + ref_atoms = [atom for atom in ref_residues_group1[i].get_atoms()] + mod_atoms = [atom for atom in mod_residues_group1[i].get_atoms()] + ref_atoms_ids = [atom.id for atom in ref_atoms] + mod_atoms_ids = [atom.id for atom in mod_atoms] + ref_interface += [atom for atom in ref_atoms if atom.id in atom_types and atom.id in mod_atoms_ids] + mod_interface += [atom for atom in mod_atoms if atom.id in atom_types and atom.id in ref_atoms_ids] for j in interface_residues_group2: - ref_interface += [atom for atom in ref_residues_group2[j].get_atoms()] - mod_interface += [atom for atom in mod_residues_group2[j].get_atoms()] + ref_atoms = [atom for atom in ref_residues_group2[j].get_atoms()] + mod_atoms = [atom for atom in mod_residues_group2[j].get_atoms()] + ref_atoms_ids = [atom.id for atom in ref_atoms] + mod_atoms_ids = [atom.id for atom in mod_atoms] + ref_interface += [atom for atom in ref_atoms if atom.id in atom_types and atom.id in mod_atoms_ids] + mod_interface += [atom for atom in mod_atoms if atom.id in atom_types and atom.id in ref_atoms_ids] return mod_interface, ref_interface @@ -845,53 +516,13 @@ def set_common_backbone_atoms(model, reference, atom_types=["CA", "C", "N", "O"] for atom_id in set(atom_ids_in_ref_res).difference(atom_ids_in_ref_and_mod_res): ref_res.detach_child(atom_id) -#@lru_cache + def copy(structure): return pickle.loads(pickle.dumps(structure, protocol=4)) @lru_cache -def run_on_groups( - model_structure, - native_structure, - native_structure_original, - group1, - group2, - nat_group1, - nat_group2, - no_needle=False, - use_CA_only=False, - capri_peptide=False, -): - remove_extra_chains(model_structure, chains_to_keep=group1 + group2) - remove_extra_chains(native_structure, chains_to_keep=nat_group1 + nat_group2) - - # realign each model chain against the corresponding native chain - for model_chain, native_chain in zip(group1 + group2, nat_group1 + nat_group2): - aln = align_model_to_native( - model_structure, - native_structure, - model_chain, - native_chain, - use_numbering=no_needle, - ) - alignment = format_alignment(aln) - fix_chain_residues(model_structure, model_chain, alignment) - fix_chain_residues(native_structure, native_chain, alignment, invert=True) - info = calc_DockQ( - model_structure, - native_structure, - native_structure_original, - group1, - group2, - nat_group1, - nat_group2, - use_CA_only=use_CA_only, - capri_peptide=capri_peptide, - ) - return info - -@lru_cache +@profile def run_on_chains( model_chains, native_chains, @@ -908,9 +539,7 @@ def run_on_chains( use_numbering=no_needle, ) alignment = format_alignment(aln) - #fix_chain_residues(model_chain, alignment) - #fix_chain_residues(native_chain, alignment, invert=True) - alignments.append(alignment["matches"]) + alignments.append(alignment.values()) info = calc_DockQ( model_chains, @@ -922,7 +551,6 @@ def run_on_chains( return info -#@profile def run_on_all_native_interfaces( model_structure, native_structure, @@ -939,62 +567,23 @@ def run_on_all_native_interfaces( native_chains = tuple([native_structure[chain] for chain in chain_pair]) model_chains = tuple([model_structure[chain] for chain in [chain_map[chain_pair[0]], chain_map[chain_pair[1]]]]) - # total number of native contacts is calculated on untouched native structure - ref_res_distances = get_residue_distances( - native_chains[0], native_chains[1] - ) - interface_size = np.nonzero(np.asarray(ref_res_distances) < 25.0)[ - 0 - ].shape[0] if ( - interface_size > 0 - and chain_pair[0] in chain_map + chain_pair[0] in chain_map and chain_pair[1] in chain_map ): - model_chains_this = copy(model_chains) - native_chains_this = copy(native_chains) - print(chain_pair) info = run_on_chains( - model_chains_this, - native_chains_this, + model_chains, + native_chains, ) - results_dic[chain_pair] = info + if info: + info["chain1"], info["chain2"] = model_chains + results_dic[chain_pair] = info return results_dic -def run_DockQ( - path_to_model, - path_to_native, - group1=["A"], - group2=["B"], - nat_group1=["A"], - nat_group2=["B"], - model_is_mmcif=False, - native_is_mmcif=False, - no_needle=False, - use_CA_only=False, - capri_peptide=False, -): - model = load_PDB(path_to_model, is_mmcif=model_is_mmcif) - native = load_PDB(path_to_native, is_mmcif=native_is_mmcif) - - return run_on_groups( - model, - native, - copy(native), - group1, - group2, - nat_group1, - nat_group2, - no_needle, - use_CA_only, - capri_peptide, - ) - - def load_PDB(path, n_model=0, is_mmcif=False): if not is_mmcif: @@ -1019,14 +608,14 @@ def group_model_chains(model_structure, native_structure, model_chains, native_c native_chain_clusters = {chain:[] for chain in native_chains} for model_chain, native_chain in alignment_targets: - aln = align_model_to_native(model_structure, native_structure, model_chain, native_chain) + aln = align_chains(model_structure[model_chain], native_structure[native_chain]) alignment = format_alignment(aln) if "." not in alignment["matches"] and ("-" not in alignment["seqA"] or "-" not in alignment["seqB"]): # 100% sequence identity, 100% coverage of native sequence in model sequence native_chain_clusters[native_chain].append(model_chain) return native_chain_clusters -#@profile + def main(): args = parse_args() @@ -1113,7 +702,7 @@ def main(): all_mappings = [element for element in all_mappings if len(set(element)) == len(element)] combo_dockq = -1 - for mapping in all_mappings[:5]: + for mapping in all_mappings: start = time.time() chain_map = {native_chain:mapping[i] for i, native_chain in enumerate(native_chains)} result_this_mapping = run_on_all_native_interfaces( @@ -1129,8 +718,8 @@ def main(): if total_dockq > best_dockq: best_dockq = total_dockq best_result = result_this_mapping + print(mapping, best_dockq) stop = time.time() - print(f"Time (s): {stop-start}") info["model"] = args.model info["native"] = args.native From 71df8303d7eb2d9d48567c3bc04fbee87226cc7b Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 4 Mar 2024 20:50:55 +0100 Subject: [PATCH 070/173] fix superposition --- src/DockQ/DockQ.py | 389 ++++++++++++++++++--------------------------- 1 file changed, 158 insertions(+), 231 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index e81c0fa..0da3aa2 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -1,12 +1,9 @@ #!/usr/bin/env python -import os import sys -import time -import pickle import traceback import itertools -from functools import lru_cache +from functools import lru_cache from argparse import ArgumentParser import Bio.PDB @@ -18,7 +15,7 @@ # fallback in case the cython version doesn't work, though it will be slower try: from .operations import residue_distances, get_fnat_stats -except: +except ImportError: print( "WARNING: It looks like cython is not working, falling back on native python. This will make DockQ slower" ) @@ -34,47 +31,41 @@ def parse_args(): "native", metavar="", type=str, help="path to native file" ) parser.add_argument( - "-capri_peptide", + "--capri_peptide", default=False, action="store_true", help="use version for capri_peptide (DockQ cannot not be trusted for this setting)", ) parser.add_argument( - "-short", default=False, action="store_true", help="short output" + "--short", default=False, action="store_true", help="short output" ) parser.add_argument( - "-verbose", default=False, action="store_true", help="talk a lot!" + "--verbose", "-v", default=False, action="store_true", help="talk a lot!" ) parser.add_argument( - "-quiet", default=False, action="store_true", help="keep quiet!" + "--use_CA", "-ca", default=False, action="store_true", help="use CA instead of backbone" ) parser.add_argument( - "-useCA", default=False, action="store_true", help="use CA instead of backbone" - ) - parser.add_argument( - "-mmcif_model", + "--mmcif_model", default=False, action="store_true", help="The model is in mmCIF format", ) parser.add_argument( - "-mmcif_native", + "--mmcif_native", default=False, action="store_true", help="The native is in mmCIF format", ) parser.add_argument( - "-no_needle", + "--no_needle", default=False, action="store_true", help="Do not align native and model using sequence alignments, but use the numbering of residues instead", ) parser.add_argument( - "-auto_map", - default=True, - action="store_true", - help="automatically calculate chain mapping between model and native to maximize total DockQ (sum DockQ for all native interfaces)", - ) + "--mapping", + help="Specify a chain mapping between model and native (e.g.: 'ABC:ACB' to switch last two chains in the native)") parser.add_argument( "-model_chain1", metavar="model_chain1", @@ -122,11 +113,11 @@ def get_aligned_residues(chainA, chainB, alignment): if match == "|": aligned_resA.append(rA) aligned_resB.append(rB) - + return aligned_resA, aligned_resB - -@profile + +# @profile def calc_DockQ( sample_chains, ref_chains, @@ -139,20 +130,22 @@ def calc_DockQ( interface_threshold = 8.0 if capri_peptide else 10.0 # total number of native contacts is calculated on untouched native structure - ref_res_distances = get_residue_distances( - ref_chains[0], ref_chains[1] - ) + ref_res_distances = get_residue_distances(ref_chains[0], ref_chains[1]) nat_total = np.nonzero(np.asarray(ref_res_distances) < fnat_threshold**2)[ 0 ].shape[0] - + if nat_total == 0: # if the native has no interface between the two chain groups # nothing to do here return None - aligned_sample_1, aligned_ref_1 = get_aligned_residues(sample_chains[0], ref_chains[0], alignments[0]) - aligned_sample_2, aligned_ref_2 = get_aligned_residues(sample_chains[1], ref_chains[1], alignments[1]) + aligned_sample_1, aligned_ref_1 = get_aligned_residues( + sample_chains[0], ref_chains[0], alignments[0] + ) + aligned_sample_2, aligned_ref_2 = get_aligned_residues( + sample_chains[1], ref_chains[1], alignments[1] + ) sample_res_distances = get_residue_distances(aligned_sample_1, aligned_sample_2) ref_res_distances = get_residue_distances(aligned_ref_1, aligned_ref_2) @@ -175,7 +168,7 @@ def calc_DockQ( ) # Get interfacial atoms from reference, and corresponding atoms from sample interacting_pairs = get_interacting_pairs( - # working with squared thresholds to avoid using sqrt in distance calculations + # working with squared thresholds to avoid using sqrt ref_res_distances, threshold=interface_threshold**2, ) @@ -185,15 +178,14 @@ def calc_DockQ( interacting_pairs, [aligned_sample_1, aligned_sample_2], [aligned_ref_1, aligned_ref_2], - atom_types=["CA", "C", "N", "O"], + atom_types=atom_for_sup, ) - super_imposer = Bio.PDB.Superimposer() super_imposer.set_atoms(sample_interface_atoms, ref_interface_atoms) irms = super_imposer.rms - # assign which group of chains constitutes the receptor, then the other is the ligand + # assign which chains constitute the receptor, ligand ref_group1_size = len(ref_chains[0]) ref_group2_size = len(ref_chains[1]) receptor_chains = ( @@ -212,19 +204,32 @@ def calc_DockQ( else ("ligand", "receptor") ) - receptor_atoms_native = get_atoms_per_residue(receptor_chains[0]) - receptor_atoms_sample = get_atoms_per_residue(receptor_chains[1]) - - ligand_atoms_native = np.asarray(get_atoms_per_residue(ligand_chains[0], coords=True)) - ligand_atoms_sample = np.asarray(get_atoms_per_residue(ligand_chains[1], coords=True)) + receptor_atoms_native = np.asarray( + get_atoms_per_residue(receptor_chains[0], coords=True, atom_types=atom_for_sup) + ) + receptor_atoms_sample = np.asarray( + get_atoms_per_residue(receptor_chains[1], coords=True, atom_types=atom_for_sup) + ) + ligand_atoms_native = np.asarray( + get_atoms_per_residue(ligand_chains[0], coords=True, atom_types=atom_for_sup) + ) + ligand_atoms_sample = np.asarray( + get_atoms_per_residue(ligand_chains[1], coords=True, atom_types=atom_for_sup) + ) # Set to align on receptor - super_imposer.set_atoms(receptor_atoms_native, receptor_atoms_sample) - super_imposer.apply([atom for chain in sample_chains for atom in chain.get_atoms()]) + # super_imposer.set_atoms(receptor_atoms_native, receptor_atoms_sample) + # super_imposer.apply([atom for chain in sample_chains for atom in chain.get_atoms()]) sup = SVDSuperimposer() + sup.set(receptor_atoms_native, receptor_atoms_sample) + sup.run() + + rot, tran = sup.get_rotran() + rotated_sample_atoms = np.dot(ligand_atoms_sample, rot) + tran + Lrms = sup._rms( - ligand_atoms_native, ligand_atoms_sample + ligand_atoms_native, rotated_sample_atoms ) # using the private _rms function which does not superimpose info = {} @@ -249,32 +254,26 @@ def calc_DockQ( return info -def f1(tp, fp, p): - precision = tp / tp + fp - recall = tp / p - return 2 * (precision * recall) / (precision + recall) +def f1_formula(tp, fp, p): + return 2 * tp / (tp + fp + p) def dockq_formula(fnat, irms, Lrms): - # fnat is recall - # precision is num - dockq = ( + return ( float(fnat) + 1 / (1 + (irms / 1.5) * (irms / 1.5)) + 1 / (1 + (Lrms / 8.5) * (Lrms / 8.5)) ) / 3 -def align_chains( - model_chain, native_chain, use_numbering=False -): +def align_chains(model_chain, native_chain, use_numbering=False): """ Function to align two PDB structures. This can be done by sequence (default) or by numbering. If the numbering is used, then each residue number from the pdb structure is converted to a unique character. Then the two vectors of character are aligned as if they were two sequences """ - + if use_numbering: model_numbering = [] native_numbering = [] @@ -295,13 +294,11 @@ def align_chains( else: model_sequence = "".join( - seq1(residue.get_resname()) - for residue in model_chain.get_residues() + seq1(residue.get_resname()) for residue in model_chain.get_residues() ) native_sequence = "".join( - seq1(residue.get_resname()) - for residue in native_chain.get_residues() + seq1(residue.get_resname()) for residue in native_chain.get_residues() ) aligner = Align.PairwiseAligner() @@ -322,14 +319,6 @@ def format_alignment(aln): return alignment -def remove_extra_chains(model, chains_to_keep): - chains = [chain.id for chain in model.get_chains()] - - chains_to_remove = set(chains).difference(set(chains_to_keep)) - for chain in chains_to_remove: - model.detach_child(chain) - - def remove_hetatms(model): chains = [chain.id for chain in model.get_chains()] residues_to_delete = [] @@ -359,31 +348,13 @@ def remove_h(model): model[chain][res].detach_child(atom[0]) -def fix_chain_residues(chain, alignment, invert=False): - residues = chain.get_residues() - residues_to_delete = [] - - seqA = alignment["seqA"] if not invert else alignment["seqB"] - seqB = alignment["seqB"] if not invert else alignment["seqA"] - for (aligned_residue_A, aligned_residue_B) in zip(seqA, seqB): - if aligned_residue_A != "-": - residue = next(residues) - if aligned_residue_B == "-": # gap residue: remove from structure - residues_to_delete.append(residue.get_full_id()) - - for _, _, _, res in residues_to_delete: - chain.detach_child(res) - return chain - - - -#@lru_cache +# @lru_cache def get_residue_distances(chain1, chain2, alignments=[], all_atom=True): if all_atom: - # get information about how many atoms correspond to each amino acid in each group of chains + # how many atoms per aligned amino acid n_atoms_per_res_chain1 = list_atoms_per_residue(chain1) n_atoms_per_res_chain2 = list_atoms_per_residue(chain2) - + model_A_atoms = np.asarray( [ atom.get_coord() @@ -427,22 +398,30 @@ def get_residue_distances(chain1, chain2, alignments=[], all_atom=True): def list_atoms_per_residue(chain): n_atoms_per_residue = [] residues = [r for r in chain] - + for residue in residues: - # important to remove duplicate atoms (e.g. alternates) at this stage, remove also hydrogens - atom_ids = set( - [a.id for a in residue.get_unpacked_list()] - ) + # important to remove duplicate atoms (e.g. alternates) at this stage + atom_ids = set([a.id for a in residue.get_unpacked_list()]) n_atoms_per_residue.append(len(atom_ids)) return np.array(n_atoms_per_residue).astype(int) -def get_atoms_per_residue(chain, coords=False, atom_types=["CA", "C", "N", "O"],): +def get_atoms_per_residue( + chain, + coords=False, + atom_types=["CA", "C", "N", "O"], +): residues = chain atoms = [] for residue in residues: - atoms.extend([atom.coord if coords else atom for atom in residue.get_atoms() if atom.id in atom_types]) + atoms.extend( + [ + atom.coord if coords else atom + for atom in residue.get_atoms() + if atom.id in atom_types + ] + ) return atoms @@ -459,19 +438,11 @@ def get_interface_atoms( ref_interface = [] mod_interface = [] - ref_residues_group1 = [ - res for res in ref_chains[0] - ] - ref_residues_group2 = [ - res for res in ref_chains[1] - ] + ref_residues_group1 = [res for res in ref_chains[0]] + ref_residues_group2 = [res for res in ref_chains[1]] - mod_residues_group1 = [ - res for res in model_chains[0] - ] - mod_residues_group2 = [ - res for res in model_chains[1] - ] + mod_residues_group1 = [res for res in model_chains[0]] + mod_residues_group2 = [res for res in model_chains[1]] # remove duplicate residues interface_residues_group1 = set(interacting_pairs[0]) interface_residues_group2 = set(interacting_pairs[1]) @@ -481,48 +452,38 @@ def get_interface_atoms( mod_atoms = [atom for atom in mod_residues_group1[i].get_atoms()] ref_atoms_ids = [atom.id for atom in ref_atoms] mod_atoms_ids = [atom.id for atom in mod_atoms] - ref_interface += [atom for atom in ref_atoms if atom.id in atom_types and atom.id in mod_atoms_ids] - mod_interface += [atom for atom in mod_atoms if atom.id in atom_types and atom.id in ref_atoms_ids] + ref_interface += [ + atom + for atom in ref_atoms + if atom.id in atom_types and atom.id in mod_atoms_ids + ] + mod_interface += [ + atom + for atom in mod_atoms + if atom.id in atom_types and atom.id in ref_atoms_ids + ] for j in interface_residues_group2: ref_atoms = [atom for atom in ref_residues_group2[j].get_atoms()] mod_atoms = [atom for atom in mod_residues_group2[j].get_atoms()] ref_atoms_ids = [atom.id for atom in ref_atoms] mod_atoms_ids = [atom.id for atom in mod_atoms] - ref_interface += [atom for atom in ref_atoms if atom.id in atom_types and atom.id in mod_atoms_ids] - mod_interface += [atom for atom in mod_atoms if atom.id in atom_types and atom.id in ref_atoms_ids] + ref_interface += [ + atom + for atom in ref_atoms + if atom.id in atom_types and atom.id in mod_atoms_ids + ] + mod_interface += [ + atom + for atom in mod_atoms + if atom.id in atom_types and atom.id in ref_atoms_ids + ] return mod_interface, ref_interface -def set_common_backbone_atoms(model, reference, atom_types=["CA", "C", "N", "O"]): - # model and reference should have the same number of amino acids and be aligned - for mod_res, ref_res in zip(model.get_residues(), reference.get_residues()): - mod_atoms = [atom for atom in mod_res.get_atoms()] - ref_atoms = [atom for atom in ref_res.get_atoms()] - - atom_ids_in_mod_res = [atm.id for atm in mod_atoms] - atom_ids_in_ref_res = [atm.id for atm in ref_atoms] - - atom_ids_in_ref_and_mod_res = ( - set(atom_ids_in_mod_res) - .intersection(atom_types) - .intersection(atom_ids_in_ref_res) - ) - # whatever atom is not in the shared list, remove it from the both structures - for atom_id in set(atom_ids_in_mod_res).difference(atom_ids_in_ref_and_mod_res): - mod_res.detach_child(atom_id) - - for atom_id in set(atom_ids_in_ref_res).difference(atom_ids_in_ref_and_mod_res): - ref_res.detach_child(atom_id) - - -def copy(structure): - return pickle.loads(pickle.dumps(structure, protocol=4)) - - @lru_cache -@profile +# @profile def run_on_chains( model_chains, native_chains, @@ -561,22 +522,25 @@ def run_on_all_native_interfaces( ): """Given a native-model chain map, finds all non-null native interfaces and runs DockQ for each native-model pair of interfaces""" results_dic = {} - native_chain_ids = [c.id for c in native_structure] + native_chain_ids = list(chain_map.keys()) for chain_pair in itertools.combinations(native_chain_ids, 2): - native_chains = tuple([native_structure[chain] for chain in chain_pair]) - model_chains = tuple([model_structure[chain] for chain in [chain_map[chain_pair[0]], chain_map[chain_pair[1]]]]) + model_chains = tuple( + [ + model_structure[chain] + for chain in [chain_map[chain_pair[0]], chain_map[chain_pair[1]]] + ] + ) - if ( - chain_pair[0] in chain_map - and chain_pair[1] in chain_map - ): + if chain_pair[0] in chain_map and chain_pair[1] in chain_map: info = run_on_chains( model_chains, native_chains, + no_needle=no_needle, + use_CA_only=use_CA_only, + capri_peptide=capri_peptide, ) - if info: info["chain1"], info["chain2"] = model_chains results_dic[chain_pair] = info @@ -585,7 +549,6 @@ def run_on_all_native_interfaces( def load_PDB(path, n_model=0, is_mmcif=False): - if not is_mmcif: pdb_parser = Bio.PDB.PDBParser(QUIET=True) else: @@ -600,17 +563,21 @@ def load_PDB(path, n_model=0, is_mmcif=False): print(" (use -mmcif_model or -mmcif_native with mmCIF inputs)") print(traceback.format_exc()) sys.exit(1) + remove_hetatms(model) + remove_h(model) return model def group_model_chains(model_structure, native_structure, model_chains, native_chains): alignment_targets = itertools.product(model_chains, native_chains) - native_chain_clusters = {chain:[] for chain in native_chains} + native_chain_clusters = {chain: [] for chain in native_chains} for model_chain, native_chain in alignment_targets: aln = align_chains(model_structure[model_chain], native_structure[native_chain]) alignment = format_alignment(aln) - if "." not in alignment["matches"] and ("-" not in alignment["seqA"] or "-" not in alignment["seqB"]): + if "." not in alignment["matches"] and ( + "-" not in alignment["seqA"] or "-" not in alignment["seqB"] + ): # 100% sequence identity, 100% coverage of native sequence in model sequence native_chain_clusters[native_chain].append(model_chain) return native_chain_clusters @@ -627,104 +594,64 @@ def main(): native_structure = load_PDB(args.native, is_mmcif=args.mmcif_native) model_structure = load_PDB(args.model, is_mmcif=args.mmcif_model) - remove_hetatms(native_structure) - remove_hetatms(model_structure) - remove_h(model_structure) - remove_h(native_structure) - best_info = "" info = {} model_chains = [c.id for c in model_structure] native_chains = [c.id for c in native_structure] + if args.mapping: + model_mapping, native_mapping = args.mapping.split(":") + if model_mapping: + if "*" not in model_mapping: + model_chains = [chain for chain in model_mapping] + if native_mapping: + if "*" not in native_mapping: + native_chains = [chain for chain in native_mapping] + if len(model_chains) < 2 or len(native_chains) < 2: print("Need at least two chains in the two inputs\n") sys.exit() - if not args.auto_map: - # Some of these might be None - group1 = [model_chains[0]] if len(model_chains) == 2 else args.model_chain1 - group2 = args.model_chain2 - nat_group1 = args.native_chain1 - nat_group2 = args.native_chain2 - - # at this stage either group1 or nat_group1 are not None - if not nat_group1: # then the user has set group1. Try to follow the same mapping - if ( - model_chains == native_chains - ): # easier case: the chains have the same naming between native/model, so just copy them - nat_group1 = group1 - # use complement to nat_group1 if group2 hasn't been decided yet - nat_group2 = group2 - else: # otherwise, group the chains by however many where in either model group - nat_group1 = native_chains[: len(group1)] - nat_group2 = ( - native_chains[len(group1) : len(group1) + len(group2)] - if group2 - else None - ) - - if not group1: # viceversa, the user has set nat_group1 - if model_chains == native_chains: - group1 = nat_group1 - group2 = nat_group2 - else: - group1 = model_chains[: len(nat_group1)] - group2 = ( - model_chains[len(nat_group1) : len(nat_group1) + len(nat_group2)] - if nat_group2 - else None - ) - - if not group2: # no group2 set yet, use the complement to group1 - group2 = [chain for chain in model_chains if chain not in group1] - if not nat_group2: - nat_group2 = [chain for chain in native_chains if chain not in nat_group1] - - info = run_on_groups( + # permute chains and run on a for loop + best_dockq = -1 + best_result = None + + native_chain_clusters = group_model_chains( + model_structure, native_structure, model_chains, native_chains + ) + + all_mappings = itertools.product(*[cluster for cluster in native_chain_clusters.values() if cluster]) + # remove mappings where the same model chain is present more than once + all_mappings = [ + element for element in all_mappings if len(set(element)) == len(element) + ] + + for mapping in all_mappings: + chain_map = { + native_chain: mapping[i] for i, native_chain in enumerate(native_chains) + } + + result_this_mapping = run_on_all_native_interfaces( model_structure, native_structure, - group1, - group2, - nat_group1, - nat_group2, - args.no_needle, - args.useCA, - args.capri_peptide, + chain_map=chain_map, + no_needle=args.no_needle, + use_CA_only=args.use_CA, + capri_peptide=args.capri_peptide, ) - else: # permute chains and run on a for loop - best_dockq = -1 - best_result = None - - native_chain_clusters = group_model_chains(model_structure, native_structure, model_chains, native_chains) - all_mappings = itertools.product(*native_chain_clusters.values()) - # remove mappings where the same model chain is present more than once - all_mappings = [element for element in all_mappings if len(set(element)) == len(element)] - combo_dockq = -1 - - for mapping in all_mappings: - start = time.time() - chain_map = {native_chain:mapping[i] for i, native_chain in enumerate(native_chains)} - result_this_mapping = run_on_all_native_interfaces( - model_structure, - native_structure, - chain_map=chain_map, - no_needle=args.no_needle, - use_CA_only=args.useCA, - capri_peptide=args.capri_peptide, - ) - total_dockq = sum([result["DockQ"] for result in result_this_mapping.values()]) - if total_dockq > best_dockq: - best_dockq = total_dockq - best_result = result_this_mapping - print(mapping, best_dockq) - stop = time.time() - - info["model"] = args.model - info["native"] = args.native - info["best_dockq"] = best_dockq - info["best_result"] = best_result + total_dockq = sum( + [result["DockQ"] for result in result_this_mapping.values()] + ) + if total_dockq > best_dockq: + best_dockq = total_dockq + best_result = result_this_mapping + print(mapping, best_dockq) + + info["model"] = args.model + info["native"] = args.native + info["best_dockq"] = best_dockq + info["best_result"] = best_result print_results(info, args.short, args.capri_peptide) From 239a22e4c1279b545c6ba0bcad0fd66ff57b988b Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 4 Mar 2024 22:53:13 +0100 Subject: [PATCH 071/173] optimizations --- src/DockQ/DockQ.py | 85 +++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 0da3aa2..03b4da9 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -98,6 +98,7 @@ def parse_args(): return parser.parse_args() +@lru_cache def get_aligned_residues(chainA, chainB, alignment): aligned_resA = [] aligned_resB = [] @@ -114,10 +115,10 @@ def get_aligned_residues(chainA, chainB, alignment): aligned_resA.append(rA) aligned_resB.append(rB) - return aligned_resA, aligned_resB + return tuple(aligned_resA), tuple(aligned_resB) -# @profile +#@profile def calc_DockQ( sample_chains, ref_chains, @@ -125,12 +126,12 @@ def calc_DockQ( use_CA_only=False, capri_peptide=False, ): - atom_for_sup = ["CA", "C", "N", "O"] if not use_CA_only else ["CA"] + atom_for_sup = ("CA", "C", "N", "O") if not use_CA_only else ("CA") fnat_threshold = 4.0 if capri_peptide else 5.0 interface_threshold = 8.0 if capri_peptide else 10.0 # total number of native contacts is calculated on untouched native structure - ref_res_distances = get_residue_distances(ref_chains[0], ref_chains[1]) + ref_res_distances = get_residue_distances(ref_chains[0], ref_chains[1], "ref") nat_total = np.nonzero(np.asarray(ref_res_distances) < fnat_threshold**2)[ 0 ].shape[0] @@ -147,8 +148,8 @@ def calc_DockQ( sample_chains[1], ref_chains[1], alignments[1] ) - sample_res_distances = get_residue_distances(aligned_sample_1, aligned_sample_2) - ref_res_distances = get_residue_distances(aligned_ref_1, aligned_ref_2) + sample_res_distances = get_residue_distances(aligned_sample_1, aligned_sample_2, "sample") + ref_res_distances = get_residue_distances(aligned_ref_1, aligned_ref_2, "ref") assert ( sample_res_distances.shape == ref_res_distances.shape @@ -176,8 +177,8 @@ def calc_DockQ( # get a copy of each structure, then only keep backbone atoms sample_interface_atoms, ref_interface_atoms = get_interface_atoms( interacting_pairs, - [aligned_sample_1, aligned_sample_2], - [aligned_ref_1, aligned_ref_2], + (aligned_sample_1, aligned_sample_2), + (aligned_ref_1, aligned_ref_2), atom_types=atom_for_sup, ) super_imposer = Bio.PDB.Superimposer() @@ -205,16 +206,16 @@ def calc_DockQ( ) receptor_atoms_native = np.asarray( - get_atoms_per_residue(receptor_chains[0], coords=True, atom_types=atom_for_sup) + get_atoms_per_residue(receptor_chains[0], what="ref", atom_types=atom_for_sup) ) receptor_atoms_sample = np.asarray( - get_atoms_per_residue(receptor_chains[1], coords=True, atom_types=atom_for_sup) + get_atoms_per_residue(receptor_chains[1], what="sample", atom_types=atom_for_sup) ) ligand_atoms_native = np.asarray( - get_atoms_per_residue(ligand_chains[0], coords=True, atom_types=atom_for_sup) + get_atoms_per_residue(ligand_chains[0], what="ref", atom_types=atom_for_sup) ) ligand_atoms_sample = np.asarray( - get_atoms_per_residue(ligand_chains[1], coords=True, atom_types=atom_for_sup) + get_atoms_per_residue(ligand_chains[1], what="sample", atom_types=atom_for_sup) ) # Set to align on receptor @@ -265,7 +266,7 @@ def dockq_formula(fnat, irms, Lrms): + 1 / (1 + (Lrms / 8.5) * (Lrms / 8.5)) ) / 3 - +@lru_cache def align_chains(model_chain, native_chain, use_numbering=False): """ Function to align two PDB structures. This can be done by sequence (default) or by @@ -348,13 +349,12 @@ def remove_h(model): model[chain][res].detach_child(atom[0]) -# @lru_cache -def get_residue_distances(chain1, chain2, alignments=[], all_atom=True): +@lru_cache +def get_residue_distances(chain1, chain2, what, all_atom=True): if all_atom: # how many atoms per aligned amino acid - n_atoms_per_res_chain1 = list_atoms_per_residue(chain1) - n_atoms_per_res_chain2 = list_atoms_per_residue(chain2) - + n_atoms_per_res_chain1 = list_atoms_per_residue(chain1, what) + n_atoms_per_res_chain2 = list_atoms_per_residue(chain2, what) model_A_atoms = np.asarray( [ atom.get_coord() @@ -395,7 +395,8 @@ def get_residue_distances(chain1, chain2, alignments=[], all_atom=True): return model_res_distances -def list_atoms_per_residue(chain): +@lru_cache +def list_atoms_per_residue(chain, what): n_atoms_per_residue = [] residues = [r for r in chain] @@ -406,10 +407,11 @@ def list_atoms_per_residue(chain): return np.array(n_atoms_per_residue).astype(int) +@lru_cache def get_atoms_per_residue( chain, - coords=False, - atom_types=["CA", "C", "N", "O"], + what, + atom_types=("CA", "C", "N", "O"), ): residues = chain atoms = [] @@ -417,7 +419,7 @@ def get_atoms_per_residue( for residue in residues: atoms.extend( [ - atom.coord if coords else atom + atom.coord for atom in residue.get_atoms() if atom.id in atom_types ] @@ -426,9 +428,11 @@ def get_atoms_per_residue( def get_interacting_pairs(distances, threshold): - return np.nonzero(np.asarray(distances) < threshold) + interacting_pairs = np.nonzero(np.asarray(distances) < threshold) + return tuple(interacting_pairs[0]), tuple(interacting_pairs[1]) +@lru_cache def get_interface_atoms( interacting_pairs, model_chains, @@ -586,12 +590,6 @@ def group_model_chains(model_structure, native_structure, model_chains, native_c def main(): args = parse_args() - bio_ver = 1.79 - if float(Bio.__version__) < bio_ver: - print( - f"WARNING: Biopython version {Bio.__version__} is older than the recommended version {bio_ver}" - ) - native_structure = load_PDB(args.native, is_mmcif=args.mmcif_native) model_structure = load_PDB(args.model, is_mmcif=args.mmcif_model) @@ -599,19 +597,28 @@ def main(): model_chains = [c.id for c in model_structure] native_chains = [c.id for c in native_structure] - if args.mapping: - model_mapping, native_mapping = args.mapping.split(":") - if model_mapping: - if "*" not in model_mapping: - model_chains = [chain for chain in model_mapping] - if native_mapping: - if "*" not in native_mapping: - native_chains = [chain for chain in native_mapping] - if len(model_chains) < 2 or len(native_chains) < 2: print("Need at least two chains in the two inputs\n") sys.exit() + initial_mapping = None + if args.mapping: + model_mapping, native_mapping = args.mapping.split(":") + if not native_mapping: + print("When using --mapping, native chains must be set (e.g. ABC:ABC or :ABC)") + sys.exit() + else: + # :ABC or *:ABC only use those natives chains, permute model chains + if not model_mapping or model_mapping == "*": + native_chains = [chain for chain in native_mapping] + elif len(model_mapping) == len(native_mapping): + # ABC*:ABC* fix the first part of the mapping, try all other combinations + initial_mapping = {nm:mm for nm, mm in zip(native_mapping, model_mapping) if nm != "*" and mm != "*"} + if model_mapping[-1] != "*" and native_mapping[-1] != "*": + # ABC:ABC use the specific mapping + model_chains = [chain for chain in model_mapping] + native_chains = [chain for chain in native_mapping] + # permute chains and run on a for loop best_dockq = -1 best_result = None @@ -630,6 +637,8 @@ def main(): chain_map = { native_chain: mapping[i] for i, native_chain in enumerate(native_chains) } + if initial_mapping and not initial_mapping.items() <= chain_map.items(): + continue result_this_mapping = run_on_all_native_interfaces( model_structure, From 365a2bc61d06d2b2c431aac83daaac00be8600c0 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 4 Mar 2024 23:02:14 +0100 Subject: [PATCH 072/173] fix version --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index 9a324ea..fb79fa1 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,6 @@ [metadata] name = DockQ +version = 2.0 [options] package_dir = From f343f391d2105f06971fe39bd06b424dcce997e4 Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 5 Mar 2024 00:17:56 +0100 Subject: [PATCH 073/173] fix bug --- src/DockQ/DockQ.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 03b4da9..1ad7fb8 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -195,9 +195,9 @@ def calc_DockQ( else (aligned_ref_2, aligned_sample_2) ) ligand_chains = ( - (aligned_ref_2, aligned_sample_2) + (aligned_ref_1, aligned_sample_1) if ref_group1_size <= ref_group2_size - else (aligned_ref_1, aligned_sample_1) + else (aligned_ref_2, aligned_sample_2) ) class1, class2 = ( ("receptor", "ligand") @@ -206,16 +206,16 @@ def calc_DockQ( ) receptor_atoms_native = np.asarray( - get_atoms_per_residue(receptor_chains[0], what="ref", atom_types=atom_for_sup) + get_atoms_per_residue(receptor_chains[0], what="refr", atom_types=atom_for_sup) ) receptor_atoms_sample = np.asarray( - get_atoms_per_residue(receptor_chains[1], what="sample", atom_types=atom_for_sup) + get_atoms_per_residue(receptor_chains[1], what="sampler", atom_types=atom_for_sup) ) ligand_atoms_native = np.asarray( - get_atoms_per_residue(ligand_chains[0], what="ref", atom_types=atom_for_sup) + get_atoms_per_residue(ligand_chains[0], what="refl", atom_types=atom_for_sup) ) ligand_atoms_sample = np.asarray( - get_atoms_per_residue(ligand_chains[1], what="sample", atom_types=atom_for_sup) + get_atoms_per_residue(ligand_chains[1], what="samplel", atom_types=atom_for_sup) ) # Set to align on receptor @@ -235,7 +235,7 @@ def calc_DockQ( info = {} - info["F1"] = f1_formula(nat_correct, nonnat_count, nat_total) + info["DockQ_F1"] = f1_formula(nat_correct, nonnat_count, nat_total) info["DockQ"] = dockq_formula(fnat, irms, Lrms) info["irms"] = irms info["Lrms"] = Lrms @@ -546,7 +546,7 @@ def run_on_all_native_interfaces( capri_peptide=capri_peptide, ) if info: - info["chain1"], info["chain2"] = model_chains + info["chain1"], info["chain2"] = chain_map[chain_pair[0]], chain_map[chain_pair[1]] results_dic[chain_pair] = info return results_dic @@ -705,9 +705,14 @@ def print_results(info, short=False, capri_peptide=False): print("****************************************************************") print(f"Model : {info['model']}") print(f"Native : {info['native']}") + items = ["DockQ_F1", "DockQ", "irms", "Lrms", "fnat"] if "best_dockq" in info: - print(info["best_result"]) - print(info["best_dockq"]) + for chains, results in info["best_result"].items(): + print(f"Native chains: {chains[0]}, {chains[1]}") + print(f"\tModel chains: {results['chain1']} {results['chain2']}") + print("\n".join([f"\t{item}: {results[item]:.3f}" for item in items])) + #print(info["best_result"]) + #print(info["best_dockq"]) else: print( f"Number of equivalent residues in chain {info['chain1']} {info['len1']} ({info['class1']})" From 62f580f1b660c0c06568af237350d42e3ee3868f Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 5 Mar 2024 09:17:14 +0100 Subject: [PATCH 074/173] dockq F1 --- src/DockQ/DockQ.py | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 1ad7fb8..53ac375 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -206,22 +206,19 @@ def calc_DockQ( ) receptor_atoms_native = np.asarray( - get_atoms_per_residue(receptor_chains[0], what="refr", atom_types=atom_for_sup) + get_atoms_per_residue(receptor_chains[0], what="ref", atom_types=atom_for_sup) ) receptor_atoms_sample = np.asarray( - get_atoms_per_residue(receptor_chains[1], what="sampler", atom_types=atom_for_sup) + get_atoms_per_residue(receptor_chains[1], what="sample", atom_types=atom_for_sup) ) ligand_atoms_native = np.asarray( - get_atoms_per_residue(ligand_chains[0], what="refl", atom_types=atom_for_sup) + get_atoms_per_residue(ligand_chains[0], what="ref", atom_types=atom_for_sup) ) ligand_atoms_sample = np.asarray( - get_atoms_per_residue(ligand_chains[1], what="samplel", atom_types=atom_for_sup) + get_atoms_per_residue(ligand_chains[1], what="sample", atom_types=atom_for_sup) ) # Set to align on receptor - # super_imposer.set_atoms(receptor_atoms_native, receptor_atoms_sample) - # super_imposer.apply([atom for chain in sample_chains for atom in chain.get_atoms()]) - sup = SVDSuperimposer() sup.set(receptor_atoms_native, receptor_atoms_sample) sup.run() @@ -235,7 +232,7 @@ def calc_DockQ( info = {} - info["DockQ_F1"] = f1_formula(nat_correct, nonnat_count, nat_total) + info["DockQ_F1"] = dockq_formula(f1(nat_correct, nonnat_count, nat_total), irms, Lrms) info["DockQ"] = dockq_formula(fnat, irms, Lrms) info["irms"] = irms info["Lrms"] = Lrms @@ -255,7 +252,7 @@ def calc_DockQ( return info -def f1_formula(tp, fp, p): +def f1(tp, fp, p): return 2 * tp / (tp + fp + p) @@ -564,7 +561,7 @@ def load_PDB(path, n_model=0, is_mmcif=False): except Exception as e: print("ERROR: is the file in the correct format? (.pdb, .mmcif)") if not is_mmcif: - print(" (use -mmcif_model or -mmcif_native with mmCIF inputs)") + print("\t(use --mmcif_model or --mmcif_native with mmCIF inputs)") print(traceback.format_exc()) sys.exit(1) remove_hetatms(model) @@ -711,8 +708,6 @@ def print_results(info, short=False, capri_peptide=False): print(f"Native chains: {chains[0]}, {chains[1]}") print(f"\tModel chains: {results['chain1']} {results['chain2']}") print("\n".join([f"\t{item}: {results[item]:.3f}" for item in items])) - #print(info["best_result"]) - #print(info["best_dockq"]) else: print( f"Number of equivalent residues in chain {info['chain1']} {info['len1']} ({info['class1']})" From 31e51ec4ed17bf2f2aed499754a3f2eb928e4b24 Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 5 Mar 2024 09:45:51 +0100 Subject: [PATCH 075/173] pretty print --- src/DockQ/DockQ.py | 86 +++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 39 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 53ac375..09eccf4 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -165,7 +165,7 @@ def calc_DockQ( if capri_peptide: ref_res_distances = get_residue_distances( - ref_chains[0], ref_chains[1], all_atom=False + ref_chains[0], ref_chains[1], "ref", all_atom=False ) # Get interfacial atoms from reference, and corresponding atoms from sample interacting_pairs = get_interacting_pairs( @@ -659,10 +659,10 @@ def main(): info["best_dockq"] = best_dockq info["best_result"] = best_result - print_results(info, args.short, args.capri_peptide) + print_results(info, args.short, args.verbose, args.capri_peptide) -def print_results(info, short=False, capri_peptide=False): +def print_results(info, short=False, verbose=False, capri_peptide=False): if short: capri_peptide_str = "-capri_peptide" if capri_peptide else "" print( @@ -670,45 +670,16 @@ def print_results(info, short=False, capri_peptide=False): ) else: - if capri_peptide: - print("****************************************************************") - print("* DockQ-CAPRI peptide *") - print("* Do not trust any thing you read.... *") - print("* OBS THE DEFINITION OF Fnat and iRMS are different for *") - print("* peptides in CAPRI *") - print("* *") - print("* For the record: *") - print("* Definition of contact <4A all heavy atoms (Fnat) *") - print("* Definition of interface <8A CB (iRMS) *") - print("* For comments, please email: bjorn.wallner@.liu.se *") - print("****************************************************************") - else: - print("****************************************************************") - print("* DockQ *") - print("* Scoring function for protein-protein docking models *") - print("* Statistics on CAPRI data: *") - print("* 0.00 <= DockQ < 0.23 - Incorrect *") - print("* 0.23 <= DockQ < 0.49 - Acceptable quality *") - print("* 0.49 <= DockQ < 0.80 - Medium quality *") - print("* DockQ >= 0.80 - High quality *") - print("* Ref: S. Basu and B. Wallner, DockQ: A quality measure for *") - print("* protein-protein docking models *") - print("* doi:10.1371/journal.pone.0161879 *") - print("* For the record: *") - print("* Definition of contact <5A (Fnat) *") - print("* Definition of interface <10A all heavy atoms (iRMS) *") - print("* For comments, please email: bjorn.wallner@.liu.se *") - print("* *") - print("****************************************************************") + print_header(verbose, capri_peptide) print(f"Model : {info['model']}") print(f"Native : {info['native']}") items = ["DockQ_F1", "DockQ", "irms", "Lrms", "fnat"] - if "best_dockq" in info: - for chains, results in info["best_result"].items(): - print(f"Native chains: {chains[0]}, {chains[1]}") - print(f"\tModel chains: {results['chain1']} {results['chain2']}") - print("\n".join([f"\t{item}: {results[item]:.3f}" for item in items])) - else: + + for chains, results in info["best_result"].items(): + print(f"Native chains: {chains[0]}, {chains[1]}") + print(f"\tModel chains: {results['chain1']} {results['chain2']}") + print("\n".join([f"\t{item}: {results[item]:.3f}" for item in items])) + """ print( f"Number of equivalent residues in chain {info['chain1']} {info['len1']} ({info['class1']})" ) @@ -730,7 +701,44 @@ def print_results(info, short=False, capri_peptide=False): else "" ) print(f"DockQ {info['DockQ']:.3f}{peptide_disclaimer}") + """ + + +def print_header(verbose=False, capri_peptide=False): + if not capri_peptide: + header = """**************************************************************** +* DockQ * +* Scoring function for protein-protein docking models * +* Statistics on CAPRI data: * +* 0.00 <= DockQ < 0.23 - Incorrect * +* 0.23 <= DockQ < 0.49 - Acceptable quality * +* 0.49 <= DockQ < 0.80 - Medium quality * +* DockQ >= 0.80 - High quality * +* Ref: S. Basu and B. Wallner, DockQ: A quality measure for * +* protein-protein docking models * +* doi:10.1371/journal.pone.0161879 * +* For comments, please email: bjorn.wallner@.liu.se *""" + else: + header = """**************************************************************** +* DockQ-CAPRI peptide * +* Do not trust any thing you read.... * +* OBS THE DEFINITION OF Fnat and iRMS are different for * +* peptides in CAPRI * +* * +* Ref: S. Basu and B. Wallner, DockQ: A quality measure for * +* protein-protein docking models * +* doi:10.1371/journal.pone.0161879 * +* For comments, please email: bjorn.wallner@.liu.se *""" + if verbose: + notice = f"""* For the record: * +* Definition of contact <{"5A" if not capri_peptide else "4A"} (Fnat) * +* Definition of interface <{"10A all heavy atoms" if not capri_peptide else "8A CB "} (iRMS) * +****************************************************************""" + else: + notice = "****************************************************************" + print(header) + print(notice) if __name__ == "__main__": main() From 6853038f6e9a37795d3894428184234636337c4e Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 5 Mar 2024 10:01:27 +0100 Subject: [PATCH 076/173] pretty print --- src/DockQ/DockQ.py | 50 ++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 09eccf4..149da55 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -705,39 +705,37 @@ def print_results(info, short=False, verbose=False, capri_peptide=False): def print_header(verbose=False, capri_peptide=False): + reference = "* Ref: S. Basu and B. Wallner, DockQ: A quality measure for *\n" \ + "* protein-protein docking models *\n" \ + "* doi:10.1371/journal.pone.0161879 *\n" \ + "* For comments, please email: bjorn.wallner@.liu.se *" if not capri_peptide: - header = """**************************************************************** -* DockQ * -* Scoring function for protein-protein docking models * -* Statistics on CAPRI data: * -* 0.00 <= DockQ < 0.23 - Incorrect * -* 0.23 <= DockQ < 0.49 - Acceptable quality * -* 0.49 <= DockQ < 0.80 - Medium quality * -* DockQ >= 0.80 - High quality * -* Ref: S. Basu and B. Wallner, DockQ: A quality measure for * -* protein-protein docking models * -* doi:10.1371/journal.pone.0161879 * -* For comments, please email: bjorn.wallner@.liu.se *""" + header = "****************************************************************\n" \ + "* DockQ *\n" \ + "* Scoring function for protein-protein docking models *\n" \ + "* Statistics on CAPRI data: *\n" \ + "* 0.00 <= DockQ < 0.23 - Incorrect *\n" \ + "* 0.23 <= DockQ < 0.49 - Acceptable quality *\n" \ + "* 0.49 <= DockQ < 0.80 - Medium quality *\n" \ + "* DockQ >= 0.80 - High quality *" else: - header = """**************************************************************** -* DockQ-CAPRI peptide * -* Do not trust any thing you read.... * -* OBS THE DEFINITION OF Fnat and iRMS are different for * -* peptides in CAPRI * -* * -* Ref: S. Basu and B. Wallner, DockQ: A quality measure for * -* protein-protein docking models * -* doi:10.1371/journal.pone.0161879 * -* For comments, please email: bjorn.wallner@.liu.se *""" + header = "****************************************************************\n" \ + "* DockQ-CAPRI peptide *\n" \ + "* Do not trust any thing you read.... *\n" \ + "* OBS THE DEFINITION OF Fnat and iRMS are different for *\n" \ + "* peptides in CAPRI *\n" \ + "* *" + if verbose: - notice = f"""* For the record: * -* Definition of contact <{"5A" if not capri_peptide else "4A"} (Fnat) * -* Definition of interface <{"10A all heavy atoms" if not capri_peptide else "8A CB "} (iRMS) * -****************************************************************""" + notice = "* For the record: *\n" \ + f"* Definition of contact <{'5A' if not capri_peptide else '4A'} (Fnat) *\n" \ + f"* Definition of interface <{'10A all heavy atoms (iRMS) ' if not capri_peptide else '8A CB (iRMS) '} *\n" \ + "****************************************************************" else: notice = "****************************************************************" print(header) + print(reference) print(notice) if __name__ == "__main__": From b0470262f17ca813d4ca99ef94f69450188e1fda Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 5 Mar 2024 10:09:07 +0100 Subject: [PATCH 077/173] formatting --- setup.py | 3 +-- src/DockQ/DockQ.py | 8 +++++--- src/DockQ/__main__.py | 1 - src/DockQ/operations_nocy.py | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/setup.py b/setup.py index e84146c..2b083c7 100644 --- a/setup.py +++ b/setup.py @@ -5,11 +5,10 @@ extensions = [ Extension( "DockQ.operations", sources=["src/DockQ/operations.pyx"], - include_dirs = [numpy.get_include()], + include_dirs=[numpy.get_include()], ), ] setup( ext_modules=cythonize(extensions) ) - diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 149da55..08e681e 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -118,7 +118,7 @@ def get_aligned_residues(chainA, chainB, alignment): return tuple(aligned_resA), tuple(aligned_resB) -#@profile +# @profile def calc_DockQ( sample_chains, ref_chains, @@ -263,6 +263,7 @@ def dockq_formula(fnat, irms, Lrms): + 1 / (1 + (Lrms / 8.5) * (Lrms / 8.5)) ) / 3 + @lru_cache def align_chains(model_chain, native_chain, use_numbering=False): """ @@ -558,7 +559,7 @@ def load_PDB(path, n_model=0, is_mmcif=False): try: structure = pdb_parser.get_structure("-", path) model = structure[n_model] - except Exception as e: + except Exception: print("ERROR: is the file in the correct format? (.pdb, .mmcif)") if not is_mmcif: print("\t(use --mmcif_model or --mmcif_native with mmCIF inputs)") @@ -610,7 +611,7 @@ def main(): native_chains = [chain for chain in native_mapping] elif len(model_mapping) == len(native_mapping): # ABC*:ABC* fix the first part of the mapping, try all other combinations - initial_mapping = {nm:mm for nm, mm in zip(native_mapping, model_mapping) if nm != "*" and mm != "*"} + initial_mapping = {nm: mm for nm, mm in zip(native_mapping, model_mapping) if nm != "*" and mm != "*"} if model_mapping[-1] != "*" and native_mapping[-1] != "*": # ABC:ABC use the specific mapping model_chains = [chain for chain in model_mapping] @@ -738,5 +739,6 @@ def print_header(verbose=False, capri_peptide=False): print(reference) print(notice) + if __name__ == "__main__": main() diff --git a/src/DockQ/__main__.py b/src/DockQ/__main__.py index c37fe97..3077441 100644 --- a/src/DockQ/__main__.py +++ b/src/DockQ/__main__.py @@ -2,4 +2,3 @@ if __name__ == "__main__": main() - diff --git a/src/DockQ/operations_nocy.py b/src/DockQ/operations_nocy.py index 6edb480..d41566b 100644 --- a/src/DockQ/operations_nocy.py +++ b/src/DockQ/operations_nocy.py @@ -16,7 +16,7 @@ def atom_distances_to_residue_distances(atom_distances, atoms_per_res1, atoms_pe cum_j_atoms = 0 for j, j_atoms in enumerate(atoms_per_res2): res_distances[i, j] = atom_distances[ - cum_i_atoms : cum_i_atoms + i_atoms, cum_j_atoms : cum_j_atoms + j_atoms + cum_i_atoms:cum_i_atoms + i_atoms, cum_j_atoms:cum_j_atoms + j_atoms ].min() cum_j_atoms += j_atoms cum_i_atoms += i_atoms From eb57f465ebf36edc7636d71572aa9f2b74adffca Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 5 Mar 2024 12:54:19 +0100 Subject: [PATCH 078/173] fix short --- src/DockQ/DockQ.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 08e681e..d406d5c 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -653,7 +653,7 @@ def main(): if total_dockq > best_dockq: best_dockq = total_dockq best_result = result_this_mapping - print(mapping, best_dockq) + #print(mapping, best_dockq) info["model"] = args.model info["native"] = args.native @@ -666,9 +666,10 @@ def main(): def print_results(info, short=False, verbose=False, capri_peptide=False): if short: capri_peptide_str = "-capri_peptide" if capri_peptide else "" - print( - f"DockQ{capri_peptide_str} {info['DockQ']:.3f} Fnat {info['fnat']:.3f} iRMS {info['irms']:.3f} LRMS {info['Lrms']:.3f} Fnonnat {info['fnonnat']:.3f} {info['model']} {info['native']} {info['best']}" - ) + for chains, results in info["best_result"].items(): + print( + f"DockQ{capri_peptide_str} {results['DockQ']:.3f} Fnat {results['fnat']:.3f} iRMS {results['irms']:.3f} LRMS {results['Lrms']:.3f} Fnonnat {results['fnonnat']:.3f} {info['native']} {chains[0]} {chains[1]} -> {info['model']} {results['chain1']} {results['chain2']}" + ) else: print_header(verbose, capri_peptide) From 97597ed8a721c3954bb1925afc9c3fdc0d15db95 Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 5 Mar 2024 12:56:25 +0100 Subject: [PATCH 079/173] fix short --- src/DockQ/DockQ.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index d406d5c..dd49f60 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -668,7 +668,7 @@ def print_results(info, short=False, verbose=False, capri_peptide=False): capri_peptide_str = "-capri_peptide" if capri_peptide else "" for chains, results in info["best_result"].items(): print( - f"DockQ{capri_peptide_str} {results['DockQ']:.3f} Fnat {results['fnat']:.3f} iRMS {results['irms']:.3f} LRMS {results['Lrms']:.3f} Fnonnat {results['fnonnat']:.3f} {info['native']} {chains[0]} {chains[1]} -> {info['model']} {results['chain1']} {results['chain2']}" + f"DockQ{capri_peptide_str} {results['DockQ']:.3f} DockQ_F1 {results['DockQ_F1']:.3f} Fnat {results['fnat']:.3f} iRMS {results['irms']:.3f} LRMS {results['Lrms']:.3f} Fnonnat {results['fnonnat']:.3f} {info['native']} {chains[0]} {chains[1]} -> {info['model']} {results['chain1']} {results['chain2']}" ) else: From 11dbbd0c546662d1ccaca72f2eade45a90e88de5 Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 5 Mar 2024 18:37:16 +0100 Subject: [PATCH 080/173] special mapping cases --- src/DockQ/DockQ.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index dd49f60..4196147 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -511,9 +511,11 @@ def run_on_chains( use_CA_only=use_CA_only, capri_peptide=capri_peptide, ) + #print(info) return info +# @lru_cache def run_on_all_native_interfaces( model_structure, native_structure, @@ -534,7 +536,8 @@ def run_on_all_native_interfaces( for chain in [chain_map[chain_pair[0]], chain_map[chain_pair[1]]] ] ) - + if len(set(model_chains)) < 2: + continue if chain_pair[0] in chain_map and chain_pair[1] in chain_map: info = run_on_chains( model_chains, @@ -626,15 +629,19 @@ def main(): ) all_mappings = itertools.product(*[cluster for cluster in native_chain_clusters.values() if cluster]) + # remove mappings where the same model chain is present more than once - all_mappings = [ - element for element in all_mappings if len(set(element)) == len(element) - ] + # only if the mapping is supposed to be 1-1 + if len(model_chains) == len(native_chains): + all_mappings = [ + element for element in all_mappings if len(set(element)) == len(element) + ] for mapping in all_mappings: chain_map = { native_chain: mapping[i] for i, native_chain in enumerate(native_chains) } + if initial_mapping and not initial_mapping.items() <= chain_map.items(): continue From 5e21818c1e1c3e7df1337cd19b95f82a18e1f9b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wallner?= Date: Wed, 6 Mar 2024 10:19:34 +0100 Subject: [PATCH 081/173] fix to handle both old (<=1.79) and new alignment object --- src/DockQ/DockQ.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 4196147..fbfb02e 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -308,16 +308,31 @@ def align_chains(model_chain, native_chain, use_numbering=False): aln = aligner.align(model_sequence, native_sequence)[0] return aln - def format_alignment(aln): alignment = {} - formatted_aln = aln.format().split("\n") - alignment["seqA"] = formatted_aln[0] - alignment["matches"] = formatted_aln[1] - alignment["seqB"] = formatted_aln[2] + if 'target' in str(aln): + formatted_aln=aln.format('fasta').split('\n') + matches=[] + for a,b in zip(formatted_aln[1],formatted_aln[3]): + if a==b: + matches.append('|') + elif a=='-' or b=='-': + matches.append('-') + else: + matches.append('.') + #The order in the dict matters, since only the .values are used in alignments argument in calc_DockQ + alignment["seqA"] = formatted_aln[1] + alignment["matches"] = "".join(matches) + alignment["seqB"] = formatted_aln[3] + else: + formatted_aln = aln.format().split("\n") + alignment["seqA"] = formatted_aln[0] + alignment["matches"] = formatted_aln[1] + alignment["seqB"] = formatted_aln[2] return alignment + def remove_hetatms(model): chains = [chain.id for chain in model.get_chains()] residues_to_delete = [] From 27304a0e4d8e4108636bb98504f058b9abac4204 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 6 Mar 2024 15:45:54 +0100 Subject: [PATCH 082/173] update biopython version --- pyproject.toml | 2 +- setup.cfg | 6 ++++-- src/DockQ/DockQ.py | 51 ++++++---------------------------------------- 3 files changed, 11 insertions(+), 48 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index fa680af..455dc25 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [build-system] name = "DockQ" version = "2.0" -requires = ["setuptools", "cython", "numpy ~= 1.21", "biopython == 1.79"] +requires = ["setuptools", "cython", "numpy ~= 1.21", "biopython >= 1.81"] build-backend = "setuptools.build_meta" diff --git a/setup.cfg b/setup.cfg index fb79fa1..a2935fc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -7,8 +7,10 @@ package_dir = =src packages = find: install_requires = - numpy - biopython>=1.78 + setuptools + cython + numpy~=1.21 + biopython>=1.81 [options.packages.find] where=src diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index fbfb02e..9ed7149 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -308,31 +308,17 @@ def align_chains(model_chain, native_chain, use_numbering=False): aln = aligner.align(model_sequence, native_sequence)[0] return aln + def format_alignment(aln): alignment = {} - if 'target' in str(aln): - formatted_aln=aln.format('fasta').split('\n') - matches=[] - for a,b in zip(formatted_aln[1],formatted_aln[3]): - if a==b: - matches.append('|') - elif a=='-' or b=='-': - matches.append('-') - else: - matches.append('.') - #The order in the dict matters, since only the .values are used in alignments argument in calc_DockQ - alignment["seqA"] = formatted_aln[1] - alignment["matches"] = "".join(matches) - alignment["seqB"] = formatted_aln[3] - else: - formatted_aln = aln.format().split("\n") - alignment["seqA"] = formatted_aln[0] - alignment["matches"] = formatted_aln[1] - alignment["seqB"] = formatted_aln[2] + alignment["seqA"] = aln[0, :] + alignment["matches"] = "".join(["|" if aa1 == aa2 else + " " if (aa1 == "-" or aa2 == "-") else + "." for aa1, aa2 in zip(aln[0,:], aln[1,:])]) + alignment["seqB"] = aln[1, :] return alignment - def remove_hetatms(model): chains = [chain.id for chain in model.get_chains()] residues_to_delete = [] @@ -526,7 +512,6 @@ def run_on_chains( use_CA_only=use_CA_only, capri_peptide=capri_peptide, ) - #print(info) return info @@ -675,7 +660,6 @@ def main(): if total_dockq > best_dockq: best_dockq = total_dockq best_result = result_this_mapping - #print(mapping, best_dockq) info["model"] = args.model info["native"] = args.native @@ -703,29 +687,6 @@ def print_results(info, short=False, verbose=False, capri_peptide=False): print(f"Native chains: {chains[0]}, {chains[1]}") print(f"\tModel chains: {results['chain1']} {results['chain2']}") print("\n".join([f"\t{item}: {results[item]:.3f}" for item in items])) - """ - print( - f"Number of equivalent residues in chain {info['chain1']} {info['len1']} ({info['class1']})" - ) - print( - f"Number of equivalent residues in chain {info['chain2']} {info['len2']} ({info['class2']})" - ) - print( - f"Fnat {info['fnat']:.3f} {info['nat_correct']} correct of {info['nat_total']} native contacts" - ) - print( - f"Fnonnat {info['fnonnat']:.3f} {info['nonnat_count']} non-native of {info['model_total']} model contacts" - ) - print(f"iRMS {info['irms']:.3f}") - print(f"LRMS {info['Lrms']:.3f}") - - peptide_disclaimer = ( - " DockQ not reoptimized for CAPRI peptide evaluation" - if capri_peptide - else "" - ) - print(f"DockQ {info['DockQ']:.3f}{peptide_disclaimer}") - """ def print_header(verbose=False, capri_peptide=False): From 3a26b503a02d7782d952d7ccb7fdeac262a048d8 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 6 Mar 2024 16:04:45 +0100 Subject: [PATCH 083/173] simplify main --- src/DockQ/DockQ.py | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 9ed7149..f981afb 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -313,8 +313,9 @@ def format_alignment(aln): alignment = {} alignment["seqA"] = aln[0, :] alignment["matches"] = "".join(["|" if aa1 == aa2 else - " " if (aa1 == "-" or aa2 == "-") else - "." for aa1, aa2 in zip(aln[0,:], aln[1,:])]) + " " if (aa1 == "-" or aa2 == "-") else + "." for aa1, aa2 in + zip(aln[0, :], aln[1, :])]) alignment["seqB"] = aln[1, :] return alignment @@ -588,6 +589,26 @@ def group_model_chains(model_structure, native_structure, model_chains, native_c return native_chain_clusters +def format_mapping(args_mapping, model_chains, native_chains): + mapping = None + model_mapping, native_mapping = args_mapping.split(":") + if not native_mapping: + print("When using --mapping, native chains must be set (e.g. ABC:ABC or :ABC)") + sys.exit() + else: + # :ABC or *:ABC only use those natives chains, permute model chains + if not model_mapping or model_mapping == "*": + native_chains = [chain for chain in native_mapping] + elif len(model_mapping) == len(native_mapping): + # ABC*:ABC* fix the first part of the mapping, try all other combinations + mapping = {nm: mm for nm, mm in zip(native_mapping, model_mapping) if nm != "*" and mm != "*"} + if model_mapping[-1] != "*" and native_mapping[-1] != "*": + # ABC:ABC use the specific mapping + model_chains = [chain for chain in model_mapping] + native_chains = [chain for chain in native_mapping] + return mapping, model_chains, native_chains + + def main(): args = parse_args() @@ -604,21 +625,7 @@ def main(): initial_mapping = None if args.mapping: - model_mapping, native_mapping = args.mapping.split(":") - if not native_mapping: - print("When using --mapping, native chains must be set (e.g. ABC:ABC or :ABC)") - sys.exit() - else: - # :ABC or *:ABC only use those natives chains, permute model chains - if not model_mapping or model_mapping == "*": - native_chains = [chain for chain in native_mapping] - elif len(model_mapping) == len(native_mapping): - # ABC*:ABC* fix the first part of the mapping, try all other combinations - initial_mapping = {nm: mm for nm, mm in zip(native_mapping, model_mapping) if nm != "*" and mm != "*"} - if model_mapping[-1] != "*" and native_mapping[-1] != "*": - # ABC:ABC use the specific mapping - model_chains = [chain for chain in model_mapping] - native_chains = [chain for chain in native_mapping] + initial_mapping, model_chains, native_chains = format_mapping(args.mapping, model_chains, native_chains) # permute chains and run on a for loop best_dockq = -1 From a64b58fbc0b5bed43f2b06649422d16be2708279 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 6 Mar 2024 16:23:47 +0100 Subject: [PATCH 084/173] more help --- src/DockQ/DockQ.py | 42 +++++++++++++----------------------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index f981afb..3d3e75b 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -65,35 +65,19 @@ def parse_args(): ) parser.add_argument( "--mapping", - help="Specify a chain mapping between model and native (e.g.: 'ABC:ACB' to switch last two chains in the native)") - parser.add_argument( - "-model_chain1", - metavar="model_chain1", - type=str, - nargs="+", - help="pdb chain order to group together partner 1", - ) - parser.add_argument( - "-model_chain2", - metavar="model_chain2", - type=str, - nargs="+", - help="pdb chain order to group together partner 2 (complement to partner 1 if undef)", - ) - parser.add_argument( - "-native_chain1", - metavar="native_chain1", - type=str, - nargs="+", - help="pdb chain order to group together from native partner 1", - ) - parser.add_argument( - "-native_chain2", - metavar="native_chain2", - type=str, - nargs="+", - help="pdb chain order to group together from native partner 2 (complement to partner 1 if undef)", - ) + default=None, + help="""Specify a chain mapping between model and native chains. + Chain identifiers are separated by ":". + If the native structure contains two chains "H" and "L" + while the model contains two chains "A" and "B", + where the "A" chain is a model of native chain + "H" and "B" is a model of native chain "L", + the flag can be set as: '--mapping AB:HL'. + This can also help limit the search to specific native interfaces. + For example, if the native is a tetramer (ABCD) but the user is only interested + in the interface between chains B and C, the flag can be set as: '--mapping :BC' + or the equivalent '--mapping *:BC'.""" + ) return parser.parse_args() From 18e40b764166eaaa09e9f80b0bbaacbbbd991017 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 6 Mar 2024 16:27:07 +0100 Subject: [PATCH 085/173] simplify --- src/DockQ/DockQ.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 3d3e75b..77f5eba 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -573,9 +573,11 @@ def group_model_chains(model_structure, native_structure, model_chains, native_c return native_chain_clusters -def format_mapping(args_mapping, model_chains, native_chains): - mapping = None - model_mapping, native_mapping = args_mapping.split(":") +def format_mapping(mapping, model_chains, native_chains): + if not mapping: + return mapping, model_chains, native_chains + + model_mapping, native_mapping = mapping.split(":") if not native_mapping: print("When using --mapping, native chains must be set (e.g. ABC:ABC or :ABC)") sys.exit() @@ -607,9 +609,7 @@ def main(): print("Need at least two chains in the two inputs\n") sys.exit() - initial_mapping = None - if args.mapping: - initial_mapping, model_chains, native_chains = format_mapping(args.mapping, model_chains, native_chains) + initial_mapping, model_chains, native_chains = format_mapping(args.mapping, model_chains, native_chains) # permute chains and run on a for loop best_dockq = -1 From 4da2e749ca11e9369225b1a873502ea5cab36fe6 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 6 Mar 2024 16:40:45 +0100 Subject: [PATCH 086/173] fix mapping bug --- src/DockQ/DockQ.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 77f5eba..cd2f91e 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -66,12 +66,12 @@ def parse_args(): parser.add_argument( "--mapping", default=None, - help="""Specify a chain mapping between model and native chains. - Chain identifiers are separated by ":". - If the native structure contains two chains "H" and "L" + metavar="MODELCHAINS:NATIVECHAINS", + help="""Specify a chain mapping between model and native structure. + If the native contains two chains "H" and "L" while the model contains two chains "A" and "B", - where the "A" chain is a model of native chain - "H" and "B" is a model of native chain "L", + and chain A is a model of native chain + H and chain B is a model of native chain L, the flag can be set as: '--mapping AB:HL'. This can also help limit the search to specific native interfaces. For example, if the native is a tetramer (ABCD) but the user is only interested @@ -573,11 +573,12 @@ def group_model_chains(model_structure, native_structure, model_chains, native_c return native_chain_clusters -def format_mapping(mapping, model_chains, native_chains): - if not mapping: +def format_mapping(mapping_str, model_chains, native_chains): + mapping = None + if not mapping_str: return mapping, model_chains, native_chains - model_mapping, native_mapping = mapping.split(":") + model_mapping, native_mapping = mapping_str.split(":") if not native_mapping: print("When using --mapping, native chains must be set (e.g. ABC:ABC or :ABC)") sys.exit() @@ -663,6 +664,7 @@ def main(): def print_results(info, short=False, verbose=False, capri_peptide=False): if short: capri_peptide_str = "-capri_peptide" if capri_peptide else "" + print(f"Total DockQ over {len(info['best_result'])} native interfaces: {info['best_dockq']:.3f}") for chains, results in info["best_result"].items(): print( f"DockQ{capri_peptide_str} {results['DockQ']:.3f} DockQ_F1 {results['DockQ_F1']:.3f} Fnat {results['fnat']:.3f} iRMS {results['irms']:.3f} LRMS {results['Lrms']:.3f} Fnonnat {results['fnonnat']:.3f} {info['native']} {chains[0]} {chains[1]} -> {info['model']} {results['chain1']} {results['chain2']}" @@ -672,6 +674,7 @@ def print_results(info, short=False, verbose=False, capri_peptide=False): print_header(verbose, capri_peptide) print(f"Model : {info['model']}") print(f"Native : {info['native']}") + print(f"Total DockQ over {len(info['best_result'])} native interfaces: {info['best_dockq']:.3f}") items = ["DockQ_F1", "DockQ", "irms", "Lrms", "fnat"] for chains, results in info["best_result"].items(): From 487193d49db7b27edd92d653d37f476504bf9414 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 7 Mar 2024 14:35:23 +0100 Subject: [PATCH 087/173] bugfix, attempt at speedups --- src/DockQ/DockQ.py | 478 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 396 insertions(+), 82 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index cd2f91e..2183ee3 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -1,9 +1,10 @@ #!/usr/bin/env python import sys +import hashlib import traceback import itertools -from functools import lru_cache +from functools import lru_cache, wraps from argparse import ArgumentParser import Bio.PDB @@ -17,14 +18,16 @@ from .operations import residue_distances, get_fnat_stats except ImportError: print( - "WARNING: It looks like cython is not working, falling back on native python. This will make DockQ slower" + "WARNING: It looks like cython is not working, \ + falling back on native python. This will make DockQ slower" ) from operations_nocy import residue_distances, get_fnat_stats def parse_args(): parser = ArgumentParser( - description="DockQ - Quality measure for protein-protein docking models" + description="DockQ - Quality measure for \ + protein-protein docking models" ) parser.add_argument("model", metavar="", type=str, help="path to model file") parser.add_argument( @@ -34,7 +37,8 @@ def parse_args(): "--capri_peptide", default=False, action="store_true", - help="use version for capri_peptide (DockQ cannot not be trusted for this setting)", + help="use version for capri_peptide \ + (DockQ cannot not be trusted for this setting)", ) parser.add_argument( "--short", default=False, action="store_true", help="short output" @@ -89,6 +93,9 @@ def get_aligned_residues(chainA, chainB, alignment): resA = chainA.get_residues() resB = chainB.get_residues() + if alignment[0] == alignment[2]: + return tuple(resA), tuple(resB) + for A, match, B in zip(*alignment): if A != "-": rA = next(resA) @@ -102,11 +109,363 @@ def get_aligned_residues(chainA, chainB, alignment): return tuple(aligned_resA), tuple(aligned_resB) +@lru_cache +def list_atoms_per_residue2(chain, what): + n_atoms_per_residue = [] + atoms_ids = [] + for residue in chain: + # important to remove duplicate atoms (e.g. alternates) at this stage + atom_ids = tuple([a.id for a in residue.get_unpacked_list()]) + atoms_ids.append(atom_ids) + n_atoms_per_residue.append(len(set(atom_ids))) + return tuple(n_atoms_per_residue), tuple(atoms_ids) + + +@lru_cache +def get_atoms(chain, what): + atoms = np.array( + [ + atom.get_coord() + for res in chain + for atom in res.get_atoms() + ] + ) + return atoms + + +@lru_cache +def get_residue_distances(chain1, chain2, what, all_atom=True): + if all_atom: + # how many atoms per aligned amino acid + n_atoms_per_res_chain1 = list_atoms_per_residue(chain1, what) + n_atoms_per_res_chain2 = list_atoms_per_residue(chain2, what) + model_A_atoms = np.asarray( + [ + atom.get_coord() + for res in chain1 + for atom in res.get_atoms() + ] + ) + model_B_atoms = np.asarray( + [ + atom.get_coord() + for res in chain2 + for atom in res.get_atoms() + ] + ) + + else: # distances were already between CBs only + model_A_atoms = np.asarray( + [ + res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() + for res in chain1 + ] + ) + model_B_atoms = np.asarray( + [ + res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() + for res in chain2 + ] + ) + + n_atoms_per_res_chain1 = np.ones(model_A_atoms.shape[0]).astype(int) + n_atoms_per_res_chain2 = np.ones(model_B_atoms.shape[0]).astype(int) + + model_res_distances = residue_distances( + model_A_atoms, model_B_atoms, n_atoms_per_res_chain1, n_atoms_per_res_chain2 + ) + return model_res_distances + + +@lru_cache +def get_aligned_atoms(n_atoms_per_res_chainA, n_atoms_per_res_chainB, alignment): + + if alignment[0] == alignment[2]: # no need to align + return np.ones(sum(list(n_atoms_per_res_chainA))).astype(bool), np.ones(sum(list(n_atoms_per_res_chainB))).astype(bool), [i for i in range(len(alignment[0]))], [i for i in range(len(alignment[1]))] + atom_index_A = np.zeros(sum(list(n_atoms_per_res_chainA))).astype(bool) + atom_index_B = np.zeros(sum(list(n_atoms_per_res_chainB))).astype(bool) + res_index_A = [] + res_index_B = [] + + n_atoms_per_res_chainA = iter(n_atoms_per_res_chainA) + n_atoms_per_res_chainB = iter(n_atoms_per_res_chainB) + countA = iA = 0 + countB = iB = 0 + + for A, match, B in zip(*alignment): + if A != "-": + nA = next(n_atoms_per_res_chainA) + countA += nA + iA += 1 + if B != "-": + nB = next(n_atoms_per_res_chainB) + countB += nB + iB += 1 + + if match == "|": + atom_index_A[countA-nA:countA] = 1 + atom_index_B[countB-nB:countB] = 1 + res_index_A.append(iA-1) + res_index_B.append(iB-1) + + return atom_index_A, atom_index_B, res_index_A, res_index_B + + +class NpWrapper: + def __init__(self, x: np.array) -> None: + self.values = x + # here you can use your own hashing function + self.h = hashlib.sha224(x.view()).hexdigest() + + def __hash__(self) -> int: + return hash(self.h) + + def __eq__(self, __value: object) -> bool: + return __value.h == self.h + + +def dist_memoizer(get_atom_distances): + @lru_cache() + def cached_wrapper(np1, np2, n_atoms, what): + return get_atom_distances(np1.values, np2.values, n_atoms, what) + + @wraps(get_atom_distances) + def wrapper(x: np.array, y: np.array, n_atoms, what): + np1 = NpWrapper(x) + np2 = NpWrapper(y) + return cached_wrapper(np1, np2, n_atoms, what) + + return wrapper + + +@dist_memoizer +def get_atom_distances(chain1_atoms, chain2_atoms, n_atoms_per_res, what): + n_atoms_per_res_chain1, n_atoms_per_res_chain2 = n_atoms_per_res + + model_res_distances = residue_distances( + chain1_atoms, chain2_atoms, np.array(n_atoms_per_res_chain1).astype(int), np.array(n_atoms_per_res_chain2).astype(int) + ) + return model_res_distances + + +def sup_memoizer(superimpose): + @lru_cache() + def cached_wrapper(np1, np2): + return superimpose(np1.values, np2.values) + + @wraps(superimpose) + def wrapper(x: np.array, y: np.array): + np1 = NpWrapper(x) + np2 = NpWrapper(y) + return cached_wrapper(np1, np2) + + return wrapper + + +@sup_memoizer +def superimpose(from_atoms, to_atoms): + super_imposer = SVDSuperimposer() + # Set to align on receptor + super_imposer.set(to_atoms, from_atoms) + super_imposer.run() + rot, tran = super_imposer.get_rotran() + return rot, tran, super_imposer + + +# @profile +def calc_DockQ2( + model_chains, + native_chains, + alignments, + use_CA_only=False, + capri_peptide=False, +): + atom_for_sup = ("CA", "C", "N", "O") if not use_CA_only else ("CA") + fnat_threshold = 4.0 if capri_peptide else 5.0 + interface_threshold = 8.0 if capri_peptide else 10.0 + + native_atoms_1 = get_atoms(native_chains[0], "native") + native_atoms_2 = get_atoms(native_chains[1], "native") + native_n_atoms_1, native_atom_ids_1 = list_atoms_per_residue2(native_chains[0], "native") + native_n_atoms_2, native_atom_ids_2 = list_atoms_per_residue2(native_chains[1], "native") + + native_distances = get_atom_distances(native_atoms_1, native_atoms_2, (native_n_atoms_1, native_n_atoms_2), "native") + nat_total = np.nonzero(np.asarray(native_distances) < fnat_threshold**2)[ + 0 + ].shape[0] + + if nat_total == 0: + return None + + model_atoms_1 = get_atoms(model_chains[0], "model") + model_atoms_2 = get_atoms(model_chains[1], "model") + model_n_atoms_1, model_atom_ids_1 = list_atoms_per_residue2(model_chains[0], "model") + model_n_atoms_2, model_atom_ids_2 = list_atoms_per_residue2(model_chains[1], "model") + + model_atom_index_1, native_atom_index_1, model_res_index_1, native_res_index_1 = get_aligned_atoms( + model_n_atoms_1, native_n_atoms_1, tuple(alignments[0]) + ) + model_atom_index_2, native_atom_index_2, model_res_index_2, native_res_index_2 = get_aligned_atoms( + model_n_atoms_2, native_n_atoms_2, tuple(alignments[1]) + ) + + if len(model_res_index_1) != len(model_chains[0]): + # filter model, native atoms by alignment atom indexes + model_atoms_1 = model_atoms_1[model_atom_index_1] + model_n_atoms_1 = tuple([n_atoms for i, n_atoms in enumerate(model_n_atoms_1) if i in model_res_index_1]) + model_atom_ids_1 = tuple([atom_ids for i, atom_ids in enumerate(model_atom_ids_1) if i in model_res_index_1]) + + if len(model_res_index_2) != len(model_chains[1]): + model_atoms_2 = model_atoms_2[model_atom_index_2] + model_n_atoms_2 = tuple([n_atoms for i, n_atoms in enumerate(model_n_atoms_2) if i in model_res_index_2]) + model_atom_ids_2 = tuple([atom_ids for i, atom_ids in enumerate(model_atom_ids_2) if i in model_res_index_2]) + + model_distances = get_atom_distances(model_atoms_1, model_atoms_2, (model_n_atoms_1, model_n_atoms_2), "model") + # only recalculate distances if model was missing residues compared to native + if len(native_res_index_1) != len(native_chains[0]) or len(native_res_index_2) != len(native_chains[1]): + native_atoms_1 = native_atoms_1[native_atom_index_1] + native_atoms_2 = native_atoms_1[native_atom_index_2] + native_n_atoms_1 = tuple([n_atoms for i, n_atoms in enumerate(native_n_atoms_1) if i in native_res_index_1]) + native_n_atoms_2 = tuple([n_atoms for i, n_atoms in enumerate(native_n_atoms_2) if i in native_res_index_2]) + native_atom_ids_1 = tuple([atom_ids for i, atom_ids in enumerate(native_atom_ids_1) if i in native_res_index_1]) + native_atom_ids_2 = tuple([atom_ids for i, atom_ids in enumerate(native_atom_ids_2) if i in native_res_index_2]) + native_distances = get_atom_distances(native_atoms_1, native_atoms_2, (native_n_atoms_1, native_n_atoms_2), "native") + + assert ( + model_distances.shape == native_distances.shape + ), f"Native and model have incompatible sizes ({model_distances.shape} != {native_distances.shape})" + + nat_correct, nonnat_count, _, model_total = get_fnat_stats( + model_distances, native_distances, threshold=fnat_threshold + ) + + # avoids divide by 0 errors + fnat = nat_total and nat_correct / nat_total or 0 + fnonnat = model_total and nonnat_count / model_total or 0 + + # filter out backbone atoms now + model_index_1, native_index_1, n_atoms_1 = filter_atoms(model_atom_ids_1, native_atom_ids_1, filter=atom_for_sup) + model_index_2, native_index_2, n_atoms_2 = filter_atoms(model_atom_ids_2, native_atom_ids_2, filter=atom_for_sup) + model_atoms_1 = model_atoms_1[model_index_1] + model_atoms_2 = model_atoms_2[model_index_2] + native_atoms_1 = native_atoms_1[native_index_1] + native_atoms_2 = native_atoms_2[native_index_2] + + # assign which chains constitute the receptor, ligand + native1_size = len(native_chains[0]) + native2_size = len(native_chains[1]) + receptor_atoms = ( + (model_atoms_1, native_atoms_1) + if native1_size > native2_size + else (model_atoms_2, native_atoms_2) + ) + ligand_atoms = ( + (model_atoms_1, native_atoms_1) + if native1_size <= native2_size + else (model_atoms_2, native_atoms_2) + ) + receptor_n_atoms = ( + n_atoms_1 + if native1_size > native2_size + else n_atoms_2 + ) + ligand_n_atoms = ( + n_atoms_1 + if native1_size <= native2_size + else n_atoms_2 + ) + + class1, class2 = ( + ("receptor", "ligand") + if native1_size > native2_size + else ("ligand", "receptor") + ) + + # Set to align on receptor + rot, tran, super_imposer = superimpose(receptor_atoms[0], receptor_atoms[1]) + rotated_ligand_atoms = np.dot(ligand_atoms[0], rot) + tran + + Lrms = super_imposer._rms( + ligand_atoms[1], rotated_ligand_atoms + ) # using the private _rms function which does not superimpose + + # Get interfacial atoms from reference, and corresponding atoms from sample + interacting_pairs = get_interacting_pairs( + # working with squared thresholds to avoid using sqrt + native_distances, + threshold=interface_threshold**2, + ) + + if class1 == "ligand": + interacting_pairs = interacting_pairs[::-1] + + receptor_interface_index, _, _ = filter_atoms(receptor_n_atoms, None, filter=interacting_pairs[0]) + ligand_interface_index, _, _ = filter_atoms(ligand_n_atoms, None, filter=interacting_pairs[1]) + + model_interface_atoms = np.vstack((receptor_atoms[0][receptor_interface_index], ligand_atoms[0][ligand_interface_index])) + native_interface_atoms = np.vstack((receptor_atoms[1][receptor_interface_index], ligand_atoms[1][ligand_interface_index])) + + _, _, super_imposer = superimpose(model_interface_atoms, native_interface_atoms) + irms = super_imposer.get_rms() + + info = {} + + info["DockQ_F1"] = dockq_formula(f1(nat_correct, nonnat_count, nat_total), irms, Lrms) + info["DockQ"] = dockq_formula(fnat, irms, Lrms) + info["irms"] = irms + info["Lrms"] = Lrms + info["fnat"] = fnat + info["nat_correct"] = nat_correct + info["nat_total"] = nat_total + + info["fnonnat"] = fnonnat + info["nonnat_count"] = nonnat_count + info["model_total"] = model_total + + info["len1"] = native1_size + info["len2"] = native2_size + info["class1"] = class1 + info["class2"] = class2 + return info + + +@lru_cache +def filter_atoms(model_info, native_info, filter=("CA", "C", "N", "O")): + model_bools = [] + native_bools = [] + if "CA" in filter: # backbone filter + model_atom_ids = model_info + native_atom_ids = native_info + + n_atoms_per_res = [] + + for model_ids, native_ids in zip(model_atom_ids, native_atom_ids): + model_select = [1 if atom in filter and atom in native_ids else 0 for atom in model_ids] + native_select = [1 if atom in filter and atom in model_ids else 0 for atom in native_ids] + model_bools.extend(model_select) + native_bools.extend(native_select) + n_atoms_per_res.append(sum(native_select)) + if sum(model_select) != sum(native_select): + print("ERROR!") + else: # filter by index + n_atoms_per_res = model_info + + for i, n_atoms in enumerate(n_atoms_per_res): + if i in filter: + model_bools.extend([1 for i in range(n_atoms)]) + else: + model_bools.extend([0 for i in range(n_atoms)]) + native_bools = model_bools + model_bools = np.array(model_bools).astype(bool) + native_bools = np.array(native_bools).astype(bool) + return model_bools, native_bools, tuple(n_atoms_per_res) + + # @profile def calc_DockQ( sample_chains, ref_chains, - alignments=[], + alignments, use_CA_only=False, capri_peptide=False, ): @@ -165,10 +524,10 @@ def calc_DockQ( (aligned_ref_1, aligned_ref_2), atom_types=atom_for_sup, ) - super_imposer = Bio.PDB.Superimposer() - super_imposer.set_atoms(sample_interface_atoms, ref_interface_atoms) - - irms = super_imposer.rms + super_imposer = SVDSuperimposer() + super_imposer.set(sample_interface_atoms, ref_interface_atoms) + super_imposer.run() + irms = super_imposer.get_rms() # assign which chains constitute the receptor, ligand ref_group1_size = len(ref_chains[0]) @@ -203,14 +562,13 @@ def calc_DockQ( ) # Set to align on receptor - sup = SVDSuperimposer() - sup.set(receptor_atoms_native, receptor_atoms_sample) - sup.run() + super_imposer.set(receptor_atoms_native, receptor_atoms_sample) + super_imposer.run() - rot, tran = sup.get_rotran() + rot, tran = super_imposer.get_rotran() rotated_sample_atoms = np.dot(ligand_atoms_sample, rot) + tran - Lrms = sup._rms( + Lrms = super_imposer._rms( ligand_atoms_native, rotated_sample_atoms ) # using the private _rms function which does not superimpose @@ -317,6 +675,10 @@ def remove_hetatms(model): for _, _, chain, res in residues_to_delete: model[chain].detach_child(res) + for chain in chains: + if not model[chain]: + model.detach_child(chain) + def remove_h(model): chains = [chain.id for chain in model.get_chains()] @@ -333,58 +695,11 @@ def remove_h(model): model[chain][res].detach_child(atom[0]) -@lru_cache -def get_residue_distances(chain1, chain2, what, all_atom=True): - if all_atom: - # how many atoms per aligned amino acid - n_atoms_per_res_chain1 = list_atoms_per_residue(chain1, what) - n_atoms_per_res_chain2 = list_atoms_per_residue(chain2, what) - model_A_atoms = np.asarray( - [ - atom.get_coord() - for i, res in enumerate(chain1) - for atom in res.get_atoms() - if atom.element != "H" - ] - ) - model_B_atoms = np.asarray( - [ - atom.get_coord() - for i, res in enumerate(chain2) - for atom in res.get_atoms() - if atom.element != "H" - ] - ) - - else: # distances were already between CBs only - model_A_atoms = np.asarray( - [ - res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() - for i, res in enumerate(chain1) - ] - ) - model_B_atoms = np.asarray( - [ - res["CB"].get_coord() if "CB" in res else res["CA"].get_coord() - for i, res in enumerate(chain2) - ] - ) - - n_atoms_per_res_chain1 = np.ones(model_A_atoms.shape[0]).astype(int) - n_atoms_per_res_chain2 = np.ones(model_B_atoms.shape[0]).astype(int) - - model_res_distances = residue_distances( - model_A_atoms, model_B_atoms, n_atoms_per_res_chain1, n_atoms_per_res_chain2 - ) - return model_res_distances - - @lru_cache def list_atoms_per_residue(chain, what): n_atoms_per_residue = [] - residues = [r for r in chain] - for residue in residues: + for residue in chain: # important to remove duplicate atoms (e.g. alternates) at this stage atom_ids = set([a.id for a in residue.get_unpacked_list()]) n_atoms_per_residue.append(len(atom_ids)) @@ -397,17 +712,15 @@ def get_atoms_per_residue( what, atom_types=("CA", "C", "N", "O"), ): - residues = chain - atoms = [] - for residue in residues: - atoms.extend( - [ - atom.coord - for atom in residue.get_atoms() - if atom.id in atom_types - ] - ) + atoms = ( + [ + atom.coord + for res in chain + for atom in res.get_atoms() + if atom.id in atom_types + ] + ) return atoms @@ -417,6 +730,7 @@ def get_interacting_pairs(distances, threshold): @lru_cache +# @profile def get_interface_atoms( interacting_pairs, model_chains, @@ -441,12 +755,12 @@ def get_interface_atoms( ref_atoms_ids = [atom.id for atom in ref_atoms] mod_atoms_ids = [atom.id for atom in mod_atoms] ref_interface += [ - atom + atom.coord for atom in ref_atoms if atom.id in atom_types and atom.id in mod_atoms_ids ] mod_interface += [ - atom + atom.coord for atom in mod_atoms if atom.id in atom_types and atom.id in ref_atoms_ids ] @@ -457,17 +771,17 @@ def get_interface_atoms( ref_atoms_ids = [atom.id for atom in ref_atoms] mod_atoms_ids = [atom.id for atom in mod_atoms] ref_interface += [ - atom + atom.coord for atom in ref_atoms if atom.id in atom_types and atom.id in mod_atoms_ids ] mod_interface += [ - atom + atom.coord for atom in mod_atoms if atom.id in atom_types and atom.id in ref_atoms_ids ] - return mod_interface, ref_interface + return np.asarray(mod_interface), np.asarray(ref_interface) @lru_cache @@ -488,19 +802,18 @@ def run_on_chains( use_numbering=no_needle, ) alignment = format_alignment(aln) - alignments.append(alignment.values()) + alignments.append(tuple(alignment.values())) info = calc_DockQ( model_chains, native_chains, - alignments=alignments, + alignments=tuple(alignments), use_CA_only=use_CA_only, capri_peptide=capri_peptide, ) return info -# @lru_cache def run_on_all_native_interfaces( model_structure, native_structure, @@ -509,7 +822,8 @@ def run_on_all_native_interfaces( use_CA_only=False, capri_peptide=False, ): - """Given a native-model chain map, finds all non-null native interfaces and runs DockQ for each native-model pair of interfaces""" + """Given a native-model chain map, finds all non-null native interfaces + and runs DockQ for each native-model pair of interfaces""" results_dic = {} native_chain_ids = list(chain_map.keys()) @@ -679,7 +993,7 @@ def print_results(info, short=False, verbose=False, capri_peptide=False): for chains, results in info["best_result"].items(): print(f"Native chains: {chains[0]}, {chains[1]}") - print(f"\tModel chains: {results['chain1']} {results['chain2']}") + print(f"\tModel chains: {results['chain1']}, {results['chain2']}") print("\n".join([f"\t{item}: {results[item]:.3f}" for item in items])) From 0e90c85cbf2b6d376d99e49a330e86886edd9a68 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 7 Mar 2024 15:30:46 +0100 Subject: [PATCH 088/173] the mystery of missing backbone atoms --- src/DockQ/DockQ.py | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 2183ee3..690f9cd 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -548,19 +548,12 @@ def calc_DockQ( else ("ligand", "receptor") ) - receptor_atoms_native = np.asarray( - get_atoms_per_residue(receptor_chains[0], what="ref", atom_types=atom_for_sup) + receptor_atoms_native, receptor_atoms_sample = np.asarray( + get_atoms_per_residue(receptor_chains, what="receptor", atom_types=atom_for_sup) ) - receptor_atoms_sample = np.asarray( - get_atoms_per_residue(receptor_chains[1], what="sample", atom_types=atom_for_sup) + ligand_atoms_native, ligand_atoms_sample = np.asarray( + get_atoms_per_residue(ligand_chains, what="ligand", atom_types=atom_for_sup) ) - ligand_atoms_native = np.asarray( - get_atoms_per_residue(ligand_chains[0], what="ref", atom_types=atom_for_sup) - ) - ligand_atoms_sample = np.asarray( - get_atoms_per_residue(ligand_chains[1], what="sample", atom_types=atom_for_sup) - ) - # Set to align on receptor super_imposer.set(receptor_atoms_native, receptor_atoms_sample) super_imposer.run() @@ -708,20 +701,31 @@ def list_atoms_per_residue(chain, what): @lru_cache def get_atoms_per_residue( - chain, + chains, what, atom_types=("CA", "C", "N", "O"), ): + chain1, chain2 = chains + atoms1 = ( + [ + atom.coord + for res1, res2 in zip(chain1, chain2) + for atom in res1.get_atoms() + if atom.id in atom_types + and atom.id in [a.id for a in res2.get_atoms()] + ] + ) - atoms = ( + atoms2 = ( [ atom.coord - for res in chain - for atom in res.get_atoms() + for res1, res2 in zip(chain1, chain2) + for atom in res2.get_atoms() if atom.id in atom_types + and atom.id in [a.id for a in res1.get_atoms()] ] ) - return atoms + return atoms1, atoms2 def get_interacting_pairs(distances, threshold): From 989fa00c1f60635832c9a925731288f2af780ef5 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 7 Mar 2024 15:43:29 +0100 Subject: [PATCH 089/173] alignment fix --- src/DockQ/DockQ.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 690f9cd..55525a3 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -638,7 +638,7 @@ def align_chains(model_chain, native_chain, use_numbering=False): aligner = Align.PairwiseAligner() aligner.match = 5 aligner.mismatch = 0 - aligner.open_gap_score = -10 + aligner.open_gap_score = -4 aligner.extend_gap_score = -0.5 aln = aligner.align(model_sequence, native_sequence)[0] return aln @@ -937,7 +937,6 @@ def main(): native_chain_clusters = group_model_chains( model_structure, native_structure, model_chains, native_chains ) - all_mappings = itertools.product(*[cluster for cluster in native_chain_clusters.values() if cluster]) # remove mappings where the same model chain is present more than once From fbb277c3997a655f48283ab3cfdec5ddbee03f24 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 7 Mar 2024 16:09:58 +0100 Subject: [PATCH 090/173] older bio align format --- src/DockQ/DockQ.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 55525a3..6e6803c 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -646,12 +646,19 @@ def align_chains(model_chain, native_chain, use_numbering=False): def format_alignment(aln): alignment = {} - alignment["seqA"] = aln[0, :] - alignment["matches"] = "".join(["|" if aa1 == aa2 else - " " if (aa1 == "-" or aa2 == "-") else - "." for aa1, aa2 in - zip(aln[0, :], aln[1, :])]) - alignment["seqB"] = aln[1, :] + try: + alignment["seqA"] = aln[0, :] + alignment["matches"] = "".join(["|" if aa1 == aa2 else + " " if (aa1 == "-" or aa2 == "-") else + "." for aa1, aa2 in + zip(aln[0, :], aln[1, :])]) + alignment["seqB"] = aln[1, :] + except NotImplementedError: + formatted_aln = aln.format().split("\n") + alignment["seqA"] = formatted_aln[0] + alignment["matches"] = formatted_aln[1] + alignment["seqB"] = formatted_aln[2] + return alignment From 6b2493b2a7df28fc0e773e38722ae69cbf4da661 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 7 Mar 2024 16:13:13 +0100 Subject: [PATCH 091/173] back compatibility with AF biopython --- pyproject.toml | 2 +- setup.cfg | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 455dc25..fb41b01 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [build-system] name = "DockQ" version = "2.0" -requires = ["setuptools", "cython", "numpy ~= 1.21", "biopython >= 1.81"] +requires = ["setuptools", "cython", "numpy ~= 1.21", "biopython >= 1.79"] build-backend = "setuptools.build_meta" diff --git a/setup.cfg b/setup.cfg index a2935fc..7a1cefc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -10,7 +10,7 @@ install_requires = setuptools cython numpy~=1.21 - biopython>=1.81 + biopython>=1.79 [options.packages.find] where=src From c0c949f6fe1915e9eccce6e75ee74438d623a9cc Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 7 Mar 2024 16:30:46 +0100 Subject: [PATCH 092/173] bug in faster function --- src/DockQ/DockQ.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 6e6803c..2011585 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -438,14 +438,15 @@ def filter_atoms(model_info, native_info, filter=("CA", "C", "N", "O")): native_atom_ids = native_info n_atoms_per_res = [] - for model_ids, native_ids in zip(model_atom_ids, native_atom_ids): - model_select = [1 if atom in filter and atom in native_ids else 0 for atom in model_ids] - native_select = [1 if atom in filter and atom in model_ids else 0 for atom in native_ids] + model_select = [1 if atom in filter and atom in native_ids else 0 for atom in list(dict.fromkeys(model_ids))] + native_select = [1 if atom in filter and atom in model_ids else 0 for atom in list(dict.fromkeys(native_ids))] model_bools.extend(model_select) native_bools.extend(native_select) n_atoms_per_res.append(sum(native_select)) if sum(model_select) != sum(native_select): + print(model_ids, model_select) + print(native_ids, native_select) print("ERROR!") else: # filter by index n_atoms_per_res = model_info @@ -815,7 +816,7 @@ def run_on_chains( alignment = format_alignment(aln) alignments.append(tuple(alignment.values())) - info = calc_DockQ( + info = calc_DockQ2( model_chains, native_chains, alignments=tuple(alignments), From f0bb5241023a42e77b1fa05c183defb2dbf4c90f Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 7 Mar 2024 16:31:57 +0100 Subject: [PATCH 093/173] mantaing old version --- src/DockQ/DockQ.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 2011585..d733446 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -816,7 +816,7 @@ def run_on_chains( alignment = format_alignment(aln) alignments.append(tuple(alignment.values())) - info = calc_DockQ2( + info = calc_DockQ( model_chains, native_chains, alignments=tuple(alignments), From f4e91af5884b60b4527e12bf59c53da43fdf67fd Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 12 Mar 2024 14:48:45 +0100 Subject: [PATCH 094/173] add NC measures --- src/DockQ/DockQ.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index d733446..25cc6e2 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -430,7 +430,7 @@ def calc_DockQ2( @lru_cache -def filter_atoms(model_info, native_info, filter=("CA", "C", "N", "O")): +def filter_atoms(model_info, native_info, filter=("CA", "C", "N", "O", "P")): model_bools = [] native_bools = [] if "CA" in filter: # backbone filter @@ -470,7 +470,7 @@ def calc_DockQ( use_CA_only=False, capri_peptide=False, ): - atom_for_sup = ("CA", "C", "N", "O") if not use_CA_only else ("CA") + atom_for_sup = ("CA", "C", "N", "O", "P") if not use_CA_only else ("CA", "P") fnat_threshold = 4.0 if capri_peptide else 5.0 interface_threshold = 8.0 if capri_peptide else 10.0 @@ -628,12 +628,14 @@ def align_chains(model_chain, native_chain, use_numbering=False): native_sequence = "".join([chr(resn + min_resn) for resn in native_numbering]) else: + model_sequence = [residue.get_resname() for residue in model_chain.get_residues()] + native_sequence = [residue.get_resname() for residue in native_chain.get_residues()] model_sequence = "".join( - seq1(residue.get_resname()) for residue in model_chain.get_residues() + seq1(r) if len(r) == 3 else r[:-1] if (len(r) == 2) else r for r in model_sequence ) native_sequence = "".join( - seq1(residue.get_resname()) for residue in native_chain.get_residues() + seq1(r) if len(r) == 3 else r[:-1] if len(r) == 2 else r for r in native_sequence ) aligner = Align.PairwiseAligner() @@ -711,7 +713,7 @@ def list_atoms_per_residue(chain, what): def get_atoms_per_residue( chains, what, - atom_types=("CA", "C", "N", "O"), + atom_types=("CA", "C", "N", "O", "P"), ): chain1, chain2 = chains atoms1 = ( @@ -891,9 +893,7 @@ def group_model_chains(model_structure, native_structure, model_chains, native_c for model_chain, native_chain in alignment_targets: aln = align_chains(model_structure[model_chain], native_structure[native_chain]) alignment = format_alignment(aln) - if "." not in alignment["matches"] and ( - "-" not in alignment["seqA"] or "-" not in alignment["seqB"] - ): + if "." not in alignment["matches"]: # 100% sequence identity, 100% coverage of native sequence in model sequence native_chain_clusters[native_chain].append(model_chain) return native_chain_clusters From 5b0a91070c0e9ec7bdc6d0fc271b760e314cb11b Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 19 Mar 2024 14:28:38 +0100 Subject: [PATCH 095/173] seamless mmcif handling --- src/DockQ/DockQ.py | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 25cc6e2..b4cc9e6 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -49,18 +49,6 @@ def parse_args(): parser.add_argument( "--use_CA", "-ca", default=False, action="store_true", help="use CA instead of backbone" ) - parser.add_argument( - "--mmcif_model", - default=False, - action="store_true", - help="The model is in mmCIF format", - ) - parser.add_argument( - "--mmcif_native", - default=False, - action="store_true", - help="The native is in mmCIF format", - ) parser.add_argument( "--no_needle", default=False, @@ -866,21 +854,16 @@ def run_on_all_native_interfaces( return results_dic -def load_PDB(path, n_model=0, is_mmcif=False): - if not is_mmcif: +def load_PDB(path, n_model=0): + try: pdb_parser = Bio.PDB.PDBParser(QUIET=True) - else: + structure = pdb_parser.get_structure("-", path) + model = structure[n_model] + except KeyError: pdb_parser = Bio.PDB.MMCIFParser(QUIET=True) - - try: structure = pdb_parser.get_structure("-", path) model = structure[n_model] - except Exception: - print("ERROR: is the file in the correct format? (.pdb, .mmcif)") - if not is_mmcif: - print("\t(use --mmcif_model or --mmcif_native with mmCIF inputs)") - print(traceback.format_exc()) - sys.exit(1) + remove_hetatms(model) remove_h(model) return model @@ -925,8 +908,8 @@ def format_mapping(mapping_str, model_chains, native_chains): def main(): args = parse_args() - native_structure = load_PDB(args.native, is_mmcif=args.mmcif_native) - model_structure = load_PDB(args.model, is_mmcif=args.mmcif_model) + native_structure = load_PDB(args.native) + model_structure = load_PDB(args.model) info = {} model_chains = [c.id for c in model_structure] From 48576026f7a3223826cd413e03d0667e33aaab23 Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 19 Mar 2024 15:55:36 +0100 Subject: [PATCH 096/173] any exception to load as cif --- src/DockQ/DockQ.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index b4cc9e6..2d06747 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -859,7 +859,7 @@ def load_PDB(path, n_model=0): pdb_parser = Bio.PDB.PDBParser(QUIET=True) structure = pdb_parser.get_structure("-", path) model = structure[n_model] - except KeyError: + except Exception: pdb_parser = Bio.PDB.MMCIFParser(QUIET=True) structure = pdb_parser.get_structure("-", path) model = structure[n_model] From 7a96dd568150a581f774743ea1fcd36b600711a8 Mon Sep 17 00:00:00 2001 From: clami66 Date: Tue, 19 Mar 2024 16:14:29 +0100 Subject: [PATCH 097/173] seamless gzip file handling --- src/DockQ/DockQ.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 2d06747..0e03c6c 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import sys +import gzip import hashlib import traceback import itertools @@ -74,6 +75,15 @@ def parse_args(): return parser.parse_args() +def open_file(filename): + if filename.endswith(".gz"): + with gzip.open(filename) as f: + yield f + else: + with open(filename) as f: + yield f + + @lru_cache def get_aligned_residues(chainA, chainB, alignment): aligned_resA = [] @@ -857,11 +867,11 @@ def run_on_all_native_interfaces( def load_PDB(path, n_model=0): try: pdb_parser = Bio.PDB.PDBParser(QUIET=True) - structure = pdb_parser.get_structure("-", path) + structure = pdb_parser.get_structure("-", (gzip.open if path.endswith(".gz") else open)(path, "rt")) model = structure[n_model] except Exception: pdb_parser = Bio.PDB.MMCIFParser(QUIET=True) - structure = pdb_parser.get_structure("-", path) + structure = pdb_parser.get_structure("-", (gzip.open if path.endswith(".gz") else open)(path, "rt")) model = structure[n_model] remove_hetatms(model) From a4dd878a5635f4c587db6c91f971ca2e3c4e24fc Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 20 Mar 2024 11:02:40 +0100 Subject: [PATCH 098/173] overload PDBParser --- src/DockQ/DockQ.py | 24 ++-- src/DockQ/parsers.py | 265 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 279 insertions(+), 10 deletions(-) create mode 100644 src/DockQ/parsers.py diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 0e03c6c..6b4d271 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -13,6 +13,7 @@ from Bio import Align from Bio.SeqUtils import seq1 from Bio.SVDSuperimposer import SVDSuperimposer +from .parsers import PDBParser # fallback in case the cython version doesn't work, though it will be slower try: @@ -864,10 +865,11 @@ def run_on_all_native_interfaces( return results_dic -def load_PDB(path, n_model=0): +#@profile +def load_PDB(path, chains=[], n_model=0): try: - pdb_parser = Bio.PDB.PDBParser(QUIET=True) - structure = pdb_parser.get_structure("-", (gzip.open if path.endswith(".gz") else open)(path, "rt")) + pdb_parser = PDBParser(QUIET=True) + structure = pdb_parser.get_structure("-", (gzip.open if path.endswith(".gz") else open)(path, "rt"), chains=chains) model = structure[n_model] except Exception: pdb_parser = Bio.PDB.MMCIFParser(QUIET=True) @@ -892,8 +894,10 @@ def group_model_chains(model_structure, native_structure, model_chains, native_c return native_chain_clusters -def format_mapping(mapping_str, model_chains, native_chains): +def format_mapping(mapping_str): mapping = None + model_chains = None + native_chains = None if not mapping_str: return mapping, model_chains, native_chains @@ -915,22 +919,22 @@ def format_mapping(mapping_str, model_chains, native_chains): return mapping, model_chains, native_chains +#@profile def main(): args = parse_args() + initial_mapping, model_chains, native_chains = format_mapping(args.mapping) - native_structure = load_PDB(args.native) - model_structure = load_PDB(args.model) + model_structure = load_PDB(args.model, chains=model_chains) + native_structure = load_PDB(args.native, chains=native_chains) info = {} - model_chains = [c.id for c in model_structure] - native_chains = [c.id for c in native_structure] + model_chains = [c.id for c in model_structure] if not model_chains else model_chains + native_chains = [c.id for c in native_structure] if not native_chains else native_chains if len(model_chains) < 2 or len(native_chains) < 2: print("Need at least two chains in the two inputs\n") sys.exit() - initial_mapping, model_chains, native_chains = format_mapping(args.mapping, model_chains, native_chains) - # permute chains and run on a for loop best_dockq = -1 best_result = None diff --git a/src/DockQ/parsers.py b/src/DockQ/parsers.py new file mode 100644 index 0000000..bc809fd --- /dev/null +++ b/src/DockQ/parsers.py @@ -0,0 +1,265 @@ +import numpy as np +from Bio.PDB.StructureBuilder import StructureBuilder +from Bio.PDB.PDBExceptions import PDBConstructionWarning +from Bio.PDB.PDBParser import as_handle +import Bio +import warnings + +class PDBParser(Bio.PDB.PDBParser): + def get_structure(self, id, file, chains): + """Return the structure. + + Arguments: + - id - string, the id that will be used for the structure + - file - name of the PDB file OR an open filehandle + + """ + with warnings.catch_warnings(): + if self.QUIET: + warnings.filterwarnings("ignore", category=PDBConstructionWarning) + + self.header = None + self.trailer = None + # Make a StructureBuilder instance (pass id of structure as parameter) + self.structure_builder.init_structure(id) + + with as_handle(file) as handle: + lines = handle.readlines() + if not lines: + raise ValueError("Empty file.") + self._parse(lines, chains) + + self.structure_builder.set_header(self.header) + # Return the Structure instance + structure = self.structure_builder.get_structure() + + return structure + + + def _parse(self, header_coords_trailer, chains): + """Parse the PDB file (PRIVATE).""" + # Extract the header; return the rest of the file + self.header, coords_trailer = self._get_header(header_coords_trailer) + # Parse the atomic data; return the PDB file trailer + self.trailer = self._parse_coordinates(coords_trailer, chains) + + + def _parse_coordinates(self, coords_trailer, chains=[]): + """Parse the atomic data in the PDB file (PRIVATE).""" + allowed_records = { + "ATOM ", + "HETATM", + "MODEL ", + "ENDMDL", + "TER ", + } + local_line_counter = 0 + structure_builder = self.structure_builder + current_model_id = 0 + # Flag we have an open model + model_open = 0 + current_chain_id = None + current_segid = None + current_residue_id = None + current_resname = None + + for i in range(len(coords_trailer)): + line = coords_trailer[i].rstrip("\n") + record_type = line[0:6] + global_line_counter = self.line_counter + local_line_counter + 1 + structure_builder.set_line_counter(global_line_counter) + if not line.strip(): + continue # skip empty lines + elif record_type == "HETATM": + continue + elif record_type == "ATOM ": + # Initialize the Model - there was no explicit MODEL record + if not model_open: + structure_builder.init_model(current_model_id) + current_model_id += 1 + model_open = 1 + chainid = line[21] + if chains and chainid not in chains: + continue + fullname = line[12:16] + # get rid of whitespace in atom names + split_list = fullname.split() + if len(split_list) != 1: + # atom name has internal spaces, e.g. " N B ", so + # we do not strip spaces + name = fullname + else: + # atom name is like " CA ", so we can strip spaces + name = split_list[0] + altloc = line[16] + resname = line[17:20].strip() + try: + serial_number = int(line[6:11]) + except Exception: + serial_number = 0 + resseq = int(line[22:26].split()[0]) # sequence identifier + icode = line[26] # insertion code + if record_type == "HETATM": # hetero atom flag + if resname == "HOH" or resname == "WAT": + hetero_flag = "W" + else: + hetero_flag = "H" + else: + hetero_flag = " " + residue_id = (hetero_flag, resseq, icode) + # atomic coordinates + try: + x = float(line[30:38]) + y = float(line[38:46]) + z = float(line[46:54]) + except Exception: + # Should we allow parsing to continue in permissive mode? + # If so, what coordinates should we default to? Easier to abort! + raise PDBConstructionException( + "Invalid or missing coordinate(s) at line %i." + % global_line_counter + ) from None + coord = np.array((x, y, z), "f") + + # occupancy & B factor + if not self.is_pqr: + try: + occupancy = float(line[54:60]) + except Exception: + self._handle_PDB_exception( + "Invalid or missing occupancy", global_line_counter + ) + occupancy = None # Rather than arbitrary zero or one + if occupancy is not None and occupancy < 0: + # TODO - Should this be an error in strict mode? + # self._handle_PDB_exception("Negative occupancy", + # global_line_counter) + # This uses fixed text so the warning occurs once only: + warnings.warn( + "Negative occupancy in one or more atoms", + PDBConstructionWarning, + ) + try: + bfactor = float(line[60:66]) + except Exception: + self._handle_PDB_exception( + "Invalid or missing B factor", global_line_counter + ) + bfactor = 0.0 # PDB uses a default of zero if missing + + elif self.is_pqr: + # Attempt to parse charge and radius fields + try: + pqr_charge = float(line[54:62]) + except Exception: + self._handle_PDB_exception( + "Invalid or missing charge", global_line_counter + ) + pqr_charge = None # Rather than arbitrary zero or one + try: + radius = float(line[62:70]) + except Exception: + self._handle_PDB_exception( + "Invalid or missing radius", global_line_counter + ) + radius = None + if radius is not None and radius < 0: + # In permissive mode raise fatal exception. + message = "Negative atom radius" + self._handle_PDB_exception(message, global_line_counter) + radius = None + + segid = line[72:76] + element = line[76:78].strip().upper() + if current_segid != segid: + current_segid = segid + structure_builder.init_seg(current_segid) + if current_chain_id != chainid: + current_chain_id = chainid + structure_builder.init_chain(current_chain_id) + current_residue_id = residue_id + current_resname = resname + try: + structure_builder.init_residue( + resname, hetero_flag, resseq, icode + ) + except PDBConstructionException as message: + self._handle_PDB_exception(message, global_line_counter) + elif current_residue_id != residue_id or current_resname != resname: + current_residue_id = residue_id + current_resname = resname + try: + structure_builder.init_residue( + resname, hetero_flag, resseq, icode + ) + except PDBConstructionException as message: + self._handle_PDB_exception(message, global_line_counter) + + if not self.is_pqr: + # init atom with pdb fields + try: + structure_builder.init_atom( + name, + coord, + bfactor, + occupancy, + altloc, + fullname, + serial_number, + element, + ) + except PDBConstructionException as message: + self._handle_PDB_exception(message, global_line_counter) + elif self.is_pqr: + try: + structure_builder.init_atom( + name, + coord, + pqr_charge, + radius, + altloc, + fullname, + serial_number, + element, + pqr_charge, + radius, + self.is_pqr, + ) + except PDBConstructionException as message: + self._handle_PDB_exception(message, global_line_counter) + elif record_type == "ANISOU": + continue + elif record_type == "MODEL ": + try: + serial_num = int(line[10:14]) + except Exception: + self._handle_PDB_exception( + "Invalid or missing model serial number", global_line_counter + ) + serial_num = 0 + structure_builder.init_model(current_model_id, serial_num) + current_model_id += 1 + model_open = 1 + current_chain_id = None + current_residue_id = None + elif record_type == "END " or record_type == "CONECT": + # End of atomic data, return the trailer + self.line_counter += local_line_counter + return coords_trailer[local_line_counter:] + elif record_type == "ENDMDL": + model_open = 0 + current_chain_id = None + current_residue_id = None + elif record_type == "SIGUIJ": + continue + elif record_type == "SIGATM": + continue + elif record_type not in allowed_records: + warnings.warn( + f"Ignoring unrecognized record '{record_type}' at line {global_line_counter}", + PDBConstructionWarning, + ) + local_line_counter += 1 + # EOF (does not end in END or CONECT) + self.line_counter = self.line_counter + local_line_counter + return [] From 541a1ca15a4b174ab0b35b614295e6b93c16bdf8 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 20 Mar 2024 13:02:02 +0100 Subject: [PATCH 099/173] no need to remove hetatms again --- src/DockQ/DockQ.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 6b4d271..466e44d 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -876,7 +876,7 @@ def load_PDB(path, chains=[], n_model=0): structure = pdb_parser.get_structure("-", (gzip.open if path.endswith(".gz") else open)(path, "rt")) model = structure[n_model] - remove_hetatms(model) + #remove_hetatms(model) remove_h(model) return model From c6481373ec93e485d3bf95acf55d00307ad609c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wallner?= Date: Wed, 20 Mar 2024 13:39:54 +0100 Subject: [PATCH 100/173] changed to output mapping in the same format as the input, GlobalDockQ is averaged --- src/DockQ/DockQ.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 466e44d..d2f6e82 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -918,7 +918,18 @@ def format_mapping(mapping_str): native_chains = [chain for chain in native_mapping] return mapping, model_chains, native_chains - +def format_mapping_string(chain_mapping, model_first=True): + chain1="" + chain2="" + if model_first: + mapping=sorted([(b,a) for a,b in chain_mapping.items()]) + else: + mapping=sorted(chain_mapping.items()) + for model_chain,native_chain in mapping: #sorted([(b,a) for a,b in chain_mapping.items()]): + chain1+=model_chain + chain2+=native_chain + + return f'{chain1}:{chain2}' #@profile def main(): args = parse_args() @@ -938,7 +949,8 @@ def main(): # permute chains and run on a for loop best_dockq = -1 best_result = None - + best_mapping = None + ref_switch=False native_chain_clusters = group_model_chains( model_structure, native_structure, model_chains, native_chains ) @@ -974,19 +986,23 @@ def main(): if total_dockq > best_dockq: best_dockq = total_dockq best_result = result_this_mapping + best_mapping = chain_map info["model"] = args.model info["native"] = args.native info["best_dockq"] = best_dockq info["best_result"] = best_result - + info["GlobalDockQ"] = best_dockq/len(best_result) + info['best_mapping']=best_mapping + info['best_mapping_str']=f'{format_mapping_string(best_mapping,model_first=not ref_switch)} {best_mapping}' print_results(info, args.short, args.verbose, args.capri_peptide) def print_results(info, short=False, verbose=False, capri_peptide=False): if short: capri_peptide_str = "-capri_peptide" if capri_peptide else "" - print(f"Total DockQ over {len(info['best_result'])} native interfaces: {info['best_dockq']:.3f}") + print(f"Total DockQ over {len(info['best_result'])} native interfaces: {info['GlobalDockQ']:.3f} with {info['best_mapping_str']} model:native mapping") + print(info['best_result']) for chains, results in info["best_result"].items(): print( f"DockQ{capri_peptide_str} {results['DockQ']:.3f} DockQ_F1 {results['DockQ_F1']:.3f} Fnat {results['fnat']:.3f} iRMS {results['irms']:.3f} LRMS {results['Lrms']:.3f} Fnonnat {results['fnonnat']:.3f} {info['native']} {chains[0]} {chains[1]} -> {info['model']} {results['chain1']} {results['chain2']}" From 2562d586851a7ff6e8f46ca0ac3ef4b897ac330a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wallner?= Date: Wed, 20 Mar 2024 13:44:31 +0100 Subject: [PATCH 101/173] added option to optimize on DockQF1 instead of DockQ --- src/DockQ/DockQ.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index d2f6e82..b10a71e 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -57,6 +57,12 @@ def parse_args(): action="store_true", help="Do not align native and model using sequence alignments, but use the numbering of residues instead", ) + parser.add_argument( + "--optDockQF1", + default=False, + action="store_true", + help="optimize on DockQ_F1 instead of DockQ", + ) parser.add_argument( "--mapping", default=None, @@ -979,10 +985,14 @@ def main(): use_CA_only=args.use_CA, capri_peptide=args.capri_peptide, ) - - total_dockq = sum( - [result["DockQ"] for result in result_this_mapping.values()] - ) + if args.optDockQF1: + total_dockq = sum( + [result["DockQ_F1"] for result in result_this_mapping.values()] + ) + else: + total_dockq = sum( + [result["DockQ"] for result in result_this_mapping.values()] + ) if total_dockq > best_dockq: best_dockq = total_dockq best_result = result_this_mapping From d73882674cb166cb5a8fbdc2a72d257675878522 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 20 Mar 2024 13:52:05 +0100 Subject: [PATCH 102/173] fix reverse mapping --- src/DockQ/DockQ.py | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 466e44d..92bd906 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -881,17 +881,24 @@ def load_PDB(path, chains=[], n_model=0): return model -def group_model_chains(model_structure, native_structure, model_chains, native_chains): - alignment_targets = itertools.product(model_chains, native_chains) - native_chain_clusters = {chain: [] for chain in native_chains} - - for model_chain, native_chain in alignment_targets: - aln = align_chains(model_structure[model_chain], native_structure[native_chain]) +def group_chains(query_structure, ref_structure, query_chains, ref_chains): + reverse_map = False + # this might happen e.g. when modelling only part of a large homomer + if len(query_chains) < len(ref_chains): + query_structure, ref_structure = ref_structure, query_structure + query_chains, ref_chains = ref_chains, query_chains + reverse_map = True + + alignment_targets = itertools.product(query_chains, ref_chains) + chain_clusters = {chain: [] for chain in ref_chains} + + for query_chain, ref_chain in alignment_targets: + aln = align_chains(query_structure[query_chain], ref_structure[ref_chain]) alignment = format_alignment(aln) if "." not in alignment["matches"]: # 100% sequence identity, 100% coverage of native sequence in model sequence - native_chain_clusters[native_chain].append(model_chain) - return native_chain_clusters + chain_clusters[ref_chain].append(query_chain) + return chain_clusters, reverse_map def format_mapping(mapping_str): @@ -939,10 +946,10 @@ def main(): best_dockq = -1 best_result = None - native_chain_clusters = group_model_chains( + chain_clusters, reverse_map = group_chains( model_structure, native_structure, model_chains, native_chains ) - all_mappings = itertools.product(*[cluster for cluster in native_chain_clusters.values() if cluster]) + all_mappings = itertools.product(*[cluster for cluster in chain_clusters.values() if cluster]) # remove mappings where the same model chain is present more than once # only if the mapping is supposed to be 1-1 @@ -952,10 +959,14 @@ def main(): ] for mapping in all_mappings: - chain_map = { - native_chain: mapping[i] for i, native_chain in enumerate(native_chains) - } - + if reverse_map: + chain_map = { + mapping[i]: model_chain for i, model_chain in enumerate(model_chains) + } + else: + chain_map = { + native_chain: mapping[i] for i, native_chain in enumerate(native_chains) + } if initial_mapping and not initial_mapping.items() <= chain_map.items(): continue From 7fcd2974aee1719e00b1352b73710e6b07cffd23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wallner?= Date: Wed, 20 Mar 2024 13:52:06 +0100 Subject: [PATCH 103/173] added option to specify the number of allowed mismatches in alignment --- src/DockQ/DockQ.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index b10a71e..f735b2c 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -63,6 +63,12 @@ def parse_args(): action="store_true", help="optimize on DockQ_F1 instead of DockQ", ) + parser.add_argument( + "--allowed_mismatches", + default=0, + type=int, + help="number of allowed mismatches when mapping model sequence to native sequence.", + ) parser.add_argument( "--mapping", default=None, @@ -887,16 +893,24 @@ def load_PDB(path, chains=[], n_model=0): return model -def group_model_chains(model_structure, native_structure, model_chains, native_chains): +def group_model_chains(model_structure, native_structure, model_chains, native_chains,allowed_mismatches=0): alignment_targets = itertools.product(model_chains, native_chains) native_chain_clusters = {chain: [] for chain in native_chains} - + mismatches_={} # for diagnostics for model_chain, native_chain in alignment_targets: aln = align_chains(model_structure[model_chain], native_structure[native_chain]) alignment = format_alignment(aln) - if "." not in alignment["matches"]: + mismatches=alignment["matches"].count('.') + if mismatches > 0 and mismatches < 10: + mismatches_[(model_chain,native_chain)]=mismatches + + if mismatches <= allowed_mismatches: # 100% sequence identity, 100% coverage of native sequence in model sequence native_chain_clusters[native_chain].append(model_chain) + chains_without_match=[native_chain for native_chain in native_chain_clusters if len(native_chain_clusters[native_chain])==0] + if len(chains_without_match): + print(f'For these chains {chains_without_match} no match was found between model and native, try increasing the --allowed_mismatches from {allowed_mismatches}') + print(f'Current number of alignments with 1-10 mismatches: {mismatches_}') return native_chain_clusters @@ -958,7 +972,7 @@ def main(): best_mapping = None ref_switch=False native_chain_clusters = group_model_chains( - model_structure, native_structure, model_chains, native_chains + model_structure, native_structure, model_chains, native_chains,args.allowed_mismatches ) all_mappings = itertools.product(*[cluster for cluster in native_chain_clusters.values() if cluster]) From cffe74f61e6756c1662baa13235dc1b338be1117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wallner?= Date: Wed, 20 Mar 2024 13:59:09 +0100 Subject: [PATCH 104/173] added clash count in calc_DockQ output --- src/DockQ/DockQ.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index f735b2c..2a777b1 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -432,7 +432,7 @@ def calc_DockQ2( info["fnonnat"] = fnonnat info["nonnat_count"] = nonnat_count info["model_total"] = model_total - + info["len1"] = native1_size info["len2"] = native2_size info["class1"] = class1 @@ -484,7 +484,7 @@ def calc_DockQ( atom_for_sup = ("CA", "C", "N", "O", "P") if not use_CA_only else ("CA", "P") fnat_threshold = 4.0 if capri_peptide else 5.0 interface_threshold = 8.0 if capri_peptide else 10.0 - + clash_threshold=2.0 # total number of native contacts is calculated on untouched native structure ref_res_distances = get_residue_distances(ref_chains[0], ref_chains[1], "ref") nat_total = np.nonzero(np.asarray(ref_res_distances) < fnat_threshold**2)[ @@ -590,7 +590,7 @@ def calc_DockQ( info["fnonnat"] = fnonnat info["nonnat_count"] = nonnat_count info["model_total"] = model_total - + info["clashes"]=np.nonzero(np.asarray(sample_res_distances) < clash_threshold**2)[0].shape[0] info["len1"] = ref_group1_size info["len2"] = ref_group2_size info["class1"] = class1 From 81ff6e0fa92dda6b3174858a2ee2f0422b35a725 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 20 Mar 2024 14:04:38 +0100 Subject: [PATCH 105/173] fix reverse mapping --- src/DockQ/DockQ.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 92bd906..b801f34 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -961,7 +961,7 @@ def main(): for mapping in all_mappings: if reverse_map: chain_map = { - mapping[i]: model_chain for i, model_chain in enumerate(model_chains) + mapping[i]: model_chain for i, model_chain in enumerate(model_chains) } else: chain_map = { From 234bf3e732662251dfc03f419e7e943f5e2d1e68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wallner?= Date: Wed, 20 Mar 2024 14:05:12 +0100 Subject: [PATCH 106/173] added a custom map to handle MSE and CME residues, possible that we should have more types here --- src/DockQ/DockQ.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 2a777b1..46d925f 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -612,7 +612,7 @@ def dockq_formula(fnat, irms, Lrms): @lru_cache -def align_chains(model_chain, native_chain, use_numbering=False): +def align_chains(model_chain, native_chain, use_numbering=False,verbose=False): """ Function to align two PDB structures. This can be done by sequence (default) or by numbering. If the numbering is used, then each residue number from the pdb structure @@ -639,14 +639,15 @@ def align_chains(model_chain, native_chain, use_numbering=False): native_sequence = "".join([chr(resn + min_resn) for resn in native_numbering]) else: + custom_map={'MSE':'M','CME':'C'} model_sequence = [residue.get_resname() for residue in model_chain.get_residues()] native_sequence = [residue.get_resname() for residue in native_chain.get_residues()] model_sequence = "".join( - seq1(r) if len(r) == 3 else r[:-1] if (len(r) == 2) else r for r in model_sequence + seq1(r,custom_map=custom_map) if len(r) == 3 else r[:-1] if (len(r) == 2) else r for r in model_sequence ) native_sequence = "".join( - seq1(r) if len(r) == 3 else r[:-1] if len(r) == 2 else r for r in native_sequence + seq1(r,custom_map=custom_map) if len(r) == 3 else r[:-1] if len(r) == 2 else r for r in native_sequence ) aligner = Align.PairwiseAligner() From 92b5207ea3adfff9749259dd0ccd5421fd217a99 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 20 Mar 2024 14:33:09 +0100 Subject: [PATCH 107/173] simplify --- src/DockQ/DockQ.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 0bd70ea..8d9a845 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -1150,14 +1150,11 @@ def main(): use_CA_only=args.use_CA, capri_peptide=args.capri_peptide, ) - if args.optDockQF1: - total_dockq = sum( - [result["DockQ_F1"] for result in result_this_mapping.values()] - ) - else: - total_dockq = sum( - [result["DockQ"] for result in result_this_mapping.values()] - ) + + total_dockq = sum( + [result["DockQ_F1" if args.optDockQF1 else "DockQ"] for result in result_this_mapping.values()] + ) + if total_dockq > best_dockq: best_dockq = total_dockq best_result = result_this_mapping From 9e1f3273bf5437ddef477b1ab3edf4509a3f69c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wallner?= Date: Wed, 20 Mar 2024 14:55:50 +0100 Subject: [PATCH 108/173] adding mapping string to short output and switch order to model.pdb native.pdb also in the short output --- src/DockQ/DockQ.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 8d9a845..b300247 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -1028,7 +1028,7 @@ def group_chains( n_mismatches = alignment["matches"].count(".") if n_mismatches > 0 and n_mismatches < 10: - mismatch_dict[(model_chain, native_chain)] = n_mismatches + mismatch_dict[(query_chain, ref_chain)] = n_mismatches if n_mismatches <= allowed_mismatches: # 100% sequence identity, 100% coverage of native sequence in model sequence @@ -1176,12 +1176,11 @@ def print_results(info, short=False, verbose=False, capri_peptide=False): print( f"Total DockQ over {len(info['best_result'])} native interfaces: {info['GlobalDockQ']:.3f} with {info['best_mapping_str']} model:native mapping" ) - print(info["best_result"]) + #print(info["best_result"]) for chains, results in info["best_result"].items(): print( - f"DockQ{capri_peptide_str} {results['DockQ']:.3f} DockQ_F1 {results['DockQ_F1']:.3f} Fnat {results['fnat']:.3f} iRMS {results['irms']:.3f} LRMS {results['Lrms']:.3f} Fnonnat {results['fnonnat']:.3f} {info['native']} {chains[0]} {chains[1]} -> {info['model']} {results['chain1']} {results['chain2']}" + f"DockQ{capri_peptide_str} {results['DockQ']:.3f} DockQ_F1 {results['DockQ_F1']:.3f} Fnat {results['fnat']:.3f} iRMS {results['irms']:.3f} LRMS {results['Lrms']:.3f} Fnonnat {results['fnonnat']:.3f} mapping {results['chain1']}{results['chain2']}:{chains[0]}{chains[1]} {info['model']} {results['chain1']} {results['chain2']} -> {info['native']} {chains[0]} {chains[1]}" ) - else: print_header(verbose, capri_peptide) print(f"Model : {info['model']}") From 0558ba155c4402754e1ae7b9b9a8e286bfb03a55 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 20 Mar 2024 15:02:27 +0100 Subject: [PATCH 109/173] still remove HETATMS in cifs --- src/DockQ/DockQ.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 8d9a845..0a8b31b 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -1002,8 +1002,8 @@ def load_PDB(path, chains=[], n_model=0): "-", (gzip.open if path.endswith(".gz") else open)(path, "rt") ) model = structure[n_model] + remove_hetatms(model) - # remove_hetatms(model) remove_h(model) return model @@ -1166,7 +1166,7 @@ def main(): info["best_result"] = best_result info["GlobalDockQ"] = best_dockq / len(best_result) info["best_mapping"] = best_mapping - info["best_mapping_str"] = f"{format_mapping_string(best_mapping)} {best_mapping}" + info["best_mapping_str"] = f"{format_mapping_string(best_mapping)}" print_results(info, args.short, args.verbose, args.capri_peptide) @@ -1176,7 +1176,6 @@ def print_results(info, short=False, verbose=False, capri_peptide=False): print( f"Total DockQ over {len(info['best_result'])} native interfaces: {info['GlobalDockQ']:.3f} with {info['best_mapping_str']} model:native mapping" ) - print(info["best_result"]) for chains, results in info["best_result"].items(): print( f"DockQ{capri_peptide_str} {results['DockQ']:.3f} DockQ_F1 {results['DockQ_F1']:.3f} Fnat {results['fnat']:.3f} iRMS {results['irms']:.3f} LRMS {results['Lrms']:.3f} Fnonnat {results['fnonnat']:.3f} {info['native']} {chains[0]} {chains[1]} -> {info['model']} {results['chain1']} {results['chain2']}" From 28302efcab0b71a1a6c6d4b47f60cee96ace314e Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 21 Mar 2024 14:50:14 +0100 Subject: [PATCH 110/173] skip combinatorials when complete mapping is provided, avoid products with repeats --- src/DockQ/DockQ.py | 79 ++++++++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 30 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index c415d04..ce8c6e9 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -13,7 +13,7 @@ from Bio import Align from Bio.SeqUtils import seq1 from Bio.SVDSuperimposer import SVDSuperimposer -from .parsers import PDBParser +from .parsers import PDBParser, MMCIFParser # fallback in case the cython version doesn't work, though it will be slower try: @@ -935,7 +935,7 @@ def run_on_chains( alignment = format_alignment(aln) alignments.append(tuple(alignment.values())) - info = calc_DockQ( + info = calc_DockQ2( model_chains, native_chains, alignments=tuple(alignments), @@ -986,7 +986,7 @@ def run_on_all_native_interfaces( return results_dic -# @profile +#@profile def load_PDB(path, chains=[], n_model=0): try: pdb_parser = PDBParser(QUIET=True) @@ -997,14 +997,14 @@ def load_PDB(path, chains=[], n_model=0): ) model = structure[n_model] except Exception: - pdb_parser = Bio.PDB.MMCIFParser(QUIET=True) + pdb_parser = MMCIFParser(QUIET=True) structure = pdb_parser.get_structure( - "-", (gzip.open if path.endswith(".gz") else open)(path, "rt") + "-", (gzip.open if path.endswith(".gz") else open)(path, "rt"), + chains=None, ) model = structure[n_model] - remove_hetatms(model) - remove_h(model) + #remove_h(model) return model @@ -1090,19 +1090,33 @@ def format_mapping_string(chain_mapping): return f"{chain1}:{chain2}" -# @profile +def product_without_dupl(*args, repeat=1): + pools = [tuple(pool) for pool in args] * repeat + result = [[]] + for pool in pools: + result = [x+[y] for x in result for y in pool if y not in x] # here we added condition + #result = set(list(map(lambda x: tuple(sorted(x)), result))) # to remove symmetric duplicates + for prod in result: + yield tuple(prod) + + +#@profile def main(): args = parse_args() initial_mapping, model_chains, native_chains = format_mapping(args.mapping) - + model_structure = load_PDB(args.model, chains=model_chains) native_structure = load_PDB(args.native, chains=native_chains) + + group_and_combine = False + if not model_chains or not native_chains: + group_and_combine = True + model_chains = [c.id for c in model_structure] if not model_chains else model_chains + native_chains = ( + [c.id for c in native_structure] if not native_chains else native_chains + ) info = {} - model_chains = [c.id for c in model_structure] if not model_chains else model_chains - native_chains = ( - [c.id for c in native_structure] if not native_chains else native_chains - ) if len(model_chains) < 2 or len(native_chains) < 2: print("Need at least two chains in the two inputs\n") @@ -1112,24 +1126,29 @@ def main(): best_dockq = -1 best_result = None - chain_clusters, reverse_map = group_chains( - model_structure, - native_structure, - model_chains, - native_chains, - args.allowed_mismatches, - ) - all_mappings = itertools.product( - *[cluster for cluster in chain_clusters.values() if cluster] - ) + if group_and_combine: + chain_clusters, reverse_map = group_chains( + model_structure, + native_structure, + model_chains, + native_chains, + args.allowed_mismatches, + ) + all_mappings = product_without_dupl( + *[cluster for cluster in chain_clusters.values() if cluster] + ) + #print([cluster for cluster in chain_clusters.values() if cluster]) + else: + all_mappings = [list(initial_mapping.values())] + reverse_map = False # remove mappings where the same model chain is present more than once # only if the mapping is supposed to be 1-1 - if len(model_chains) == len(native_chains): - all_mappings = [ - element for element in all_mappings if len(set(element)) == len(element) - ] - + #if len(model_chains) == len(native_chains): + # all_mappings = [ + # element for element in all_mappings if len(set(element)) == len(element) + # ] + # print(list(set(all_mappings))) for mapping in all_mappings: if reverse_map: chain_map = { @@ -1139,8 +1158,8 @@ def main(): chain_map = { native_chain: mapping[i] for i, native_chain in enumerate(native_chains) } - if initial_mapping and not initial_mapping.items() <= chain_map.items(): - continue + #if initial_mapping and not initial_mapping.items() <= chain_map.items(): + # continue result_this_mapping = run_on_all_native_interfaces( model_structure, From e0c604cda1144a01b3ce749ff25b35c8def3e1d9 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 21 Mar 2024 15:38:19 +0100 Subject: [PATCH 111/173] MMcif parser --- src/DockQ/parsers.py | 354 ++++++++++++++++++++++++++++++++----------- 1 file changed, 265 insertions(+), 89 deletions(-) diff --git a/src/DockQ/parsers.py b/src/DockQ/parsers.py index bc809fd..b3948fd 100644 --- a/src/DockQ/parsers.py +++ b/src/DockQ/parsers.py @@ -1,9 +1,231 @@ +import warnings import numpy as np +import Bio +from Bio.PDB.MMCIF2Dict import MMCIF2Dict from Bio.PDB.StructureBuilder import StructureBuilder from Bio.PDB.PDBExceptions import PDBConstructionWarning from Bio.PDB.PDBParser import as_handle -import Bio -import warnings + + +class MMCIFParser(Bio.PDB.MMCIFParser): + def get_structure(self, structure_id, filename, chains=[]): + """Return the structure. + + Arguments: + - structure_id - string, the id that will be used for the structure + - filename - name of mmCIF file, OR an open text mode file handle + + """ + self.auth_chains = True + self.auth_residues = True + with warnings.catch_warnings(): + if self.QUIET: + warnings.filterwarnings("ignore", category=PDBConstructionWarning) + self._mmcif_dict = MMCIF2Dict(filename) + self._build_structure(structure_id, chains) + self._structure_builder.set_header(self._get_header()) + + return self._structure_builder.get_structure() + + + def _build_structure(self, structure_id, chains): + # two special chars as placeholders in the mmCIF format + # for item values that cannot be explicitly assigned + # see: pdbx/mmcif syntax web page + _unassigned = {".", "?"} + + mmcif_dict = self._mmcif_dict + + atom_serial_list = mmcif_dict["_atom_site.id"] + atom_id_list = mmcif_dict["_atom_site.label_atom_id"] + residue_id_list = mmcif_dict["_atom_site.label_comp_id"] + try: + element_list = mmcif_dict["_atom_site.type_symbol"] + except KeyError: + element_list = None + if self.auth_chains: + chain_id_list = mmcif_dict["_atom_site.auth_asym_id"] + else: + chain_id_list = mmcif_dict["_atom_site.label_asym_id"] + x_list = [float(x) for x in mmcif_dict["_atom_site.Cartn_x"]] + y_list = [float(x) for x in mmcif_dict["_atom_site.Cartn_y"]] + z_list = [float(x) for x in mmcif_dict["_atom_site.Cartn_z"]] + alt_list = mmcif_dict["_atom_site.label_alt_id"] + icode_list = mmcif_dict["_atom_site.pdbx_PDB_ins_code"] + b_factor_list = mmcif_dict["_atom_site.B_iso_or_equiv"] + occupancy_list = mmcif_dict["_atom_site.occupancy"] + fieldname_list = mmcif_dict["_atom_site.group_PDB"] + try: + serial_list = [int(n) for n in mmcif_dict["_atom_site.pdbx_PDB_model_num"]] + except KeyError: + # No model number column + serial_list = None + except ValueError: + # Invalid model number (malformed file) + raise PDBConstructionException("Invalid model number") from None + try: + aniso_u11 = mmcif_dict["_atom_site_anisotrop.U[1][1]"] + aniso_u12 = mmcif_dict["_atom_site_anisotrop.U[1][2]"] + aniso_u13 = mmcif_dict["_atom_site_anisotrop.U[1][3]"] + aniso_u22 = mmcif_dict["_atom_site_anisotrop.U[2][2]"] + aniso_u23 = mmcif_dict["_atom_site_anisotrop.U[2][3]"] + aniso_u33 = mmcif_dict["_atom_site_anisotrop.U[3][3]"] + aniso_flag = 1 + except KeyError: + # no anisotropic B factors + aniso_flag = 0 + + if self.auth_residues: + # if auth_seq_id is present, we use this. + # Otherwise label_seq_id is used. + if "_atom_site.auth_seq_id" in mmcif_dict: + seq_id_list = mmcif_dict["_atom_site.auth_seq_id"] + else: + seq_id_list = mmcif_dict["_atom_site.label_seq_id"] + else: + seq_id_list = mmcif_dict["_atom_site.label_seq_id"] + # Now loop over atoms and build the structure + current_chain_id = None + current_residue_id = None + current_resname = None + structure_builder = self._structure_builder + structure_builder.init_structure(structure_id) + structure_builder.init_seg(" ") + # Historically, Biopython PDB parser uses model_id to mean array index + # so serial_id means the Model ID specified in the file + current_model_id = -1 + current_serial_id = -1 + for i in range(len(atom_id_list)): + chainid = chain_id_list[i] + if chains and chainid not in chains: + continue + fieldname = fieldname_list[i] + if fieldname == "HETATM": + continue + element = element_list[i].upper() if element_list else None + if element == "H": + continue + # set the line_counter for 'ATOM' lines only and not + # as a global line counter found in the PDBParser() + structure_builder.set_line_counter(i) + + # Try coercing serial to int, for compatibility with PDBParser + # But do not quit if it fails. mmCIF format specs allow strings. + try: + serial = int(atom_serial_list[i]) + except ValueError: + serial = atom_serial_list[i] + warnings.warn( + "PDBConstructionWarning: Some atom serial numbers are not numerical", + PDBConstructionWarning, + ) + + x = x_list[i] + y = y_list[i] + z = z_list[i] + resname = residue_id_list[i] + + altloc = alt_list[i] + if altloc in _unassigned: + altloc = " " + resseq = seq_id_list[i] + if resseq == ".": + # Non-existing residue ID + try: + msg_resseq = mmcif_dict["_atom_site.auth_seq_id"][i] + msg = f"Non-existing residue ID in chain '{chainid}', residue '{msg_resseq}'" + except (KeyError, IndexError): + msg = f"Non-existing residue ID in chain '{chainid}'" + warnings.warn( + "PDBConstructionWarning: " + msg, + PDBConstructionWarning, + ) + continue + int_resseq = int(resseq) + icode = icode_list[i] + if icode in _unassigned: + icode = " " + name = atom_id_list[i] + # occupancy & B factor + try: + tempfactor = float(b_factor_list[i]) + except ValueError: + raise PDBConstructionException("Invalid or missing B factor") from None + try: + occupancy = float(occupancy_list[i]) + except ValueError: + raise PDBConstructionException("Invalid or missing occupancy") from None + hetatm_flag = " " + + resseq = (hetatm_flag, int_resseq, icode) + + if serial_list is not None: + # model column exists; use it + serial_id = serial_list[i] + if current_serial_id != serial_id: + # if serial changes, update it and start new model + current_serial_id = serial_id + current_model_id += 1 + structure_builder.init_model(current_model_id, current_serial_id) + current_chain_id = None + current_residue_id = None + current_resname = None + else: + # no explicit model column; initialize single model + structure_builder.init_model(current_model_id) + + if current_chain_id != chainid: + current_chain_id = chainid + structure_builder.init_chain(current_chain_id) + current_residue_id = None + current_resname = None + + if current_residue_id != resseq or current_resname != resname: + current_residue_id = resseq + current_resname = resname + structure_builder.init_residue(resname, hetatm_flag, int_resseq, icode) + + coord = np.array((x, y, z), "f") + + structure_builder.init_atom( + name, + coord, + tempfactor, + occupancy, + altloc, + name, + serial_number=serial, + element=element, + ) + if aniso_flag == 1 and i < len(aniso_u11): + u = ( + aniso_u11[i], + aniso_u12[i], + aniso_u13[i], + aniso_u22[i], + aniso_u23[i], + aniso_u33[i], + ) + mapped_anisou = [float(_) for _ in u] + anisou_array = np.array(mapped_anisou, "f") + structure_builder.set_anisou(anisou_array) + # Now try to set the cell + try: + a = float(mmcif_dict["_cell.length_a"][0]) + b = float(mmcif_dict["_cell.length_b"][0]) + c = float(mmcif_dict["_cell.length_c"][0]) + alpha = float(mmcif_dict["_cell.angle_alpha"][0]) + beta = float(mmcif_dict["_cell.angle_beta"][0]) + gamma = float(mmcif_dict["_cell.angle_gamma"][0]) + cell = np.array((a, b, c, alpha, beta, gamma), "f") + spacegroup = mmcif_dict["_symmetry.space_group_name_H-M"][0] + spacegroup = spacegroup[1:-1] # get rid of quotes!! + if spacegroup is None: + raise Exception + structure_builder.set_symmetry(spacegroup, cell) + except Exception: + pass # no cell found, so just ignore + class PDBParser(Bio.PDB.PDBParser): def get_structure(self, id, file, chains): @@ -81,6 +303,9 @@ def _parse_coordinates(self, coords_trailer, chains=[]): chainid = line[21] if chains and chainid not in chains: continue + element = line[76:78].strip().upper() + if element == "H": + continue fullname = line[12:16] # get rid of whitespace in atom names split_list = fullname.split() @@ -99,13 +324,7 @@ def _parse_coordinates(self, coords_trailer, chains=[]): serial_number = 0 resseq = int(line[22:26].split()[0]) # sequence identifier icode = line[26] # insertion code - if record_type == "HETATM": # hetero atom flag - if resname == "HOH" or resname == "WAT": - hetero_flag = "W" - else: - hetero_flag = "H" - else: - hetero_flag = " " + hetero_flag = " " residue_id = (hetero_flag, resseq, icode) # atomic coordinates try: @@ -121,56 +340,31 @@ def _parse_coordinates(self, coords_trailer, chains=[]): ) from None coord = np.array((x, y, z), "f") - # occupancy & B factor - if not self.is_pqr: - try: - occupancy = float(line[54:60]) - except Exception: - self._handle_PDB_exception( - "Invalid or missing occupancy", global_line_counter - ) - occupancy = None # Rather than arbitrary zero or one - if occupancy is not None and occupancy < 0: - # TODO - Should this be an error in strict mode? - # self._handle_PDB_exception("Negative occupancy", - # global_line_counter) - # This uses fixed text so the warning occurs once only: - warnings.warn( - "Negative occupancy in one or more atoms", - PDBConstructionWarning, - ) - try: - bfactor = float(line[60:66]) - except Exception: - self._handle_PDB_exception( - "Invalid or missing B factor", global_line_counter - ) - bfactor = 0.0 # PDB uses a default of zero if missing - - elif self.is_pqr: - # Attempt to parse charge and radius fields - try: - pqr_charge = float(line[54:62]) - except Exception: - self._handle_PDB_exception( - "Invalid or missing charge", global_line_counter - ) - pqr_charge = None # Rather than arbitrary zero or one - try: - radius = float(line[62:70]) - except Exception: - self._handle_PDB_exception( - "Invalid or missing radius", global_line_counter - ) - radius = None - if radius is not None and radius < 0: - # In permissive mode raise fatal exception. - message = "Negative atom radius" - self._handle_PDB_exception(message, global_line_counter) - radius = None + try: + occupancy = float(line[54:60]) + except Exception: + self._handle_PDB_exception( + "Invalid or missing occupancy", global_line_counter + ) + occupancy = None # Rather than arbitrary zero or one + if occupancy is not None and occupancy < 0: + # TODO - Should this be an error in strict mode? + # self._handle_PDB_exception("Negative occupancy", + # global_line_counter) + # This uses fixed text so the warning occurs once only: + warnings.warn( + "Negative occupancy in one or more atoms", + PDBConstructionWarning, + ) + try: + bfactor = float(line[60:66]) + except Exception: + self._handle_PDB_exception( + "Invalid or missing B factor", global_line_counter + ) + bfactor = 0.0 # PDB uses a default of zero if missing segid = line[72:76] - element = line[76:78].strip().upper() if current_segid != segid: current_segid = segid structure_builder.init_seg(current_segid) @@ -195,38 +389,20 @@ def _parse_coordinates(self, coords_trailer, chains=[]): except PDBConstructionException as message: self._handle_PDB_exception(message, global_line_counter) - if not self.is_pqr: - # init atom with pdb fields - try: - structure_builder.init_atom( - name, - coord, - bfactor, - occupancy, - altloc, - fullname, - serial_number, - element, - ) - except PDBConstructionException as message: - self._handle_PDB_exception(message, global_line_counter) - elif self.is_pqr: - try: - structure_builder.init_atom( - name, - coord, - pqr_charge, - radius, - altloc, - fullname, - serial_number, - element, - pqr_charge, - radius, - self.is_pqr, - ) - except PDBConstructionException as message: - self._handle_PDB_exception(message, global_line_counter) + # init atom with pdb fields + try: + structure_builder.init_atom( + name, + coord, + bfactor, + occupancy, + altloc, + fullname, + serial_number, + element, + ) + except PDBConstructionException as message: + self._handle_PDB_exception(message, global_line_counter) elif record_type == "ANISOU": continue elif record_type == "MODEL ": From b84be47d93e1971ceffefe8390594a90bb453329 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 21 Mar 2024 16:25:50 +0100 Subject: [PATCH 112/173] only combine non-fixed chains --- src/DockQ/DockQ.py | 59 +++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index ce8c6e9..d647839 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -935,7 +935,7 @@ def run_on_chains( alignment = format_alignment(aln) alignments.append(tuple(alignment.values())) - info = calc_DockQ2( + info = calc_DockQ( model_chains, native_chains, alignments=tuple(alignments), @@ -1048,7 +1048,7 @@ def group_chains( def format_mapping(mapping_str): - mapping = None + mapping = dict() model_chains = None native_chains = None if not mapping_str: @@ -1104,17 +1104,13 @@ def product_without_dupl(*args, repeat=1): def main(): args = parse_args() initial_mapping, model_chains, native_chains = format_mapping(args.mapping) - model_structure = load_PDB(args.model, chains=model_chains) native_structure = load_PDB(args.native, chains=native_chains) - group_and_combine = False - if not model_chains or not native_chains: - group_and_combine = True - model_chains = [c.id for c in model_structure] if not model_chains else model_chains - native_chains = ( - [c.id for c in native_structure] if not native_chains else native_chains - ) + model_chains = [c.id for c in model_structure] if not model_chains else model_chains + native_chains = ( + [c.id for c in native_structure] if not native_chains else native_chains + ) info = {} @@ -1125,22 +1121,22 @@ def main(): # permute chains and run on a for loop best_dockq = -1 best_result = None + model_chains_to_combo = [mc for mc in model_chains if mc not in initial_mapping.values()] + native_chains_to_combo = [nc for nc in native_chains if nc not in initial_mapping.keys()] + + chain_clusters, reverse_map = group_chains( + model_structure, + native_structure, + model_chains_to_combo, + native_chains_to_combo, + args.allowed_mismatches, + ) - if group_and_combine: - chain_clusters, reverse_map = group_chains( - model_structure, - native_structure, - model_chains, - native_chains, - args.allowed_mismatches, - ) - all_mappings = product_without_dupl( - *[cluster for cluster in chain_clusters.values() if cluster] - ) + all_mappings = product_without_dupl( + *[cluster for cluster in chain_clusters.values() if cluster] + ) + #print(len(list(all_mappings))) #print([cluster for cluster in chain_clusters.values() if cluster]) - else: - all_mappings = [list(initial_mapping.values())] - reverse_map = False # remove mappings where the same model chain is present more than once # only if the mapping is supposed to be 1-1 @@ -1150,16 +1146,15 @@ def main(): # ] # print(list(set(all_mappings))) for mapping in all_mappings: + chain_map = {key:value for key, value in initial_mapping.items()} if reverse_map: - chain_map = { - mapping[i]: model_chain for i, model_chain in enumerate(model_chains) - } + chain_map.update({ + mapping[i]: model_chain for i, model_chain in enumerate(model_chains_to_combo) + }) else: - chain_map = { - native_chain: mapping[i] for i, native_chain in enumerate(native_chains) - } - #if initial_mapping and not initial_mapping.items() <= chain_map.items(): - # continue + chain_map.update({ + native_chain: mapping[i] for i, native_chain in enumerate(native_chains_to_combo) + }) result_this_mapping = run_on_all_native_interfaces( model_structure, From 0a9d4dbf3ccecae921e8c26f00f917c8ae330460 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wallner?= Date: Fri, 22 Mar 2024 08:06:24 +0100 Subject: [PATCH 113/173] small output changes --- src/DockQ/DockQ.py | 61 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index b300247..6d15c65 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -7,6 +7,7 @@ import itertools from functools import lru_cache, wraps from argparse import ArgumentParser +from tqdm import tqdm import Bio.PDB import numpy as np @@ -1089,6 +1090,32 @@ def format_mapping_string(chain_mapping): return f"{chain1}:{chain2}" +import math +def product_without_dupl(*args, repeat=1): + pools = [tuple(pool) for pool in args] * repeat + result = [[]] + for pool in pools: + result = [x+[y] for x in result for y in pool if y not in x] # here we added condition + #result = set(list(map(lambda x: tuple(sorted(x)), result))) # to remove symmetric duplicates + for prod in result: + yield tuple(prod) +def chain_combinations(chain_clusters): + counts={} + for chain in chain_clusters: + chains=tuple(chain_clusters[chain]) + if chains not in counts: + counts[chains]=0 + counts[chains]+=1 + #set(chain_clusters.values()) + + combos=itertools.product(*[itertools.permutations(chains) for chains in set([tuple(ch) for ch in chain_clusters.values()])]) + + + print(len(list(combos))) + sys.exit() + number_of_combinations=np.prod([math.factorial(a) for a in counts.values()]) + print(number_of_combinations) + # @profile def main(): @@ -1098,6 +1125,7 @@ def main(): model_structure = load_PDB(args.model, chains=model_chains) native_structure = load_PDB(args.native, chains=native_chains) + info = {} model_chains = [c.id for c in model_structure] if not model_chains else model_chains native_chains = ( @@ -1119,18 +1147,41 @@ def main(): native_chains, args.allowed_mismatches, ) + + if args.verbose: + print(chain_clusters) + number_of_chain_combinations(chain_clusters) + all_mappings = itertools.product( *[cluster for cluster in chain_clusters.values() if cluster] ) + all_mappings = product_without_dupl( + *[cluster for cluster in chain_clusters.values() if cluster] + ) + + all_mappings = itertools.product( + *[itertools.permutations(chains) for chains in set([tuple(ch) for ch in chain_clusters.values()])]) + #print(len(list(all_mappings))) + #sys.exit() + # remove mappings where the same model chain is present more than once # only if the mapping is supposed to be 1-1 if len(model_chains) == len(native_chains): + #unique_mappings=set() + #for element in tqdm(all_mappings): + # if element not in unique_mappings: + # unique_mappings.add(element) + all_mappings = [ - element for element in all_mappings if len(set(element)) == len(element) + element for element in tqdm(list(all_mappings)) if len(set(element)) == len(element) ] - - for mapping in all_mappings: + + #print(all_mappings) + def progressbar(l): + return tqdm(l,desc='Chain combinations') if len(l) > 1 else l + + for mapping in progressbar(list(all_mappings)): if reverse_map: chain_map = { mapping[i]: model_chain for i, model_chain in enumerate(model_chains) @@ -1176,10 +1227,10 @@ def print_results(info, short=False, verbose=False, capri_peptide=False): print( f"Total DockQ over {len(info['best_result'])} native interfaces: {info['GlobalDockQ']:.3f} with {info['best_mapping_str']} model:native mapping" ) - #print(info["best_result"]) + print(info["best_result"]) for chains, results in info["best_result"].items(): print( - f"DockQ{capri_peptide_str} {results['DockQ']:.3f} DockQ_F1 {results['DockQ_F1']:.3f} Fnat {results['fnat']:.3f} iRMS {results['irms']:.3f} LRMS {results['Lrms']:.3f} Fnonnat {results['fnonnat']:.3f} mapping {results['chain1']}{results['chain2']}:{chains[0]}{chains[1]} {info['model']} {results['chain1']} {results['chain2']} -> {info['native']} {chains[0]} {chains[1]}" + f"DockQ{capri_peptide_str} {results['DockQ']:.3f} DockQ_F1 {results['DockQ_F1']:.3f} Fnat {results['fnat']:.3f} iRMS {results['irms']:.3f} LRMS {results['Lrms']:.3f} Fnonnat {results['fnonnat']:.3f} clashes {results['clashes']} mapping {results['chain1']}{results['chain2']}:{chains[0]}{chains[1]} {info['model']} {results['chain1']} {results['chain2']} -> {info['native']} {chains[0]} {chains[1]}" ) else: print_header(verbose, capri_peptide) From a85adfcc32e3b8afefccb491839336f31eb97275 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 22 Mar 2024 10:45:13 +0100 Subject: [PATCH 114/173] Enable CI --- .github/workflows/main.yml | 19 +++++++++++++++++++ run_test.sh | 11 +++++++++++ test | 0 3 files changed, 30 insertions(+) create mode 100644 .github/workflows/main.yml create mode 100644 run_test.sh delete mode 100644 test diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..4812957 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,19 @@ +name: CI + +on: [push, pull_request, workflow_dispatch] + +jobs: + test: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + runs-on: ubuntu-latest + timeout-minutes: 10 + defaults: + run: + shell: bash -l {0} + + steps: + - uses: actions/checkout@v3 + - name: Test pipeline output + run: | + python -m pip install . + ./run_test.sh diff --git a/run_test.sh b/run_test.sh new file mode 100644 index 0000000..75dcfeb --- /dev/null +++ b/run_test.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -euo pipefail + +DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb +DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align +DockQ examples/model2.pdb examples/native2.pdb +DockQ examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short +DockQ examples/model.pdb examples/native.pdb --allowed_mismatches 1 +DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping AB*:BA* +DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping :ABC +DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping ABCDEFGH:BADCFEHG diff --git a/test b/test deleted file mode 100644 index e69de29..0000000 From 3670bdbb15bb718eda30f3626c4cec62c3315070 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 22 Mar 2024 10:46:48 +0100 Subject: [PATCH 115/173] avoid permission denied --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4812957..9f7cdd7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -16,4 +16,4 @@ jobs: - name: Test pipeline output run: | python -m pip install . - ./run_test.sh + bash ./run_test.sh From 6b17fa5074446126d15d5d8211aad4afd27c2aa5 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 22 Mar 2024 10:48:42 +0100 Subject: [PATCH 116/173] missing library --- pyproject.toml | 2 +- setup.cfg | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index fb41b01..d29aa11 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [build-system] name = "DockQ" version = "2.0" -requires = ["setuptools", "cython", "numpy ~= 1.21", "biopython >= 1.79"] +requires = ["setuptools", "cython", "tqdm", "numpy ~= 1.21", "biopython >= 1.79"] build-backend = "setuptools.build_meta" diff --git a/setup.cfg b/setup.cfg index 7a1cefc..c115d82 100644 --- a/setup.cfg +++ b/setup.cfg @@ -9,6 +9,7 @@ packages = find: install_requires = setuptools cython + tqdm numpy~=1.21 biopython>=1.79 From fdcddc289565a0daec1e976060a0ea872104c1e9 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 22 Mar 2024 10:51:19 +0100 Subject: [PATCH 117/173] change flag name --- src/DockQ/DockQ.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 37bb944..1ec0c80 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -57,7 +57,7 @@ def parse_args(): help="use CA instead of backbone", ) parser.add_argument( - "--no_needle", + "--no_align", default=False, action="store_true", help="Do not align native and model using sequence alignments, but use the numbering of residues instead", @@ -921,7 +921,7 @@ def get_interface_atoms( def run_on_chains( model_chains, native_chains, - no_needle=False, + no_align=False, use_CA_only=False, capri_peptide=False, ): @@ -931,7 +931,7 @@ def run_on_chains( aln = align_chains( model_chain, native_chain, - use_numbering=no_needle, + use_numbering=no_align, ) alignment = format_alignment(aln) alignments.append(tuple(alignment.values())) @@ -950,7 +950,7 @@ def run_on_all_native_interfaces( model_structure, native_structure, chain_map={"A": "A", "B": "B"}, - no_needle=False, + no_align=False, use_CA_only=False, capri_peptide=False, ): @@ -973,7 +973,7 @@ def run_on_all_native_interfaces( info = run_on_chains( model_chains, native_chains, - no_needle=no_needle, + no_align=no_align, use_CA_only=use_CA_only, capri_peptide=capri_peptide, ) @@ -1186,7 +1186,7 @@ def progressbar(l): model_structure, native_structure, chain_map=chain_map, - no_needle=args.no_needle, + no_align=args.no_align, use_CA_only=args.use_CA, capri_peptide=args.capri_peptide, ) From 944caddba37966408fac30a7c7350fa63b3ffbb2 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 22 Mar 2024 10:54:09 +0100 Subject: [PATCH 118/173] old biopython tests --- .github/workflows/main.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9f7cdd7..62a1b9e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,3 +17,18 @@ jobs: run: | python -m pip install . bash ./run_test.sh + + test_oldbio: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + runs-on: ubuntu-latest + timeout-minutes: 10 + defaults: + run: + shell: bash -l {0} + + steps: + - uses: actions/checkout@v3 + - name: Test pipeline output + run: | + python -m pip install biopython==1.79 + bash ./run_test.sh From 22257d622bc465a6e54477b418d1cc4b5e1f3ae3 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 22 Mar 2024 10:55:02 +0100 Subject: [PATCH 119/173] need to install dockq --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 62a1b9e..aa8d40c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,4 +31,5 @@ jobs: - name: Test pipeline output run: | python -m pip install biopython==1.79 + python -m pip install . bash ./run_test.sh From 59f86aab610babcad2268e2903aa598439734193 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 22 Mar 2024 10:59:23 +0100 Subject: [PATCH 120/173] add badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 89dfb25..a63be8c 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +![CI status](https://github.com/bjornwallner/DockQ/actions/workflows/main.yml/badge.svg) + # DockQ Requires python packages: `numpy` and `Biopython` From cd5ea154b534be5cbbea2c3803576adccc0bdff3 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 22 Mar 2024 11:03:51 +0100 Subject: [PATCH 121/173] redraft README --- README.md | 233 ++++++++++++++---------------------------------------- 1 file changed, 60 insertions(+), 173 deletions(-) diff --git a/README.md b/README.md index a63be8c..45bdc39 100644 --- a/README.md +++ b/README.md @@ -1,66 +1,72 @@ ![CI status](https://github.com/bjornwallner/DockQ/actions/workflows/main.yml/badge.svg) # DockQ -Requires python packages: `numpy` and `Biopython` Installation -Just clone the repository, the main script `DockQ.py` is in the cloned folder: +Clone the repository, then install the necessary libraries with `pip`: ``` git clone https://github.com/bjornwallner/DockQ/ +cd DockQ +pip install . ``` -Install (i) `numpy` (a prerequisite to install 'Biopython') and (ii) `Biopython` - -- Numpy: http://www.scipy.org/install.html -- Biopython: http://biopython.org/wiki/Download#Installation_Instructions - -This version of DockQ has been tested with numpy v1.21.6 and biopython v1.79. - Quick start for two interacting partners (two-chain-models) run with: -`./DockQ.py ` +`DockQ ` Example ``` -bash$ ./DockQ.py examples/model.pdb examples/native.pdb -*********************************************************** -* DockQ * -* Scoring function for protein-protein docking models * -* Statistics on CAPRI data: * -* 0 < DockQ < 0.23 - Incorrect * -* 0.23 <= DockQ < 0.49 - Acceptable quality * -* 0.49 <= DockQ < 0.80 - Medium quality * -* DockQ >= 0.80 - High quality * -* Reference: Sankar Basu and Bjorn Wallner, DockQ:... * -* For comments, please email: bjornw@ifm.liu.se * -*********************************************************** - -Number of equivalent residues in chain A 1492 (receptor) -Number of equivalent residues in chain B 912 (ligand) -Fnat 0.533 32 correct of 60 native contacts -Fnonnat 0.238 10 non-native of 42 model contacts -iRMS 1.232 -LRMS 1.516 -CAPRI Medium -DockQ_CAPRI Medium -DockQ 0.700 - +bash$ DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb + +**************************************************************** +* DockQ * +* Scoring function for protein-protein docking models * +* Statistics on CAPRI data: * +* 0.00 <= DockQ < 0.23 - Incorrect * +* 0.23 <= DockQ < 0.49 - Acceptable quality * +* 0.49 <= DockQ < 0.80 - Medium quality * +* DockQ >= 0.80 - High quality * +* Ref: S. Basu and B. Wallner, DockQ: A quality measure for * +* protein-protein docking models * +* doi:10.1371/journal.pone.0161879 * +* For comments, please email: bjorn.wallner@.liu.se * +**************************************************************** +Model : examples/1A2K_r_l_b.model.pdb +Native : examples/1A2K_r_l_b.pdb +Total DockQ over 3 native interfaces: 1.959 +Native chains: A, B + Model chains: B, A + DockQ_F1: 0.996 + DockQ: 0.994 + irms: 0.000 + Lrms: 0.000 + fnat: 0.983 +Native chains: A, C + Model chains: B, C + DockQ_F1: 0.567 + DockQ: 0.511 + irms: 1.237 + Lrms: 6.864 + fnat: 0.333 +Native chains: B, C + Model chains: A, C + DockQ_F1: 0.500 + DockQ: 0.453 + irms: 2.104 + Lrms: 8.131 + fnat: 0.500 ``` Help page ``` -bash$ ./DockQ.py -h -usage: DockQ.py [-h] [-short] [-verbose] [-useCA] [-skip_check] [-no_needle] - [-perm1] [-perm2] - [-model_chain1 model_chain1 [model_chain1 ...]] - [-model_chain2 model_chain2 [model_chain2 ...]] - [-native_chain1 native_chain1 [native_chain1 ...]] - [-native_chain2 native_chain2 [native_chain2 ...]] - +bash$ DockQ -h + +usage: DockQ [-h] [--capri_peptide] [--short] [--verbose] [--use_CA] [--no_align] [--optDockQF1] [--allowed_mismatches ALLOWED_MISMATCHES] [--mapping MODELCHAINS:NATIVECHAINS] + DockQ - Quality measure for protein-protein docking models @@ -70,138 +76,19 @@ positional arguments: optional arguments: -h, --help show this help message and exit - -short short output - -verbose talk a lot! - -useCA use CA instead of backbone - -skip_check skip initial check fo speed up on two chain examples - -no_needle do not use global alignment to fix residue numbering - between native and model during chain permutation (use - only in case needle is not installed, and the residues - between the chains are identical - -perm1 use all chain1 permutations to find maximum DockQ - (number of comparisons is n! = 24, if combined with - -perm2 there will be n!*m! combinations - -perm2 use all chain2 permutations to find maximum DockQ - (number of comparisons is n! = 24, if combined with - -perm1 there will be n!*m! combinations - -model_chain1 model_chain1 [model_chain1 ...] - pdb chain order to group together partner 1 - -model_chain2 model_chain2 [model_chain2 ...] - pdb chain order to group together partner 2 - (complement to partner 1 if undef) - -native_chain1 native_chain1 [native_chain1 ...] - pdb chain order to group together from native partner - 1 - -native_chain2 native_chain2 [native_chain2 ...] - pdb chain order to group together from native partner - 2 (complement to partner 1 if undef) - - - -``` - - -##### Multi-chain functionality - -For targets with more than two interacting chains. For instance a -dimer interacting with a partner. There are options to control which -chains to group together and also in which order to combine -them. There are also options to try all possible chain combinations -(`-perm1` and `-perm2`), this is important if for instance a homo -oligomer is interacting asymmetrically with a third partner, or if -there are symmetries that make multiple solution possibly correct. - -For this mode to work if there are missing residues the global -alignment program `needle` from the [EMBOSS -package](http://emboss.sourceforge.net/download/) needs to be in your -path, i.e `which needle` should return the location. - -This mode is illustrated by a homodimer that is interacting with a -third partner asymmetrically (A,B) <-> C (1A2K from docking benchmark -5.0). - -The following commands will put the chains A,B as one partner and the -remaining chain, C, as the second partner. It will assume the chain -naming is the same in the model protein: - -`./DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb -native_chain1 A B -model_chain1 A B -native_chain2 C -model_chain2 C` - -Assuming the chains are the same in the model and native it is enough to just specify one set chains to group and the second group will be formed from the complement using the the remaining chains. - -`./DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb -native_chain1 A B` -(chain C is remaining) - -these are also equivalent: - -`./DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb -native_chain1 C` -(chain AB is remaining) - -`./DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb -native_chain1 A B -model_chain1 A B` - -This will reverse the relative chain order of AB, comparing modelBA with nativeAB interacting with chain C: - -`./DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb -native_chain1 A B -model_chain1 B A` (observe how the score increases) - - -To try all permutations for model_chain1, observe at the reverse -mapping BA -> AB gets the best score: - -``` -bash$ ./DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb -native_chain1 A B -perm1 -1/2 AB -> C 0.00972962403319 -Current best 0.00972962403319 -2/2 BA -> C 0.476267208558 -Current best 0.476267208558 -Best score ( 0.476267208558 ) found for model -> native, chain1:BA -> AB chain2:C -> C -*********************************************************** -* DockQ * -* Scoring function for protein-protein docking models * -* Statistics on CAPRI data: * -* 0.00 <= DockQ < 0.23 - Incorrect * -* 0.23 <= DockQ < 0.49 - Acceptable quality * -* 0.49 <= DockQ < 0.80 - Medium quality * -* DockQ >= 0.80 - High quality * -* Reference: Sankar Basu and Bjorn Wallner, DockQ:... * -* For comments, please email: bjornw@ifm.liu.se * -*********************************************************** -Model : examples/1A2K_r_l_b.model.pdb -Native : examples/1A2K_r_l_b.pdb -Best score ( 0.476267208558 ) found for model -> native, chain1:BA -> AB chain2:C -> C -Number of equivalent residues in chain A 248 (receptor) -Number of equivalent residues in chain B 196 (ligand) -Fnat 0.491 26 correct of 53 native contacts -Fnonnat 0.103 3 non-native of 29 model contacts -iRMS 1.988 -LRMS 7.300 -CAPRI Medium -DockQ_CAPRI Acceptable -DockQ 0.476 - + --capri_peptide use version for capri_peptide (DockQ cannot not be trusted for this setting) + --short short output + --verbose, -v talk a lot! + --use_CA, -ca use CA instead of backbone + --no_align Do not align native and model using sequence alignments, but use the numbering of residues instead + --optDockQF1 optimize on DockQ_F1 instead of DockQ + --allowed_mismatches ALLOWED_MISMATCHES + number of allowed mismatches when mapping model sequence to native sequence. + --mapping MODELCHAINS:NATIVECHAINS + Specify a chain mapping between model and native structure. If the native contains two chains "H" and "L" while the model contains two chains "A" and "B", + and chain A is a model of native chain H and chain B is a model of native chain L, the flag can be set as: '--mapping AB:HL'. This can also help limit the + search to specific native interfaces. For example, if the native is a tetramer (ABCD) but the user is only interested in the interface between chains B and + C, the flag can be set as: '--mapping :BC' or the equivalent '--mapping *:BC'. ``` - -To try all permutations for model_chain1 and model_chain2 (ok only 1 chain in this example:-): - -`./DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb -native_chain1 A B -perm1 -perm2` - -For a dimer interacting with one partner this is only 2 (2!\*1!), -however for larger oligomers the number of possible permutations -explodes. For two tetramers the number will be 576 (4!\*4!) - -Multimeric biological assemblies of proteins (of higher order than -that of dimers) are also found in nature to interact: e.g., PDB IDS: -3J07, 4IXZ, 4IY7, 4IYO, 3IYW, 2VQ0, 1E57, 2IZN etc. particularly -common in viral envelopes / capsids. We choose an instance of two -interacting tetramers (1EXB) to further demonstrate the multi-chain -functionality of DockQ - -Tetramer example (24 combinations): - -`./DockQ.py examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb -native_chain1 A B C D -perm1` - -Tetramer example with all possible permutations (576 combinations): - -`./DockQ.py examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb -native_chain1 A B C D -perm1 -perm2` - - From e682be50729723196c042ed7cf2eb17c6d371a88 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 22 Mar 2024 11:14:12 +0100 Subject: [PATCH 122/173] Change license in v2 --- LICENSE | 674 -------------------------------------------------------- 1 file changed, 674 deletions(-) delete mode 100644 LICENSE diff --git a/LICENSE b/LICENSE deleted file mode 100644 index f288702..0000000 --- a/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. From 301a69b8e43d7b83003fe21c106d7e7ab0228e05 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 22 Mar 2024 11:28:30 +0100 Subject: [PATCH 123/173] a few more details --- README.md | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 45bdc39..842416e 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ ![CI status](https://github.com/bjornwallner/DockQ/actions/workflows/main.yml/badge.svg) -# DockQ +# DockQ: A Quality Measure for Protein-Protein Docking Models -Installation +## Installation Clone the repository, then install the necessary libraries with `pip`: @@ -12,15 +12,19 @@ cd DockQ pip install . ``` -Quick start for two interacting partners (two-chain-models) run with: +## Quick start: + +After installing DockQ with `pip`, the `DockQ` binary will be in your path. Just run DockQ with: `DockQ ` -Example +**Example** + +When running DockQ on model/native complexes with one or more interfaces, you will get a result for each interface. Results are computed to maximise the average DockQ across all interface: ``` -bash$ DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb +$ DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb **************************************************************** * DockQ * @@ -61,7 +65,21 @@ Native chains: B, C fnat: 0.500 ``` -Help page +A more compact output option is available with the flag `--short`: + +``` +$ DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --short + +DockQ 0.994 DockQ_F1 0.996 Fnat 0.983 iRMS 0.000 LRMS 0.000 Fnonnat 0.008 clashes 0 mapping BA:AB examples/1A2K_r_l_b.model.pdb B A -> examples/1A2K_r_l_b.pdb A B +DockQ 0.511 DockQ_F1 0.567 Fnat 0.333 iRMS 1.237 LRMS 6.864 Fnonnat 0.000 clashes 0 mapping BC:AC examples/1A2K_r_l_b.model.pdb B C -> examples/1A2K_r_l_b.pdb A C +DockQ 0.453 DockQ_F1 0.500 Fnat 0.500 iRMS 2.104 LRMS 8.131 Fnonnat 0.107 clashes 0 mapping AC:BC examples/1A2K_r_l_b.model.pdb A C -> examples/1A2K_r_l_b.pdb B C + +``` + +**Other uses** + +Run DockQ with `-h/--help` to see a list of the available flags: + ``` bash$ DockQ -h From 340258d54023624acb65088941273e1621ffe26b Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 22 Mar 2024 12:47:24 +0100 Subject: [PATCH 124/173] let parser import even in nocython case --- src/DockQ/DockQ.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 1ec0c80..dd61127 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -14,17 +14,18 @@ from Bio import Align from Bio.SeqUtils import seq1 from Bio.SVDSuperimposer import SVDSuperimposer -from .parsers import PDBParser, MMCIFParser # fallback in case the cython version doesn't work, though it will be slower try: from .operations import residue_distances, get_fnat_stats + from .parsers import PDBParser, MMCIFParser except ImportError: print( - "WARNING: It looks like cython is not working, \ - falling back on native python. This will make DockQ slower" + """WARNING: It looks like cython is not working, + falling back on native python. This will make DockQ slower""" ) from operations_nocy import residue_distances, get_fnat_stats + from parsers import PDBParser, MMCIFParser def parse_args(): From f2c86f8c8faecb9fd369e1d57e475d01cc91bfaa Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 22 Mar 2024 13:21:27 +0100 Subject: [PATCH 125/173] test script runs --- run_test.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/run_test.sh b/run_test.sh index 75dcfeb..464135f 100644 --- a/run_test.sh +++ b/run_test.sh @@ -2,7 +2,9 @@ set -euo pipefail DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb +python src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align +python src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align DockQ examples/model2.pdb examples/native2.pdb DockQ examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short DockQ examples/model.pdb examples/native.pdb --allowed_mismatches 1 From ab93ea26160bc6c87ec91a7941cff8c67436179a Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 22 Mar 2024 13:37:07 +0100 Subject: [PATCH 126/173] testing cif, gz --- examples/1EXB.cif.gz | Bin 0 -> 99594 bytes examples/model2.pdb | 4672 --------------------- examples/native2.pdb | 9274 ------------------------------------------ run_test.sh | 8 +- 4 files changed, 7 insertions(+), 13947 deletions(-) create mode 100644 examples/1EXB.cif.gz delete mode 100644 examples/model2.pdb delete mode 100644 examples/native2.pdb diff --git a/examples/1EXB.cif.gz b/examples/1EXB.cif.gz new file mode 100644 index 0000000000000000000000000000000000000000..e1c5e633e9c6e137ff138131dd206abd1ec79473 GIT binary patch literal 99594 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 Date: Fri, 22 Mar 2024 13:37:20 +0100 Subject: [PATCH 127/173] remove duplicate function --- src/DockQ/DockQ.py | 242 --------------------------------------------- 1 file changed, 242 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index dd61127..5a67763 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -283,248 +283,6 @@ def superimpose(from_atoms, to_atoms): return rot, tran, super_imposer -# @profile -def calc_DockQ2( - model_chains, - native_chains, - alignments, - use_CA_only=False, - capri_peptide=False, -): - atom_for_sup = ("CA", "C", "N", "O") if not use_CA_only else ("CA") - fnat_threshold = 4.0 if capri_peptide else 5.0 - interface_threshold = 8.0 if capri_peptide else 10.0 - - native_atoms_1 = get_atoms(native_chains[0], "native") - native_atoms_2 = get_atoms(native_chains[1], "native") - native_n_atoms_1, native_atom_ids_1 = list_atoms_per_residue2( - native_chains[0], "native" - ) - native_n_atoms_2, native_atom_ids_2 = list_atoms_per_residue2( - native_chains[1], "native" - ) - - native_distances = get_atom_distances( - native_atoms_1, native_atoms_2, (native_n_atoms_1, native_n_atoms_2), "native" - ) - nat_total = np.nonzero(np.asarray(native_distances) < fnat_threshold ** 2)[0].shape[ - 0 - ] - - if nat_total == 0: - return None - - model_atoms_1 = get_atoms(model_chains[0], "model") - model_atoms_2 = get_atoms(model_chains[1], "model") - model_n_atoms_1, model_atom_ids_1 = list_atoms_per_residue2( - model_chains[0], "model" - ) - model_n_atoms_2, model_atom_ids_2 = list_atoms_per_residue2( - model_chains[1], "model" - ) - - ( - model_atom_index_1, - native_atom_index_1, - model_res_index_1, - native_res_index_1, - ) = get_aligned_atoms(model_n_atoms_1, native_n_atoms_1, tuple(alignments[0])) - ( - model_atom_index_2, - native_atom_index_2, - model_res_index_2, - native_res_index_2, - ) = get_aligned_atoms(model_n_atoms_2, native_n_atoms_2, tuple(alignments[1])) - - if len(model_res_index_1) != len(model_chains[0]): - # filter model, native atoms by alignment atom indexes - model_atoms_1 = model_atoms_1[model_atom_index_1] - model_n_atoms_1 = tuple( - [ - n_atoms - for i, n_atoms in enumerate(model_n_atoms_1) - if i in model_res_index_1 - ] - ) - model_atom_ids_1 = tuple( - [ - atom_ids - for i, atom_ids in enumerate(model_atom_ids_1) - if i in model_res_index_1 - ] - ) - - if len(model_res_index_2) != len(model_chains[1]): - model_atoms_2 = model_atoms_2[model_atom_index_2] - model_n_atoms_2 = tuple( - [ - n_atoms - for i, n_atoms in enumerate(model_n_atoms_2) - if i in model_res_index_2 - ] - ) - model_atom_ids_2 = tuple( - [ - atom_ids - for i, atom_ids in enumerate(model_atom_ids_2) - if i in model_res_index_2 - ] - ) - - model_distances = get_atom_distances( - model_atoms_1, model_atoms_2, (model_n_atoms_1, model_n_atoms_2), "model" - ) - # only recalculate distances if model was missing residues compared to native - if len(native_res_index_1) != len(native_chains[0]) or len( - native_res_index_2 - ) != len(native_chains[1]): - native_atoms_1 = native_atoms_1[native_atom_index_1] - native_atoms_2 = native_atoms_1[native_atom_index_2] - native_n_atoms_1 = tuple( - [ - n_atoms - for i, n_atoms in enumerate(native_n_atoms_1) - if i in native_res_index_1 - ] - ) - native_n_atoms_2 = tuple( - [ - n_atoms - for i, n_atoms in enumerate(native_n_atoms_2) - if i in native_res_index_2 - ] - ) - native_atom_ids_1 = tuple( - [ - atom_ids - for i, atom_ids in enumerate(native_atom_ids_1) - if i in native_res_index_1 - ] - ) - native_atom_ids_2 = tuple( - [ - atom_ids - for i, atom_ids in enumerate(native_atom_ids_2) - if i in native_res_index_2 - ] - ) - native_distances = get_atom_distances( - native_atoms_1, - native_atoms_2, - (native_n_atoms_1, native_n_atoms_2), - "native", - ) - - assert ( - model_distances.shape == native_distances.shape - ), f"Native and model have incompatible sizes ({model_distances.shape} != {native_distances.shape})" - - nat_correct, nonnat_count, _, model_total = get_fnat_stats( - model_distances, native_distances, threshold=fnat_threshold - ) - - # avoids divide by 0 errors - fnat = nat_total and nat_correct / nat_total or 0 - fnonnat = model_total and nonnat_count / model_total or 0 - - # filter out backbone atoms now - model_index_1, native_index_1, n_atoms_1 = filter_atoms( - model_atom_ids_1, native_atom_ids_1, filter=atom_for_sup - ) - model_index_2, native_index_2, n_atoms_2 = filter_atoms( - model_atom_ids_2, native_atom_ids_2, filter=atom_for_sup - ) - model_atoms_1 = model_atoms_1[model_index_1] - model_atoms_2 = model_atoms_2[model_index_2] - native_atoms_1 = native_atoms_1[native_index_1] - native_atoms_2 = native_atoms_2[native_index_2] - - # assign which chains constitute the receptor, ligand - native1_size = len(native_chains[0]) - native2_size = len(native_chains[1]) - receptor_atoms = ( - (model_atoms_1, native_atoms_1) - if native1_size > native2_size - else (model_atoms_2, native_atoms_2) - ) - ligand_atoms = ( - (model_atoms_1, native_atoms_1) - if native1_size <= native2_size - else (model_atoms_2, native_atoms_2) - ) - receptor_n_atoms = n_atoms_1 if native1_size > native2_size else n_atoms_2 - ligand_n_atoms = n_atoms_1 if native1_size <= native2_size else n_atoms_2 - - class1, class2 = ( - ("receptor", "ligand") - if native1_size > native2_size - else ("ligand", "receptor") - ) - - # Set to align on receptor - rot, tran, super_imposer = superimpose(receptor_atoms[0], receptor_atoms[1]) - rotated_ligand_atoms = np.dot(ligand_atoms[0], rot) + tran - - Lrms = super_imposer._rms( - ligand_atoms[1], rotated_ligand_atoms - ) # using the private _rms function which does not superimpose - - # Get interfacial atoms from reference, and corresponding atoms from sample - interacting_pairs = get_interacting_pairs( - # working with squared thresholds to avoid using sqrt - native_distances, - threshold=interface_threshold ** 2, - ) - - if class1 == "ligand": - interacting_pairs = interacting_pairs[::-1] - - receptor_interface_index, _, _ = filter_atoms( - receptor_n_atoms, None, filter=interacting_pairs[0] - ) - ligand_interface_index, _, _ = filter_atoms( - ligand_n_atoms, None, filter=interacting_pairs[1] - ) - - model_interface_atoms = np.vstack( - ( - receptor_atoms[0][receptor_interface_index], - ligand_atoms[0][ligand_interface_index], - ) - ) - native_interface_atoms = np.vstack( - ( - receptor_atoms[1][receptor_interface_index], - ligand_atoms[1][ligand_interface_index], - ) - ) - - _, _, super_imposer = superimpose(model_interface_atoms, native_interface_atoms) - irms = super_imposer.get_rms() - - info = {} - - info["DockQ_F1"] = dockq_formula( - f1(nat_correct, nonnat_count, nat_total), irms, Lrms - ) - info["DockQ"] = dockq_formula(fnat, irms, Lrms) - info["irms"] = irms - info["Lrms"] = Lrms - info["fnat"] = fnat - info["nat_correct"] = nat_correct - info["nat_total"] = nat_total - - info["fnonnat"] = fnonnat - info["nonnat_count"] = nonnat_count - info["model_total"] = model_total - - info["len1"] = native1_size - info["len2"] = native2_size - info["class1"] = class1 - info["class2"] = class2 - return info - - @lru_cache def filter_atoms(model_info, native_info, filter=("CA", "C", "N", "O", "P")): model_bools = [] From 2e298d3a339d2fd5e7b8c9acd14cf32c473b315b Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 22 Mar 2024 14:04:19 +0100 Subject: [PATCH 128/173] code coverage test --- .github/workflows/main.yml | 9 +++++++++ run_test.sh | 23 ++++++++++++----------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index aa8d40c..64ae2e3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -2,6 +2,10 @@ name: CI on: [push, pull_request, workflow_dispatch] +env: + MIN_COVERAGE_REQUIRED: 50 + + jobs: test: if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name @@ -16,7 +20,11 @@ jobs: - name: Test pipeline output run: | python -m pip install . + python -m pip install coverage bash ./run_test.sh + - name: Coverage + run: | + test $(coverage report | grep TOTAL | awk '{ print $4 }' | tr -d "%") -ge $MIN_COVERAGE_REQUIRED test_oldbio: if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name @@ -31,5 +39,6 @@ jobs: - name: Test pipeline output run: | python -m pip install biopython==1.79 + python -m pip install coverage python -m pip install . bash ./run_test.sh diff --git a/run_test.sh b/run_test.sh index 4f61b55..fa577a2 100644 --- a/run_test.sh +++ b/run_test.sh @@ -2,18 +2,19 @@ set -euo pipefail # Test that cython version behaves the same as nocython -DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb -python src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb -DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align -python src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align +coverage run -a -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb +coverage run -a src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb +coverage run -a -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align +coverage run -a src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align # Multiple interfaces -DockQ examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short +coverage run -a -m DockQ.DockQ examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short # Test on structures with slightly different sequences -DockQ examples/model.pdb examples/native.pdb --allowed_mismatches 1 +coverage run -a -m DockQ.DockQ examples/model.pdb examples/native.pdb --allowed_mismatches 1 # Test various mapping strategies -DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping AB*:BA* -DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping :ABC -DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping ABCDEFGH:BADCFEHG +coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping AB*:BA* +coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping :ABC +coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping ABCDEFGH:BADCFEHG # Test that cif parsing behaves same as pdb parsing -DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --mapping DH:AE -DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB.cif.gz +coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --mapping DH:AE +coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB.cif.gz --mapping DH:AE +coverage report From 16696ced10e009885f2977ef57c3331eb021d79e Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 22 Mar 2024 14:07:53 +0100 Subject: [PATCH 129/173] all tests together --- .github/workflows/main.yml | 40 +++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 64ae2e3..c8eb96b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -17,28 +17,32 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Test pipeline output + - name: Test outputs run: | python -m pip install . python -m pip install coverage - bash ./run_test.sh + bash run_test.sh + - name: Test with old biopython + run: | + python -m pip install biopython==1.79 + bash run_test.sh - name: Coverage run: | test $(coverage report | grep TOTAL | awk '{ print $4 }' | tr -d "%") -ge $MIN_COVERAGE_REQUIRED - test_oldbio: - if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name - runs-on: ubuntu-latest - timeout-minutes: 10 - defaults: - run: - shell: bash -l {0} - - steps: - - uses: actions/checkout@v3 - - name: Test pipeline output - run: | - python -m pip install biopython==1.79 - python -m pip install coverage - python -m pip install . - bash ./run_test.sh + #test_oldbio: + # if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + # runs-on: ubuntu-latest + # timeout-minutes: 10 + # defaults: + # run: + # shell: bash -l {0} +# +# steps: +# - uses: actions/checkout@v3 +# - name: Test pipeline output +# run: | +# python -m pip install biopython==1.79 +# python -m pip install coverage +# python -m pip install . +# bash ./run_test.sh From 5b5be5a7dacb7947f2d4d41c0f6836d819407e42 Mon Sep 17 00:00:00 2001 From: clami66 Date: Fri, 22 Mar 2024 14:11:40 +0100 Subject: [PATCH 130/173] unused line in test --- run_test.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/run_test.sh b/run_test.sh index fa577a2..e421fad 100644 --- a/run_test.sh +++ b/run_test.sh @@ -17,4 +17,3 @@ coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b # Test that cif parsing behaves same as pdb parsing coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --mapping DH:AE coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB.cif.gz --mapping DH:AE -coverage report From 796b9277f821d919b516a43a753df14307bf6517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wallner?= Date: Sat, 23 Mar 2024 10:10:59 +0100 Subject: [PATCH 131/173] Added multi-threading support --- src/DockQ/DockQ.py | 172 +++++++++++++++++++++++++++++---------------- 1 file changed, 111 insertions(+), 61 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 37bb944..36b2b11 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -5,9 +5,11 @@ import hashlib import traceback import itertools +import math from functools import lru_cache, wraps from argparse import ArgumentParser from tqdm import tqdm +from parallelbar import progress_map import Bio.PDB import numpy as np @@ -49,6 +51,9 @@ def parse_args(): parser.add_argument( "--verbose", "-v", default=False, action="store_true", help="talk a lot!" ) + #parser.add_argument( + # "--progress_bar", "-v", default=False, action="store_true", help="talk a lot!" + #) parser.add_argument( "--use_CA", "-ca", @@ -62,6 +67,21 @@ def parse_args(): action="store_true", help="Do not align native and model using sequence alignments, but use the numbering of residues instead", ) + parser.add_argument( + "--n_cpu", + default=32, + type=int, + metavar="n_cpu", + help="Number of cores to use", + ) + parser.add_argument( + "--chunk_size", + default=64, + type=int, + metavar="chunk_size", + help="Size of chunks given to the cores", + ) + parser.add_argument( "--optDockQF1", default=False, @@ -570,6 +590,7 @@ def calc_DockQ( alignments, use_CA_only=False, capri_peptide=False, + low_memory=False, ): atom_for_sup = ("CA", "C", "N", "O", "P") if not use_CA_only else ("CA", "P") fnat_threshold = 4.0 if capri_peptide else 5.0 @@ -670,11 +691,13 @@ def calc_DockQ( ) # using the private _rms function which does not superimpose info = {} - + info["DockQ_F1"] = dockq_formula( f1(nat_correct, nonnat_count, nat_total), irms, Lrms ) info["DockQ"] = dockq_formula(fnat, irms, Lrms) + if low_memory: + return info info["irms"] = irms info["Lrms"] = Lrms info["fnat"] = fnat @@ -924,6 +947,7 @@ def run_on_chains( no_needle=False, use_CA_only=False, capri_peptide=False, + low_memory=False, ): # realign each model chain against the corresponding native chain alignments = [] @@ -942,6 +966,7 @@ def run_on_chains( alignments=tuple(alignments), use_CA_only=use_CA_only, capri_peptide=capri_peptide, + low_memory=False, ) return info @@ -953,6 +978,7 @@ def run_on_all_native_interfaces( no_needle=False, use_CA_only=False, capri_peptide=False, + low_memory=False, ): """Given a native-model chain map, finds all non-null native interfaces and runs DockQ for each native-model pair of interfaces""" @@ -976,6 +1002,7 @@ def run_on_all_native_interfaces( no_needle=no_needle, use_CA_only=use_CA_only, capri_peptide=capri_peptide, + low_memory=False, ) if info: info["chain1"], info["chain2"] = ( @@ -1080,7 +1107,10 @@ def format_mapping(mapping_str): def format_mapping_string(chain_mapping): chain1 = "" chain2 = "" - mapping = sorted([(b, a) for a, b in chain_mapping.items()]) + + #mapping = sorted([(b, a) for a, b in chain_mapping.items()]) + #Sorting might change LRMSD since the definition of receptor/ligand for equal length depends on order + mapping = [(b, a) for a, b in chain_mapping.items()] for ( model_chain, native_chain, @@ -1090,7 +1120,6 @@ def format_mapping_string(chain_mapping): return f"{chain1}:{chain2}" -import math def product_without_dupl(*args, repeat=1): pools = [tuple(pool) for pool in args] * repeat result = [[]] @@ -1099,24 +1128,55 @@ def product_without_dupl(*args, repeat=1): #result = set(list(map(lambda x: tuple(sorted(x)), result))) # to remove symmetric duplicates for prod in result: yield tuple(prod) -def chain_combinations(chain_clusters): +def count_chain_combinations(chain_clusters): counts={} for chain in chain_clusters: chains=tuple(chain_clusters[chain]) if chains not in counts: counts[chains]=0 counts[chains]+=1 + number_of_combinations=np.prod([math.factorial(a) for a in counts.values()]) + #combos=itertools.product(*[itertools.permutations(chains) for chains in set([tuple(ch) for ch in chain_clusters.values()])]) + return(number_of_combinations,counts) #set(chain_clusters.values()) - - combos=itertools.product(*[itertools.permutations(chains) for chains in set([tuple(ch) for ch in chain_clusters.values()])]) - - print(len(list(combos))) - sys.exit() - number_of_combinations=np.prod([math.factorial(a) for a in counts.values()]) - print(number_of_combinations) +def get_all_mappings( + model_structure, native_structure, model_chains, native_chains,initial_mapping,allowed_mismatches=0 +): + model_chains_to_combo = [mc for mc in model_chains if mc not in initial_mapping.values()] + native_chains_to_combo = [nc for nc in native_chains if nc not in initial_mapping.keys()] + + chain_clusters, reverse_map = group_chains( + model_structure, + native_structure, + model_chains_to_combo, + native_chains_to_combo, + allowed_mismatches, + ) + + all_mappings = product_without_dupl( + *[cluster for cluster in chain_clusters.values() if cluster] + ) + chain_maps=[] + for mapping in all_mappings: + chain_map = {key:value for key, value in initial_mapping.items()} + if reverse_map: + chain_map.update({ + mapping[i]: model_chain for i, model_chain in enumerate(model_chains_to_combo) + }) + else: + chain_map.update({ + native_chain: mapping[i] for i, native_chain in enumerate(native_chains_to_combo) + }) + chain_maps.append(chain_map) + return chain_maps + +def run_on_all_native_interfaces_multi(args): + return run_on_all_native_interfaces(*args) +def func(args): + print(args) #@profile def main(): args = parse_args() @@ -1124,7 +1184,7 @@ def main(): model_structure = load_PDB(args.model, chains=model_chains) native_structure = load_PDB(args.native, chains=native_chains) - + #check user-given chains are in the structures model_chains = [c.id for c in model_structure] if not model_chains else model_chains native_chains = ( [c.id for c in native_structure] if not native_chains else native_chains @@ -1138,68 +1198,58 @@ def main(): best_dockq = -1 best_result = None best_mapping = None - model_chains_to_combo = [mc for mc in model_chains if mc not in initial_mapping.values()] - native_chains_to_combo = [nc for nc in native_chains if nc not in initial_mapping.keys()] - chain_clusters, reverse_map = group_chains( + + # model_chains_to_combo = [mc for mc in model_chains if mc not in initial_mapping.values()] + # native_chains_to_combo = [nc for nc in native_chains if nc not in initial_mapping.keys()] + + # chain_clusters, reverse_map = group_chains( + # model_structure, + # native_structure, + # model_chains_to_combo, + # native_chains_to_combo, + # args.allowed_mismatches, + # ) + + + #all_mappings = product_without_dupl( + # *[cluster for cluster in chain_clusters.values() if cluster] + #) + chain_maps=get_all_mappings( model_structure, native_structure, - model_chains_to_combo, - native_chains_to_combo, + model_chains, + native_chains, + initial_mapping, args.allowed_mismatches, ) - - all_mappings = product_without_dupl( - *[cluster for cluster in chain_clusters.values() if cluster] - ) -# else: -# all_mappings = itertools.product( -# *[itertools.permutations(chains) for chains in set([tuple(ch) for ch in chain_clusters.values()])]) - - #print(len(list(all_mappings))) - - #sys.exit() - #print(len(list(all_mappings))) - #print([cluster for cluster in chain_clusters.values() if cluster]) - - # remove mappings where the same model chain is present more than once - # only if the mapping is supposed to be 1-1 - #if len(model_chains) == len(native_chains): - # all_mappings = [ - # element for element in all_mappings if len(set(element)) == len(element) - # ] - def progressbar(l): - return tqdm(l,desc='Chain combinations') if len(l) > 1 else l - - for mapping in progressbar(list(all_mappings)): - chain_map = {key:value for key, value in initial_mapping.items()} - if reverse_map: - chain_map.update({ - mapping[i]: model_chain for i, model_chain in enumerate(model_chains_to_combo) - }) - else: - chain_map.update({ - native_chain: mapping[i] for i, native_chain in enumerate(native_chains_to_combo) - }) - result_this_mapping = run_on_all_native_interfaces( - model_structure, - native_structure, - chain_map=chain_map, - no_needle=args.no_needle, - use_CA_only=args.use_CA, - capri_peptide=args.capri_peptide, - ) + low_memory=len(chain_maps) > 100 + chain_map_args=[(model_structure,native_structure,chain_map,args.no_needle,args.use_CA,args.capri_peptide,low_memory) for chain_map in chain_maps] + if len(chain_maps)>1: + chunk_size=len(chain_maps) // args.n_cpu + result_this_mappings=progress_map(run_on_all_native_interfaces_multi,chain_map_args, n_cpu=args.n_cpu, chunk_size=chunk_size) + else: #skip multi-threading for single jobs (skip the bar basically) + result_this_mappings=[run_on_all_native_interfaces(*chain_map_arg) for chain_map_arg in chain_map_args] + for chain_map,result_this_mapping in zip(chain_maps,result_this_mappings): total_dockq = sum( [result["DockQ_F1" if args.optDockQF1 else "DockQ"] for result in result_this_mapping.values()] ) - if total_dockq > best_dockq: best_dockq = total_dockq best_result = result_this_mapping best_mapping = chain_map - + if low_memory: #retrieve the full output by reruning the best chain mapping + best_result=run_on_all_native_interfaces( + model_structure, + native_structure, + best_mapping, + args.no_needle, + args.use_CA, + args.capri_peptide, + low_memory=False) + info["model"] = args.model info["native"] = args.native info["best_dockq"] = best_dockq @@ -1216,7 +1266,7 @@ def print_results(info, short=False, verbose=False, capri_peptide=False): print( f"Total DockQ over {len(info['best_result'])} native interfaces: {info['GlobalDockQ']:.3f} with {info['best_mapping_str']} model:native mapping" ) - print(info["best_result"]) + # print(info["best_result"]) for chains, results in info["best_result"].items(): print( f"DockQ{capri_peptide_str} {results['DockQ']:.3f} DockQ_F1 {results['DockQ_F1']:.3f} Fnat {results['fnat']:.3f} iRMS {results['irms']:.3f} LRMS {results['Lrms']:.3f} Fnonnat {results['fnonnat']:.3f} clashes {results['clashes']} mapping {results['chain1']}{results['chain2']}:{chains[0]}{chains[1]} {info['model']} {results['chain1']} {results['chain2']} -> {info['native']} {chains[0]} {chains[1]}" From a5e175afcbf4c7f907cfc1f8bd435fcda76bc5a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wallner?= Date: Sat, 23 Mar 2024 10:34:19 +0100 Subject: [PATCH 132/173] added parallbar packages --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index c115d82..b95a414 100644 --- a/setup.cfg +++ b/setup.cfg @@ -10,6 +10,7 @@ install_requires = setuptools cython tqdm + parallelbar numpy~=1.21 biopython>=1.79 From 2b48ef31eebcb5cc91b331cbc51047a06d1e7784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wallner?= Date: Sat, 23 Mar 2024 10:44:49 +0100 Subject: [PATCH 133/173] made sure chuck_size is at least 1 --- src/DockQ/DockQ.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 541d300..9278f78 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -972,7 +972,7 @@ def main(): low_memory=len(chain_maps) > 100 chain_map_args=[(model_structure,native_structure,chain_map,args.no_align,args.use_CA,args.capri_peptide,low_memory) for chain_map in chain_maps] if len(chain_maps)>1: - chunk_size=len(chain_maps) // args.n_cpu + chunk_size=max(1,len(chain_maps) // args.n_cpu) result_this_mappings=progress_map(run_on_all_native_interfaces_multi,chain_map_args, n_cpu=args.n_cpu, chunk_size=chunk_size) else: #skip multi-threading for single jobs (skip the bar basically) result_this_mappings=[run_on_all_native_interfaces(*chain_map_arg) for chain_map_arg in chain_map_args] From de84d75e5db3854c03f66eb572b3270769222431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wallner?= Date: Sat, 23 Mar 2024 10:44:49 +0100 Subject: [PATCH 134/173] made sure chunk_size is at least 1 --- src/DockQ/DockQ.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 541d300..9278f78 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -972,7 +972,7 @@ def main(): low_memory=len(chain_maps) > 100 chain_map_args=[(model_structure,native_structure,chain_map,args.no_align,args.use_CA,args.capri_peptide,low_memory) for chain_map in chain_maps] if len(chain_maps)>1: - chunk_size=len(chain_maps) // args.n_cpu + chunk_size=max(1,len(chain_maps) // args.n_cpu) result_this_mappings=progress_map(run_on_all_native_interfaces_multi,chain_map_args, n_cpu=args.n_cpu, chunk_size=chunk_size) else: #skip multi-threading for single jobs (skip the bar basically) result_this_mappings=[run_on_all_native_interfaces(*chain_map_arg) for chain_map_arg in chain_map_args] From 2bb0db29da3d0b5e220e159aabbe71da5302c0f1 Mon Sep 17 00:00:00 2001 From: bjornwallner Date: Sat, 23 Mar 2024 11:00:57 +0100 Subject: [PATCH 135/173] Update main.yml --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c8eb96b..9983776 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,6 +28,7 @@ jobs: bash run_test.sh - name: Coverage run: | + coverage report test $(coverage report | grep TOTAL | awk '{ print $4 }' | tr -d "%") -ge $MIN_COVERAGE_REQUIRED #test_oldbio: From a5222d0089d43989f8fc8c20fd925bce1953495f Mon Sep 17 00:00:00 2001 From: bjornwallner Date: Sat, 23 Mar 2024 11:19:40 +0100 Subject: [PATCH 136/173] Update main.yml, changed min coverage to 35, to avoid failing the coverage test --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9983776..289c406 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,7 +3,7 @@ name: CI on: [push, pull_request, workflow_dispatch] env: - MIN_COVERAGE_REQUIRED: 50 + MIN_COVERAGE_REQUIRED: 35 jobs: From aacdc6080b0c7db1a69591671d9341ff048e2cc8 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 08:59:00 +0100 Subject: [PATCH 137/173] small fixes --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 842416e..d89bfee 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ ![CI status](https://github.com/bjornwallner/DockQ/actions/workflows/main.yml/badge.svg) -# DockQ: A Quality Measure for Protein-Protein Docking Models +# DockQ +## A Quality Measure for Protein-Protein Docking Models ## Installation @@ -12,7 +13,7 @@ cd DockQ pip install . ``` -## Quick start: +## Quick start After installing DockQ with `pip`, the `DockQ` binary will be in your path. Just run DockQ with: From 0148f55a1c8901c3fec700bcfab51f889f15b142 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 09:41:24 +0100 Subject: [PATCH 138/173] debug coverage issue --- run_test.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/run_test.sh b/run_test.sh index e421fad..90041b1 100644 --- a/run_test.sh +++ b/run_test.sh @@ -17,3 +17,5 @@ coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b # Test that cif parsing behaves same as pdb parsing coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --mapping DH:AE coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB.cif.gz --mapping DH:AE + +coverage report From 0728794183f2b99e728b0109ff7dfa21531a49d9 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 09:50:26 +0100 Subject: [PATCH 139/173] coverage version output --- run_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run_test.sh b/run_test.sh index 90041b1..e5bf086 100644 --- a/run_test.sh +++ b/run_test.sh @@ -1,6 +1,6 @@ #!/bin/bash set -euo pipefail - +coverage --version # Test that cython version behaves the same as nocython coverage run -a -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb coverage run -a src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb From 2d1933f3e6071914c753bae8fd33021a5594588d Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 09:54:28 +0100 Subject: [PATCH 140/173] more debugging --- run_test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/run_test.sh b/run_test.sh index e5bf086..4445709 100644 --- a/run_test.sh +++ b/run_test.sh @@ -1,8 +1,8 @@ #!/bin/bash set -euo pipefail -coverage --version + # Test that cython version behaves the same as nocython -coverage run -a -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb +coverage run -a -m --debug=trace DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb coverage run -a src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb coverage run -a -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align coverage run -a src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align From fa1e7d661d147fc178efb14d14880564d28a0aa3 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 10:05:04 +0100 Subject: [PATCH 141/173] move coverage install --- .github/workflows/main.yml | 1 - setup.cfg | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 289c406..7ad4286 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,7 +20,6 @@ jobs: - name: Test outputs run: | python -m pip install . - python -m pip install coverage bash run_test.sh - name: Test with old biopython run: | diff --git a/setup.cfg b/setup.cfg index b95a414..75e37af 100644 --- a/setup.cfg +++ b/setup.cfg @@ -11,6 +11,7 @@ install_requires = cython tqdm parallelbar + coverage numpy~=1.21 biopython>=1.79 From 3d404e795c56c214fcd87c6b3f4b08a4816109ba Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 10:10:15 +0100 Subject: [PATCH 142/173] add source in covtest --- run_test.sh | 22 +++---- setup.cfg | 1 - src/DockQ/DockQ.py | 148 ++++++++++++++++++++++++++++----------------- 3 files changed, 105 insertions(+), 66 deletions(-) diff --git a/run_test.sh b/run_test.sh index 4445709..e25b0ee 100644 --- a/run_test.sh +++ b/run_test.sh @@ -2,20 +2,20 @@ set -euo pipefail # Test that cython version behaves the same as nocython -coverage run -a -m --debug=trace DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb -coverage run -a src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb -coverage run -a -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align -coverage run -a src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align +coverage run -a -m --source=src/ DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb +coverage run -a --source=src/ src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb +coverage run -a -m --source=src/ DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align +coverage run -a --source=src/ src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align # Multiple interfaces -coverage run -a -m DockQ.DockQ examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short +coverage run -a -m --source=src/ DockQ.DockQ examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short # Test on structures with slightly different sequences -coverage run -a -m DockQ.DockQ examples/model.pdb examples/native.pdb --allowed_mismatches 1 +coverage run -a -m --source=src/ DockQ.DockQ examples/model.pdb examples/native.pdb --allowed_mismatches 1 # Test various mapping strategies -coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping AB*:BA* -coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping :ABC -coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping ABCDEFGH:BADCFEHG +coverage run -a -m --source=src/ DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping AB*:BA* +coverage run -a -m --source=src/ DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping :ABC +coverage run -a -m --source=src/ DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping ABCDEFGH:BADCFEHG # Test that cif parsing behaves same as pdb parsing -coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --mapping DH:AE -coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB.cif.gz --mapping DH:AE +coverage run -a -m --source=src/ DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --mapping DH:AE +coverage run -a -m --source=src/ DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB.cif.gz --mapping DH:AE coverage report diff --git a/setup.cfg b/setup.cfg index 75e37af..b95a414 100644 --- a/setup.cfg +++ b/setup.cfg @@ -11,7 +11,6 @@ install_requires = cython tqdm parallelbar - coverage numpy~=1.21 biopython>=1.79 diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 9278f78..de73b9c 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -68,7 +68,7 @@ def parse_args(): ) parser.add_argument( "--n_cpu", - default=32, + default=8, type=int, metavar="n_cpu", help="Number of cores to use", @@ -448,7 +448,7 @@ def calc_DockQ( ) # using the private _rms function which does not superimpose info = {} - + info["DockQ_F1"] = dockq_formula( f1(nat_correct, nonnat_count, nat_total), irms, Lrms ) @@ -771,7 +771,7 @@ def run_on_all_native_interfaces( return results_dic -#@profile +# @profile def load_PDB(path, chains=[], n_model=0): try: pdb_parser = PDBParser(QUIET=True) @@ -784,12 +784,13 @@ def load_PDB(path, chains=[], n_model=0): except Exception: pdb_parser = MMCIFParser(QUIET=True) structure = pdb_parser.get_structure( - "-", (gzip.open if path.endswith(".gz") else open)(path, "rt"), + "-", + (gzip.open if path.endswith(".gz") else open)(path, "rt"), chains=None, ) model = structure[n_model] - #remove_h(model) + # remove_h(model) return model @@ -828,7 +829,7 @@ def group_chains( f"For these chains {chains_without_match} no match was found between model and native, try increasing the --allowed_mismatches from {allowed_mismatches}" ) print(f"Current number of alignments with 1-10 mismatches: {mismatch_dict}") - + return chain_clusters, reverse_map @@ -864,9 +865,9 @@ def format_mapping(mapping_str): def format_mapping_string(chain_mapping): chain1 = "" chain2 = "" - - #mapping = sorted([(b, a) for a, b in chain_mapping.items()]) - #Sorting might change LRMSD since the definition of receptor/ligand for equal length depends on order + + # mapping = sorted([(b, a) for a, b in chain_mapping.items()]) + # Sorting might change LRMSD since the definition of receptor/ligand for equal length depends on order mapping = [(b, a) for a, b in chain_mapping.items()] for ( model_chain, @@ -877,32 +878,46 @@ def format_mapping_string(chain_mapping): return f"{chain1}:{chain2}" + def product_without_dupl(*args, repeat=1): pools = [tuple(pool) for pool in args] * repeat result = [[]] for pool in pools: - result = [x+[y] for x in result for y in pool if y not in x] # here we added condition - #result = set(list(map(lambda x: tuple(sorted(x)), result))) # to remove symmetric duplicates + result = [ + x + [y] for x in result for y in pool if y not in x + ] # here we added condition + # result = set(list(map(lambda x: tuple(sorted(x)), result))) # to remove symmetric duplicates for prod in result: yield tuple(prod) + + def count_chain_combinations(chain_clusters): - counts={} + counts = {} for chain in chain_clusters: - chains=tuple(chain_clusters[chain]) + chains = tuple(chain_clusters[chain]) if chains not in counts: - counts[chains]=0 - counts[chains]+=1 - number_of_combinations=np.prod([math.factorial(a) for a in counts.values()]) - #combos=itertools.product(*[itertools.permutations(chains) for chains in set([tuple(ch) for ch in chain_clusters.values()])]) - return(number_of_combinations,counts) - #set(chain_clusters.values()) + counts[chains] = 0 + counts[chains] += 1 + number_of_combinations = np.prod([math.factorial(a) for a in counts.values()]) + # combos=itertools.product(*[itertools.permutations(chains) for chains in set([tuple(ch) for ch in chain_clusters.values()])]) + return (number_of_combinations, counts) + # set(chain_clusters.values()) def get_all_mappings( - model_structure, native_structure, model_chains, native_chains,initial_mapping,allowed_mismatches=0 -): - model_chains_to_combo = [mc for mc in model_chains if mc not in initial_mapping.values()] - native_chains_to_combo = [nc for nc in native_chains if nc not in initial_mapping.keys()] + model_structure, + native_structure, + model_chains, + native_chains, + initial_mapping, + allowed_mismatches=0, +): + model_chains_to_combo = [ + mc for mc in model_chains if mc not in initial_mapping.values() + ] + native_chains_to_combo = [ + nc for nc in native_chains if nc not in initial_mapping.keys() + ] chain_clusters, reverse_map = group_chains( model_structure, @@ -915,32 +930,39 @@ def get_all_mappings( all_mappings = product_without_dupl( *[cluster for cluster in chain_clusters.values() if cluster] ) - chain_maps=[] - for mapping in all_mappings: - chain_map = {key:value for key, value in initial_mapping.items()} + chain_maps = [] + for mapping in all_mappings: + chain_map = {key: value for key, value in initial_mapping.items()} if reverse_map: - chain_map.update({ - mapping[i]: model_chain for i, model_chain in enumerate(model_chains_to_combo) - }) + chain_map.update( + { + mapping[i]: model_chain + for i, model_chain in enumerate(model_chains_to_combo) + } + ) else: - chain_map.update({ - native_chain: mapping[i] for i, native_chain in enumerate(native_chains_to_combo) - }) + chain_map.update( + { + native_chain: mapping[i] + for i, native_chain in enumerate(native_chains_to_combo) + } + ) chain_maps.append(chain_map) return chain_maps + def run_on_all_native_interfaces_multi(args): return run_on_all_native_interfaces(*args) -#@profile +# @profile def main(): args = parse_args() initial_mapping, model_chains, native_chains = format_mapping(args.mapping) model_structure = load_PDB(args.model, chains=model_chains) native_structure = load_PDB(args.native, chains=native_chains) - #check user-given chains are in the structures + # check user-given chains are in the structures model_chains = [c.id for c in model_structure] if not model_chains else model_chains native_chains = ( [c.id for c in native_structure] if not native_chains else native_chains @@ -955,11 +977,7 @@ def main(): best_result = None best_mapping = None - - - - - chain_maps=get_all_mappings( + chain_maps = get_all_mappings( model_structure, native_structure, model_chains, @@ -968,32 +986,54 @@ def main(): args.allowed_mismatches, ) - - low_memory=len(chain_maps) > 100 - chain_map_args=[(model_structure,native_structure,chain_map,args.no_align,args.use_CA,args.capri_peptide,low_memory) for chain_map in chain_maps] - if len(chain_maps)>1: - chunk_size=max(1,len(chain_maps) // args.n_cpu) - result_this_mappings=progress_map(run_on_all_native_interfaces_multi,chain_map_args, n_cpu=args.n_cpu, chunk_size=chunk_size) - else: #skip multi-threading for single jobs (skip the bar basically) - result_this_mappings=[run_on_all_native_interfaces(*chain_map_arg) for chain_map_arg in chain_map_args] - for chain_map,result_this_mapping in zip(chain_maps,result_this_mappings): + low_memory = len(chain_maps) > 100 + chain_map_args = [ + ( + model_structure, + native_structure, + chain_map, + args.no_align, + args.use_CA, + args.capri_peptide, + low_memory, + ) + for chain_map in chain_maps + ] + if len(chain_maps) > 1: + chunk_size = max(1, len(chain_maps) // args.n_cpu) + result_this_mappings = progress_map( + run_on_all_native_interfaces_multi, + chain_map_args, + n_cpu=args.n_cpu, + chunk_size=chunk_size, + ) + else: # skip multi-threading for single jobs (skip the bar basically) + result_this_mappings = [ + run_on_all_native_interfaces(*chain_map_arg) + for chain_map_arg in chain_map_args + ] + for chain_map, result_this_mapping in zip(chain_maps, result_this_mappings): total_dockq = sum( - [result["DockQ_F1" if args.optDockQF1 else "DockQ"] for result in result_this_mapping.values()] + [ + result["DockQ_F1" if args.optDockQF1 else "DockQ"] + for result in result_this_mapping.values() + ] ) if total_dockq > best_dockq: best_dockq = total_dockq best_result = result_this_mapping best_mapping = chain_map - if low_memory: #retrieve the full output by reruning the best chain mapping - best_result=run_on_all_native_interfaces( + if low_memory: # retrieve the full output by reruning the best chain mapping + best_result = run_on_all_native_interfaces( model_structure, native_structure, best_mapping, args.no_align, args.use_CA, args.capri_peptide, - low_memory=False) - + low_memory=False, + ) + info["model"] = args.model info["native"] = args.native info["best_dockq"] = best_dockq @@ -1010,7 +1050,7 @@ def print_results(info, short=False, verbose=False, capri_peptide=False): print( f"Total DockQ over {len(info['best_result'])} native interfaces: {info['GlobalDockQ']:.3f} with {info['best_mapping_str']} model:native mapping" ) - # print(info["best_result"]) + # print(info["best_result"]) for chains, results in info["best_result"].items(): print( f"DockQ{capri_peptide_str} {results['DockQ']:.3f} DockQ_F1 {results['DockQ_F1']:.3f} Fnat {results['fnat']:.3f} iRMS {results['irms']:.3f} LRMS {results['Lrms']:.3f} Fnonnat {results['fnonnat']:.3f} clashes {results['clashes']} mapping {results['chain1']}{results['chain2']}:{chains[0]}{chains[1]} {info['model']} {results['chain1']} {results['chain2']} -> {info['native']} {chains[0]} {chains[1]}" From cb01c01e01564ab6149baa009f1ce7a58a90aadf Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 10:11:25 +0100 Subject: [PATCH 143/173] fix pip command --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7ad4286..289c406 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,6 +20,7 @@ jobs: - name: Test outputs run: | python -m pip install . + python -m pip install coverage bash run_test.sh - name: Test with old biopython run: | From 71b089600f3b9cc93a01effb30e235e20090a21b Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 10:18:25 +0100 Subject: [PATCH 144/173] add source to coverage --- run_test.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/run_test.sh b/run_test.sh index e25b0ee..33faaf6 100644 --- a/run_test.sh +++ b/run_test.sh @@ -2,20 +2,20 @@ set -euo pipefail # Test that cython version behaves the same as nocython -coverage run -a -m --source=src/ DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb -coverage run -a --source=src/ src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb -coverage run -a -m --source=src/ DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb +coverage run -a --source=src/ src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align coverage run -a --source=src/ src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align # Multiple interfaces -coverage run -a -m --source=src/ DockQ.DockQ examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short # Test on structures with slightly different sequences -coverage run -a -m --source=src/ DockQ.DockQ examples/model.pdb examples/native.pdb --allowed_mismatches 1 +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/model.pdb examples/native.pdb --allowed_mismatches 1 # Test various mapping strategies -coverage run -a -m --source=src/ DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping AB*:BA* -coverage run -a -m --source=src/ DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping :ABC -coverage run -a -m --source=src/ DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping ABCDEFGH:BADCFEHG +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping AB*:BA* +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping :ABC +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping ABCDEFGH:BADCFEHG # Test that cif parsing behaves same as pdb parsing -coverage run -a -m --source=src/ DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --mapping DH:AE -coverage run -a -m --source=src/ DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB.cif.gz --mapping DH:AE +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --mapping DH:AE +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB.cif.gz --mapping DH:AE coverage report From 4c2a379d97a73a1d61962ceb5d10fd4ce2b93062 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 10:33:47 +0100 Subject: [PATCH 145/173] fix src --- run_test.sh | 4 ++-- src/DockQ/DockQ.py | 18 ------------------ 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/run_test.sh b/run_test.sh index 33faaf6..a30f6ea 100644 --- a/run_test.sh +++ b/run_test.sh @@ -3,9 +3,9 @@ set -euo pipefail # Test that cython version behaves the same as nocython coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb -coverage run -a --source=src/ src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb +coverage run -a src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align -coverage run -a --source=src/ src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align +coverage run -a src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align # Multiple interfaces coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short # Test on structures with slightly different sequences diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index de73b9c..a180061 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -52,7 +52,6 @@ def parse_args(): parser.add_argument( "--verbose", "-v", default=False, action="store_true", help="talk a lot!" ) - parser.add_argument( "--use_CA", "-ca", @@ -73,14 +72,6 @@ def parse_args(): metavar="n_cpu", help="Number of cores to use", ) - parser.add_argument( - "--chunk_size", - default=64, - type=int, - metavar="chunk_size", - help="Size of chunks given to the cores", - ) - parser.add_argument( "--optDockQF1", default=False, @@ -112,15 +103,6 @@ def parse_args(): return parser.parse_args() -def open_file(filename): - if filename.endswith(".gz"): - with gzip.open(filename) as f: - yield f - else: - with open(filename) as f: - yield f - - @lru_cache def get_aligned_residues(chainA, chainB, alignment): aligned_resA = [] From 540a70f9ed9dda0f2f5472ea67adfabe17e41630 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 11:03:22 +0100 Subject: [PATCH 146/173] actual tests --- run_test.sh | 39 +++++++++++++++++++-------- src/DockQ/DockQ.py | 3 ++- testdata/1A2K.dockq | 37 +++++++++++++++++++++++++ testdata/1EXB_.ABC.dockq | 3 +++ testdata/1EXB_AB.BA.dockq | 17 ++++++++++++ testdata/1EXB_ABCDEFGH.BADCFEHG.dockq | 17 ++++++++++++ testdata/1EXB_DH.AE.dockq | 23 ++++++++++++++++ testdata/1EXB_DH.AE_cif.dockq | 23 ++++++++++++++++ testdata/dimer_dimer.dockq | 5 ++++ testdata/model.dockq | 23 ++++++++++++++++ 10 files changed, 178 insertions(+), 12 deletions(-) create mode 100644 testdata/1A2K.dockq create mode 100644 testdata/1EXB_.ABC.dockq create mode 100644 testdata/1EXB_AB.BA.dockq create mode 100644 testdata/1EXB_ABCDEFGH.BADCFEHG.dockq create mode 100644 testdata/1EXB_DH.AE.dockq create mode 100644 testdata/1EXB_DH.AE_cif.dockq create mode 100644 testdata/dimer_dimer.dockq create mode 100644 testdata/model.dockq diff --git a/run_test.sh b/run_test.sh index a30f6ea..768240f 100644 --- a/run_test.sh +++ b/run_test.sh @@ -1,21 +1,38 @@ #!/bin/bash set -euo pipefail +which DockQ + # Test that cython version behaves the same as nocython -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb -coverage run -a src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align -coverage run -a src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb > test +diff test testdata/1A2K.dockq +coverage run -a --source='DockQ.DockQ' src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb > test +diff test testdata/1A2K.dockq +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align > test +diff test testdata/1A2K.dockq +coverage run -a --source='DockQ.DockQ' src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align > test +diff test testdata/1A2K.dockq + # Multiple interfaces -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short > test +diff test testdata/dimer_dimer.dockq + # Test on structures with slightly different sequences -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/model.pdb examples/native.pdb --allowed_mismatches 1 +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/model.pdb examples/native.pdb --allowed_mismatches 1 > test +diff test testdata/model.dockq + # Test various mapping strategies -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping AB*:BA* -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping :ABC -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping ABCDEFGH:BADCFEHG +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping AB*:BA* > test +diff test testdata/1EXB_AB.BA.dockq +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping :ABC > test +diff test testdata/1EXB_.ABC.dockq +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping ABCDEFGH:BADCFEHG > test +diff test testdata/1EXB_ABCDEFGH.BADCFEHG.dockq + # Test that cif parsing behaves same as pdb parsing -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --mapping DH:AE -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB.cif.gz --mapping DH:AE +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --mapping DH:AE > test +diff test testdata/1EXB_DH.AE.dockq +coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB.cif.gz --mapping DH:AE > test +diff test testdata/1EXB_DH.AE_cif.dockq coverage report diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index a180061..a11e91b 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -3,6 +3,7 @@ import sys import gzip import hashlib +import warnings import traceback import itertools import math @@ -22,7 +23,7 @@ from .operations import residue_distances, get_fnat_stats from .parsers import PDBParser, MMCIFParser except ImportError: - print( + warnings.warn( """WARNING: It looks like cython is not working, falling back on native python. This will make DockQ slower""" ) diff --git a/testdata/1A2K.dockq b/testdata/1A2K.dockq new file mode 100644 index 0000000..0ac14cc --- /dev/null +++ b/testdata/1A2K.dockq @@ -0,0 +1,37 @@ +**************************************************************** +* DockQ * +* Scoring function for protein-protein docking models * +* Statistics on CAPRI data: * +* 0.00 <= DockQ < 0.23 - Incorrect * +* 0.23 <= DockQ < 0.49 - Acceptable quality * +* 0.49 <= DockQ < 0.80 - Medium quality * +* DockQ >= 0.80 - High quality * +* Ref: S. Basu and B. Wallner, DockQ: A quality measure for * +* protein-protein docking models * +* doi:10.1371/journal.pone.0161879 * +* For comments, please email: bjorn.wallner@.liu.se * +**************************************************************** +Model : examples/1A2K_r_l_b.model.pdb +Native : examples/1A2K_r_l_b.pdb +Total DockQ over 3 native interfaces: 1.959 +Native chains: A, B + Model chains: B, A + DockQ_F1: 0.996 + DockQ: 0.994 + irms: 0.000 + Lrms: 0.000 + fnat: 0.983 +Native chains: A, C + Model chains: B, C + DockQ_F1: 0.567 + DockQ: 0.511 + irms: 1.237 + Lrms: 6.864 + fnat: 0.333 +Native chains: B, C + Model chains: A, C + DockQ_F1: 0.500 + DockQ: 0.453 + irms: 2.104 + Lrms: 8.131 + fnat: 0.500 diff --git a/testdata/1EXB_.ABC.dockq b/testdata/1EXB_.ABC.dockq new file mode 100644 index 0000000..f63b8b2 --- /dev/null +++ b/testdata/1EXB_.ABC.dockq @@ -0,0 +1,3 @@ +Total DockQ over 2 native interfaces: 0.998 with ABC:ABC model:native mapping +DockQ 0.995 DockQ_F1 0.998 Fnat 0.985 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping AC:AC examples/1EXB_r_l_b.model.pdb A C -> examples/1EXB_r_l_b.pdb A C +DockQ 1.000 DockQ_F1 1.000 Fnat 1.000 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping BC:BC examples/1EXB_r_l_b.model.pdb B C -> examples/1EXB_r_l_b.pdb B C diff --git a/testdata/1EXB_AB.BA.dockq b/testdata/1EXB_AB.BA.dockq new file mode 100644 index 0000000..b864372 --- /dev/null +++ b/testdata/1EXB_AB.BA.dockq @@ -0,0 +1,17 @@ +Total DockQ over 16 native interfaces: 0.852 with ABCDFHEG:BADCEGFH model:native mapping +DockQ 0.995 DockQ_F1 0.998 Fnat 0.985 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping AC:BD examples/1EXB_r_l_b.model.pdb A C -> examples/1EXB_r_l_b.pdb B D +DockQ 0.995 DockQ_F1 0.998 Fnat 0.985 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping AD:BC examples/1EXB_r_l_b.model.pdb A D -> examples/1EXB_r_l_b.pdb B C +DockQ 0.742 DockQ_F1 0.772 Fnat 0.609 iRMS 0.850 LRMS 3.426 Fnonnat 0.176 clashes 0 mapping AE:BF examples/1EXB_r_l_b.model.pdb A E -> examples/1EXB_r_l_b.pdb B F +DockQ 0.824 DockQ_F1 0.853 Fnat 0.800 iRMS 0.625 LRMS 3.994 Fnonnat 0.000 clashes 0 mapping AG:BH examples/1EXB_r_l_b.model.pdb A G -> examples/1EXB_r_l_b.pdb B H +DockQ 1.000 DockQ_F1 1.000 Fnat 1.000 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping BC:AD examples/1EXB_r_l_b.model.pdb B C -> examples/1EXB_r_l_b.pdb A D +DockQ 0.995 DockQ_F1 0.998 Fnat 0.985 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping BD:AC examples/1EXB_r_l_b.model.pdb B D -> examples/1EXB_r_l_b.pdb A C +DockQ 0.552 DockQ_F1 0.606 Fnat 0.304 iRMS 1.458 LRMS 3.757 Fnonnat 0.000 clashes 0 mapping BF:AE examples/1EXB_r_l_b.model.pdb B F -> examples/1EXB_r_l_b.pdb A E +DockQ 0.694 DockQ_F1 0.751 Fnat 0.400 iRMS 0.793 LRMS 2.831 Fnonnat 0.000 clashes 0 mapping BH:AG examples/1EXB_r_l_b.model.pdb B H -> examples/1EXB_r_l_b.pdb A G +DockQ 0.687 DockQ_F1 0.737 Fnat 0.600 iRMS 1.161 LRMS 3.757 Fnonnat 0.000 clashes 0 mapping CF:DE examples/1EXB_r_l_b.model.pdb C F -> examples/1EXB_r_l_b.pdb D E +DockQ 0.477 DockQ_F1 0.502 Fnat 0.087 iRMS 1.425 LRMS 3.994 Fnonnat 0.000 clashes 0 mapping CG:DH examples/1EXB_r_l_b.model.pdb C G -> examples/1EXB_r_l_b.pdb D H +DockQ 0.775 DockQ_F1 0.812 Fnat 0.609 iRMS 0.711 LRMS 2.831 Fnonnat 0.125 clashes 0 mapping DH:CG examples/1EXB_r_l_b.model.pdb D H -> examples/1EXB_r_l_b.pdb C G +DockQ 0.914 DockQ_F1 0.914 Fnat 1.000 iRMS 0.547 LRMS 3.426 Fnonnat 0.000 clashes 0 mapping DE:CF examples/1EXB_r_l_b.model.pdb D E -> examples/1EXB_r_l_b.pdb C F +DockQ 0.992 DockQ_F1 0.996 Fnat 0.976 iRMS 0.001 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping FH:EG examples/1EXB_r_l_b.model.pdb F H -> examples/1EXB_r_l_b.pdb E G +DockQ 0.992 DockQ_F1 0.996 Fnat 0.976 iRMS 0.001 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping FG:EH examples/1EXB_r_l_b.model.pdb F G -> examples/1EXB_r_l_b.pdb E H +DockQ 0.992 DockQ_F1 0.996 Fnat 0.976 iRMS 0.001 LRMS 0.001 Fnonnat 0.000 clashes 0 mapping HE:GF examples/1EXB_r_l_b.model.pdb H E -> examples/1EXB_r_l_b.pdb G F +DockQ 1.000 DockQ_F1 0.996 Fnat 1.000 iRMS 0.001 LRMS 0.001 Fnonnat 0.024 clashes 0 mapping EG:FH examples/1EXB_r_l_b.model.pdb E G -> examples/1EXB_r_l_b.pdb F H diff --git a/testdata/1EXB_ABCDEFGH.BADCFEHG.dockq b/testdata/1EXB_ABCDEFGH.BADCFEHG.dockq new file mode 100644 index 0000000..1c263d6 --- /dev/null +++ b/testdata/1EXB_ABCDEFGH.BADCFEHG.dockq @@ -0,0 +1,17 @@ +Total DockQ over 16 native interfaces: 0.852 with ABCDEFGH:BADCFEHG model:native mapping +DockQ 0.995 DockQ_F1 0.998 Fnat 0.985 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping AC:BD examples/1EXB_r_l_b.model.pdb A C -> examples/1EXB_r_l_b.pdb B D +DockQ 0.995 DockQ_F1 0.998 Fnat 0.985 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping AD:BC examples/1EXB_r_l_b.model.pdb A D -> examples/1EXB_r_l_b.pdb B C +DockQ 0.742 DockQ_F1 0.772 Fnat 0.609 iRMS 0.850 LRMS 3.426 Fnonnat 0.176 clashes 0 mapping AE:BF examples/1EXB_r_l_b.model.pdb A E -> examples/1EXB_r_l_b.pdb B F +DockQ 0.824 DockQ_F1 0.853 Fnat 0.800 iRMS 0.625 LRMS 3.994 Fnonnat 0.000 clashes 0 mapping AG:BH examples/1EXB_r_l_b.model.pdb A G -> examples/1EXB_r_l_b.pdb B H +DockQ 1.000 DockQ_F1 1.000 Fnat 1.000 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping BC:AD examples/1EXB_r_l_b.model.pdb B C -> examples/1EXB_r_l_b.pdb A D +DockQ 0.995 DockQ_F1 0.998 Fnat 0.985 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping BD:AC examples/1EXB_r_l_b.model.pdb B D -> examples/1EXB_r_l_b.pdb A C +DockQ 0.552 DockQ_F1 0.606 Fnat 0.304 iRMS 1.458 LRMS 3.757 Fnonnat 0.000 clashes 0 mapping BF:AE examples/1EXB_r_l_b.model.pdb B F -> examples/1EXB_r_l_b.pdb A E +DockQ 0.694 DockQ_F1 0.751 Fnat 0.400 iRMS 0.793 LRMS 2.831 Fnonnat 0.000 clashes 0 mapping BH:AG examples/1EXB_r_l_b.model.pdb B H -> examples/1EXB_r_l_b.pdb A G +DockQ 0.687 DockQ_F1 0.737 Fnat 0.600 iRMS 1.161 LRMS 3.757 Fnonnat 0.000 clashes 0 mapping CF:DE examples/1EXB_r_l_b.model.pdb C F -> examples/1EXB_r_l_b.pdb D E +DockQ 0.477 DockQ_F1 0.502 Fnat 0.087 iRMS 1.425 LRMS 3.994 Fnonnat 0.000 clashes 0 mapping CG:DH examples/1EXB_r_l_b.model.pdb C G -> examples/1EXB_r_l_b.pdb D H +DockQ 0.914 DockQ_F1 0.914 Fnat 1.000 iRMS 0.547 LRMS 3.426 Fnonnat 0.000 clashes 0 mapping DE:CF examples/1EXB_r_l_b.model.pdb D E -> examples/1EXB_r_l_b.pdb C F +DockQ 0.775 DockQ_F1 0.812 Fnat 0.609 iRMS 0.711 LRMS 2.831 Fnonnat 0.125 clashes 0 mapping DH:CG examples/1EXB_r_l_b.model.pdb D H -> examples/1EXB_r_l_b.pdb C G +DockQ 1.000 DockQ_F1 0.996 Fnat 1.000 iRMS 0.001 LRMS 0.001 Fnonnat 0.024 clashes 0 mapping EG:FH examples/1EXB_r_l_b.model.pdb E G -> examples/1EXB_r_l_b.pdb F H +DockQ 0.992 DockQ_F1 0.996 Fnat 0.976 iRMS 0.001 LRMS 0.001 Fnonnat 0.000 clashes 0 mapping EH:FG examples/1EXB_r_l_b.model.pdb E H -> examples/1EXB_r_l_b.pdb F G +DockQ 0.992 DockQ_F1 0.996 Fnat 0.976 iRMS 0.001 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping FG:EH examples/1EXB_r_l_b.model.pdb F G -> examples/1EXB_r_l_b.pdb E H +DockQ 0.992 DockQ_F1 0.996 Fnat 0.976 iRMS 0.001 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping FH:EG examples/1EXB_r_l_b.model.pdb F H -> examples/1EXB_r_l_b.pdb E G diff --git a/testdata/1EXB_DH.AE.dockq b/testdata/1EXB_DH.AE.dockq new file mode 100644 index 0000000..3b5e296 --- /dev/null +++ b/testdata/1EXB_DH.AE.dockq @@ -0,0 +1,23 @@ +**************************************************************** +* DockQ * +* Scoring function for protein-protein docking models * +* Statistics on CAPRI data: * +* 0.00 <= DockQ < 0.23 - Incorrect * +* 0.23 <= DockQ < 0.49 - Acceptable quality * +* 0.49 <= DockQ < 0.80 - Medium quality * +* DockQ >= 0.80 - High quality * +* Ref: S. Basu and B. Wallner, DockQ: A quality measure for * +* protein-protein docking models * +* doi:10.1371/journal.pone.0161879 * +* For comments, please email: bjorn.wallner@.liu.se * +**************************************************************** +Model : examples/1EXB_r_l_b.model.pdb +Native : examples/1EXB_r_l_b.pdb +Total DockQ over 1 native interfaces: 0.775 +Native chains: A, E + Model chains: D, H + DockQ_F1: 0.812 + DockQ: 0.775 + irms: 0.711 + Lrms: 2.831 + fnat: 0.609 diff --git a/testdata/1EXB_DH.AE_cif.dockq b/testdata/1EXB_DH.AE_cif.dockq new file mode 100644 index 0000000..52d2056 --- /dev/null +++ b/testdata/1EXB_DH.AE_cif.dockq @@ -0,0 +1,23 @@ +**************************************************************** +* DockQ * +* Scoring function for protein-protein docking models * +* Statistics on CAPRI data: * +* 0.00 <= DockQ < 0.23 - Incorrect * +* 0.23 <= DockQ < 0.49 - Acceptable quality * +* 0.49 <= DockQ < 0.80 - Medium quality * +* DockQ >= 0.80 - High quality * +* Ref: S. Basu and B. Wallner, DockQ: A quality measure for * +* protein-protein docking models * +* doi:10.1371/journal.pone.0161879 * +* For comments, please email: bjorn.wallner@.liu.se * +**************************************************************** +Model : examples/1EXB_r_l_b.model.pdb +Native : examples/1EXB.cif.gz +Total DockQ over 1 native interfaces: 0.775 +Native chains: A, E + Model chains: D, H + DockQ_F1: 0.812 + DockQ: 0.775 + irms: 0.711 + Lrms: 2.831 + fnat: 0.609 diff --git a/testdata/dimer_dimer.dockq b/testdata/dimer_dimer.dockq new file mode 100644 index 0000000..1f4c077 --- /dev/null +++ b/testdata/dimer_dimer.dockq @@ -0,0 +1,5 @@ +Total DockQ over 4 native interfaces: 1.000 with ABLH:ABLH model:native mapping +DockQ 1.000 DockQ_F1 1.000 Fnat 1.000 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping AB:AB examples/dimer_dimer.model.pdb A B -> examples/dimer_dimer.pdb A B +DockQ 1.000 DockQ_F1 1.000 Fnat 1.000 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping AL:AL examples/dimer_dimer.model.pdb A L -> examples/dimer_dimer.pdb A L +DockQ 1.000 DockQ_F1 1.000 Fnat 1.000 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping AH:AH examples/dimer_dimer.model.pdb A H -> examples/dimer_dimer.pdb A H +DockQ 1.000 DockQ_F1 1.000 Fnat 1.000 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping LH:LH examples/dimer_dimer.model.pdb L H -> examples/dimer_dimer.pdb L H diff --git a/testdata/model.dockq b/testdata/model.dockq new file mode 100644 index 0000000..767269a --- /dev/null +++ b/testdata/model.dockq @@ -0,0 +1,23 @@ +**************************************************************** +* DockQ * +* Scoring function for protein-protein docking models * +* Statistics on CAPRI data: * +* 0.00 <= DockQ < 0.23 - Incorrect * +* 0.23 <= DockQ < 0.49 - Acceptable quality * +* 0.49 <= DockQ < 0.80 - Medium quality * +* DockQ >= 0.80 - High quality * +* Ref: S. Basu and B. Wallner, DockQ: A quality measure for * +* protein-protein docking models * +* doi:10.1371/journal.pone.0161879 * +* For comments, please email: bjorn.wallner@.liu.se * +**************************************************************** +Model : examples/model.pdb +Native : examples/native.pdb +Total DockQ over 1 native interfaces: 0.700 +Native chains: A, B + Model chains: A, B + DockQ_F1: 0.731 + DockQ: 0.700 + irms: 1.232 + Lrms: 1.516 + fnat: 0.533 From 8ae5f6ae5f5157514708c8147194c7207d572330 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 11:19:56 +0100 Subject: [PATCH 147/173] testing on src --- run_test.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/run_test.sh b/run_test.sh index 768240f..d3ccac1 100644 --- a/run_test.sh +++ b/run_test.sh @@ -1,16 +1,17 @@ #!/bin/bash set -euo pipefail -which DockQ +src=$(find $(dirname $(which DockQ))/../ -name "DockQ.py" -exec dirname {} \;) +echo $src # Test that cython version behaves the same as nocython coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb > test diff test testdata/1A2K.dockq -coverage run -a --source='DockQ.DockQ' src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb > test +coverage run -a --source=$src $src/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb > test diff test testdata/1A2K.dockq coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align > test diff test testdata/1A2K.dockq -coverage run -a --source='DockQ.DockQ' src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align > test +coverage run -a --source=$src $src/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align > test diff test testdata/1A2K.dockq # Multiple interfaces From f7def987c309cef310556a1caa8adac2aeec37ef Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 11:53:31 +0100 Subject: [PATCH 148/173] move includes to setup.cfg --- .github/workflows/main.yml | 18 ------------------ run_test.sh | 26 ++++++++++++-------------- setup.cfg | 4 ++++ 3 files changed, 16 insertions(+), 32 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 289c406..e49e179 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,22 +28,4 @@ jobs: bash run_test.sh - name: Coverage run: | - coverage report test $(coverage report | grep TOTAL | awk '{ print $4 }' | tr -d "%") -ge $MIN_COVERAGE_REQUIRED - - #test_oldbio: - # if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name - # runs-on: ubuntu-latest - # timeout-minutes: 10 - # defaults: - # run: - # shell: bash -l {0} -# -# steps: -# - uses: actions/checkout@v3 -# - name: Test pipeline output -# run: | -# python -m pip install biopython==1.79 -# python -m pip install coverage -# python -m pip install . -# bash ./run_test.sh diff --git a/run_test.sh b/run_test.sh index d3ccac1..d5cd7f0 100644 --- a/run_test.sh +++ b/run_test.sh @@ -1,39 +1,37 @@ #!/bin/bash set -euo pipefail - -src=$(find $(dirname $(which DockQ))/../ -name "DockQ.py" -exec dirname {} \;) -echo $src +rm -f .coverage # Test that cython version behaves the same as nocython -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb > test +coverage run -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb > test diff test testdata/1A2K.dockq -coverage run -a --source=$src $src/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb > test +python src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb > test diff test testdata/1A2K.dockq -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align > test +coverage run -a -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align > test diff test testdata/1A2K.dockq -coverage run -a --source=$src $src/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align > test +python src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align > test diff test testdata/1A2K.dockq # Multiple interfaces -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short > test +coverage run -a -m DockQ.DockQ examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short > test diff test testdata/dimer_dimer.dockq # Test on structures with slightly different sequences -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/model.pdb examples/native.pdb --allowed_mismatches 1 > test +coverage run -a -m DockQ.DockQ examples/model.pdb examples/native.pdb --allowed_mismatches 1 > test diff test testdata/model.dockq # Test various mapping strategies -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping AB*:BA* > test +coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping AB*:BA* > test diff test testdata/1EXB_AB.BA.dockq -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping :ABC > test +coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping :ABC > test diff test testdata/1EXB_.ABC.dockq -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping ABCDEFGH:BADCFEHG > test +coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping ABCDEFGH:BADCFEHG > test diff test testdata/1EXB_ABCDEFGH.BADCFEHG.dockq # Test that cif parsing behaves same as pdb parsing -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --mapping DH:AE > test +coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --mapping DH:AE > test diff test testdata/1EXB_DH.AE.dockq -coverage run -a --source='DockQ.DockQ' -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB.cif.gz --mapping DH:AE > test +coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB.cif.gz --mapping DH:AE > test diff test testdata/1EXB_DH.AE_cif.dockq coverage report diff --git a/setup.cfg b/setup.cfg index b95a414..a206c6c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -21,3 +21,7 @@ where=src console_scripts = DockQ = DockQ.__main__:main +[coverage:run] +include = + */DockQ/* + From c0a9a169101238a41c6e7f2fdf79e485de96fbbb Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 12:01:01 +0100 Subject: [PATCH 149/173] coverage not mandatory --- run_test.sh | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/run_test.sh b/run_test.sh index d5cd7f0..a84aba5 100644 --- a/run_test.sh +++ b/run_test.sh @@ -1,37 +1,42 @@ #!/bin/bash set -euo pipefail -rm -f .coverage +rm -f test .coverage + +if command -v coverage &> /dev/null; then + binary="coverage run -a -m DockQ.DockQ" +else + binary="DockQ" +fi + # Test that cython version behaves the same as nocython -coverage run -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb > test +$binary examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb > test diff test testdata/1A2K.dockq python src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb > test diff test testdata/1A2K.dockq -coverage run -a -m DockQ.DockQ examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align > test +$binary examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align > test diff test testdata/1A2K.dockq python src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align > test diff test testdata/1A2K.dockq # Multiple interfaces -coverage run -a -m DockQ.DockQ examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short > test +$binary examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short > test diff test testdata/dimer_dimer.dockq # Test on structures with slightly different sequences -coverage run -a -m DockQ.DockQ examples/model.pdb examples/native.pdb --allowed_mismatches 1 > test +$binary examples/model.pdb examples/native.pdb --allowed_mismatches 1 > test diff test testdata/model.dockq # Test various mapping strategies -coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping AB*:BA* > test +$binary examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping AB*:BA* > test diff test testdata/1EXB_AB.BA.dockq -coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping :ABC > test +$binary examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping :ABC > test diff test testdata/1EXB_.ABC.dockq -coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping ABCDEFGH:BADCFEHG > test +$binary examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping ABCDEFGH:BADCFEHG > test diff test testdata/1EXB_ABCDEFGH.BADCFEHG.dockq # Test that cif parsing behaves same as pdb parsing -coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --mapping DH:AE > test +$binary examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --mapping DH:AE > test diff test testdata/1EXB_DH.AE.dockq -coverage run -a -m DockQ.DockQ examples/1EXB_r_l_b.model.pdb examples/1EXB.cif.gz --mapping DH:AE > test +$binary examples/1EXB_r_l_b.model.pdb examples/1EXB.cif.gz --mapping DH:AE > test diff test testdata/1EXB_DH.AE_cif.dockq - -coverage report From 5dedab7e45296b449007919dca2a7695256132b6 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 12:03:55 +0100 Subject: [PATCH 150/173] coverage report --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e49e179..ed4cfc5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -28,4 +28,5 @@ jobs: bash run_test.sh - name: Coverage run: | + coverage report test $(coverage report | grep TOTAL | awk '{ print $4 }' | tr -d "%") -ge $MIN_COVERAGE_REQUIRED From b28d6a906b1580cad3fefc24213e531f3914893d Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 12:07:24 +0100 Subject: [PATCH 151/173] remove useCA --- src/DockQ/DockQ.py | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index a11e91b..be3b4c8 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -53,13 +53,6 @@ def parse_args(): parser.add_argument( "--verbose", "-v", default=False, action="store_true", help="talk a lot!" ) - parser.add_argument( - "--use_CA", - "-ca", - default=False, - action="store_true", - help="use CA instead of backbone", - ) parser.add_argument( "--no_align", default=False, @@ -328,11 +321,10 @@ def calc_DockQ( sample_chains, ref_chains, alignments, - use_CA_only=False, capri_peptide=False, low_memory=False, ): - atom_for_sup = ("CA", "C", "N", "O", "P") if not use_CA_only else ("CA", "P") + atom_for_sup = ("CA", "C", "N", "O", "P") fnat_threshold = 4.0 if capri_peptide else 5.0 interface_threshold = 8.0 if capri_peptide else 10.0 clash_threshold = 2.0 @@ -685,7 +677,6 @@ def run_on_chains( model_chains, native_chains, no_align=False, - use_CA_only=False, capri_peptide=False, low_memory=False, ): @@ -704,7 +695,6 @@ def run_on_chains( model_chains, native_chains, alignments=tuple(alignments), - use_CA_only=use_CA_only, capri_peptide=capri_peptide, low_memory=False, ) @@ -716,7 +706,6 @@ def run_on_all_native_interfaces( native_structure, chain_map={"A": "A", "B": "B"}, no_align=False, - use_CA_only=False, capri_peptide=False, low_memory=False, ): @@ -740,7 +729,6 @@ def run_on_all_native_interfaces( model_chains, native_chains, no_align=no_align, - use_CA_only=use_CA_only, capri_peptide=capri_peptide, low_memory=False, ) @@ -976,7 +964,6 @@ def main(): native_structure, chain_map, args.no_align, - args.use_CA, args.capri_peptide, low_memory, ) @@ -1012,7 +999,6 @@ def main(): native_structure, best_mapping, args.no_align, - args.use_CA, args.capri_peptide, low_memory=False, ) From c81209d392d051272b031d6a356c3eae5b7c797d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wallner?= Date: Mon, 25 Mar 2024 12:49:04 +0100 Subject: [PATCH 152/173] changed argument lists to argument iterators --- src/DockQ/DockQ.py | 101 +++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 44 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 9278f78..e1f9c7b 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -6,7 +6,7 @@ import traceback import itertools import math -from functools import lru_cache, wraps +from functools import lru_cache, wraps, partial from argparse import ArgumentParser from tqdm import tqdm from parallelbar import progress_map @@ -761,7 +761,7 @@ def run_on_all_native_interfaces( capri_peptide=capri_peptide, low_memory=False, ) - if info: + if info and not low_memory: info["chain1"], info["chain2"] = ( chain_map[chain_pair[0]], chain_map[chain_pair[1]], @@ -885,6 +885,7 @@ def product_without_dupl(*args, repeat=1): #result = set(list(map(lambda x: tuple(sorted(x)), result))) # to remove symmetric duplicates for prod in result: yield tuple(prod) + def count_chain_combinations(chain_clusters): counts={} for chain in chain_clusters: @@ -893,29 +894,18 @@ def count_chain_combinations(chain_clusters): counts[chains]=0 counts[chains]+=1 number_of_combinations=np.prod([math.factorial(a) for a in counts.values()]) + return number_of_combinations #combos=itertools.product(*[itertools.permutations(chains) for chains in set([tuple(ch) for ch in chain_clusters.values()])]) - return(number_of_combinations,counts) + + #return(number_of_combinations,counts) #set(chain_clusters.values()) -def get_all_mappings( - model_structure, native_structure, model_chains, native_chains,initial_mapping,allowed_mismatches=0 -): - model_chains_to_combo = [mc for mc in model_chains if mc not in initial_mapping.values()] - native_chains_to_combo = [nc for nc in native_chains if nc not in initial_mapping.keys()] - - chain_clusters, reverse_map = group_chains( - model_structure, - native_structure, - model_chains_to_combo, - native_chains_to_combo, - allowed_mismatches, - ) +def get_all_chain_maps(chain_clusters,initial_mapping,reverse_map,model_chains_to_combo,native_chains_to_combo): all_mappings = product_without_dupl( *[cluster for cluster in chain_clusters.values() if cluster] ) - chain_maps=[] for mapping in all_mappings: chain_map = {key:value for key, value in initial_mapping.items()} if reverse_map: @@ -926,11 +916,7 @@ def get_all_mappings( chain_map.update({ native_chain: mapping[i] for i, native_chain in enumerate(native_chains_to_combo) }) - chain_maps.append(chain_map) - return chain_maps - -def run_on_all_native_interfaces_multi(args): - return run_on_all_native_interfaces(*args) + yield(chain_map) #@profile @@ -955,35 +941,62 @@ def main(): best_result = None best_mapping = None + model_chains_to_combo = [mc for mc in model_chains if mc not in initial_mapping.values()] + native_chains_to_combo = [nc for nc in native_chains if nc not in initial_mapping.keys()] - - - - chain_maps=get_all_mappings( + chain_clusters, reverse_map = group_chains( model_structure, native_structure, - model_chains, - native_chains, - initial_mapping, + model_chains_to_combo, + native_chains_to_combo, args.allowed_mismatches, ) + num_chain_combinations=count_chain_combinations(chain_clusters) + chain_maps=get_all_chain_maps(chain_clusters,initial_mapping,reverse_map,model_chains_to_combo,native_chains_to_combo) + + low_memory=num_chain_combinations>100 + run_chain_map=partial(run_on_all_native_interfaces, + model_structure, + native_structure, + no_align=args.no_align, + use_CA_only=args.use_CA, + capri_peptide=args.capri_peptide, + low_memory=low_memory) ##args: chain_map + + if num_chain_combinations>1: + #chunk_size=max(1,num_chain_combinations // args.n_cpu) + #I suspect large chunk_size will result in large input arguments to the workers. + chuck_size=128 + + #for large num_chain_combinations it should be possible to divide the chain_maps in chunks + result_this_mappings=progress_map(run_chain_map,chain_maps, total=num_chain_combinations,n_cpu=args.n_cpu, chunk_size=chunk_size) + #get a fresh iterator + chain_maps=get_all_chain_maps(chain_clusters,initial_mapping,reverse_map,model_chains_to_combo,native_chains_to_combo) + for chain_map,result_this_mapping in zip(chain_maps,result_this_mappings): + total_dockq = sum( + [result["DockQ_F1" if args.optDockQF1 else "DockQ"] for result in result_this_mapping.values()] + ) + if total_dockq > best_dockq: + best_dockq = total_dockq + best_result = result_this_mapping + best_mapping = chain_map + + - low_memory=len(chain_maps) > 100 - chain_map_args=[(model_structure,native_structure,chain_map,args.no_align,args.use_CA,args.capri_peptide,low_memory) for chain_map in chain_maps] - if len(chain_maps)>1: - chunk_size=max(1,len(chain_maps) // args.n_cpu) - result_this_mappings=progress_map(run_on_all_native_interfaces_multi,chain_map_args, n_cpu=args.n_cpu, chunk_size=chunk_size) else: #skip multi-threading for single jobs (skip the bar basically) - result_this_mappings=[run_on_all_native_interfaces(*chain_map_arg) for chain_map_arg in chain_map_args] - for chain_map,result_this_mapping in zip(chain_maps,result_this_mappings): - total_dockq = sum( - [result["DockQ_F1" if args.optDockQF1 else "DockQ"] for result in result_this_mapping.values()] - ) - if total_dockq > best_dockq: - best_dockq = total_dockq - best_result = result_this_mapping - best_mapping = chain_map + # result_this_mappings=[run_chain_map(chain_map) for chain_map in chain_maps] + for chain_maps in chain_maps: + result_this_mapping=run_chain_map(chain_map) + total_dockq = sum( + [result["DockQ_F1" if args.optDockQF1 else "DockQ"] for result in result_this_mapping.values()] + ) + if total_dockq > best_dockq: + best_dockq = total_dockq + best_result = result_this_mapping + best_mapping = chain_map + + if low_memory: #retrieve the full output by reruning the best chain mapping best_result=run_on_all_native_interfaces( model_structure, @@ -1010,7 +1023,7 @@ def print_results(info, short=False, verbose=False, capri_peptide=False): print( f"Total DockQ over {len(info['best_result'])} native interfaces: {info['GlobalDockQ']:.3f} with {info['best_mapping_str']} model:native mapping" ) - # print(info["best_result"]) + print(info["best_result"]) for chains, results in info["best_result"].items(): print( f"DockQ{capri_peptide_str} {results['DockQ']:.3f} DockQ_F1 {results['DockQ_F1']:.3f} Fnat {results['fnat']:.3f} iRMS {results['irms']:.3f} LRMS {results['Lrms']:.3f} Fnonnat {results['fnonnat']:.3f} clashes {results['clashes']} mapping {results['chain1']}{results['chain2']}:{chains[0]}{chains[1]} {info['model']} {results['chain1']} {results['chain2']} -> {info['native']} {chains[0]} {chains[1]}" From a084434eb812a2698c99da8da7c27893aa9cf628 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 13:37:58 +0100 Subject: [PATCH 153/173] new tests --- examples/6qwn-assembly1.cif.gz | Bin 0 -> 83223 bytes examples/6qwn-assembly2.cif.gz | Bin 0 -> 84398 bytes run_test.sh | 15 ++- src/DockQ/DockQ.py | 193 --------------------------------- 4 files changed, 10 insertions(+), 198 deletions(-) create mode 100644 examples/6qwn-assembly1.cif.gz create mode 100644 examples/6qwn-assembly2.cif.gz diff --git a/examples/6qwn-assembly1.cif.gz b/examples/6qwn-assembly1.cif.gz new file mode 100644 index 0000000000000000000000000000000000000000..ea1a8cdb2009b8bec6ec09981cf07eb7078ab74a GIT binary patch literal 83223 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 j`0q8Yka|4(M1_DY8(xHqA(lNTbyKDPB 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� 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 pD>^9kM5}Al_I+`O4f0B) test diff test testdata/1A2K.dockq -python src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb > test -diff test testdata/1A2K.dockq $binary examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align > test diff test testdata/1A2K.dockq -python src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align > test -diff test testdata/1A2K.dockq # Multiple interfaces $binary examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short > test @@ -40,3 +35,13 @@ $binary examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --mapping DH:AE > diff test testdata/1EXB_DH.AE.dockq $binary examples/1EXB_r_l_b.model.pdb examples/1EXB.cif.gz --mapping DH:AE > test diff test testdata/1EXB_DH.AE_cif.dockq + +# Peptide measures +$binary examples/6qwn-assembly1.cif.gz examples/6qwn-assembly2.cif.gz --capri_peptide > test +diff test testdata/6q2n_peptide.dockq + +# Test that cython version behaves the same as nocython +python src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb > test +diff test testdata/1A2K.dockq +python src/DockQ/DockQ.py examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align > test +diff test testdata/1A2K.dockq diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 1bc0a08..a231bef 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -120,24 +120,6 @@ def get_aligned_residues(chainA, chainB, alignment): return tuple(aligned_resA), tuple(aligned_resB) -@lru_cache -def list_atoms_per_residue2(chain, what): - n_atoms_per_residue = [] - atoms_ids = [] - for residue in chain: - # important to remove duplicate atoms (e.g. alternates) at this stage - atom_ids = tuple([a.id for a in residue.get_unpacked_list()]) - atoms_ids.append(atom_ids) - n_atoms_per_residue.append(len(set(atom_ids))) - return tuple(n_atoms_per_residue), tuple(atoms_ids) - - -@lru_cache -def get_atoms(chain, what): - atoms = np.array([atom.get_coord() for res in chain for atom in res.get_atoms()]) - return atoms - - @lru_cache def get_residue_distances(chain1, chain2, what, all_atom=True): if all_atom: @@ -174,148 +156,6 @@ def get_residue_distances(chain1, chain2, what, all_atom=True): return model_res_distances -@lru_cache -def get_aligned_atoms(n_atoms_per_res_chainA, n_atoms_per_res_chainB, alignment): - - if alignment[0] == alignment[2]: # no need to align - return ( - np.ones(sum(list(n_atoms_per_res_chainA))).astype(bool), - np.ones(sum(list(n_atoms_per_res_chainB))).astype(bool), - [i for i in range(len(alignment[0]))], - [i for i in range(len(alignment[1]))], - ) - atom_index_A = np.zeros(sum(list(n_atoms_per_res_chainA))).astype(bool) - atom_index_B = np.zeros(sum(list(n_atoms_per_res_chainB))).astype(bool) - res_index_A = [] - res_index_B = [] - - n_atoms_per_res_chainA = iter(n_atoms_per_res_chainA) - n_atoms_per_res_chainB = iter(n_atoms_per_res_chainB) - countA = iA = 0 - countB = iB = 0 - - for A, match, B in zip(*alignment): - if A != "-": - nA = next(n_atoms_per_res_chainA) - countA += nA - iA += 1 - if B != "-": - nB = next(n_atoms_per_res_chainB) - countB += nB - iB += 1 - - if match == "|": - atom_index_A[countA - nA : countA] = 1 - atom_index_B[countB - nB : countB] = 1 - res_index_A.append(iA - 1) - res_index_B.append(iB - 1) - - return atom_index_A, atom_index_B, res_index_A, res_index_B - - -class NpWrapper: - def __init__(self, x: np.array) -> None: - self.values = x - # here you can use your own hashing function - self.h = hashlib.sha224(x.view()).hexdigest() - - def __hash__(self) -> int: - return hash(self.h) - - def __eq__(self, __value: object) -> bool: - return __value.h == self.h - - -def dist_memoizer(get_atom_distances): - @lru_cache() - def cached_wrapper(np1, np2, n_atoms, what): - return get_atom_distances(np1.values, np2.values, n_atoms, what) - - @wraps(get_atom_distances) - def wrapper(x: np.array, y: np.array, n_atoms, what): - np1 = NpWrapper(x) - np2 = NpWrapper(y) - return cached_wrapper(np1, np2, n_atoms, what) - - return wrapper - - -@dist_memoizer -def get_atom_distances(chain1_atoms, chain2_atoms, n_atoms_per_res, what): - n_atoms_per_res_chain1, n_atoms_per_res_chain2 = n_atoms_per_res - - model_res_distances = residue_distances( - chain1_atoms, - chain2_atoms, - np.array(n_atoms_per_res_chain1).astype(int), - np.array(n_atoms_per_res_chain2).astype(int), - ) - return model_res_distances - - -def sup_memoizer(superimpose): - @lru_cache() - def cached_wrapper(np1, np2): - return superimpose(np1.values, np2.values) - - @wraps(superimpose) - def wrapper(x: np.array, y: np.array): - np1 = NpWrapper(x) - np2 = NpWrapper(y) - return cached_wrapper(np1, np2) - - return wrapper - - -@sup_memoizer -def superimpose(from_atoms, to_atoms): - super_imposer = SVDSuperimposer() - # Set to align on receptor - super_imposer.set(to_atoms, from_atoms) - super_imposer.run() - rot, tran = super_imposer.get_rotran() - return rot, tran, super_imposer - - -@lru_cache -def filter_atoms(model_info, native_info, filter=("CA", "C", "N", "O", "P")): - model_bools = [] - native_bools = [] - if "CA" in filter: # backbone filter - model_atom_ids = model_info - native_atom_ids = native_info - - n_atoms_per_res = [] - for model_ids, native_ids in zip(model_atom_ids, native_atom_ids): - model_select = [ - 1 if atom in filter and atom in native_ids else 0 - for atom in list(dict.fromkeys(model_ids)) - ] - native_select = [ - 1 if atom in filter and atom in model_ids else 0 - for atom in list(dict.fromkeys(native_ids)) - ] - model_bools.extend(model_select) - native_bools.extend(native_select) - n_atoms_per_res.append(sum(native_select)) - if sum(model_select) != sum(native_select): - print(model_ids, model_select) - print(native_ids, native_select) - print("ERROR!") - else: # filter by index - n_atoms_per_res = model_info - - for i, n_atoms in enumerate(n_atoms_per_res): - if i in filter: - model_bools.extend([1 for i in range(n_atoms)]) - else: - model_bools.extend([0 for i in range(n_atoms)]) - native_bools = model_bools - model_bools = np.array(model_bools).astype(bool) - native_bools = np.array(native_bools).astype(bool) - return model_bools, native_bools, tuple(n_atoms_per_res) - - # @profile def calc_DockQ( sample_chains, @@ -544,39 +384,6 @@ def format_alignment(aln): return alignment -def remove_hetatms(model): - chains = [chain.id for chain in model.get_chains()] - residues_to_delete = [] - - for chain in chains: - residues = model[chain].get_residues() - - for res in residues: - if res.id[0] != " ": - residues_to_delete.append(res.get_full_id()) - for _, _, chain, res in residues_to_delete: - model[chain].detach_child(res) - - for chain in chains: - if not model[chain]: - model.detach_child(chain) - - -def remove_h(model): - chains = [chain.id for chain in model.get_chains()] - atoms_to_delete = [] - - for chain in chains: - residues = model[chain].get_residues() - for residue in residues: - for atom in residue.get_atoms(): - if atom.element == "H": - atoms_to_delete.append(atom.get_full_id()) - - for _, _, chain, res, atom in atoms_to_delete: - model[chain][res].detach_child(atom[0]) - - @lru_cache def list_atoms_per_residue(chain, what): n_atoms_per_residue = [] From 40d392ef9ea81966a1010b5b0479c8a8b76a25be Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 13:39:13 +0100 Subject: [PATCH 154/173] blacken --- src/DockQ/DockQ.py | 133 +++++++++++++++++++++++------------- testdata/6q2n_peptide.dockq | 21 ++++++ 2 files changed, 105 insertions(+), 49 deletions(-) create mode 100644 testdata/6q2n_peptide.dockq diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index a231bef..4c55eca 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -545,7 +545,6 @@ def run_on_all_native_interfaces( chain_map[chain_pair[1]], ) results_dic[chain_pair] = info - return results_dic @@ -669,28 +668,34 @@ def product_without_dupl(*args, repeat=1): for prod in result: yield tuple(prod) + def count_chain_combinations(chain_clusters): counts = {} for chain in chain_clusters: chains = tuple(chain_clusters[chain]) if chains not in counts: - counts[chains]=0 - counts[chains]+=1 - number_of_combinations=np.prod([math.factorial(a) for a in counts.values()]) + counts[chains] = 0 + counts[chains] += 1 + number_of_combinations = np.prod([math.factorial(a) for a in counts.values()]) return number_of_combinations - #combos=itertools.product(*[itertools.permutations(chains) for chains in set([tuple(ch) for ch in chain_clusters.values()])]) - - #return(number_of_combinations,counts) - #set(chain_clusters.values()) + # combos=itertools.product(*[itertools.permutations(chains) for chains in set([tuple(ch) for ch in chain_clusters.values()])]) + # return(number_of_combinations,counts) + # set(chain_clusters.values()) -def get_all_chain_maps(chain_clusters,initial_mapping,reverse_map,model_chains_to_combo,native_chains_to_combo): +def get_all_chain_maps( + chain_clusters, + initial_mapping, + reverse_map, + model_chains_to_combo, + native_chains_to_combo, +): all_mappings = product_without_dupl( *[cluster for cluster in chain_clusters.values() if cluster] ) - for mapping in all_mappings: - chain_map = {key:value for key, value in initial_mapping.items()} + for mapping in all_mappings: + chain_map = {key: value for key, value in initial_mapping.items()} if reverse_map: chain_map.update( { @@ -699,11 +704,13 @@ def get_all_chain_maps(chain_clusters,initial_mapping,reverse_map,model_chains_t } ) else: - chain_map.update({ - native_chain: mapping[i] for i, native_chain in enumerate(native_chains_to_combo) - }) - yield(chain_map) - + chain_map.update( + { + native_chain: mapping[i] + for i, native_chain in enumerate(native_chains_to_combo) + } + ) + yield (chain_map) # @profile @@ -728,8 +735,12 @@ def main(): best_result = None best_mapping = None - model_chains_to_combo = [mc for mc in model_chains if mc not in initial_mapping.values()] - native_chains_to_combo = [nc for nc in native_chains if nc not in initial_mapping.keys()] + model_chains_to_combo = [ + mc for mc in model_chains if mc not in initial_mapping.values() + ] + native_chains_to_combo = [ + nc for nc in native_chains if nc not in initial_mapping.keys() + ] chain_clusters, reverse_map = group_chains( model_structure, @@ -739,51 +750,75 @@ def main(): args.allowed_mismatches, ) - num_chain_combinations=count_chain_combinations(chain_clusters) - chain_maps=get_all_chain_maps(chain_clusters,initial_mapping,reverse_map,model_chains_to_combo,native_chains_to_combo) - - low_memory=num_chain_combinations>100 - run_chain_map=partial(run_on_all_native_interfaces, - model_structure, - native_structure, - no_align=args.no_align, - capri_peptide=args.capri_peptide, - low_memory=low_memory) ##args: chain_map - - if num_chain_combinations>1: - #chunk_size=max(1,num_chain_combinations // args.n_cpu) - #I suspect large chunk_size will result in large input arguments to the workers. - chunk_size=512 - #for large num_chain_combinations it should be possible to divide the chain_maps in chunks - result_this_mappings=progress_map(run_chain_map,chain_maps, total=num_chain_combinations,n_cpu=args.n_cpu, chunk_size=chunk_size) - #get a fresh iterator - chain_maps=get_all_chain_maps(chain_clusters,initial_mapping,reverse_map,model_chains_to_combo,native_chains_to_combo) - for chain_map,result_this_mapping in zip(chain_maps,result_this_mappings): + num_chain_combinations = count_chain_combinations(chain_clusters) + chain_maps = get_all_chain_maps( + chain_clusters, + initial_mapping, + reverse_map, + model_chains_to_combo, + native_chains_to_combo, + ) + + low_memory = num_chain_combinations > 100 + run_chain_map = partial( + run_on_all_native_interfaces, + model_structure, + native_structure, + no_align=args.no_align, + capri_peptide=args.capri_peptide, + low_memory=low_memory, + ) ##args: chain_map + + if num_chain_combinations > 1: + # chunk_size=max(1,num_chain_combinations // args.n_cpu) + # I suspect large chunk_size will result in large input arguments to the workers. + chunk_size = 512 + # for large num_chain_combinations it should be possible to divide the chain_maps in chunks + result_this_mappings = progress_map( + run_chain_map, + chain_maps, + total=num_chain_combinations, + n_cpu=args.n_cpu, + chunk_size=chunk_size, + ) + # get a fresh iterator + chain_maps = get_all_chain_maps( + chain_clusters, + initial_mapping, + reverse_map, + model_chains_to_combo, + native_chains_to_combo, + ) + for chain_map, result_this_mapping in zip(chain_maps, result_this_mappings): total_dockq = sum( - [result["DockQ_F1" if args.optDockQF1 else "DockQ"] for result in result_this_mapping.values()] + [ + result["DockQ_F1" if args.optDockQF1 else "DockQ"] + for result in result_this_mapping.values() + ] ) - + if total_dockq > best_dockq: best_dockq = total_dockq best_result = result_this_mapping best_mapping = chain_map - else: #skip multi-threading for single jobs (skip the bar basically) - # result_this_mappings=[run_chain_map(chain_map) for chain_map in chain_maps] + else: # skip multi-threading for single jobs (skip the bar basically) + # result_this_mappings=[run_chain_map(chain_map) for chain_map in chain_maps] for chain_map in chain_maps: - result_this_mapping=run_chain_map(chain_map) + result_this_mapping = run_chain_map(chain_map) total_dockq = sum( - [result["DockQ_F1" if args.optDockQF1 else "DockQ"] for result in result_this_mapping.values()] + [ + result["DockQ_F1" if args.optDockQF1 else "DockQ"] + for result in result_this_mapping.values() + ] ) if total_dockq > best_dockq: best_dockq = total_dockq best_result = result_this_mapping best_mapping = chain_map - - - - if low_memory: #retrieve the full output by reruning the best chain mapping - best_result=run_on_all_native_interfaces( + + if low_memory: # retrieve the full output by reruning the best chain mapping + best_result = run_on_all_native_interfaces( model_structure, native_structure, best_mapping, diff --git a/testdata/6q2n_peptide.dockq b/testdata/6q2n_peptide.dockq new file mode 100644 index 0000000..eb84ff6 --- /dev/null +++ b/testdata/6q2n_peptide.dockq @@ -0,0 +1,21 @@ +**************************************************************** +* DockQ-CAPRI peptide * +* Do not trust any thing you read.... * +* OBS THE DEFINITION OF Fnat and iRMS are different for * +* peptides in CAPRI * +* * +* Ref: S. Basu and B. Wallner, DockQ: A quality measure for * +* protein-protein docking models * +* doi:10.1371/journal.pone.0161879 * +* For comments, please email: bjorn.wallner@.liu.se * +**************************************************************** +Model : examples/6qwn-assembly1.cif.gz +Native : examples/6qwn-assembly2.cif.gz +Total DockQ over 1 native interfaces: 0.872 +Native chains: B, G + Model chains: A, F + DockQ_F1: 0.885 + DockQ: 0.872 + irms: 0.588 + Lrms: 0.982 + fnat: 0.762 From e5cbf52ba297d726e5f2726e1342531ce57f7e97 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 13:41:58 +0100 Subject: [PATCH 155/173] cleanup --- src/DockQ/DockQ.py | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 4c55eca..5fc49dc 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -2,21 +2,22 @@ import sys import gzip +import math import hashlib import warnings import traceback import itertools -import math -from functools import lru_cache, wraps, partial from argparse import ArgumentParser -from tqdm import tqdm -from parallelbar import progress_map +from functools import lru_cache, wraps, partial import Bio.PDB import numpy as np from Bio import Align from Bio.SeqUtils import seq1 from Bio.SVDSuperimposer import SVDSuperimposer +from tqdm import tqdm +from parallelbar import progress_map + # fallback in case the cython version doesn't work, though it will be slower try: @@ -664,7 +665,7 @@ def product_without_dupl(*args, repeat=1): result = [ x + [y] for x in result for y in pool if y not in x ] # here we added condition - # result = set(list(map(lambda x: tuple(sorted(x)), result))) # to remove symmetric duplicates + for prod in result: yield tuple(prod) @@ -678,10 +679,6 @@ def count_chain_combinations(chain_clusters): counts[chains] += 1 number_of_combinations = np.prod([math.factorial(a) for a in counts.values()]) return number_of_combinations - # combos=itertools.product(*[itertools.permutations(chains) for chains in set([tuple(ch) for ch in chain_clusters.values()])]) - - # return(number_of_combinations,counts) - # set(chain_clusters.values()) def get_all_chain_maps( @@ -770,8 +767,6 @@ def main(): ) ##args: chain_map if num_chain_combinations > 1: - # chunk_size=max(1,num_chain_combinations // args.n_cpu) - # I suspect large chunk_size will result in large input arguments to the workers. chunk_size = 512 # for large num_chain_combinations it should be possible to divide the chain_maps in chunks result_this_mappings = progress_map( @@ -803,7 +798,6 @@ def main(): best_mapping = chain_map else: # skip multi-threading for single jobs (skip the bar basically) - # result_this_mappings=[run_chain_map(chain_map) for chain_map in chain_maps] for chain_map in chain_maps: result_this_mapping = run_chain_map(chain_map) total_dockq = sum( From b3790ce9469cc019cf97267345e4a41239a2a17f Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 13:42:32 +0100 Subject: [PATCH 156/173] higher coverage needed --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ed4cfc5..383193f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,7 +3,7 @@ name: CI on: [push, pull_request, workflow_dispatch] env: - MIN_COVERAGE_REQUIRED: 35 + MIN_COVERAGE_REQUIRED: 85 jobs: From 8dcbef29c50fadc3f16aeb2357db995aa1a3458b Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 14:17:24 +0100 Subject: [PATCH 157/173] NA backbone atoms --- run_test.sh | 4 ++-- src/DockQ/DockQ.py | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/run_test.sh b/run_test.sh index 78cdf6c..6c59803 100644 --- a/run_test.sh +++ b/run_test.sh @@ -9,10 +9,10 @@ else binary="DockQ" fi -$binary examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb > test -diff test testdata/1A2K.dockq $binary examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb --no_align > test diff test testdata/1A2K.dockq +$binary examples/1A2K_r_l_b.model.pdb examples/1A2K_r_l_b.pdb > test +diff test testdata/1A2K.dockq # Multiple interfaces $binary examples/dimer_dimer.model.pdb examples/dimer_dimer.pdb --short > test diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 5fc49dc..c005952 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -165,7 +165,10 @@ def calc_DockQ( capri_peptide=False, low_memory=False, ): - atom_for_sup = ("CA", "C", "N", "O", "P") + atom_for_sup = ("CA", "C", "N", "O", + "P", "OP1", "OP2", + "O2'", "O3'", "O4'", "O5'", + "C1'", "C2'", "C3'", "C4'", "C5'") fnat_threshold = 4.0 if capri_peptide else 5.0 interface_threshold = 8.0 if capri_peptide else 10.0 clash_threshold = 2.0 @@ -304,7 +307,7 @@ def dockq_formula(fnat, irms, Lrms): @lru_cache -def align_chains(model_chain, native_chain, use_numbering=False, verbose=False): +def align_chains(model_chain, native_chain, use_numbering=False): """ Function to align two PDB structures. This can be done by sequence (default) or by numbering. If the numbering is used, then each residue number from the pdb structure @@ -588,7 +591,7 @@ def group_chains( chain_clusters = {chain: [] for chain in ref_chains} for query_chain, ref_chain in alignment_targets: - aln = align_chains(query_structure[query_chain], ref_structure[ref_chain]) + aln = align_chains(query_structure[query_chain], ref_structure[ref_chain], use_numbering=False) alignment = format_alignment(aln) n_mismatches = alignment["matches"].count(".") @@ -645,13 +648,12 @@ def format_mapping_string(chain_mapping): chain1 = "" chain2 = "" - # mapping = sorted([(b, a) for a, b in chain_mapping.items()]) # Sorting might change LRMSD since the definition of receptor/ligand for equal length depends on order mapping = [(b, a) for a, b in chain_mapping.items()] for ( model_chain, native_chain, - ) in mapping: # sorted([(b,a) for a,b in chain_mapping.items()]): + ) in mapping: chain1 += model_chain chain2 += native_chain From 34a4029b115eb3b207ee14b1574ac403473befcb Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 15:09:53 +0100 Subject: [PATCH 158/173] caching alignments gives unexpected results when # mod chains < # nat chains --- src/DockQ/DockQ.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index c005952..1c1b11c 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -306,7 +306,7 @@ def dockq_formula(fnat, irms, Lrms): ) / 3 -@lru_cache +#@lru_cache def align_chains(model_chain, native_chain, use_numbering=False): """ Function to align two PDB structures. This can be done by sequence (default) or by From fd4555d8437d05c7442e1be21fc4db02942726d1 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 15:21:54 +0100 Subject: [PATCH 159/173] keep cache but be careful with use_numbering flag --- src/DockQ/DockQ.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 1c1b11c..b647436 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -157,7 +157,6 @@ def get_residue_distances(chain1, chain2, what, all_atom=True): return model_res_distances -# @profile def calc_DockQ( sample_chains, ref_chains, @@ -306,7 +305,7 @@ def dockq_formula(fnat, irms, Lrms): ) / 3 -#@lru_cache +@lru_cache def align_chains(model_chain, native_chain, use_numbering=False): """ Function to align two PDB structures. This can be done by sequence (default) or by @@ -326,7 +325,7 @@ def align_chains(model_chain, native_chain, use_numbering=False): for residue in native_chain.get_residues(): resn = int(residue.id[1]) native_numbering.append(resn) - # if the samllest resn is negative, it will be used to shift all numbers so they start from 0 + # if the smallest resn is negative, it will be used to shift all numbers so they start from 0 # the minimum offset is 45 to avoid including the "-" character that is reserved for gaps min_resn = max(45, -min(model_numbering + native_numbering)) @@ -483,7 +482,6 @@ def get_interface_atoms( @lru_cache -# @profile def run_on_chains( model_chains, native_chains, @@ -553,7 +551,6 @@ def run_on_all_native_interfaces( return results_dic -# @profile def load_PDB(path, chains=[], n_model=0): try: pdb_parser = PDBParser(QUIET=True) @@ -572,7 +569,6 @@ def load_PDB(path, chains=[], n_model=0): ) model = structure[n_model] - # remove_h(model) return model @@ -591,7 +587,7 @@ def group_chains( chain_clusters = {chain: [] for chain in ref_chains} for query_chain, ref_chain in alignment_targets: - aln = align_chains(query_structure[query_chain], ref_structure[ref_chain], use_numbering=False) + aln = align_chains(query_structure[query_chain], ref_structure[ref_chain], use_numbering=None) alignment = format_alignment(aln) n_mismatches = alignment["matches"].count(".") @@ -712,7 +708,6 @@ def get_all_chain_maps( yield (chain_map) -# @profile def main(): args = parse_args() initial_mapping, model_chains, native_chains = format_mapping(args.mapping) @@ -766,7 +761,7 @@ def main(): no_align=args.no_align, capri_peptide=args.capri_peptide, low_memory=low_memory, - ) ##args: chain_map + ) if num_chain_combinations > 1: chunk_size = 512 @@ -839,7 +834,6 @@ def print_results(info, short=False, verbose=False, capri_peptide=False): print( f"Total DockQ over {len(info['best_result'])} native interfaces: {info['GlobalDockQ']:.3f} with {info['best_mapping_str']} model:native mapping" ) - # print(info["best_result"]) for chains, results in info["best_result"].items(): print( f"DockQ{capri_peptide_str} {results['DockQ']:.3f} DockQ_F1 {results['DockQ_F1']:.3f} Fnat {results['fnat']:.3f} iRMS {results['irms']:.3f} LRMS {results['Lrms']:.3f} Fnonnat {results['fnonnat']:.3f} clashes {results['clashes']} mapping {results['chain1']}{results['chain2']}:{chains[0]}{chains[1]} {info['model']} {results['chain1']} {results['chain2']} -> {info['native']} {chains[0]} {chains[1]}" From 1f0f72abea848b20dc4465515ea5a8c2e193f19e Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 15:42:32 +0100 Subject: [PATCH 160/173] explaining the mapping flag --- README.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/README.md b/README.md index d89bfee..4c0191f 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,58 @@ DockQ 0.453 DockQ_F1 0.500 Fnat 0.500 iRMS 2.104 LRMS 8.131 Fnonnat 0.107 clashe ``` +## Model/Native chain mapping + +By default, DockQ will try to find the optimal mapping between interfaces found in the native and in the model. + +The simplest case is when a homodimer has been modelled. Then, the native interface "AB" (between native chains A and B) could be compared to +either the model AB interface, but also BA, as changing the order of the chains will generally change the results. If the user runs: + +`DockQ homodimer_model.pdb homodimer_native.pdb` + +the software will report the mapping (AB -> AB or AB -> BA) with highest DockQ score. + +If the user wishes to enforce a certain mapping, the flag `--mapping` can be used. This is useful, for example, when model/native contain a large number of homologous chains, +as it will speed up computations. + +**Complete mapping** + +The user defines the complete mapping between native and model chains with: `--mapping MODELCHAINS:NATIVECHAINS`. For example, in the previous case, two possible mappings can be: + +* `--mapping AB:AB` (native chain A corresponds to model chain A, native B to model B), +* `--mapping AB:BA` (native chain A corresponds to model chain B, native B to model A). + +The pair before the colon `:` defines the chain order in the model, the pair after defines the order in the native. + +**Partial mapping** + +If the user wishes to fix part of the mapping and let DockQ optimize the rest, wildcards can be used. For example, if a tetramer has chains `ABCD` in the model and `WXYZ` in the native, +the user might use: + +``` +--mapping A*:W* +``` + +where the wildcard `*` indicates that DockQ should optimize the mapping between BCD and XYZ while keeping A -> W fixed. Multiple chains can be fixed: + +``` +--mapping AD*:WY* +``` + +**Limiting the search to subset of native interfaces** + +If the user is interested one or more specific interfaces in the native, while the rest should be ignored, the following can be used: + +``` +--mapping :WX +``` + +Then DockQ will find the interface in the model that best matches the WX interface in the native. More native interfaces can be included: + +``` +--mapping :WXY +``` + **Other uses** Run DockQ with `-h/--help` to see a list of the available flags: From 442b5dd76be9341222be8f4258cfc0ca229bb0d5 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 15:43:56 +0100 Subject: [PATCH 161/173] small fixes --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4c0191f..e695264 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![CI status](https://github.com/bjornwallner/DockQ/actions/workflows/main.yml/badge.svg) # DockQ -## A Quality Measure for Protein-Protein Docking Models +**A Quality Measure for Protein-Protein Docking Models** ## Installation @@ -115,7 +115,7 @@ where the wildcard `*` indicates that DockQ should optimize the mapping between --mapping AD*:WY* ``` -**Limiting the search to subset of native interfaces** +**Limiting the search to subsets of native interfaces** If the user is interested one or more specific interfaces in the native, while the rest should be ignored, the following can be used: From e3c0bc6e88c350f6c69811727f1a63da0ec301a5 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 15:49:34 +0100 Subject: [PATCH 162/173] small fixes --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e695264..3f1dbad 100644 --- a/README.md +++ b/README.md @@ -123,10 +123,18 @@ If the user is interested one or more specific interfaces in the native, while t --mapping :WX ``` -Then DockQ will find the interface in the model that best matches the WX interface in the native. More native interfaces can be included: +which is equivalent to: + + +``` +--mapping *:WX +``` + +Then DockQ will find the interface in the model that best matches the WX interface in the native. Multiple native interfaces can be included: ``` --mapping :WXY +--mapping *:WXY ``` **Other uses** From b930d66857e9f24eea1ceddd76d0bc43279b35f9 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 15:51:16 +0100 Subject: [PATCH 163/173] small fixes --- src/DockQ/DockQ.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index b647436..ef1e729 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -37,9 +37,9 @@ def parse_args(): description="DockQ - Quality measure for \ protein-protein docking models" ) - parser.add_argument("model", metavar="", type=str, help="path to model file") + parser.add_argument("model", metavar="", type=str, help="Path to model file") parser.add_argument( - "native", metavar="", type=str, help="path to native file" + "native", metavar="", type=str, help="Path to native file" ) parser.add_argument( "--capri_peptide", @@ -49,10 +49,10 @@ def parse_args(): (DockQ cannot not be trusted for this setting)", ) parser.add_argument( - "--short", default=False, action="store_true", help="short output" + "--short", default=False, action="store_true", help="Short output" ) parser.add_argument( - "--verbose", "-v", default=False, action="store_true", help="talk a lot!" + "--verbose", "-v", default=False, action="store_true", help="Verbose output" ) parser.add_argument( "--no_align", @@ -71,13 +71,13 @@ def parse_args(): "--optDockQF1", default=False, action="store_true", - help="optimize on DockQ_F1 instead of DockQ", + help="Optimize on DockQ_F1 instead of DockQ", ) parser.add_argument( "--allowed_mismatches", default=0, type=int, - help="number of allowed mismatches when mapping model sequence to native sequence.", + help="Number of allowed mismatches when mapping model sequence to native sequence.", ) parser.add_argument( "--mapping", From f902a8133833f15beee917932c08a466914320b9 Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 16:52:58 +0100 Subject: [PATCH 164/173] simplify --- README.md | 19 +++++++++--------- src/DockQ/DockQ.py | 48 ++++++++++++++++++---------------------------- 2 files changed, 28 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 3f1dbad..ab5b6cd 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ After installing DockQ with `pip`, the `DockQ` binary will be in your path. Just **Example** -When running DockQ on model/native complexes with one or more interfaces, you will get a result for each interface. Results are computed to maximise the average DockQ across all interface: +When running DockQ on model/native complexes with one or more interfaces, you will get a result for each interface. Results are computed to maximise the average DockQ across all interfaces: ``` @@ -144,30 +144,29 @@ Run DockQ with `-h/--help` to see a list of the available flags: ``` bash$ DockQ -h -usage: DockQ [-h] [--capri_peptide] [--short] [--verbose] [--use_CA] [--no_align] [--optDockQF1] [--allowed_mismatches ALLOWED_MISMATCHES] [--mapping MODELCHAINS:NATIVECHAINS] +usage: DockQ [-h] [--capri_peptide] [--short] [--verbose] [--no_align] [--n_cpu n_cpu] [--optDockQF1] [--allowed_mismatches ALLOWED_MISMATCHES] [--mapping MODELCHAINS:NATIVECHAINS] DockQ - Quality measure for protein-protein docking models positional arguments: - path to model file - path to native file + Path to model file + Path to native file optional arguments: -h, --help show this help message and exit --capri_peptide use version for capri_peptide (DockQ cannot not be trusted for this setting) - --short short output - --verbose, -v talk a lot! - --use_CA, -ca use CA instead of backbone + --short Short output + --verbose, -v Verbose output --no_align Do not align native and model using sequence alignments, but use the numbering of residues instead - --optDockQF1 optimize on DockQ_F1 instead of DockQ + --n_cpu n_cpu Number of cores to use + --optDockQF1 Optimize on DockQ_F1 instead of DockQ --allowed_mismatches ALLOWED_MISMATCHES - number of allowed mismatches when mapping model sequence to native sequence. + Number of allowed mismatches when mapping model sequence to native sequence. --mapping MODELCHAINS:NATIVECHAINS Specify a chain mapping between model and native structure. If the native contains two chains "H" and "L" while the model contains two chains "A" and "B", and chain A is a model of native chain H and chain B is a model of native chain L, the flag can be set as: '--mapping AB:HL'. This can also help limit the search to specific native interfaces. For example, if the native is a tetramer (ABCD) but the user is only interested in the interface between chains B and C, the flag can be set as: '--mapping :BC' or the equivalent '--mapping *:BC'. - ``` diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index ef1e729..f3b7af4 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -7,6 +7,7 @@ import warnings import traceback import itertools +from collections import Counter from argparse import ArgumentParser from functools import lru_cache, wraps, partial @@ -669,13 +670,8 @@ def product_without_dupl(*args, repeat=1): def count_chain_combinations(chain_clusters): - counts = {} - for chain in chain_clusters: - chains = tuple(chain_clusters[chain]) - if chains not in counts: - counts[chains] = 0 - counts[chains] += 1 - number_of_combinations = np.prod([math.factorial(a) for a in counts.values()]) + tuples = [tuple(l) for l in chain_clusters.values()] + number_of_combinations = np.prod([math.factorial(a) for a in Counter(tuples).values()]) return number_of_combinations @@ -743,7 +739,6 @@ def main(): native_chains_to_combo, args.allowed_mismatches, ) - num_chain_combinations = count_chain_combinations(chain_clusters) chain_maps = get_all_chain_maps( chain_clusters, @@ -793,29 +788,24 @@ def main(): best_dockq = total_dockq best_result = result_this_mapping best_mapping = chain_map - - else: # skip multi-threading for single jobs (skip the bar basically) - for chain_map in chain_maps: - result_this_mapping = run_chain_map(chain_map) - total_dockq = sum( - [ - result["DockQ_F1" if args.optDockQF1 else "DockQ"] - for result in result_this_mapping.values() - ] + if low_memory: # retrieve the full output by rerunning the best chain mapping + best_result = run_on_all_native_interfaces( + model_structure, + native_structure, + best_mapping, + args.no_align, + args.capri_peptide, + low_memory=False, ) - if total_dockq > best_dockq: - best_dockq = total_dockq - best_result = result_this_mapping - best_mapping = chain_map - if low_memory: # retrieve the full output by reruning the best chain mapping - best_result = run_on_all_native_interfaces( - model_structure, - native_structure, - best_mapping, - args.no_align, - args.capri_peptide, - low_memory=False, + else: # skip multi-threading for single jobs (skip the bar basically) + best_mapping = next(chain_maps) + best_result = run_chain_map(best_mapping) + best_dockq = sum( + [ + result["DockQ_F1" if args.optDockQF1 else "DockQ"] + for result in best_result.values() + ] ) info["model"] = args.model From 337ef7fefdc507d3ea37d68893e3c8c0154907ab Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 17:21:57 +0100 Subject: [PATCH 165/173] unused imports --- src/DockQ/DockQ.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index f3b7af4..bb05b40 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -3,20 +3,16 @@ import sys import gzip import math -import hashlib import warnings -import traceback import itertools from collections import Counter from argparse import ArgumentParser -from functools import lru_cache, wraps, partial +from functools import lru_cache, partial -import Bio.PDB import numpy as np from Bio import Align from Bio.SeqUtils import seq1 from Bio.SVDSuperimposer import SVDSuperimposer -from tqdm import tqdm from parallelbar import progress_map From 083b6bf489bdebea53608bf2f642abcbc8135c1d Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 17:31:15 +0100 Subject: [PATCH 166/173] copy of iterator rather than re-generating it --- src/DockQ/DockQ.py | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index bb05b40..702c64c 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -161,9 +161,9 @@ def calc_DockQ( capri_peptide=False, low_memory=False, ): - atom_for_sup = ("CA", "C", "N", "O", - "P", "OP1", "OP2", - "O2'", "O3'", "O4'", "O5'", + atom_for_sup = ("CA", "C", "N", "O", + "P", "OP1", "OP2", + "O2'", "O3'", "O4'", "O5'", "C1'", "C2'", "C3'", "C4'", "C5'") fnat_threshold = 4.0 if capri_peptide else 5.0 interface_threshold = 8.0 if capri_peptide else 10.0 @@ -743,6 +743,8 @@ def main(): model_chains_to_combo, native_chains_to_combo, ) + # copy iterator to use later + chain_maps, chain_maps2 = itertools.tee(chain_maps) low_memory = num_chain_combinations > 100 run_chain_map = partial( @@ -764,15 +766,8 @@ def main(): n_cpu=args.n_cpu, chunk_size=chunk_size, ) - # get a fresh iterator - chain_maps = get_all_chain_maps( - chain_clusters, - initial_mapping, - reverse_map, - model_chains_to_combo, - native_chains_to_combo, - ) - for chain_map, result_this_mapping in zip(chain_maps, result_this_mappings): + + for chain_map, result_this_mapping in zip(chain_maps2, result_this_mappings): total_dockq = sum( [ result["DockQ_F1" if args.optDockQF1 else "DockQ"] From 73bf92d2fd0c88cb6f38682e2444f3e9eb12853a Mon Sep 17 00:00:00 2001 From: clami66 Date: Mon, 25 Mar 2024 19:52:28 +0100 Subject: [PATCH 167/173] slight optimizations --- src/DockQ/DockQ.py | 19 +++++++++++-------- src/DockQ/operations.pyx | 6 +++++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 702c64c..1a1f3b4 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -125,10 +125,10 @@ def get_residue_distances(chain1, chain2, what, all_atom=True): n_atoms_per_res_chain1 = list_atoms_per_residue(chain1, what) n_atoms_per_res_chain2 = list_atoms_per_residue(chain2, what) model_A_atoms = np.asarray( - [atom.get_coord() for res in chain1 for atom in res.get_atoms()] + [atom.coord for res in chain1 for atom in res.get_atoms()] ) model_B_atoms = np.asarray( - [atom.get_coord() for res in chain2 for atom in res.get_atoms()] + [atom.coord for res in chain2 for atom in res.get_atoms()] ) else: # distances were already between CBs only @@ -154,6 +154,7 @@ def get_residue_distances(chain1, chain2, what, all_atom=True): return model_res_distances +#@profile def calc_DockQ( sample_chains, ref_chains, @@ -189,7 +190,8 @@ def calc_DockQ( sample_res_distances = get_residue_distances( aligned_sample_1, aligned_sample_2, "sample" ) - ref_res_distances = get_residue_distances(aligned_ref_1, aligned_ref_2, "ref") + if ref_res_distances.shape != sample_res_distances.shape: + ref_res_distances = get_residue_distances(aligned_ref_1, aligned_ref_2, "ref") assert ( sample_res_distances.shape == ref_res_distances.shape @@ -424,7 +426,6 @@ def get_interacting_pairs(distances, threshold): @lru_cache -# @profile def get_interface_atoms( interacting_pairs, model_chains, @@ -517,7 +518,7 @@ def run_on_all_native_interfaces( ): """Given a native-model chain map, finds all non-null native interfaces and runs DockQ for each native-model pair of interfaces""" - results_dic = {} + results_dic = dict() native_chain_ids = list(chain_map.keys()) for chain_pair in itertools.combinations(native_chain_ids, 2): @@ -666,8 +667,8 @@ def product_without_dupl(*args, repeat=1): def count_chain_combinations(chain_clusters): - tuples = [tuple(l) for l in chain_clusters.values()] - number_of_combinations = np.prod([math.factorial(a) for a in Counter(tuples).values()]) + clusters = [tuple(li) for li in chain_clusters.values()] + number_of_combinations = np.prod([math.factorial(a) for a in Counter(clusters).values()]) return number_of_combinations @@ -700,6 +701,7 @@ def get_all_chain_maps( yield (chain_map) +#@profile def main(): args = parse_args() initial_mapping, model_chains, native_chains = format_mapping(args.mapping) @@ -711,7 +713,7 @@ def main(): native_chains = ( [c.id for c in native_structure] if not native_chains else native_chains ) - info = {} + if len(model_chains) < 2 or len(native_chains) < 2: print("Need at least two chains in the two inputs\n") sys.exit() @@ -799,6 +801,7 @@ def main(): ] ) + info = dict() info["model"] = args.model info["native"] = args.native info["best_dockq"] = best_dockq diff --git a/src/DockQ/operations.pyx b/src/DockQ/operations.pyx index f95b2b6..7ac0fcd 100644 --- a/src/DockQ/operations.pyx +++ b/src/DockQ/operations.pyx @@ -11,7 +11,7 @@ def residue_distances(float [:,:] atom_coordinates1, float [:,:] atom_coordinate int n_res_i = atoms_per_res1.shape[0] int n_res_j = atoms_per_res2.shape[0] float this_d, min_d - float [:,:] res_distances = np.zeros((n_res_i, n_res_j), dtype=np.float32) + float [:,:] res_distances = np.zeros((n_res_i, n_res_j), dtype=np.float32) cum_i_atoms = 0 for i in range(n_res_i): @@ -27,6 +27,10 @@ def residue_distances(float [:,:] atom_coordinates1, float [:,:] atom_coordinate this_d = (atom_coordinates1[x][0] - atom_coordinates2[y][0])**2 + (atom_coordinates1[x][1] - atom_coordinates2[y][1])**2 + (atom_coordinates1[x][2] - atom_coordinates2[y][2])**2 if this_d < min_d: min_d = this_d + if min_d > 400.0: + break + if min_d > 400.0: + break res_distances[i, j] = min_d cum_j_atoms = cum_j_atoms + j_atoms cum_i_atoms = cum_i_atoms + i_atoms From 9b6d9984383f73b8c1ab03c498f70ace09f8bf52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Wallner?= Date: Thu, 28 Mar 2024 15:02:49 +0100 Subject: [PATCH 168/173] final changes --- src/DockQ/DockQ.py | 89 +++++++++++++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 25 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 1a1f3b4..d5d1b99 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -61,9 +61,16 @@ def parse_args(): "--n_cpu", default=8, type=int, - metavar="n_cpu", + metavar="CPU", help="Number of cores to use", ) + parser.add_argument( + "--max_chunk", + default=512, + type=int, + metavar="CHUNK", + help="Maximum size of chunks given to the cores, actual chunksize is min(max_chunk,combos/cpus)", + ) parser.add_argument( "--optDockQF1", default=False, @@ -503,7 +510,7 @@ def run_on_chains( native_chains, alignments=tuple(alignments), capri_peptide=capri_peptide, - low_memory=False, + low_memory=low_memory, ) return info @@ -515,10 +522,11 @@ def run_on_all_native_interfaces( no_align=False, capri_peptide=False, low_memory=False, + optDockQF1=False, ): """Given a native-model chain map, finds all non-null native interfaces and runs DockQ for each native-model pair of interfaces""" - results_dic = dict() + result_mapping = dict() native_chain_ids = list(chain_map.keys()) for chain_pair in itertools.combinations(native_chain_ids, 2): @@ -537,16 +545,23 @@ def run_on_all_native_interfaces( native_chains, no_align=no_align, capri_peptide=capri_peptide, - low_memory=False, + low_memory=low_memory, ) if info: info["chain1"], info["chain2"] = ( chain_map[chain_pair[0]], chain_map[chain_pair[1]], ) - results_dic[chain_pair] = info + info['chain_map']=chain_map #diagonstics + result_mapping[chain_pair] = info + total_dockq = sum( + [ + result["DockQ_F1" if optDockQF1 else "DockQ"] + for result in result_mapping.values() + ] + ) + return result_mapping,total_dockq - return results_dic def load_PDB(path, chains=[], n_model=0): @@ -687,7 +702,7 @@ def get_all_chain_maps( if reverse_map: chain_map.update( { - mapping[i]: model_chain + mapping[i]: model_chain for i, model_chain in enumerate(model_chains_to_combo) } ) @@ -700,6 +715,25 @@ def get_all_chain_maps( ) yield (chain_map) +def get_chain_map_from_dockq(result): + chain_map={} + for ch1,ch2 in result: + chain_map[ch1]=result[ch1,ch2]['chain1'] + chain_map[ch2]=result[ch1,ch2]['chain2'] + return chain_map +def get_best_mapping(result_mappings,optDockF1=False): + total_dockq=0 + for result_mapping in result_mappings: + total_dockq = sum( + [ + result["DockQ_F1" if optDockQF1 else "DockQ"] + for result in result_mapping.values() + ] + ) + if total_dockq > best_dockq: + best_dockq = total_dockq + return best_result, best_dockq + #@profile def main(): @@ -737,7 +771,8 @@ def main(): native_chains_to_combo, args.allowed_mismatches, ) - num_chain_combinations = count_chain_combinations(chain_clusters) + + chain_maps = get_all_chain_maps( chain_clusters, initial_mapping, @@ -745,6 +780,14 @@ def main(): model_chains_to_combo, native_chains_to_combo, ) + num_chain_combinations = count_chain_combinations(chain_clusters) + if num_chain_combinations==1 and not args.mapping: #A HACK count_chain_combinations does not work if there are different number of chains in native. + chain_maps, chain_maps_ = itertools.tee(chain_maps) + num_chain_combinations=sum(1 for _ in chain_maps_) + #print(num_chain_combinations,chain_clusters) + #print(list(chain_maps)) + + #sys.exit() # copy iterator to use later chain_maps, chain_maps2 = itertools.tee(chain_maps) @@ -759,30 +802,32 @@ def main(): ) if num_chain_combinations > 1: - chunk_size = 512 + #chunk_size = args.n_chunk + cpus=min(num_chain_combinations,args.n_cpu) + chunk_size=min(args.max_chunk,max(1,num_chain_combinations//cpus)) + #print(cpus,chunk_size) # for large num_chain_combinations it should be possible to divide the chain_maps in chunks result_this_mappings = progress_map( run_chain_map, chain_maps, total=num_chain_combinations, - n_cpu=args.n_cpu, + n_cpu=cpus, chunk_size=chunk_size, ) - for chain_map, result_this_mapping in zip(chain_maps2, result_this_mappings): - total_dockq = sum( - [ - result["DockQ_F1" if args.optDockQF1 else "DockQ"] - for result in result_this_mapping.values() - ] - ) + for chain_map, (result_this_mapping,total_dockq) in zip(chain_maps2, result_this_mappings): + #print(chain_map,result_this_mapping) if total_dockq > best_dockq: best_dockq = total_dockq best_result = result_this_mapping + #best_mapping2=get_chain_map_from_dockq(best_result) best_mapping = chain_map + #print(best_result) + #print(f"{format_mapping_string(best_mapping)}") + #print(f"{format_mapping_string(best_mapping2)}") if low_memory: # retrieve the full output by rerunning the best chain mapping - best_result = run_on_all_native_interfaces( + best_result,total_dockq = run_on_all_native_interfaces( model_structure, native_structure, best_mapping, @@ -793,13 +838,7 @@ def main(): else: # skip multi-threading for single jobs (skip the bar basically) best_mapping = next(chain_maps) - best_result = run_chain_map(best_mapping) - best_dockq = sum( - [ - result["DockQ_F1" if args.optDockQF1 else "DockQ"] - for result in best_result.values() - ] - ) + best_result,best_dockq = run_chain_map(best_mapping) info = dict() info["model"] = args.model From b43262253c17ed9d7a7c84a1cc7590708ebce495 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 4 Apr 2024 15:12:46 +0200 Subject: [PATCH 169/173] lowmem test --- run_test.sh | 4 ++ src/DockQ/DockQ.py | 109 ++++++++++++++++++++++++++------------------- 2 files changed, 66 insertions(+), 47 deletions(-) diff --git a/run_test.sh b/run_test.sh index 6c59803..2e38441 100644 --- a/run_test.sh +++ b/run_test.sh @@ -22,6 +22,10 @@ diff test testdata/dimer_dimer.dockq $binary examples/model.pdb examples/native.pdb --allowed_mismatches 1 > test diff test testdata/model.dockq +# lowmem test +$binary examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short > test +diff test testdata/1EXB.dockq + # Test various mapping strategies $binary examples/1EXB_r_l_b.model.pdb examples/1EXB_r_l_b.pdb --short --mapping AB*:BA* > test diff test testdata/1EXB_AB.BA.dockq diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index d5d1b99..bcf0c12 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -161,7 +161,7 @@ def get_residue_distances(chain1, chain2, what, all_atom=True): return model_res_distances -#@profile +# @profile def calc_DockQ( sample_chains, ref_chains, @@ -169,10 +169,24 @@ def calc_DockQ( capri_peptide=False, low_memory=False, ): - atom_for_sup = ("CA", "C", "N", "O", - "P", "OP1", "OP2", - "O2'", "O3'", "O4'", "O5'", - "C1'", "C2'", "C3'", "C4'", "C5'") + atom_for_sup = ( + "CA", + "C", + "N", + "O", + "P", + "OP1", + "OP2", + "O2'", + "O3'", + "O4'", + "O5'", + "C1'", + "C2'", + "C3'", + "C4'", + "C5'", + ) fnat_threshold = 4.0 if capri_peptide else 5.0 interface_threshold = 8.0 if capri_peptide else 10.0 clash_threshold = 2.0 @@ -552,16 +566,15 @@ def run_on_all_native_interfaces( chain_map[chain_pair[0]], chain_map[chain_pair[1]], ) - info['chain_map']=chain_map #diagonstics + info["chain_map"] = chain_map # diagonstics result_mapping[chain_pair] = info total_dockq = sum( - [ - result["DockQ_F1" if optDockQF1 else "DockQ"] - for result in result_mapping.values() - ] - ) - return result_mapping,total_dockq - + [ + result["DockQ_F1" if optDockQF1 else "DockQ"] + for result in result_mapping.values() + ] + ) + return result_mapping, total_dockq def load_PDB(path, chains=[], n_model=0): @@ -600,7 +613,9 @@ def group_chains( chain_clusters = {chain: [] for chain in ref_chains} for query_chain, ref_chain in alignment_targets: - aln = align_chains(query_structure[query_chain], ref_structure[ref_chain], use_numbering=None) + aln = align_chains( + query_structure[query_chain], ref_structure[ref_chain], use_numbering=None + ) alignment = format_alignment(aln) n_mismatches = alignment["matches"].count(".") @@ -683,7 +698,9 @@ def product_without_dupl(*args, repeat=1): def count_chain_combinations(chain_clusters): clusters = [tuple(li) for li in chain_clusters.values()] - number_of_combinations = np.prod([math.factorial(a) for a in Counter(clusters).values()]) + number_of_combinations = np.prod( + [math.factorial(a) for a in Counter(clusters).values()] + ) return number_of_combinations @@ -702,7 +719,7 @@ def get_all_chain_maps( if reverse_map: chain_map.update( { - mapping[i]: model_chain + mapping[i]: model_chain for i, model_chain in enumerate(model_chains_to_combo) } ) @@ -715,27 +732,30 @@ def get_all_chain_maps( ) yield (chain_map) + def get_chain_map_from_dockq(result): - chain_map={} - for ch1,ch2 in result: - chain_map[ch1]=result[ch1,ch2]['chain1'] - chain_map[ch2]=result[ch1,ch2]['chain2'] + chain_map = {} + for ch1, ch2 in result: + chain_map[ch1] = result[ch1, ch2]["chain1"] + chain_map[ch2] = result[ch1, ch2]["chain2"] return chain_map -def get_best_mapping(result_mappings,optDockF1=False): - total_dockq=0 + + +def get_best_mapping(result_mappings, optDockF1=False): + total_dockq = 0 for result_mapping in result_mappings: total_dockq = sum( - [ - result["DockQ_F1" if optDockQF1 else "DockQ"] - for result in result_mapping.values() - ] - ) + [ + result["DockQ_F1" if optDockQF1 else "DockQ"] + for result in result_mapping.values() + ] + ) if total_dockq > best_dockq: best_dockq = total_dockq - return best_result, best_dockq + return best_result, best_dockq -#@profile +# @profile def main(): args = parse_args() initial_mapping, model_chains, native_chains = format_mapping(args.mapping) @@ -771,7 +791,6 @@ def main(): native_chains_to_combo, args.allowed_mismatches, ) - chain_maps = get_all_chain_maps( chain_clusters, @@ -781,13 +800,12 @@ def main(): native_chains_to_combo, ) num_chain_combinations = count_chain_combinations(chain_clusters) - if num_chain_combinations==1 and not args.mapping: #A HACK count_chain_combinations does not work if there are different number of chains in native. + if ( + num_chain_combinations == 1 and not args.mapping + ): # A HACK count_chain_combinations does not work if there are different number of chains in native. chain_maps, chain_maps_ = itertools.tee(chain_maps) - num_chain_combinations=sum(1 for _ in chain_maps_) - #print(num_chain_combinations,chain_clusters) - #print(list(chain_maps)) + num_chain_combinations = sum(1 for _ in chain_maps_) - #sys.exit() # copy iterator to use later chain_maps, chain_maps2 = itertools.tee(chain_maps) @@ -802,10 +820,9 @@ def main(): ) if num_chain_combinations > 1: - #chunk_size = args.n_chunk - cpus=min(num_chain_combinations,args.n_cpu) - chunk_size=min(args.max_chunk,max(1,num_chain_combinations//cpus)) - #print(cpus,chunk_size) + cpus = min(num_chain_combinations, args.n_cpu) + chunk_size = min(args.max_chunk, max(1, num_chain_combinations // cpus)) + # for large num_chain_combinations it should be possible to divide the chain_maps in chunks result_this_mappings = progress_map( run_chain_map, @@ -815,19 +832,17 @@ def main(): chunk_size=chunk_size, ) - for chain_map, (result_this_mapping,total_dockq) in zip(chain_maps2, result_this_mappings): - #print(chain_map,result_this_mapping) + for chain_map, (result_this_mapping, total_dockq) in zip( + chain_maps2, result_this_mappings + ): if total_dockq > best_dockq: best_dockq = total_dockq best_result = result_this_mapping - #best_mapping2=get_chain_map_from_dockq(best_result) best_mapping = chain_map - #print(best_result) - #print(f"{format_mapping_string(best_mapping)}") - #print(f"{format_mapping_string(best_mapping2)}") + if low_memory: # retrieve the full output by rerunning the best chain mapping - best_result,total_dockq = run_on_all_native_interfaces( + best_result, total_dockq = run_on_all_native_interfaces( model_structure, native_structure, best_mapping, @@ -838,7 +853,7 @@ def main(): else: # skip multi-threading for single jobs (skip the bar basically) best_mapping = next(chain_maps) - best_result,best_dockq = run_chain_map(best_mapping) + best_result, best_dockq = run_chain_map(best_mapping) info = dict() info["model"] = args.model From ba73963e6929649b572bd47278f9f07d4ce09484 Mon Sep 17 00:00:00 2001 From: clami66 Date: Thu, 4 Apr 2024 15:14:10 +0200 Subject: [PATCH 170/173] add test output --- testdata/1EXB.dockq | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 testdata/1EXB.dockq diff --git a/testdata/1EXB.dockq b/testdata/1EXB.dockq new file mode 100644 index 0000000..fdc0805 --- /dev/null +++ b/testdata/1EXB.dockq @@ -0,0 +1,17 @@ +Total DockQ over 16 native interfaces: 0.852 with BACDFHEG:ABDCEGFH model:native mapping +DockQ 1.000 DockQ_F1 1.000 Fnat 1.000 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping BC:AD examples/1EXB_r_l_b.model.pdb B C -> examples/1EXB_r_l_b.pdb A D +DockQ 0.995 DockQ_F1 0.998 Fnat 0.985 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping BD:AC examples/1EXB_r_l_b.model.pdb B D -> examples/1EXB_r_l_b.pdb A C +DockQ 0.552 DockQ_F1 0.606 Fnat 0.304 iRMS 1.458 LRMS 3.757 Fnonnat 0.000 clashes 0 mapping BF:AE examples/1EXB_r_l_b.model.pdb B F -> examples/1EXB_r_l_b.pdb A E +DockQ 0.694 DockQ_F1 0.751 Fnat 0.400 iRMS 0.793 LRMS 2.831 Fnonnat 0.000 clashes 0 mapping BH:AG examples/1EXB_r_l_b.model.pdb B H -> examples/1EXB_r_l_b.pdb A G +DockQ 0.995 DockQ_F1 0.998 Fnat 0.985 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping AC:BD examples/1EXB_r_l_b.model.pdb A C -> examples/1EXB_r_l_b.pdb B D +DockQ 0.995 DockQ_F1 0.998 Fnat 0.985 iRMS 0.000 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping AD:BC examples/1EXB_r_l_b.model.pdb A D -> examples/1EXB_r_l_b.pdb B C +DockQ 0.742 DockQ_F1 0.772 Fnat 0.609 iRMS 0.850 LRMS 3.426 Fnonnat 0.176 clashes 0 mapping AE:BF examples/1EXB_r_l_b.model.pdb A E -> examples/1EXB_r_l_b.pdb B F +DockQ 0.824 DockQ_F1 0.853 Fnat 0.800 iRMS 0.625 LRMS 3.994 Fnonnat 0.000 clashes 0 mapping AG:BH examples/1EXB_r_l_b.model.pdb A G -> examples/1EXB_r_l_b.pdb B H +DockQ 0.687 DockQ_F1 0.737 Fnat 0.600 iRMS 1.161 LRMS 3.757 Fnonnat 0.000 clashes 0 mapping CF:DE examples/1EXB_r_l_b.model.pdb C F -> examples/1EXB_r_l_b.pdb D E +DockQ 0.477 DockQ_F1 0.502 Fnat 0.087 iRMS 1.425 LRMS 3.994 Fnonnat 0.000 clashes 0 mapping CG:DH examples/1EXB_r_l_b.model.pdb C G -> examples/1EXB_r_l_b.pdb D H +DockQ 0.775 DockQ_F1 0.812 Fnat 0.609 iRMS 0.711 LRMS 2.831 Fnonnat 0.125 clashes 0 mapping DH:CG examples/1EXB_r_l_b.model.pdb D H -> examples/1EXB_r_l_b.pdb C G +DockQ 0.914 DockQ_F1 0.914 Fnat 1.000 iRMS 0.547 LRMS 3.426 Fnonnat 0.000 clashes 0 mapping DE:CF examples/1EXB_r_l_b.model.pdb D E -> examples/1EXB_r_l_b.pdb C F +DockQ 0.992 DockQ_F1 0.996 Fnat 0.976 iRMS 0.001 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping FH:EG examples/1EXB_r_l_b.model.pdb F H -> examples/1EXB_r_l_b.pdb E G +DockQ 0.992 DockQ_F1 0.996 Fnat 0.976 iRMS 0.001 LRMS 0.000 Fnonnat 0.000 clashes 0 mapping FG:EH examples/1EXB_r_l_b.model.pdb F G -> examples/1EXB_r_l_b.pdb E H +DockQ 0.992 DockQ_F1 0.996 Fnat 0.976 iRMS 0.001 LRMS 0.001 Fnonnat 0.000 clashes 0 mapping HE:GF examples/1EXB_r_l_b.model.pdb H E -> examples/1EXB_r_l_b.pdb G F +DockQ 1.000 DockQ_F1 0.996 Fnat 1.000 iRMS 0.001 LRMS 0.001 Fnonnat 0.024 clashes 0 mapping EG:FH examples/1EXB_r_l_b.model.pdb E G -> examples/1EXB_r_l_b.pdb F H From 3e08445796ed689a0f69df5671268748bdc072ff Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 17 Apr 2024 13:35:01 +0200 Subject: [PATCH 171/173] remove hack --- .github/workflows/main.yml | 2 +- src/DockQ/DockQ.py | 28 +++++++++++++++------------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 383193f..02d7dda 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,7 +3,7 @@ name: CI on: [push, pull_request, workflow_dispatch] env: - MIN_COVERAGE_REQUIRED: 85 + MIN_COVERAGE_REQUIRED: 80 jobs: diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index bcf0c12..83a4730 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -696,13 +696,19 @@ def product_without_dupl(*args, repeat=1): yield tuple(prod) -def count_chain_combinations(chain_clusters): - clusters = [tuple(li) for li in chain_clusters.values()] - number_of_combinations = np.prod( - [math.factorial(a) for a in Counter(clusters).values()] - ) +def count_chain_combinations(chain_clusters, reverse_map=False): + if not reverse_map: + clusters = [tuple(li) for li in chain_clusters.values()] + number_of_combinations = np.prod( + [math.factorial(a) for a in Counter(clusters).values()] + ) + else: + number_of_combinations = np.prod([len(c) for c in chain_clusters.values()]) + return number_of_combinations +def count_chain_combinations_from_maps(maps): + return sum(1 for _ in maps) def get_all_chain_maps( chain_clusters, @@ -799,15 +805,11 @@ def main(): model_chains_to_combo, native_chains_to_combo, ) - num_chain_combinations = count_chain_combinations(chain_clusters) - if ( - num_chain_combinations == 1 and not args.mapping - ): # A HACK count_chain_combinations does not work if there are different number of chains in native. - chain_maps, chain_maps_ = itertools.tee(chain_maps) - num_chain_combinations = sum(1 for _ in chain_maps_) + + num_chain_combinations = count_chain_combinations(chain_clusters, reverse_map=reverse_map) # copy iterator to use later - chain_maps, chain_maps2 = itertools.tee(chain_maps) + chain_maps, chain_maps_ = itertools.tee(chain_maps) low_memory = num_chain_combinations > 100 run_chain_map = partial( @@ -833,7 +835,7 @@ def main(): ) for chain_map, (result_this_mapping, total_dockq) in zip( - chain_maps2, result_this_mappings + chain_maps_, result_this_mappings ): if total_dockq > best_dockq: From f0d6b0e9c1c52b5096dc375879604a4ddd96dfa9 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 17 Apr 2024 13:42:59 +0200 Subject: [PATCH 172/173] blacken --- src/DockQ/DockQ.py | 8 ++++++-- src/DockQ/operations_nocy.py | 6 +++--- src/DockQ/parsers.py | 5 +---- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/DockQ/DockQ.py b/src/DockQ/DockQ.py index 83a4730..67d77e1 100755 --- a/src/DockQ/DockQ.py +++ b/src/DockQ/DockQ.py @@ -696,7 +696,7 @@ def product_without_dupl(*args, repeat=1): yield tuple(prod) -def count_chain_combinations(chain_clusters, reverse_map=False): +def count_chain_combinations(chain_clusters, reverse_map=False): if not reverse_map: clusters = [tuple(li) for li in chain_clusters.values()] number_of_combinations = np.prod( @@ -707,9 +707,11 @@ def count_chain_combinations(chain_clusters, reverse_map=False): return number_of_combinations + def count_chain_combinations_from_maps(maps): return sum(1 for _ in maps) + def get_all_chain_maps( chain_clusters, initial_mapping, @@ -806,7 +808,9 @@ def main(): native_chains_to_combo, ) - num_chain_combinations = count_chain_combinations(chain_clusters, reverse_map=reverse_map) + num_chain_combinations = count_chain_combinations( + chain_clusters, reverse_map=reverse_map + ) # copy iterator to use later chain_maps, chain_maps_ = itertools.tee(chain_maps) diff --git a/src/DockQ/operations_nocy.py b/src/DockQ/operations_nocy.py index d41566b..079964f 100644 --- a/src/DockQ/operations_nocy.py +++ b/src/DockQ/operations_nocy.py @@ -16,7 +16,7 @@ def atom_distances_to_residue_distances(atom_distances, atoms_per_res1, atoms_pe cum_j_atoms = 0 for j, j_atoms in enumerate(atoms_per_res2): res_distances[i, j] = atom_distances[ - cum_i_atoms:cum_i_atoms + i_atoms, cum_j_atoms:cum_j_atoms + j_atoms + cum_i_atoms : cum_i_atoms + i_atoms, cum_j_atoms : cum_j_atoms + j_atoms ].min() cum_j_atoms += j_atoms cum_i_atoms += i_atoms @@ -35,8 +35,8 @@ def residue_distances( def get_fnat_stats(model_res_distances, native_res_distances, threshold=5.0): - native_contacts = native_res_distances < threshold**2 - model_contacts = model_res_distances < threshold**2 + native_contacts = native_res_distances < threshold ** 2 + model_contacts = model_res_distances < threshold ** 2 n_native_contacts = np.sum(native_contacts) n_model_contacts = np.sum(model_contacts) n_shared_contacts = np.sum(model_contacts * native_contacts) diff --git a/src/DockQ/parsers.py b/src/DockQ/parsers.py index b3948fd..e522469 100644 --- a/src/DockQ/parsers.py +++ b/src/DockQ/parsers.py @@ -26,8 +26,7 @@ def get_structure(self, structure_id, filename, chains=[]): self._structure_builder.set_header(self._get_header()) return self._structure_builder.get_structure() - - + def _build_structure(self, structure_id, chains): # two special chars as placeholders in the mmCIF format # for item values that cannot be explicitly assigned @@ -257,7 +256,6 @@ def get_structure(self, id, file, chains): return structure - def _parse(self, header_coords_trailer, chains): """Parse the PDB file (PRIVATE).""" # Extract the header; return the rest of the file @@ -265,7 +263,6 @@ def _parse(self, header_coords_trailer, chains): # Parse the atomic data; return the PDB file trailer self.trailer = self._parse_coordinates(coords_trailer, chains) - def _parse_coordinates(self, coords_trailer, chains=[]): """Parse the atomic data in the PDB file (PRIVATE).""" allowed_records = { From 0b99811d5441336c1ae4d3a16ab6125d086bddb1 Mon Sep 17 00:00:00 2001 From: clami66 Date: Wed, 17 Apr 2024 13:50:02 +0200 Subject: [PATCH 173/173] api example --- README.md | 35 +++++++++++++++++++++++++++++++++++ journal.pone.0161879.PDF | Bin 1045833 -> 0 bytes 2 files changed, 35 insertions(+) delete mode 100644 journal.pone.0161879.PDF diff --git a/README.md b/README.md index ab5b6cd..2ad348b 100644 --- a/README.md +++ b/README.md @@ -170,3 +170,38 @@ optional arguments: C, the flag can be set as: '--mapping :BC' or the equivalent '--mapping *:BC'. ``` +**Import as a python module** + +Once DockQ is installed with pip, it can also be used as a module in your python code: + +```{python} +from DockQ.DockQ import load_PDB, run_on_all_native_interfaces + +model = load_PDB("examples/1A2K_r_l_b.model.pdb") +native = load_PDB("examples/1A2K_r_l_b.pdb") + +# model:native chain map dictionary for two interfaces +chain_map = {"A":"A", "B":"B"} +# returns a dictionary containing the results and the total DockQ score +run_on_all_native_interfaces(model, native, chain_map=chain_map) + +({('A', 'B'): {'DockQ_F1': 0.9437927182141027, + 'DockQ': 0.9425398964102757, + 'irms': 0.3753064373774967, + 'Lrms': 0.5535111803522507, + 'fnat': 0.8907563025210085, + 'nat_correct': 106, + 'nat_total': 119, + 'fnonnat': 0.1016949152542373, + 'nonnat_count': 12, + 'model_total': 118, + 'clashes': 0, + 'len1': 124, + 'len2': 124, + 'class1': 'ligand', + 'class2': 'receptor', + 'chain1': 'A', + 'chain2': 'B', + 'chain_map': {'A': 'A', 'B': 'B'}}}, + 0.9425398964102757) +``` diff --git a/journal.pone.0161879.PDF b/journal.pone.0161879.PDF deleted file mode 100644 index 6516ec5c17dfb8d34c3f7274a07fd93c2573a81c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1045833 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

PCseu$iEoJ=|4 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 -a_)7xHOQ*i5>b!7p)LI;0-GLJoULv_|VW7{!5 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

0zQ)t*$x%O|^*Y%zi(m!ySSJlxv{hD*^ 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

aZGJ$FlSAu+TcttI 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%0A*|DB>SrgFSpZ7HM^N# zKbe)wf@EzhNG}?1Q7_T@nPWHFu*+Nt%`+R1fy5xFzMWkG=IbwEsmIR7V_5bw^Q}^c{+NRjruu*91{$aj^%S*#J)LVx44`Yg;+_ZLRv9dG$zuBc+0LT;k zPGk!E4YtwSw!WTLwmaN+h&e~D10T+r8%u)rIAfuurR}HB^l1Y9_I=fONe;$of_OSI z@L%d?!$!ma7H~)3oPmuLPo}Z^qoWH=Ti!6>)IjF97PL7%e~hjbf5V|R>eX`py_%K+Ho(j!mjBA zW-#Ks{5{Iih@SQb=J&ebM$~!4&F{K7{Y6sZmfVPK0-2LJUbla6DW%=6wFf`+!*^VR z?Fg1W{DlWFRhc*^G$`}*b{+pVXj71W*1 zR8%g93W1&#zSJey`HFTgB}^@+!!m|ODAf896^BaPjRO~lt!scP&3b|EDo0j4C^$@K zQTgiRoL_6WUepyHu6V6NJD+uQc){+i$9M007&$(7gw~b{xC8^tLrX`5RDV})$HP-) zGhxr+z!ixbNSBc{@! z@Z^qjGTGC+aMc{Y*nl%ippsvQPav95%?3(A%;ld*`TEHn8jkmE)odTZr{(_#|)S2vc)D^dRLaUc0(0)DRk zL?p}n)q_727LkcIdn8x0sSC1tPB_KqpIs7ie^8OmpL8XvuZCGvd}u>HYZDS(;LhUAhmL~h{}V6587!@Hr1ao z{zd}+|2NEj0{L3JzXYRlUdw*{thabR*0x-^H3w{wkKi-{*4Hto8Dk(6kipZ@`xg z2mzrH$f9^`u(wF8i2afA;)L&uV_|M*WVi@@>I}ShxAyn(lQmB1D?F(6@E*(pn0L!r z-9A>;KAa{ry%~2R{n%g(JN7069^qPlPoMO427BcVZ)rulS_a1q$1Hkcvaly+Fx~wA zygs*$h^X9mH!s#Oslbt+g9K(-ngZ`=B)+bM`*K9u-a4@`ilPfKxzzs#ygwnI2j9zZ zba3F^VBD^oaG7caVA)U2YGJ@LV4ZG*F39rncHQ{xMF4{VDa`b>PV733Xw6M%TKueN zwQ)PdvvlK=5ZrVA*3HitBs=hqQ98R>cQY|OO7IC5ijI-pA8T2GE$0Eh$f7^$)||nR z#>K^Fku!L1iUo($+mhmy%tQ>V(t*bYS{}mZ2^8pVMi5%AyX{frxzNn6<#Voxl z?S-58T3Klt(r6Ck!`)C_iJOD>0NZ9uc?s)Lw9tYZKbQPl9w>`LnX8$o`*^lp54Lm+3fYS-r2 zIeta{rL&Adf=FjxIZ#T{o1p1Y&=+vCNDiE~xF#PTQdYXICr(0O;Z}-@e|I##NNLoJlsfp}Wz*$GL{D z5YXP>cRElXiuXGGv`b7lL7l|S{g(#Ja>^@T}n%&_{N zX7yiqTWU2NqNCB)u@qA8FMPhRFz-YYcP}Nq)57QvHJRmXrf0sauFI0{SB+vE+v@N7 zn12-s$-7dBG0MIR2=)73jLCa!IWHNXRo|`6MkFw}t*UAl2Pw&X+~00XL!e`i6!PbB z)=<5jI0vY)ij3GQo{yA5&ee@$ z^MyVp=TgWpw*4BYl%hOLqdFS&WZp}Bvkl-Ew`)@bW2tptFF;q^wWG!LI{5@Xr zL4qHtYR7STc$u98UD%+dnx^KAwZdL;4I+*MpW;~I!@zyS3-BvRS~rpT)ruG?U|ddI zi8HyhztA>?l&`kAfI)@nqqF3b&&9iNt~t<=K?)O+h3riiX9Smr$r3ye7@-Yu8v{HL zG{aS&B-5zhF=o-9IO&cLn4^S?IKTvF1#V_Bu;F%Po~r1rs8*uCdTk92HE>ciKqfXQzN887ca+8Jj0=H8QB6tDGj9JTv5a+ z*og|URPAw*euvC3-Bkt^s(Y;703J^Pe1WiQf8h=HpV9+CH`@*ywppKiYIYx6-v|VN z5MlgDrTKY?B-hh(r0MWJ4BHBPv3>d)puTZe8S`tt2KsJv# zzlvn|=&~wTu*z(exWNS_OGDYIq~7V%Qq|*|1kc z;>PhX2bPqSqfb_AeD?DlxvXb(^o3#;0-+06OC^9CLYBXznjk_XNZi7LJz$N7e5!e@ z9l#8WMrZX7nApqP8g?M%hMMeyymk3ErC46S$P1s%`k9y2^cPBOWV;_%4=sxt}pQ`RAP3 z9^v~eBmL!l9yZU|C(vIf_Z=5<(vah7kvf|&{ltd@_l^Ek8)RrC;zYAQkVjJpQ?)Dy zp}+O$`9b%Y*6Y{jg^pKTm1yse+F^KA&=&*nn6+*9dSJfBFmWsr|h(s%QLslA-IbUk95NiNlBYnlF1@-vp9&O;FS zq_M0%VlJ7!jJ|=De)*8}o$@PA4sPB#{Kf%1X4`uheE`Ow)7nxO4JPLLs|G#Xk5w%) z9DLe4@}0Ei>siFN7(f>cXCI3wBX3w*{D?0BeQ>-?wE>_{Sgoj!lq);qeY&1__M>uy znyueLYT6#_l!&jMgJcqo0$av=3fIeW-V+P}XA17f%ea(}SdFfyFy#V2a5l!QeybRO z3H7i4g~w~Z2&pmin4TGwa!`%24J{8Wn|hiZk;BlUCnYqkDhqOx{EmS5OGxb7@JU6J z4hhPv+G5SakvMk{8vpbI`tfcmyh^1@xnZb{LUX545>wMmt!Wa)#G%@xeL`^{ zf)~g7&RdF!`l&b6!!@*-y>EOp&OicWV=fOccf1Kfreaqr(gHd+C6}K1(ir=`8RrsK zxpAN!pLO`+g*F_ySAnHDxeOF>wGRyr`YijMaO3+)Y9;vS4bYa48*{i39O@&V%S$DB z&e#g@ds)ud)Krvtf5NszQpwW--)EEj^v`sqo_}~Xk0(5QU3Zq{-TK)oh)s}5uq|*V zpdLrkIvuk(5!LXMD%8g^pr^_ab8ra~>mFYChe(A|tLfg;F*7Oy1xD$+uQP6)^gmf! zi;MLw+?Nrcv5;OTUNO&XL$U>2ZIU~ix|~cb6sydvyeBneiz58ZEwbMl_;zNo%l64z zI;>c~Jx7ogQ~)460N{KuFlN^!Kt$6J1dtU4NSCR@9bXe^|Dmle>P9~T#Tk{vfOY?-5?|Y7cnX`tT7p-aWFB+)GL7CIl8NS5b z2z0!8CM-GS6b0Ip*V)mhj_Z1?OZGcu8mr4>?3}(W(|IL1oA4Ljt&w;RZBkV9YogGT!KqHzsCP5?+a1C$1&= zJIn%VjEb#g9>6-we&bCJbot}Z=$HDmH8rII*Q-lSltB4yZNPpQ)IJ4~cXZ2DuzG&KxO zg<{GQYy=pwu5AaZP2L^>H_umg_!=v?tbarG_a=h2z2As zse%i!i}Sp`(2D*Jsq^Rh`ZH4@_9y!o$$N?SMCZrQh%-=4&1}qYhsgTtw^T|7aW|Jb zFM;lmm|d;|188GU+xLUf1HSR9xsF{$>L*6bS9graj$jv@_TM)53EW(?3FO^Z7ciMP zGKqPHm~k$AqTCzdl5PY}`(~Ed1(ZvY%Y7v@OD)9C&)`v{;cKA;9v(@EK<=4`VQE-I z*xdq_BXTJhh(A}wF0@603(t5O+ zegg94ex@i+5_Sv9ClNiOt$!5Z+f!cU?0tIoni%_OvnOWMy2ImN-`3SDviJchh5g7= z3FH6j-h-cH=|h%OzjZ!-Dk=u$VJzJ^ zLbINl7E7bs!OJCcKD7iAQf4Jx`aFwulKxAXu;qz;7IK4+A;e!@Q}32RK`L`gKny)n zB%tEUPh<(UUyAHfVc^N-ovxy>8R7@pwGLC=60sL_yGQ-cpM>m2Jf)QJ4`AuX5e60& zrP_3BkkGSPchUr!oLvMC1EV2Xw^5U&b(aS@rOy>V_{4QH^d%db+}lt+!;6J`fR2o( zELJ;7K#TGTwujWUQtznoBnke*zp}K(XOCemPhX(IP!ZUErF=AsMW_x5OWSy0(98M%3J^U^aEnooL z$r^fM=$p$)yc1DURi&CF=HtTNxOyrk zCUmT7z0_q{6{Se!yza$q-xrPPB7kK2M zdscGiBUNY0U}kjmKFd&VVJ|QJ2W7_>KfH^qtw%Oe5K{IpEI@a5T4k|yQ`kO{^816{ z@g{>0jYdojP+WV!*yIHy9T+vQ#^plLf>A3`nKB{Y&X>4){2@3)n08#Ym1PQDL?Z=x z5b|BXr+r{?ZRsrl*hJDD1}p) zlANTK+l`Il@=X_U1O({!8WCa1K;SE$ab)LWSJl8Y@+{yp!^mbn37t0x!` z_Ib|NKhBqZeN^mVz#h8lJ#2nv4%DUzCzWFh@m2`o?+3VUe+fyD0y*EzJ(WY?zGgN( z1+@PEI^q8>SDF9qAO8at@(N(BiAWm8%&qh3qc$Ipj}2nqst-gOYCR_62vYjUlZ8|3 z%(FGq9mRh5ynD~6xrsUHo`;H^kV>;d*O$_cayy_v9{N)t&jK8mZ`ULkoj~31dFzoe zsoY!5(0-sc;MKjR!?=DNb)@rr`VDj;7g;#U!ad-Jr@@1BzJyeyMHDqxFgbQ@ybPoX^PqspJ*OwWNN-&6Wo`_PL++J*H@_wJ@Om z-^S4BFtuu9d)ku@QdLkMEz}6O7oaOXM2pdbaWCPVamEHpg$_nKqJ!(+tMQrySRG-? zO)YY6*|Sb<7<#8-Nd3hiPH!BzSFf4bm6NA;jPBbf)g=URUX7&#qNo~+evFK31eVqT;k!1ke|>evok(xNQdsfZnSxpea0~$a4bf z-+~FTHl{&sO}0{>7AWOh@+|ro8n=P<40$NV3k3Dc|G|;|S1yYGDqi>BzUQuHWbynq z14U7(UGb>t+{`eqYKw0vjm%oo4yPr7(v#a&dx28IJ8o+|_Ci^5=QMoS9tUt*D`ZkM zU23G%USGX5J;U-re6T*>E4kk;b5bsx6&yufD&Ju$HPGR$BfBmHi`a$dO|5y|0P~Ty zb*?lo0a2V8=G}mdg}x~eSMyQj({-VR%*av2N53WOjg*&ENsV!!VX$)zT}@yKg6P(A zj0(OQ4e`kF+k}E&V(A`cZmMwcjCw=)z~^rG)BbY%(6%}f ziGiwYcjCAU;=)bK!GC$dQcA6FA+PH))!XFwYPLptqDPWHkbnhKRt9->?nLC0hio#| zU^YJf(Qd`b9Xvn*{O}NsFUhV-MV@JSQ(LhkrYPU2wrHjTWRJ{^y?Eq+1(6&r=+m+Y zv{o!%{s6jrN_IGt6{-8We-m&)JulCOMww+6AKw-wy}@1C6_Q&Ti6;L)jaqk1P?26g&=x1E|Jx${n}6N_wtfosq`A@>M;m=$^{q*`*E!ozm9{iy zUBA#z9~cOAAqsgVz;txn6&kDlbK!L9g3@21aBmQhp$N&#ul?fiVUM``&C2-^zHcFgCZu0&GPojxy?Mlgbv(we8_zzeFyC0_qEGM2#iv0|L4f0CIdR|S zBXfEpRTdX-d~p|t8se4Gn?V>-V$Z7`dD~$(KWQtsk0bbpOdM3buO-A2D-4it1OW|T zF7A#P8DYzd(hmXRP39NG$T8e=tq2w_dLc$P-CGwP*5>FSy{2C~O`X$v43CX(^8Pp$ zCT4uJZR7=nI0{&`uUN(&9|!o@qETLmBcJ||pPh^>T=yRge~bk`UcVL_f8$?fSpM0A zDM7LCi^O}yZmGv)9ag0C1fYx>%neQsg&?`2<%&!&J9d9#!A6~CSE(7UpPVB8_QSdg zkKacvrJ*9n%cbh;k`enSQSrT0c=I&)AcE_$8ME0l?=lTxC0;hXdDZ8fV8ZWbYAC`! zqu2zgusn>%0B;wLB&{cZDvZnKmW*s{k&NA0dyU(!=!~$%r3x)l_BK@Z?7X(pJIu~{ zIAohc`|$HkZ2OEyy3fhO>nMionkFw4DIZcXM&3E<3%495s+z*kGA>J<$`SNrE=20v zfK_lF4UqCABcF(KP3+Mu=WLGlsoTNjR8zp??I#g7&4Fd`Xb`aKy8e094ZxO1W-T>b z;|c5=wvP3ODuxhdGluO&#+`3%-ixs+#E3A{zShD=(Ids(vl4_-)-z>Ln5T}T{p{kI z90{7fQX}HVuK*ss1X@;VY@4Fb&{f15IXcOeVMnPTPiuLCpK5o48WfBn7yzck5_@|_ zw~LBVvMqwGm{M zFMpY=D$5*K2E2GxltSOnbSB8jwMc%~`Ss|Z!;l(%o*tVR&{*nQ@M_%uw#rv(5)NUu zdw64&>;cnfieYHK@HZRX4;WFL+4XO|U68dtC+8*}Q7Q*Fg4B*9fYOntO)!5_e}LE^ zO|k0UylSRDq?Pjyog^hp zA%X?!0qjO0oB_t0v0`BOiQ2oj*0=od;*<95(*xI;*5BR#^-K;2=zfRHF$#x{F#eirmOug3 z(z%(Qp)dH-gf~GonrkUn3V+x+^BcA9Jwlp0ak(=3^NcNJ0084`u!J}HS|)O$(sE_w z;la-Upx%i^O#vU(i7!#e#D|yV6PNuWsjLCEm2m{+-b*Q0-UBWd3|EgrYF?u4iK#x| zvwS@Cn6h^RFTdE+$gGWdd70BmM@`KV+BXRQ{tD%jP>>D=yYR3*;@Y$;PIvm? z<>tI7?o_HFID;DRHEJ>d?5Y8u=kZAB7Rx z2GNF1U*QTt*pQ2_g!&u1w$A{X(TKDt+>dm5A-hxHpn)kJf&Hj9cyfG^E5yFNw65MH zGYk~rb8IC^Cg<>9w`ag$EQ5XKk?i)XZi)4=wM(ceS9ZSxRnjPvo&#Zc>5pF0P~h zqn|AkhwD*{*+Io3bO znrw&XW7ux{OTF(-%oF+VqnUC`J=oRCdW+)VkLcpZ#r^oaO?kUs3JJ!oD?O!LU+Qh+ zf|}0*p7?4i_0>&Da2-~TAaz?Fbs{H!%~?~MCN_E$J^t_SU#HL7%xAUePQ|UoV!~3} zAOm1@wt3opGc(jeY~smm&cud?$otQsVG*k&IOo?gGmF6FN#z>im9#wIqa6HVNWbk@ zU7#?IfH{O*;SDPmnrzRz@7Fr|YeE1DCEzfPKX@<$|5txHgwV^Dr*R z^cm<8!(;GV=i}VxPcDVK!OLa&-38;8{b6H|2s?=8OJjzE0EI{Oi%$xrotYXwT!QQm zm>a2;T>KBq{0*F_6kjH!H_~XrcO;TSjmq;ct*1B0 zJ2daaqD-h@W@<#1krr;7B<#z>>Tm-HQ#_J}Z~=mIy`|#i#{a2Yi6!d5FfZY$ zQ0~;;`=^qgbJEr7fO+fDlgXD>0~BvARSuz%Bfw29E8VpIr6DW+UQFfitIKcLBaF^e zZxbyd$#yUt|MFD)UD8H}c{pI{0F5y?Z7%hYdy#Unc+$Lt)I?NlTj@{zO?S4uMo zCrPkwerR3_^-4IAP+Uaxt#$LyX0K78jOKIK=-2g6Cq6iq%W*0$;yYngictK(tN zKE>qd&Xpg1-BCv_>6Wc7g6pUMt9nnPL%SS=3yCT#JhVd>@ffPLJt>iAA2(xntbS=c zsm=7(c>MHn-GYP3QC;hfrX{Zj7sblX9 zG-l2hO~aIV#5i*x9vnaG%ZVZoFMzhpjM`gOG0Wkfc~$qY;Zn> z=+n0gQTB_o!Zy48mH3X;Tn+zSD!Q?&jpJUCz`9=Xq=f>1+GhGD`OzQyW%yJsQy zTeR%n?%LIW?v*(3N>|7-mx0*+3Vz>TKPT3jzJ;@J*4TCzIvnbD8lGoiJ0Tm=x3$om zl{`No5GRf*<;`GO=HX#lm^1=?Xi9U4et`z;42Uj;CeO-z{au$|^Nt?gLw1yOnvV?e z)Mrd4(_&Wtu6j1-g$>zZhPr!UiBJcGZv36yORuhM5)TcX`L3SNJ{eiMm`Xr>8-lw2 zWe;~ii|bvM8Ohl&ASgxS#A%OnI?WrW%l_MTw%pV3bvNrx11h;KxsK2-c}B_%F9eXP z10+cpX+AZ#b-Q*IkDuU(XMa~NXQg-h!UnnT^t(S*ut%a%&u3A@mRM^a{Q^z$YNr&qn>KtH_mq5MDCMd+tRzcZY#Rbu@45bCk%o9dnI#I#O5vo!wng zVpiF;F~_sRH_{)+>`&TtONbQZe^=q*#s5BZ89^NJ14y|p)-<1C(CXzt#7cA=UIg2j zxhEWb?NP%V9acm~oCSdsgQqQ;^%-Pz8ZR5!>E&HW z8PZbG4%uyPQn8;AkA3~sP`j0os_OSd77lvR1c~QS7~@(mSo*l;GjzeDfL?)4>3Sdw ztc=sGo@wL30Y_Y)huO{_)>GEL$-1=`;+AjE%~9JJv64)wsC1Y8p#T4AlAy^iOg};5o3-& z*xs(#j3^KMc-C-skcC`cDRDi`m1U|}yj;S$7Ac^>87#&nBKa(~V^rel`SCw>#wlnc zwB8lAOYP!rF_b%}kwk_4N-zEV?5p0hfIJ-8?Bd8MK6TOsJ-HU1i^-SU?2A`0bj4sQ zTnVLEyBP>_*frMkF-pF5jnDoAlHxBgb2RDTw$gjj_xyS|@``@O;Oa$<>o)3ID2@hA z*`fXn4I8|KR^HDbs`NQ`>tRA?_r;N`CUZqgmmqYIXC5kvr0pvm1drp|0@3yRe4158 zObrx>UqKPHH40aNXNOnDeKaDeh2FQ5zo1A9QT4On(`6P$R@wH{n>$?ddH@lAqbtPJ zBD_0skw@q{wzI_n=TVxxU+dH1@JGZ-m+WiLGVC>_?QyXwHOfp#A#xl%9xhfC&YBD}y6dOh@Fw0= z@SxP3H9QJo@<@`~;&>5Kupg)a=M<~bU_}$iQ+}(W%T?A=xD~2!S65pWZx3%kTshJD zM^aRDb|04Pk7nOjVDoT&F$~jN*qw(-5)vUBzHxlr(2qwhzy+{#iMlej_g~pFM7mRn^p&y^<>tk@Q(%7k z1F-i7pOU@Bk(fN2?}$tVB6HmTEdYhp^_|{g+eo?zO`dbW`M)oz1se5KXvi`!L|z~f zgqkTKDrU7`>=w;yoy^S|K2DAb)QSwy>V5Z;ehgR^%n0|lcaTMFJ$u+YvW41#th|j# ziaqKu1QQ4Cz>WXpIcG)sGPS@<{GDw_jbF-_;umg^aDW2#o;ZBh|At4)Eq@Ysg2-;! z%&hTunF+e7$z(mMeS$dok&no{Jj(>|N!vOlhFH&aZjg7|i6Ft?qnG6ljlDtSyW@ch zh)BA0KG3)L&=ZFre@-ARqaVn$WK|;$%ol=>w$t(NJYq2>ASNj-YmFTq28Jz$%y1Ud z4%GHd@IrnkBQ2YHpF9$s@4=n+PmhM*OahExb=BJ^pV{4@y(OGTqE2~p9%@thj-P=PZTW8{^~z#-oZrt7EA!@jtl$45;W zPnLcl6VHH5xc+J{p|O4_ORG}i%Hr4=*%g<*H1E0K?jj{S$``g-fdxpAq&A+z;nY)7 z2BeNwp>j@{YstJQeom3&l0SHlrK0Be;v19TmZrJKm_P97gwpREEsmGP-nP&?K@W~j z!R$~=Tl2IG5vap&q+&Ifdj}z-XP$n}AhG=!e;|=%2)C5E56U-Y?(E&GnT(LaL7Imf z*cZ+3KKkA2tG#Q@zDY8u#HG-{>m-%>S;7C(URr3-rR4hP{S!c-Hd=c=FgEKuASEpB zdhW(>wGj0kqT_a<#Bl-3>~Pp{%zR=B*vS1~BWC^`3#ua!7F*x1kF&wXj^~cD*%=L8 z4qZC4HNOr1Bnf&Wv07n=O#xQ%d(^Wm82?Fy#Lq9&bF=M5@>7C?9t^$2h0P@Kq-6QY z)6}oDH5$s$b2wK&q!t!Xykxz{{=gnK6l}&53>V3H+bRTFU$)4&mdhP=n&&N{lb^X7 zLbZG+9lCU5Pnc0y`CEy1@Q52b&0K&*PfXZ}Az$B2eETr53fltdG`F;<$O0p|+mI|L zhnSuvjs;(y(-d+QaA45_wYjSGf&)&4)t$ME2m1zFkL|)<0xwV7(v0FePeqP<5+x%- ze)9e%xJlT~3yDm?0}R*8BJ*IttR0fAO$Lm7Qf`T@M0KY)i(IoD{~F@k--xz8OMyHj z02H>+FMt6YY=~bDxT~>^r`6+zT@XV6t)4ubP@ejl?Gx^U=e?q$ zALc1M$K)>ke*{nHtl85VGn=u4a*+mjarLjWI=!9lRZp7Vt?fl@-gC52B(VRVLgnm0 z=oq+q9g06Z(BXZc!(8H|T~ChX2_EscPIK9RMM@qMMph2@2w+n$LD=?sY?h<$9^HS@ z{N{gBdHhcl+rQ^;@aOa9|5PmgF9m@fZ{&LD8`TU3marv8l?bLOU~cPwzC7x1uwpQq z5#_HSV}%BBQLKtR(5!!ax=JZ0*NSO9dpEPUP@eg-eZdN@&3vf7S5(z_<)OX&Cg=GE zdmno<)*Bd{dVkmtY!EI^BL~>n{_2a$|OQd7jN8tyC=mUeq&j zn?Jg=W<(CB)o*7L@#$C2-s(3zR_t9l>AT-3iM~IIki=O*P3_xKBo>BKMAxO3-AkV6 zuqP`i>i9G5eZNyz=^aD2+2I@AZGgG|J23k!jM%|$t@xL3^qPOi`Tgy`@UY7*g%vLA z-@7N{M<))|3@?M;Tb@kj>z_FoK|*0a%{l2EELYIfr}}|#s3&$97>(a+csNT%7cN9~ zI>rB33cG_a2Rw^rAxR>bS|9-22TC_=QSYS3`01z@nWlseMd25B@nvDbRztFKVMVkM_$>i zee-7n2Gu^oIU8bSmTw{&m;8mNU+p_tiNuL^`JUtPUI$}FHexYDOG26z&!yTeZA9$y zUwcNFND$cd2wKSaLuwq_memVm2v<~1-WYHeV|2mKy;HG-HSuF00*_-n4jKgz5B_D2 zi^P0KDm9h%_!HJ~tw?0h5D`bn2quJsj5K1aO!gVGJ1<|eF6Ib!V4sa-Xe4ic~5off$;;XZFM2C8YWrPXCn~liox9p*oQ(Bo=4_FGm;deIZu* z(h$QYUkvxEBwQFo9RwExX4`HIrxl`-kG;_>xJeYo5g_e;()Lnxz?x6RTQ?T@xw zO2WuE0;JsMgB5kYKJVsRQlHvBfzPh3bc_3l6*Uru4(ax|Q5MF&do~3_$AZyu)zCly z3H4VDJXW(5Nf|l~r&X~mCMz(=2K-xxTB^=Oyg@`2Dvz|{7!NG`81ZEOAU(=A?0ZO} z?=Sv#)sp|sG@(majZXr1ZoESyWM=lbkU-%*_&mOa`}rxalyB$YD{{x><8p% zckBG7907`}Li5v0$a|f&a4tVK-8NQ`+x}m87q{$Ow>A>h#s4G+mxd=hd*cOwiX(pl z^5l>Pb}70@s0~|V8@LT%DQdr$-&aa~sRB}sw3|ha-uNAtr8ZV?1o;O05z9}v*~2ND zPQB6=J(YQAespWF=wlvt&z~zzhtJxPir-#|bFua*QGdlB@9P%$Fn9V6orub9M~C(A zZUw@k`QmS23+k;)rd=SX|Me-8&~p~I|cLkgZA~z+9${r1^r!nSSm#? z5x2Ks=pds|ztX2I<#L<}2?W2mr&ZW|ZYAIk>rKFZ!st7%zF57C$=3oGob9_{Sp=E5 zezre|i~bTr1ydUgI0p_5U8E_yuB}wgEqex&DxF7U#Zf_Lt{tAogGgZA{sb$e((aIk z{+QQhy(-xP3_-|R5Scf3BL04*7_1CtZR0J(7NWe0k`D7}%*s?m4qC)}e5s_vULJ!T zt~|X9s|;6pB=HXz11p9W7yZ>(W~TaI;cHLJ`zkqHv;jC9`4Gkxuuz1V(?gSdYij*A z&TnK}^qw=-W{ZwhMEn5Pex;V*o7?>rWV8}Vy3tMgT42R zimF?)g;5YhktiY=0RhQTGKG>wq9Q0s36eoTLQzm9qGTv?j*>w#2$D)A=bS^4iyW$; zprGKr+xLXg-S?h8r|;$?J?Nwu=ZN>nQK0C^1D)rL{qJenM)4LG=KwoJ~x$@ zq?WMfSv%P9r&f(oH+o7>Zw_QWJKymY-E8AQWBf=o1O%(`9CT!Ros>CU=(^28fcHt2 zi12ze{yyDwEo0!9Eg)B9$W{uxui_;Sh&0Pj`LR$Y>BH5|$InQDDR}1rqY85Q_yC=v z_C(67�FPOQ}>&%D{|E&i|>;=-=SPe-ln>u?OHWu+n=ODM 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

pTU_%{87aN}C-`W@Yb6eoaN^)I1wgaJ{_cnp zd=)q;oh@Iv-r{an7L?d#ua`eHv}~JvFpi4?20Q=>?zI6DJ`gu9$0ApFeuH+A(G|w@ ztd?}4g7?g~0~`j$9?xH)`AKvI7klTV9U#6PTX<>YZ?p=;UI_eB2wWodClMDO2K92< zpB88=;a&6`@ za`jyf9wvzEQ$D-ini_1noNEC6p8C=?TV{}#kmCN!G=KrZ4`b+{0uW3NO8e374tUZe z7&Vg2YBg}5_RMSXErb=KQ4y_zfPi{JKU*@hfb)MGF{v?8* z%dJ?6d1kN&!lM=lb&r1%9nBAew!kz{%|C+L-z90dJYbU|6A4d%$2HV>Dt)iP!d^RC z%w?^LUoj?*?d%8a#3WiQTv7LBaV`dI_}TSHO^^PX+UU=po|6Tig?CsM;ef>j=~iP&DoKF?F{xUi_dU-y zugsg#ImAVO>E+BL(s>Db!F%Ri)!Ohkw8I5JJEX3U19RdivGk>UzpK*25|AD#u?ki} zhykuyFD5qD;kfv%e~7Q~`2!%dVgS6Ocf(Yh1KEyPr2&?wMJkty%jx^ej04h_E5An? z;5>oXFdtg_jIXSk;~6Syo&1O}(DPR^LsM^JlRaA(;j^2|#B8Un9lJ zjbA!DD#G0Y498Q?f|;8y_sxY3oA)0tXxw+p(SmVNgm4?o zoIO4{*-;R7t4Lvky@G(Ifjl9o0<%jh37*o}3Me8+*b(DMFw|J9SWQ-1zPYghBXbY_ z(IuQBYA;YiUv3)?iH-8c_0fBudpny!RDnCNe3kx_7e9ccHdI~@l+y6^5 z1s-6$ObDgk`7W z_ixIDjAmJ}uZBgz@s=h=o9pTj+~p4N6F`pvB&)3bi2emZh^`-G7s2A+Y$khmSj`UP zIP>O>!m0MyhiEhn6m$Y4^Irky^ftaf8le-RA;|5xb0@bdWaQi<8>b-#b1FW02;1i> zqunADE6Okwn04+<(YMRp&hfE2l6dS~e(VlLOuFWAPB!mB+3#BJzZGBmLY2Qg=tN4K#Wx8=UXITlXTVT6%}*{8PZo z1mXIM^Z^OfmnOb+CjDXe;45&(4znfPw3sz~&$sfzexHzlfzsVoJ!TGq$Dmg$iEtCD z{GrRyFwgNMU{vT!&C2Gl-n^R8Nfh?p=lz;*i6jgM{Cy^IIRcL~KfWW!TDIZpI3=P1 zc&P{PfQRzSL5l%|58HfVQsnuO@1h&6#z05+&wWLK!cV2TBO~KuWUyvxQ$wP z#vXijJQ%X7+~n?s=nS_+6)K?MJkttK3ulXsmtKo0-ng-rdu6$@cL9ex#;;Vo^+A#1 zcZT>s)Q%raQ+i*%rKBsP_fg&^m*z>o9EU}Hhb7P{F4u-1YQdsWUfJg3t0HqafAq%t z>30$ZJa$o9{udt+9d&^7f19<$H4r>7BW8$R3h{!bWSh~uHf%2pBIAM9Cvf2xnw30PkamCY-1AuGR=mM4^KYcwgVXXD z7(SG`1k9s!5;9u<6>kC74VaaS6ez;4K;v8kSJ!HsMsr|}AEiF@JXi9O-hvq(7YG?4 z;YcukWj6;O*VXoe!9A+MA9{-Znnuis8hx`RWA@s+G?S4&74W=uvp`$!;ronu**_j@r zqwyr1FX2>}M|UI^o*A4TySW3XsOKN3CO42NS>aQ1|ItdkL~h=1u6!n1*lh+ynaU>>fZfZ)&`b?9PB&ycTM{W<5t6`gRR zQ5whsM2%oQ4SD9rt&Ckw;Z;qUh--Pp*uuFi#o>ETR$+lgo&beBbp%KVSmY;L=F9p& z=8KD{P+F_^vEPU!M=x{GK!l)(vcR|?0FCdr@WFz0BQwl2{3x?Cf}EC>5`a_6oy>a% z%rgD+;L0D`_g@w11_G@GQWiL%7CIf2WNC{DJfB!Soi-e3Iv4(u1z7-SrhMRxX%lQ` zanAiLR`~phOtbloz`ILoI#jj|EE&q@&ML#wy{7SHLGIX>;>L#h{*cO^9-H%h(WC!aL7#m@NSh`G6 z);lW9T^V8;0>V6M#@~-tC27Jo&c!8CV>)!xx!{F<$>ZMOyOy)yX<1){v#=IJQSkd; z9wsBc8{drqI(p?^`JmmTzpDWEzGY`G-F)s*Sl$ckDIy@Cy@&;+L4}}bBs8@o*YAZ? znM{iHZC#0brVmuF@fYTbmXT@$oRS^jriFNDJj4_qiWzT+mq~K1>bQ=QK~fm{Q5bm; zm2Anr?68FYK8sF{?nZ|`RCHZnRf|G*s2us&8JM1G6B|*QmUoAK zwD?z)FJA?m7-igomZi8{P}R#Jl6y0AU8cVKiB>?{&B<-jRaSzz0|;q=J~Qk9XM!_W z<7bLcMXSLCO{b>ng$>6bdpqyz)kLP~(d7d>!96T%9iXSdb%5Iuv4DL=0Pu)RDE15X zI8A1Ww$4t#rs1Tt;9ItK??VVi*`fq^2c3V@3;Jh*f*S{3CJJ{SjTyzZwqa$h-AXq? z5W0sqTn5L-)gSxhdjn0BXWRHn?0Cv5ILRwV#*r%jqmy{-pyo4rzG~ub$Dxv`=q?(+ zE<8Y#pT=bX? ztTNOncPuGeKlYdD4EJ&4Ckwm~_L$IOfS&^bG&vbCHX4pi2<^*uEXew>VMI%8LZC6W ziA~LyJNG(*HPGOUpO55R%5xu58i)@RG0<{agmc5VJ;FrI6$>8Xo-{N>!zm96)Qm^J zh54*Uw2Tsh0P>k~Izaf$v0A6Uqy4(#6eI~d^!Z(pkg?AyYcgq8U}YIj ze(0L^w^alrr!}%@zXJ?#lAodnd2k%Km15l0exyl7ag8JApzlQo8%L_T^}ew4ogY$R zC*mF8aNr;vRSxi}Jskq^9P}7!jQa_?S?lW+KR7WXN5ZTsfhj2H%b>fiAbvPEzWKdV znDv%U$Y@F|}Dt1Kxuo6&m5qwkhj z*U;6q^xfX{tmGnM3EKGHWvOwUS3)&J?nWq9{MoEVOHL2Lcx(wd;qDY&O?2%>DobRb zjF8a~9J`GWar8$cD^iNq^;8aFmv^k1-Wq!<3)fvG&&%QkyuhIS2zVwKha*h|GO=P1 zA7e*LizM!*Y7J+#GhvF|{5S?B75xW5TtRpV@SgME^@8&__`Bv8xGs*CTP2wldqqOPlbtozx}iB#AYEADvjCs8ajD(A-+s3q?y=wBWL+$q6B z188wl0;D_=6Vw$iHuKPn0%rT-qUGh6Z1?tW#wyIt(m?LvJbQDniBN1vgT((~?>)ep zdbfPxAS$RRHUv=!2nqrcK#E9-NC)Y?NR%Q?Km?_;6+{%I_hzJ*fJj#l3z&L5^3!pZ1=y-=nvY{HJl;Rm*6GS4Pui#CijEX}u-)rZyDo@) zRD&fEO^h9vp-s0XEC)uCzVfFs94B=P4s`ikQG5~4KEW37`WKrfB_pbF7p|i^UW70g z@vNUAd;R{8h=ixC0^;W*4v%7<&t2o zvM}PsXjlgdvy}7R?>5O@P4}*;-JeyYH@0&JxZFEvZZ~m`vEgMd9QQ|OAg1C{LiPIa zX(E9KD3|&ZauLxb3@-X0U{PUCpr|9kMgU0H>(M*q#OX+S7^PTs!_`MJL7h=;r|{Nn z`7yQCGlX$yZW|U8*a}~Uwe$V7d(#8cZOR$79BLD@9SHF<=bHsL?pI8sLQCrV9JnnGf53qpA+QS8|u1cXDnL`r$*KCdVMxDdgzaI_%_?&hh9p zXW=ydeaG)RVo7qcwoI3Fn68@4Kg84K^k@~X=&#afim4FQ74bZUojb{d&&J}V#~%cn zQ0pnKx1E~@XR48fNN)fdHUh=z$IpGK}@k!$t1`g&Tf<{B1rVJ>m_l`L-(_LBBd{1vSmLiO$p1wvKb>4h|q zK|{Jx=?5lH=sd4|>ky~%$yAVcNvmV2wd2R*k3Ve7!L9?hu)?iwGKgnF=c&T_{K?dn z-r}N*MJqLY=be0a?r9D*S^FYHW2XV5Fw>egK+&Vk2qTwasAI&(#`e2F3(-U&J zda6d-YsvZhEt8zYJ>jij;)3gNH83iC$V~tfk<|ky`;Ks%l9$6;CsX_?bax$G?|MOh z8X2-Q;;CBZ(`q$D6oKYWfKeP$a>9CD<^lt>XGcORb@}d&^XSgq38?qIZWKXuCmzEd zuhx5m6CCqn>|{Q3uAwkBLb5+=Y@+Q&07FEh`x>XVpPiDa(%ccZB?(Cz%sAcm~RwBZ!_K zL*$(L$KRh<<-DWHwWa70@ZJp`d&3DSTa0nHdb51ef9mue~=mved~z?wHl~9lJdp7TQ@V zLQU3elS8xQ!X)1@MpSlA!tG$1IZ<9oAbFMR*y4v-gN6E+ZtmPs6{zR8c6{5O%jU06 zoARJ-Omr>J-uu}s_?XV|5L{_%Vb`oh{=<67ZbOt!&I2EmVJcz0_g4zvpDBeD8N@3L zG@rEU=ETr*j3M@Z0mg%$ zs`+0%zB+Q>o#^mdsGXKFgZl~ebao$`>VP7L(^j1;5yUAy}(hvY0gdMcZqw zwVHloe8f@mPiz3cKCSid@#nve^S`hBD*=(ehggnIX+OY@SwaTjZDS9<5dQJr z|9PwzsxHc=;iTnIILLbh8PE9SU_-J=nv{8BtgJ#A>idQ{0c4+b^uq1LPF#3H=hROH51U)%D58PIjurr2SN%h^3y5~&G}wdZ9Fro_!=S7@`}X`j|_&upSZt%HMu z)n6i9Ad|A#Pr`XMjPv-$g_7#r;f#$;ll5@grbQk#4o|fhoZ4Am#)c`-Nde0u%Bs`qlT8=~}woFWjQ)TUFA?nelCUAkc)AjH7&| zYj=#76=c9L>_>nxdJWg&Y^JS1Qmi6`9{wQ;ZFIe8+BcdS$3-_#a zDR9MaP?*SGU7XSp7Ah&FJyT+@Z^g}*FSXjd1QfRxsS|=#mi)7x9+UkTp~@n7&h2}v zkq7*8$A0u1JppauZK{=7Y4;zYthEh2jkiEOw$6wv?Iku5ooK1@;mX5z--v^}31Rsa z+rtxYTXS;7Xo1i@C<4HL2prx-ohFLO1C;kn3Q0SqrfzViF2l&Tou`z1O@FZPd!Q!Y zWUUaLhn7vdL-v?yy6;Mw6j-?VwLyGa`rLq#WUt=+tOY~8#R;~b!@_0j!F6&;lU>k> zNqDlOcAq)isqx_b#5*e<^~}Q0vX%#?SY2#O0W`9U@_K_pAa{JwJKc3<#M>`J?^#?s zM(8!lg5zO+U3n*4Q0wm<=>GzBNAm%D+dXJzlm_AnwK-7x=r^;a4;cvAY7_MucxCq< zm`p)n{;!w?V(eEt`y;GQN7R<|+~}&wH<0zq`DN)GEp|i--XZ;Var{A_8t72ZDK6)( zG{I&EQ9cueC;X}mDRXm*Pqz)%ov86FEUk>ztq7@%IMAO|7$t7@4oykrR_Slpfc0iC z%30m!_q}TW@PnbEV7}7V=MP(qr^-Pz^#hbD^L;W_!eu-`vip(s{@XD?xH3=bC$OebG%k7GK#P5A9CUs{FPQp5T;>+HLvLmIs% z*O)h=g?@ZTy!y@uYx#xkMP>7$_GAGt8ACFgGfT%x%M(DtVhdXEVvLY;|Aa<*blLR} z8P?h9nmb=u-YP~j=j&ks*7G4)15x$Ek=f6McRbXp-EnSr>%fXs3%>fx`*yjhaEuoWB3W0USoW2F*r~#cOS@`oexTk3lMS7SigMZaIulRgxktJb!7konvQ)K(<` zd}4v)1SdNEODdY6u((yB&yk>bG*5tU#~^I#q1;%Km`ib_*f-L7^s z4^v0|O6{SZk)~XKj5%cTC2x)KUB~8C;*i6eIU-UfZV9Z&`C(} zYGA^w?*lVx3?TqwkjqOE%ziuYbXP>vF4|qNZBjxe(}J(iifJbfH= zmMs*tq?;RP@(}6)h+2=)Qn1yCI&Ip6Hq(#9P{PsHZ`*1vCLUZma`o#+B<2+Nv z;Mp;f`MS*Ns2JKzFG*f)y35AGY35m&jN{$yb4LWf>?MoHpJj|_#E}Dj7C>B_%i^A- zITO@DlC-!whZRAXh`Os$XrokC`nm-d0&kWjAxa-T&B|0~p zq83_@1U)K!v3Kapxr2{?5SCft7R(!n%1-PgpikJa1=(D2?N&9DYWspg@j9lBu}O2 zQIHtNl4kUG+eNn6>~Dr@ZETmh)qvJ)o5#y+?@5#R%qjkfBZ=?c#+Gh6B4_apr2e z$Gix&ECbgMz^4Wl=lWIYBy5KVLNJuGwndmI<8=y)2nrr4 z5g&lvk!epGilm%IJfC-*((6dSce2RYOY>!p+9eBvqW9m8^zQ6Y_-3|9PinrX#MKp7 zePNL!H$oy|lvZJE`m51HfVln^#Q$D`_z%bJ{^wdVn`1j2-0i)*uRC0J`}xkp)@7%x zIFA_5&o}b&nDfrwUiuE#l|9_9dAK{cd-I&ZD0^J>xNdaqvYi7)#o?y2or9tJd5oI# zRd0vu7!_q>6$d*Hdk2h$gR`TPH;?2Q8O#L-cSmn09&w4&(%>hf8@Aql*BmgKZkHV$ zFvdUMn(NuRIM{h(%$)7Pc@h$0Vv36YLel2w<`>i+B|w)0%KjD#g<{y8K;1!Y*|LRk z3**);Tefc7%D8pg_HE$U&dl`lVBWRkk7L)r94vq9U|?iqWZK5Gn~7;R>+apVSy}gh zgO&A`Tb~BM+kAoA$ILLtoXW_s54B|<1LHo1%@&3nKp+#t&jY;q2hAoWywxYK2?iW`w z*nZ&hG0)ovCE~J~*ecHRy)^9mbo!9(SN`iE-;OIw8pY>S+IhW_QV~eVt&(Opw)bxC zpJF}{x??BD;X8?{YI)VB115r;Fip9Wm{Fd>*{*EO3)DNda)c{4wzf)aIp>Yth0>j7bND|3NWbs*y~p2&G?H8cVg15d{I5jW zc|zA(Zf`v0lMrM3a_$jmjc^x7d5{3-l8q=w-hk9FY-)<3C?2NYC>dY;+ODV76HrVK zI&tSV{o~XjqQfo*fKXC@U6Rn>G-b>y`Qq=rs9ZyRQS>ET?FdbXMJ?)%5?o%su;&SV z`{3WjPX7~j08YSf0!+do%aNCGM6y6;!~1Q?_4ysV4K>m}l^mHxE{CGG+uZTC6*qf| zSOvSl%9KzIoHSzYD((Lvw#V-DSjSP}sE#um8ZY+xKG}U9K;F0i6V&|T?DYT0&>+eX z=RP**R=`5(bF^Fm3ZE98x1%ZLELwSRS&O^`o-glz(epKxEA(qt8kX9H$2gzOj~XU8 z;L0qOybdNbE4NVN2#2(|Vt8aG*j&(O=Gi%`9~y+3R0Q2TK6gCiU5mSk6K5H-`z8HQ z!$xL>Z^jAj#Po-Hw3hn8Rs1p6^x$&8oUT)Af>$5!cdSXQ!t6L7Z%`5~7*PDR)nZ-f zg**i=o>}RXeiB33Wj(NJI&?yM{TTHVFSR8Hzcuj9%;ert-v=i6UzA<|uYjtP?KKqE zS@o2kRc~kdW}G~>wasp?^KdSnw0gX2{wyxU9Uac;y)b3_%Ui1G2pR5>r`rUE<- zPFnLYBvLM^jqc|1xTt7dqoc0UH#;EtBUk3^Rfn>8nULdgmZ2eR3c71-9E3%pAOJ0N z-dX!$$OGMHL7l`}agB%EJBtOMClh0pS<=gcrR4W~VNM?{*qVfb()R&$VC7e#12zDu zkj216rWqMhcp6da@lNVp7+GVQz6&ij;?275azbWs=bw;^T z@VLPmj0obka611v?t`9?GXKbhiBn(Jq)X8 zwId$6HQ_dHS~9-baX)sY)UGCVDHG28IN8^0ZKB?dr{HZajmUqS#e#q<{Mw_l6R+4l zgSeJWa%ml5-mfthmm8XnEqR%g?hoi9U5zIE#%!S^4-0V?E?*~v6W=td;Eqx;6A z5FNi2JCUmAc%%MX>Sj?|#Dac~#%p&#T~Z9x;|bP-0pjR{&LSocq1v_k%*zs` z;_-JSxteW5Vdn`4)rFKUX|c&$-YWTVnrueN?VbeTzBnxY5HYz)f3RU~R<7IdO6@?| z<3r4s?|%4VBvRRZ{5(T9+dkv!2fpPOOg;lvfw%#uBaP%in}TL->IxRVE8-~9p=-iA zRu_`buXym;w7yI}SEN;U=txOrW#yC6{e*rRNdA*`&IX(~1@eJ|OT`@$rOJvtJ-f-zLa)6c2M+HEo5qTKBdgbe2`N zY%C^2J z>ijZit@T?Lj#BvAI8R?BOR(RQyg{$j*-}2x^($ivA&AqWk0mBSzO~fZu$sL#U6uA# zt9mA0-Tm_eVFUehX9!;>ksy#sAxi+Ysz?o7Y~N-d}3=+;Qc^ zxkbXczC)xpYx@S4-3jb85Yx=;rhTNn1^>sB%Vy5LUyC7`WzbsX{nb)5?ie`_S4uT% zeCnODC!}wp{CcuL)n46fA&s`H9Z{kL=fXxay`peRuZ>;b-u6;eQU-%}veG$`jWv!*mgy|hiu3r1d98yEqHf3UZMhuJW1hx( zocZ9B*vhXbo)X9)$9D+{7I%QFV5uM(k^??dKBGvlcs%&t&|F=7&ygQFiTC?Ie0e|S zx9xqds1U=V5(nYE{3kfl)pd3fZrg>H0P|*s&-T>h%~$R^B}N!^F>GH8RyS~b8Wkfg zX}8d!m8{@tHvXK6Mk-8dXoUv|P>+zs=%Vm!5O?oV)%&w5B4Y}I4mo16&m`0QAF(m9 zf$U>p?3_eHHeB-<2Kg!6xF>@j>uL4QDMkUQQ^u*y{BJ&lALd9;<;)DZs{WQh0^x0} zFRcu(q$lg#WJPfs#&f-`8?=wqd(d{N^jy?j#?Y!#V#30s>vQ*u*epxBG1$2Ud}8u* zBrdPbVRnanS!q}DFyegHOEo`j{C1qp`ATe_hJ{x4N7sriPYJ7eoL|I$1vcg9IES5? zO9thof%!qOd`8ZX8=j6iR;9vSQCSr(wWfMdzl0nE_jq*c1W=SgHG<~~#jDHo+eN={BVsyY z6=1Szmwf4R4$twYJ=33Xq6E*j~% z#fompW3Z#vPxP?<>;0!&3`;WHQLQ#(U$)wdo0^%Pkd8?+wX9@wu`PduJ>5_arvUnTVc|LSF~8>ae#FKlUdK^1 z)T7vjf5q!~mB>t&fmy$q!)mK3!6xAL1(PW74MM?A2;_G}iwuFHo`*z1(dC@Jrs6ys zznIlK$2#Pg1s^_DW#Lxhn2+byY24;JRUSbDy==}Xmmvm-vmeonl0v#!2xrg4h<)gU z@@$+e8G9o zPZkVadQ0>~_Pw(b(vf`dd0!{{(SxT@Y;5mJDDQog{ z+^iij753z6sM@7`weN|JS(l41 zw$I{^O)NSMbnov8IVADgSc9AY+RkF9M$53p^W{>spIzuoDLpZO_p&qi9?*Wo7|(-T zoUqd9w^D`J`sz-(d7R5J#{x~h0XVq;zlZDL2@=%l*U(GC zi%s^7&}eU6KGf&=LXaI;4@!Q+iy&qc>B>H&55 zHk{()=;i!KStPjBvl&{ud&=x%{)6cA$us+yF!!HMmDW?f{~Qmu3pB$zKn^~|uEB2O zNh3bdSi^|+UVoy{Wq9vFAAiRu<>EWLGxwMJ%J49l?1K*g;?@c;f?63X>we-Kw-jC| z_`x7=!}AfT-qY3>l6AJ(8*SY!cp9%S$hJ-6U4an&u| zq-7)X{!`Ulav(trvX)+teRJGd)cv54rtsNl`E6U`r6<^exL|A}`W5w6 z)szgCl=QfPhjJm`)Z$+6)iG0@!DW;Tg*)J|h!bMxH$nj=Y92qWGf(mg$uT{5I51l@ zV|$sOXzCPmclnvb7mxhQCG(r4_94p`!lDGV%JZ?(5GHUa08RrpS5`DOZ<$y7TskeM zpiuIrQKdztR2}cNm(KevIm3muI9FSZq0<=oA#iFN;70}_IKah5XN1;C!b>{uaK1Fo zmi^QxsjO`3pN>DHy<~_ z-6H)Tp4~lp=1yw%wVDS{YAR@yclM(iYCWc?Np7Tg{*zUBuL{&H&uH9xaw!8%An0oi-gI4a#$-iWOru|$dKaC-6iX#a#2a;muzNccm$5vU-1UWA1Tgey9 zVoeuL;7lx~lvE8_54n9amPv%>_65Fw1Xygk1lC*9_mpv0*vjOI^po+t_>5MM5~~-o zCm*Qm8i z>NvR?Jk9z+ULHh=P;{XIx-xImp8fpyt%vu#H>)7Oc7VqhVmzUN;a3!7YiD#^zd z2!!*@2>ZYU~kO{ih88{LyfyK7K9q`Y;{g}XVj33F9RId4fr_8d=II@IR(TnWQh z%%WFMDs?9@tYUF*Truc`KR@T zg#eAjM6%X!Na&X4WiKYAL$79`E9(z;-!ur-6F=FRsPt~+#xSB=UsKO$Ha4o8YZR@2 z$7M$Kc7TVeYj5l#=q-_5O#^#YalPIKD6>fSDg_QXb!F{j5WZ}R*e4xH*AF5V&u*eJ zpbUr-13lz6Z3M{RYs&GY+1o|_YEv9@4-a{0sm2L@3%jhQe^YL?jlOFM8q8l0uGvJX zjAPc6){(sLZ-@W_jl(4)7yD_UB#flF)%i{;6UgZ9qoEc{i*ecF}zRfw8lh(A%aux)#oH z3Ad^P+#h2w_}hoRyO6|0*BOT<1%9etc2NFMto@npirlZpEru@Bb^qV20Lb-u>f|4s zfc}*cldIDBMD&`B^Cl_~PtnEB zJ07eL4Zbg=lcArRM0St|HLZ=x zQAhsRbC@Qm05ti{k^jjYse$dfIrTDEN9Ef|R&UCyJCjHUzt$bUOnv!{$um7lE#3FT z<=DOIVi%k6Ml5{?UMn%h?O4|b9p?TD*84|(eAVPR(9k!7>BaFpr6kuEIU#OM6sBQs z*ZVwH%)GTvoUyagx2%3*m@M8?4SmnMP8BYY>e=Ag6kCexebPWDAC5l>h5@+0k-C;cuI$3qREW zzY8>2h{WTHC&?A^giVxL_h}>n0F>z!h{4OBMV1BVGALdOyJ)nD(!>m|z~&E4Hc^CG z;H7EC0%HxB$buh{Kxlw8ipxII=@fxIvT?k*o z%|z)@K~Yz~HjsEzfh1@VE`a*&u@qBm#~Cahz1qB1PF5?VYe5Uge~PQ{fezwY-~e_( z0u2+;q@(EG80ux}$ZsC~=F#tU^oOkJ11*s?vqDYvj-l$+0m-F!(K7IKU1&jX(Hq_2 z53OlHK!_*FRSiI%jP}F<$pty%6dPY$1Rz*ruZVQ7x` zl(*}`YAu|TxP3Wev|(z0vPf#Bmbk>;yXPE5_t~p(vaj&?Wkd5gj2y+ZXWB4olTvtE<+>GAA{dkRRHb^^bo&q z_khcR4}@8}ie1=5*#egjlnWODk2DFY0q)pM>>58jf_wx)Kfv8E5>ggU2ZIq-P0(vc zC&}gO^~l|xHY5)Za?#!$CeAiMZySh1Pc~77^vHjNa;VQ38uWrXh~vO5lS5PE0|B;s z4J?OrV0!+A3mB?U3^m#VHru!eTr)>IVAbknL0?!Ve=ZCg+~O!SfPnlHRfA2G0U#9E zl&-|T;wf+xJLy)eRA`j=n^nJA^`~t8UR6MK{F?v*g)k=~2^+U!;^pVxytr$W6VI%m zbo6h_p^Z`=Tu%-?KV;TzDKPW6(7BY4df$&J(QP^nSAP6P_Up7 zt8!ImA|)9yP0+9Ir;X&hHd%(Obs6AXld;A%Yp5dSleP?e`8U7u@gz7+z$H~7LVu43*9gUzFH79`1^CqYP-ZD;F_>;gEvq|ad>R-&clq3Ox4 z{v}VBZBwzaTrKElNmowC|08JCU#!fqCfCH;wCW-C`hCyB9BhmF^}n&4<3A}`jEa@B zEx)^o5~1CP=SVAE@4YDMT~xC~)3$CXdwK25@(rso{+du-^#=_MWd}7r^9w{KvZ1cG z;!NO@{#`3#PKW9$_}|uzJmZfztaFU%nv2BgTd_GJepPMp`tk<++}|qfp-&2|NLey& zH3m%^NJNa#6g%=Bb@E-0xlXz`-F*|aV;)+&S_!;bVBG*L`eY1T0dGU}yJ;{~fGwN+ z_aBcTiEpB$u{^|%!$dr0wQa4QCXfvfr^-$wZW=rePg((Xwrz$TR+gcVkW{1&y0eO< z)>=UQ@(_TZ6WeH`v=D$@T|okg1L)zEuMfe~Htobv)nfqqOil&3JvtUgVwvnsq1sX3 zBM07Yq87&-Hc=WtZFZmellWb<>W+DX`F-cVpZV|A{!hwz0|n%|sdrAMrhEJQ-E*!> zu8fSdA{^Jqi`Hjm%ZYsvdY)PF*xhik8}yhMgMH2OiFyYeSTE%Az6s$fx8G3D(Bx~i z;1zE^W54#=K>p=csRJ{+ljB~=JA-@mbW-* zDg(B!)5_YG57nPPCYACsP=F^*phIPk^74=Rh7axQjxJi)KQB%{7QgdC#qYI*{2TJb zM=I2jjHppwr?IBV7dsZ%EDVg?sTgk?(qZN);)(uv%d4pW=Ci?b_N}q8{$svD(B)t~ z-qs9`2jOD2*eA5Z0zZU1iEB<^U&%8k&StjLW^r@cv(}h)Tf`pfj~QI~YL)^m_5lx2 zqXNXk5HAcRpCSy4;JRX{2GlHMCwYZ#DS}-%gaHbv#{uzfa)6FU!f~4@Evymor44Yn z2&&=qW5B%v8mWuelhRc_Qvpd}7t|Mh{`$Ki*%Y`RPNF4aX4UC}KjRYH{CtqIL+I5= zb`TPrlK{0IgtieB9`)PX`Hu{`us3%iHB5 z@)LRfTC^R>3%pV&bQQ0m8r}IqbLVH|@%HGGGzRRAXR+&{>b!O$iu|liX)8&AVCGM` z{Qcg98v$I#R%{1?bf;t+C5EOuZ%dZ#7EV2zwdbOOZ$+X<%HCs$yL$>Q+#vX1uF%{o zrSb&PF0)hrVC=JLCzz0POxNJ zUFYBFByKho>=UnJ*50p8usq`IZd(K9fK+NOr18gOUNBB{mlD!AuIKW=gda8d_J;$yI2By$CZpKiX^j2FZSAkMWhSr3gq1EW8 z04aNqrY0(CBM;=%={NzZ?FyA0>cmo$s)A#wrG z_g6O&L*@GOMv3#y)zAJtMJI!=;{?)U}C->Xy@@NXA$x)8`|1rHzG<^K&px%H7NKv{TyuAuB zlERX!ftC;g!bW0J2XEAuG{Ilzm_7#*ucx3>@Hrl*NaySJ!tw3yAy0S+=lg{A>V6EZ z(`~$Sdc8K;tYBz{hpsI0fc{#cYbJo*f)g}iI-+iCe^1dN7^`MR$!3x7$ z-l^=?Blhdu~Me?yswYPD@KY&VF|4z$iT`fYi z)?E?(xu3Ouwx2-itygi4Y|M%B7_?|H-6Muf^gzSxNZWcj*`o?a4#U6}8+-Q!pIfBz z2AxsTel;}9Cn#11ze?i|Bhsq&w0 zjo3uB{|FXfg})O6GRR98$koMOpqNCwpef^&!4ah$(AmyGub7WH`*4vJ1p*TfM_zfz zJHCPjNv}P+-0ISqXsq?D`oh}rN0q&%m0#WGHk^b6O8of96XYYk{vzDY1A$e!RxibG zI6eLtebUZ%l#pAjU>vf02RD=SbBz1xMb8Iu-8`)4okC%Jp(HMy?ug!NY)@8M7|}ak$Y?S z#VWY`Pi?ObBK3#R9S}8PHHNBY4fSzX(M=(#f7z{QSzwQ7hV{VK5gZ3Ly3QCX-!N3t zJ4^gyzdBW%P9O^*3w+|M;F|7sq7~5Q3xMOJjoY|14q0P6(ph1klk($nGfe}xt)tBZ`O;n64<5NLjvL&Fvp#w;<$cE7wol78H0-ZHtF}S6;~SpLEZR(S7=D-C`nK zjPi7O&PMy?cy7R}z!EFivTqIpzd6JP+&9=y@AfbUlGjGg%0LJSAgt;DKL&=AVL0_B zk#rq#b$YabT%uJyYa;55y9pcIE;E;2JlLsLbVT~SzgrAhH#)e;1;y2We`-Ve`^jau zD++~$5(?j9KW$i{A8w*jr=kQ%YLEHKtfSQ4KCzj>cg>spkCF z?*dP+zP1@slj}TmiAmz}6Rx>nJx|a&u{Qw{&yi8o7!kQ~Twhz{G^Xg0VScXUHJL4W zh6QN_!#8b$#7mzf22Fe51^n`sKkJiTO_UvlR~MwmxBav|IorLpU2nU|*1Gy&gx{12Ui#wnLcb2?V+#Ov zVKuwu-k2qGUuvWuFIFy)u>Qbo%4%~i(OKd6aih4&d;EJ+2?OCu5p{p*K{HE)J6UNd zWN1PgWYZNDQPS4yXvSb7H~LHHcmN|Jk1bB1zYIE=b-MMRsuB68PRvzar?Pi%r|U;iLtok z5aVz%Dg~l`~0Y? zn6ilk|M@!+{q;c`v%##+YkOn1K6Px2+3Oki<@n3q&#%+3Plrv9$K3U0_^`+?RHdUa zOdqBofu(96*zZBy_7;J)y?)WyXQ_xa5Ni!{*E-9QWTIqtH90)BT5~EoK)YM*eP6#5 zT}8azgyr1ErJbkDye?MADUZQ+40SNA7c)`;JGfv;i(1!93^eD{hF25x**9Ov@vy zJ(Kw0s%X_OT4=&tF7;r~OC|oDNehNvr`cUx#3Q0LZ&He99DQ!t8ZThCS1>xq;K-qq><_VWK+iii^wIiAHI(j52T@)ygZxs3 zVjS*++VHaBMP~W)^zvD$3I6$dtnt>0nXh_$I~WzH+@e!cQ65gtn$Z`6#byQe^VS(O ze>i*ym`1VzGXatJE{&Y3Dcdt_*J86sy;@sav^r*ET2gHHWZ4E*({s3iI>5LijwTkH z*u>D$wyc{O_gVnu-*H0xM@pYRYnmipa)L{*Q)YNPD)nZ}aCO>=nD{jt4UM8NruO%2X*$&ZR|4yI!7+pN|SLMlk7b| zG+2J-)6OM>A#-=;&q_tIe4oEOi1<29o}3*)UzJnQ(0-lvm{Qkro%e1zZTfX~PJ-hM z`s`A=XuQ+ww-OhFDeIYW&MC_&Hy(`9WFT zT&1G^b92$odbd0|I-c4yi9h)=6ELxwRhBz4!)dXQ{lNa%G2fNw{c`URC_R`Aci)ydrB=HwhJ3>HhLhx~JESHz}z?XBSc@w+wG36>|FcJ8lVl?!T? z;nZ`IvJA>TeX(s2J7!fd9H5Xl=pk>r(N;+B7W-MAEl(CX)vWS-q?(|Z)8A(PJR0?W z^yC#O_l;Rcs_-DX^t^hL{(Vv4w+=)-a@_a+aQcRuBYnq8!k+%c;48s3q_X!un<$5H zI@=uLj)lz*0!QI0wx=D*tcH$3VyjhDxei>&V zI}ta2@?1c~%Yzzhx1TYKLU~E939megdm2QUIiGUu)r84ToHs1;aO{N(a3; z2)_SX)!TqYuJd)AC1y1wc>!V>ZWQIW=J%ho=8d)Ls+1^}yUyz*JSiF6=R|gqe9h6C zai2i=#4|9k!8^`To&IK~%hy&V_r{IZ1AFz7H!Ar2;Dy;IyUPl0lU#3psCx5#1ckQW za&}e#?R;fMe2Uw?2Y02Xx%u-&8Ci#(z*}wTy1}Q2hTn*FHYH_NwES4s2QE?Ot41@2 z8KuM#d9%fH!2@*h#Yf3Z>g%G03}w5U0d!ZFa~PDZkd7P-?~ zm)=d}61SBx@ZT)%j?Sp5;oy52ef{3tx!9$ei*W^m+A$)0d>wD<;$Z^f8LnN|P)G5Z z$$CpROIt>%CckEr_G+_~cxU-J{;JNN7Vetms(}FY(+6UV<;}U{6(0pmi(VdbY0S9A zcOv%3X)ap@ejhFQ2oA(7_~r#{5S-<47`sBmOhD}Io2ZjcOs8aj%%m*Z(bC459zF^b zZ(FPI!^%No*c0X6Q8LK&?VVcO*3TbmZ>Q|e`?AB^(9kbu`nA|c_eUdfKh7y{ig}$YLBS!gKEH2ry;y#nU`J{`E4J_t2M_h^M zSWUa_s{SG7o9>upg*5|-n<({3vb}BTFKSI#o*wuT-c{OOx@6-(#$>GRW?nKp)wTY% z`2fLMWcWG)$ZN`_K3%yQr(?vga^1U z=05Ik(Uw1E%e+4}d95>|>HArQ$T5Ff{M`ipmYE%QSb}8CKD{4PU|fm}xc6l$dT}hY zRfv$gC(PU!o#$wAc*ia-95$0h^Zu-~(5U%8jTQ z`^=p8%>2m(7s>NHzvq^9ueI)_{zf6M8ddcPilNXPwn|(PaiI0ReiEtE`;l*+k4$F#P^YwRSwtPsIAMg0{d&h27WzKdy1GOU+!TF*W2E&@?;KLan$9iI~h=# zrJnM^XNUA6Z?HZHL)?fEA>Brh*uIIvVOBdB?tm33p1irdYoya(s8AwewpFJ6+h$`A z$vfJ2pSufW*NO8+F{kqVxYi@g2m1)gGL`I;>)H8U%$t*r2O%$r>6+4E-YVO( zPoWu{z@SHuhkI!(slpz+T(7HB+j+XsOxZVepXEnI+FGXK1o=xykoB+<>Vm^o7N-Fc z)!qS?BXdp1)H%=)a1Zxj&oSS)Pgol-z!z;sLOr@PdN+n>!i1tIH#tT z!EY2PNbkEYFeS%=(?_4Km=1nMI{?K-H6c#L^G3uDS{t+fb3VN05je7xH*XuYV4Zq!@HlPSQgzV|7&+J}t=b%B*eaxVEm-qV zAivd|tRz&wjKL;QS7P#VD~E}5wx=w__0W?3D;wX33(VY^Ke+A+0j%sy$x{)rntDSY zzLL+g-@SWRh~`8&3Jyj%8Y5KOtI>uatNlw~mrQhik3P@danTpq}GVQDp<}-N8+1X1siQ z>hJHIMP1s50NlT0(QP-vtDAOQM1VDB^8zo$9%hvWuTuKGWpGW^+LM)fC2MbJQ_$## zHHZzjh9tTXGr06p-b3c^`Oz=caj1$5b6X6OtMUlYh)mJZ8h3Q$$)mMR)k=|EkohZk z$2_0CmzyGcv_VcLBV&5bFmu^>T)mBL$sj8w6LG^2BFg23Edm?;K6P>iEULgwF`Q2} zJ`ne_{%1uAS{j=HLei+0AR1*e^v&^$~LDMoN)uPIbF>2QFr|j}IRY+m9Bc?#7x& z$f2jaTRj457BryY5He{71)dcDp6ZX`YbGE+w8_k9Tl>DG$IK(zs{J<4Zm6?mw7&{F z`_VUDtVi?*eUX0FuO)KIZdZKjXc7~)A|$4(rN{b*C8uUUaAOg9{l51@glGP@tELx7 zYh*$p$Z_up+8sVv*_^~TFts9QnaXPE%qw>Qw%1pmO!)4uxFnG$K_eZ-sDC1eD;|E; z-Zg%V>u`qOdJ+ffBOZMMPUm$0KLyz@3J5$$uw%f)0iV23aX;38U2Jt_+?-%U%>x0t)Fh=Fd6g00~)hX$w2Td zUcLv80w?9AgVTZr4&f7HNe2}UD&2cyu5q)!)jfWNZ<)ukC$y61bO?zZoZa_P&0|e* z>Pgz)*oXKLy$|?2>DXFO@%4FsHw{-!Tn$E$)gCWzpOP|BTyfMrnlc`? zpnu{#Vn4#l;56HIRf3>ucmIK4}7&9R#GI6l2rFoU~gTk>bz?`a+%R_;xrA*bYB!2h~mzj&H|c5~~% zBEXk2sGezCcujWY=kDnf)&pq{dmRDnM^d^t1+3U!B1wgFRx`?0eLhyAVU&6WgJmBE zlU-%bxe}Yyp4*ur;=0p83V;;B?gDnyn5TQ;ftMqD40dS(d7@@z-*u@hS;QwzS-#T2 z>ft3(4LTX?tbA6>vV08clJ zrtNnu({;33G27VL|HGC4GqFZh-!j`ZgKRz^{jSh**S$x;`sna&_?Ru63vOLx(+$%w*UXO9u%aP0{jHYwHElUNSxYfqca{0nK;HB(f5%dJ zcOPTIxDM$TuW`C~*t@cFpr>Y*H^65qku>c|B8h}twA=dy)SyXmF|-;goIRa1w5#oK zWB@f&fTc=Z$<3f;*@`R<=jmXAc-Cc%_or_Gss8~TpcY2MZw@=^;#v&5+@I}o?W$2J zSF|0*@7JfJiV+x6%~0NOu5bGn9VXr8xlge$M(Z2m>qxS#=$Nb+qszAMXvJBJ^(St= z(68|l-!AFA=R4Ej=rGBp7=C$Gc1>Y$k(Wp4)&mz{8@undpoa! zh<&|L+v_RTolTRTH%@wT&}wT13XazU`g5!d=wqw+yMbNM0@_9ixX*3zSF7hd!Xyqw zBrLhQK$vtt6%ruKC@RS zjQM+W#!d>V1}Z*L+>cpe$I(?dgY^xF!|*Zdh`mxsAA%#1M&`%Kb_N#w%kU9ofFw0l zqX%}6Q8?#S*M$o-&R|(y#L!>p>sai7CQ9|v-sz;HE#ud8W*1eY>eGV&v;79Odpx>- zc%!mFZr~A|9kUxNOkp#eI_C23cdW>5bYa)#NkI1RSk%40W8sJ0d>RxF-X$O!?oI<4 zLH*}Tm-a6Y3l?egcq=_=BG0j*w`8Nv6LXe5g@f$%#8kvPj-TB9j2aponvnUSBpGMS z=Rx3bRC@9{A}Le1fwdl0J>>}&7$=ZWdTA56;J=#{`QhZwsPr*EFU8Djpqjs|{4Iak zL|mPSD_9yYVlX4)iAqkJj%dhg05(q|7`#@biWNGOJOi+sCA1OSLgB z0uP@#GZ8;v7Btzz;~(3#Iw&fg>1F>iLYE25U7sA3uNV$`s-AEcIqCc49rgcYAoFLz z`5%QSkS};#7!3lMp$(9#yAT@xd8hMLQw~SnL?we%Gaa3ioa7X325o1)_G5G(^q>Jh z-Q1cK*O{#=VdqEAhh<+U&U()46?L-@yTHVnJNQZFZ@0# zopX#Gb6>7q7`$Yh7p)&)iPCNp*qA|=-C{_7`*|ne%@MtiLa;Y3k==q#M8aq#AU0YD zn1yyt_2b#Onm>;sFgte?X-iY>tQ1N(SZ^9DvZ6l(bXJJgh&%F@I}Z4Pb2_;1#imDM!y&etbbOy|2-W7|Q?lRN`A11q~7^ z4FHb8Qb1CiAy!T>sd?XzA%FjMAz-iSJcfYwL^Y`zX*sG#k(YFO;U^)8P?@*7SR?l6 zX~r9Ugmb)+Wcf}zmyn3h@FkZEb*w4 zJoBW~7r_01C$7jA48>8GKkPS41Qc?hCXkNE4;YB(&aRorL7Uo6XmI&q-BP7*<)nO( z%G>w*mgcE<`Z$x=2FR^qmcZJXnUQQayYh$`kR?cC55p8mD^GNT@nQJR5-omI0*r|EB-{mpwjH=mTk-7HV zwh_@Rr0~QhZlyaRinTmwtcAYX8e*q$HVrmOQcM-8qexZ>`r(6N^niIA={Uq|cIOkn z5yd`h62mP?NDoL~)7cDQ`;C&&%r1H|c4W?SnI<6YIZFhsD`4yf*s0y_*U;eGVE-y% zAziso&j2@z%6R<7O>qk~i^zkimPo|ydbUCvA?cb*504*wv(*v+2|u{or|vJ6n{u2& zI19BawydPmpr2uPWd_yNw0JXI62>*wMR>V>k7rONwDkZQ->R|(kYE} zk_ebEjW8+Hm9U_-QuAQa9<~nf_yTwpv zusHrfft>lwwQmTyM1_e0PwJd9gCND3#LOeVmwtNH^WQ~o0EEgOa+1#_t|F3~YvI&+ z+2+Ui3vhiAA7#O%*F0-+en%_Yrk%g~$Z{dhvwnv78dkDrY^4k)7_Am*N1xW+~D$qzO2J4 z&JiHQlUMOB-~4)la0Oy*5raCiHFAx)U}A+h@TLB|fEnMx(oT^**y-&>6oKZv`fKxx zQ@r!<*Y%nr*hjgUMV7GIe$!>-y$S~k3^L1{+N9#Swt3M}f(v{G2V%cJlPfzg&?Yu* z>NnH22U#R(+L!kwRha*3ok8|!rWY`%_VG^_a?oI-Kc}beNE&{7!wX!W!7hmeynHhna*xPs;9osPo@>uj|lkt z>(I~%!OVmf78klaem$-G-%ptSs)N+T6EFF!Bz8cu->l+E?*=qn<2~|MaxDXhcR1AF zc`eso*+|XF`>xL{0B0gEvpc2BJ!{;Mc_(Zeu{X7DKljw|UFy>3k@z1u!M>5^D+zC0 zmj_COIy08^@8j)XhnS!V`Q2umM#i1}pU=uiWkM@IU3}svV~D9piIV;_JD~p68t;Sa8NQG8Ep=P# z7lGCM!uZ@zuiuL)^^)+$<=)b&Bk3m$iFPEDo@RC=1<>RdjgD6Ed(x6*^48bl7y5AH z&Dqu4mu$eOc&Ta9=H4xth=Yo?lW>YyJB`BE7**W){ zU(#>=IY$oERn^Bf2FE)Oyqrm1B(}R5Mn=w)0l8Aatld2R>$@iR5Kj^CtJij@0)qLy zEb8AleboHCX$u%(y~bF2(Z;F5TJf4k{bTppE<2feC)5EM>v~ZB#ktLmWyqUa;U|;V z56GPNq~fnv(v#`G^J7!#d=~^HVzLc5J=b!|vwMQIqsclS3D$@+j8cU|^%$E7-u(8~ zMPOzAjzTQS=srm(`#I+}$Ag-JCQN%P#*7i2?A@T1qjhpN|E0&rB(mcMBWK)FMNLd^ zO*UmzJH>QD^-`|{6MfyK`E@q;pf4I3oQVuCuy(o|+XX3x-YX}_C_J(Y5)E@%SZzpZ zfM=)osq_tK#J7&{?hp-$X8?8|`xo#KRhu0yWr61BE({iE(_eonqZu&=7}qOZ&j3E> zATO`90qwCYU_C0ZO64r3MxnrHq!v|xNJn5PQWt6ImAa+c7M~SZ5N{Atxe|y8C^VlN zh57vW!l)EyGAsnXL`c>gnk;#smk#)p<@KJ~#zc~apP#q>_@FC+N$HrlIPp6cm&4kd zDb(=ps*7^ntZfUxAl9ff;Y&fi8;b&6tEu)U%Ht;9amZ!x&78n<&Od;w-(>j|)BVNd+J(StS9(&c=9 zT?yRkkA3~>f{3qj5;i^B%df1kgIkE%07WJLXU)Q|f`fL{XqW!9|5k|#?39187hJr8 z#n_T_k6s-w zsZ}8S$^GjOsb$WblGAeEb0urONj}zU_CN~zsVTeR#?df?sG~QGAYoBM*5=We z!hn@O9zko%qnu+J&cO4{E6GW0Zv5g;C%Bk}OUu7v(MdTN`cpI&UYo!X&0iumQv5Zb z6-0$pI>-^s9yB2?04GQH?jr#LfGUkfsJ_R(|5D5M#>~e;cV%PVwfY7f=WE=l@O?Fl z%uTO20Wu+E(=t7dpT4QBmz1M;H?VVD{MM6fNtB&f{;4#%s%-iR?maU90OTN24MTAl zy|vY?odR=o)D=5EMR(;9Z+O=eHxrg;PrG656^~+MM z88Q{ue`Rm;=SN`&gCOvDQJTzWCNn7ghjkvRU&)`|#c_(}$7eCwd)w7$Eg^5Kc z{)s0Nx-^8@avJgQjfw@`+k*nM+f#MG9%P$Vpy^;ziDa?lH{318L%f$3mCKi=}W_Bi(0BXv7u2#A>rU`t0YyW-eQNz`}U2uI-oLlin5XyvG&qX z^_&*|(J@*Vd&IFnFVz-6IqYlO$<(EuUeR4+@%Q2-ar5_JZx83LxK{@nmWC4hzLI&E zk4TYW6E|-Op2f%4wNI$tXDVbtR#>I~2@Ej`-~%v=mmoU{ifZ!MV9A^rUv_())QO8n1*qCvl~=}B-Ax5Y*theHt+mLA$p8**!eB=BMbLjQz=8wM5d5EP~A91QH;{Oo# z*_NJ4N&OTJtKUo&c{Yl%ne}>p;A#`A5b-sL=!MX4JR{50e}oYIt;@jUR0gI+S4kZH zGZjl{eTU4b1Me=)7!GvxDSKDPB;#=0A@LG~!(>A*e|w~|9P?5Y3IG_5O_52`2$R&h z0L!-pJwWVC*><)?(}1^R8YOSE(}m~Qh+hwqVH%U2r>L!~bO0}xCpADH)iZAnm#c)f zPdb^`M2(AAJ2q^7~~#%I{d@ zqBVyY)w+k-8{0Q$vA+s!e^p@pb93CkuZ{me2+$3$9xP`2sRlt?V5A_sWCE*}(um_i zj4({J^LVYnsoKDBWOLjx;*L*siioRWeCby($4lLfrQMm{rn3Pb73=V5e1=z>#FWp> z0D%58VFA*k==#vNKE=v?n|K?{={Y9eME!oYvU8RGgKu4`_uL0POE8CDieElal)IE} zmpTi-PT`wH_(IU7u)93F%=dTHJ=9vtRZV~X&CPQ$8sp?N$nRL^0l#B0$+3-}{TqUz zeKI%Ow@*h>{Zhb`n(dbO%4%!qC-_?0McKB!RYH}en@Nn~&kx0D^2#`ieM|c1v4Y;$ z((S{?oNca;L`q(%Q^~xO7-crYfP3cfCk+AvMQ`mTlS+*N{BQlUrfZInOb;~kP%Ub-P*V~hI|E%O$4N#chev6T=@bZ)!4EuAL)R^NhJMwQIL z8d{9H0d{)2XZ0$st}agOB>A_y8mpj@NVr3y)aWw;uc+sD5nn%idBMcsej`FyJ;QLr z)mR%rL(Qp>)M&{XaSw95<4Y)&L^NhLdTZK^QQbkx%wJ1Bgj|l6*HWJ=y{%cjwZCc?YmF5L`AluQVA10RX}7$rT$x?O>K30cF=w`L!yaf(~X0N=bqbaf=pqunNkrdj-a zE+W()j85%)|MvFYaR$*NEES|?WByl(${8AC+wLij_S4l_<^^iIg>1_0Wrr^*|ig!!r)ac z8Z(S81tQ7CkXcz;arto3I8JYH=61bb^?Y9gBko7Fj!UIi4keYZbv@qTiiV zGJ7LdIkPw%X?{=dn*%D2K7dHurU+TJ-AU73i0UnRC2!jqLff9=2J|yhi#r&;gMNSO zs1Y_Ye(PA@+sv2ZQca$o3X0HIPPV1T1DrRij z=au|B*3b~xumHUmR)l1p$b7oPl-+if>^yw{O{{uTG0=NyC09W2$9+F*2O?Y3Umiw7 zZ+T2}HtKJ}Wq+ybM5y*q+(&Ie-iO{oVzif!`cFsT7MN{3rg_LH*s9Vn1w6DKTD69= z)SqH@nsY%(nTAS3 z4gVBhEm$rK`koi8U1#=z>xF~}g{JmF+>yKe(vt8H$PwqtO)Tz01i=kBRZ~B>VK!pP z8`(v}=`GP^gh{lgVXyzfB0>In5c>C0t^RR5(+6aAbBI^$F5D6c+doO$O6+E}pgPDR ziq>dzdNZBnF-mP_vjL5S+~M+B-yK`>0y{Z)$o;TN_I>BI4oTWMe8~#lrShMzq$Y)2 zH|N77+{E-|sv52Qidu3RU%0*yBU1iCS4KV&KB^Yvt`oFRruZJ?oxmmL$EFc9IJ8P;qbHt%2<-G8XC%y`jnjN<4)R=_QIo^t+_)dvCBx;l1jWT^jx9xSC z2P+ltZW5&zHAWg!^Jm~EcKh_D+?81f@o?Bvd<(89 zroIndlRGgEHimT7R>noA2}J-eTkAd#`AZ^-ps4EV8zd4W|$@LAP2SDYJ;*liKha0ekDhZa?XL1LB_Kk6C6HK=^KL0W_+&Pck_1qE1(;*AYeptn^$IAR~oX9!@~)z)F~J=GA`c+EdMZATwatO zdB%K{w2{2uSr#I^RbHyfTm3BQh3^p#n19My*Y~;dwA;63ntEqx8*hxca%bY1sD9|@b%wUulg91Iest1lZY}q;>QMD?{-_{Ty=C4 zc|Rq5$E!9gf^1ktPrN1?YILam*$N~4AwMdKQB7t$AM`(% zYevK-c90NGsn1CsM!UI>v@HfyIKcw=I~6NyuiKN%u58(7wl2Np3H1xko?b0a!Y+Fo z-5!XP{16A6*zY}|k%R9fW6kgfNUr5bywp#+U>OUQAbb|U9eyQ4GFAV_OBK>jHC=@@SMJGP z>@=xn|Kv+3bRHubZP!>>diOPAE26>HoZxC%0Wcqik z7u{U^4%7e$#T(+)Dth;;R_5nXwT%pq%eMeZGqE@bpStXu)5x*KTQAtebRRHQfg3Hl}l)6knzGW$FyRv zS$#d$FxY+|u+r$|7^QlJUK+&*NU^=2k`g=l{R(Uh*&;a_I4*foPc7OhWO0~Z-pfH) z{pvvnZyLK6B8>;{Vcp1Kq7w|G9p_>P#v=W{RB+6Ftct&9=rGw-cVVwZG6a=>&tg~U zMb9zqCl$utA!5w9%G2BJnG@l9BfZF>itAIm0U_G86!!xQe>foCx00Bt-V%!A{Ii$J zj0FU$o$|jyzTH)M6Va+6*eSn2+BgfD|Vonw!B9e_uvu@1QlEEBl{!RmHFo<@954x2`)j- zlwW^wGv+~7co=FMKS5c-6A_j+GyU?%EykHh{EKc!r>dW3a`DA@b{u7c*YY=v1;F%~ z-+&?PPBO8MN>yjE4sTM+hZPW>fH~-{?=Ff%2IC z4n0?irfK%tp&}D%>6iDQkG$xL2kWY!JRv;VG}G4 zqR}l=5-}}hUQcw?U#NQMr`(+`@I4V67gAdgt<=osQ58NLk&_NFZrS6qo7rotaqtk? zh~o6u9Ls$4NZhT`kMuyGBf9z~HxCwv99U=AdrEIOTU9jQloMs<$lJ8?vEvo^gZB@U z2K%B*7q#fKA*w{Q#{}_>*9|pI`?7?M-Ou;*j{zCs?}-}R5q^E#gU(Ud56UR8$h5Jr zr~|3_{ITu^L*B^Ajl-BE^{1a8FV1I<>WWJOg=a!L~SufIk+ z%kS3zz&Cc=pzXB{gAJdB!8q1;29rBlXkinn;`vlhb@hZSOw{zg5HIT*EcV0-AHcCF z%QI;f`!8jh7P!%7G;DMuyL=ieNwt)De)}{SzGSEBrvrp7gMwUstdPWKoN{?P__l04 zKnO^S$Wv<$9#24KGzFLr9FT)w@7E66J2E`)_HFXbz%vO0P+X8FRZd=pSn%OzyG7sx z(aAA*QX+n~2IMUTB#2Op^lp69pzqJ%OHcce(;VJ8=9ghM+bz~{q?j8(JDkdKL(B?w z!IEURe*|EMY#dX|^WoD&u9AMoig+)4L#a4q1y!23(nlK&Yp$bR!E&<(&fUBhIksa$ z7$>ZYt)lKJY*}q0hislpOR6iVDp2jb&<8vnqP85pFi4n0BYy9i_`cab%=!pzg!%$+ zNt%>~1yBrpWhr6dm@?Wo7ojcO*;QFwc>iD!cW?z~eQf8Vv#xBGax78vYA6A|jU<&r z&|r`&VFWUG2h3q)f8CKOaW1GQYMO%?8jUno7miO6)fXf@G(3LeH7m^!T-5-sP? zOUxZDmAZRS9UPD+1>J*R?gSHRiCehx#VU?#d>|(4>4#>nA0M1Q1MIS~^9Lw4PK;3# zVg@L+V~!UUPdjM})35*}UCFQNzW}Vg`R_L_wLiPj!FS()e$)T(l!jxp&5bg6`+)I? z0lu|0wH@ll*vms5;?=&Ha#w78Rip{C{9UWp<=xU{1WW>SD%G+%Zy4RYt{W)~`HlUv zTExC#AXZKIVXTY8E2{VX@n78&sOT^x@R^d!$0Mdslz$e)-*S^|B?t`tI3gubL%Yon z6U(x%8O3SM94$Wf;#|)?x??&2` z-e^VonTIOp%|_H@lmyVeZP;4ZN_s+kD-!iPmJ+2S3W)6Ac}0|p%CIc>cFQ!^gf%KL zs!k}qtqRDShoMjL-|mWl!cV$~O_EA5N=o*y_Qx#X;@sh<>7;j{i-MVH1g&_j7H z@6Y;%=^{O9;e#*XUYRKkKb@Vde%iJqwJGFCVaBq4RBK+g4iOqV9uWH^oo1s(0<_NNd#_ zx|*Su*8_R{?)^hG!r7v;UN1f+XspxY2ff~uy5bv-)E`rLJF0GI^oEFx!c8`*D8P4 zJpbj#fsWbjRicR}DxZ4~$Jp0P=< zSSKo!GAVbOj{xG7M&35O8v`ZzHwuG{kUMb7x9X{xqr~fj6nA7~-1}#>eNvf%{inh7 z2N*ezYvwDkptQvsHR8I{*OkdIQtzi^b`Az<9mg?~F^U6Nn z55_&zeH5H&E$tL0IoTV`QRXs%FZw>l#ZdQ7H(2feqWuES?|@;=dB~#Ad0YpHN>1W@ z@<2b$R#?g4eUMmTjRTV%$|aO6r70_dhLO z4qC}m(U;ByxhmgV@8PUXpk4#*8Z6w_uqUPFslS5UmG`Fd#rz6(8o-x*IQ5H%{U0Yo zmlzp?@ix7fzsAri-~l|kE`OXT{Y`cGXaDGz@901M$2IZd7>r69?qbl08iJda1USN? zVl2o#$9RZM2iDfqbvL(WG=}sxYKVW-ah-?|PEM;y#oP9?;*tj^0(ze1mFvJU7fMv` zCr#_Hk(#7|3t<_MV_mgMF6emf-;PAkq?KSu-y+ON41@47$ZiIyAi`l>V@C1{>xP1A zNq$L%9F{7EY!mS#U(&$N=39nbp8oKA=f*J9@VaN~J-LC36wZ4oYN@eFp;lmqOt38I zSB4EpuJP{cNf5>x=qp(N)-gve4$bEdHYMW0n8n4g1E5)l%CNPZUlhYJ7~E=H8f0Xj zYi~AkD?NJs&eYC6arr=n8=pDeO~Ih++eoixbglcMt6u$P%_Bq$YC8=U1{=o=7k0t? z`)yve6_iRY7{h}4%;)K)FCRG%yl$dA?>8vfA?VWsY0Pp~nOKD?;ZalLT3cI{(#3?+ zzsHP!{>ByR&+6#EdiI8&YS>)1BJ(-<50!>3+S-FyZ362eR>?9RdTuI|R{drlpDH{Q z^oqd^ekCZ){|PsOj>en@guVcNkKGY!{vw;m`naGVP$xO^Kbr7pj3DUq056ZAAbo;D zlgrBmhc=GgWL+Mok~Kq!9mKhU_HoJs8mtF*?<~J75KQG8aCO7XdzXogL<|Ew&URw` zzR0~ctq`?Qm5hf2YFgS5aWAe&X1mZco8l6M)lCSQNVCEH1u3Qsc<_vNd< zyBm4u+y?q!dry(st@{CWWS1^t7lzSkx=1X8>_938`%3Pf_5#J9(_9#M8e?allCXo{ z1+q3@lu3$=9NxSXlu&@~W3vY__M01^>5bP;>)YK`(que*kyfQcZ|>761Ofud10-%& ziPz!PU_sPyOJ>KJOYv*p-u(T8l5NKHR21*T_OX}QDIad^5ysaqfMcmURg4SgO4O2X zJ=OMh)JumJ5tVBM&9FvPSJVK5q}mCjHIoO_t`mOTgN5Bbe4BSQJ)CqsBLIIqcuRG_ zb6gV2ZU!CT+I^`GKtzIcgElujoa7Cs&y5l*msImWKMWCfKbEqsKXrv%Y=bAOAE{xN zJj?qY9UgaRi;fduqVEf39R(+6W0#n$F8igMrHJnep|;jDPQV-h-X_Nk@f>zM&W~kg zeQyS#9Yn%auL++62|I;j8XhWENu;IkUyw>t-;33xYTvZpK5Dwn6mwUhHcg_EGgpA% z(ge&rLI|n^6rFqJAX~OO^_0x`77v$z(+jPno!{ixLZew=3IMq+*E;g4t>XakjZM74 zu&%GLQ=gU950!&SJ*li`PPGx@w{zpioZq`c#g+IMKkr@>1O>g^Z!#(ubkp?WL>i*O%3`&@z_Q#R=-evXz$xc z1JyoaC{;3(h0kZZSQ(yd>_PmG!J|*V0Wi9i)Gm2c8NxeWdY(i~0 z0E^b|?z8(^>b}I;(#!wX9q#{+16>$H%WNouup}R?KT!hoJurHh?k0sPA(}~#@kA4vpUg_tfMP{>vac{yzn-Uo6Xs@R= zZIf!3y3whol`N(BYFp>gBQiXu&@aOdVzit|LOc8#F^_z{D^eM)#->er5P=IX!w9=o zkgC(kM+!bbtOy>mUd_&*zK}B5)ZsdYcbIvZ>y~N8k`MxJS^C@p+lKRtR=LwwGxC5y&ur zUZX?lrG63p`5T$Z*4hsQT8A%vbkOS+b(%V$+=KdqRE(9eU=niE(Y=Z>HhU?1iu(~| zpaoxj?gtS#-FY$Fc?@8*O|FWyak}ZDQpUGbo?dY`0URw^h8Z%|e+Q%EuPT6F)W2SA z^$OEgb~frmUor4{5MkdV-{8Qgg<@X11xr%oQ;7FV25$<<+(RB1ouhsn{pLF1?rwVh zuu0X?4m-u$vYvG7I9lv-CIPlOy$NUkHi_S{gie|M&|ksL za=;g#P#CN!5M6gYFB(IOve`j*&{$%IEfo6TGNHK)NT=A}*IPQ2X+E2Y3VO+r(K`ML zl=wPGHJHggrMd21yrxbU{aC?ns7H*SSx39MgzoH<1K`JAfSC@X?1OcC9~NpJy?ry- zK)z=MQcY^s(?aE9F3nmT)|SEWf&B1vC|d{FPB4-480~I^mIb<~BGghmooqF(Pm0Qw zo3CiiuG@M8obdVI`jK^0yk_uwJCQ7vPUur{kT-(Jm&Jfo7oVBqPdPnR?$fgMP^XMd zzi-VHuKE_If%jQL>NiJO01?}R&6-dAalEDudJpa0KOa0%&`uKQY5vY4N~>z?kh@OE z2I2YNwFmz><53cDda5>Gh4BPBOszFFgzKGG(;JW`W|nP!jSOxbsox0I=;g*(*9Qu36&@SNgeIygR7_;ik zn|@>F(w?shu)u&zGnPLH7&%G&K(GO)rr&6u7>S<`V>QH3c{C= zFitub)2yAArhuGOad{?It6YV6*>NQGo>QmMmm}JD^l8GqxzAiJ;*-?~x$l1uKcgOV z)w!+ln8d7Z^^Yn?`p%4t#@09$8?97;cCM{rt*tDoi`Wzk?zKLakX!7Wxsfi;eV(dC zj8hm+aw6upW~6fz+d>00j}=jlt;OyOZWTH~@?dKCkVUBp}kOs}~`9Zx=h8qV$#D znh!L`Z}0;tPCO-=j^;q)(YEme8Y$3EJ_VN9E*&6|r`0>FyE*@phTIg0EJJ#iVBB!b zG~lYW31pogrpc|tmG+dSHrUEa`odga^8p$J;L|p-`fG#l3G@#n`oA7aV0-#lN9wdL zBzXAJ`T*5Xo4c78IcAU+^c#eQ5hxz+^$Bfif2?%vUR7xKBq}=JATf99_lDRQ42~qK$=ZpI7VNGa}=i^nVxbhA>hmjCC2tPgfL` zR*E)VS(OO6VtN=Qwg(kkT3s4#SRQ?Rw89|E=(XKMMpn%R2Xlb5Ko-F6@l2c@uHDtk z&?%%GWzCeJ=mX>TnU^O3IVDJFYrbZkoBoD+k5U6UMKGC7t~;u19;3hPXxZ(Cn2qM> zuI$lR894EW)&>?{>Lz}zP*iea2r^ast{WBE;d}^}N4Ov;xLzW;5PsTlC`boBS5kbC zWNbINdh4x`q-=h9Ff2gdqU))f7Odd4nT$ggpjDHHTomvA7n_v*XR!N6Y4@-4PRBjO zDSYl~{D~lq1KgimC`-KCllme{0T-Ak+OX`diA&;Cx7@rEF%E9I5j5DMN)J5aNnlx5 z7a2hPjzzWBu&BBen(Ee@o%fJknbG*O>NgK?*3a!cjJuG>9&LJEfE;V;#HipIz1ez>E*3I2rkK_(zf@jpAzt#0FK(s^>|7boTP} z-+i@DO&pR0hSLF@NZ_(@-;a?lmIIxzX+k#CE-l7wJ`z%K|FUo+SY~)YhjzZ;CLL z6aCmAGu;t?{ZXyhSfTuLMPye_Eu0Tz4AR~Qr0MCYluAYw?`OKN3<;%wwTP~}-!33Z zaoo&y`IDW)DGS;hD!i6lPN$`o{;ZtqZ|mZ}y9NKwAAvYKMB6SY06x!$0p6oORsy`% z=yAjxBj|W#)Hq4r)71xS-d|O8Gqx=YEOG6^8*p@6) zZnBAdngC3LP+&BOF&%m7rmC}CoZ&#HwLGMqf$OW=0Ny9nh^Io4gCho*_s;}@gEYwyyOGu6u{kW^c~2ja{c z>eg6S8_Aa0KP5I^R*rh1NLum#QTN_aO>W!zFbWD-Kt!a2Ql&fl}#?Qy0d z3E;tG&WUD3>pxIxsEjxSVcXMr#@f(;)rO}J1ab9|wx7mvpLRZcd>)xRnMTwsaAqN4 zWL?_AeIS{_!(B~Nx_+kFYe2nVH7q%4T?R3nvioK(%Mt6`*I+y%I7S8IOlR6)7)9=5AaZoDi|tW{na*-|uB3Wq8b%p||}{8}k3P4$xn3&`Ha% zmWp;XxQEVZduE_8S!mctGLolfVtp;1E{^a#_3GPmQ#K`x!TGNvy6#UeCZ6Hi$c{mE zC)+VJ$TZ(u0Q21G+uFXjS$Sq_7zyvYD4K4C$Oq9)k3^om40+2lx8Y`$Fwhg{d+gbo z*qRM0QD86)wOPt>&{$3L^%b7&r$MZiBivd zzJ<4y^$+N!?fM>K$FT~~$~hCf4c_Fv5p+-a!cq*&{s$SZb#-H13N6x&gG=u7_0!k; z6mvBj4BhbA2i7M{AEqnqZU=Cxlr}%^t-k3;jNSi^!H=aOF!Y#cNMp!4Ua`I^epCzN zFcZ*qd32fOPWyeL1EPscbeUi746V%9&#aANeU12{`JUdXv-lvTjJo3JPuXg z;I5?&t%;)iV=X}`{4KB6?ce*+9cG;|8OT3ovtx-=qfo8l8}^bCY?-eu@20#Lkjq>; zM#@@Aa;{N*d(8%!(jjcXbtZhCg_J2)jM7~3{Whf`Y>h{~hL*L<*m z&nEpMVed1Z^-|U2Oq1-?4j$`P@^d~b*PiS^<<^~2Uaa%~=3Vsac0Xis-FxoJh7s}nS9Q)RHo#niC8$W-L!Qv!p_fY&QwS70g)3ppid4`(TO)u`d zjNP*As~q9!J=E~jB>B7b{5gew=G(dk?ym$UT=w2HG&5BmX4gVSVo0U<=|@LbH1xig z8eiEs^*T-w!Zw>;;lbZ@*c-%?gQg(w#~kju7l$t5?wT1S`a<+=?;eu)*MBP;vjpnKZoNAn!_(x<6j`xzpC5q}r zahSCqG(QOP@ayf{tLKuX(}Pov%Dz3O4IU@$=w48F+p68%Mlt=PrrR%vxGK9p8mmwb z!v?0~S;K0z|H&NMZ$8^!J%)b>iv8m^mtP~vnPbo^P;mY9k!MLkaf(D)DAu7(Z@9j$ zIat4{p~I^~g#ONrG&(V)tF-<4M$K+1GjZ)w@Ecj)VJ{ z%tmm>Sn@Ilb8WOaz)aU#O-pvAce}-sP<&Uzbnb z`A8e^dMRO9D@;yQrd;d9O=usv$i;-T8(e1A`>aimUc$TXA%~@h;cFalkjnuN2$1BM z&q|wo7D_h)O&FqgzEs0*QZ(z-c~!JOf@##AGfa$KfS&rZW|8m3U5>)3Oy7HIR|NWe zIhtNda`sco9o|%1)f^&c$6GA|+zPozYT-S);DYsip)kjNMYc<(mz;H-QpL&UMmJZV zgy}1(cb-<1f8Now5l$nylKNF<=W(d^Zt~U1#9BtkAl?l9ozrZ*jQ9KDNoT)yc5{l2 zjni{pi0QJ_DzRDN_JAU6cYn})J^q+D$srp90Fg;_k7)8RjAiKa=S&`BMhX%+gm0aj zn|wNMeUz&}20eFdbQ;+DXPWAxm$9Z_KRaB>bg3n@Hs5rN&E|Vx$jq;+> zqb~s>V%gDbZt|)epH}5c2Z9Xqp4^qCzxMn#eY}HlR1KMSOnV32(!~)4ce6Kt6L>4r zTZVxop?o#^oE4D!o zSaLfl_?cayXG*o=zVTwjHy%bJf)rWI_j{2{IwSQUfNj~2(7a_ow}*>e3ndxtIF46y zwRN|5>9bfUc2^sXCm+`)P!*KUGFz-{9oul#tT_xMIkfEe z6H&RFpj4U-+uZdV&M=vk_(%2Bzrn%gA4iw}95<)};6*6CGOlyDLb4oXC*M$8(a*Ih z|AU~G?WyeYrWcWaNksePx+@^K480JDA#U-yw(SF|7hHG0GNn#|j@hCmdwWPuQimI8 z!-Y3Bpbgga)&R>Bi-J_tjnE$i(2bW;^m*nA)`ZWNVsFju(x8GE3;73G$;#%G53F)q zVOP5FmC}`u;;V1ZQiw+lMPK=JhN7p3?5}WCNbTd9;}<3K*Rnxa^n#gO?@VM{zRQ&$ zE~feR3$9Z?2*{bH;UkXK4oWw%OJ_SyAGGjwSuDf4-AvsqKjWBb}(28r=T(kh`@ao5wqe&OaI6Yy|EE`-4Ps0Apv zW?p8#-q*q>p(-dW$sp!E)RcM7s5|0y_&>&!%4~Rj5)3t6G z=fC7s=wuu!7_Y_?ed=HjKBT|tu>b&qky7!}LqADz zz~3a87yu$HV({hrrNWFCx&K!ZXf0dKdQs-QD-`qC_$dyl`#frd}Mc z?Mf!Unzq~8rre)yB7gCMp)O;{{UTnvc6591iRp;>#tB&}RY%2$WVk&wOTUBqi%B#oIYQfi)XBN2Fztxd24T7A`BTP57S$N^$y*^KMq;NFl7X7-Vl)UbRHnu z&$*Ro#LE4VPABWa%Tpzu$>$W!N`Tz`9edy8}?eVwhb!u{&315aMY9KZAK1oA%nln*>1P?jy_y; zG7Yv7!hBoyB^2Tp30fER?3iG-F!Hi&r zC2m-d75%(@w$)(#{&E7=6~XXu{c7VW)O^@&C{OL3ox)KS6+kaKUU z?h&eE*)QqybHN@Z<^41!xl>&q&tm#68u@6k7uw65EeEGGnkl}CC{1iP1!o3~%R2iJ zI^ca<4st6f&L))fJF+3J?Bnrc*?q}cV(pxPX-MlxJTI&>VmfE+<1R2(pFh2Rs;N0U z9%xK-Pft$B;Z{~`j|h_-vUW534zv*iQ7YwObJ8boG z$J-x8Sa&^T(j=W>%#K$|GIR?|fSxU#hRg{*?0xn(Z2-s}*x(bW@yuRNGB{-dV>*ou z@3T7zO7wE%id;?%DVweI_JiP{xCE&zn&wqPio?io98( z&*V2BML+b?Wr4T!ajyE{x7fx97|k-t>f&h!u)Z_pnFdPiOayOmFtsn;O{L+ycWZPh z?gXzJFvAXFtErM#U{n)$OYkB?FJi|3G1MGyx4rGzD(Dz$$mZG&y?pN;9YG0AoXYw| z?f?uiF7M}PXYL+WP(a`7_aef7scQf4rtZJS-QcGBfE{@+*Sr$)Ta0o9_Nsde!K`;k z-ER)kvNJ9#A4@x9KuCBRt`IeWIbI!ai_tmi;uGKeyqDP`5RxZIs`cPb|M*H%$!XY{ zXz}*k_j}(@WUnr>SUBI(ZoA#yf8fJM{dB`q9D;Bh)O^^#a(`^~MKC$(@+vV{2nMh> z)^3$;SH$-%rZ>1jA^i+tjTM&-!JY#1qob0+GRkullTT|kcZe)}rL?{kt{pIKX7kO| z`}eB4?$-&@R%2n_65p%OOqiCAo#;(QahduZN`^G`Ajsal%9_G17HI`B*Qr z;id(Rm=Ch9up3`31)u4ki(_$keolpNQjF22fR52C6#S5rTsv1MMZ(OJ;*?o-d*`P4 z*mi9&qb3J$R*dp;6f1qA5xuIJ1XjAPp*iS?W{-E?IzW${KIejw;ZJrMMW&S%8?W=_ zj~W+=x*mi~1r9_0qBCmF{FAj>FtZ6slD4CJ%_Ta1fCw*wl2;3nScNHkvwB9WX>ree z`$&$_TwK_V;577|G^?%J&P@S6Cbf<0N-dX(myCju(f~C8%85v;D84smZn|;vp1M#_ z1zM7%zuzZLUBlvefxuNo%7{Vqaw^PvVtZat7rz!IB3(Dj&{nS!_m&1G%W(HKD z`p!7}E3rN>6iM!QZcDUAVk_-HnL*s6H+9Jt_nhPDUTxI9DzQ^|-U)~>hqXClIC01! zq*8+LK^4C9NS{|; zc@D-VX2zx$tgp+l`Nn>HRz^suttDVkLiTs=6aQZi_g`g@|EvL5WSS;-o4IGPl$HNs zPQNt3_|4G8b)oy9atb)OpZ*jy!p}3Uqm`X`Lr0ioTlva=%wWCQgSh*RR@_0w{j!YyAUv}v% z-_6K{OH=eMYOjeL{2Bv)F4L+ecJQhWdKBH@M5&pjrVC81QOdnfww~R^F7ReQUPTHTF@_V2blB5?wfTDe( zujo)S-Z-~h*(4mv)ZQ;5O2^ddcy%|^i(byv$(646Ms-y#Ywr27yr;4^0PV~z9b6Wg ztQ9yS7m(Q;*vow<{K=N95*IOw)zX=Tv$M@@%^X)n<`;w>eS5{%O^5GenkwDS7T=sW z;s1a3nG2uLkUS^CZIIp*)|fbCM2ckTpoFGW35PVkB7TJ~Ht z%|c?KYdiNaJo3Q<;^alu5<)udf{Ago@%AjwyagGfTqMAdtL6f6)N`^Z5)^p~)PHh2 zBkf8znQCg+9*|2zxRHw5pxY#D`RL(mbV2Aj*9=uF8=lZ z{+XVsj2kM01$+3(^K5V5+%xrsC+F`1|kfZ7BK$jiGjavXh zzz5t*^v(Ep3WZP}wIuR>u+&!4iDIh9`@}Pgrj`VRrw8Ta6471Wnx`$gZ)VahDjQnn z3k5H#Ed*FQKZ z)g0riceJaQ60`z9r<=<8k%6qamjZwoK|5~Q!$I^8(8eMs1q8EtK0gk)3Jmt<3jTTc z?8O>jQh--u7KP2;1mrjyoIViaT&NFMj^9Vyfja=(3>}D@3zqK(0U-6+2S4fNzn zRsft5+TJs$AM!)>4}wnMM+dwsH+s)>`%f9fUm}67v$1@T;!Az42(1_OA~;tABrM^n z(AFaM)4a`=!6oxO1pdhw$ojFE@DGBC3U+&j!$YD?QHg-ukAP?}Gr}bO!{VKF>a=Q0 zKaoUB_D?Q#)^^ug{jmB?rE4zOelv|d6ZBCumK-^4%x83#8&Qf*c*9bj|Fazik;J>=A1a{KMGuaVIQx7oTs_N7^|Oy|7_0EG z4oS-X_rS3Ljng%$S;h##_GsclHkAZr0#kVYq6=hutuFYY=4IW7-}*@&D#y29#xow} zRmuV7DT&x;JG5Y!bJ;cO}pyK;?rIA);{3(-1ptXL7Z4gH&V;|s>dBN5p> zi~W(Dn82RlDF7k+Fbi;5PoR-s>KX;(__c~xhFrql`lY!HglvBR-=EyDE$;d-(%j9!4e!R=iYv85_w6gS$1%U=~csgDVY#KvN`P>d4BP3ZdiesR8v z#KP7Lu;F{z8 z{%MKP5Y25Z9!O}o@C6_-1mA`AsQ{BXC(?kr0xOm6i~kN!;4f9o|4@v?7NWHxi3b*Z z(5CS9PoDB)Ps`rlX=sXsJ`DfD8y8d=ZtxU!N`DN+SRgl-BVg~81olAoJD|O~_f9g0 z-dET`8y#t(Qu~p<%xbpE`@e!@SS7q${3)O?H-x)-P&v-wfgf-KRB%bN*P$-<%}YNB zg5?g{Dh8iy{!P%)nrwKsDT1*-E@ErU5($%+qGizjg|~zTAPw+Rg z9$8rC@tT}ihK;zbSIv>e4Q*y67t|)4znDD1wSjvAr30=gj^KeLyu;|yNU}QQc0s!M zeCY|?och%l8J5D`GiJ?fahz$>sKaul*f^kKei(fZ|7-)2X8t&Cx}_2sc@uS&Zrm(l zF>h~O2VJT%f6D@GB z3rE?{TD~^dCt8OoNR59vcfsf-nrRWd<3bW6m}{!7un-x;%Berm>03R(!ss_}=FW zY<8asDT;gG~}hkgv3{;p$u9#{1j3>sTTch?~LT$XIth-a*Yif(yq-(ywUkpU&ESP$MfcrzQ1i#x=hu8`*Z!c>Qhj_8p(D?l~xPx=8<|;a^TE zgbN5#rupNQ$wJIR#?x~PGj`_Iqn;+n`slG(J|_e%1D}Gu_VL&k-8Iea>QIEF)l1u` zXOY`i@^zUYGu5}lXbITl*f_c8zIAQ4MWefa4tm|+xM}Wy#F=D)>o0@1#bS)m(QB~OLX1+@ z)4jFVc6i$lNqsXHP!C}m#RYo_%k7uGCU-FI8w}%BzPR8j-x*b5B*B@?$wwm& z>TF!L6&roMgO2x0dcI-u*&^cXXxtd1-2Dm*5rzH2FU}>+iLo|(W3=>BYTc2bGzv5* zkjgG$x$&@C(>qG8nzHh1@(0@{sM0{1OO{Z$rZDt5#6+_tLWQ29GdQd!bNtm*;1|@M zN=Z;IO)uf&7Py_ApdA`PrmYj2d-7?M{6X(M_Vz!eWk>+6(%b`v3Bcb(N8q}tqo=|M zFpdM3gKRBW3&b;$kDPq?>zWb5;{R+~Va-Ki7Hw9g6?kpazmTLs~9=@Pq}Cf3Lf89UZBu?8zhRb3UF1$TZIx6w4tV)3qu( z_*lw#(wu=!$r->EV(zp4CdVK4Y<+a?FuKRxF)yGO0o1tXq@Gd?|5Fbv&+zX6BBVsDPnD{pT8Xc8fBj6ERiR|3KOYV*p7cYh9Fxd z+>qLr=-8=G89$a{712ojSrtdY2IXL@)flg{Y8Ut_!e+J#*0m2a2m2Hq1>!V8hwR6I z24dVI7K8&PYM!b~;B!W~cVPP&*^|i&CLfq_Cd`Md_*JQU!h^rHe)2T~FegTEd`m8> zl@dda;Xz}7JUQFNmRC-{wn03PPDO?L@&+#Q%Bx;cQp)=zH|q$gyeE;3z;LYST2R&m zKubxB3NM>|wjvzHYhLCc!oyegQaNE=?ro=$XbhY~G81bCE8hJ1HY;!NhCBWI%#1|0 z&B$#B<)n`%0?kN8yJ5ALV)}tp-ci4h2LI2xp}&(r0ZXqB@>-4N-=v1*gAT$;E4jNT z;wCr%+1o4ymEyPkM(eJsraG@x_HLPEM%Nu)izae=NcNS5xNi|i3kMakH@kb2Lb2nk z9?7a0j&xUt+M&mFDo$w%Dn$D)^%Aw>btGK0GrH^2Xf{@`Euyp?;R0Lq1p8$21V;}y)&eJEx76Ymo1^}?O z6I}!wlR$adz#=U1E&kt@jtalGX>O{W^*(`NBAKz=E!n`va@53%+yl)p@Atze!9Jne z$KSI+o8-;Av;|)LznpO2LSRP;pujz9Qlba8xYbfS1McM*qlKVAzSlTI4PET!rQ zLi6vXD=vLzmof6tT$P_gZMuyZ=TNNPVN+BNbM~(G4qF}SN}xu4({*5y9!=8!Rb&1l z_nGIP%lJR$)lqHGGns}1W1<&cj4f){w?Npjk=N0b)=x2=F1`iH7d}VNm$Eaw`TpF7 zrBIA(li0?=x`RA8#+8i1;vSx-LSJ32fPEuZ1tkqY$@)f6UUMh|01XU6CHvEME2H808Ebm zRsj}=ckDToj4W^v5m{Gmg3B8;YQx!@zMFG1ZdNpvVu*Dy+werd|G@<#&7Aev$zqiKLfd;5=s=8I|eG*w7 z4_y|{d1q2L81IM(gi&4;pke}KU08d1D3QC+AtWee5*^+zUbtGBRbdmv#m_lbM_;?bwVkmK+u~NKmZ`m9+_|a&&&gDq`Zxq6#VG~LhQYIU=)i175*?#{CrTi;e%fBXm z|MmjCEQu}k%A-3TPZWVu`{LR&3ZENY^7Q0Ma4Epr(z$LLAlwgv5o+|>C}w`i#(O4t zymUtwANAea(2CBRy=ejB4Q)%sEAx3mS*R0mwPb6Dy zi1bk#N4&*PJbDNGH+8%j&?fV4$geQoI6i-WW_e`2&Ru?6^btM5TA`M>)-i2z@Qf2% zPA6AL7GQO7?EXwxx?}5W%x9W>0h@d}fm@zccD|$Ktbkbxdd)=Hsv5%>B1(B?&X%O9 zGQB1HO_{1GemG>=*KOPU%Z8wyRTSz?n&_?s4tjqk+R8_cl*Q1tszzp+z^5}DjXDGx zYAzOPAH=R3vT60QJ*73$d_Xc4xO~rrmh>`x0A}>ntFJNd!~&}?VLA9a4Vh7exEymU zUXaGIX& za@H;`zknA>uQl1E&i&~TV;#L*QHFqx*8W;Hz$FLVn0Ph?*NyWUP9~ZwOncsEMbM4CMt(UL2A2V@N0?w4_B z(qJk623=S7$x}K%xvghsHg%Q9rp*UOojQvEHmLST!v?qYxF0cf1PbA@c1M-EjXd#u``oI?(LEX&HG6t{@+ zpP6|$Ow3yCpc}Oy23YBF-i%|#HZsFVOTV{*8)*RTHK4&HCN<}Jy)tlJa-B)xXWrWf z#w27f;>}@8F8Th&_X>|3lVIN;{veP;_^1yNQjLM(CJUwjXdv-8x5 z1w(1IG2cet6a7-;D1*S6>Q`;6a}Nm=*Z1GQ7k||Q7~V#4Pu?~cUMvTEoAtxbsiqk` z2?JR8|L3Z?zZ1`f;DA~k=zv+uepCr1#WDFPiyr!>vGP(+Uw=Uc>D+buFMyMp1o-AV z;*OA5g7I*ygn!S@(-X;;%NcJ;8FZD2Ao>@8y0Ek8%pJX^T-B7CHztHk>N{i%jpJHQ z3{*T^D6Kj(dbK^MHu8XNIlN;o)tayeQr>_|$);DG;X zo!B!L{Ow$42|`ZsV!KNv}=o6EpM25B5K*oHw$pkJ694dX@Hb zpq%QL<+8$olg{iE-$_uMjp^7!$1n?)22Y>i$L7jVaT5q&zq^d^sa1J+#KBGVDi z5ES;tj+jzG`@mK}uEx`}l+2iLypD5MGH^DPY4OXhi+0eepLAKu0PF@d#s{07zH{O6 zlK3^XVr(~C&9jh+e7;iFkrhfFac#2b?=!9teF>t zcg_7lz-|D{DeOer1I|QU)~9lKvE-ArJy$6}_?fcvO!io+U1$*bGp<=w_QS=XEl3DInfTg#liBV=Eo|5)`U34uWYH*jMCt{qG;Fr0_? z0K&BaOEqT8(i!Dc^bvT=6{q$*10iH#6H~=c`_g5)NUGYP5H|SC!7C{{vDPll7j0b7 zTDG3XIQFGl$;3=fE9mmeG7{E|r@fGi_e)7|pV6YpFm{+QoXZo|H_tsJCti=rL1sQ+ zl)ljzg=*itZYp0>_L%rC;!@2$y`=KCH7cJU1i013OrZbf(gzcRZXujm#ytkEA1zPl z@ND$4-e$^Pr9`ZELdfy@B9T~d9+t9y!3$SD%G**~YQ9l51I;oC;Xj!Vp zcD|gEl)Cax4Ba?+(<{c|u9DvqZgnTY;3(xOz=iau5~A3|XA8M7U@!#&?v2uljd(@$ zR2Fp!nBko&{cpgARQ~QzdW_dY+(0xY9xdft&PI+bI^fAciS1f0=^v?ub+3cudKJ|C z0N^(fs@4m^BueW}`XbgMSw_*DYL&usGv;Qc^A3t^j*hwwnrdN$it<i{gQ~!t37sgjEuAlhF!pTxWKVB@pB@d>epY z9RWw*@Gkk8@O0F~z+5Ntki#gi#tONSE=Nf3O3rj!=9b$cm4AbMa;{Eo$QqB2!`+&hDnmg?LRT9*xK~4U3fW50B+r0LOFhiN4cimxOsLIFt9-&f2 z^H&KnQ^P!sk%*`zvUgjETp$MWN`A{uX)_wd&9ExlHiw_F%rj@_2&Sn}dfbkEL&EZQ z+udgWyVVEJHL)7yPeF)BIoa0<`%T zSSS*o*S5Nd1{%NYKL`?GJE4WJF>!0NO8mX}6Z9#<%kl?7xFtRhHWyrA(>(Q?M5r!%e~H|%Fc1hH)SlzR4?8*7tI*j3CYb; zL8oI05jXv{8^=J0p+Z~k*UdNMy^r0iimwVKFr>t*esKze1Hi_ULV!&=NVa8Q+$6`o zn2c+O`LLert;E;6@+hxW7IA7f&rvZEQu)W=jpybUuu3v5-P$?e0A>$QBB(HaOZ zN7FGeFKRN!j>N*thJjfGz?Gi4Gg?%l_Jb0CIIsH?;XCPP!7WTV=*dJJwgNUNB?n3X z3-5Sd9^y7JFKFSI z_w5!_nX}rSj2@Oo^URvIznj@G_L*)!49}xb_i^1+P%!9XeC@qKD_E+-We9rSUhMtGCJc*X?Orbb7+})McS?t{D{nC$5;edQZjeIBI-VNy|wr(5Tx_Ao1M_t)8ubVu8MlCS8W!A$1BE$qrl? zXUwqP*s$7`Kgxc;>SKK|--SOLMmOLjE~L}7T(bT-BF~G6&dT=OT}!@CQ$a6k)EHjB zvkQD2^;+5rm+7R5UKvQsUiGi_cJ_F|X9-82s?!*$S6i@$P|dz3DhYe(D>CIS6=j=0 z#K$nuagO)7=+{lDVdN>(>!E*E zKgU3CC;L172BhTS##tIN8&3)Tf?gPP2YS0?!5e;N8SP`gIk}Ys5Nt0n1j+BafgQ-h z664(<#`QJmi7yUu^EhP<-KN~hiaRW`_!Mpxm_(%Sl z5WuUgk6e0vW7SW>IKYMX@_@0}O$oKqJNaoe?1>0TZ4E2!=4A&SQ@szNX#s^=rj*hp0Cvl8$Bkw80L?5+n87g}7p|_cDQx}_ z*_3^d@t#-oyjATqhtS&=;UAdMDZqQcZ?-^VRB$G2_SpLVxO<{wK( z+|P8@W2kLcVFgo@icoc$A3njtY_XaE%^YuRhi*CYz8aNT*eR4Q89*E<79)O>rEbUA zqVoBl8zR4fVSlsQ{}CsDsW|@qFR_n+Gow@wunRa-C2NuOj%FNd3JqiVbxM}h6Zx5e zeb?e{RDF9p_kE4$?dQACgC4#(3Vj*Nct3P*bpEK}opD8PdpfAZlI<8b8K^~9&Le_8F8;yu@y{g zZu(d-wkqmfc&B6*&CLvGL(&0*!nPTb+1NL0n*AwY4oP%_xnsCeevAGyVv}&1f+!;^ zrb4=&N*bc;nuLf3?lTrNc^a_Qkvrf4@uYa495eIJ?D6VjdODkPV^P;j;s~A0Lbt-& zUW~!l$Xbev<`;}2O-uuOjg#Ja0$+iv-6K42&P*u4fVV9*)gn%IQ{}vBwZzzd4l9*U zS0&cZu@svthuMNaW`}ZQeTYQ#k1z19nbhl9O5V~@jJS0WsdQcw$YVg_!07?mOWRL) zx(M1aJ;4ws5vPn(L+Xc}-vwQj$+O^hW(!jcdqhJ~7gOilcR}+OJ(V|8JyMFZ2bS!` zq=rr`F|wO6PjKSnTdAa34wL4tXN#|zi&K$^H`Uu*`GbHDe?ls9cDI+{Z?-F!Rd!Yx z%*Ad9-jxbV3y_A=epJ?d6SX|Vq#_e4AEU$~!n%wFaP70g3aCQCP^A(W6qcAUE?b&pkYr9Pg5J8J5MGC^H3R%N(iIBTHkqceE3} zroAJl%5Y=I<39~X^ta{?y&t2CjuG|=Wear%30>~hzq=G?Je=}|s+ds1xoeO!oub-C zOL+eR#(!>9jfvqSp>{;)WGsCiU|siDZC2|Y^6x0fR(9+7>95y$)L*W1W@t3tjaUy? zJI22abX;K|Pmj?gsB~!s^!eD9$RpYQZ_qe)Y7z9aLZKI_P=oNQ0`7Q#IV=W44hc3@ z;R?{;bV)>M!*C~4ph)(4DSu|;P3)5>_Fa?ZxAfG2N*ZyzN%nanF^Y{sm5`(@6i9&K%JnX}a;R;-T-*8W#L%G0oo;_j%%z z`X!8JvJ7PfK64dA%0edo#@khg2PnB+G6q||)6GHG4pK6_=Edl#SD`)&lQl}H5BEfp znI~x@#uuXmz9vGuwz1MFgQ?4zVZSK5)b{MPxLO5sA}5Y_SP@xM|0Y@pm=MEdgv(oJB?E^&|xI26exDpg)4i+wWgj zl^HOwWNZn-i5V4)Y;Fo4^uEg!Q-8_7-r3C0FkkL${nBObU586WrM6-TwC* zV{xTZ`#%Gwp(X%bzng*MJ`MaJpy)IzS_irr{}Sf=?|rjQtBV5Ab$rwHrUKwPQfsFa z1j*`IOGRUM5^X;*RNqahdVU+OUYtc5k%XL3e;9GJzY2;!2|z1gOpL!VObAP8Qd?)Y+|tl^a@ewa)go>z6q-X{y03q! z{h5Y+>)TO=8KYO#gdt2TjN4v}4Iq{6s5<-lDJ0LWEYfqh2mWbNBsHYO&FTISXsF~o zGLyA`pS3IbNXwKcCdhT*TrS1f_l$w1vTC&H248lt|A)FC|Lv3T4TM7)Gv8j=T(FOzIT#Yg0(H7_3rm#w?j5so8S|pI z)V%GM_3nfqcY3}n$BzHUo?T9~&@ zzUv7);L1KjOaNUZ@PC}~%-}l6N-C@p)Vkyc@L;ZYo++OVIS<@>|0nv~YBaWQcHVWe zcR_cwes+ilYH2pv8P!_8f#wyx`@jkLf<+~Tf}|-^hZUs9TXGdb^}r5}2@~g!Ei&5t zhJOM*LGAzrpdr8HuuxT><+D$05ALjw<$`v&SgHJcgobAokEzM3JL!_W+|HN0(ovBh zAbu29<-+dofW3!d+Y5D4#%hhS^)e1v@q4qp!WH2lpI%d_&GB!@a~It%0` z2@%B0RxMIJ{6jLde>t;SX>Z=Nl{!i%7b&vWH-~;r6It)s)Jr(MW*^fVp}`?IN1-%l zB4C{)M%pnGZj(P}=i844AFoFj63igfK87Gxc->4dF5eK8sGmYIZ5 z3=m}#q+m#K?h;E;#C`(?+vZw_Om?E~q%M!0(-{a8<1}p=m}WYuMV*L>i$?hZ9X~OZ zGhhH{4S(^(U^8AEX47o@gW&bhfn;Od+&5Tz&I!Z-&|&;-;rWw)C3#lr4>}6eV;ku@7qjtK%YYD`Pvi##~?$o|LYx*Huy74@TZJ zauQ_A3q4%`+KN{V(;oTi9Tp~feAuB>svZ%ZS5${+H#A1^L_V-v3Ej2Q%T?{AA<2(g zy>m&zqBv#D>1yw&{J!5a&^>bD!~5U&%kB3b>d}Vf&}-Ez3bgEBy!e`0OZIeMpYso4 zsP<1li={p6P#~bZUJwID?r!1VBKt1^+#e6ffdF~ahXGNX^-=WMrJ+6YVi?daKtr%5 z_^C9nGr0l}#_C@>20sWq%$2Hv(N`e5{&n;<^EXpPH$3fi* zCX|(C(!-ZgR(_lHr5qeQb!t{^066DGEMfwUgA;{(T79uf2en4Bhbv{OOyB2TGgW6I z*)tJi$;Aez%Brzpa4k4DbuR+R$PVLd%g0~2xpDwmU%uLy+XL`*)te@oO8Wp^H-rl! zlG8XFk?fTW*Q*_)R{k(SsoCtrv2d1hry=P(=ex?DH<%HSdT!HolLFbmIfT71!x9x3wQy8r`RL+Ll!V*n^L`k2O zv^Mo#S{0R~UGtTlvnc!KK~wtTe~~lrpWm7g2H2nrK&QU|Kq5|tu+{$NqMuWTiwF0D z&qha{16E-0lN&>LiVEYW{Crvqd;hXdzV3=!x&+}hvv;hQp zf5{8b-8f_&EO7^E!iwF?L7+@*$1H-Chj%QK96t;^(6x@b!xB0gpMcWjASt;laHA7K z2L;?*VzVF^#bD-aINKro){s}RNoTIZNwGaIzKub+&V`LyCnV2{K#|S-%Hma517MU8 zlSwTIeD*TG3s!bzhXd}i!+WVJI#2gJX)H3i#fcwioeD7S>&9ckWkw}mVXLuX?>sN%du z!;e<%S}LxDUHKtIuk@*eB!C+J2A1q}06-NQ%@xqWD4=Eb|Hymqs3!OHUlc1UB8mb^ z7X&0U=~5&D(m`sdLZnFt>4X*q1p(>3hTcMv-ieB#g!NCILY#PhoMzQ5VC zXXe~>?p-r`uQPvUEi~o*mgo7jr@eeuF#nsJQSEeltBs`L^d@Bq%~XP)HGkb#kWF+a zJ(zZ6srr@dMj17aIsRxSWa*3?>b~rKDI#XF zl(KXmt^e|`0+7E);@mKo$&{onV7{0)Eya|pN}4lQ;wOi9%P)JM7+j*dNmpuZx|2I( zR|kHx2YamXeK>*^9u?(q?8tP#quM2Q$o`h2C0Wx?^h7W#%SY|KH*ywk#h%4}CI9CI z>Z`>8EjBFxZ4(b-8b}>q%g{n6t@#GHc(~Yxu%7JW7y!2|HORIBBXW)vID!c=2h_Dj?ozGX^K%m~^-^8N-tCj_<}^l*zP@z0R6T{1Xu#9NpFE(RKWNBFEU2HF zHuB|OcS;I7{uzH?%hry9cJDj#0fZRsO|&jp0~20;17`jD)I23N&?Przvkep?sx@FY zFzz?B1z=*-OiXa)PDF{)viXkDMohB5Hy@wNz3R*E=RJ15;_}MAFID$ddg6yLc$5L5 z3Fo^SyRsYn2>+$iaZ)^$aNbuUmBDA$Ie|}wy^jBe{n9xb_FE4Nb6DJs*1$R9ZPXfl z39wl0Y};|c>-BAsUP!*Tc;)q_kU~0fCL=nV1C=bXY#&eSqM@<-S6cM1l)Vy@X??ob zLud0J!mIzGBl_p>3zdcsL5RAfX`)j_m)qxxDR-(7eB|gu*?C@yxPjc#oyrR{1>d4B zNqY(pofakRUgA{AW7nTJWGTHkrA#|-L)-HJy%OX0tx+)Dnc5MW{(%tpgR{&L;f3)5qa_8l4!@Z;ejb^| z)j92hMKB>u1}c*@tvxbp9zBS~8i+p(lYmiPu7k)Q3)n?N&#WCRuEwT$^`dT(P(C}o0%-pRDkpr)oY_b!BPemeG`5iBS4w>+Y!>vX*-*_*C9FgPwjKe`P z0(q(+zk3RQ9P-H<`b^A&k5k_pqoLy8%A81{nd@{ z+WY<)x+Y^(CflcR^!Of} zB=(-6Z>JO9wTwH@t$4BDGUR|M%0ZxteeW)Z)H$_&-ZP+zn~PM;kR{efz}*4>NKzoN zpGJQP;yE@>n4y4~HfnN@?}HW9Tm(E8?vQ7c9-iHma${m(LRO3{eP<^=Ii{pFEG&D~U1)rx?B50=hOc%TDo-4pbl z8JN}Vo}xTD-x-;!s{6*oKsp`lC&{m(3Bl3>zo48WK`6}&EJF4nE@_Jz!yI?K??`Gi zjC~w;8QgU=c!W~r{#ydxH=tyw%Ekc5Y+-vfA-v*e~O_J>~JI1I3sKk9E&sp zES)VCL_l`jMWU_Lpg3 zY}MCvGBC$5Gl%B87g*zG0C~~xPDsCM(uy5+s({!;w8OzMv4R6}j{c3={PdgGIV2Jv z8Lw~@-bnfgWXjf{p<;m4cSwtv0j!U)U<))+2q;H(G#j~lc5PA&msKwGt+`7sloahf zguBJQKgxpauC73_4a3+bY%0L*@yQN?EIv5+-|0m7VDy=4d(e|k3OWYm)4}Xk)oH+* z%`zpuN$dyyk`V2C@C{ffN%YgYKPU<-M57(eMfjdR&hR{UK;e8{G_?0ExNYS==#X|* zlb}aze0!+XSr^rJac#WIw-zpP3_g>r6AP#S<~VxDn%rhH;9sfLX0dNSD8A#|z5{NJ4-C1uHxs{B z*uN~53bx@{?NriQzT;x5g>%j&JETLCj`>^Ldx`6{-J^Z%CnrvwBzfg$?-+Hp289DT z=3bxSg1a<>G}i}n=kD@vHf&%XNw=Eio_RS^_;voo;q!xOxq z*NOMns&@w^CRA9KrQ06J2*bD^X+Nt^5S1#P_l@#8<%(N~Cw42R&;+rBkEA|a z|KwL*dk}x(&EQ3Mej1kVduR)BTrBb3Hi+20M3j9~0m~1f(r-?{?JFF~_=wG97~wvT zgspHq;;!MV@S2O3KwGq|x=2hb<1O+E9dwF1lB=@5%AZ%KY#-VJnzg?00l_iyG7qpg7;N7!E*qmh#Q~l4)l|~*K3T(!4?f2| zO=cIpJhQzc`x6uYa;Fl=L_QCkC4E8Lf190!X9KVcZrLWM5>puGfQ27HA`_e@i*bip z-Y}h<_tpELO;uADF-kmhi7wl!H2O9^w-`j+qTwYQz=Q~V+NA0Uuz34tvTIXEJxBMl z*(6tkK5}Z%>Qf)~U`td0u#|kv&0zB19DsMv@iA z#kH6)8HUNYY_r|1YB#&{zWycoaYr5y-F`Q%v-fbpf*^ao#=pAz^S73vnxC`-?1cav z{Lsb%-d8+muq8??JR-1VxUlKejCvi(O$sIq0pY_%Y5g0F z{+5$|c&?S}^v%dEXz!+eKjU;78Nl(Ch!R2ZJ3pKfN8EHAw~&Z;_Yt7qTG$%XFj3Ha6VD~j?j?9TLu4Nf z1#1HyDL`kQ4%93wqu!ZRu=YdTw%mIn!qmxRS$M7Q;67i-y)m7>Ju`b+u8(I0zA*q2 z^Q*rxQh!xj`!CD0U6kxWgJF=~PPuG0UKs5v+XB1LUZbItNOf^c%=WoD-gIPSTYjNH zY4bwTN>>l7--?Lt#+we9^B!xTQ$e_%`vBwM<*=UH-;+)vD_OILweWTs0_~f54hyd1 z$q941jWO6uFZlD&eoeGWDvGEFGoKq2bt9#$`|q-47H$fhuTL)t3H-!)dDYx^J8=6C zu)7S~|G@6r{|a`03tr_33`LUdgCWG~UJJdY+3up^K9+jdH-<)fY@?54j@{J1#$$;I zgb)P7u`VhE3?7l@y}>4=h^@S6s&Ojo;_N#zQsb6rf49R2>pgXMoiZhhB*<{Iab)EcKScurOO-flX1WrM% zYSP_DznY-S*jnBP0GT60B>T{ z=ww}CQL*?SVOH%C7SvynQuFR*(5)abS-&Dxv~hSQc=Z|z1ix`vlk|F8oJLCQq7$QS zyR&Rp*#qUod2^L3)M75;=jD*>3Ar&mkCohw78A8t+TGkAZ!qhY+4-=8O6dUkAcgmB zG7&hOPXO)^VqmPhM1#r!3_>Mjz+&m}oKe7TO0N(BkXwgb2riU~jg}c3sX@CZp?R z7mRsz)qGYuq+EH&rR?v17I#O-9=1=fk!|w%fwf>(8c>n0;$+X0DgM1Rm<{?ME~`{I z*!^=rqdw3M|D7r=r{I5j`R=2C5fo){f>?(AR3MLo4g|r6rF&8XJH03yl3fPCM&pr^ z5~yca&B-;|;lYl|Z}=kHJ>bM{l&IO-cGVzpa`lrf^J#2OPu1_Eb&boXy!3<$hK9b^u%l>Sqk zyl^N?28RO`NIN$)X%YVn=0={O2jeY87W#fQF(17tY5GCYBMR^0A%E_ml(_KwQ3HOd zt9MF(c&1!fIH6!L<5WypKq1UmC&qy*L?XwDE}}4Dc*53-Bk4=OW9CF?p0Dx&aT!bx?nW|FmqQ0P3Ij_s^a_j2>v#`sT^t2}cM^ooO4#6#z#N9Js_M$C{bhum<-d1?-CyMl2C^u6fe8e@ z!}PN}Szv+cid}%wCaUO47pHRPzMM*=eEzAqv3Yri-}BxIgK6z8!xPRB!pTrz>}wq8ahxem-U16mh}>~)9oT>C2q!}uVsjf&}wEGRA1@@?E*pfQDxy+ z>(9Eqqoz(7xX^+{5#iscNU3udSiwQIvAYPTaMe8f|RN51WJp(>+w#`!(i#j3p6)?1OinQZxkK?by z$D#YX-43TTmH-w(X1(U~>~`w5UF4E2*1z2)H^Fz|66$IfW58G%QexD*xuG{_X@RPg zjwyn{5N}o^R;kciuDZ`;RW|fji46LAmE&Ru)AfV~7BPm&$;X-}ljzxxo4%)z+`9kT zS8Cu}O{Htj;VK!sDRcbBH=o+J8hD#J`0o+f;{PY@4=?mDgL4yu1Av;5#FY&6gW&RRt5w?4>`kHx3w5uT+KzhB=*&a#}f z<$T(Ffu_ou%~@&f09Cgg+4-E*i4P~0()4H2-0YH^Ucom$(=B3uDw{Hr>T|s9^h0}@ z6Pgg>oHx;~$N`|>B>=W@svnMZLEE~lst~UG9DGSl&}^c;hrew2w7}Z!Gu(G=#Jvi1 zK%i^bOJ907K;(a%#zOK*lkI{n zm2zk2rBtE1(t)f<>fV>KcUxHAhH642@b_yRh>1ld8DODyym%#t^35hw_~*kHQ9_WF z_={J4Dcu2CNE1o4;s?b98gTuqeuM9+&?!1>lslLnbtVUuYr&n|Z9Rq6@}8b+*Hb8$ zkGQz&spB+9=YRT7*?;YI1ON=++6H>?&3G742xf|#w~%>%=2~TM*Rd^shkuGYd}~Y8 z0+M}H0Lox99`FrwUl#a+*l~sffF)x9oa8A<5`k|;jd(s>XZf2V$RKmTlrB6&47n`; z3*ka&Ob8U$w?;(MeMS{Q>?yNV<*^v?QJ<7Bc`@RImYvIn&*sUi1$FLxvh>%z8v z?W>4)av6^B551!_A0qBL&_7A$34{QOW$cA$EL@OyLU9yzlRIXkzwy9Xqj3I4XYC*Z zV?~(uoS-(h>lZaN6hYRGy`M;a>}Kp@9Sz0gSS9RsNHHx|K1dZ>oY*7zVzr$i2X~0} z({5NAq0UOoMvq#JBr|!s{Na7?eXQwHb*~VyZ+o!g1c3>&n3nU1;N(a@yIBi_aJN?% zJ#aAUPic&UcI~y5WOaQ$>t-q)I{c|A<_2}&JRP(=qbJjATQ=C-f>?*4=AR8($d-Bi zD8$Up^?FK})Fg}K$v|~kf2)c)^~r{)w&$UGW7I`0dYawqyf^Q@cQ@Zho813XR>Qvl zjA{(85o3V`kOJ&zXXGOB7V-HkblwI4@Rq)`F_D}YNFr=op|n6L9SmT1E?Boin^|C< z-)XB~owf0Y+2IYSoje5jno!4=Yt69fU)sn{Agm?}6C|ffiY*SdzW;48c{<11Say^> z`P1_PiLuPvTPq5;XFEosZC4c7o=7bLS=Eel7WkkhEIwE-*mQoaXCRd=(*uKz7SiQA1D0@rr?X|{xXL+C$aXlnyW}geX3`_hQ+wobwAm6~fN zyIW{&Mz*&By=K;ZJlA$kU=uO9*nv?Q;fDP#v>YU|sMcWYTG)E&z@rzU#5&*8FN%J_ zZ*SCEZT*+^3H|Kd2*V^ScZ|0-Cfjg*YHq5dW>@fIykV{Unr8Hk(hmj|mJ#gJ(Vp4g zN@!RU?okPsotV(2SMjF$eh2<)HkPLTI<2F~QUnW^JNvyDWvm%%1r6DQN4Ifu6VC5# zE&<6ITON`Yt5FXt|J=KB>l^2t%QLc}H$;JXvTrzO;5?X)S6%!jkKbCo7`~|D&QSM- zf7K%5_k=5ur#YPEy@=WFM@hiOd%KQ?9A+O7=D-(%61Up|w2q{JD+_K$Ly^UO19NZ?p{yF(voM=hvAUYHpfA+6wug&I3Fl&skid^H$ zKIwFwqVKBL74s+~*Jk9}@GYX}eLOs&Cnd0jqH&zxaEi%KQS`A=_Dv}%{@{fBpgmd0 zGxEd8wVU8g%VOXPb2diyG%ON(XLj$X6O^DFu+Fch57a1H8pjp8giiAfN#H=y>SbG^ z`ER~_?>i>MbnzASHCLg$xy-@UZ_k#~!$Z?XIo|QJ38QWx$zfruKPUuNvr$|0U|f6C z5q0cdAb9Nug|*QEH+UVuTgHN?(}6syU>6KAn#e^gvX)HoK00FtQ!$9ss4zJ)zkzjK zj$~D?kdFV9u{HW7uZZGhTsGoka{RWBdFE`1f$D9%0t&&(w9m7TibtgafdXuCtwGh9 zUgqLw@Xssz9jRQd_|hkGg|yD2Z|UsxFy^uL!@Th36T@*h~KoEEc+Wm_OK;k@W z{VaVO4#hXW;lG_`y1`6*W(N^(;jn10eXg2(5I2W z=jVN--Ll%#y~{Ql>HBHv+g`P)R&Jknx?3yVJ1VNv=@SQ9CDA#6$3t`b~m!&C_uyTbN$H^(&eUhBcwdi=t@?kTYtL0XR`)imLV zr{^t7=z^aB&liAiO@OeoQhZMm=@ZRlLz)1qS*F#S&Z=oq*`;&Qv4uA-ZIYUiY!kq< zxfmE)zMd+bv{_yp6;v8+LBP~FigHK0`!lOPN*G|JOnkESsx75=6}dI<>^MG5Re2N(Gr*-|Y$Oc2Tw zQ)11=T*9jNJou65Y4;uW0|_()C5)CuB4ddj|4rD#3WC_bI2gs&f3>}=0=96d9oown z^XkAZZPP6`#?#Zu-ASnA4YROqj7~Kuzs~=me)Fts9>gL8Jn*JdDK2x8z zat)RWt>PXxx_8y0CsmV^6?M~|T)fCPM;G+rw=MG*8Xo>nDnf$x5S(~7aQLTke4BV{ zred>t=K*RWb>4ij4!-;zXcz#60~>GfLwG+OQ3xQ_X;R@UU4TZ4@_QjLzQFkC4Ho_} zkt_@T?6ljr-|aZR|2sx^g$~EDi4i&a$91PF__>-xh7LNPy^-{Ke2vcl zE8pwkc;P#81@RNVlZ6lQz+yDO13~oDm~pcYJuDMIomKeWIKga!t`^q8we*g>Ra*=-+6eF}bM>B( z1ZtHB3(jzr&07t?+;kRqSgMP}cj-q`1aW%W@ly2Bsm2(@o9le#N~N=c6QU4_3y<-> zX|f+yw}<0qt8uJ(9x1%I>tftf+iK5J8)Js1q{S1igFBzU5fIwGqju^HuDsAJWwCTVycM)-*fQ` z$$q#O1ye%cX{P|I z8*8=4NPR)*`9qoOEUvUZtT!aVQ#1*(d$LBXs-(04Uz01a*t-h4p%i_W`Ka4M&T!UT zks1SpwB);MJW%}0;Ex3GSB^@5|dV?-?AgZfn-e$M#KB?mfa1Z4zASQs$raa#gDbPqOe(1xeMqOfw= z1=ZQ@8@ZBc#Vu2XSq@V^qe_?6>2EuTjfwUjXSdA{8FCmk>I^neBWABH&XWC9u*^K5^l(KbY1FK zqox&uoXUQ`Yj7%Nm&vLEpj!!XY^jJeX^E0m8W1sL%!N&j z4&!5*5Fru(jAbQ~>H!1h&nz%(b(%|qmNK8GkEJRuI)mcP`Lgx=vlm5gu4JXUcYZHF zfk6VUEp;5O1G_d;wO#X%*#^ z_eehK7o3k(9ze2|{y&gk|C-qT{X+g-+4DQx;@5xs?;%J70YqBrLlS)x2d%hs9(E};KQb_9ji2b;K2@a z*`6S*(YPzW_b{@kzRAZlNl(m4*5T_}Yd>=hq1h|MrRs{`v;_a1N|8@yi^T5g!9gB# z!s$w)C9$*fa`!7l*X_=YrTU{$Si} zQ}S-xi}|(1PjkBK@*DoO==J)S%M-{85H6U37aAI*CFZl!f$pksS1!ta|D-(EAmRS& zV-rgi41LgyPEAs8KpI@A{Y}w^hsnhzz7h+?$5vHcY0+sVTer)Wl9yfd~kmV4q-Uu;rp!9*kyCTB5G>UD3kqTk=`#Iq9a8 zR_ZY;=d8*~{=yPrt8&ll2@=s-RJ;_V?z2?q^X=ydbjT8zUGIW=-04gVB7J1dV*q7k zN2|f>&2sk$d((He#g247h%rc+wfR%Zjr}d^*i1Nyp@+3vtCYD;m z8)m!T?c1FapaQ}oa75BTIKdZBzlymOA=|was1f5Q!VsJg9+*yqtBFy zsTSrm+E6+1OxQ~^r33l;uS*m2?nkTnH@<)OsAl~c{hLj-Vg1-^M+|OCHGm%QTqeys znFcJCRzOb9W@pS(i&t?lI7^+;j9S06MBhLXHst#Uc?hskS?ZGjDO6bI4+`BHt7@?+ zICpzbxg&#Vb~U2m@U|;=f-5K;dz71ygHB zh2zW59(pww-lgc>d4MciOxJ*8m56}tUl0taaMtF?Wmsr0429+7nK{TrjVfo7b#MKk zs6BE6G}u`$N$tSUdLkz=&$EJ9U_dyojTO)n3j=V$V4O~C@1V$%xwF75Ah{_bthD8D2XO*XF(+dDdzivKXh%S9F z>|WA-UcgH24%7FSR+5L}FMFjZXigW;sod*^uQG}Yi4a4LNL{3M(o@3Zw+14tWNu9b zlk;er!^MivY~RNTW6bUIV&PuRbGC&`mv1pgP$pDslD6^nj4H{24W7W+dYPDQmk&d! z6ByQLgoyb95=?x?RnIO&oo^g(9}!8*xErK)Ia!6?kg1#)Fbq%cd`#LRwG)CPDp|n8 z7KV7c^me3gP&MpPzd_@4eOi^_vQE=Q&t#jFNnKOR^Rd_T;&U|kYH?M3o&&CJ_sE+66$5l zDZyo1>$KENdzne48jNo<9WgF3Wu{-=5WdRGP~5QFe6>Gjz4Hio_TKo; zIb40h3+b?VJymhS6rI8Qfn~D4>=ARkJ&3Xqw4;hz{Q$rROD^g(60jX1L3*(aZ^HQy zHG1i<7d}bdGR@LoBH=2Q`E~qzKVVlUE5%QZx$Y&sYIfnC{h6JR0c0m6cwE;qi)=afOLhWa zWSCqPBK8k+!D#e4$4F==+{xN8?5%ai3V%9MhIh>sew$X~$j7Fn`|a@oukz3qMXN6A z(i6XaCayR0hCu*Veqx0rZ-)_6S#Amc!vroU&TAU?l- zT6~aFrPIc$aAsls7Fycl3cECI_{@v#$U<=Dg83K)qc9db_I1NCM(+AXpYr?5~Z+_1MQHQ zmW0!-ANa)k*Seiqj8^XI!A91ZQ$9GlLp4t&(!*#n&tnVqhJ~!mk}VW{ z%b>;i*0rx-4QIk{G+)mbkbYKq58>=yDGvx155QUV+5R8jJ9zXGo(n3?EX#GKfq(=gAjV?bZ zfb=SOlq+f-T@Li>bMVPPh)s?|j;*jpuA}qIn~;R}Av9KZ0wHH%l~n~a6Ad&1&|$an zu@pWP?eCX`ua-A7rLELPxHywK%9PHX1F5i-m$JUrl8>xxC!BD+BwhprBa2`A=+?ko zGuw(t6TRqexGDQ~HjvNG68k~<%tc+!7#RZyE5+F-SIb#3MzNX>H^u{Nf?UTXdC%+2 zUiaB?6+H(G!)q0=Wp7E;55-8X!ERFBz)z0hL+a!Byj^T-0{wkbGuNOr<7U zK^LhoH@G18JfuEHn?JdV9C7~-GFyLZL$Qb)Fj43i06uD%C^l2RIlQC!6M)|i0;(*w zuAlP(7A_0*yAc&+0kN!e6dUnYx|_|fdH=y5$AK$nIUV&W@n@t@XeOo3A9iAa=lU6& z1Jr&y({p%6X7Ft!zNc?zZR}@!0d<8tlIT02?QfA4y+2i@k-EL^PnN-#0O`G~qBfTD>WzJ*ee|$*8Qx-p|W7vrlkfxU_x|Dlar` zds4EZai2NkOq3!-kzeGLXJ02XGshU_kP9#co4!G00VP2 z8OCZkN@^?ZLYg@ENZ*ro)?1jH9?8JItCI~8(Ks_5LZ2sIBy7}43?=J90iI}dpOk(T zDf64X>ko_a&wEJ>U*(eK$>6|00DOpFgB{kS^U{OgXerQp-Mv7H6S%s2rxyP8&e4Lo z&*cFH{m$gLceq()tV4d&CQp^HHG&Fg(jv*$wTn+ecS3> z=`)(2%B|Qwc<|5#MY|WniUOxC1Bw?-lvdKb);_h451gFu_~gB7qvp@=_%u|=Lmmy4 zgYEYr5EcRB;&4ovIGE@CXVZ3H32h|W&40gU<^jC|{p8%JsJ~WEd}_E*RID@PizHdU z4gexI5eZ@nxGt5t@d|-~uqx{&`vSe5mg`DEJ4V%iPEr1^w>Exwn2nU$2?#!7z}&wQoEw z=47@Jb(1>`Z$jNvd@Y0XqK-zv7pa^iK-utC61o>O3IAA$S`Pzle~q3#f_g*0^SK@5 zMYeAcga&hrNm=992||Dz#C6wPWC<(4k+ZJhZInHkZhhrR0$TS4YY&|&TmaBy!GSYP zay9infQffYqrY$_rA$rxgn2`8!eSiv!C3c_PS7{--@QW{i4%}W8+|Y$pPM6>T2;sl zAB3e6&9R4za>Ug^#-f<;5{^5QZ!Y$|F`p8bwQhPO{^-O*|D}o+*)n&Ih|3m}>aR|+ z8h)T5eFe<5!4JuBvLP9=zKLa%Bimp~HZGO7Pj#yn`O&prJL0pu7&^WG+y{Wb_gR?K z!v_o{4z`}+0yZ`!w!||QaI;QoRw)v6=VM+aKMc6&ZZQ1!AFVw2e#WM&cQoi=%jsQh zhw7(h&(FgHG%S7f)_R*1ZHSrr$k{|Ih&*>_YbVY+9U2EVCBJzTB`y!rCyt zjj4h1PZOr-!|n;vbn$SPDz@mD6*~n`Hhh}#-@H3<_E=fB@Nygjs~pR-7g!q|Vs?|i zkiE=h9%mnmv^Cqy0ynUU{AWKQjwPqxV|{qS4u0KZ=0Giz=Qm^EAHSsGrGJ3e{_OVW z4AP9z_ zZK9E!`45Ve>pv(sZ~UOhs4++!=rqA2lEtDG2c;|H4^lE6?yQhA`v=$FT#Nr66OaS4 zmszS#sD!WHgoD5eGq8PgJR-9`mIvBJH(YV2=0VMZ% zp?F{_W_3+dUVfIXui7GbnsTmvSWW=OAhh1{IQNP@MEWI!6)f1^>PxSH*h$bPBI%sS zkm*!D?Xq(KKWqZVRY0(8iKf+wC}}aiSc%WA_oh<59aI$+iTTpjcyc4Wz6~vh#-r2E zTI|X!RrnIj2$cA3d^My7FE!c#z6HbRhiD+RC>6rYkkd^sM@t^ts4hK|>{{30;B`qU zWQG_4QC}#)Tf`VsfITA?t)f8iiD%Y_el}gvn_W~okFv7WNBwnJH@PJ<`7WVyvDy zE%Mx^ev0LjtY>Pus`M}#(JiMz(KG4CY>wM|$|)}F0MSoU)HpmJ@XOW>vISKi84N`c zDJe;Xz?ZN+$O$0&f=LA{hfF^x^1=vkvgx8&(6_}seYO>THhg^SQR+GrI}dn~V-vsl zHIY`_GO9@%E<~A%jaDw))5nV$2mH!CIv;J9UIB9(kE_scb~<>^+J8ix=jP^HkDhMx z^~{^Vh}|waaU!s2Pz0zr4oAE`P+{aAkmg4!^O^{_=eUluVosk8xG+p@?>}a|mmbZK zva+MO#$`<1JrjoGgvbJ#TPY@D)atO%8rgG7HWQ2BG@rGfx@gZa!_(4{GAdZy+6r6B z%yL@iP@&z?qltZ1GV@|o8OX?!sn$L}F^DBDD9!>Z;JyIj^Sz)BE+DX~zDq{J<(n7cDh2|-Owp;hs z#SP{-#j}qOSp~0#$X)IP4WhV#G1EX#Dn$Xr_KJ1L?;?2YL&#lf_JTn|2dg_qglUnib&tlnxi1>p=)h6w&N<+WvIRW-}XRKrF9NA|ym?8Tq zpf{w-9~3NZ!a#770^31ID4pHaKj9kl0THXo9zutUobZp(Vsgol)2!UD6Ef_+zy-9A zs8)_>ibRY2dj5HD`;Ur*KimL+^2>jp>*)7q*gr{PdAOJk$44&)<^!<+$jJ7(LB^8R zBKV+`D-H#cR7u)uA%yg^(Tj) zGb>9rT}qzLz5y-q!x}rdku7SL4lGAHMrmhmuu%-p%w8rM;pu2Uv(V-GcP+81zCF+-}&| z27ZhEl*?;1$sH4*DOg5+&H+qzS@w8~y4A9WP52{J{O*j;TA|EF2}4U;+!@sK9!wTCY;>*}AD4&&wz? z?MGa-0OI}$`xSGzZ4_TXVuo(*{ z_9O+qKIahG`I;09e5{A0X1w=L-My%68};CJ26dK^9xTK~dCMtkzcq9}VO}_?@U4Yy zNNtk-yIc!CC1?(c5G!4@h!DR5P*THf2n;-BHa49!>iy8A(0({WDABmZ!HXz366(Ut ze%k4wq1mfohL6|IRlkCBFExw+2_-)$#CEk@3|Z8-(Kx$6S7)O7nfkTWll`)*$Zcjwh!X;z zWDnkn(g9R$Du31>yMIe~1+d>s%{De%1ZQ0|^fF`uH2h{wijzZBnC(FW0~6zMK>2I({`~u*Zame9ZV$-yvhmZM~O8^;D@pM8D1asA;zbDCl}aC|+k;_bp5!PX_~as9*u_jCWJv&~3K{3>ZFI+7T!N!Z4r zGTPs)4w@-uZb)nT&o{2w*}1EqU9PVWJM;3jbFC_KHDt*btt%G*tYe3kDcR|=U|X^g ztj8FyTvILY=2k^5!KCrR?Rjldm^I6U-kGgSG{-!vJ=NrIU=BYPON1S3Ua0x!*@gj* zMf1jnk1pP6%lB_J%-=8B9|7Qs)t7}?!IY2GZ$dsTJO;jt27&u2O`0ow^(yJ897fmB z*wQI|H)LvClkwTxN`3|V94B4AZJzwyld1QryCOT9$nH(}ApknY9P#yQ6$!?dJr9W1 zyYA<<;6yZSVxTp@MJ=ihq+$9{j67dzx2Fqe{EJ%!kpFa7ZLoBsqb(|GSvArzL+bo@Y|VO1DNCmI%fpr?GP z57cd?^4+BSJ97P%B1OOBg^w>GcoYzhBj82DJ-;sEm}5%tgaxQJr!4AB=a1S-d$C46 zPPp&<)+pkPY*7r)-D3|`7wH0ovb|-r-1;OBh7v^{7=Ku+baxZ8OHjKKk5|!?4%0g$ z2XHby^1#@S0TfYryHgk5H;Fcx0-TEcQ@c)JVTb8p=oIH(g-|87q4`CE6k6npcPV>h z8At9kT_CamK13O;{JGlE8vm*-q&KgrVM3hhaL#xD{wQVoavwFrD_;4?j&XtzKD-~A zIV)?SPatQcW(3vmn45l0P~~dOVZZ0`MvOl}iQ~9Jtw;u~G_9}!0!US2=mqi~4E>8U zu>v9`4_y5l(7OcagGJU;lv8#sup99Tw0S0x&u>tG+zokG0Nhsy1IK7tO%HTxz3OO4 z)ON7w9$9aF)+kX4s+9^EQ=2_mUPEy*fBF+uWGx?p*aOF4hI!4&5cALR8rZ10wLK{p z3zG;2&mmV3Uzd&iI(C^`Tv^!DUW6ndu&R<`Seov26Mf~o|aoQ{{xs4%$C zO%=836Ob0SO>>L&ma*s^Ag;O)ZOq*Q9N)^JKPav?(0qU9_a~wH{}$WwPb}yABH6Q6 zIT7EqD^_8oJsJ20yD6!2;^CC9bkgTzq%-nEYVMwZ%Vk|9j{ z;V&S&(>dZiV-3SXAG#bo{pYKV#u^OlfGm*i-kWl8Wzb-~mW7rTPmU84k~aDs*KBvi zoMAy|bBSwnxmG#6U%L=Kz+C`L@o7SvPjlZFx44H=?~&MFn$@}SGV zYjB z2|{Tkj%hfbycx22E3ikR9IRr6AOzV)kkgCZa9Hmfp8 z;2*4l!2Ipom2XxSc{YT~);+bootLKiH=M98+0*~V26e>Jwtj?HbK{kQ`D^yGq zzzT2X(HzOk|5>PP;56{-GaT*5qrM7_!}V9iH`#v8RjvC5PAMTj#|MXxrH{2+|Di2q zCHNo(L-QQ{vE_t}{(c-ze8VtO;;~$Uun|^#72Ek7kPQrRn+C&7<`htADc|TjeON7* z5)!S?qR^`$QtC1230g2Sga`zaN|^zp zgB|i=%5V$~J5gUNkpLbt5L{7y&Z&{Dm+CJ>kS zc|p~FuWWW5H?}b7YG?4s!9wz-%yS(zetEIuZ6oI)$)CxO$Gzu5txJyVCeJ-MnDV_< zdF;fd24kh~n(0yn;;)sk|L+5Zl~+_P!R2j3zQ-V zD4oy+L}?L~4k9IlB1Gvu(hV&(5J7qmy_W!y-oZuhqiCfY)e|I7;EXi8>LT(w{PqlXh0V-5lX9!pW-N_(&s#GdEVm*T&CH znT2jmI5tuPA9L`@*B*r~#&w4NflEPwl(OHtOT2CYpNT7(LKJjA#>kL@?Z5ZxXrgdO z=DBxomNhxvxVYup?Jj9au!|k^a79)_7r12{T+7zI2gGT%Gc+rd+m{=)IF$Qc)TXIn zOkBiho_iwktW&HJj~R1xNqd5ppx7hG>kIINO$6`KjO8PRl+0U+LrdaJ*RGW{nfA$D zxpGiXC)jH3p);P@nA$}BI^IkOh(TqN00i37c(7b7uc>Zi)3{>eky>`K=Q%khZ8w7M zwXXC~t2{$y6bwft(!yo)>oV7xi-{b_o+kX;$~yA%LGy4Po1{VQr;o?BM|`6AncdjW z7nEqwJr1iH=!H_c@n``cPtXk&Lz&+uL(|aL-;}*^EfA}GJvOBCwMvoP$9{t`+Nj}N zcut`J-@#k*->HN%gU;+v6QB~*7$Wy2#3JL%Ny@NtLB)iwjELOmjkp1}`bMKWW~UU9{j^QQs0Bxr&}D45;!|+i zDgHSqOegs?S){KqDXk`grQezJ%&dwlk~7Wofk0Alqfp`;45ps){qrrld3R$tnxb1g zvozy5WZ2i(t4D0$T(vhn(;A7}|K@c^){|RC^*D7acX%Qoj_$vRiXw$5ao>0cmGZVH zwZ`$p6M-eg%S42~ek6+@a|_ho#Tql*qcz zMrBh^O4%h&O*u~HU31`g9z)(Z%;(lyQ=}9LPvSnO;}U+rgs9k=>UN^_+}lO=^Mmuw z*(4=PGw1>*|NhL+QF7=hZJJBJ|L!U7&4Ae@z-s}VUM?e`&6z|~;5z_jknNpBEBv?5 zb?%#ulH3lwaCC z4c4&L&O-$c?h_ZT=TVz4U(OfnZs35*rLW$6N1f3-{pgp8Q*5W$R>ztKj6wVP3Iiyk z^ovmn`!G+?86xi4sCBK+F0w+do4WGbHb>Z{k=_pBoB7#4=p2RAxfBegIXwW1{qi~? zvmXf!GH?iPUdK|b)@E;w9!y^=%QKr+MsW^vxa#Az(1o3~KGH}v(;(H6C%2Z|w2KWj0!TY47+ z*`q>~d`WRMk1CpnvPAFtx#^SBjuZo^Umczv>c zg1BPULKHs*NirYE#LV0smJmx-uR()R)3OV#70nfiyyrA7RBR?#CrW7tyYVYa^8@Xb z34{o`)4UhG_3kMxE34hK0|ecF)7<*2_~`flv(*`_PdII-YxW20Qd=<@vlaD6Ig|H0 z+<1`dU!y>;FX=2|VV4Kw^GB48?r&aUa&9+Qk*UbOfjUq@ zvNbR%639D-Ia%Tk&;B1*#u?BDuU(&74Ki7YG@MtlP7-T($?c^Te~(6+?_Db9DK0E3 zE~Jq|qJtSa^pavg710$zT2~nlz~_PiQlAc8v`Pr+r1D2?p3vA$nEgTe18yp;K878c zC#B%QK&>qpq(_a3#U-eO(oOTg>!!_#wB0Y8(+2PD>f=Y#V>zCfZE*zf-n}Xu)`IRc zMZ7)!)bFKg1l-2Jy8NjD@7Gh z&cKZ*Vl33F8g+)H)Ak8^xX|kI zhISCR;m>Rp1Rkj~2Twlj76vxjj0&jxirqfY)N}!chX7qPSEUsw+ix~-FD_L7N;jHM zidw!3ybWs)4NfY=wItRsBtQOOQH9+9*?mO$CXqGq&( z(QlCRu7aA6cEgzclO@VI=T`91YQ_Tbvt{n^ZuW)wtAJ$ZHMthMFd&Q?@5OLqWb4Mg z()GFg3eLJcD));iMr5+OOxxk0Ua&OJP88mB|^gDL#W9(#_m81`MHmV{OY8 zAaTn}g>ILHHBmLo&?8N#U+FY2p*PK$&1S5|*wdODd>oua-0dsCxW+`u`Zs|Z0MA@q z*yVc<4x$Up85M5g=RqR8&n_x!&qPo-!)gP%OVgv0kl-LovHbQs_sCq8SrCfP*L^Sc z&kfM9R^l-01hzq*yOU+EZ~&ouy=M{$Zl!ghPQBgnQYU^99( zZRQaOqtP<_!nl_?I1!nY~fqg=5=0p7>k3n?J*G{YR(OfB!(_Pl&n1p!+}-t%VHT zt(1Vy58GkupzXly8z4MewyddW2EaXeU#CsDjc|lCyIU!Wo_}rI5=Rq@+K$W3v)t6P?mr$2nDjVLUG3E#$8I?zp2W^izm|gT?5)#r=Yq!ky_eU0dz!xnu z<*~d_8|o7+Wn}!t!_H1--&JP5FNYvxpa>e|j^ZX8YfnJM0^Ss?lohhI&n~XS*E9Mh zeCm#l`R49~oR}+G|Cc5pvIzS>O;RVY=Ma|{8L*jx1z0O@g5IsAIU=tYQ^NdRLVx^B zv!f0yX0F(9rP0N=I7buZ*7*EErTN)totMXAnVLiCeAuv@|I<$^DFZmQE5Y;W(zlwP zec3Dys3=^9<{+B~Pd*G}nItDa%Z*(~5*NO(XTP7^51iu_X@UjsfDbfo+{bTX)cg2w zp~`))hG9K9p3_&JTWGMzDW1ukCewq-@mxv_sGZf~00hVr{np*sN&W<^`JYe{`BNnF z*ABK+n#@hp7xSmRhqsaLl8;xn)pze|2DZQVk^3eTW}a(*VCg?1!G&t!@y# zhMsu4u-?i143~zDNGkjN-RW>Vi##AOX4P$X1?NLV1jz^vTwJ zY<7G39$!~yWg}JWi^h6bHd?846_EZ`P^7SwAhy+Y!f1^J=kA$f=6Z2DiRz)j`zvzW zIreSA9`Gb%zhJQ@$n4mjEg8&=jl+DH>WRqbLOnfBM|iDHy|uzU2RvvpcqI<8!t14 z^uP*Z*Suv`_9w3Vg!nDdva4~`Iwpoi8|m%JHry^S*?%p+_D5{(e-bKWtVCQjwm5uk zWD^ftP)bPX>vbM0JLB>(kk1O&<3E6pV9*9d6zyv2dR1*OT5@$`2O%FN`IQ^t3R^HQ z^mO0-#L)HnRvov_S1|Orax>=sWJE-HHqSTI$4Gpai>zF*{&tg(q64LuNh&_Uz{8}zR0FRXWmp+{!j!6bE4DQv@@h>-YNP_;Ci zG*bB4GGWdU;R2HynkOH>nQI!Zr)?=1Qpx*Ac+a`1eF;iODDk_)*_9k-DrB}*4!QB zy?S%CW~a(~zlBDnK&<(sAK^F743MDz$`n`S?f=J_f1!-jl-d@#=zg9- zc`4*r%(Ww5d4cU=rOv5i&{tI`48BCXBU+#g7yC&Rs{UfsvPU7Rv;gxxsIK4+e4lpc zjga%aA6BjYyjXwt0x69>VC%cQ+~}?9@tccQX}96AN8VlBzN6m&uLZ*lWCfBS*}R{I z8iHPwL0ob0kwQ5UX|AUxT@RV|Y6c<~HR?`D{GxSjEZA6{6R-(|lApt)Q8(U{;yF9A zV&0d%9aOW{yy1{ibC`Uv*#U4bPD`q`t$4GZSu)`vOBrTlU^iFp6;v(40lj#+4 z2*CaQSg(H5MxV*Dr1WFforo@;wUqpmT~|I>_ zxv~6H%JVzE{r~+_%^%3Dq_3#mjVtV5CTYQ=t2O!>lC?B?5`XTA@O1*G_B zptT~oS)`at5c5+=zxGwfMO(%Fj9d=Gx^5n+qvH0xY{FvGs^M?|Y?13fBihS=^gTEW zE$OQCyJ;Q7$0gokG@Q-Z0SWzSGG4+?0$qHTrq+ZD4~4tu@036sAU8k6>A+6!eFXk+ z){2njDw|P*w30yQ;mttt>zT)f6Xb`Q;GN7j{tk|!guQ=jRzDai%CDK__bv9)iGq-j zC$1w_MQJ}R@npNs*<`&FmiJ))TTvPsma=KU9 zX2>O=)A!B0;d12NNTQyh&F9mS$nY(nA5Cy(_5b)$z8!pj#5kbC3cJz2L&>7@kY9zFQ$6JGT+Fx%BJ6u!2-J7!*sym(m^mJY)$P3;BwRXl z0a6-JQ?fFNNNTRYq2hE%G5SO?J*}|mtO{$kgwL=w?k!3gfBUIte-Nm3WZim*EwdDV zBCaUA@W^}SI!fbeSnkii0;Y8aH~n3GCY-_v{iB63z zwGrnGXDf^__g!NjWX{~2li~0YRoksF8rZx0@&|`yFd^&gAHEX7&ZFB`dJiv@on;#S zBzt{}gAi6=^3x36I>UXqzbwnC(cp4Kxr^J~Q!k?nG*XzaqZGlJ8uP~iTf1M@cfh@zW*m+a;La@w1Sr1auHOe>J2$@|IbzL84-EdlhM zmRed2fZ5lHB{s=b%Fr1(TTC6L2xd5{M|M>dW zmgWuQLlN88SJ+RiZel5G03%(T)2&5sdT0mj2I)rs_j=sFUha0qRk`GV?wo0dTE7D; zGBcS>-;J|_&N4@6L~n7iVMYF{z0SXWzW?lYG8W<|A0Z2qB^J-p%Dp~0cCHvVQ=Wy7 zW#kL%p>vsS(f_?q!(T67yJCz)azIUvnL|?JiB*|>6t=Z8EvkXEi_U`$FoOBtetVQ? zm(@ZAlOF!Te`?i7JbR2^&9RyUZQDAlts|J8m8WO;` z26FG3$wqCf1i)rLgHq7)U@3a&_#Cjx-0Hv58An*tq7lI4ZbP?$RNTg+AK13eL15)` zO@Mi31-4o_idM$nxqH49*kN!Dhu{AiCNIc3k9#A^XivwKOS}kmCpQImtgJ@zo!@OP zg;i$$gRc4yda|dP)?o2({&Ddu5PYZt-P6}Ahc-`go0x~*ddh8Jea$2zD`uA27V)q7 zHh!`$#v;ThneGzh#4(KW3)S-6lW*G=b%fb-ANeY*sl5q+CHz<0b$|Yx?Hl0P?6J$+ z@!QHT&Num6Gj7LWLO&h*0C(a(2aEr&_GkuZNy^)0GuT$9YwpS+$5p#$`zr4pmuKdP zyIIKWcPZichxg{@y_dV9J4zLg+&a>(|6|Wk7jX!n3+0`*xJ*enA|W$XFpQ&2uwU7+ zY4k?#J`KVBbHbJ_j2|Je$ab}9DPu>_Rx2d9LCK% ze&|RD=Ig)U9sf@2RLq(r1B3~D-a6i!ax@Ua5Z%;-JIKAHn49*6@`23lhBN<<-oWql zJpayaD^bTeD7%bjKbka;fJhyjE}P&H?$d3?3L$Eh$Js&KE8|~rcm7UmQ!G{&b?DLTnumowYE=34mjN_Ajdr`P;P#_T>{(i_j7&%GPC4Gd z5XMsjT1qL}z3?#)Cwbf2igR?9lW&bQtYVMas)z=}UoT*H}>J5vq2Ci%xP z0xw2nRa}=I+UI{rO>MwvvdEg`9Pp66YZlGy)O+>79PS(mNu9T0pT)QUJ#j@cp$yr> zPAfa{on6PT(!5%(+l^kULf2Kai(gd{BLI2j%glydr0!W(#OQnWDvI`AiGl`^h1s0#ryvp3S7c%g#g?$Mu81mEkGlEdxk6}kw`gQ9 z%jF!Erf%K@jdyPSFRhBz2@FKQ^gBQ}DM6OQOHO@oY%KNAJR=ucEbr%0t-}dRqwi)= zyNn%j-=olG+*GP%6CJF2AXb--zF3esAff;`Z7Y-q7_oXUqw6*cgm`iqVNX*99`O$s z)T4By>bMQZHTa|NMShxNtYWM`a1ORP1EKhRrg`{qs>9lb(c;ayLTvPhb56Y_`%9{tnjk#Fc1UIeFi?-{Pi5%+&|;2fHFKpsB$gfgWTB@% zGA5;{c`rXZg-bB@%H8NgpZVO>`E6yuwJ!n%-f57g2zp^HtSug`ZLb)#KGq)g+Eu}u^a_SSqD0(QkFqxsHp3sinxX2B77r}=_R6KE2hmE z$r(q><`adP5g+ey#7faUhpn^ic@6;n)D!5v&zDC~P{ckc>ATsx=C=#_Bc(FQnLeq(xuah!&Zwk_&n&GfDM_mhesPmn zqZK=p1ixij{8FKIx!4CV1RbcIzzzlkFRap&6|Pm2>tb+Vq19VXSf$Vlmq@9rtM7{$ zd;vPti(2lE8c5^TZDl*A+iYhIzBVLQG+a(zJ{5Z)cjms7si&CF-M#; z)cE-5NJ3tsdUg&^+*Q4+HzA2MlOT7BJ=sI#GvSIG(~ee(>n5i%ZOmEWgC-{`3p3-b zerx3$uVFYtrS2)nrYPX?O`J`i(V7ud<)iGtMmg&3%4jenE~>e1Zx9PRbAgsfD-(m1@k(7f9qc1Ee$?S%-P ziRXp-$bkFnVJ&YoM!(eTaJYKjsE=IHYYtHe_YXCZ@o47>Q8(sbzN2!O8KpI&7ghIZ>ja4z9Or1Y3-#G%iwVQScE(K z(HNBjUlkukPyOK$VWXlO3L+8CCK(FO$2Dv+=1?XO^)pVU)5%|$ukvMrf$4!b^a5ys zNhq$DEM*{u3rEU0Zu5INmuYLYR92593;UT(=`pEafE*Vp5^u_Kfo+ukY@=QPHeri| znD?#$RcWFswbt>zz@?>=`F+Fn4-UnDtBbt0|IoqkTl;32{R9)KZ|)LT1>W?Tod|K2 zHmC_9jTw|Se@ds%b-#0@B--IBZ!0AIuOYvGY+2ur%0MrigNmUqddDm7Krx5&SWp-B}Zs1G|o>qB%2uCB5z?v)YbB> zs~Fz+ar;`-`Cu+}M;qld_bhJP#(X8cZir45M^*y2NrUkdzi%6s; zU;PbJCJo!U;7=GiOn|xvYN4$2Cl5h(`j38Yd?xNXp=coF zb+;b!Ix8x<9l;WGH|TzlM-beRJ&IVD7Lb(PIUjMpdAv4pyEk^Z+bT+}9x)}>B&ioQ z$Y2)0bJGO-rB9y5X*_h&pf?Wb$)tOh=LxpRwrI7YT|apbD~n^KlBv_Fq(a@Hk0e@} zY?Le|-0-Q|pv*$*yGZ9^SXy=EH#bIAcEwmpV;Qr322#cf6kAFQ(R}s_f~Ez?OMKXU zF{>LBn^=(u$eiXET&blYeWhPftUBMtK?^qa5V+y>N?eZk+Q;FKi8Pu~$m9V>+eEcv zp`m~d(}9l8C=Q@&37K6Ilx~I0evo*ga`E;zZ z*oJjXsh)e%W0l(+bt4M%=;&oE_$)w>%Zj4q1JVnEtQ{|r-j|WO;@I}mJ8}WGC7g+&tYVNU;zE6 zr##F-P;Ty!lX`%R7$Hhwy1j6TG=b>$^e&v9RvR*V6%fV5d-hR+#A)|PtqTXZOt8zp zt$oOc9(nP6VvD9lnM{*H`1?eu?%sQ9Lz4PagSv+!AwLT6G!K6=gXSO=OQ~B}7g=JN zO`^HA42!uAy)jG-yxA>lZ&a0NBUyTpB%YCT<7KDewW*tso#DR>&;L}YjSBLl4D?&7 z4|Y^goC$cOWd9>aH(Fh>7=WR+pY@pE_Naa`^bqDeg|RA*n$IMj%S^SrMp_`+_LaQX zE?-I zCNbuXqImZlR`$AKE~90A2?x!c0rsNyUBE7}FoOdvVHtE66-(?Ps+)XrIQd$&&$Ou7 z%=X?%2fds1C2-0cVxXH|pVF0pP6D^|3YR9Srr9hpWt-)dcy{xcz^NQmxYpx{G`kpn zhV{IQ@b8Xcb-&Une56!DYFX zu-4Ce!7KoLBW29jFDkD2P2u9F2K}2S&jYr{TII(1jx#+PeJj z@ThE*uTIr74dUd3#=6iOS;%G49;X%+!;kLprQW1(^xKSX+3Zc`XAMsCY(HUmI`YX< z^}35$eE9_S+X^Z7Dp@@ikj$|cQojx>Qm~GecS-T=&0ifg`9$(n#Uj2;txAZQ9>ti> zpIla`kBi5?2|W%&;93nv7s!W#3!KN_r8=jsh&ZR*QL;u^!);_~299Bs=k|yl;GNtV zl?9oUQHliC>4^ZwjoNKf37ud~l6Tl{99ivttx-JZboe%G@^t>MbW{REvUqh{*hy%Y zylp|wqEoTwrCgbJyg%gf&OT81CcEfvgr#|`7}t_zpGF5%5gb=Pk9h+n#L4z-O0ew$ zOOiM8%+RjwWiII}M)!?bl+#KH2#^o(Q|n)hDTagXcF>*B*4qLLm?bJX_vm`wEjz+8 zq^sOBw8~wf=4$AZI?i4-CI1SwRxOU4Ws^50b z;ZJ%&M(v2yR=cM+qiFY>wOmD_UJ+W3nP01(mk6qH>w>oxuk0#fXPJZY-*1P^@Otll zQ(d6d$Wh(l?dVKDuwMPDPSWUpQ5pi$XU*If4^#pidrn@QJPXj@b8bRhy&3dbz7z7m}iebznY` zyx}yD$L8#?{n`|CVQc=I>~wG8#Hkjj^Uy*^)3>d5eKa`nE;kct3IAT7$8C>zea@z72>CPacR`KCRIY`HG{wh4wOB$n4APMG6I3R!1)- zITGdvU1`~<{l{Guv`ubv8}o1U#9ZZv3kHB=57|k2 ziZkk{<)MO67uWWBCt7FjmcK!Li8J^R`;gqceF8m`>nL()B$HxizV!AC$VG>bcTzE+ z|M#gCMw%tErU8S|CKuOZY4x~g)h?iot;JQIW2gAeCDpP|s%cNO@6BMlReCfz>@4{b z5HLVv732s!UaGQgAiQ7y11{Ms9d7Wh=Bz7o;-r6s{HH9(PsV&DnpdYZ6*WaHKplOr zN)0Z$Z9$>;F-g5Q3_7D8C@X;`GS(b9*pBYrzp&QFF-E~g*>u@Z>@_& zhYp-+ekXPA#|vg&X7HQ+!hr35{bG;<&DEi;nKYi<+;_}T?kXealv&_&T@;)zLXzd`<>;RUSXvywxjH{`nBLAB?$#1 zy!i@0!Qyp5$%!7ggqk)ycV7$QBWXNQamXCra6Z1~5v||(Mty8To});X&ti6o1H|2^ z4G;LQpt9h`4EvO?Ha&*DYsSvM|01!;A!u3_yq4>KuEP9ibi5;rkk0cn85fcgjZib(kJ>1SvRN^q& zZmCZ>T#6b)P`Z%N4=c3W!!m;cF@)-o+?r9Hxt_}(8@B6ml*_owmN6k_H+bl7wYb9< ziF?{v_$y@<@puzAp3%jk(-fh>8Y{)C-(U^+J8N<^p^vxGv_bles zmkc_%8=7em*)KW?~6Bh*gji3Z^_R*z^`fg z&P@Zh&P{#-Pht(y9OJF3Z)hR~wxw)_qlKp|nqw6)d>#*7^a(#^&QFc8$d=x9xIfGs z7`0bSMFB!BSdi1OYn_mJ6UF3(+>QXaR|YIFIvXTaOUjAC7Q znn7)t*AsF|;_@CXtxm?dl&`vGY<)U!YUk|BBO|UZc%EHoY7WN^V$`$b*(6{J6@bLK zILgp${a%8N-!H zbX8sf=cXp)yG~2+>Y8i$FPdj6G%i=l*Qgv||HU1i5@a596-7@9TmEcJZ5h1qqOBoV zEU&@QF5~V2JM1w{g|2R<^tTQ$`2d9zFmq#S2T2WuvF0PYsa4XzlM#toCorSPraDCWeQ{G!es{0$U-pdeoc+OW#<#c6sgNz9*8wnok z1;v-K40mT}Rz}?%6un+nQ>q%K#yP20$aC|{+cp2W(!#y(?6u4~r9-c0SFjgL2`>b% zNX%P&euOt#rhsj29;Xnxir+peZ8WC(T*;Sk8@6!_-Z{_LvRE(R4nhhz?tkHQ^eTS4C3^ zva~>5Wa!3cN|-|9#LUxMF+ClZ5hIS*J4T6-oGFj7hYnyE!?0iMbL$^KejbYl~}6&!y0-Rg=*1V#av&iff5m%l)62lPk`pRdIGJ z#O+;{1XFKksD0F@fJ)3;K|)U3zhp7UZun#D5GUe#v$H~#v+(@Z+RKa0st2*0Q;Q+Y*7GN7lX>V&|FX!=@ejh2Go+q1$k&V+n;$VFObUcp-LqT+BPr>+VfPk)EsjcoD&j%=)ShHGB!Cf`mH4S_%bDz(aXZ zPTIv@E8OrQ|M!z~*2_IZb;8_p$Y*^b?{4|D8!6UM9CJ~Iy&2YITEYq~fvl5g;3S}_ z-PzN_fNftY-l2bL<_&cEuI_F4D0nhG&HZstTQWO9d|+mF%m>{zQ}3_JRu9Ua70nsF z@Jx%xB8R@~iGbwNYdxL#g^pzGmGL$KYE8LA5R*_!xq7Lkf zKC)oq#=vDqxmF{xQmOBxS}u~mY`Xe&vFOEOxEj|1_MlSOC!np?Mt&Xyr?!rjHc!@V z&(sCxnQPkToO+Fi@5tWlhs0B_-8xavP1v0^+m8jN2)0G8S^C zqqa?z6^XK+&&1rgDmo}E!l5;EhTHCG0Bn=%X9t~^It`Rh(O0T}R5M6AVaC#}9@$`& zxNpUF-R_jXcYop2?i@4j^#`{AcjGo8sKCZRx9cT636!tlSk3YM7c{I!H;+oFR^Jmm z5P1qcon;mvQu_wjm9?K-uGp?3#}RlyR|!OQU2B!caTQM{Z4SozlKS(*gs@!K)w$|t zVy=uy`&lxtnTp3~FJJGCxa;KYt*41Radh)RW)FX%vhrvF zB)KJzNhc}xMua&>uJsd?RN9c9G8O2c3voy53^G&Lx_~Kj{1zMcH&Xoo;TI-*? z11X}T6Qbh`f&8gz_-7Vg>po9o#A>;|O^7OF@#DoxFk!9mi@JVTmP{anE@`zAbUCW( zDyj^$UO6+VvI!O+dvKCwQgU%@=s4eoXpV+;v71zpzOk&p;|7H^ShwQ=L#26lo&h0! zzK2)sj&EJ(DoB`Ykup--bM1^$O-RHzBKHmFEta}jINF%I^kwX}8`Sa2ll2Lj!#WhhvZ${cmB5E9bnq2CNTYY?((c)U%`MZPl^*p&1 z?S_|gG#KwZgz>5#E6JjxJ43e*Fx?vN>1|7N3n`wOLvH1=x{%jnlUrX&4H;}qR|J$V z%0B>r($brd)Zb7c0h(rR2fwP08RO$=VjF(>+)(;X3(}xtYuJv zN0?Kr4IC_fl=&P;uP}PkjR4(D^7kZ(06+k^tj!gZU;S+vaO^vZJxN^YaahYq=6(Gw zV&XD~8|27k>`{^gl^_@gxU;pzIPk{XD`v|s_(G?+#iXxG;{ir3R*kV2IL{iz+d*(U zd|*ZkDu?bjrEql1eIH~0!cJP+zP*ktTK?u>_5|aK?Qo#w54FDuH0L`3%gvRPh`OB^=V_3SUP*4$#1k{J8y=4&`(^rUegx4 zy&5##ZFm1|KwAtv6i^HMfuBW;w8{TUC*Ryu7-YW!#3kNML>RBlEa>QoPjZ`aaC8KZ z+~hkE0=r&sRw#zmf!W8@fZ_qT?J@FfGBtkzdlCW_M-{>cH+IF>uRZcd@m4|xpOw?+ zWl6e;_FOsUF*R3w4Bf9uyAyQJ0UZaoR2>nc<`5W)8dZxtG^t& z(XQ*<9;{ga*^8t~jok>vn8oeF~>FJuWDBR*8;1ufPDUwvG3in^R+H;uyK)bvLR-*WP z+2se=rL^DoZ2Zh5?_E0CBc(H$O{+->XvlJEy<4ps>wlahwPCu;QHZ0Ni#vRF zvW^IJCz=R@lwhK(+N=)gYhBpVx`d61wFZH%P{4{#Fq+Pr?;SF%VjYj{U%x=RcRZ6~ z?6(_P!Jouk+Kv=lw_@1R?s$3GcsEhx`ovr*5`-<}I8dHa8M7hzrYX+mO*l&?oc^GF z@5)unv>R_>R%NP6*Xm1LDNn&o(o;MsdP+4t54kZP z@GRtv{DEbq&QKR0>rzw6f(u9jSFUx5SmZNQ(NbN^#i_~W=xhaYTehbR+L?o)sE1=t;boa=k4+8 zLWFixMHWoo0MG_82P9BXlyFKurHKOQPejy7n=))}n=Qtu4RcpJg@i{+jGQ^a`OY3T zj>IDZhi#4vvIodQnt|$FY9=`*$bsAjB4%M1*EWgIql(x=sY)ZHpo9%u_UEpAR`OC# zMFt$v9H4oRm!0iv>(_4U4Q=BMNI(+KjFu@D+T)yjO^a$(L~UIUH>gcob(}df(=aQ{OB+OnF6xrc5MP z06B6J*_kY1OvRD)V%OYsB<9;BopcGiS7p$xb*)X7#-~L_7MPoTk^m`s$_Yk#s)DhO(=>iicAs1*kPht}TUZQV6Xqo~w8T*(K$gbW} z*H+WK-AKl8o6+wy3@S@=h@Dk|tm?p`uqM^BFyO*eYt-pigdfl3B ztg+S5noq=8AHG@$smz&N43$9(gNMEDI6iZm3{R4Yujl}{^I*t>5l5uU}GnB?Y# z;`t1+e>{E2hV63o)*c2;rpv7-N881}2*^QO(6iiM7oG5Jo!)4&u`y-Mnq5NY@C{Ch?UoXR^={1?y#eUOAl=)Pg#q-ZRS~?O8y4Bwn`DJ7z1_bg zC@j)AsCw{{Y`ZBugZi8V+R}2QOY40zjy0r~wpj1ub%|m=#2Mn;9LLCwSk!2I57i>r z+|Te0GfEjpi6KS_qkPF^5~#r;N2r|u8FZtnX|U#f`P=bYI9y6W*8$0M%*G+?(NV?W zFLAeFh<;yEkiG-g4f1!wVImiRZ7vv(cquqGH=xSWEjiT``uDF%yI$~(dQ=513J#P< z0-zUAc)Q|SVi9Dq6ojBsh6)k|NFg=u$$16b&+IJ`B=}V6rRjJE{kA{oX|%ls*_fI zwsH3RkdJF}?UqPN3dJ1sFZ%^i<9H}JmgV#^duJlkCoi#pmGQXc*d?FwFH8zMrfX)J z=Z{L9NjsFQwp$#Q*On56n#WPPIMKaacggdaNsS1Mj1s?>uAR2R*)MB}z48MNZb-(V zv&>UkyeC>q+Qfc5hec2ZNW|g3*#vMjCff+e^i;BRFFSs*Y6WWWXp~8H*wjpecNIx!S;sFhq7 z5&EQc4))bJpVCG1f7iTHLUW|qE-PD-`7^RhmyBm_4DnV(&a2aFayD~4sU=%j$i6=4 zdH%xX2HvpZ3r6aRLfV;JtqD)${NKXWfg7bPV_CK7bveOJRRWyC393=gVqo zjN5%(0pq6hU(Wc@Ezgj8`}AGH>=hIe-uBhp1P9{-<$ZpotDP^8&EYCv9WZhOU8E>l z;Fnizf?`^jsA043dOMDKVa;-+q2xHO>o11kaTMR4?XCQx%e$et84i;(nXFzO`)Jqvt#DPp z%P##LeaIa&22Bd4MA0U;pYC37g;3*$(7XY&1YN}2RetDX?tC3)CP~uZOn^Nshirik;lLF$+8uQYFXiF^Z7)eE|?}k)XjTuaSMOhskpN87`!>#=gk7;)(po zh`apheY-WUu|m<^-ct8JCK#xw=8UXeu`1T1er#Vz5Q7Q@;r#V0m*YInW4w;zJl|tXeEKtd4818cmrG4wy>Vj8tT)D%Ce86yrh1eJq59~QPL7VZ zAeUNZG}J&|Q2g=<+i}S|@6-=ouTD>S|K7{V<4~Vm75}iAo~RAEcvFLL_3Vy|k-8ji zCzQ1kYblp%i!Brs`!sTV)wdwB=x?{P6xK|NyD1WG{^$ZVSF2A;|KgxMJ;MlW8_TE>>LcEt%ERCtr>caldluyc}0|cpawinsq=JH z^y(-fvQ0G`keX3wiI_Y*O&XEgf3Byu|4Gi*urLoq)Uglu9$?w=R;N1XP6>~L#OUyo zmO8Jcn#9Jw+BxP=HjN4Tn5f?7$EgVBtEsO(kSJY2YYyK)_u|^bvKG^HmztKGGQKMI zFY(Td&m3*+El5}m82xm*SwT+m2prl-{VjzV9 z&1JIFr{dI>t}k%{_wRORsb-o?>Pgq7VumPT)XjkpV;yJRIV{q8KESo>=O3SpQ`hzL zJ96&s{oaTqo~x^EV6qd0g@g(1t03Aq*)-Z@u&OrFZ>TV)K>TtH6lM-c%tzhqmbp$t zkDeQv?Y-nK^gj1Zdm~ z^1Jon%~967vYb)=yQfD)s{k?BERyoF4E`iuZYEZ823UPnyU|LEJ^a+nOVo#qlKI)o zd=+gpI%iMuoqsApZZ{7efs^o6(No)eStAORmHD4!AN??(-QiTcV|k~-GuelQ37EDK ziQU={Od`8)*abK+mpw3T5J~Uke|CF}vrW^E(nW@+K6=v!BG&A!3K-01O*sex((b$cAe zDSIA@Odjx5RIl;F!pEPq@Oz3a^?|vac4%nr^)Qew(z3!zKiS>hIOGxi_FQpdm_hKf z#1`S1Yp=lE6}Oh5%Q&7Do89xYc2lpeQO#fWPt#KHH1PL)s%M`bXSA4L=klt zBtM|k%lGX0;BBw)B9rjhKCM_mgBehVlx(;Bn0?sP`hvyPz|TkL^lh2ssj7HoRi?gF z>Ds=aEx^=xt=6|Y@ zd~vo)!`$oiaz#rhW!cZ`4Q1-rYwJW#YtkLFUfs)Hl>NaE4k|4|XJ6L5gMzk(xBOop&)KA} z*$j5RS!qe+Q#$}%l$!jODMCJ&$~>l46t|xyX&Vmdfi=P7MA;vs4-G@ zIyw18j%ZFw)d3I;4$~sGP?BPij z9m4Q|UMTPR?$_d}b#6RW#C-yEVGqJ;&nQ1gkhmdeemwa8rQ7#KQ1E5Bj<*wobPA3wDa$)&vG?b!6_nDyys0l^=;_VN^!TCy z>J=($3-8LL64EaYgs@F|Swyk*e#!cZOV293Khd}5(ze{fy z)&05saL=e&+;ZLfi>qcIzSgkn7Q9hdg=@quX*95&Zo4!wW@U4#^u|PUOolV{hcHYJ&o;edGg;y`%xb%>N2b~&d+*DMH@2c zYVsVObxl<59G#jP)=}$?%;E`K;y;@(NQl`rSstuAA zh4;bLcUX{(@_9u~zc9V@7zA~N8KrkM9t#N59G~N{n7eo}Z?v>Ux3@}DcqBg@nE!=` z7Su;an3vGcp3i^OojuePv5=^dGWtw$nmoPw&ZR?wIcJh*pkTXkoXN8piGs3Nr4iAw z#cN)g2lJW}5A~e5=$U)!O>6<1GHYkmS?IV_?9#rJ0kg#EGOhYOUbKA6F7Mxeyc~WuC|naCH?EvQdudh3GCtAyBc|U8}V!`K~0fGkwl+-&}ighwkf(PIJds zO4%OEt3@<1gsl_Ffrl*$NWbsQf6A&e(&}OIVT^0;>jR20gW1K42~jUzgz%>Zmr&BV zMvY*@QP3l%*jtHFF^%VHB5a)GCf4|^MsAq$y?U$P(I?JlS^wo>P1+f!kg$+>xVp)G z$&tAkOdd36xx+~sVxkXMMWlO4ldQ7`1x zM!p(OYlP2fyVnYtccRmIt;nPxrCROkGSsg=FS~ovw^vk^U2M~$5F{TaGd3gZp;epZ z{@V)4-%yPI?+ofA8{S^GQ-`#4i>B=!2{d-udB)S*bDo0SBB7Xz5IZIJZfZpYu1IDl zuNJqtLN6?TN{$$rp$~8$L+X9y4w<-mZ_jP2^VDr28Ea=5U&eN@F^QadXf781zdr1F zy=S+PwV{Kfy^)?3;gyZP`EERd9mY<0aq=Wo)Y{s{(LoE31h-DJ<5Ax(=x-Oyw+r^$ z1^4ZO-?+eGu+1xc^GX=>v^G@S#@f-y+R=d>4%-+LDsFFMD`w-WMff}hj$p^)5!z4% zBSSO2f4i%!XAgdr9kGD|dfLdr#>w8mh%nUV9UDhIM090UzVvSY9~2o8^BN1|{L7?2MJ2i{}R+E7&|eMbTec{6K^Z-6#r z`4b`n=s$o6zKIA8Lqp(rb_@m$!Nbw)XgCUj#UcPeGysU)4j{s`{sBOUO+Y9Z90G>{ z1ZV_7B^gp06~y_ukywXuzWp^X_7tbRBW3x}Em zt8J}k39%&%2ZLkaI4mCG0E5Ag3kgC0)iiHdS_BOIC4@f=SXKlu9|-UVV-N^-1Re)L z!nd<*zxjtvnTy+4+Ssew>KPb;KULfT$Bx)=W8k|bT^*%W2_6LeKw6bxAAnp=gC9r% zp9Stofm<6+4!ptxr?cS&p;Ab8uwcLkp;9<@Pwlyo-OAY?X6iGPhaBfHd;2PWjO)6f14NeX!tR@` z$`2~8o_A>u5iZswBB8_EO%H`q+x1ix40;xy(VUWuK5`Wn%+U6>qv~Z#fo0AoXtx+Y zLJqs86nZu;aYU?F$jdF~CLGI!@ zu!rg6VY%?oqoYWv%CjtEk8blp#8}5$7|S~l*N|TYIqm7C-Y;YvII0qDWEqx2`_c7A zy8a`aFH*+dHdokZRB!*n_?60cuk6c_^ht4oPiq^Bucl8B?|N+o(WI49F*JsC*^w~t zDKfZ41W@=gP0llfc|Pc?sM7ZLVuc8iq%j#DO%u&iD0_Ck%8s7C{9=SFQve_1xkCL5 zBCwCM0mt{5NhpLEimn$9Hr#c8(8f|)!|{-rI7-$wySJ!6?Ss9VpPh&=XSD8Y$?L(c z5Jxt$PrI^lmKFQP$`yl$Ir%kq-8m)R0l*g&gq{GOkk3IZbU9@{xtlG;K*N`aoMiAy+l)@W6Tl<%m?=kx?qGdh>u~-YeqpP54zA$u9;&=u_ zW!q?fB8^YQ&7qWnY3Y=4iqFnz1e2Ii_9XMQWH|I_#1(Tna)~0<^GGI5HSW|*qY{ht-$`_^^;$prnxx#OWxa#pkiYVd zfHL%#*yryj^d=67g^P}m^bRhI!p`h1Ci~LeceYu}*PDgzVIKEa`ZKLDSOdY7l8>PW zrdH)@sAzH+t)Ke_?L2Z_3Ay+DCz9x6_0w+8CNERhD&OFEoq04p;1H>vkJM+!%6H1G zCy8htU$}mvVzk?Dr|5we6On-@oKNW)2kzJAr&U|aCem=Gm{;N`iCzh4>eV;y*(p&= z(tZC!?c!e6n@uVS*H?=KWnSpX+DcYeiNFGMGMhvNNsIZeIe4VD1PPNlSt~KV>|4$; zr;InwB4IzWFZN#ExQ5>_4>Dk8B$dwhh^K=9&X2#F?CmUXu@fKe;gt_|rj+PiW;<}b z7SU!h3&U&V5AH2!Uo@fQLy&WQKCEd~MdT+Ir%F`)*42|FR60iL1A9o~{%H~^ZU|4V z302At>WXmk2t7~H`!E{5@!Oio>8$%icC)eWRrcoejeqxPsb8)~Q>=tdO;9uIqH^?e zD*oHTZ;UOUFj9$x#Zc9Y4AXPqiH_u>n0(POPW+!bL$C4$cbSV9YCjyJ5Tb0^$JJ`g zeofr(iAT1)XLTenYYG(CMBZ|kR7a$be zx&u$hOpNwVydnOC!|C649+0WG#S2t_+4txr{SFJRK)E#sw(|P>*>s;rlRg=mW)?B= zwO_g-PJZ{Si|_^g+ZeGE+(YA~0v}oXoALS=1k9B0JmFl%#A`lfSGa8Qc{Q~C!9fFN zqqF&OX0koZf-UFN=6*L@gnSY$eHmVSkd!NUmt&o#qJx+-i*)Fo?dcl)vF{f%1h9F5m)`< zpduA5$y#sovKugm*Ur?_S5>d) zNMeMNDUy#`sM^p9QqvtfDZuM{tX5r-*&!j>ff}(Rko-|XyQqV`j@tE8d+I2fA)U0l zHL%PVPks@%!R*7mE;?6}cQjJq_$w(r@xZGG{nsu?3it)}XuQ>XqTwElCx<7Vef^Gt z1{op#{4%uV$c1BMxv2cJ^K&M9y1JEp>Z+*1CC~QOtUfCg3W+Q9J2Xwp>rR9-r<@*P)4+K)%8Aij3?^2v+G9HU=Y6o94M*Hw0?i4dITda!GXZzLh$GvAQ zFa31LGfeWb{e<*2SXNJyUM+9dra+%|&nU#flb7)hOYGwx`6=~E1 zT=Fk`t`YQ4gf@#dbOhKc-&>Lxk9nW8gLMBY}5E|g@5ZN~{T?PRBAORarGTvo8eM4!a+5gM#hEiPSBl(#%+adfEX z=?nR?!v`*QX*y8l7PiGp;mOsYRy%Abqa`meDU-|%58moWkMZTn1 zlq}e%Hc*r$P}No=*Y&#NUKV{8O?{5Z5PVwxEbDP4`Xc4z1W^`K2IQ<6WsVTzb!L_i z&hPd$5lf=Rhqzx^^uIgTE}Dzqk$42>ZoO zH+7NBFBd|VR6B$^?MotguY-uOP3v^Li0v*r6J=xd=e1LpcRAIw&+ecXJ(5}O?tM?E z_kMY)#?Ij=KxXCIb5_Bev-Zx_b@&O-53e59L`xf%Wkzz|jx_0IwtlN4*4iW?EqrZ4 zx=-%ny#u>)+4KAN-x5rwbe6W1_#ka{o~EDk5bx#L1GM9h+x9{zt3z1)*HkjKiK8=i zCT45gvu0Ku8CiUnPvdT{im(W^@@`hxLm!xZO|kDrhk8|O#onRTV4?C9A9Koy6Q@ES zG=z~RmlSKe@!8+J@eJnpv8xc}yO!3*mJ=0$qiN_^s~G3*SY52p2s4 zF-Rfr7R$$})IKr)Ku_(5&pzMo3R;!xrrx)Z^5Nox$dVV_O(sT~7P zDU}aiIz}HV4V2K<4(O!M*+C@fLhZ1p7%!!pZ~;ZZnecGFN0%!{E2GbVYywj@PeY{G zPnlHOj@Ht1;JBX|qfUyweQh+^X6JPe9r6cX-LK44Y40wNJ^Wx8wfpRO&-+>OoKy5I z4z4WbPvelmb2bcN$8VX%9hq@T;5)3kA8|_f6VyN{w%EBT*f&>3@8Ma)Qn!`21$0CF zPtJ|zr8v(U#h-AA@4k5TvghF2l{EBAO!zStzb49Nb7ya>udAPXULdX2uct6F zpo+S4M1Gx$Mv{{*e!|&h(7EK$Nl8gEOXmm^_q+Cw!}4us!tGA%&m%V9^XXXNXP4|O zjw1A>#Be%Io#*~dyP?&3(jwwyUrFfLr#fYpKb){9mXrHf8>`OY%si_1T&(5o8Kw2% zleR?JcKTdR4PNmQL&2r~JE8Y04I3xgN=&6Z>0XYj%$+@kO0=CJI$G%ZcyWsCeD+%6&`8hW@z87f zlVpd}Q9-kl;Qi}Y@Enzh3gu%D>m3K&jiX%#Zr_?NmfL%@OZnBL;sB!=gWk=xe#e8YeM4lE zM+JHgm$OfKA`Go6*ERI&p9GD)eYm9E7**^a#5Xp$Hb4Jr{^sD`;){s##KBAC)9DR#+%fGjU%hthBBCfTv-@`*7!Lc1f7>L2;jnLPFC6xb z?u7&LgTM^K;hTIfe3S15OzyY)8yPY9`9_8dt{b^BxNc2 z!ceDw!@qx1oJ~ICUs;~-1ibt<2zWruf9Jh6X(2SAgs;nT61SAw3kAiMRU!k!O7?^!D zC={STfdB;5Z=Lj55+ED{2$2-^|e#&ZAP zMTf_rVKBs&qQj#B!$;uPKuH6K1uQFI{J?@hV*vS!+ZMOEVUGTQ=zb8u-?a{fgunm; z_(ODHR`K|4k&zpg@t=#%N#DxI5Rj;7P%uE@w@@}DP%=0k$BsrKfpUS03%CH3XcQcR z!lJe{u>`B|2L$%L#PLJd5HO(rfNlN0Oc8|Tu)R4XSeO4=V8AosurSyb0wbst9FWRr zz)s__;0o#rD8g!m;~_A_cB*FIJlY?S*!LRDcZs3!SfEmW2@I6?@VM>GA;CBNPGE+v z5WvW9aQOsQp0EUM?QI+(2p9r`+CoxDB&aiB38fBD_(UMtfnGsyAPPVMdy9r+wxwGH zU-dg&ghIo=+uKdeN29P91bQpYMY@_7|Uy0u^IC7W0?HFrX}n*p|dL;>F)dY)jn-^(5>TqCx<(ipK#F0jrM& z5ib&j1v3alhlYdq+ln`36oCUh8$aNI7?F^X{1bRT+5Z0}%*OvZkwB+@4zp2k zg4NiTgWO2TekZZ5W)jpu@mpChLJUY)f=EyWCWO^!V6{*nv_iqQ9ae9oh<_Rv0>n84 z4MXAx0R*8#0N?|r3<=K%tC^^{59bP84w}1|1pigH*Pbw-{3m_0HR;>NF->| z`8l>H^uld3w%?##{s5$3^D`uz5Ilp1jm?;gVCc6QJ#R2TztgH;%oQAmfx>|);zxkw zj318TN8q+nDm3VbLjlGI2~ZJYXf$x#Xut&^fic}?486fi{okPbZn_AKH6WJ-eU^Y8 z0HzfQOe&txmHD3;l?}G+cj$h%A`vJU7LP`4m8u~Ky=g#r-{BEpApjlrPvHHL2p>-L zYjO)_d?SSZu5AeXwnOL*KJj-F`@Oay`GHm1!h{h};V>Zf!UC5F)&dd-v<*;o2pn*g zxNQYH8!YGV(EWBkL31S%2HR>e5TewLh+-2SA$moC=<1)qBaoY$@ctJQ`)leAD3*;l z|Hpg+)!SyAzrh3lPGY~zCk&5->YLdRy5#JwK=Yh|161G98G+m?)+Z#77(gN;fENG; z4RB#-AT>f48yuue+ajP)KgIfgOMCv05P#Sa6v2}N{R3Al_)-MO>d@O_d^X7Q-wE-z zYKMVg5vVQGUIb{2Bv51oR0MQLz+(_NvVVY%KXs`+32Rsn!g52Prp!-9f;a4UD0ozOiHscTkh)cGY25c0DekZSASLqKD57_&y zTmqpb9|4pejt8m*`hEdJ2CNAX9GG9glx@ewZxpJ2hwHa%6PP;;2DerIivol{3~-*` z;h}+gf%W;1;Qb+&@GFr4qC7&D^4%kVf)B7B+fw|EO5X1T_UlCcokwtlA-Cc*P)Gy> zR8ir;jRFb-Q2%HM26%fo@bVxL-PV-;Cx`IcDMcbtp!a+$jr;Bl;212ym;o~jC=CD; z4wfijLbe6(Cno5B@$$b?8h{=JaS(vCxi;Zodk6}*tvGk13j0sy^vB{vfek}jSTRuQ z0uAm!G$8HXAH5%^8~wzgowH>&2p6WA|n^KbSq0OAR@Wl;iT zQW)Tf;J|GXHjANw(!)Ro2Pd$iux;_#8}O2}mX3A{hz4-o&>b^wZIAoBT(*alU`?bx!7 zHjLj%>t7WP1%fQ7xtW!fleLW{*xmz5lGv@34de_PrAuHofVlu$QD7kI#;_B3$ZcZ# z$QmpLWk=X!Y6mRp0XH z(wH*aebOj@*;6IKF~^|pR%T#YVRcp~t%MjgA9d>v(c_9uE{*F=!>d&vOLwqSv_A=t zi;L!NYx=BXkzF#sD-gxZUPngWv4iy_E6Y~_Zr_!v9ZVy>zFw5%&w}2RojKTp@yO?r}tPo`Gv|bmtwBmE``gRNnB$kuRbsy50_^T zb}zeP!AM+8<;VV_^8;1g#WMfnl@Z=|A2GkW5qi)r&ArU;0Jdj2@KD3yU1r2yr-Jqx zt?*r~7`uLJXE*MxL{^sE)vq)6VD2rUpZ44*3TS)ewtL*aNoVjdtUcIze@`g`2h-c# zS7MwhE*RoIX){(?>+Nmsezbr7xnP#sWJQXIX6lY`TM9LI4%wm5BRwp+2GD3CCOth@ zx=WImmo2;0k9{1t(6;|Bi!9%Ac|ebAOXwjPb8^1pddFIse3F=my^kuaf6kGLj&9;8 zetXqhtGfnUl^OWyY3nTRR%46K^_7Xj>w%p(Ih5y>&d%H+%;p|oMB`~gc&8pna9G1}P z%PgF`;fg~M`(C<#BHd3@s^?I9qlED~SEbO7LN^oWsl(h=&6&@apS-Uiu6VKHLV0vF zKNoK3{_MFl%S}eAF6CTm$X=Jyk&&^XseL3AOs`*`EvaA(I9_3Km6!X>URsv@M?>qa z$H=<1Pxrq74^mufX%Iy~COv# z!!pD}+5F|CN#;#c4uxKeQaU>q2c6ECBtqut?ihCik{vp6r>o z1G+LfWmJpYg?l?zTRw2f^!TyT>!>ez=sZAb3aQB)>EJ0z52@H+5yQ2(yG|qD{KzAl zblbvfA|oyf%M0|HMlEjh`eiq{*Y(yf-wwAlPiDEne&XnYMLMYzoYQ5;3*zHLRBzan zf~Sf&{QW{nNo^mdsPBQxE2OFKctV$Sn#jU`c5_@X!w#Jh{D@ zLzE*eAxCt%-QpF7)g%_P+3Tuur)+Zl^bfC3C12ww4fJNrCt?#$Ug9f>Ut$!qaE|ni z;iV24yPK7GV?U*?j*c?C^HF=9)s5gD7P_SuRJQsQMbJdb#If)fPYzPYbuJm+;@_VQ zQDS1Qz^I9#;H$QDpSW|SZO@$&2tKv@oN1S|i(XaI(rj&FrtIkuawTrF_~v?duUwwv zlW)__@JciKj-xU ztCdWBp?^SznmxkZo15R1x%<-l9jzR4oaXcLXZ3R)`*xKh0}t|H%N<(p-Xo<1sFwQi&Nu8A9wvY0 zq{xOefD<%rJ4W6{s`z*~wL>_v2$IXl|O3*md_L%D` zQ}o>t-@Cq0qxeFl;w>qyoCVJziF4%R=+|AUzW1WfYbPYmA*&SW{qY={msQ5ATb_C& zQ=aASdj7`p(!JqgTh;(B?{La}H?vJf`}I{Wex+AA6{2^4A7xgV0;_S)Rq+t6kf*|; z3D3Of4qOa}a#P-pREX`ni5ww4b2RFG;_&FFuyqllY89#uqkYuMCKziq=Cv67yX@&mTTzxRH@Eyz)GnwR3^<+US*lSgv)Qq{q*`UeV9T*EKx5{ID_L zvq3G4rsg0{TE>5o0jkQ)F?|dodHksqjRgzI8!gic|6umx{Gm#3EXkBehzn>IRmkz$!Ct@tlK)YW?IvF!tMy3bb(ZTKXDd;+cz|`cFNxhA4jXpbG=C}^ z34z61C5N@kBUKcWjRr#4eGjUlrT23NzMM_2XWb=NfAEp1nLdk`Csn7nbUH6wKgd7L5kx?^Q|TJ>2@!NIOb zc14ci7Y`J~@bgfVvOa!oj59A5NlbcJ$tR2N5`CMtUJ&hs?DDG%4?0Aw;v3~^trKu4 z{L_vk$@JJj>=HUDpsh-`z z<_y7QNk-S|<-B_P7oF2w-f(g)4cYGstK;wXCM%YfoA?0#Y?Sbl&JvgOQt??p_@T3k zeVzS&xsf4ecsEN4@$R#%^{K*`Sn`V%5ux1jk@yerR*807k?Zfos6KH#CAn$Y{ppph zf8{f#bcmJDZjMve)tPhBVxfb)>g9*2xcxiDUBvWb%X~X89|_|%ozONdBlC@82>Fr$ z9efsicRn>P>5WI=$g%gKd4sa(~c;RvqGzvRRat=gfF; zPEzPhxO9TcNxZgtb>uqpAg)79thFtWl0T^DdlD)QQ) z2U+_2)qGg1K8S?Qg}2Exa8FKBAySnqjRGczl%HehuH3(Mol)V^@wRghkJ+Ood?<;H zyVX^49gpy`BIO6(WEPJU-+OYsZIFg{QKIPZeU&81VfjM^U4h8siOi|LRa+lJ3WTvj05Fx?KQ*f5rKf2RgvWC1zGO!~cBTy=fE@R=T277ysexv1Hw|t6?0sU+7s@{-Wa^$yHh=Yw zg?7h)>78PX*G)CaqH9M`le1@Ttk<6$HyUrc`lL4Yh52A9Pn6OCe_!Z1hXxGsZkw@2 zO1H;($IfL=TJC|S2+>+AcnlsG%_Dy*cl4}d;85+%d&E_botmAh>Mz~$$>XW>I1 zZ76gb9x=>4k3u>2w+)*1?U*qg-rq|GAq~i zGDK>sl;)Aq^1a@T9#w1zgWPI6aoydoddJJ%P0XQ5>{QMqhWs+Sb(}xAdOaw6v~%|b zjyXyO=Lynii!w>G*UG$Fr0iaqJ!0Gelo?X`*`2)lM>xxR#rTr#OD2hmY5hKnLRX?& zTH4cDinv}sjLKA{w3%SwdDSbAxsZ zk-31&`&Qw5s$>0B;bGUQ+ec46mflw5o~L zZd(u0J?);@`s$i`=negOc}~Zx85ie;nwO!8y8T=(k3Y7ozDl-ubM>x@Qg|Q5$f@u? zp}3UAmNedA>6wyMW~-A{%uEN)9|__y16MyrhNcee@9>WWT(TfJcTu@b35P14AJSpCHI%zl3Q72 zX;gV`Cm1;&Thc_?<&xLq_3-SMB^JG^xsYC@GHvQ=Z-Mh`4m0w{G3@V~cTJ4*Vd~7r zue7-0V@F%e4(w}lUyq17(lNQ@@LBlL2Rpkto`HJr!*5dK&<|FI7=tCJF_{Us6h7Hr z>~YPTu+LdEx3ZdUeL@ahb!7INJJYCY6= zmE#5Hyw+5~MD{*mr5sPn@paZC-D`qMf!;x3@W&S)`h^4v@PMAcr@m0&sWWj-sBG5mZ!0 zN5M)GZ3NCkGlYooB4AKiM?Fh315v^WK>&}cqmh;R_v6_JzfHhkZ)WRg zWB=2^H=t?%M|u7Gu0!nRZZ^QBZ|r6RJ+j}fgvu4zeF$23zg;(X+kuA5Z|^sE$6*QL zA$)FgcN}hWJWw^*xR2W$4^ZFV-fxWe^KLm%mjOTdBfI55BROHH-|m*%_=7k3%m1ZT z@@uOe7Bo#^LDSv$nirOEO5FB3>o;V-ed-zzk$epg%v*fj(6X*l+kx z(EU_j{a+^Y*Cs~{XqCl+O5yj(#DE4b%=W7I8w=)l0{hoG1n9)ZL9GpJtgIYB?Pbdr zJv3dzlLZ_P7ul zL-1fuL0~|W5080*!gKgEm0ydC>^#KmK`-YCt;EMz{_Mf2p z$vOTn8un{rBL-A?fqD2#!@vdw?Dnem8z%R60{e9$u}G+`wVngPQh-iHEI7+|_2;%l^Y`f=(&yR(+~q`yd1bHX{FkN2ue2 z6AQPGZo@lmitc}z&0pIZF@ys+!GV`Q>;=#}P$Jxpz&0G^KbcK}z0h-XvNr;aGw`hx z9|bfWOf@@((3S+6LqLNF1djsi5_C<0PK0d%`>D(RZ#&=q!%Tvc1d&@hrp>(^Xgruf zLVMX}?+O}pPhqyV*>@wL_ybeMhe z;U?0pGZHu+f%+*2iHKIw=qseI8Js!3n(~pFqwXf3UE-Z5%9`hP_arz(^^?^c7cs3o1BCFUs21sdN)s9c`RRolBH0O`;0hnUhh<{ z#Hpa;CKfcO9*tQ>Q5a0gzL(e?bfoDOH&YeUv&nOe{%5&7%x>;(418@?!KHpsp0Tj_ zDXaW_Yikacpoq3&hC5Y|8N~HxKraOt?EAJ&m~1oSDUYdzLiS;_-37U&~C8@`goce{A=}$f7;sG4J|5<6G9Bu0Gnylv|+JnNe_gYL8=N zL3rOKl^f+cck4e-_YN(;vhHKwdD@Yl{^s31eUnV$(hoCj-!)Rb zJhxWE&*@-o*yBARS$;aHVx?r=drogObiyy0BkP@4izCzL3{RtBp({SD!~dL2%?7-<-kNVN{#Ycn8UqpQ;_OKG?oQbT5~ z*B1`U@UAP3qBl#6Am2Z`NV&5@eJEnj=*b;4qx_fCu;ju8bMb>Fvkf}e`co-5E_g6o zQpUtSdb-zRjzs(dO+5o&IYy{~IgGw(Ybz<~_ea~3n^{8GS&#HTX4+eiaaUv`O1MC?xSkx{M;e{rdZ zaP7KBFa_pr`XNJAAy@Yp?>Z|3vfLSg?1be@PI5Zop37e*{G|M0bH1q`+a-7yk{bFT ziIH?eldT^Ub`=PXYDdf7adFPkd`Uzxt^3AN^qMmM`KPw|$0|~|ayU|llxF#u!t${b zutUV*-OH9ckIBCD)V`daFef>Y?5fD)C$+C?e$L8lbMckS2PULhLj21}Y;d=dMBxAkuc~+_=v(d^Wuz5Q2lZ#d?yQI^Z z%*XF_BAzX%sr6=2(u-?YRC$rPLK_79I1e=kSOu5Y%^knsBh|2jL%A1rT)JVUzVRb> zvM;M(go4aT>?Fq6<)x}#)b&r-YUH!}O&fjd(lJSPtbKd53i5fzAt$LvwdK=k_uqMH zM{}SgM+z6!sJ|=V6fSy~RRD=!Co|VdZjR(@z30Wjsa~2R;_BKAMy?U>y6#$O7_+`* zycfOaE8jhoU|>a@N_jy9tNBsElu?JfH5F zj`qXdoT&YpFK-p9rd&F`lwEn~^pzk!&g_(8UirHGqN@e=qXjFkuW;$TE8F=+(7Eor1HY?40I3$WQ|OkOf%8_!`qV0tj-P$vg-_l#w9 zZ#7@NmTEw_-7#o=5prMW(FDzaVS}E2>1$$=#Ff0E=Fs#LM@oFepZ7I1Ax733)!jx8 z=9;~fGB=nnl<^UZ&Hao%hYP%GJ#*a1R^HzP7kp+f?sRH_spCuZn`Jr{Qq`ThOe=To zeNEmYx#FE)9IPq5XuenNX0X+#TM}2j-rC+Q61aU;q0R0jvBGip%wF;gHiN^sGvTIfg`eSq9$`-5g5Drlt7AKKN$grKU4 z(4nbmkE%?KFka`o9AShr_k6C;U{A$Xv8XJ4tcpp7b?>rgkz1nudY0mly5}yWhi_Dk z-_4Q3PnUKkjK^xcljlCW8x7BJDeO}qIr`OjoNY)arebEwb_5!z%x{95qY$U==1QeI z|0ev}PU6ooxZd@`J9RnxG+snu#hQ^RDDv0jct0X)Vu&C1T{rz;Stakwhr%Kgb)(&3 z)H-kZ-|Ktu?4C7>)G%5Y!S0>co3YtVp<(;w^`eECW7Ar~1 zXGDDu()1jR2-FlHwIs!q6$qr(nKLl7fdK-B!Sce8P)U#m8-g>h**EqH0v627-oa5E zuxsq_4MyxQP77=n-5`48^?rQd`wqGdY7%dB3aJPdLRzl?XVMQQ{~`H2eobsD_!fsI`OHcf>zIMdN?P3iiVOD_G1g zMC!L^82k(l?4)4_X%HdEBV2z13I`$Ij~H|7&chWZ&Drv^&J*1JU^t z_x3hvKiJ!)-jsJ@NBChh$pOU3<+jhEcl4Cwd)RC6Z`y4wXhIP zEB}Dka3F-(H;wrEmDXjRwW}-#OxxDH3tn=@ooZfa3$N~x^A|1JAv&8ztoMl6aoOwo zN$cQ&6ev?*YY-RX30z-=vl%I1Z_SYgUB0jXlZyGCwT_Di%)0Km=0sv#BhwgKtlAU%tscwj)ZZ^Q(~0S~LVqEfZPj@| zE>`Xvs6*1G^+lQXWQy9OsDk%bs}xR^U)}2vy<}WE$;`NmWankQ=-Q!3JtNzZ#-YsA zFwcixu6N2_(LI|V&ivv#u~Nn(IWOm$?e_F$AkhsypX)U-70D3;tPcyc-m4WwCX~*s zXAtko*kPNvBZSCxHzOm7Lg{XDA9Y(A+H&cn_}j)pB+aB!J85204JyLW{!KU5n)?-c zonc+I2GeoT74s)4t{+f8{Kmp$kYA#MD(SIl4vK&MO}M7Metd#{wJ zoLGuE^`V9PySfiH9`Trw6*Lpoh?G5a2d>_QWV-L^UY>hiV>+l>Gl8Ve;BFHBY{zUq zZm{7+5ySfJWgc1Ye1(s!j?VI-m>b!&N*6iaWE1TqYCocR98VzOH_h(marOv2 zb}O~sK}14Kv}4B(YG9cE)!-5C(k(LYrMF!1U4FRaL)t>wap3Ag2{qvdd;T(vL_|A? zSauST?$|-hV-eM}f8pMOOak2szo51ALI03|u;}id1@gz2qKNW z86FaSFv>T=Gr%_>(2sThVqo2h0Uf9w`CmEc748##J0v zo*n^Smjei2wm=j{=kDtp;C0Y5+&4NT{6@%4@P!M}q>&*Jq0!*8A(z8gR|z+6`1yrg zVfOU(@$w80i1lMzj9LjI-T!xz{;3IG!pzv%2s}pzJUB-S4iyL4F%tX_ibV*hIQSn9 zToEweQ1EaDJ16j<2k_Vd@X}Pz(wMNj4tmDa#@-t2orFP+z|#j1XcW|ua7X)_clhpU z{&HC$`~7Q@Hw#l(IQXg`r71vSLkaG4qd4UNb%g3cji5GAW2h)T9lyP@Csezj>d-S#DFST39vea(U2LEd zPz$Kaf2w%_ht3b4F9K>_z@g#LfEFfryUm){wXk)%^{fF19R zH7?mDYq}O<{Fa%PC3YW6cB_r8_!zq=%Z>UGhD@EO_79H<+@EqyI#zn-ZX=&^ptDT- zp3!zOw-^M{;OQ{|VO>X&xcK{L0{0v8AV$+tt13tTKla``o~!Q<9M?b;DY8ci8S%15 zc1C1|?7cTxWwn%+s63L zj2^8NXcNIdOml%qD|HPc*o_az*oJVFy;xV5a z1!Fj2kFDpY-n3JApJyRu*d>Z7wjtcMYk%z#CnFvL1=|xJ9X|L570Q*w+5UM^3$=Dffu>no$bSDPppf zWh^n#uzj7kwv zbn|sS1HWDqam)LhOKN*h2iCDPkM^D}h>Ui)s&V3*U!&`J&jVhmM40ZRLnXI4dW6eX za!J1Nk$-gz3n(9tXL2D=(AF#OwTxI0qsJl?N9?+2NFq|b(mt6#uYJptW&S`Dfz8B3 zDJxydQDQ?wk%2v@>vRkkL+9Sq5eQC}0lBb0M`Pt;vD*G0q2mYjtxZ*W3I6 z1J%zenS1?c?m#y6K?1@nbn-nH5^~R0UaK|YR3kLwl>A0wDuVUa>$%rA%rB3tUm23$ zJ&y6ov5Q}xfK6ZVS%ziV;}Aii**@ySC)a7iI|~nXU9~Z?zV`a9iYh&u^PNS`E@9kD zwpghyuMGuL^czR`1@dhZ>Wkak_zKCqNS~MV7$tirEv(hEeI}Wa%01@$p~Y8hx3>Rm zggV7{`L0G^ai+niF9z4z-wpWTohtWndSLC$>MmR&^wxJ#){d|XZ#_|AH`QI)uK~9+ zd!!eSGc=aO-SRDyN5t@Jl^?exob~RYIe5cU^kMf?QV|VG#$D4mFH`PazelTkj3jQn z&BUEJG>UogMKM=K5@z50hopg-i33B;KI*(n&Z*Vfgv~Ab880olC1X|?$jAqLde{6m z#->bqy}pYsrW@uojv6r7^wgJ97HA)6SalROkGPzh5ggvUe(BQD{WaPTYflCnM5*Tl zXUB4CH#Y>Cf2KCS>p(HDKfUqJudX$_+1JpE=Jfz}*_a*a3b!LpZgb%1YuYxJ>p>+B zv014HRB4{)_}<1hu^U=m$EsVrKB``j{PB+Vt9MT#YOlQyP~L4`cf=9#%Q{ZkjrX# zJU>bIp1wuS*W9zQ?1IxN7djgC3%=IietD5l{NfyjQQh>xIS(Tm1CXR{?d z!4W`rvTj4C%IwhkgZ7&rcvLHDPwG=l4|@2u_swJ0V&|NGYLYR1AVwsMzMMX7arXJE zHM0@5F}4Gju@euc))~(g_Y2H=wM-T9-k}Mm)Tzuk`pI(FdD?c4v~b;S0vTFs6D0<1 zqDNI&rzI-ltb2hxK+E2-_MTcqqA1Xhus) zvWsMlM^j`V9$)3l!ED7>cez}mgIirv3L=KQTHj|a*}o~PA2rgP_4B+Sie+Bl*N}A8 zb7d^@9ow2-={-KIVJ!Y*Oav^SO?z=HL={S|iLTUB)V$*1)lciQX3dz9YVI@cxiuTm zE(<<8OVqycH?OzVRCVR42J2}w_MBdZA?c$tE-vK3 zUm}>4ippvCjKuEe;6LH>Laq3~cSqvAqL1WzdE5jlWY~l-YWCJ1$4&DLrMr{aQ-5YT zj=DHhIU}y}+a6PgO7))8-5%*JRt{et#XZrlYK-r{eYS=wE+#>7_H|Mroi2gLvDJ^A zpNc~5_m>OqDK|WIEb{G<^I_6O*}c+uSMM(#wIZUdkF(>!7tWN8m}-1LE->h)SD;SQ zt?JIc+qL~XF{?Yj(AtU-v-!m=OM%B6-_$OGJjaZb?>#Ioy;0A-sZoI+%$$v|Ves7G z{Je1<_v3CF0^tmnVtw8wAr}X>SCmC}WJ^kCJ2EWlS(aNLRQRg` zJrgmFqA>0|3zcBQ!O5Tmk@yR1w)(s?14Uv7&M8~wihcKuWbKw_9HVJwmyJ=+Yi42Q z!Q#=<9$m0zB-AtGxa+9kUS6TA{38Ful+YXn6|w#mhxtz!123@B%k8;S)M@2!Wqs<(_N@U`w9nbyI=@Nzab*!MA<9_m@M`cA$Qwh_JJb3BvOt@PMgbRdg#=nHes2Oc~Fe+)CYl= z8j@#CLQgO#Q_~MlE%Wiq4tl9LFc0pbs`4Laa$fuHv1lvWj4vv9`6%52ZAnPZi*jr^ z#!0ZNfPQYGTDU*|Rybbb2kR4N*(o+w>QvE1DT>PZc45>3FUe>S5i+KM>pA56^Jz|s zU=n}vp|_pV(mnN1NH*O->3q9qr)myf>uM(ZBBN0J?$BEH;y!Xu;6(^#w2hc zyiV&TK}v8HLwbX~n)%_X!P}eL($W?yFSVx1?G#;HKX7^o`w7odb=Sx<4 zD)I=*w%mKnbB^Ab-mz4-DN2VTsI*!8;)wGr&)O;Dx#m9os{GD(OJVk9nLP^K=R@w` z4>mv2z14c|N{_|oQT^({T!!b%4muuT!q%N9SE?dtwL~HlRc~t?l@Uqe31^{v?2`TF zx{#HThrRkVSxiA7M_*LjiwdV;so;0IkIB6^CMHh2JF@Yuu_4D^_TAOw+SHPa+G@?= zllSpvo`$qkD@K=zKVw?TcxX~}(5rdr)PWX7pR`lv&+R8UT@VaU%RY367V;1HvMKY* z4Yp+~eM}ONveG_RPD`($pdR}=`t=LEXRE1rlN&_*3rEiFVi&Gsspr-WnI*CFi}&8I zX~DW|y`j$)BKjb6=6v}0n=-;4MgtBH^JnjjWTH#B)1n^U96V;E6?oCOU*!9~y(8Zu z6B70I>n&0)&fCvaXBZOu&(!*s;qfGXAo(0!+TLrO+rlW6!Z&Rv9iLZhqqckTqm=R` zp=(sB`c>qQB-U$zI)W23fc94*88yZsx^nebDQ`>8{fmYbNXU@%h@uTfioz<0AL?KZ z0d#@xR~0K42-(L4hmM7GCD1RZWCw9uK;UI?AbM{=bVJ!kES+8abx<^OV z=G``}f$SYfKJjPcA2I>U4{p!(Gr2;^!BNd=NRA8sM@0+Oa~Rd)cNWFsC$Npy-@Zq` zTKoXlhIrlflme#1pJvoAC<0~=F??{KAPI$Y+E(QMooz!pSx6u2V(DaN_AA>$+k*h} z=`D5aFMJy5Ll5=ewmKHQPyPqK#Q}UHw;QsZU>EFL*i7aA(}of>iv(KbC>Dv3uU^|0 ziS?f>5(1D#;_zLd>iX%8xtAj$~^P-E>+|w+50)hhlsh`}dFKDKCTY5@B zP)kTnfo4r@%^LIS)t~@p@)c|>2(v58lShUM&M>V}O4}P4ip95B(&YJOr4*9qJ0{sX z+jtwWzn5L!wT%Dv?WZC6m&cQ-htiw72g!%H8d(@bl|-#mEX|T4)B>lnz;XBv4;XfqRok4ro^_%9_(s>AN|#4&&7c@Id){v<>Ww3 z!kae$W{AQ5HH00s=mSG zJySBGjyNj%l2(x1(D__{{$3a7eWLudQV)`?>WmR@#`OFS3e&bVtnER_i48>R=k^Sb z6BUd1aUXpVX-$pOzLE5e)4qDO?<93xYrmT0pkDWrj#eS6yDiRwO$_*NjmJ+ zrY+EuV+6XNq#W z+hsSxjMk4mKHfL9;ym_rU*FvA^%0Z3m9@2pj1A3A-!NJ-c0P7-=498+G&D6dOdh=( zo)nQqpsS@D9;=fx8WSCFpcZBjp&1@~FJtuXom7H|n8b4`IRp{f@!D!whY$4b?^E4} z!Q94j&QX@NPnDgQw;zNk>sFmdw9BxnFk;9ZVIjKzHqG>H+O!cr*!)(Q0CvLN&WxLD zU7+D=j(X^+WSekF<-^*UCExi`MH{QQ65EUBALGi@>^DAR7HP=LX~*dm$Xs@M9`SMN zPP%-&kZVK4hSkvXICJhNU7AxPaf8%4F%eYc2GrfUZQa^^>JhBx4|gUe^^eqftS(dY zj=befA}(*3!<2jJ%}{#P_T{3UueXwcT>SbRzS~Gt->7=|X*ZFpK(@;byWI9WLPHTO z&<&uQg!M-QCY+D$cMAjAO|fvB)c_mn){6Eo-(e1(Uj##B3b!BMVdxRGPtLCkSs-Vj z@))p{W&68@!Vje-C4bqKw-X$J?>;nDP-It5kShb7F9KWef8Yp7ljut{$hZpqK}(3A z|F-UJU58{+USN^kl0YH(6uJk=oXBUumaXl#K(g+Sw+j4LGKQpDAUT8Rryv~`*fat% z4*#7{@3F4SGTy6QHXs{OI}FJ?;868WE3M-9-2L*bSTA$1W=Gdr5cA5$~c5`#vctu?Nbznl^T! zu9hW(i}InRC9^JxG0%^587IahB(8EiU4Ly;J*_vle0gM}X0lOd{PE(aPwvM*Kf5+R zKOdaZ&@eEOIcG~aJ5a7iTKu$9%AJws=?62GAm!PSu9NF^erKW^1FvxBZ|Jq!2pQ1O zSbY+!dsSawzbmC7UhQ06;bE<7jB>;Tw-ci7B*ooHQaO4U3-gA#IaZTwbNFs8v3MDV z4#a1+7Hq2hxcm*f9`4`WAoVc$YFOB8+%V2CIT3-*(Lnfb3D|c?gxMOyv*?(r3*lIe?-%uf8&>kt!u}@n# zPD6k9T(6Z5br?1AjkeQrw9KDu+0EXBlFL^R(tULx$WvcGrzCd`BX8dJgbF9uQwBk< zJlzWwc_C(}RAW9gvm-tYI5fqOwOb_U8{aJ?DDAARtW zYt-W!PZq{B`fVBFm9uBnH@X4@xRaiuXPo zovNz75*XvEpID=`QD8wi=0=V=h(n5f$~smviZ?ETGjGH4=fEqnPa0*AANayW(`8a8tH)JxWw3L%Kqm=j+hFXO2|c~`{Fv!$Rh$zCnIog+9lOk@-4HoeoVY#72kxJNer}dCX{(R_=Axk#L6{Uu@7ui{xgI}s2V%vB1sX+hoL-HlEDXm>KnS7$gR(usqyF!bJsVq8i3-oe_9uHyc zP5iRI)^Swti%02)n}ZW&SsyYpH!cW&l$OPyKS?e9DY4Njf}wsR$0(A#2_cc8Vby1; z^q#Y1JiLcrnC;prK7LcSQqnv!-QEdTC5mM4NE{!gpp&&EKC6kuH8|N?bZi^q`9qJ> z;A;B4JWo`Yi-0(v_}W|=@hxza+TFY zjYa&(!ECawNA=X|cJ5~zT>(HFMtwwb6^y3T1-6->deBwgu z6)w?6-MFrp5*%QOr+-s6C7*~*!A~wym1H*bq%J1|-DqjL)XNeZ;@Kq0O7myOyvXCO zIw;oTsX89l_vyT+K$Bd;Wx1zp;{g7!@7k%4Uxe*SN6N-`$DHAoR;yU?i0sf5k7Ooq zA$vslBrBi3^8M25lXA>QG|1QvO^z+}EG!)6bdc$LHQcoH(53o$k6F9T6cMu>=WKo%$)wiNV)N{Kf8p3|5sjEj5#5?kq@%2-rlu^|2J!H4 zS?m!CWdWJi@-CV&r1g>shi=Xtzx{NgWIpNR>q?KgQ>>3>$!et9Y*v`ey=VRIzuO;{ zd`XEcvze=&Dp!j}>E6gS?eZ*Xi4?;(e){6s-B|C-zCSHZA53R^+qLgI<4V@znlBq+ zh~f}k$0V)^P9za8esrV4qHw~V>a-qnX~)-#47!S@vXYahnP=KM4e*{QF+6(Rqy6ff zjeXTX$d&5v*+(nLgG3WOKT_Ta4?k4mCpl_#lrG3s#27}U7ZPNiN~ z%oQ<6Pzk=$tWQppve$CD_=IoU;r{dUb18>Tb|edCrEwXS1+96Pysf08T*VyFdVaOu z_xRQG<#;2yj&ZNnS~V#bo7N6}rr_`|vZG@TbR?lInBMxkxLX$BNYaU|Cp5 zT$-3^ZOu`tB3gZSBUCO+QHo+QC8e|P183RSR0d3rF@6vJVs?c~(jsdw8#l&wrCukmMoqxJ*^$I z9VW%E#p0h8wCp>afMs-QqPtdA#_&W2+h9(9rIN?S?(vS(kr(uZxdtnk6_pP2=kPUU zRX=M@oTgl$%g&zc@gQ1%l^HtR$)-+X(d}e*PV1b&1_32gurl@YaRI}754%X^Xpiw* zJ|gI(@;&9i?(v)w=Sy;RMq{4@9$rTyX)(o(sbHp4h;QsJmlO$ggKKN{*hy5m->7GG zWZD}##=BzOW^kyH@n)0WvVBu>9d``l*_GoOZwJ=+$~n9#&I%EIB9J6H6Va3{@ac|r z&<1}w>A?^(?%R}tE){ibeRY>*8v3v0WlHob)F0VHP<3OvJ^Gv|ZEeqCJE=q7qrwft z;{`6NcP@6_o3xR_o>+V;s2xOBf4?>0tiYL6t?H@cJ$JA~a;>Td6sHxuN^+VWq^k`E zx#CKjF&nGeTqyoTOZ)6_vG417vfYj>-&PLOU|uIJxlrr7|1%5!+4s!M*%2=ahn7b< z8Sf@gO}{_)riANyE<4G_>2=(DK_=%5$-7!F9LW}yx<~o3VB-;Ah(5_cXW9pR9Fw{= z*4bb?HRsgQs+&e7>Z#TEbA`Yssa;Os+v(ek0w08C6YkF+I@hcJ$=&RPJ!@O8(!D;l zGg7m(Wx|I-9#08sEv?&f%CSB67g!w4i|@)CPb#HkkM6;3b@_z-qKJm!$_D4~x4byn z_b1=Ggy($>NxYz8EstOw{rapwI^ZmyfvSo*V_INS6oTy17^Y=j?Lhv+F^bW+yWvs; zY#TM)VH30X7rT#^PF7q>wBs#gzEZ$V!$n2g;>>eMv@DAx_ z(MfOhu{@J}oeLxtVY?XAg0uRZ@9evEY#r+>w%6XuJ$wocW)e!26L_T*uZ6CjATh31 zJ4ZGUUy*m3HA}urH=n-|PkiiR!@F^kM+AfpXTSTHvXrR^X?#w8Z_=Cm(&O>M#SIn@ z8#Cu|v*I_*+8ZK#Dt?7yG_Rlf)mBmpRk)jSExYf*(!G|C?>%?deEP(P@A>nxC6R>s zhfnAk5R{R;%~vVcT^<6$nl^K;5IqGv}7Q*6=gy&)#LkVOf*D_^n6Fo;I zfHRu!U=8ktL+UJ@vF5rV=M!0i)Dx*04SG4-l4j?uD@J-eQf?0Vv`Mr%obX63v^{b| z)2GNi%Pz_}$L(fD*b2=qEDVZS>HgoSE?^7nuL=kdaYqX2eaz2k!fnoN!VSgS`QH=} zoa~U90mTxq6Ac8&;`zhP8~FxwnHN|!x1GFEESx)wKLq4?Rw&0k?2FCE@sm0aX$wSA z=l#An{wE0)#Z>!e3H2B2BdUOks?Gyprg~v@ULpHgURf?#-fk$!l^Q`Q z#Ta*@fOdFQHWRl#vY9@!ycsvqy?s>*b5$yUK9k7<7dJ#e09X7dSJ08`DnY729aryB zX9}2Q(#Nz1;KnrL2H?_51u$in2S~ldUA4j$iE&@0kHpNZ5R($X4f%*0;Lh}QRSGvo zY)_!voj@*CPQoBg)u1ozUi3v^)L94Y_=DaFVl2RR12l3+H56IdS-CjtFm8Ou zkjHSuaKNy~FvDQOV8`IV-~|Ui1|Nn1_-zKRuw!sCLC>lDI-f(B{hwuRzTzByPtv&*M z48g$M>%Z#w0R!U&vyh#`z_>w#{GWaMqaJPuH<*NWUJnlh1C!g%VR#{!9gX`B-1s1v z9gY1D7=8c)`w;y@9|%A&JEDQDdN@FS7Xb55bie`A0SFoP597lD<|3%)pXh)C1EK@q zQT0#tKy(07VE+>gLTR~)8GM0E;5!g?z$rlCJAeCXA-`@=?*og;<|zO7^Uw^06K3x4 z{ZOyN*(?9^`5#{_IG5xOpNH|;p51@LANhV5pY0L-+w)u84f(}_b0PjGPCsB^ytX;~ z&gy}2+ve~)gMla%w$c3qZV-jSM$&(PfhZKV=luf=M2kGzGka(4fjAZH+4T?gK%5Fr z@3vzYBu*poxQwW&HEopy`2(Zv68dXc8df9shg>B6Va0Wb`{o#)gcE{PP`% zY(e_z?J2c|8x%? zcsno%Hy8j21e9nX5K7x1AOkvt;T8bCV-~yLX8G1 zsq+&E=zh2{{HQ)U$RYkiEg*0&3<63t#GtYN0|*b8V^A%iL<2$bHvAbe5LXrk0VOI3 zYP3;F9V83iZa!GA!foN=MFWBO{5E3fAkY>N7%_D13QS*r00E&5kcgrC(V)i8l+-~^ zt1ZO1fMNlv1(axrp$$Je#qa^y6>bYB+PI)bar}kIHb)<%2}G?0RuSIpo%`{9(F)jVCCT><9vVP6F`lSsNjc!3zbs27Lue)V_kX zE5C=}2J11n4qh~phjlCe2Jz=H|5F`*9`ipz{CUhd!TvR<9iT*O`Jc!9PY~#14og)3 zLGGyWu6NZbg-gEZx8S00s)k$ z-G;hx=2sZVsTttL%Y)V)Sn2X7++Y`N2nOWoKp7s??R3A^^ZO+dtaSNPJv<;-9E2Mv z(dt1XgP;0e8VtjM_VIv~E`O?r3(Cg;a04Y; zJ!s6}r}5zeLLdyoi^dILrOO}d`Ms!s>Ll??d$=~+14=a9{zeCoJPhFmN;DXBI`~P7 z1)m2925@XN7<4+=5e%$!`OybEgF#yl{48Pr9yd7X>t;QQu6E8k?4ZR^8&yzSfEvwJ z6(Na2M<~N9;ou6AP6;58rgNm=eH30)1EPT52>J#tke>vw>j3_R{GHnK2tMyU=pHmZV|i;=03i_uZ&tEPf9l!MhCY@bFzfbvGhX130tJ(3GXz8e#6Lt67FHu%iR%$&`^$pQg-2#hg8)YQRB7^FYp;Ns&zSc4w1H?n1O z1ly6>*g@tUem(&PQwKXED|=x_Q}aJHf)_~WAdwZ&dhv6!aRHq=H%M3otmr#JAEJoA zqYq+PSh<-&IhGvkonhQT>NGQZXESGnu{(mBjs1_k3o^QZJBt+Zb2IPf(*7E=Y9!w}gDx~BC zA6@7G-g)o={{}-0Ev2Dra23!p2Rs8+1F{Grp9S|}xXtIb;Q$PDE&$uRx2{5OL86O9 z7zJ(c?k)6Dn*;g6KnJwMf=Z~~t>?B%s2kw>;O+1=@GOKgbZzSZ(3|@eAq@U+{UL|v z|JK`4-wU-9^*6HR=vRLH0#BnX0gzMow`6`6N#-2fTtLNb^kcjIU-rOq^ZZKYNQSUY z<{Tgn&VTGLMN-BOj8V^!esDjo@WQMINq0Z4BG33?wgP%%lcs;ZkNz9l4GKpz0$dL+ z!J32%h{@17pcq*71NMV%dSq=q4ZQ{; z({OwNH8nm{ZUH_nGae9Jdk2UE zYHnofYz9sgKqenm@y(yA3P(W-Ly-6YT4irbK8W)YDnDQy9FY(IkP48?_RVUx(;o1n z?1%va{v+z23PK8`Di8-j9%Ml30$Gso;53K`;Q+!vn1e77b|CPB3kd(X&s!coDt_iFo?~B3C0L(gb~P%uoYM0!e;ykX%IQW z10{I^6qn1x%*g>Yi^2t02N&=@D0er)97v|fpk0V_2xBKB6B{!ZIP1dZ`BvTqdn@oF zb0A(rRYK{-5!wi6Taa%YosBtd9?x)`+GKb<^fQ7vPaJdwK@?1kQ zDl(-5lwukdM^R#k{VKKXcn=Xmb2HaEPy?e90?G&Iw}gPQHA)o>v^^L~CoufZAPNXH zD#+osMj2iWI8+D}MNJlvg##b}6F@9bBoGxqAku&sHiz37P|rC)RgQpyWI(_WcR)SA z&6lBso?!zH&IXcbTtto}JoeClA%_k*Z16xs6oWbh96)^iHJ3cFRQ(tNpo&Kuf=!J8 z+7SG@)ZOtQ{OEY3#%*&3{&^!82XG17&Os#;a9{ng%7i+>&>Bl|Rr<4pwJ7c&wMz%u z<&&)o5;}}I_Zu0QTw^7ZZIRkQ)N)U|j6|K3zu7^ntf`?=+covv?or{Pe*BG5X4B97 z;|_`Iyy4x^GSUZc`!C%l>Q?wXD;Q6bdazdB%w?o*jh0;aTEJBUvX@O#J!!hyWSx9t zW9CHDO$#R#M$Ls^JF;tqN?sHeB^wI4ly&^$f&1!)Yb(rohePBTJ5IIQ#o`qvj7ysz zTR1FnfNfASF^eudbF`1%C#X2Yq61IlT~W6m3l3Y+B;y#_`rgMMAKbuTjtJIec=Vh( z$UN@$KH@LJl;+Os1EDpA?HN-UMeUkr-9An8tM@oHcQF(_CFxIU8L==p8gP#emljw2 z=F+=k!9`)x*7A$Ndg_a=CB65Ilc(t}#-eCH*{ZL)lkG4#8tO-;xFkv~~-`QxH%QVMgKV zPz{J6vhFo4$zYBTys_hOAPB+wfCzebk11;*VqVK_s?2@JzC{H?)1dT)*W)aDZN|ic z{Oo8f+Pw$C9_!1h+;+ha3CN;PB1l$Rt{NWwR8eu|nB2aLdJ&xYy`cE~yyGiN-^Oe?&)@YI&-Y_<>NBKrlVaT0tiQ2y(FVv`t zQ#0Iu;tgqQ+)y*2g+l1`$CRwc-<~!*HTDlEwg*xrbgwX#2q6eRC+DP4FoR`I0ZAYnhrt77-*32U-YlcSvv-6l<*8EM!? z?^S;b4;&Z>olRSIP0X_pRV85AZ9dye#f4m=zy6 zHaK1opKQa9D2~6LZzjc`^5|V<1^(jgYfs51+K8w}CW8%>8QYmZFy23_7oOszU|jJ* zqh!u4!=%JukJr_Z$Qz$z4R!Us zNvF#!q2Q)#vqHU_S^%T}wyf&iJGa!8V*K)I?9;Ew5Pv%0)}fp%m14e>&+lbRCt;day3I`w+j3Cofh?$?VFU=8GWG?L2P*M0Nly0-TE zk=OoOXRcEw2NmZ(IXzMvgVgc zt)ATsR(;jCuj_xY*Ig31vMkaq3Nj+{Oox#Fx@i+>r}%H~$-xJ{bC>l6um=A>!SI+gP%cpV&Je8jcJX zDrz4?`uno zI`{$?ZWn%&4Q*2Hde1yYf5&_#;7<6lXO2C-2dWj`p;A0 z{2eS-x3ZYLyDq!0txX6IW60)^7fWfLO~+zol53B>d^a=X5}Q-uy{|a;xw9_37&?@? zpZ~J!+q0f--TEU0R2~eLioAxYPy0 z{@r-bG0Ny8cvPu026F=`J_vZdgZk$^Vm)U~hi$0!5-|@*kluHt|jjzZZXi>i0 zhSi`^aL|y`l)ss^B)%b4sy+rG%~x@Kbr>hZs)z9jw_rPFnvY75%ZVFAEDj74&L6st zW2mGpP|xW}B;RcJpcK0v>7jS_@LjDzA^dMH3_Qp1`e(c?*z}!jln+)==&{P{7%bMN zKi4~W_!1dox~X&-IfVr=UBwsYp~Ja7`wix8hW&dhcGWQ~$7m%EN=f?6)I4*2_}QQ6 zq?bTVaB;S8b!h9p!&ONKr7^ixHM9)P?qiEBizy!W4=8_`7B)Rt;Ka{7E&ka(zC%5% z^x>)7#f#ZyWb}TDgtygjIT4+Q&ZcH8y$E?7+K0{aAh*_C|BEZNA%@@$LXGa%-vvq2 zMN5YRqsX$qc6C|LG8Frlmn=ThNvj-s$wWlzQue}hAxre!2mj9w2x?7s4B9B$tE5@= zlC{I6{VHC)Wy#s}?gv;1N2(uksfwL=EJ@IcbI^o6#bNfz0Rj^Dz1Nbp#rEt;isyXo zwZ616e?ji7!iMLe;en{n7c4(XujXDmt^GQbpfSe4T~y}FgDSDa26v3J3?geUmgsT~ zI3j2AE{na4r+5*eIC_Ae1xs^*)7@-OdFV##f`CCeTTMMrK!KsCfhDub1DWHU#`L-w z{MYIAS;rzZ&V{x={i zkO~G;i1GoWJ#;|NK_xFRL?InefQ1LZL-84*;DNl{KzRz<3`MU-V!nw#u%rO(HqeAa z_7phkB2c10C8XeiGYmk=9#Au6Wr3nFLM1=Yk;5?;0Sp{}5vYgYoB_b530W$kYg@4w zA#C92i?B-j|Gshr8VO`ATgs^at`q9@|9A%($j#XUD5K$-%X&=?XGw}eGCAa7a%f$a1lM-ks)CBe36DGel04YI5WAjJT}4(N2O9Bti!7C{r}9-wP>R`%eAHmbnN zvn{axHZ~^E8T=F*lMA_z8x~==;*OvGg>mdyT;0|gaC3o7$Xi-1q;trBFTQ{^8fEcy zLtQQuEWT>iG~TOR#qWFgpv+0G!m85S><+0gcl$M#ZeBuJ7s-yP-QPYXjDqWS16hF@`UxW>6fSgKmFkxJ}d1erZp)yYwG#T02YQ8eBY`-n zkMzDZRc`)Nnv%XiFMiTPwV5ogNqpRt+S%>OcM5#f^yQBv`h2T=A0-)P%$Pr^=9{s6 zO+1{Xbpl(MTrl8^?}-cTIphb6>CKk*y&9RjtV`eR+v=`$rcwvPG}I})INh{EnH-OT z$4sl}TnF2&Tznk==b2aNWbgzP9^UcfsklkD*W%tQN>{lc=e{oWxm}8QHh2n7=KVO8 zH*7qOZVj&a$GcX1d+&@mwk&?}Azw&CZ1p)4mi#a^fn()2h4UG&Bokc{ciQi!;`Z@o zB(-+1e?a~%@3onYFH}_HPIXlAMhsa;)TeGQ?8^KqP9YbO^rkraYOXlJw+X!VG+T^5 z+_GHXF`olZ5+c{-g`(sQnJLTm$G44sIdtIo3G9xSw&Bvt&TYxNNG$}&zTd5%7{~Xd zi|4#McSU?C?CcQ=$)jWvSbLcStt48wac4q`9(f!xAkW5HAYD1@Yn7qmKV};m?z5kU z#IU2XR=41w2glJF^4y2ltBiYJ5^5GarEWDzcIOqjh|h9mW-4dAE zr{`I^J~L?=9-cUJ7%KsnKq#)dyqwZoEtln;FI97M?Ln0galKTM8y4M98=m{Ry{gou zthf^Pp;OolyR^HJT~N`P*Vp%4L4q^Oqclk^F@pOH7Py|c9Bug#Q$(aAhduK|1VXOH z;zV8$7T2UBnX+kpA|6Y5u-uSn7skVn=NUM{g1-rs)>nL~J=dq`()60S z`_3(c3$B?xiiu|VN_!GjIRpmh8*n=0WIom|%!^PV&R=xxu! zD$ZJ>`%!E<@0{h@y@|W2>GxthYm=+8zQ1hy_WDj=v&MNb`7H6<#npG;+xfIHr8myq zjuvY;JQ|o$du=r<=wsweC4a4>G{~Y+E5Yeky33 zGjyCTIQ;!Ypu}!>y~cqraLbP0$iS4Z>#GQGYh=E_lHM3N6ztYBB>(Z1_f_SR zgP4`!H&hu#Yi?NM`Zo#qdOZFZ&=kDp+Gpi&7otasA9ly_6P~~us@DS-=lYsB*d;OV z)F&2weELEQ_vC=wtw}cVcRjPS`a+CD(>~VSSeGWlnkZfE(l~nbu4?VRKEsWJX-*+1 zU>Eg@-A;`3#I?fVOr{}s=^nEv#3##p^VCkP$5uuHCIycat3LClImN91`dM3n#cF^3 zrQxAx?TXdwKDy^uLvfn|{Z4z5cvHqs^J6U*$mbc~{m>mR}cwNZ-5vX0z;^ z{3vX;SY0nvm*;?YZ7pr6-u+Kait(ZSv%~?k)Xc$6d&YN}UlcEXm33tON=U-%7{MZ) zV>ceW&`)Z*Ff%bBf6yWNo|;F;G2h0a(+%tgTPHI#s%l>vO`oq_U7dGxch+RINmiRD z8EG5)RunlG{q)))#&HAtNROw-9-u6nE$BoT_Hd@wGu&|* zN2scZ@N90cs%boP;Z41dFFaNjMlVdzEnk1Hc!=cPbxDZ>uap09Sj$HE_%u!LNp)8K8%=?BExhvFEaWui zCYPQZBNq-649^^vFZFBlY5i0)pqwDkI$!8b-dsv`n3?|Nt)s{2@Kj2YFjN&(okMPB zP1>Fii&l`-#WPh7%-OfWdhmPAb)JD6mv1L&VJ@zXcgKdj3})ElC+I09tQ)#|gSTA( zYl`WKb6EP3k2IB^ip^^{y)(SK9*;dT_52pw`zcT*cwdacrHfu}7p$KgDblEGSR%ZC zM^S~H0c@O6Cn$(EO=Qms-x+d{6zj(UPO z3FE*a)AxvUrXj+pqwgtn=y6p|DBez$kR@j&%#sy{`3Ky*BTsP=$5aG^C^TvJ{M8PM zeM&F<kWL>m=SS-(*N9x-ynq*0eAGgFWhY9x0_? zT}$l5*RTt3)?$)kkUl&h_d8C4Vt)R!twBIQ0ELm{sLR<8fgB%eL^Wc2&(VGnkk$~c zlknMXhg-aC;NlxGyByCJgn{3BpZ+#wh`zP+3{OdpXBK;l<(f|TaMZVfVU=t*5A(E) zUiZOf-!q3IxxZeua7hcE3zv_L#S{;JsE};y9j#_lUsU#(jU|wAs;S?5Ao1H=VYP!n z=}0Aic=hB91vk6ctd|=r^UE|k($s0QqGc~)s|I2VdY{fJgc~K5MYJB3->tal-%WRq&$MQO>?=;l!_vH5eF9gp>z9a4aI4=>vB)}x2?n00x1!=J z4k5gTxJqVvWw;{<^BJZctE?w8BD;0`e0Fw}r1#*>y$0MHEJL@i>m;8Mx#oPfWis2u zW4(@8{C?}H7Z=~yea7P#<;|cyClR0!_=-^XoYq^D#*Y)1Xgqm2nVt*^(TRQ9m`F(d z7;j%h_@sySkl-_)DcAY0^HFMno_JJP(E0!5w_V&cnW~-=Im_!2Z zHVfF=L)V5p3p4pzI94_ z6Q_YF6V5 zZR`horD;lr!;C)IWxA9fvo_W8xp~eq>_+KV;Wzl9W*nCpS6Mm=O(|Kv&SOqYl1vdD zJATVKa9Bx->#`7!*zIF)WbH=JmPWs9Q!ABct{5K0qd#umGkb>Jo-*$}*#iN5ilFJ( zu&YBtA<=}=wa)a7T(%)PtR5b8o<#jmx-eZMuha5ct8*LdK49@sU8A%-3QrJ=`|;Sl znos>cnfgb|Y8G}i(W_5&_}4w%&m4UL%kt|nJ;HV2xUuX0oSYZC7m1B&l=W@S=_`7w ztQW)>8c{JGP9OVLeuUKgN!uaM((5#ZQIhlyWpbB0jmsQ z){p0C-ygKUWkx*p#FCA0Lhscob%VR)bD=1$tJB9T^6jeGj70M84AE=hmCdbODfToT zlCAib4^ol5v)n`WE3bgPLN*s2XzC{=*da+x4Qv50GBVp)EYIKg_aU9Jf2g0phKm1E zKW+KLL5d1kbp-rSwp2*mKn6xVfcoX9E6{JGvgwDS16JWcsWTv-9_WD1VTBO#%|N*W zu0W7b5)D`_1%hco*P#7mKSON#-GRG5YJkqRF#&$#TjvlaTjw0$-O#}e?n5P1*Va9# z1h{~fLU*^Jz&TVqbZzTEuk-)xFZ5(@NT>GS(#EDY9lro4hlzmk4!u8leo5oPwdt3? z?XLDexYZbPvhN_gK@RQB0de~8=kJt63sc2wi{uH-@mUzHtAg@YjW4) z#j8oZl!6P9W3NVNu6VC|zLYYLURHZmRh9e3w^IM>##ckj*TMW&0pe-p?``e(@1@RN zXjW-lx^c@fMJpp3b2!ZWlndh%fgxw|Cr>(y#VlI!MEmB5Wb^dahTr>Xsxv$Gzmo6k z7mRvBbo@%Oy3wp4OXk}`yV~2Y${qMW2z@=Tnuk{|Cc^SDg)KZ9Q>8pjrT^Rm2^vBc4leAma$yx$L` zXY&-o)bZEECS)60K370W*f{2>^4>)#$0|#STbg{re2<0#lCc7i*gdU7U9!%PO$3xB z=J95lGcr^4`!K&p^-O;W^`9yckAEVT<)wA4pgj?J*ygkU`54U&$diaQBFrb3`5vag zyoo}BUkNbY66seL<)zl*Co{_m7{~MK92Eb71=vm^JPLV|L)$4PAHCt+c#c7Y(l=Ip z_Og)_p`y5w`o%GgIcCH9m+GC1mMLE$UV9SJGzhqZk)Ma4USgbZi{-s@FRngLABk^v zl$DXN9$&=SH`M|u@YXbHc#%+s2J%AB3>vKuMP^Q*$4@h+-nv>yrzdbf?t8AyRT5yx zW6ub?#Bx zUd49|5jgbs!~K}&*OQTb1yN@ccvAjb#0Urx`!b8OTofNyKf-zn-s7Z)bv>REY6|0p~8glkcY$xVrf~;xJ-T ze@rWsyM1%`BJTy_fBV?^e+O0nLoWHh#*%+#SpR_~)~Y&o*zAaam6}#DT_ncO?@_J& z)<5ecO;(@+3NHdGhsx2FR>quu9~ayWo!lD|2CJ#0DHB_38rd=@jdg7sw9d6IY}M!| zk@Q(tus+r)0o8nNgsN9U|32+{p9b}FM5$2XEyWe>+m%B|9GwPnG=q}rP7@3ENOF{~j0vm;1)mm*m%4wy01?}w_LyQx)Vr>;E+A`^<*a^C zt)Psk@?9^Jnh_ErvNbzCPMIH`6KUi@WJTMsbG@(ZV;~g;&GrerCnb{8@!%pB7~CEJ zFyZo)3|R-Wo{WZj7R2V~g6K%7JE!0E7l;zTht4RCpSjm^;un_Jq2AN;sL_u95RV#! zf-xc0FDwg1gAj8VF$0yM;X36jQFvk)-4y?DpS3iKft!P|yrglubE_R+^p`U#_5^WWup{di+6R|} z8*vh`JgR{-7W?YqW+VB&$>S4`dOd0x0GO3$+VRhb_s9yq9lD}a^ z{Olv?oEDfHwChO(J^Wt#L;9k-=Mn`yMAfxLvjR9=hhr)-nKLs);T57MZJ8^NdLtTu zjoNFqJz%t`4yb>ZuDt^35Qk#G-fJouKaNTtra~KMWC*v}3KQAXuS#Q^HZ_!$+{hlj zO!Sw~sVisGaAD>HCW?c%I`v@{j~fJE)?R0?kn-{wQ0cMyIPp8gWG^y?9@yEty?A$* zABHL>h92WPWog*FOf(1~ z9CszK>b7l3y{mhQ8+H5)ia3jRVe|FZ89KOCw2c~1Z^K8=PT-3_e=Ho^{Jk<-mR+M( zsrFnp1TnOZl2LR~AzfjVRK*Xyg4sq#MQ%Qvq{_K^=xI}5vUgjpd53OXKuGywzGP4D zmSD8BFmUo-*JJj!2+CTB-7qq8-~eo>0R~Ec>S}tP=E|1NA8woU_H`hl`4N1#<+6M_ z-aK~>P;~z`^7u6%WYDfTobP1(-l!I3tMY8<;cY%|9_b+7FpR*e)(+h8=KJo&;DjkPWu1pjm*l) z`hQ7DBy9d^?*B)d{QuO_{!`KzJDdMkNdA91k%>8-SZ>_DLFMz^s;T1*G&jifCEJd@m}H{_^Z9l8fRb zHZTQR@^E!&q@hW`tp+=rtB4LNwpP$gb$A{1c|L`%*y|;3l#T*>sGgD-P&zBSYfxYK zyo6#i`?hu8%;{#m$^{$UFkdCBt6h_ei`7YWj-wZX97mDs?fGlYRnKr1mTPs_dRIp- zD_rMQL8#-3tzWVm;HTnMJR{euO2u|T2rjn?V8ZW}8=w9CqX5_f{#DvE?q%`LU)y4R z#11U=j&axJ2z5U3=*!&i-IaO%yCqy* zZ$g2sw<=HEtwuMH`i(H6OQ{ng7Uk}CNbxdf6topkmz_C>Zo$A??(BN^?0Oe7Kad*Z z>gsUkiixfycFP*Glp155vg!Njg#r;YJXf=C)8Q^7y&F97nO=9-#V?VIPu?N7H?e3j zP$CxIJZgHc%(e4ceeWx$92l?53_%hyoyqC6e7TDN;gd?jIex-mIxXh3m1|iVd=Yi% z@n8dskB{`{rTfIVcwsA%AA%=bZx-53&Z}<6x1ZkYwI7v$q>K{RlwOlZmvS*%&WnL7 z+~R(CCgELbL8-2ti{_O^h*V(3WG%qGy7=J!w-Om97hk>snY9)3)OeGz$v-1S>kpM< z>!l^DRJUd;4^nnL$VSO7lM4^7c+O0k2jkDUO}Oy>Ck|ID4psC{xV(UJP`2|Z$YmzJ ze#fQaDY(x?1Z+<4xCq}#8?Acsg5lB)T{}|&T#V748*&2(kAKnh5`z%@4v`%IoQk(DyaZK5Ghc%1Qw`2mrgn-LJl%g| zoQ+^!4yUkfB<5jAQogR!r@!zYoR*_&1OWQMJ227RV>{xNkf_IZFVy5&artTYW&Q_B zHoI&bUx&r;K&TCTt95Bnv`X#e5O@AceDr>H!til)C29xfphc9~jMe}u`r&nBEL`{G ztdie=wdyEMpq_uPE<1S~c@biaBjz_OzV-+|@4$t{%ppp%G-+FrLmDWVTvJg9q8Yz5 zb|q+d(PuilkU%}HJzxz*IMkj+-=Xq&6!%fJc6q=jEyq>GVCr5@3ePO&4C?Tq==ssR*CB$t>5`4mt}h zl#m!n-D%dUMxDxX7l8Qz!8I2(X#$HPoBWR}4`@r0Y;HVeSK#Lhgfmzme8EvoI1ZrB zgdB~qEsYd$4~rs9u3{tGiYjVk+UBKdL+d`d8Sb~%_u|5^+iUNo?1*~7b|&Hk3A+me z0pMFol4Hh=M`KHDOacgkR)K#Lj!bVR#GxRU_;y1C=}(3JA_6q#D^Cj8oBY1-x0EiR zEhBMr?u3NLrCQ?+!bbbuBi52!eDzYT{TIUJP>S>!Ux8Z%`JBskP~Yyxx7J%b-O1`! zO!AGbPi2zDVaiIRN8=-rPG2wm=ufVdo}>m%&wvN{Q8ff%<(BVa5l8gfIGVCoWT%SlD10>1GbyQQp$iakqLKwdigShno68HsX=KW z?y(xWhH^LI*ZzpSg_%AlIgase$Bd5$F7w*im=;&}62hyxG~PXXs^%u*?hDG(bY#Xl zp?}4?k4c+R-Isa4{Vi`k_XVqrBpzUUWSTh>2cT!aL}k!BIdDST8q}1V(5~6*$hU-! zzwM%*Aq}vB_K*)~fi|Ie71w{QLbDXomeO8fGU%v=^M!iFS+{PonmW#kg_!C9zbkX!{aweYHwh0NwnUodQjjR*S&zAL)xsgOBy7%>ChVeQ(wL^sAbrVFq0LV zU+Luj)sWwAdiSLnL|c;)sQ#MWPapF4k8m%9jQm05;o3WBX%VH-bLHuSN-i%KNs(< z+f~-(0=$yA7^xlV{rSOr43-x0>vT%~eS{idy{>Ei{*yeZ=Hit%q{bd4uqH0FX24Pe zk(P&suNEbxp(^LO(CAgZvaCi3J)SYAxOeBZ{8Sl{0&Dye zTJ>3cL1`-QSz_!}9rECBByJu2L?dcHxoP_#&7f*`V7n)$Cxj}YiIWEq(%6n0H;CfYl6#A4(;nM8$%{~dzPG!>^ zp?K29#mte*ibQbcT&N)gjf8b|Lk6fl3P@3P7VR*CvG3M?@GWQVc0KPnCf$>Mx)pE; zLQrtStxR0hjan&p1aHQ5UX7&|9{2DAo?+>R-`)9F4~cm**}K%>i8^2J?=izP)Y54EJ!)afH@BhNG)pMb zUfe{%=Q92i!#HS|9zFt66Ucvd!7Kjn8Zc+Iw;i{6i&{i{RSDNLFgqHP1V5^7>~4cR zwWi9Qk`9tu4K#cRbJ#lqhh|2iaUSfwt1!QET<{$I%BTfFUi+z>PKd{LH(qD&>z_?X zH;KtP9e>}8uqnZ#1zQ3I%IQci7286!6QC`(k==&z6iB%AJN@zTg+S}6W zj)>+XpJxjAX2#XZ7#O<*x*8(#&Bs3@WhVoi-nz-`Qa8khBVc>S(30*Bu$^pSBuYKC zDr;RpYn{c$mb?>!Ew1=S(x19m^0l-V(wZNSMve^xE>w2$=NmyH!pzu-HU+<($nG2K zA{0Q#1%^HI0=t9Q-4yl5?dhAIUB2)2!MyJ_==bv>e|3MA3Cd=wLiOSFoLu6+e1O_q zIb{~Stgk2&a05yG)&>NDHr?p?$LKrWY1Fg|j-?Q*1SHO)9(y?AFo-Y$pD6Wl-`93? z!+cz_z0D9hs&B@STXl$&rJ6g+biw{PJrStCTk{ql9dbk1=)*3>-dT079*2`*SIWcpk17w9+5hARCM z${fcnt=_$=eV;fFuVFv;Yqf8CRa`YK7#w3Jj?1_a+xl>RVEkKCXUpj+IYBDWJy(LQ zhnyb&VUJQXP(;s~85&E`T2?0AzQKo@{0#MwIjlH5l!uh&Ms`25n+FxQMB<6~n6tR` zrzSdrjr*)|T7$g1rPh;w|ETp=t=*jZV|3(%8F&gGXQ4MOqP_9tfH2RVC%t2w;TiR8|yc4QKa{NbrBQ{_;D`D!~O^OvGbRS((#{QZSLW6x`ByD5ECkx39o=9Vx zTSDJl5}L2@AA4=2t=!v)-&@5#dJ;Cayh(xd9}H-fNntYv84cWV(s^j$7hM0_L*>M*&oBQ+2EFHria`td{pb9XIr#O^DK z3VLd+>|^ld^hidR#s0U~WDosjVCAfZr2+I-FOVg2w$dw)2|g;jhm$zk;jEV?O4RY1|SaolxoebSTxxD$6Z20d(^ zgwGr?R_pcL>_-n9HIRJyC^wCgd!oS{eEB}mv&bx9DoGgo;;-{*YQz1W&L(_7B=PMsiQz^X(8I<|KZzpu9? zwP|$J_{ot8{s~k#@@wt$f!Xax#zk-}f%be%lH0E+dKq6VKRZkuOO}?)Ws>X0`}i%) zr=Mf3aohSL>D-o&QuNqh1n((G$4qyY=*pVQhQwxb-WH3_oN(ocv&Z#*a%c926F^>+ zEcKN;XC%hF?9NuL3-188-VaR7r$u=7>*&nS_u~U*{1ON_M=-^mfDTj6kP_w;8X-E- zcrujVqYh~Abt#5Pc&wgu)KbnnnB#2%SWV*nc4zQ);=;ikVkVw{4XXadpUjo!=AulG!8^Zt;wFSGYK zjAHwV=GJMn{33ZM^HVUtK*u)D7alr)Lu_B(O%BJdS0t8RO+V zBq8CT^u8w6?qHVui>ae_Iw1YDXjO6feE=%%)lx2AR0--=<6p*5q>k$KO*>fCP=J2L zRs5^`vUHFxlI*+2&N|+Z)f2VuU;L`R7`_j3i{ce<0Ju2bdq!`~jdJpIQiDYwbk|d? zF^0n`=Fq}GHuEf5T`oSL>fFhH9<)fN!VZbTMg%bX0h{5E3AcN z3lC8PY!H1zb)jA`rC4XbtwVy`+&d~CzJ zIXZ4o$ECOX;-}5u^vc6s#lECy3Ao(E^@#XfSc>&Btv&m;*CBIiTesOs0Fh;)jFG)O z#t^8sVRt~gz$4)A*jv__Rck31+9AplE_!_);jiVV7X0RQ+MX#IkPZ10Bo#Jfuuytx zs1hb4{&Jn%dX_M(;@(`Uin?PPfV3AECzr6A+c2hRZDTj%#Np>^2z-ClweP9>#hd{fvH{cZeG~&*UG0yT z^I`4&u>@FpQAe!&t}}vi!--XvNAyj#2Ahtis#3F@G;lfKs;WmsIt{retaXv?b}5$Z zDm5rB5cqq$-P~FmYB%vDU6nT4IxWx0&eakFD=75T?ME_VHm#x2NHtCuJqG(Iwn{qu ztGT!F5RykI@dw|OGg_o$lxNdGG4E`YT<8%bdl@4uQQh6jgCP=YbM4{FlD{!qmZ4@c zz6M;f@L5>^g{_&~S>dsL^IavIFviJ=+%2nI8OR-zd{h!#aO?1@7hz#dI`3qC^#L)q z+hbNO7Ac)&$i*MrPT#FKv2{+|tnI=r#d~|iUWQ|JEeYstWa)9pnu|^?BZI?vV%nBIDJlvTGU$ zd>!{crk-uEY)B<$5bp>bG`kK1YV7)*rLaGfV#?b!P2yxk_tg-a*a-K`n^dA=wU>}H zO1ZnC;-x-?NGdRB_!Qb+D44%SC|xS1=w;4vx>-<*>#xm(&Ej5hk~HbL;ftm&KgmR0 zLqhGoPGX;V)(c5XJydMcm+B~g`2A}V9G8rt<#d5K$s^E$lyDeATifh!9 zcS<`^BP4QG!L4x(K^7Klc)7vCr4wF>f+J!VT)*&CdYhG>OiNP( z;YD2`$l507a;)nv3I_{y!eb~!T5O`WOw5^*`pl}1c!FNK8m6MNOx*Wt){?-R!H2I) zo%ZwkUefBA&$E?Z3eQ}aF`ULJmV zjwbw3l=zbPn%E9a8a=Ssg@cQK(a!do&fC03$T03us!LMo+Vb7}B<0H(UKK~%Uu*0U z)_du(^YMurQ{7)?slLeHChL6Y<7pEwZ$(aYO))P?fL^BR3M`T~B2^}eY!jRUcXa|6 zRt8ULv%_K*Wr}n{vL$R#Co9t=xG6b6mB5tR1I?%S6MxRz`}T=-J9AbRX^fZB|DI@p z#Pz$S)xtAc6BwvqxmNEeEFE=r96@345$j=qL6=BlIL-dqJtB8QI!H@eO7LZVnB|qUwaO=TL*(-7xj_X9@r zOMKAiW}@u+FOrQ)f!t1|T#r&J8}!L@U%~Cf@6*Lixn)?-**9p8e+nhcr)+J2A2e!D|LSu!Hbi{>hi`sTC)Ss-Eq8iJOZ_uk%DNCQ(Y$ft z=vN*ria4wHn7b`fIdb||>5}!!3kNXAwIDx2B+Q|(u0y+K2WQBmEE(|lnFs?cUd?s5 z9X)8ik%D77Bq-BnLwyYsDrv&3KC!wY8$074&A5uCYrJfqyBZ7ZESyiiGMI?aZ!_{( zYDvQ+oxBIRi14eNlBKNE^kQ=zfPyl~K+%^3k%znQiVDH?6qhE(?<;yxE>tM6i)aqV94hwRa`l$4!~UK)mdN z3>Jo4XAB*WGHC-Uqcf%)7e4#IufuEcIXSo0j+8e}t@q}pZikof(q(eIoeX68!uNf? z^w#d{%x#Lz28`%Q=AhK65MWg027eyM<==t0aT`F7?KIk)nyAl065+KQHK&^P*r^J# zJ(loO)Yc4V9*EC5AuKtJzVpnQQ74D({^2GUyn*WAW{GU`JGbihR zkc2n`ps*MaKtQ!?%{Cj&Q#1c{eVci=-e|V*no4K+AL5i0>wQFH zw6-Ztb{BR4Yt8fG)%OVhm`ccFYwWc#{X*7I;lF8V71+M56!M%O*ma`y@jB^d>X2SE zX(2(qI^Vq99EKTfs#$%u$deGt34sh!g1 z)Yy$<`L>?9%fxNwZERfhzBIhk1_wWFi}JZC z(&qA#;bC=~k?f_A8pl9MuXTD$_NCEDTOU*nYtCf(A<8B5N=}V)UbVQc)vf9fy9Hx2 zobIj(Mf=))qIHCdtuDP{>WUS+t1LCs5iz1fg}S44&1Wv~mvsqp^*F zSD$EgdCY^}z6NRQSj~uQV|d}!FX9V^0py_I>;K=JHUH@Z^#8M;>`d(c_r7DH|JdJ7 zHAs2Xv*v8zce_70U{?-V%h!ECQV>uHsNv%Qety8H&JY3$NZ`iwYAZ`RYQo?Re)(b5 zoRyeP>fRw881i7!6#M6nLo_ce*~^|kwIAo6c2^aiDmP0NW$y!N{F%33JDgR@sTh<= zlBDP?EHoSx{fy>K`rEUq3T9 z8z*sW1{)VEFV8gA+BX}a=rnC+7t7W;2GTg!TN^VQFL|hN)7e<*Y1xTYN~T8V&Kuj- z+Mz7c+Ak^BE1hkWhZ`$5KhG?to#&KoW)Z7w*TGgQt!*H93CxQ5$c+R;=(ve#M~?KS zlqh}+=P@Wz(X>;51@{+s^v{ShisxZe%7eYglTf23qDD+W54i;IR|_JEeHAh&6jG{E zP0zn^pJT(A&>vBlB;UuyuaC~0Vi$Z2Lmx;CmqgWI_plL?VM~{%;YmX)O;~D7c>u!y;E9sX! zWzo5|Tje#@w%j(4wv;xSUv73dd7ku7%aqGf(W`V?=A9Rw2a=ktZOjijrW}>fDc}#N zFr51}hC5kfY|bn0%+52FP7is=$0f=a@Ts{x_RolojF3mk;qf_M`cnriqVs>nqJ2|+ z4U!^ie5Ouk5>u^#9XHMF%KOvJtzrwYVmRSeZRcg!$G--8;gt5Ofj-Fb`+{YI=zQTQ zamxEmn4H4pVTECWsCxIxgpt0?eu0$Fss%oXaeET$R0gZqrw&Z&j}DeKG5juGCb9`Q zE8>e?G8!K z9@QqMvLN`(8kjZ4*4j8^`xQKEWK*Mu-_R$YCj!@uq7PlHKMs}|&}{AnRPqP95XX;F zpSl!iuq9QE%~xUj`uH?I@1oz#uxEo?!8y0|M3(<~oEZXmy3?`P7nw*&zDeC2=eOx8 z2XMRQJRP13&PCI_Y@E7@*`@cCSWaW&g=|6?>1!p(!j_>%u6~i4#e9~(h3?>9h7UNe zHr31u%hKt*K~%oJ@P}OR5EUb&@mh@~tmR9V`~9izu3=$I9pd7QxeJiOScUbk>>zOz zaff*bgYGX(!O65u_-$Oc+1BmHS^u$myzqH|4b_b2&}R!g$Its3Llty=q@VpA6?*1n zu#0;dYWfl<96d8JRk%WvEXjHLfLpKP!&6Ld$kyJP?2a3Q2$^j;$~n@*)A=;ZcQ=>@ zXJ%_b0L04g#Yq+|kwJ-y#@Ny##PaLODD*BRBd|hZY?w0b_z3WEpUA%;Ze?IhbUyHWORE(3>V7?$kPdexNOgzGz%9b{P zXB?r5IdFGvE~@Pca2ix119}fm80?bf$0Ew2;F%7c>mSZr+7lm-+jsd?{)n%KgrS*Q z>c8oqzcXJ*x6_7t2&un&3ZA=zb7NUSx&;yB4;U7S z!KsQ3AmGyYr9*6I&#)*ehVn>grcE+oVhLAK+(eEII z%mYIWoe%LGG-(UN5X3qB#?dC+y(|4o*ZjD~>l*0pruVjVkdD3=U5a!IVez-a5mD}% z?`?hA_t9JnNh#b?tD~hc3^dXX$A8Fxr)dN$%K^d`QVtu#9=R`^bTVq6 zkq2Ut0WqY<7ycak#%a#8qIBI=4-OJ)vdSN77rbm#&@Kw8E~4?>9#LR7Qj|Ta_ty^n zoaUft^wsD=Z8S!>p=)-gImSY40g^{EdgSM|U zmcwDE2(|W5?^Dy|tFUz}_$^}*u0{z`e1t?#_8P1N=Tv5v#-;yw*|kduQf|2Uf-@8z zoS_=W)FJP3*4rH9yGq{~6$H$pAh7c<+yveppK?!w1jo?)Dp(&AJVr!P5e2ip%xwY- z#&js7Ml&>W?a z_PNZOiqQ5>5K>qJ{Mabmq!APhCVi#T{@d8b*QYh+wWH*1{qirBgLL)d9 zfJRj+Pc1fXUmG2f2W9Yk8;vjV%5P!`3;(}gs(#>wgYQV*=R#DkU;zf zTUHElm*NIBpr8yulTs=)!x0IO{fzPu(&zXRl9DIhVecK2YM)u1y?#jxnf62p%M0iPw5=(~3rK!-?XdYGuXFES9a$SG- zF37n>^nv*7gT4gu%cT&d$NHOq;#SiRi_8eA*aIb{Es-sPh2HJw89#ds+9eOvH+?jSj zcbmeqc!ax{2SQa|qI-8hMm-hvY+xhi8=FF8EWNjup!Uy*@6yR$c7#htaD_^S9r};C zB&O`)^^c<4555<~hXTX=YUN*1$0od`%e{KIkCh}^%|_AI3A#7a=>*PBwf#Y$IbM?2 zWS)8rED58fub!3A_KKtjOkvllMZI^oNXwWjuFnFF=xA;6hEAL8o&8~r0LUkIPUr87 z-*{*={;OQ)f9(YJd%JgRdw>r_Wv0=f4S1u4m@iAx4xab45U3M`z(2j1!Pk`S|59-v zwB@IX=Sb^%ta_7qNgJNfV2~a{CiKrIh>-G>rm*4v-tc9*tF>ag{nuoDdJ7-DyPHelAVu+Ynb8n`~lhI1p z0;?=2z6x%_xqmVjayZjNU~6>T1?>w_#rXCQ2@rNKuU->mu3=TT6L3*qg;idVw&4X` zWNlQuhI?q8ad?+|ga$oSuf|+Pi+_|EAzS&xzRyxLVt)9Rf8;(F$;ssxGo7m2`d|we zX>Cq}jWcZX75#CN#^AFs_i*#C;D49^HF!}{Wby4wXafk>^LZwyzpm=H5W*{V8c*A# zfr1P_x?lxckA^?41NLOtlwMMdFy>cJybdy3e3c-k-S`TUow{VRc)r8MD! zHk7aiABhp^)fgJPF^E+dVv^eT0*&R?nq`{JvXSlc6%h=HI}}~7$lI8n2b+zo#YSSl zaL%?%a2Yy({l%$*Qp2FY;Wk2b4Jm~$hU@$7tUBh$m}ekcC}K(kN`~u|>{3do$a?uJ zD(Pjms~y}a;VtviMCv5s+gf1lJU|gIRfUwHOraCPKZW3y2`rtaz2O#8hY&2FItWof=U=7XiczFhgHsQ!Gjb--`$KVwbcq4R_G z_MttE%H1&-B|Gwxm6?gNWdx>B7xS$_*ea8JA5a9*a6MTg9O_^3sm6IN1X5-=f?Job5@WT}UTN>D*)l$-mWh~goyyim;wT*{6D=Vf zt@q?BH(Ymc%aM8JnyKN$!4ld4bW)i)<#1r%?8vc!!vTdOiyOMow}*3L4?yCZW|74y z$z&dX+q7-RwRq{?a^-H*so8o>Dx}0!Dv^cDD$jb~SqLaDD~^`&8g@B$b@-WrIo|3= zGcZ}5;RqMoLnygP)n)oB!4zQb&TMlsov2J}fS>XF)?Bqxd!>H$dX@N$T2nHGoVHD8 zc99*-^s1@Q{V}}GZyRs(?XG)_o_Ii;gvoM?Q5QExb~~9#tI7B|%h1w3ghC!bv{=4(H9_S{#Uz5jA8Vp43k>h8Lz-1k{5Ds8$}t z>!8TJkCa?$b@=U$U#|W``b)sKz}my8_#$SB@evkHDkfW0nA-6_DHVHsod(7D&X-bV9h#X)e5r~7(3@+I8Zl9pZR~FuaErQ zdYP_U_+NCs5N~zbGg@2y+}Jgr)G>k*#f5g!9iomVvNBB z|CJYP8X=&%rb>td!Cz-E?P&REZdLGgnW)to8~};#SALah7Vn4~04aTyT9GI2o6#9- z!zI*eOc(=QdDsHQoCNDyn*UBu$JN2yDLbCjMgr~0U*KQ409q($7)b{TzM zoxNYA54 znyq3STmh}7!#l&~TgCWfPBo#kSYTyPp&cogQv_7}yebLVjQM4 zAU<-!=gR}RnW6uVzHR1~l^@zMStW|1yQ955C&2g6+7&>@BM7S(=JqTTDJ5;>`uP6L zLqd6u9D8d;0rdpiKqwuha?oH`>d zHin#NF>}a1Z&VI7-cc@1E$l4)1OcpOqo}X&ln9lVUk&$(WcJPa&17 z9e@vTS-SsZG^)UxJQv163Qs`R64~0Kts3zhtQw0lHGKG4R=(F`UE-viYLbYIcZNx@ z6`3a@p$+aTb$1Hl6b+Ugz%ioTA3KK=S<2||TDEuFy*Y1U>=oMI3}V1&fZogQ@ww{@ zxqEt`O-&)3N%}NIuzvyi=F^v|-^3G@V7 zz!Au{Qjuz#f2MkbjXc!~wFNMuVa|4SW2RZPD}IlCDBz5(wJ{{biW&+r=qX7h>B6F` zOk_jy%YNRiWn$0Xd;~|5B*fkCAGI(SU=v>*l|oi=$2SHEzw8@$H8{W9>nDO5F@ws0 z@EY)2j}UDYjKc`&rjZ#J;)wLf;<-LhwzgyK-=q)WG?u7PD}UTgXvrJj?a~&8r;&9$ zRRm&?Ff5D`DB$PtdG*HZO!X+vhUSN2e-PMPz2;~>L%i7RH|R;C9yxbJKr-Hg#uCI% z?ru`Ba87f7VM+9nsSdx38H*mnAP=vz@op1yfq3q{#y&^5qZkM}O|7!jLo2k8*aX^bnTi@Gn!^BvWS@q zJIlx&lpXL4gbgm|9bI#_ifw&x{!{?xnZ_3kvio<0cLDXPO86vX@qMQ;RU1kZ;;09% ziAmPz=K-0jeCXswQ8C6LRgMD!gW#V)zn6bw*EVIjjNvatY}sG;8Ai zM@%Tez88kYX8_YxI!$Ut_L8@(W=j57yBUP@$eaJf1No2(z4(RTWt+m!WO1{PV%2n=K(smcFuSJ4uHYfwG*?0}2!*UNxO{wg(Qiev3hgEL@J6Opr^IWejc3aZ*RFH^ zjo)C|H6io#(XHU^1`KZb7?M>(+N}b; zAEMRN2?K8)48yv0e=zf;<%LbhpDE{XfUnG!b_=~J5yHsZ+hllh zo8g@%+}Fc@Z@MjxM^|2@gN+@`v9Y85a({`?ymv8ZRh4&jXN8JfS`BKL+C&Dvkyb$2 zNQzmBl#FbSXMl533@uHxPzjSiRtvI5)2!XnbSOIKslJxa`AP;`SDZX&n;X2Ur`z*Z z<0`z$Zvw4SNtrK(`IRV?d+{is?nU6o~fY6^97jmDESz*Js*?x+O~u zDCNh4pwS8L-q8r7%kkFVq38E2gZ){&H5TAg#*AEE2ekQ{kP~lO_AQ?twV#lv2l7r< z&a&WCQM$ag-IrkN^LbEva}+0Dhi&V%1vx7&uf&LxgiL_1B{dc)D+VN zQf5{+kwGmCRenB*`9L{R9Y9ur@m56w2JAWQ{W1)YL28lSX)x9KkL7kA-vk{+;B=jQ zkXOcB>rYl2NMFGq-BIj4E0|N^HpO>;E@Jhm+&}c}$)fx(`0Uq7ijO?o1gb~gcA{n~ z$w@pFf@_(#Xjn(|#4#f}6St!IPuraDz&XiqBA6Cz90-eTP-)VnU0L^YMSRWhOY8JA z;)`b_YMZgS^~i;WRxuqnOW2J^FB%UWkgCf{c{C+tD#3FQcPW-*SQ+rc;7j& z96=ln4HZ+P9!c0z_aW8QG^Kt$hny?VIdn3y)$cQaL$yRt5Wc94PJtaOJcP!?Vp@z(sKZU@CI;uqH%fwJ?daW*?+P|JZ>;SnP-5xJY9(T`fLmn0x5$6Er zx+gkfj(v^3#>E^d>{ zMGwptpTY&VO`B)OLSB-v*VWgy;cu2RkcTyjZ;ceLf73rdHRzl9f5C*R1&4p z1FaG#h}06b7+V=(yCKl~Ila2Ur&;0*^{}7hoJ$F)!B$a%%go`Rq!>8{>Rm1wvRK?n zZ>U^8WEa+$C;!&Hqw7PwAzXIU``5c_Zv1bgynPJXRZAl>$>l?uX9_TsYocODbl7HEe`be7wJNMs+UNT zr7wv8u4YF{Glu0RFm!=;27{{c`-+cwv#L)dnZ+vflU&OQnq(`$(~efhFzzdhu4%XD zZ8`b8h;W9@=GT=cbEFw*pS=}dmdz!!H!32SSb-gl?KVutN3SqvA_}0^dyWOJqrh~3 zuOBLJuFU0&{5}8zy%J$h6`A>g6^6)8)wu1j&`GFdCdgEBZ`-&oNn6x(zmSXG4ya~y z77qZ|a?j^cdS-TNgo_j?qW8O&peqMdTw4DVKMrsQsE6J0au$OWmVgSz7|xn1se;d@ zu~T5)bwfx; zgAtxFec6}>NLzJQ*V}IY*?3S>lMoXj*#S5B0?V~G+VRRY1e{k>1QH0uBQSON6Qnod zE#;n>a&+5m7ZgsoW@#De$-0x-1K9Ld=Wne#Won{a0Db#GbPapVX5I3Kib~Y2z6m3w zMdR0roOhV5@e)Sv2^&_b}8oNW9dj~ zvub^1?y_2Aj05LD==EYs4X%+Kum*Xm7kz97z)xLF^U$u_1FK_y0kjqBb&roL;>39C zuNXVcas)EVBWo;PJ1wM?${93mwcR1gnI4ft+$GSHbCes0{N!F4?CT1UZqts_7teja zeHs8O_-&k3ft!rjY_z13jA8E7P&&V&sT8P^w2X>ga>q5ho?{(Hn;;w+SW={aYF@#kijPW}Jlmo+(#~JCk3WYtY3Qb;K*Scvg zcl#NbD=bG#|DmqAO}-x)ISq9+-b<7+yd)7mG)}CLtQSS_&yV%Q*!5xeJD^NRi-pn$ zMIi?Vg}}80ohij*LM0(NbnOfq=X<^(0@B(3NJozb)QL_vcU#98VJ@i$*F8}*7U}Yt zY?8`t13UWY41aM>toG`;QZBJ)YGe4~ghRP&ssSM9l1&3I2XFP+Dw|V-Dy(BSy?m+Y zvb084P0z#;_`yR$S?zVv0CY(IUqE_tl8V3Ermf-auV{YOw_h&twDRSTzL3$`Q{LwUjVhGY zo$P&lqI>@_o0R>69Sm+wuD}*lFKhB~hk?H9Kpf)|R|f@OtC8Y7|4?fLbjjMlQp@<)q>G!`=l36MM|izCa{kwl%G< zj#5EeNjUxaw=XFJu^RcHgTrAe{9N@x8cK?BINRrZdA1gYXUYJe6ed#A;*6};vaFH* zLL<~*@ecI5Z5|!9i&P)d%nEX<8l==>$n`)v!)D7Rd5+0^O~iLAN&1`pnh zg3D%lt4kflW$f|M*7FUyEY*nXdeiSu6(x1bXlBhNiG+=uri`L7(x(9TnKf@;yvJ3& z`{9kaS3#^GZ3RkcwxpyBbhB>1T7KL|XV(OZR?lqV@%?yoxDL@UZ=;mq54TrfP#}7K zi3q8ZC08RHhoc`=LsLU@edej5HM8|%4G*uCJDBHU&UPD3%xcOXOs|FQ)btJqd{Naf z(Rm~L)5bQI>8lYVmKZICKNceD89!7Cm6;F~DrNFY*=S(|;w62!(O40MM zR5Th-)<_!VyAq8@kS-rsNBJ`|i)u9SXiuir_7qR81QTmtK3AK|6;dYAy!jWJ7@fh} z=UPg1Du+ztgPe2T1XT)xKFUS(xK=DehJ2AR^4x@uyd=1OUA@4GVX9Z5~b`{*48t5Q-a`N;P{5<%LU42z4xQ}r8rpV{ZS z7W|%hIuRt#wmKM+AV=FK(wch#6MDPCn(Uk)O5$P7i+SOYuTrAv9cn7I07^7!47Kka zoIsaEmkW$EK={e_TdOTrlR)W4#FQTwNODM@WGsHF{kAPc2XN6g_FG9ikH|{j_3ZmO zm=`XrT%dTr5nlX_qG>qni?Bh+3~_#<)zHR0xkj0*UUGUn$AqF)A$@hwEJb9RIM$YK znYksQ+y!Bf@H0s940Gm_+@1P{vaQlqM0$Z)5vh4&_0<$rbKDT%1e;wjYes~qWcVEv zMrWc_F_PW>xC_SZ$wu4m#NERDu}N1e#zK2xIG9a{H5%dD1XeLOC-VM!$US)P%YHyd zWcdin_&k}O{GNHulDaUP{l0_n{Fnzek;tQFN#0FX*n{vyV+w##i!}nvrp6R`o zwx%qq-)nf1ZtIE&UW3{LIw-(B`J_t*&PLJ#B1>^ZK9am>OmY@%N54aM0c`sKIwF;q z2_83OtG_L>^{y7M1dY$?Fm|I3QyMk8>~XXC#(L41z(_k83+bId{U*>EVY_TN+Kb4- zmEBigV25bPFjbgF6n3F^+-K>D-Byh>k1;=R9^5i%WZ0|!hwTy=>jz*)DCE5_S+P!* zhpSuf>C-DNh|`^b5Be|Y%xq?DdZjD@PgNf#B&57*x@|<47p|I#u4Buyo1&)u;`00D zd(l&DJmwPmlDfG1xPsBS1<&m@6ZM86uXXtnSPVJEI;~utp5}9fzWF>LFuGo#3Yc(+ zUTp?sL&bFTXr}w74AV;0D6 znx&G}6?_D+7)fVZujc)Js=0As`M?v8@MKoUbiLp^GC zz-}Q;nZ|`avWtn^H<3!EEUqo8ZEp-+SLV4c3Ge-_wTJyNW%5@y8vnHa<=@|Ee6K`j z{r9cC0%bEr#AWzP-%}2NKY+0<%C!uGNDJ(g_a&I{@ywpA|$!$%)Yv3dve^=XufnQ z?<&&(7dI0iLk#oHm4nmEo$VKJ3O6XGK}Fj^h(V9}gG5YIi(d|#>Bdo{yTn8A#g-T( zqwSm2btvsw_9n*+F4Uh37Ie;UAgu0|Ma$@vvV*Y0vnGK3;WqTc74rHL&E5FdyZg`& zJVg`HS%`UXhr9c5`#>?ZQecCo-js~uWmho%lfJ+{#Z}`fTBYoA7V0G9{CfzLvpahE z_`nEFJhc%9;WCQVyWS;h;YjB2Z0*8>Hqbez%IUTjFCfe1UB8Vu*`kazEpeNr?_6CiBC{ z7#@I}Qr*g~l`3Qz$=j^PE z)H5zE?{NM}p*`V2Qx#q0F9TYEMjdH|r*XU%p@~@5f5*E2)3=pT&{?}a;t~8ILl9o7 zE}7|f&Wbtm!SD4WIDH4`Mm+=vNV^M{LMEtL7u5ff^#EDzG+DlcMtPdC)Y^u99 zFkYqy0r+eN?$5|}V{fMEpB)n5$;^@AysX*7wU_G z5kn{MAvrnk;joit)FDEU5sk>cGnoP8^bStyfOVEXXM0%fupL$!j$RR(DxHVUa{?GK zcLpU`6su4h=X9u${Q$D?vzKuy+9~5X0;_; zAG`cok$VxI3b8ByzTE{&B(OBp#aA_D7}bevLd^s6H>g1kCIIs?hAOUwS;&V0-I*_) z>!Gam_a&}rHW!Oig78$C3GT9_voc(_$Tt`|D-xE{ZW*rg6Y&wryBZK5Fim zv&$A5ITYIRjI~h+ta2NOcuuQ2vsAUjn~6FyK+QSh*y3ekaaR?A29^p@bSLX)HUZ%2 zZ~%Sz`=Y78xIt!Ui;u<87N(y&-uxJw!B&(g$+gIAQ==9|P#^;+z#X%#N;eLYPH(pD zs42?-K}V<3iy=0iz)CkObF=17UO+!*JL0||^+v<%xCSRnFQ%#k;iso6>W?U`>&1Dc znx7J}E>Hus=ZmM{(o`Z88h?H}fJOF;7ZXb99n)-hTzhU6%qjN3qmK0e+y4lj+Yzbh z;0PR&^~32D&FxL@!PsMoNOjz$M$Zo|+6yDVB-v>)(b(7ada9}viL&UPY-g>@D%Y|p zeGyvcMzN&L=r;k>tQ0^^5stzfjRcdJg50MI3b7%>3us_M8j{M)L>V?{F|6hgq}0vo z<^d1VCk~Ilal-Vmm<607y$C8X$@y`mj=ecL(nnVRp?02)YXk*wm({HKE11gnj^YJd z(gc)}14x)mB@-SGNagmo9DgWu1Y!XL56z%sgG{fAZ2vxN9-J;6rqRx?`(X%LU~OLS zvo;hmdoSe>BHPs7@tv(q{KIqRieRe~>grx2B^i2`VpWu;cA}+q=j3sP za8T%)ra2-&tU+aTsJJd%Ze|2jQ%^~MjGvXyDa;x;{=AGNj{x+)VU`Lw-2g2f`?y+y zEgs!|@1!Ai4EwedO#HMzd3C}KWfgf9)z`(16QB*ApGdrv8x^GvMC0iFqJ+FXsv64^IK?!I=Sh7rRNp|1#~QNxD6!_ zBfq2aK4~5t4{RnXYRHrZzpSq#_G{2mvYzh=72}4EXH}E zaAuYxZTE$a?ye|}`jPif_I&gp8)Av^aBhpmygRI;$drZA)z=3QsyA+~cQ}(5({Yh( z&%7njJwes!0o34^=b~npt*zIOXsyOxFHGdndNf2ra@K5?_!X>T6b;pDE)t{-JlK7E zm3EHcrX*4lu=X%f_{)hpD}yu@y&KkAhuRA?);44Ucg`BvFjJZ`idb5Ja{FX zK3TLFdr!W{voNlw_sFT&zp5zkIBw%%UTaK`_x$Nt4=}-ZEZ90<4xqO%fu;t`NqRe! z)>j|)mu3z8<^?=GBV^PI|CIf-5&qIP_l**I{cw*g|1DP=*+cH}F{4X4Hhf^p=wtq? zW!rlT5Wv|EbZ1yob9u%w%8EOU!3~S1y9G#})#0o3$+&L2p(}75fRV1VeITI^I$BB? z!|Ri^8QOvslpL%wTeTlBxdc6_NImEi>|rw7Q?I8oh|9fs1c+XpiJgjy@Vb+xTeDZ} zr$`&-LVa&g-~-amiw}wvIYp!rB&(`3PS+YD9XlnlfQN#U=ifFNBzh8%=FUVT&0UfT?b@aitkmSW>mcYMO| zxuKfNJ8wVC{P1zIgQ(&{Z>Fe+1t}?-1Bt3U1HFT@wRNMoem#w6>yOjBMCcv>$? zCB&yJ8}kO$={{U}PzbNoR1&E*l-n{g)zw=wgNrz1 zL`J2p|Kvht5n{(X98F|Dyg)%)i{H|aJGQ~UX}s08?K@?#0UD-6*8QOkT~j7`iL8Um zJb(wCuVA{}FJPPfsIAx$f3N%~c)+d2iS!p0jozVw=m%{XZ>u^edM;bo*=*<{hd{S0 z?yw={8^vN{pS_GXho=wNOEGxA0M|CCQC22E3`o(?&{$e(c1g&p&?HlB z4<_FfihE6te_;}v$W6rwvB}`FwN_+g*Vt>1jJleMO`Wl^S=iez(TtPvJGj}~Zw0JR zsAbes2akmw-5*CBX6Q7S!`aLhiX240-^i`!GlX-fovFF22Cq=8pdF|k5Ea0>g2dtp z8^X3mSPP#L1xiSB8+%SXtl%WsCwslHUfo1zt-KEmAV8X=+&vjdBwJ}MHAvP+xY{4b z4`-|2D9+DMb80<0Ud=m9b3RTCneJ3jE;jFUQrE{iK;yl76yNs9A-d(@NcrB$#ECd1uXo8Fz%f5eidg#_pQ>0I|w zU=&s(nMzy&XD;}vw@Kxg_Ca!VD0Y-Q0baq|E#Hv_TWz*7;0<#~8_(j<{k3-t+TA!? zfExjxDXpgnb>MnI-JE$@z=4lbup@AxmE-%y6jQ~!<0pen>BAEd-n-^*zQo3Sx8%tb z9uLf8+q-|yatbjJcyBmO^gfZ&Kqv*>iQ(ou+MhDq2-J5m;H;N=g4Gd{oKi|~X56s- z3$s0SoYJl`ashTR*4l|DOFAfsz|e5T6CwwdH?kSAe;_80Ofi~;vAhhaAaAW9NzVY& zmf6Mgky4{ro^+7BRy;2`b#@!SKlanGj3qIufXmF$Z*mlQxMuG;DFhMJ4&1*Sb?k;;FN+ZWWx$(~l(!X;XedQ7RWP+uDr+#dz~T zxfSJF-zkR-n8;%HnXG$Ut|%F3i$Ct8TW;Pj+7-QPf?{CeW%6RBB}}GyWZ7Gl_TqBE z2PLWjRtgupDsYKRoQv2U1^6+gBxelY@MZ{7&T^~`nG5DD5m@B|3Vu2T_^Y$W!uAo> zXcI?Z4l~RoqR;}#gUWuSGUfaY%f9gHCok;Fta zdIdDfwGb=$s}c%4@jv259M_&mpI)f-I!<{P_+z78F<3j_ymf}70N<(Tk^^fnZL%0d z2{EAQh6|;LOR&K`MsXLSb1@GORk>A}Mx*&_4zx+{PE9x(xR>jySW)*pJygB++Jo zorY~&-nuNxHfDK-fJ6$WX^loL>9qJ^U1Yh z!?Gp8pbvz7AJz%KrX9{O_j2N7f%A?Cv7=f0`RHNoiQQ0E@}pq&8h_P^+{SQ?A%}v- z)48-BR<)%Bm_`vndDgUX-k_pIw!aP4&>3`7@(~(JY2y`e6UD~g8Y_4b4WR**x8kg; z*|fS@m|Ux_NC%I=N)>kyl(-b!4WLa#pQJ0=mm)8U6C#6YE2Ck<#XJzK)w9&3`#Pk` z=`%8*rw%cA3ah0_j_W&pew2838=O(B+#Rtnxr0txn>ES?i3dImnRj$7CBw(&B^XyY zAp^zl7*HE#=cS({Nq9)L$W~Y+#MTKLDA6e&l|_bv*)f`l?wI0gtnXm1~(xzV!Yu94@Q((1Ah-?Fq{t>WhV|&If zm#(}Z7s?>9a%T|UJH2vx0*4_beBLmO#lMNCK^Zuxkza(X2Y%9N4q~ptf>k+$mND6y zl;}&aF@2E6l!t}H^s;z3_{ZgD^Nq`nTMYpvYHTXEPHlhKrDpw-qIO=;vdG4eFqBw? zxMTh~6(Q}_;J{YPg|73EN@z=m(7kwRkLg#vxMUvzk~xK(RiV-J`pVsBUzdDdgN-J0 zcr@g*yzHC&uHCU~g2To8FVVx11>JNa=|{BoM6En(xsa>FTy5>+OP3m^p~*UY{w4`U zEea8%clvqgjNVK8UWM~gJ`O0mLIJR=ALuELQ`&<^6DCRo0p@~fh^}(Mb-O1&Gt`ET z2x)q8R~ySyuF&XOI>TBgF#+$&VWW2c^gSGwr<_F~5~|RN9X;}sv_VyGwdq80a`vu6 z^7f$qsK8m7ut|~I$}8lUT5J=U$&1Jm#~^_}@&0u2h!qrqw{A394mdK{GQ z_eKF#l4?ZAc@yl{fG(0ScW}A;B>BysL76tGOA+vCa%$D4cmh8sY>&T;TXu=g3wMI> zMn-zYR@FG+nqAvO)nxaqngoQkRYf<$Cm=PTV8)bpZ3It+MYNEbM0BXFaR>a!54VzP ze3@II0nN&$HLJN2$gn!-E6JgV_aLNR2?w>HLPBOhYWInN zXf)JVneNT`(Be8?!>Ayt->nUodZ7V|5ZkKk9M+iU8kS4W30I6(U7vw=Tg$pjvy@{L z=@&&1<3WVX_>6$*mC!Gj0R@QT#xnEHT9;Vw?w+{>4U>-=nEV&3D`pG4rCu`Jy3JPnu*f3co zpX@6f$mju*9~cWqp8dvL{RG^Fg{^hy(Vyo6RDu49SaB1{mC{OUf6#ux zG%#_`_wpWrO60N(-|Zx;Cl@1Dj1_J}FD$<(Y_CyS(D?I+VAP0oE3a8r)2dW3RtX_* zcMnUte|cJBFAi!_uY!~#OAgy0e65&q86G#Q{j`8|US=mAOFS25tR52n-5MW(@GZ6E z7*d12^vm2hBOZ4?`~=qPs>v00`N1AB!rHJs%%sxQ+XbdMiAfS=LY!CseDY%vvNN7l z@o=SnG{(d?QW}L9Ks`|)Xqo9WUY`3c`hhibZI~Kkj1AiB z;3(eg$ItHE;ihDXp3-(hR=~&-Y;y9KtUHRwFCpUivPtGr`8j?CgP71|@|P>6%I1r& z68AqT1&Lscq#^tncd4C!6#D|*#R)Ay-jRIdWo^$>Hb{X)^EX!y(r)4G#&}6|O6KE5 z1r!ez4J;FUI1=}8ITRQc!s6hJ^a7=}Z*CFCpTQG}d(}3D_2hy*Pk0+ZIw#mKz^oG| zF2Y-xYzx-C3a&_-(#mN-$TjHY1(avUtRKADNApBTXeXZDYNkE9i`;QAoQPZMjTJ7o z4YSJ~zzzIv)ZRAJ5d)+@F3+!e+kUY>F&Os0^R#?lu611P4!Uo2PjUs*mS1Kcx$)>V zzGZ-1v`ia0xWr{%MlAp)aWS*-gjv!jn-K;m&RfFnpg+K+ryWpctF0`)OMw1{Sg8F3 zZ46n3VrIy$)z)L+0rvIeP?bF74=D{CMxOZf`$N%s>1oz&ARROypL+r0w2tKZk~$n3 zxpu19mT|UJmXJTcOB8YoRa!ycG;{Fs)`bq(5-=MN0OT9lJo~44il6nt_Ic9cE{gTEP2!3L^7_=< zpFh^9caFTUTIgA&BVeTa>bM!c_w-=&LVUUrJ=VE7T>SJK-mYE=z1qM*3*LNaK_Bax z+@QJyK|(p3h1%)dbfm%5a_5p&r^YBU?2G}#_r}uRF0k^k?&wu*gNpMZJKQR7=|HmP zfpx>RoSk|G(35!Yu3`HWTM@SnoI47bFOU#X&`UVwtyq;8?VdaF%OKqGNfM_N49au9 zH8=-HWI|QjIuFhxo?Yl4c_{LvrJw)&(V~Or7<75tH=> zS7{7jM%#F@zF49*qdh&Gg4(CH1*CnX{p7sRmhPYCA(b;8H{`CL*^qtzhM9|sTsM=D zPP<+R-PJxa{ZzVX-kil8EbCB0g+4sgkxGb(9^b!3#_HdYhATegvz6~$jyc)X7FpE6 zP#L+|ZkM}Zz7WsuuT(swnCX@sYOA_`ME57dTo#8GC<41vA(CB5P-T-8U$77S z1N*)8N!nk;i4YMPw`J0)%BZoN@#@Sr^iK&u*QDNK1MrOU*PG`&Y6^81J5-j?k#uc} z6-!fv$rS!xe;PD|UPJ5pd&}lauO7|lPZtLsp$7a!{-5bV{Q5`&Rjlu@!#>>lVtGl1 zZ##s*)>CxDFrL#0n?vhmB?$OCU}ottp{X+lGv9ck9n~44vhk-V*P4^z4#wCV_x(``#f~Ctia-;QH+-GRWJhx3TPi zGw(4~lb(>$U)V5#lxe|K7pwgeZ{>{X6n?5m(-~=wqf{`jIm|@9abhu(oHndxW@hzc zMOlB9267#5>U&RS*xzI>PK|lI)fkL$-GkV&+gR&O%MBt^O_NTujFDAtMWi{cF*8Y@ zva>hJs+??`frc0**KVOOOGAe*G|5=3~+=NWxm^ETT*w(e{g#o22Dg}9!z0K>3jgS|LI)ek{~nz876j{ z$+|(fXYBI4333U%N{H#ex|J%gRoOd}zQ7G5HW^g8K09`&mWtg!)?e=K@!IyNf9A9+ zGE}k0_&k0QX(ef(N=yR|rPLudV_e+l^uh%I;?B?R3e&pDk~9jDG$*zFmDDH(1Xg|< zj^$*em_=j^`A7HRgfWv`RoAwKNC}<+u?k+qO7#2ghR%Q`fq(;wiuNLORi2bYg>oUUoQAn*s~h&2ZGUsP+{2~V%^U54F`13ihc93M#7BFroyDnHWYo^8 zopId`2s~{#PNEc_+pd3le?JqiC)Vh{cqR;g<52!zm+#Tjf8#h6ob(-CZU2*!L-$|K zSe4yv5rwd`r0BWis+EO6oHW||6$s!7K{rlcejFmg%DM)KVDrK=`<@dM;^FmN8rQco zaKx{sdK%WJgR~4lgdXtya3%E97wp+Xyb(W~nrma{q-3q+Xza++3~o=C;w;bbHZE#! zJAU)*zIt<$lvD>dpig}UqM=l8(fuyT2{BP9PkLEOKfb@DGn0_yKuf)Tbf>jMtciTS z*$l)LTayI31YLF?-hoMmjW%q(YT7B4E^2Eg&~fGG)peMP3I@!d1sqP4W1k=)}O6}M7Ejzf;n{2t#soLX-j>a!2E z$rGUer}Hzn=~4r2k%cIQOyv%QJO&PEH@aoJ%+EA}4g%#kYvM?P(gSuG;=^~^D@gX+ zy**<$lmdhv=;~tR?T+|zh?hsaI@tI9@_}`e8<1m=Dg<3u(OnZ2>Wv!g!y{^o6oBJD z04zO)5SM#+@77*V)h4PFZjT{N$tvg=Na1}-5xC6MZ~oLNAew$B@U)fKp8knHksb^z z>v2uncZFqX!rBcrJ@0-h?`81OMM?WE*Iz61Ij}uE_Z^# z_;HcXv8okzWZ`SV$JyHBA+?>aa?{@qGVVTWyA>ar8nXp}>9_1_!#@RgJ2cCYLxdQr zx3|9lQ3no&ze7Jdz(C}+Hs=={dmpzKd@w@$bb-?>hahbqkbI3NcUMwEtckJ(M`ca3 z-d)I)Ss1dwu}!sO<@Yw?~h>}0`%K5;{axJ!aQa=ih;k>2x1>Vs^?)qYwa zFTm}uXjss2Rmf2*EaY1*l&3&VQk(^MK$N8BIuWaKgfm# z%pZZFa|kD>A;62IMK1A@URs-LjS{={7BsPl_UrD+RUNKn_+LzxOG5a!I?7t3Xo6bn z%+1w7;|}DOMk#`=DKsa-aT}z)586v)V%)`tM+Csd{Fqq4RD4uLJ3V+!4R4vZ&A6i- zl5?W~tQrR7r&Gp)ua9l7C95?)F^aXQ~T z_*$!QcY+DhmRBq>j<1_Y0?&sie^q%VwjToKw3t1y*vfK=KIULAOx0nJNfj1bpr`$- z@sQ{YJn6#5Fwo4MZkQ})W$5&PW)jx~4y`HI5bs_9JP!^Zk4mAOqF0#`QbT+0TgA#NVP3zk#Z;jC0{EAi$6#=ekgMmHp%1Kbyj-!`CtASqODq1+#GVa3q<^gOG{Q%j zBa@k5FA3aoh%Jg4Ev9kA{L|~Ykx-XxYA(hnk&Xl;*u6`Xjm!9K*BP1kF*IoW}V8$c1;*3A=|vn|6RAkrL!j}wtuU$^?xF=4qN237Fhbxyc$ z6r!Sx+`K36MF~g!7dl|~aQG=@TR`GH2;T+U@x7X(+Xy6L4QmbSZRd(M z0EjHe((2QFDbQ?9pN$U{rb1+J=NI0yo2)m@Y5&Mx@q9IqbZbGbrc33i(r}9#XKnJa zz4|`lpbtr)UrIdxwA&8>Z`Qwa-7H#K$bWdl0 z1}15LuQIG2cki*h`ReiM{R{F(1C`a>U&JIjrhmkwzazNm{t3ZN`wsy3{|?Z0`bKhF z{vD(JP2B#5asLgbZT-(UZT)|yUeo_2^_rRfn|l3C5ocv#!eyiVuhi@R2y)-#LmO*H zX+0|=8a`1Wem-#uK0{|2MLNcBhB%9!KFxoddi@X5HN!V*`@fM8>DZY5eL&PV)YUW8 zH8ezYy0>+*zn^uMB!d8>laQ2T5M!43DJJ?6WBiWSPk{W{ex))&6)+t{@ug%oe8icCTinj&L z@5l6cO7{15d|B%E=DgKQlWjI{i{#qdpWmHieF7oCzjDO?4rTxLz~7PV|KtZfhi?|8 znS;eY^!-b5nf@j&6D=+qGb=6|Bg=n5n*WCe|0=HJ-^5i^WY*I&W;9?n{GW;Y-y4Zo z|3S)B{2l@ROZxwtxcYw=_jd7H+&dV$8d??>MtTN-zl*!{{4MS-jmFZ|<7TNc}y78 zZa!A-@(+gXX15=abh;>hTiU)^?c8W>GkomZ1a3D$sAaBnYfLJ>Q+ab=+`9NXbVp8E zDt}NvZRYwV!r=D&pma5T`zznD{^RHLzuqMOZ@!_U{a?OeWy57-_!r;&P2PX;4ZqZX zz7%L#Sy<@knVJ7*zG3*sxA^y?G#x7&O_Uu-gIS1)644;i>yMw^`5aWZ73n+!2LKDQ+krsr&c z=7}PaizjyBlH<#2lgGUFK#;@VHof&VQ^}lEUqu`_7dU)&I~;LNPq-f)9d$MR-feU^ z-g;irCv`ZTJDs60kp}GF zW=N2Q&(crR7ro>ke(W!Sk(<0XstZVrJEsyVN?Ml?5fF;-r4wy3wg2>c%9WFcd(YQ} z=i&EO+7l;)#!l)JW+uf156jo?_uh1q>4Od$SJ&-!9oO%Az*L#e8d?rC`O7BcV4XxLOzd@^euN492Tx3fj(6U7KtO_bD)Zug^{FS9W_xH<=`fVhyQRcAN=ld zc(8Cv&hh9o7^phYE(1X9i_L{S~@rYt7L zD-QR|cL>3WIh4fwRJS$EIC`B*sf%STO_1NSK>^j;WhG1Qn!@l*6;eKq9yfv&k zt`-rFK))3f3)nG5OIujmfqD~KZ@hVX`~%JN{_Qf-{kijO9p-|^Pl1~~O@h!KH$6mI zMGl{!6j8dAs8e4_a;WNww{!SO%TQx&$(hz^ID_55gz-eCttaiggk?5;p8Rx=x)ecf z;A^zFe%#l}Ol5s=LCc|>#cl||#T>xBuKY6h$tEFAz$1k=PmgeFu$-;}onr8A)B`_W zOddBoghB4!ejvs0dZMMy1!vXf!sS=7XEL-iu4P5Ps*yjlxH=yhsbV_3Z%Q#BcxRpF zXkT7^En%&+po2vrENS41ENG~>9hGk>7{ek#=0*-}sn3{U@VdZL)%eULl>vLkCEw$S z(3L{=*OaB#BOkBxVivTKGu1df)~1s08jiSvqB&OOW&=~F>o4%qAc;u3HL@(=vP z&t@p=jRA(N?==U^d&&CWK~#jNz0co{KQXqvUn)qpP(0$OoQO2eo2XV}pp>q9`q-No z1)<_?9PQ2s)F~kxEpmnCsn8=W>lib*+GI-(#@L9Vh8e&Te~@?v)^B+~zelsCe9oRr zuPbR*cIP}otv6W~+eAXnphX_gv7^;E!nl}562exEGFzzD0}t{pKBMoX5^IQ1W54&l z)n474yTnmE3~u?&AW#ClPI3LE-a)su4I$<|SC>pW8vCO}dD5o4$-KPF@MKZ} z70orZxsMzqF*FVP_X7Gca~s+pETMq}cPK{47Z)HK!Z(P~B@4lC5F-qyM9vWl$qF({ z$ok;#NkVpZ7)yg?q|CX)#3)SiHgx8a&~oV&zP4&RE3Wt*SZbL(%>=tNZdtu6+qlrL zVqHDjq`LUpiL|=lyeM3DCh8b8t886<0seaFCL@fiH9VKVO5 z&w)fa$UQ=jI$fJN$znQ**dy(HN}9`7}pJ7}@Md>uz(Z;Yx& z7>ztf-|>uJg}Zw4{G9tddvoyBa+b%|z0cW+AvQB^NPsl_RTl&=m?^bes@}vuN2rxE zMo4CXX>8S`!C*n0&tQ&JVp}{Xnk&6bu39Ny znWUCh*oqH>KB!+G5@#skCm0sUTsdbh6wHGTrD2QL3ddGeOvklJ^j4^CrL9gTqetSiOCFCkP{|>QV$f!U0PRtnqhO95CNGvMPl~2rov;umFNX$2 zYn~5~T)ra5D5=aOWOHUEKo5kQVm!`I6<)2;qQ=6Cm6WS^NN<`PC=Zurr$_AlXup#{ z<940*goNX?^yaet;@^E898d=_xz?x-H5x9|>NjdsSys<(VUMhNuAJN~w~R!Ha`hQ$ zM$6exb1nIR?vHGitJOhXDay)@ZXX4U*qiG z(!;;T66ybpvn+;;Y%B~$Ow?lkvtaVy`l}!vEi3K64<;G%8j>17sN6!*?t7vrnMC^; zu2Z3O637NWgMEeQ^jaXGgXz8da*UGsQsKYhJ)@$f*5O#D!#M6N!#4ZJ(1(4m0C zu&}t>=1kX7B!t6(1C6XXQBYg8ig;GLt4F{k;+9U;L1jx^eZ!CG)qj9oOlv2Umum-% z-f3JW`W>iVxKxbSp;&n#Zz1H?svhVeLBcopeH|o-g=r(|_uQ*5jk%qvAWyOC1Ap007j(X-k<2Hv%ZT zW5o+lph}|JT9FvBj~1PM#?dh{$Ww%U>$NvSUWWGnarPx(kCWB@vWe`Q>>%TSzz}AV zHcgrgFxWP2)3i;~rb*MVCTWvqYm+o>(}=RDfS?TfF2ZHsK|wAc`@SlRpn&YkCJ4%o z;Q#$vE})m|z0beT%=dg>n)l>=&pGc|e&;0F{k~E+alrB;?^$gfV(-(>sPIcRePq>7 zZawQ47yPQZ*&S;hSS_ETAHCbj)#`R%yXAam7k}r~w>)ScYRR|t)AqT4=bLZ3aP^g2 z?SB$iy>1`%Hh<5%zInwuyDr@@UHM1lyLW%Y4|X|Gz^{7gsvGv}?~*y?v2%y(eUiNKxgD-N zcdwV%&78$vdHq@!Zu+}aqjJ$hcVCjddzU|Np1Q5|(|2y%?9rW0J`vt((Z{z2wQYXC z?>p4ySA1}HM|C!T{(C?B?xJ(+r?4#S3zq9$uc*Td&U&?PEdBb)ufxGy2TKdx`e>Z;VSY+?jerVqf zo$For&K?4G(M6VhDWAFbx?T2KBe?M4tuMaoRqgeQ_u1{}_^um2+Vbz6qgxyP>Z->M z$9FvTy33Cl9DCepYwddFmIu7O=HG9=(mdkq^Zqjyk9}|_bCllxq>JA^WXC_B`tA4D zUw`=CBVWC6k>P&w*qZ$Bo_c_;-M#VR9p64@?ZqcN$ZmPSZy#N>(OHY%TH^)t2TP3S zoe!lQgo)1Y_`|I+kf}C$G&3SU@RW7FaI)6K6(Vw`rT7R_fH@H=~qj) z7N+lz`+oO=-SqD}SN`ymZfC{v1JXbK;XdEnfL!I6O(t)w@$9#6dS=B@Pux&wyn_E> zqigT`Rd?Tmi@AI6!dAI2MOEI(>(5OezhuutKh%!-&9R&R_34!>`-}FnZ@4}A%g#~O zYTF*X{xu+^Xfc^HtJ18oKU@`;Wf1`kN;YKmNDZ9+0iPeB7^ln_qq8yC>W- zdilVQU&VI0cOCNM727R;<8LbuJ^JXI9{=-gcRp}-VcSby$2MNw!cY6~?ZY2?`R$EP zp8g6()_^;E9s2sRHDC39vfj~Od*vJBYmt-e&i$($x0<&8=C207D>{ci@V!T#yLp?V z4&E9+`8zis_{y`3|FRt@u3dNY-$!3!YLj0muKoL5&j`8-KndVXVD=5z=?;f*4FE)W zn1wTN4(9(CbDK&4Yl{Hf0AL3MiTyKnuwW7Y)!5eN#x{YW34-YUe_{t;z{LLN959Ka z=>KeL_ZDq$lgBqb@rrZ)u;E2`>5sQQ-Fdw9h`!?~-~8q|)5Kce{N^{ee11dq>F+6; zvX1iFmDkI!T`BM3-o5%>m!ELev0|;f+1S0}%C+{td5cvm_wDe5Uz)pZq942dl084% z>8B~Q75?Fr%an)Bk6wG~+L!*k$4dviboyT|X`CgW$L(^$o=?8{?rE0~rte+2-ag>{ zJo_H-%I~p{_I>rKYd(DETbo|6O852WHhpK!b1&QNg@5dQ@uBape9qqB2ix6v(>s|v zlIQ;QgY-&#_mA#JVcdD`p>*oh4=cz2;gUggTL(Msl5LN_<T3;nQ-Ize{P(5!p~s)qKhxS{=6qH*oxotvZH!W|Mnd07pJcA z;vVN5vf_|KANuthul;JEl0X0ZkN$Y#9e=z?Rvk=fz5&mZ{U6V~gm z#ijFqzsAp6<^BWTC~dYuZ~uS%bc`Lq9k=gO7wom>9iw9}IB~u7Emy6-*nM|&!(S%h zCZ=;|bq?G!-jt9O$S*Q zx8AtwwP!OA+*&z$>u(jV-Ds~1FMo8WSAQs`e!mrXr;NR>W9;Ss^0!Y{_v-!Php&vz zb_T60wxq@N_TKmUOZWQoM_)bVqIL5qwd3O3U&!u#_@>*x(CawSpLQQB9*!LP(aM-v z_Rx|iUI@3?cD%*P)M}T0WPSY8cc0ktmEyzez0xLjx{ow>`qh$4zkSsNyXpABQRT~T z-k|%zS#PiPA1B;+?GDe}_Q!u%#jDBvl{oU90J?4m0pKwoj^phoj^+!9OzT?Bsbq=YWeZcbLmn!G(|KMqN z-e69i+O&{kU-->8&b)Nl55KZ<(c|nIo#rlYth#io`a@eha*bAXPW$~qr>z&qD+jlq zVI;#-m%Vy%^`_$vKjGoCPu=g9^M7)ZbJy;-?y~acJBSbRM{Sv0t+D*_3ootz;o-ec zCN^d^y45>m?3u*dCx!>^-}Ub0{c|2V{`)`P>fndA@^<^$ zZm&&}TWsQ=_lM}zJ?`8$*!Sw6U3Jn&_kBFQ_%}zceZw&yZ!2m4V86TO(`P-SerHR1 zs$5UTrAaPrZB7+rH)XPqa?kVMqCn$z!Vh`f1ng_2!9huotZ% z-E+aWH$La)ub(c2du)7gexE0=_$KpQJ*m`&JDSp)4S8p;t@^X8p^V|#E3zm!;KNW6x_L?7$zp}|4_4RMfe0cq-SKRsX(?8zy zn$8h>Z~EekiA}zidG@~NUbx~YdCA8=h|jM#4oXi>cxi(T51qbrHGIY3_Sg9H-+F|9 ziMeSNqjtrKzWP+-#CG9WW9`lV2j$K#E42`!c8$9&gJN=J08$*Bl z{fkTf{^;%ZJWq1FtbXn8$Gq_KasANa4znm(dg>y3%QxEht~_G5M)180@Bg;=%Zm8M zAFnxRpAVk-`>vC}Jp%u6P58ExLN0&pnA@iiobcNVUV7r@>%SBH;;ZU2+x+c=rGJL6 z-5UMd`*&?}{@R=0^4n{_b@TZXa3AohL*_WzxPRw|iEsUBkFIw~Dp;1G7G1X60k@|A zbpKhTap37+J?8;!xH0?0GZ)`=)$ps^KKjmfR~{xkebc?aK7Y-1&OCnWqt07v#WsJu zZPl$dJM@T6ez)C5hh6xLe%vuv)HCb!-njSITdnnR`=j&s`}m;SU)*@(KdJ{U-Ea-O zeB_RAZ}1HK>M`pbyzM2c80+B|-*fQt%0~xWpSkZ7`c~@Xjl&a{o^{zVH@{50yY%nb z$G`sMPO^98$uAYYeeTIS8$WVR`Pq#JEsbhV-SHzvKIoKBE?;rbYu&<$4<9Z)sIOB> zwRbMuyTAIVaZ>5YGp>BIkgBXd>ECfqZHG;F-Tv{f*4}?4I^(sKr)A&=>d95lIq)xf zg`r>F?e+3i({tawdi@nUT>c-2o%qB*9&L=iF>?X*=_w_TsQpt zD^Klu#%Y)S_$Mzt^!NAQdjH3jBmeaJBe%c(?%ppHoa@g&<@ZOT-+AE9)$m8hXFmDJ z8u(v!eQ>nlw!{11xk=q{t(V7de)QMPo;rPNzje#Y^v@Ts)_ktE_stJ}=e$$a-dDNg zkhR`!x6vG;|D}Wa(Gd;Es&o;(eG?mXwAeOCG70ofgoyPtO6O^zQ* z4+p<{amVDx-`?@VeNGm)ItYIJnLE1QFPu(q{=?O`+B~UjbbNV5@kcKoBVNFN{O$#t z5P!(9f2uraZ2fZn`!^hR+GF<|cj^yoFQ2*m@~6MCn{~#Tf86`<%@5yUyN#04-??44 zxaIrGGG~KJm))@6;&m>#^7&JjANjz!=N%=!_3A_Xh0wFlUvk)G8w<+^bZSrLveVy^ z|N8pPx3BwQxA@5_8yx0;bHCjW`r9XKy>aYo*SvdNcrdljiSHlGIw#%m$o{wgkB(C+3$q6>DP)Up7oVCzVWB;ulno{pOcPycI!t^ zKR3Pq>fdedu;lV9&)I3~UC& zqqCMBdB@<4*OI*#Z`kxve#?{3xa-;KbpHeHK5yj{hrRy(6?;6-MD;;-i@U#4 zUw56qK1~1h6z&`A{qa!tnVZjihC|{0A?7{n@o2cxH3qna7&e;TCw!=$ap$5lpUs;B;-%m%Qt?+z#BZw#p`FzH-)v zx#+Cy9y_16!CH%c_M@lI{Wv1=Z$0w^cnm^t4+P^QSOrzwAwWQ;umMvr54&&yE`1)F zgWBwuR`x*kZWf)V$;2Wu`7afkg&_K0qVw9Pl|6z?CNxsjmSz9{ppgI5dmvIc{)KlN z{`tiFtf!E#ANto*W+jAR#eB!fPYr8P?K9Bdey{_T@XuJGIZ>_rV>PJ1`y?yz^SKPVe zoe~_JKV0k7i+`28cGvoDhJ9^%tvk_h@b;NM-r#iWa;kU_vC1lI9ADVvnRo74^z^I7 z>A@QJ(DPbv1aj?0Zyx@m zYmwS1y>xXA=$f_qr>~1U@Ve~gjCDiDdhdl_JjHCj%g3kRbmajr4PHFw*VnZU`Nz_q zynfkP__^cj-yL4ND}CE8du=}0d-Kz(n}1C1Q(p4$jZ5}i>&nLqS3i_)4UXCF+Dzq> z>USTDw!8YLCcMU${X4$D+V_r0WOlrJ^-~sY(mAAZbZd=M?zrvxt(cEazU=jjKe+rW zt9@nf*WSDMOEw0;<36kBXGURf5bT`Mx{LUM9!`{?y9CZHgRO+23RFU#`Dt@glRc$Kn=N zMXFw|+cW7n=<+e!)M8sBJB#;RvG(rK^2qgEFxN$q>-2}qqdgWY3(Hy#eqT5YFJ3e| zCA9ZgJYTO=!hwiHP$Pb8Nk$f8d_ zi&v}-e%n3h=*t^a;nT~3zxG(%3qx-?3{NJLWfOGSATZzrNs=&a9vFoDPlJjj*ZB7X4cK&z|7m!&`tJw3?w5`n zhK=s$4E@si4rl7q=ne;?KnN|a(-MynN*9U>Cgew%!b4*QHP;b~948ysy?+$-{#^;k<7#1#AnAtA-O!;Tq zE#rj$e01S53;V?}7q;PYN9hCBMoT+gT^Tvy;uW78sT^?j!G6PV!LoE94NS-09i9*U zXOi=y|9qv{O#gLKy8|vR|I~su2Lortf3u>Cay-6h=c=Na{ctesE!iFZ*CAh6_Ge#p zDS!{ISg=1!5%7;_CXnSQxg5hG1Y3?GUm!9+^IvFG2OU$N{$FT(;mm)f@u|uGKT-MO zx&K0^*&DfPUooBGzwmg0@&C-?xuE|`m2lu{ZG8CMyXNE$tH|`Y4SSgZ|5>*{lGnrJ~cGwJrWM-di z2Asd}$!B)lKFaKtsV@u$pL!+>L#Yg97i=}jIGJK|b~vNMYNiCfH0q#NP{?Nup^!D~ zVz%C9aucJNHH-?C8I*IAL3u`y%4VumX0q_VPGwSDK10-~Y_(a))|>fgq86i}Mn{DH z+5btN&Q3Iz${=lUg?6zgGzyKu?E4wP&rbZ}p#S6VFaZ`?H^8E)Qf88G%$J-gH8S;T z11v3{QD&>BGYhM$=jThF{j3)0ULG zO(NHr8sofEj~h+fFHhSjmt%!`-^Ob(+v^B2-K3CFsl*JbOs;3hJqEDO=Mgbv#d0>7 zreH2VBbcZ)5m{;#9Ho_rI+8=S9$ zvYDE))&R=c7%w_rx9!R^g1*{klHER5w!Cu7^>EYk{n0Q`@bRFL$&|qIOH{TF)TQ3e z=YT?}3%u>+scbIKSA~2*Xt2GKAxDOspUwylRC-dV(v1|)<_aQXYU6y&Pz}oHDZDUk zneB8Xmqj_A?J{{I>InA4m@S#Hn;|J(9s1R=^{S}g}NW!D>NeHqtnzh--i()Y`*@8i=j z@S!oRWHJ+=CYfA*LB%K{LkcNBU69&e{4pa~Xql5@IcT}{4$n;@v90APe) zH}EAIwF+W|WLl)2p6J~%k&z0bSVe$*HBIEVO1rI+^e)p45h z%gqFl$!TIc=)(O%rVkN#P*ytSA(x0SnWn0Qq1#b4Wx0Yg(&HIHH_^k*T3i?L{D^|1 zL3LC#V;U+L8c`#&FcGN4BoW}%77v%?F*Zi4dYrG3#UzTwiXUbf*{gS&F%7fD`ix-B zoLW$R*z5OD50mvirA$H6U2d=`J+DV3SC-qJ<>oje&QH1xS@QIL+*F5yQs5U%J=rLQ z-Eps3s=AG&J0m!Zral$d)1;dPd~vnTB*^6RDwK-ERyO-@xEa;TzF>pFQbDj1%{Z&H zW(57LC)aXm)wVkdlq`=~y{cowR=(}@h8Dw>SOc%tLq(`z#a4>QV|}F8t1v~bI%Y|c zNZ<)y=$DnWlTrn1Mv!v*DNVtK1T8yitVxVN#(be*Hif=MYDuA*FA)Y^aBRCPccxQ3 zNsU^ppLQ%|gte2ws8tSw(sWo9>}qXButy8Bg|V#V#Ab0?Yt^v=$I=9@VBXLuqXJ@! z^_C@16@={uSzivSW7!^qWz!i88@plO zax#gMfC+Mj=npzhz>aHPnHAJ@f+0AyRJ9Sy5l3#>cmG*kX9Q;|97Q4}iPKUdX!X&Q zA5~%&8;2olxVF<5YnfygQ(bSs4#h4F$sFenm2s(%_Y6azQl+G-S)-;KAv1!bUMj@W z*+@$c0;N*qBgO~p3*1zcN=*ulLak74aI8OSwIWaGg=teZhJp%=XwK+Y^-56HY8q(& zCApeR&Ip#uN)mNcQ4W)4Re_kYMdT*2D0k74g*PD1PFD&^)^_3~Opludj**&uE#Iw8 zfrnySZDE9J{dzW;?@mf{f^wm&Gd2xpatKRK;lz|CM)H^$!Zt;t4%O@mv_K=+sFBW@ z@PuMpQa#=2Co+mm8kAS^R1K$mfq_Tn6q?PjOf;cEznZ3!aZXC8x`oz8amT{in!!71 zuhc7bc#jtHLaek2f`R$E)QThCiVGD5Q`MX^K2^(O z4XipLhPulIMR$ygaalF9)(ElKY0E1#1u-Co$jC$FC~avq-Hc6%bIF((ciZZWU>7!e zZqIEsn5@b_cMl9pi=md|AC^wddHC__q zb~2SH`4N(Y#@;+wa>9I^z=zo(=jvWujPYr)T7*>9n(%f@!bOZTL%>|BSB2{hgRSdL zSngMpI8?y5YNqQUQk!V2@xb}iFWX@%pKJIfaJ(GWvm{WNVuzTf{aQXFWW3O?*14ob zrgdb>6_ee(SZoU5eSU~ORw0)w7VA-g;(SEZLpnWMauW7>sib5$&05e97f$5JYRTq#d{gHA*pP`C+XOsv6|eA$sA;G<-R+eB>1@1%Bglu z${R$z-fiG>d&ssiwK9;MPQ9)qAgO2i!55We+L#P*U@p{{3kcC_H{%-a`vancG!Y(CaHh(_GlCM68IGx( z+Yv_%cr<|t76ylWtt}2ZYM*X3i548#JtnB-nVyQ1Ot^4pD&-UWqzAG=l@c&sKnrYg zI`_*qGMx-Z;h2Gd7h=nmg5F3J92N0WxF|c&w3r=Gtx<$o?MYST55Oq$+Tu5zpB^$i(yA+x8w8F;p!muUeX{A4Qo1O;LKAuud zw_hjFK3ZW>)nI^Nn&YxNfZC*Fgle}68Lfb;)w{WpM_281$3g;^_UAi=FIhc0!9sLF z9uFWp1XiL+mWNqc(ep#r4+_bgVc9Y5D|VmI5;PmT8Q7INW-&QpaUrD#(_$0n;|LbG znUuSPou~+~;OH9JNU3lpW7XO^pQ?KmN)yv?rbHFps0~0zA|qS8Ux{;liKyC{aM1B| zB2#mDPi?Ub+;7emn@@Ty+k};gQ3^xVu*Oi4Ernu%nA)A@sD?Jt$jfHBxb9dTw&Ia~ zt~qKAbg$Tl zy_$o!86!m%>`XR58KNrcY)E#dC=29WLK(De_ak3JyZzo|LK(6wF^xv6WB7*M4;_0( z5Hm}|VYV38b$*O>AW>E8T!r*|y%cU~72HXbQZ%azp2&`jj35uNxN6CrUa^$%9Lp{{ z1zaxJL=R>=$+@HV(FUC05*W>pj9Qfv7TQb2oHmkaznk)gdPa^*6yEi6oiPFO?ounP zqGK|eAdw)sDqN)*A@rO4P$vg-Yojz2G(k0?NeX0-y`hWS8%hqa;;Mz*f> z&2pOdEItWP>#{peIm#FDYlArO=7?s>qSWGm? zS_BcYsl-L92o2O>9%nfZo`yayg}yAubk#<-O8t$8@tZ5PA-lya0VC#DHY&G-Ed0j!Od&ICOWH$V!mr>*n^Nmrn8Nv<_i zjhjiX!c=uZ*GFYoCbDTPo>2H~$qFClJvdImldPsRRM$~q&VnV1uLzO@99BPq10W^a z*L@aV_`~)=Ji~+C8uXzNTTvpEgLE1im2z`OFLEwAJHUH|Q3aNLJ=trff#8%DiZmgy z1f#{I?12krs%V$P>re-S11CKt6|=2rE;7)C3SUfz*kGOoh*UiuAevb%8@*mL6JWrC zux?MP^%Ru#$VrB_0GQFq73*NnK&r%J;6WEK@RP39;5D|M0BMO`@ViOfo+pn1&&d)y zl-PE%Que%Iu>_lxYxgq|TS(^RR;8P4A;3F~Q*bb)7%37XyzM*1VO%K5R4PNmy`iXA z`k1NA^^ob{cvKN{B?H9SnG#26F`2K)nkvwCu_D&w#HdO_FjL`6X=$3!BsrUR&|01E z;*m-bt(sz0IMY%46Kn4EJe(Ee)>KhJtQuE{L>tGO-4M0|Ak!wW;3FE3(i2E)xoV=A zq@_rj(4pJ&$TEX=@Bl(l(A}AjfB>q&Ov zolG)xfY4xQvuG#7PI7);l*@^I&>1>|4Vt-V?o$RMbdt`btr5Ty0NsktbC?joqw>&7 z(@+ukda|T*8cbpp)WL^Nt=3eWXwWc&s6s$t8K_r43j<`Jn$_71qv<#m(g>WAssYdY z4XV*ECdTD*pS4tT2z*K|NHo%tfDNE}jxT2vh+`E!s3~ZxLDnlyiVB-}3z@b@<~$TB z0q2t+Mn$sPLn6@wDdA8d5@^XpAY6loQ36h>1!<}V8tN-XnhqLzLLP<;2?DgSU)M?) zKNy?!>bPGX%w}kZT0_=FkexMqUeaul9$FtY!)Cf^V?GVmH!6pD5C{?k%ocK;+&G4# zR<+0Bz*Oh~*pmf~KD7CY3rRlSKxVv_5!U?05{eT(h8drro{>{vfMj z3#7;)xZ&9|drDU~QM3=a1*%vExir!v$QVX#U{*a`mw_oAfv`75XEP+yl|0Hh-CRQt>u8p14%=Q1 zY(KNc_sU)tfO|UE(URmS*XNuTM$&?<`ZcYiE0$HQv_NW`ss;EIVf{%oBiN6!AkcJk zSh-_)rk||Clo{kW&Wp(dMfrpUpWY#zvkB{N#HLN*ix$p%oi ziBx6;4c)Sdh|IQAuutKTSoeEkGLx2lv?@9(KVMzx5zsl4g)kL#Rx-ON*2@ke`KF^k%@42i$28lVxk{w8jTge`r079`; zwu|vPHRG!&6; znbMg)lrAQLna3%%2K8unOgBAS2n;IK_LLHe>pjy`20E4N0i;f-(bI@W>(By{nN32) z5!^G4@f;$Mh`{y+0B9pD$W>=b3w^4z1D>q9NVtIG5J<&S^=VL!U{$thWHQykB#B5H zCW9X1VI8UO=jIk074+^TUU2j!RV$&oZJvHpMnU^wtduR1v;7J zj4Be~#jY|as1pvQvx+!1pe&S1<&9d2GxSld9CRz)g(K?Rry%0|a9NuVDTpZn!RfSR z$U;~i3qlr8gUG8FD!S0eWVI`$X;^?g7oUY*0S9+^5|dNK5~fFa{JQA)y2 z5(y_M(esi@U+cA9;0d##O=zlJtb&-7OK3@URB19`HJ~5|awJAI5IG4aBA4;!LYb<= z5;hLFhLDOH)+7s(97Z--Tmz;eSkSi$EB3Ic#^piAS#p3N6qp_J{UNFHf|Zic3vux3J%8VmhWi!Yak;}Qr0rev9H8Y1BU zq@Rra(O@ctQ_KeWXD$MU#Hn*Bxt~fAB~6is1HMpnTu=lH=E)WDs7_$+2g5! zFlv*RnW9VN$I`%wy;gu$1>Y{yP=a?cUz-v_x=`b6s}VApDC<*oOqu9)31eZGX`>+W zQ|NAfUWU`GK3$B9{%{oK(*1M`^IW=CC``elg>j3ea5+n9h&q@|GZn^^FoT8TzyU6k zXcLzGdC1)EoAx}DYWU7*;EfhyFb&Ecj(C2koZQ!2H-I(_jq%kLmMZNlnKfik~tS#jj+UR0u6Z5v8Ql zZ8Lgr(8A3ThU*<8EG@9C0~1;e36j~^(|{OI&aLS)Py`QCPI;b<1|_t}>QM;C}?5ma*Dzs3js$7@L~{xj{0OBBg{rX!Uh5l&1a`xyzr z`x*aIgOZ#ggeFnLG+T-x z0^@ni9JFTyd!k}nsa{h{L&-*1>XNz>P%+X<0$|3J9C2(n!oJXs@kY8IQ!FWy7~dxn zaNL0F8n1M`W~8@dp*;rZ^o*c|mFr%TPJ*3+skwsVIpuyFa2g-S99zb^eBE)|Y1_se zL!fCU)Rh(zCaR^uq{VnGBdCj>R22MN9i*Kzf@4hT@@W9$)IvFFwk4{pIL@G66pDQb zR4roF&IqI$4h)0M8oc=_4hMWyGdC)Gg}`+JEjjcH_4;IvaJFgEwm{(<1J)QUqcS3f zs#Eb3bghaA>2hs?Bh#3!x%pI*2(_wJpaoFR>Sb{Qvy(^(ZgkX9$c#W;Fg;IiLGf45 zMfJ2{wJi)Q3aZ?2nxKV%Ks#I_m?oh3sSbeV<1K)TONcoL{w zo2|(F+`x*kQ9|i9JO$9S(_qL(qX6omXr~zzXi$et3nh=ht?D@Ic^C@`pf1rGrCU)u z(;x*1!wZ;7^!SMI7{4%`@vzPfO(Vkr8A$$POpc6o0i&>X-ROhUQ}X1ZfPSZ)Y4$T!*KLCHp%{Al&p4V1QkOENmMf5pMdfU zoUa)*bd1E=RA0;08%_dJHMTdfaLyy-E|v@P2+TM++wS=pfo%{(8uZV&B{If(t~)nh zC5Xg44Hd$uEX#aLLkc|K?Z+`_cG3hlIVgEDCYq)&Oc#wzRP}`%Iz&N0=Y(LJdts_v zi6zqm@uCkKvl%AgbghkGL_2zErZTegAA9fSB+`2o^#6}UHQC|!;2eb z+|G*tcPRkuNro$(zF!#42nueG3WkbKr2>#~LLDy7!4*Ynrv21Nt(BWdMAQM}a9c$< z00dVZwaU~(%q!WpssRJZ!sW?8n^qJ>m}9W0T}V(7Q;_pnFIDI{t+tehFaVQy**@(` zaY0c4lpU(=D4wQ^4SzTtjPrRa)vVhvS5pyM#-^aPGnXNI$=M8@B%10pqI{lg#&R0V z5>u!t3q~P{RK>}JWBVYFMMbCt?km>Nq1HCb#dta-ynbnFt4ueYb=YU3P#7ja z`@=AaBct@(r<7>eOg7pOYAEfr58?p`QuXqXap6YX;H6xZYbwvBn`bV6qVVM%LxbbZ~+6IN<}tDNg(S9#{f|$)nu!!rY3w1!<$1i z^wXAGBFu@I$`;6uPRPJXldgtyRG8^vm{igQaYm5O6}z2@T?UnX)+m#m;gHF+GcD49 zD;6=#vWzM@=^Q2`)YPaHj6nNR6R$>ClL2a$>B0&%NQ{*h?$P{`>4;zzd*2qosW?$eiyW37BawhHylsD-+5=hLmDW%Ki zX(GW@dy+*eBfU?yojKeWSd&UL;4!$W0>j*E1g_xg80NJApfu?g$3?q?2E~EY)I7P* z0IM#*`95QosQk1{F+qaW>|TICjX_qJ2TPe^w$)GySTT_ny;4MhB7lYjAhp4v3Dhsq zrA(a9ks)E}Hm+ttYTW2&{X)(lbJU1;1v{BE1hR*u`GV1y38he|7m8pg*3Nq&O-BVF zk}ukU&n-eIXS$>Epok-QS;$n&;7KR|&Y_{UJ|&Q*Fu>+cN(v2d143%z1w*cH22(Yb zpax)fg5`Lj-`2!BH6fZ!P2$)c;8U5kkdAnIrZ%{kI;G3b!W zT13*tt(?NQ5VH?*Js#kqRi2`IWxC8$zDLK|NwOEDK&wO!Yhx|8&;Uqgre8z`F2#46 zU`%B+-^&_Y6=12Ek+WQ`1wu%uH5#Fq6{xWVq8^bQLpjE?DLd`9qj6KONLVphwi1;D zlZ#4F!46P3VL`=u)ojf{3^PND2tDPzTEEc<)MTn@p{Y>Px~yhSWl)x_YHcL z2*u22k>-Eb{d8d_6e%x)hB<;CQbP{(xaFEk*CIs;Sf6~`H!A&lTdvm;B~M2UP=pjq z>GYKH!ni&LeQs7{S|IBc+hiAZD&E}d1qE_|fYX+5-ccj#1!s z>q9cI4uaF z$P7x=xjp>6IY&uZprLUP1*x__WXDC&X-9$sIR$jX;2keS{rs?M55+#kXndpIfP(Tg zDof=k@@vguo$Jl*VW$ZoZ3Tg`X$`LAnlYsSbjy&SzT$P8jTWJSpcOzm1#DWd$Y!Ek zC~zg!79tTJ<4U(!4v7Ys0FfpzxIbGm=np|bR$Ci8mVl`~$oN|&Gcine(!G&@!JP<^ zbT=90tf*KXj)m-vyn4EHN(=3n1jr zC5fOl^~p)TJsDtSU-F1j+b9|g=tP0kF)LvM(18e)wDEm)AFEnEv@7OW-}=vYGUHz=@69mxW1Xf&VhCB|}T zMsQ@gi7Ye(;CVd~{b-VaiXjCdny5GXPGzbBH#q>V&7&PCvW9A{P|xKv*tD8$_R9bj z@f$HJ55+p@t(wlkG*Gd}aL|4t1_dkIfxJQ~^eR=SWjHcluq_Rg^r&WUx&~VxDAX&F-X<{Tvu0plapkZbR z`lCl3zEWt5cGD6waYnNU1xY3RX1(oOdKv9g(+CR?l$BP913L8k5G!nUq3y%UfX}4Nc1h;Ijkv8;%m%UJ7c9{l)cUxtOL@g`tenv6$&Lrwcr)|Jf%N+Y2_Ye##*7MvgAj=) zWn1t20Su8sBRTK z#RMIBXq_4Xjn0m2RB|Z+juD~{$sJAVbs#xZ5b)~C0d5m*CT!$2-W;b(tunxPSx~SU z%$7XPE>;t5!_ek%P5yP}}K7KB5CG zF2r7`Z1gO1?Np>_h4nZ;+6|jjUj__%t287~+E;7FX;sH<`HoB4wTB#BN>BwlK zU8*!ZN73zOT?dwk*NKW5NUlUo;SvYfJcsU8V26vNq}!JgSbfqWVnj8Y^%_}*+#c8H z52|9fq!U=K8t8o#0ts(@8g`Qnu{X+5ezgU9nA0R?5hx^n3XBWj)!HrvdQSL(+B5Au z=r$Shqe+1;RPrL=PQ7UAt_n$`v0~BQ$m+HON?_{_#nMWWz!w;nmCb^XNM`0f1sJ6c zh(fhW%W~kVC1I-V1Z237JPKHz?KFylJAy%f5|EZ$Txj*hU`Pc`t)QTbI##O#Iy(7w z1r=EinMv7CL!P7!m~I70c}zZqlyDAkazev>x=DB(B=)*|AC4Mbo}PBR1g7Z%ONV{X z_=6%gpW`vN(}7W?&?t^)1T86)Y~O`3eA?o$I_xAo4pX5=v`` zgCcXCA%wUF?hb(_o&>I(l!(y+F3U0WTo1WvPr+H%WBWR4O#;XP_g(ZXx0`Zh9d-DW znkw5p5zllE( zdO;AO4rs3BJ2dcz4I)JQ{ZTe;O;x#7>LR8B$~9%eaI!8CwC1r<1c(5w>Mgyri@6|$tF5AH1~q6xW`b91$EI?000RnW%TggdICBDF+So%#(?V)S;K#8_Msx4>$f{w&+2-;BtA(`v?LmeSBv58K(ppWH%4a($t1x!N}6iK9t zVU*V^WK7f9PQzyEh+xgT?&AgFV``cJg`0jK!2J#Y{xMy5NKnrrdB^C3;1WxlX(!~< zb;pwi{eqV_+wdsS3Ps>lCo$;#8In9;%}mNF0fY9iD5u0@t`d$_v|3SnDNG2FPLoK~ zKo=d1MQ|cVz!i?bNgXc3qTGT!rB|A^@>V+Q4V-EiGR?twuGq;K^vl&m5EqQ=9HjMB z2=t68X-tO8H1D-|H7;mO7f+Y^tx7ZKn2DyOYSA!7n+B~HBzKHOEf(;Qz#95&h7R0L zYRV+(43Y-e%4O5^XmF+=P?MbLmdBuEm0>H>W*0npixEKuFYE{^UmSxD28C!)41~8D zE!!&h2A{TE;-*up2Pi1RSAcF}m9D^5IJ*uBOuAbUgI1e2$&u>jN_-QfId)j5)2zab z_%a3NXTv}{dX!&4D*$1d_uI7cc25Ce-w1UKi(ztO4wycVfI(rY#ev|nCZaYy?PDV6 z@E9olH&k5jq9LXgI|HME2MpdU(IA;~LAi0Z;;R8;H@1wj-LX#(Ll zfV;Z)?%w_0`+a}!Kkv;S@Z`zNJoB8HIdjVAoH1j~CRUsh1q|_a7AuZ|RU@ShuN=q5 z$edoe-syLu;z3*!2wYG>8EywKzG1X*iJxSpxb0LO%Ah1zop3kUT(mM9KwIE!J_1#U z1Nat-2@Q*#hPO{Mu}F^&_f)(-U$R0YpoN8VX);erwzq{#o7RX zA{NY66P9Na*=;mqoL?>Xn)nEZM1?fTj3T~}?Z9*5>;$(C1{4~okwro@G-wtOqF4il$rj4(1hd@-_DwB-qo|Ewl>oN}u;`fmR#}V;g>S^$*yE8buRJC;mQGSg z;ITk&=W}fqEi_sWTsES33I+oA}qN`}IS!M>NSYM(6-(?8#n;mfqlOA_NUsS_!~0njJ4uZdv1oFM!$(3J(Qd5M z%7Qs!*?ck(o_K(ffcO(On_{-9O(?ON$-%g>1Twu59)kjAp?IJ-AovWw6U%^E4FsJJ zxC3}@FmYnkW-SbhP-B3jmCb|#{700M3s75jkS2v>P=jzGyV{7t#5r+x9!1b7!7>5< z049>lR3ep(Ya>fBv8q@o#YBmskmPa%$||4$4FSwk1_O%+kSv^BqULZgTHqm8>VXqL zNnk}sD|lF7y45#&eDq{%oRtFd|Jl?|5wK4<;=mv%U}%iQgoEihQZ=4y@`@<+a~wth zIVGZ)UIajmfaO47fEg;SpPO`K3>5@XHgasdogNDpi>YF~lWf#0qK#59B8JJdM-jLH zA4hWofG#v1NULU=8t+BJSZ1S(g|qu;cBa`X5oyG+A}(Lda)4k&L*ulO#c*MC1e5_F zCMLWCDrHgeei=oI#aIv?C&KCk__BDw`UyHaiC{#qL{fo^xejY}McR^)JnhCD< zN5^}y+D2z99Kddw7Pg;c@iDC=x(CO!0>u;!;^q80uTmBbU}Wlg7^c}R;>0loGy}mV zf;#93w$AA>IHBBVtO5}a<50wQ*jIiS>(%0YDk)7b@q3|Cs!fKHTD@|tkwT`EML@;E z17rynhLKo-ImRTms|`*pu=xo<#D)>)XW2ML7?;3tT5)`FqvW6=u!Sh5(u0r?q-Gja zh!TLXu2@(s2LKdIR;WPa#L0PTj>_hdNk|I2QXrE#6bvul31)@cA>bjn3}D~{aj5RN zMoYU6K)`AZffW1oLnxCYx5aIK>8)QfMm>*DPev+0fWFhxdN=D zUU@b_;SwJ~!Sn)u6UE#pEU7p#G@D^vjIah`0Rl1a_~H?QBSbyxxZP7&3+t|M~0cqek_M=G-E6-LNtPp zbXaf_0r;!+=?r?MPfAm`I6@xWz%a2vL|2ScAg2i9Y#gu-RBBcXPo~BY8V7~R0Jd8n zfkp?m5s?&0rkY@4RWvCMi+2c^d^Q*A7dSx}f|?@csR2!eRFg{WW*`kJvDoFe0?fKZ zEhZp^8Xd{l$PZO0tw95|dl6C|O$2<@D!oFcmI5J3t%EVZgl1t84mX@9g_+z+yM@4x zfjX@YvJ-f{DC`)Np0BbBH844n0SBhhhAlv<#PDHpG#-$R3_1+n4nPk&mEYj9VDxeJ zXog#9!kPsdfRg1>m^vIqX_J#EViFPtxDC`LhMB-F?B%LWv39bm5w?nQ0AM*ntz(c7 zv2+9Qc*eu6Ttzf6QsMj(jL@NG0;>m*cf?kvG)^s)i|jIfyv`o&<7kXgNN6k#WUm3* zkJ6$xHaZu4aIovhRAK@{X%{0Ma;{kEWNK(EzD=PP;bSmzv>y%hRRh}w!=qgSnG>UR zs+nNoshlF0Q{fPh5mvR2$EEU_je!Ontbr%g%h5Cx5Ve8Q2)HE!X*TKcZUKe|Bt?u$ z=2ckPau*!oi|6SuS|f#Pq(q^a7Lm>>agmT9>=_{c#6Y%e+?V5!a6ST#@^e7?Rg%Qb zFdFGJ4c^I!jZ?wZ8m`Yyx0+3~7&k5kIQQy9RXO#V7m3Z{0tqHQRt^&YYT9D0dI_Vk zK{{NAj6uQ`HjmS%*SSm>J`}kAMKYaTNCP{o+6)*2#_MsZ*~k zhkHU0YvI5GcmUroGlSKpC1Zg0s_iA<2h6U2APBH_KL-JbFE%x*p**MERg`LMPkk!pOmfuQj;oJh2Q3G#(?DYQoV;KAKPoe8&x=tT&*e zy*`k!5-uhIE{pNIfm#ih^OOt(l_YR-5h|>hfp$yP0tFJ`P@0Skj)Q?f0w5j@13Uo+ zx+MxBcc}bIdTb+e5Mp>tiJchnbJvSJfR08k zn$86vG7z_?qoV-j;(b1l6oI7W0HdM_X>Rm9+N~<9M=fTt-1Imk%I+n|PzJt;p?CVY z4yGwK3UAWKHUvnMX?`Inn+kxAEg;Gkhn3hUP7wCRjiow41d|3} z4-LXNp@#?TJ`9D4s^Hk7^*ArzY@?YtAUM+LF*2KOBVkXPXDiz2^A+^Er6pJ5E5i?Lcl!eWW zLPpVqUumc{@ud=YoLL4Fc(pW&N3Rk_0qIx-5I!cn6Khnkf+H8=-n5}q2w8G+R1bE{;LX#QBwEGaz7`NPqh*R*qJ}(j{@S_|CINw9} zxjoF-SYSD@BZP3^KQrmQia4O(!srT#E=nl_rffICr^Fm!r@$yy(e->~#VAfZ95n*lY*L>N1a>GrFY(0B`-z%u}Y6x#;}P)-rq zz!cKFdIQ~TvtkqsgcU^mE4*|b+3Is!aDJgw8V_<0P#fnVoG7d*+vjk zErrJ*;7GX6VULH#$BAHE4G&;7STvSUD~bZqQwTDbu5$wyk zCurcN!b7dG6k4nS?{;`3Ub+#$htxO}j1}*tU}-Re6{?K^J}!&|?*#ID9I4)L?2J>3 z0oF>4Hme9`HyvSSO8JehOq)Yyr&D9pF;PfVJe0!JThTltu)1U7I8Kmhgeewy&}5I6 z90Q^xz(nGMj3{oPLZaP9u}7?eI-Lv`TFG&eqtISkCMAOcT zm(tnQL8;f=r z^j_bs)Jeih7kpV0p1YVkJF=_LZ^!3#xu1IgMtJWRIFO(15qVzJqXCflA|#WxIn-H zb_g{O#{t-Rj#SUnG6)V7GFCw2uzfZx%*miyP&6b!?DOetVHCkHw>sdCh6YtyLp+YA z2T0RsrQM{LNio3jWcL~4Fe)e9A+R%0EVoT$1dJXn(Se9MyNSi6(2zQ%7V6g;$vhv= zZqt*DMu6aHoY+#5S3x0z&=>&IQG@7v1)S#RS&%kpyqn3=lWZzG)~FU(l~f>Wm?)wc ze7pgJKr2*YuULy!MS0>u?xR>XCRVDnHQK%~XsOo=KxbY(StOD8`9Kv`s>JR%juD0T zXl-OQ!p^nF39WHLfC{EdEl>d$;8{R~Fo;;R`lukVI#%Ly0_(EE)ad?*)uNSF6AOw1 zMn0y~ZG%%V7%l>?63c=6j|4RW^C$vp^D*QOD@)`e`@FGKGsPfL&=g8G#v_P!#aehM zDOM$nVK$lwIAo)N5bc7BLG}%T7o)(tQ8WymFLrvZN-Ik)z_Jkt0O5_M!sY&YKNN-O zGxB3FIENDNU`C_eaTc@#7_zBa2fxvKt5Yg~Z`R<(VC}&0X@N>Xth!8t_tE%3v1R+5 zavMhHMB~I{o506s%h+5NR!fm-KztVvshB_?lndi!GMb&u(KU{;K|@BWH7XqwuEql= zJ{hV}DF`%~ALtcgv6IS>^X05KZ7dosWf=TCgq{jlm?m15y;1PW^=@CYO{h=W%^fqT^lSc}0;qEWmo4#p(DVd8kpb81wLF4gYBg& zK;XPd$YmPne!D>c^m0xt%feE?C1QYi0fEeZUPFU&o}JCYm_&LeO`w4r{0c4~g9SiV z1B`@<#+j*XJ13d}vXYtP1e8k#@<+s3p?a0n$wPo-MmkwEOJqUdtQIs(WNPHtRG7`i zP#9%S0iwP-J%&feT7AIdC7@Bs8UQcSBM3exMu#^e*)FWrVzQvfaEH*PMMb;pN;;H7 zLB`Nht((pAZtwbeq(?NzYu>~b|2!KdxL%Jk3 z9a}B5do>aQQ)s18Z5oCS7Q=GOsZ=_Th4;Cvz~f{9dB%7ewuUEZT+4o+Ivy%w#TnsP zKS<-MGr3~pfQF35Yv7tFI*rU=s7YEc+DjHvsX+d6;9Yc`)5ZfK?>-DDC*Z}Ic}~6v z1iV-q`5{$G;=!eSst6t%ZSgtk!4M|CIf_rA0KAz>OpOP?ODYAR#A9QTMuJRC05C1! zdnWJzB!Xk3*<5BSMFvbq2M_6rH<-wDuiK2ViZBRxtWpk+ zbK&CzSd>Cc_Q~R~fW65$9uQx^SE)dr3A%;Lk71+1R=}Zr-IrZ*LaYhT;eniK5<7;5 ziZ;TGcDyT2!dEKP5&{>&z#`mYJq=41p;Qz#N(j6%RGm(Tz^kz!_ZyQ%^~vKjGQGsq zC}VR-dNNmwBH1){H{OaFXzRnml?-JRI;AT zi?(`zG%iN#KvF3Hy+nx&CX*U(Q?T$%x)-gH1A>d75{K9&!^mVffPPYf5G1F)5sxhg zSxYP;kb%S@Mw6K&6o8Ma;&dz&uoklHdc7u|N;i^C1Smm@0d1?mejuhGPy&L`4Rmw| z2(m`I4M-|%vc8#lz(SiU# zluZIc3fy!8h}M$9K&luN0Oh)AF>)Ew>~h7}No19UM~(uCmk=DcoWE38b2ML<+s3;ts)X=>@R{hq)ug%iU zAXlqdq59ga?%!zkyQ=@xED4;?>{cl$c8jSY(emFX8I5R2MLb6Ltv@ao=!{B<#;6r= z!YCykjTl8hqLHKIDx`cATrHC!F&L~0r&342{;BS_4%MfwZTwmJje-qLqmam$=x8(& zK|&MA2m~S;jw6vl1~CK~i9?eyiV{Ym}rdeB&grgMON<-YG8UQgKi{IPtM?T>eV`vD{i{VK|Jf}5r>cM5zDKJv|EpBNjZHO_ z`s+pLLnr@w3Iw-Mn0B~Zlz4C&7jssC}R zG%l>KiPR%wd@}Rj@zqEspcXin;&02vt3X_*=WmNe8$pu&KQGmI_m3U^odkdSlD|=a z?*XxqTB_aRvi_Si_#e)JuXF=TfI3D~|CoAmN0J&(66oLf`2G#gZ|Ly%g}x1EV_Ix#7-VR%$q@Kn9NT_--Ej-fn%C&I{?CpWuU^ji$6@@- z-qk<8q40lBd1pPVM!>%@&&KxZ@BaN`|FdaQKfDM${y!M(-%fe}Yq5Up|Gt9_gNsIf zeboPIsQ--r{XP%AKH#s{|6k6d|77}n$DtaQIn^%nfhaZOZ%h3f5Bw7feOI}GnKgz|PMD;fVv ztp5JzKW@bT+llyRle>X7^&;e7?B5aK<@*$zH;N!zB@RpVI?=-1;=uM6Tx7=9|`s^7y0k6{lC5V%dz<1HvE14|32h zf64W?B>KLzodb${u3@r`DK(8KplS)*#~Y z!6Bw97)j;UDO4b#6Y!4ejKG`>BgF_vDu5_Z!GM<(96i?`0U`pv9+8Sb!%^RkNTt`G z71wx3s)Q}qs}xR{xc-Q{`WnBVmRk3)?jxi_!_k8f<#Y%H(zNagWHzMf@1GEG719j+ z4QbZAS^cMZi{=fV7A;z~Y}K-5i`K2%v}xVC-5)DaNM(AR(M8o&Lq-tXV)&O^Gjf+Rtbnl<* z5K-I~U1bApGrA#{ZEe~8Q1qY+ygRQ@J>@r34 ztj&?ej+-vr{iCJsNU1s`~v!$A~%_UpbyI(b9qg*2v zNV48#qN+9o?bmLj4{5PopTh?aKGI`;$As3sDvECgXFW>1^WaX#9DzTHR<*vmuW0-6 zgYuN6=RT^smJL}bdR@?q?Opk0NyU)yL?miOL0IXEbBU)$m64Af5$*4`ZsLs6yc*Qr ztibuqN#j1fnLRCgP(_pS(;GKu<%Gr2tBDMf?n>nSOKDS=52$z$`zA84G`n_ppeMAKMY|Kw8 zT^Tfsf<+z8Q$vD!?Qas3_82STT4p0 zoAshPWv?v!=$)q9YnLO4#iyQ5-B|}Akl*f)rR^^pKJ@Ne^c!>Yt|vaMqxJogH)Ma| zGuC2ZQlBk>9j&T7DT|0&#m&!G!W^dE6FXmf@l!zsHg8?Ow{F?zg`c0#$XgU9ojH6z zZ0kw7F!nTUVf*MxLdlITeJbBHheS1-IgH9(K|3&TZPUfO&NT~!EHid-!+s7|Uz)U` zyW1#ybV&T$<-?VScZ`UCIIL;PQsU%cLpN=_ek*mYpSaptyC+yo#Z*n|j z?cfi~n`|G-Y5In;Y*lAQO79Ufc=Y1X(xTEIg7%mR4{}c)`t&AQp=7`wT(u4FZch3E z(u(lJ-SUw1z}=9+br8>zGo{4)VLJ*-H*I~gG|jg7Q;mb#%e0^PeD#;~*Gcd0tRGQ5 zwhq#~y7VUQ^v;jlQBM;lUG+rFUb9>@nmO$%;r*r+g~^(7Qy=T8C9hY1s*QOWa#f!~ zjoenb_*vTWh1n~vZC)knMSQz?zy)kc$leMJzU#e;Tg#vJ9yalq+CgfbIdf(}B-4*& zFn0$lMk~D`g)%Z(J$hMFY4Xl$7)xEP`MpX zlo9R}PBQ+qkXJRLmX~ve)cMi8mL=)Wp=%cno+-)CUJeh2E}Qju^3BZ8ni-YZ&$HGX z!AQ>iY7c9A=h(@n=YC!~W@+m%Z~8d))F(MN+s(}BPhEDRUHW1fX=eLYTZ;*a$yE}R zJY#)}P{>L)+|#z}unj%hu3AS^4Uw3887Yi2$$2l3RnfU)7xfgbf7U&1Tr&3a=GncG zg7*2TfvGR2Xo4*tkE5aPCbgON^krh7jI=jJ=xHe%I`925_wm}cuP{A=1MFk`Ij`0R zj)WO%S2>;}tV%6iUhYqk=5LnSb{BNK)a<7v+j4(t9{T2CQb=Xq((+`5ehLmYcQfXx zFTHxn%d>NSK6w4pL_bJUVc>gq36V7_g*fb^>6K=ibr}im~J0%nea|&-vsB(s!>7Rmc0k!<#=|F%TPk`tr9bTAd2wJ$$HUJrDYE7jVB~p+I_HPI_gpXRXX*NQ z+M$s<(n9xCR0PunYdSxHMyd6Z?wgCsH+tH>Or2k}u_&9Ei@I|or?c{QhndTZp$DH< zDs!#}so7<>kId_RExoAh)XM49s)4HrdHrtJK`ub4Th90c&)-yhp=KnfoFsf z2lOQ%h{;Ve_dOyX>#jT7v<{MeCInvOUV4|YJLd!c;<~a;SoZOG=PP#xawkvdlXez) zJG9NfXIZU3?vF^>+lHy=%cd^!;+`K`_)s@?0(a+{9(|V2|1>ypP1NJa47dAe=QYiy zz2sJRZdzb%dUOsc;qdaQ`pBqXki+*@br{}#=bZ!b(p5dOn%=L%b>2MdVI8EH{ou!e zW40ivsrhR%msQTaUhN4s>(oCp2HCMxm7v_v-ZJ#ooEG69cD?_+_r*sd#bJuR1!%DL z!ZdR+KL3g_kveYHp|jiWlpn<(Ej{ueT-R}K{+r4Sy&Jpl2y&xzZLg$A>Qn#Tt8Fib z7)wq(TE-OAL1GF$=b_Gb7nUtJ_>Q7^e^i1wxp?HAF7u13Gi;?+glhG0+xR<96vNVg zbx*|U&$2H|j{CDd5rg)o72{Km-ad2HS*klwu=LrL!kgV=A+1NY?9}qk3uAGSu6E_s zN4%U2`$b>BL!Z{XFDO5|>TwQn*91mU#h~@WlJDdmC(p^(-+h$)=ttbBu#$w7$hE$} zjUN6>o6cT3laF=`JUr&`(wGs;?krhsOCL8lT&JcV#Exy07vu-74IVbQu*HbNw@GU^ zd$MYhx4)SD?CD5)GYflOQ+CfSVZEL%Tizt&`clZL&O2Nr-mNzy_7u?Hp>is6J-OJO zdHekZAAJuWLl2&qyKI1XS^qXGayDNmv>b_HHu>ci(VMt5FxyiHk<`w3m6C9Dv96Cb za`U;sA^4`{k5QVC7U8w;*YaOm-nOhFN3PhI`)D*Qe8GbUJvP7gv~D+Cq*kLLO*TE> zC;pkaINpA3duQe8iQc!%qY+P6_8vsLAP^*-Y;teK!*&&G-X_)LDEm#m{kn8+?vRrw z@2i*G&#F22vShkTeDZ~ROLbWBgu)2%W0(O|zH)JdGNY#_-gmvsUa{tA;m6B!Hb*#~ zC)l^HlK*lcCGmbnV0mT7#MII2Zq;PvK14rQHb^;s8LSmoFk-Q}d1O=E?pK>}kNun5 zmG%ql{W9g@G6F%)eK6W82Ic{}jZ&?iB#s_sYRIm-98)MOp4ozX9K z$uVne)&NwZqQH0~ZdX!4axL!$>hWQ>t#D+*k`D>_Z_L%D9eIO;pX(s!lWX}`0?;c2 zN%aq5o}AoY4$cY&p3KfGZOdaM`Ac8itb<%lh9`HfIcd6<)-M9TOX$^x;&-ga4?&C6xzZOf4X0E;>Ud7)TH&*{KG?bMOdGQ*+19LnZxs#k5|d zxt3gYwGMJK^w=bM!sv&SM2{a(x;9swnX!4ddeD#eZe={`aJlyfcE70Vljf;!?-F;M z$ut?x;EU5g@+Szf$1fM{D19(iU!L&9_GNC?W=t1C|2AFRA>($%4{W~T$mQb4?WjCR z_wXN4`Rtn4sc*nZ0;|^KQa2b^n|M`p_&I(pJn)}@FsmHbQ7ekortY5Rt> z8MXK5$@u|VaPiCX+C`6MHH)BkAa`Vh!St6Ww+=wZKe;qNjzLG{FG?CaTw zR}ZNaZpbjcIq!*gw~DI_RL#n*dh@_CDy_q?dB-aC?C`;1s~lIyZM(PjJu>6wmpVwW zg@0Hbq(3N#6}_LF=xuU9KQ=M+$5~Kv z+vryBD_@3=KG}C~rRq?ILAMaw=WO;S5@~9%AD6%D$JzxecdqCkUP*mk*|Vl^$-H-;4~G>juY=g<+;d)ebq8j~ z!TLOS>3Xtkb?UyzN0D=PRPDZIe|NfeeL-*R?w)N^)CIFYJIBQgf7*Fd<+9ncw`u3* z4eE@)ccS@EP$Y;0Q(;<0k`rw~iT=f^ex{RmMlX4QelnwM(GT1(wZSd#R^2(e)wt3p z<5ri?cCYT&XKuxzyxIXZMcKK<)Al{eV63q0_(VQDa^BEI(ffLj2`QhDc6siJat$)8 z47w=tQ`?ghw_kkq%dR=ovlTh7HY|Q{Tk)Yi`e5dshZT&i)}xPZwVSCZ?)mtNX;=KP z(2i*%HQNU~T3K^>ni&wnS#zC@@%itDehhj3=%+a^dpz5lKjQd@r&BbUU-qLvR}EP# z-`SP?dE8Lj^8P=KeJ?W+1Vgs0^soLnWxF%^?Hawn~?fAOb^r2E%jR((7{xViHBZqnnT zS=TRg{P-ic+aSx~ZL7Zc^EBX9tTji7>k`&t;V(!x-`4gxar)kZ=6K48J%Ma9^m8`) z+++9Eto%9%tmD3L;;`WJ$?qN2J*hdW*K3B=7PMGhe6(yJ<(H`7vB*K6Ln^W&Z%i00 zDxoY*KbY2gr2BUN*M~08T<}ZF@hyD)r`QgQH|{QVtlS)bu4(Fzb&zycTyNdYtBT`zgdtdhqvdo8(f?BG*4Bi{q+>_m&l5X#Fr)KW-;m@?TH^_nYrHH zVIwDX*%))vlzw~BEarn>&XyLXuBKKmIM&RRKb_)n*W`3yhutCrMYUy>s$*{WQVbOT zV;95e5g4$ALmWef-A$XkdwEDyPTWJcSj&#uJ4gF@Y}H~Cetqq*dvbWhmw}^pO5W^P z^?64hRY=;QFCD5%HVc=xR?UgJOq;l40X2Hp+;Q(a{6g5;XW85SttxtEs=9WG%I&Up8jS2YlVXHgSU5|>hLYk+otsDgB#7=yWh~T z8I)cuD;_?y-;YN3kg>({pF9ly%9)fjhM0$(`t-r+xG@p-rRKIN(*xI>llHxSbhdm7 zy=s#i|G7ox>9MCHvv0n7OP2FF=Gt@nybCKj;O6bnY@6C* zngdMq$WNS46>rz%r~GVPKX<+Pv1jd)c~7F7UQVfltnQOHe+oId=J|0)O32-DX~m4E z<&=%`^J8!2o42K9cN(_k#N>9w>jfD_Pu^ut6jbKUf3&meCK36%Z0cG6u3dWqBGxFM zZ!B>PaUHI8&&^XaLLJ2un`EqEre=q}*_7Hg`)%;VyMFA)FN()JdGsu-X5_TDAG*Xd ztV<`3oIr1%T7(z$mR>kfq1l~zE}DGLRS9OarK<&hVGY!k@dNdKsK z@tRniP*ys)e<1APp0&ns^bSRGby4ul%buH2)zo0y;5pT{mL;|GSTD0awhDfjnwU}R zy*xiBSp*DNb&%w>aUFB2d#vhxIj6RKL*P=NEGKm2o+(L{u&UH{a?s?=pN|~cyrVcF z39$Rgh>pVHFF=!)tJb89@_|{zJx`0OkG)6+x>MncaX=WtPba0W>oQEPJ-GSUL9aHYc%cfYMV7qPkf+~whWj*eY+H#P6Yz^ji+CIs!`t4S{dH%*BTo@3^uiB=u^ zp&9p*XzZ-adF7KQCN3;X20Cr--9EgrIhdgC?U%{W<41G)P3g1qbO7?@(otjyWY6cM zr(3!aiwA4MKHb_odcy%-wk~`ZPu1r_K5tm!te6dK?dLS%)~me_x9n7r;prH&;^NJ& z#gxaCW>3SaPu<_P)H}CZ=BYZ!ilCx*(W=i=Zn;nsNE1aVUu@!2C7GR9yz8Zs{ml3w zX7Don_Vi1=rtIB%>&~QoPYy&~jh|lDqO}1k-gc-C@)JHLw5KLxN!1OL>f_W`-Pd0& zPP?iL?mI>NRbwlp^mn1w1$))zl}GG0XUf8erGpoG7KQEG_G~}2 zIO(2svB^gmOT-d4pwNMJ{R|6@U5b-=V>*`2@mb90`b;2wqd?$ zeRt^YJbib1YVNNe+C{9H-aoKCDkgz^y6DC6@sUSAhxM#M0KQwweibA(`5=qed@b{p{acUfHsilfLjK;H&Kdxo6gN%qi}*YnkNo zc2!ld5LDWV^43Ap!m5%xf?v8j9+HU4qU@JpWii8d{odM=jPm};#}Cb?6i}<10FI1+ z3F{y?lB$x2q*c~58=AnIGjrMc%Ho9T@XX0|kXxZ4xLoD=@&yBN;pI!JsAGzh$FHvV zvb|_3EZE^iNzzVW&rGTqGCin{=@U6&_JG01ZVZ^gIm0em)O^sAycY+iRo#jFp{*@A zKJ-Z{E@Q=cc)|9JkZ{edKvibnF2LLtQnh$UQ=O>b)@$}B1>$hWs$q`9BsBlitEJnpz8{C< zIxmg-p_9Hty+LB5_qU>}V*EzEB%`NCxmEWC4R(C~^jti+!LBlZZl2)l(m)GRt%7LnDLo3kKg zP^6CYMR+^8Fzo*97G2*I*4#<7cS&78**Tt_mPnm^uU}Q}w3Ea%`;b&yV3fi!mY%+jKph>Yv* zu%=sZh?3V^1fVDTyLmFtjgjPNAa#(z8hyfsoU5fDLj~TKj3eoR(v8PUu2y-rJUup! zF^xWR>LyWYN#{)+50@gcFP;g$E*Ptw+;PE_x38|13kq*z66f%1P;Yx8UTr>d`BS$W zkq07B?~7_)o!JjtAvlo`&wkPOoOg{rohn?}F^^F+CGjS1LFCJeWv`eNc9;1HDdS!R zfk9nXgOYwYJ@{e5zUU!G*7hw}I6RpCs-3#9aw`x?Ji9S#lBBU*<$8DD)HAXV!KhpB zAKq9s@=#IdYFOEsBvXbrDez7cF#uCxQP5SFqhw^3|Yq9NKSRwVe zF9`_li{DfPr`LkD9Fkg<@i|a@sAA27NcQTE#dDV8;Y<7HR@(;MnKOOrBud$nG{Tm* zC#nGd$todwSRXaac)q5xw|DbZ~4(d%f0Ps znBDvnHTM_2zL@%?7IAc74{dC6Y*}qm)jmwetj{_6AAGWAV1A^QityV5n*zJq#&(+& zJux|<;}IaGYK{i-T5KOxwc9m0Nwg$5c-oPJ<+NaFcp1>I#5H|W)6uELS;034JKk)q zFtxbQnKm$=u;TV+lo>Z}52|R~oChTxn}ijqPNwom&5@|)3l*yt`kox__MmjY%G7d0ZbCvJzmnUM$ z{BA?m239~ro}ABP7M|Olc7I0AOKQIFh8tt4UvK z63T$1>~?bMwYfoUI-{g=#QqjL(s2);T&jb-4|1lPvVrzP=|{|Xxog7;zA2c&&Lx&5 zbpLX4U{cR#4G*bm#)XdNW4#g^7p+x^<8FJ}~ib@jYQQ8+t! zC>tnO=KxD=X({Oos{ww!QzOTgHZ41FbPD{&{)?}MHQA5dpeRYrj4X&p^eEv3uiSe5 zV#BPA;vdz6A$oSyqMeUEB?TSZZ(iT)dlB;~9pztEm3U|UE2?hS>-1^&s*fBgk7@n- z>YAr5p9f-YmOp2#R6PBhJSaZwmlu;xJX%j))Urm=4D565HxJC(|2P=Dd$Y+X#|W?i zH1pJ;4&B#BwBudzH=Q(cK*oU1_cxxQ_eQOUERd|2JY5`F5V%EnH)@v;7pq>leG=?J zudvF4r01bIU8Zb`&_?w8k|6z5z?wKK_UVLlv9YXuWC!A#tl}$#O`XLC46J7kC}Zub>!C|t^{?6FKGL&KE9Pftmh6{D zPZO^!6Ga6Xz57(|b+naEWSihQqf(CAhxfggHO|n(w!EqB4f)K(EpqL-MYJ9ydZ$m+ zCM!SOE=nS&=Cuf*WG7DD3yeNCybj_@{NUILIBepGsfs`@`AIEjY+maR*rjQ>c`fc% ze+e!*_HIfTH~%GUSWWt!H**Xo5qjwGu6H*sUU0r9+|oPmu1I_vL>AM*s zd;a9c!4wYq=!RPUm%~xBe?C&`s>*3|BKO7S4Owp|MJ-{QQ-91`?f$$Z?{GEPY)cz< z+w7X0$HdBne3<7`ZO)~)AI1#XkkxO%mE@1x9?lr?xyo~E^3wg(kNZ-m*IPz+AWLhe zK7Z61lT#F2sbii))j@>C)Get+NkGtxSQ3_$le>p_;DiB;X0t%Sae`@O9pp5ySiOH9 zvLdsjR7k+I3@iCGt)bo#%rDv1NtIk6xRr!Pfa!{HN*B)1m2HD&=Mc*#j2b0K`WUFM z8XgXs-8bZ3!jkHHftQ)Jq6X00$&9k|u? z$-FuU%F-)5?CIq(yiM+E=%(F=9A{1ieu?~4$*$>#y`v+(s<&cYuE}s__m;LuoT^!v zy~=PjrS^E0=E**G#b)Bt%<+k)<}>B~TZd$C7qt|Xj^2yBpxQa%%&&#o*4*1uK0+!6 z_4lBA@F3DR)Kz!!_s%Sb3!?6=I2aPyG*MA?IuPM|awAcFir8cKH1wf8Pe-5*amJl^ zGLC&1{bE%XrLQl^SHr(l@M+_zc1bktV|pdC>>LdETI5}wY`@of{_+Q}-JGYi?%msv#~19YSorbm zhHP67UUh5i5>KHo@=jJU`{%9G+Ez{bb?Dxmqc+Z6^=#hj`%e#hgM{l5TXQ$XTn);y zA};K@RXj1jbmT90*7sc$=y2-PhxYyN%YX%A%F~EY*6{f)ChdE7`+e_ex01$iHBx9+ z;lZb!KM^XHeA-YNMz4AJY4W=L4<`<|mouX$=NNCq@>Tmrji8CP4*zh1+z*sk1`72Bj&|A z`a@(3W=~ZlPt7$LFPzKBd=*wo(ZyxtR8PL&sbazP^7p|T^*Ybs3Ao9`;?z=gOnTUo z53!w|4@18Jv$!UE`LwWWCr-~?7pESU(q($r6I?<5rk08+&C|9*Uai!*mKIcEMZe%`sghwtq&DdId zjvZCF`*`m#?dP1)>nCrWXdP@jU$yvSzJ27Bo98B;`?RWPC;IxdollP>E_fhQfbJ1?*NI_Weup*$q0 zy#~k;HgivFOUu#~!7G3?@$ZYO(l&VJmiBvjxOux}KSk&!ZKzqcDf{5zuM3q}(~nlO zc||Z3Rxy0q=Zljf$M;%3bitP8x}#@Du%_+K8lcNr6k`)|?$Z1t7VpU0b|tISNj_9q z1&o=5!kb%)!3`IkhCGRO7W|z?1=2+m>27BDI=F1tVq23 zxpu>@;@7YZc>&^k#$Nrd2QAtgG>4ZxJFU4lp;z;>XSB_SZApYo@v66^oSf5q790tX zBM*N{kJfH#wLdCsMz1YDyS;ORcEcxk7*4y!bG&?GQGbzoSZe2}f>S%Y?&;5;dhKq3 zYF7V^z9pB&JX3E}&Tk(1Dfg6Zi{6?L{i0QbnstdSU08W_zpm%w9@}lZ5-2=xd+2TW zfg8|InY6q5k^&m_hN5qKM(QGO)!)zU4s^fajFA`HQVlQL~g%2&zE!M zeeT#8n{nni*8N`R_2XAq4*M(HRU@`ny||vVE)r}5oqYDPA->nOHO+o<`OS;B)Qqa^ zeDVoiH$DgL8#nA~pJfND5*$S+P`JVy@%A$Hmx77l^+=2<)U~QcfgyE z6|(A z9{+vz(O;!eqw;rBZdxzQWu0kRJ^KCTn|FwLeO?q?+17mi_=lS9>GP%!0+Rou4slti zb;xB{I+k8Er1>7-`y0}Qxl?|AFlu}^XPXx1Ay`O<>9Up^QuF!_#vU0Y{dLyQ%?FE5 zTpxB{SE4W3=#vlWl3SjjE2s|V_GPVBhYq?oE#1{}&)9Cvxk(s<_wA9hIeYTg2qrv> z)USQR(U0jA)puV1#ar?gMC4S7fAxtz{eO*Jc{rBY`!_=|T1;iM$TEWwh4+1*y{s)F zsVpsHs}$0r6}_@FE!u>HN)t(O7!n7*5sP$Eh z^yxX`cfZ*)wj!vbxO;-biZxamTcg(eB3Yr{U+(5twg^g$Wv)tLInzWgMV~Z0+q%-F zU5&rwt0gn1mxhRlC!Wn)b0tq1T{GO~ z?y+>0fs?LjdEl(bIKPA!cAYjy%6AJr+DzLVe^70YepwhaQR3%YGCJJMkd;i;fS28T zpLE(Icpg2_Id#sx1>aq|*lW=H$fB?3LZVbwaD9QUlil}AgkpA270!MzSh3}fXSzST zpSK{=chNw0!z7I-+A5C$@$|`*eAu!^W}~=9mCjG0@tr4^`T#DA+CF$ew4-%!{k%7s za`bzt%4SuEi)RZpeIIuk?^eCLX3i?_huxJ67KD_wrtv#XyDnKvi|Goq7dHO)jYp~e zBuy>jnsrU$eQP9slv%y;rT4Bwwe0h>Hl3l?@}ZUl2cK>0pT3heo#`t7EFk1aT1x$D z->KtUvg{h*%8O#t1?|&HeCOx*xEfXo~>|J!&{lLuJ7uT8d5sQy^(eIlc z&px`i&CWXQu|{!_-$YSRR(fA)Lw(9Z)#AYTovp*gZ`HSVq$?J6WXw8od{e-r$M0&J z%Kc8Y>2RWDgT*6WHM(cx3hC>fvCA_*Bx)3yO6*c0b{l$$nd-~8C*-R^4K*{$if(AW zoYIsSt?Ex0F3Ws*)X_uaUiRXa&-q8uiP?p(JF1orh=!u35A=-u@FlWI@N7$u;>9z~ zvB7?3VT<8+q-2M-UuyF$WPZAx^ipl}9fR&1k5l(*2Xa1J;%OC?+sukJ;1`Q}sP7%wtZn_oPos9u-*2Ya}lFt4uz2bI8x?KQFVq z{nSYAZA+eTC?c~@>*~-v$-;bk)#U^JTb=fVnp}6AuwLTI;wvU9XXMuwPTAqU+eKh! zyXiD|)Q&uO`g2lUOk$X8aaJb&oaP}9& zD)fvM(dvDhFYfWxl8s9nH%yo8)^FitkWpOz3BPFr_?Oql5 zecZ2fTk1mNW8ymX?&`qY!3 zZKMC%yqi59V{I+X-Q4A~$SSY8yRC|vn{_8Q+s$gFik#!ha{c4?1KABK-x-Pg_Y$-) zFF31W`@Y+j4-=qR!!y|VHan{?M)U-ezG_p8*+#F;a+S(WR1DKRCb&YVj%$p`fM8~sh4 z9iK;3Ud!&Bv(aRewV{}p%%2ymBF3rJWorEUP12=QlXUIs%y5m3rV=ObhlMIe=URV$ zHSVTGmP@%#xu2*o!DpX+XM{pr?4G=dRNr1!xowYY?Cu5b3KMQr zZ}B%Q_rB0RY+J<4?clPXH65#&*H~?$aMa6ZW}i%%!=k?Fp>A>M)!WqqS=$r0=M+gE zQ(j^{)R$E05vXNYS9K?UcGLJBEoT|lU+*E?wIXRSze|4B(cHujA@c6)#Kv2>bNB# zjsfv{QgzAqmF`WFw5qyv9qL2TC(&tMDPI_V}&61F}8OmcAYGZXEJSYVNgPG_t#I?diIXoYK1w)~BY;ojXiE z|4?>9a;Saec(HAeW<2y)!cTX76*Gx?#4q3EtW+=%RMWV?Mk(m+rjU`P!qQ19firbi zQsN`3yC!`a8k$@J^727Ja?a_zNQVBaB`!UOx zCg>%_H(WDLetEThYM=~?P;2q-PAqx#KWe;%H! zy`tt!YbhBddUR)hk$y%}daKWEtr*R?;j^>a&*av&>ky*K*WJ1I6YV;u8mta6-nb&Y zv1*vhx*uI|WINNN+vID$yuIXZ`;$ETilKm_FXIl`G>TgZS6GIO)33iicq`A`#kOkS zDJ8AOlG>W^bB--5*Em?I%qVd<@0VV@aLy!G^Rx*o>%6pnz3EkA@#>El%jBy)o_4?Y z=y_!~1lCn|?yLJ)|Ep8bOkJ^_0`GghdQaZodQ+2AmeyA6qpvV`O-*9Ni<0TVm2+-d zo21QrZM39cGs8vpwN1tfQDeR)yj|m6(O&%ABl6+8?Lx7a2?rVRPXU)dbUoeKTa?k1 zs?t%I-P7^DXVbN(%MKKuy*Knplz+|j`)vy2LIzjuINeYYvn(*drncjGdz4-NoO~5> zrK;<|Ukgl{-)de^=l^aVTwxTnL8{CF?v6G;7hMqdqfBUqmgV5uoRHoTkK2(8O`TQy zMeVUkTEAqRu#naHas0i>2Pfa#zxjtfEwjwtJC9%S&$kKx{b)cZ_gPYRi_`wwLzDsrmS^{|`$2^upW8Dpkhbdlp)^wBA!ak&&B|8s?I5 z>1CLd=402}<&j^-&I7pcw>f?F+;j)qwVD|kvdj7xM8>buF{%q_=onnDtry#==sn^V zW8n0lML&u; zy;EN0duZ>DpiEwIAhi3E62w$GuqQyq#LtUS#wzTx02Z9h21Rp}X-n?uMth?2^Bd_@sE}PpVTs zZ4jS*W6P#p-cp>)@fmAFwx-zfZj=P*E)oy4J#b7}Rlw}$2J)%2@8s4G(_htH)MM06^D0}`WO@zwdtGt&e$6~IMP<<8mDbB&&9GY=qwqg z<sYRMU7o2vKB?3RI78$|_8jPZd3cby5c;Doz_ z`;NjzX%D_V`2mkr@AawP*RR?|dU%7O&c9wloq3}VHL&j=-{YQ@`rSLqA zDFc-)IVS~;>x|f~Rk{{gHlL$E6l|ZYZ2w33+Mz?eYc4x1incZGv2>VIA>-R6r}%5k z!MU;3B^%~>PJI}2B_Y^AJa|HosIW)fq%|qv62EK=O?H(JepgqxeD-qx^BPaCZ=L#8On6{{cT@h&efB!NE=9A}PTLl3 zv-sZO$3_aBmoqJ&Xpq?9ht zcEdy2_h06k{1PWsWmV_5eBuN9L#`_>IzIW=_ZR=?Kb>ZIcJ!Q72pF#QHSnLCmQrx+ z?T0V$nrC34Hs-8aaRwIAi?#q#EtFA%B{rm0U4fsQHXc8{|!hsZ33M z*8TPC-dn{ezMGcQ=2v!hPlR-zJpF3V~@dpQ4hhuh&P3H?_a zuBCqQ64%SbySElGI^L-cHPUl0Db`!&2*%2XnG>f6-k3n{|QxwCYl=<}T^q znl^@wtZhjC7@4Tp7{B@B2h%5eTif&g*jjPgOXwb>>3EZy%C7R==AYYB)a>mot!j0{ z_q+F6_rzT7mWAOO-@nJnS(*o*U9!^uIgD%cZ)KXI2uj&m`5zjeQvUnDmEHcKkuVOS zkpu@uG5Y6!$B{GzUvwfgII2Guzn&xQIMM-pT3 z0y84d^7tG@V*BM7662YJgN>1W2zY!YUq0Jo;FSR4}YI4lkc z_hxF!$~n5+cA3@T@c5SSf+&I#0> zVHa2|5il%jFFXNUjg76r!p$?NjzFZSzX@14#rfND97Vt?-_qa{eVRh}gKLo~26+}} zi~!Lk&{!IyfdFwD548h8Hxx=^Xby|nEJskICl>rWR{)KnkhlRfmP2I4LNF$gy#WoF zM&~05R7Wt5L~RXdv;dzEl!?v9@iG1=9;!7`Q=s9w0-`gDH((r#`V7Z|!^seyfd;qweY-cH5j?~P zfkvXX1~i(F=mTgBgUB9eAS`qZIL#f2VG!)ckb!_;5PODk6zcmxqtUnlG?qa01~d$B zaNvY!tOFWu2Rs4{72O9xVR@fNFsRSKd@LHDIo{|A9q4@EADCQ7g2d!ULL$VTrEy)7 zaArO>j>C0C!6EzTIPe8bmlTP`HSjDHD|0-G!FdKzVe`>g4&`{@=9tcD04peeG@g@r zG=_m;J{H#-&7t^|<1u^!lRYCqb0drc^oa5T*aGtzhQTl>1rJgq$(Pu~=*ZoJeEyfjwjMLD)d$!Usr=>Wxof`Ij3_$@njd6*52 zVlLDU1OP42SPV!Rtp_33!WAFr8c@Qb@)H1bM0HL8c0`{g0A!-P5WozoOMqq=&jh45 zH0D5PNAWYjAv{k**23Z+(9rs56iT7B0nqSx3N#dR!8iu<8K8|ZjvZqhJH|LLEJXHD zHR9u7I&2)cB~AmtfzHSB#~3FVW1L`&al{zo0LWr%kQg2!0HdS!M}P=08)7M}wuh1! zi#b3;@gzWC2E$iCLu(Qk$MP_nWML6(9~_puM`1R$4?tMhJ|OF%Ih26uFuUjYSY9PK zsMb(kpsvMyivy3t#t~=_iX%8ufb&N(I4@)5EsjF#UziWiM?gb+9xx6HLX1C##rMYI zzR$5(+=Uho9&-TTqiaCB1oM5Maj2}oO3~U6N+zi85uSlY;cF0>twH*w@HI%xhM+9N z@+HZmFxvncmM;N?3D7lwhSf6!l-QV^(hP=y2~ZolH=v<4A_pB0EN=k~kM|6YK?nxx zv%+M6Ob|H(4Z}19l-;O4fQIEpk_Qfg%m=+l%s+sJVM4guYK-|<3?G0dG2BT)t%mM{ z1VDt!9@04$hoI$##Z!`l%^~{$C^dRW;lFzTP$mm7dWZ;wx?jI2B@cD3@4c$r1-=N)&#Xsm|K> zJzD5u;+O%f50gDq=a_yeP&&E>2fx&yd5d9id=Fi8EM`Ln#p*mr)0mx(rs;2W#Di!L z-9AJHkV3KC2!RO0yQ7WZf5~s(o{ex}&K_x9U7f$Lje#BMSi-%>%7RfO3O^~Dx;gJu z2BnVvbFs3mt`mO~O_CcOo%x#?CyEaUX*0($jwDBbH_|Mvuj|B7jv#$!*b7Yvc#fN) z(do={qM<$qXLoYaw}%5o)m*Ke_V3f8v?*;u8ZNxsv+wU8zeep33_)5=ZOKYw>Hh)o Cv4If)