/* Copyright (C) 2001 Damir Zucic */

/*=============================================================================

				chi5_from_cdnecznh1.c

Purpose:
	Calculate dihedral angle chi5, using CD, NE, CZ and NH1 coordinates.

Input:
	(1) Pointer to AtomS structure, pointing to the first atom of the
	    current macromolecular complex.
	(2) Index of the first atom of the current residue.
        (3) Index of the last atom of the currrent residue.

Output:
	Return value.

Return value:
	(1) Dihedral angle chi5, on success.
	(2) BADDIHEDANGLE on failure.

========includes:============================================================*/

#include <stdio.h>

#include <math.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>

#include "defines.h"
#include "typedefs.h"

/*======function prototypes:=================================================*/

int		ExtractFourAtoms_ (VectorS *, VectorS *, VectorS *, VectorS *,
				   char *, char *, char *, char *,
				   AtomS *, size_t, size_t);
void		VectorProduct_ (VectorS *, VectorS *, VectorS *);
double		AbsoluteValue_ (VectorS *);
double		ScalarProduct_ (VectorS *, VectorS *);

/*======calculate chi5 from CD, NE, CZ and NH1:===============================*/

double Chi5FromCDNECZNH1_ (AtomS *atomSP, size_t atom_startI, size_t atom_endI)
{
static VectorS		CD_vectorS, NE_vectorS, CZ_vectorS, NH1_vectorS;
int			n;
VectorS			NE_CD_vectorS, NE_CZ_vectorS;
VectorS			CZ_NE_vectorS, CZ_NH1_vectorS;
VectorS			u1S, u2S;
VectorS			v1S, v2S;
double			denom, ratio, alpha;
double			chi5;

/* Extract CD, NE, CZ and NH1 coordinates: */
n = ExtractFourAtoms_ (&CD_vectorS, &NE_vectorS, &CZ_vectorS, &NH1_vectorS,
		       "CD", "NE", "CZ", "NH1",
		       atomSP, atom_startI, atom_endI);

/* All four atoms are required to calculate the angle chi5: */
if (n < 4) return BADDIHEDANGLE;

/* The first pair of auxiliary vectors: */
NE_CD_vectorS.x = CD_vectorS.x - NE_vectorS.x;
NE_CD_vectorS.y = CD_vectorS.y - NE_vectorS.y;
NE_CD_vectorS.z = CD_vectorS.z - NE_vectorS.z;
NE_CZ_vectorS.x = CZ_vectorS.x - NE_vectorS.x;
NE_CZ_vectorS.y = CZ_vectorS.y - NE_vectorS.y;
NE_CZ_vectorS.z = CZ_vectorS.z - NE_vectorS.z;

/* The second pair of auxiliary vectors: */
CZ_NE_vectorS.x = NE_vectorS.x - CZ_vectorS.x;
CZ_NE_vectorS.y = NE_vectorS.y - CZ_vectorS.y;
CZ_NE_vectorS.z = NE_vectorS.z - CZ_vectorS.z;
CZ_NH1_vectorS.x = NH1_vectorS.x - CZ_vectorS.x;
CZ_NH1_vectorS.y = NH1_vectorS.y - CZ_vectorS.y;
CZ_NH1_vectorS.z = NH1_vectorS.z - CZ_vectorS.z;

/* Two vectors  perpendicular to  NE_CZ_vectorS,  mutually orthogonal, */
/* the second in the plane defined by NE_CD_vectorS and NE_CZ_vectorS: */
VectorProduct_ (&u1S, &NE_CD_vectorS, &NE_CZ_vectorS);
VectorProduct_ (&u2S, &u1S, &NE_CZ_vectorS);

/* Two vectors  perpendicular to  CZ_NE_vectorS,  mutually  orthogonal, */
/* the second in the plane defined by CZ_NE_vectorS and CZ_NH1_vectorS: */
VectorProduct_ (&v1S, &CZ_NE_vectorS, &CZ_NH1_vectorS);
VectorProduct_ (&v2S, &CZ_NE_vectorS, &v1S);

/* Calculate the angle alpha, which will be used to calculate chi5: */

/* Avoid division by zero: */
denom = AbsoluteValue_ (&u1S) * AbsoluteValue_ (&v1S);
if (denom == 0.0) return BADDIHEDANGLE;

/* Use the scalar product to calculate the cosine of the angle: */
ratio = ScalarProduct_ (&u1S, &v1S) / denom;

/* Arc cosine is very sensitive to floating point errors: */
if (ratio <= -1.0) alpha = 3.1415927;
else if (ratio >= 1.0) alpha = 0.0;
else alpha = acos (ratio);

/* There are two possible solutions; the right one is resolved here: */
if (ScalarProduct_ (&v2S, &u1S) >= 0) chi5 = alpha;
else chi5 = -alpha;

/* Return the angle (in radians): */
return chi5;
}

/*===========================================================================*/


