stcrpy 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. examples/__init__.py +0 -0
  2. examples/egnn.py +425 -0
  3. stcrpy/__init__.py +5 -0
  4. stcrpy/tcr_datasets/__init__.py +0 -0
  5. stcrpy/tcr_datasets/tcr_graph_dataset.py +499 -0
  6. stcrpy/tcr_datasets/tcr_selector.py +0 -0
  7. stcrpy/tcr_datasets/tcr_structure_dataset.py +0 -0
  8. stcrpy/tcr_datasets/utils.py +350 -0
  9. stcrpy/tcr_formats/__init__.py +0 -0
  10. stcrpy/tcr_formats/tcr_formats.py +114 -0
  11. stcrpy/tcr_formats/tcr_haddock.py +556 -0
  12. stcrpy/tcr_geometry/TCRCoM.py +350 -0
  13. stcrpy/tcr_geometry/TCRCoM_LICENCE +168 -0
  14. stcrpy/tcr_geometry/TCRDock.py +261 -0
  15. stcrpy/tcr_geometry/TCRGeom.py +450 -0
  16. stcrpy/tcr_geometry/TCRGeomFiltering.py +273 -0
  17. stcrpy/tcr_geometry/__init__.py +0 -0
  18. stcrpy/tcr_geometry/reference_data/__init__.py +0 -0
  19. stcrpy/tcr_geometry/reference_data/dock_reference_1_imgt_numbered.pdb +6549 -0
  20. stcrpy/tcr_geometry/reference_data/dock_reference_2_imgt_numbered.pdb +6495 -0
  21. stcrpy/tcr_geometry/reference_data/reference_A.pdb +31 -0
  22. stcrpy/tcr_geometry/reference_data/reference_B.pdb +31 -0
  23. stcrpy/tcr_geometry/reference_data/reference_D.pdb +31 -0
  24. stcrpy/tcr_geometry/reference_data/reference_G.pdb +31 -0
  25. stcrpy/tcr_geometry/reference_data/reference_data.py +104 -0
  26. stcrpy/tcr_interactions/PLIPParser.py +147 -0
  27. stcrpy/tcr_interactions/TCRInteractionProfiler.py +433 -0
  28. stcrpy/tcr_interactions/TCRpMHC_PLIP_Model_Parser.py +133 -0
  29. stcrpy/tcr_interactions/__init__.py +0 -0
  30. stcrpy/tcr_interactions/utils.py +170 -0
  31. stcrpy/tcr_methods/__init__.py +0 -0
  32. stcrpy/tcr_methods/tcr_batch_operations.py +223 -0
  33. stcrpy/tcr_methods/tcr_methods.py +150 -0
  34. stcrpy/tcr_methods/tcr_reformatting.py +18 -0
  35. stcrpy/tcr_metrics/__init__.py +2 -0
  36. stcrpy/tcr_metrics/constants.py +39 -0
  37. stcrpy/tcr_metrics/tcr_interface_rmsd.py +237 -0
  38. stcrpy/tcr_metrics/tcr_rmsd.py +179 -0
  39. stcrpy/tcr_ml/__init__.py +0 -0
  40. stcrpy/tcr_ml/geometry_predictor.py +3 -0
  41. stcrpy/tcr_processing/AGchain.py +89 -0
  42. stcrpy/tcr_processing/Chemical_components.py +48915 -0
  43. stcrpy/tcr_processing/Entity.py +301 -0
  44. stcrpy/tcr_processing/Fragment.py +58 -0
  45. stcrpy/tcr_processing/Holder.py +24 -0
  46. stcrpy/tcr_processing/MHC.py +449 -0
  47. stcrpy/tcr_processing/MHCchain.py +149 -0
  48. stcrpy/tcr_processing/Model.py +37 -0
  49. stcrpy/tcr_processing/Select.py +145 -0
  50. stcrpy/tcr_processing/TCR.py +532 -0
  51. stcrpy/tcr_processing/TCRIO.py +47 -0
  52. stcrpy/tcr_processing/TCRParser.py +1230 -0
  53. stcrpy/tcr_processing/TCRStructure.py +148 -0
  54. stcrpy/tcr_processing/TCRchain.py +160 -0
  55. stcrpy/tcr_processing/__init__.py +3 -0
  56. stcrpy/tcr_processing/annotate.py +480 -0
  57. stcrpy/tcr_processing/utils/__init__.py +0 -0
  58. stcrpy/tcr_processing/utils/common.py +67 -0
  59. stcrpy/tcr_processing/utils/constants.py +367 -0
  60. stcrpy/tcr_processing/utils/region_definitions.py +782 -0
  61. stcrpy/utils/__init__.py +0 -0
  62. stcrpy/utils/error_stream.py +12 -0
  63. stcrpy-1.0.0.dist-info/METADATA +173 -0
  64. stcrpy-1.0.0.dist-info/RECORD +68 -0
  65. stcrpy-1.0.0.dist-info/WHEEL +5 -0
  66. stcrpy-1.0.0.dist-info/licenses/LICENCE +28 -0
  67. stcrpy-1.0.0.dist-info/licenses/stcrpy/tcr_geometry/TCRCoM_LICENCE +168 -0
  68. stcrpy-1.0.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,449 @@
