/* Copyright (C) 2001, 2002 Damir Zucic */

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

				edit_chi1.c

Purpose:
	Edit the chi1 angle for every selected residue in the specified
	macromolecular complex. A residue is treated as selected if the
	first atom of this residue is selected.  For proteins,  this is
	typically the N atom (nitrogen).

Input:
	(1) Pointer to MolComplexS structure.
	(2) Pointer to RuntimeS structure.
	(3) Pointer to ConfigS structure.
	(4) Rotation angle.

Output:
	(1) The angle chi1 changed for every selected residue.
	(2) Return value.

Return value:
	(1) Positive always (trivial).

========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		ExtractCACB_ (VectorS *, VectorS *, AtomS *, size_t, size_t);
int		RotateAtom_ (AtomS *, VectorS *, VectorS *, double);
int		DihedralAngles_ (MolComplexS *, ConfigS *);

/*======change chi1 angle for selected residues:=============================*/

int EditChi1_ (MolComplexS *mol_complexSP,
	       RuntimeS *runtimeSP, ConfigS *configSP,
	       double delta_chi1)
{
int			residuesN, residueI;
size_t			atomsN;
ResidueS		*residueSP;
size_t			atom_startI, atom_endI, atomI;
AtomS			*atomSP;
char			*residue_nameP;
int			n;
char			*atom_nameP;
static VectorS		CA_vectorS, CB_vectorS;

/* Copy the number of residues in the current complex: */
residuesN = mol_complexSP->residuesN;

/* Copy the number of atoms in the current complex: */
atomsN = mol_complexSP->atomsN;

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

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

	/* Pointer to the first atom: */
	atomSP = mol_complexSP->atomSP + atom_startI;

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

	/* Edit chi1 angle if the current residue is selected. */

	/* If the first atom of the current residue is */
	/* not selected,  the residue is not selected: */
	if (atomSP->selectedF == 0) continue;

	/* Extract CA and CB coordinates: */
	n = ExtractCACB_ (&CA_vectorS, &CB_vectorS,
			  mol_complexSP->atomSP, atom_startI, atom_endI);
	if (n < 2) continue;

	/* Change the chi1 angle: */
	for (atomI = atom_startI; atomI <= atom_endI; atomI++)
		{
		/* Pointer to the current atom: */
		atomSP = mol_complexSP->atomSP + atomI;

		/* Pointer to the purified atom name: */
		atom_nameP = atomSP->raw_atomS.pure_atom_nameA;

		/* Do not rotate H, N, CA, HA, C, O and CB: */
		if (!strcmp (atom_nameP, "H" )) continue;
		if (!strcmp (atom_nameP, "N" )) continue;
		if (!strcmp (atom_nameP, "CA")) continue;
		if (!strcmp (atom_nameP, "HA")) continue;
		if (!strcmp (atom_nameP, "C" )) continue;
		if (!strcmp (atom_nameP, "O" )) continue;
		if (!strcmp (atom_nameP, "CB")) continue;

		/* Rotate the current atom about CA-CB bond: */
		RotateAtom_ (atomSP, &CA_vectorS, &CB_vectorS, delta_chi1);
                }
	}

/* Update dihedral angles and cis-trans flags: */
DihedralAngles_ (mol_complexSP, configSP);

/* Return positive value (trivial): */
return 1;
}

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


