Beispiel #1
0
class _BoundedIntRange(_IntRange):
    step = CInt(
        1,
        help="Minimum step that the value can take (ignored by some views)",
        sync=True)
    max = CInt(100, help="Max value", sync=True)
    min = CInt(0, help="Min value", sync=True)

    def __init__(self, *pargs, **kwargs):
        any_value_given = 'value' in kwargs or 'upper' in kwargs or 'lower' in kwargs
        _IntRange.__init__(self, *pargs, **kwargs)

        # ensure a minimal amount of sanity
        if self.min > self.max:
            raise ValueError("min must be <= max")

        if any_value_given:
            # if a value was given, clamp it within (min, max)
            self._validate("value", None, self.value)
        else:
            # otherwise, set it to 25-75% to avoid the handles overlapping
            self.value = (0.75 * self.min + 0.25 * self.max,
                          0.25 * self.min + 0.75 * self.max)
        # callback already set for 'value', 'lower', 'upper'
        self.on_trait_change(self._validate, ['min', 'max'])

    def _validate(self, name, old, new):
        if name == "min":
            if new > self.max:
                raise ValueError("setting min > max")
        elif name == "max":
            if new < self.min:
                raise ValueError("setting max < min")

        low, high = self.value
        if name == "value":
            low, high = min(new), max(new)
        elif name == "upper":
            if new < self.lower:
                raise ValueError("setting upper < lower")
            high = new
        elif name == "lower":
            if new > self.upper:
                raise ValueError("setting lower > upper")
            low = new

        low = max(self.min, min(low, self.max))
        high = min(self.max, max(high, self.min))

        # determine the order in which we should update the
        # lower, upper traits to avoid a temporary inverted overlap
        lower_first = high < self.lower

        self.value = (low, high)
        if lower_first:
            self.lower = low
            self.upper = high
        else:
            self.upper = high
            self.lower = low
Beispiel #2
0
class _BoundedInt(_Int):
    """Base class used to create widgets that represent a int that is bounded
    by a minium and maximum."""
    step = CInt(1, help="Minimum step that the value can take (ignored by some views)", sync=True)
    max = CInt(100, help="Max value", sync=True)
    min = CInt(0, help="Min value", sync=True)

    def __init__(self, *pargs, **kwargs):
        """Constructor"""
        super(_BoundedInt, self).__init__(*pargs, **kwargs)
        self.on_trait_change(self._validate_value, ['value'])
        self.on_trait_change(self._handle_max_changed, ['max'])
        self.on_trait_change(self._handle_min_changed, ['min'])

    def _validate_value(self, name, old, new):
        """Validate value."""
        if self.min > new or new > self.max:
            self.value = min(max(new, self.min), self.max)

    def _handle_max_changed(self, name, old, new):
        """Make sure the min is always <= the max."""
        if new < self.min:
            raise ValueError("setting max < min")

    def _handle_min_changed(self, name, old, new):
        """Make sure the max is always >= the min."""
        if new > self.max:
            raise ValueError("setting min > max")
Beispiel #3
0
class _IntRange(_Int):
    value = Tuple(CInt, CInt, default_value=(0, 1), help="Tuple of (lower, upper) bounds", sync=True)
    lower = CInt(0, help="Lower bound", sync=False)
    upper = CInt(1, help="Upper bound", sync=False)
    
    def __init__(self, *pargs, **kwargs):
        value_given = 'value' in kwargs
        lower_given = 'lower' in kwargs
        upper_given = 'upper' in kwargs
        if value_given and (lower_given or upper_given):
            raise ValueError("Cannot specify both 'value' and 'lower'/'upper' for range widget")
        if lower_given != upper_given:
            raise ValueError("Must specify both 'lower' and 'upper' for range widget")
        
        super(_IntRange, self).__init__(*pargs, **kwargs)
        
        # ensure the traits match, preferring whichever (if any) was given in kwargs
        if value_given:
            self.lower, self.upper = self.value
        else:
            self.value = (self.lower, self.upper)

        self.on_trait_change(self._validate, ['value', 'upper', 'lower'])
    
    def _validate(self, name, old, new):
        if name == 'value':
            self.lower, self.upper = min(new), max(new)
        elif name == 'lower':
            self.value = (new, self.value[1])
        elif name == 'upper':
            self.value = (self.value[0], new)
Beispiel #4
0
class _BoundedInt(_Int):
    """Base class used to create widgets that represent a int that is bounded
    by a minium and maximum."""
    step = CInt(1, help="Minimum step to increment the value (ignored by some views)", sync=True)
    max = CInt(100, help="Max value", sync=True)
    min = CInt(0, help="Min value", sync=True)

    def __init__(self, *pargs, **kwargs):
        """Constructor"""
        super(_BoundedInt, self).__init__(*pargs, **kwargs)

    def _value_validate(self, value, trait):
        """Cap and floor value"""
        if self.min > value or self.max < value:
            value = min(max(value, self.min), self.max)
        return value

    def _min_validate(self, min, trait):
        """Enforce min <= value <= max"""
        if min > self.max:
            raise TraitError("Setting min > max")
        if min > self.value:
            self.value = min
        return min

    def _max_validate(self, max, trait):
        """Enforce min <= value <= max"""
        if max < self.min:
            raise TraitError("setting max < min")
        if max < self.value:
            self.value = max
        return max
Beispiel #5
0
class Renderer(DOMWidget):
    _view_name = Unicode('RendererView', sync=True)
    width = CInt(600, sync=True)
    height = CInt(400, sync=True)
    renderer_type = Enum(['webgl', 'canvas', 'auto'], 'auto', sync=True)
    scene = Instance(Scene, sync=True)
    camera = Instance(Camera, sync=True)
    controls = Instance(Controls, sync=True)
Beispiel #6
0
class RingGeometry(Geometry):
    _view_name = Unicode('RingGeometryView', sync=True)
    innerRadius = CFloat(1.0, sync=True)
    outerRadius = CFloat(3.0, sync=True)
    thetaSegments = CInt(8, sync=True)
    phiSegments = CInt(8, sync=True)
    thetaStart = CFloat(0, sync=True)
    thetaLength = CFloat(math.pi*2, sync=True)
Beispiel #7
0
class SurfaceGeometry(Geometry):
    """
    A regular grid with heights
    """
    _view_name = Unicode('SurfaceGeometryView', sync=True)
    z = List(CFloat, [0]*100, sync=True)
    width = CInt(10, sync=True)
    height = CInt(10, sync=True)
    width_segments = CInt(10, sync=True)
    height_segments = CInt(10, sync=True)
Beispiel #8
0
class _BoundedIntWidget(_IntWidget):
    step = CInt(1, help="Minimum step that the value can take (ignored by some views)", sync=True)
    max = CInt(100, help="Max value", sync=True)
    min = CInt(0, help="Min value", sync=True)

    def __init__(self, *pargs, **kwargs):
        """Constructor"""
        DOMWidget.__init__(self, *pargs, **kwargs)
        self.on_trait_change(self._validate, ['value', 'min', 'max'])

    def _validate(self, name, old, new):
        """Validate value, max, min."""
        if self.min > new or new > self.max:
            self.value = min(max(new, self.min), self.max)
