/* Copyright (C) 2003 Damir Zucic */

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

				    color_size.c

Purpose:
	Size color scheme: assign colors according to the side chain size.
	The smallest residue  (GLY) will be colored  blue and  the largest
	residue  (TRP) will be colored  red.  The size  is defined  as the
	total number of carbon, oxygen and nitrogen atoms.


Input:
	(1) Pointer to MolComplexS structure, with macromol. complexes.
	(2) Number of macromolecular complexes.
	(3) Pointer to GUIS structure, with GUI data.
	(4) Pointer to ColorSchemeS structure.

Output:
	(1) Return value.

Return value:
	(1) Positive always.

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

#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		MixColors_ (AtomS *, ColorSchemeS *, ColorSchemeS *,
			    double, GUIS *);

/*======size color scheme:===================================================*/

int ColorSize_ (MolComplexS *mol_complexSP, int mol_complexesN,
		GUIS *guiSP, ColorSchemeS *color_schemeSP)
{
size_t		rgb_struct_size;
ColorSchemeS	*blue_schemeSP, *white_schemeSP, *red_schemeSP;
static double	min_size = 0, threshold_size = 4, max_size = 10;
double		delta_size1, delta_size2;
double		inverse_range1, inverse_range2;
int		mol_complexI;
MolComplexS	*curr_mol_complexSP;
int		residuesN, residueI;
ResidueS	*residueSP;
AtomS		*first_atomSP;
char		*residue_nameP;
int		i;
static char	amino_acidAA[23][4] =
		{"ALA","ARG","ASN","ASP","CYS","GLN","GLU","GLY","HIS","ILE",
		 "LEU","LYS","MET","PHE","PRO","SER","THR","TRP","TYR","VAL",
		 "ASX","GLX","UNK"};
static double	res_sizeA[23] =
		{ 1.0,  7.0,  4.0,  4.0,  2.0,  5.0,  5.0,  0.0,  6.0,  4.0,
		  4.0,  5.0,  4.0,  7.0,  3.0,  2.0,  3.0, 10.0,  8.0,  3.0,
		  4.0,  5.0,  5.0 }; 
double		res_size;
size_t		startI, endI, atomI;
AtomS		*atomSP;
double		scale_factor;

/* The size of RGBS structure: */
rgb_struct_size = sizeof (RGBS);

/* Red scheme pointer: */
red_schemeSP = color_schemeSP + 0;

/* White scheme pointer: */
white_schemeSP = color_schemeSP + 6;

/* Blue scheme pointer: */
blue_schemeSP = color_schemeSP + 2;

/* Inverse size ranges: */
delta_size1 = max_size - threshold_size;
if (delta_size1 != 0.0) inverse_range1 = 1.0 / delta_size1;
else inverse_range1 = 0.0;
delta_size2 = threshold_size - min_size;
if (delta_size2 != 0.0) inverse_range2 = 1.0 / delta_size2;
else inverse_range2 = 0.0;

/* Scan every macromolecular complex: */
for (mol_complexI = 0; mol_complexI < mol_complexesN; mol_complexI++)
	{
	/* Pointer to the current macromolecular complex: */
	curr_mol_complexSP = mol_complexSP + mol_complexI;

	/* Check is the current macromolecular complex caught: */
	if (curr_mol_complexSP->catchF == 0) continue;

	/* Copy and check the number of residues: */
	residuesN = curr_mol_complexSP->residuesN;
	if (residuesN == 0) continue;

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

		/* Pointer to the first atom of this residue: */
		first_atomSP = mol_complexSP->atomSP +
			       residueSP->residue_startI;

		/* Pointer to the residue name: */
		residue_nameP = first_atomSP->raw_atomS.pure_residue_nameA;

		/* The threshold value is used as default: */
		res_size = threshold_size;

		/* Compare the purified residue name with 23 standard names: */
		for (i = 0; i < 23; i++)
			{
			/* If amino acid is recognized: */
			if (strcmp (residue_nameP, amino_acidAA[i]) == 0)
				{
				res_size = res_sizeA[i];
				break;
				}
			}

		/* All atoms of this residue should be colored: */

		/* The range of atomic indices for the current residue: */
		startI = residueSP->residue_startI;
		endI   = residueSP->residue_endI;

		/* Scan the whole residue: */
		for (atomI = startI; atomI <= endI; atomI++)
			{
			/* Pointer to the current atom: */ 
			atomSP = mol_complexSP->atomSP + atomI;

			/* If residue size is below threshold value: */
			if (res_size <= threshold_size)
				{
				scale_factor = (threshold_size - res_size) *
						inverse_range2;
				MixColors_ (atomSP,
					    white_schemeSP, blue_schemeSP,
					    scale_factor, guiSP);
				}

			/* If residue size is above threshold value: */
			else
				{
				scale_factor = (res_size - threshold_size) *
						inverse_range1;
				MixColors_ (atomSP,
					    white_schemeSP, red_schemeSP,
					    scale_factor, guiSP);
				}
			}
		}

	/* Reset the position_changedF: */
	curr_mol_complexSP->position_changedF = 1;
	}

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

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


