Commits

Matthew Turk  committed 3bad7bd Merge

Merging from the Scene work

  • Participants
  • Parent commits c38c0ac, 8fa22fe

Comments (0)

Files changed (11)

File yt/data_objects/data_containers.py

         """
         verts = []
         samples = []
+        pb = get_pbar("Extracting ", len(list(self._get_grid_objs())))
         for i, g in enumerate(self._get_grid_objs()):
+            pb.update(i)
             my_verts = self._extract_isocontours_from_grid(
                             g, field, value, sample_values)
             if sample_values is not None:
                 my_verts, svals = my_verts
                 samples.append(svals)
             verts.append(my_verts)
+        pb.finish()
         verts = na.concatenate(verts).transpose()
         verts = self.comm.par_combine_object(verts, op='cat', datatype='array')
         verts = verts.transpose()

File yt/gui/reason/bottle_mods.py

   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 """
 
+import uuid
+import json
+import logging, threading
+import sys
+import urllib, urllib2
+import numpy as na
+
 from yt.utilities.bottle import \
     server_names, debug, route, run, request, ServerAdapter, response
-import uuid
 from extdirect_router import DirectRouter, DirectProviderDefinition
-import json
-import logging, threading
 from yt.utilities.logger import ytLogger as mylog
 from yt.funcs import *
-import sys
-import urllib, urllib2
 
 route_functions = {}
 route_watchers = []
 def notify_route(watcher):
     route_watchers.append(watcher)
 
+class BinaryDelivery(object):
+    delivered = False
+    payload = ""
+    def __init__(self, payload, name = ""):
+        self.name = name
+        self.payload = payload
+        #sys.__stderr__.write("CREATING A BINARY PAYLOAD %s (%s)\n" % (
+        #    self.name, len(self.payload)))
+
+    def get(self):
+        # We set our 
+        #sys.__stderr__.write("REQUESTED A BINARY PAYLOAD %s (%s)\n" % (
+        #    self.name, len(self.payload)))
+        p = self.payload
+        if p == "":
+            response.status = 404
+            return
+        self.payload = ""
+        return p
+
 class PayloadHandler(object):
     _shared_state = {}
     payloads = None
+    binary_payloads = None
     recorded_payloads = None
     multicast_ids = None
     multicast_payloads = None
     event = None
     count = 0
     debug = False
+    _prefix = ""
 
     def __new__(cls, *p, **k):
         self = object.__new__(cls, *p, **k)
         if self.event is None: self.event = threading.Event()
         if self.multicast_payloads is None: self.multicast_payloads = {}
         if self.multicast_ids is None: self.multicast_ids = {}
+        if self.binary_payloads is None: self.binary_payloads = []
 
     def deliver_payloads(self):
         with self.lock:
 
     def add_payload(self, to_add):
         with self.lock:
+            if "binary" in to_add:
+                self._add_binary_payload(to_add)
             self.payloads.append(to_add)
             # Does this next part need to be in the lock?
             if to_add.get("widget_id", None) in self.multicast_ids:
             if self.debug:
                 sys.__stderr__.write("**** Adding payload of type %s\n" % (to_add['type']))
 
+    def _add_binary_payload(self, bp):  
+        # This shouldn't be called by anybody other than add_payload.
+        bkeys = ensure_list(bp['binary'])
+        bp['binary'] = []
+        for bkey in bkeys:
+            bdata = bp.pop(bkey) # Get the binary data
+            if isinstance(bdata, na.ndarray):
+                bdata = bdata.tostring()
+            bpserver = BinaryDelivery(bdata, bkey)
+            self.binary_payloads.append(bpserver)
+            uu = uuid.uuid4().hex
+            bp['binary'].append((bkey, uu))
+            route("%s/%s" % (self._prefix, uu))(bpserver.get)
+            if self.debug:
+                sys.__stderr__.write(
+                    "**** Adding binary payload (%s) to %s\n" % (bkey, uu))
+
     def replay_payloads(self):
         return self.recorded_payloads
 

File yt/gui/reason/extdirect_repl.py

         reason_pylab()
 
     def activate(self):
+        self.payload_handler._prefix = self._global_token
         self._setup_logging_handlers()
         # Setup our heartbeat
         self.last_heartbeat = time.time()

File yt/gui/reason/html/app/controller/WidgetDirector.js

         }
         /*console.log("Directing payload for " + payload['widget_id'] +
                     " to resultId " + resultId);*/