Beispiel #9
0
class TrajectoryViewer(MolecularViewer):

    frame = CInt()

    def __init__(self, coordinate_frames, topology, width=500, height=500):
        '''Display a trajectory in the IPython notebook.

        :param list coordinate_frames: A list containing the positions of the atoms (as np.ndarray) for each frame.
        :param dict topology: A dictionary specifying the topology 

        .. seealso:: :class:`MolecularViewer`

        '''
        self.coordinate_frames = coordinate_frames
        super(TrajectoryViewer, self).__init__(coordinate_frames[0],
                                               topology,
                                               width=width,
                                               height=height)

        self.controls = TrajectoryControls(len(coordinate_frames))
        link((self, 'frame'), (self.controls, 'frame'))

    def _frame_changed(self, name, old, new):
        self.coordinates = self.coordinate_frames[new]

    def _ipython_display_(self):
        display(self.controls)
        super(TrajectoryViewer, self)._ipython_display_()
Beispiel #10
0
class TubeGeometry(Geometry):
    _view_name = Unicode('TubeGeometryView', sync=True)
    path = List(vector3(), sync=True)
    segments = CInt(64, sync=True)
    radius = CFloat(1, sync=True)
    radialSegments = CFloat(8, sync=True)
    closed = Bool(False, sync=True)
Beispiel #11
0
class TextTexture(Texture):
    _view_name = Unicode('TextTextureView', sync=True)
    fontFace = Unicode('Arial', sync=True)
    size = CInt(12, sync=True)
    color = Color('black', sync=True)
    string = Unicode('', sync=True)
    squareTexture = Bool(True, sync=True)
class _SelectionContainer(Box):
    """Base class used to display multiple child widgets."""
    _titles = Dict(help="Titles of the pages", sync=True)
    selected_index = CInt(0, sync=True)

    # Public methods
    def set_title(self, index, title):
        """Sets the title of a container page.

        Parameters
        ----------
        index : int
            Index of the container page
        title : unicode
            New title"""
        self._titles[index] = title
        self.send_state('_titles')

    def get_title(self, index):
        """Gets the title of a container pages.

        Parameters
        ----------
        index : int
            Index of the container page"""
        if index in self._titles:
            return self._titles[index]
        else:
            return None
Beispiel #13
0
class TrajectoryControls(DOMWidget):
    _view_name = Unicode('TrajectoryControls', sync=True)

    frame = CInt(sync=True)
    n_frames = CInt(sync=True)
    fps = CInt(sync=True)

    def __init__(self, n_frames, fps=30):
        '''Play/Pause controls useful for playing trajectories.

        Example:

        You can connect a callback to be executed every time the frame changes.

        .. code::

            from IPython.display import display

            controls = TrajectoryControls(10) # 10 frames

            def callback(frame):
                print("Current frame %d" % frame)

            controls.on_frame_change(callback)
            display(controls)

        .. py:attribute:: frame

            Current frame

        .. py:attribute:: n_frames

            Total number of frames

        .. py:attribute:: fps

            Frames per second (defaults to 30)

        '''
        super(TrajectoryControls, self).__init__()
        self.n_frames = n_frames - 1
        self.fps = fps

    def on_frame_change(self, callback):
        '''Connect a callback to be executed every time the frame attribute changes.'''
        self.on_trait_change(lambda name, old, new: callback(new), "frame")
Beispiel #14
0
class _Int(DOMWidget):
    """Base class used to create widgets that represent an int."""
    value = CInt(0, help="Int value", sync=True)
    disabled = Bool(False, help="Enable or disable user changes", sync=True)
    description = Unicode(help="Description of the value this widget represents", sync=True)

    def __init__(self, value=None, **kwargs):
        if value is not None:
            kwargs['value'] = value
        super(_Int, self).__init__(**kwargs)
Beispiel #15
0
class DataTexture(Texture):
    _view_name = Unicode('DataTextureView', sync=True)
    data = List(CInt, sync=True)
    format = Enum(['RGBAFormat', 'AlphaFormat', 'RGBFormat', 'LuminanceFormat', 'LuminanceAlphaFormat'],
                'RGBAFormat', sync=True)
    width = CInt(256, sync=True)
    height = CInt(256, sync=True)
    type = Enum(['UnsignedByteType', 'ByteType', 'ShortType', 'UnsignedShortType', 'IntType',
                'UnsignedIntType', 'FloatType', 'UnsignedShort4444Type', 'UnsignedShort5551Type',
                'UnsignedShort565Type'], 'UnsignedByteType', sync=True)
    mapping = Enum(['UVMapping', 'CubeReflectionMapping', 'CubeRefractionMapping', 'SphericalReflectionMapping',
                    'SphericalRefractionMapping'], 'UVMapping', sync=True)
    wrapS = Enum(['ClampToEdgeWrapping', 'RepeatWrapping', 'MirroredRepeatWrapping'], 'ClampToEdgeWrapping',
                sync=True)
    wrapT = Enum(['ClampToEdgeWrapping', 'RepeatWrapping', 'MirroredRepeatWrapping'], 'ClampToEdgeWrapping',
                sync=True)
    magFilter = Enum(['LinearFilter', 'NearestFilter'], 'LinearFilter', sync=True)
    minFilter = Enum(['NearestFilter', 'NearestMipMapNearestFilter', 'NearestMipMapLinearFilter',
                        'LinearFilter', 'LinearMipMapNearestFilter'], 'NearestFilter', sync=True)
    anisotropy = CInt(1, sync=True)
Beispiel #16
0
class Picker(Controls):
    _view_name  = Unicode('PickerView', sync=True)
    event = Unicode('click', sync=True)
    root = Instance(Object3d, sync=True)
    picked = List(Dict, sync=True)
    distance = CFloat(sync=True)
    point = vector3(CFloat, sync=True)
    object = Instance(Object3d, sync=True)
    face = vector3(CInt, sync=True)
    faceNormal = vector3(CFloat, sync=True)
    faceVertices = List(vector3(), sync=True)
    faceIndex = CInt(sync=True)
    all = Bool(False, sync=True)
