1   
  2   
  3   
  4   
  5   
  6   
  7   
  8   
  9   
 10   
 11   
 12   
 13   
 14   
 15   
 16   
 17   
 18   
 19   
 20   
 21   
 22   
 23  from math import cos, pi, sin 
 24  from numpy import array, dot, eye, float64, zeros 
 25   
 26   
 27  from lib.geometry.rotations import two_vect_to_R 
 28  from lib.structure.angles import angles_regular, angles_uniform 
 29  from lib.structure.conversion import get_proton_name 
 30  from lib.structure.geometric import generate_vector_dist 
 31   
 32   
 33 -def cone_edge(mol=None, cone_obj=None, res_name='CON', res_num=None, chain_id='', apex=None, axis=None, R=None, scale=None, inc=None, distribution='uniform', debug=False): 
  34      """Add a residue to the atomic data representing a cone of the given angle. 
 35   
 36      A series of vectors totalling the number of increments and starting at the origin are equally spaced around the cone axis.  The atoms representing neighbouring vectors will be directly bonded together.  This will generate an object representing the outer edge of a cone. 
 37   
 38   
 39      @keyword mol:           The molecule container. 
 40      @type mol:              MolContainer instance 
 41      @keyword cone_obj:      The cone object.  This should provide the limit_check() method with determines the limits of the distribution accepting two arguments, the polar angle phi and the azimuthal angle theta, and return True if the point is in the limits or False if outside.  It should also provide the phi_max() method for returning the phi value for the given theta. 
 42      @type cone_obj:         class instance 
 43      @keyword res_name:      The residue name. 
 44      @type res_name:         str 
 45      @keyword res_num:       The residue number. 
 46      @type res_num:          int 
 47      @keyword chain_id:      The chain identifier. 
 48      @type chain_id:         str 
 49      @keyword apex:          The apex of the cone. 
 50      @type apex:             numpy array, len 3 
 51      @keyword axis:          The central axis of the cone.  If supplied, then this arg will be used to construct the rotation matrix. 
 52      @type axis:             numpy array, len 3 
 53      @keyword R:             A 3x3 rotation matrix.  If the axis arg supplied, then this matrix will be ignored. 
 54      @type R:                3x3 numpy array 
 55      @keyword scale:         The scaling factor to stretch all points by. 
 56      @type scale:            float 
 57      @keyword inc:           The number of increments or number of vectors used to generate the outer edge of the cone. 
 58      @type inc:              int 
 59      @keyword distribution:  The type of point distribution to use.  This can be 'uniform' or 'regular'. 
 60      @type distribution:     str 
 61      """ 
 62   
 63       
 64      atom_num = mol.atom_num[-1]+1 
 65   
 66       
 67      mol.atom_add(pdb_record='HETATM', atom_num=atom_num, atom_name='APX', res_name=res_name, res_num=res_num, pos=apex, segment_id=None, element='H') 
 68      origin_atom = atom_num 
 69   
 70       
 71      if distribution == 'uniform': 
 72          phi, theta = angles_uniform(inc) 
 73      else: 
 74          phi, theta = angles_regular(inc) 
 75   
 76       
 77      if R == None: 
 78          R = eye(3) 
 79   
 80       
 81      if axis != None: 
 82          two_vect_to_R(array([0, 0, 1], float64), axis, R) 
 83   
 84       
 85      phi_max = zeros(len(theta), float64) 
 86      edge_index = zeros(len(theta), int) 
 87      for i in range(len(theta)): 
 88           
 89          phi_max[i] = cone_obj.phi_max(theta[i]) 
 90   
 91           
 92          for j in range(len(phi)): 
 93              if phi[j] <= phi_max[i]: 
 94                  edge_index[i] = j 
 95                  break 
 96   
 97       
 98      edge_index_rev = len(phi) - 1 - edge_index 
 99   