+        if (payload['binary'] != null) {
+            this.loadBinaryData(payload);
+            return;
+        }
         var widgetInfo = this.getWidgetInstancesStore().getAt(resultId).data;
         widgetInfo['widget'].applyPayload(payload);
     },
 
+    loadBinaryData: function(payload1) {
+        /* https://developer.mozilla.org/en/using_xmlhttprequest
+           including progress */
+        function loadBinaryPayload(payload) {
+            var req = new XMLHttpRequest();
+            var bkeys = payload['binary'];
+            var nLeft = bkeys.length;
+            var bkey = bkeys[nLeft - 1];
+            var director = this;
+            payload['binary'] = null;
+            req.open("GET", bkey[1], true);
+            req.responseType = "arraybuffer";
+            onLoad = function(e) {
+                payload[bkey[0]] = req.response;
+                nLeft = nLeft - 1;
+                if (nLeft == 0) {
+                  director.sendPayload(payload);
+                } else {
+                  bkey = bkeys[nLeft - 1];
+                  req.open("GET", bkey[1], true);
+                  req.responseType = "arraybuffer";
+                  req.onload = onLoad;
+                  req.send();
+                  exaine = payload;
+                }
+            }
+            req.onload = onLoad;
+            req.send();
+        }
+        loadBinaryPayload.call(this, payload1);
+    },
+
     enableDebug: function() {
         if(this.instanceView) {return;}
         this.instanceView = Ext.widget('widgetinstancesgrid');

File yt/gui/reason/html/app/controller/widgets/Scene.js

 Ext.define("Reason.controller.widgets.Scene", {
     extend: 'Reason.controller.widgets.BaseWidget',
     requires: ['Reason.view.widgets.Scene',
+               'Reason.view.widgets.IsocontourCreator',
                'Reason.store.widgets.CameraKeyFrames',
+               'Reason.store.widgets.CameraPathElements',
                'Reason.store.widgets.SceneWidgets',
                'Ext.ux.CheckColumn'],
     templates: {
         createScene: 'widget_store.create_scene({varname})',
         deliverGrids: 'widget_store["{widget.varname}"].deliver_gridlines()',
+        createIsocontour: 'widget_store["{varname}"].deliver_isocontour(' +
+                          '"{field}", {value}, {relValue:capitalize})',
     },
 
     /* These call functions on the controller object */
         ["#renderPath", "click", "renderPath"],
         ["#keyframeview", "select", "shiftToKeyframe"],
         ["#widgetEnabled", "checkchange", "toggleWidgetEnabled"],
+        ["#addIsocontour", "click", "createIsocontour"],
+        ["#cameraPathSlider", "change", "updateCameraPosition"],
     ],
 
     /* These call templates */
         { ref:'scenePanel', selector: '#scenepanel' },
         { ref:'keyFrameView', selector: '#keyframeview' },
         { ref:'widgetPanel', selector: '#widgetlist'},
+        { ref:'cameraPathSlider', selector: '#cameraPathSlider'},
     ],
 
     /* key: , shift: and tpl: */
     keyTriggers: [
     ],
 
-
     applyPayload: function(payload) {
         if (payload['ptype'] == 'grid_lines') {
-            this.addGridLines(payload['corners'], payload['levels'],
-                              payload['max_level']);
+            payload['corners'] = new Float64Array(payload['corners']);
+            payload['levels'] = new Int32Array(payload['levels']);
+            this.addGridLines(payload['corners'], payload['levels'], payload['max_level']);
+        } else if (payload['ptype'] == 'isocontour') {
+            payload['vert'] = new Float64Array(payload['vert']);
+            payload['normals'] = new Float64Array(payload['normals']);
+            this.addIsocontour(payload['vert'], payload['normals']);
+        } else if (payload['ptype'] == 'camerapath') {
+            this.updateCameraPathElements(payload['data']);
         } else {
             console.log("Unknown payload type received for 3D scene: " +
                         payload['ptype']);
         this.applyExecuteHandlers(this.dataView);
         this.keyFrames = Ext.create("Reason.store.widgets.CameraKeyFrames");
         this.getKeyFrameView().bindStore(this.keyFrames);
+        this.pathElements = Ext.create("Reason.store.widgets.CameraPathElements");
         this.widgets = Ext.create("Reason.store.widgets.SceneWidgets");
         this.getWidgetPanel().bindStore(this.widgets);
+        this.fieldStore = Ext.create("Reason.store.Fields")
+        this.fieldStore.loadData(wd['fields']);
         return this.dataView;
     },
 
     },
 
     addGridLines: function(corners, levels, maxLevel) {
-        var i, g, n, p;
+        var i, g, n, p, offset, ind;
         var order1 = [0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3];
         var order2 = [1, 2, 3, 0, 5, 6, 7, 4, 4, 5, 6, 7];
+        var nv = levels.length;
         gw = [];
         for (i = 0; i < maxLevel + 1; i = i + 1) {
             var grids = new X.mesh();
             });
             grids.ga = "LINES";
         }
