def accGeneric(donor, donorHyds, acceptor, r2, minAngle):
	if base.verbose:
		print "generic acceptor"
	dp = donor.xformCoord()
	ap = acceptor.xformCoord()
	if donor.element.name == "S":
		r2 = sulphurCompensate(r2)
	if base.verbose:
		print "distance: %g, cut off: %g" % (distance(dp, ap), sqrt(r2))
	if sqdistance(dp, ap) > r2:
		if base.verbose:
			print "dist criteria failed"
		return 0
	if base.verbose:
		print "dist criteria okay"
	 
	ap = acceptor.xformCoord()
	dp = donor.xformCoord()
	for bonded in acceptor.primaryNeighbors():
		bp = bonded.xformCoord()
		if base.verbose:
			print "angle: %g" % angle(bp, ap, dp)
		ang = angle(bp, ap, dp)
		if ang < minAngle:
			if base.verbose:
				print "angle too sharp (%g < %g)" % (ang,
								minAngle)
			return 0
	if base.verbose:
		print "angle(s) okay (all > %g)" % minAngle
	return 1
def accSynAnti(donor, donorHyds, acceptor, synAtom, planeAtom, synR2, synPhi,
		synTheta, antiR2, antiPhi, antiTheta):
	"""'planeAtom' (in conjunction with acceptor, and with 'synAtom'
	    defining the 'up' direction) defines a plane.  If donor is on
	    the same side as 'synAtom', use syn params, otherwise anti params.
	"""

	if base.verbose:
		print "accSynAnti"
	dc = donor.xformCoord()
	dp = dc
	ac = acceptor.xformCoord()
	ap = ac
	pp = planeAtom.xformCoord()
	sp = synAtom.xformCoord()

	synXform = Xform.lookAt(ap, pp, sp - pp)
	xdp = synXform.apply(dp)

	phiBasePos = pp
	phiPlane = [ap, pp, sp]

	if xdp.y > 0.0:
		if base.verbose:
			print "Syn"
		if donor.element.name == "S":
			# increase distance cutoff to allow for larger
			# vdw radius of sulphur (which isn't considered
			# considered as a donor in original paper)
			synR2 = sulphurCompensate(synR2)
		return testPhiPsi(dp, donorHyds, ap, phiBasePos, phiPlane,
						synR2, synPhi, synTheta)
	if base.verbose:
		print "Anti"
	if donor.element.name == "S":
		# increase distance to compensate for sulphur radius
		antiR2 = sulphurCompensate(antiR2)
	return testPhiPsi(dp, donorHyds, ap, phiBasePos, phiPlane,
						antiR2, antiPhi, antiTheta)
def accPhiPsi(donor, donorHyds, acceptor, bonded1, bonded2, r2, phi, theta):
	if base.verbose:
		print "accPhiPsi"

	# when acceptor bonded to one heavy atom
	if not bonded1:
		# water
		bonded = acceptor.primaryNeighbors()
		if len(bonded) > 0:
			bonded1 = bonded[0]
			if len(bonded) > 1:
				bonded2 = bonded[1]
		
	phiPlane, phiBasePos = getPhiPlaneParams(acceptor, bonded1, bonded2)
	if donor.element.name == "S":
		r2 = sulphurCompensate(r2)
	return testPhiPsi(donor.xformCoord(), donorHyds,
		acceptor.xformCoord(), phiBasePos, phiPlane, r2, phi, theta)
def accThetaTau(donor, donorHyds, acceptor, upsilonPartner, r2,
						upsilonLow, upsilonHigh, theta):
	if base.verbose:
		print "accThetaTau"
	dp = donor.xformCoord()
	ap = acceptor.xformCoord()

	if donor.element.name == "S":
		r2 = sulphurCompensate(r2)
	if base.verbose:
		print "distance: %g, cut off: %g" % (distance(dp, ap), sqrt(r2))
	if sqdistance(dp, ap) > r2:
		if base.verbose:
			print "dist criteria failed"
		return 0
	if base.verbose:
		print "dist criteria okay"
	
	if upsilonPartner:
		upPos = upsilonPartner.xformCoord()
	else:
		# upsilon measured from "lone pair" (bisector of attached
		# atoms)
		bondedPos = []
		for bonded in acceptor.primaryNeighbors():
			bondedPos.append(bonded.xformCoord())
		lonePairs = bondPositions(ap, tetrahedral, 1.0, bondedPos)
		bisectors = []
		for lp in lonePairs:
			bisectors.append(ap - (lp - ap))
		upPos = bisectors[0]
		for bs in bisectors[1:]:
			if base.verbose:
				print "Testing 'extra' lone pair"
			if testThetaTau(dp, donorHyds, ap, bs,
						upsilonLow, upsilonHigh, theta):
				return 1
	return testThetaTau(dp, donorHyds, ap, upPos,
						upsilonLow, upsilonHigh, theta)