Beispiel #17
0
class MolecularViewer(DOMWidget):

    # Name of the javascript class which this widget syncs against on the
    # browser side. To work correctly, this javascript class has to be
    # registered and loaded in the browser before this widget is constructed
    # (that's what enable_notebook() does)
    _view_name = Unicode('MolecularView', sync=True)

    frame = CInt(0, help='Which frame from the trajectory to display')
    trajectory = Any()

    # The essence of the IPython interactive widget API on the python side is
    # that by declaring traitlets with sync=True, these variables are
    # automatically synced by the IPython runtime between this class in Python
    # and the browser-side model. Changes to these attributes are propagated
    # automatically to the browser (and changes on the browser side can trigger
    # events on this class too, although we're not using that feature).
    coordinates = Dict(sync=True)
    topology = Dict(sync=True)
    point_size = CFloat(sync=True)

    def __init__(self, trajectory, frame=0, **kwargs):
        super(MolecularViewer, self).__init__(**kwargs)
        self.trajectory = trajectory
        self.frame = frame
        self.coordinates = encode_numpy(self.trajectory.xyz[self.frame])

    def _frame_changed(self, name, old, new):
        """Automatically called by the traitlet system when self.frame is modified"""
        self.coordinates = encode_numpy(self.trajectory.xyz[self.frame])

    def _trajectory_changed(self, name, old, new):
        """Automatically called by the traitlet system when self.trajectory is modified"""
        self.trajectory = new
        self.frame = 0

        # The topology gets changed immediately
        top = {}

        bondIndices = []
        for ai, aj in self.trajectory.topology.bonds:
            bondIndices.append((ai.index, aj.index))

        top['bonds'] = bondIndices
        top['atom_colors'] = [
            get_atom_color(a.element.symbol)
            for a in self.trajectory.topology.atoms
        ]
        self.topology = top
Beispiel #18
0
class LoadBalancedView(View):
    """An load-balancing View that only executes via the Task scheduler.

    Load-balanced views can be created with the client's `view` method:

    >>> v = client.load_balanced_view()

    or targets can be specified, to restrict the potential destinations:

    >>> v = client.client.load_balanced_view([1,3])

    which would restrict loadbalancing to between engines 1 and 3.

    """

    follow = Any()
    after = Any()
    timeout = CFloat()
    retries = CInt(0)

    _task_scheme = Any()
    _flag_names = List(
        ['targets', 'block', 'track', 'follow', 'after', 'timeout', 'retries'])

    def __init__(self, client=None, socket=None, **flags):
        super(LoadBalancedView, self).__init__(client=client,
                                               socket=socket,
                                               **flags)
        self._task_scheme = client._task_scheme

    def _validate_dependency(self, dep):
        """validate a dependency.

        For use in `set_flags`.
        """
        if dep is None or isinstance(dep,
                                     (basestring, AsyncResult, Dependency)):
            return True
        elif isinstance(dep, (list, set, tuple)):
            for d in dep:
                if not isinstance(d, (basestring, AsyncResult)):
                    return False
        elif isinstance(dep, dict):
            if set(dep.keys()) != set(Dependency().as_dict().keys()):
                return False
            if not isinstance(dep['msg_ids'], list):
                return False
            for d in dep['msg_ids']:
                if not isinstance(d, basestring):
                    return False
        else:
            return False

        return True

    def _render_dependency(self, dep):
        """helper for building jsonable dependencies from various input forms."""
        if isinstance(dep, Dependency):
            return dep.as_dict()
        elif isinstance(dep, AsyncResult):
            return dep.msg_ids
        elif dep is None:
            return []
        else:
            # pass to Dependency constructor
            return list(Dependency(dep))

    def set_flags(self, **kwargs):
        """set my attribute flags by keyword.

        A View is a wrapper for the Client's apply method, but with attributes
        that specify keyword arguments, those attributes can be set by keyword
        argument with this method.

        Parameters
        ----------

        block : bool
            whether to wait for results
        track : bool
            whether to create a MessageTracker to allow the user to
            safely edit after arrays and buffers during non-copying
            sends.

        after : Dependency or collection of msg_ids
            Only for load-balanced execution (targets=None)
            Specify a list of msg_ids as a time-based dependency.
            This job will only be run *after* the dependencies
            have been met.

        follow : Dependency or collection of msg_ids
            Only for load-balanced execution (targets=None)
            Specify a list of msg_ids as a location-based dependency.
            This job will only be run on an engine where this dependency
            is met.

        timeout : float/int or None
            Only for load-balanced execution (targets=None)
            Specify an amount of time (in seconds) for the scheduler to
            wait for dependencies to be met before failing with a
            DependencyTimeout.

        retries : int
            Number of times a task will be retried on failure.
        """

        super(LoadBalancedView, self).set_flags(**kwargs)
        for name in ('follow', 'after'):
            if name in kwargs:
                value = kwargs[name]
                if self._validate_dependency(value):
                    setattr(self, name, value)
                else:
                    raise ValueError("Invalid dependency: %r" % value)
        if 'timeout' in kwargs:
            t = kwargs['timeout']
            if not isinstance(t, (int, long, float, type(None))):
                raise TypeError("Invalid type for timeout: %r" % type(t))
            if t is not None:
                if t < 0:
                    raise ValueError("Invalid timeout: %s" % t)
            self.timeout = t

    @sync_results
    @save_ids
    def _really_apply(self,
                      f,
                      args=None,
                      kwargs=None,
                      block=None,
                      track=None,
                      after=None,
                      follow=None,
                      timeout=None,
                      targets=None,
                      retries=None):
        """calls f(*args, **kwargs) on a remote engine, returning the result.

        This method temporarily sets all of `apply`'s flags for a single call.

        Parameters
        ----------

        f : callable

        args : list [default: empty]

        kwargs : dict [default: empty]

        block : bool [default: self.block]
            whether to block
        track : bool [default: self.track]
            whether to ask zmq to track the message, for safe non-copying sends

        !!!!!! TODO: THE REST HERE  !!!!

        Returns
        -------

        if self.block is False:
            returns AsyncResult
        else:
            returns actual result of f(*args, **kwargs) on the engine(s)
            This will be a list of self.targets is also a list (even length 1), or
            the single result if self.targets is an integer engine id
        """

        # validate whether we can run
        if self._socket.closed:
            msg = "Task farming is disabled"
            if self._task_scheme == 'pure':
                msg += " because the pure ZMQ scheduler cannot handle"
                msg += " disappearing engines."
            raise RuntimeError(msg)

        if self._task_scheme == 'pure':
            # pure zmq scheme doesn't support extra features
            msg = "Pure ZMQ scheduler doesn't support the following flags:"
            "follow, after, retries, targets, timeout"
            if (follow or after or retries or targets or timeout):
                # hard fail on Scheduler flags
                raise RuntimeError(msg)
            if isinstance(f, dependent):
                # soft warn on functional dependencies
                warnings.warn(msg, RuntimeWarning)

        # build args
        args = [] if args is None else args
        kwargs = {} if kwargs is None else kwargs
        block = self.block if block is None else block
        track = self.track if track is None else track
        after = self.after if after is None else after
        retries = self.retries if retries is None else retries
        follow = self.follow if follow is None else follow
        timeout = self.timeout if timeout is None else timeout
        targets = self.targets if targets is None else targets

        if not isinstance(retries, int):
            raise TypeError('retries must be int, not %r' % type(retries))

        if targets is None:
            idents = []
        else:
            idents = self.client._build_targets(targets)[0]
            # ensure *not* bytes
            idents = [ident.decode() for ident in idents]

        after = self._render_dependency(after)
        follow = self._render_dependency(follow)
        subheader = dict(after=after,
                         follow=follow,
                         timeout=timeout,
                         targets=idents,
                         retries=retries)

        msg = self.client.send_apply_message(self._socket,
                                             f,
                                             args,
                                             kwargs,
                                             track=track,
                                             subheader=subheader)
        tracker = None if track is False else msg['tracker']

        ar = AsyncResult(self.client,
                         msg['header']['msg_id'],
                         fname=f.__name__,
                         targets=None,
                         tracker=tracker)

        if block:
            try:
                return ar.get()
            except KeyboardInterrupt:
                pass
        return ar

    @spin_after
    @save_ids
    def map(self, f, *sequences, **kwargs):
        """view.map(f, *sequences, block=self.block, chunksize=1, ordered=True) => list|AsyncMapResult

        Parallel version of builtin `map`, load-balanced by this View.

        `block`, and `chunksize` can be specified by keyword only.

        Each `chunksize` elements will be a separate task, and will be
        load-balanced. This lets individual elements be available for iteration
        as soon as they arrive.

        Parameters
        ----------

        f : callable
            function to be mapped
        *sequences: one or more sequences of matching length
            the sequences to be distributed and passed to `f`
        block : bool [default self.block]
            whether to wait for the result or not
        track : bool
            whether to create a MessageTracker to allow the user to
            safely edit after arrays and buffers during non-copying
            sends.
        chunksize : int [default 1]
            how many elements should be in each task.
        ordered : bool [default True]
            Whether the results should be gathered as they arrive, or enforce
            the order of submission.
            
            Only applies when iterating through AsyncMapResult as results arrive.
            Has no effect when block=True.

        Returns
        -------

        if block=False:
            AsyncMapResult
                An object like AsyncResult, but which reassembles the sequence of results
                into a single list. AsyncMapResults can be iterated through before all
                results are complete.
            else:
                the result of map(f,*sequences)

        """

        # default
        block = kwargs.get('block', self.block)
        chunksize = kwargs.get('chunksize', 1)
        ordered = kwargs.get('ordered', True)

        keyset = set(kwargs.keys())
        extra_keys = keyset.difference_update(set(['block', 'chunksize']))
        if extra_keys:
            raise TypeError("Invalid kwargs: %s" % list(extra_keys))

        assert len(sequences) > 0, "must have some sequences to map onto!"

        pf = ParallelFunction(self,
                              f,
                              block=block,
                              chunksize=chunksize,
                              ordered=ordered)
        return pf.map(*sequences)
