File: is_part_of_ring.c

package info (click to toggle)
garlic 1.5-2
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 4,324 kB
  • ctags: 1,378
  • sloc: ansic: 50,306; makefile: 1,088
file content (252 lines) | stat: -rw-r--r-- 8,412 bytes parent folder | download | duplicates (5)
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;
}

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