100       
101      atom_num = atom_num + 1 
102      for i in range(len(theta)): 
103           
104          x = cos(theta[i]) * sin(phi_max[i]) 
105          y = sin(theta[i])* sin(phi_max[i]) 
106          z = cos(phi_max[i]) 
107          vector = array([x, y, z], float64) 
108   
109           
110          vector = dot(R, vector) 
111   
112           
113          atom_id = 'T' + repr(i) 
114   
115           
116          pos = apex+vector*scale 
117   
118           
119          if debug: 
120              print("i: %s; theta: %s" % (i, theta[i])) 
121              print("%sAdding atom %s." % (" "*4, get_proton_name(atom_num))) 
122   
123           
124          mol.atom_add(pdb_record='HETATM', atom_num=atom_num, atom_name=get_proton_name(atom_num), res_name=res_name, res_num=res_num, pos=pos, segment_id=None, element='H') 
125   
126           
127          mol.atom_connect(index1=origin_atom-1, index2=atom_num-1) 
128   
129           
130          atom_num = atom_num + 1 
131   
132           
133          for j in range(len(phi)): 
134               
135              k = len(phi) - 1 - j 
136   
137               
138              if debug: 
139                  print("%sj: %s; phi: %-20s; k: %s; phi: %-20s; phi_max: %-20s" % (" "*4, j, phi[j], k, phi[k], phi_max[i])) 
140   
141               
142              skip = True 
143   
144               
145              fwd_index = i+1 
146              if i == len(theta)-1: 
147                  fwd_index = 0 
148              if j >= edge_index[i] and j < edge_index[fwd_index] and not abs(phi_max[fwd_index] - phi[j]) < 1e-6: 
149                   
150                  if debug: 
151                      print("%sForward edge." % (" "*8)) 
152   
153                   
154                  skip = False 
155   
156                   
157                  phi_val = phi[j] 
158                  if fwd_index == 0: 
159                      theta_max = theta[fwd_index] + 2*pi 
160                  else: 
161                      theta_max = theta[fwd_index] 
162                  theta_max = cone_obj.theta_max(phi_val, theta_min=theta[i], theta_max=theta_max-1e-7) 
163   
164               
165              rev_index = i-1 
166              if i == 0: 
167                  rev_index = len(theta)-1 
168              if i < len(theta)-1 and j > edge_index_rev[i] and j <= edge_index_rev[i+1] and not abs(phi_max[fwd_index] - phi[k]) < 1e-6: 
169                   
170                  if debug: 
171                      print("%sBack edge." % (" "*8)) 
172   
173                   
174                  skip = False 
175   
176                   
177                  phi_val = phi[k] 
178                  theta_max = cone_obj.theta_max(phi_val, theta_min=theta[i-1], theta_max=theta[i]) 
179   
180               
181              if skip: 
182                  continue 
183   
184               
185              if debug: 
186                  print("%sAdding atom %s." % (" "*8, get_proton_name(atom_num))) 
187   
188               
189              x = cos(theta_max) * sin(phi_val) 
190              y = sin(theta_max) * sin(phi_val) 
191              z = cos(phi_val) 
192              pos = array([x, y, z], float64) * scale 
193   
194               
195              pos = apex + dot(R, pos) 
196   
197               
198              mol.atom_add(pdb_record='HETATM', atom_num=atom_num, atom_name=get_proton_name(atom_num), res_name=res_name, chain_id=chain_id, res_num=res_num, pos=pos, segment_id=None, element='H') 
199   
200               
201              atom_num = atom_num + 1 
202   
203       
204      if debug: 
205          print("\nBuilding the edge.") 
206   
207       
208      for i in range(origin_atom, atom_num-2): 
209           
210          if debug: 
211              print("%sCone edge, connecting %s to %s" % (" "*4, get_proton_name(i), get_proton_name(i+1))) 
212   
213           
214          mol.atom_connect(index1=i, index2=i+1) 
215   
216       
217      mol.atom_connect(index1=atom_num-2, index2=origin_atom) 
 218   
