コード例 #1
0
ファイル: qttrajectory.py プロジェクト: yotama9/chemlab
class QtTrajectoryViewer(QMainWindow):
    """Bases: `PySide.QtGui.QMainWindow`

    Interface for viewing trajectory.

    It provides interface elements to play/pause and set the speed of
    the animation.
    
    **Example**

    To set up a QtTrajectoryViewer you have to add renderers to the
    scene, set the number of frames present in the animation by calling
    ;py:meth:`~chemlab.graphics.QtTrajectoryViewer.set_ticks` and
    define an update function.

    Below is an example taken from the function
    :py:func:`chemlab.graphics.display_trajectory`::
    
        from chemlab.graphics import QtTrajectoryViewer
        
        # sys = some System
        # coords_list = some list of atomic coordinates
        
        v = QtTrajectoryViewer()
        sr = v.add_renderer(AtomRenderer, sys.r_array, sys.type_array,
                            backend='impostors')
        br = v.add_renderer(BoxRenderer, sys.box_vectors)
        
        v.set_ticks(len(coords_list))
        
        @v.update_function
        def on_update(index):
            sr.update_positions(coords_list[index])
            br.update(sys.box_vectors)
            v.set_text(format_time(times[index]))
            v.widget.repaint()
     
        v.run()
    
    .. warning:: Use with caution, the API for this element is not
                 fully stabilized and may be subject to change.

    """

    def __init__(self):
        super(QtTrajectoryViewer, self).__init__()
        
        self.controls = QDockWidget()
        self._timer = QtCore.QTimer(self)
        self._timer.timeout.connect(self.do_update)
        
        # Eliminate the dock titlebar
        title_widget = QtGui.QWidget(self)
        self.controls.setTitleBarWidget(title_widget)
        
        vb = QtGui.QVBoxLayout()
        hb = QtGui.QHBoxLayout() # For controls
        
        containerhb2 = QtGui.QWidget(self)
        
        hb2 = QtGui.QHBoxLayout() # For settings
        containerhb2.setLayout(hb2)
        containerhb2.setSizePolicy(QtGui.QSizePolicy.Minimum,
                                   QtGui.QSizePolicy.Minimum)
        
        

        vb.addWidget(containerhb2)
        vb.addLayout(hb)
        self.vb = vb
        
        # Settings buttons
        hb2.addWidget(QtGui.QLabel('Speed'))
        self._speed_slider = QtGui.QSlider(Qt.Horizontal)
        self._speed_slider.resize(100, self._speed_slider.height())
        self._speed_slider.setSizePolicy(QtGui.QSizePolicy.Fixed,
                                         QtGui.QSizePolicy.Fixed)
        
        self.speeds = np.linspace(15, 250, 11).astype(int)
        self.speeds = self.speeds.tolist()
        self.speeds.reverse()
        self._speed_slider.setMaximum(10)
        self._speed_slider.setValue(7)
        self._speed_slider.valueChanged.connect(self.on_speed_changed)
        
        hb2.addWidget(self._speed_slider)
        hb2.addStretch(1)
        
        wrapper = QtGui.QWidget()
        wrapper.setLayout(vb)

        # Molecular viewer
        self.widget = QChemlabWidget(self)
        self.setCentralWidget(self.widget)
        
        # Control buttons
        self.play_stop = PlayStopButton()
        hb.addWidget(self.play_stop)

        
        self.slider = AnimationSlider()
        hb.addWidget(self.slider, 2)
        
        self._label_tmp = '<b><FONT SIZE=30>{}</b>'
        self.timelabel = QtGui.QLabel(self._label_tmp.format('0.0'))
        hb.addWidget(self.timelabel)
        
        self._settings_button = QtGui.QPushButton()
        self._settings_button.setStyleSheet('''
                                 QPushButton {
                                     width: 30px;
                                     height: 30px;
                                 }''')
        icon = QtGui.QIcon(os.path.join(resources_dir, 'settings_icon.svg'))
        self._settings_button.setIcon(icon)
        self._settings_button.clicked.connect(self._toggle_settings)
        
        hb.addWidget(self._settings_button)
        
        self.controls.setWidget(wrapper)
        self.addDockWidget(Qt.DockWidgetArea(Qt.BottomDockWidgetArea),
                           self.controls)
        

        self._settings_pan = containerhb2
        self.show()

        
        self.speed = self.speeds[self._speed_slider.value()]
        # Connecting all the signals
        self.play_stop.play.connect(self.on_play)
        self.play_stop.pause.connect(self.on_pause)
        
        self.slider.valueChanged.connect(self.on_slider_change)
        self.slider.sliderPressed.connect(self.on_slider_down)

        self.play_stop.setFocus()
        vb.setSizeConstraint(QtGui.QLayout.SetMaximumSize)
        containerhb2.setVisible(False)
        
    def set_ticks(self, number):
        '''Set the number of frames to animate.

        '''
        self.max_index = number
        self.current_index = 0
        
        self.slider.setMaximum(self.max_index-1)
        self.slider.setMinimum(0)
        self.slider.setPageStep(1)
        
    def set_text(self, text):
        '''Update the time indicator in the interface.'''
        self.timelabel.setText(self._label_tmp.format(text))
        
    def on_play(self):
        if self.current_index == self.max_index - 1:
            # Restart
            self.current_index = 0


        self._timer.start(self.speed)

    def do_update(self):
        if self.current_index >= self.max_index:
            self.current_index = self.max_index - 1
            self._timer.stop()
            self.play_stop.set_pause()
        else:
            self.current_index += 1
            self.slider.setSliderPosition(self.current_index)
            
        
    def on_pause(self):
        self._timer.stop()
        
    def on_slider_change(self, value):
        #print 'Slider moved', value
        self.current_index = value
        self._update_function(self.current_index)
        
    def on_slider_down(self):
        self._timer.stop()
        self.play_stop.set_pause()
        
    def on_speed_changed(self, index):
        self.speed = self.speeds[index]
        if self._timer.isActive():
            self._timer.stop()
            self._timer.start(self.speed)
        
    def add_renderer(self, klass, *args, **kwargs):
        '''The behaviour of this function is the same as
        :py:meth:`chemlab.graphics.QtViewer.add_renderer`.

        '''
        renderer = klass(self.widget, *args, **kwargs)
        self.widget.renderers.append(renderer)
        return renderer
    
    def add_ui(self, klass, *args, **kwargs):
        '''Add an UI element for the current scene. The approach is
        the same as renderers.

        .. warning:: The UI api is not yet finalized

        '''

        ui = klass(self.widget, *args, **kwargs)
        self.widget.uis.append(ui)
        return ui
    
    def add_post_processing(self, klass, *args, **kwargs):
        pp = klass(self.widget, *args, **kwargs)
        self.widget.post_processing.append(pp)
        return pp

    def run(self):
        app.exec_()
        
    def update_function(self, func):
        '''Set the function to be called when it's time to display a frame.

        *func* should be a function that takes one integer argument that
        represents the frame that has to be played::

            def func(index):
                # Update the renderers to match the
                # current animation index

        '''
        self._update_function = func

    def _toggle_settings(self):
        self._settings_pan.setVisible(not self._settings_pan.isVisible())
