File: edit_bond.c

package info (click to toggle)
garlic 1.6-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 4,516 kB
  • sloc: ansic: 52,465; makefile: 2,254
file content (289 lines) | stat: -rw-r--r-- 8,992 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
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
/* Copyright (C) 2001-2003 Damir Zucic */

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

				edit_bond.c

Purpose:
	Edit  (rotate) the specified bond.  The array indices of two atoms
	which form the bond are used to specify the bond. 

Input:
	(1) Pointer to MolComplexS structure, pointing to default complex.
	    element.
	(2) The index 
	(3) Pointer to RuntimeS structure.
	(4) Pointer to ConfigS structure.
	(5) Rotation angle.

Output:
	(1) Part of  the chosen residue  rotated about the specified bond.
	(2) Return value.

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

========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		RotateAtom_ (AtomS *, VectorS *, VectorS *, double);
int		DihedralAngles_ (MolComplexS *, ConfigS *);

/*======edit (rotate) the specified bond:====================================*/

int EditBond_ (MolComplexS *curr_mol_complexSP, int mol_complexI,
	       RuntimeS *runtimeSP, ConfigS *configSP,
	       double rotation_angle)
{
size_t		atomsN;
size_t		atom1_arrayI, atom2_arrayI;
int		residueI;
int		start_atomI, end_atomI, atomI;
AtomS		*curr_atomSP;
int		stepI, previous_stepI;
int		atoms_in_residueN;
int		propagationF;
int		atom_reachedF;
int		bondI;
TrueBondS	*curr_bondSP;
AtomS		*curr_neighborSP;
char		*atom_nameP;
int		CA_foundF;
VectorS		atom1_vectorS, atom2_vectorS;

/*------prepare required indices:--------------------------------------------*/

/* Prepare and check the number of atoms: */
atomsN = curr_mol_complexSP->atomsN;
if (atomsN == 0) return -1;

/* Copy the array indices of two atoms which define the chosen bond: */
atom1_arrayI = runtimeSP->atom1_arrayI;
atom2_arrayI = runtimeSP->atom2_arrayI;

/* Two atoms which specify the bond 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;
	}

/* Prepare and check the atomic array indices which */
/* define the residue  to which  both atoms belong. */
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;
	}

/*------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;
	}

/*------try to find the CA atom:---------------------------------------------*/

/* Only the atoms which are opposite to the main chain with */
/* respect to the specified bond should be rotated. To find */
/* these atoms, a shock wave is send from the first atom to */
/* the second atom and further. If this wave will reach the */
/* CA atom,  the atoms  which should be rotated  are on the */
/* opposite side of the specified bond.  Otherwise,  the CA */
/* atom is either  missing or  placed on the opposite side. */

/* Initialize the step index: */
stepI = 1;

/* Associate the first step index with the first atom: */
curr_atomSP = curr_mol_complexSP->atomSP + atom1_arrayI;
curr_atomSP->auxiliaryI = 1;

/* Associate the second step index with the second atom: */
curr_atomSP = curr_mol_complexSP->atomSP + atom2_arrayI;
curr_atomSP->auxiliaryI = 2;

/* 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;

/* Initialize the flag which says that CA atom is found: */
CA_foundF = 0;

/* 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 = curr_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 check  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 CA atom, set the flag: */
			atom_nameP = curr_atomSP->raw_atomS.pure_atom_nameA;
			if (strcmp (atom_nameP, "CA") == 0) CA_foundF = 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;
	}
 
/* If the  CA atom was reached by the shock wave,  the atoms which should */
/* be rotated about  the specified bond are  on the opposite side of this */
/* bond,  and for that reason all  auxiliaryI  values  should be changed. */
/* Zeros should be replaced by values different from zero and vice versa. */
if (CA_foundF)
	{
	/* 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;

		/* Revert the auxiliaryI: */
		if (curr_atomSP->auxiliaryI) curr_atomSP->auxiliaryI = 0;
		else curr_atomSP->auxiliaryI = 1;
		}
	}

/*------rotate atoms:--------------------------------------------------------*/

/* Prepare the coordinates of two atoms which define the rotation axis: */

/* The position of the first atom: */
curr_atomSP = curr_mol_complexSP->atomSP + atom1_arrayI;
atom1_vectorS.x = curr_atomSP->raw_atomS.x[0];
atom1_vectorS.y = curr_atomSP->raw_atomS.y;
atom1_vectorS.z = curr_atomSP->raw_atomS.z[0];

/* The position of the second atom: */
curr_atomSP = curr_mol_complexSP->atomSP + atom2_arrayI;
atom2_vectorS.x = curr_atomSP->raw_atomS.x[0];
atom2_vectorS.y = curr_atomSP->raw_atomS.y;
atom2_vectorS.z = curr_atomSP->raw_atomS.z[0];

/* Rotate all atoms after the current residue about CA-C bond: */
for (atomI = start_atomI + 1; atomI <= end_atomI; atomI++)
	{
	/* Pointer to the current atom: */
	curr_atomSP = curr_mol_complexSP->atomSP + atomI;

	/* If this atom is not in the outer portion of the side chain */
	/* (with respect to  the specified bond),  do not  rotate it: */
	if (curr_atomSP->auxiliaryI == 0) continue;

	/* Rotate atom: */
	RotateAtom_ (curr_atomSP,
		     &atom1_vectorS, &atom2_vectorS, rotation_angle);
	}

/*---------------------------------------------------------------------------*/

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

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

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