class ForceDirectedGraph(widgets.DOMWidget):
    _view_module = Unicode('nbextensions/d3networkx/widget', sync=True)
    _view_name = Unicode('D3ForceDirectedGraphView', sync=True)

    width = CInt(1000, sync=True)
    height = CInt(1000, sync=True)
    charge = CFloat(270., sync=True)
    distance = CFloat(30., sync=True)
    strength = CFloat(0.3, sync=True)

    def __init__(self, eventful_graph, *pargs, **kwargs):
        widgets.DOMWidget.__init__(self, *pargs, **kwargs)

        self._eventful_graph = eventful_graph
        self._send_dict_changes(eventful_graph.graph, 'graph')
        self._send_dict_changes(eventful_graph.node, 'node')
        self._send_dict_changes(eventful_graph.adj, 'adj')

    def _ipython_display_(self, *pargs, **kwargs):

        # Show the widget, then send the current state
        widgets.DOMWidget._ipython_display_(self, *pargs, **kwargs)
        for (key, value) in self._eventful_graph.graph.items():
            self.send({
                'dict': 'graph',
                'action': 'add',
                'key': key,
                'value': value
            })
        for (key, value) in self._eventful_graph.node.items():
            self.send({
                'dict': 'node',
                'action': 'add',
                'key': key,
                'value': value
            })
        for (key, value) in self._eventful_graph.adj.items():
            self.send({
                'dict': 'adj',
                'action': 'add',
                'key': key,
                'value': value
            })

    def _send_dict_changes(self, eventful_dict, dict_name):
        def key_add(key, value):
            self.send({
                'dict': dict_name,
                'action': 'add',
                'key': key,
                'value': value
            })

        def key_set(key, value):
            self.send({
                'dict': dict_name,
                'action': 'set',
                'key': key,
                'value': value
            })

        def key_del(key):
            self.send({'dict': dict_name, 'action': 'del', 'key': key})

        eventful_dict.on_add(key_add)
        eventful_dict.on_set(key_set)
        eventful_dict.on_del(key_del)
Beispiel #20
0
class RepresentationViewer(DOMWidget):

    # Name of the javascript class which this widget syncs against on the
    # browser side. To work correctly, this javascript class has to be
    # registered and loaded in the browser before this widget is constructed
    # (that's what enable_notebook() does)
    _view_module = Unicode('nbextensions/chemview_widget', sync=True)
    _view_name = Unicode('MolecularView', sync=True)

    width = CInt(sync=True)
    height = CInt(sync=True)
    background = CInt(sync=True)

    # Update Camera Hack
    camera_str = CUnicode(sync=True)
    static_moving = CBool(sync=True)

    # Helper
    loaded = CBool(False, sync=True)

    def __init__(self, width=500, height=500):
        '''RepresentationViewer is an IPython notebook widget useful to display 3d scenes through webgl.

        Example:

        .. code::

            from IPython.display import display

            rv = RepresentationViewer()
            rv.add_representation('point', {'coordinates': coordinates, 'colors': colors, 'sizes': sizes})
            display(rv)

        .. py:attribute: width

            Width in pixels of the IPython widget

        .. py:attribute: height

            Height in pixels of the IPython widget

        .. py:attribute: camera_str

            A string-representation of camera position and orientation

        .. py:attribute: static_moving

            Set to True to make the camera lose the "bouncy" rotation.


        '''
        super(RepresentationViewer, self).__init__()
        self.displayed = False
        self.width = width
        self.height = height

        # Store the events sent from the javascript side
        self._event_handlers = defaultdict(list)

        # What to do when we export
        def callback(content):
            display(Image(url=content.get('dataUrl')))

        self._connect_event('displayImg', callback)

        # A record of the new representations
        self.representations = {}

        # Things to be called when the js part is done loading
        self._displayed_callbacks = []

        def on_loaded(name, old, new):
            for cb in self._displayed_callbacks:
                cb(self)

        self.on_trait_change(on_loaded, "loaded")

    def add_representation(self, rep_type, options):
        '''Add a 3D representation to the viewer.  See User Guide for
        a complete description of the representations available.

        :return: An unique hexadecimal identifier for the representation.
        :rtype: str

        '''
        # Add our unique id to be able to refer to the representation
        rep_id = uuid4().hex
        self.representations[rep_id] = {
            'type': rep_type,
            'options': options.copy()
        }
        self._remote_call('addRepresentation',
                          type=rep_type,
                          repId=rep_id,
                          options=options)
        return rep_id

    def remove_representation(self, rep_id):
        '''Remove a representation from the viewer

        :param str rep_id: the unique identifier generated by RepresentationViewer.add_representation

        '''
        self._remote_call('removeRepresentation', repId=rep_id)
        del self.representations[rep_id]

    def update_representation(self, rep_id, options):
        '''Update a representation with new data.

        :param str rep_id: the unique identifier returned by RepresentationViewer.add_representation
        :param dict options: dictionary containing the updated data.

        '''
        self.representations[rep_id]['options'].update(options)
        self._remote_call('updateRepresentation',
                          repId=rep_id,
                          options=options)

    def _connect_event(self, event_name, callback):
        '''Respond to an event sent by the Javascript side.

        Events available:

            - displayImg
            - serialize


        '''
        self._event_handlers[event_name].append(callback)

    def _remote_call(self, method_name, **kwargs):
        '''Call a method remotely on the javascript side'''
        msg = {}
        msg['type'] = 'callMethod'
        msg['methodName'] = method_name
        msg['args'] = self._recursive_serialize(kwargs)

        if self.displayed is True:
            self.send(msg)  # This will be received with View.on_msg
        else:
            # We should prepare a callback to be
            # called when widget is displayed
            def callback(widget, msg=msg):
                widget.send(msg)

            self._displayed_callbacks.append(callback)

    def _recursive_serialize(self, dictionary):
        '''Serialize a dictionary inplace'''
        for k, v in dictionary.items():
            if isinstance(v, dict):
                self._recursive_serialize(v)
            else:
                # This is when custom serialization happens
                if isinstance(v, np.ndarray):
                    if v.dtype == 'float64':
                        # We don't support float64 on js side
                        v = v.astype('float32')

                    dictionary[k] = encode_numpy(v)
        return dictionary

    def _handle_custom_msg(self, content):
        # Handle custom messages sent by the javascript counterpart
        event = content.get('event', '')
        for cb in self._event_handlers[event]:
            cb(content)

    def _ipython_display_(self, **kwargs):
        super(RepresentationViewer, self)._ipython_display_(**kwargs)
        self.displayed = True

    def get_scene(self):
        '''Return a dictionary that uniquely identifies the scene displayed'''

        scene = {}

        # Camera
        camspec = json.loads(self.camera_str)
        location = np.array([
            camspec['position']['x'], camspec['position']['y'],
            camspec['position']['z']
        ], 'float')
        quaternion = np.array([
            camspec['quaternion']['_x'], camspec['quaternion']['_y'],
            camspec['quaternion']['_z'], camspec['quaternion']['_w']
        ], 'float')
        target = np.array([
            camspec['target']['x'], camspec['target']['y'],
            camspec['target']['z']
        ], 'float')

        scene['camera'] = dict(location=location,
                               quaternion=quaternion,
                               target=target,
                               vfov=camspec['fov'],
                               aspect=camspec['aspect'])
        # Lights: TODO
        scene['lights'] = [{
            'position': np.array([2, 4, -3]) * 1000,
            'color': 0xffffff
        }, {
            'position': np.array([-1, 2, 3]) * 1000,
            'color': 0xffffff
        }]
        # Objects
        scene['representations'] = self.representations.values()
        scene['background'] = self.background

        return scene