コード例 #2
0
ファイル: qttrajectory.py プロジェクト: ajjackson/chemlab
class QtTrajectoryViewer(QMainWindow):
    """Bases: `PySide.QtGui.QMainWindow`

    Interface for viewing trajectory.

    It provides interface elements to play/pause and set the speed of
    the animation.
    
    **Example**

    To set up a QtTrajectoryViewer you have to add renderers to the
    scene, set the number of frames present in the animation by calling
    ;py:meth:`~chemlab.graphics.QtTrajectoryViewer.set_ticks` and
    define an update function.

    Below is an example taken from the function
    :py:func:`chemlab.graphics.display_trajectory`::
    
        from chemlab.graphics import QtTrajectoryViewer
        
        # sys = some System
        # coords_list = some list of atomic coordinates
        
        v = QtTrajectoryViewer()
        sr = v.add_renderer(AtomRenderer, sys.r_array, sys.type_array,
                            backend='impostors')
        br = v.add_renderer(BoxRenderer, sys.box_vectors)
        
        v.set_ticks(len(coords_list))
        
        @v.update_function
        def on_update(index):
            sr.update_positions(coords_list[index])
            br.update(sys.box_vectors)
            v.set_text(format_time(times[index]))
            v.widget.repaint()
     
        v.run()
    
    .. warning:: Use with caution, the API for this element is not
                 fully stabilized and may be subject to change.

    """

    def __init__(self):
        super(QtTrajectoryViewer, self).__init__()
        
        self.controls = QDockWidget()
        
        # Eliminate the dock titlebar
        title_widget = QtGui.QWidget(self)
        self.controls.setTitleBarWidget(title_widget)
        
        traj_controls = TrajectoryControls(self)
        self.controls.setWidget(traj_controls)
        
        # Molecular viewer
        self.widget = QChemlabWidget(self)
        self.setCentralWidget(self.widget)
        self.addDockWidget(Qt.DockWidgetArea(Qt.BottomDockWidgetArea),
                           self.controls)

        self.show()
        # Replace in this way
        
        traj_controls.frame_changed.connect(self.on_frame_changed)
        self.traj_controls = traj_controls

    def set_ticks(self, number):
        self.traj_controls.set_ticks(number)
        
    def set_text(self, text):
        '''Update the time indicator in the interface.

        '''
        self.traj_controls.timelabel.setText(self.traj_controls._label_tmp.format(text))

    def on_frame_changed(self, index):
        self._update_function(index)

    def on_pause(self):
        self._timer.stop()

    def on_slider_change(self, value):
        self.current_index = value
        self._update_function(self.current_index)

    def on_slider_down(self):
        self._timer.stop()
        self.play_stop.set_pause()

    def on_speed_changed(self, index):
        self.speed = self.speeds[index]
        if self._timer.isActive():
            self._timer.stop()
            self._timer.start(self.speed)

    def add_renderer(self, klass, *args, **kwargs):
        '''The behaviour of this function is the same as
        :py:meth:`chemlab.graphics.QtViewer.add_renderer`.

        '''
        renderer = klass(self.widget, *args, **kwargs)
        self.widget.renderers.append(renderer)
        return renderer

    def add_ui(self, klass, *args, **kwargs):
        '''Add an UI element for the current scene. The approach is
        the same as renderers.

        .. warning:: The UI api is not yet finalized

        '''

        ui = klass(self.widget, *args, **kwargs)
        self.widget.uis.append(ui)
        return ui

    def add_post_processing(self, klass, *args, **kwargs):
        pp = klass(self.widget, *args, **kwargs)
        self.widget.post_processing.append(pp)
        return pp

    def run(self):
        app.exec_()

    def update_function(self, func, frames=None):
        '''Set the function to be called when it's time to display a frame.

        *func* should be a function that takes one integer argument that
        represents the frame that has to be played::

            def func(index):
                # Update the renderers to match the
                # current animation index

        '''
        # Back-compatibility
        if frames is not None:
            self.traj_controls.set_ticks(frames)
        
        self._update_function = func

    def _toggle_settings(self):
        self._settings_pan.setVisible(not self._settings_pan.isVisible())