def donGeneric(donor, donorHyds, acceptor, sp2Orp2, sp3Orp2, sp3Nrp2,
	sp2Or2, sp3Or2, sp3Nr2, genRp2, genR2, minHydAngle, minBondedAngle):
	if base.verbose:
		print "donGeneric"
	dc = donor.xformCoord()
	ac = acceptor.xformCoord()

	accType = acceptor.idatmType
	if not typeInfo.has_key(accType):
		return 0

	geom = typeInfo[accType].geometry
	element = acceptor.element.name
	if element == 'O' and geom == planar:
		if base.verbose:
			print "planar O"
		r2 = sp2Or2
		rp2 = sp2Orp2
	elif element == 'O' and geom == tetrahedral \
	or element == 'N' and geom == planar:
		if base.verbose:
			print "planar N or tet O"
		r2 = sp3Or2
		rp2 = sp3Orp2
	elif element == 'N' and geom == tetrahedral:
		if base.verbose:
			print "tet N"
		r2 = sp3Nr2
		rp2 = sp3Nrp2
	else:
		if base.verbose:
			print "generic acceptor"
		if acceptor.element.name == "S":
			r2 = sulphurCompensate(genR2)
			minBondedAngle = minBondedAngle - 9
		r2 = genR2
		rp2 = genRp2

	ap = acceptor.xformCoord()
	dp = donor.xformCoord()
	if len(donorHyds) == 0:
		D2 = dc.sqdistance(ac)
		if D2 > r2:
			if base.verbose:
				print "dist criteria failed (%g > %g)" % (
							sqrt(D2), sqrt(r2))
			return 0
	else:
		for hydPos in donorHyds:
			if sqdistance(hydPos, ap) < rp2:
				break
		else:
			if base.verbose:
				print "hyd dist criteria failed (all >= %g)" % (
								sqrt(rp2))
			return 0
		
	if base.verbose:
		print "dist criteria OK"

	for bonded in donor.primaryNeighbors():
		if bonded.element.number <= 1:
			continue
		bp = bonded.xformCoord()
		ang = angle(bp, dp, ap)
		if ang < minBondedAngle:
			if base.verbose:
				print "bonded angle too sharp (%g < %g)" % (
						ang, minBondedAngle)
			return 0
		
	if len(donorHyds) == 0:
		if base.verbose:
			print "No specific hydrogen positions; default accept"
		return 1

	for hydPos in donorHyds:
		ang = angle(dp, hydPos, ap)
		if ang >= minHydAngle:
			if base.verbose:
				print "hydrogen angle okay (%g >= %g)" % (
						ang, minHydAngle)
			return 1
	if base.verbose:
		print "hydrogen angle(s) too sharp (< %g)" % minHydAngle
	return 0
def donThetaTau(donor, donorHyds, acceptor,
					sp2Orp2, sp2Otheta,
					sp3Orp2, sp3Otheta, sp3Ophi,
					sp3Nrp2, sp3Ntheta, sp3Nupsilon,
					genRp2, genTheta,
					isWater=0):
					# 'isWater' only for hydrogenless water
	if base.verbose:
		print "donThetaTau"
	if len(donorHyds) == 0 and not isWater:
		if base.verbose:
			print "No hydrogens; default failure"
		return 0
	ap = acceptor.xformCoord()
	dp = donor.xformCoord()

	accType = acceptor.idatmType
	if not typeInfo.has_key(accType):
		if base.verbose:
			print "Unknown acceptor type failure"
		return 0
	
	geom = typeInfo[accType].geometry
	element = acceptor.element.name
	if element == 'O' and geom == planar:
		if base.verbose:
			print "planar O"
		for hydPos in donorHyds:
			if sqdistance(hydPos, ap) <= sp2Orp2:
				break
		else:
			if not isWater:
				if base.verbose:
					print "dist criteria failed (all > %g)"\
						% sqrt(sp2Orp2)
				return 0
		theta = sp2Otheta
	elif element == 'O' and geom == tetrahedral \
	or element == 'N' and geom == planar:
		if base.verbose:
			print "planar N or tet O"
		for hydPos in donorHyds:
			if sqdistance(hydPos, ap) <= sp3Orp2:
				break
		else:
			if not isWater:
				if base.verbose:
					print "dist criteria failed (all > %g)"\
						% sqrt(sp3Orp2)
				return 0
		theta = sp3Otheta
		
		# only test phi for acceptors with two bonded atoms
		if len(acceptor.primaryBonds()) == 2:
			if base.verbose:
				print "testing donor phi"
			bonded = acceptor.primaryNeighbors()
			phiPlane, basePos = getPhiPlaneParams(acceptor,
							bonded[0], bonded[1])
			if not testPhi(donor.xformCoord(), ap, basePos,
							phiPlane, sp3Ophi):
				return 0

	elif element == 'N' and geom == tetrahedral:
		if base.verbose:
			print "tet N"
		for hydPos in donorHyds:
			if sqdistance(hydPos, ap) <= sp3Nrp2:
				break
		else:
			if not isWater:
				if base.verbose:
					print "dist criteria failed (all > %g)"\
						% sqrt(sp3Nrp2)
				return 0
		theta = sp3Ntheta

		# test upsilon against lone pair directions
		bondedPos = []
		for bonded in acceptor.primaryNeighbors():
			bondedPos.append(bonded.xformCoord())
		lpPos = bondPositions(ap, geom, 1.0, bondedPos)
		if lpPos:
			# fixed lone pair positions
			for lp in bondPositions(ap, geom, 1.0, bondedPos):
				# invert position so that we are
				# measuring angles correctly
				ang = angle(dp, ap, ap - (lp - ap))
				if ang > sp3Nupsilon:
					if base.verbose:
						print "acceptor upsilon okay"\
							" (%g > %g)" % (
							ang, sp3Nupsilon)
					break
			else:
				if base.verbose:
					print "all acceptor upsilons failed"\
						" (< %g)" % sp3Nupsilon
				return 0
		# else: indefinite lone pair positions; default okay
	else:
		if base.verbose:
			print "generic acceptor"
		if acceptor.element.name == "S":
			genRp2 = sulphurCompensate(genRp2)
		for hydPos in donorHyds:
			if sqdistance(hydPos, ap) <= genRp2:
				break
		else:
			if base.verbose:
				print "dist criteria failed (all > %g)" % sqrt(
								genRp2)
			return 0
		theta = genTheta
	if base.verbose:
		print "dist criteria OK"

	return testTheta(dp, donorHyds, ap, theta)
