コード例 #1
0
    def run(self):
        if not self.part.molecules:
            return
        for chunk in self.part.molecules:
            if chunk.atoms:
                for atom in chunk.atoms.itervalues():
                    atom.setOverlayText("?")
                chunk.showOverlayText = True

        selection = self.part.selection_for_all()
        simaspect = sim_aspect(
            self.part, selection.atomslist(), cmdname_for_messages="CheckAtomTypes", anchor_all_nonmoving_atoms=False
        )

        movie = Movie(self.assy)
        # self._movie = movie

        writemovie(
            self.part,
            movie,
            1,
            simaspect=simaspect,
            print_sim_warnings=True,
            cmdname="Simulator",
            cmd_type="Check AtomTypes",
            useGromacs=False,
            background=False,
            useAMBER=True,
            typeFeedback=True,
        )

        self.part.gl_update()
コード例 #2
0
ファイル: sim_commandruns.py プロジェクト: vcsrc/nanoengineer
    def run(self):
        if not self.part.molecules:
            return
        for chunk in self.part.molecules:
            if (chunk.atoms):
                for atom in chunk.atoms.itervalues():
                    atom.setOverlayText("?")
                chunk.showOverlayText = True

        selection = self.part.selection_for_all()
        simaspect = sim_aspect(self.part,
                               selection.atomslist(),
                               cmdname_for_messages="CheckAtomTypes",
                               anchor_all_nonmoving_atoms=False)

        movie = Movie(self.assy)
        #self._movie = movie

        writemovie(self.part,
                   movie,
                   1,
                   simaspect=simaspect,
                   print_sim_warnings=True,
                   cmdname="Simulator",
                   cmd_type="Check AtomTypes",
                   useGromacs=False,
                   background=False,
                   useAMBER=True,
                   typeFeedback=True)

        self.part.gl_update()
コード例 #3
0
    def makeSimMovie(self): ####@@@@ some of this should be a Movie method since it uses attrs of Movie...
        #bruce 050324 made this from the Part method makeSimMovie.
        # It's called only from self.run() above; not clear it should be a separate method,
        # or if it is, that it's split from the caller at the right boundary.
        suffix = self.part.movie_suffix()
        if suffix is None: #bruce 050316 temporary kluge
            msg = redmsg( "Simulator is not yet implemented for clipboard items.")
            env.history.message(self.cmdname + ": " + msg)
            return -1
        ###@@@ else use suffix below!

        self.simcntl = SimSetup(self.win, self.part, suffix = suffix)
            # this now has its own sticky params, doesn't need previous_movie [bruce 060601, fixing bug 1840]
            # Open SimSetup dialog [and run it until user dismisses it]
        movie = self.simcntl.movie # always a Movie object, even if user cancelled the dialog

        if movie.cancelled:
            # user hit Cancel button in SimSetup Dialog. No history msg went out; caller will do that.
            movie.destroy()
            return -1
        r = writemovie(self.part, movie, print_sim_warnings = True, cmdname = self.cmdname)
            # not passing mtype means "run dynamic sim (not minimize), make movie"
            ###@@@ bruce 050324 comment: maybe should do following in that function too
        if not r:
            # Movie file created. Initialize. ###@@@ bruce 050325 comment: following mods private attrs, needs cleanup.
            movie.IsValid = True # Movie is valid.###@@@ bruce 050325 Q: what exactly does this (or should this) mean?
                ###@@@ bruce 050404: need to make sure this is a new obj-- if not always and this is not init False, will cause bugs
            self.movie = movie # bruce 050324 added this
            # it's up to caller to store self.movie in self.assy.current_movie if it wants to.
        return r
コード例 #4
0
ファイル: sim_commandruns.py プロジェクト: vcsrc/nanoengineer
    def makeSimMovie(
        self
    ):  ####@@@@ some of this should be a Movie method since it uses attrs of Movie...
        #bruce 050324 made this from the Part method makeSimMovie.
        # It's called only from self.run() above; not clear it should be a separate method,
        # or if it is, that it's split from the caller at the right boundary.
        suffix = self.part.movie_suffix()
        if suffix is None:  #bruce 050316 temporary kluge
            msg = redmsg(
                "Simulator is not yet implemented for clipboard items.")
            env.history.message(self.cmdname + ": " + msg)
            return -1
        ###@@@ else use suffix below!

        self.simcntl = SimSetup(self.win, self.part, suffix=suffix)
        # this now has its own sticky params, doesn't need previous_movie [bruce 060601, fixing bug 1840]
        # Open SimSetup dialog [and run it until user dismisses it]
        movie = self.simcntl.movie  # always a Movie object, even if user cancelled the dialog

        if movie.cancelled:
            # user hit Cancel button in SimSetup Dialog. No history msg went out; caller will do that.
            movie.destroy()
            return -1
        r = writemovie(self.part,
                       movie,
                       print_sim_warnings=True,
                       cmdname=self.cmdname)
        # not passing mtype means "run dynamic sim (not minimize), make movie"
        ###@@@ bruce 050324 comment: maybe should do following in that function too
        if not r:
            # Movie file created. Initialize. ###@@@ bruce 050325 comment: following mods private attrs, needs cleanup.
            movie.IsValid = True  # Movie is valid.###@@@ bruce 050325 Q: what exactly does this (or should this) mean?
            ###@@@ bruce 050404: need to make sure this is a new obj-- if not always and this is not init False, will cause bugs
            self.movie = movie  # bruce 050324 added this
            # it's up to caller to store self.movie in self.assy.current_movie if it wants to.
        return r
コード例 #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
コード例 #6
0
ファイル: sim_commandruns.py プロジェクト: vcsrc/nanoengineer
    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