コード例 #3
0
class QtTrajectoryViewer(QMainWindow):
    """Bases: `PySide.QtGui.QMainWindow`

    Interface for viewing trajectory.

    It provides interface elements to play/pause and set the speed of
    the animation.
    
    **Example**

    To set up a QtTrajectoryViewer you have to add renderers to the
    scene, set the number of frames present in the animation by calling
    ;py:meth:`~chemlab.graphics.QtTrajectoryViewer.set_ticks` and
    define an update function.

    Below is an example taken from the function
    :py:func:`chemlab.graphics.display_trajectory`::
    
        from chemlab.graphics import QtTrajectoryViewer
        
        # sys = some System
        # coords_list = some list of atomic coordinates
        
        v = QtTrajectoryViewer()
        sr = v.add_renderer(AtomRenderer, sys.r_array, sys.type_array,
                            backend='impostors')
        br = v.add_renderer(BoxRenderer, sys.box_vectors)
        
        v.set_ticks(len(coords_list))
        
        @v.update_function
        def on_update(index):
            sr.update_positions(coords_list[index])
            br.update(sys.box_vectors)
            v.set_text(format_time(times[index]))
            v.widget.repaint()
     
        v.run()
    
    .. warning:: Use with caution, the API for this element is not
                 fully stabilized and may be subject to change.

    """
    def __init__(self):
        super(QtTrajectoryViewer, self).__init__()

        self.controls = QDockWidget()
        self._timer = QtCore.QTimer(self)
        self._timer.timeout.connect(self.do_update)

        # Eliminate the dock titlebar
        title_widget = QtGui.QWidget(self)
        self.controls.setTitleBarWidget(title_widget)

        vb = QtGui.QVBoxLayout()
        hb = QtGui.QHBoxLayout()  # For controls

        containerhb2 = QtGui.QWidget(self)

        hb2 = QtGui.QHBoxLayout()  # For settings
        containerhb2.setLayout(hb2)
        containerhb2.setSizePolicy(QtGui.QSizePolicy.Minimum,
                                   QtGui.QSizePolicy.Minimum)

        vb.addWidget(containerhb2)
        vb.addLayout(hb)
        self.vb = vb

        # Settings buttons
        hb2.addWidget(QtGui.QLabel('Speed'))
        self._speed_slider = QtGui.QSlider(Qt.Horizontal)
        self._speed_slider.resize(100, self._speed_slider.height())
        self._speed_slider.setSizePolicy(QtGui.QSizePolicy.Fixed,
                                         QtGui.QSizePolicy.Fixed)

        self.speeds = np.linspace(15, 250, 11).astype(int)
        self.speeds = self.speeds.tolist()
        self.speeds.reverse()
        self._speed_slider.setMaximum(10)
        self._speed_slider.setValue(7)
        self._speed_slider.valueChanged.connect(self.on_speed_changed)

        hb2.addWidget(self._speed_slider)
        hb2.addStretch(1)

        wrapper = QtGui.QWidget()
        wrapper.setLayout(vb)

        # Molecular viewer
        self.widget = QChemlabWidget(self)
        self.setCentralWidget(self.widget)

        # Control buttons
        self.play_stop = PlayStopButton()
        hb.addWidget(self.play_stop)

        self.slider = AnimationSlider()
        hb.addWidget(self.slider, 2)

        self._label_tmp = '<b><FONT SIZE=30>{}</b>'
        self.timelabel = QtGui.QLabel(self._label_tmp.format('0.0'))
        hb.addWidget(self.timelabel)

        self._settings_button = QtGui.QPushButton()
        self._settings_button.setStyleSheet('''
                                 QPushButton {
                                     width: 30px;
                                     height: 30px;
                                 }''')
        icon = QtGui.QIcon(os.path.join(resources_dir, 'settings_icon.svg'))
        self._settings_button.setIcon(icon)
        self._settings_button.clicked.connect(self._toggle_settings)

        hb.addWidget(self._settings_button)

        self.controls.setWidget(wrapper)
        self.addDockWidget(Qt.DockWidgetArea(Qt.BottomDockWidgetArea),
                           self.controls)

        self._settings_pan = containerhb2
        self.show()

        self.speed = self.speeds[self._speed_slider.value()]
        # Connecting all the signals
        self.play_stop.play.connect(self.on_play)
        self.play_stop.pause.connect(self.on_pause)

        self.slider.valueChanged.connect(self.on_slider_change)
        self.slider.sliderPressed.connect(self.on_slider_down)

        self.play_stop.setFocus()
        vb.setSizeConstraint(QtGui.QLayout.SetMaximumSize)
        containerhb2.setVisible(False)

    def set_ticks(self, number):
        '''Set the number of frames to animate.

        '''
        self.max_index = number
        self.current_index = 0

        self.slider.setMaximum(self.max_index - 1)
        self.slider.setMinimum(0)
        self.slider.setPageStep(1)

    def set_text(self, text):
        '''Update the time indicator in the interface.'''
        self.timelabel.setText(self._label_tmp.format(text))

    def on_play(self):
        if self.current_index == self.max_index - 1:
            # Restart
            self.current_index = 0

        self._timer.start(self.speed)

    def do_update(self):
        if self.current_index >= self.max_index:
            self.current_index = self.max_index - 1
            self._timer.stop()
            self.play_stop.set_pause()
        else:
            self.current_index += 1
            self.slider.setSliderPosition(self.current_index)

    def on_pause(self):
        self._timer.stop()

    def on_slider_change(self, value):
        #print 'Slider moved', value
        self.current_index = value
        self._update_function(self.current_index)

    def on_slider_down(self):
        self._timer.stop()
        self.play_stop.set_pause()

    def on_speed_changed(self, index):
        self.speed = self.speeds[index]
        if self._timer.isActive():
            self._timer.stop()
            self._timer.start(self.speed)

    def add_renderer(self, klass, *args, **kwargs):
        '''The behaviour of this function is the same as
        :py:meth:`chemlab.graphics.QtViewer.add_renderer`.

        '''
        renderer = klass(self.widget, *args, **kwargs)
        self.widget.renderers.append(renderer)
        return renderer

    def add_ui(self, klass, *args, **kwargs):
        '''Add an UI element for the current scene. The approach is
        the same as renderers.

        .. warning:: The UI api is not yet finalized

        '''

        ui = klass(self.widget, *args, **kwargs)
        self.widget.uis.append(ui)
        return ui

    def add_post_processing(self, klass, *args, **kwargs):
        pp = klass(self.widget, *args, **kwargs)
        self.widget.post_processing.append(pp)
        return pp

    def run(self):
        app.exec_()

    def update_function(self, func):
        '''Set the function to be called when it's time to display a frame.

        *func* should be a function that takes one integer argument that
        represents the frame that has to be played::

            def func(index):
                # Update the renderers to match the
                # current animation index

        '''
        self._update_function = func

    def _toggle_settings(self):
        self._settings_pan.setVisible(not self._settings_pan.isVisible())