Ejemplo n.º 1
0
 def setup_ruc(self):
     """
     #doc
     """
     #bruce 060705 use new common code, if it works
     from widgets.widget_controllers import realtime_update_controller
     self.ruc = realtime_update_controller(
         #( self.update_btngrp, self.update_number_spinbox, self.update_units_combobox ),
         ( self.watch_motion_buttongroup, self.update_number_spinbox, self.update_units_combobox ),
         self.watch_motion_groupbox,
         Minimize_watchRealtimeMinimization_prefs_key
     )
     ## can't do this yet: self.ruc.set_widgets_from_update_data( self.previous_movie._update_data ) # includes checkbox
     # for A8, only the checkbox will be persistent; the others will be sticky only because the dialog is not remade at runtime
     return
Ejemplo n.º 2
0
    def setup(self):
        self.movie.cancelled = True  # We will assume the user will cancel
        #bruce 050324: fixed KnownBug item 27 by making these call setValue, not assign to it:
        # If the sim parameters change, they need to be updated in all places marked "SIMPARAMS"
        # Movie.__init__ (movie.py), toward the end
        # SimSetup.setup (SimSetup.py)
        # FakeMovie.__init (runSim.py)
        self.totalFramesSpinBox.setValue(
            self.previous_movie.totalFramesRequested)
        self.temperatureSpinBox.setValue(self.previous_movie.temp)
        self.stepsPerFrameDoubleSpinBox.setValue(self.previous_movie.stepsper /
                                                 10.0)
        #        self.timestepSB.setValue( self.previous_movie.timestep ) # Not supported in Alpha
        # new checkboxes for Alpha7, circa 060108
        #self.create_movie_file_checkbox.setChecked( self.previous_movie.create_movie_file )
        # whether to store movie file (see NFR/bug 1286). [bruce & mark 060108]
        # create_movie_file_checkbox removed for A7 (bug 1729). mark 060321

        ##e the following really belongs in the realtime_update_controller,
        # and the update_cond is not the best thing to set this from;
        # but we can leave it here, then let the realtime_update_controller override it if it knows how. [now it does]
        self.watch_motion_groupbox.setChecked(
            self.previous_movie.watch_motion
        )  # whether to move atoms in realtime

        try:
            #bruce 060705 use new common code, if it works
            from widgets.widget_controllers import realtime_update_controller
            self.ruc = realtime_update_controller(
                (self.watch_motion_buttongroup, self.update_number_spinbox,
                 self.update_units_combobox), self.watch_motion_groupbox
                # no prefs key for checkbox
            )
            self.ruc.set_widgets_from_update_data(
                self.previous_movie._update_data)  # includes checkbox
        except:
            print_compact_traceback(
                "bug; reverting to older code in simsetep setup: ")
            if self.previous_movie._update_data:
                update_number, update_units, update_as_fast_as_possible_data, watchjunk = self.previous_movie._update_data
                self.watch_motion_groupbox.setChecked(watchjunk)  ###060705
                self.watch_motion_groupbox.setButton(
                    update_as_fast_as_possible_data)
                self.update_number_spinbox.setValue(update_number)
                self.update_units_combobox.setCurrentText(update_units)
                #k let's hope this changes the current choice, not the popup menu item text for the current choice!
        return
Ejemplo n.º 3
0
    def setup(self):
        self.movie.cancelled = True # We will assume the user will cancel
        #bruce 050324: fixed KnownBug item 27 by making these call setValue, not assign to it:
        # If the sim parameters change, they need to be updated in all places marked "SIMPARAMS"
        # Movie.__init__ (movie.py), toward the end
        # SimSetup.setup (SimSetup.py)
        # FakeMovie.__init (runSim.py)
        self.totalFramesSpinBox.setValue( self.previous_movie.totalFramesRequested )
        self.temperatureSpinBox.setValue( self.previous_movie.temp )
        self.stepsPerFrameDoubleSpinBox.setValue( self.previous_movie.stepsper / 10.0 )