+        examine = {n: n, p: p, corners: corners};
+        var i0, i1, i2;
         Ext.each(levels, function(level, index, allLevels) {
             p = gw[level].points;
             n = gw[level].normals;
             for (i = 0; i < 12; i = i + 1) {
                 n.add(1.0, 0.0, 0.0);
                 n.add(1.0, 0.0, 0.0);
-                p.add(corners[order1[i]][0][index],
-                      corners[order1[i]][1][index],
-                      corners[order1[i]][2][index]);
-                p.add(corners[order2[i]][0][index],
-                      corners[order2[i]][1][index],
-                      corners[order2[i]][2][index]);
+                p.add(corners[(((order1[i] * 3 + 0)*nv)+index)],
+                      corners[(((order1[i] * 3 + 1)*nv)+index)],
+                      corners[(((order1[i] * 3 + 2)*nv)+index)]);
+                p.add(corners[(((order2[i] * 3 + 0)*nv)+index)],
+                      corners[(((order2[i] * 3 + 1)*nv)+index)],
+                      corners[(((order2[i] * 3 + 2)*nv)+index)]);
             }
         });
         for (i = 0; i < maxLevel + 1; i = i + 1) {
         this.renderer.render();
     },
 
+    createIsocontour: function() {
+        var win; 
+        var controller = this;
+        /* field , value */
+        function callExtract(b, e) {
+            var conf = {
+                varname: controller.dataView.varname,
+                field: win.query("#field")[0].getValue(),
+                value: win.query("#value")[0].getValue(),
+                relValue: "" + win.query("#relValue")[0].getValue(),
+            };
+            cmd = controller.templateManager.applyObject(
+                    conf, "createIsocontour");
+            reason.server.execute(cmd);
+            win.destroy();
+        }
+        win = Ext.widget("isocontourcreator");
+        win.query("#field")[0].bindStore(this.fieldStore);
+        win.query("#extract")[0].on('click', callExtract);
+        win.query("#cancel")[0].on('click', function(){win.destroy();});
+        win.show();
+    },
+
+    addIsocontour: function(vertices, normals) {
+        console.log("Adding isocontours ...");
+        var i, g, n, p;
+        var nv = vertices.length/3;
+        var last = 0;
+        var surf = new X.mesh();
+        this.widgets.add({
+          name: "Isocontour",
+          type: 'isocontour',
+          widget: surf,
+          enabled: true,
+        });
+        surf.ga = "TRIANGLES";
+        p = surf.points;
+        n = surf.normals;
+
+        for (index = 0; index < nv; index = index + 1) {
+            p.add(vertices[index * 3 + 0],
+                  vertices[index * 3 + 1],
+                  vertices[index * 3 + 2]);
+            n.add(normals[index * 3 + 0],
+                  normals[index * 3 + 1],
+                  normals[index * 3 + 2]);
+        }
+        surf.color = [1.0, 0.0, 0.0];
+        this.renderer.add(surf);
+        this.renderer.render();
+    },
+
     addKeyframe: function() {
+        this.getCameraPathSlider().setValue(0);
+        this.getCameraPathSlider().disable();
         var v = this.renderer.camera.view;
         var va = v.toArray();
         this.keyFrames.add({
     },
 
     renderPath: function() {
-        
         var t = new Ext.XTemplate("[[{0}, {1}, {2}, {3}], ",
                                   " [{4}, {5}, {6}, {7}], ",
                                   " [{8}, {9}, {10}, {11}], ",
                                   " [{12}, {13}, {14}, {15}]],\n");
         var cmdt = new Ext.XTemplate("widget_store['{0}'].render_path(\n",
-                                     "[{1}]\n,[{2}], 100)");
+                                     "[{1}]\n,[{2}], 101)");
         var path = "";
         var times = "";
         Ext.each(this.keyFrames.data.items, function(rec, ind, all) {
             path = path + t.apply(rec.data.view.flatten());
         });
         var cmd = cmdt.apply([this.dataView.varname, path, times]);
+        reason.server.execute(cmd);
+    },
+
+    updateCameraPathElements: function(elements) {
+        var cpe = this.pathElements;
+        var i;
+        cpe.removeAll();
+        for (i = 0; i < elements[0].length; i = i + 1) {
+            cpe.add({position: elements[0][i],
+                     focus: elements[1][i],
+                     up: elements[2][i]});
+        }
+        v = this.getCameraPathSlider().enable();
+    },
+
+    updateCameraPosition: function(b, e) {
+        v = this.getCameraPathSlider().getValue();
+        console.log(v);
+        rec = this.pathElements.data.items[v].data;
+        this.renderer.camera.position = rec.position;
+        this.renderer.camera.focus = rec.focus;
+        this.renderer.camera.up = rec.up;
+        this.renderer.render();
     },
 
 });

