yt-extjs4 / yt / gui / reason /

This is a place to store widgets, and to create them.

Author: Matthew Turk <>
Affiliation: Columbia University
  Copyright (C) 2011 Matthew Turk.  All Rights Reserved.

  This file is part of yt.

  yt is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <>.

from yt.mods import *
import weakref
from .bottle_mods import PayloadHandler, lockit
from .widget_builders import RenderingScene, get_corners, get_isocontour
from yt.visualization.plot_window import PWViewerExtJS
from yt.visualization.volume_rendering.create_spline import create_spline
import uuid

_phase_plot_mds = """<pre>
Field X: %s
Field Y: %s
Field Z: %s
Weight : %s

class WidgetStore(dict):
    def __init__(self, global_token = ""):
        self._global_token = global_token
        self.payload_handler = PayloadHandler()
        super(WidgetStore, self).__init__()

    def _add_widget(self, widget, widget_data = None):
        # We need to make sure that we aren't running in advance of a new
        # object being added.
        #uu = str(uuid.uuid1()).replace("-","_")
        #varname = "%s_%s" % (widget._widget_name, uu)
        varname = "%s_%s" % (widget._widget_name, len(self))
        widget._ext_widget_id = varname
        payload = {'type': 'widget',
                   'widget_type': widget._widget_name,
                   'varname': varname}
        widget._ext_widget_id = varname
        payload['data'] = widget_data
        self[varname] = widget

    def activate_multicast(self, widget_id, multicast_session, multicast_token):
        # Here we have to conduct the handshake between us and the GAE
        self.payload_handler.multicast_ids[widget_id] = (
            multicast_session, multicast_token)"Multicasting %s to %s", widget_id, multicast_session)

    def create_slice(self, pf, center, axis, field, onmax):
        if onmax: 
            center = pf.h.find_max('Density')[1]
            center = na.array(center)
        axis = inv_axis_names[axis.lower()]
        coord = center[axis]
        sl = pf.h.slice(axis, coord, center = center, periodic = True)
        xax, yax = x_dict[axis], y_dict[axis]
        DLE, DRE = pf.domain_left_edge, pf.domain_right_edge
        pw = PWViewerExtJS(sl, (DLE[xax], DRE[xax], DLE[yax], DRE[yax]), setup = False)
        field_list = list(set(pf.h.field_list + pf.h.derived_field_list))
        field_list = [dict(text = f) for f in sorted(field_list)]
        cb = pw._get_cbar_image()
        trans = pw._field_transform[pw._current_field].name
        widget_data = {'fields': field_list,
                         'initial_field': field,
                         'title': "%s Slice" % (pf),
                         'colorbar': cb,
                         'initial_transform' : trans}
        self._add_widget(pw, widget_data)

    def create_proj(self, pf, axis, field, weight):
        if weight == "None": weight = None
        axis = inv_axis_names[axis.lower()]
        proj = pf.h.proj(axis,field, weight_field=weight, periodic = True)
        xax, yax = x_dict[axis], y_dict[axis]
        DLE, DRE = pf.domain_left_edge, pf.domain_right_edge
        pw = PWViewerExtJS(proj, (DLE[xax], DRE[xax], DLE[yax], DRE[yax]),
                           setup = False)
        field_list = list(set(pf.h.field_list + pf.h.derived_field_list))
        field_list = [dict(text = f) for f in sorted(field_list)]
        cb = pw._get_cbar_image()
        widget_data = {'fields': field_list,
                       'initial_field': field,
                       'title': "%s Projection" % (pf),
                       'colorbar': cb}
        self._add_widget(pw, widget_data)

    def create_grid_dataview(self, pf):
        levels = pf.h.grid_levels
        left_edge = pf.h.grid_left_edge
        right_edge = pf.h.grid_right_edge
        dimensions = pf.h.grid_dimensions
        cell_counts =
        # This is annoying, and not ... that happy for memory.
        i = pf.h.grids[0]._id_offset
        vals = []
        for i, (L, LE, RE, dim, cell) in enumerate(zip(
            levels, left_edge, right_edge, dimensions, cell_counts)):
            vals.append([ int(i), int(L[0]),
                          float(LE[0]), float(LE[1]), float(LE[2]),
                          float(RE[0]), float(RE[1]), float(RE[2]),
                          int(dim[0]), int(dim[1]), int(dim[2]),
                          int(cell)] )
        varname = "gg_%s" % (len(self))
        self[varname] = None
        payload = {'type': 'widget',
                   'widget_type': 'grid_data',
                   'varname': varname, # Is just "None"
                   'data': dict(gridvals = vals),

    def create_pf_display(self, pf):
        widget = ParameterFileWidget(pf)
        widget_data = {'fields': widget._field_list(),
                       'level_stats': widget._level_stats(),
                       'pf_info': widget._pf_info(),
        self._add_widget(widget, widget_data)

    def create_mapview(self, widget_name):
        widget = self[widget_name]
        # We want multiple maps simultaneously
        uu = "/%s/%s" % (self._global_token,
        from .pannable_map import PannableMapServer
        data = widget.data_source
        field_name = widget._current_field
        pm = PannableMapServer(data, field_name, route_prefix = uu)
        widget_data = {'prefix': uu, 'field':field_name}
        self._add_widget(pm, widget_data)

    def create_phase(self, obj, field_x, field_y, field_z, weight):
        from yt.visualization.profile_plotter import PhasePlotterExtWidget
        pp = PhasePlotterExtWidget(obj, field_x, field_y, field_z, weight)
        mds = _phase_plot_mds % (field_x, field_y, field_z, 
        widget_data = {'title': "%s Phase Plot" % (obj),
                       'metadata_string': mds}
        self._add_widget(pp, widget_data)

    def create_scene(self, pf):
        '''Creates 3D XTK-based scene'''
        widget = SceneWidget(pf)
        field_list = list(set(pf.h.field_list
                            + pf.h.derived_field_list))
        widget_data = {'title':'Scene for %s' % pf,
                       'fields': field_list}
        self._add_widget(widget, widget_data)

class ParameterFileWidget(object):
    _ext_widget_id = None
    _widget_name = "parameterfile"

    def __init__(self, pf): = weakref.proxy(pf)

    def _field_list(self):
        field_list = list(set(
        return [dict(text = field) for field in field_list]

    def _level_stats(self):
        level_data = []
        level_stats =
        ngrids = float(level_stats['numgrids'].sum())
        ncells = float(level_stats['numcells'].sum())
        for level in range( + 1):
            cell_count = level_stats['numcells'][level]
            grid_count = level_stats['numgrids'][level]
            level_data.append({'level' : level,
                               'cell_count': int(cell_count),
                               'grid_count': int(grid_count),
                               'cell_rel': int(100*cell_count/ncells),
                               'grid_rel': int(100*grid_count/ngrids)})
        return level_data

    def _pf_info(self):
        tr = {}
        for k, v in
            if isinstance(v, na.ndarray):
                tr[k] = v.tolist()
                tr[k] = v
        return tr

    def deliver_field(self, field):
        ph = PayloadHandler()
             'field_source':[field].get_source() })

class SceneWidget(object):
    _ext_widget_id = None
    _widget_name = "scene"
    _rendering_scene = None

    def __init__(self, pf): = weakref.proxy(pf)

    def add_volume_rendering(self):
        return None
        self._rendering_scene = RenderingScene(, None, None)

    def deliver_rendering(self, scene_config):
        ph = PayloadHandler()
        ph.widget_payload(self, {'ptype':'rendering',

    def deliver_isocontour(self, field, value, rel_val = False):
        ph = PayloadHandler()
        vert = get_isocontour(, field, value, rel_val)
        normals = na.empty(vert.shape)
        for i in xrange(vert.shape[0]/3):
            n = na.cross(vert[i*3,:], vert[i*3+1,:])
            normals[i*3:i*3+3,:] = n[None,:]
        ph.widget_payload(self, {'ptype':'isocontour',
                                 'binary': ['vert', 'normals'],

    def deliver_gridlines(self):
        ph = PayloadHandler()
        corners, levels = get_corners(
        ph.widget_payload(self, {'ptype':'grid_lines',
                                 'binary': ['corners', 'levels'],
                                 'corners': corners,
                                 'levels': levels,
                                 'max_level': int(})

    def render_path(self, views, times, N):
        # Assume that path comes in as a list of matrice
        # Assume original vector is (0., 0., 1.), up is (0., 1., 0.)
        # for matrix in matrices:

        views = [na.array(view) for view in views]
        times = na.linspace(0.0,1.0,len(times))
        norm = na.array([0.,0.,1.,1.])
        up = na.array([0.,1.,0.,1.])
        centers = na.array([*R[3,2],, norm)) for R in views])
        r = views[0]
        print r 
        ups = na.array([,up) for R in views])
        print 'centers'
        for center in centers: print center
        print 'ups'
        for up in ups: print up

        pos = na.empty((N,3), dtype="float64")
        uv = na.empty((N,3), dtype="float64")
        f = na.zeros((N,3), dtype="float64")
        for i in range(3):
            pos[:,i] = create_spline(times, centers[:,i], na.linspace(0.0,1.0,N))
            uv[:,i] = create_spline(times, ups[:,i], na.linspace(0.0,1.0,N))
        path = [pos.tolist(), f.tolist(), uv.tolist()]
        ph = PayloadHandler()
        ph.widget_payload(self, {'ptype':'camerapath',


    def deliver_streamlines(self):
        pf = PayloadHandler()