Beispiel #21
0
class _IntWidget(DOMWidget):
    value = CInt(0, help="Int value", sync=True) 
    disabled = Bool(False, help="Enable or disable user changes", sync=True)
    description = Unicode(help="Description of the value this widget represents", sync=True)
Beispiel #22
0
class ParametricGeometry(Geometry):
    _view_name = Unicode('ParametricGeometryView', sync=True)
    func = Unicode('', sync=True)
    slices = CInt(105, sync=True)
    stacks = CInt(105,sync=True)
class OpenMMSimulator(Device):
    name = 'OpenMM'
    path = 'msmaccelerator.simulate.simulation.OpenMMSimulator'
    short_description = 'Run a single round of dynamics with OpenMM'
    long_description = '''This device will connect to the msmaccelerator server,
        request the initial conditions with which to start a simulation, and
        propagate dynamics'''

    # configurables.
    system_xml = Unicode('system.xml',
                         config=True,
                         help='''
        Path to the XML file containing the OpenMM system to propagate''')
    system = Instance('simtk.openmm.openmm.System')

    integrator_xml = Unicode('integrator.xml',
                             config=True,
                             help='''
        Path to the XML file containing the OpenMM Integrator to use''')
    integrator = Instance('simtk.openmm.openmm.Integrator')

    number_of_steps = CInt(10000,
                           config=True,
                           help='''
        Number of steps of dynamics to do''')

    report_interval = CInt(1000,
                           config=True,
                           help='''
        Interval at which to save positions to a disk, in units of steps''')

    minimize = Bool(True,
                    config=True,
                    help='''Do local energy minimization on
        the configuration that's passed to me, before running dynamics''')

    random_initial_velocities = Bool(True,
                                     config=True,
                                     help='''Choose
        random initial velocities from the Maxwell-Boltzmann distribution''')

    platform = Enum(
        ['Reference', 'CUDA', 'OpenCL'],
        default_value='CUDA',
        config=True,
        help='''The OpenMM platform on which to run the simulation''')
    device_index = CInt(0,
                        config=True,
                        help='''OpenMM device index for CUDA or
        OpenCL platforms. This is used to select which GPU will be used on a
        multi-gpu system. This option is ignored on reference platform''')

    # expose these as command line flags on --help
    # other settings can still be specified on the command line, its just
    # less convenient
    aliases = dict(system_xml='OpenMMSimulator.system_xml',
                   integrator_xml='OpenMMSimulator.integrator_xml',
                   number_of_steps='OpenMMSimulator.number_of_steps',
                   report_interval='OpenMMSimulator.report_interval',
                   zmq_port='Device.zmq_port',
                   zmq_url='Device.zmq_url',
                   platform='OpenMMSimulator.platform',
                   device_index='OpenMMSimulator.device_index')

    def start(self):
        # load up the system and integrator files
        with open(self.system_xml) as f:
            self.system = XmlSerializer.deserialize(f.read())
            # reset the random number seed for any random
            # forces (andersen thermostat, montecarlo barostat)
            for i in range(self.system.getNumForces()):
                force = self.system.getForce(i)
                if hasattr(force, 'setRandomNumberSeed'):
                    force.setRandomNumberSeed(random_seed())
        with open(self.integrator_xml) as f:
            self.integrator = XmlSerializer.deserialize(f.read())

            # reset the random number seed for a stochastic integrator
            if hasattr(self.integrator, 'setRandomNumberSeed'):
                self.integrator.setRandomNumberSeed(random_seed())

        super(OpenMMSimulator, self).start()

    def on_startup_message(self, msg):
        """This method is called when the device receives its startup message
        from the server.
        """

        assert msg.header.msg_type in ['simulate']  # only allowed RPC
        return getattr(self, msg.header.msg_type)(msg.header, msg.content)

    def simulate(self, header, content):
        """Main method that is "executed" by the receipt of the
        msg_type == 'simulate' message from the server.

        We run some OpenMM dynamics, and then send back the results.
        """
        self.log.info('Setting up simulation...')
        state, topology = self.deserialize_input(content)
        starting_state_path = content.starting_state.path

        # set the GPU platform
        platform = Platform.getPlatformByName(str(self.platform))
        if self.platform == 'CUDA':
            properties = {
                'CudaPrecision': 'mixed',
                'CudaDeviceIndex': str(self.device_index)
            }
        elif self.platform == 'OpenCL':
            properties = {
                'OpenCLPrecision': 'mixed',
                'OpenCLDeviceIndex': str(self.device_index)
            }
        else:
            properties = None

        simulation = Simulation(topology, self.system, self.integrator,
                                platform, properties)
        # do the setup
        self.set_state(state, simulation)
        self.sanity_check(simulation)
        if self.minimize:
            self.log.info('minimizing...')
            simulation.minimizeEnergy()

        if self.random_initial_velocities:
            try:
                temp = simulation.integrator.getTemperature()
                simulation.context.setVelocitiesToTemperature(temp)
            except AttributeError:
                print "I don't know what temperature to use!!"
                # TODO: look through the system's forces to find an andersen
                # thermostate?
                raise
            pass

        assert content.output.protocol == 'localfs', "I'm currently only equiped for localfs output"
        self.log.info('adding reporters...')
        self.add_reporters(simulation, content.output.path)

        # run dynamics!
        self.log.info('Starting dynamics')
        simulation.step(self.number_of_steps)

        for reporter in simulation.reporters:
            # explicitly delete the reporters so that any open file handles
            # are closed.
            del reporter

        # tell the master that I'm done
        self.send_recv(msg_type='simulation_done',
                       content={
                           'status': 'success',
                           'starting_state': {
                               'protocol': 'localfs',
                               'path': starting_state_path
                           },
                           'output': {
                               'protocol': 'localfs',
                               'path': content.output.path
                           }
                       })

    ##########################################################################
    # Begin helpers for setting up the simulation
    ##########################################################################

    def sanity_check(self, simulation):
        positions = simulation.context.getState(
            getPositions=True).getPositions(asNumpy=True)
        for atom1, atom2 in simulation.topology.bonds():
            d = np.linalg.norm(positions[atom1.index, :] -
                               positions[atom2.index, :])
            if not d < 0.3:
                self.log.error(positions[atom1.index, :])
                self.log.error(positions[atom2.index, :])
                raise ValueError(
                    'atoms are bonded according to topology but not close by '
                    'in space: %s. %s' % (d, positions))

    def deserialize_input(self, content):
        """Retreive the state and topology from the message content

        The message protocol tries not to pass 'data' around within the
        messages, but instead pass paths to data. So far we're only sending
        paths on the local filesystem, but we might could generalize this to
        HTTP or S3 or something later.

        The assumption that data can be passed around on the local filesystem
        shouldn't be built deep into the code at all
        """
        # todo: better name for this function?

        if content.starting_state.protocol == 'localfs':
            with open(content.starting_state.path) as f:
                self.log.info('Opening state file: %s',
                              content.starting_state.path)
                state = XmlSerializer.deserialize(f.read())
        else:
            raise ValueError('Unknown protocol')

        if content.topology_pdb.protocol == 'localfs':
            topology = PDBFile(content.topology_pdb.path).topology
        else:
            raise ValueError('Unknown protocol')

        return state, topology

    def set_state(self, state, simulation):
        "Set the state of a simulation to whatever is in the state object"
        # why do I have to do this so... manually?
        # this is why:

        # simulation.context.setState(state)
        # TypeError: in method 'Context_setState', argument 2 of type 'State const &'

        simulation.context.setPositions(state.getPositions())
        simulation.context.setVelocities(state.getVelocities())
        simulation.context.setPeriodicBoxVectors(
            *state.getPeriodicBoxVectors())
        for key, value in state.getParameters():
            simulation.context.setParameter(key, value)

    def add_reporters(self, simulation, outfn):
        "Add reporters to a simulation"

        def reporter_callback(report):
            """Callback for processing reporter output"""
            self.log.info(report)

        callback_reporter = CallbackReporter(reporter_callback,
                                             self.report_interval,
                                             step=True,
                                             potentialEnergy=True,
                                             temperature=True,
                                             time=True,
                                             total_steps=self.number_of_steps)
        h5_reporter = HDF5Reporter(outfn,
                                   self.report_interval,
                                   coordinates=True,
                                   time=True,
                                   cell=True,
                                   potentialEnergy=True,
                                   kineticEnergy=True,
                                   temperature=True)

        simulation.reporters.append(callback_reporter)
        simulation.reporters.append(h5_reporter)
