1#A* ------------------------------------------------------------------- 2#B* This file contains source code for the PyMOL computer program 3#C* Copyright (c) Schrodinger, LLC. 4#D* ------------------------------------------------------------------- 5#E* It is unlawful to modify or remove this copyright notice. 6#F* ------------------------------------------------------------------- 7#G* Please see the accompanying LICENSE file for further information. 8#H* ------------------------------------------------------------------- 9#I* Additional authors of this source file include: 10#-* Filipe Maia (slicing code) 11#-* 12#-* 13#Z* ------------------------------------------------------------------- 14 15from __future__ import print_function, absolute_import 16 17if True: 18 19 import pymol 20 from . import selector 21 import traceback 22 cmd = __import__("sys").modules["pymol.cmd"] 23 import re 24 import gzip 25 import os 26 from .cmd import _cmd, Shortcut, is_list, is_string, \ 27 safe_list_eval, safe_alpha_list_eval, \ 28 DEFAULT_ERROR, DEFAULT_SUCCESS, is_ok, is_error, \ 29 is_tuple 30 import tempfile 31 import sys 32 33 from chempy import fragments 34 35 map_type_dict = { 36 'vdw' : 0, 37 'coulomb' : 1, 38 'gaussian' : 2, # gaussian summation 39 'coulomb_neutral' : 3, 40 'coulomb_local' : 4, 41 'gaussian_max' : 5, # gaussian maximum contributor 42 } 43 44 map_type_sc = Shortcut(map_type_dict.keys()) 45 46 ramp_spectrum_dict = { 47 "traditional" : 1, 48 "sludge" : 2, 49 "ocean" : 3, 50 "hot" : 4, 51 "grayable" : 5, 52 "rainbow" : 6, 53 "afmhot" : 7, 54 "grayscale" : 8, 55 "object" : [[-1.0,-1.0,-1.0]] 56 } 57 58 ramp_spectrum_sc = Shortcut(ramp_spectrum_dict.keys()) 59 60 group_action_dict = { 61 "add" : 1, 62 "remove" : 2, 63 "open" : 3, 64 "close" : 4, 65 "toggle" : 5, 66 "auto" : 6, 67 "ungroup" : 7, 68 "empty" : 8, 69 "purge" : 9, 70 "excise" : 10, 71 } 72 73 group_action_sc = Shortcut(group_action_dict.keys()) 74 75 # must correspond to the driver's constants 76 reflection_format_dict = { 77 "cns" : 1, 78 "mtz" : 2, 79 "cif" : 3 80 } 81 82 def group(name, members="", action='auto', quiet=1,_self=cmd): 83 ''' 84 85DESCRIPTION 86 87 "group" creates or updates a group object: a container for 88 organizing objects into a hierarchy. 89 90USAGE 91 92 group name [, members [, action ]] 93 94ARGUMENTS 95 96 name = string: name of the group 97 98 members = string: space-separated list of objects to include in 99 the group 100 101 action = add, remove, open, close, toggle, auto, empty, 102 purge, excise 103 104ACTIONS 105 106 add: add members to group 107 remove: remove members from group (members will be ungrouped) 108 empty: remove all members from group 109 purge: remove all members from group and delete them 110 excise: remove all members from group and delete group 111 open: expand group display in object menu panel 112 close: collapse group display in object menu panel 113 toggle: toggle group display in object menu panel 114 auto: add or toggle 115 ungroup: DEPRECATED, use ungroup command 116 117EXAMPLE 118 119 group kinases, 1oky 1pkg 1t46 1uwh 1z5m 120 group kinases, open 121 group kinases, close 122 123NOTES 124 125 Group objects can typically be used as arguments to commands. In 126 such cases, the command should be applied to all members of the 127 group. If the group is used as a selection, then all atoms in all 128 objects in the group should be included in the selection. 129 130 When a group objects is open, objects can be added or removed from 131 the group by right-clicking and dragging in the control panel. 132 133SEE ALSO 134 135 ungroup, order, "group_auto_mode" setting 136 137''' 138 action = group_action_dict[group_action_sc.auto_err(str(action),'group action')] 139 if name=='all': name='*' 140 if action == 6: # auto 141 if len(members): 142 action = 1 # add 143 elif '*' in name or name in _self.get_names(): 144 action = 5 # toggle 145 else: 146 action = 1 # add 147 elif action == 7: 148 print('action=ungroup is deprecated, use the "ungroup" command') 149 with _self.lockcm: 150 return _cmd.group(_self._COb,str(name),str(members),int(action),int(quiet)) 151 152 def ungroup(members, quiet=1, _self=cmd): 153 ''' 154 155DESCRIPTION 156 157 "ungroup" removes an object from a group object, returning it to 158 the top level. 159 160USAGE 161 162 ungroup name 163 164 165SEE ALSO 166 167 group 168 169 ''' 170 with _self.lockcm: 171 return _cmd.group(_self._COb, "", str(members), 7, int(quiet)) 172 173 def map_generate(name, reflection_file, amplitudes, phases, weights="None", 174 reso_low=50.0, reso_high=1.0,quiet=1,zoom=1,_self=cmd): 175 ''' 176 177DESCRIPTION 178 179 "map_generate" generates a map object from a PDB object or selection and 180 reflection data. 181 182 Experimental use with caution. 183 184USAGE 185 186 map_generate name, reflection_file, amplitudes, phases, weights [, 187 reso_low [, reso_high ]] 188 189ARGUMENTS 190 191 name = string: name of the map object to create or modify 192 193 reflection_file = string: name of reflection file on disk; if None, then 194 PyMOL attempts to download the CIF file from the PDB. 195 Default = None; attempt to download from PDB. 196 197 amplitudes = string: fully qualified apmlitudes column name. Properly 198 qualified names are: project/crysta/column. For example, 199 KINASE/cryastl1/FWT. 200 201 phases = string: fully qualified phases column name. Properly 202 qualified names are: project/crystal/column. For example, 203 KINASE/crystal1/DELPHWT. 204 205 weights = string: fully qualified phases column name. Properly 206 qualified names are: project/crystal/column. For example, 207 KINASE/crystal1/FOM. 208 209 reso_low = float : minimum resolution; if set to equal max_reso, then 210 reso_low and reso_high will be read from the reflection file. 211 212 reso_high = float : maximum resolution; if set to equal min_reso then 213 reso_low and reso_high will be read from the reflection file. 214 215NOTES 216 217 This function can be used to synthesize x-ray maps from the reflection data. 218 Supported reflection file formats are "mtz". Other formats coming soon. 219 220 New in PyMOL v1.4 for Mac and Linux. 221 222 ''' 223 quiet = int(quiet) 224 r = DEFAULT_ERROR 225 try: 226 _self.lock(_self) 227 if not os.path.isfile(reflection_file): 228 print(" MapGenerate-Error: Could not find file '%s'.\n Please check the filename and try again." % reflection_file) 229 raise pymol.CmdException 230 231 # TODO: work for CIF, MTZ, and CNS 232 from . import headering 233 mtzFile = headering.MTZHeader(reflection_file) 234 235 # FORMAT: crystal/dataset/column 236 _, datasetName, ampColName = ('//' + amplitudes).rsplit('/', 2) 237 238 # if datasetName is empty, take any dataset that has ampColName 239 for dataset in list(mtzFile.datasets.values()): 240 if (not datasetName or dataset["name"] == datasetName) and \ 241 ampColName in dataset["cols"]: 242 break 243 else: 244 raise pymol.CmdException("no dataset found") 245 246 cellX, cellY, cellZ = dataset['x'], dataset['y'], dataset['z'] 247 cellAlpha, cellBeta, cellGamma = dataset['alpha'], dataset['beta'], dataset['gamma'] 248 if reso_low==reso_high: 249 reso_low, reso_high = mtzFile.reso_min, mtzFile.reso_max 250 space_group = mtzFile.space_group 251 252 phases = phases.rsplit('/', 1)[-1] 253 if not phases: 254 raise pymol.CmdException("phase name missing") 255 256 if weights and weights!="None": 257 weights = weights.rsplit('/', 1)[-1] 258 if not weights: 259 raise pymol.CmdException("Improperly formatted weights name") 260 261 tempFile = tempfile.NamedTemporaryFile(delete=False) 262 tempFileName = tempFile.name 263 tempFile.close() 264 265 r = _cmd.map_generate(_self._COb,str(name),str(reflection_file),str(tempFileName), 266 str(ampColName),str(phases), 267 str(weights),float(reso_low),float(reso_high),str(space_group), 268 float(cellX), float(cellY), float(cellZ), 269 float(cellAlpha), float(cellBeta), float(cellGamma), 270 int(quiet),int(zoom)) 271 if r is not None: 272 if not quiet: 273 print("Loading map '%s'" % (name)) 274 r = _self.load(r, name, format="ccp4", finish=1) 275 else: 276 print(' Error: Map generation failed') 277 278 os.remove(tempFileName) 279 280 except ImportError: 281 print(" MapGenerate-Error: Cannot import headering module. Cannot read MTZ file or make map.") 282 finally: 283 _self.unlock(r,_self) 284 if _self._raising(r,_self): raise pymol.CmdException 285 286 return name 287 288 def map_new(name, type='gaussian', grid=None, selection="(all)", 289 buffer=None, box=None, state=0, quiet=1, zoom=0, 290 normalize=-1, clamp=[1.0,-1.0], resolution=0.0, _self=cmd): 291 292 ''' 293 294DESCRIPTION 295 296 "map_new" creates a map object using one of the built-in map 297 generation routines. This command not yet fully supported. 298 299USAGE 300 301 map_new name [, type [, grid [, selection [, buffer [, box [, state ]]]]]] 302 303ARGUMENTS 304 305 name = string: name of the map object to create or modify 306 307 type = vdw, gaussian, gaussian_max, coulomb, coulomb_neutral, coulomb_local 308 309 grid = float: grid spacing 310 311 selection = string: atoms about which to generate the map 312 313 buffer = float: cutoff 314 315 state > 0: use the indicated state 316 317 state = 0: use all states independently with independent extents 318 319 state = -1: use current global state 320 321 state = -2: use effective object state(s) 322 323 state = -3: use all states in one map 324 325 state = -4: use all states independent states by with a unified extent 326 327NOTES 328 329 This command can be used to create low-resolution surfaces of 330 protein structures. 331 332 ''' 333 # preprocess selection 334 r = DEFAULT_ERROR 335 selection = selector.process(selection) 336 if box is not None: # box should be [[x1,y1,z1],[x2,y2,z2]] 337 if _self.is_string(box): 338 box = safe_list_eval(box) 339 box = (float(box[0][0]), 340 float(box[0][1]), 341 float(box[0][2]), 342 float(box[1][0]), 343 float(box[1][1]), 344 float(box[1][2])) 345 box_flag = 1 346 else: 347 box = (0.0,0.0,0.0,1.0,1.0,1.0) 348 box_flag = 0 349 if grid is None: 350 grid = _self.get_setting_float('gaussian_resolution')/3.0 351 if buffer is None: 352 buffer = -1.0 353 grid = float(grid) # for now, uniform xyz; later (x,y,z) 354 355 if not is_list(clamp): 356 clamp = safe_list_eval(str(clamp)) 357 if len(clamp)<2: 358 clamp = [1.0,-1.0] 359 type = map_type_dict[map_type_sc.auto_err(str(type),'map type')] 360 try: 361 _self.lock(_self) 362 r = _cmd.map_new(_self._COb,str(name),int(type),grid,str(selection), 363 float(buffer),box,int(state)-1, 364 int(box_flag),int(quiet),int(zoom),int(normalize), 365 float(clamp[0]),float(clamp[1]),float(resolution)) 366 finally: 367 _self.unlock(r,_self) 368 if _self._raising(r,_self): raise pymol.CmdException 369 return r 370 371 def ramp_new(name, map_name, range=[-1.0,0.0,1.0], 372 color=['red',[1.0,1.0,1.0],'blue'], state=1, 373 selection='', beyond=2.0, within=6.0, sigma=2.0, 374 zero=1, quiet=1, _self=cmd): 375 376 ''' 377DESCRIPTION 378 379 "ramp_new" creates a color ramp based on a map potential value or 380 based on proximity to a molecular object. 381 382USAGE 383 384 ramp_new name, map_name [, range [, color [, state [, selection [, 385 beyond [, within [, sigma [, zero ]]]]]]]] 386 387ARGUMENTS 388 389 name = string: name of the ramp object 390 391 map_name = string: name of the map (for potential) or molecular 392 object (for proximity) 393 394 range = list: values corresponding to slots in the ramp 395 396 color = list: colors corresponding to slots in the ramp 397 398 state = integer: state identifier 399 400 selection = selection: for automatic ranging 401 402 beyond = number: with automatic ranging, are we excluding 403 values beyond a certain distance from the selection? 404 405 within = number: with automatic ranging, are we only including 406 valuess within a certain distance from the selection? 407 408 sigma = number: with automatic ranging, how many standard 409 deviations from the mean do we go? 410 411 zero = integer: with automatic ranging, do we force the central 412 value to be zero? 413 414EXAMPLES 415 416 ramp_new e_pot_color, e_pot_map, [-10,0,10], [red,white,blue] 417 418NOTES 419 420 Color ramps are extremely powerful but complicated to use. 421 422 In the simplest case, they can be used to color representations 423 based on the potential values found in a map object at the 424 corresponding positions in space. 425 426 In another simple case, representations can be colored based on 427 proximity to a target. Note that since ramp targets must 428 themselves be real objects (not merely selections), the "create" 429 command may be needed in order to generate an appropriate target. 430 431 In more complicated cases, they can be used to color 432 representations on one object based atoms found in another. 433 434 Ramps can operate recursively. In other words, the output color 435 from one ramp can be used as the input color for another. For 436 example, you could color by map potential within a certain 437 distance of the target object, beyond which, a uniform color is applied. 438 439 440PYMOL API 441 442 def ramp_new(string name, string map_name, list range, list color, 443 int state, string selection, float beyond, float 444 within, float sigma, int zero, int quiet) 445 446SEE ALSO 447 448 ramp_update, load, color, create, slice, gradient 449 450 ''' 451 r = DEFAULT_ERROR 452 safe_color = str(color).strip() 453 if(safe_color[0:1]=="["): # looks like a list 454 color = safe_alpha_list_eval(str(safe_color)) 455 else: # looks like a literal 456 color = str(color) 457 new_color = [] 458 # preprocess selection 459 if selection!='': 460 selection = selector.process(selection) 461 # coerce range 462 try: 463 if isinstance(range, str): 464 range = safe_list_eval(range) 465 range = list(map(float, range)) 466 except: 467 raise pymol.CmdException('invalid range') 468 if is_list(color): 469 for a in color: 470 if not is_list(a): 471 new_color.append(list(_self.get_color_tuple(a,4))) # incl negative RGB special colors 472 else: 473 new_color.append(a) 474 elif is_string(color): 475 new_color = ramp_spectrum_dict[ramp_spectrum_sc.auto_err(str(color),'ramp color spectrum')] 476 else: 477 new_color=int(color) 478 try: 479 _self.lock(_self) 480 r = _cmd.ramp_new(_self._COb,str(name),str(map_name),range,new_color, 481 int(state)-1,str(selection),float(beyond),float(within), 482 float(sigma),int(zero),int(quiet)) 483 _self._invalidate_color_sc(_self) 484 finally: 485 _self.unlock(r,_self) 486 if _self._raising(r,_self): raise pymol.CmdException 487 return r 488 489 def ramp_update(name, range=[], color=[], quiet=1, _self=cmd): 490 ''' 491DESCRIPTION 492 493 "ramp_update" updates range and/or color of a color ramp. 494 495USAGE 496 497 ramp_update name [, range [, color ]] 498 499EXAMPLES 500 501 ramp_new e_pot_color, e_pot_map, [-10,0,10], [red,white,blue] 502 ramp_update e_pot_color, range=[-15,0,15] 503 ramp_update e_pot_color, color=[green,white,orange] 504 505SEE ALSO 506 507 ramp_new 508 ''' 509 return _self.ramp_new(name, '', range, color, quiet=quiet) 510 511 def isomesh(name, map, level=1.0, selection='', buffer=0.0, 512 state=1, carve=None, source_state=0, quiet=1, _self=cmd): 513 ''' 514DESCRIPTION 515 516 "isomesh" creates a mesh isosurface object from a map object. 517 518USAGE 519 520 isomesh name, map, level [, selection [, buffer [, state [, carve ]]]] 521 522ARGUMENTS 523 524 name = the name for the new mesh isosurface object. 525 526 map = the name of the map object to use for computing the mesh. 527 528 level = the contour level. 529 530 selection = an atom selection about which to display the mesh with 531 an additional "buffer" (if provided). 532 533 state = the state into which the object should be loaded (default=1) 534 (set state=0 to append new mesh as a new state) 535 536 carve = a radius about each atom in the selection for which to 537 include density. If "carve" is not provided, then the whole 538 brick is displayed. 539 540NOTES 541 542 If the mesh object already exists, then the new mesh will be 543 appended onto the object as a new state (unless you indicate a state). 544 545 state > 0: specific state 546 state = 0: all states 547 state = -1: current state 548 549 source_state > 0: specific state 550 source_state = 0: include all states starting with 0 551 source_state = -1: current state 552 source_state = -2: last state in map 553 554SEE ALSO 555 556 isodot, load 557''' 558 # preprocess selection 559 selection = selector.process(selection) 560 # 561 if carve is None: 562 carve=0.0 563 with _self.lockcm: 564 return _cmd.isomesh(_self._COb,str(name),str(map), 565 selection,float(buffer), 566 float(level),0,int(state)-1,float(carve), 567 int(source_state)-1,int(quiet), 568 float(level)) 569 570 def volume(name, map, ramp='', selection='', buffer=0.0, 571 state=1, carve=None, source_state=0, quiet=1, _self=cmd): 572 ''' 573DESCRIPTION 574 575 "volume" creates a volume object from a map object. 576 577USAGE 578 579 volume name, map [, ramp [, selection [, buffer [, state [, carve ]]]]] 580 581ARGUMENTS 582 583 name = the name for the new volume object. 584 585 map = the name of the map object to use for computing the volume. 586 587 ramp = str: named color ramp {default: } 588 589 selection = an atom selection about which to display the mesh with 590 an additional "buffer" (if provided). 591 592 carve = a radius about each atom in the selection for which to 593 include density. If "carve" is not provided, then the whole 594 brick is displayed. 595 596NOTES 597 598 If the volume object already exists, then the new volume will 599 overwrite the existing object. 600 601EXAMPLE 602 603 fetch 1oky, async=0 604 fetch 1oky, type=2fofc, async=0 605 volume 1okyVol, 1oky_2fofc 606 607SEE ALSO 608 609 map_new, isosurface, isomesh, volume_color, volume_ramp_new 610 611''' 612 r = DEFAULT_ERROR 613 614 # preprocess selection 615 selection = selector.process(selection) 616 617 if carve is None: 618 carve=0.0 619 620 try: 621 # legacy 622 level = float(ramp) 623 ramp = '' 624 except (ValueError, TypeError): 625 level = 0.0 626 627 with _self.lockcm: 628 r = _cmd.volume(_self._COb,str(name),str(map), 629 selection,float(buffer), 630 float(level),int(state)-1,float(carve), 631 int(source_state)-1,int(quiet)) 632 633 if ramp: 634 _self.volume_color(name, ramp) 635 636 return r 637 638 639 def set_raw_alignment(name, raw, guide='', state=1, quiet=1, _self=cmd): 640 ''' 641DESCRIPTION 642 643 API only. Create an alignment object from lists of indices. 644 645ARGUMENTS 646 647 name = str: alignment object name 648 649 raw = list: list (columns) of lists with (model, index) tuples 650 651 guide = str: name of guide object 652 653 state = int: object state 654 655EXAMPLE 656 657 cmd.align('1t46', '1oky', object='aln') 658 raw = cmd.get_raw_alignment('aln') 659 cmd.delete('aln') 660 cmd.set_raw_alignment('alnnew', raw) 661 662SEE ALSO 663 664 cmd.get_raw_alignment 665 ''' 666 with _self.lockcm: 667 return _cmd.set_raw_alignment(name, raw, guide, 668 int(state) - 1, int(quiet), _self._COb) 669 670 671 def slice_new(name, map, state=1, source_state=0, _self=cmd): 672 ''' 673DESCRIPTION 674 675 "slice_map" creates a slice object from a map object. 676 677USAGE 678 679 slice_map name, map, [opacity, [resolution, [state, [source_state]]]] 680 681ARGUMENTS 682 683 name = the name for the new slice object. 684 685 map = the name of the map object to use for computing the slice. 686 687 opacity = opacity of the new slice (default=1) 688 689 resolution = the number of pixels per sampling (default=5) 690 691 state = the state into which the object should be loaded (default=1) 692 (set state=0 to append new mesh as a new state) 693 694 source_state = the state of the map from which the object should be loaded (default=0) 695 696SEE ALSO 697 698 isomesh, isodot, load 699''' 700 r = DEFAULT_ERROR 701 try: 702 _self.lock(_self) 703 r = _cmd.slice_new(_self._COb,str(name),str(map),int(state)-1,int(source_state)-1) 704 finally: 705 _self.unlock(r,_self) 706 if _self._raising(r,_self): raise pymol.CmdException 707 return r 708 709 710 def isosurface(name, map, level=1.0, selection='', buffer=0.0, state=1, 711 carve=None, source_state=0, side=1, mode=3, quiet=1, 712 _self=cmd): 713 ''' 714DESCRIPTION 715 716 "isosurface" creates a new surface object from a map object. 717 718USAGE 719 720 isosurface name, map, level [, selection [, buffer [, state [, carve ]]]] 721 722ARGUMENTS 723 724 name = the name for the new mesh isosurface object. 725 726 map = the name of the map object to use for computing the mesh. 727 728 level = the contour level. 729 730 selection = an atom selection about which to display the mesh with 731 an additional "buffer" (if provided). 732 733 state = the state into which the object should be loaded (default=1) 734 (set state=0 to append new surface as a new state) 735 736 carve = a radius about each atom in the selection for which to 737 include density. If "carve= not provided, then the whole 738 brick is displayed. 739 740NOTES 741 742 If the surface object already exists, then the new surface will be 743 appended onto the object as a new state (unless you indicate a state). 744 745SEE ALSO 746 747 isodot, isomesh, load 748 ''' 749 # preprocess selection 750 selection = selector.process(selection) 751 # 752 if carve is None: 753 carve=0.0 754 with _self.lockcm: 755 return _cmd.isosurface(_self._COb,str(name),str(map), 756 selection,float(buffer), 757 float(level),int(mode),int(state)-1,float(carve), 758 int(source_state)-1,int(side),int(quiet)) 759 760 761 def isodot(name,map,level=1.0,selection='',buffer=0.0,state=0, 762 carve=None,source_state=0,quiet=1,_self=cmd): 763 ''' 764DESCRIPTION 765 766 "isodot" creates a dot isosurface object from a map object. 767 768USAGE 769 770 isodot name, map [, level [, selection [, buffer [, state 771 [, carve [, source_state [, quiet ]]]]]]] 772 773ARGUMENTS 774 775 map = the name of the map object to use. 776 777 level = the contour level. 778 779 selection = an atom selection about which to display the mesh with 780 an additional "buffer" (if provided). 781 782NOTES 783 784 If the dot isosurface object already exists, then the new dots will 785 be appended onto the object as a new state. 786 787SEE ALSO 788 789 load, isomesh 790 ''' 791 # preprocess selections 792 selection = selector.process(selection) 793 # 794 if carve is None: 795 carve=0.0 796 with _self.lockcm: 797 return _cmd.isomesh(_self._COb,str(name),str(map), 798 selection,float(buffer), 799 float(level),1,int(state)-1, 800 float(carve),int(source_state)-1,int(quiet), 801 float(level)) 802 803 804 def isolevel(name,level=1.0,state=0,query=0,quiet=1,_self=cmd): 805 ''' 806DESCRIPTION 807 808 "isolevel" changes the contour level of a isodot, isosurface, or isomesh object. 809 810USAGE 811 812 isolevel name, level, state 813 814 ''' 815 r = DEFAULT_ERROR 816 try: 817 _self.lock(_self) 818 r = _cmd.isolevel(_self._COb,str(name),float(level),int(state)-1,int(query),int(quiet)) 819 finally: 820 _self.unlock(r,_self) 821 if not int(query): 822 if _self._raising(r,_self): raise pymol.CmdException 823 return r 824 825 def gradient(name, map, minimum=1.0, maximum=-1.0, 826 selection='', buffer=0.0, state=0, 827 carve=None, source_state=0, quiet=1, _self=cmd): 828 ''' 829DESCRIPTION 830 831 "gradient" creates a gradient object from a map object. 832 833USAGE 834 835 gradient name, map [, minimum [, maximum [, selection [, buffer [, state 836 [, carve [, source_state [, quiet ]]]]]]]] 837 838ARGUMENTS 839 840 map = the name of the map object to use. 841 842 minimum, maximum = minimum and maximum levels (default: full map range) 843 844 selection = an atom selection about which to display the mesh with 845 an additional "buffer" (if provided). 846 847SEE ALSO 848 849 load, isomesh 850 ''' 851 # preprocess selections 852 selection = selector.process(selection) 853 # 854 if carve is None: 855 carve=0.0 856 with _self.lockcm: 857 return _cmd.isomesh(_self._COb,str(name),str(map), 858 selection,float(buffer), 859 float(minimum),3,int(state)-1, 860 float(carve),int(source_state)-1,int(quiet), 861 float(maximum)) 862 863 def copy(target,source,zoom=-1,_self=cmd): 864 ''' 865DESCRIPTION 866 867 "copy" creates a new object that is an identical copy of an 868 existing object. 869 870USAGE 871 872 copy target, source [, zoom ] 873 874NOTES 875 876 Currently, this command only works for molecular objects. 877 878SEE ALSO 879 880 create 881 ''' 882 r = DEFAULT_ERROR 883 try: 884 _self.lock(_self) 885 r = _cmd.copy(_self._COb,str(source),str(target),int(zoom)) 886 finally: 887 _self.unlock(r,_self) 888 if _self._raising(r,_self): raise pymol.CmdException 889 return r 890 891 def symexp(prefix, object, selection, cutoff, segi=0, quiet=1,_self=cmd): 892 ''' 893DESCRIPTION 894 895 "symexp" creates all symmetry-related objects for the specified 896 object that occur within a cutoff about an atom selection. 897 898USAGE 899 900 symexp prefix, object, selection, cutoff 901 902NOTES 903 904 The newly objects are labeled using the prefix provided along with 905 their crystallographic symmetry operation and translation. 906 907SEE ALSO 908 909 load 910 ''' 911 r = DEFAULT_ERROR 912 # preprocess selection 913 selection=selector.process(selection) 914 # 915 try: 916 _self.lock(_self) 917 r = _cmd.symexp(_self._COb,str(prefix),str(object), 918 "("+str(selection)+")",float(cutoff), 919 int(segi),int(quiet)) 920 finally: 921 _self.unlock(r,_self) 922 if _self._raising(r,_self): raise pymol.CmdException 923 return r 924 925 def fragment(name, object=None, origin=1, zoom=0, quiet=1, _self=cmd): 926 ''' 927DESCRIPTION 928 929 "fragment" retrieves a 3D structure from the fragment library, 930 which is currently pretty meager (just amino acids). 931 932USAGE 933 934 fragment name 935 936 ''' 937 r = DEFAULT_ERROR 938 try: 939 if object is None: 940 object=name 941 model = fragments.get(str(name)) 942 la = len(model.atom) 943 if la and int(origin): 944 position = _self.get_position() 945 for c in range(0,3): 946 mean_c = sum([a.coord[c] for a in model.atom]) / la 947 mean_c = position[c] - mean_c 948 for a in model.atom: 949 a.coord[c] += mean_c 950 r = _self.load_model(model,str(object),quiet=quiet,zoom=zoom, _self=_self) 951 except IOError: 952 raise pymol.CmdException("unable to load fragment '%s'." % name) 953 if _self._raising(r,_self): raise pymol.CmdException 954 return r 955 956 def create(name, selection, source_state=0, 957 target_state=0, discrete=0, zoom=-1, quiet=1, 958 singletons=0, extract=None, copy_properties=False, _self=cmd): 959 ''' 960DESCRIPTION 961 962 "create" creates a new molecule object from a selection. It can 963 also be used to create states in an existing object. 964 965USAGE 966 967 create name, selection [,source_state [,target_state ] ] 968 969ARGUMENTS 970 971 name = string: name of object to create or modify 972 973 selection = string: atoms to include in the new object 974 975 source_state = integer: {default: 0 -- copy all states} 976 977 target_state = integer: -1 appends after last state {default: 0} 978 979PYMOL API 980 981 cmd.create(string name, string selection, int state, 982 int target_state, int discrete) 983 984NOTES 985 986 If the source and target states are zero (default), then all 987 states will be copied. Otherwise, only the indicated states will 988 be copied. 989 990SEE ALSO 991 992 load, copy, extract 993 ''' 994 r = DEFAULT_ERROR 995 target_state = int(target_state) 996 if target_state == -1: 997 target_state = _self.count_states('?' + name) + 1 998 if copy_properties: 999 print(' Warning: properties are not supported in Open-Source PyMOL') 1000 # preprocess selection 1001 selection = selector.process(selection) 1002 1003 # TODO is this too much convenience? 'extract' should be a simple boolean 1004 if extract in (None, 0, '0', ''): 1005 extract = '' 1006 elif extract in (1, '1'): 1007 extract = selection 1008 else: 1009 print(' Warning: non-boolean extract values are deprecated!') 1010 extract = selector.process(extract) 1011 1012 if extract: 1013 extract_sele = _self.get_unused_name('_extract') 1014 _self.select(extract_sele, extract, 0) 1015 1016 try: 1017 _self.lock(_self) 1018 if not name: 1019 name = _self.get_unused_name("obj") 1020 r = _cmd.create(_self._COb,str(name),"("+str(selection)+")", 1021 int(source_state)-1,int(target_state)-1, 1022 int(discrete),int(zoom),int(quiet),int(singletons), int(copy_properties)) 1023 finally: 1024 _self.unlock(r,_self) 1025 1026 if extract: 1027 if not is_error(r): 1028 _self.remove(extract_sele) 1029 _self.delete(extract_sele) 1030 1031 if _self._raising(r,_self): raise pymol.CmdException 1032 return r 1033 1034 def extract(name, selection, *arg,**kw): 1035 ''' 1036DESCRIPTION 1037 1038 "extract" is simply a shorthand way calling the "create" command 1039 with the extract argument activated, so that atoms in the new 1040 object are removed from the source object. 1041 1042USAGE 1043 1044 extract name, selection [, source_state [, target_state ]] 1045 1046SEE ALSO 1047 1048 create 1049 1050 ''' 1051 1052 kw['extract'] = 1 1053 return create(name, selection, *arg, **kw) 1054 1055 pseudoatom_mode_dict = { 1056 "unit" : 0, # radius 0.5 1057 "extent" : 1, 1058 "rms" : 2, 1059# "ellipse" : 2, for anisotropic b-factors? 1060 } 1061 1062 pseudoatom_mode_sc = Shortcut(pseudoatom_mode_dict.keys()) 1063 1064 unquote_re = re.compile(r"r?('.*'|\".*\")$") 1065 1066 def unquote(s): 1067 if sys.version_info[0] > 2 and isinstance(s, bytes): 1068 s = s.decode('utf-8', 'replace') 1069 1070 s = str(s) 1071 if unquote_re.match(s): 1072 try: 1073 return cmd.safe_eval(s) 1074 except SyntaxError: 1075 print(" Warning: unquote failed for", repr(s)) 1076 return s 1077 1078 def pseudoatom(object='', selection='', name='PS1', resn='PSD', resi='1', chain='P', 1079 segi='PSDO', elem='PS', vdw=-1.0, hetatm=1, b=0.0, q=0.0, color='', 1080 label='', pos=None, state=0, mode='rms', quiet=1,_self=cmd): 1081 ''' 1082 1083DESCRIPTION 1084 1085 "pseudoatom" adds a pseudoatom to a molecular object, and will 1086 creating the molecular object if it does not yet exist. 1087 1088USAGE 1089 1090 pseudoatom object [, selection [, name [, resn [, resi [, chain 1091 [, segi [, elem [, vdw [, hetatm [, b [, q [, color [, label 1092 [, pos [, state [, mode [, quiet ]]]]]]]]]]]]]]]]] 1093 1094NOTES 1095 1096 "pseudoatom" can be used for a wide variety of random tasks where 1097 on must place an atom or a label in 3D space. 1098 1099 ''' 1100 1101 r = DEFAULT_ERROR 1102 # preprocess selection 1103 if len(color): 1104 color = _self.get_color_index(str(color)) 1105 else: 1106 color = -1 # default 1107 selection = selector.process(selection) 1108 mode = pseudoatom_mode_dict[pseudoatom_mode_sc.auto_err(str(mode),'pseudoatom mode')] 1109 1110 (name,resn,resi,chain,segi,elem,label) = list(map(unquote,(name,resn,resi,chain,segi,elem,label))) 1111 # 1112 try: 1113 _self.lock(_self) 1114 if pos is not None: 1115 if not (is_list(pos) or is_tuple(pos)): 1116 pos = safe_list_eval(pos) 1117 pos = (float(pos[0]), # tuple-ize 1118 float(pos[1]), 1119 float(pos[2])) 1120 if len(selection.split())>1: 1121 selection = "("+str(selection)+")" 1122 r = _cmd.pseudoatom(_self._COb,str(object), str(selection), 1123 str(name), str(resn), str(resi), str(chain), 1124 str(segi), str(elem), float(vdw), int(hetatm), 1125 float(b), float(q), str(label), pos, int(color), 1126 int(state)-1, int(mode), int(quiet)) 1127 finally: 1128 _self.unlock(r,_self) 1129 if _self._raising(r,_self): raise pymol.CmdException 1130 return r 1131 1132 def join_states(name, selection='all', mode=2, zoom=0, quiet=1, _self=cmd): 1133 ''' 1134DESCRIPTION 1135 1136 The reverse of split_states. Create a multi-state object from a 1137 selection which spans multiple objects. 1138 1139ARGUMENTS 1140 1141 name = string: name of object to create or modify 1142 1143 selection = string: atoms to include in the new object 1144 1145 mode = int: how to match states {default: 2} 1146 0: Create discrete object, input objects can be (totally) different 1147 1: Assume identical topology (same number of atoms and matching atom 1148 identifiers) in all input objects 1149 2: Assume matching atom identifiers in all input objects, but also 1150 check for missing atoms and only include atoms that are present 1151 in all input objects 1152 3: match atoms by sequence alignment, slowest but most robust option 1153 1154EXAMPLE 1155 1156 fragment ala 1157 fragment his 1158 join_states multi, (ala|his), mode=0 1159 ''' 1160 1161 mode, quiet = int(mode), int(quiet) 1162 1163 if mode == 3: 1164 aln_name = _self.get_unused_name('_join_states_aln') 1165 1166 sele_name = _self.get_unused_name('_join_states_sele1') 1167 msel_name = _self.get_unused_name('_join_states_sele2') 1168 1169 _self.select(sele_name, selection, 0) 1170 models = _self.get_object_list('?' + sele_name) 1171 1172 for i, model in enumerate(models): 1173 _self.select(msel_name, '?%s & ?%s' % (sele_name, model), 0) 1174 if mode == 2 and i > 0: 1175 _self.remove('?%s & ! ((alt A+) & (?%s in ?%s))' % (name, name, msel_name)) 1176 _self.create(name, '?%s in ?%s' % (msel_name, name), 0, -1, 0, 0, quiet) 1177 elif mode == 3 and i > 0: 1178 _self.align(msel_name, name, cycles=0, transform=0, object=aln_name) 1179 _self.select(msel_name, '?%s & ?%s' % (sele_name, aln_name), 0) 1180 _self.remove('?%s and not ?%s' % (name, aln_name)) 1181 _self.delete(aln_name) 1182 1183 n = _self.count_states('?' + name) 1184 for j in range(_self.count_states('?' + model)): 1185 _self.create(name, name, 1, -1, 0, 0, quiet) 1186 _self.update(name, '?' + msel_name, n + j + 1, 1, 0, quiet) 1187 else: 1188 _self.create(name, msel_name, 0, -1, mode == 0, 0, quiet) 1189 1190 _self.delete(sele_name) 1191 _self.delete(msel_name) 1192 _self.rebuild('?' + name) 1193 1194 if int(zoom): 1195 _self.zoom(name, state=0) 1196