#        self.timestepSB.setValue( self.previous_movie.timestep ) # Not supported in Alpha
        # new checkboxes for Alpha7, circa 060108
        #self.create_movie_file_checkbox.setChecked( self.previous_movie.create_movie_file )
            # whether to store movie file (see NFR/bug 1286). [bruce & mark 060108]
            # create_movie_file_checkbox removed for A7 (bug 1729). mark 060321

        ##e the following really belongs in the realtime_update_controller,
        # and the update_cond is not the best thing to set this from;
        # but we can leave it here, then let the realtime_update_controller override it if it knows how. [now it does]
        self.watch_motion_groupbox.setChecked( self.previous_movie.watch_motion ) # whether to move atoms in realtime

        try:
            #bruce 060705 use new common code, if it works
            from widgets.widget_controllers import realtime_update_controller
            self.ruc = realtime_update_controller(
                ( self.watch_motion_buttongroup, self.update_number_spinbox, self.update_units_combobox ),
                self.watch_motion_groupbox
                # no prefs key for checkbox
            )
            self.ruc.set_widgets_from_update_data( self.previous_movie._update_data ) # includes checkbox
        except:
            print_compact_traceback( "bug; reverting to older code in simsetep setup: ")
            if self.previous_movie._update_data:
                update_number, update_units, update_as_fast_as_possible_data, watchjunk = self.previous_movie._update_data
                self.watch_motion_groupbox.setChecked(watchjunk) ###060705
                self.watch_motion_groupbox.setButton( update_as_fast_as_possible_data)
                self.update_number_spinbox.setValue( update_number)
                self.update_units_combobox.setCurrentText( update_units)
                    #k let's hope this changes the current choice, not the popup menu item text for the current choice!
        return
