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#-*
11#-*
12#-*
13#Z* -------------------------------------------------------------------
14
15from __future__ import print_function
16
17from .constants import CURRENT_STATE, ALL_STATES
18
19if True:
20
21    import pymol
22    import math
23    from . import selector
24    cmd = __import__("sys").modules["pymol.cmd"]
25    from .cmd import _cmd,lock,unlock,Shortcut,is_string, \
26          boolean_sc,boolean_dict,safe_list_eval, is_sequence, \
27          DEFAULT_ERROR, DEFAULT_SUCCESS, _raising, is_ok, is_error
28    from chempy import cpv
29
30    ref_action_dict = {
31        'store'     : 1,
32        'recall'    : 2,
33        'validate'  : 3,
34        'swap'      : 4,
35    }
36
37    ref_action_sc = Shortcut(ref_action_dict.keys())
38
39    def reference(action='validate', selection='(all)',
40                  state=0, quiet=1, _self=cmd):
41        r = DEFAULT_ERROR
42        if is_string(action):
43            action = ref_action_sc.auto_err(action,"action")
44            action = ref_action_dict[action]
45        else:
46            action = int(action)
47        selection = selector.process(selection)
48        try:
49            _self.lock(_self)
50            r = _cmd.reference( _self._COb, int(action), str(selection),
51                               int(state)-1, int(quiet))
52        finally:
53            _self.unlock(r,_self)
54        if _self._raising(r,_self): raise pymol.CmdException
55        return r
56
57    def sculpt_purge(_self=cmd):
58        '''
59DESCRIPTION
60
61    "sculpt_purge" is an unsupported feature.
62
63    '''
64        r = DEFAULT_ERROR
65        try:
66            _self.lock(_self)
67            r = _cmd.sculpt_purge(_self._COb)
68        finally:
69            _self.unlock(r,_self)
70        if _self._raising(r,_self): raise pymol.CmdException
71        return r
72
73    def sculpt_deactivate(object, _self=cmd):
74        '''
75DESCRIPTION
76
77    "sculpt_deactivate" deactivates sculpting for the given object and
78    clears the stored restraints.
79
80ARGUMENTS
81
82    object = str: name of a single object or "all"
83
84SEE ALSO
85
86    sculpt_activate
87    '''
88        r = 0
89        try:
90            _self.lock(_self)
91            r = _cmd.sculpt_deactivate(_self._COb,str(object))
92        finally:
93            _self.unlock(r,_self)
94        if _self._raising(r,_self): raise pymol.CmdException
95        return r
96
97    def sculpt_activate(object, state=0, match_state=-1,
98                        match_by_segment=0, _self=cmd):
99        '''
100DESCRIPTION
101
102    "sculpt_activate" enables sculpting for the given object. The current
103    geometry (bond lengths, angles, etc.) of the given state is remembered as
104    the reference geometry.
105
106ARGUMENTS
107
108    object = str: name of a single object or "all"
109
110    state = int: object state or 0 for current state {default: 0}
111
112SEE ALSO
113
114    sculpt_iterate, sculpt_deactivate
115    '''
116        r = DEFAULT_ERROR
117        try:
118            _self.lock(_self)
119            r = _cmd.sculpt_activate(_self._COb,str(object),
120                                     int(state)-1,
121                                     int(match_state)-1,
122                                     int(match_by_segment))
123        finally:
124            _self.unlock(r,_self)
125        if _self._raising(r,_self): raise pymol.CmdException
126        return r
127
128    def split_states(object, first=1, last=0, prefix=None, _self=cmd):
129        '''
130DESCRIPTION
131
132    "split_states" separates a multi-state molecular object into a set
133    of single-state molecular objects.
134
135USAGE
136
137    split_states object [, first [, last [, prefix ]]]
138
139EXAMPLE
140
141    load docking_hits.sdf
142    split_states docking_hits, prefix=hit
143    delete docking_hits
144
145SEE ALSO
146
147    join_states
148        '''
149        r = DEFAULT_SUCCESS
150        prefix_set = bool(prefix)
151        first=int(first)
152        last=int(last)
153        prefix_a = first - 1
154
155        # support selections, not only objects
156        sele = _self.get_unused_name('_sele_Abnqh5s5VS')
157        _self.select(sele, object, 0)
158
159        # all names to check for name conflicts
160        names = set(_self.get_names('all'))
161
162        # iterate over objects
163        for object in _self.get_object_list(sele):
164            olast = _self.count_states('%' + object)
165
166            if 0 < last < olast:
167                olast = last
168
169            for a in range(first, olast + 1):
170                name = None
171                if prefix_set:
172                    prefix_a += 1
173                else:
174                    prefix_a = a
175                    prefix = object + "_"
176                    name = _self.get_title(object,a)
177
178                if not name:
179                    name = prefix + "%04d" % prefix_a
180                elif name in names:
181                    name = _self.get_unused_name(name)
182                names.add(name)
183
184                r = _self.create(name, "?%s & ?%s" % (sele, object), a, 1)
185
186                if is_error(r):
187                    break
188
189        _self.delete(sele)
190        if _self._raising(r,_self): raise pymol.CmdException
191        return r
192
193    def sculpt_iterate(object, state=0, cycles=10, _self=cmd):
194        '''
195DESCRIPTION
196
197    "sculpt_iterate" performs a simple energy minimization of atomic
198    coordinates based on the geometry restraints which were defined with
199    the "sculpt_activate" invocation and which are selected in the
200    "sculpt_field_mask" setting. Sculpting currently supports local
201    geometry restraints and vdw repulsion, but no solvation or
202    electrostatic effects.
203
204ARGUMENTS
205
206    object = str: name of a single object or "all"
207
208    state = int: object state or 0 for current state {default: 0}
209
210    cycles = int: number of iterations {default: 10}
211
212SEE ALSO
213
214    commands: sculpt_activate, sculpt_deactivate
215    settings: "sculpting" setting, all "sculpt_*" settings
216    '''
217        r = DEFAULT_ERROR
218        try:
219            _self.lock(_self)
220            r = _cmd.sculpt_iterate(_self._COb,str(object),int(state)-1,int(cycles))
221        finally:
222            _self.unlock(r,_self)
223        if _self._raising(r,_self): raise pymol.CmdException
224        return r
225
226    def smooth(selection="all", passes=1, window=5, first=1,
227               last=0, ends=0, quiet=1, _self=cmd):
228
229        '''
230DESCRIPTION
231
232    "smooth" performs a window average of coordinate states.
233
234USAGE
235
236    smooth [ selection [, passes [, window [, first [, last [, ends]]]]]]
237
238ARGUMENTS
239
240    ends = 0 or 1: controls whether or not the end states are also smoothed
241    using a weighted asymmetric window
242
243NOTES
244
245    This type of averaging is often used to suppress high-frequency
246    vibrations in a molecular dynamics trajectory.
247
248    This function is not memory efficient.  For reasons of
249    flexibility, it uses two additional copies of every atomic
250    coordinate for the calculation.  If you are memory-constrained in
251    visualizing MD trajectories, then you may want to use an external
252    tool such as ptraj to perform smoothing before loading coordinates
253    into PyMOL.
254
255SEE ALSO
256
257    load_traj
258
259    '''
260
261        r = DEFAULT_ERROR
262        selection = selector.process(selection)
263        try:
264            _self.lock(_self)
265            r = _cmd.smooth(_self._COb,str(selection),int(passes),int(window),
266                                 int(first)-1,int(last)-1,int(ends),int(quiet))
267
268        finally:
269            _self.unlock(r,_self)
270        if _self._raising(r,_self): raise pymol.CmdException
271        return r
272
273    def set_state_order(name, order, quiet=1, _self=cmd):
274        '''
275DESCRIPTION
276
277    API only. Set the order of states for an object.
278
279ARGUMENTS
280
281    name = str: object name
282
283    order = list of int: index array (1-based state indices)
284
285EXAMPLE
286
287    # reverse the order of a 20 model object
288    cmd.set_state_order('1nmr', range(20, 0, -1))
289        '''
290        with _self.lockcm:
291            return _cmd.set_state_order(_self._COb, name, [i - 1 for i in order])
292
293    def set_discrete(name, discrete=1, quiet=1, _self=cmd):
294        '''
295DESCRIPTION
296
297    Convert discrete to non-discrete object or vice versa.
298        '''
299        with _self.lockcm:
300            return _cmd.set_discrete(_self._COb, name, int(discrete))
301
302    def set_symmetry(selection,
303            a, b, c, alpha, beta, gamma, spacegroup="P1",
304            state=-1, quiet=1,
305            _self=cmd):
306
307        '''
308DESCRIPTION
309
310    "set_symmetry" defines or redefines the crystal and spacegroup
311    parameters for a molecule or map object.
312
313USAGE
314
315    set_symmetry selection, a, b, c, alpha, beta, gamma, spacegroup
316
317ARGUMENTS
318
319    selection = str: object name pattern
320
321PYMOL API
322
323    cmd.set_symmetry(string selection, float a, float b, float c,
324          float alpha, float beta, float gamma, string spacegroup)
325
326        '''
327        with _self.lockcm:
328            r = _cmd.set_symmetry(_self._COb,str(selection), int(state) - 1,
329                                         float(a),float(b),float(c),
330                                         float(alpha),float(beta),float(gamma),
331                                         str(spacegroup),
332                                         int(quiet))
333        return r
334
335    def symmetry_copy(source_name,
336                      target_name,
337                      source_state=1,
338                      target_state=1,
339                      quiet=1,
340                      _self=cmd):
341        """
342DESCRIPTION
343
344    "symmetry_copy" copies symmetry information from one object to another.
345
346USAGE
347
348    symmetry_copy source_name, target_name, source_state, target_state
349
350ARGUMENTS
351
352    source_name = str: object name
353    target_name = str: object name pattern
354    source_state = int: object state (maps only)
355    target_state = int: object state (maps only)
356
357NOTES
358
359    Molecular objects don't support individual states yet.
360        """
361        with _self.lockcm:
362            return _cmd.symmetry_copy(_self._COb,
363                                   str(source_name),
364                                   str(target_name),
365                                   int(source_state)-1,
366                                   int(target_state)-1,
367                                   int(quiet))
368
369
370    def set_name(old_name, new_name,_self=cmd):
371        '''
372DESCRIPTION
373
374    "set_name" changes the name of an object or selection.
375
376USAGE
377
378    set_name old_name, new_name
379
380PYMOL API
381
382    cmd.set_name(string old_name, string new_name)
383
384        '''
385        r = DEFAULT_ERROR
386        try:
387            _self.lock(_self)
388            r = _cmd.set_name(_self._COb,str(old_name),
389                                    str(new_name))
390        finally:
391            _self.unlock(r,_self)
392        if _self._raising(r,_self): raise pymol.CmdException
393        return r
394
395
396    def set_geometry(selection, geometry, valence, _self=cmd):
397        '''
398DESCRIPTION
399
400    "set_geometry" changes PyMOL\'s assumptions about the proper valence
401    and geometry of atoms in the selection.
402
403USAGE
404
405    set_geometry selection, geometry, valence
406
407NOTES
408
409    Immature functionality. See code for details.
410
411PYMOL API
412
413    cmd.set_geometry(string selection, int geometry, int valence)
414
415SEE ALSO
416
417    remove, attach, fuse, bond, unbond
418    '''
419        r = DEFAULT_ERROR
420        # preprocess selection
421        selection = selector.process(selection)
422        try:
423            _self.lock(_self)
424            r = _cmd.set_geometry(_self._COb,str(selection),int(geometry),int(valence))
425        finally:
426            _self.unlock(r,_self)
427        if _self._raising(r,_self): raise pymol.CmdException
428        return r
429
430    def undo(_self=cmd):
431        '''
432DESCRIPTION
433
434    "undo" restores the previous conformation of the object currently
435    being edited.
436
437USAGE
438
439    undo
440
441SEE ALSO
442
443    redo, push_undo
444    '''
445        r = DEFAULT_ERROR
446        try:
447            _self.lock(_self)
448            r = _cmd.undo(_self._COb,-1)
449        finally:
450            _self.unlock(r,_self)
451        if _self._raising(r,_self): raise pymol.CmdException
452        return r
453
454    def push_undo(selection, just_coordinates=1, finish_undo=0, add_objects=0, delete_objects=0, state=0, _self=cmd):
455        '''
456DESCRIPTION
457
458    "push_undo" stores the current conformations of objects in the
459    selection onto their individual undo rings.
460
461    Notice: This command is only partly implemented in open-source PyMOL.
462
463USAGE
464
465    push_undo (all)
466
467SEE ALSO
468
469    undo, redo
470    '''
471        # preprocess selections
472        selection = selector.process(selection)
473        #
474        r = DEFAULT_ERROR
475        try:
476            _self.lock(_self)
477            r = _cmd.push_undo(_self._COb,"("+str(selection)+")",int(state)-1)
478        finally:
479            _self.unlock(r,_self)
480        if _self._raising(r,_self): raise pymol.CmdException
481        return r
482
483    def redo(_self=cmd):
484        '''
485DESCRIPTION
486
487    "redo" reapplies the conformational change of the object currently
488    being edited.
489
490USAGE
491
492    redo
493
494SEE ALSO
495
496    undo, push_undo
497    '''
498        r = DEFAULT_ERROR
499        try:
500            _self.lock(_self)
501            r = _cmd.undo(_self._COb,1)
502        finally:
503            _self.unlock(r,_self)
504        if _self._raising(r,_self): raise pymol.CmdException
505        return r
506
507    order_dict = {
508    # simulation
509        '0'         : 0,
510        '1'         : 1,
511        '2'         : 2,
512        '3'         : 3,
513        '4'         : 4,
514        'aromatic'  : 4,
515        'guess'     : -1,
516        'copy'      : -2
517    }
518
519    order_sc = Shortcut(order_dict.keys())
520
521    def valence(order, selection1=None, selection2=None, source='',
522                target_state=0, source_state=0, reset=1,
523                quiet=1, _self=cmd):
524        '''
525DESCRIPTION
526
527    "valence" modifies the valences of all existing bonds formed
528    between two atom selections.
529
530USAGE
531
532    valence 2, (name C), (name O)
533
534PYMOL API
535
536    cmd.valence(string selection1, selection2)
537
538SEE ALSO
539
540    unbond, fuse, attach, replace, remove_picked
541    '''
542        if is_string(order):
543            order = order_sc.auto_err(order,"order")
544            order = order_dict[order]
545        else:
546            order = int(order)
547        r = DEFAULT_ERROR
548        # preprocess selections
549        if selection1 is None:
550            selection1="(pk1)"
551            if selection2 is None:
552                selection2="(pk2)"
553        if selection2 is None:
554            selection2 = selection1
555        selection1 = selector.process(selection1)
556        selection2 = selector.process(selection2)
557        if source!='':
558            source = selector.process(source)
559        try:
560            _self.lock(_self)
561            if order>=0:
562                r = _cmd.bond(_self._COb, "("+selection1+")", "("+selection2+")", int(order), 2, int(quiet))
563            else:
564                r = _cmd.revalence(_self._COb,
565                                   "("+selection1+")",
566                                   "("+selection2+")",
567                                   str(source),
568                                   int(target_state)-1, int(source_state)-1,
569                                   int(reset), int(quiet))
570        finally:
571            _self.unlock(r,_self)
572        if _self._raising(r,_self): raise pymol.CmdException
573        return r
574
575    def add_bond(oname, index1, index2, order=1, _self=cmd):
576        '''
577DESCRIPTION
578
579    API-only function to add a bond by atom indices (1-based, same as "index"
580    in cmd.iterate()).
581
582    To add bonds by atom selection, use cmd.bond()
583
584ARGUMENTS
585
586    oname = str: object name
587
588    index1 = int: first atom index
589
590    index2 = int: second atom index
591
592    order = int: bond order {default: 1}
593
594SEE ALSO
595
596    cmd.get_bonds()
597        '''
598        with _self.lockcm:
599            return _cmd.add_bond(_self._COb, oname, index1 - 1, index2 - 1, order)
600
601    def rebond(oname, state=CURRENT_STATE, _self=cmd):
602        '''
603DESCRIPTION
604
605    Discard all bonds and do distance based bonding.
606
607ARGUMENTS
608
609    oname = str: object name
610
611    state = int: object state {default: -1 (current state)}
612        '''
613        with _self.lockcm:
614            return _cmd.rebond(_self._COb, oname, state - 1)
615
616    def bond(atom1="(pk1)", atom2="(pk2)", order=1, edit=1, quiet=1, _self=cmd):
617        '''
618DESCRIPTION
619
620    "bond" creates a new bond between two selections, each of which
621    should contain one atom.
622
623USAGE
624
625    bond [atom1, atom2 [,order]]
626
627NOTES
628
629    The atoms must both be within the same object.
630
631    The default behavior is to create a bond between the (lb) and (rb)
632    selections.
633
634PYMOL API
635
636    cmd.bond(string atom1, string atom2)
637
638SEE ALSO
639
640    unbond, fuse, attach, replace, remove_picked
641    '''
642        r = DEFAULT_ERROR
643        # preprocess selections
644        atom1 = selector.process(atom1)
645        atom2 = selector.process(atom2)
646        try:
647            _self.lock(_self)
648            r = _cmd.bond(_self._COb,
649                          atom1, atom2,
650                          int(order),1,int(quiet))
651        finally:
652            _self.unlock(r,_self)
653        if _self._raising(r,_self): raise pymol.CmdException
654        return r
655
656    def invert(quiet=1, _self=cmd):
657        '''
658DESCRIPTION
659
660    "invert" inverts the stereo-chemistry of atom (pk1), holding attached atoms
661    (pk2) and (pk3) immobile.
662
663USAGE
664
665    invert
666
667NOTES
668
669    The invert function is usually bound to CTRL-E in Editing Mode.
670
671PYMOL API
672
673    cmd.invert( )
674
675    '''
676        #
677        with _self.lockcm:
678            return _cmd.invert(_self._COb, int(quiet))
679
680    def unbond(atom1="(pk1)", atom2="(pk2)", quiet=1, _self=cmd):
681        '''
682DESCRIPTION
683
684    "unbond" removes all bonds between two selections.
685
686USAGE
687
688    unbond atom1,atom2
689
690ARGUMENTS
691
692    atom1 = string {default: (pk1)}
693
694    atom2 = string {default: (pk2)}
695
696PYMOL API
697
698    cmd.unbond(selection atom1, selection atom2)
699
700SEE ALSO
701
702    bond, fuse, remove_picked, attach, detach, replace
703
704    '''
705        r = DEFAULT_ERROR
706        # preprocess selections
707        atom1 = selector.process(atom1)
708        atom2 = selector.process(atom2)
709        try:
710            _self.lock(_self)
711            r = _cmd.bond(_self._COb,
712                          atom1, atom2,
713                          0,0,int(quiet))
714        finally:
715            _self.unlock(r,_self)
716        if _self._raising(r,_self): raise pymol.CmdException
717        return r
718
719    def remove(selection, quiet=1, _self=cmd):
720        '''
721DESCRIPTION
722
723    "remove" eleminates the atoms in a selection from their respective
724    molecular objects.
725
726USAGE
727
728    remove selection
729
730EXAMPLES
731
732    remove resi 124
733
734PYMOL API
735
736    cmd.remove( string selection )
737
738SEE ALSO
739
740    delete
741    '''
742        r = DEFAULT_ERROR
743        # preprocess selection
744        selection = selector.process(selection)
745        #
746        r = 1
747        try:
748            _self.lock(_self)
749            r = _cmd.remove(_self._COb,"("+selection+")",int(quiet))
750        finally:
751            _self.unlock(r,_self)
752        if _self._raising(r,_self): raise pymol.CmdException
753        return r
754
755
756    def remove_picked(hydrogens=1,quiet=1,_self=cmd):
757        '''
758DESCRIPTION
759
760    "remove_picked" removes the atom or bond currently picked for
761    editing.
762
763USAGE
764
765    remove_picked [ hydrogens ]
766
767NOTES
768
769    This function is usually connected to the
770    DELETE key and "CTRL-D".
771
772    By default, attached hydrogens will also be deleted unless
773    hydrogen-flag is zero.
774
775PYMOL API
776
777    cmd.remove_picked(integer hydrogens)
778
779SEE ALSO
780
781    attach, replace
782    '''
783        r = DEFAULT_ERROR
784        try:
785            _self.lock(_self)
786            r = _cmd.remove_picked(_self._COb,int(hydrogens),int(quiet))
787        finally:
788            _self.unlock(r,_self)
789        if _self._raising(r,_self): raise pymol.CmdException
790        return r
791
792
793    def cycle_valence(h_fill=1, quiet=1, _self=cmd):
794        '''
795DESCRIPTION
796
797    "cycle_valence" cycles the valence on the currently selected bond.
798
799USAGE
800
801    cycle_valence [ h_fill ]
802
803ARGUMENTS
804
805    h_fill = 0 or 1: updated hydrogens too? {default: 1 (yes)}
806
807EXAMPLE
808
809    cycle_valence
810
811NOTES
812
813    If the h_fill flag is true, hydrogens will be added or removed to
814    satisfy valence requirements.
815
816    This function is usually connected to the DELETE key and "CTRL-W".
817
818PYMOL API
819
820    cmd.cycle_valence(int h_fill)
821
822SEE ALSO
823
824    remove_picked, attach, replace, fuse, h_fill
825    '''
826        r = DEFAULT_ERROR
827        try:
828            _self.lock(_self)
829            r = _cmd.cycle_valence(_self._COb,quiet)
830        finally:
831            _self.unlock(r,_self)
832        if h_fill:
833            globals()['h_fill'](quiet)
834        if _self._raising(r,_self): raise pymol.CmdException
835        return r
836
837
838    def attach(element,geometry,valence,name='',quiet=1,_self=cmd):
839        '''
840DESCRIPTION
841
842    "attach" adds a single atom on to the picked atom.
843
844USAGE
845
846    attach element, geometry, valence
847
848PYMOL API
849
850    cmd.attach( element, geometry, valence )
851
852    '''
853        with _self.lockcm:
854            return _cmd.attach(_self._COb,str(element),int(geometry),int(valence),str(name))
855
856    def fuse(selection1="(pk1)", selection2="(pk2)",
857             mode=0, recolor=1, move=1, _self=cmd):
858        '''
859DESCRIPTION
860
861    "fuse" joins two objects into one by forming a bond.  A copy of
862    the object containing the first atom is moved so as to form an
863    approximately resonable bond with the second, and that copy is
864    then merged with the first object.
865
866USAGE
867
868    fuse [ selection1 [, selection2 [, mode [, recolor [, move ]]]]]
869
870ARGUMENTS
871
872    selection1 = str: single atom selection (will be copied to object 2)
873
874    selection2 = str: single atom selection
875
876    mode = int: {default: 0}
877      3: don't move and don't create a bond, just combine into single object
878
879    recolor = bool: recolor C atoms to match target {default: 1}
880
881    move = bool: {default: 1}
882
883NOTES
884
885    Each selection must include a single atom in each object.
886    The atoms can both be hydrogens, in which case they are
887    eliminated, or they can both be non-hydrogens, in which
888    case a bond is formed between the two atoms.
889
890SEE ALSO
891
892    bond, unbond, attach, replace, fuse, remove_picked
893    '''
894        r = DEFAULT_ERROR
895        # preprocess selections
896        selection1 = selector.process(selection1)
897        selection2 = selector.process(selection2)
898        #
899        try:
900            _self.lock(_self)
901            r = _cmd.fuse(_self._COb,str(selection1),str(selection2),
902                              int(mode),int(recolor),int(move))
903        finally:
904            _self.unlock(r,_self)
905        if _self._raising(r,_self): raise pymol.CmdException
906        return r
907
908    def unpick(_self=cmd):
909        '''
910DESCRIPTION
911
912    "unpick" deletes the special "pk" atom selections (pk1, pk2, etc.)
913    used in atom picking and molecular editing.
914
915USAGE
916
917    unpick
918
919PYMOL API
920
921    cmd.unpick()
922
923SEE ALSO
924
925    edit
926        '''
927
928        r = DEFAULT_ERROR
929        try:
930            _self.lock(_self)
931            r = _cmd.unpick(_self._COb)
932        finally:
933            _self.unlock(r,_self)
934        if _self._raising(r,_self): raise pymol.CmdException
935        return r
936
937    def drag(selection=None, wizard=1, edit=1, quiet=1, mode=-1, _self=cmd):
938        '''
939DESCRIPTION
940
941    "drag" activates dragging for a selection, enabling the user to
942    manipulate the atom coordinates of the atoms using mouse controls
943    similar to those for controlling the camera.
944
945USAGE
946
947    drag [ selection ]
948
949ARGUMENTS
950
951    selection = string: atoms to drag.  If not provided, and dragging
952    is active, then dragging is instead deactivated.
953
954NOTES
955
956    Currently, the selection of atom to drag must all reside in a
957    single molecular object.
958
959'''
960        import pymol.wizard.dragging
961
962        quiet = int(quiet)
963        if (selection is not None) and (selection!=""):
964            selection = selector.process(selection)
965            if is_string(edit):
966                edit=boolean_dict[boolean_sc.auto_err(edit,'boolean')]
967            if is_string(wizard):
968                wizard=boolean_dict[boolean_sc.auto_err(wizard,'boolean')]
969            edit = int(edit)
970            wizard = int(wizard)
971            old_button_mode = _self.get('button_mode')
972        else:
973            wizard = 0
974            edit = 0
975            selection = ""
976        #
977        r = DEFAULT_ERROR
978        try:
979            _self.lock(_self)
980            r = _cmd.drag(_self._COb,str(selection),int(quiet),int(mode))
981        finally:
982            _self.unlock(r,_self)
983        if not is_error(r):
984            if edit:
985                _self.edit_mode(edit)
986            if wizard:
987                wiz = _self.get_wizard()
988                if (wiz is None):
989                    _self.wizard("dragging",old_button_mode)
990                elif not isinstance(wiz, pymol.wizard.dragging.Dragging):
991                    _self.wizard("dragging",old_button_mode)
992                else:
993                    wiz.recount()
994        if _self._raising(r,_self): raise pymol.CmdException
995        return r
996
997    def edit(selection1='', selection2='none', selection3='none',
998             selection4='none', pkresi=0, pkbond=1, quiet=1, _self=cmd):
999        '''
1000DESCRIPTION
1001
1002    "edit" picks atoms or a bond for editing.
1003
1004USAGE
1005
1006    edit selection1 [, selection2 [, selection3 [, selection4 [, pkresi [, pkbond ]]]]]
1007
1008NOTES
1009
1010    If only one selection is provided, an atom is picked.
1011
1012    If two selections are provided, the bond between them
1013    is picked (by default, if one exists).
1014
1015PYMOL API
1016
1017    cmd.edit(string selection1, string selection2,
1018             string selection3, string selection4,
1019             int pkresi, int pkbond, int quiet)
1020
1021SEE ALSO
1022
1023    unpick, remove_picked, cycle_valence, torsion
1024    '''
1025        # preprocess selections
1026        selection1 = selector.process(selection1)
1027        selection2 = selector.process(selection2)
1028        selection3 = selector.process(selection3)
1029        selection4 = selector.process(selection4)
1030        #
1031        r = DEFAULT_ERROR
1032        try:
1033            _self.lock(_self)
1034            r = _cmd.edit(_self._COb,str(selection1),str(selection2),
1035                              str(selection3),str(selection4),
1036                              int(pkresi),int(pkbond),int(quiet))
1037        finally:
1038            _self.unlock(r,_self)
1039        if _self._raising(r,_self): raise pymol.CmdException
1040        return r
1041
1042    def get_editor_scheme(_self=cmd):
1043        r = DEFAULT_ERROR
1044        try:
1045            _self.lock(_self)
1046            r = _cmd.get_editor_scheme(_self._COb)
1047        finally:
1048            _self.unlock(r,_self)
1049        if _self._raising(r,_self): raise pymol.CmdException
1050        return r
1051
1052    def torsion(angle,_self=cmd):
1053        '''
1054DESCRIPTION
1055
1056    "torsion" rotates the torsion on the bond currently
1057    picked for editing.  The rotated fragment will correspond
1058    to the first atom specified when picking the bond (or the
1059    nearest atom, if picked using the mouse).
1060
1061USAGE
1062
1063    torsion angle
1064
1065PYMOL API
1066
1067    cmd.torsion( float angle )
1068
1069SEE ALSO
1070
1071    edit, unpick, remove_picked, cycle_valence
1072    '''
1073        r = DEFAULT_ERROR
1074        try:
1075            _self.lock(_self)
1076            r = _cmd.torsion(_self._COb,float(angle))
1077        finally:
1078            _self.unlock(r,_self)
1079        if _self._raising(r,_self): raise pymol.CmdException
1080        return r
1081
1082    def h_fill(quiet=1, _self=cmd):
1083        '''
1084DESCRIPTION
1085
1086    "h_fill" removes and replaces hydrogens on the atom or bond picked
1087    for editing.
1088
1089USAGE
1090
1091    h_fill
1092
1093NOTES
1094
1095    This is useful for fixing hydrogens after changing bond valences.
1096
1097PYMOL API
1098
1099    cmd.h_fill()
1100
1101SEE ALSO
1102
1103    edit, cycle_valence, h_add
1104    '''
1105        r = DEFAULT_ERROR
1106        try:
1107            _self.lock(_self)
1108            r = _cmd.h_fill(_self._COb,int(quiet))
1109        finally:
1110            _self.unlock(r,_self)
1111        if _self._raising(r,_self): raise pymol.CmdException
1112        return r
1113
1114    def h_fix(selection="",quiet=1,_self=cmd):
1115        '''
1116DESCRIPTION
1117
1118    "h_fix" is an unsupported command that may have something to do
1119    with repositioning hydrogen atoms.
1120
1121    '''
1122        # preprocess selection
1123        selection = selector.process(selection)
1124
1125        r = DEFAULT_ERROR
1126        try:
1127            _self.lock(_self)
1128            r = _cmd.h_fix(_self._COb,str(selection),int(quiet))
1129        finally:
1130            _self.unlock(r,_self)
1131        if _self._raising(r,_self): raise pymol.CmdException
1132        return r
1133
1134
1135    def h_add(selection="(all)", quiet=1, state=0, legacy=0, _self=cmd):
1136        '''
1137DESCRIPTION
1138
1139    "h_add" adds hydrogens onto a molecule based on current valences.
1140
1141USAGE
1142
1143    h_add [ selection [, state ]]
1144
1145ARGUMENTS
1146
1147    selection = string {default: (all)}
1148
1149    state = int {default: 0 (all states)}
1150
1151NOTES
1152
1153    Because PDB files do not normally contain bond valences for
1154    ligands and other nonstandard components, it may be necessary to
1155    manually correct ligand conformations before adding hydrogens.
1156
1157SEE ALSO
1158
1159    h_fill
1160    '''
1161        # preprocess selection
1162        selection = selector.process(selection)
1163        #
1164        r = DEFAULT_ERROR
1165        try:
1166            _self.lock(_self)
1167            r = _cmd.h_add(_self._COb,selection,int(quiet),
1168                    int(state) - 1, int(legacy))
1169        finally:
1170            _self.unlock(r,_self)
1171        if _self._raising(r,_self): raise pymol.CmdException
1172        return r
1173
1174
1175
1176    def sort(object="",_self=cmd):
1177        '''
1178DESCRIPTION
1179
1180    "sort" reorders atoms in the structure.  It usually only necessary
1181    to run this routine after an "alter" command which has modified the
1182    names of atom properties.  Without an argument, sort will resort
1183    all atoms in all objects.
1184
1185USAGE
1186
1187    sort [object]
1188
1189PYMOL API
1190
1191    cmd.sort(string object)
1192
1193SEE ALSO
1194
1195    alter
1196    '''
1197        r = DEFAULT_ERROR
1198        try:
1199            _self.lock(_self)
1200            r = _cmd.sort(_self._COb,str(object))
1201        finally:
1202            _self.unlock(r,_self)
1203        if _self._raising(r,_self): raise pymol.CmdException
1204        return r
1205
1206
1207    def replace(element, geometry, valence, h_fill=1, name="",
1208		quiet=1, _self=cmd):
1209        '''
1210DESCRIPTION
1211
1212    "replace" replaces the picked atom with a new atom.
1213
1214USAGE
1215
1216    replace element, geometry, valence [, h_fill [, name ]]
1217
1218NOTES
1219
1220    Immature functionality. See code for details.
1221
1222PYMOL API
1223
1224    cmd.replace(string element, int geometry, int valence, int h_fill,
1225                string name)
1226
1227SEE ALSO
1228
1229    remove, attach, fuse, bond, unbond
1230    '''
1231        r = DEFAULT_ERROR
1232        if "pk1" not in _self.get_names("selections"):
1233            print(" Error: you must first pick an atom to replace.")
1234            raise pymol.CmdException
1235        try:
1236            if h_fill: # strip off existing hydrogens
1237                remove("((neighbor pk1) and elem H)",quiet=quiet)
1238            _self.lock(_self)
1239            r = _cmd.replace(_self._COb,str(element),int(geometry),int(valence),str(name),quiet)
1240        finally:
1241            _self.unlock(r,_self)
1242        if _self._raising(r,_self): raise pymol.CmdException
1243        return r
1244
1245    def rename(selection="all", force=0, quiet=1, _self=cmd):
1246        '''
1247DESCRIPTION
1248
1249    "rename" creates new atom names which are unique within residues.
1250
1251USAGE
1252
1253    rename selection [, force ]
1254
1255PYMOL API
1256
1257    cmd.rename(string selection, int force )
1258
1259SEE ALSO
1260
1261    alter
1262    '''
1263        r = DEFAULT_ERROR
1264        selection = "("+selector.process(selection)+")"
1265        try:
1266            _self.lock(_self)
1267            r = _cmd.rename(_self._COb,str(selection),int(force),int(quiet))
1268        finally:
1269            _self.unlock(r,_self)
1270        if _self._raising(r,_self): raise pymol.CmdException
1271        return r
1272
1273    def dss(selection="(all)", state=0, context=None, preserve=0,
1274            quiet=1, _self=cmd):
1275
1276        '''
1277DESCRIPTION
1278
1279    "dss" defines secondary structure based on backbone geometry
1280    and hydrogen bonding patterns.
1281
1282USAGE
1283
1284    dss selection, state
1285
1286ARGUMENT
1287
1288    selection = string: {default: (all)}
1289
1290    state = integer: {default: 0 -- all states}
1291
1292EXAMPLE
1293
1294    dss
1295
1296NOTES
1297
1298    With PyMOL, heavy emphasis is placed on cartoon aesthetics, and so
1299    both hydrogen bonding patterns and backbone geometry are used in
1300    the assignment process.  Depending upon the local context, helix
1301    and strand assignments are made based on geometry, hydrogen
1302    bonding, or both.
1303
1304    This command will generate results which differ slightly from DSSP
1305    and other programs.  Most deviations occur in borderline or
1306    transition regions.  Generally speaking, PyMOL is more strict, thus
1307    assigning fewer helix/sheet residues, except for partially
1308    distorted helices, which PyMOL tends to tolerate.
1309
1310    WARNING: This algorithm has not yet been rigorously validated.
1311
1312    If you dislike one or more of the assignments made by dss, you can
1313    use the alter command to make changes (followed by "rebuild").
1314    For example:
1315
1316        alter 123-125/, ss=\'L\'
1317        alter pk1, ss=\'S\'
1318        alter 90/, ss=\'H\'
1319        rebuild
1320
1321PYMOL API
1322
1323    cmd.dss(string selection, int state)
1324
1325        '''
1326        # preprocess selections
1327        selection = selector.process(selection)
1328        r = DEFAULT_ERROR
1329        if context is None:
1330            context = ""
1331        else:
1332            context = selector.process(context)
1333        #
1334        try:
1335            _self.lock(_self)
1336            r = _cmd.dss(_self._COb,str(selection),int(state)-1,str(context),
1337                            int(preserve),int(quiet))
1338        finally:
1339            _self.unlock(r,_self)
1340        if _self._raising(r,_self): raise pymol.CmdException
1341        return r
1342
1343    def alter(selection, expression, quiet=1, space=None, _self=cmd):
1344
1345        '''
1346DESCRIPTION
1347
1348    "alter" changes atomic properties using an expression evaluated
1349    within a temporary namespace for each atom.
1350
1351USAGE
1352
1353    alter selection, expression
1354
1355EXAMPLES
1356
1357    alter chain A, chain='B'
1358    alter all, resi=str(int(resi)+100)
1359    sort
1360
1361NOTES
1362
1363    Symbols defined (* = read only):
1364
1365    name, resn, resi, resv, chain, segi, elem, alt, q, b, vdw, type,
1366    partial_charge, formal_charge, elec_radius, text_type, label,
1367    numeric_type, model*, state*, index*, ID, rank, color, ss,
1368    cartoon, flags
1369
1370    All strings must be explicitly quoted.  This operation typically
1371    takes several seconds per thousand atoms altered.
1372
1373    You may need to issue a "rebuild" in order to update associated
1374    representations.
1375
1376    WARNING: You should always issue a "sort" command on an object
1377    after modifying any property which might affect canonical atom
1378    ordering (names, chains, etc.).  Failure to do so will confound
1379    subsequent "create" and "byres" operations.
1380
1381SEE ALSO
1382
1383    alter_state, iterate, iterate_state, sort
1384        '''
1385        if not expression:
1386            raise pymol.CmdException('missing expression')
1387
1388        if space is None:
1389            space = _self._pymol.__dict__
1390        r = DEFAULT_ERROR
1391        # preprocess selections
1392        selection = selector.process(selection)
1393        #
1394        try:
1395            _self.lock(_self)
1396            r = _cmd.alter(_self._COb,"("+str(selection)+")",str(expression),0,int(quiet),dict(space))
1397        finally:
1398            _self.unlock(r,_self)
1399        if _self._raising(r,_self): raise pymol.CmdException
1400        return r
1401
1402    def alter_list(object, expr_list, quiet=1, space=None, _self=cmd):
1403        '''
1404DESCRIPTION
1405
1406    "alter_list" is an unsupported feature.
1407
1408        '''
1409        #
1410        r = DEFAULT_ERROR
1411        if space is None:
1412            space = _self._pymol.__dict__
1413        try:
1414            _self.lock(_self)
1415            r = _cmd.alter_list(_self._COb,str(object),list(expr_list),int(quiet),dict(space))
1416        finally:
1417            _self.unlock(r,_self)
1418        if _self._raising(r,_self): raise pymol.CmdException
1419        return r
1420
1421
1422    def iterate(selection, expression, quiet=1, space=None, _self=cmd):
1423
1424        '''
1425DESCRIPTION
1426
1427    "iterate" iterates over an expression within a temporary namespace
1428    for each atom.
1429
1430USAGE
1431
1432    iterate selection, expression
1433
1434EXAMPLES
1435
1436    stored.net_charge = 0
1437    iterate all, stored.net_charge = stored.net_charge + partial_charge
1438    print stored.net_charge
1439
1440    stored.names = []
1441    iterate all, stored.names.append(name)
1442    print stored.names
1443
1444NOTES
1445
1446    Unlike with the "alter" command, atomic properties cannot be
1447    altered.  For this reason, "iterate" is more efficient than
1448    "alter".
1449
1450SEE ALSO
1451
1452    iterate_state, alter, alter_state
1453        '''
1454        if not expression:
1455            raise pymol.CmdException('missing expression')
1456
1457        if space is None:
1458            space = _self._pymol.__dict__
1459        r = DEFAULT_ERROR
1460        # preprocess selection
1461        selection = selector.process(selection)
1462        #
1463        try:
1464            _self.lock(_self)
1465            r = _cmd.alter(_self._COb,"("+str(selection)+")",str(expression),1,int(quiet),dict(space))
1466        finally:
1467            _self.unlock(r,_self)
1468        if _self._raising(r,_self): raise pymol.CmdException
1469        return r
1470
1471    def alter_state(state, selection, expression, quiet=1,
1472                    space=None, atomic=1, _self=cmd):
1473
1474        '''
1475DESCRIPTION
1476
1477    "alter_state" changes atom coordinates and flags over a particular
1478    state and selection using the Python evaluator with a temporary
1479    namespace for each atomic coordinate.
1480
1481USAGE
1482
1483    alter_state state, selection, expression
1484
1485EXAMPLES
1486
1487    alter_state 1, all, x=x+5
1488    rebuild
1489
1490NOTES
1491
1492    By default, most of the symbols from "alter" are available for use
1493    on a read-only basis.
1494
1495    It is usually necessary to "rebuild" representations once your
1496    alterations are complete.
1497
1498SEE ALSO
1499
1500    iterate_state, alter, iterate
1501        '''
1502        if not expression:
1503            raise pymol.CmdException('missing expression')
1504
1505        if space is None:
1506            space = _self._pymol.__dict__
1507        r = DEFAULT_ERROR
1508        # preprocess selection
1509        selection = selector.process(selection)
1510        #
1511        state = int(state)
1512        try:
1513            _self.lock(_self)
1514            r = _cmd.alter_state(_self._COb,
1515                                 int(state)-1,"("+str(selection)+")",
1516                                 str(expression),
1517                                 0,int(atomic),int(quiet),dict(space))
1518        finally:
1519            _self.unlock(r,_self)
1520        if _self._raising(r,_self): raise pymol.CmdException
1521        return r
1522
1523    def iterate_state(state, selection, expression, quiet=1,
1524                      space=None, atomic=1, _self=cmd):
1525
1526        '''
1527DESCRIPTION
1528
1529    "iterate_state" is to "alter_state" as "iterate" is to "alter"
1530
1531USAGE
1532
1533    iterate_state state, selection, expression
1534
1535EXAMPLES
1536
1537    stored.sum_x = 0.0
1538    iterate_state 1, all, stored.sum_x = stored.sum_x + x
1539    print stored.sum_x
1540
1541SEE ALSO
1542
1543    iterate, alter, alter_state
1544        '''
1545        if not expression:
1546            raise pymol.CmdException('missing expression')
1547
1548        r = DEFAULT_ERROR
1549        if space is None:
1550            space = _self._pymol.__dict__
1551        # preprocess selection
1552        selection = selector.process(selection)
1553        state = int(state)
1554        #
1555        try:
1556            _self.lock(_self)
1557            r = _cmd.alter_state(_self._COb,int(state)-1,"("+str(selection)+")",
1558                                        str(expression),1,int(atomic),
1559                                        int(quiet),dict(space))
1560        finally:
1561            _self.unlock(r,_self)
1562        if _self._raising(r,_self): raise pymol.CmdException
1563        return r
1564
1565    def translate(vector=[0.0,0.0,0.0], selection="all", state=-1,
1566                  camera=1, object=None, object_mode=0, _self=cmd):
1567
1568        '''
1569DESCRIPTION
1570
1571    "translate" translates the atomic coordinates of atoms in a
1572    selection.  Alternatively, is modifies the matrix associated with
1573    a particular object or object-state.
1574
1575USAGE
1576
1577    translate vector [, selection [, state [, camera [, object ]]]]
1578
1579ARGUMENTS
1580
1581    vector = float vector: translation vector
1582
1583    selection = string: atoms whose coordinates should be modified {default: all}
1584
1585    state > 0: only the indicated state is modified
1586
1587    state = 0: all states are modified
1588
1589    state = -1: only current state is modified {default}
1590
1591    camera = 0 or 1: is the vector in camera coordinates? {default: 1 (yes)}
1592
1593    object = string: object name (only if rotating object matrix) {default: None}
1594
1595
1596PYMOL API
1597
1598    cmd.translate(list vector, string selection, int state, int
1599                  camera, string object)
1600
1601EXAMPLES
1602
1603    translate [1,0,0], name CA
1604
1605NOTES
1606
1607    "translate" can be used to translate the atomic coordinates of a
1608    molecular object.  Behavior differs depending on whether or not
1609    the "object" parameter is specified.
1610
1611    If object is None, then translate translates atomic coordinates
1612    according to the vector provided for the selection and in the state
1613    provided.  All representation geometries will need to be
1614    regenerated to reflect the new atomic coordinates.
1615
1616    If object is set to an object name, then selection is ignored and
1617    instead of translating the atomic coordinates, the object\'s
1618    overall representation display matrix is modified.  This option is
1619    for use in animations only.
1620
1621    The "camera" option controls whether the camera or the model\'s
1622    axes are used to interpret the translation vector.
1623
1624        '''
1625        r = DEFAULT_ERROR
1626        object_mode = int(object_mode)
1627        if _self.is_string(vector):
1628            vector = safe_list_eval(vector)
1629        if not _self.is_sequence(vector):
1630            print("Error: bad vector.")
1631            raise pymol.CmdException
1632        else:
1633            vector = [float(vector[0]),float(vector[1]),float(vector[2])]
1634            selection = selector.process(selection)
1635            camera=int(camera)
1636            view = _self.get_view(0)
1637            if camera:
1638                mat = [ view[0:3],view[3:6],view[6:9] ]
1639                shift = cpv.transform(mat,vector)
1640            else:
1641                shift = vector
1642            if object is None:
1643                ttt = [1.0,0.0,0.0,shift[0],
1644                         0.0,1.0,0.0,shift[1],
1645                         0.0,0.0,1.0,shift[2],
1646                         0.0,0.0,0.0,1.0]
1647                r=_self.transform_selection(selection,ttt,state=state)
1648            elif object_mode==0: # update the TTT display matrix
1649                try:
1650                    _self.lock(_self)
1651                    r=_cmd.translate_object_ttt(_self._COb,str(object),shift)
1652                finally:
1653                    _self.unlock(r,_self)
1654            elif object_mode==1: # either updates TTT or coordinates & history
1655                     # depending on the current matrix mode
1656                matrix = [1.0, 0.0, 0.0, shift[0],
1657                          0.0, 1.0, 0.0, shift[1],
1658                          0.0, 0.0, 1.0, shift[2],
1659                          0.0, 0.0, 0.0, 1.0]
1660                try:
1661                    _self.lock(_self)
1662                    r = _cmd.transform_object(_self._COb,str(object),int(state)-1,
1663                                                      list(matrix),0,'',1)
1664                finally:
1665                    _self.unlock(r,_self)
1666            else:
1667                print(" Error: translate: unrecognized object_mode")
1668        if _self._raising(r,_self): raise pymol.CmdException
1669        return r
1670
1671    def rotate(axis='x', angle=0.0, selection="all", state=-1, camera=1,
1672               object=None, origin=None, object_mode=0, _self=cmd):
1673
1674        '''
1675DESCRIPTION
1676
1677    "rotate" rotates the atomic coordinates of atoms in a selection
1678    about an axis.  Alternatively, it modifies the matrix associated
1679    with a particular object or object state.
1680
1681USAGE
1682
1683    rotate axis, angle [, selection [, state [, camera [, object
1684        [, origin ]]]]]
1685
1686ARGUMENTS
1687
1688    axis = x, y, z, or float vector: axis about which to rotate
1689
1690    angle = float: degrees of rotation
1691
1692    selection = string: atoms whose coordinates should be modified {default: all}
1693
1694    state > 0: only the indicated state is modified
1695
1696    state = 0: all states are modified
1697
1698    state = -1: only the current state is modified {default}
1699
1700    camera = 0 or 1: is the axis specific in camera coordinates? {default: 1}
1701
1702    object = string: object name (only if rotating object matrix) {default: None}
1703
1704    origin = float vector: origin of rotateion {default: None}
1705
1706EXAMPLES
1707
1708    rotate x, 45, pept
1709
1710    rotate [1,1,1], 10, chain A
1711
1712NOTES
1713
1714    Behavior differs depending on whether or not the "object"
1715    parameter is specified.
1716
1717    If object is None, then the atomic coordinates are modified
1718    directly, and all representation geometries will need to be
1719    regenerated to reflect the new atomic coordinates.
1720
1721    If object is set to an object name, then the selection field is
1722    ignored and instead of translating the atomic coordinates, the
1723    object matrix is modified.  This option is only intended for use
1724    in animations and is not yet fully supported.
1725
1726PYMOL API
1727
1728    cmd.rotate(list-or-string axis, float angle, string selection,
1729               int state, int camera, string object)
1730
1731        '''
1732        r = DEFAULT_ERROR
1733        object_mode = int(object_mode)
1734        have_origin = 0
1735        if axis in ['x','X']:
1736            axis = [1.0,0.0,0.0]
1737        elif axis in ['y','Y']:
1738            axis = [0.0,1.0,0.0]
1739        elif axis in ['z','Z']:
1740            axis = [0.0,0.0,1.0]
1741        else:
1742            axis = safe_list_eval(str(axis))
1743        if not _self.is_list(axis):
1744            print("Error: bad axis.")
1745            raise pymol.CmdException
1746        else:
1747            axis = [float(axis[0]),float(axis[1]),float(axis[2])]
1748            angle = math.pi*float(angle)/180.0
1749            view = _self.get_view(0)
1750            if origin is not None:
1751                have_origin = 1
1752                if _self.is_string(origin):
1753                    if ',' in origin:
1754                        origin = safe_list_eval(origin) # should be a sequence of floats
1755                    else:
1756                        _self.lock(_self)
1757                        try:
1758                            origin = _cmd.get_origin(_self._COb,str(origin))
1759                        finally:
1760                            unlock(-1)
1761                origin = [float(origin[0]),float(origin[1]),float(origin[2])]
1762            else:
1763                origin = [view[12],view[13],view[14]]
1764            camera=int(camera)
1765            if camera:
1766                vmat = [ view[0:3],view[3:6],view[6:9] ]
1767                axis = cpv.transform(vmat,axis)
1768            mat = cpv.rotation_matrix(angle,axis)
1769            if object is None:
1770                ttt = [mat[0][0],mat[0][1],mat[0][2],origin[0],
1771                       mat[1][0],mat[1][1],mat[1][2],origin[1],
1772                       mat[2][0],mat[2][1],mat[2][2],origin[2],
1773                       -origin[0],-origin[1],-origin[2], 1.0]
1774                r=_self.transform_selection(selection,ttt,state=state)
1775            elif object_mode==0:
1776                _self.lock(_self)
1777                try:
1778                    if not have_origin:
1779                        origin = _cmd.get_origin(_self._COb,str(object))
1780                    if is_sequence(origin):
1781                        ttt = [mat[0][0],mat[0][1],mat[0][2], origin[0],
1782                               mat[1][0],mat[1][1],mat[1][2], origin[1],
1783                               mat[2][0],mat[2][1],mat[2][2], origin[2],
1784                               -origin[0], -origin[1], -origin[2], 1.0]
1785                        r=_cmd.combine_object_ttt(_self._COb,str(object),ttt)
1786                finally:
1787                    _self.unlock(r,_self)
1788                if not is_sequence(origin):
1789                    print(" Error: rotate: unknown object '%s'."%object)
1790                    if _self._raising(r,_self):
1791                        raise pymol.CmdException
1792            elif object_mode==1:
1793
1794                matrix = [mat[0][0],mat[0][1],mat[0][2], origin[0],
1795                          mat[1][0],mat[1][1],mat[1][2], origin[1],
1796                          mat[2][0],mat[2][1],mat[2][2], origin[2],
1797                          -origin[0],-origin[1],-origin[2], 1.0]
1798                try:
1799                    _self.lock(_self)
1800                    r = _cmd.transform_object(_self._COb,str(object),int(state)-1,
1801                                                      list(matrix),0,'',0)
1802                finally:
1803                    _self.unlock(r,_self)
1804
1805            else:
1806                print(" Error: rotate: unrecognized object_mode")
1807        if _self._raising(r,_self): raise pymol.CmdException
1808        return r
1809
1810
1811    def set_title(object, state, text, _self=cmd):
1812        '''
1813DESCRIPTION
1814
1815    "set_title" attaches a text string to the state of a particular
1816    object which can be displayed next to the object name when that
1817    state is active.  This is useful for display the energies of a set
1818    of conformers.
1819
1820USAGE
1821
1822    set_title object, state, text
1823
1824PYMOL API
1825
1826    cmd.set_title(string object, int state, string text)
1827
1828    '''
1829        r = DEFAULT_ERROR
1830        try:
1831            _self.lock(_self)
1832            r = _cmd.set_title(_self._COb,str(object),int(state)-1,str(text))
1833        finally:
1834            _self.unlock(r,_self)
1835
1836    def set_object_ttt(object, ttt, state=0, quiet=1, homogenous=0,
1837                       _self=cmd):
1838        '''
1839DESCRIPTION
1840
1841    "set_object_ttt" is an API-only function which sets the TTT matrix
1842    (view transformation) for an object.
1843
1844    When a movie is defined and the object has key frames for object
1845    motions, then the key frames take priority and update the TTT matrix
1846    while the movie is playing.
1847
1848    Unlike a homogenous matrix where the last row is always [0,0,0,1],
1849    a TTT matrix may have a pre-translation vector in the last row.
1850
1851ARGUMENTS
1852
1853    object = str: object name
1854
1855    ttt = list of 16 floats: TTT matrix
1856
1857    state = int: UNUSED, TTT matrices are not state specific
1858
1859    homogenous = 0/1: NAME IS MISLEADING AND IMPLEMENTATION
1860    POSSIBLY WRONG! If 1, then transpose the input matrix and
1861    set the last column (post-translation) to [0,0,0,1].
1862
1863SEE ALSO
1864
1865    cmd.transform_object, cmd.matrix_reset
1866        '''
1867        r = None
1868        if _self.is_string(ttt):
1869            ttt = safe_list_eval(str(ttt))
1870        if homogenous: # passed a homogenous matrix, so do the best we can
1871            ttt = [ # NOTE: this appears to be incorrect...
1872                ttt[ 0], ttt[ 4], ttt[ 8], 0.0,
1873                ttt[ 1], ttt[ 5], ttt[ 9], 0.0,
1874                ttt[ 2], ttt[ 6], ttt[10], 0.0,
1875                ttt[ 3], ttt[ 7], ttt[11], 1.0]
1876        try:
1877            _self.lock(_self)
1878            r = _cmd.set_object_ttt(_self._COb,str(object),
1879				    (float(ttt[ 0]),
1880				     float(ttt[ 1]),
1881				     float(ttt[ 2]),
1882				     float(ttt[ 3]),
1883				     float(ttt[ 4]),
1884				     float(ttt[ 5]),
1885				     float(ttt[ 6]),
1886				     float(ttt[ 7]),
1887				     float(ttt[ 8]),
1888				     float(ttt[ 9]),
1889				     float(ttt[10]),
1890				     float(ttt[11]),
1891				     float(ttt[12]),
1892				     float(ttt[13]),
1893				     float(ttt[14]),
1894				     float(ttt[15])),
1895				    int(state)-1,int(quiet))
1896        finally:
1897            _self.unlock(r,_self)
1898        if _self._raising(r,_self): raise pymol.CmdException
1899        return r
1900
1901    def transform_selection(selection, matrix, state=-1, log=0,
1902                            homogenous=0, transpose=0, _self=cmd):
1903        '''
1904
1905DESCRIPTION
1906
1907    "transform_selection" transforms the atomic coordinates of a
1908    selection.
1909
1910PYMOL API
1911
1912    cmd.transform_selection(string selection, list matrix, int state,
1913                            int log, int homogenous, int transpose):
1914
1915NOTES
1916
1917    Note that when homogenous is zero, the input matrix is NOT a
1918    standard homogenous 4x4 transformation matrix.  Instead it is
1919    something PyMOL-specific which consists of the following:
1920
1921    1) a 3x3 matrix containing the rotation in the upper-left quadrant
1922
1923    2) a 1x3 translation to be applied *before* rotation in the bottom row
1924        (matrix[12],matrix[13],matrix[14]).
1925
1926    3) a 3x1 translation to be applied *after* rotation in the right-hand
1927        column (matrix[3],matrix[7],matrix[11])
1928
1929    In other words, if the matrix is:
1930
1931    [  m0  m1  m2  m3 \\
1932       m4  m5  m6  m7 \\
1933       m8  m9 m10 m11 \\
1934      m12 m13 m14 m15 ]
1935
1936    Atoms will be transformed as follows
1937
1938    Y = M X
1939
1940    y0 = m0*(x0+m12) + m1*(x1+m13) +  m2*(x2+m14) + m3 \\
1941    y1 = m4*(x0+m12) + m5*(x1+m13) +  m6*(x2+m14) + m7 \\
1942    y2 = m8*(x0+m12) + m9*(x1+m13) + m10*(x2+m14) + m11
1943
1944        '''
1945        r = DEFAULT_ERROR
1946        selection = selector.process(selection)
1947        if int(transpose):
1948            matrix = [ matrix[0], matrix[4], matrix[8 ], matrix[12],
1949                       matrix[1], matrix[5], matrix[9 ], matrix[13],
1950                       matrix[2], matrix[6], matrix[10], matrix[14],
1951                       matrix[3], matrix[7], matrix[11], matrix[15]]
1952        try:
1953            _self.lock(_self)
1954            r = _cmd.transform_selection(_self._COb,str(selection),int(state)-1,
1955                                                  list(matrix),int(log),int(homogenous))
1956        finally:
1957            _self.unlock(r,_self)
1958        if _self._raising(r,_self): raise pymol.CmdException
1959        return r
1960
1961    def transform_object(name, matrix, state=-1, log=0, selection='',
1962                         homogenous=0, transpose=0, _self=cmd):
1963        '''
1964DESCRIPTION
1965
1966    "transform_object" in an API-only function which applies a
1967    transformation matrix to an object.
1968
1969    If setting "matrix_mode" > 0 and selection is empty, then this
1970    function operates on the TTT (movie) matrix.
1971
1972ARGUMENTS
1973
1974    name = str: object name
1975
1976    matrix = list of 16 floats: transformation matrix
1977
1978    state = int: object state {default: -1}
1979
1980    log = 0/1: write action to log file (only applies if object is a
1981    molecular object) {default: 0}
1982
1983    selection = str: atom selection (only applies to molecular objects,
1984    if empty then the whole object state is transformed).
1985
1986    homogenous = 0/1: if 0, then matrix[12:15] may contain a pre-translation,
1987    otherwise those values must be zeros (see also cmd.transform_selection)
1988    {default: 0}
1989
1990    transpose = 0/1: matrix is 0=row-major, 1=column-major {default: 0}
1991
1992SEE ALSO
1993
1994    cmd.transform_selection, cmd.set_object_ttt, cmd.matrix_reset
1995        '''
1996        r = DEFAULT_ERROR
1997        if int(transpose):
1998            matrix = [ matrix[0], matrix[4], matrix[8 ], matrix[12],
1999                          matrix[1], matrix[5], matrix[9 ], matrix[13],
2000                          matrix[2], matrix[6], matrix[10], matrix[14],
2001                          matrix[3], matrix[7], matrix[11], matrix[15]]
2002        try:
2003            _self.lock(_self)
2004            r = _cmd.transform_object(_self._COb,str(name),int(state)-1,
2005                                              list(matrix),int(log),
2006                                              str(selection),
2007                                              int(homogenous))
2008        finally:
2009            _self.unlock(r,_self)
2010        if _self._raising(r,_self): raise pymol.CmdException
2011        return r
2012
2013    def matrix_copy(source_name='', target_name='',
2014                    source_mode=-1, target_mode=-1,
2015                    source_state=1, target_state=1,
2016                    target_undo=1, log=0, quiet=1,
2017                    _self=cmd):
2018        '''
2019
2020DESCRIPTION
2021
2022    "matrix_copy" copies a transformation matrix from one object to
2023    another.
2024
2025USAGE
2026
2027    matrix_copy source_name, target_name
2028
2029NOTES
2030
2031    This command is often used after a protein structure alignment to
2032    bring other related objects into the same frame of reference.
2033
2034SEE ALSO
2035
2036    matrix_reset, align, fit, pair_fit
2037'''
2038
2039        r = DEFAULT_ERROR
2040        if source_name is None:
2041            source_name = ''
2042        target_name = str(target_name).strip()
2043        source_name = str(source_name).strip()
2044        if (target_name == '' and source_name != ''): # tentative -- create a new command instead?
2045            mat = _self.get_object_matrix(source_name,source_state)
2046            view = _self.get_view()
2047            new_view = (
2048                mat[ 0]*view[ 0] + mat[ 4]*view[ 3] + mat[ 8]*view[ 6],
2049                mat[ 0]*view[ 1] + mat[ 4]*view[ 4] + mat[ 8]*view[ 7],
2050                mat[ 0]*view[ 2] + mat[ 4]*view[ 5] + mat[ 8]*view[ 8],
2051                mat[ 1]*view[ 0] + mat[ 5]*view[ 3] + mat[ 9]*view[ 6],
2052                mat[ 1]*view[ 1] + mat[ 5]*view[ 4] + mat[ 9]*view[ 7],
2053                mat[ 1]*view[ 2] + mat[ 5]*view[ 5] + mat[ 9]*view[ 8],
2054                mat[ 2]*view[ 0] + mat[ 6]*view[ 3] + mat[10]*view[ 6],
2055                mat[ 2]*view[ 1] + mat[ 6]*view[ 4] + mat[10]*view[ 7],
2056                mat[ 2]*view[ 2] + mat[ 6]*view[ 5] + mat[10]*view[ 8],
2057                view[ 9] ,         view[10] ,         view[11],
2058                mat[ 0]*view[12] + mat[ 1]*view[13] + mat[ 2]*view[14] -
2059                mat[ 0]* mat[ 3] - mat[ 4]* mat[ 7] - mat[ 8]* mat[11],
2060                mat[ 4]*view[12] + mat[ 5]*view[13] + mat[ 6]*view[14] -
2061                mat[ 1]* mat[ 3] - mat[ 5]* mat[ 7] - mat[ 9]* mat[11],
2062                mat[ 8]*view[12] + mat[ 9]*view[13] + mat[10]*view[14] -
2063                mat[ 2]* mat[ 3] - mat[ 6]* mat[ 7] - mat[10]* mat[11],
2064                view[15] ,         view[16] ,         view[17] )
2065            r = _self.set_view(new_view)
2066        else:
2067            with _self.lockcm:
2068                r = _cmd.matrix_copy(_self._COb,str(source_name),
2069                                                 str(target_name),
2070                                                 int(source_mode),
2071                                                 int(target_mode),
2072                                                 int(source_state)-1,
2073                                                 int(target_state)-1,
2074                                                 int(target_undo),
2075                                                 int(log),
2076                                                 int(quiet))
2077            if _self._raising(r,_self):
2078                raise pymol.CmdException
2079        return r
2080
2081    def matrix_reset(name, state=1, mode=-1, log=0, quiet=1,_self=cmd):
2082        '''
2083
2084DESCRIPTION
2085
2086    "matrix_reset" resets the transformation for an object.
2087
2088USAGE
2089
2090    matrix_reset name [, state [, mode ]]
2091
2092ARGUMENTS
2093
2094    name = str: object name
2095
2096    state = int: object state {default: 1}
2097
2098    mode = int: {defualt: -1 = matrix_mode or 0}
2099      0: transformation was applied to coordinates
2100      1: reset TTT matrix (movie transformation)
2101      2: reset state matrix
2102
2103SEE ALSO
2104
2105    matrix_copy, align, super, fit, pair_fit
2106
2107'''
2108
2109        r = DEFAULT_ERROR
2110        try:
2111            _self.lock(_self)
2112            r = _cmd.reset_matrix(_self._COb,str(name),
2113                                         int(mode),
2114                                         int(state)-1,
2115                                         int(log),
2116                                         int(quiet))
2117        finally:
2118            _self.unlock(r,_self)
2119        if _self._raising(r,_self):
2120            raise pymol.CmdException
2121        return r
2122
2123
2124    def translate_atom(sele1, v0, v1, v2, state=0, mode=0,
2125                       log=0, _self=cmd):
2126
2127        r = DEFAULT_ERROR
2128        sele1 = selector.process(sele1)
2129        try:
2130            _self.lock(_self)
2131            r = _cmd.translate_atom(_self._COb,str(sele1),float(v0),float(v1),
2132                                            float(v2),int(state)-1,int(mode),int(log))
2133        finally:
2134            _self.unlock(r,_self)
2135        if _self._raising(r,_self): raise pymol.CmdException
2136        return r
2137
2138    def update(target, source, target_state=0, source_state=0,
2139               matchmaker=1, quiet=1, _self=cmd):
2140
2141        '''
2142DESCRIPTION
2143
2144    "update" transfers coordinates from one selection to another.
2145USAGE
2146
2147    update (target-selection),(source-selection)
2148
2149EXAMPLES
2150
2151    update target,(variant)
2152
2153NOTES
2154
2155    Currently, this applies across all pairs of states.  Fine
2156    control will be added later.
2157
2158SEE ALSO
2159
2160    load
2161    '''
2162        r = DEFAULT_ERROR
2163        a=target
2164        b=source
2165        # preprocess selections
2166        a = selector.process(a)
2167        b = selector.process(b)
2168        #
2169        if a[0]!='(': a="("+str(a)+")"
2170        if b[0]!='(': b="("+str(b)+")"
2171        try:
2172            _self.lock(_self)
2173            r = _cmd.update(_self._COb,str(a),str(b),int(target_state)-1,
2174                                 int(source_state)-1,int(matchmaker),int(quiet))
2175        finally:
2176            _self.unlock(r,_self)
2177        if _self._raising(r,_self): raise pymol.CmdException
2178        return r
2179
2180
2181    def set_dihedral(atom1, atom2, atom3, atom4, angle, state=1, quiet=1, _self=cmd):
2182        '''
2183DESCRIPTION
2184
2185    "set_dihedral" changes the dihedral angle formed between the four
2186    bonded atoms provided.  The atoms must be acyclic.
2187
2188USAGE
2189
2190    set_dihedral atom1, atom2, atom3, atom4, angle [, state [, quiet ]]
2191
2192NOTES
2193
2194    Because set_dihedral uses the molecular editing capability,
2195    numbered "pk" atom selections (if any) will be redefined by this
2196    operation.
2197
2198PYMOL API
2199
2200    cmd.set_dihedral(string atom1, string atom2, string atom3, string atom4,
2201                     float angle, int state, int quiet)
2202
2203    '''
2204        # preprocess selections
2205        atom1 = selector.process(atom1)
2206        atom2 = selector.process(atom2)
2207        atom3 = selector.process(atom3)
2208        atom4 = selector.process(atom4)
2209        #
2210        r = DEFAULT_ERROR
2211        try:
2212            _self.lock(_self)
2213            r = _cmd.set_dihe(_self._COb,atom1,atom2,atom3,atom4,
2214                                    float(angle),int(state)-1,int(quiet))
2215        finally:
2216            _self.unlock(r,_self)
2217        if _self._raising(r,_self): raise pymol.CmdException
2218        return r
2219
2220    map_op_dict = {
2221        'minimum'       : 0,
2222        'maximum'       : 1,
2223        'sum'           : 2,
2224        'average'       : 3,
2225        'difference'    : 4,
2226        'copy'          : 5,
2227        'unique'        : 6,
2228        }
2229
2230    map_op_sc = Shortcut(map_op_dict.keys())
2231
2232    def map_set(name, operator, operands='', target_state=0,
2233                source_state=0, zoom=0, quiet=1, _self=cmd):
2234
2235        '''
2236DESCRIPTION
2237
2238    "map_set" provides a number of common operations on and between maps.
2239
2240USAGE
2241
2242    map_set name, operator, operands, target_state, source_state
2243
2244    operator may be "minimum, maximum, average, sum, or difference"
2245
2246EXAMPLES
2247
2248    map my_sum, add, map1 map2 map3
2249    map my_avg, average, map1 map2 map3
2250
2251NOTES
2252
2253    source_state = 0 means all states
2254    target_state = -1 means current state
2255
2256    experimental
2257
2258SEE ALSO
2259
2260    map_new
2261        '''
2262        r = DEFAULT_ERROR
2263        operator_index = map_op_dict[map_op_sc.auto_err(operator,'operator')]
2264        try:
2265            _self.lock(_self)
2266            r = _cmd.map_set(_self._COb,str(name), int(operator_index), str(operands),
2267                         int(target_state)-1, int(source_state)-1, int(zoom), int(quiet))
2268        finally:
2269            _self.unlock(r,_self)
2270        if _self._raising(r,_self): raise pymol.CmdException
2271        return r
2272
2273    def map_set_border(name, level=0.0, state=0, _self=cmd):
2274
2275        '''
2276DESCRIPTION
2277
2278    "map_set_border" is a function (reqd by PDA) which allows you to set the
2279    level on the edge points of a map
2280
2281USAGE
2282
2283    map_set_border name, level
2284
2285NOTES
2286
2287    unsupported.
2288
2289SEE ALSO
2290
2291    load
2292        '''
2293        r = DEFAULT_ERROR
2294        try:
2295            _self.lock(_self)
2296            r = _cmd.map_set_border(_self._COb,str(name),float(level),int(state))
2297        finally:
2298            _self.unlock(r,_self)
2299        if _self._raising(r,_self): raise pymol.CmdException
2300        return r
2301
2302    def map_double(name, state=0, _self=cmd):
2303        '''
2304DESCRIPTION
2305
2306    "map_double" resamples a map at twice the current resolution.
2307
2308NOTES
2309
2310     The amount of memory required to store the map will increase
2311     eight-fold.
2312
2313USAGE
2314
2315    map_double map_name, state
2316        '''
2317        r = DEFAULT_ERROR
2318        try:
2319            _self.lock(_self)
2320            r = _cmd.map_double(_self._COb,str(name),int(state)-1)
2321        finally:
2322            _self.unlock(r,_self)
2323        if _self._raising(r,_self): raise pymol.CmdException
2324        return r
2325
2326    def map_halve(name, state=0, smooth=1, _self=cmd):
2327
2328        '''
2329DESCRIPTION
2330
2331    "map_halve" resamples a map at half the current resolution.
2332
2333USAGE
2334
2335    map_halve map_name, state
2336
2337NOTES
2338
2339    The amount of memory required to store the map will decrease
2340    eight-fold.
2341
2342SEE ALSO
2343
2344    map_double
2345        '''
2346
2347        r = DEFAULT_ERROR
2348        try:
2349            _self.lock(_self)
2350            r = _cmd.map_halve(_self._COb,str(name),int(state)-1,int(smooth))
2351        finally:
2352            _self.unlock(r,_self)
2353        if _self._raising(r,_self): raise pymol.CmdException
2354        return r
2355
2356    def map_trim(name, selection, buffer=0.0, map_state=0, sele_state=0, quiet=1, _self=cmd):
2357        '''
2358DESCRIPTION
2359
2360    "map_trim" is an unsupported command that may have something to do with
2361    reducing the extent of a map to cover just a single selection of atoms.
2362
2363    '''
2364
2365        r = DEFAULT_ERROR
2366        # preprocess selection
2367        selection = selector.process(selection)
2368        #
2369        try:
2370            _self.lock(_self)
2371            r = _cmd.map_trim(_self._COb,str(name),str(selection),
2372                                  float(buffer),int(map_state)-1,
2373                                  int(sele_state)-1,int(quiet))
2374        finally:
2375            _self.unlock(r,_self)
2376        if _self._raising(r,_self): raise pymol.CmdException
2377        return r
2378
2379
2380    def protect(selection="(all)", quiet=1, _self=cmd):
2381        '''
2382DESCRIPTION
2383
2384    "protect" protects a set of atoms from tranformations performed
2385    using the editing features.  This is most useful when you are
2386    modifying an internal portion of a chain or cycle and do not wish
2387    to affect the rest of the molecule.
2388
2389USAGE
2390
2391    protect (selection)
2392
2393PYMOL API
2394
2395    cmd.protect(string selection)
2396
2397SEE ALSO
2398
2399    deprotect, mask, unmask, mouse, editing
2400    '''
2401        r = DEFAULT_ERROR
2402        # preprocess selection
2403        selection = selector.process(selection)
2404        #
2405        try:
2406            _self.lock(_self)
2407            r = _cmd.protect(_self._COb,"("+str(selection)+")",1,int(quiet))
2408        finally:
2409            _self.unlock(r,_self)
2410        if _self._raising(r,_self): raise pymol.CmdException
2411        return r
2412
2413    def deprotect(selection="(all)", quiet=1, _self=cmd):
2414        '''
2415DESCRIPTION
2416
2417    "deprotect" reverses the effect of the "protect" command.
2418
2419USAGE
2420
2421    deprotect (selection)
2422
2423PYMOL API
2424
2425    cmd.deprotect(string selection)
2426
2427SEE ALSO
2428
2429    protect, mask, unmask, mouse, editing
2430    '''
2431        r = DEFAULT_ERROR
2432        # preprocess selection
2433        selection = selector.process(selection)
2434        #
2435        try:
2436            _self.lock(_self)
2437            r = _cmd.protect(_self._COb,"("+str(selection)+")",0,int(quiet))
2438        finally:
2439            _self.unlock(r,_self)
2440        if _self._raising(r,_self): raise pymol.CmdException
2441        return r
2442
2443    flag_dict = {
2444    # simulation
2445        'focus'         : 0,
2446        'free'          : 1,
2447        'restrain'      : 2,
2448        'fix'           : 3,
2449        'exclude'       : 4,
2450        'study'         : 5,
2451
2452    # rendering
2453        'exfoliate'     : 24,
2454        'ignore'        : 25,
2455        'no_smooth'     : 26,
2456    }
2457
2458    flag_sc = Shortcut(flag_dict.keys())
2459
2460    flag_action_dict = {
2461        'reset' : 0,
2462        'set'   : 1,
2463        'clear' : 2,
2464        }
2465
2466    flag_action_sc = Shortcut(flag_action_dict.keys())
2467
2468    def fix_chemistry(selection1="all", selection2="all",
2469		      invalidate=1, quiet=1, _self=cmd):
2470        '''
2471DESCRIPTION
2472
2473    "fix chemistry" is an unsupported feature.
2474
2475'''
2476        selection1 = selector.process(selection1)
2477        selection2 = selector.process(selection2)
2478        with _self.lockcm:
2479            return _cmd.fix_chemistry(_self._COb,str(selection1),
2480				   str(selection2),int(invalidate),
2481				   int(quiet))
2482
2483    def set_object_color(name, color, quiet=1, _self=cmd):
2484        r = DEFAULT_ERROR
2485        try:
2486            _self.lock(_self)
2487            r = _cmd.set_object_color(_self._COb,str(name),str(color),int(quiet))
2488        finally:
2489            _self.unlock(r,_self)
2490        if _raising(r,_self): raise pymol.CmdException
2491        return r
2492
2493    def flag(flag, selection, action="reset", quiet=1, _self=cmd):
2494        '''
2495DESCRIPTION
2496
2497    "flag" sets the indicated flag for atoms in the selection and
2498     clears the indicated flag for atoms not in the selection.
2499
2500USAGE
2501
2502    flag flag, selection [, action ]
2503
2504ARGUMENTS
2505
2506    action = reset: {default} set flag for atoms in selection and clear it for all others
2507
2508    action = set: set the flag for atoms in selection, leaving other atoms unchanged
2509
2510    action = clear: clear the flag for selected atoms, leaving other atoms unchanged
2511
2512EXAMPLES
2513
2514    flag free, (resi 45 x; 6)
2515
2516NOTES
2517
2518    This is primarily useful for passing selection information into
2519    Chempy models, which have a 32 bit attribute "flag" which holds
2520    this information.
2521
2522    If the 'auto_indicate_flags' setting is true, then PyMOL will automatically
2523    create a selection called "indicate" which contains all atoms with that flag
2524    after applying the command.
2525
2526    SPECIAL FLAGS
2527
2528    * Flags 0-5 are reserved for molecular modeling
2529
2530        focus      0 = Atoms of Interest (i.e. a ligand in an active site) \\
2531        free       1 = Free Atoms (free to move subject to a force-field) \\
2532        restrain   2 = Restrained Atoms (typically harmonically contrained) \\
2533        fix        3 = Fixed Atoms (no movement allowed) \\
2534        exclude    4 = Atoms which should not be part of any simulation
2535        study      5
2536
2537    * Flags 6-7 are for protein and nucleic acid classification
2538
2539    * Flags 8-15 are free for end users to manipulate
2540
2541    * Flags 16-21 are reserved for external GUIs and linked applications
2542
2543    * Flags 22-23 are for temporary use only (flag 23 used for coverage
2544      tracking when assigning parameters in chempy.champ.assign)
2545
2546    * Flags 24-31 are reserved for PyMOL internal usage
2547
2548        exfoliate 24 = Remove surface from atoms when surfacing \\
2549        ignore    25 = Ignore atoms altogether when surfacing \\
2550        no_smooth 26 = Do not smooth atom position
2551
2552PYMOL API
2553
2554    cmd.flag(int flag, string selection, string action="reset",
2555             int indicate=0)
2556
2557        '''
2558        r = DEFAULT_ERROR
2559        # preprocess selection
2560        new_flag = flag_sc.interpret(str(flag))
2561        if new_flag:
2562            if _self.is_string(new_flag):
2563                flag = flag_dict[new_flag]
2564            else:
2565                flag_sc.auto_err(flag,'flag')
2566        # preprocess selection
2567        selection = selector.process(selection)
2568        action = flag_action_dict[flag_action_sc.auto_err(action,'action')]
2569        #
2570        try:
2571            _self.lock(_self)
2572            r = _cmd.flag(_self._COb,int(flag),"("+str(selection)+")",
2573                              int(action),int(quiet))
2574        finally:
2575            _self.unlock(r,_self)
2576        if _self._raising(r,_self): raise pymol.CmdException
2577        return r
2578
2579    def vdw_fit(selection1, selection2, state1=1,state2=1,buffer=0.24,quiet=1,_self=cmd):
2580        '''
2581DESCRIPTION
2582
2583    "vdw_fit" is an unsupported feature.
2584
2585    '''
2586        # preprocess selections
2587        selection1 = selector.process(selection1)
2588        selection2 = selector.process(selection2)
2589        #
2590        r = DEFAULT_ERROR
2591        try:
2592            _self.lock(_self)
2593            r = _cmd.vdw_fit(_self._COb,str(selection1),int(state1)-1,
2594                             str(selection2),int(state2)-1,
2595                             float(buffer),int(quiet))
2596        finally:
2597            _self.unlock(r,_self)
2598        if _self._raising(r,_self): raise pymol.CmdException
2599        return r
2600
2601    def split_chains(selection='(all)', prefix=None, group=None, quiet=1, _self=cmd):
2602        '''
2603DESCRIPTION
2604
2605    Create a single object for each chain in selection
2606
2607SEE ALSO
2608
2609    split_states
2610        '''
2611        count = 0
2612        models = _self.get_object_list('(' + selection + ')')
2613        names_list = []
2614        for model in models:
2615            for chain in _self.get_chains('(%s) and model %s' % (selection, model)):
2616                count += 1
2617                if not prefix:
2618                    name = '%s_%s' % (model, chain)
2619                else:
2620                    name = '%s%04d' % (prefix, count)
2621                _self.create(name, '(%s) and model %s and chain "%s"' %
2622                        (selection, model, chain), zoom=0)
2623                names_list.append(name)
2624            _self.disable(model)
2625
2626        if group:
2627            _self.group(group, ' '.join(names_list), 'add')
2628
2629    def alphatoall(selection='polymer', properties='b', operator='byca',
2630            quiet=1, _self=cmd):
2631        '''
2632DESCRIPTION
2633
2634    Expand any given property of the CA atoms to all atoms in the residue
2635
2636ARGUMENTS
2637
2638    selection = string: atom selection {default: polymer}
2639
2640    properties = string: space separated list of atom properties {default: b}
2641        '''
2642        properties = '(' + ','.join(properties.split()) + ')'
2643        space = {'props': {}}
2644        _self.iterate('%s (%s)' % (operator, selection),
2645                'props[model,segi,chain,resi] = ' + properties,
2646                space=space)
2647        _self.alter(selection,
2648                properties + ' = props.get((model,segi,chain,resi), ' + properties + ')',
2649                space=space)
2650        if not int(quiet):
2651            print(' Modified %d residues' % (len(space['props'])))
2652
2653    def mse2met(selection='all', quiet=1, _self=cmd):
2654        '''
2655DESCRIPTION
2656
2657    Mutate selenomethionine to methionine
2658        '''
2659        x = _self.alter('(%s) and MSE/SE' % selection, 'name="SD";elem="S"')
2660        _self.flag('ignore', '(%s) and resn MSE' % (selection), 'clear')
2661        _self.alter('(%s) and resn MSE' % selection, 'resn="MET";type="ATOM"')
2662        if not int(quiet):
2663            print(' Altered %d MSE residues to MET' % (x))
2664
2665
2666    def _base(i, numerals, _emptyzero=False):
2667        if i == 0:
2668            return '' if _emptyzero else numerals[0]
2669
2670        b = len(numerals)
2671        return _base(i // b, numerals, True) + numerals[i % b]
2672
2673
2674    def uniquify(identifier, selection, reference='', quiet=1, _self=cmd):
2675        '''
2676DESCRIPTION
2677
2678    Make `identifier` unique with respect to reference selection.
2679
2680ARGUMENTS
2681
2682    identifier = str: atom identifier (chain, segi, etc.)
2683
2684    selection = str: atom selection to modify
2685
2686    reference = str: atom selection whose identifiers must not be
2687    present in the first selection {default: !selection}
2688
2689EXAMPLE
2690
2691    fetch 1a00 1hbb, async=0
2692    uniquify chain, 1hbb
2693    # 1hbb now has chains E,F,G,H
2694        '''
2695        import itertools
2696        import string
2697
2698        if not reference:
2699            reference = '!(' + selection + ')'
2700
2701        p = identifier
2702
2703        set_ref = set()
2704        set_sel = set()
2705        mapping = {}
2706        space = {'set_ref': set_ref, 'set_sel': set_sel, 'mapping': mapping}
2707
2708        _self.iterate(reference, 'set_ref.add(' + p + ')', space=space)
2709        _self.iterate(selection, 'set_sel.add(' + p + ')', space=space)
2710
2711        set_union = set_ref | set_sel
2712        set_inter = set_ref & set_sel
2713
2714        if not set_inter:
2715            return
2716
2717        baseargs = ()
2718        i_iter = itertools.count(1)
2719
2720        if isinstance(next(iter(set_inter)), int):
2721            basefunc = int
2722        elif p in ('resi',):
2723            basefunc = str
2724        else:
2725            basefunc = _base
2726            baseargs = (string.ascii_uppercase + '123456789',)
2727            i_iter = itertools.count(0)
2728
2729        for name in set_inter:
2730            for i in i_iter:
2731                newname = basefunc(i, *baseargs)
2732                if newname not in set_union:
2733                    mapping[name] = newname
2734                    set_union.add(newname)
2735                    break
2736
2737        _self.alter(selection, '%s = mapping.get(%s, %s)' % (p, p, p),
2738                space=space)
2739
2740        if not int(quiet):
2741            print(' Uniquify: renamed %d %s identifier(s)' % (len(mapping), p))
2742
2743
2744    def copy_to(name, selection, rename='chain segi ID', zoom=-1, quiet=1, _self=cmd):
2745        '''
2746DESCRIPTION
2747
2748    Copies selection to object `name` (all states) and by default
2749    renames chain, segi and ID identifiers to avoid naming conflicts.
2750
2751ARGUMENTS
2752
2753    name = str: object name to modify
2754
2755    selection = str: atom selection (will be copied to `name`)
2756
2757    rename = str: space separated list of identifiers to rename
2758    {default: chain segi ID}
2759
2760SEE ALSO
2761
2762    create, fuse
2763        '''
2764        temp = _self.get_unused_name('_tmp')
2765
2766        try:
2767            _self.create(temp, selection, zoom=0)
2768            _self.disable(' '.join(_self.get_object_list(selection)))
2769
2770            for prop in rename.split():
2771                if prop.upper() == 'ID':
2772                    _self.alter(temp, 'ID = -1')
2773                else:
2774                    uniquify(prop, temp, '?' + name, quiet=quiet)
2775
2776            _self.create(name, '?' + name + ' ' + temp, zoom=zoom)
2777            _self.unpick()
2778
2779            if not int(quiet):
2780                n = _self.count_atoms(temp)
2781                print(' Copied %d atoms to object %s' % (n, name))
2782        finally:
2783            _self.delete(temp)
2784