1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
|
/* Copyright (C) 2001-2003 Damir Zucic */
/*=============================================================================
is_part_of_ring.c
Purpose:
Check is the specified bond part of a ring or of some other closed
structural element. The array indices of two atoms which form the
bond are used to specify the chosen bond.
Input:
(1) Pointer to MolComplexS structure.
(2) The macromolecular complex index.
(3) The array index of the first atom of the chosen bond.
(4) The array index of the second atom of the chosen bond.
Output:
(1) Return value.
Return value:
(1) Positive if bond is part of a ring.
(2) Zero if the specified bond is not involved in formation of a
ring or some other closed structural element.
(3) Negative, if the macromolecular complex contains no atoms, if
two specified atoms do not belong to the same residue or if
this residue does not contain any atoms (rather strange).
Notes:
(1) Imagine that chemical bonds form a system of tunnels dug in a
mountain. Atoms are treated as places where two, three or more
tunnels are connected. The shock wave is initiated starting at
the position of the first atom, propagating in a direction of
the second atom. One or more shock waves will leave the second
atom, but there will be no reflected wave. In each step, each
of the waves will travel the distance between two neighboring
atoms, i.e. the length of a single bond. The waves may branch,
but no reflection is allowed. After the shock wave passes any
tunnel section (half of a single bond), this section collapses
so that shock waves cannot traverse it. If any of the waves
reaches the atom where the whole process started (the first
atom), both the first atom and the second atom belong to some
closed structure (an aromatic ring or something like that). If
this is the case no rotation is allowed about the specified
bond.
(2) Step indices are assigned to the atoms which were reached by
shock waves. The first step index (one) is assigned to the
first input atom. The second step index (two) is assigned to
the second atom. After that, the whole residue is repeatedly
scanned, atom by atom. For each atom, all bonds are scanned.
The atom is reached by the shock wave in the current step if
the step index assigned to at least one bond partner is equal
to the previous step index.
(3) The auxiliaryI index should be reinitialized before every use.
========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"
/*======check is bond part of a closed structure:============================*/
int IsPartOfRing_ (MolComplexS *mol_complexSP, int mol_complexI,
size_t atom1_arrayI, size_t atom2_arrayI)
{
MolComplexS *curr_mol_complexSP;
size_t atomsN;
int residueI;
int start_atomI, end_atomI;
int stepI, previous_stepI;
AtomS *curr_atomSP;
int atoms_in_residueN;
int propagationF;
int atomI;
int atom_reachedF;
int bondI;
TrueBondS *curr_bondSP;
AtomS *curr_neighborSP;
/* Pointer to the chosen macromolecular complex: */
curr_mol_complexSP = mol_complexSP + mol_complexI;
/* Prepare and check the number of atoms: */
atomsN = curr_mol_complexSP->atomsN;
if (atomsN == 0) return -1;
/* Two specified atoms should belong to the same residue: */
residueI = (curr_mol_complexSP->atomSP + atom1_arrayI)->residue_arrayI;
if ((int) (curr_mol_complexSP->atomSP + atom2_arrayI)->residue_arrayI !=
residueI)
{
return -2;
}
/* If this point is reached, both atoms belong to the same residue. */
/* Prepare and check the atomic array indices which */
/* define the residue to which both atoms belong. */
/* This check might be redundant but I am paranoic. */
start_atomI = (curr_mol_complexSP->residueSP + residueI)->residue_startI;
end_atomI = (curr_mol_complexSP->residueSP + residueI)->residue_endI;
if (((int) atom1_arrayI < start_atomI) || ((int) atom1_arrayI > end_atomI))
{
return -3;
}
if (((int) atom2_arrayI < start_atomI) || ((int) atom2_arrayI > end_atomI))
{
return -4;
}
/* Initialize the step index: */
stepI = 1;
/*------reset auxiliaryI for each atom of a chosen residue:------------------*/
/* Scan the chosen residue, atom by atom: */
for (atomI = start_atomI; atomI <= end_atomI; atomI++)
{
/* Pointer to the current atom: */
curr_atomSP = curr_mol_complexSP->atomSP + atomI;
/* Reset the auxiliaryI: */
curr_atomSP->auxiliaryI = 0;
}
/*------the shock wave starts from the first atom:---------------------------*/
/* Associate the first step index with the first atom: */
curr_atomSP = curr_mol_complexSP->atomSP + atom1_arrayI;
curr_atomSP->auxiliaryI = 1;
/*------the shock wave reaches the second atom:------------------------------*/
/* Associate the second step index with the second atom: */
curr_atomSP = curr_mol_complexSP->atomSP + atom2_arrayI;
curr_atomSP->auxiliaryI = 2;
/*------further propagation of shock waves:----------------------------------*/
/* Now scan the residue repeatedly. The number of scans should not */
/* exceed the number of atoms in the residue, because the length */
/* of the fully extended residue is equal to number_of_atoms - 1. */
atoms_in_residueN = end_atomI - start_atomI + 1;
/* Initialize the index of the previous step: */
previous_stepI = 2;
/* The loop which counts steps should start from the third step: */
for (stepI = 3; stepI < atoms_in_residueN; stepI++)
{
/* Reset the wave propagation flag: */
propagationF = 0;
/* In each step, scan the entire residue, atom by atom: */
for (atomI = start_atomI; atomI <= end_atomI; atomI++)
{
/* In the third step, the first atom of */
/* the specified bond should be skipped: */
if ((stepI == 3) && (atomI == (int) atom1_arrayI)) continue;
/* Pointer to the current atom: */
curr_atomSP = curr_mol_complexSP->atomSP + atomI;
/* If the current atom was reached */
/* in the previous step, skip it: */
if (curr_atomSP->auxiliaryI == previous_stepI) continue;
/* Reset the flag which says that the */
/* atom is reached by the shock wave: */
atom_reachedF = 0;
/* Scan all bonds of the current atom: */
for (bondI = 0; bondI < curr_atomSP->bondsN; bondI++)
{
/* Pointer to the current bond: */
curr_bondSP = curr_atomSP->true_bondSA + bondI;
/* Only the covalent bonds are taken into account. */
/* Hydrogen, disulfide and pseudo-bonds are ignored. */
if (curr_bondSP->bond_typeI != 1) continue;
/* Bonds formed with atoms from another */
/* macromolecular complex are ignored: */
if (curr_bondSP->neighbor_mol_complexI != mol_complexI)
{
continue;
}
/* If the bond partner was reached by the shock */
/* wave in the previous step, the current atom */
/* is reached by the shock wave in this step: */
curr_neighborSP = mol_complexSP->atomSP +
curr_bondSP->neighbor_arrayI;
if (curr_neighborSP->auxiliaryI == previous_stepI)
{
/* Set the flag which says that the */
/* shock wave continues propagation: */
propagationF = 1;
/* Set the flag which says that this */
/* atom is reached by the shock wave: */
atom_reachedF = 1;
/* Do not inspect the remaining */
/* bonds, it is not necessary: */
break;
}
}
/* If the current atom is reached in this step: */
if (atom_reachedF)
{
/* If the current atom is the first atom of the */
/* specified bond and if it was reached in this */
/* step, the bond is involved in ring formation: */
if (atomI == (int) atom1_arrayI) return 1;
/* If the shock wave reached the current atom */
/* for the first time, store the step index: */
if (curr_atomSP->auxiliaryI == 0)
{
curr_atomSP->auxiliaryI = stepI;
}
}
}
/* If the shock wave is not propagating any more, break: */
if (!propagationF) break;
/* Update the value of the previous step index: */
previous_stepI = stepI;
}
/*---------------------------------------------------------------------------*/
/* Return zero if this point is reached: */
return 0;
}
/*===========================================================================*/
|