219   
220 -def cone(mol=None, cone_obj=None, start_res=1, apex=None, axis=None, R=None, inc=None, scale=30.0, distribution='regular', axis_flag=True): 
 221      """Create a structural representation of the given cone object. 
222   
223      @keyword mol:           The molecule container. 
224      @type mol:              MolContainer instance 
225      @keyword cone_obj:      The cone object.  This should provide the limit_check() method with determines the limits of the distribution accepting two arguments, the polar angle phi and the azimuthal angle theta, and return True if the point is in the limits or False if outside.  It should also provide the theta_max() method for returning the theta value for the given phi, the phi_max() method for returning the phi value for the given theta. 
226      @type cone_obj:         class instance 
227      @keyword start_res:     The starting residue number. 
228      @type start_res:        str 
229      @keyword apex:          The apex of the cone. 
230      @type apex:             rank-1, 3D numpy array 
231      @keyword axis:          The central axis of the cone.  If not supplied, the z-axis will be used. 
232      @type axis:             rank-1, 3D numpy array 
233      @keyword R:             The rotation matrix. 
234      @type R:                rank-2, 3D numpy array 
235      @keyword inc:           The increment number used to determine the number of latitude and longitude lines. 
236      @type inc:              int 
237      @keyword scale:         The scaling factor to stretch the unit cone by. 
238      @type scale:            float 
239      @keyword distribution:  The type of point distribution to use.  This can be 'uniform' or 'regular'. 
240      @type distribution:     str 
241      @keyword axis_flag:     A flag which if True will create the cone's axis. 
242      @type axis_flag:        bool 
243      """ 
244   
245       
246      if not axis: 
247          axis = array([0, 0, 1], float64) 
248   
249       
250      if R == None: 
251          R = eye(3) 
252   
253       
254      start_atom = 1 
255      if hasattr(mol, 'atom_num'): 
256          start_atom = mol.atom_num[-1]+1 
257   
258       
259      if axis_flag: 
260           
261          mol.atom_add(pdb_record='HETATM', atom_num=start_atom, atom_name='R', res_name='APX', res_num=start_res, pos=apex, element='C') 
262   
263           
264          print("\nGenerating the axis vectors.") 
265          res_num = generate_vector_residues(mol=mol, vector=dot(R, axis), atom_name='Axis', res_name_vect='AXE', res_num=start_res+1, origin=apex, scale=scale) 
266   
267       
268      print("\nGenerating the cone outer edge.") 
269      edge_start_atom = mol.atom_num[-1]+1 
270      cone_edge(mol=mol, cone_obj=cone_obj, res_name='EDG', res_num=start_res+2, apex=apex, R=R, scale=scale, inc=inc, distribution=distribution) 
271   
272       
273      print("\nGenerating the cone cap.") 
274      cone_start_atom = mol.atom_num[-1]+1 
275      generate_vector_dist(mol=mol, res_name='CON', res_num=start_res+3, centre=apex, R=R, limit_check=cone_obj.limit_check, scale=scale, inc=inc, distribution=distribution) 
276      stitch_cone_to_edge(mol=mol, cone_obj=cone_obj, dome_start=cone_start_atom, edge_start=edge_start_atom+1, scale=scale, inc=inc, distribution=distribution) 
 277   
