/* Copyright (C) 2001 Damir Zucic */

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

				reset_phi.c

Purpose:
	Reset the phi angle in each residue. Each phi angle will be changed
	to -180 degrees.  The chain will be messed up!  Please note that if
	you modify default angle  you will also have to modify the function
	ApplyStructure_ (), because in that function it is assumed that you
	are using -180 degrees here.

Input:
	(1) Pointer to MolComplexS structure, with macromolecular data.

Output:
	(1) Phi angle changed to -180 degrees (in each residue).
	(2) Return value.

Return value:
	(1) Positive on success.
	(2) Negative on failure.

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

#include <stdio.h>

#include <string.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		ExtractHNCAC_ (VectorS *, VectorS *, VectorS *, VectorS *,
			       AtomS *, size_t, size_t);
double          PhiFromHNCAC_ (VectorS *, VectorS *, VectorS *, VectorS *);
int		RotateAtom_ (AtomS *, VectorS *, VectorS *, double);

/*======change phi angle to -180 degrees; do it for each residue:============*/

int ResetPhi_ (MolComplexS *mol_complexSP)
{
int			residuesN;
int			residueI;
ResidueS		*curr_residueSP;
size_t			atom_startI, atom_endI, atomI;
AtomS			*atomSP;
char			*curr_residue_nameP;
int			n;
static VectorS		H_vectorS, N_vectorS, CA_vectorS, C_vectorS;
double			phi, delta_phi;

/* Prepare the number of residues: */
residuesN = mol_complexSP->residuesN;

/* Scan the macromolecular complex: */
for (residueI = 0; residueI < residuesN; residueI++)
	{
	/* Pointer to the current residue: */
	curr_residueSP = mol_complexSP->residueSP + residueI;

	/* Prepare the atomic index range: */
	atom_startI = curr_residueSP->residue_startI;
	atom_endI   = curr_residueSP->residue_endI;

	/* Skip proline: */
	atomSP = mol_complexSP->atomSP + atom_startI;
	curr_residue_nameP = atomSP->raw_atomS.pure_residue_nameA;
	if (strcmp (curr_residue_nameP, "PRO") == 0) continue;

	/* Extract H, N, CA and C coordinates: */
	n = ExtractHNCAC_ (&H_vectorS, &N_vectorS, &CA_vectorS, &C_vectorS,
			   mol_complexSP->atomSP, atom_startI, atom_endI);

	/* All four atoms are required to reset the phi angle: */
	if (n < 4) continue;

	/* If this point is reached, the coordinates */
	/* of required  four atoms  were  retrieved. */

	/* Calculate the phi angle (radians), using the H atom coordinates: */
	phi = PhiFromHNCAC_ (&H_vectorS, &N_vectorS, &CA_vectorS, &C_vectorS);

	/* Prepare the rotation angle: */
	delta_phi = -3.1415927 - phi;

	/* Now rotate all atoms except H, N and CA about the N-CA bond: */
	for (atomI = atom_startI; atomI <= atom_endI; atomI++)
		{
		/* Pointer to the current atom: */
		atomSP = mol_complexSP->atomSP + atomI;

		/* Skip H, N and CA: */
		if ((strcmp (atomSP->raw_atomS.pure_atom_nameA, "H")  == 0) ||
		    (strcmp (atomSP->raw_atomS.pure_atom_nameA, "N")  == 0) ||
		    (strcmp (atomSP->raw_atomS.pure_atom_nameA, "CA") == 0))
			{
			continue;
			}

		/* Rotate the current atom about the N-CA bond: */
		RotateAtom_ (atomSP, &N_vectorS, &CA_vectorS, delta_phi);
		}
	}

/* Return positive value on success: */
return 1;
}

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