Ejemplo n.º 4
0
    def doMinimize(self, mtype = 1, simaspect = None):
        #bruce 051115 renamed method from makeMinMovie
        #bruce 051115 revised docstring to fit current code #e should clean it up more
        """
        Minimize self.part (if simaspect is None -- no longer used)
        or its given simaspect (simulatable aspect) (used for both Minimize Selection and Minimize All),
        generating and showing a movie (no longer asked for) or generating and applying to part an xyz file.

        The mtype flag means:
        1 = tell writemovie() to create a single-frame XYZ file.
        2 = tell writemovie() to create a multi-frame DPB moviefile.
            [###@@@ not presently used, might not work anymore]
        """
        assert mtype == 1 #bruce 051115
        assert simaspect is not None #bruce 051115
        #bruce 050324 made this from the Part method makeMinMovie.
        suffix = self.part.movie_suffix()
        if suffix is None: #bruce 050316 temporary kluge; as of circa 050326 this is not used anymore
            msg = "%s is not yet implemented for clipboard items." % self.word_Minimize
            env.history.message( redmsg( msg))
            return
        #e use suffix below? maybe no need since it's ok if the same filename is reused for this.

        # bruce 050325 change: don't use or modify self.assy.current_movie,
        # since we're not making a movie and don't want to prevent replaying
        # the one already stored from some sim run.
        # [this is for mtype == 1 (always true now) and might affect writemovie ###@@@ #k.]

        # NOTE: the movie object is used to hold params and results from minimize,
        # even if it makes an xyz file rather than a movie file.
        # And at the moment it never makes a movie file when called from this code.
        # [bruce 051115 comment about months-old situation]

        movie = Movie(self.assy)
            # do this in writemovie? no, the other call of it needs it passed in
            # from the dialog... #k
            # note that Movie class is misnamed since it's really a
            # SimRunnerAndResultsUser... which might use .xyz or .dpb results...
            # maybe rename it SimRun? ###e also, it needs subclasses for the
            # different kinds of sim runs and their results... or maybe it needs
            # a subobject which has such subclasses -- not yet sure. [bruce 050329]

        self._movie = movie
            #bruce 050415 kluge; note that class SimRun does the same thing.
            # Probably it means that this class, SimRun, and this way of using
            # class Movie should all be the same, or at least have more links
            # than they do now. ###@@@

        # Set update_cond for controlling realtime update settings for watching
        # this "movie" (an ongoing sim). There are three possible ways
        # (soon after A8 only the first one will be used) [bruce 060705]:
        # - caller specified it.
        # - if it didn't, use new common code to get it from General Prefs page.
        # - if that fails, use older code for that.
        #
        # WARNING: it turns out this happens whether or not the checkbox pref
        # says it should -- that is checked separately elsewhere! That's a bug,
        # since we need to use a different checkbox depending on the command.
        # let's see if we can consolidate the "enabling flag" into
        # update_cond itself? so it is None or False if we won't update.
        # this is now attempted...
        if env.debug():
            print "debug fyi: runSim/sim_commandruns watch_motion update_cond computed here " \
                  "(even if not watching motion)" #bruce 060705
        try:
            # Only the client code knows where to find the correct realtime
            # update settings widgets (or someday, knows whether these values
            # come from widgets at all, vs from a script).
            # It should figure out the update_cond
            # (False if we should not watch motion),
            # and tell us in self.kws['update_cond'].
            update_cond = self.kws['update_cond']
            assert update_cond or (update_cond is False) # a callable or False [remove when works]
            # WARNING: as of 080321, this apparently fails routinely
            # for Adjust All, and then the first fallback in the
            # except clause also fails (userPrefs.watch_motion_buttongroup
            # attributeerror), and then its fallback finally works.
            # Cleanup is severely needed. [bruce 080321 comment]
        except:
            ## print_compact_traceback("bug ...: ")
            if env.debug():
                print "debug: fyi: sim_commandruns grabbing userPrefs data"
            # For A8, this is normal, since only (at most) Minimize Energy sets self.kws['update_cond'] itself.
            # This will be used routinely in A8 by Adjust All and Adjust Selection, and maybe Adjust Atoms (not sure).
            #
            # Just get the values from the "Adjust" prefs page.
            # But at least try to do that using new common code.
            try:
                from widgets.widget_controllers import realtime_update_controller
                userPrefs = env.mainwindow().userPrefs
                from utilities.prefs_constants import Adjust_watchRealtimeMinimization_prefs_key
                    ###@@@ should depend on command, or be in movie...
                ruc = realtime_update_controller(
                    ( userPrefs.watch_motion_buttongroup,
                          # Note: watch_motion_buttongroup exists in MinimizeEnergyProp.py
                          # and in SimSetup.py and now its back in Preferences.py,
                          # so this is no longer a bug (for "Adjust All"). [mark 2008-06-04]
                      userPrefs.update_number_spinbox,
                      userPrefs.update_units_combobox ),
                    None, # checkbox ###@@@ maybe not needed, since UserPrefs sets up the connection #k
                    Adjust_watchRealtimeMinimization_prefs_key )
                update_cond = ruc.get_update_cond_from_widgets()
                # note, if those widgets are connected to env.prefs, that's not handled here or in ruc;
                # I'm not sure if they are. Ideally we'd tell ruc the prefs_keys and have it handle that too,
                # perhaps making it a long-lived object (though that might not be necessary).
                assert update_cond or (update_cond is False) # a callable or False
            except:
                # even that didn't work. Complain, then fall back to otherwise-obsolete old code.
                msg = "bug using realtime_update_controller in sim_commandruns, will use older code instead: "
                print_compact_traceback(msg)
                # This code works (except for always using the widgets from the General Prefs page,
                # even for Minimize Energy), but I'll try to replace it with calls to common code.
                # [bruce 060705]
                # This code for setting update_cond is duplicated (inexactly)
                # in SimSetup.createMoviePressed() in SimSetup.py.
                userPrefs = env.mainwindow().userPrefs
                update_units = userPrefs.update_units_combobox.currentText()
                update_number = userPrefs.update_number_spinbox.value()
                if userPrefs.update_asap_rbtn.isChecked():
                    update_cond = ( lambda simtime, pytime, nframes:
                                    simtime >= max(0.05, min(pytime * 4, 2.0)) )
                elif update_units == 'frames':
                    update_cond = ( lambda simtime, pytime, nframes, _nframes = update_number:  nframes >= _nframes )
                elif update_units == 'seconds':
                    update_cond = ( lambda simtime, pytime, nframes, _timelimit = update_number:  simtime + pytime >= _timelimit )
                elif update_units == 'minutes':
                    update_cond = ( lambda simtime, pytime, nframes, _timelimit = update_number * 60:  simtime + pytime >= _timelimit )
                elif update_units == 'hours':
                    update_cond = ( lambda simtime, pytime, nframes, _timelimit = update_number * 3600:  simtime + pytime >= _timelimit )
                else:
                    print "don't know how to set update_cond from (%r, %r)" % (update_number, update_units)
                    update_cond = None
                # new as of 060705, in this old code
                if not env.prefs[Adjust_watchRealtimeMinimization_prefs_key]:
                    update_cond = False
            pass
        # now do this with update_cond, however it was computed
        movie.update_cond = update_cond

        # semi-obs comment, might still be useful [as of 050406]:
        # Minimize Selection [bruce 050330] (ought to be a distinct
        # command subclass...) this will use the spawning code in writemovie
        # but has its own way of writing the mmp file.
        # To make this clean, we need to turn writemovie into more than one
        # method of a class with more than one subclass, so we can override
        # one of them (writing mmp file) and another one (finding atom list).
        # But to get it working I might just kluge it
        # by passing it some specialized options... ###@@@ not sure

        movie._cmdname = self.cmdname
            #bruce 050415 kluge so writemovie knows proper progress bar caption to use
            # (not really wrong -- appropriate for only one of several
            # classes Movie should be split into, i.e. one for the way we're using it here,
            # to know how to run the sim, which is perhaps really self (a SimRunner),
            # once the code is fully cleaned up.
            # [review: is that the same SimRunner which is by 080321
            #  a real class in runSim?]

        # write input for sim, and run sim
        # this also sets movie.alist from simaspect
        r = writemovie(self.part,
                       movie,
                       mtype,
                       simaspect = simaspect,
                       print_sim_warnings = True,
                       cmdname = self.cmdname,
                       cmd_type = self.cmd_type,
                       useGromacs = self.useGromacs,
                       background = self.background)
        if r:
            # We had a problem writing the minimize file.
            # Simply return (error message already emitted by writemovie). ###k
            return

        if mtype == 1:  # Load single-frame XYZ file.
            if (self.useGromacs):
                if (self.background):
                    return
                tracefileProcessor = movie._simrun.tracefileProcessor
                newPositions = readGromacsCoordinates(movie.filename + "-out.gro", movie.alist, tracefileProcessor)
            else:
                newPositions = readxyz( movie.filename, movie.alist )
                    # movie.alist is now created in writemovie [bruce 050325]
            # retval is either a list of atom posns or an error message string.
            assert type(newPositions) in [type([]),type("")]
            if type(newPositions) == type([]):
                #bruce 060102 note: following code is approximately duplicated somewhere else in this file.
                movie.moveAtoms(newPositions)
                # bruce 050311 hand-merged mark's 1-line bugfix in assembly.py (rev 1.135):
                self.part.changed() # Mark - bugfix 386
                self.part.gl_update()
            else:
                #bruce 050404: print error message to history
                env.history.message(redmsg( newPositions))
        else: # Play multi-frame DPB movie file.
            ###@@@ bruce 050324 comment: can this still happen? [no] is it correct [probably not]
            # (what about changing mode to movieMode, does it ever do that?) [don't know]
            # I have not reviewed this and it's obviously not cleaned up (since it modifies private movie attrs).
            # But I will have this change the current movie, which would be correct in theory, i think, and might be needed
            # before trying to play it (or might be a side effect of playing it, this is not reviewed either).
            ###e bruce 050428 comment: if self.assy.current_movie exists, should do something like close or destroy it... need to review
            self.assy.current_movie = movie
            # If cueMovie() returns a non-zero value, something went wrong loading the movie.
            if movie.cueMovie():
                return
            movie._play()
            movie._close()
        return
