1
2
3
4
5 """Classes for representing biological macromolecules.
6 """
7 import copy
8 import math
9 import string
10 import itertools
11
12 try:
13 import numpy
14 try:
15 from numpy.oldnumeric import linear_algebra as linalg
16 except ImportError:
17 from numpy.linalg import old as linalg
18 except ImportError:
19 import NumericCompat as numpy
20 from NumericCompat import linalg
21
22 import ConsoleOutput
23 import Constants
24 import GeometryDict
25 import AtomMath
26 import Library
27 import UnitCell
28 import Sequence
29 import mmCIFDB
30
31
33 """Base class of errors raised by Structure objects.
34 """
35 pass
36
38 """Raised by Structure.add_model() when a Model added to a Structure
39 has the same model_id of a Model already in the Structure.
40 """
41 pass
42
44 """Raised by Structure.add_chain() or by Model.add_chain() when a
45 Chain added to a Structure has the same chain_id of a Chain already
46 in the Structure.
47 """
48 pass
49
51 """Raised by Chain.add_fragment() when a Fragment added to a Chain
52 has the same fragment_id as a Fragment already in the Chain.
53 """
54 pass
55
57 """Raised by Structure.add_atom() or Fragment.add_atom() when an Atom
58 added to a Structure or Fragment has the same chain_id, fragment_id,
59 name, and alt_loc as an Atom already in the Structure or Fragment.
60 """
66
68 """The Structure object is the parent container object for the entire
69 macromolecular data structure. It contains a list of the Chain objects
70 in the structure hierarchy, and contains these additional data
71 objects:
72
73 cifdb(mmLib.mmCIFDB) A mmCIF database with additional structure data.
74
75 unit_cell(mmLib.UnitCell) Unit cell/Spacegroup for the structure.
76
77 default_alt_loc(string) The default alternate location identifier used
78 when iterating or retreiving Atom objects in the structure.
79 """
81 self.structure_id = args.get("structure_id") or "XXXX"
82 self.header = None
83 self.title = None
84 self.experimental_method = None
85 self.cifdb = args.get("cifdb") or mmCIFDB.mmCIFDB("XXXX")
86
87 self.unit_cell = args.get("unit_cell") or UnitCell.UnitCell()
88
89 self.default_alt_loc = "A"
90 self.default_model = None
91 self.model_list = []
92 self.model_dict = {}
93
95 return "Struct(%s)" % (self.structure_id)
96
98 structure = Structure(
99 cifdb = copy.deepcopy(self.cifdb, memo),
100 unit_cell = copy.deepcopy(self.unit_cell, memo))
101
102 for model in self.model_list:
103 structure.add_model(copy.deepcopy(model, memo), True)
104
105 return structure
106
108 """Returns the number of stored Chain objects.
109 """
110 try:
111 return len(self.default_model)
112 except TypeError:
113 return 0
114
116 """Same as get_chain, but raises KeyError if the requested chain_id
117 is not found.
118 """
119 try:
120 return self.default_model[chain_idx]
121 except TypeError:
122 raise KeyError, chain_idx
123
125 """Iterates the Chain objects in the Structure.
126 """
127 if self.default_model:
128 return iter(self.default_model.chain_list)
129 return iter(list())
130
132 """Returns True if item is a Model in the Structure, or a
133 Chain or chain_id in the default Model.
134 """
135 if isinstance(model_chain_idx, Model):
136 return self.model_list.__contains__(model_chain_idx)
137 elif isinstance(model_chain_idx, Chain) or \
138 isinstance(model_chain_idx, str):
139 try:
140 return self.default_model.__contains__(model_chain_idx)
141 except AttributeError:
142 raise KeyError, model_chain_idx
143 raise TypeError, model_chain_idx
144
145 - def index(self, model_chain):
146 """If item is a Model, returns the index of the Model in the
147 Structure, or if the item is a Chain, returns the index of the
148 Chain in the default Model.
149 """
150 if isinstance(model_chain, Model):
151 return self.model_list.index(model_chain)
152 elif isinstance(model_chain, Chain):
153 try:
154 return self.default_model.index(model_chain)
155 except AttributeError:
156 raise ValueError, model_chain
157 raise TypeError, model_chain
158
160 """Sorts all Models and Chains in the Structure according to standard
161 model_id, chain_id, and fragment_id sorting rules.
162 """
163 self.model_list.sort()
164 for model in self.model_list:
165 model.sort()
166
167 - def add_model(self, model, delay_sort=True):
168 """Adds a Model to a Structure. Raises the ModelOverwrite exception
169 if the model_id of the Model matches the model_id of a Model
170 already in the Structure. If there are no Models in the Structure,
171 the Model is used as the default Model.
172 """
173 assert isinstance(model, Model)
174
175 if self.model_dict.has_key(model.model_id):
176 raise ModelOverwrite()
177
178
179 if self.default_model is None:
180 self.default_model = model
181
182 self.model_list.append(model)
183 self.model_dict[model.model_id] = model
184
185 model.structure = self
186
187 if not delay_sort:
188 self.model_list.sort()
189
191 """Removes a child Model object. If the Model object is the default
192 Model, then choose the Model with the lowest model_id as the
193 new default Model, or None if there are no more Models.
194 """
195 assert isinstance(model, Model)
196
197 self.model_list.remove(model)
198 del self.model_dict[model.model_id]
199 model.structure = None
200
201
202
203 if model == self.default_model:
204 if len(self.model_list) > 0:
205 self.default_model = self.model_list[0]
206 else:
207 self.default_model = None
208
210 """Return the Model object with the argument model_id, or None if
211 not found.
212 """
213 if self.model_dict.has_key(model_id):
214 return self.model_dict[model_id]
215 return None
216
218 """Returns the default Model object.
219 """
220 return self.default_model
221
223 """Sets the default Model for the Structure to model_id. Returns
224 False if a Model with the proper model_id does
225 not exist in the Structure.
226 """
227 try:
228 self.default_model = self.model_dict[model_id]
229 except KeyError:
230 return False
231 return False
232
234 """DEP: Use set_default_model()
235 Sets the default Model for the Structure to model_id. Returns
236 False if a Model with the proper model_id does
237 not exist in the Structure.
238 """
239 self.set_default_model(model_id)
240
242 """Iterates over all Model objects.
243 """
244 return iter(self.model_list)
245
247 """Counts all Model objects in the Structure.
248 """
249 return len(self.model_list)
250
251 - def add_chain(self, chain, delay_sort = True):
252 """Adds a Chain object to the Structure. Creates necessary parent
253 Model if necessary.
254 """
255 assert isinstance(chain, Chain)
256
257 try:
258 model = self.model_dict[chain.model_id]
259 except KeyError:
260 model = Model(model_id = chain.model_id)
261 self.add_model(model, delay_sort)
262
263 model.add_chain(chain, delay_sort)
264
266 """Removes a Chain object.
267 """
268 assert isinstance(chain, Chain)
269 self.model_dict[chain.model_id].remove_chain(chain)
270
272 """Returns the Chain object matching the chain_id character.
273 """
274 if self.default_model is None:
275 return None
276 if self.default_model.chain_dict.has_key(chain_id):
277 return self.default_model.chain_dict[chain_id]
278 return None
279
281 """Counts all Chain objects in the default Model.
282 """
283 if self.default_model:
284 return self.default_model.count_chains()
285 return 0
286
288 """Iterates over all Chain objects in the default Model, in
289 alphabetical order according to their chain_id.
290 """
291 if self.default_model:
292 return iter(self.default_model.chain_list)
293 return iter(list())
294
296 """Iterates over all Chain objects in all Model objects.
297 """
298 for model in self.model_list:
299 for chain in model.chain_list:
300 yield chain
301
303 """Adds a Fragment object.
304 """
305 assert isinstance(fragment, Fragment)
306
307 try:
308 model = self.model_dict[fragment.model_id]
309 except KeyError:
310 model = Model(model_id=fragment.model_id)
311 self.add_model(model, delay_sort)
312
313 model.add_fragment(fragment)
314
316 """Removes a Fragment object.
317 """
318 assert isinstance(fragment, Fragment)
319 self.model_dict[fragment.model_id].remove_fragment(fragment)
320
322 """Counts all Fragment objects in the default Model.
323 """
324 n = 0
325 for chain in self.iter_chains():
326 n += chain.count_fragments()
327 return n
328
330 """Iterates over all Fragment objects in the default Model.
331 The iteration is performed in order according the the parent
332 Chain's chain_id, and the Fragment's position within the chain.
333 """
334 if self.default_model is None:
335 raise StopIteration
336
337 for chain in self.default_model.chain_list:
338 for frag in chain.fragment_list:
339 yield frag
340
342 """Iterates over all Fragment objects in all Models.
343 The iteration is performed in order according the the parent
344 Chain's chain_id, and the Fragment's position within the chain.
345 """
346 for model in self.model_list:
347 for chain in model.chain_list:
348 for frag in chain.fragment_list:
349 yield frag
350
352 """Returns True if there are AminoAcidResidue objects in the
353 default Model of the Structure.
354 """
355 for frag in self.iter_amino_acids():
356 return True
357 return False
358
360 """Counts all AminoAcidResidue objects in the default Model.
361 """
362 n = 0
363 for chain in self.iter_chains():
364 n += chain.count_amino_acids()
365 return n
366
368 """Same as iter_fragments() but only iterates over Fragments of the
369 subclass AminoAcidResidue.
370 """
371 for chain in self.iter_chains():
372 for frag in chain.iter_amino_acids():
373 yield frag
374
376 """Iterates over all AminoAcidResidue objects in all Models.
377 """
378 for model in self.model_list:
379 for chain in model.chain_list:
380 for frag in chain.iter_amino_acids():
381 yield frag
382
384 """Returns True if the Structure contains NucleicAcidResiudes in the
385 default Model.
386 """
387 for frag in self.iter_nucleic_acids():
388 return True
389 return False
390
392 """Counts all NucleicAcidResidue objects in the default Model.
393 """
394 n = 0
395 for chain in self.iter_chains():
396 n += chain.count_nucleic_acids()
397 return n
398
400 """Same as iter_fragments() but only iterates over Fragments of the
401 subclass NucleicAcidResidue.
402 """
403 for chain in self.iter_chains():
404 for frag in chain.iter_nucleic_acids():
405 yield frag
406
408 """Iterates over all NucleicAcidResidue objects in all Models.
409 """
410 for model in self.model_list:
411 for chain in model.chain_list:
412 for frag in chain.iter_nucleic_acids():
413 yield frag
414
416 """Returns True if the Structure contains amino or nucleic acids
417 in the default Model.
418 """
419 for frag in self.iter_standard_residues():
420 return True
421 return False
422
424 """Counts the number of standard residues in the default Model.
425 """
426 n = 0
427 for na in self.iter_standard_residues():
428 n += 1
429 return n
430
432 """Iterates over standard residues in the default Model.
433 """
434 fpred = lambda f: f.is_standard_residue()
435 return itertools.ifilter(fpred, self.iter_fragments())
436
438 """Returns True if there are non-standard residues in the default
439 Model.
440 """
441 for frag in self.iter_non_standard_residues():
442 return True
443 return False
444
446 """Counts all non-standard residues in the default Model.
447 """
448 n = 0
449 for frag in self.iter_non_standard_residues():
450 n += 1
451 return n
452
454 """Iterates over non-standard residues in the default Model.
455 Non-standard residues are any Fragments which are not an amino or
456 nucleic acid.
457 """
458 fpred = lambda f: f.is_standard_residue()
459 return itertools.ifilterfalse(fpred, self.iter_fragments())
460
462 """Returns True if there are waters in the default Model.
463 """
464 for frag in self.iter_waters():
465 return True
466 return False
467
469 """Counts all waters in the default Model.
470 """
471 n = 0
472 for frag in self.iter_waters():
473 n += 1
474 return n
475
477 """Iterate over all waters in the default Model.
478 """
479 fpred = lambda f: f.is_water()
480 return itertools.ifilter(fpred, self.iter_fragments())
481
482 - def add_atom(self, atom, delay_sort = False):
483 """Adds an Atom object to the Structure. If a collision occurs, an
484 error is raised.
485 """
486 assert isinstance(atom, Atom)
487
488
489 try:
490 model = self.model_dict[atom.model_id]
491 except KeyError:
492 model = Model(model_id = atom.model_id)
493 self.add_model(model, delay_sort)
494
495
496 chain_id = atom.chain_id
497 fragment_id = atom.fragment_id
498
499 if model.chain_dict.has_key(chain_id):
500 chain = model.chain_dict[chain_id]
501
502 if chain.fragment_dict.has_key(fragment_id):
503 fragment = chain.fragment_dict[fragment_id]
504
505 if fragment.res_name == atom.res_name:
506 fragment.add_atom(atom)
507 else:
508 raise FragmentOverwrite()
509 else:
510 chain.add_atom(atom, delay_sort)
511 else:
512 model.add_atom(atom, delay_sort)
513
515 """Removes an Atom.
516 """
517 assert isinstance(atom, Atom)
518 self.model_dict[atom.model_id].remove_atom(atom)
519
521 """Iterates over all Atom objects in the default Model, using the
522 default alt_loc. The iteration is preformed in order according to
523 the Chain and Fragment ordering rules the Atom object is a part of.
524 """
525 if self.default_model is None:
526 raise StopIteration
527
528 for chain in self.default_model.chain_list:
529 for frag in chain.fragment_list:
530 for atm in frag.atom_list:
531 yield atm
532
534 """Counts all Atom objects in the default Model using the
535 default alt_loc.
536 """
537 n = 0
538 for chain in self.iter_chains():
539 n += chain.count_atoms()
540 return n
541
543 """Iterates over all Atom objects in the Structure. The iteration is
544 performed according to common PDB ordering rules, over all Models and
545 all alternate conformations.
546 """
547 for model in self.iter_models():
548 for atm in model.iter_all_atoms():
549 yield atm
550
552 """Counts all atoms in the default Model using the default alt_loc.
553 """
554 n = 0
555 for model in self.iter_models():
556 n += model.count_all_atoms()
557 return n
558
560 """Returns the atom with the same fragment_id and name as the
561 argument atom, or None if it is not found.
562 """
563 try:
564 return self.model_dict[atom.model_id].chain_dict[atom.chain_id].fragment_dict[atom.fragment_id].atom_dict[atom.name]
565 except KeyError:
566 return None
567
569 """Iterates over all Bond objects. The iteration is preformed by
570 iterating over all Atom objects in the same order as iter_atoms(),
571 then iterating over each Atom's Bond objects.
572 """
573 visited = {}
574 for atm in self.iter_atoms():
575 for bond in atm.iter_bonds():
576 if visited.has_key(bond):
577 continue
578 yield bond
579 visited[bond] = True
580
582 """Counts all Bond objects using the default Model and default
583 alt_loc.
584 """
585 n = 0
586 for bond in self.iter_bonds():
587 n += 1
588 return n
589
591 """Return the unique list of Atom alternate location IDs found in
592 the Structure.
593 """
594 al_list = []
595 for atm in self.iter_all_atoms():
596 if atm.alt_loc != "" and atm.alt_loc not in al_list:
597 al_list.append(atm.alt_loc)
598 return al_list
599
601 """Adds an AlphaHelix to the default Model object.
602 """
603 assert self.default_model is not None
604 self.default_model.add_alpha_helix(alpha_helix)
605
607 """Iterates over all child AlphaHelix objects in the default
608 Model.
609 """
610 if self.default_model:
611 return self.default_model.iter_alpha_helicies()
612 return iter(list())
613
615 """Adds a BetaSheet to the default Model object.
616 """
617 assert self.default_model is not None
618 self.default_model.add_beta_sheet(beta_sheet)
619
621 """Iterate over all beta sheets in the Structure.
622 """
623 if self.default_model:
624 return self.default_model.iter_beta_sheets()
625 return iter(list())
626
628 """Adds a Site object to the default Model.
629 """
630 assert self.default_model is not None
631 self.default_model.add_site(site)
632
634 """Iterate over all active/important sites defined in the Structure.
635 """
636 if self.default_model:
637 return self.default_model.iter_sites()
638 return iter(list())
639
641 """Returns self.
642 """
643 return self
644
646 """Returns the default alt_loc string.
647 """
648 return self.default_alt_loc
649
651 """Sets the default alt_loc for the Stucture.
652 """
653 assert isinstance(alt_loc, str)
654
655 self.default_alt_loc = alt_loc
656 for frag in self.iter_all_fragments():
657 frag.set_default_alt_loc(alt_loc)
658
660 """Builds a Structure's bonds by atomic distance distance using
661 the covalent radii in element.cif. A bond is built if the the
662 distance between them is less than or equal to the sum of their
663 covalent radii + 0.54A.
664 """
665 for model in self.iter_models():
666 xyzdict = GeometryDict.XYZDict(2.0)
667
668 for atm in model.iter_all_atoms():
669 if atm.position is not None:
670 xyzdict.add(atm.position, atm)
671
672 for (p1,atm1),(p2,atm2),dist in xyzdict.iter_contact_distance(2.5):
673
674 if (atm1.alt_loc == "" or atm2.alt_loc == "") or (atm1.alt_loc == atm2.alt_loc):
675
676
677
678 edesc1 = Library.library_get_element_desc(atm1.element)
679 edesc2 = Library.library_get_element_desc(atm2.element)
680
681
682
683 if edesc1 is None or edesc2 is None:
684 continue
685
686 bond_dist = edesc1.covalent_radius + edesc2.covalent_radius + 0.54
687
688
689
690
691 if dist > bond_dist:
692 continue
693
694 if atm1.get_bond(atm2) is None:
695 atm1.create_bond(atom = atm2, standard_res_bond = False)
696
698 """Builds bonds for all Fragments in the Structure from bond tables
699 for monomers retrieved from the Library implementation of the
700 Structure.
701 """
702 for frag in self.iter_all_fragments():
703 frag.create_bonds()
704
705
707 """Multiple models support.
708 """
709 - def __init__(self, model_id=1, **args):
710 assert isinstance(model_id, int)
711
712 self.structure = None
713
714 self.model_id = model_id
715 self.chain_dict = {}
716 self.chain_list = []
717
718 self.alpha_helix_list = []
719 self.beta_sheet_list = []
720 self.site_list = []
721
723 return "Model(model_id=%d)" % (self.model_id)
724
726 model = Model(model_id = self.model_id)
727 for chain in self.chain_list:
728 model.add_chain(copy.deepcopy(chain, memo), True)
729 return model
730
732 assert isinstance(other, Model)
733 return int(self.model_id) < int(other.model_id)
734
736 assert isinstance(other, Model)
737 return int(self.model_id) <= int(other.model_id)
738
740 assert isinstance(other, Model)
741 return int(self.model_id) > int(other.model_id)
742
744 assert isinstance(other, Model)
745 return int(self.model_id) >= int(other.model_id)
746
748 """Returns the number of stored Chain objects.
749 """
750 return len(self.chain_list)
751
753 """Same as get_chain, but raises KeyError if the requested chain_id
754 is not found.
755 """
756 if isinstance(chain_idx, str):
757 return self.chain_dict[chain_idx]
758 elif isinstance(chain_idx, int):
759 return self.chain_list[chain_idx]
760 raise TypeError, chain_idx
761
763 """Iterates the Chain objects in the Model.
764 """
765 return iter(self.chain_list)
766
768 """Returns True if the argument Chain or chain_id is in the Model.
769 """
770 if isinstance(chain_idx, Chain):
771 return self.chain_list.__contains__(chain_idx)
772 elif isinstance(chain_idx, str):
773 return self.chain_dict.__contains__(chain_idx)
774 raise TypeError, chain_idx
775
777 """Returns the numeric index of the Chain object in the Model.
778 """
779 assert isinstance(chain, Chain)
780 return self.chain_list.index(chain)
781
783 """Sorts all Chains in the Model by their chain_id.
784 """
785 self.chain_list.sort()
786 for chain in self.chain_list:
787 chain.sort()
788
789 - def add_chain(self, chain, delay_sort=False):
790 """Adds a Chain to the Model.
791 """
792 assert isinstance(chain, Chain)
793
794 if self.chain_dict.has_key(chain.chain_id):
795 raise ChainOverwrite()
796
797 self.chain_list.append(chain)
798 self.chain_dict[chain.chain_id] = chain
799 chain.model = self
800
801 if not delay_sort:
802 self.chain_list.sort()
803
805 """Removes the Chain from the Model.
806 """
807 assert isinstance(chain, Chain)
808 self.chain_list.remove(chain)
809 del self.chain_dict[chain.chain_id]
810 chain.model = None
811
813 """Returns the Chain object matching the chain_id character.
814 """
815 if self.chain_dict.has_key(chain_id):
816 return self.chain_dict[chain_id]
817 return None
818
820 """Iterates over all Chain objects in alphabetical order according
821 to their chain_id.
822 """
823 return iter(self.chain_list)
824
826 """Counts all Chain objects.
827 """
828 return len(self.chain_list)
829
831 """Adds a Fragment instance
832 """
833 assert isinstance(fragment, Fragment)
834 assert fragment.model_id == self.model_id
835
836
837 try:
838 chain = self.chain_dict[fragment.chain_id]
839 except KeyError:
840 chain = Chain(
841 model_id = fragment.model_id,
842 chain_id = fragment.chain_id)
843 self.add_chain(chain, delay_sort)
844
845 chain.add_fragment(fragment, delay_sort)
846
848 """Removes a Fragment object.
849 """
850 assert isinstance(fragment, Fragment)
851 self.chain_dict[fragment.chain_id].remove_fragment(fragment)
852
854 """Counts all Fragment objects.
855 """
856 n = 0
857 for chain in self.iter_chains():
858 n += chain.count_fragments()
859 return n
860
862 """Iterates over all Fragment objects. The iteration is performed
863 in order according the the parent Chain's chain_id, and the
864 Fragment's position within the chain.
865 """
866 for chain in self.chain_list:
867 for frag in chain.fragment_list:
868 yield frag
869
874
880
885
890
896
901
906
912
916
922
927
931
933 for frag in self.iter_waters():
934 return True
935 return False
936
938 n = 0
939 for frag in self.iter_waters():
940 n += 1
941 return n
942
946
947 - def add_atom(self, atom, delay_sort=False):
948 assert isinstance(atom, Atom)
949 assert atom.model_id == self.model_id
950
951
952 try:
953 chain = self.chain_dict[atom.chain_id]
954 except KeyError:
955 chain = Chain(
956 model_id = atom.model_id,
957 chain_id = atom.chain_id)
958 self.add_chain(chain, delay_sort)
959
960
961 chain.add_atom(atom, delay_sort)
962
964 """Removes an Atom object.
965 """
966 assert isinstance(atom, Atom)
967 assert atom.model_id == self.model_id
968 self.chain_dict[atom.chain_id].remove_atom(atom)
969
971 """Iterates over all Atom objects according to the Structure
972 defaults.
973 """
974 for chain in self.chain_list:
975 for frag in chain.fragment_list:
976 for atm in frag.atom_list:
977 yield atm
978
980 """Counts all Atom objects in according to the Structure defaults.
981 """
982 n = 0
983 for chain in self.iter_chains():
984 n += chain.count_atoms()
985 return n
986
988 """Iterates over all Atom objects including all atoms in multiple
989 conformations.
990 """
991 for chain in self.iter_chains():
992 for atm in chain.iter_all_atoms():
993 yield atm
994
996 """Counts all Atom objects including all atoms in multiple
997 conformations.
998 """
999 n = 0
1000 for chain in self.iter_chains():
1001 n += chain.count_all_atoms()
1002 return n
1003
1005 """Returns the atom with the same fragment_id and name as the
1006 argument atom, or None if it is not found.
1007 """
1008 try:
1009 return self.chain_dict[atom.chain_id].fragment_dict[atom.fragment_id].atom_dict[atom.name]
1010 except KeyError:
1011 return None
1012
1014 """Adds an AlphaHelix object to the Model.
1015 """
1016 assert isinstance(alpha_helix, AlphaHelix)
1017 self.alpha_helix_list.append(alpha_helix)
1018 alpha_helix.model = self
1019
1021 """Removes an AlphaHelix object from the Model.
1022 """
1023 assert isinstance(alpha_helix, AlphaHelix)
1024 self.alpha_helix_list.remove(alpha_helix)
1025 alpha_helix.model = None
1026
1028 """Iterates over all AlphaHelix objects in the Model.
1029 """
1030 return iter(self.alpha_helix_list)
1031
1033 """Adds a BetaSheet object to the Model.
1034 """
1035 assert isinstance(beta_sheet, BetaSheet)
1036 self.beta_sheet_list.append(beta_sheet)
1037 beta_sheet.model = self
1038
1040 """Removes a BetaSheet object from the Model.
1041 """
1042 assert isinstance(beta_sheet, BetaSheet)
1043 self.beta_sheet_list.remove(beta_sheet)
1044 beta_sheet.model = None
1045
1047 """Iterate over all child BetaSheet objects in the Model.
1048 """
1049 return iter(self.beta_sheet_list)
1050
1052 """Adds a Site (of interest) object to the Model.
1053 """
1054 assert isinstance(site, Site)
1055 self.site_list.append(site)
1056 site.model = self
1057
1059 """Removes a Site (of interest) object from the Model.
1060 """
1061 assert isinstance(site, Site)
1062 self.site_list.append(site)
1063 site.model = None
1064
1066 """Iterate over all active/important sites defined in the Structure.
1067 """
1068 return iter(self.site_list)
1069
1071 """Returns the parent Structure.
1072 """
1073 return self.structure
1074
1076 """Iterates over all Bond objects. The iteration is preformed by
1077 iterating over all Atom objects in the same order as iter_atoms(),
1078 then iterating over each Atom's Bond objects.
1079 """
1080 visited = {}
1081 for atm in self.iter_atoms():
1082 for bond in atm.iter_bonds():
1083 if visited.has_key(bond):
1084 continue
1085 yield bond
1086 visited[bond] = True
1087
1089 """Counts all Bond objects.
1090 """
1091 n = 0
1092 for bond in self.iter_bonds():
1093 n += 1
1094 return n
1095
1097 """Sets the model_id of all contained objects.
1098 """
1099 assert isinstance(model_id, int)
1100
1101 if self.structure is not None:
1102 chk_model = self.structure.get_model(model_id)
1103 if chk_model is not None or chk_model != self:
1104 raise ModelOverwrite()
1105
1106 self.model_id = model_id
1107
1108 for chain in self.iter_chains():
1109 chain.set_model_id(model_id)
1110
1111 if self.structure is not None:
1112 self.structure.model_list.sort()
1113
1114
1116 """Segment objects are a container for Fragment objects, but are
1117 disassociated with the Structure object hierarch. Chain objects are
1118 a subclass of Segment objects which are part of the Structure hierarchy.
1119 """
1120 - def __init__(self,
1121 model_id = 1,
1122 chain_id = "",
1123 **args):
1124
1125 assert isinstance(model_id, int)
1126 assert isinstance(chain_id, str)
1127
1128 self.model = None
1129 self.chain = None
1130
1131 self.model_id = model_id
1132 self.chain_id = chain_id
1133
1134
1135
1136 self.fragment_list = []
1137 self.fragment_dict = {}
1138
1139
1140 self.sequence = Sequence.Sequence()
1141
1143 try:
1144 return "Segment(%d:%s, %s...%s)" % (
1145 self.model_id, self.chain_id, self.fragment_list[0], self.fragment_list[-1])
1146 except IndexError:
1147 return "Segment(%d:%s)" % (self.model_id, self.chain_id)
1148
1150 """Implements copy module protocol for deepcopy() operation.
1151 """
1152 segment = Segment(model_id = self.model_id, chain_id = self.chain_id)
1153
1154 for fragment in self.fragment_list:
1155 segment.add_fragment(copy.deepcopy(fragment, memo), True)
1156
1157 return segment
1158
1160 """Less than operator based on the chain_id.
1161 """
1162 assert isinstance(other, Segment)
1163 return self.chain_id < other.chain_id
1164
1166 """Less than or equal operator based on chain_id.
1167 """
1168 assert isinstance(other, Segment)
1169 return self.chain_id <= other.chain_id
1170
1172 """Greator than operator based on chain_id.
1173 """
1174 assert isinstance(other, Segment)
1175 return self.chain_id > other.chain_id
1176
1178 """Greator than or equal to operator based on chain_id.
1179 """
1180 assert isinstance(other, Segment)
1181 return self.chain_id >= other.chain_id
1182
1184 """Return the number of Fragments in the Segment.
1185 """
1186 return len(self.fragment_list)
1187
1189 """Retrieve a Fragment within the Segment. This can take an integer
1190 index of the Fragment's position within the segment, the fragment_id
1191 string of the Fragment to retrieve, or a slice of the Segment to
1192 return a new Segment object containing the sliced subset of Fragments.
1193 If the slice values are fragment_id strings, then the Segment which
1194 is returned includes those Fragments. If the slice values are
1195 integers, then normal list slicing rules apply.
1196 """
1197 if isinstance(fragment_idx, int):
1198 return self.fragment_list[fragment_idx]
1199
1200 elif isinstance(fragment_idx, str):
1201 return self.fragment_dict[fragment_idx]
1202
1203 elif isinstance(fragment_idx, slice):
1204
1205
1206 start = fragment_idx.start
1207 stop = fragment_idx.stop
1208
1209
1210 if (start is None and stop is None) or \
1211 (start is None and isinstance(stop, int)) or \
1212 (stop is None and isinstance(start, int)) or \
1213 (isinstance(start, int) and isinstance(stop, int)):
1214
1215 segment = self.construct_segment()
1216 for frag in self.fragment_list[start:stop]:
1217 segment.add_fragment(frag, True)
1218 return segment
1219
1220
1221 if (start is None and isinstance(stop, str)) or \
1222 (stop is None and isinstance(start, str)) or \
1223 (isinstance(start, str) and isinstance(stop, str)):
1224
1225 return self.construct_sub_segment(start, stop)
1226
1227 raise TypeError, fragment_idx
1228
1230 """Iterate all Fragments contained in the Segment.
1231 """
1232 return iter(self.fragment_list)
1233
1235 """Checks for Fragment objects, or the fragment_id string.
1236 """
1237 if isinstance(fragment_idx, Fragment):
1238 return self.fragment_list.__contains__(fragment_idx)
1239 elif isinstance(fragment_idx, str):
1240 return self.fragment_dict.__contains__(fragment_idx)
1241 raise TypeError, fragment_idx
1242
1243 - def index(self, fragment):
1244 """Return the 0-based index of the fragment in the segment list.
1245 """
1246 return self.fragment_list.index(fragment)
1247
1249 """Sort the Fragments in the Segment into proper order.
1250 """
1251 self.fragment_list.sort()
1252
1254 """Constructs a new Segment object so that it has a valid .chain
1255 reference.
1256 """
1257 segment = Segment(
1258 model_id = self.model_id,
1259 chain_id = self.chain_id)
1260
1261 segment.chain = self.chain
1262 segment.model = self.model
1263
1264 return segment
1265
1267 """Construct and return a sub-Segment between start_frag_id and
1268 stop_frag_id. If start_frag_id is None, then the slice is taken from
1269 the beginning of this Segment, and if stop_frag_id is None it is taken
1270 to the end of this Segment.
1271 """
1272 fragiter = iter_fragments(iter(self.fragment_list), start_frag_id, stop_frag_id)
1273 segment = self.construct_segment()
1274 for frag in fragiter:
1275 segment.add_fragment(frag, True)
1276 return segment
1277
1279 """Adds a Fragment instance to the Segment. If delay_sort is True,
1280 then the fragment is not inserted in the proper position within the
1281 segment.
1282 """
1283 assert isinstance(fragment, Fragment)
1284 assert fragment.chain_id == self.chain_id
1285
1286 if self.fragment_dict.has_key(fragment.fragment_id):
1287 raise FragmentOverwrite()
1288
1289 self.fragment_list.append(fragment)
1290 self.fragment_dict[fragment.fragment_id] = fragment
1291
1292 if not delay_sort:
1293 self.fragment_list.sort()
1294
1296 """Removes a Fragment object from the Segment.
1297 """
1298 assert isinstance(fragment, Fragment)
1299 self.fragment_list.remove(fragment)
1300 del self.fragment_dict[fragment.fragment_id]
1301
1303 """Returns the PDB fragment uniquely identified by its fragment_id.
1304 """
1305 if self.fragment_dict.has_key(fragment_id):
1306 return self.fragment_dict[fragment_id]
1307 return None
1308
1310 """Iterates over all Fragment objects. The iteration is performed in
1311 order according to the Fragment's position within the Segment object.
1312 """
1313 return iter_fragments(iter(self.fragment_list), frag_id_begin, frag_id_end)
1314
1316 """Return the number of Fragment objects.
1317 """
1318 return len(self.fragment_list)
1319
1321 for frag in self.fragment_list:
1322 if frag.is_amino_acid():
1323 return True
1324 return False
1325
1327 n = 0
1328 for frag in self.fragment_list:
1329 if frag.is_amino_acid():
1330 n += 1
1331 return n
1332
1334 fpred = lambda f: f.is_amino_acid()
1335 return itertools.ifilter(fpred, self.fragment_list)
1336
1338 for frag in self.fragment_list:
1339 if frag.is_nucleic_acid():
1340 return True
1341 return False
1342
1344 n = 0
1345 for frag in self.fragment_list:
1346 if frag.is_nucleic_acid():
1347 n += 1
1348 return n
1349
1351 fpred = lambda f: f.is_nucleic_acid()
1352 return itertools.ifilter(fpred, self.fragment_list)
1353
1355 for frag in self.fragment_list:
1356 if frag.is_standard_residue():
1357 return True
1358 return False
1359
1361 n = 0
1362 for frag in self.fragment_list:
1363 if frag.is_standard_residue():
1364 n += 1
1365 return n
1366
1368 fpred = lambda f: f.is_standard_residue()
1369 return itertools.ifilter(fpred, self.fragment_list)
1370
1372 for frag in self.fragment_list:
1373 if not frag.is_standard_residue():
1374 return True
1375 return False
1376
1378 n = 0
1379 for frag in self.fragment_list:
1380 if not frag.is_standard_residue():
1381 n += 1
1382 return n
1383
1385 fpred = lambda f: f.is_standard_residue()
1386 return itertools.ifilterfalse(fpred, self.fragment_list)
1387
1389 for frag in self.fragment_list:
1390 if frag.is_water():
1391 return True
1392 return False
1393
1395 n = 0
1396 for frag in self.fragment_list:
1397 if frag.is_water():
1398 n += 1
1399 return n
1400
1402 fpred = lambda f: f.is_water()
1403 return itertools.ifilter(fpred, self.fragment_list)
1404
1405 - def add_atom(self, atom, delay_sort = False):
1406 """Adds an Atom.
1407 """
1408 assert isinstance(atom, Atom)
1409 assert atom.model_id == self.model_id
1410 assert atom.chain_id == self.chain_id
1411
1412
1413 if not self.fragment_dict.has_key(atom.fragment_id):
1414
1415 if Library.library_is_amino_acid(atom.res_name):
1416 fragment = AminoAcidResidue(
1417 model_id = atom.model_id,
1418 chain_id = atom.chain_id,
1419 fragment_id = atom.fragment_id,
1420 res_name = atom.res_name)
1421
1422 elif Library.library_is_nucleic_acid(atom.res_name):
1423 fragment = NucleicAcidResidue(
1424 model_id = atom.model_id,
1425 chain_id = atom.chain_id,
1426 fragment_id = atom.fragment_id,
1427 res_name = atom.res_name)
1428 else:
1429 fragment = Fragment(
1430 model_id = atom.model_id,
1431 chain_id = atom.chain_id,
1432 fragment_id = atom.fragment_id,
1433 res_name = atom.res_name)
1434
1435 self.add_fragment(fragment, delay_sort)
1436
1437 else:
1438 fragment = self.fragment_dict[atom.fragment_id]
1439 if fragment.res_name != atom.res_name:
1440 raise FragmentOverwrite()
1441
1442 fragment.add_atom(atom)
1443
1445 """Removes an Atom object.
1446 """
1447 assert isinstance(atom, Atom)
1448 self.fragment_dict[atom.fragment_id].remove_atom(atom)
1449
1451 """Iterates over all Atom objects within the Segment using the
1452 default conformation set in the parent Structure.
1453 """
1454 for frag in self.fragment_list:
1455 for atm in frag.atom_list:
1456 yield atm
1457
1463
1465 """Performs an in-order iteration of all atoms in the Segment,
1466 including alternate conformations.
1467 """
1468 for frag in self.fragment_list:
1469 for atm in frag.iter_all_atoms():
1470 yield atm
1471
1477
1479 """Returns the atom with the same fragment_id and name as the
1480 argument atom, or None if it is not found.
1481 """
1482 try:
1483 return self.fragment_dict[atom.fragment_id].atom_dict[atom.name]
1484 except KeyError:
1485 return None
1486
1488 """Iterates over all Bond objects attached to Atom objects within the
1489 Segment.
1490 """
1491 visited = {}
1492 for atm in self.iter_atoms():
1493 for bond in atm.iter_bonds():
1494 if visited.has_key(bond):
1495 continue
1496 yield bond
1497 visited[bond] = True
1498
1500 """Returns the Chain object this Segment is part of.
1501 """
1502 return self.chain
1503
1505 """Returns the parent Model object.
1506 """
1507 return self.model
1508
1510 """Returns the parent Structure object.
1511 """
1512 return self.model.structure
1513
1515 """Sets the model_id of all contained objects.
1516 """
1517 assert isinstance(model_id, int)
1518 self.model_id = model_id
1519
1520 for frag in self.iter_fragments():
1521 frag.set_model_id(model_id)
1522
1524 """Sets the model_id of all contained objects.
1525 """
1526 assert isinstance(chain_id, str)
1527 self.chain_id = chain_id
1528
1529 for frag in self.iter_fragments():
1530 frag.set_chain_id(chain_id)
1531
1533 """Returns True if there are no disagreements in the sequences of
1534 this segment and segment2.
1535 """
1536 hdict = {}
1537
1538 for fragment in self.fragment_list:
1539 hdict[fragment.fragment_id] = fragment.res_name
1540
1541 for fragment in segment2.fragment_list:
1542 if hdict.get(fragment.fragment_id, fragment.res_name) != fragment.res_name:
1543 return False
1544
1545 return True
1546
1548 """Chain objects contain an ordered list of Fragment objects.
1549 """
1550 - def __init__(self,
1551 model_id = 1,
1552 chain_id = "",
1553 **args):
1554
1555 args["model_id"] = model_id
1556 args["chain_id"] = chain_id
1557 Segment.__init__(self, **args)
1558 self.model = None
1559
1561 try:
1562 return "Chain(%d:%s, %s...%s)" % (
1563 self.model_id, self.chain_id, self.fragment_list[0], self.fragment_list[-1])
1564 except IndexError:
1565 return "Chain(%d:%s)" % (self.model_id, self.chain_id)
1566
1568 """Implements the copy module deepcopy() protocol.
1569 """
1570 chain = Chain(model_id = self.model_id,
1571 chain_id = self.chain_id)
1572 for fragment in self.fragment_list:
1573 chain.add_fragment(copy.deepcopy(fragment, memo), True)
1574 return chain
1575
1577 """Constructs a new Segment object so that it has a valid .chain
1578 reference.
1579 """
1580 segment = Segment(
1581 model_id = self.model_id,
1582 chain_id = self.chain_id)
1583
1584 segment.chain = self
1585 segment.model = self.model
1586
1587 return segment
1588
1590 """The sequence_list is a list of 3-letter residue name codes which
1591 define the polymer sequence for the chain. Setting the sequence
1592 attempts to map the sequence codes to Fragment objects.
1593 """
1594 self.sequence_fragment_list = []
1595 for res_name in sequence_list:
1596 self.sequence_fragment_list.append((res_name, None))
1597
1599 """Removes the current sequence mapping.
1600 """
1601 self.sequence_fragment_list = []
1602
1604 """Iterates over all 3-letter residue codes for the polymer sequence.
1605 """
1606 for res_name, fragment in self.sequence_fragment_list:
1607 yield res_name
1608
1610 """Constructs and returns a list with the 3-letter residue codes
1611 for the polymer sequence.
1612 """
1613 return list(self.iter_sequence())
1614
1616 return self.sequence_fragment_list[seq_index][1]
1617
1619 """Adds a Fragment instance to the Chain. If delay_sort is True,
1620 then the fragment is not inserted in the proper position within the
1621 chain.
1622 """
1623 Segment.add_fragment(self, fragment, delay_sort)
1624 fragment.chain = self
1625
1627 """Remove the Fragment from the Chain.
1628 """
1629 Segment.remove_fragment(self, fragment)
1630 fragment.chain = None
1631
1633 """Sets a new ID for the Chain, updating the chain_id
1634 for all objects in the Structure hierarchy.
1635 """
1636
1637 if self.model is not None:
1638 chk_chain = self.model.get_chain(chain_id)
1639 if chk_chain is not None or chk_chain != self:
1640 raise ChainOverwrite()
1641
1642 Segment.set_chain_id(self, chain_id)
1643
1644
1645 if self.model is not None:
1646 self.model.chain_list.sort()
1647
1648
1650 """Fragment objects are a basic unit for organizing small groups of Atoms.
1651 Amino acid residues are fragments, as well as nucleic acids and other
1652 small molecules. In terms of a PDB file, they are all the atoms from a
1653 unique residue in a chain.
1654
1655 Fragments have the following attributes:
1656
1657 Fragment.res_name - the fragment/residue name
1658 Fragment.res_seq - the sequence id of the fragment/residue
1659 Fragment.chain_id - the ID of the chain containing this fragment
1660 """
1661 - def __init__(self,
1662 model_id = 1,
1663 chain_id = "",
1664 fragment_id = "",
1665 res_name = "",
1666 **args):
1667
1668 assert isinstance(model_id, int)
1669 assert isinstance(res_name, str)
1670 assert isinstance(fragment_id, str)
1671 assert isinstance(chain_id, str)
1672
1673 self.chain = None
1674
1675 self.model_id = model_id
1676 self.chain_id = chain_id
1677 self.fragment_id = fragment_id
1678 self.res_name = res_name
1679
1680 self.default_alt_loc = "A"
1681
1682
1683
1684 self.atom_order_list = []
1685
1686
1687 self.alt_loc_dict = {}
1688
1689
1690
1691 self.atom_list = []
1692 self.atom_dict = {}
1693
1695 return "Frag(%s,%s,%s)" % (
1696 self.res_name,
1697 self.fragment_id,
1698 self.chain_id)
1699
1701 fragment = Fragment(
1702 model_id = self.model_id,
1703 chain_id = self.chain_id,
1704 fragment_id = self.fragment_id,
1705 res_name = self.res_name)
1706
1707 for atom in self.iter_all_atoms():
1708 fragment.add_atom(copy.deepcopy(atom, memo))
1709
1710 return fragment
1711
1715
1719
1723
1727
1729 return len(self.atom_list)
1730
1732 """Lookup an atom contained in a fragment by its name, or by its index
1733 within the fragment's private atom_list. If the atom is not found,
1734 an exception is raised. The type of exception depends on the argument
1735 type. If the argument was an integer, then an IndexError is raised.
1736 If the argument was a string, then a KeyError is raised.
1737 """
1738 if isinstance(name_idx, str):
1739 return self.atom_dict[name_idx]
1740 elif isinstance(name_idx, int):
1741 return self.atom_list[name_idx]
1742 raise TypeError, name_idx
1743
1745 """Iterates the atoms within the fragment. If the fragment contains
1746 atoms in alternate conformations, only the atoms with the structure's
1747 default_alt_loc are iterated.
1748 """
1749 return iter(self.atom_list)
1750
1752 """Return True if the Atom object is contained in the fragment.
1753 """
1754 if isinstance(atom_idx, Atom):
1755 return self.atom_list.__contains__(atom_idx)
1756 elif isinstance(atom_idx, str):
1757 return self.atom_dict.__contains__(atom_idx)
1758 raise TypeError, atom_idx
1759
1761 """Returns the sequential index of the atom.
1762 """
1763 return self.atom_list.index(atom)
1764
1766 """Sets the default alt_loc of the Fragment.
1767 """
1768 self.default_alt_loc = alt_loc
1769
1770 ishift = 0
1771 for i, atm in enumerate(self.atom_order_list):
1772 if isinstance(atm, Atom):
1773
1774 try:
1775 self.atom_list[i-ishift] = atm
1776 except IndexError:
1777 self.atom_list.append(atm)
1778 self.atom_dict[atm.name] = atm
1779
1780 else:
1781 try:
1782 atmx = atm[alt_loc]
1783 except KeyError:
1784
1785
1786 try:
1787 del self.atom_list[i-ishift]
1788 except IndexError:
1789 pass
1790 for atmx in atm.itervalues():
1791 try:
1792 del self.atom_dict[atmx.name]
1793 except KeyError:
1794 pass
1795 break
1796 ishift += 1
1797 else:
1798
1799
1800 try:
1801 self.atom_list[i-ishift] = atmx
1802 except IndexError:
1803 self.atom_list.append(atmx)
1804 self.atom_dict[atmx.name] = atmx
1805
1807 """Adds an atom to the fragment, and sets the atom's atom.fragment
1808 attribute to the fragment.
1809 """
1810 assert isinstance(atom, Atom)
1811 assert atom.chain_id == self.chain_id
1812 assert atom.fragment_id == self.fragment_id
1813 assert atom.res_name == self.res_name
1814
1815 name = atom.name
1816 alt_loc = atom.alt_loc
1817
1818 if alt_loc == "":
1819 if not self.alt_loc_dict.has_key(name):
1820
1821
1822
1823
1824
1825
1826
1827 if not self.atom_dict.has_key(name):
1828 self.atom_order_list.append(atom)
1829 self.atom_list.append(atom)
1830 self.atom_dict[name] = atom
1831
1832 else:
1833
1834
1835
1836
1837 atomA = self.atom_dict[name]
1838 assert atomA != atom
1839
1840 msg = "atom name clash %s, " % (str(atomA))
1841 msg += "automatically assigning ALTLOC labels"
1842 ConsoleOutput.warning(msg)
1843
1844 iA = self.atom_order_list.index(atomA)
1845
1846 self.alt_loc_dict[name] = altloc = Altloc()
1847 self.atom_order_list[iA] = altloc
1848
1849 altloc.add_atom(atomA)
1850 altloc.add_atom(atom)
1851 self.set_default_alt_loc(self.default_alt_loc)
1852
1853 else:
1854
1855
1856
1857
1858
1859
1860 altloc = self.alt_loc_dict[name]
1861 altloc.add_atom(atom)
1862 self.set_default_alt_loc(self.default_alt_loc)
1863
1864 else:
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878 if not self.alt_loc_dict.has_key(name):
1879
1880 if not self.atom_dict.has_key(name):
1881
1882
1883
1884 self.alt_loc_dict[name] = altloc = Altloc()
1885 altloc.add_atom(atom)
1886
1887 self.atom_order_list.append(altloc)
1888
1889 self.atom_list.append(atom)
1890 self.atom_dict[name] = atom
1891
1892 else:
1893
1894
1895
1896
1897
1898
1899 atomA = self.atom_dict[name]
1900 iA = self.atom_order_list.index(atomA)
1901
1902 self.alt_loc_dict[name] = altloc = Altloc()
1903 self.atom_order_list[iA] = altloc
1904
1905 altloc.add_atom(atomA)
1906 altloc.add_atom(atom)
1907
1908 else:
1909
1910
1911
1912
1913 altloc = self.alt_loc_dict[name]
1914 altloc.add_atom(atom)
1915
1916 self.set_default_alt_loc(self.default_alt_loc)
1917
1918 atom.fragment = self
1919
1921 """Removes the Atom instance from the Fragment.
1922 """
1923 assert atom.fragment == self
1924
1925 if self.alt_loc_dict.has_key(atom.name):
1926 altloc = self.alt_loc_dict[atom.name]
1927 if altloc.has_key(atom.alt_loc):
1928 altloc.remove_atom(atom)
1929 if len(altloc) == 0:
1930 del self.alt_loc_dict[atom.name]
1931 self.atom_order_list.remove(altloc)
1932 if atom in self.atom_list:
1933 self.atom_list.remove(atom)
1934 del self.atom_dict[atom.name]
1935 else:
1936 self.atom_order_list.remove(atom)
1937 self.atom_list.remove(atom)
1938 del self.atom_dict[atom.name]
1939
1940 atom.fragment = None
1941
1942 - def get_atom(self, name, alt_loc = None):
1943 """Returns the matching Atom instance contained in the Fragment.
1944 Returns None if a match is not found. If alt_loc is not given,
1945 then the default alt_loc is used.
1946 """
1947 if alt_loc:
1948 if self.alt_loc_dict.has_key(name):
1949 altloc = self.alt_loc_dict[name]
1950 if altloc.has_key(alt_loc):
1951 return altloc[alt_loc]
1952 return None
1953 else:
1954 if not self.atom_dict.has_key(name):
1955 return None
1956 return self.atom_dict[name]
1957
1959 """Returns the atom with the same fragment_id and name as the
1960 argument atom, or None if it is not found.
1961 """
1962 try:
1963 return self.atom_dict[atom.name]
1964 except KeyError:
1965 return None
1966
1968 """Iterates over all Atom objects contained in the Fragment matching
1969 the current model and default alt_loc.
1970 """
1971 return iter(self.atom_list)
1972
1974 """Counts Atom objects.
1975 """
1976 return len(self.atom_list)
1977
1979 """Iterates of all Atoms in the Fragment including Altlocs.
1980 """
1981 for atm in self.atom_order_list:
1982 if isinstance(atm, Atom):
1983 yield atm
1984 else:
1985 for atmx in atm:
1986 yield atmx
1987
1989 """Counts all Atom objects including Atoms in alternate conformations.
1990 """
1991 n = 0
1992 for atm in self.atom_order_list:
1993 if isinstance(atm, Atom):
1994 n += 1
1995 else:
1996 n += len(atm)
1997 return n
1998
2000 """Iterates over all Bond objects. The iteration is preformed by
2001 iterating over all Atom objects in the same order as iter_atoms(),
2002 then iterating over each Atom's Bond objects."""
2003 visited = {}
2004 for atm in self.iter_atoms():
2005 for bond in atm.iter_bonds():
2006 if not visited.has_key(bond):
2007 yield bond
2008 visited[bond] = True
2009
2011 """Returns the fragment in the same chain at integer offset from
2012 self. Returns None if no fragment is found.
2013 """
2014 assert isinstance(offset, int)
2015
2016 i = self.chain.index(self) + offset
2017 if i < 0:
2018 return None
2019 try:
2020 return self.chain[i]
2021 except IndexError:
2022 return None
2023
2025 """Returns the parent Chain object.
2026 """
2027 return self.chain.model
2028
2030 """Returns the parent Chain object.
2031 """
2032 return self.chain
2033
2035 """Returns the parent Structure object.
2036 """
2037 return self.chain.model.structure
2038
2040 """Constructs bonds within a fragment. Bond definitions are retrieved
2041 from the monomer library.
2042 """
2043 mdesc = Library.library_get_monomer_desc(self.res_name)
2044 if mdesc is None:
2045 return
2046
2047 def find_atom(name):
2048 try:
2049 return self[name]
2050 except KeyError:
2051 return self[mdesc.alt_atom_dict[name]]
2052 for bond in mdesc.bond_list:
2053 try:
2054 atm1 = find_atom(bond["atom1"])
2055 atm2 = find_atom(bond["atom2"])
2056 except KeyError:
2057 continue
2058 else:
2059 atm1.create_bonds(atom = atm2, standard_res_bond = True)
2060
2062 """Returns True if the Fragment/Residue object is one of the
2063 PDB defined standard residues. PDB standard residues are amino
2064 and nucleic acid residues.
2065 """
2066 return False
2067
2069 """Returns True if the Fragment is an Amino Acid residue.
2070 """
2071 return False
2072
2074 """Returns True if the Fragment is a Nucleic Acid residue.
2075 """
2076 return False
2077
2079 """Returns True if the Fragment is a water molecule, returns False
2080 otherwise.
2081 """
2082 return Library.library_is_water(self.res_name)
2083
2085 """Sets the model_id of the Fragment and all contained Atom
2086 objects.
2087 """
2088 assert isinstance(model_id, int)
2089 self.model_id = model_id
2090
2091 for atm in self.iter_atoms():
2092 atm.set_model_id(model_id)
2093
2095 """Sets the chain_id of the Fragment and all contained Atom objects.
2096 """
2097 assert isinstance(chain_id, str)
2098 self.chain_id = chain_id
2099
2100 for atm in self.iter_atoms():
2101 atm.set_chain_id(chain_id)
2102
2104 """Sets the fragment_id of the Fragment and all contained Atom
2105 objects.
2106 """
2107 assert isinstance(fragment_id, str)
2108
2109 if self.chain is not None:
2110 chk_frag = self.chain.get_fragment(fragment_id)
2111 if chk_frag is not None or chk_frag != self:
2112 raise FragmentOverwrite()
2113
2114 self.fragment_id = fragment_id
2115
2116 for atm in self.iter_atoms():
2117 atm.set_fragment_id(fragment_id)
2118
2119 if self.chain is not None:
2120 self.chain.sort()
2121
2123 """Sets the res_name of the Fragment and all contained Atom
2124 objects.
2125 """
2126 assert isinstance(res_name, str)
2127 self.res_name = res_name
2128
2129 for atm in self.iter_atoms():
2130 atm.set_res_name(res_name)
2131
2132
2134 """A subclass of Fragment representing one residue in a polymer chain.
2135 """
2137 return "Res(%s,%s,%s)" % (self.res_name,
2138 self.fragment_id,
2139 self.chain_id)
2140
2142 """Returns the residue along the chain at the given integer offset
2143 from self. Returns None if there is no residue at that offset, or
2144 if the fragment found is not the same type of residue as self.
2145 """
2146 assert isinstance(offset, int)
2147 frag = Fragment.get_offset_fragment(self, offset)
2148 if type(self) == type(frag):
2149 return frag
2150 return None
2151
2153 """Constructs bonds within a fragment. Bond definitions are retrieved
2154 from the monomer library. This version also constructs the bonds
2155 between adjacent residues.
2156 """
2157 Fragment.create_bonds(self)
2158 return
2159
2160
2161 next_res = self.get_offset_residue(1)
2162 if next_res is None:
2163 return
2164
2165 mdesc1 = Library.library_get_monomer_desc(self.res_name)
2166 mdesc2 = Library.library_get_monomer_desc(next_res.res_name)
2167
2168 if mdesc1 is None or mdesc2 is None:
2169 return
2170
2171 for (name1, name2) in mdesc1.get_polymer_bond_list(self, next_res):
2172 try:
2173 atm1 = self[name1]
2174 atm2 = next_res[name2]
2175 except KeyError:
2176 continue
2177 else:
2178 atm1.create_bonds(atom = atm2, standard_res_bond = True)
2179
2180
2182 """A subclass of Residue representing one amino acid residue in a
2183 polypeptide chain.
2184 """
2186 fragment = AminoAcidResidue(
2187 model_id = self.model_id,
2188 res_name = self.res_name,
2189 fragment_id = self.fragment_id,
2190 chain_id = self.chain_id)
2191
2192 for atom in self.iter_all_atoms():
2193 fragment.add_atom(copy.deepcopy(atom, memo))
2194
2195 return fragment
2196
2198 """Returns True if the Fragment/Residue object is one of the
2199 PDB defined standard residues. PDB standard residues are amino
2200 and nucleic acid residues.
2201 """
2202 return True
2203
2205 """Returns True if the Fragment is an Amino Acid residue.
2206 """
2207 return True
2208
2210 """Returns True if the Fragment is a water molecule, returns False
2211 otherwise.
2212 """
2213 return False
2214
2216 """Calculates the main chain bond lengths: (N-CA, CA-C, C-O, CA-CB,
2217 CA-(next)N). The result is returned as a 5-tuple in that order. Bond
2218 lengths involving missing atoms are returned as None in the tuple.
2219 """
2220 aN = self.get_atom('N')
2221 aCA = self.get_atom('CA')
2222 aC = self.get_atom('C')
2223 aO = self.get_atom('O')
2224 aCB = self.get_atom('CB')
2225
2226 try:
2227 naN = self.get_offset_residue(1).get_atom('N')
2228 except AttributeError:
2229 naN = None
2230
2231 N_CA = AtomMath.calc_distance(aN, aCA)
2232 CA_C = AtomMath.calc_distance(aCA, aC)
2233 C_O = AtomMath.calc_distance(aC, aO)
2234 C_nN = AtomMath.calc_distance(aC, naN)
2235 CA_CB = AtomMath.calc_distance(aCA, aCB)
2236 return (N_CA, CA_C, C_O, CA_CB, C_nN)
2237
2239 """Calculates main chain bond angles (N-CA-C, N-CA-CB, CB-CA-C,
2240 CA-C-O, CA-C-(next)N, C-(next residue)N-(next residue)CA) and
2241 returns the result as a 6-tuple in that order. Angles involving
2242 missing atoms are returned as None in the tuple.
2243 """
2244 aN = self.get_atom('N')
2245 aCA = self.get_atom('CA')
2246 aC = self.get_atom('C')
2247 aO = self.get_atom('O')
2248 aCB = self.get_atom('CB')
2249
2250 naN = None
2251 naCA = None
2252 next_res = self.get_offset_residue(1)
2253 if next_res:
2254 naN = next_res.get_atom('N')
2255 naCA = next_res.get_atom('CA')
2256
2257 N_CA_C = AtomMath.calc_angle(aN, aCA, aC)
2258 CA_C_O = AtomMath.calc_angle(aCA, aC, aO)
2259 N_CA_CB = AtomMath.calc_angle(aN, aCA, aCB)
2260 CB_CA_C = AtomMath.calc_angle(aCB, aCA, aC)
2261 CA_C_nN = AtomMath.calc_angle(aCA, aC, naN)
2262 C_nN_nCA = AtomMath.calc_angle(aC, naN, naCA)
2263
2264 return (N_CA_C, N_CA_CB, CB_CA_C, CA_C_O, CA_C_nN, C_nN_nCA)
2265
2267 """Calculates the Psi torsion angle of the amino acid. Raises a
2268 CTerminal exception if called on a C-terminal residue which does
2269 not have a Psi torsion angle.
2270 """
2271 next_res = self.get_offset_residue(1)
2272 if next_res is None:
2273 return None
2274
2275 aN = self.get_atom('N')
2276 aCA = self.get_atom('CA')
2277 aC = self.get_atom('C')
2278 naN = next_res.get_atom('N')
2279 return AtomMath.calc_torsion_angle(aN, aCA, aC, naN)
2280
2282 """Calculates the Phi torsion angle of the amino acid. Raises a
2283 NTerminal exception if called on an N-terminal residue which does
2284 not have a Phi torsion angle.
2285 """
2286 prev_res = self.get_offset_residue(-1)
2287 if prev_res is None:
2288 return None
2289
2290 paC = prev_res.get_atom('C')
2291 aN = self.get_atom('N')
2292 aCA = self.get_atom('CA')
2293 aC = self.get_atom('C')
2294 return AtomMath.calc_torsion_angle(paC, aN, aCA, aC)
2295
2297 """Calculates the Omega torsion angle of the amino acid. Raises a
2298 CTerminal exception if called on a C-terminal residue which does
2299 not have an Omega torsion angle.
2300 """
2301 next_res = self.get_offset_residue(1)
2302 if next_res is None:
2303 return None
2304
2305 aCA = self.get_atom('CA')
2306 aC = self.get_atom('C')
2307 naN = next_res.get_atom('N')
2308 naCA = next_res.get_atom('CA')
2309 return AtomMath.calc_torsion_angle(aCA, aC, naN, naCA)
2310
2312 """Returns True if this is a CIS amino acid, otherwise returns False.
2313 It uses calc_torsion_omega, and if there are missing atoms this method
2314 will return None.
2315 """
2316 prev_res = self.get_offset_residue(-1)
2317 if prev_res is None:
2318 return None
2319
2320 prev_omega = prev_res.calc_torsion_omega()
2321 if prev_omega is None:
2322 return None
2323
2324 if abs(prev_omega) <= (math.pi/2.0):
2325 return True
2326
2327 return False
2328
2330 """Calculates the given torsion angle for the monomer. The torsion
2331 angles are defined by name in monomers.cif.
2332 """
2333 mdesc = Library.library_get_monomer_desc(self.res_name)
2334 try:
2335 (atom1_name,
2336 atom2_name,
2337 atom3_name,
2338 atom4_name) = mdesc.torsion_angle_dict[torsion_angle_name]
2339 except KeyError:
2340 return None
2341
2342 atom1 = self.get_atom(atom1_name)
2343 atom2 = self.get_atom(atom2_name)
2344 atom3 = self.get_atom(atom3_name)
2345 atom4 = self.get_atom(atom4_name)
2346
2347 return AtomMath.calc_torsion_angle(atom1, atom2, atom3, atom4)
2348
2351
2354
2357
2360
2362 """Calculates CHI side-chain torsion angles according to the
2363 amino acid specific definitions in the AminoAcids library.
2364 Returns the 4-tuple (CHI1, CHI2, CHI3, CHI4). Angles involving
2365 missing atoms, or angles which do not exist for the amino acid
2366 are returned as None in the tuple.
2367 """
2368 return (self.calc_torsion("chi1"),
2369 self.calc_torsion("chi2"),
2370 self.calc_torsion("chi3"),
2371 self.calc_torsion("chi4"))
2372
2374 """Calculates the Pucker torsion of a ring system. Returns None
2375 for Amino Acids which do not have Pucker torsion angles.
2376 """
2377 return self.calc_torsion("pucker")
2378
2379
2381 """A subclass of Residue representing one nuclic acid in a strand of
2382 DNA or RNA.
2383 """
2385 fragment = NucleicAcidResidue(
2386 model_id = self.model_id,
2387 res_name = self.res_name,
2388 fragment_id = self.fragment_id,
2389 chain_id = self.chain_id)
2390
2391 for atom in self.iter_all_atoms():
2392 fragment.add_atom(copy.deepcopy(atom, memo))
2393
2394 return fragment
2395
2397 """Returns True if the Fragment/Residue object is one of the
2398 PDB defined standard residues. PDB standard residues are amino
2399 and nucleic acid residues.
2400 """
2401 return True
2402
2404 """Returns True if the Fragment is a Nucleic Acid residue.
2405 """
2406 return True
2407
2409 """Returns True if the Fragment is a water molecule, returns False
2410 otherwise.
2411 """
2412 return False
2413
2414
2416 """Container holding the same atom, but for different conformations and
2417 occupancies.
2418 """
2420 altloc = Altloc()
2421 for atom in self.itervalues():
2422 altloc.add_atom(copy.deepcopy(atom, memo))
2423 return altloc
2424
2426 """Iterates over all Altloc representations of this Atom.
2427 """
2428 alt_locs = self.keys()
2429 alt_locs.sort()
2430 for alt_loc in alt_locs:
2431 yield self[alt_loc]
2432
2434 """Adds an atom to the Altloc.
2435 """
2436 if self.has_key(atom.alt_loc) or atom.alt_loc == "":
2437 atom.alt_loc = self.calc_next_alt_loc_id(atom)
2438
2439 self[atom.alt_loc] = atom
2440 atom.altloc = self
2441
2443 """Removes the atom from this Altloc container.
2444 """
2445 assert atom.altloc == self
2446 del self[atom.alt_loc]
2447 atom.altloc = None
2448
2450 """Returns the next vacant alt_loc letter to be used for a key.
2451 This is part of a half-ass algorithm to deal with disordered
2452 input Atoms with improper alt_loc tagging.
2453 """
2454 if len(self) == 0:
2455 return "A"
2456 for alt_loc in string.uppercase:
2457 if not self.has_key(alt_loc):
2458 return alt_loc
2459
2460 raise AtomOverwrite("exhausted availible alt_loc labels for "+str(atom))
2461
2462
2463 -class Atom(object):
2464 """Class representing a single atom. Atoms have the following default
2465 attributes. If an attribute has the value None, then the attribute was
2466 never set. If the attribute has a default, then it is required.
2467
2468 Atom[alt_loc] - Atom objects in alternate locations can be accessed
2469 by using Python's dictionary syntax with the alt_loc
2470 character
2471 iter(Atom) - iterates over all alt_loc versions of the Atom
2472 Atom.name - label of the atom
2473 Atom.alt_loc - alternate location indicater for the atom
2474 Atom.res_name - the name of the resiude/fragment this atom is part of
2475 Atom.res_seq - the residue/fragment sequence number
2476 Atom.icode - the insertion code for the residue/fragment
2477 Atom.chain_id - the chain ID of the chain containing this atom
2478 Atom.element - symbol for the element
2479 Atom.position - a numpy.array[3] (Numeric Python)
2480 Atom.occupancy - [1.0 - 0.0] float
2481 Atom.temp_factor - float represting B-style temp factor
2482 Atom.column6768 - string value. Can be used for anything in columns 67+68
2483 Atom.U - a 6-tuple of the anisotropic values
2484 Atom.charge - charge on the atom
2485 Atom.label_entity_id -
2486 entity id corresponding to entity_poly_seq.entity_id
2487 Atom.label_asym_id -
2488 asym id corresponding to struct_conf.beg_label_asym_id
2489 Atom.label_seq_id -
2490 sequence id corresponding to entity_poly_seq_num
2491 and struct_conn.ptnr?_label_seq_id
2492 """
2493 - def __init__(
2494 self,
2495 name = "",
2496 alt_loc = "",
2497 res_name = "",
2498 fragment_id = "",
2499 chain_id = "",
2500 model_id = 1,
2501 element = "",
2502 position = None,
2503 x = None,
2504 y = None,
2505 z = None,
2506 sig_position = None,
2507 sig_x = None,
2508 sig_y = None,
2509 sig_z = None,
2510 temp_factor = None,
2511 column6768 = None,
2512 sig_temp_factor = None,
2513 occupancy = None,
2514 sig_occupancy = None,
2515 charge = None,
2516 label_entity_id = None,
2517 label_asym_id = None,
2518 label_seq_id = None,
2519
2520 U = None,
2521 u11 = None, u22 = None, u33 = None,
2522 u12 = None, u13 = None, u23 = None,
2523
2524 sig_U = None,
2525 sig_u11 = None, sig_u22 = None, sig_u33 = None,
2526 sig_u12 = None, sig_u13 = None, sig_u23 = None,
2527
2528 **args):
2529
2530 assert isinstance(name, str)
2531 assert isinstance(model_id, int)
2532 assert isinstance(alt_loc, str)
2533 assert isinstance(res_name, str)
2534 assert isinstance(fragment_id, str)
2535 assert isinstance(chain_id, str)
2536
2537 self.fragment = None
2538 self.altloc = None
2539
2540 self.name = name
2541 self.alt_loc = alt_loc
2542 self.res_name = res_name
2543 self.fragment_id = fragment_id
2544 self.chain_id = chain_id
2545 self.asym_id = chain_id
2546 self.model_id = model_id
2547 self.element = element
2548 self.temp_factor = temp_factor
2549 self.column6768 = column6768
2550 self.sig_temp_factor = sig_temp_factor
2551 self.occupancy = occupancy
2552 self.sig_occupancy = sig_occupancy
2553 self.charge = charge
2554 self.label_entity_id = label_entity_id
2555 self.label_asym_id = label_asym_id
2556 self.label_seq_id = label_seq_id
2557
2558
2559 if position is not None:
2560 self.position = position
2561 elif x is not None and y is not None and z is not None:
2562 self.position = numpy.array([x, y, z], float)
2563 else:
2564 self.position = None
2565
2566
2567 if sig_position is not None:
2568 self.sig_position = sig_position
2569 elif sig_x is not None and sig_y is not None and sig_z is not None:
2570 self.sig_position = numpy.array([sig_x, sig_y, sig_z], float)
2571 else:
2572 self.sig_position = None
2573
2574 if U is not None:
2575 self.U = U
2576 elif u11 is not None:
2577 self.U = numpy.array(
2578 [ [u11, u12, u13],
2579 [u12, u22, u23],
2580 [u13, u23, u33] ], float)
2581 else:
2582 self.U = None
2583
2584 if sig_U is not None:
2585 self.sig_U = sig_U
2586 elif sig_u11 is not None:
2587 self.sig_U = numpy.array(
2588 [ [sig_u11, sig_u12, sig_u13],
2589 [sig_u12, sig_u22, sig_u23],
2590 [sig_u13, sig_u23, sig_u33] ], float)
2591 else:
2592 self.sig_U = None
2593
2594 self.bond_list = []
2595
2597 return "Atom(n=%s alt=%s res=%s chn=%s frag=%s mdl=%d)" % (
2598 self.name, self.alt_loc, self.res_name,
2599 self.chain_id, self.fragment_id, self.model_id)
2600
2601 return "Atom(%4s%2s%4s%2s%4s%2d)" % (
2602 self.name, self.alt_loc, self.res_name,
2603 self.chain_id, self.fragment_id, self.model_id)
2604
2606 atom_cpy = Atom(
2607 name = self.name,
2608 alt_loc = self.alt_loc,
2609 res_name = self.res_name,
2610 fragment_id = self.fragment_id,
2611 chain_id = self.chain_id,
2612 model_id = copy.copy(self.model_id),
2613 element = self.element,
2614 position = copy.deepcopy(self.position),
2615 sig_position = copy.deepcopy(self.sig_position),
2616 temp_factor = copy.copy(self.temp_factor),
2617 column6768 = copy.copy(self.column6768),
2618 sig_temp_factor = copy.copy(self.sig_temp_factor),
2619 occupancy = copy.copy(self.occupancy),
2620 sig_occupancy = copy.copy(self.sig_occupancy),
2621 charge = copy.copy(self.charge),
2622 U = copy.deepcopy(self.U),
2623 sig_U = copy.deepcopy(self.sig_U),
2624 label_entity_id = self.label_entity_id,
2625 label_asym_id = self.label_asym_id,
2626 label_seq_id = self.label_seq_id)
2627
2628 for bond in self.bond_list:
2629 partner = bond.get_partner(self)
2630 if memo.has_key(id(partner)):
2631 partner_cpy = memo[id(partner)]
2632 bond_cpy = copy.deepcopy(bond, memo)
2633
2634 if bond.atom1 == self:
2635 bond_cpy.atom1 = atom_cpy
2636 bond_cpy.atom2 = partner_cpy
2637 else:
2638 bond_cpy.atom1 = partner_cpy
2639 bond_cpy.atom2 = atom_cpy
2640
2641 atom_cpy.bond_list.append(bond_cpy)
2642 partner_cpy.bond_list.append(bond_cpy)
2643
2644 return atom_cpy
2645
2647 assert isinstance(other, Atom)
2648
2649 if self.chain_id < other.chain_id:
2650 return True
2651 if self.chain_id > other.chain_id:
2652 return False
2653
2654 if fragment_id_lt(self.fragment_id, other.fragment_id):
2655 return True
2656 if fragment_id_gt(self.fragment_id, other.fragment_id):
2657 return False
2658
2659 if self.name < other.name:
2660 return True
2661 if self.name > other.name:
2662 return False
2663
2664 if self.alt_loc == "" and other.alt_loc != "":
2665 return False
2666 if self.alt_loc != "" and other.alt_loc == "":
2667 return True
2668
2669 return self.name < other.name
2670
2672 assert isinstance(other, Atom)
2673
2674 if self.chain_id < other.chain_id:
2675 return True
2676 if self.chain_id > other.chain_id:
2677 return False
2678
2679 if fragment_id_lt(self.fragment_id, other.fragment_id):
2680 return True
2681 if fragment_id_gt(self.fragment_id, other.fragment_id):
2682 return False
2683
2684 if self.name < other.name:
2685 return True
2686 if self.name > other.name:
2687 return False
2688
2689 if self.alt_loc == "" and other.alt_loc != "":
2690 return False
2691 if self.alt_loc != "" and other.alt_loc == "":
2692 return True
2693
2694 return self.name <= other.name
2695
2697 assert isinstance(other, Atom)
2698
2699 if self.chain_id > other.chain_id:
2700 return True
2701 if self.chain_id < other.chain_id:
2702 return False
2703
2704 if fragment_id_gt(self.fragment_id, other.fragment_id):
2705 return True
2706 if fragment_id_lt(self.fragment_id, other.fragment_id):
2707 return False
2708
2709 if self.name > other.name:
2710 return True
2711 if self.name < other.name:
2712 return False
2713
2714 if self.alt_loc == "" and other.alt_loc != "":
2715 return True
2716 if self.alt_loc != "" and other.alt_loc == "":
2717 return False
2718
2719 return self.name > other.name
2720
2722 assert isinstance(other, Atom)
2723
2724 if self.chain_id > other.chain_id:
2725 return True
2726 if self.chain_id < other.chain_id:
2727 return False
2728
2729 if fragment_id_gt(self.fragment_id, other.fragment_id):
2730 return True
2731 if fragment_id_lt(self.fragment_id, other.fragment_id):
2732 return False
2733
2734 if self.name > other.name:
2735 return True
2736 if self.name < other.name:
2737 return False
2738
2739 if self.alt_loc == "" and other.alt_loc != "":
2740 return True
2741 if self.alt_loc != "" and other.alt_loc == "":
2742 return False
2743
2744 return self.name >= other.name
2745
2747 """Returns the number of alternate conformations of this atom.
2748 """
2749 if self.altloc:
2750 return len(self.altloc)
2751 return 0
2752
2754 """This is an alternative to calling get_alt_loc, but a KeyError
2755 exception is raised if the alt_loc Atom is not found.
2756 """
2757 assert isinstance(alt_loc, str)
2758
2759 if self.altloc is None:
2760 if self.alt_loc == alt_loc:
2761 return self
2762 raise KeyError, alt_loc
2763
2764 else:
2765 return self.altloc[alt_loc]
2766
2768 """Iterates over all Altloc representations of this Atom.
2769 """
2770 if self.altloc is None:
2771 yield self
2772
2773 else:
2774 alt_locs = self.altloc.keys()
2775 alt_locs.sort()
2776 for alt_loc in alt_locs:
2777 yield self.altloc[alt_loc]
2778
2780 """Returns True if the argument matches an alternate conformation of
2781 the Atom. The argument can be an alt_loc label, or an Atom object.
2782 """
2783 if isinstance(atom_alt_loc, Atom):
2784 if self.altloc is None:
2785 return atom_alt_loc == self
2786 else:
2787 return self.altloc[atom_alt_loc.alt_loc] == atom_alt_loc
2788
2789 elif isinstance(atom_alt_loc, str):
2790 if self.altloc is None:
2791 return atom_alt_loc == self.alt_loc
2792 else:
2793 return self.altloc.__contains__(atom_alt_loc)
2794
2795 return False
2796
2798 """Removes the argument Atom from the Altloc.
2799 """
2800 try:
2801 self.fragment.remove_atom(atom)
2802 except AttributeError:
2803 if self.altloc is not None and self.altloc.has_key(atom.alt_loc):
2804 del self.altloc[atom.alt_loc]
2805
2807 """Returns the Atom object matching the alt_loc argument.
2808 """
2809 try:
2810 return self[alt_loc]
2811 except KeyError:
2812 return None
2813
2815 """Iterate over all alt_loc versions of this atom in the
2816 alphabetical order of the alt_loc labels, within the current model.
2817 """
2818 return iter(self)
2819
2820 - def create_bond(self,
2821 atom = None,
2822 bond_type = None,
2823 atom1_symop = None,
2824 atom2_symop = None,
2825 standard_res_bond = False):
2826
2827 """Creates a bond between this atom and the argumentatom. The
2828 argument bond_type is a string, atom1_symop and atom2_symop are
2829 symmetry operations to be applied to self and the argument atom
2830 before distance calculations, and standard_res_bond is a flag
2831 used to indicate this bond is a standard bond.
2832 """
2833 assert isinstance(atom, Atom)
2834 assert ((self.alt_loc == atom.alt_loc) or
2835 (self.alt_loc == "" and atom.alt_loc != "") or
2836 (self.alt_loc != "" and atom.alt_loc == ""))
2837
2838 bond = Bond(atom1 = self,
2839 atom2 = atom,
2840 bond_type = bond_type,
2841 atom1_symop = atom1_symop,
2842 atom2_symop = atom2_symop,
2843 standard_res_bond = standard_res_bond)
2844
2845 self.bond_list.append(bond)
2846 atom.bond_list.append(bond)
2847
2848 - def create_bonds(self,
2849 atom = None,
2850 bond_type = None,
2851 atom1_symop = None,
2852 atom2_symop = None,
2853 standard_res_bond = False):
2854 """Like create_bonds, but it bonds all alternate locations of this
2855 atom.
2856 """
2857 assert isinstance(atom, Atom)
2858
2859 if self.altloc is None:
2860 if atom.altloc is None:
2861
2862 self.create_bond(
2863 atom = atom,
2864 bond_type = bond_type,
2865 atom1_symop = atom1_symop,
2866 atom2_symop = atom2_symop,
2867 standard_res_bond = standard_res_bond)
2868 else:
2869
2870 for atmx in atom.altloc.itervalues():
2871 self.create_bond(
2872 atom = atmx,
2873 bond_type = bond_type,
2874 atom1_symop = atom1_symop,
2875 atom2_symop = atom2_symop,
2876 standard_res_bond = standard_res_bond)
2877
2878
2879 else:
2880 if atom.altloc is None:
2881
2882 for (alt_loc, atmx) in self.altloc.iteritems():
2883 atmx.create_bond(
2884 atom = atom,
2885 bond_type = bond_type,
2886 atom1_symop = atom1_symop,
2887 atom2_symop = atom2_symop,
2888 standard_res_bond = standard_res_bond)
2889
2890 else:
2891
2892 for (alt_loc, atmx) in self.altloc.iteritems():
2893 if atom.altloc.has_key(alt_loc):
2894 atmx.create_bond(
2895 atom = atom.altloc[alt_loc],
2896 bond_type = bond_type,
2897 atom1_symop = atom1_symop,
2898 atom2_symop = atom2_symop,
2899 standard_res_bond = standard_res_bond)
2900
2902 """Returns the Bond connecting self with the argument atom.
2903 """
2904 assert isinstance(atom, Atom)
2905 assert atom != self
2906
2907 for bond in self.bond_list:
2908 if atom == bond.atom1 or atom == bond.atom2:
2909 return bond
2910 return None
2911
2913 """Iterates over all the Bond edges connected to self.
2914 """
2915 for bond in self.bond_list:
2916 yield bond
2917
2919 """Iterates over all the Atoms bonded to self.
2920 """
2921 for bond in self.iter_bonds():
2922 partner = bond.get_partner(self)
2923 assert partner is not None
2924 yield partner
2925
2927 """From atom, follow the bonding path specified by a sequence of atom
2928 names given in name_list and return the last atom instance in the
2929 list. Returns None if any atom in the bonding path cannot be found.
2930 """
2931 current_atom = self
2932 for name in name_list:
2933 moveto_atom = None
2934 for atom in current_atom.iter_bonded_atoms():
2935 if atom.name == name:
2936 moveto_atom = atom
2937 break
2938 if moveto_atom is None:
2939 return None
2940 current_atom = moveto_atom
2941 return current_atom
2942
2944 """Returns the parent Fragment object.
2945 """
2946 return self.fragment
2947
2949 """Returns the parent Chain object.
2950 """
2951 return self.fragment.chain
2952
2954 """Returns the parent Model object.
2955 """
2956 return self.fragment.chain.model
2957
2959 """Returns the parent Structure object.
2960 """
2961 return self.fragment.chain.model.structure
2962
2963 - def set_U(self, u11, u22, u33, u12, u13, u23):
2964 """Sets the symmetric U tensor from the six unique values.
2965 """
2966 self.U = numpy.array([[u11, u12, u13],
2967 [u12, u22, u23],
2968 [u13, u23, u33]], float)
2969
2970 - def set_sig_U(self, u11, u22, u33, u12, u13, u23):
2971 """Sets the symmetric sig_U tensor from the six unique values.
2972 """
2973 self.sig_U = numpy.array([[u11, u12, u13],
2974 [u12, u22, u23],
2975 [u13, u23, u33]], float)
2976
2978 """Calculates the Uiso tensor from the Atom's temperature factor.
2979 """
2980 if self.temp_factor is None:
2981 return None
2982 return numpy.identity(3, float) * (self.temp_factor * Constants.B2U)
2983
2985 """Returns the Atoms's U tensor if it exists, otherwise returns
2986 the isotropic U tensor calculated by self.calc_Uiso
2987 """
2988 if self.U is not None:
2989 return self.U
2990 return self.calc_Uiso()
2991
2993 """Calculates the anisotropy of that atom. Anisotropy is defined
2994 as the ratio of the minimum/maximum eigenvalues of the 3x3
2995 symmetric tensor defined by U.
2996 """
2997
2998 if self.U is None:
2999 return 1.0
3000
3001 evals = linalg.eigenvalues(self.U)
3002 ansotropy = min(evals) / max(evals)
3003 return ansotropy
3004
3006 """Calculates the eigenvalues of the U matrix and returns the
3007 3-tuple of the eigenvalue ratios: (e1/e2, e1/e3, e2/e3)
3008 """
3009
3010 if self.U is None:
3011 return (1.0, 1.0, 1.0)
3012
3013 e1, e2, e3 = linalg.eigenvalues(self.U)
3014 elist = [e1, e2, e3]
3015 elist.sort()
3016 e1, e2, e3 = elist
3017
3018 return (min(e1, e2) / max(e1, e2),
3019 min(e1, e3) / max(e1, e3),
3020 min(e2, e3) / max(e2, e3))
3021
3040
3042 """Sets the chain_id of the Atom and all alt_loc Atom
3043 objects.
3044 """
3045 assert isinstance(model_id, int)
3046 for atm in self.iter_alt_loc():
3047 atm.model_id = model_id
3048
3050 """Sets the chain_id of the Atom and all alt_loc Atom
3051 objects.
3052 """
3053 assert isinstance(chain_id, str)
3054 for atm in self.iter_alt_loc():
3055 atm.chain_id = chain_id
3056
3058 """Sets the fragment_id of the Atom and all alt_loc Atom
3059 objects.
3060 """
3061 assert isinstance(fragment_id, str)
3062 for atm in self.iter_alt_loc():
3063 atm.fragment_id = fragment_id
3064
3066 """Sets the fragment_id of the Atom and all alt_loc Atom
3067 objects.
3068 """
3069 assert isinstance(res_name, str)
3070 for atm in self.iter_alt_loc():
3071 atm.res_name = res_name
3072
3073
3074 -class Bond(object):
3075 """Indicates two atoms are bonded together.
3076 """
3077 - def __init__(
3078 self,
3079 atom1 = None,
3080 atom2 = None,
3081 bond_type = None,
3082 atom1_symop = None,
3083 atom2_symop = None,
3084 standard_res_bond = False,
3085 **args):
3086
3087 self.atom1 = atom1
3088 self.atom2 = atom2
3089 self.bond_type = bond_type
3090 self.atom1_symop = atom1_symop
3091 self.atom2_symop = atom2_symop
3092 self.standard_res_bond = standard_res_bond
3093
3095 return "Bond(%s %s)" % (self.atom1, self.atom2)
3096
3098 return Bond(
3099 bond_type = self.bond_type,
3100 atom1_symop = self.atom1_symop,
3101 atom2_symop = self.atom2_symop,
3102 standard_res_bond = self.standard_res_bond)
3103
3105 """Returns the other atom involved in the bond.
3106 """
3107 if atm == self.atom1:
3108 return self.atom2
3109 elif atm == self.atom2:
3110 return self.atom1
3111 return None
3112
3114 """Returns atom #1 of the pair of bonded atoms. This is also
3115 accessible by bond.atom1.
3116 """
3117 return self.atom1
3118
3120 """Returns atom #2 of the pair of bonded atoms.
3121 """
3122 return self.atom2
3123
3125 """Returns the Fragment object of atom #1.
3126 """
3127 return self.atom1.fragment
3128
3130 """Returns the Fragment object of atom #2.
3131 """
3132 return self.atom2.fragment
3133
3135 """Returns the Chain object of atom #1.
3136 """
3137 return self.atom1.fragment.chain
3138
3140 """Returns the Chain object of atom #2.
3141 """
3142 return self.atom2.fragment.chain
3143
3145 """Returns the Model object of atom #1.
3146 """
3147 return self.atom1.fragment.chain.model
3148
3150 """Returns the Structure object of atom #2.
3151 """
3152 return self.atom2.fragment.chain.model
3153
3155 """Returns the Structure object of atom #1.
3156 """
3157 return self.atom1.fragment.chain.model.structure
3158
3160 """Returns the Structure object of atom #2.
3161 """
3162 return self.atom2.fragment.chain.model.structure
3163
3165 """Returns the length of the bond.
3166 """
3167 return AtomMath.length(self.atom1.position - self.atom2.position)
3168
3169
3171 """Class containing information on a protein alpha helix.
3172 """
3173 - def __init__(self,
3174 helix_id = "",
3175 helix_class = "1",
3176 helix_length = 0,
3177 chain_id1 = "",
3178 frag_id1 = "",
3179 res_name1 = "",
3180 chain_id2 = "",
3181 frag_id2 = "",
3182 res_name2 = "",
3183 details = "",
3184 **args):
3185
3186 assert isinstance(helix_id, str)
3187 assert isinstance(helix_class, str)
3188 assert isinstance(helix_length, int)
3189 assert isinstance(details, str)
3190 assert isinstance(chain_id1, str)
3191 assert isinstance(frag_id1, str)
3192 assert isinstance(res_name1, str)
3193 assert isinstance(chain_id2, str)
3194 assert isinstance(frag_id2, str)
3195 assert isinstance(res_name2, str)
3196 assert isinstance(details, str)
3197
3198 self.model = None
3199
3200 self.helix_id = helix_id
3201 self.helix_class = helix_class
3202 self.helix_length = helix_length
3203 self.chain_id1 = chain_id1
3204 self.fragment_id1 = frag_id1
3205 self.res_name1 = res_name1
3206 self.chain_id2 = chain_id2
3207 self.fragment_id2 = frag_id2
3208 self.res_name2 = res_name2
3209 self.details = details
3210
3211 self.segment = None
3212
3214 return "AlphaHelix(%s %s %s:%s...%s:%s)" % (
3215 self.helix_id, self.helix_class,
3216 self.chain_id1,
3217 self.fragment_id1,
3218 self.chain_id2,
3219 self.fragment_id2)
3220
3222 """Adds the Segment object this AlphaHelix spans. If the AlphaHelix
3223 already has a Segment, then it is replaced. The Segment objects added
3224 to AlphaHelix objects must have the attribute segment.chain referencing
3225 the source Chain object the Segment was sliced from.
3226 """
3227 assert segment is None or isinstance(segment, Segment)
3228 self.segment = segment
3229
3230
3231 if segment is None:
3232 return
3233
3234
3235
3236 try:
3237 frag1 = segment[0]
3238 frag2 = segment[-1]
3239 except IndexError:
3240 return
3241
3242 self.chain_id1 = frag1.chain_id
3243 self.fragment_id1 = frag1.fragment_id
3244 self.res_name1 = frag1.res_name
3245
3246 self.chain_id2 = frag2.chain_id
3247 self.fragment_id2 = frag2.fragment_id
3248 self.res_name2 = frag2.res_name
3249
3250 self.helix_length = len(segment)
3251
3253 """Constructs the child Segment object from the Chain object found in
3254 the parent Structure object by the AlphaHelix chain_id/fragment_id
3255 information. Returns True if the Segment was created, or False if
3256 it was not. The Segment is not created when the fragment range
3257 fragment_id1:fragment_id2 cannot be found in the parent Chain object.
3258 """
3259 if self.chain_id1 != self.chain_id2:
3260 ConsoleOutput.fatal("alpha helix spans multiple chains -- not supported")
3261
3262
3263 try:
3264 chain = self.model[self.chain_id1]
3265 except KeyError:
3266 self.add_segment(None)
3267 return False
3268
3269
3270
3271 try:
3272 segment = chain[self.fragment_id1:self.fragment_id2]
3273 segment.chain = chain
3274 except KeyError:
3275 self.add_segment(None)
3276 return False
3277
3278 self.add_segment(segment)
3279 return True
3280
3282 """Returns the parent Chain object. If the AlphaHelix does not have
3283 a Segment child the raised AttributeError.
3284 """
3285 return self.segment.chain
3286
3288 """Returns the parent Model object.
3289 """
3290 return self.model
3291
3293 """Returns the parent Structure object.
3294 """
3295 return self.model.structure
3296
3298 """Return the child Segment object this AlphaHelix spans in the
3299 parent Model.
3300 """
3301 return self.segment
3302
3304 """Iterates all Fragment objects in the AlphaHelix.
3305 """
3306 if self.segment is None:
3307 return iter(list())
3308 return self.segment.iter_fragments()
3309
3311 """Iterates all Atom objects in the AlphaHelix.
3312 """
3313 if self.segment is None:
3314 return iter(list())
3315 return self.segment.iter_atoms()
3316
3318 """Iterates all Atom objects in all AlphaHelix, plus any in
3319 non-default alt_loc conformations.
3320 """
3321 if self.segment is None:
3322 return iter(list())
3323 return self.segment.iter_all_atoms()
3324
3325
3327 """One strand of a BetaSheet.
3328 """
3329 - def __init__(self,
3330 chain_id1 = "",
3331 frag_id1 = "",
3332 res_name1 = "",
3333 chain_id2 = "",
3334 frag_id2 = "",
3335 res_name2 = "",
3336 reg_chain_id = "",
3337 reg_frag_id = "",
3338 reg_res_name = "",
3339 reg_atom = "",
3340 reg_prev_chain_id = "",
3341 reg_prev_frag_id = "",
3342 reg_prev_res_name = "",
3343 reg_prev_atom = "",
3344 **args):
3345
3346 assert isinstance(chain_id1, str)
3347 assert isinstance(frag_id1, str)
3348 assert isinstance(res_name1, str)
3349 assert isinstance(chain_id2, str)
3350 assert isinstance(frag_id2, str)
3351 assert isinstance(res_name2, str)
3352 assert isinstance(reg_chain_id, str)
3353 assert isinstance(reg_frag_id, str)
3354 assert isinstance(reg_res_name, str)
3355 assert isinstance(reg_atom, str)
3356 assert isinstance(reg_prev_chain_id, str)
3357 assert isinstance(reg_prev_frag_id, str)
3358 assert isinstance(reg_prev_res_name, str)
3359 assert isinstance(reg_prev_atom, str)
3360
3361 self.beta_sheet = None
3362
3363 self.chain_id1 = chain_id1
3364 self.fragment_id1 = frag_id1
3365 self.res_name1 = res_name1
3366 self.chain_id2 = chain_id2
3367 self.fragment_id2 = frag_id2
3368 self.res_name2 = res_name2
3369 self.reg_chain_id = reg_chain_id
3370 self.reg_fragment_id = reg_frag_id
3371 self.reg_res_name = reg_res_name
3372 self.reg_atom = reg_atom
3373 self.reg_prev_chain_id = reg_prev_chain_id
3374 self.reg_prev_fragment_id = reg_prev_frag_id
3375 self.reg_prev_res_name = reg_prev_res_name
3376 self.reg_prev_atom = reg_prev_atom
3377
3378 self.segment = None
3379
3381 return "Strand(%s:%s-%s:%s %s:%s:%s-%s:%s:%s)" % (
3382 self.chain_id1, self.fragment_id1,
3383 self.chain_id2, self.fragment_id2,
3384 self.reg_chain_id, self.reg_fragment_id, self.reg_atom,
3385 self.reg_prev_chain_id, self.reg_prev_fragment_id,
3386 self.reg_prev_atom)
3387
3389 """Adds the Segment object this Strand spans. If the Strand
3390 already has a Segment, then it is replaced. The Segment objects added
3391 to Strand objects must have the attribute segment.chain referencing
3392 the source Chain object the Segment was sliced from.
3393 """
3394 assert segment is None or isinstance(segment, Segment)
3395
3396 self.segment = segment
3397 if segment is None:
3398 return
3399
3400
3401
3402 try:
3403 frag1 = segment[0]
3404 frag2 = segment[-1]
3405 except IndexError:
3406 return
3407
3408 self.chain_id1 = frag1.chain_id
3409 self.fragment_id1 = frag1.fragment_id
3410 self.res_name1 = frag1.res_name
3411
3412 self.chain_id2 = frag2.chain_id
3413 self.fragment_id2 = frag2.fragment_id
3414 self.res_name2 = frag2.res_name
3415
3417 """Constructs the child Segment object from the Chain object found in
3418 the parent Structure object by the BetaSheet chain_id/fragment_id
3419 information. Returns True if the Segment was created, or False if
3420 it was not. The Segment is not created when the fragment range
3421 fragment_id1:fragment_id2 cannot be found in the parent Chain object.
3422 """
3423 assert self.chain_id1 == self.chain_id2
3424
3425
3426 try:
3427 chain = self.beta_sheet.model[self.chain_id1]
3428 except KeyError:
3429 self.add_segment(None)
3430 return False
3431
3432
3433
3434 try:
3435 segment = chain[self.fragment_id1:self.fragment_id2]
3436 segment.chain = chain
3437 except KeyError:
3438 self.add_segment(None)
3439 return False
3440
3441 self.add_segment(segment)
3442 return True
3443
3445 """Returns the parent BetaSheet object.
3446 """
3447 return self.beta_sheet
3448
3450 """Returns the parent Chain object. If the Strand does not have
3451 a Segment child the raised AttributeError.
3452 """
3453 return self.segment.chain
3454
3456 """Returns the parent Model object.
3457 """
3458 return self.beta_sheet.model
3459
3461 """Returns the parent Structure object.
3462 """
3463 return self.beta_sheet.model.structure
3464
3466 """Return the child Segment object this AlphaHelix spans in the
3467 parent Model.
3468 """
3469 return self.segment
3470
3472 """Iterates all Fragment objects.
3473 """
3474 if self.segment is None:
3475 return iter(list())
3476 return self.segment.iter_fragments()
3477
3479 """Iterates all Atom objects.
3480 """
3481 if self.segment is None:
3482 return iter(list())
3483 return self.segment.iter_atoms()
3484
3486 """Iterates all Atom objects plus any in non-default alt_loc
3487 conformations.
3488 """
3489 if self.segment is None:
3490 return iter(list())
3491 return self.segment.iter_all_atoms()
3492
3493
3495 """Class containing information on a protein beta sheet. BetaSheet
3496 objects contain a list of Segments spanning the beta sheet.
3497 """
3498 - def __init__(self,
3499 sheet_id = "",
3500 **args):
3501
3502 assert isinstance(sheet_id, str)
3503
3504 self.model = None
3505
3506 self.sheet_id = sheet_id
3507 self.strand_list = []
3508
3510 return "BetaSheet(%s %d)" % (self.sheet_id, len(self.strand_list))
3511
3513 """Adds a Segment instance.
3514 """
3515 assert isinstance(strand, Strand)
3516 assert strand not in self.strand_list
3517 self.strand_list.append(strand)
3518 strand.beta_sheet = self
3519
3521 """Calls Strand.construct_segment() on all child Strand objects.
3522 """
3523 for strand in self.strand_list:
3524 strand.construct_segment()
3525
3527 """REturns the parent Model object.
3528 """
3529 return self.model
3530
3532 """Returns the parent Structure object.
3533 """
3534 return self.model.structure
3535
3537 """Iterates over all child Strands objects.
3538 """
3539 return iter(self.strand_list)
3540
3542 """Iterates over all Fragment objects.
3543 """
3544 for strand in self.strand_list:
3545 for frag in strand.iter_fragments():
3546 yield frag
3547
3549 """Iterates all Atom objects.
3550 """
3551 for strand in self.strand_list:
3552 for atm in strand.iter_atoms():
3553 yield atm
3554
3556 """Iterates all Atom objects plus any in non-default alt_loc
3557 conformations.
3558 """
3559 for strand in self.strand_list:
3560 for atm in strand.iter_all_atoms():
3561 yield atm
3562
3563
3564 -class Site(object):
3565 """List of Fragments within a structure involved in a SITE description.
3566 """
3567 - def __init__(self,
3568 site_id = "",
3569 fragment_list = [],
3570 **args):
3571
3572 assert isinstance(site_id, str)
3573 assert isinstance(fragment_list, list)
3574
3575 self.model = None
3576 self.site_id = site_id
3577 self.fragment_dict_list = fragment_list
3578
3580 return "Site(id=%s)" % (self.site_id)
3581
3583 """Adds a Fragment object to the fragment_dict and updates the
3584 values in fragment_dict to reflect the new Fragment object. The
3585 fragment_dict is added to the Site if it is not already in it.
3586 """
3587 if fragment is not None:
3588 fragment_dict["fragment"] = fragment
3589 fragment_dict["chain_id"] = fragment.chain_id
3590 fragment_dict["frag_id"] = fragment.fragment_id
3591 fragment_dict["res_name"] = fragment.res_name
3592
3593 if fragment_dict not in self.fragment_dict_list:
3594 self.fragment_dict_list.append(fragment_dict)
3595
3596 else:
3597 if fragment_dict.has_key("fragment"):
3598 del fragment_dict["fragment"]
3599
3601 """Using the site fragment descriptions, finds the Fragment objects
3602 in the parent Model.
3603 """
3604 for frag_dict in self.fragment_dict_list:
3605 try:
3606 chain = self.model[frag_dict["chain_id"]]
3607 frag = chain[frag_dict["frag_id"]]
3608 except KeyError:
3609 self.add_fragment(frag_dict, None)
3610 continue
3611
3612 self.add_fragment(frag_dict, frag)
3613
3615 """Returns the parent Model object.
3616 """
3617 return self.model
3618
3620 """Returns the parent Structure object.
3621 """
3622 return self.model.structure
3623
3625 """Iterates child Fragment objects.
3626 """
3627 for frag_dict in self.fragment_dict_list:
3628 try:
3629 yield frag_dict["fragment"]
3630 except KeyError:
3631 pass
3632
3634 """Iterates all Atom objects.
3635 """
3636 for frag in self.iter_fragments():
3637 for atm in frag.iter_atoms():
3638 yield atm
3639
3641 """Iterates all Atom objects plus any in non-default alt_loc
3642 conformations.
3643 """
3644 for frag in self.iter_fragments():
3645 for atm in frag.iter_all_atoms():
3646 yield atm
3647
3649 """Split a string fragment_id into a 2-tuple of:
3650 (sequence_num, insertion_code)
3651 """
3652 try:
3653 return (int(frag_id), None)
3654 except ValueError:
3655 return (int(frag_id[:-1]), frag_id[-1:])
3656
3658 """Performs a proper equivalency of fragment_id strings according
3659 to their sequence number, then insertion code.
3660 """
3661 return frag_id1 == frag_id2
3662
3664 """Performs a proper less than comparison of fragment_id strings
3665 according to their sequence number, then insertion code.
3666 """
3667 return fragment_id_split(frag_id1) < fragment_id_split(frag_id2)
3668
3670 """Performs a proper less than or equal to comparison of fragment_id
3671 strings according to their sequence number, then insertion code.
3672 """
3673 return fragment_id_split(frag_id1) <= fragment_id_split(frag_id2)
3674
3676 """Performs a proper greater than comparison of fragment_id strings
3677 according to their sequence number, then insertion code.
3678 """
3679 return fragment_id_split(frag_id1) > fragment_id_split(frag_id2)
3680
3682 """Performs a proper greater than or equal to comparison of
3683 fragment_id strings according to their sequence number, then
3684 insertion code.
3685 """
3686 return fragment_id_split(frag_id1) >= fragment_id_split(frag_id2)
3687
3689 """Compare two fragment ids.
3690 """
3691 if fragment_id_lt(frag_id1, frag_id2):
3692 return -1
3693 if fragment_id_lt(frag_id1, frag_id2):
3694 return 0
3695 return 1
3696
3697 -def iter_fragments(fragiter, start_frag_id = None, stop_frag_id = None):
3698 """Given a fragment iterator and a start and end fragment id,
3699 return an iterator which yields only fragments within the range.
3700 """
3701 if start_frag_id and stop_frag_id:
3702 dpred = lambda f: fragment_id_lt(f.fragment_id, start_frag_id)
3703 tpred = lambda f: fragment_id_le(f.fragment_id, stop_frag_id)
3704 return itertools.takewhile(tpred, itertools.dropwhile(dpred, fragiter))
3705 elif start_frag_id and not stop_frag_id:
3706 dpred = lambda f: fragment_id_lt(f.fragment_id, start_frag_id)
3707 return itertools.dropwhile(dpred, fragiter)
3708 elif not start_frag_id and stop_frag_id:
3709 tpred = lambda f: fragment_id_le(f.fragment_id, stop_frag_id)
3710 return itertools.takewhile(tpred, fragiter)
3711 return fragiter
3712
3714 """Stores a fragment_id as integer residue sequence number and a
3715 single-character insertion code.
3716 """
3718 self.res_seq = 1
3719 self.icode = ""
3720 try:
3721 self.res_seq = int(frag_id)
3722 except ValueError:
3723 try:
3724 self.res_seq = int(frag_id[:-1])
3725 except ValueError:
3726 pass
3727 else:
3728 self.icode = frag_id[-1]
3730 return "%d%s" % (self.res_seq, self.icode)
3732 assert isinstance(other, FragmentID)
3733 return (self.res_seq, self.icode) < (other.res_seq, other.icode)
3735 assert isinstance(other, FragmentID)
3736 return (self.res_seq, self.icode) <= (other.res_seq, other.icode)
3738 assert isinstance(other, FragmentID)
3739 return (self.res_seq, self.icode) == (other.res_seq, other.icode)
3741 assert isinstance(other, FragmentID)
3742 return (self.res_seq, self.icode) != (other.res_seq, other.icode)
3744 assert isinstance(other, FragmentID)
3745 return (self.res_seq, self.icode) > (other.res_seq, other.icode)
3747 assert isinstance(other, FragmentID)
3748 return (self.res_seq, self.icode) >= (other.res_seq, other.icode)
3749
3750
3752 """Provides the functionality of a Python list class for containing
3753 Atom instances. It also provides class methods for performing some
3754 useful calculations on the list of atoms.
3755 """
3757 """Calculates the centroid of all contained Atom instances and
3758 returns a Vector to the centroid.
3759 """
3760 num = 0
3761 centroid = numpy.zeros(3, float)
3762 for atm in self:
3763 if atm.position is not None:
3764 centroid += atm.position
3765 num += 1
3766 return centroid / num
3767
3769 """Calculates the average temperature factor of all contained Atom
3770 instances and returns the average temperature factor.
3771 """
3772 num_tf = 0
3773 adv_tf = 0.0
3774
3775 for atm in self:
3776 if atm.temp_factor is not None:
3777 adv_tf += atm.temp_factor
3778 num_tf += 1
3779
3780 return adv_tf / num_tf
3781
3783 """Calculates the average U matrix of all contained Atom instances and
3784 returns the 3x3 symmetric U matrix of that average.
3785 """
3786 num_U = 0
3787 adv_U = numpy.zeros((3,3), float)
3788
3789 for atm in self:
3790
3791
3792
3793 if atm.U is not None:
3794 adv_U += atm.U
3795 num_U += 1
3796
3797 return adv_U / num_U
3798
3800 """Calculates the average anisotropy for all Atoms in the AtomList.
3801 """
3802 num_atoms = 0
3803 adv_aniso = 0.0
3804
3805 for atm in self:
3806 try:
3807 adv_aniso += atm.calc_anisotropy()
3808 except ZeroDivisionError:
3809 pass
3810 else:
3811 num_atoms += 1
3812
3813 return adv_aniso / num_atoms
3814
3816 """Calculates the average anisotropy 3-tuple for all Atoms in the
3817 AtomList.
3818 """
3819 num_atoms = 0
3820 adv_aniso1 = 0.0
3821 adv_aniso2 = 0.0
3822 adv_aniso3 = 0.0
3823
3824 for atm in self:
3825 try:
3826 a1, a2, a3 = atm.calc_anisotropy3()
3827 except ZeroDivisionError:
3828 pass
3829 else:
3830 adv_aniso1 += a1
3831 adv_aniso2 += a2
3832 adv_aniso3 += a3
3833 num_atoms += 1
3834
3835 return (adv_aniso1 / num_atoms,
3836 adv_aniso2 / num_atoms,
3837 adv_aniso3 / num_atoms)
3838
3839
3840
3842 struct = Structure()
3843
3844 for mx in xrange(1, 4):
3845 mid = str(mx)
3846 for cid in ["A", "B", "C", "D"]:
3847 for fx in xrange(1, 4):
3848 fid = str(fx)
3849
3850 for name in ["N", "CA", "C", "O"]:
3851
3852 for alt_loc in ["A", "B", "C"]:
3853
3854 if alt_loc == "C" and name == "CA": continue
3855
3856 atm = Atom(
3857 name = name,
3858 alt_loc = alt_loc,
3859 model = mid,
3860 chain_id = cid,
3861 res_name = "GLY",
3862 fragment_id = fid)
3863
3864 struct.add_atom(atm)
3865
3866 for cx in struct.iter_chains():
3867 print "iter_chains: ",cx
3868 for fx in struct.iter_fragments():
3869 print "iter_fragments: ",fx
3870 for ax in fx.iter_all_atoms():
3871 print "iter_all_atoms: ",ax
3872
3873 for ax in struct.iter_atoms():
3874 print "iter_atoms: ",ax
3875
3876 struct.set_default_alt_loc("C")
3877 for ax in struct.iter_atoms():
3878 print "iter_atoms: ",ax
3879
3880
3881
3882 chk_atm = Atom(
3883 name = "CX",
3884 alt_loc = "B",
3885 model = "1",
3886 chain_id = "A",
3887 res_name = "GLY",
3888 fragment_id = "1")
3889
3890 for a in struct.iter_atoms():
3891 print "WARNING! Bad atom name: ", a
3892
3893 if __name__ == "__main__":
3894 test_module()
3895
3896