278   
279 -def stitch_cone_to_edge(mol=None, cone_obj=None, chain_id='', dome_start=None, edge_start=None, scale=1.0, inc=None, distribution='uniform', debug=False): 
 280      """Function for stitching the cone dome to its edge, in the PDB representations. 
281   
282      @keyword mol:           The molecule container. 
283      @type mol:              MolContainer instance 
284      @keyword cone_obj:      The cone object.  This should provide the limit_check() method with determines the limits of the distribution accepting two arguments, the polar angle phi and the azimuthal angle theta, and return True if the point is in the limits or False if outside.  It should also provide the theta_max() method for returning the theta value for the given phi. 
285      @type cone_obj:         class instance 
286      @keyword chain_id:      The chain identifier. 
287      @type chain_id:         str 
288      @keyword dome_start:    The starting atom number of the cone dome residue. 
289      @type dome_start:       int 
290      @keyword edge_start:    The starting atom number of the cone edge residue. 
291      @type edge_start:       int 
292      @keyword scale:         The scaling factor to stretch all points by. 
293      @type scale:            float 
294      @keyword inc:           The number of increments or number of vectors used to generate the outer edge of the cone. 
295      @type inc:              int 
296      @keyword distribution:  The type of point distribution to use.  This can be 'uniform' or 'regular'. 
297      @type distribution:     str 
298      """ 
299   
300       
301      if distribution == 'uniform': 
302          phi, theta = angles_uniform(inc) 
303      else: 
304          phi, theta = angles_regular(inc) 
305   
306       
307      phi_max = zeros(len(theta), float64) 
308      edge_index = zeros(len(theta), int) 
309      for i in range(len(theta)): 
310           
311          phi_max[i] = cone_obj.phi_max(theta[i]) 
312   
313           
314          for j in range(len(phi)): 
315              if phi[j] <= phi_max[i]: 
316                  edge_index[i] = j 
317                  break 
318   
319       
320      edge_index_rev = len(phi) - 1 - edge_index 
321   
322       
323      if debug: 
324          print("\nDome start: %s" % dome_start) 
325          print("Edge start: %s" % edge_start) 
326          print("Edge indices:     %s" % edge_index) 
327          print("Edge indices rev: %s" % edge_index_rev) 
328   
329       
330      dome_atom = dome_start 
331      edge_atom = edge_start 
332      for i in range(len(theta)): 
333           
334          if debug: 
335              print("i: %s; theta: %s" % (i, theta[i])) 
336              print("%sDome atom: %s" % (" "*4, get_proton_name(dome_atom))) 
337              print("%sStitching longitudinal line to edge - %s to %s." % (" "*4, get_proton_name(edge_atom), get_proton_name(dome_atom))) 
338   
339           
340          mol.atom_connect(index1=dome_atom-1, index2=edge_atom-1) 
341   
342           
343          edge_atom = edge_atom + 1 
344   
345           
346          for j in range(len(phi)): 
347               
348              k = len(phi) - 1 - j 
349   
350               
351              if debug: 
352                  print("%sj: %s; phi: %-20s; k: %s; phi: %-20s; phi_max: %-20s" % (" "*4, j, phi[j], k, phi[k], phi_max[i])) 
353   
354               
355              skip = True 
356   
357               
358              fwd_index = i+1 
359              if i == len(theta)-1: 
360                  fwd_index = 0 
361              if j >= edge_index[i] and j < edge_index[fwd_index] and not abs(phi_max[fwd_index] - phi[j]) < 1e-6: 
362                   
363                  if debug: 
364                      print("%sForward edge." % (" "*8)) 
365   
366                   
367                  skip = False 
368                  forward = True 
369   
370               
371              rev_index = i-1 
372              if i == 0: 
373                  rev_index = len(theta)-1 
374              if i < len(theta)-1 and j > edge_index_rev[i] and j <= edge_index_rev[i+1] and not abs(phi_max[fwd_index] - phi[k]) < 1e-6: 
375                   
376                  if debug: 
377                      print("%sBack edge." % (" "*8)) 
378   
379                   
380                  skip = False 
381                  forward = False 
382   
383               
384              if skip: 
385                  continue 
386   
387               
388              if forward: 
389                  atom = dome_atom + j - edge_index[i] 
390              else: 
391                  atom = dome_atom + (edge_index_rev[i]+1) + k - edge_index[fwd_index] 
392   
393               
394              if debug: 
395                  print("%sStitching latitude line to edge - %s to %s." % (" "*8, get_proton_name(edge_atom), get_proton_name(atom))) 
396   
397               
398              mol.atom_connect(index1=atom-1, index2=edge_atom-1) 
399   
400               
401              edge_atom = edge_atom + 1 
402   
403           
404          dome_atom = dome_atom + (len(phi) - edge_index[i]) 
 405