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

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

				edit_chi2.c

Purpose:
	Edit the chi2 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). In this function the symbol XG
	stands for CG, CG1, OG, OG1 or SG.  The CG atom appears in PRO,
	LEU, MET, PHE, TRP, ASN, GLN, TYR, ASP, GLU, LYS, ARG and  HIS.
	The CG1 atom appears in ILE,  OG in SER,  OG1 in THR  and SG in
	CYS. This function is not able to handle non-standard residues.

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

Output:
	(1) Chi2 angle 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		ExtractCBXG_ (VectorS *, VectorS *, AtomS *, size_t, size_t);
int		RotateAtom_ (AtomS *, VectorS *, VectorS *, double);
int		DihedralAngles_ (MolComplexS *, ConfigS *);

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

int EditChi2_ (MolComplexS *mol_complexSP,
	       RuntimeS *runtimeSP, ConfigS *configSP,
	       double delta_chi2)
{
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		CB_vectorS, XG_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 chi2 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 CB and XG coordinates: */
	n = ExtractCBXG_ (&CB_vectorS, &XG_vectorS,
			  mol_complexSP->atomSP, atom_startI, atom_endI);
	if (n < 2) continue;

	/* Change the chi2 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, CB and HB: */
		if (strcmp (atom_nameP, "H" ) == 0) continue;
		if (strcmp (atom_nameP, "N" ) == 0) continue;
		if (strcmp (atom_nameP, "CA") == 0) continue;
		if (strcmp (atom_nameP, "HA") == 0) continue;
		if (strcmp (atom_nameP, "C" ) == 0) continue;
		if (strcmp (atom_nameP, "O" ) == 0) continue;
		if (strcmp (atom_nameP, "CB") == 0) continue;
		if (strcmp (atom_nameP, "HB") == 0) continue;

		/* Rotate the current atom about CB-XG bond: */
		RotateAtom_ (atomSP, &CB_vectorS, &XG_vectorS, delta_chi2);
                }
	}

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

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

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