Ejemplo n.º 5
0
    def doMinimize(self, mtype=1, simaspect=None):
        #bruce 051115 renamed method from makeMinMovie
        #bruce 051115 revised docstring to fit current code #e should clean it up more
        """
        Minimize self.part (if simaspect is None -- no longer used)
        or its given simaspect (simulatable aspect) (used for both Minimize Selection and Minimize All),
        generating and showing a movie (no longer asked for) or generating and applying to part an xyz file.

        The mtype flag means:
        1 = tell writemovie() to create a single-frame XYZ file.
        2 = tell writemovie() to create a multi-frame DPB moviefile.
            [###@@@ not presently used, might not work anymore]
        """
        assert mtype == 1  #bruce 051115
        assert simaspect is not None  #bruce 051115
        #bruce 050324 made this from the Part method makeMinMovie.
        suffix = self.part.movie_suffix()
        if suffix is None:  #bruce 050316 temporary kluge; as of circa 050326 this is not used anymore
            msg = "%s is not yet implemented for clipboard items." % self.word_Minimize
            env.history.message(redmsg(msg))
            return
        #e use suffix below? maybe no need since it's ok if the same filename is reused for this.

        # bruce 050325 change: don't use or modify self.assy.current_movie,
        # since we're not making a movie and don't want to prevent replaying
        # the one already stored from some sim run.
        # [this is for mtype == 1 (always true now) and might affect writemovie ###@@@ #k.]

        # NOTE: the movie object is used to hold params and results from minimize,
        # even if it makes an xyz file rather than a movie file.
        # And at the moment it never makes a movie file when called from this code.
        # [bruce 051115 comment about months-old situation]

        movie = Movie(self.assy)
        # do this in writemovie? no, the other call of it needs it passed in
        # from the dialog... #k
        # note that Movie class is misnamed since it's really a
        # SimRunnerAndResultsUser... which might use .xyz or .dpb results...
        # maybe rename it SimRun? ###e also, it needs subclasses for the
        # different kinds of sim runs and their results... or maybe it needs
        # a subobject which has such subclasses -- not yet sure. [bruce 050329]

        self._movie = movie
        #bruce 050415 kluge; note that class SimRun does the same thing.
        # Probably it means that this class, SimRun, and this way of using
        # class Movie should all be the same, or at least have more links
        # than they do now. ###@@@

        # Set update_cond for controlling realtime update settings for watching
        # this "movie" (an ongoing sim). There are three possible ways
        # (soon after A8 only the first one will be used) [bruce 060705]:
        # - caller specified it.
        # - if it didn't, use new common code to get it from General Prefs page.
        # - if that fails, use older code for that.
        #
        # WARNING: it turns out this happens whether or not the checkbox pref
        # says it should -- that is checked separately elsewhere! That's a bug,
        # since we need to use a different checkbox depending on the command.
        # let's see if we can consolidate the "enabling flag" into
        # update_cond itself? so it is None or False if we won't update.
        # this is now attempted...
        if env.debug():
            print "debug fyi: runSim/sim_commandruns watch_motion update_cond computed here " \
                  "(even if not watching motion)" #bruce 060705
        try:
            # Only the client code knows where to find the correct realtime
            # update settings widgets (or someday, knows whether these values
            # come from widgets at all, vs from a script).
            # It should figure out the update_cond
            # (False if we should not watch motion),
            # and tell us in self.kws['update_cond'].
            update_cond = self.kws['update_cond']
            assert update_cond or (update_cond is False
                                   )  # a callable or False [remove when works]
            # WARNING: as of 080321, this apparently fails routinely
            # for Adjust All, and then the first fallback in the
            # except clause also fails (userPrefs.watch_motion_buttongroup
            # attributeerror), and then its fallback finally works.
            # Cleanup is severely needed. [bruce 080321 comment]
        except:
            ## print_compact_traceback("bug ...: ")
            if env.debug():
                print "debug: fyi: sim_commandruns grabbing userPrefs data"
            # For A8, this is normal, since only (at most) Minimize Energy sets self.kws['update_cond'] itself.
            # This will be used routinely in A8 by Adjust All and Adjust Selection, and maybe Adjust Atoms (not sure).
            #
            # Just get the values from the "Adjust" prefs page.
            # But at least try to do that using new common code.
            try:
                from widgets.widget_controllers import realtime_update_controller
                userPrefs = env.mainwindow().userPrefs
                from utilities.prefs_constants import Adjust_watchRealtimeMinimization_prefs_key
                ###@@@ should depend on command, or be in movie...
                ruc = realtime_update_controller(
                    (
                        userPrefs.watch_motion_buttongroup,
                        # Note: watch_motion_buttongroup exists in MinimizeEnergyProp.py
                        # and in SimSetup.py and now its back in Preferences.py,
                        # so this is no longer a bug (for "Adjust All"). [mark 2008-06-04]
                        userPrefs.update_number_spinbox,
                        userPrefs.update_units_combobox),
                    None,  # checkbox ###@@@ maybe not needed, since UserPrefs sets up the connection #k
                    Adjust_watchRealtimeMinimization_prefs_key)
                update_cond = ruc.get_update_cond_from_widgets()
                # note, if those widgets are connected to env.prefs, that's not handled here or in ruc;
                # I'm not sure if they are. Ideally we'd tell ruc the prefs_keys and have it handle that too,
                # perhaps making it a long-lived object (though that might not be necessary).
                assert update_cond or (update_cond is False
                                       )  # a callable or False
            except:
                # even that didn't work. Complain, then fall back to otherwise-obsolete old code.
                msg = "bug using realtime_update_controller in sim_commandruns, will use older code instead: "
                print_compact_traceback(msg)
                # This code works (except for always using the widgets from the General Prefs page,
                # even for Minimize Energy), but I'll try to replace it with calls to common code.
                # [bruce 060705]
                # This code for setting update_cond is duplicated (inexactly)
                # in SimSetup.createMoviePressed() in SimSetup.py.
                userPrefs = env.mainwindow().userPrefs
                update_units = userPrefs.update_units_combobox.currentText()
                update_number = userPrefs.update_number_spinbox.value()
                if userPrefs.update_asap_rbtn.isChecked():
                    update_cond = (lambda simtime, pytime, nframes: simtime >=
                                   max(0.05, min(pytime * 4, 2.0)))
                elif update_units == 'frames':
                    update_cond = (lambda simtime, pytime, nframes, _nframes=
                                   update_number: nframes >= _nframes)
                elif update_units == 'seconds':
                    update_cond = (
                        lambda simtime, pytime, nframes, _timelimit=
                        update_number: simtime + pytime >= _timelimit)
                elif update_units == 'minutes':
                    update_cond = (
                        lambda simtime, pytime, nframes, _timelimit=
                        update_number * 60: simtime + pytime >= _timelimit)
                elif update_units == 'hours':
                    update_cond = (
                        lambda simtime, pytime, nframes, _timelimit=
                        update_number * 3600: simtime + pytime >= _timelimit)
                else:
                    print "don't know how to set update_cond from (%r, %r)" % (
                        update_number, update_units)
                    update_cond = None
                # new as of 060705, in this old code
                if not env.prefs[Adjust_watchRealtimeMinimization_prefs_key]:
                    update_cond = False
            pass
        # now do this with update_cond, however it was computed
        movie.update_cond = update_cond

        # semi-obs comment, might still be useful [as of 050406]:
        # Minimize Selection [bruce 050330] (ought to be a distinct
        # command subclass...) this will use the spawning code in writemovie
        # but has its own way of writing the mmp file.
        # To make this clean, we need to turn writemovie into more than one
        # method of a class with more than one subclass, so we can override
        # one of them (writing mmp file) and another one (finding atom list).
        # But to get it working I might just kluge it
        # by passing it some specialized options... ###@@@ not sure

        movie._cmdname = self.cmdname
        #bruce 050415 kluge so writemovie knows proper progress bar caption to use
        # (not really wrong -- appropriate for only one of several
        # classes Movie should be split into, i.e. one for the way we're using it here,
        # to know how to run the sim, which is perhaps really self (a SimRunner),
        # once the code is fully cleaned up.
        # [review: is that the same SimRunner which is by 080321
        #  a real class in runSim?]

        # write input for sim, and run sim
        # this also sets movie.alist from simaspect
        r = writemovie(self.part,
                       movie,
                       mtype,
                       simaspect=simaspect,
                       print_sim_warnings=True,
                       cmdname=self.cmdname,
                       cmd_type=self.cmd_type,
                       useGromacs=self.useGromacs,
                       background=self.background)
        if r:
            # We had a problem writing the minimize file.
            # Simply return (error message already emitted by writemovie). ###k
            return

        if mtype == 1:  # Load single-frame XYZ file.
            if (self.useGromacs):
                if (self.background):
                    return
                tracefileProcessor = movie._simrun.tracefileProcessor
                newPositions = readGromacsCoordinates(
                    movie.filename + "-out.gro", movie.alist,
                    tracefileProcessor)
            else:
                newPositions = readxyz(movie.filename, movie.alist)
                # movie.alist is now created in writemovie [bruce 050325]
            # retval is either a list of atom posns or an error message string.
            assert type(newPositions) in [type([]), type("")]
            if type(newPositions) == type([]):
                #bruce 060102 note: following code is approximately duplicated somewhere else in this file.
                movie.moveAtoms(newPositions)
                # bruce 050311 hand-merged mark's 1-line bugfix in assembly.py (rev 1.135):
                self.part.changed()  # Mark - bugfix 386
                self.part.gl_update()
            else:
                #bruce 050404: print error message to history
                env.history.message(redmsg(newPositions))
        else:  # Play multi-frame DPB movie file.
            ###@@@ bruce 050324 comment: can this still happen? [no] is it correct [probably not]
            # (what about changing mode to movieMode, does it ever do that?) [don't know]
            # I have not reviewed this and it's obviously not cleaned up (since it modifies private movie attrs).
            # But I will have this change the current movie, which would be correct in theory, i think, and might be needed
            # before trying to play it (or might be a side effect of playing it, this is not reviewed either).
            ###e bruce 050428 comment: if self.assy.current_movie exists, should do something like close or destroy it... need to review
            self.assy.current_movie = movie
            # If cueMovie() returns a non-zero value, something went wrong loading the movie.
            if movie.cueMovie():
                return
            movie._play()
            movie._close()
        return