File yt/gui/reason/html/app/store/widgets/CameraPathElements.js

+/**********************************************************************
+Camera Path Element store for Reason
+
+Author: Matthew Turk <matthewturk@gmail.com>
+Affiliation: Columbia University
+Homepage: http://yt-project.org/
+License:
+  Copyright (C) 2012 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
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  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 <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+Ext.define('Reason.store.widgets.CameraPathElements', {
+    extend: 'Ext.data.Store',
+    id: 'camerapathelements',
+    fields: [
+       {name: 'position'},
+       {name: 'focus'},
+       {name: 'up'},
+    ],
+    data: [],
+});
+

File yt/gui/reason/html/app/view/widgets/IsocontourCreator.js

+/**********************************************************************
+The Isocontour Creator
+
+Author: Matthew Turk <matthewturk@gmail.com>
+Affiliation: Columbia University
+Homepage: http://yt-project.org/
+License:
+  Copyright (C) 2012 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
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  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 <http://www.gnu.org/licenses/>.
+***********************************************************************/
+
+Ext.define("Reason.view.widgets.IsocontourCreator", {
+    extend: 'Ext.window.Window',
+    alias: 'widget.isocontourcreator',
+    width: 370,
+    height: 200,
+    modal: true,
+    resizable: false,
+    draggable: false,
+    border: false,
+    layout: 'fit',
+    title: "Create Phase Plot",
+
+    items: [{ xtype: 'form', // FormPanel
+              labelWidth:80,
+              frame:true,
+              items: [ {
+                xtype:'combo',
+                fieldLabel: 'Field',
+                id: 'field',
+                width: 290,
+                queryMode: 'local',
+                editable: false,
+                triggerAction: 'all',
+                value: 'Density'
+              },{
+                xtype:'checkboxfield',
+                fieldLabel: 'Relative Value?',
+                itemId: 'relValue',
+                value: true,
+                checked: true,
+                width: 290,
+                allowBlank:false,
+              },{
+                xtype:'textfield',
+                fieldLabel: 'Value',
+                itemId: 'value',
+                value: '0.5',
+                width: 290,
+                allowBlank:false,
+              }
+            ],
+            buttons: [
+                {
+                    text: 'Extract',
+                    itemId: 'extract',
+                },{
+                    text: 'Cancel',
+                    itemId: 'cancel',
+                }
+            ]
+        }],
+});
+

File yt/gui/reason/html/app/view/widgets/Scene.js

         }, {
             xtype: 'multislider',
             itemId: 'cameraPathSlider',
+            disabled: true,
             minValue: 0,
             maxValue: 100,
             increment: 1,
                   layout: 'absolute',
                   flex: 1,
                   items : [
+                    {
+                      xtype: 'button',
+                      text: 'Add Isocontour',
+                      itemId: 'addIsocontour'
+                    },
                   ]
                 },
                 ] } /* tabpanel items and entry */

File yt/gui/reason/widget_builders.py

 def get_corners(pf, max_level=None):
     DL = pf.domain_left_edge[None,:,None]
     DW = pf.domain_width[None,:,None]/100.0
-    corners = ((pf.h.grid_corners-DL)/DW).tolist()
-    levels = pf.h.grid_levels.tolist()
+    corners = ((pf.h.grid_corners-DL)/DW)
+    levels = pf.h.grid_levels
     return corners, levels
 