1
+ """
2
+ Created on 30 Apr 2016
3
+
4
+ @author: leem, based on work by dunbar
5
+
6
+ The MHC class. This is similar to the Fab class.
7
+
8
+ """
9
+
10
+ from .Entity import Entity
11
+
12
+
13
+ class MHC(Entity):
14
+ """
15
+ MHC class.
16
+ Holds paired MHC domains.
17
+ """
18
+
19
+ def __init__(self, c1, c2):
20
+ if hasattr(c1, "chain_type"):
21
+ Entity.__init__(self, c1.id + c2.id)
22
+ else:
23
+ Entity.__init__(self, c2.id + c1.id)
24
+
25
+ self.level = "H"
26
+ self._add_domain(c1)
27
+ self._add_domain(c2)
28
+ self._set_MHC_type()
29
+ self.child_list = sorted(self.child_list, key=lambda x: x.id)
30
+ self.antigen = []
31
+ self.tcr = []
32
+ self.engineered = False
33
+
34
+ def _add_antigen(self, antigen=None):
35
+ if antigen not in self.antigen:
36
+ self.antigen.append(antigen)
37
+
38
+ def _add_tcr(self, tcr=None):
39
+ self.tcr.append(tcr)
40
+
41
+ def get_TCR(self):
42
+ return self.tcr
43
+
44
+ def get_antigen(self):
45
+ """
46
+ Return a list of bound antigens.
47
+ If the antigen has more than one chain, those in contact with the antibody will be returned.
48
+ """
49
+ return self.antigen
50
+
51
+ def is_bound(self):
52
+ """
53
+ Check whether there is an antigen bound to the antibody fab
54
+ """
55
+ if self.get_antigen():
56
+ return True
57
+ else:
58
+ return False
59
+
60
+ def get_chains(self):
61
+ for c in self:
62
+ yield c
63
+
64
+ def get_residues(self):
65
+ for c in self.get_chains():
66
+ for r in c:
67
+ yield r
68
+
69
+ def get_atoms(self):
70
+ for r in self.get_residues():
71
+ for a in r:
72
+ yield a
73
+
74
+ def get_MHC_type(self):
75
+ if hasattr(self, "MHC_type"):
76
+ return self.MHC_type
77
+
78
+ def get_allele_assignments(self):
79
+ return {c.id: c.get_allele_assignments() for c in self.get_chains()}
80
+
81
+
82
+ class MH1(MHC):
83
+ """
84
+ Type 1 MHC class.
85
+ Holds paired MHC domains.
86
+ """
87
+
88
+ def __repr__(self):
89
+ if self.MHC_type == "MH1":
90
+ return "<%s %s%s GA1/GA2=%s; B2M=%s>" % (
91
+ self.MHC_type,
92
+ self.MH1,
93
+ self.B2M,
94
+ self.MH1,
95
+ self.B2M,
96
+ )
97
+ else:
98
+ return "<GA1/GA2 %s%s GA1=%s; GA2=%s>" % (
99
+ self.GA1,
100
+ self.GA2,
101
+ self.GA1,
102
+ self.GA2,
103
+ )
104
+
105
+ def _set_MHC_type(self):
106
+ if hasattr(self, "MH1"):
107
+ self.MHC_type = "MH1"
108
+ elif hasattr(self, "GA1") or hasattr(self, "GA2"):
109
+ self.MHC_type = "MH1"
110
+ else:
111
+ self.MHC_type = ""
112
+
113
+ def _add_domain(self, chain):
114
+ if chain.chain_type == "MH1":
115
+ self.MH1 = chain.id
116
+ self.GA1 = chain.id
117
+ self.GA2 = chain.id
118
+ elif chain.chain_type == "GA1":
119
+ self.MH1 = chain.id
120
+ self.GA1 = chain.id
121
+ elif chain.chain_type == "GA2":
122
+ self.MH1 = chain.id
123
+ self.GA2 = chain.id
124
+ elif chain.chain_type == "B2M":
125
+ self.B2M = chain.id
126
+
127
+ # Add the chain as a child of this entity.
128
+ self.add(chain)
129
+
130
+ def get_alpha(self):
131
+ for MH1_domain in set(["MH1", "GA1", "GA2"]):
132
+ if hasattr(self, MH1_domain):
133
+ return self.child_dict[getattr(self, MH1_domain)]
134
+
135
+ def get_MH1(self):
136
+ if hasattr(self, "MH1"):
137
+ return self.child_dict[self.MH1]
138
+
139
+ def get_GA1(self):
140
+ if hasattr(self, "GA1"):
141
+ return self.child_dict[self.GA1]
142
+ else:
143
+ return self.get_MH1()
144
+
145
+ def get_GA2(self):
146
+ if hasattr(self, "GA2"):
147
+ return self.child_dict[self.GA2]
148
+ else:
149
+ return self.get_MH1()
150
+
151
+ def get_B2M(self):
152
+ if hasattr(self, "B2M"):
153
+ return self.child_dict[self.B2M]
154
+
155
+
156
+ class MH2(MHC):
157
+ """
158
+ Type 2 MHC class.
159
+ Holds paired MHC domains.
160
+ """
161
+
162
+ def __repr__(self):
163
+ if self.MHC_type == "MH2":
164
+ return "<%s %s%s GA=%s; GB=%s>" % (
165
+ self.MHC_type,
166
+ self.GA,
167
+ self.GB,
168
+ self.GA,
169
+ self.GB,
170
+ )
171
+ else:
172
+ return "<GA/GB %s%s GA=%s; GB=%s>" % (self.GA, self.GB, self.GA, self.GB)
173
+
174
+ def _set_MHC_type(self):
175
+ if hasattr(self, "GA") and hasattr(self, "GB"):
176
+ self.MHC_type = "MH2"
177
+ else:
178
+ self.MHC_type = ""
179
+
180
+ def _add_domain(self, chain):
181
+ if chain.chain_type == "GA":
182
+ self.GA = chain.id
183
+ elif chain.chain_type == "GB":
184
+ self.GB = chain.id
185
+
186
+ # Add the chain as a child of this entity.
187
+ self.add(chain)
188
+
189
+ def get_GA(self):
190
+ if hasattr(self, "GA"):
191
+ return self.child_dict[self.GA]
192
+
193
+ def get_GB(self):
194
+ if hasattr(self, "GB"):
195
+ return self.child_dict[self.GB]
196
+
197
+
198
+ class CD1(MHC):
199
+ """
200
+ CD1 class.
201
+ Holds paired CD1/B2M domains.
202
+ """
203
+
204
+ def __repr__(self):
205
+ if self.MHC_type == "CD1":
206
+ return "<%s %s%s GA1L/GA2L=%s; B2M=%s>" % (
207
+ self.MHC_type,
208
+ self.CD1,
209
+ self.B2M,
210
+ self.CD1,
211
+ self.B2M,
212
+ )
213
+ else:
214
+ return "<GA1L/GA2L %s%s GA1L=%s; GA2L=%s>" % (
215
+ self.GA1L,
216
+ self.GA2L,
217
+ self.GA1L,
218
+ self.GA2L,
219
+ )
220
+
221
+ def _set_MHC_type(self):
222
+ if hasattr(self, "CD1"):
223
+ self.MHC_type = "CD1"
224
+ elif hasattr(self, "GA1L") and hasattr(self, "GA2L"):
225
+ self.MHC_type = "CD1"
226
+ elif hasattr(self, "GA1L") and hasattr(self, "B2M"):
227
+ self.MHC_type = "CD1"
228
+ else:
229
+ self.MHC_type = ""
230
+
231
+ def _add_domain(self, chain):
232
+ if chain.chain_type == "CD1":
233
+ self.MHC_type = "CD1"
234
+ self.CD1 = chain.id
235
+ self.GA1L = chain.id
236
+ self.GA2L = chain.id
237
+ elif chain.chain_type == "GA1L":
238
+ self.CD1 = chain.id
239
+ self.GA1L = chain.id
240
+ elif chain.chain_type == "GA2L":
241
+ self.GA2L = chain.id
242
+ elif chain.chain_type == "B2M":
243
+ self.B2M = chain.id
244
+
245
+ # Add the chain as a child of this entity.
246
+ self.add(chain)
247
+
248
+ def get_CD1(self):
249
+ if hasattr(self, "CD1"):
250
+ return self.child_dict[self.CD1]
251
+
252
+ def get_B2M(self):
253
+ if hasattr(self, "B2M"):
254
+ return self.child_dict[self.B2M]
255
+
256
+
257
+ class MR1(MHC):
258
+ """
259
+ MR1 class.
260
+ Holds paired MR1/B2M domains.
261
+ """
262
+
263
+ def __repr__(self):
264
+ if self.MHC_type == "MR1":
265
+ return "<%s %s%s GA1L/GA2L=%s; B2M=%s>" % (
266
+ self.MHC_type,
267
+ self.MR1,
268
+ self.B2M,
269
+ self.MR1,
270
+ self.B2M,
271
+ )
272
+ else:
273
+ return "<GA1L/GA2L %s%s GA1L=%s; GA2L=%s>" % (
274
+ self.GA1L,
275
+ self.GA2L,
276
+ self.GA1L,
277
+ self.GA2L,
278
+ )
279
+
280
+ def _set_MHC_type(self):
281
+ if hasattr(self, "MR1"):
282
+ self.MHC_type = "MR1"
283
+ elif hasattr(self, "GA1L") and hasattr(self, "GA2L"):
284
+ self.MHC_type = "MR1"
285
+ else:
286
+ self.MHC_type = ""
287
+
288
+ def _add_domain(self, chain):
289
+ if chain.chain_type == "MR1":
290
+ self.MHC_type = "MR1"
291
+ self.MR1 = chain.id
292
+ self.GA1L = chain.id
293
+ self.GA2L = chain.id
294
+ elif chain.chain_type == "GA1L":
295
+ self.GA1L = chain.id
296
+ elif chain.chain_type == "GA2L":
297
+ self.GA2L = chain.id
298
+ elif chain.chain_type == "B2M":
299
+ self.B2M = chain.id
300
+
301
+ # Add the chain as a child of this entity.
302
+ self.add(chain)
303
+
304
+ def get_MR1(self):
305
+ if hasattr(self, "MR1"):
306
+ return self.child_dict[self.MR1]
307
+
308
+ def get_B2M(self):
309
+ if hasattr(self, "B2M"):
310
+ return self.child_dict[self.B2M]
311
+
312
+
313
+ class scMH1(MHC):
314
+ """
315
+ Type 1 MHC class.
316
+ Holds single chain MHC domains for Class I MHC if the identiifed chain
317
+ is the double alpha helix, ie. MH1 without B2M, with exception for GA1.
318
+ """
319
+
320
+ def __init__(self, c1):
321
+ assert c1.chain_type in [
322
+ "GA1",
323
+ "GA2",
324
+ "MH1",
325
+ ], f"Chain {c1} with can not form a single chain MHC class I."
326
+ Entity.__init__(self, c1.id)
327
+
328
+ self.level = "H"
329
+ self._add_domain(c1)
330
+ self._set_MHC_type()
331
+ self.child_list = sorted(self.child_list, key=lambda x: x.id)
332
+ self.antigen = []
333
+ self.tcr = []
334
+ self.engineered = False
335
+
336
+ def __repr__(self):
337
+ if self.MHC_type == "MH1":
338
+ return "<%s %s GA1/GA2=%s>" % (
339
+ self.MHC_type,
340
+ self.MH1,
341
+ self.MH1,
342
+ )
343
+ else:
344
+ return "<GA1/GA2 %s GA1/GA2=%s>" % (
345
+ self.GA1,
346
+ self.GA1,
347
+ )
348
+
349
+ def _set_MHC_type(self):
350
+ if hasattr(self, "MH1") or hasattr(self, "GA1") or hasattr(self, "GA2"):
351
+ self.MHC_type = "MH1"
352
+ else:
353
+ self.MHC_type = ""
354
+
355
+ def _add_domain(self, chain):
356
+ if chain.chain_type in ["MH1", "GA1", "GA2"]:
357
+ self.MH1 = chain.id
358
+ self.GA1 = chain.id
359
+ self.GA2 = chain.id
360
+
361
+ # Add the chain as a child of this entity.
362
+ self.add(chain)
363
+
364
+ def get_alpha(self):
365
+ for MH1_domain in set(["MH1", "GA1", "GA2"]):
366
+ if hasattr(self, MH1_domain):
367
+ return self.child_dict[getattr(self, MH1_domain)]
368
+
369
+ def get_MH1(self):
370
+ if hasattr(self, "MH1"):
371
+ return self.child_dict[self.MH1]
372
+
373
+ def get_GA1(self):
374
+ if hasattr(self, "GA1"):
375
+ return self.child_dict[self.GA1]
376
+ else:
377
+ return self.get_MH1()
378
+
379
+ def get_GA2(self):
380
+ if hasattr(self, "GA2"):
381
+ return self.child_dict[self.GA2]
382
+ else:
383
+ return self.get_MH1()
384
+
385
+ def get_B2M(self):
386
+ return None
387
+
388
+
389
+ class scCD1(MHC):
390
+ """
391
+ Type 1 MHC class.
392
+ Holds single chain MHC domains of type CD1 for Class I MHC if the identiifed chain
393
+ is the double alpha helix, ie. CD1 without B2M.
394
+ """
395
+
396
+ def __init__(self, c1):
397
+ assert c1.chain_type in [
398
+ "GA1L",
399
+ "CD1",
400
+ ], f"Chain {c1} with can not form a single chain MHC class I."
401
+ Entity.__init__(self, c1.id)
402
+
403
+ self.level = "H"
404
+ self._add_domain(c1)
405
+ self._set_MHC_type()
406
+ self.child_list = sorted(self.child_list, key=lambda x: x.id)
407
+ self.antigen = []
408
+ self.tcr = []
409
+ self.engineered = False
410
+
411
+ def __repr__(self):
412
+ if self.MHC_type == "CD1":
413
+ return "<%s %s GA1L=%s>" % (
414
+ self.MHC_type,
415
+ self.CD1,
416
+ self.CD1,
417
+ )
418
+ else:
419
+ return "<GA1L %s GA1L=%s>" % (
420
+ self.GA1L,
421
+ self.GA1L,
422
+ )
423
+
424
+ def _set_MHC_type(self):
425
+ if hasattr(self, "CD1") or hasattr(self, "GA1L"):
426
+ self.MHC_type = "CD1"
427
+ else:
428
+ self.MHC_type = ""
429
+
430
+ def _add_domain(self, chain):
431
+ if chain.chain_type in ["CD1", "GA1L"]:
432
+ self.CD1 = chain.id
433
+ self.GA1L = chain.id
434
+
435
+ # Add the chain as a child of this entity.
436
+ self.add(chain)
437
+
438
+ def get_CD1(self):
439
+ if hasattr(self, "CD1"):
440
+ return self.child_dict[self.CD1]
441
+
442
+ def get_GA1L(self):
443
+ if hasattr(self, "GA1L"):
444
+ return self.child_dict[self.GA1L]
445
+ else:
446
+ return self.get_CD1()
447
+
448
+ def get_B2M(self):
449
+ return None
@@ -0,0 +1,149 @@
1
+ """
2
+ Created on 30 Apr 2016
3
+ @author: leem
4
+
5
+ Based on the ABchain class from @dunbar
6
+
7
+ """
8
+
9
+ from .utils.region_definitions import get_region
10
+ from Bio.PDB.Chain import Chain
11
+ from .Entity import Entity
12
+ from .Fragment import Fragment
13
+ from Bio import SeqUtils
14
+
15
+
16
+ class MHCchain(Chain, Entity):
17
+ """
18
+ A class to hold an MHC chain
19
+ """
20
+
21
+ def __init__(self, id):
22
+ Chain.__init__(self, id)
23
+ Entity.__init__(self, id)
24
+ self.level = "C"
25
+ self.antigen = []
26
+ self.unnumbered = []
27
+ self.sequence = {}
28
+ self.residue_order = {}
29
+ self.engineered = False
30
+ self.tcr = []
31
+
32
+ def __repr__(self):
33
+ return "<MHCchain %s type: %s>" % (self.id, self.chain_type)
34
+
35
+ def _add_antigen(self, antigen=None):
36
+ if antigen not in self.antigen:
37
+ self.antigen.append(antigen)
38
+
39
+ def _add_tcr(self, tcr):
40
+ self.tcr.append(tcr)
41
+
42
+ def get_TCR(self):
43
+ return self.tcr
44
+
45
+ def analyse(self, chain_type):
46
+ self.set_chain_type(chain_type)
47
+ # self._init_fragments()
48
+ self.annotate_children()
49
+ self.set_sequence()
50
+
51
+ def set_chain_type(self, chain_type):
52
+ """
53
+ Set the MHC's chain type
54
+ """
55
+ self.chain_type = chain_type
56
+
57
+ def set_engineered(self, engineered):
58
+ if engineered:
59
+ self.engineered = True
60
+ else:
61
+ self.engineered = False
62
+
63
+ def set_sequence(self):
64
+ i = 0
65
+ for residue in self:
66
+ if (
67
+ residue.get_resname().capitalize()
68
+ in SeqUtils.IUPACData.protein_letters_3to1
69
+ ):
70
+ resname = SeqUtils.IUPACData.protein_letters_3to1[
71
+ residue.get_resname().capitalize()
72
+ ] # change this to use our chemical components.
73
+ else:
74
+ # skip the residue if the code is not recognised - e.g. UNK
75
+ continue
76
+ hetflag, resseq, icode = residue.get_id()
77
+ self.sequence[(self.chain_type + str(resseq) + str(icode)).strip()] = (
78
+ resname
79
+ )
80
+ self.residue_order[(self.chain_type + str(resseq) + str(icode)).strip()] = i
81
+ i += 1
82
+
83
+ def add_unnumbered(self, residue):
84
+ self.unnumbered.append(residue.id)
85
+
86
+ def _get_region(self, residue):
87
+ region = ""
88
+ if hasattr(residue, "imgt_numbered") and residue.imgt_numbered:
89
+ # Call the get_region function from ..Annotate.region_definitions module
90
+ region = get_region((residue.id[1], residue.id[2]), residue.chain_type)
91
+ return region
92
+ return "?"
93
+
94
+ def annotate_children(self):
95
+ for residue in self:
96
+ residue.chain_type = self.chain_type
97
+ residue.region = self._get_region(residue)
98
+ for atom in residue:
99
+ atom.chain_type = self.chain_type
100
+ atom.region = residue.region
101
+ # if residue.region != "?":
102
+ # self.fragments.child_dict[residue.region].add(residue)
103
+
104
+ def _init_fragments(self):
105
+ self.fragments = Entity("Fragments")
106
+ self.fragments.set_parent(self)
107
+ for region in regions[self.chain_type]:
108
+ self.fragments.add(Fragment(region))
109
+
110
+ def is_bound(self):
111
+ """
112
+ Check whether there is an antigen bound to the antibody chain
113
+ """
114
+ if self.get_antigen():
115
+ return True
116
+ else:
117
+ return False
118
+
119
+ def get_antigen(self):
120
+ return self.antigen
121
+
122
+ def get_fragments(self):
123
+ for f in self.fragments:
124
+ yield f
125
+
126
+ def get_sequence(self, type=dict):
127
+ if not self.sequence:
128
+ self.set_sequence()
129
+ if type is dict:
130
+ return self.sequence
131
+ else:
132
+ ordered = sorted(
133
+ list(self.sequence.items()), key=lambda x: self.residue_order[x[0]]
134
+ )
135
+ if type is str:
136
+ return "".join([r[1] for r in ordered])
137
+ else:
138
+ return ordered
139
+
140
+ def get_unnumbered(self):
141
+ for r in self.unnumbered:
142
+ yield self.child_dict[r]
143
+
144
+ def get_chains(self): # implemented to retain interface with MHC.get_chains()
145
+ for c in [self]:
146
+ yield c
147
+
148
+ def get_allele_assignments(self):
149
+ return self.xtra["genetic_origin"]
@@ -0,0 +1,37 @@
1
+ """
2
+ Created on 9 May 2017
3
+ @author: leem
4
+
5
+ Based on the ABDB.AbPDB.Model class.
6
+ """
7
+
8
+ import Bio
9
+
10
+
11
+ class Model(Bio.PDB.Model.Model, Bio.PDB.Entity.Entity):
12
+ """
13
+ Override to use our Entity
14
+
15
+ @change: __getitem__ changed so that single chains can be called as well as holder object from a model.
16
+ e.g. s[0]["B"] and s[0]["BA"] gets the B chain and the BA tcr respectively.
17
+ """
18
+
19
+ def __init__(self, identifier, serial_num=None):
20
+ Bio.PDB.Model.Model.__init__(self, identifier, serial_num)
21
+ Bio.PDB.Entity.Entity.__init__(self, identifier)
22
+
23
+ def __getitem__(self, identifier):
24
+ "Return the child with given identifier."
25
+ if identifier in self.child_dict:
26
+ return self.child_dict[identifier]
27
+ else:
28
+ # Allow a single chain to be called from a model.
29
+ for child in self:
30
+ if (
31
+ child.id in self.child_dict
32
+ and identifier in self.child_dict[child.id].child_dict
33
+ ):
34
+ return self.child_dict[child.id].child_dict[identifier]
35
+ raise KeyError(
36
+ identifier
37
+ ) # raise error if chain belonging to identifier is not found