Beispiel #24
0
class PolyhedronGeometry(Geometry):
    _view_name = Unicode('PolyhedronGeometryView', sync=True)
    radius = CFloat(1, sync=True)
    detail = CInt(0, sync=True)
    vertices = List(List(CFloat), sync=True)
    faces = List(List(CInt), sync=True)
Beispiel #25
0
class TrajectoryView(DOMWidget):
    """IPython notebook widget for displaying trajectories in the browser with WebGL

    Example
    -------
    # if the final line occurs at the end of an IPython notebook cell, the
    # resulting interactive widget will be displayed
    >>> t = md.load('trajectory.pdb')
    >>> from mdtraj.html import enable_notebook, TrajectoryView
    >>> enable_notebook()
    >>> widget = TrajectoryView(t)
    >>> widget

    Attributes
    ----------
    camera : {'perspective', 'orthographic'}
        Camera mode (default='perspective')
    background : {'black', 'grey', 'white'}
        Background color (default='black')
    colorBy : {'spectrum', 'chain', 'secondary structure', 'residue',
               'polarity', 'atom'}
        Color scheme (default='white')
    primaryStructure : {'lines', 'stick', 'ball & stick','sphere', 'nothing'}
        Drawing method for the primary structure (default='nothing')
    secondaryStructure = {'ribbon', 'strand', 'cylinder & plate', 'C alpha trace', 'nothing'}
        Drawing method for secondary structure. (default='cylinder & plate')
    surfaceRepresentation = {'Van der Waals surface', 'solvent excluded surface',
                                'solvent accessible surface', 'molecular surface', 'nothing'}
        Drawing method for surface representation. (default='nothing')

    Notes
    -----
    All of the attributes listed above are synced with the browser's widget.
    Modifying these attributes, after the widget is constructed, will cause
    the widget to update *live*. They can also be set at widget construction
    time as keyword arguments to ``__init__``.

    The viewer WebGL viewer used, iview, is documented in [1].

    References
    ----------
    ..[1] Li, Hongjian, et al. "iview: an interactive WebGL visualizer for
          protein-ligand complex." BMC Bioinformatics 15.1 (2014): 56.

    See Also
    --------
    enable_notebook() : Executing this function before using the widget is
        required to load the required browser-side libraries
    """
    disabled = Bool(False, help="Enable or disable user changes.", sync=True)

    # Name of the javascript class which this widget syncs against on the
    # browser side. To work correctly, this javascript class has to be
    # registered and loaded in the browser before this widget is constructed
    # (that's what enable_notebook() does)
    _view_name = Unicode('TrajectoryView', sync=True)

    frame = CInt(0, help='Which frame from the trajectory to display')
    trajectory = Any()

    # The essence of the IPython interactive widget API on the python side is
    # that by declaring traitlets with sync=True, these variables are
    # automatically synced by the IPython runtime between this class in Python
    # and the browser-side model. Changes to these attributes are propagated
    # automatically to the browser (and changes on the browser side can trigger
    # events on this class too, although we're not using that feature).
    _topology = Dict(sync=True)
    _frameData = Dict(sync=True)

    # Display options
    camera = Enum(['perspective', 'orthographic'], 'perspective', sync=True)
    background = Enum(['black', 'grey', 'white'], 'white', sync=True)
    colorBy = Enum([
        'spectrum', 'chain', 'secondary structure', 'residue', 'polarity',
        'atom'
    ],
                   'spectrum',
                   sync=True)
    primaryStructure = Enum(
        ['lines', 'stick', 'ball & stick', 'sphere', 'nothing'],
        'nothing',
        sync=True)
    secondaryStructure = Enum(
        ['ribbon', 'strand', 'cylinder & plate', 'C alpha trace', 'nothing'],
        'cylinder & plate',
        sync=True)
    surfaceRepresentation = Enum([
        'Van der Waals surface', 'solvent excluded surface',
        'solvent accessible surface', 'molecular surface', 'nothing'
    ],
                                 'nothing',
                                 sync=True)

    def __init__(self, trajectory, frame=0, **kwargs):
        super(TrajectoryView, self).__init__(**kwargs)
        self.trajectory = trajectory
        self.frame = frame

    def _frame_changed(self, name, old, new):
        """Automatically called by the traitlet system when self.frame is modified"""
        self._update_frame_data()

    def _trajectory_changed(self, name, old, new):
        """Automatically called by the traitlet system when self.trajectory is modified"""
        self._topology = self._computeTopology()
        self._update_frame_data()

    def _update_frame_data(self):

        self._frameData = {
            'coordinates': encode_numpy(self.trajectory.xyz[self.frame]),
            'secondaryStructure': self._computeSecondaryStructure()
        }

    def _computeSecondaryStructure(self):
        """Compute the secondary structure of the selected frame and
        format it for the browser
        """
        SS_MAP = {'C': 'coil', 'H': 'helix', 'E': 'sheet'}

        top = self.trajectory.topology
        dssp = md.compute_dssp(self.trajectory[self.frame])[0]
        result = {}

        # iterate over the (rindx, ss) pairs in enumerate(dssp),
        # and use itertools to group them into streaks by contiguous
        # chain and ss.
        keyfunc = lambda ir: (top.residue(ir[0]).chain, ir[1])
        for (chain, ss), grouper in groupby(enumerate(dssp), keyfunc):
            # rindxs is a list of residue indices in this contiguous run
            rindxs = [g[0] for g in grouper]
            for r in rindxs:
                # add entry for each atom in the residue
                for a in top.residue(r).atoms:
                    result[a.index] = {
                        'ss': SS_MAP[ss],
                        'ssbegin': (r == rindxs[0] and ss in set(['H', 'E'])),
                        'ssend': (r == rindxs[-1] and ss in set(['H', 'E']))
                    }
        return result

    def _computeTopology(self):
        """Extract the topology and format it for the browser. iview has a
        particular format for storing topology-based information, and
        for simplicity and hack-ability the best place to do the
        conversion is here in python.
        """
        # TODO(rmcgibbo). Document this schema. It needs to match with what's
        # going on inside iview.loadTopology on the browser side.

        atoms = {}

        # these should be mutually exclusive. you're only in one of
        # these categories
        peptideIndices = []
        waterIndices = []
        ionIndices = []
        ligandIndices = []

        bondIndices = []
        calphaIndices = []

        hetIndices = []

        for atom in self.trajectory.topology.atoms:
            atoms[atom.index] = {
                'alt': ' ',
                'b': 0,
                'chain': atom.residue.chain.index,
                'elem':
                atom.element.symbol if atom.element is not None else 'X',
                'insc': ' ',
                'name': atom.name,
                'resi': atom.residue.index,
                'resn': atom.residue.name,
                'serial': atom.index,
                'ss': None,
                'coord': None,
                'bonds': [],
            }
            if atom.name == 'CA':
                calphaIndices.append(atom.index)

            if atom.residue.is_water:
                waterIndices.append(atom.index)
            elif not atom.residue.is_protein:
                ligandIndices.append(atom.index)
            else:
                peptideIndices.append(atom.index)

        for ai, aj in self.trajectory.topology.bonds:
            bondIndices.append((ai.index, aj.index))

        return {
            'atoms': atoms,
            'bondIndices': bondIndices,
            'ionIndices': ionIndices,
            'calphaIndices': calphaIndices,
            'hetIndices': hetIndices,
            'peptideIndices': peptideIndices,
            'ligandIndices': ligandIndices,
            'waterIndices': waterIndices
        }