-def get_grid_vertices(pf, max_level=None):
-    if max_level is None: max_level = pf.h.max_level
-    fns = []
-    for lvl in range(max_level):
-        fn = "%s_lvl_%02i_grids.vtk"%(pf, lvl)
-        f = open(fn, "w")
-
-        f.write("""# vtk DataFile Version 3.0
-        vtk output
-        ASCII
-        DATASET POLYDATA
-        POINTS %s float
-        """ % (pf.h.num_grids * 8))
-
-        for gi in xrange(pf.h.num_grids):
-            if pf.h.grid_levels[gi][0] != lvl: continue
-            gc = pf.h.grid_corners[:, :, gi] * 100.0
-            for i in range(8):
-                f.write("%0.9f %0.9f %0.9f\n" % (gc[i, 0], gc[i, 1], gc[i, 2]))
-
-        f.write("LINES %s %s\n" % (pf.h.num_grids * 12, 3 * pf.h.num_grids * 12))
-
-        order1 = (0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3)
-        order2 = (1, 2, 3, 0, 5, 6, 7, 4, 4, 5, 6, 7)
-
-        for gi in xrange(pf.h.num_grids):
-            if pf.h.grid_levels[gi][0] != lvl: continue
-            offset = 8 * gi
-            for p1, p2 in zip(order1, order2):
-                f.write("2 %s %s\n" % (p1 + offset, p2 + offset))
-        f.close()
-        fns.append(fn)
-    return fn
-
-def get_isocontour(pf, field, value=None):
+def get_isocontour(pf, field, value=None, rel_val = False):
 
     dd = pf.h.all_data()
-    if value is None:
+    if value is None or rel_val:
+        if value is None: value = 0.5
         mi, ma = na.log10(dd.quantities["Extrema"]("Density")[0])
-        value = 10.**((mi + ma)/2.)
+        value = 10.0**(value*(ma - mi) + mi)
     vert = dd.extract_isocontours("Density", value)
     na.multiply(vert, 100, vert)
-
-    fn = "%s_surface.vtk" % pf
-    f = open(fn, "w")
-    f.write("vtk output\nASCII\nDATASET POLYDATA\nPOINTS %s float\n" % (vert.shape[0]))
-    for v in vert:
-        f.write("%0.14f %0.14f %0.14f\n" % (v[0], v[1], v[2]))
-    f.write("VERTICES %s %s\n" % (vert.shape[0]/3, vert.shape[0] + vert.shape[0]/3))
-    for i in range(vert.shape[0]/3):
-        f.write("3 %i %i %i\n" % (i*3, i*3+1, i*3+2))
-    f.close()
-    return fn
+    return vert
 
 def get_streamlines(pf):
     from yt.visualization.api import Streamlines

File yt/gui/reason/widget_store.py

 from yt.mods import *
 import weakref
 from .bottle_mods import PayloadHandler, lockit
-from .widget_builders import RenderingScene, get_corners
+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>
     def create_scene(self, pf):
         '''Creates 3D XTK-based scene'''
         widget = SceneWidget(pf)
-        widget_data = {'title':'Scene for %s' % pf}
+        field_list = list(set(pf.h.field_list
+                            + pf.h.derived_field_list))
+        field_list.sort()
+        widget_data = {'title':'Scene for %s' % pf,
+                       'fields': field_list}
         self._add_widget(widget, widget_data)
 
 
                                  'image':self._rendering_scene.snapshot()})
         return
 
+    def deliver_isocontour(self, field, value, rel_val = False):
+        ph = PayloadHandler()
+        vert = get_isocontour(self.pf, 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'],
+                                 'vert':vert,
+                                 'normals':normals})
+
     def deliver_gridlines(self):
         ph = PayloadHandler()
         corners, levels = get_corners(self.pf)
         ph.widget_payload(self, {'ptype':'grid_lines',
+                                 'binary': ['corners', 'levels'],
                                  'corners': corners,
                                  'levels': levels,
                                  'max_level': int(self.pf.h.max_level)})
         return
 
+    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([na.dot(na.eye(4)*R[3,2],na.dot(R, norm)) for R in views])
+        r = views[0]
+        print r 
+        ups = na.array([na.dot(R,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',
+                                 'data':path,})
+
+        return
+
+
     def deliver_streamlines(self):
         pf = PayloadHandler()
         pass

File yt/visualization/volume_rendering/camera.py

         self.back_center =  center - 0.5*width[2]*unit_vectors[2]
         self.front_center = center + 0.5*width[2]*unit_vectors[2]         
 
+    def update_view_from_matrix(self, mat):
+        pass
+
     def look_at(self, new_center, north_vector = None):
         r"""Change the view direction based on a new focal point.