Package mmLib :: Module TLS
[hide private]
[frames] | no frames]

Source Code for Module mmLib.TLS

   1  ## Copyright 2002-2010 by PyMMLib Development Group (see AUTHORS file) 
   2  ## This code is part of the PyMMLib distribution and governed by 
   3  ## its license.  Please see the LICENSE file that should have been 
   4  ## included as part of this package. 
   5  """Utility classes for loading, manipulating, and analyzing TLS parameters. 
   6  """ 
   7  import re 
   8  import fpformat 
   9  import math 
  10   
  11  try: 
  12      import numpy 
  13      try: 
  14          from numpy.oldnumeric import linear_algebra as linalg 
  15      except ImportError: 
  16          from numpy.linalg import old as linalg 
  17  except ImportError: 
  18      import NumericCompat as numpy 
  19      from NumericCompat import linalg 
  20   
  21  import Constants 
  22  import ConsoleOutput 
  23  import AtomMath 
  24  import PDB 
  25  import Structure 
  26  import Viewer 
  27  import Gaussian 
  28  import Colors 
  29   
  30  ############################################################################### 
  31  ## EXCEPTION BASE CLASS 
  32  ## 
  33   
34 -class TLSError(Exception):
35 """Base exception class for TLS module exceptions. 36 """ 37 pass
38 39 ############################################################################### 40 ## SUPPORTED TLS FILE FORMATS 41 ## 42
43 -class TLSFileFormatError(TLSError):
44 """Raised when a file format error is encountered while loading a 45 TLS group description file. 46 """ 47 pass
48 49
50 -class TLSGroupDesc(object):
51 """Description of one TLS Group. 52 """
53 - def __init__(self):
54 self.name = "" # text name 55 self.origin = None # array(3) 56 self.range_list = [] # (chain1, res1, chain2, res2, selection) 57 self.T = None # array(3,3) 58 self.L = None # array(3,3) 59 self.S = None # array(3,3)
60
61 - def set_name(self, name):
62 """Sets the TLS group name. 63 """ 64 self.name = name
65
66 - def set_origin(self, x, y, z):
67 """Sets the TLS group origin of calculations. 68 """ 69 self.origin = numpy.array((x, y, z), float)
70
71 - def add_range(self, chain_id1, frag_id1, chain_id2, frag_id2, selection):
72 """Adds a segment of residues to the TLS group. Not too sure how to 73 handle segments which span chains, so assert on that condition. 74 """ 75 ## XXX: This is a temporary fix, 2009-08-19 76 #assert chain_id1 == chain_id2 77 self.range_list.append((chain_id1, frag_id1, chain_id2, frag_id2, selection))
78
79 - def set_T(self, t11, t22, t33, t12, t13, t23):
80 """Sets the T tensor from the component arguments. Units are in 81 square Angstroms. 82 """ 83 self.T = numpy.array( [[t11, t12, t13], 84 [t12, t22, t23], 85 [t13, t23, t33]], float)
86
87 - def set_L(self, l11, l22, l33, l12, l13, l23):
88 """Sets the L tensor from the component arguments. Units are in 89 square Radians. 90 """ 91 self.L = numpy.array( [[l11, l12, l13], 92 [l12, l22, l23], 93 [l13, l23, l33]], float)
94
95 - def set_L_deg2(self, l11, l22, l33, l12, l13, l23):
96 """Sets the L tensor from the component arguments. Units are in 97 square Degrees. 98 """ 99 self.set_L(l11*Constants.DEG2RAD2, l22*Constants.DEG2RAD2, l33*Constants.DEG2RAD2, 100 l12*Constants.DEG2RAD2, l13*Constants.DEG2RAD2, l23*Constants.DEG2RAD2)
101
102 - def set_S(self, s2211, s1133, s12, s13, s23, s21, s31, s32):
103 """Sets the S tensor from the component arguments. Units are in 104 Radians*Angstroms. The trace of S is set to 0.0. 105 """ 106 s22 = 2.0*(s2211)/3.0 + s1133/3.0 107 s11 = s22 - s2211 108 s33 = s11 - s1133 109 110 self.S = numpy.array([[s11, s12, s13], 111 [s21, s22, s23], 112 [s31, s32, s33]])
113
114 - def set_S_deg(self, s2211, s1133, s12, s13, s23, s21, s31, s32):
115 """Sets the S tensor from the component arguments. Units are in 116 Degrees*Angstroms. The trace of S is set to 0.0. 117 """ 118 self.set_S(s2211*Constants.DEG2RAD, s1133*Constants.DEG2RAD, s12*Constants.DEG2RAD, 119 s13*Constants.DEG2RAD, s23*Constants.DEG2RAD, s21*Constants.DEG2RAD, 120 s31*Constants.DEG2RAD, s32*Constants.DEG2RAD)
121
122 - def set_tls_group(self, tls_group):
123 """Sets the TLSGroupDesc tensor values from the TLSGroup instance. 124 """ 125 self.set_origin( 126 tls_group.origin[0], 127 tls_group.origin[1], 128 tls_group.origin[2]) 129 130 self.set_T( 131 tls_group.T[0,0], 132 tls_group.T[1,1], 133 tls_group.T[2,2], 134 tls_group.T[0,1], 135 tls_group.T[0,2], 136 tls_group.T[1,2]) 137 138 self.set_L( 139 tls_group.L[0,0], 140 tls_group.L[1,1], 141 tls_group.L[2,2], 142 tls_group.L[0,1], 143 tls_group.L[0,2], 144 tls_group.L[1,2]) 145 146 self.set_S( 147 tls_group.S[1,1] - tls_group.S[0,0], 148 tls_group.S[0,0] - tls_group.S[2,2], 149 tls_group.S[0,1], 150 tls_group.S[0,2], 151 tls_group.S[1,2], 152 tls_group.S[1,0], 153 tls_group.S[2,0], 154 tls_group.S[2,1])
155
156 - def is_null(self):
157 """Returns True if the T,L,S tensors are not set, or are set 158 with values of zero. 159 """ 160 if self.T is None or self.L is None or self.S is None: 161 return True 162 return False
163
164 - def calc_tls_name(self):
165 """Creates a name for the TLS group using the selected residue ranges. 166 """ 167 listx = [] 168 for (chain_id1, frag_id1, chain_id2, frag_id2, sel) in self.range_list: 169 listx.append("%s%s-%s%s %s" % (chain_id1, frag_id1, chain_id2, frag_id2, sel)) 170 return ";".join(listx)
171
172 - def iter_atoms(self, struct):
173 """Uses the TLS definition and the given Structure object to iterate 174 over all atoms which should be included in the TLS group according 175 to the range_list definitions. 176 """ 177 for (chain_id1, frag_id1, chain_id2, frag_id2, sel) in self.range_list: 178 ## XXX: This is a temporary fix, 2009-08-19 179 #assert chain_id1 == chain_id2 180 181 chain1 = struct.get_chain(chain_id1) 182 if chain1 is None: 183 ConsoleOutput.warning("iter_tls_atoms(): no chain id=%s" % (chain_id1)) 184 continue 185 186 try: 187 seg = chain1[frag_id1:frag_id2] 188 except KeyError: 189 ConsoleOutput.warning( 190 "iter_tls_atoms():unable to find segment={%s..%s}" % (frag_id1, frag_id2)) 191 192 for atm in seg.iter_all_atoms(): 193 yield atm
194
195 - def construct_tls_group(self):
196 """Creates a TLSGroup() object with the origin, T, L, and S tensors 197 set according to the TLS description. 198 """ 199 tls_group = TLSGroup() 200 201 if self.name == "": 202 tls_group.name = self.calc_tls_name() 203 else: 204 tls_group.name = self.name 205 206 if self.origin is not None: 207 tls_group.set_origin(self.origin[0], self.origin[1], self.origin[2]) 208 209 if self.T is not None: 210 tls_group.set_T(self.T[0,0], self.T[1,1], self.T[2,2], 211 self.T[0,1], self.T[0,2], self.T[1,2]) 212 213 if self.L is not None: 214 tls_group.set_L(self.L[0,0], self.L[1,1], self.L[2,2], 215 self.L[0,1], self.L[0,2], self.L[1,2]) 216 217 if self.S is not None: 218 ## s2211, s1133, s12, s13, s23, s21, s31, s32) 219 tls_group.set_S( 220 self.S[1,1] - self.S[0,0], 221 self.S[0,0] - self.S[2,2], 222 self.S[0,1], 223 self.S[0,2], 224 self.S[1,2], 225 self.S[1,0], 226 self.S[2,0], 227 self.S[2,1]) 228 229 return tls_group
230
231 - def construct_tls_group_with_atoms(self, struct):
232 """Creates a TLSGroup() object with the origin, T, L, and S tensors 233 set according to the TLS description, then add the Atoms to the 234 TLSGroup from the given argument Structure. 235 """ 236 tls_group = self.construct_tls_group() 237 238 for atm in self.iter_atoms(struct): 239 tls_group.append(atm) 240 241 return tls_group
242 243
244 -class TLSFile(object):
245 """Read/Write TLS files containing one or more TLSGroupDesc objects. 246 """
247 - def __init__(self):
248 self.path = None 249 self.tls_desc_list = [] 250 self.file_format = None
251
252 - def set_file_format(self, file_format):
253 """Set a instance of a TLSFileFormat subclass to use for reading and 254 writing TLS description files. 255 """ 256 self.file_format = file_format
257
258 - def load(self, fil, path=None):
259 """Load TLS description file using the current TLSFileFormat instance. 260 """ 261 assert self.file_format is not None 262 self.path = path 263 self.tls_desc_list = self.file_format.load(fil)
264
265 - def save(self, fil, path=None):
266 """Save TLS description file using the curent TLSFileFormat instance. 267 """ 268 assert self.file_format is not None 269 self.path = path 270 self.file_format.save(fil, self.tls_desc_list)
271
272 - def construct_tls_groups(self, struct):
273 """Returns a list of TLSGroup instances constructed from the 274 TLSGroupDesc instances contained in this class. 275 """ 276 tls_group_list = [] 277 278 for tls_desc in self.tls_desc_list: 279 tls_group = tls_desc.construct_tls_group(struct) 280 if tls_group is not None: 281 tls_group_list.append(tls_group) 282 283 return tls_group_list
284
285 - def construct_tls_groups_with_atoms(self, struct):
286 """Returns a list of TLSGroup instances constructed from the Structure 287 instance argument and the TLSGroupDesc instances contained in this 288 class. 289 """ 290 tls_group_list = [] 291 292 for tls_desc in self.tls_desc_list: 293 tls_group = tls_desc.construct_tls_group_with_atoms(struct) 294 if tls_group is not None: 295 tls_group_list.append(tls_group) 296 297 return tls_group_list
298 299
300 -class TLSFileFormat(object):
301 """Base class for TLS file types. 302 """
303 - def load_supported(self):
304 """Returns True if file loading is supported, otherwise returns False. 305 """ 306 return False
307
308 - def save_supported(self):
309 """Return True if file saving is supported, otherwise returns False. 310 """ 311 return False
312
313 - def load(self, fil):
314 """Returns a list containing one TLSGroupDesc object for each TLS group 315 description found in the file. 316 """ 317 pass
318
319 - def save(self, fil, tls_desc_list):
320 """Writes the list of TLSGroupDesc object to the given file. 321 """ 322 pass
323 324
325 -class TLSFileFormatPDB(TLSFileFormat, PDB.RecordProcessor):
326 """Reads TLS descriptions from the REMARK records in PDB files. These 327 records are only written by REFMAC5. 328 """ 329 330 ##========================================================================= 331 ## REFMAC5 input format from REMARK-3 records in PDB header: 332 ##REMARK 3 TLS DETAILS 333 ##REMARK 3 NUMBER OF TLS GROUPS : 3 334 ##REMARK 3 335 ##REMARK 3 TLS GROUP : 1 336 ##REMARK 3 NUMBER OF COMPONENTS GROUP : 1 337 ##REMARK 3 COMPONENTS C SSSEQI TO C SSSEQI 338 ##REMARK 3 RESIDUE RANGE : A 23 A 106 339 ##REMARK 3 ORIGIN FOR THE GROUP (A): 43.3300 61.2750 -0.1400 340 ##REMARK 3 T TENSOR 341 ##REMARK 3 T11: 0.0072 T22: -0.1166 342 ##REMARK 3 T33: -0.1198 T12: -0.0189 343 ##REMARK 3 T13: 0.0133 T23: 0.0079 344 ##REMARK 3 L TENSOR 345 ##REMARK 3 L11: 1.4119 L22: 1.2835 346 ##REMARK 3 L33: 2.0809 L12: 0.3942 347 ##REMARK 3 L13: 0.4458 L23: 0.8102 348 ##REMARK 3 S TENSOR 349 ##REMARK 3 S11: 0.0511 S12: -0.0559 S13: 0.0504 350 ##REMARK 3 S21: -0.0142 S22: -0.0301 S23: -0.2120 351 ##REMARK 3 S31: -0.0319 S32: 0.2292 S33: -0.0211 352 ##========================================================================= 353 ## PHENIX input format from REMARK-3 records in PDB header: 354 ##REMARK 3 TLS DETAILS 355 ##REMARK 3 NUMBER OF TLS GROUPS : 6 356 ##REMARK 3 TLS GROUP : 1 357 ##REMARK 3 SELECTION: CHAIN A AND RESID -2:94 358 ##REMARK 3 ORIGIN FOR THE GROUP (A): 27.6759 1.8796 16.0823 359 ##REMARK 3 T TENSOR 360 ##REMARK 3 T11: 0.7434 T22: 0.8763 361 ##REMARK 3 T33: 0.5338 T12: 0.0946 362 ##REMARK 3 T13: 0.0705 T23: -0.0385 363 ##REMARK 3 L TENSOR 364 ##REMARK 3 L11: 5.3788 L22: 3.0831 365 ##REMARK 3 L33: 2.9430 L12: 0.9633 366 ##REMARK 3 L13: -2.1458 L23: 0.6345 367 ##REMARK 3 S TENSOR 368 ##REMARK 3 S11: 0.0744 S12: 0.1555 S13: -1.1965 369 ##REMARK 3 S21: 0.1582 S22: -0.3137 S23: -0.2880 370 ##REMARK 3 S31: 0.4884 S32: 0.4111 S33: 0.0007 371 ##========================================================================= 372 ## The important differences are: 373 ## REFMAC5: 374 ##REMARK 3 RESIDUE RANGE : A 23 A 106 375 ## PHENIX: 376 ##REMARK 3 SELECTION: CHAIN A AND RESID -2:94 377 378 pdb_regex_dict = { 379 "group": re.compile("\s*TLS GROUP :\s+(\d+)\s*$"), 380 "range": re.compile("\s*RESIDUE RANGE :\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*$"), 381 "phenix_range":re.compile("\s*SELECTION:\s+CHAIN\s+(\w+)\s+AND\s+RESID\s+(-?\w+):(-?\w+)\s*$"), 382 "origin": re.compile("\s*ORIGIN\s+FOR\s+THE\s+GROUP\s+[(]A[)]:([\s\-\.0-9]+)$"), 383 "t11_t22": re.compile("\s*T11:\s*(\S+)\s+T22:\s*(\S+)\s*$"), 384 "t33_t12": re.compile("\s*T33:\s*(\S+)\s+T12:\s*(\S+)\s*$"), 385 "t13_t23": re.compile("\s*T13:\s*(\S+)\s+T23:\s*(\S+)\s*$"), 386 "l11_l22": re.compile("\s*L11:\s*(\S+)\s+L22:\s*(\S+)\s*$"), 387 "l33_l12": re.compile("\s*L33:\s*(\S+)\s+L12:\s*(\S+)\s*$"), 388 "l13_l23": re.compile("\s*L13:\s*(\S+)\s+L23:\s*(\S+)\s*$"), 389 "s11_s12_s13": re.compile("\s*S11:\s*(\S+)\s+S12:\s*(\S+)\s+S13:\s*(\S+)\s*$"), 390 "s21_s22_s23": re.compile("\s*S21:\s*(\S+)\s+S22:\s*(\S+)\s+S23:\s*(\S+)\s*$"), 391 "s31_s32_s33": re.compile("\s*S31:\s*(\S+)\s+S32:\s*(\S+)\s+S33:\s*(\S+)\s*$") 392 } 393
394 - def load_supported(self):
395 return True
396
397 - def load(self, fil):
398 if isinstance(fil, str): 399 fileobj = open(fil, "r") 400 else: 401 fileobj = fil 402 403 self.tls_desc = None 404 self.tls_scrap = {} 405 self.tls_desc_list = [] 406 407 filter_func = lambda pdb_record: isinstance(pdb_record, PDB.REMARK) 408 self.process_pdb_records(PDB.iter_pdb_records(iter(fileobj)), filter_func) 409 410 return self.tls_desc_list
411
412 - def complete_T(self):
413 for key in ("t11","t22","t33","t12","t13","t23"): 414 if not self.tls_scrap.has_key(key): 415 return 416 try: 417 self.tls_desc.set_T( 418 self.tls_scrap["t11"], 419 self.tls_scrap["t22"], 420 self.tls_scrap["t33"], 421 self.tls_scrap["t12"], 422 self.tls_scrap["t13"], 423 self.tls_scrap["t23"]) 424 except AttributeError: 425 raise TLSFileFormatError()
426
427 - def complete_L(self):
428 for key in ("l11","l22","l33","l12","l13","l23"): 429 if not self.tls_scrap.has_key(key): 430 return 431 try: 432 self.tls_desc.set_L_deg2( 433 self.tls_scrap["l11"], 434 self.tls_scrap["l22"], 435 self.tls_scrap["l33"], 436 self.tls_scrap["l12"], 437 self.tls_scrap["l13"], 438 self.tls_scrap["l23"]) 439 except AttributeError: 440 raise TLSFileFormatError()
441
442 - def complete_S(self):
443 for key in ("s11","s22","s33","s12","s13","s23","s21","s31","s32"): 444 if not self.tls_scrap.has_key(key): 445 return 446 447 ## s2211, s1133, s12, s13, s23, s21, s31, s32 448 try: 449 self.tls_desc.set_S_deg( 450 self.tls_scrap["s22"] - self.tls_scrap["s11"], 451 self.tls_scrap["s11"] - self.tls_scrap["s33"], 452 self.tls_scrap["s12"], 453 self.tls_scrap["s13"], 454 self.tls_scrap["s23"], 455 self.tls_scrap["s21"], 456 self.tls_scrap["s31"], 457 self.tls_scrap["s32"]) 458 except AttributeError: 459 raise TLSFileFormatError()
460
461 - def process_REMARK(self, rec):
462 """Callback for the PDBFile parser for REMARK records. If the REMARK 463 records contain TLS group information, then it is extracted and added 464 to the TLSGroups list. 465 """ 466 ## TLS REMARKs use remarkNum 3 467 if rec.get("remarkNum", 0) != 3: 468 return 469 470 ## no text == no tls info 471 if not rec.has_key("text"): 472 return 473 474 ## attempt to extract information from the text 475 text = rec["text"] 476 for (re_key, re_tls) in self.pdb_regex_dict.items(): 477 mx = re_tls.match(text) 478 if mx is not None: 479 break 480 481 ## no match 482 if mx is None: 483 return 484 485 if re_key == "group": 486 self.tls_desc = TLSGroupDesc() 487 self.tls_desc_list.append(self.tls_desc) 488 self.tls_scrap = {} 489 490 elif re_key == "origin": 491 strx = mx.group(1) 492 ox = [0.0, 0.0, 0.0] 493 494 ## Example origin lines. Note the shifted decimals in the last one. 495 ## strx= "REMARK 3 ORIGIN FOR THE GROUP (A): -19.1703 -24.0598 8.2757" 496 ## strx= "REMARK 3 ORIGIN FOR THE GROUP (A): -19.1703-124.0598 8.2757" 497 ## strx= "REMARK 3 ORIGIN FOR THE GROUP (A): -0.576 -34.88 -34.8830" 498 499 ## this is nasty -- I wish I could trust the numbers 500 ## to stay in fixed columns, but I can't 501 #for i in (0,1,2): 502 # j = strx.find(".") 503 # if j==-1: 504 # break 505 # x = strx[ max(0, j-4) : j+5] 506 # strx = strx[j+5:] 507 # ox[i] = float(x) 508 509 j = strx.find(".") ## find the first decimal in the string 510 if j == -1: 511 ## no decimal found anywhere in the string 512 #raise TLSFileFormatError() 513 raise "ERROR: Could not find a decimal point in the ORGIN values." 514 x = strx[j-4:] ## capture just the x,y,z values 515 ox[0] = float(x[0:9].strip()) 516 ox[1] = float(x[9:18].strip()) 517 ox[2] = float(x[18:].strip()) 518 519 try: 520 self.tls_desc.set_origin(ox[0], ox[1], ox[2]) 521 except AttributeError: 522 raise TLSFileFormatError() 523 except ValueError: 524 raise TLSFileFormatError() 525 526 elif re_key == "range": 527 (chain_id1, frag_id1, chain_id2, frag_id2) = mx.groups() 528 try: 529 self.tls_desc.add_range( 530 chain_id1, frag_id1, chain_id2, frag_id2, "") 531 except AttributeError: 532 raise TLSFileFormatError() 533 534 ## Allow for PHENIX's unique ranges 535 elif re_key == "phenix_range": 536 (chain_id1, frag_id1, frag_id2) = mx.groups() 537 try: 538 self.tls_desc.add_range( 539 chain_id1, frag_id1, chain_id1, frag_id2, "") 540 except AttributeError: 541 raise TLSFileFormatError() 542 543 elif re_key == "t11_t22": 544 (t11, t22) = mx.groups() 545 try: 546 self.tls_scrap["t11"] = float(t11) 547 self.tls_scrap["t22"] = float(t22) 548 except ValueError: 549 raise TLSFileFormatError() 550 self.complete_T() 551 552 elif re_key == "t33_t12": 553 (t33, t12) = mx.groups() 554 try: 555 self.tls_scrap["t33"] = float(t33) 556 self.tls_scrap["t12"] = float(t12) 557 except ValueError: 558 raise TLSFileFormatError() 559 self.complete_T() 560 561 elif re_key == "t13_t23": 562 (t13, t23) = mx.groups() 563 try: 564 self.tls_scrap["t13"] = float(t13) 565 self.tls_scrap["t23"] = float(t23) 566 except ValueError: 567 raise TLSFileFormatError() 568 self.complete_T() 569 570 elif re_key == "l11_l22": 571 (l11, l22) = mx.groups() 572 try: 573 self.tls_scrap["l11"] = float(l11) 574 self.tls_scrap["l22"] = float(l22) 575 except ValueError: 576 raise TLSFileFormatError() 577 self.complete_L() 578 579 elif re_key == "l33_l12": 580 (l33, l12) = mx.groups() 581 try: 582 self.tls_scrap["l33"] = float(l33) 583 self.tls_scrap["l12"] = float(l12) 584 except ValueError: 585 raise TLSFileFormatError() 586 self.complete_L() 587 588 elif re_key == "l13_l23": 589 (l13, l23) = mx.groups() 590 try: 591 self.tls_scrap["l13"] = float(l13) 592 self.tls_scrap["l23"] = float(l23) 593 except ValueError: 594 raise TLSFileFormatError() 595 self.complete_L() 596 597 elif re_key == "s11_s12_s13": 598 (s11, s12, s13) = mx.groups() 599 try: 600 self.tls_scrap["s11"] = float(s11) 601 self.tls_scrap["s12"] = float(s12) 602 self.tls_scrap["s13"] = float(s13) 603 except ValueError: 604 raise TLSFileFormatError() 605 self.complete_S() 606 607 elif re_key == "s21_s22_s23": 608 (s21, s22, s23) = mx.groups() 609 try: 610 self.tls_scrap["s21"] = float(s21) 611 self.tls_scrap["s22"] = float(s22) 612 self.tls_scrap["s23"] = float(s23) 613 except ValueError: 614 raise TLSFileFormatError() 615 self.complete_S() 616 617 elif re_key == "s31_s32_s33": 618 (s31, s32, s33) = mx.groups() 619 try: 620 self.tls_scrap["s31"] = float(s31) 621 self.tls_scrap["s32"] = float(s32) 622 self.tls_scrap["s33"] = float(s33) 623 except ValueError: 624 raise TLSFileFormatError() 625 self.complete_S()
626 627
628 -class TLSFileFormatTLSOUT(TLSFileFormat):
629 """Read/Write REFMAC TLSIN/TLSOUT files. Note that this includes TLS+Biso 630 values. 631 """ 632 tlsout_regex_dict = { 633 "group": re.compile("(?:^\s*TLS\s*$)|(?:^\s*TLS\s+(.*)$)"), 634 "range": re.compile("^\s*RANGE\s+[']([A-Z])\s*([-0-9A-Z.]+)\s*[']\s+[']([A-Z])\s*([-0-9A-Z.]+)\s*[']\s*(\w*).*$"), 635 "origin": re.compile("^\s*ORIGIN\s+(\S+)\s+(\S+)\s+(\S+).*$"), 636 "T": re.compile("^\s*T\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+).*$"), 637 "L": re.compile("^\s*L\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+).*$"), 638 "S": re.compile("^\s*S\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+).*$") 639 } 640
641 - def convert_frag_id_load(self, frag_id):
642 """Converts the residue sequence code to a mmLib fragment_id. 643 """ 644 if len(frag_id) == 0: 645 return "" 646 if frag_id[-1] == ".": 647 frag_id = frag_id[:-1] 648 return frag_id
649
650 - def convert_frag_id_save(self, frag_id):
651 """Converts a mmLib fragment_id to a TLSOUT fragment id. 652 """ 653 if len(frag_id) == 0: 654 return "." 655 if frag_id[-1].isdigit(): 656 frag_id += "." 657 return frag_id
658
659 - def load_supported(self):
660 return True
661 - def save_supported(self):
662 return True
663
664 - def load(self, fil):
665 tls_desc_list = [] 666 tls_desc = None 667 668 for ln in fil.xreadlines(): 669 ln = ln.rstrip() 670 671 ## search all regular expressions for a match 672 for (re_key, re_tls) in self.tlsout_regex_dict.items(): 673 mx = re_tls.match(ln) 674 if mx is not None: 675 break 676 677 ## no match was found for the line 678 if mx is None: 679 continue 680 681 ## do not allow a match if tls_info is None, because then 682 ## somehow we've missed the TLS group begin line 683 if tls_desc is None and re_key!="group": 684 raise TLSFileFormatError() 685 686 if re_key == "group": 687 tls_desc = TLSGroupDesc() 688 tls_desc_list.append(tls_desc) 689 690 if mx.group(1) is not None: 691 tls_desc.set_name(mx.group(1)) 692 693 elif re_key == "origin": 694 (x, y, z) = mx.groups() 695 try: 696 tls_desc.set_origin(float(x), float(y), float(z)) 697 except ValueError: 698 raise TLSFileFormatError() 699 700 elif re_key == "range": 701 (chain_id1, frag_id1, chain_id2, frag_id2, sel) = mx.groups() 702 703 frag_id1 = self.convert_frag_id_load(frag_id1) 704 frag_id2 = self.convert_frag_id_load(frag_id2) 705 706 tls_desc.add_range(chain_id1, frag_id1, chain_id2, frag_id2, sel) 707 708 elif re_key == "T": 709 ## REFMAC ORDER: t11 t22 t33 t12 t13 t23 710 (t11, t22, t33, t12, t13, t23) = mx.groups() 711 712 try: 713 tls_desc.set_T(float(t11), float(t22), float(t33), 714 float(t12), float(t13), float(t23)) 715 except ValueError: 716 raise TLSFileFormatError() 717 718 elif re_key == "L": 719 ## REFMAC ORDER: l11 l22 l33 l12 l13 l23 720 (l11, l22, l33, l12, l13, l23) = mx.groups() 721 722 try: 723 tls_desc.set_L_deg2(float(l11), float(l22), float(l33), 724 float(l12), float(l13), float(l23)) 725 except ValueError: 726 raise TLSFileFormatError() 727 728 elif re_key == "S": 729 ## REFMAC ORDER: 730 ## <S22 - S11> <S11 - S33> <S12> <S13> <S23> <S21> <S31> <S32> 731 (s2211, s1133, s12, s13, s23, s21, s31, s32) = mx.groups() 732 733 try: 734 tls_desc.set_S_deg(float(s2211), float(s1133), float(s12), 735 float(s13), float(s23), float(s21), 736 float(s31), float(s32)) 737 except ValueError: 738 raise TLSFileFormatError() 739 740 return tls_desc_list
741
742 - def tlsout_tls_desc(self, tls_desc):
743 """Converts TLSGroupDesc instance to a multi-line string format 744 ready to write to a TLSOUT file. 745 """ 746 listx = [] 747 748 if tls_desc.name != "": 749 listx.append("TLS %s" % (tls_desc.name)) 750 else: 751 listx.append("TLS") 752 753 for (chain_id1, frag_id1, 754 chain_id2, frag_id2, sel) in tls_desc.range_list: 755 756 frag_id1 = self.convert_frag_id_save(frag_id1) 757 frag_id2 = self.convert_frag_id_save(frag_id2) 758 759 listx.append("RANGE '%s%s' '%s%s' %s" % ( 760 chain_id1, frag_id1.rjust(5), 761 chain_id2, frag_id2.rjust(5), sel)) 762 763 if tls_desc.origin is not None: 764 listx.append("ORIGIN %8.4f %8.4f %8.4f" % ( 765 tls_desc.origin[0], tls_desc.origin[1], tls_desc.origin[2])) 766 767 if tls_desc.T is not None: 768 ## REFMAC ORDER: t11 t22 t33 t12 t13 t23 769 listx.append("T %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f" % ( 770 tls_desc.T[0,0], tls_desc.T[1,1], tls_desc.T[2,2], 771 tls_desc.T[0,1], tls_desc.T[0,2], tls_desc.T[1,2])) 772 773 if tls_desc.L is not None: 774 ## REFMAC ORDER: l11 l22 l33 l12 l13 l23 775 listx.append("L %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f" % ( 776 tls_desc.L[0,0] * Constants.RAD2DEG2, 777 tls_desc.L[1,1] * Constants.RAD2DEG2, 778 tls_desc.L[2,2] * Constants.RAD2DEG2, 779 tls_desc.L[0,1] * Constants.RAD2DEG2, 780 tls_desc.L[0,2] * Constants.RAD2DEG2, 781 tls_desc.L[1,2] * Constants.RAD2DEG2)) 782 783 if tls_desc.S is not None: 784 ## REFMAC ORDER: 785 ## <S22 - S11> <S11 - S33> <S12> <S13> <S23> <S21> <S31> <S32> 786 listx.append( 787 "S %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f %8.4f" % ( 788 (tls_desc.S[1,1] - tls_desc.S[0,0]) * Constants.RAD2DEG, 789 (tls_desc.S[0,0] - tls_desc.S[2,2]) * Constants.RAD2DEG, 790 tls_desc.S[0,1] * Constants.RAD2DEG, 791 tls_desc.S[0,2] * Constants.RAD2DEG, 792 tls_desc.S[1,2] * Constants.RAD2DEG, 793 tls_desc.S[1,0] * Constants.RAD2DEG, 794 tls_desc.S[2,0] * Constants.RAD2DEG, 795 tls_desc.S[2,1] * Constants.RAD2DEG)) 796 797 return "\n".join(listx)
798
799 - def save(self, fil, tls_desc_list):
800 ## with this line, the tensor components will be read by some 801 ## programs in a different order, mangling the tensor values 802 fil.write("REFMAC\n\n") 803 804 for tls_desc in tls_desc_list: 805 tls_desc_str = self.tlsout_tls_desc(tls_desc) 806 fil.write(tls_desc_str + "\n")
807 808
809 -class TLSFileFormatPureTLSOUT(TLSFileFormat):
810 """Read/Write REFMAC5 TLSIN/TLSOUT files. Note that this is "pure" TLS 811 values, in that the Biso is not included, nor are the origin, T, L, or S 812 values. 813 """ 814 ## NOTE: The file format is identical to the Refmac format, except that it 815 ## does not contain the T, L, S, and origin fields. 816 tlsout_regex_dict = { 817 "group": re.compile("(?:^\s*TLS\s*$)|(?:^\s*TLS\s+(.*)$)"), 818 "range": re.compile("^\s*RANGE\s+[']([A-Z])\s*([-0-9A-Z.]+)\s*[']\s+[']([A-Z])\s*([-0-9A-Z.]+)\s*[']\s*(\w*).*$"), 819 "origin": re.compile("^\s*ORIGIN\s+(\S+)\s+(\S+)\s+(\S+).*$"), 820 "T": re.compile("^\s*T\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+).*$"), 821 "L": re.compile("^\s*L\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+).*$"), 822 "S": re.compile("^\s*S\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+).*$") 823 } 824
825 - def convert_frag_id_load(self, frag_id):
826 """Converts the residue sequence code to a mmLib fragment_id. 827 """ 828 if len(frag_id) == 0: 829 return "" 830 if frag_id[-1] == ".": 831 frag_id = frag_id[:-1] 832 return frag_id
833
834 - def convert_frag_id_save(self, frag_id):
835 """Converts a mmLib fragment_id to a TLSOUT fragment id. 836 """ 837 if len(frag_id) == 0: 838 return "." 839 if frag_id[-1].isdigit(): 840 frag_id += "." 841 return frag_id
842
843 - def load_supported(self):
844 return True
845 - def save_supported(self):
846 return True
847
848 - def load(self, fil):
849 tls_desc_list = [] 850 tls_desc = None 851 852 for ln in fil.xreadlines(): 853 ln = ln.rstrip() 854 855 ## search all regular expressions for a match 856 for (re_key, re_tls) in self.tlsout_regex_dict.items(): 857 mx = re_tls.match(ln) 858 if mx is not None: 859 break 860 861 ## no match was found for the line 862 if mx is None: 863 continue 864 865 ## do not allow a match if tls_info is None, because then 866 ## somehow we've missed the TLS group begin line 867 if tls_desc is None and re_key!="group": 868 raise TLSFileFormatError() 869 870 if re_key == "group": 871 tls_desc = TLSGroupDesc() 872 tls_desc_list.append(tls_desc) 873 874 if mx.group(1) is not None: 875 tls_desc.set_name(mx.group(1)) 876 877 elif re_key == "range": 878 (chain_id1, frag_id1, chain_id2, frag_id2, sel) = mx.groups() 879 880 frag_id1 = self.convert_frag_id_load(frag_id1) 881 frag_id2 = self.convert_frag_id_load(frag_id2) 882 883 tls_desc.add_range(chain_id1, frag_id1, chain_id2, frag_id2, sel) 884 885 return tls_desc_list
886
887 - def tlsout_tls_desc(self, tls_desc):
888 """Converts TLSGroupDesc instance to a multi-line string format 889 ready to write to a TLSOUT file. 890 """ 891 listx = [] 892 893 if tls_desc.name != "": 894 listx.append("TLS %s" % (tls_desc.name)) 895 else: 896 listx.append("TLS") 897 898 for (chain_id1, frag_id1, 899 chain_id2, frag_id2, sel) in tls_desc.range_list: 900 901 frag_id1 = self.convert_frag_id_save(frag_id1) 902 frag_id2 = self.convert_frag_id_save(frag_id2) 903 904 listx.append("RANGE '%s%s' '%s%s' %s" % ( 905 chain_id1, frag_id1.rjust(5), 906 chain_id2, frag_id2.rjust(5), sel)) 907 908 return "\n".join(listx)
909
910 - def save(self, fil, tls_desc_list):
911 ## with this line, the tensor components will be read by some 912 ## programs in a different order, mangling the tensor values 913 fil.write("REFMAC\n\n") 914 915 for tls_desc in tls_desc_list: 916 tls_desc_str = self.tlsout_tls_desc(tls_desc) 917 fil.write(tls_desc_str + "\n")
918 919 920 ################################################################################ 921 ## START: PHENIX (OUTPUT) class. Christoph Champ, 2007-12-17
922 -class TLSFileFormatPHENIXOUT(TLSFileFormat):
923 """Write PHENIX-TLSOUT files. 924 """ 925 #TLS 926 #RANGE 'A 8.' 'A 39.' ALL 927 #ORIGIN 45.1700 23.3521 121.5435 928 #T 0.4302 0.5151 0.3667 0.0051 0.0781 0.0212 929 #L 5.4300 5.8590 8.8541 -0.2476 -2.1140 -0.3333 930 #S -0.2126 0.0250 0.0406 -0.1994 0.2472 0.3260 0.3855 -0.4986 931 tlsout_regex_dict = { 932 "group": re.compile("(?:^\s*TLS\s*$)|(?:^\s*TLS\s+(.*)$)"), 933 "range": re.compile("^\s*RANGE\s+[']([A-Z])\s*([-0-9A-Z.]+)\s*[']\s+[']([A-Z])\s*([-0-9A-Z.]+)\s*[']\s*(\w*).*$"), 934 "origin": re.compile("^\s*ORIGIN\s+(\S+)\s+(\S+)\s+(\S+).*$"), 935 "T": re.compile("^\s*T\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+).*$"), 936 "L": re.compile("^\s*L\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+).*$"), 937 "S": re.compile("^\s*S\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+).*$") 938 } 939
940 - def convert_frag_id_load(self, frag_id):
941 """Converts the residue sequence code to a mmLib fragment_id. 942 """ 943 if len(frag_id) == 0: 944 return "" 945 if frag_id[-1] == ".": 946 frag_id = frag_id[:-1] 947 return frag_id
948
949 - def convert_frag_id_save(self, frag_id):
950 """Converts a mmLib fragment_id to a TLSOUT fragment id. 951 """ 952 if len(frag_id) == 0: 953 return "." 954 if frag_id[-1].isdigit(): 955 frag_id += "." 956 return frag_id
957
958 - def load_supported(self):
959 return True
960 - def save_supported(self):
961 return True
962
963 - def load(self, fil):
964 tls_desc_list = [] 965 tls_desc = None 966 967 for ln in fil.xreadlines(): 968 ln = ln.rstrip() 969 970 ## search all regular expressions for a match 971 for (re_key, re_tls) in self.tlsout_regex_dict.items(): 972 mx = re_tls.match(ln) 973 if mx is not None: 974 break 975 976 ## no match was found for the line 977 if mx is None: 978 continue 979 980 ## do not allow a match if tls_info is None, because then 981 ## somehow we've missed the TLS group begin line 982 if tls_desc is None and re_key!="group": 983 raise TLSFileFormatError() 984 985 if re_key == "group": 986 tls_desc = TLSGroupDesc() 987 tls_desc_list.append(tls_desc) 988 989 if mx.group(1) is not None: 990 tls_desc.set_name(mx.group(1)) 991 992 elif re_key == "origin": 993 (x, y, z) = mx.groups() 994 try: 995 tls_desc.set_origin(float(x), float(y), float(z)) 996 except ValueError: 997 raise TLSFileFormatError() 998 999 elif re_key == "range": 1000 (chain_id1, frag_id1, chain_id2, frag_id2, sel) = mx.groups() 1001 1002 frag_id1 = self.convert_frag_id_load(frag_id1) 1003 frag_id2 = self.convert_frag_id_load(frag_id2) 1004 1005 tls_desc.add_range(chain_id1, frag_id1, chain_id2, frag_id2, sel) 1006 1007 elif re_key == "T": 1008 ## REFMAC ORDER: t11 t22 t33 t12 t13 t23 1009 (t11, t22, t33, t12, t13, t23) = mx.groups() 1010 1011 try: 1012 tls_desc.set_T(float(t11), float(t22), float(t33), 1013 float(t12), float(t13), float(t23)) 1014 except ValueError: 1015 raise TLSFileFormatError() 1016 1017 elif re_key == "L": 1018 ## REFMAC ORDER: l11 l22 l33 l12 l13 l23 1019 (l11, l22, l33, l12, l13, l23) = mx.groups() 1020 1021 try: 1022 tls_desc.set_L_deg2(float(l11), float(l22), float(l33), 1023 float(l12), float(l13), float(l23)) 1024 except ValueError: 1025 raise TLSFileFormatError() 1026 1027 elif re_key == "S": 1028 ## REFMAC ORDER: 1029 ## <S22 - S11> <S11 - S33> <S12> <S13> <S23> <S21> <S31> <S32> 1030 (s2211, s1133, s12, s13, s23, s21, s31, s32) = mx.groups() 1031 1032 try: 1033 tls_desc.set_S_deg(float(s2211), float(s1133), float(s12), 1034 float(s13), float(s23), float(s21), 1035 float(s31), float(s32)) 1036 except ValueError: 1037 raise TLSFileFormatError() 1038 1039 return tls_desc_list
1040
1041 - def tlsout_tls_desc(self, tls_desc):
1042 """Converts TLSGroupDesc instance to a multi-line string format 1043 ready to write to a TLSOUT file. 1044 """ 1045 listx = [] 1046 1047 for (chain_id1, frag_id1, chain_id2, frag_id2, sel) in tls_desc.range_list: 1048 listx.append("\ttls=\"(chain %s and resid %s:%s)\"" % ( 1049 chain_id1, frag_id1, frag_id2)) 1050 1051 return "\n".join(listx)
1052
1053 - def save(self, fil, tls_desc_list):
1054 ## with this line, the tensor components will be read by some 1055 ## programs in a different order, mangling the tensor values 1056 fil.write("refinement.refine {\n adp {\n") 1057 1058 for tls_desc in tls_desc_list: 1059 tls_desc_str = self.tlsout_tls_desc(tls_desc) 1060 fil.write(tls_desc_str + "\n") 1061 fil.write(" }\n}\n")
1062 ## END: PHENIX (OUTPUT) class. Christoph Champ, 2007-12-17 1063 ################################################################################ 1064 1065 1066 ################################################################################ 1067 ## START: PHENIX (INPUT) class. Christoph Champ, 2007-11-02
1068 -class TLSFileFormatPHENIX(TLSFileFormat):
1069 """Read/Write PHENIX TLSIN/TLSOUT files. 1070 """ 1071 #TLS 1072 #RANGE 'A 8.' 'A 39.' ALL 1073 #ORIGIN 45.1700 23.3521 121.5435 1074 #T 0.4302 0.5151 0.3667 0.0051 0.0781 0.0212 1075 #L 5.4300 5.8590 8.8541 -0.2476 -2.1140 -0.3333 1076 #S -0.2126 0.0250 0.0406 -0.1994 0.2472 0.3260 0.3855 -0.4986 1077 tlsout_regex_dict = { 1078 "group": re.compile("(?:^\s*TLS\s*$)|(?:^\s*TLS\s+(.*)$)"), 1079 "range": re.compile("^\s*RANGE\s+[']([A-Z])\s*([-0-9A-Z.]+)\s*[']\s+[']([A-Z])\s*([-0-9A-Z.]+)\s*[']\s*(\w*).*$"), 1080 "origin": re.compile("^\s*ORIGIN\s+(\S+)\s+(\S+)\s+(\S+).*$"), 1081 "T": re.compile("^\s*T\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+).*$"), 1082 "L": re.compile("^\s*L\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+).*$"), 1083 "S": re.compile("^\s*S\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+).*$") 1084 } 1085 1086 ## Needs to look something like the following (from Pavel): 1087 #refinement.refine { 1088 # adp { 1089 # tls="(chain A and resid 1:155)" 1090 # tls="(chain B and resid 0:155)" 1091 # tls="(chain C and (resid 1:68 or resid 79:124 or resid 14:155))" 1092 # } 1093
1094 - def convert_frag_id_load(self, frag_id):
1095 """Converts the residue sequence code to a mmLib fragment_id. 1096 """ 1097 if len(frag_id) == 0: 1098 return "" 1099 if frag_id[-1] == ".": 1100 frag_id = frag_id[:-1] 1101 return frag_id
1102
1103 - def convert_frag_id_save(self, frag_id):
1104 """Converts a mmLib fragment_id to a TLSOUT fragment id. 1105 """ 1106 if len(frag_id) == 0: 1107 return "." 1108 if frag_id[-1].isdigit(): 1109 frag_id += "." 1110 return frag_id
1111
1112 - def load_supported(self):
1113 return True
1114 - def save_supported(self):
1115 return True
1116
1117 - def load(self, fil):
1118 tls_desc_list = [] 1119 tls_desc = None 1120 1121 for ln in fil.xreadlines(): 1122 ln = ln.rstrip() 1123 1124 ## search all regular expressions for a match 1125 for (re_key, re_tls) in self.tlsout_regex_dict.items(): 1126 mx = re_tls.match(ln) 1127 if mx is not None: 1128 break 1129 1130 ## no match was found for the line 1131 if mx is None: 1132 continue 1133 1134 ## do not allow a match if tls_info is None, because then 1135 ## somehow we've missed the TLS group begin line 1136 if tls_desc is None and re_key!="group": 1137 raise TLSFileFormatError() 1138 1139 if re_key == "group": 1140 tls_desc = TLSGroupDesc() 1141 tls_desc_list.append(tls_desc) 1142 1143 if mx.group(1) is not None: 1144 tls_desc.set_name(mx.group(1)) 1145 1146 elif re_key == "origin": 1147 (x, y, z) = mx.groups() 1148 try: 1149 tls_desc.set_origin(float(x), float(y), float(z)) 1150 except ValueError: 1151 raise TLSFileFormatError() 1152 1153 elif re_key == "range": 1154 (chain_id1, frag_id1, chain_id2, frag_id2, sel) = mx.groups() 1155 1156 frag_id1 = self.convert_frag_id_load(frag_id1) 1157 frag_id2 = self.convert_frag_id_load(frag_id2) 1158 1159 tls_desc.add_range(chain_id1, frag_id1, chain_id2, frag_id2, sel) 1160 1161 elif re_key == "T": 1162 ## REFMAC ORDER: t11 t22 t33 t12 t13 t23 1163 (t11, t22, t33, t12, t13, t23) = mx.groups() 1164 1165 try: 1166 tls_desc.set_T(float(t11), float(t22), float(t33), 1167 float(t12), float(t13), float(t23)) 1168 except ValueError: 1169 raise TLSFileFormatError() 1170 1171 elif re_key == "L": 1172 ## REFMAC ORDER: l11 l22 l33 l12 l13 l23 1173 (l11, l22, l33, l12, l13, l23) = mx.groups() 1174 1175 try: 1176 tls_desc.set_L_deg2(float(l11), float(l22), float(l33), 1177 float(l12), float(l13), float(l23)) 1178 except ValueError: 1179 raise TLSFileFormatError() 1180 1181 elif re_key == "S": 1182 ## REFMAC ORDER: 1183 ## <S22 - S11> <S11 - S33> <S12> <S13> <S23> <S21> <S31> <S32> 1184 (s2211, s1133, s12, s13, s23, s21, s31, s32) = mx.groups() 1185 1186 try: 1187 tls_desc.set_S_deg(float(s2211), float(s1133), float(s12), 1188 float(s13), float(s23), float(s21), 1189 float(s31), float(s32)) 1190 except ValueError: 1191 raise TLSFileFormatError() 1192 1193 return tls_desc_list
1194
1195 - def ptlsout_tls_desc(self, tls_desc):
1196 """Converts TLSGroupDesc instance to a multi-line string format 1197 ready to write to a PHENIX-TLSOUT file. 1198 """ 1199 listx = [] 1200 1201 for (chain_id1, frag_id1, chain_id2, frag_id2, sel) in tls_desc.range_list: 1202 listx.append("\ttls=\"(chain %s and resid %s:%s)\"" % ( 1203 chain_id1, frag_id1, frag_id2)) 1204 1205 return "\n".join(listx)
1206
1207 - def save(self, fil, tls_desc_list):
1208 ## with this line, the tensor components will be read by some 1209 ## programs in a different order, mangling the tensor values 1210 fil.write("refinement.refine {\n adp {\n") 1211 1212 for tls_desc in tls_desc_list: 1213 tls_desc_str = self.ptlsout_tls_desc(tls_desc) 1214 fil.write(tls_desc_str + "\n") 1215 fil.write(" }\n}\n")
1216 ## END: PHENIX (INPUT) class. Christoph Champ, 2007-11-02 1217 ############################################################################### 1218 1219 ############################################################################### 1220 ## SOLVE TLS LSQ-FIT BY SVD (Singular Value Decomposition) 1221 ## 1222
1223 -def solve_TLS_Ab(A, b):
1224 """Solve an overdetermined TLS system by singular value decomposition. 1225 """ 1226 ## solve by SVD 1227 U, W, Vt = linalg.singular_value_decomposition(A, full_matrices=0) 1228 1229 V = numpy.transpose(Vt) 1230 Ut = numpy.transpose(U) 1231 1232 ## analyze singular values and generate smallness cutoff 1233 cutoff = max(W) * 1E-10 1234 1235 ## make W 1236 dim_W = len(W) 1237 Wi = numpy.zeros((dim_W, dim_W), float) 1238 1239 for i in range(dim_W): 1240 if W[i]>cutoff: 1241 Wi[i,i] = 1.0 / W[i] 1242 else: 1243 #print "SVD: ill conditioned value %d=%f" % (i, W[i]) 1244 Wi[i,i] = 0.0 1245 1246 ## solve for x 1247 Utb = numpy.dot(Ut, b) 1248 WUtb = numpy.dot(Wi, Utb) 1249 x = numpy.dot(V, WUtb) 1250 1251 return x
1252
1253 -def calc_rmsd(msd):
1254 """Calculate RMSD from a given MSD. 1255 """ 1256 if msd < 0.0: 1257 return 0.0 1258 return math.sqrt(msd)
1259 1260 ############################################################################### 1261 ## ISOTROPIC TLS MODEL 1262 ## 1263
1264 -def set_TLSiso_b(b, i, Uiso, w):
1265 """Sets the six rows of vector b with the experimental/target anisotropic 1266 ADP values U starting at index b[i] and ending at b[i+6] with weight w. 1267 """ 1268 b[i] = w * Uiso
1269
1270 -def set_TLSiso_A(A, i, j, x, y, z, w):
1271 """Sets the one row of matrix A starting at A[i,j] with the isotropic 1272 TLS model coefficients for an atom located at t position x, y, z with 1273 least-squares weight w. Matrix A is filled to coumn j+12. 1274 """ 1275 ## use label indexing to avoid confusion! 1276 T, L11, L22, L33, L12, L13, L23, S1, S2, S3 = ( 1277 j,1+j,2+j,3+j,4+j,5+j,6+j,7+j,8+j,9+j) 1278 1279 ## indices of the components of U 1280 UISO = i 1281 1282 ## C Matrix 1283 xx = x*x 1284 yy = y*y 1285 zz = z*z 1286 1287 xy = x*y 1288 xz = x*z 1289 yz = y*z 1290 1291 A[UISO, T] = w * 1.0 1292 1293 A[UISO, L11] = w * ((zz + yy) / 3.0) 1294 A[UISO, L22] = w * ((xx + zz) / 3.0) 1295 A[UISO, L33] = w * ((xx + yy) / 3.0) 1296 1297 A[UISO, L12] = w * ((-2.0 * xy) / 3.0) 1298 A[UISO, L13] = w * ((-2.0 * xz) / 3.0) 1299 A[UISO, L23] = w * ((-2.0 * yz) / 3.0) 1300 1301 A[UISO, S1] = w * (( 2.0 * z) / 3.0) 1302 A[UISO, S2] = w * (( 2.0 * y) / 3.0) 1303 A[UISO, S3] = w * (( 2.0 * x) / 3.0)
1304
1305 -def calc_itls_uiso(T, L, S, position):
1306 """Calculate the TLS predicted uiso from the isotropic TLS model for the 1307 atom at position. 1308 """ 1309 x, y, z = position 1310 1311 xx = x*x 1312 yy = y*y 1313 zz = z*z 1314 1315 ## note: S1 == S21-S12; S2 == S13-S31; S3 == S32-S23 1316 u_tls = T + ( 1317 L[0,0]*(zz+yy) + L[1,1]*(xx+zz) + L[2,2]*(xx+yy) 1318 - 2.0*L[0,1]*x*y - 2.0*L[0,2]*x*z - 2.0*L[1,2]*y*z 1319 + 2.0*S[0]*z + 2.0*S[1]*y + 2.0*S[2]*x) / 3.0 1320 return u_tls
1321
1322 -def iter_itls_uiso(atom_iter, T, L, S, O):
1323 """Iterates the pair (atom, u_iso) 1324 """ 1325 for atm in atom_iter: 1326 yield atm, calc_itls_uiso(T, L, S, atm.position - O)
1327
1328 -def calc_itls_center_of_reaction(iT, iL, iS, origin):
1329 """iT is a single float; iL[3,3]; iS[3] 1330 """ 1331 ## construct TLS tensors from isotropic TLS description 1332 T0 = numpy.array([[iT, 0.0, 0.0], 1333 [0.0, iT, 0.0], 1334 [0.0, 0.0, iT]], float) 1335 1336 L0 = iL.copy() 1337 1338 S0 = numpy.array([ [ 0.0, 0.0, iS[1]], 1339 [iS[0], 0.0, 0.0], 1340 [ 0.0, iS[2], 0.0] ], float) 1341 1342 1343 ## LSMALL is the smallest magnitude of L before it is considered 0.0 1344 LSMALL = 0.5 * Constants.DEG2RAD2 1345 1346 rdict = {} 1347 1348 rdict["T'"] = T0.copy() 1349 rdict["L'"] = L0.copy() 1350 rdict["S'"] = S0.copy() 1351 1352 rdict["rT'"] = T0.copy() 1353 1354 rdict["L1_eigen_val"] = 0.0 1355 rdict["L2_eigen_val"] = 0.0 1356 rdict["L3_eigen_val"] = 0.0 1357 1358 rdict["L1_rmsd"] = 0.0 1359 rdict["L2_rmsd"] = 0.0 1360 rdict["L3_rmsd"] = 0.0 1361 1362 rdict["L1_eigen_vec"] = numpy.zeros(3, float) 1363 rdict["L2_eigen_vec"] = numpy.zeros(3, float) 1364 rdict["L3_eigen_vec"] = numpy.zeros(3, float) 1365 1366 rdict["RHO"] = numpy.zeros(3, float) 1367 rdict["COR"] = origin 1368 1369 rdict["L1_rho"] = numpy.zeros(3, float) 1370 rdict["L2_rho"] = numpy.zeros(3, float) 1371 rdict["L3_rho"] = numpy.zeros(3, float) 1372 1373 rdict["L1_pitch"] = 0.0 1374 rdict["L2_pitch"] = 0.0 1375 rdict["L3_pitch"] = 0.0 1376 1377 rdict["Tr1_eigen_val"] = 0.0 1378 rdict["Tr2_eigen_val"] = 0.0 1379 rdict["Tr3_eigen_val"] = 0.0 1380 1381 rdict["Tr1_rmsd"] = 0.0 1382 rdict["Tr2_rmsd"] = 0.0 1383 rdict["Tr3_rmsd"] = 0.0 1384 1385 ## set the L tensor eigenvalues and eigenvectors 1386 (L_evals, RL) = linalg.eigenvectors(L0) 1387 L1, L2, L3 = L_evals 1388 1389 good_L_eigens = [] 1390 1391 if numpy.allclose(L1, 0.0) or isinstance(L1, complex): 1392 L1 = 0.0 1393 else: 1394 good_L_eigens.append(0) 1395 1396 if numpy.allclose(L2, 0.0) or isinstance(L2, complex): 1397 L2 = 0.0 1398 else: 1399 good_L_eigens.append(1) 1400 1401 if numpy.allclose(L3, 0.0) or isinstance(L3, complex): 1402 L3 = 0.0 1403 else: 1404 good_L_eigens.append(2) 1405 1406 ## no good L eigenvalues 1407 if len(good_L_eigens) == 0: 1408 Tr1, Tr2, Tr3 = linalg.eigenvalues(T0) 1409 1410 if numpy.allclose(Tr1, 0.0) or isinstance(Tr1, complex): 1411 Tr1 = 0.0 1412 if numpy.allclose(Tr2, 0.0) or isinstance(Tr2, complex): 1413 Tr2 = 0.0 1414 if numpy.allclose(Tr3, 0.0) or isinstance(Tr3, complex): 1415 Tr3 = 0.0 1416 1417 rdict["Tr1_eigen_val"] = Tr1 1418 rdict["Tr2_eigen_val"] = Tr2 1419 rdict["Tr3_eigen_val"] = Tr3 1420 1421 rdict["Tr1_rmsd"] = calc_rmsd(Tr1) 1422 rdict["Tr2_rmsd"] = calc_rmsd(Tr2) 1423 rdict["Tr3_rmsd"] = calc_rmsd(Tr3) 1424 return rdict 1425 1426 ## one good eigenvalue -- reconstruct RL about it 1427 elif len(good_L_eigens) == 1: 1428 i = good_L_eigens[0] 1429 evec = RL[i] 1430 1431 RZt = numpy.transpose(AtomMath.rmatrixz(evec)) 1432 xevec = numpy.dot(RZt, numpy.array([1.0, 0.0, 0.0], float)) 1433 yevec = numpy.dot(RZt, numpy.array([0.0, 1.0, 0.0], float)) 1434 1435 if i == 0: 1436 RL[1] = xevec 1437 RL[2] = yevec 1438 elif i == 1: 1439 RL[0] = xevec 1440 RL[2] = yevec 1441 elif i == 2: 1442 RL[0] = xevec 1443 RL[1] = yevec 1444 1445 ## two good eigenvalues -- reconstruct RL about them 1446 elif len(good_L_eigens) == 2: 1447 i = good_L_eigens[0] 1448 j = good_L_eigens[1] 1449 1450 xevec = AtomMath.normalize(numpy.cross(RL[i], RL[j])) 1451 for k in range(3): 1452 if k == i: continue 1453 if k == j: continue 1454 RL[k] = xevec 1455 break 1456 1457 rdict["L1_eigen_val"] = L1 1458 rdict["L2_eigen_val"] = L2 1459 rdict["L3_eigen_val"] = L3 1460 1461 rdict["L1_rmsd"] = calc_rmsd(L1) 1462 rdict["L2_rmsd"] = calc_rmsd(L2) 1463 rdict["L3_rmsd"] = calc_rmsd(L3) 1464 1465 rdict["L1_eigen_vec"] = RL[0].copy() 1466 rdict["L2_eigen_vec"] = RL[1].copy() 1467 rdict["L3_eigen_vec"] = RL[2].copy() 1468 1469 ## begin tensor transformations which depend upon 1470 ## the eigenvectors of L0 being well-determined 1471 ## make sure RLt is right-handed 1472 if numpy.allclose(linalg.determinant(RL), -1.0): 1473 I = numpy.identity(3, float) 1474 I[0,0] = -1.0 1475 RL = numpy.dot(I, RL) 1476 1477 if not numpy.allclose(linalg.determinant(RL), 1.0): 1478 return rdict 1479 1480 RLt = numpy.transpose(RL) 1481 1482 ## carrot-L tensor (tensor WRT principal axes of L) 1483 cL = numpy.dot(numpy.dot(RL, L0), RLt) 1484 1485 ## carrot-T tensor (T tensor WRT principal axes of L) 1486 cT = numpy.dot(numpy.dot(RL, T0), RLt) 1487 1488 ## carrot-S tensor (S tensor WRT principal axes of L) 1489 cS = numpy.dot(numpy.dot(RL, S0), RLt) 1490 1491 ## ^rho: the origin-shift vector in the coordinate system of L 1492 L23 = L2 + L3 1493 L13 = L1 + L3 1494 L12 = L1 + L2 1495 1496 ## shift for L1 1497 if not numpy.allclose(L1, 0.0) and abs(L23)>LSMALL: 1498 crho1 = (cS[1,2] - cS[2,1]) / L23 1499 else: 1500 crho1 = 0.0 1501 1502 if not numpy.allclose(L2, 0.0) and abs(L13)>LSMALL: 1503 crho2 = (cS[2,0] - cS[0,2]) / L13 1504 else: 1505 crho2 = 0.0 1506 1507 if not numpy.allclose(L3, 0.0) and abs(L12)>LSMALL: 1508 crho3 = (cS[0,1] - cS[1,0]) / L12 1509 else: 1510 crho3 = 0.0 1511 1512 crho = numpy.array([crho1, crho2, crho3], float) 1513 1514 ## rho: the origin-shift vector in orthogonal coordinates 1515 rho = numpy.dot(RLt, crho) 1516 rdict["RHO"] = rho 1517 rdict["COR"] = origin + rho 1518 1519 ## set up the origin shift matrix PRHO WRT orthogonal axes 1520 PRHO = numpy.array([ [ 0.0, rho[2], -rho[1]], 1521 [-rho[2], 0.0, rho[0]], 1522 [ rho[1], -rho[0], 0.0] ], float) 1523 1524 ## set up the origin shift matrix cPRHO WRT libration axes 1525 cPRHO = numpy.array([ [ 0.0, crho[2], -crho[1]], 1526 [-crho[2], 0.0, crho[0]], 1527 [ crho[1], -crho[0], 0.0] ], float) 1528 1529 ## calculate transpose of cPRHO, ans cS 1530 cSt = numpy.transpose(cS) 1531 cPRHOt = numpy.transpose(cPRHO) 1532 1533 ## calculate S'^ = S^ + L^*pRHOt 1534 cSp = cS + numpy.dot(cL, cPRHOt) 1535 1536 ## calculate T'^ = cT + cPRHO*S^ + cSt*cPRHOt + cPRHO*cL*cPRHOt * 1537 cTp = cT + numpy.dot(cPRHO, cS) + numpy.dot(cSt, cPRHOt) + \ 1538 numpy.dot(numpy.dot(cPRHO, cL), cPRHOt) 1539 1540 ## transpose of PRHO and S 1541 PRHOt = numpy.transpose(PRHO) 1542 St = numpy.transpose(S0) 1543 1544 ## calculate S' = S + L*PRHOt 1545 Sp = S0 + numpy.dot(L0, PRHOt) 1546 rdict["S'"] = Sp 1547 1548 ## calculate T' = T + PRHO*S + St*PRHOT + PRHO*L*PRHOt 1549 Tp = T0 + numpy.dot(PRHO, S0) + numpy.dot(St, PRHOt) + \ 1550 numpy.dot(numpy.dot(PRHO, L0), PRHOt) 1551 rdict["T'"] = Tp 1552 1553 ## now calculate the TLS motion description using 3 non 1554 ## intersecting screw axes, with one 1555 1556 ## libration axis 1 shift in the L coordinate system 1557 ## you cannot determine axis shifts from the isotropic TLS parameters 1558 cL1rho = numpy.zeros(3, float) 1559 cL2rho = numpy.zeros(3, float) 1560 cL3rho = numpy.zeros(3, float) 1561 1562 ## libration axes shifts in the original orthogonal coordinate system 1563 rdict["L1_rho"] = numpy.dot(RLt, cL1rho) 1564 rdict["L2_rho"] = numpy.dot(RLt, cL2rho) 1565 rdict["L3_rho"] = numpy.dot(RLt, cL3rho) 1566 1567 ## calculate screw pitches (A*R / R*R) = (A/R) 1568 ## no screw pitches either 1569 rdict["L1_pitch"] = 0.0 1570 rdict["L2_pitch"] = 0.0 1571 rdict["L3_pitch"] = 0.0 1572 1573 ## rotate the newly calculated reduced-T tensor from the carrot 1574 ## coordinate system (coordinate system of L) back to the structure 1575 ## coordinate system 1576 Tiso = numpy.trace(Tp) / 3.0 1577 rdict["rT'"] = Tiso * numpy.identity(3, float) 1578 1579 rdict["Tr1_eigen_val"] = Tiso 1580 rdict["Tr2_eigen_val"] = Tiso 1581 rdict["Tr3_eigen_val"] = Tiso 1582 1583 rdict["Tr1_rmsd"] = calc_rmsd(Tiso) 1584 rdict["Tr2_rmsd"] = calc_rmsd(Tiso) 1585 rdict["Tr3_rmsd"] = calc_rmsd(Tiso) 1586 1587 return rdict
1588 1589 ############################################################################### 1590 ## ANISOTROPIC TLS MODEL 1591 ## 1592
1593 -def calc_s11_s22_s33(s2211, s1133):
1594 """Calculates s11, s22, s33 based on s22-s11 and s11-s33 using 1595 the constraint s11+s22+s33=0 1596 """ 1597 s22 = 2.0*(s2211)/3.0 + s1133/3.0 1598 s11 = s22 - s2211 1599 s33 = s11 - s1133 1600 return s11, s22, s33
1601
1602 -def calc_Utls(T, L, S, position):
1603 """Returns the calculated value for the anisotropic U tensor for 1604 the given position. 1605 """ 1606 x, y, z = position 1607 1608 xx = x*x 1609 yy = y*y 1610 zz = z*z 1611 1612 xy = x*y 1613 yz = y*z 1614 xz = x*z 1615 1616 u11 = T[0,0] + L[1,1]*zz + L[2,2]*yy - 2.0*L[1,2]*yz + 2.0*S[1,0]*z - 2.0*S[2,0]*y 1617 u22 = T[1,1] + L[0,0]*zz + L[2,2]*xx - 2.0*L[2,0]*xz - 2.0*S[0,1]*z + 2.0*S[2,1]*x 1618 u33 = T[2,2] + L[0,0]*yy + L[1,1]*xx - 2.0*L[0,1]*xy - 2.0*S[1,2]*x + 2.0*S[0,2]*y 1619 u12 = T[0,1] - L[2,2]*xy + L[1,2]*xz + L[2,0]*yz - L[0,1]*zz - S[0,0]*z + S[1,1]*z + S[2,0]*x - S[2,1]*y 1620 u13 = T[0,2] - L[1,1]*xz + L[1,2]*xy - L[2,0]*yy + L[0,1]*yz + S[0,0]*y - S[2,2]*y + S[1,2]*z - S[1,0]*x 1621 u23 = T[1,2] - L[0,0]*yz - L[1,2]*xx + L[2,0]*xy + L[0,1]*xz - S[1,1]*x + S[2,2]*x + S[0,1]*y - S[0,2]*z 1622 1623 return numpy.array([[u11, u12, u13], 1624 [u12, u22, u23], 1625 [u13, u23, u33]], float)
1626
1627 -def calc_LS_displacement(cor, Lval, Lvec, Lrho, Lpitch, position, prob):
1628 """Returns the amount of rotational displacement from L for an atom at the 1629 given position. 1630 """ 1631 Lrot = Gaussian.GAUSS3C[prob] * calc_rmsd(Lval) 1632 Lorigin = cor + Lrho 1633 D = AtomMath.dmatrixu(Lvec, Lrot) 1634 1635 drot = numpy.dot(D, position - Lorigin) 1636 dscw = (Lrot * Lpitch) * Lvec 1637 1638 return drot + dscw
1639
1640 -def set_TLS_A(A, i, j, x, y, z, w):
1641 """Sets the six rows of matrix A starting at A[i,j] with the TLS 1642 coefficients for an atom located at position x,y,z with least-squares 1643 weight w. Matrix A is filled to row i+6 and column j+20. 1644 """ 1645 ## use label indexing to avoid confusion! 1646 T11, T22, T33, T12, T13, T23, L11, L22, L33, L12, L13, L23, \ 1647 S1133, S2211, S12, S13, S23, S21, S31, S32 = ( 1648 j,1+j,2+j,3+j,4+j,5+j,6+j,7+j,8+j,9+j,10+j,11+j,12+j,13+j,14+j,15+j, 1649 16+j,17+j,18+j,19+j) 1650 1651 ## indices of the components of U 1652 U11 = i 1653 U22 = U11 + 1 1654 U33 = U11 + 2 1655 U12 = U11 + 3 1656 U13 = U11 + 4 1657 U23 = U11 + 5 1658 1659 ## C Matrix 1660 xx = x*x 1661 yy = y*y 1662 zz = z*z 1663 1664 xy = x*y 1665 xz = x*z 1666 yz = y*z 1667 1668 A[U11, T11] = w * 1.0 1669 A[U11, L22] = w * zz 1670 A[U11, L33] = w * yy 1671 A[U11, L23] = w * -2.0 * yz 1672 A[U11, S31] = w * -2.0 * y 1673 A[U11, S21] = w * 2.0 * z 1674 1675 A[U22, T22] = w * 1.0 1676 A[U22, L11] = w * zz 1677 A[U22, L33] = w * xx 1678 A[U22, L13] = w * -2.0 * xz 1679 A[U22, S12] = w * -2.0 * z 1680 A[U22, S32] = w * 2.0 * x 1681 1682 A[U33, T33] = w * 1.0 1683 A[U33, L11] = w * yy 1684 A[U33, L22] = w * xx 1685 A[U33, L12] = w * -2.0 * xy 1686 A[U33, S23] = w * -2.0 * x 1687 A[U33, S13] = w * 2.0 * y 1688 1689 A[U12, T12] = w * 1.0 1690 A[U12, L33] = w * -xy 1691 A[U12, L23] = w * xz 1692 A[U12, L13] = w * yz 1693 A[U12, L12] = w * -zz 1694 A[U12, S2211] = w * z 1695 A[U12, S31] = w * x 1696 A[U12, S32] = w * -y 1697 1698 A[U13, T13] = w * 1.0 1699 A[U13, L22] = w * -xz 1700 A[U13, L23] = w * xy 1701 A[U13, L13] = w * -yy 1702 A[U13, L12] = w * yz 1703 A[U13, S1133] = w * y 1704 A[U13, S23] = w * z 1705 A[U13, S21] = w * -x 1706 1707 A[U23, T23] = w * 1.0 1708 A[U23, L11] = w * -yz 1709 A[U23, L23] = w * -xx 1710 A[U23, L13] = w * xy 1711 A[U23, L12] = w * xz 1712 A[U23, S2211] = w * -x 1713 A[U23, S1133] = w * -x 1714 A[U23, S12] = w * y 1715 A[U23, S13] = w * -z
1716
1717 -def set_TLS_b(b, i, u11, u22, u33, u12, u13, u23, w):
1718 """Sets the six rows of vector b with the experimental/target anisotropic 1719 ADP values U starting at index b[i] and ending at b[i+6] with weight w. 1720 """ 1721 b[i] = w * u11 1722 b[i+1] = w * u22 1723 b[i+2] = w * u33 1724 b[i+3] = w * u12 1725 b[i+4] = w * u13 1726 b[i+5] = w * u23
1727
1728 -def calc_TLS_least_squares_fit(atom_list, origin, weight_dict=None):
1729 """Perform a LSQ-TLS fit on the given AtomList. The TLS tensors 1730 are calculated at the given origin, with weights of weight_dict[atm]. 1731 Return values are T, L, S, lsq_residual. 1732 """ 1733 ## calculate the number of parameters in the model 1734 num_atoms = len(atom_list) 1735 params = 20 1736 1737 A = numpy.zeros((num_atoms * 6, params), float) 1738 B = numpy.zeros(num_atoms * 6, float) 1739 1740 i = -1 1741 for atm in atom_list: 1742 i += 1 1743 iU11 = i * 6 1744 1745 ## is this fit weighted? 1746 if weight_dict is not None: 1747 w = math.sqrt(weight_dict[atm]) 1748 else: 1749 w = 1.0 1750 1751 ## set the b vector 1752 U = atm.get_U() 1753 set_TLS_b(B, iU11, U[0,0], U[1,1], U[2,2], U[0,1], U[0,2], U[1,2], w) 1754 1755 ## set the A matrix 1756 x, y, z = atm.position - origin 1757 set_TLS_A(A, iU11, 0, x, y, z, w) 1758 1759 ## solve by SVD 1760 X = solve_TLS_Ab(A, B) 1761 1762 ## use label indexing to avoid confusion! 1763 T11, T22, T33, T12, T13, T23, L11, L22, L33, L12, L13, L23, \ 1764 S1133, S2211, S12, S13, S23, S21, S31, S32 = ( 1765 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19) 1766 1767 T = numpy.array([ [ X[T11], X[T12], X[T13] ], 1768 [ X[T12], X[T22], X[T23] ], 1769 [ X[T13], X[T23], X[T33] ] ], float) 1770 1771 L = numpy.array([ [ X[L11], X[L12], X[L13] ], 1772 [ X[L12], X[L22], X[L23] ], 1773 [ X[L13], X[L23], X[L33] ] ], float) 1774 1775 s11, s22, s33 = calc_s11_s22_s33(X[S2211], X[S1133]) 1776 1777 S = numpy.array([ [ s11, X[S12], X[S13] ], 1778 [ X[S21], s22, X[S23] ], 1779 [ X[S31], X[S32], s33 ] ], float) 1780 1781 ## calculate the lsq residual 1782 UTLS = numpy.dot(A, X) 1783 D = UTLS - B 1784 lsq_residual = numpy.dot(D, D) 1785 1786 return T, L, S, lsq_residual
1787
1788 -def calc_TLS_center_of_reaction(T0, L0, S0, origin):
1789 """Calculate new tensors based on the center for reaction. 1790 This method returns a dictionary of the calculations: 1791 1792 T^: T tensor in the coordinate system of L 1793 L^: L tensor in the coordinate system of L 1794 S^: S tensor in the coordinate system of L 1795 1796 COR: Center of Reaction 1797 1798 T',S',L': T,L,S tensors in original coordinate system 1799 with the origin shifted to the center of reaction. 1800 """ 1801 ## LSMALL is the smallest magnitude of L before it is considered 0.0 1802 LSMALL = 0.5 * Constants.DEG2RAD2 1803 1804 rdict = {} 1805 1806 rdict["T'"] = T0.copy() 1807 rdict["L'"] = L0.copy() 1808 rdict["S'"] = S0.copy() 1809 1810 rdict["rT'"] = T0.copy() 1811 1812 rdict["L1_eigen_val"] = 0.0 1813 rdict["L2_eigen_val"] = 0.0 1814 rdict["L3_eigen_val"] = 0.0 1815 1816 rdict["L1_rmsd"] = 0.0 1817 rdict["L2_rmsd"] = 0.0 1818 rdict["L3_rmsd"] = 0.0 1819 1820 rdict["L1_eigen_vec"] = numpy.zeros(3, float) 1821 rdict["L2_eigen_vec"] = numpy.zeros(3, float) 1822 rdict["L3_eigen_vec"] = numpy.zeros(3, float) 1823 1824 rdict["RHO"] = numpy.zeros(3, float) 1825 rdict["COR"] = origin 1826 1827 rdict["L1_rho"] = numpy.zeros(3, float) 1828 rdict["L2_rho"] = numpy.zeros(3, float) 1829 rdict["L3_rho"] = numpy.zeros(3, float) 1830 1831 rdict["L1_pitch"] = 0.0 1832 rdict["L2_pitch"] = 0.0 1833 rdict["L3_pitch"] = 0.0 1834 1835 rdict["Tr1_eigen_val"] = 0.0 1836 rdict["Tr2_eigen_val"] = 0.0 1837 rdict["Tr3_eigen_val"] = 0.0 1838 1839 rdict["Tr1_rmsd"] = 0.0 1840 rdict["Tr2_rmsd"] = 0.0 1841 rdict["Tr3_rmsd"] = 0.0 1842 1843 ## set the L tensor eigenvalues and eigenvectors 1844 (L_evals, RL) = linalg.eigenvectors(L0) 1845 L1, L2, L3 = L_evals 1846 1847 good_L_eigens = [] 1848 1849 if numpy.allclose(L1, 0.0) or isinstance(L1, complex): 1850 L1 = 0.0 1851 else: 1852 good_L_eigens.append(0) 1853 1854 if numpy.allclose(L2, 0.0) or isinstance(L2, complex): 1855 L2 = 0.0 1856 else: 1857 good_L_eigens.append(1) 1858 1859 if numpy.allclose(L3, 0.0) or isinstance(L3, complex): 1860 L3 = 0.0 1861 else: 1862 good_L_eigens.append(2) 1863 1864 ## no good L eigenvalues 1865 if len(good_L_eigens) == 0: 1866 return rdict 1867 1868 ## one good eigenvalue -- reconstruct RL about it 1869 elif len(good_L_eigens) == 1: 1870 i = good_L_eigens[0] 1871 evec = RL[i] 1872 1873 RZt = numpy.transpose(AtomMath.rmatrixz(evec)) 1874 xevec = numpy.dot(RZt, numpy.array([1.0, 0.0, 0.0], float)) 1875 yevec = numpy.dot(RZt, numpy.array([0.0, 1.0, 0.0], float)) 1876 1877 if i == 0: 1878 RL[1] = xevec 1879 RL[2] = yevec 1880 elif i == 1: 1881 RL[0] = xevec 1882 RL[2] = yevec 1883 elif i == 2: 1884 RL[0] = xevec 1885 RL[1] = yevec 1886 1887 ## two good eigenvalues -- reconstruct RL about them 1888 elif len(good_L_eigens) == 2: 1889 i = good_L_eigens[0] 1890 j = good_L_eigens[1] 1891 1892 xevec = AtomMath.normalize(numpy.cross(RL[i], RL[j])) 1893 for k in range(3): 1894 if k == i: continue 1895 if k == j: continue 1896 RL[k] = xevec 1897 break 1898 1899 rdict["L1_eigen_val"] = L1 1900 rdict["L2_eigen_val"] = L2 1901 rdict["L3_eigen_val"] = L3 1902 1903 rdict["L1_rmsd"] = calc_rmsd(L1) 1904 rdict["L2_rmsd"] = calc_rmsd(L2) 1905 rdict["L3_rmsd"] = calc_rmsd(L3) 1906 1907 rdict["L1_eigen_vec"] = RL[0].copy() 1908 rdict["L2_eigen_vec"] = RL[1].copy() 1909 rdict["L3_eigen_vec"] = RL[2].copy() 1910 1911 ## begin tensor transformations which depend upon 1912 ## the eigenvectors of L0 being well-determined 1913 ## make sure RLt is right-handed 1914 if numpy.allclose(linalg.determinant(RL), -1.0): 1915 I = numpy.identity(3, float) 1916 I[0,0] = -1.0 1917 RL = numpy.dot(I, RL) 1918 1919 if not numpy.allclose(linalg.determinant(RL), 1.0): 1920 return rdict 1921 1922 RLt = numpy.transpose(RL) 1923 1924 ## carrot-L tensor (tensor WRT principal axes of L) 1925 cL = numpy.dot(numpy.dot(RL, L0), RLt) 1926 rdict["L^"] = cL.copy() 1927 1928 ## carrot-T tensor (T tensor WRT principal axes of L) 1929 cT = numpy.dot(numpy.dot(RL, T0), RLt) 1930 rdict["T^"] = cT.copy() 1931 1932 ## carrot-S tensor (S tensor WRT principal axes of L) 1933 cS = numpy.dot(numpy.dot(RL, S0), RLt) 1934 rdict["S^"] = cS.copy() 1935 1936 ## ^rho: the origin-shift vector in the coordinate system of L 1937 L23 = L2 + L3 1938 L13 = L1 + L3 1939 L12 = L1 + L2 1940 1941 ## shift for L1 1942 if not numpy.allclose(L1, 0.0) and abs(L23)>LSMALL: 1943 crho1 = (cS[1,2] - cS[2,1]) / L23 1944 else: 1945 crho1 = 0.0 1946 1947 if not numpy.allclose(L2, 0.0) and abs(L13)>LSMALL: 1948 crho2 = (cS[2,0] - cS[0,2]) / L13 1949 else: 1950 crho2 = 0.0 1951 1952 if not numpy.allclose(L3, 0.0) and abs(L12)>LSMALL: 1953 crho3 = (cS[0,1] - cS[1,0]) / L12 1954 else: 1955 crho3 = 0.0 1956 1957 crho = numpy.array([crho1, crho2, crho3], float) 1958 rdict["RHO^"] = crho.copy() 1959 1960 ## rho: the origin-shift vector in orthogonal coordinates 1961 rho = numpy.dot(RLt, crho) 1962 rdict["RHO"] = rho 1963 rdict["COR"] = origin + rho 1964 1965 ## set up the origin shift matrix PRHO WRT orthogonal axes 1966 PRHO = numpy.array([ [ 0.0, rho[2], -rho[1]], 1967 [-rho[2], 0.0, rho[0]], 1968 [ rho[1], -rho[0], 0.0] ], float) 1969 1970 ## set up the origin shift matrix cPRHO WRT libration axes 1971 cPRHO = numpy.array([ [ 0.0, crho[2], -crho[1]], 1972 [-crho[2], 0.0, crho[0]], 1973 [ crho[1], -crho[0], 0.0] ], float) 1974 1975 ## calculate transpose of cPRHO, ans cS 1976 cSt = numpy.transpose(cS) 1977 cPRHOt = numpy.transpose(cPRHO) 1978 1979 rdict["L'^"] = cL.copy() 1980 1981 ## calculate S'^ = S^ + L^*pRHOt 1982 cSp = cS + numpy.dot(cL, cPRHOt) 1983 rdict["S'^"] = cSp.copy() 1984 1985 ## calculate T'^ = cT + cPRHO*S^ + cSt*cPRHOt + cPRHO*cL*cPRHOt * 1986 cTp = cT + numpy.dot(cPRHO, cS) + numpy.dot(cSt, cPRHOt) +\ 1987 numpy.dot(numpy.dot(cPRHO, cL), cPRHOt) 1988 rdict["T'^"] = cTp.copy() 1989 1990 ## transpose of PRHO and S 1991 PRHOt = numpy.transpose(PRHO) 1992 St = numpy.transpose(S0) 1993 1994 ## calculate S' = S + L*PRHOt 1995 Sp = S0 + numpy.dot(L0, PRHOt) 1996 rdict["S'"] = Sp 1997 1998 ## calculate T' = T + PRHO*S + St*PRHOT + PRHO*L*PRHOt 1999 Tp = T0 + numpy.dot(PRHO, S0) + numpy.dot(St, PRHOt) +\ 2000 numpy.dot(numpy.dot(PRHO, L0), PRHOt) 2001 rdict["T'"] = Tp 2002 2003 ## now calculate the TLS motion description using 3 non 2004 ## intersecting screw axes, with one 2005 2006 ## libration axis 1 shift in the L coordinate system 2007 if abs(L1) > LSMALL: 2008 cL1rho = numpy.array([0.0, -cSp[0,2]/L1, cSp[0,1]/L1], float) 2009 else: 2010 cL1rho = numpy.zeros(3, float) 2011 2012 ## libration axis 2 shift in the L coordinate system 2013 if abs(L2) > LSMALL: 2014 cL2rho = numpy.array([cSp[1,2]/L2, 0.0, -cSp[1,0]/L2], float) 2015 else: 2016 cL2rho = numpy.zeros(3, float) 2017 2018 ## libration axis 2 shift in the L coordinate system 2019 if abs(L3) > LSMALL: 2020 cL3rho = numpy.array([-cSp[2,1]/L3, cSp[2,0]/L3, 0.0], float) 2021 else: 2022 cL3rho = numpy.zeros(3, float) 2023 2024 ## libration axes shifts in the original orthogonal coordinate system 2025 rdict["L1_rho"] = numpy.dot(RLt, cL1rho) 2026 rdict["L2_rho"] = numpy.dot(RLt, cL2rho) 2027 rdict["L3_rho"] = numpy.dot(RLt, cL3rho) 2028 2029 ## calculate screw pitches (A*R / R*R) = (A/R) 2030 if abs(L1) > LSMALL: 2031 rdict["L1_pitch"] = cS[0,0]/L1 2032 else: 2033 rdict["L1_pitch"] = 0.0 2034 2035 if L2 > LSMALL: 2036 rdict["L2_pitch"] = cS[1,1]/L2 2037 else: 2038 rdict["L2_pitch"] = 0.0 2039 2040 if L3 > LSMALL: 2041 rdict["L3_pitch"] = cS[2,2]/L3 2042 else: 2043 rdict["L3_pitch"] = 0.0 2044 2045 ## now calculate the reduction in T for the screw rotation axes 2046 cTred = cT.copy() 2047 2048 for i in (0, 1, 2): 2049 for k in (0, 1, 2): 2050 if i == k: 2051 continue 2052 if abs(cL[k,k]) > LSMALL: 2053 cTred[i,i] -= (cS[k,i]**2) / cL[k,k] 2054 2055 for i in (0, 1, 2): 2056 for j in (0, 1, 2): 2057 for k in (0, 1, 2): 2058 if j == i: 2059 continue 2060 if abs(cL[k,k]) > LSMALL: 2061 cTred[i,j] -= (cS[k,i]*cS[k,j]) / cL[k,k] 2062 2063 ## rotate the newly calculated reduced-T tensor from the carrot 2064 ## coordinate system (coordinate system of L) back to the structure 2065 ## coordinate system 2066 Tr = numpy.dot(numpy.dot(RLt, cTred), RL) 2067 rdict["rT'"] = Tr 2068 2069 Tr1, Tr2, Tr3 = linalg.eigenvalues(Tr) 2070 2071 if numpy.allclose(Tr1, 0.0) or isinstance(Tr1, complex): 2072 Tr1 = 0.0 2073 if numpy.allclose(Tr2, 0.0) or isinstance(Tr2, complex): 2074 Tr2 = 0.0 2075 if numpy.allclose(Tr3, 0.0) or isinstance(Tr3, complex): 2076 Tr3 = 0.0 2077 2078 rdict["Tr1_eigen_val"] = Tr1 2079 rdict["Tr2_eigen_val"] = Tr2 2080 rdict["Tr3_eigen_val"] = Tr3 2081 2082 rdict["Tr1_rmsd"] = calc_rmsd(Tr1) 2083 rdict["Tr2_rmsd"] = calc_rmsd(Tr2) 2084 rdict["Tr3_rmsd"] = calc_rmsd(Tr3) 2085 2086 return rdict
2087 2088 ############################################################################### 2089 ## TLS + 1 Uiso per Atom 2090 ## 2091
2092 -def calc_TLS_plus_b_least_squares_fit(atom_list, origin, weight_dict=None):
2093 """Perform a LSQ-TLS fit on the given Segment object using 2094 the TLS model with amino acid side chains which can pivot 2095 about the CA atom. This model uses 20 TLS parameters and 6 2096 libration parameters per side chain. 2097 """ 2098 ## calculate the number of parameters in the model 2099 num_atoms = len(atom_list) 2100 params = 20 + num_atoms 2101 2102 A = numpy.zeros((num_atoms * 6, params), float) 2103 B = numpy.zeros(num_atoms * 6, float) 2104 2105 i = -1 2106 for atm in atom_list: 2107 i += 1 2108 iU11 = i * 6 2109 2110 if weight_dict is None: 2111 w = 1.0 2112 else: 2113 w = math.sqrt(weight_dict[atm]) 2114 2115 ## set the b vector 2116 U = atm.get_U() 2117 assert numpy.trace(U) > 0.0 2118 set_TLS_b(B, iU11, U[0,0], U[1,1], U[2,2], U[0,1], U[0,2], U[1,2], w) 2119 2120 ## set the A matrix 2121 x, y, z = atm.position - origin 2122 set_TLS_A(A, iU11, 0, x, y, z, w) 2123 2124 ## set A for additional Uiso / atom 2125 A[iU11, 20+i] = 1.0 2126 A[iU11+1, 20+i] = 1.0 2127 A[iU11+2, 20+i] = 1.0 2128 2129 ## solve by SVD 2130 X = solve_TLS_Ab(A, B) 2131 2132 ## use label indexing to avoid confusion! 2133 T11, T22, T33, T12, T13, T23, L11, L22, L33, L12, L13, L23, \ 2134 S1133, S2211, S12, S13, S23, S21, S31, S32 = ( 2135 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19) 2136 2137 T = numpy.array([ [ X[T11], X[T12], X[T13] ], 2138 [ X[T12], X[T22], X[T23] ], 2139 [ X[T13], X[T23], X[T33] ] ], float) 2140 2141 L = numpy.array([ [ X[L11], X[L12], X[L13] ], 2142 [ X[L12], X[L22], X[L23] ], 2143 [ X[L13], X[L23], X[L33] ] ], float) 2144 2145 s11, s22, s33 = calc_s11_s22_s33(X[S2211], X[S1133]) 2146 2147 S = numpy.array([ [ s11, X[S12], X[S13] ], 2148 [ X[S21], s22, X[S23] ], 2149 [ X[S31], X[S32], s33 ] ], float) 2150 2151 ## calculate the lsq residual 2152 UTLS = numpy.dot(A, X) 2153 D = UTLS - B 2154 lsq_residual = numpy.dot(D, D) 2155 2156 rdict = {} 2157 rdict["T"] = T 2158 rdict["L"] = L 2159 rdict["S"] = S 2160 rdict["lsq_residual"] = lsq_residual 2161 2162 uiso_residual = {} 2163 i = 19 2164 for atm in atom_list: 2165 i += 1 2166 uiso_residual[atm] = X[i] 2167 rdict["uiso_residual"] = uiso_residual 2168 2169 return rdict
2170 2171 ############################################################################### 2172 ## NESTED VIBRATIONAL MODELS 2173 ## 2174 2175 CA_PIVOT_ATOMS = { 2176 "GLY": None, 2177 "ALA": None, 2178 "VAL": "CA", 2179 "LEU": "CA", 2180 "ILE": "CA", 2181 "PRO": None, 2182 "PHE": "CA", 2183 "TYR": "CA", 2184 "TRP": "CA", 2185 "MET": "CA", 2186 "CYS": "CA", 2187 "SER": "CA", 2188 "THR": "CA", 2189 "ASP": "CA", 2190 "GLU": "CA", 2191 "HIS": "CA", 2192 "LYS": "CA", 2193 "ARG": "CA", 2194 "ASN": "CA", 2195 "GLN": "CA" } 2196
2197 -def set_L_A(A, i, j, x, y, z, w):
2198 """Sets coefficients of a L tensor in matrix A for an atom at position 2199 x,y,z and weight w. This starts at A[i,j] and ends at A[i+6,j+6] 2200 Using weight w. 2201 """ 2202 L11, L22, L33, L12, L13, L23 = (j, j+1, j+2, j+3, j+4, j+5) 2203 2204 ## indices of the components of U 2205 U11 = i 2206 U22 = U11 + 1 2207 U33 = U11 + 2 2208 U12 = U11 + 3 2209 U13 = U11 + 4 2210 U23 = U11 + 5 2211 2212 ## TLS coefficients 2213 xx = x * x 2214 yy = y * y 2215 zz = z * z 2216 2217 xy = x * y 2218 xz = x * z 2219 yz = y * z 2220 2221 A[U11, L22] = w * zz 2222 A[U11, L33] = w * yy 2223 A[U11, L23] = w * -2.0 * yz 2224 2225 A[U22, L11] = w * zz 2226 A[U22, L33] = w * xx 2227 A[U22, L13] = w * -2.0 * xz 2228 2229 A[U33, L11] = w * yy 2230 A[U33, L22] = w * xx 2231 A[U33, L12] = w * -2.0 * xy 2232 2233 A[U12, L33] = w * -xy 2234 A[U12, L23] = w * xz 2235 A[U12, L13] = w * yz 2236 A[U12, L12] = w * -zz 2237 2238 A[U13, L22] = w * -xz 2239 A[U13, L23] = w * xy 2240 A[U13, L13] = w * -yy 2241 A[U13, L12] = w * yz 2242 2243 A[U23, L11] = w * -yz 2244 A[U23, L23] = w * -xx 2245 A[U23, L13] = w * xy 2246 A[U23, L12] = w * xz
2247
2248 -def calc_TLSCA_least_squares_fit(segment, origin):
2249 """Perform a LSQ-TLS fit on the given Segment object using the TLS model 2250 with amino acid side chains which can pivot about the CA atom. This model 2251 uses 20 TLS parameters and 6 libration parameters per side chain. 2252 """ 2253 ## calculate the number of parameters in the model 2254 num_atoms = segment.count_atoms() 2255 2256 ## calculate the CB pivot L11 indices for each fragment 2257 num_pivot_frags = 0 2258 i = 20 2259 iL11p = {} 2260 for frag in segment.iter_fragments(): 2261 if CA_PIVOT_ATOMS.get(frag.res_name) is not None: 2262 num_pivot_frags += 1 2263 iL11p[frag] = i 2264 i += 6 2265 2266 params = (6 * num_pivot_frags) + 20 2267 2268 A = numpy.zeros((num_atoms * 6, params), float) 2269 B = numpy.zeros(num_atoms * 6, float) 2270 2271 i = -1 2272 for atm in segment.iter_atoms(): 2273 i += 1 2274 iU11 = i * 6 2275 2276 ## set the b vector 2277 U = atm.get_U() 2278 set_TLS_b(B, iU11, 2279 U[0,0], U[1,1], U[2,2], U[0,1], U[0,2], U[1,2], 2280 1.0) 2281 2282 ## set the A matrix 2283 x, y, z = atm.position - origin 2284 set_TLS_A(A, iU11, 0, x, y, z, 1.0) 2285 2286 ## independent side-chain Ls tensor 2287 frag = atm.get_fragment() 2288 2289 assert frag.is_amino_acid() 2290 2291 if frag.is_amino_acid(): 2292 if atm.name in ["N", "CA", "C", "O"]: 2293 continue 2294 2295 ## get the name of the pivot atom for this residue 2296 patom_name = CA_PIVOT_ATOMS.get(frag.res_name) 2297 if patom_name is not None: 2298 patm = frag.get_atom(patom_name) 2299 assert patm is not None 2300 2301 iL11 = iL11p[frag] 2302 xs, ys, zs = atm.position - patm.position 2303 set_L_A(A, iU11, iL11, xs, ys, zs, 1.0) 2304 2305 ## solve by SVD 2306 X = solve_TLS_Ab(A, B) 2307 2308 ## calculate the lsq residual 2309 UTLS = numpy.dot(A, X) 2310 D = UTLS - B 2311 lsq_residual = numpy.dot(D, D) 2312 2313 ## create the T,L,S tensors 2314 2315 ## use label indexing to avoid confusion! 2316 T11, T22, T33, T12, T13, T23, L11, L22, L33, L12, L13, L23, \ 2317 S1133, S2211, S12, S13, S23, S21, S31, S32 = ( 2318 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19) 2319 2320 T = numpy.array([ [ X[T11], X[T12], X[T13] ], 2321 [ X[T12], X[T22], X[T23] ], 2322 [ X[T13], X[T23], X[T33] ] ], float) 2323 2324 L = numpy.array([ [ X[L11], X[L12], X[L13] ], 2325 [ X[L12], X[L22], X[L23] ], 2326 [ X[L13], X[L23], X[L33] ] ], float) 2327 2328 s11, s22, s33 = calc_s11_s22_s33(X[S2211], X[S1133]) 2329 2330 S = numpy.array([ [ s11, X[S12], X[S13] ], 2331 [ X[S21], s22, X[S23] ], 2332 [ X[S31], X[S32], s33 ] ], float) 2333 2334 ## extract the CA-pivot L tensors 2335 frag_L_dict = {} 2336 for frag in segment.iter_fragments(): 2337 if not iL11p.has_key(frag): 2338 print "NO PIVOT: %s" % (frag) 2339 continue 2340 2341 iL11 = iL11p[frag] 2342 CA_L = numpy.array([ [ X[iL11], X[iL11+3], X[iL11+4] ], 2343 [ X[iL11+3], X[iL11+1], X[iL11+5] ], 2344 [ X[iL11+4], X[iL11+5], X[iL11+2] ] ], float) 2345 2346 frag_L_dict[frag] = CA_L 2347 eval = linalg.eigenvalues(CA_L) * Constants.RAD2DEG2 2348 2349 print "%s %s: %6.2f %6.2f %6.2f" % ( 2350 frag.fragment_id, frag.res_name, eval[0],eval[1],eval[2]) 2351 2352 ## calculate TLSCA-U 2353 udict = {} 2354 i = -1 2355 for atm in segment.iter_atoms(): 2356 i += 1 2357 iU11 = i * 6 2358 2359 U = numpy.array( ((UTLS[iU11], UTLS[iU11+3], UTLS[iU11+4]), 2360 (UTLS[iU11+3], UTLS[iU11+1], UTLS[iU11+5]), 2361 (UTLS[iU11+4], UTLS[iU11+5], UTLS[iU11+2])), float) 2362 2363 udict[atm] = U 2364 2365 ## calculate the center of reaction for the group and 2366 rdict = {} 2367 2368 rdict["T"] = T 2369 rdict["L"] = L 2370 rdict["S"] = S 2371 2372 rdict["lsq_residual"] = lsq_residual 2373 2374 rdict["num_atoms"] = num_atoms 2375 rdict["params"] = params 2376 2377 rdict["udict"] = udict 2378 2379 return rdict
2380 2381 2382 ############################################################################### 2383 ## 2384
2385 -class TLSGroup(Structure.AtomList):
2386 """A subclass of AtomList implementing methods for performing TLS 2387 calculations on the contained Atom instances. 2388 """
2389 - def __init__(self, *args):
2390 Structure.AtomList.__init__(self, *args) 2391 2392 self.name = "" 2393 self.origin = numpy.zeros(3, float) 2394 self.T = numpy.array([[0.0, 0.0, 0.0], 2395 [0.0, 0.0, 0.0], 2396 [0.0, 0.0, 0.0]], float) 2397 self.L = numpy.array([[0.0, 0.0, 0.0], 2398 [0.0, 0.0, 0.0], 2399 [0.0, 0.0, 0.0]], float) 2400 self.S = numpy.array([[0.0, 0.0, 0.0], 2401 [0.0, 0.0, 0.0], 2402 [0.0, 0.0, 0.0]], float)
2403
2404 - def str_old(self):
2405 tstr = "TLS %s\n" % (self.name) 2406 2407 tstr += "ORIGIN %f %f %f\n" % ( 2408 self.origin[0], self.origin[1], self.origin[2]) 2409 2410 tstr += "T %f %f %f %f %f %f\n" % ( 2411 self.T[0,0], self.T[1,1], self.T[2,2], self.T[0,1], self.T[0,2], 2412 self.T[1,2]) 2413 2414 tstr += "L %f %f %f %f %f %f\n" % ( 2415 self.L[0,0], self.L[1,1], self.L[2,2], self.L[0,1], self.L[0,2], 2416 self.L[1,2]) 2417 2418 tstr += "S %f %f %f %f %f %f %f %f\n" % ( 2419 self.S[1,1]-self.S[0,0], self.S[0,0]-self.S[2,2], self.S[0,1], 2420 self.S[0,2], self.S[1,2], self.S[1,0], self.S[2,0], self.S[2,1]) 2421 2422 return tstr
2423
2424 - def set_origin(self, x, y, z):
2425 """Sets the x, y, z components of the TLS origin vector. 2426 """ 2427 self.origin = numpy.array([x, y, z])
2428
2429 - def set_T(self, t11, t22, t33, t12, t13, t23):
2430 """Sets the components of the symmetric T tensor. Units in square 2431 Angstroms. 2432 """ 2433 self.T = numpy.array([[t11, t12, t13], 2434 [t12, t22, t23], 2435 [t13, t23, t33]], float)
2436
2437 - def set_L(self, l11, l22, l33, l12, l13, l23):
2438 """Sets the components of the symmetric L tensor from arguments. 2439 Units should be in square radians. 2440 """ 2441 self.L = numpy.array([[l11, l12, l13], 2442 [l12, l22, l23], 2443 [l13, l23, l33]], float)
2444
2445 - def set_S(self, s2211, s1133, s12, s13, s23, s21, s31, s32):
2446 """Sets the componets of the asymmetric S tenssor. The trace 2447 of the S tensor is set with the standard convention of 2448 the Trace(S) = 0. Units in Radians*Angstroms. 2449 """ 2450 s11, s22, s33 = self.calc_s11_s22_s33(s2211, s1133) 2451 self.S = numpy.array([[s11, s12, s13], 2452 [s21, s22, s23], 2453 [s31, s32, s33]], float)
2454
2455 - def calc_s11_s22_s33(self, s2211, s1133):
2456 """Calculates s11, s22, s33 based on s22-s11 and s11-s33 using 2457 the constraint s11+s22+s33=0 2458 """ 2459 s22 = 2.0*(s2211)/3.0 + s1133/3.0 2460 s11 = s22 - s2211 2461 s33 = s11 - s1133 2462 return s11, s22, s33
2463
2464 - def is_null(self):
2465 """Returns True if the T,L,S tensors are not set, or are set with 2466 values of zero. 2467 """ 2468 if numpy.allclose(numpy.trace(self.T), 0.0) or numpy.allclose(numpy.trace(self.L), 0.0): 2469 return True 2470 return False
2471
2472 - def calc_TLS_least_squares_fit(self, weight_dict=None):
2473 """Perform a least-squares fit of the atoms contained in self 2474 to the three TLS tensors: self.T, self.L, and self.S using the 2475 origin given by self.origin. 2476 """ 2477 T, L, S, lsq_residual = calc_TLS_least_squares_fit(self, self.origin, weight_dict) 2478 2479 self.T = T 2480 self.L = L 2481 self.S = S 2482 2483 return lsq_residual
2484
2485 - def iter_atm_Utls(self):
2486 """Iterates over all the atoms in the TLS object, returning the 2-tuple 2487 (atm, U) where U is the calcuated U value from the current values of 2488 the TLS object's T,L,S, tensors and origin. 2489 """ 2490 T = self.T 2491 L = self.L 2492 S = self.S 2493 o = self.origin 2494 2495 for atm in self: 2496 Utls = calc_Utls(T, L, S, atm.position - o) 2497 yield atm, Utls
2498
2499 - def calc_COR(self):
2500 """Returns the calc_COR() return information for this TLS Group. 2501 """ 2502 return calc_TLS_center_of_reaction(self.T, self.L, self.S, self.origin)
2503
2504 - def shift_COR(self):
2505 """Shift the TLS group to the center of reaction. 2506 """ 2507 cor_desc = self.calc_COR() 2508 self.T = cor_desc["T'"].copy() 2509 self.L = cor_desc["L'"].copy() 2510 self.S = cor_desc["S'"].copy() 2511 self.origin = cor_desc["COR"].copy() 2512 2513 return cor_desc
2514
2515 - def calc_tls_info(self):
2516 """Calculates a number of statistics about the TLS group tensors, 2517 goodness of fit, various parameter averages, center of reaction 2518 tensors, etc... 2519 """ 2520 tls_info = self.calc_COR() 2521 2522 ## EXPERIMENTAL DATA 2523 2524 ## number of atoms 2525 tls_info["num_atoms"] = len(self) 2526 2527 ## mean temp_factor/anisotropy from experimental data (PDB file) 2528 tls_info["exp_mean_temp_factor"] = self.calc_adv_temp_factor() 2529 tls_info["exp_mean_anisotropy"] = self.calc_adv_anisotropy() 2530 2531 ## model temp factors 2532 n = 0 2533 mean_max_tf = 0.0 2534 mean_tf = 0.0 2535 mean_aniso = 0.0 2536 2537 for atm, Utls in self.iter_atm_Utls(): 2538 n += 1 2539 2540 evals = linalg.eigenvalues(Utls) 2541 max_ev = max(evals) 2542 min_ev = min(evals) 2543 2544 mean_max_tf += Constants.U2B * max_ev 2545 mean_tf += Constants.U2B * numpy.trace(Utls) / 3.0 2546 mean_aniso += AtomMath.calc_anisotropy(Utls) 2547 2548 tls_info["tls_mean_max_temp_factor"] = mean_max_tf / n 2549 tls_info["tls_mean_temp_factor"] = mean_tf / n 2550 tls_info["tls_mean_anisotropy"] = mean_aniso / n 2551 2552 return tls_info
2553 2554
2555 -class TLSStructureAnalysis(object):
2556 """Algorithm object for rigid body searches on Structure objects. 2557 """
2558 - def __init__(self, struct):
2559 self.struct = struct
2560
2561 - def iter_segments(self, chain, seg_len):
2562 """This iterator yields a series of Segment objects of width seg_len. 2563 The start at the beginning Fragment of the Chain, and the start point 2564 walks the chain one Fragment at a time until there are not enough 2565 Fragments left to cut Segments of seg_width. 2566 """ 2567 chain_len = len(chain) 2568 2569 for i in range(chain_len): 2570 start = i 2571 end = i + seg_len 2572 2573 if end > chain_len: 2574 break 2575 2576 yield chain[start:end]
2577
2578 - def atom_filter(self, atm, **args):
2579 use_side_chains = args.get("use_side_chains", True) 2580 include_hydrogens = args.get("include_hydrogens", False) 2581 include_frac_occupancy = args.get("include_frac_occupancy", False) 2582 include_single_bond = args.get("include_single_bond", True) 2583 2584 ## omit atoms which are not at full occupancy 2585 if not include_frac_occupancy and atm.occupancy<1.0: 2586 return False 2587 2588 ## omit hydrogens 2589 if not include_hydrogens and atm.element=="H": 2590 return False 2591 2592 ## omit side chain atoms 2593 if not use_side_chains and atm.name not in ("C", "N", "CA", "O"): 2594 return False 2595 2596 ## omit atoms with a single bond 2597 if not include_single_bond and len(atm.bond_list)<=1: 2598 return False 2599 2600 return True
2601
2602 - def iter_fit_TLS_segments(self, **args):
2603 """Run the algorithm to fit TLS parameters to segments of the 2604 structure. This method has many options, which are outlined in 2605 the source code for the method. This returns a list of dictionaries 2606 containing statistics on each of the fit TLS groups, the residues 2607 involved, and the TLS object itself. 2608 """ 2609 import copy 2610 2611 ## arguments 2612 chain_ids = args.get("chain_ids", None) 2613 origin = args.get("origin_of_calc") 2614 residue_width = args.get("residue_width", 6) 2615 use_side_chains = args.get("use_side_chains", True) 2616 include_hydrogens = args.get("include_hydrogens", False) 2617 include_frac_occupancy = args.get("include_frac_occupancy", False) 2618 include_single_bond = args.get("include_single_bond", True) 2619 calc_pivot_model = args.get("calc_pivot_model", False) 2620 2621 2622 for chain in self.struct.iter_chains(): 2623 2624 ## skip some chains 2625 if chain_ids is not None and chain.chain_id not in chain_ids: 2626 continue 2627 2628 ## don't bother with non-biopolymers and small chains 2629 if chain.count_amino_acids() < residue_width: 2630 continue 2631 2632 for segment in self.iter_segments(chain, residue_width): 2633 frag_id1 = segment[0].fragment_id 2634 frag_id2 = segment[-1].fragment_id 2635 name = "%s-%s" % (frag_id1, frag_id2) 2636 frag_id_cntr = segment[len(segment)/2].fragment_id 2637 2638 ## create the TLSGroup 2639 pv_struct = Structure.Structure() 2640 pv_seg = Structure.Chain(chain_id=segment.chain_id, 2641 model_id=segment.model_id) 2642 pv_struct.add_chain(pv_seg) 2643 2644 tls_group = TLSGroup() 2645 2646 ## add atoms into the TLSGroup 2647 ## filter the atoms going into the TLS group 2648 for atm in segment.iter_atoms(): 2649 if self.atom_filter(atm, **args): 2650 tls_group.append(atm) 2651 2652 atm_cp = copy.deepcopy(atm) 2653 pv_seg.add_atom(atm_cp) 2654 2655 ## check for enough atoms(parameters) after atom filtering 2656 if len(tls_group) < 20: 2657 tls_info = { 2658 "name": name, 2659 "chain_id": chain.chain_id, 2660 "frag_id1": frag_id1, 2661 "frag_id2": frag_id2, 2662 "frag_id_cntr": frag_id_cntr, 2663 "num_atoms": len(tls_group), 2664 "error": "Not Enough Atoms"} 2665 yield tls_info 2666 continue 2667 2668 tls_group.origin = tls_group.calc_centroid() 2669 lsq_residual = tls_group.calc_TLS_least_squares_fit() 2670 tls_group.shift_COR() 2671 tls_info = tls_group.calc_tls_info() 2672 tls_info["lsq_residual"] = lsq_residual 2673 2674 ## calculate using CA-pivot TLS model for side chains 2675 if calc_pivot_model == True: 2676 rdict = calc_CB_pivot_TLS_least_squares_fit(pv_seg) 2677 tls_info["ca_pivot"] = rdict 2678 2679 ## add additional information 2680 tls_info["name"] = name 2681 tls_info["chain_id"] = chain.chain_id 2682 tls_info["frag_id1"] = frag_id1 2683 tls_info["frag_id2"] = frag_id2 2684 tls_info["frag_id_cntr"] = frag_id_cntr 2685 tls_info["tls_group"] = tls_group 2686 tls_info["residues"] = segment 2687 tls_info["segment"] = segment 2688 2689 ## this TLS group passes all our tests -- yield it 2690 yield tls_info
2691
2692 - def fit_TLS_segments(self, **args):
2693 """Returns the list iterated by iter_fit_TLS_segments. 2694 """ 2695 tls_info_list = [] 2696 for tls_info in self.iter_fit_TLS_segments(**args): 2697 tls_info_list.append(tls_info) 2698 return tls_info_list
2699 2700 2701 ############################################################################### 2702 ### GLViewer Rendering components for TLS Groups 2703 ### 2704
2705 -def goodness_color(x):
2706 """x in range 0.0->1.0 2707 """ 2708 if x<=0.0: 2709 return (0.0, 0.0, 0.0) 2710 2711 r = math.sqrt(x) 2712 g = max(0.0, x**3) 2713 b = max(0.0, math.sin(2.0 * math.pi * x)) 2714 2715 return (r, g, b)
2716
2717 -class GLTLSAtomList(Viewer.GLAtomList):
2718 """OpenGL visualizations of TLS group atoms. 2719 """
2720 - def __init__(self, **args):
2721 self.tls_group = args["tls_group"] 2722 Viewer.GLAtomList.__init__(self, **args) 2723 self.glo_set_properties_id("GLTLSAtomList") 2724 self.glo_init_properties(**args)
2725
2726 - def glo_install_properties(self):
2727 Viewer.GLAtomList.glo_install_properties(self) 2728 2729 ## Show/Hide 2730 self.glo_add_property( 2731 { "name": "fan_visible", 2732 "desc": "Show COR-Backbone Fan", 2733 "catagory": "Show/Hide", 2734 "type": "boolean", 2735 "default": False, 2736 "action": "recompile" }) 2737 2738 self.glo_add_property( 2739 { "name": "L1_animation_visible", 2740 "desc": "Show L<sub>1</sub> Screw Animation", 2741 "catagory": "Show/Hide", 2742 "type": "boolean", 2743 "default": True, 2744 "action": "redraw" }) 2745 self.glo_add_property( 2746 { "name": "L2_animation_visible", 2747 "desc": "Show L<sub>2</sub> Screw Animation", 2748 "catagory": "Show/Hide", 2749 "type": "boolean", 2750 "default": True, 2751 "action": "redraw" }) 2752 self.glo_add_property( 2753 { "name": "L3_animation_visible", 2754 "desc": "Show L<sub>3</sub> Screw Animation", 2755 "catagory": "Show/Hide", 2756 "type": "boolean", 2757 "default": True, 2758 "action": "redraw" }) 2759 2760 ## TLS 2761 self.glo_add_property( 2762 { "name": "tls_color", 2763 "desc": "TLS Group Color", 2764 "catagory": "TLS", 2765 "type": "enum_string", 2766 "default": "Green", 2767 "enum_list": self.gldl_color_list, 2768 "action": "recompile" }) 2769 self.glo_add_property( 2770 { "name": "fan_opacity", 2771 "desc": "COR-Backbone Fan Opacity", 2772 "catagory": "TLS", 2773 "type": "float", 2774 "range": Viewer.PROP_OPACITY_RANGE, 2775 "default": 1.0, 2776 "action": "recompile_fan" }) 2777 self.glo_add_property( 2778 { "name": "L1_scale", 2779 "desc": "Scale L<sub>1</sub> Rotation", 2780 "catagory": "TLS", 2781 "type": "float", 2782 "default": 1.0, 2783 "action": "redraw" }) 2784 self.glo_add_property( 2785 { "name": "L2_scale", 2786 "desc": "Scale L<sub>2</sub> Rotation", 2787 "catagory": "TLS", 2788 "type": "float", 2789 "default": 1.0, 2790 "action": "redraw" }) 2791 self.glo_add_property( 2792 { "name": "L3_scale", 2793 "desc": "Scale L<sub>3</sub> Rotation", 2794 "catagory": "TLS", 2795 "type": "float", 2796 "default": 1.0, 2797 "action": "redraw" }) 2798 2799 ## TLS Analysis 2800 self.glo_add_property( 2801 { "name": "COR", 2802 "desc": "TLS Center of Reaction", 2803 "catagory": "TLS Analysis", 2804 "read_only": True, 2805 "type": "numpy.array(3)", 2806 "default": numpy.zeros(3, float), 2807 "action": "recompile" }) 2808 self.glo_add_property( 2809 { "name": "T", 2810 "desc": "T<sup>COR</sup> Tensor (A<sup>2</sup>)", 2811 "catagory": "TLS Analysis", 2812 "read_only": True, 2813 "type": "numpy.array(3,3)", 2814 "default": numpy.zeros((3,3), float), 2815 "action": "recompile" }) 2816 self.glo_add_property( 2817 { "name": "rT", 2818 "desc": "T<sup>r</sup> Tensor (A<sup>2</sup>)", 2819 "catagory": "TLS Analysis", 2820 "read_only": True, 2821 "type": "numpy.array(3,3)", 2822 "default": numpy.zeros((3,3), float), 2823 "action": "recompile" }) 2824 self.glo_add_property( 2825 { "name": "L", 2826 "desc": "L<sup>COR</sup> Tensor (DEG<sup>2</sup>)", 2827 "catagory": "TLS Analysis", 2828 "read_only": True, 2829 "type": "numpy.array(3,3)", 2830 "default": numpy.zeros((3,3), float), 2831 "action": "recompile" }) 2832 self.glo_add_property( 2833 { "name": "S", 2834 "desc": "S<sup>COR</sup> Tensor (A*DEG)", 2835 "catagory": "TLS Analysis", 2836 "read_only": True, 2837 "type": "numpy.array(3,3)", 2838 "default": numpy.zeros((3,3), float), 2839 "action": "recompile" }) 2840 self.glo_add_property( 2841 { "name": "L1_eigen_vec", 2842 "desc": "L<sub>1</sub> Eigen Vector", 2843 "catagory": "TLS Analysis", 2844 "read_only": True, 2845 "type": "numpy.array(3)", 2846 "default": numpy.zeros(3, float), 2847 "action": "recompile" }) 2848 self.glo_add_property( 2849 { "name": "L2_eigen_vec", 2850 "desc": "L<sub>2</sub> Eigen Vector", 2851 "catagory": "TLS Analysis", 2852 "read_only": True, 2853 "type": "numpy.array(3)", 2854 "default": numpy.zeros(3, float), 2855 "action": "recompile" }) 2856 self.glo_add_property( 2857 { "name": "L3_eigen_vec", 2858 "desc": "L<sub>3</sub> Eigen Vector", 2859 "catagory": "TLS Analysis", 2860 "read_only": True, 2861 "type": "numpy.array(3)", 2862 "default": numpy.zeros(3, float), 2863 "action": "recompile" }) 2864 self.glo_add_property( 2865 { "name": "L1_eigen_val", 2866 "desc": "L<sub>1</sub> Eigen Value", 2867 "catagory": "TLS Analysis", 2868 "read_only": True, 2869 "type": "float", 2870 "default": 0.0, 2871 "action": "recompile" }) 2872 self.glo_add_property( 2873 { "name": "L2_eigen_val", 2874 "desc": "L<sub>2</sub> Eigen Value", 2875 "catagory": "TLS Analysis", 2876 "read_only": True, 2877 "type": "float", 2878 "default": 0.0, 2879 "action": "recompile" }) 2880 self.glo_add_property( 2881 { "name": "L3_eigen_val", 2882 "desc": "L<sub>3</sub> Eigen Value", 2883 "catagory": "TLS Analysis", 2884 "read_only": True, 2885 "type": "float", 2886 "default": 0.0, 2887 "action": "recompile" }) 2888 self.glo_add_property( 2889 { "name": "L1_rho", 2890 "desc": "L<sub>1</sub> Position from COR", 2891 "catagory": "TLS Analysis", 2892 "read_only": True, 2893 "type": "numpy.array(3)", 2894 "default": numpy.zeros(3, float), 2895 "action": "recompile" }) 2896 self.glo_add_property( 2897 { "name": "L2_rho", 2898 "desc": "L<sub>2</sub> Position from COR", 2899 "catagory": "TLS Analysis", 2900 "read_only": True, 2901 "type": "numpy.array(3)", 2902 "default": numpy.zeros(3, float), 2903 "action": "recompile" }) 2904 self.glo_add_property( 2905 { "name": "L3_rho", 2906 "desc": "L<sub>3</sub> Position from COR", 2907 "catagory": "TLS Analysis", 2908 "read_only": True, 2909 "type": "numpy.array(3)", 2910 "default": numpy.zeros(3, float), 2911 "action": "recompile" }) 2912 self.glo_add_property( 2913 { "name": "L1_pitch", 2914 "desc": "L<sub>1</sub> Screw Pitch (A/DEG)", 2915 "catagory": "TLS Analysis", 2916 "read_only": True, 2917 "type": "float", 2918 "default": 0.0, 2919 "action": "recompile" }) 2920 self.glo_add_property( 2921 { "name": "L2_pitch", 2922 "desc": "L<sub>2</sub> Screw Pitch (A/DEG)", 2923 "catagory": "TLS Analysis", 2924 "read_only": True, 2925 "type": "float", 2926 "default": 0.0, 2927 "action": "recompile" }) 2928 self.glo_add_property( 2929 { "name": "L3_pitch", 2930 "desc": "L<sub>3</sub> Screw Pitch (A/DEG)", 2931 "catagory": "TLS Analysis", 2932 "read_only": True, 2933 "type": "float", 2934 "default": 0.0, 2935 "action": "recompile" }) 2936 2937 ## Simulation State 2938 self.glo_add_property( 2939 { "name": "both_phases", 2940 "desc": "Show Simultanius +/- Phases", 2941 "catagory": "TLS", 2942 "type": "boolean", 2943 "default": False, 2944 "action": "recompile" }) 2945 self.glo_add_property( 2946 { "name": "L1_rot", 2947 "desc": "L<sub>1</sub> Rotation", 2948 "catagory": "TLS", 2949 "type": "float", 2950 "default": 0.0, 2951 "action": "redraw" }) 2952 self.glo_add_property( 2953 { "name": "L2_rot", 2954 "desc": "L<sub>2</sub> Rotation", 2955 "catagory": "TLS", 2956 "type": "float", 2957 "default": 0.0, 2958 "action": "redraw" }) 2959 self.glo_add_property( 2960 { "name": "L3_rot", 2961 "desc": "L<sub>3</sub> Rotation", 2962 "catagory": "TLS", 2963 "type": "float", 2964 "default": 0.0, 2965 "action": "redraw" })
2966
2967 - def gldl_install_draw_methods(self):
2968 Viewer.GLAtomList.gldl_install_draw_methods(self) 2969 2970 self.gldl_draw_method_install( 2971 { "name": "fan", 2972 "func": self.draw_fan, 2973 "visible_property": "fan_visible", 2974 "opacity_property": "fan_opacity", 2975 "recompile_action": "recompile_fan" })
2976
2977 - def gldl_iter_multidraw_self(self):
2978 for draw_flag in Viewer.GLAtomList.gldl_iter_multidraw_self(self): 2979 for draw_flag2 in self.gldl_iter_multidraw_animate(): 2980 yield True
2981
2983 """ 2984 """ 2985 ## optimization: if a rotation of 0.0 degrees was already 2986 ## drawn, then there is no need to draw it again 2987 zero_rot = False 2988 2989 if self.properties["both_phases"]==True: 2990 phase_tuple = (1.0, 0.66, 0.33, 0.0, -0.33, -0.66, -1.0) 2991 else: 2992 phase_tuple = (1.0,) 2993 2994 for Lx_axis, Lx_rho, Lx_pitch, Lx_rot, Lx_scale in ( 2995 ("L1_eigen_vec", "L1_rho", "L1_pitch", "L1_rot", "L1_scale"), 2996 ("L2_eigen_vec", "L2_rho", "L2_pitch", "L2_rot", "L2_scale"), 2997 ("L3_eigen_vec", "L3_rho", "L3_pitch", "L3_rot", "L3_scale") ): 2998 2999 if Lx_axis=="L1_eigen_vec" and self.properties["L1_animation_visible"]==False: 3000 continue 3001 if Lx_axis=="L2_eigen_vec" and self.properties["L2_animation_visible"]==False: 3002 continue 3003 if Lx_axis=="L3_eigen_vec" and self.properties["L3_animation_visible"]==False: 3004 continue 3005 3006 for sign in phase_tuple: 3007 axis = self.properties[Lx_axis] 3008 rho = self.properties[Lx_rho] 3009 pitch = self.properties[Lx_pitch] 3010 3011 rot = sign * self.properties[Lx_rot] * self.properties[Lx_scale] 3012 screw = axis * (rot * pitch) 3013 3014 if numpy.allclose(rot, 0.0): 3015 if zero_rot: 3016 continue 3017 zero_rot = True 3018 3019 self.driver.glr_push_matrix() 3020 3021 self.driver.glr_translate(rho) 3022 self.driver.glr_rotate_axis(rot, axis) 3023 self.driver.glr_translate(-rho + screw) 3024 yield True 3025 3026 self.driver.glr_pop_matrix()
3027
3028 - def glal_iter_atoms(self):
3029 """ 3030 """ 3031 for atm in self.tls_group: 3032 yield atm
3033
3034 - def glal_calc_color(self, atom):
3035 """Overrides the GLAtomList coloring behavior and just 3036 colors using the tls_color. 3037 """ 3038 return self.gldl_property_color_rgbf("tls_color")
3039
3040 - def glal_calc_color_U(self, atom):
3041 r, g, b = self.glal_calc_color(atom) 3042 dim = 0.8 3043 return (r*dim, g*dim, b*dim)
3044 - def glal_calc_color_Uellipse(self, atom):
3045 return self.glal_calc_color_U(atom)
3046 - def glal_calc_color_Urms(self, atom):
3047 return self.glal_calc_color_U(atom)
3048
3049 - def glal_calc_color_trace(self):
3050 return self.gldl_property_color_rgbf("tls_color")
3051
3052 - def glal_calc_U(self, atom):
3053 """Always return the reduced T tensor. 3054 """ 3055 return self.properties["rT"]
3056
3057 - def draw_fan(self):
3058 """Draws a fan from the TLS group center of reaction to the 3059 TLS group backbone atoms. 3060 """ 3061 COR = self.properties["COR"] 3062 r, g, b = self.gldl_property_color_rgbf("tls_color") 3063 a = self.properties["fan_opacity"] 3064 3065 self.driver.glr_set_material_rgba(r, g, b, a) 3066 3067 self.driver.glr_lighting_enable() 3068 self.driver.glr_normalize_enable() 3069 self.driver.glr_light_two_sides_enable() 3070 self.driver.glr_begin_triangle_fan() 3071 3072 ## driver optimization 3073 driver = self.driver 3074 ## 3075 3076 v1 = None 3077 v2 = None 3078 3079 for atm in self.tls_group: 3080 if atm.name != "CA": 3081 continue 3082 3083 if v1 is None: 3084 v1 = atm.position - COR 3085 continue 3086 elif v2 is None: 3087 v2 = atm.position - COR 3088 driver.glr_normal(numpy.cross(v1, v2)) 3089 driver.glr_vertex3(0.0, 0.0, 0.0) 3090 else: 3091 v1 = v2 3092 v2 = atm.position - COR 3093 3094 driver.glr_normal(numpy.cross(v1, v2)) 3095 driver.glr_vertex(v1) 3096 driver.glr_vertex(v2) 3097 3098 self.driver.glr_end() 3099 self.driver.glr_light_two_sides_disable() 3100 self.driver.glr_normalize_disable() 3101 self.driver.glr_lighting_disable()
3102 3103
3104 -class GLTLSGroup(Viewer.GLDrawList):
3105 """Top level visualization object for a TLS group. 3106 """
3107 - def __init__(self, **args):
3108 self.tls_group = args["tls_group"] 3109 self.tls_info = args["tls_info"] 3110 self.tls_name = args["tls_name"] 3111 3112 Viewer.GLDrawList.__init__(self) 3113 self.glo_set_properties_id("GLTLSGroup_%s" % (self.tls_name)) 3114 self.glo_set_name(self.tls_name) 3115 3116 ## add a child GLTLSAtomList for the animated atoms 3117 self.gl_atom_list = GLTLSAtomList( 3118 tls_group = self.tls_group, 3119 trace = True, 3120 lines = False, 3121 fan_visible = False) 3122 3123 self.gl_atom_list.glo_set_name("TLS Atom Animation") 3124 self.gl_atom_list.glo_set_properties_id("gl_atom_list") 3125 self.glo_add_child(self.gl_atom_list) 3126 3127 self.glo_link_child_property( 3128 "symmetry", "gl_atom_list", "symmetry") 3129 3130 self.glo_link_child_property( 3131 "main_chain_visible", "gl_atom_list", "main_chain_visible") 3132 self.glo_link_child_property( 3133 "oatm_visible", "gl_atom_list", "oatm_visible") 3134 self.glo_link_child_property( 3135 "side_chain_visible", "gl_atom_list", "side_chain_visible") 3136 self.glo_link_child_property( 3137 "hetatm_visible", "gl_atom_list", "hetatm_visible") 3138 self.glo_link_child_property( 3139 "water_visible", "gl_atom_list", "water_visible") 3140 self.glo_link_child_property( 3141 "hydrogen_visible", "gl_atom_list", "hydrogen_visible") 3142 3143 self.glo_link_child_property( 3144 "tls_color", "gl_atom_list", "tls_color") 3145 3146 self.glo_link_child_property( 3147 "fan_visible", "gl_atom_list", "fan_visible") 3148 self.glo_link_child_property( 3149 "fan_opacity", "gl_atom_list", "fan_opacity") 3150 self.glo_link_child_property( 3151 "axes_rT", "gl_atom_list", "U") 3152 self.glo_link_child_property( 3153 "ellipse_rT", "gl_atom_list", "ellipse") 3154 self.glo_link_child_property( 3155 "rms_rT", "gl_atom_list", "rms") 3156 3157 self.glo_link_child_property( 3158 "adp_prob", "gl_atom_list", "adp_prob") 3159 3160 self.glo_link_child_property( 3161 "COR", "gl_atom_list", "origin") 3162 self.glo_link_child_property( 3163 "COR", "gl_atom_list", "atom_origin") 3164 self.glo_link_child_property( 3165 "COR", "gl_atom_list", "COR") 3166 self.glo_link_child_property( 3167 "T", "gl_atom_list", "T") 3168 self.glo_link_child_property( 3169 "rT", "gl_atom_list", "rT") 3170 self.glo_link_child_property( 3171 "L", "gl_atom_list", "L") 3172 self.glo_link_child_property( 3173 "S", "gl_atom_list", "S") 3174 3175 self.glo_link_child_property( 3176 "L1_eigen_vec", "gl_atom_list", "L1_eigen_vec") 3177 self.glo_link_child_property( 3178 "L2_eigen_vec", "gl_atom_list", "L2_eigen_vec") 3179 self.glo_link_child_property( 3180 "L3_eigen_vec", "gl_atom_list", "L3_eigen_vec") 3181 3182 self.glo_link_child_property( 3183 "L1_eigen_val", "gl_atom_list", "L1_eigen_val") 3184 self.glo_link_child_property( 3185 "L2_eigen_val", "gl_atom_list", "L2_eigen_val") 3186 self.glo_link_child_property( 3187 "L3_eigen_val", "gl_atom_list", "L3_eigen_val") 3188 3189 self.glo_link_child_property( 3190 "L1_rho", "gl_atom_list", "L1_rho") 3191 self.glo_link_child_property( 3192 "L2_rho", "gl_atom_list", "L2_rho") 3193 self.glo_link_child_property( 3194 "L3_rho", "gl_atom_list", "L3_rho") 3195 3196 self.glo_link_child_property( 3197 "L1_pitch", "gl_atom_list", "L1_pitch") 3198 self.glo_link_child_property( 3199 "L2_pitch", "gl_atom_list", "L2_pitch") 3200 self.glo_link_child_property( 3201 "L3_pitch", "gl_atom_list", "L3_pitch") 3202 3203 self.glo_link_child_property( 3204 "L1_rot", "gl_atom_list", "L1_rot") 3205 self.glo_link_child_property( 3206 "L2_rot", "gl_atom_list", "L2_rot") 3207 self.glo_link_child_property( 3208 "L3_rot", "gl_atom_list", "L3_rot") 3209 3210 self.glo_link_child_property( 3211 "both_phases", "gl_atom_list", "both_phases") 3212 3213 ## initalize properties 3214 self.glo_add_update_callback(self.tls_update_cb) 3215 3216 if not self.tls_group.is_null(): 3217 self.glo_init_properties( 3218 COR = self.tls_info["COR"], 3219 3220 T = self.tls_info["T'"], 3221 rT = self.tls_info["rT'"], 3222 L = self.tls_info["L'"] * Constants.RAD2DEG2, 3223 S = self.tls_info["S'"] * Constants.RAD2DEG, 3224 3225 L1_eigen_vec = self.tls_info["L1_eigen_vec"], 3226 L2_eigen_vec = self.tls_info["L2_eigen_vec"], 3227 L3_eigen_vec = self.tls_info["L3_eigen_vec"], 3228 3229 L1_eigen_val = self.tls_info["L1_eigen_val"] * Constants.RAD2DEG2, 3230 L2_eigen_val = self.tls_info["L2_eigen_val"] * Constants.RAD2DEG2, 3231 L3_eigen_val = self.tls_info["L3_eigen_val"] * Constants.RAD2DEG2, 3232 3233 L1_rho = self.tls_info["L1_rho"], 3234 L2_rho = self.tls_info["L2_rho"], 3235 L3_rho = self.tls_info["L3_rho"], 3236 3237 L1_pitch = self.tls_info["L1_pitch"] * (1.0/Constants.RAD2DEG), 3238 L2_pitch = self.tls_info["L2_pitch"] * (1.0/Constants.RAD2DEG), 3239 L3_pitch = self.tls_info["L3_pitch"] * (1.0/Constants.RAD2DEG), 3240 **args) 3241 else: 3242 self.glo_init_properties(**args)
3243
3244 - def set_tls_groupXXX(self, tls_group):
3245 """Set a new TLSGroup. 3246 """ 3247 self.tls_group = tls_group 3248 3249 if not self.tls_group.is_null(): 3250 self.tls_info = self.tls_group.calc_tls_info() 3251 3252 self.properties.update( 3253 COR = self.tls_info["COR"], 3254 T = self.tls_info["T'"], 3255 Tr = self.tls_info["rT'"], 3256 L = self.tls_info["L'"] * Constants.RAD2DEG2, 3257 S = self.tls_info["S'"] * Constants.RAD2DEG, 3258 3259 L1_eigen_vec = self.tls_info["L1_eigen_vec"], 3260 L2_eigen_vec = self.tls_info["L2_eigen_vec"], 3261 L3_eigen_vec = self.tls_info["L3_eigen_vec"], 3262 3263 L1_eigen_val = self.tls_info["L1_eigen_val"] * Constants.RAD2DEG2, 3264 L2_eigen_val = self.tls_info["L2_eigen_val"] * Constants.RAD2DEG2, 3265 L3_eigen_val = self.tls_info["L3_eigen_val"] * Constants.RAD2DEG2, 3266 3267 L1_rho = self.tls_info["L1_rho"], 3268 L2_rho = self.tls_info["L2_rho"], 3269 L3_rho = self.tls_info["L3_rho"], 3270 3271 L1_pitch = self.tls_info["L1_pitch"] * (1.0/Constants.RAD2DEG), 3272 L2_pitch = self.tls_info["L2_pitch"] * (1.0/Constants.RAD2DEG), 3273 L3_pitch = self.tls_info["L3_pitch"] * (1.0/Constants.RAD2DEG) ) 3274 3275 else: 3276 self.tls_info = None 3277 3278 self.properties.update( 3279 COR = Viewer.GLObject.PropertyDefault, 3280 T = Viewer.GLObject.PropertyDefault, 3281 Tr = Viewer.GLObject.PropertyDefault, 3282 L = Viewer.GLObject.PropertyDefault, 3283 S = Viewer.GLObject.PropertyDefault, 3284 3285 L1_eigen_vec = Viewer.GLObject.PropertyDefault, 3286 L2_eigen_vec = Viewer.GLObject.PropertyDefault, 3287 L3_eigen_vec = Viewer.GLObject.PropertyDefault, 3288 3289 L1_eigen_val = Viewer.GLObject.PropertyDefault, 3290 L2_eigen_val = Viewer.GLObject.PropertyDefault, 3291 L3_eigen_val = Viewer.GLObject.PropertyDefault, 3292 3293 L1_rho = Viewer.GLObject.PropertyDefault, 3294 L2_rho = Viewer.GLObject.PropertyDefault, 3295 L3_rho = Viewer.GLObject.PropertyDefault, 3296 3297 L1_pitch = Viewer.GLObject.PropertyDefault, 3298 L2_pitch = Viewer.GLObject.PropertyDefault, 3299 L3_pitch = Viewer.GLObject.PropertyDefault )
3300
3301 - def glo_install_properties(self):
3302 Viewer.GLDrawList.glo_install_properties(self) 3303 3304 ## TLS Analysis 3305 self.glo_add_property( 3306 { "name": "COR", 3307 "desc": "TLS Center of Reaction", 3308 "catagory": "TLS Analysis", 3309 "read_only": True, 3310 "type": "numpy.array(3)", 3311 "default": numpy.zeros(3, float), 3312 "action": "recompile" }) 3313 self.glo_add_property( 3314 { "name": "COR_vector", 3315 "desc": "TLS Center of Reaction", 3316 "catagory": "TLS Analysis", 3317 "read_only": True, 3318 "type": "numpy.array(3)", 3319 "default": numpy.zeros(3, float), 3320 "action": "recompile" }) 3321 self.glo_add_property( 3322 { "name": "T", 3323 "desc": "T<sup>COR</sup> Tensor (A<sup>2</sup>)", 3324 "catagory": "TLS Analysis", 3325 "read_only": True, 3326 "type": "numpy.array(3,3)", 3327 "default": numpy.zeros((3,3), float), 3328 "action": "recompile" }) 3329 self.glo_add_property( 3330 { "name": "rT", 3331 "desc": "T<sup>r</sup> Tensor (A<sup>2</sup>)", 3332 "catagory": "TLS Analysis", 3333 "read_only": True, 3334 "type": "numpy.array(3,3)", 3335 "default": numpy.zeros((3,3), float), 3336 "action": "recompile" }) 3337 self.glo_add_property( 3338 { "name": "L", 3339 "desc": "L<sup>COR</sup> Tensor (DEG<sup>2</sup>)", 3340 "catagory": "TLS Analysis", 3341 "read_only": True, 3342 "type": "numpy.array(3,3)", 3343 "default": numpy.zeros((3,3), float), 3344 "action": "recompile" }) 3345 self.glo_add_property( 3346 { "name": "S", 3347 "desc": "S<sup>COR</sup> Tensor (A*DEG)", 3348 "catagory": "TLS Analysis", 3349 "read_only": True, 3350 "type": "numpy.array(3,3)", 3351 "default": numpy.zeros((3,3), float), 3352 "action": "recompile" }) 3353 self.glo_add_property( 3354 { "name": "L1_eigen_vec", 3355 "desc": "L<sub>1</sub> Eigen Vector", 3356 "catagory": "TLS Analysis", 3357 "read_only": True, 3358 "type": "numpy.array(3)", 3359 "default": numpy.zeros(3, float), 3360 "action": "recompile" }) 3361 self.glo_add_property( 3362 { "name": "L2_eigen_vec", 3363 "desc": "L<sub>2</sub> Eigen Vector", 3364 "catagory": "TLS Analysis", 3365 "read_only": True, 3366 "type": "numpy.array(3)", 3367 "default": numpy.zeros(3, float), 3368 "action": "recompile" }) 3369 self.glo_add_property( 3370 { "name": "L3_eigen_vec", 3371 "desc": "L<sub>3</sub> Eigen Vector", 3372 "catagory": "TLS Analysis", 3373 "read_only": True, 3374 "type": "numpy.array(3)", 3375 "default": numpy.zeros(3, float), 3376 "action": "recompile" }) 3377 self.glo_add_property( 3378 { "name": "L1_eigen_val", 3379 "desc": "L<sub>1</sub> Eigen Value", 3380 "catagory": "TLS Analysis", 3381 "read_only": True, 3382 "type": "float", 3383 "default": 0.0, 3384 "action": "recompile" }) 3385 self.glo_add_property( 3386 { "name": "L2_eigen_val", 3387 "desc": "L<sub>2</sub> Eigen Value", 3388 "catagory": "TLS Analysis", 3389 "read_only": True, 3390 "type": "float", 3391 "default": 0.0, 3392 "action": "recompile" }) 3393 self.glo_add_property( 3394 { "name": "L3_eigen_val", 3395 "desc": "L<sub>3</sub> Eigen Value", 3396 "catagory": "TLS Analysis", 3397 "read_only": True, 3398 "type": "float", 3399 "default": 0.0, 3400 "action": "recompile" }) 3401 self.glo_add_property( 3402 { "name": "L1_rho", 3403 "desc": "L<sub>1</sub> Position from COR", 3404 "catagory": "TLS Analysis", 3405 "read_only": True, 3406 "type": "numpy.array(3)", 3407 "default": numpy.zeros(3, float), 3408 "action": "recompile" }) 3409 self.glo_add_property( 3410 { "name": "L2_rho", 3411 "desc": "L<sub>2</sub> Position from COR", 3412 "catagory": "TLS Analysis", 3413 "read_only": True, 3414 "type": "numpy.array(3)", 3415 "default": numpy.zeros(3, float), 3416 "action": "recompile" }) 3417 self.glo_add_property( 3418 { "name": "L3_rho", 3419 "desc": "L<sub>3</sub> Position from COR", 3420 "catagory": "TLS Analysis", 3421 "read_only": True, 3422 "type": "numpy.array(3)", 3423 "default": numpy.zeros(3, float), 3424 "action": "recompile" }) 3425 self.glo_add_property( 3426 { "name": "L1_pitch", 3427 "desc": "L<sub>1</sub> Screw Pitch (A/DEG)", 3428 "catagory": "TLS Analysis", 3429 "read_only": True, 3430 "type": "float", 3431 "default": 0.0, 3432 "action": "recompile" }) 3433 self.glo_add_property( 3434 { "name": "L2_pitch", 3435 "desc": "L<sub>2</sub> Screw Pitch (A/DEG)", 3436 "catagory": "TLS Analysis", 3437 "read_only": True, 3438 "type": "float", 3439 "default": 0.0, 3440 "action": "recompile" }) 3441 self.glo_add_property( 3442 { "name": "L3_pitch", 3443 "desc": "L<sub>3</sub> Screw Pitch (A/DEG)", 3444 "catagory": "TLS Analysis", 3445 "read_only": True, 3446 "type": "float", 3447 "default": 0.0, 3448 "action": "recompile" }) 3449 self.glo_add_property( 3450 { "name": "gof", 3451 "desc": "Goodness of Fit", 3452 "catagory": "TLS Analysis", 3453 "read_only": True, 3454 "type": "float", 3455 "default": 0.0, 3456 "action": "recompile" }) 3457 3458 ## Show/Hide 3459 self.glo_add_property( 3460 { "name": "symmetry", 3461 "desc": "Show Symmetry Equivelant", 3462 "catagory": "Show/Hide", 3463 "type": "boolean", 3464 "default": False, 3465 "action": "redraw" }) 3466 self.glo_add_property( 3467 { "name": "main_chain_visible", 3468 "desc": "Show Main Chain Atoms", 3469 "catagory": "Show/Hide", 3470 "type": "boolean", 3471 "default": True, 3472 "action": ["recompile", "recalc_positions"] }) 3473 self.glo_add_property( 3474 { "name": "oatm_visible", 3475 "desc": "Show Main Chain Carbonyl Atoms", 3476 "catagory": "Show/Hide", 3477 "type": "boolean", 3478 "default": True, 3479 "action": ["recompile", "recalc_positions"] }) 3480 self.glo_add_property( 3481 { "name": "side_chain_visible", 3482 "desc": "Show Side Chain Atoms", 3483 "catagory": "Show/Hide", 3484 "type": "boolean", 3485 "default": True, 3486 "action": ["recompile", "recalc_positions"] }) 3487 self.glo_add_property( 3488 { "name": "hetatm_visible", 3489 "desc": "Show Hetrogen Atoms", 3490 "catagory": "Show/Hide", 3491 "type": "boolean", 3492 "default": True, 3493 "action": ["recompile", "recalc_positions"] }) 3494 self.glo_add_property( 3495 { "name": "water_visible", 3496 "desc": "Show Waters", 3497 "catagory": "Show/Hide", 3498 "type": "boolean", 3499 "default": False, 3500 "action": ["recompile", "recalc_positions"] }) 3501 self.glo_add_property( 3502 { "name": "hydrogen_visible", 3503 "desc": "Show Hydrogens", 3504 "catagory": "Show/Hide", 3505 "type": "boolean", 3506 "default": False, 3507 "action": ["recompile", "recalc_positions"] }) 3508 self.glo_add_property( 3509 { "name": "fan_visible", 3510 "desc": "Show COR-Backbone Fan", 3511 "catagory": "Show/Hide", 3512 "type": "boolean", 3513 "default": False, 3514 "action": "recompile" }) 3515 self.glo_add_property( 3516 { "name": "TLS_visible", 3517 "desc": "Show TLS T<sup>r</sup> Ellipsoid/Screw Axes", 3518 "catagory": "Show/Hide", 3519 "type": "boolean", 3520 "default": True, 3521 "action": "recompile_tensors" }) 3522 self.glo_add_property( 3523 { "name": "U", 3524 "desc": "Show U<sup>TLS</sup> Thermal Axes", 3525 "catagory": "Show/Hide", 3526 "type": "boolean", 3527 "default": False, 3528 "action": "recompile_Utls_axes" }) 3529 self.glo_add_property( 3530 { "name": "ellipse", 3531 "desc": "Show U<sup>TLS</sup> Thermal Ellipsoids", 3532 "catagory": "Show/Hide", 3533 "type": "boolean", 3534 "default": False, 3535 "action": "recompile_Utls_ellipse" }) 3536 self.glo_add_property( 3537 { "name": "rms", 3538 "desc": "Show U<sup>TLS</sup> Thermal Peanuts", 3539 "catagory": "Show/Hide", 3540 "type": "boolean", 3541 "default": False, 3542 "action": "recompile_Utls_rms" }) 3543 3544 self.glo_add_property( 3545 { "name": "axes_rT", 3546 "desc": "Show T<sup>r</sup> Thermal Axes", 3547 "catagory": "Show/Hide", 3548 "type": "boolean", 3549 "default": False, 3550 "action": "redraw" }) 3551 self.glo_add_property( 3552 { "name": "ellipse_rT", 3553 "desc": "Show T<sup>r</sup> Thermal Ellipsoids", 3554 "catagory": "Show/Hide", 3555 "type": "boolean", 3556 "default": False, 3557 "action": "redraw" }) 3558 self.glo_add_property( 3559 { "name": "rms_rT", 3560 "desc": "Show T<sup>r</sup> Thermal Peanuts", 3561 "catagory": "Show/Hide", 3562 "type": "boolean", 3563 "default": False, 3564 "action": "recompile_Utls_rms" }) 3565 3566 self.glo_add_property( 3567 { "name": "L1_visible", 3568 "desc": "Show Screw L1 Displacement Surface", 3569 "catagory": "Show/Hide", 3570 "type": "boolean", 3571 "default": False, 3572 "action": "recompile_surface" }) 3573 self.glo_add_property( 3574 { "name": "L2_visible", 3575 "desc": "Show Screw L2 Displacement Surface", 3576 "catagory": "Show/Hide", 3577 "type": "boolean", 3578 "default": False, 3579 "action": "recompile_surface" }) 3580 self.glo_add_property( 3581 { "name": "L3_visible", 3582 "desc": "Show Screw L3 Displacement Surface", 3583 "catagory": "Show/Hide", 3584 "type": "boolean", 3585 "default": False, 3586 "action": "recompile_surface" }) 3587 3588 ## TLS 3589 self.glo_add_property( 3590 { "name": "add_biso", 3591 "desc": "Add Atom B<sup>ISO</sup> to U<sup>TLS</sup>", 3592 "catagory": "TLS", 3593 "type": "boolean", 3594 "default": False, 3595 "action": "recompile" }) 3596 self.glo_add_property( 3597 { "name": "both_phases", 3598 "desc": "Show Simultanius +/- Phases", 3599 "catagory": "TLS", 3600 "type": "boolean", 3601 "default": False, 3602 "action": "recompile" }) 3603 self.glo_add_property( 3604 { "name": "tls_color", 3605 "desc": "TLS Group Visualization Color", 3606 "catagory": "TLS", 3607 "type": "enum_string", 3608 "default": "Green", 3609 "enum_list": self.gldl_color_list, 3610 "action": ["redraw", "recompile"] }) 3611 self.glo_add_property( 3612 { "name": "adp_prob", 3613 "desc": "Isoprobability Magnitude", 3614 "catagory": "TLS", 3615 "type": "integer", 3616 "range": Viewer.PROP_PROBABILTY_RANGE, 3617 "default": 50, 3618 "action": "recompile" }) 3619 self.glo_add_property( 3620 { "name": "L_axis_scale", 3621 "desc": "Scale Screw Axis Length", 3622 "catagory": "TLS", 3623 "type": "float", 3624 "default": 5.00, 3625 "action": "recompile_tensors" }) 3626 self.glo_add_property( 3627 { "name": "L_axis_radius", 3628 "desc": "Screw Axes Radius", 3629 "catagory": "TLS", 3630 "type": "float", 3631 "default": 0.4, 3632 "action": "recompile_tensors" }) 3633 self.glo_add_property( 3634 { "name": "ellipse_opacity", 3635 "desc": "U<sup>TLS</sup> Thermal Ellipsoid Opacity", 3636 "catagory": "TLS", 3637 "type": "float", 3638 "range": Viewer.PROP_OPACITY_RANGE, 3639 "default": 1.0, 3640 "action": "recompile_Utls_ellipse" }) 3641 self.glo_add_property( 3642 { "name": "rms_opacity", 3643 "desc": "U<sup>TLS</sup> Thermal Peanut Opacity", 3644 "catagory": "TLS", 3645 "type": "float", 3646 "range": Viewer.PROP_OPACITY_RANGE, 3647 "default": 1.0, 3648 "action": "recompile_Utls_rms" }) 3649 self.glo_add_property( 3650 { "name": "surface_opacity", 3651 "desc": "Screw Surface Opacity", 3652 "catagory": "TLS", 3653 "type": "float", 3654 "range": Viewer.PROP_OPACITY_RANGE, 3655 "default": 1.0, 3656 "action": "recompile_surface" }) 3657 self.glo_add_property( 3658 { "name": "fan_opacity", 3659 "desc": "COR-Backbone Fan Opacity", 3660 "catagory": "TLS", 3661 "type": "float", 3662 "range": Viewer.PROP_OPACITY_RANGE, 3663 "default": 1.0, 3664 "action": "recompile_fan" }) 3665 self.glo_add_property( 3666 { "name": "time", 3667 "desc": "Simulation Time", 3668 "catagory": "TLS", 3669 "type": "float", 3670 "default": 0.0, 3671 "action": "redraw" }) 3672 self.glo_add_property( 3673 { "name": "period", 3674 "desc": "Simulation Period", 3675 "catagory": "TLS", 3676 "type": "float", 3677 "default": 1.0, 3678 "action": "redraw" }) 3679 self.glo_add_property( 3680 { "name": "amplitude", 3681 "desc": "Simulation Amplitude", 3682 "catagory": "TLS", 3683 "type": "float", 3684 "default": 1.0, 3685 "action": "redraw" }) 3686 self.glo_add_property( 3687 { "name": "L1_rot", 3688 "desc": "L<sub>1</sub> Simulated Rotation (DEG)", 3689 "catagory": "TLS", 3690 "type": "float", 3691 "default": 0.0, 3692 "action": "redraw" }) 3693 self.glo_add_property( 3694 { "name": "L2_rot", 3695 "desc": "L<sub>2</sub> Simulated Rotation (DEG)", 3696 "catagory": "TLS", 3697 "type": "float", 3698 "default": 0.0, 3699 "action": "redraw" }) 3700 self.glo_add_property( 3701 { "name": "L3_rot", 3702 "desc": "L<sub>3</sub> Simulated Rotation (DEG)", 3703 "catagory": "TLS", 3704 "type": "float", 3705 "default": 0.0, 3706 "action": "redraw" })
3707
3708 - def gldl_install_draw_methods(self):
3709 self.gldl_draw_method_install( 3710 { "name": "tls_tensors", 3711 "func": self.draw_tensors, 3712 "transparent": False, 3713 "visible_property": "TLS_visible", 3714 "recompile_action": "recompile_tensors" }) 3715 self.gldl_draw_method_install( 3716 { "name": "Utls_axes", 3717 "func": self.draw_Utls_axes, 3718 "transparent": False, 3719 "visible_property": "U", 3720 "recompile_action": "recompile_Utls_axes" }) 3721 self.gldl_draw_method_install( 3722 { "name": "Utls_ellipse", 3723 "func": self.draw_Utls_ellipse, 3724 "visible_property": "ellipse", 3725 "opacity_property": "ellipse_opacity", 3726 "recompile_action": "recompile_Utls_ellipse" }) 3727 self.gldl_draw_method_install( 3728 { "name": "Utls_rms", 3729 "func": self.draw_Utls_rms, 3730 "visible_property": "rms", 3731 "opacity_property": "rms_opacity", 3732 "recompile_action": "recompile_Utls_rms" }) 3733 self.gldl_draw_method_install( 3734 { "name": "L1_surface", 3735 "func": self.draw_L1_surface, 3736 "visible_property": "L1_visible", 3737 "opacity_property": "surface_opacity", 3738 "recompile_action": "recompile_surface" }) 3739 self.gldl_draw_method_install( 3740 { "name": "L2_surface", 3741 "func": self.draw_L2_surface, 3742 "visible_property": "L2_visible", 3743 "opacity_property": "surface_opacity", 3744 "recompile_action": "recompile_surface" }) 3745 self.gldl_draw_method_install( 3746 { "name": "L3_surface", 3747 "func": self.draw_L3_surface, 3748 "visible_property": "L3_visible", 3749 "opacity_property": "surface_opacity", 3750 "recompile_action": "recompile_surface" })
3751
3752 - def tls_update_cb(self, updates, actions):
3753 if "time" in updates or "adp_prob" in updates: 3754 self.update_time()
3755
3756 - def update_time(self):
3757 """Changes the time of the TLS group simulating harmonic motion. 3758 """ 3759 if self.tls_group.is_null(): 3760 return 3761 3762 ## time should be in the range 0.0-0.1.0 3763 sin_tm = math.sin(2.0 * math.pi * self.properties["period"] * self.properties["time"]) 3764 3765 ## calculate L eigenvalue displacements at the given 3766 ## probability levels 3767 C = Gaussian.GAUSS3C[self.properties["adp_prob"]] 3768 3769 L1_rot = self.properties["amplitude"] * C * calc_rmsd(self.properties["L1_eigen_val"]) * sin_tm 3770 L2_rot = self.properties["amplitude"] * C * calc_rmsd(self.properties["L2_eigen_val"]) * sin_tm 3771 L3_rot = self.properties["amplitude"] * C * calc_rmsd(self.properties["L3_eigen_val"]) * sin_tm 3772 3773 self.glo_update_properties(L1_rot=L1_rot, L2_rot=L2_rot, L3_rot=L3_rot)
3774
3775 - def gldl_iter_multidraw_self(self):
3776 """Specialized draw list invokation to recycle the draw list for 3777 symmetry related copies. Cartesian versions of the symmetry rotation 3778 and translation operators are generated by GLStructure/UnitCell 3779 classes. 3780 """ 3781 if self.properties["symmetry"]==False: 3782 yield True 3783 3784 else: 3785 3786 gl_struct = self.glo_get_glstructure() 3787 if gl_struct is None: 3788 yield True 3789 3790 else: 3791 for symop in gl_struct.iter_orth_symops(): 3792 self.driver.glr_push_matrix() 3793 self.driver.glr_mult_matrix_Rt(symop.R, symop.t) 3794 yield True 3795 self.driver.glr_pop_matrix()
3796
3797 - def gltls_iter_atoms(self):
3798 """Special atom iterator for the TLS drawing functions yields: 3799 atm, Utls 3800 """ 3801 T = self.tls_group.T 3802 L = self.tls_group.L 3803 S = self.tls_group.S 3804 o = self.tls_group.origin 3805 3806 for atm, visible in self.gl_atom_list.glal_iter_atoms_filtered(): 3807 if not visible: 3808 continue 3809 3810 Utls = calc_Utls(T, L, S, atm.position - o) 3811 3812 if self.properties["add_biso"] == True: 3813 if atm.temp_factor is not None: 3814 Utls = Utls + (Constants.B2U * atm.temp_factor * numpy.identity(3, float)) 3815 3816 yield atm, Utls
3817
3818 - def draw_tensors(self):
3819 """Draw tensor axis. 3820 """ 3821 if self.tls_group.is_null(): 3822 return 3823 3824 self.driver.glr_push_matrix() 3825 3826 ## get the TLS color 3827 r, g, b = self.gldl_property_color_rgbf("tls_color") 3828 3829 self.driver.glr_translate(self.properties["COR"]) 3830 3831 ## cor vector 3832 self.driver.glr_set_material_rgb(0.5, 0.5, 0.5) 3833 vec = self.properties["COR_vector"] 3834 if AtomMath.length(vec) > 1.0: 3835 vec2 = 2.0 * vec 3836 self.driver.glr_axis(-vec2 / 2.0, vec2, self.properties["L_axis_radius"]) 3837 3838 self.driver.glr_set_material_rgb(r, g, b) 3839 3840 ## T: units (A^2) 3841 self.driver.glr_Uellipse((0.0,0.0,0.0), self.properties["rT"], self.properties["adp_prob"]) 3842 3843 ## L: units (DEG^2) 3844 L_scale = self.properties["L_axis_scale"] 3845 3846 3847 for Lx_eigen_val, Lx_eigen_vec, Lx_rho, Lx_pitch in [ 3848 ("L1_eigen_val", "L1_eigen_vec", "L1_rho", "L1_pitch"), 3849 ("L2_eigen_val", "L2_eigen_vec", "L2_rho", "L2_pitch"), 3850 ("L3_eigen_val", "L3_eigen_vec", "L3_rho", "L3_pitch")]: 3851 3852 L_eigen_vec = self.properties[Lx_eigen_vec] 3853 L_eigen_val = self.properties[Lx_eigen_val] 3854 L_rho = self.properties[Lx_rho] 3855 L_pitch = self.properties[Lx_pitch] 3856 3857 C = Gaussian.GAUSS3C[self.properties["adp_prob"]] 3858 L_rot = C * (L_scale * calc_rmsd(L_eigen_val)) 3859 3860 if L_eigen_val <= 0.0: 3861 continue 3862 3863 L_v = L_eigen_vec * L_rot 3864 3865 ## line from COR to center of screw/rotation axis 3866 ## draw lines from COR to the axis 3867 self.driver.glr_lighting_disable() 3868 self.driver.glr_line((0.0, 0.0, 0.0), L_rho) 3869 3870 ## draw axis 3871 self.driver.glr_axis(L_rho - (0.5*L_v), L_v, self.properties["L_axis_radius"]) 3872 3873 ## draw disks with translational displacement 3874 L_screw_dis = L_eigen_vec * L_rot * L_pitch 3875 3876 self.driver.glr_axis( 3877 L_rho - (0.5 * L_screw_dis), 3878 L_screw_dis, 3879 1.5 * self.properties["L_axis_radius"]) 3880 3881 self.driver.glr_pop_matrix()
3882
3883 - def draw_Utls_axes(self):
3884 """Render the anisotropic thremal axes calculated from the TLS 3885 model. 3886 """ 3887 if self.tls_group.is_null(): 3888 return 3889 3890 prob = self.properties["adp_prob"] 3891 rgbf = self.gldl_property_color_rgbf("tls_color") 3892 3893 glr_Uaxes = self.driver.glr_Uaxes 3894 3895 for atm, Utls in self.gltls_iter_atoms(): 3896 glr_Uaxes(atm.position, Utls, prob, rgbf, 1.0)
3897
3898 - def draw_Utls_ellipse(self):
3899 """Render the anisotropic thremal ellipsoids at the given probability 3900 contour calculated from the TLS model. 3901 """ 3902 if self.tls_group.is_null(): 3903 return 3904 3905 prob = self.properties["adp_prob"] 3906 r, g, b = self.gldl_property_color_rgbf("tls_color") 3907 a = self.properties["ellipse_opacity"] 3908 self.driver.glr_set_material_rgba(r, g, b, a) 3909 3910 glr_Uellipse = self.driver.glr_Uellipse 3911 3912 for atm, Utls in self.gltls_iter_atoms(): 3913 glr_Uellipse(atm.position, Utls, prob)
3914
3915 - def draw_Utls_rms(self):
3916 """Render the anisotropic thremal peanuts calculated from the TLS 3917 model. 3918 """ 3919 if self.tls_group.is_null(): 3920 return 3921 3922 r, g, b = self.gldl_property_color_rgbf("tls_color") 3923 a = self.properties["rms_opacity"] 3924 self.driver.glr_set_material_rgb(r, g, b, a) 3925 3926 for atm, Utls in self.gltls_iter_atoms(): 3927 self.driver.glr_Urms(atm.position, Utls)
3928
3929 - def draw_L1_surface(self):
3930 if self.tls_group.is_null(): 3931 return 3932 self.draw_tls_surface( 3933 self.properties["L1_eigen_vec"], 3934 self.properties["L1_eigen_val"], 3935 self.properties["L1_rho"], 3936 self.properties["L1_pitch"])
3937
3938 - def draw_L2_surface(self):
3939 if self.tls_group.is_null(): 3940 return 3941 self.draw_tls_surface( 3942 self.properties["L2_eigen_vec"], 3943 self.properties["L2_eigen_val"], 3944 self.properties["L2_rho"], 3945 self.properties["L2_pitch"])
3946
3947 - def draw_L3_surface(self):
3948 if self.tls_group.is_null(): 3949 return 3950 self.draw_tls_surface( 3951 self.properties["L3_eigen_vec"], 3952 self.properties["L3_eigen_val"], 3953 self.properties["L3_rho"], 3954 self.properties["L3_pitch"])
3955
3956 - def draw_tls_surface(self, Lx_eigen_vec, Lx_eigen_val, Lx_rho, Lx_pitch):
3957 """Draws the TLS probability surface for a single non-intersecting 3958 screw axis. Lx_eigen_val is the vaiance (mean square deviation MSD) 3959 of the rotation about the Lx_eigen_vec axis. 3960 """ 3961 ## create a unique list of bonds which will be used to 3962 ## render the TLS surface; this list may be passed in a argument 3963 ## to avoid multiple calculations for each screw-rotation axis 3964 bond_list = [] 3965 in_dict = {} 3966 3967 for atm, Utls in self.gltls_iter_atoms(): 3968 in_dict[atm] = True 3969 3970 for atm, Utls in self.gltls_iter_atoms(): 3971 for bond in atm.iter_bonds(): 3972 if in_dict.has_key(bond.get_partner(atm)): 3973 bond_list.append(bond) 3974 3975 ## this just won't work... 3976 if numpy.allclose(Lx_eigen_val, 0.0): 3977 return 3978 3979 C = Gaussian.GAUSS3C[self.properties["adp_prob"]] 3980 Lx_s = C * calc_rmsd(Lx_eigen_val * Constants.DEG2RAD2) 3981 if numpy.allclose(Lx_s, 0.0): 3982 return 3983 3984 Lx_pitch = Lx_pitch * (1.0 / Constants.DEG2RAD) 3985 COR = self.properties["COR"] 3986 Lx_origin = COR + Lx_rho 3987 steps = 1 3988 rot_step = Lx_s / float(steps) 3989 3990 self.driver.glr_light_two_sides_enable() 3991 self.driver.glr_lighting_enable() 3992 self.driver.glr_normalize_enable() 3993 3994 r, g, b = self.gldl_property_color_rgbf("tls_color") 3995 a = self.properties["surface_opacity"] 3996 gam = 0.50 3997 self.driver.glr_set_material_rgba(r*gam, g*gam, b*gam, a) 3998 3999 4000 self.driver.glr_begin_quads() 4001 4002 ## driver optimization 4003 glr_normal = self.driver.glr_normal 4004 glr_vertex = self.driver.glr_vertex 4005 ## 4006 4007 for step in range(steps): 4008 rot_start = rot_step * float(step) 4009 rot_end = rot_step * float(step + 1) 4010 4011 for sign in (-1.0, 1.0): 4012 rot1 = rot_start * sign 4013 rot2 = rot_end * sign 4014 4015 Rstep1 = AtomMath.rmatrixu(Lx_eigen_vec, rot1) 4016 Rstep2 = AtomMath.rmatrixu(Lx_eigen_vec, rot2) 4017 4018 screw1 = Lx_eigen_vec * (rot1 * Lx_pitch) 4019 screw2 = Lx_eigen_vec * (rot2 * Lx_pitch) 4020 4021 for bond in bond_list: 4022 4023 pos1 = bond.atom1.position - Lx_origin 4024 pos2 = bond.atom2.position - Lx_origin 4025 4026 v1 = numpy.dot(Rstep1, pos1) + screw1 4027 v2 = numpy.dot(Rstep2, pos1) + screw2 4028 v3 = numpy.dot(Rstep2, pos2) + screw2 4029 v4 = numpy.dot(Rstep1, pos2) + screw1 4030 4031 ## one normal perpendicular to the quad 4032 glr_normal(numpy.cross(v2-v1, v4-v1)) 4033 4034 glr_vertex(v1 + Lx_origin) 4035 glr_vertex(v2 + Lx_origin) 4036 glr_vertex(v3 + Lx_origin) 4037 glr_vertex(v4 + Lx_origin) 4038 4039 self.driver.glr_end() 4040 self.driver.glr_light_two_sides_disable() 4041 self.driver.glr_normalize_disable() 4042 self.driver.glr_lighting_disable()
4043
4044 -class GLTLSChain(Viewer.GLDrawList):
4045 """Collects a list of GLTLSGroup instances which are all in the 4046 same chain. 4047 """
4048 - def __init__(self, **args):
4049 Viewer.GLDrawList.__init__(self) 4050 self.glo_set_properties_id("GLTLSChain_%s" % (args["chain_id"])) 4051 self.glo_set_name("TLS Chain %s" % (args["chain_id"])) 4052 self.glo_add_update_callback(self.update_cb) 4053 self.glo_init_properties(**args)
4054
4055 - def glo_install_properties(self):
4056 Viewer.GLDrawList.glo_install_properties(self) 4057 4058 ## show/hide 4059 self.glo_add_property( 4060 { "name": "symmetry", 4061 "desc": "Show Symmetry Equivelant", 4062 "catagory": "Show/Hide", 4063 "type": "boolean", 4064 "default": False, 4065 "action": "" }) 4066 self.glo_add_property( 4067 { "name": "main_chain_visible", 4068 "desc": "Show Main Chain Atoms", 4069 "catagory": "Show/Hide", 4070 "type": "boolean", 4071 "default": True, 4072 "action": "" }) 4073 self.glo_add_property( 4074 { "name": "oatm_visible", 4075 "desc": "Show Main Chain Carbonyl Atoms", 4076 "catagory": "Show/Hide", 4077 "type": "boolean", 4078 "default": True, 4079 "action": ["recompile", "recalc_positions"] }) 4080 self.glo_add_property( 4081 { "name": "side_chain_visible", 4082 "desc": "Show Side Chain Atoms", 4083 "catagory": "Show/Hide", 4084 "type": "boolean", 4085 "default": True, 4086 "action": "" }) 4087 self.glo_add_property( 4088 { "name": "hetatm_visible", 4089 "desc": "Show Hetrogen Atoms", 4090 "catagory": "Show/Hide", 4091 "type": "boolean", 4092 "default": True, 4093 "action": "" }) 4094 self.glo_add_property( 4095 { "name": "water_visible", 4096 "desc": "Show Waters", 4097 "catagory": "Show/Hide", 4098 "type": "boolean", 4099 "default": False, 4100 "action": "" }) 4101 self.glo_add_property( 4102 { "name": "hydrogen_visible", 4103 "desc": "Show Hydrogens", 4104 "catagory": "Show/Hide", 4105 "type": "boolean", 4106 "default": False, 4107 "action": "" }) 4108 self.glo_add_property( 4109 { "name": "fan_visible", 4110 "desc": "Show COR-Backbone Fan", 4111 "catagory": "Show/Hide", 4112 "type": "boolean", 4113 "default": False, 4114 "action": "recompile" }) 4115 self.glo_add_property( 4116 { "name": "TLS_visible", 4117 "desc": "Show TLS T<sup>r</sup> Ellipsoid/Screw Axes", 4118 "catagory": "Show/Hide", 4119 "type": "boolean", 4120 "default": True, 4121 "action": "" }) 4122 self.glo_add_property( 4123 { "name": "U", 4124 "desc": "Show U<sup>TLS</sup> Thermal Axes", 4125 "catagory": "Show/Hide", 4126 "type": "boolean", 4127 "default": False, 4128 "action": "" }) 4129 self.glo_add_property( 4130 { "name": "ellipse", 4131 "desc": "Show U<sup>TLS</sup> Thermal Ellipsoids", 4132 "catagory": "Show/Hide", 4133 "type": "boolean", 4134 "default": False, 4135 "action": "" }) 4136 self.glo_add_property( 4137 { "name": "rms", 4138 "desc": "Show U<sup>TLS</sup> Thermal Peanuts", 4139 "catagory": "Show/Hide", 4140 "type": "boolean", 4141 "default": False, 4142 "action": "" }) 4143 self.glo_add_property( 4144 { "name": "axes_rT", 4145 "desc": "Show T<sup>r</sup> Thermal Axes", 4146 "catagory": "Show/Hide", 4147 "type": "boolean", 4148 "default": False, 4149 "action": "" }) 4150 self.glo_add_property( 4151 { "name": "ellipse_rT", 4152 "desc": "Show T<sup>r</sup> Thermal Ellipsoids", 4153 "catagory": "Show/Hide", 4154 "type": "boolean", 4155 "default": False, 4156 "action": "" }) 4157 self.glo_add_property( 4158 { "name": "rms_rT", 4159 "desc": "Show T<sup>r</sup> Thermal Peanuts", 4160 "catagory": "Show/Hide", 4161 "type": "boolean", 4162 "default": False, 4163 "action": "" }) 4164 self.glo_add_property( 4165 { "name": "L1_visible", 4166 "desc": "Show L<sub>1</sub> Screw Displacement Surface", 4167 "catagory": "Show/Hide", 4168 "type": "boolean", 4169 "default": False, 4170 "action": "" }) 4171 self.glo_add_property( 4172 { "name": "L2_visible", 4173 "desc": "Show L<sub>2</sub> Screw Displacement Surface", 4174 "catagory": "Show/Hide", 4175 "type": "boolean", 4176 "default": False, 4177 "action": "" }) 4178 self.glo_add_property( 4179 { "name": "L3_visible", 4180 "desc": "Show L<sub>3</sub> Screw Displacement Surface", 4181 "catagory": "Show/Hide", 4182 "type": "boolean", 4183 "default": False, 4184 "action": "" }) 4185 4186 ## TLS 4187 self.glo_add_property( 4188 { "name": "add_biso", 4189 "desc": "Add Atom B<sup>ISO</sup> to U<sup>TLS</sup>", 4190 "catagory": "TLS", 4191 "type": "boolean", 4192 "default": False, 4193 "action": "" }) 4194 self.glo_add_property( 4195 { "name": "both_phases", 4196 "desc": "Show Simultanius +/- Phases", 4197 "catagory": "TLS", 4198 "type": "boolean", 4199 "default": False, 4200 "action": "recompile" }) 4201 self.glo_add_property( 4202 { "name": "adp_prob", 4203 "desc": "Isoprobability Magnitude", 4204 "catagory": "TLS", 4205 "type": "integer", 4206 "range": Viewer.PROP_PROBABILTY_RANGE, 4207 "default": 50, 4208 "action": "" }) 4209 4210 self.glo_add_property( 4211 { "name": "L_axis_scale", 4212 "desc": "Scale Screw Axis Length", 4213 "catagory": "TLS", 4214 "type": "float", 4215 "default": 5.00, 4216 "action": "recompile_tensors" }) 4217 self.glo_add_property( 4218 { "name": "L_axis_radius", 4219 "desc": "Screw Axes Radius", 4220 "catagory": "TLS", 4221 "type": "float", 4222 "default": 0.4, 4223 "action": "" }) 4224 self.glo_add_property( 4225 { "name": "ellipse_opacity", 4226 "desc": "U<sup>TLS</sup> Thermal Ellipsoid Opacity", 4227 "catagory": "TLS", 4228 "type": "float", 4229 "range": Viewer.PROP_OPACITY_RANGE, 4230 "default": 1.0, 4231 "action": "" }) 4232 self.glo_add_property( 4233 { "name": "rms_opacity", 4234 "desc": "U<sup>TLS</sup> Thermal Peanut Opacity", 4235 "catagory": "TLS", 4236 "type": "float", 4237 "range": Viewer.PROP_OPACITY_RANGE, 4238 "default": 1.0, 4239 "action": "" }) 4240 self.glo_add_property( 4241 { "name": "surface_opacity", 4242 "desc": "Screw Displacement Surface Opacity", 4243 "catagory": "TLS", 4244 "type": "float", 4245 "range": Viewer.PROP_OPACITY_RANGE, 4246 "default": 1.0, 4247 "action": "" }) 4248 self.glo_add_property( 4249 { "name": "fan_opacity", 4250 "desc": "COR-Backbone Fan Opacity", 4251 "catagory": "TLS", 4252 "type": "float", 4253 "range": Viewer.PROP_OPACITY_RANGE, 4254 "default": 1.0, 4255 "action": "recompile_fan" }) 4256 4257 ## color methods 4258 self.glo_add_property( 4259 { "name": "color_method", 4260 "desc": "TLS Group Coloring Scheme", 4261 "catagory": "Macros", 4262 "type": "enum_string", 4263 "default": "Color by Group", 4264 "enum_list": ["Color By Group", "Color By Goodness of Fit"], 4265 "action": "recolor" }) 4266 self.glo_add_property( 4267 { "name": "show_frac", 4268 "desc": "Show Fraction of Top Fitting Groups", 4269 "catagory": "Macros", 4270 "type": "integer", 4271 "range": "0-100,1", 4272 "default": 100, 4273 "action": "recolor" }) 4274 self.glo_add_property( 4275 { "name": "style1", 4276 "desc": "Cool Visualization Style #1", 4277 "catagory": "Macros", 4278 "type": "boolean", 4279 "default": False, 4280 "action": "style1" })
4281
4282 - def update_cb(self, updates, actions):
4283 if "recolor" in actions: 4284 if self.properties["color_method"]=="Color By Goodness of Fit": 4285 show_frac = float(self.properties["show_frac"] / 100.0) 4286 self.color_by_gof(show_frac) 4287 elif self.properties["color_method"]=="Color By Group": 4288 self.color_by_group() 4289 4290 if "style1" in actions and self.properties["style1"]==True: 4291 self.properties.update(style1=False) 4292 self.set_style1()
4293
4294 - def set_style1(self):
4295 self.properties.update( 4296 L1_visible = True, 4297 L2_visible = True, 4298 L3_visible = True) 4299 4300 for gl_tls_group in self.glo_iter_children(): 4301 gl_tls_group.properties.update( 4302 time = 0.25) 4303 4304 gl_tls_group.gl_atom_list.properties.update( 4305 trace = False, 4306 ball_stick = True, 4307 ball_radius = 0.075, 4308 stick_radius = 0.075)
4309
4310 - def color_by_group(self):
4311 """Color TLS Groups by 4312 """ 4313 colori = 2 4314 for gl_tls_group in self.glo_iter_children(): 4315 try: 4316 tls_color = Colors.COLOR_NAMES_CAPITALIZED[colori] 4317 except IndexError: 4318 colori = 2 4319 tls_color = Colors.COLOR_NAMES_CAPITALIZED[colori] 4320 4321 gl_tls_group.properties.update( 4322 visible = True, 4323 tls_color=tls_color) 4324 4325 colori += 1
4326
4327 - def color_by_gof(self, show_frac):
4328 """Color TLS Groups by goodness-of-fit. 4329 """ 4330 gof_list = [] 4331 4332 for gl_tls_group in self.glo_iter_children(): 4333 gof = gl_tls_group.properties["gof"] 4334 gof_list.append((gof, gl_tls_group)) 4335 4336 if len(gof_list)==0: 4337 return 4338 elif len(gof_list)==1: 4339 return 4340 4341 ## sort from highest->lowest since the gof metric is a minimization 4342 ## residual 4343 gof_list.sort() 4344 gof_list.reverse() 4345 4346 ## n is the number to show 4347 n = int(round(float(len(gof_list)) * show_frac)) 4348 i = len(gof_list) - n 4349 4350 ## hide the groups with the lowest gof values below the show_frac 4351 ## percentage 4352 for j in range(i): 4353 gof, gl_tls_group = gof_list[j] 4354 gl_tls_group.properties.update( 4355 visible = False, 4356 tls_color = "gray") 4357 4358 ## remove the hidden groups 4359 gof_list = gof_list[i:] 4360 4361 min_gof = gof_list[0][0] 4362 max_gof = gof_list[-1][0] 4363 4364 ## a reasonable range is needed to color by goodness of fit 4365 gof_range = max_gof - min_gof 4366 if numpy.allclose(gof_range, 0.0): 4367 for gof, gl_tls_group in gof_list: 4368 gl_tls_group.properties.update( 4369 visible = True, 4370 tls_color = "gray") 4371 return 4372 4373 for gof, gl_tls_group in gof_list: 4374 goodness = 1.0 - (gof - min_gof) / gof_range 4375 tls_color = "%4.2f,%4.2f,%4.2f" % (goodness_color(goodness)) 4376 4377 ## set TLS color for group based on goodness of fit 4378 gl_tls_group.properties.update( 4379 visible = True, 4380 tls_color = tls_color) 4381 4382 ## set trace radius based on goodness of fit 4383 gl_tls_group.gl_atom_list.properties.update( 4384 trace_radius = 0.3 + (goodness * 0.01))
4385
4386 - def add_gl_tls_group(self, gl_tls_group):
4387 self.glo_add_child(gl_tls_group) 4388 4389 child_id = gl_tls_group.glo_get_properties_id() 4390 4391 self.glo_link_child_property( 4392 "symmetry", child_id, "symmetry") 4393 4394 self.glo_link_child_property( 4395 "main_chain_visible", child_id, "main_chain_visible") 4396 self.glo_link_child_property( 4397 "oatm_visible", child_id, "oatm_visible") 4398 self.glo_link_child_property( 4399 "side_chain_visible", child_id, "side_chain_visible") 4400 self.glo_link_child_property( 4401 "hetatm_visible", child_id, "hetatm_visible") 4402 self.glo_link_child_property( 4403 "water_visible", child_id, "water_visible") 4404 self.glo_link_child_property( 4405 "hydrogen_visible", child_id, "hydrogen_visible") 4406 4407 self.glo_link_child_property( 4408 "fan_visible", child_id, "fan_visible") 4409 self.glo_link_child_property( 4410 "fan_opacity", child_id, "fan_opacity") 4411 self.glo_link_child_property( 4412 "TLS_visible", child_id, "TLS_visible") 4413 4414 self.glo_link_child_property( 4415 "U", child_id, "U") 4416 self.glo_link_child_property( 4417 "ellipse", child_id, "ellipse") 4418 self.glo_link_child_property( 4419 "rms", child_id, "rms") 4420 4421 self.glo_link_child_property( 4422 "axes_rT", child_id, "axes_rT") 4423 self.glo_link_child_property( 4424 "ellipse_rT", child_id, "ellipse_rT") 4425 self.glo_link_child_property( 4426 "rms_rT", child_id, "rms_rT") 4427 4428 self.glo_link_child_property( 4429 "L1_visible", child_id, "L1_visible") 4430 self.glo_link_child_property( 4431 "L2_visible", child_id, "L2_visible") 4432 self.glo_link_child_property( 4433 "L3_visible", child_id, "L3_visible") 4434 self.glo_link_child_property( 4435 "add_biso", child_id, "add_biso") 4436 self.glo_link_child_property( 4437 "both_phases", child_id, "both_phases") 4438 self.glo_link_child_property( 4439 "adp_prob", child_id, "adp_prob") 4440 self.glo_link_child_property( 4441 "L_axis_scale", child_id, "L_axis_scale") 4442 self.glo_link_child_property( 4443 "L_axis_radius", child_id, "L_axis_radius") 4444 self.glo_link_child_property( 4445 "ellipse_opacity", child_id, "ellipse_opacity") 4446 self.glo_link_child_property( 4447 "rms_opacity", child_id, "rms_opacity") 4448 self.glo_link_child_property( 4449 "surface_opacity", child_id, "surface_opacity") 4450 4451 ## update coloring 4452 if self.properties["color_method"]=="Color By Goodness of Fit": 4453 show_frac = float(self.properties["show_frac"] / 100.0) 4454 self.color_by_gof(show_frac) 4455 else: 4456 self.color_by_group()
4457 4458 4459 ## <testing>
4460 -def test_module():
4461 print "===============================================" 4462 print "TEST CASE 1: TLS Class" 4463 print 4464 4465 tls = TLSGroup() 4466 tls.name = "All protein" 4467 tls.set_origin(18.885, 49.302, 13.315) 4468 tls.set_T(0.0263, 0.0561, 0.0048, -0.0128, 0.0065, -0.0157) 4469 tls.set_L(0.9730, 5.1496, 0.8488, 0.2151,-0.1296, 0.0815) 4470 tls.set_S(0.0007, 0.0281, 0.0336, -0.0446,-0.2288, -0.0551, 4471 0.0487, 0.0163) 4472 4473 print tls 4474 4475 print "eigenvalues(T)" 4476 print linalg.eigenvalues(tls.T) 4477 print "eigenvalues(L)" 4478 print linalg.eigenvalues(tls.L) 4479 4480 print "===============================================" 4481 4482 print
4483 4484 ## print "===============================================" 4485 ## print "TEST CASE 2: TLS/REFMAC file loading" 4486 4487 ## import sys 4488 4489 ## fil = open(sys.argv[1], "r") 4490 ## tls_list = LoadTLSGroups(fil) 4491 4492 ## for tls in tls_list: 4493 ## print "----- TLS Group #%d ---" % (tls_list.index(tls)) 4494 ## print tls 4495 4496 ## print "eigenvalues(T)" 4497 ## print linalg.eigenvalues(tls.T) 4498 ## print "eigenvalues(L)" 4499 ## print linalg.eigenvalues(tls.L) 4500 4501 ## print "-----------------------" 4502 4503 ## print "===============================================" 4504 4505 if __name__ == "__main__": 4506 test_module() 4507 4508 ## </testing> 4509