Beispiel #26
0
class _Int(DOMWidget):
    """Base class used to create widgets that represent an int."""
    value = CInt(0, help="Int value", sync=True)
    disabled = Bool(False, help="Enable or disable user changes", sync=True)
    description = Unicode(
        help="Description of the value this widget represents", sync=True)
Beispiel #27
0
class HistoryManager(HistoryAccessor):
    """A class to organize all history-related functionality in one place.
    """
    # Public interface

    # An instance of the IPython shell we are attached to
    shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
    # Lists to hold processed and raw history. These start with a blank entry
    # so that we can index them starting from 1
    input_hist_parsed = List([""])
    input_hist_raw = List([""])
    # A list of directories visited during session
    dir_hist = List()

    def _dir_hist_default(self):
        try:
            return [os.getcwdu()]
        except OSError:
            return []

    # A dict of output history, keyed with ints from the shell's
    # execution count.
    output_hist = Dict()
    # The text/plain repr of outputs.
    output_hist_reprs = Dict()

    # The number of the current session in the history database
    session_number = CInt()
    # Should we log output to the database? (default no)
    db_log_output = Bool(False, config=True)
    # Write to database every x commands (higher values save disk access & power)
    #  Values of 1 or less effectively disable caching.
    db_cache_size = Int(0, config=True)
    # The input and output caches
    db_input_cache = List()
    db_output_cache = List()

    # History saving in separate thread
    save_thread = Instance('IPython.core.history.HistorySavingThread')
    try:  # Event is a function returning an instance of _Event...
        save_flag = Instance(threading._Event)
    except AttributeError:  # ...until Python 3.3, when it's a class.
        save_flag = Instance(threading.Event)

    # Private interface
    # Variables used to store the three last inputs from the user.  On each new
    # history update, we populate the user's namespace with these, shifted as
    # necessary.
    _i00 = Unicode(u'')
    _i = Unicode(u'')
    _ii = Unicode(u'')
    _iii = Unicode(u'')

    # A regex matching all forms of the exit command, so that we don't store
    # them in the history (it's annoying to rewind the first entry and land on
    # an exit call).
    _exit_re = re.compile(r"(exit|quit)(\s*\(.*\))?$")

    def __init__(self, shell=None, config=None, **traits):
        """Create a new history manager associated with a shell instance.
        """
        # We need a pointer back to the shell for various tasks.
        super(HistoryManager, self).__init__(shell=shell,
                                             config=config,
                                             **traits)
        self.save_flag = threading.Event()
        self.db_input_cache_lock = threading.Lock()
        self.db_output_cache_lock = threading.Lock()
        self.save_thread = HistorySavingThread(self)
        self.save_thread.start()

        self.new_session()

    def _get_hist_file_name(self, profile=None):
        """Get default history file name based on the Shell's profile.
        
        The profile parameter is ignored, but must exist for compatibility with
        the parent class."""
        profile_dir = self.shell.profile_dir.location
        return os.path.join(profile_dir, 'history.sqlite')

    @needs_sqlite
    def new_session(self, conn=None):
        """Get a new session number."""
        if conn is None:
            conn = self.db

        with conn:
            cur = conn.execute(
                """INSERT INTO sessions VALUES (NULL, ?, NULL,
                            NULL, "") """, (datetime.datetime.now(), ))
            self.session_number = cur.lastrowid

    def end_session(self):
        """Close the database session, filling in the end time and line count."""
        self.writeout_cache()
        with self.db:
            self.db.execute(
                """UPDATE sessions SET end=?, num_cmds=? WHERE
                            session==?""",
                (datetime.datetime.now(), len(self.input_hist_parsed) - 1,
                 self.session_number))
        self.session_number = 0

    def name_session(self, name):
        """Give the current session a name in the history database."""
        with self.db:
            self.db.execute("UPDATE sessions SET remark=? WHERE session==?",
                            (name, self.session_number))

    def reset(self, new_session=True):
        """Clear the session history, releasing all object references, and
        optionally open a new session."""
        self.output_hist.clear()
        # The directory history can't be completely empty
        self.dir_hist[:] = [os.getcwdu()]

        if new_session:
            if self.session_number:
                self.end_session()
            self.input_hist_parsed[:] = [""]
            self.input_hist_raw[:] = [""]
            self.new_session()

    # ------------------------------
    # Methods for retrieving history
    # ------------------------------
    def _get_range_session(self, start=1, stop=None, raw=True, output=False):
        """Get input and output history from the current session. Called by
        get_range, and takes similar parameters."""
        input_hist = self.input_hist_raw if raw else self.input_hist_parsed

        n = len(input_hist)
        if start < 0:
            start += n
        if not stop or (stop > n):
            stop = n
        elif stop < 0:
            stop += n

        for i in range(start, stop):
            if output:
                line = (input_hist[i], self.output_hist_reprs.get(i))
            else:
                line = input_hist[i]
            yield (0, i, line)

    def get_range(self, session=0, start=1, stop=None, raw=True, output=False):
        """Retrieve input by session.
        
        Parameters
        ----------
        session : int
            Session number to retrieve. The current session is 0, and negative
            numbers count back from current session, so -1 is previous session.
        start : int
            First line to retrieve.
        stop : int
            End of line range (excluded from output itself). If None, retrieve
            to the end of the session.
        raw : bool
            If True, return untranslated input
        output : bool
            If True, attempt to include output. This will be 'real' Python
            objects for the current session, or text reprs from previous
            sessions if db_log_output was enabled at the time. Where no output
            is found, None is used.
            
        Returns
        -------
        An iterator over the desired lines. Each line is a 3-tuple, either
        (session, line, input) if output is False, or
        (session, line, (input, output)) if output is True.
        """
        if session <= 0:
            session += self.session_number
        if session == self.session_number:  # Current session
            return self._get_range_session(start, stop, raw, output)
        return super(HistoryManager, self).get_range(session, start, stop, raw,
                                                     output)

    ## ----------------------------
    ## Methods for storing history:
    ## ----------------------------
    def store_inputs(self, line_num, source, source_raw=None):
        """Store source and raw input in history and create input cache
        variables _i*.

        Parameters
        ----------
        line_num : int
          The prompt number of this input.

        source : str
          Python input.

        source_raw : str, optional
          If given, this is the raw input without any IPython transformations
          applied to it.  If not given, ``source`` is used.
        """
        if source_raw is None:
            source_raw = source
        source = source.rstrip('\n')
        source_raw = source_raw.rstrip('\n')

        # do not store exit/quit commands
        if self._exit_re.match(source_raw.strip()):
            return

        self.input_hist_parsed.append(source)
        self.input_hist_raw.append(source_raw)

        with self.db_input_cache_lock:
            self.db_input_cache.append((line_num, source, source_raw))
            # Trigger to flush cache and write to DB.
            if len(self.db_input_cache) >= self.db_cache_size:
                self.save_flag.set()

        # update the auto _i variables
        self._iii = self._ii
        self._ii = self._i
        self._i = self._i00
        self._i00 = source_raw

        # hackish access to user namespace to create _i1,_i2... dynamically
        new_i = '_i%s' % line_num
        to_main = {
            '_i': self._i,
            '_ii': self._ii,
            '_iii': self._iii,
            new_i: self._i00
        }
        self.shell.user_ns.update(to_main)

    def store_output(self, line_num):
        """If database output logging is enabled, this saves all the
        outputs from the indicated prompt number to the database. It's
        called by run_cell after code has been executed.

        Parameters
        ----------
        line_num : int
          The line number from which to save outputs
        """
        if (not self.db_log_output) or (line_num
                                        not in self.output_hist_reprs):
            return
        output = self.output_hist_reprs[line_num]

        with self.db_output_cache_lock:
            self.db_output_cache.append((line_num, output))
        if self.db_cache_size <= 1:
            self.save_flag.set()

    def _writeout_input_cache(self, conn):
        with conn:
            for line in self.db_input_cache:
                conn.execute("INSERT INTO history VALUES (?, ?, ?, ?)",
                             (self.session_number, ) + line)

    def _writeout_output_cache(self, conn):
        with conn:
            for line in self.db_output_cache:
                conn.execute("INSERT INTO output_history VALUES (?, ?, ?)",
                             (self.session_number, ) + line)

    @needs_sqlite
    def writeout_cache(self, conn=None):
        """Write any entries in the cache to the database."""
        if conn is None:
            conn = self.db

        with self.db_input_cache_lock:
            try:
                self._writeout_input_cache(conn)
            except sqlite3.IntegrityError:
                self.new_session(conn)
                print("ERROR! Session/line number was not unique in",
                      "database. History logging moved to new session",
                      self.session_number)
                try:  # Try writing to the new session. If this fails, don't recurse
                    self._writeout_input_cache(conn)
                except sqlite3.IntegrityError:
                    pass
            finally:
                self.db_input_cache = []

        with self.db_output_cache_lock:
            try:
                self._writeout_output_cache(conn)
            except sqlite3.IntegrityError:
                print("!! Session/line number for output was not unique",
                      "in database. Output will not be stored.")
            finally:
                self.db_output_cache = []
Beispiel #28
0
class LatheGeometry(Geometry):
    _view_name = Unicode('LatheGeometryView', sync=True)
    points = List(vector3(), sync=True)
    segments = CInt(12, sync=True)
    phiStart = CFloat(0, sync=True)
    phiLength = CFloat(2*math.pi, sync=True)