def donUpsilonTau(donor, donorHyds, acceptor,
  sp2Or2, sp2OupsilonLow, sp2OupsilonHigh, sp2Otheta, sp2Otau,
  sp3Or2, sp3OupsilonLow, sp3OupsilonHigh, sp3Otheta, sp3Otau, sp3Ophi,
  sp3Nr2, sp3NupsilonLow, sp3NupsilonHigh, sp3Ntheta, sp3Ntau, sp3NupsilonN,
  genR2, genUpsilonLow, genUpsilonHigh, genTheta, tauSym):

	if base.verbose:
		print "donUpsilonTau"

	accType = acceptor.idatmType
	if not typeInfo.has_key(accType):
		return 0
	
	geom = typeInfo[accType].geometry
	element = acceptor.element.name
	if element == 'O' and geom == planar:
		if base.verbose:
			print "planar O"
		return testUpsilonTauAcceptor(donor, donorHyds, acceptor,
			sp2Or2, sp2OupsilonLow, sp2OupsilonHigh, sp2Otheta,
			sp2Otau, tauSym)
	elif element == 'O' and geom == tetrahedral \
	or element == 'N' and geom == planar:
		if base.verbose:
			print "planar N or tet O"
		return testUpsilonTauAcceptor(donor, donorHyds, acceptor,
			sp3Or2, sp3OupsilonLow, sp3OupsilonHigh, sp3Otheta,
			sp3Otau, tauSym)
	elif element == 'N' and geom == tetrahedral:
		if base.verbose:
			print "tet N"
		# test upsilon at the N
		# see if lone pairs point at the donor
		bondedPos = []
		for bonded in acceptor.primaryNeighbors():
			bondedPos.append(bonded.xformCoord())
		if len(bondedPos) > 1:
			ap = acceptor.xformCoord()
			dp = donor.xformCoord()
			lonePairs = bondPositions(ap, tetrahedral, 1.0,
								bondedPos)
			for lp in lonePairs:
				upPos = ap - (lp - ap)
				ang = angle(upPos, ap, dp)
				if ang >= sp3NupsilonN:
					if base.verbose:
						print "upsilon(N) okay" \
							" (%g >= %g)" % (ang,
							sp3NupsilonN)
					break
			else:
				if base.verbose:
					print "all upsilon(N) failed (< %g)" % (
								sp3NupsilonN)
				return 0
		elif base.verbose:
			print "lone pair positions indeterminate at N;" \
						"upsilon(N) default okay"
		return testUpsilonTauAcceptor(donor, donorHyds, acceptor,
			sp3Nr2, sp3NupsilonLow, sp3NupsilonHigh, sp3Ntheta,
			sp3Ntau, tauSym)
	else:
		if base.verbose:
			print "generic acceptor"
		if acceptor.element.name == "S":
			genR2 = sulphurCompensate(genR2)
		return testUpsilonTauAcceptor(donor, donorHyds, acceptor,
			genR2, genUpsilonLow, genUpsilonHigh, genTheta,
			None, None)
	if base.verbose:
		print "failed criteria"
	return 0