/* Copyright (C) 2001-2003 Damir Zucic */

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

				extract_vector.c

Purpose:
	Find the highest average hydrophobicity using the current sliding
	window width. Extract the coordinates of eight atoms which define
	the start and the end of the window which has this maximum at the
	center and prepare one vector.

Input:
	(1) Pointer to VectorS structure, where the extracted vector will
	    be stored.
	(2) Pointer to MolComplexS structure,  with the chosen structure.
	(3) Pointer to RuntimeS structure.
	(4) The threshold value for the average hydrophobicity.

Output:
	(1) On success, one vector will be prepared and initialized.
	(2) Return value.

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

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

#include <stdio.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		ExtractCA_ (VectorS *, AtomS *, size_t, size_t);

/*======extract vector:======================================================*/

int ExtractVector_ (VectorS *vectorSP,
		    MolComplexS *mol_complexSP, RuntimeS *runtimeSP,
		    double threshold)
{
int		residuesN, residueI;
int		window_width, half_window_width;
double		max_average_hyphob, min_average_hyphob;
int		central_residueI, window_startI, window_endI;
double		average_hyphob;
int		vectors_extractedN;
ResidueS	*residueSP;
VectorS		vector1S, vector2S, vector3S, vector4S;
VectorS		vector5S, vector6S, vector7S, vector8S;

/* Copy the number of residues: */
residuesN = mol_complexSP->residuesN;
if (residuesN == 0) return -1;

/* The sliding window width should be at least eight: */
window_width = runtimeSP->sliding_window_width;
if (window_width < 8) return -2;
half_window_width = window_width / 2;

/* Initialize the maximal and minimal average hydrophobicity: */
max_average_hyphob = -999999.0;
min_average_hyphob =  999999.0;

/* Initialize the index  of the residue  which is */
/* in the middle of the most hydrophobic segment. */
central_residueI = -1;

/* Find the sequence position with the highest average hydrophobicity. */
/* Find also the values of maximal and minimal average hydrophobicity. */
for (residueI = 0; residueI < residuesN; residueI++)
	{
	average_hyphob = *(runtimeSP->average_hydrophobicityP + residueI);
	if (average_hyphob > max_average_hyphob)
		{
		max_average_hyphob = average_hyphob;
		central_residueI = residueI;
		}
	else if (average_hyphob < min_average_hyphob)
		{
		min_average_hyphob = average_hyphob;
		}
	}

/* This should never happen but I am paranoic: */
if (central_residueI == -1) return -3;

/* Check is the maximal average hydrophobicity above the threshold: */
if (max_average_hyphob < threshold) return -4;

/* Now use  the index of  the central residue  to define  the entire */
/* sliding window which contains the maximal average hydrophobicity: */
window_startI = central_residueI - half_window_width;
window_endI   = window_startI + window_width;

/* Check both indices; if the central residue is too close */
/* to the first or to the last residue, discard this peak: */
if ((window_startI < 0) || (window_startI >= residuesN)) return -5;

/* Use  the first  four residues  from  the  sliding  window  to */
/* define  the first point  in space and the last  four residues */
/* to define  the second point  in space.  Use these  two points */
/* to prepare  the initial normal vector.  This vector should be */
/* approximately perpendicular to the membrane.  The coordinates */
/* of CA atoms are used (some structures contain only CA atoms). */

/* Prepare eight vectors: */
vectors_extractedN = 0;
residueSP = mol_complexSP->residueSP + window_startI;
vectors_extractedN += ExtractCA_ (&vector1S, mol_complexSP->atomSP,
				  residueSP->residue_startI,
				  residueSP->residue_endI);
residueSP = mol_complexSP->residueSP + window_startI + 1;
vectors_extractedN += ExtractCA_ (&vector2S, mol_complexSP->atomSP,
				  residueSP->residue_startI,
				  residueSP->residue_endI);
residueSP = mol_complexSP->residueSP + window_startI + 2;
vectors_extractedN += ExtractCA_ (&vector3S, mol_complexSP->atomSP,
				  residueSP->residue_startI,
				  residueSP->residue_endI);
residueSP = mol_complexSP->residueSP + window_startI + 3;
vectors_extractedN += ExtractCA_ (&vector4S, mol_complexSP->atomSP,
                                  residueSP->residue_startI,
                                  residueSP->residue_endI);
residueSP = mol_complexSP->residueSP + window_endI;
vectors_extractedN += ExtractCA_ (&vector5S, mol_complexSP->atomSP,
				  residueSP->residue_startI,
				  residueSP->residue_endI);
residueSP = mol_complexSP->residueSP + window_endI - 1;
vectors_extractedN += ExtractCA_ (&vector6S, mol_complexSP->atomSP,
				  residueSP->residue_startI,
				  residueSP->residue_endI);
residueSP = mol_complexSP->residueSP + window_endI - 2;
vectors_extractedN += ExtractCA_ (&vector7S, mol_complexSP->atomSP,
				  residueSP->residue_startI,
				  residueSP->residue_endI);
residueSP = mol_complexSP->residueSP + window_endI - 3;
vectors_extractedN += ExtractCA_ (&vector8S, mol_complexSP->atomSP,
				  residueSP->residue_startI,
				  residueSP->residue_endI);
if (vectors_extractedN != 8) return -6;

/* The first (crude) estimate of the normal vector: */
vectorSP->x = vector5S.x + vector6S.x + vector7S.x + vector8S.x
	    - vector1S.x - vector2S.x - vector3S.x - vector4S.x;
vectorSP->y = vector5S.y + vector6S.y + vector7S.y + vector8S.y
	    - vector1S.y - vector2S.y - vector3S.y - vector4S.y;
vectorSP->z = vector5S.z + vector6S.z + vector7S.z + vector8S.z
	    - vector1S.z - vector2S.z - vector3S.z - vector4S.z;

/* Remove the highest peak. Replace the average hydrophobicities */
/* in the whole interval by the  minimal average hydrophobicity. */
for (residueI = window_startI; residueI <= window_endI; residueI++)
	{
	*(runtimeSP->average_hydrophobicityP + residueI) = min_average_hyphob;
	}

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

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


