def fitModels(m0, m1, fraction=0.5): """sieveFitModels takes two conformers and identifies the fraction of the residues that produce the minimum RMSD.""" rList0 = m0.residues rList1 = m1.residues return fitResidues(rList0, rList1, fraction) def fitResidues(rList0, rList1, fraction=0.5, maxrmsd=0.1): """sieveFitModels takes two lists of corresponding residues and identifies the fraction of the residues that produce the minimum RMSD.""" # make sure the residues correspond if len(rList0) != len(rList1): raise ValueError("matching different number of residues") #for r0, r1 in zip(rList0, rList1): # if r0.type != r1.type: # raise ValueError("matching residues of different types") from util import getAtomList aList0 = getAtomList(rList0) aList1 = getAtomList(rList1) keep = int(len(rList0) * fraction) while len(aList0) > keep: if not sieve(aList0, aList1, maxrmsd): break return ([ a.residue for a in aList0 ], [ a.residue for a in aList1 ]) def sieve(aList0, aList1, maxrmsd): import numpy, math import chimera from chimera import match position0 = match._coordArray(aList0) # fixed position1 = match._coordArray(aList1) # movable m = match.Match(position0, position1, wantRMS=1) if m.rms < maxrmsd: return False matrix = m.matrix() maxdsq = 0 Si = numpy.subtract(position0, m.center(position0)) Sj = numpy.subtract(position1, m.center(position1)) result = numpy.inner(Si, m.matrix()) d = numpy.subtract(result, Sj) dsq = numpy.add.reduce(numpy.transpose(numpy.multiply(d, d))) worst = numpy.argmax(dsq) del aList0[worst] del aList1[worst] return True