[Yt-svn] commit/yt: 2 new changesets
Bitbucket
commits-noreply at bitbucket.org
Thu Nov 10 08:17:54 PST 2011
2 new commits in yt:
https://bitbucket.org/yt_analysis/yt/changeset/8608363b3d60/
changeset: 8608363b3d60
branch: yt
user: MatthewTurk
date: 2011-11-10 17:16:29
summary: Adding a "pannable map" button to slice and projection view. Closes #287.
affected #: 6 files
diff -r c038dd1e297af8267633def26899d7c7b2c1d671 -r 8608363b3d609d754c9f27a01e717dccc09b8ba5 yt/gui/reason/bottle_mods.py
--- a/yt/gui/reason/bottle_mods.py
+++ b/yt/gui/reason/bottle_mods.py
@@ -149,6 +149,7 @@
print "WARNING: %s has no _route_prefix attribute. Not notifying."
continue
w._route_prefix = token
+ repl._global_token = token
repl.activate()
repl.execution_thread.wait()
print
diff -r c038dd1e297af8267633def26899d7c7b2c1d671 -r 8608363b3d609d754c9f27a01e717dccc09b8ba5 yt/gui/reason/extdirect_repl.py
--- a/yt/gui/reason/extdirect_repl.py
+++ b/yt/gui/reason/extdirect_repl.py
@@ -220,6 +220,7 @@
_resources = ("/resources/:path#.+#", "GET"),
_philogl = ("/philogl/:path#.+#", "GET"),
_js = ("/js/:path#.+#", "GET"),
+ _leaflet = ("/leaflet/:path#.+#", "GET"),
_images = ("/images/:path#.+#", "GET"),
_theme = ("/theme/:path#.+#", "GET"),
_session_py = ("/session.py", "GET"),
@@ -340,6 +341,13 @@
return
return open(pp).read()
+ def _leaflet(self, path):
+ pp = os.path.join(local_dir, "html", "leaflet", path)
+ if not os.path.exists(pp):
+ response.status = 404
+ return
+ return open(pp).read()
+
def _images(self, path):
pp = os.path.join(local_dir, "html", "images", path)
if not os.path.exists(pp):
@@ -515,6 +523,21 @@
'widget_data_name': '_twidget_data'})
@lockit
+ def create_mapview(self, widget_name):
+ # We want multiple maps simultaneously
+ uu = "/%s/%s" % (getattr(self, "_global_token", ""),
+ str(uuid.uuid1()).replace("-","_"))
+ from .pannable_map import PannableMapServer
+ data = self.locals[widget_name].data_source
+ field_name = self.locals[widget_name]._current_field
+ pm = PannableMapServer(data, field_name, route_prefix = uu)
+ self.locals['_tpm'] = pm
+ self.locals['_twidget_data'] = {'prefix': uu, 'field':field_name}
+ self.execution_thread.queue.put({'type': 'add_widget',
+ 'name': '_tpm',
+ 'widget_data_name': '_twidget_data'})
+
+ @lockit
def create_slice(self, pfname, center, axis, field, onmax):
if not onmax:
center_string = \
diff -r c038dd1e297af8267633def26899d7c7b2c1d671 -r 8608363b3d609d754c9f27a01e717dccc09b8ba5 yt/gui/reason/html/index.html
--- a/yt/gui/reason/html/index.html
+++ b/yt/gui/reason/html/index.html
@@ -80,6 +80,10 @@
In that case, it will default to whatever is in the family. --><link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Inconsolata">
+ <!-- LEAFLET STUFF -->
+ <script type="text/javascript" src="leaflet/leaflet.js"></script>
+ <link rel="stylesheet" href="leaflet/leaflet.css" />
+
<!-- LIBS --><script type="text/javascript" src="resources/adapter/ext/ext-base.js"></script><script type="text/javascript" src="resources/ext-all.js"></script>
@@ -119,6 +123,9 @@
<!-- THE GRID VIEWER FUNCTIONS --><script type="text/javascript" src="js/widget_isocontour.js"></script>
+ <!-- THE PANNABLE MAP FUNCTIONS -->
+ <script type="text/javascript" src="js/widget_pannablemap.js"></script>
+
<script id="gv-shader-fs" type="x-shader/x-fragment">
#ifdef GL_ES
precision highp float;
diff -r c038dd1e297af8267633def26899d7c7b2c1d671 -r 8608363b3d609d754c9f27a01e717dccc09b8ba5 yt/gui/reason/html/js/widget_pannablemap.js
--- /dev/null
+++ b/yt/gui/reason/html/js/widget_pannablemap.js
@@ -0,0 +1,76 @@
+/**********************************************************************
+The Pannable Map Widget
+
+Author: Matthew Turk <matthewturk at gmail.com>
+Affiliation: Columbia University
+Homepage: http://yt-project.org/
+License:
+ 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
+ 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/>.
+***********************************************************************/
+
+var WidgetPannableMap = function(python_varname, widget_data) {
+ this.id = python_varname;
+ this.widget_data = widget_data;
+
+ viewport.get("center-panel").add(
+ {
+ xtype: 'panel',
+ id: "pm_" + this.id,
+ title: "Pannable Map",
+ iconCls: 'graph',
+ autoScroll: true,
+ layout:'absolute',
+ closable: true,
+ items: [
+ {
+ xtype:'box',
+ autoEl: {
+ tag: 'div',
+ id: "map_" + this.id,
+ width: 512,
+ height: 512,
+ },
+ x: 10,
+ y: 10,
+ width: 512,
+ height: 512,
+ listeners: {afterrender:
+ function() {
+ var map = new L.Map('map_' + python_varname, {
+ center: new L.LatLng(0.0, 0.0),
+ zoom: 0,
+ });
+ var cloudmadeUrl = widget_data['prefix'] + '/map/{z}/{x}/{y}.png';
+ cloudmade = new L.TileLayer(cloudmadeUrl, {maxZoom: 18});
+ map.addLayer(cloudmade);
+ }},
+ }
+ ]
+ }
+ );
+
+ viewport.get("center-panel").activate("pm_" + this.id);
+ viewport.doLayout();
+ this.panel = viewport.get("center-panel").get("pm_" + this.id);
+ this.panel.doLayout();
+ examine = this.panel;
+
+ this.accept_results = function(payload) { }
+}
+
+widget_types['pannable_map'] = WidgetPannableMap;
diff -r c038dd1e297af8267633def26899d7c7b2c1d671 -r 8608363b3d609d754c9f27a01e717dccc09b8ba5 yt/gui/reason/html/js/widget_plotwindow.js
--- a/yt/gui/reason/html/js/widget_plotwindow.js
+++ b/yt/gui/reason/html/js/widget_plotwindow.js
@@ -331,6 +331,21 @@
});
}
},{
+ xtype: 'button',
+ text: 'Pannable Map',
+ x: 10,
+ y: 335,
+ width: 80,
+ tooltip: "Open a pannable map in a new tab",
+ handler: function(b,e) {
+ img_data = image_dom.src;
+ yt_rpc.ExtDirectREPL.create_mapview(
+ {widget_name:python_varname},
+ function(rv) {
+ /*alert(rv);*/
+ });
+ }
+ },{
xtype: 'panel',
layout: 'vbox',
id: 'rhs_panel_' + python_varname,
diff -r c038dd1e297af8267633def26899d7c7b2c1d671 -r 8608363b3d609d754c9f27a01e717dccc09b8ba5 yt/gui/reason/pannable_map.py
--- a/yt/gui/reason/pannable_map.py
+++ b/yt/gui/reason/pannable_map.py
@@ -47,14 +47,16 @@
return func
class PannableMapServer(object):
- def __init__(self, data, field):
+ _widget_name = "pannable_map"
+ def __init__(self, data, field, route_prefix = ""):
self.data = data
self.pf = data.pf
self.field = field
- bottle.route("/map/:L/:x/:y.png")(self.map)
- bottle.route("/")(self.index)
- bottle.route("/index.html")(self.index)
- bottle.route("/static/:filename#.+#")(self.static)
+
+ bottle.route("%s/map/:L/:x/:y.png" % route_prefix)(self.map)
+ bottle.route("%s/" % route_prefix)(self.index)
+ bottle.route("%s/index.html" % route_prefix)(self.index)
+ bottle.route("%s/static/:filename#.+#" % route_prefix)(self.static)
# This is a double-check, since we do not always mandate this for
# slices:
self.data[self.field] = self.data[self.field].astype("float64")
https://bitbucket.org/yt_analysis/yt/changeset/f9e18f610a3f/
changeset: f9e18f610a3f
branch: yt
user: MatthewTurk
date: 2011-11-10 17:17:32
summary: Merging
affected #: 6 files
diff -r 8608363b3d609d754c9f27a01e717dccc09b8ba5 -r f9e18f610a3ff3fa3eb5463277aad44ca6b2a8d4 tests/object_field_values.py
--- a/tests/object_field_values.py
+++ b/tests/object_field_values.py
@@ -73,12 +73,38 @@
YTStaticOutputTest.setup(self)
known_objects[self.object_name](self)
+class YTExtractIsocontoursTest(YTFieldValuesTest):
+ def run(self):
+ val = self.data_object.quantities["WeightedAverageQuantity"](
+ "Density", "Density")
+ triangles = self.data_object.extract_isocontours("Density",
+ val, rescale = False, sample_values = "Temperature")
+ self.result = triangles
+
+ def compare(self, old_result):
+ self.compare_array_delta(self.result, old_result, 1e-7)
+
+class YTIsocontourFluxTest(YTFieldValuesTest):
+ def run(self):
+ val = self.data_object.quantities["WeightedAverageQuantity"](
+ "Density", "Density")
+ flux = self.data_object.calculate_isocontour_flux(
+ "Density", val, "x-velocity", "y-velocity", "z-velocity")
+ self.result = flux
+
+ def compare(self, old_result):
+ self.compare_value_delta(self.result, old_result, 1e-7)
+
for object_name in known_objects:
for field in field_list + particle_field_list:
if "cut_region" in object_name and field in particle_field_list:
continue
create_test(YTFieldValuesTest, "%s_%s" % (object_name, field),
field = field, object_name = object_name)
+ create_test(YTExtractIsocontoursTest, "%s" % (object_name),
+ object_name = object_name)
+ create_test(YTIsocontourFluxTest, "%s" % (object_name),
+ object_name = object_name)
class YTDerivedQuantityTest(YTStaticOutputTest):
def setup(self):
@@ -140,4 +166,3 @@
"%s_%s" % (object_name, field),
field_name = field,
object_name = object_name)
-
diff -r 8608363b3d609d754c9f27a01e717dccc09b8ba5 -r f9e18f610a3ff3fa3eb5463277aad44ca6b2a8d4 yt/data_objects/data_containers.py
--- a/yt/data_objects/data_containers.py
+++ b/yt/data_objects/data_containers.py
@@ -2266,7 +2266,7 @@
grid.child_mask, self.domain_width, dls[grid.Level],
self.axis)
-class AMR3DData(AMRData, GridPropertiesMixin):
+class AMR3DData(AMRData, GridPropertiesMixin, ParallelAnalysisInterface):
_key_fields = ['x','y','z','dx','dy','dz']
"""
Class describing a cluster of data points, not necessarily sharing any
@@ -2280,6 +2280,7 @@
used as a base class. Note that *center* is supplied, but only used
for fields and quantities that require it.
"""
+ ParallelAnalysisInterface.__init__(self)
AMRData.__init__(self, pf, fields, **kwargs)
self._set_center(center)
self.coords = None
@@ -2364,11 +2365,14 @@
f = grid[field]
return na.array([f[i,:][pointI] for i in range(3)])
else:
+ tr = grid[field]
+ if tr.size == 1: # dx, dy, dz, cellvolume
+ tr = tr * na.ones(grid.ActiveDimensions, dtype='float64')
+ if len(grid.Children) == 0 and grid.OverlappingSiblings is None \
+ and self._is_fully_enclosed(grid):
+ return tr.ravel()
pointI = self._get_point_indices(grid)
- if grid[field].size == 1: # dx, dy, dz, cellvolume
- t = grid[field] * na.ones(grid.ActiveDimensions, dtype='float64')
- return t[pointI].ravel()
- return grid[field][pointI].ravel()
+ return tr[pointI].ravel()
def _flush_data_to_grids(self, field, default_val, dtype='float32'):
"""
@@ -2479,12 +2483,19 @@
format. Suitable for loading into meshlab.
rescale : bool, optional
If true, the vertices will be rescaled within their min/max.
+ sample_values : string, optional
+ Any field whose value should be extracted at the center of each
+ triangle.
Returns
-------
verts : array of floats
The array of vertices, x,y,z. Taken in threes, these are the
triangle vertices.
+ samples : array of floats
+ If `sample_values` is specified, this will be returned and will
+ contain the values of the field specified at the center of each
+ triangle.
References
----------
@@ -2504,9 +2515,7 @@
"""
verts = []
samples = []
- pb = get_pbar("Extracting Isocontours", len(self._grids))
- for i, g in enumerate(self._grids):
- pb.update(i)
+ for i, g in enumerate(self._get_grid_objs()):
mask = self._get_cut_mask(g) * g.child_mask
vals = g.get_vertex_centered_data(field)
if sample_values is not None:
@@ -2519,20 +2528,24 @@
my_verts, svals = my_verts
samples.append(svals)
verts.append(my_verts)
- pb.finish()
- verts = na.concatenate(verts)
+ verts = na.concatenate(verts).transpose()
+ verts = self.comm.par_combine_object(verts, op='cat', datatype='array')
+ verts = verts.transpose()
if sample_values is not None:
samples = na.concatenate(samples)
+ samples = self.comm.par_combine_object(samples, op='cat',
+ datatype='array')
if rescale:
mi = na.min(verts, axis=0)
ma = na.max(verts, axis=0)
verts = (verts - mi) / (ma - mi).max()
- if filename is not None:
+ if filename is not None and self.comm.rank == 0:
f = open(filename, "w")
for v1 in verts:
f.write("v %0.16e %0.16e %0.16e\n" % (v1[0], v1[1], v1[2]))
for i in range(len(verts)/3):
f.write("f %s %s %s\n" % (i*3+1, i*3+2, i*3+3))
+ f.close()
if sample_values is not None:
return verts, samples
return verts
@@ -2602,7 +2615,7 @@
... "x-velocity", "y-velocity", "z-velocity", "Metal_Density")
"""
flux = 0.0
- for g in self._grids:
+ for g in self._get_grid_objs():
mask = self._get_cut_mask(g) * g.child_mask
vals = g.get_vertex_centered_data(field)
if fluxing_field is None:
@@ -2613,6 +2626,7 @@
[field_x, field_y, field_z]]
flux += march_cubes_grid_flux(value, vals, xv, yv, zv,
ff, mask, g.LeftEdge, g.dds)
+ flux = self.comm.mpi_allreduce(flux, op="sum")
return flux
def extract_connected_sets(self, field, num_levels, min_val, max_val,
diff -r 8608363b3d609d754c9f27a01e717dccc09b8ba5 -r f9e18f610a3ff3fa3eb5463277aad44ca6b2a8d4 yt/frontends/nyx/fields.py
--- a/yt/frontends/nyx/fields.py
+++ b/yt/frontends/nyx/fields.py
@@ -46,13 +46,13 @@
# Density
add_field("density", function=lambda a, b: None, take_log=True,
validators=[ValidateDataField("density")],
- units=r"\rm{g}} / \rm{cm}^3",
- projected_units =r"\rm{g}} / \rm{cm}^2")
-nyx_fields["density"]._projected_units =r"\rm{g}} / \rm{cm}^2"
+ units=r"\rm{g} / \rm{cm}^3",
+ projected_units =r"\rm{g} / \rm{cm}^2")
+nyx_fields["density"]._projected_units =r"\rm{g} / \rm{cm}^2"
add_field("Density", function=lambda a, b: b["density"], take_log=True,
- units=r"\rm{g}} / \rm{cm}^3",
- projected_units =r"\rm{g}} / \rm{cm}^2")
+ units=r"\rm{g} / \rm{cm}^3",
+ projected_units =r"\rm{g} / \rm{cm}^2")
# Particle mass in units of $ M_{\odot}
def _convertParticleMassMsun(data):
@@ -64,8 +64,8 @@
particle_type=True, convert_function=_convertParticleMassMsun, take_log=True, units=r"\rm{M_{\odot}}")
add_field("Dark_Matter_Density", function=lambda a, b: b["particle_mass_density"], take_log=True,
- units=r"\rm{g}} / \rm{cm}^3",particle_type=True,
- projected_units =r"\rm{g}} / \rm{cm}^2")
+ units=r"\rm{g} / \rm{cm}^3",particle_type=True,
+ projected_units =r"\rm{g} / \rm{cm}^2")
# Energy Density
diff -r 8608363b3d609d754c9f27a01e717dccc09b8ba5 -r f9e18f610a3ff3fa3eb5463277aad44ca6b2a8d4 yt/frontends/nyx/io.py
--- a/yt/frontends/nyx/io.py
+++ b/yt/frontends/nyx/io.py
@@ -28,7 +28,7 @@
import os
import numpy as na
-from yt.utilities.amr_utils import read_castro_particles
+from yt.utilities.amr_utils import read_castro_particles, read_and_seek
from yt.utilities.io_handler import BaseIOHandler
from definitions import fab_header_pattern, nyx_particle_field_names, \
@@ -57,80 +57,24 @@
if field in nyx_particle_field_names:
return self._read_particle_field(grid, field)
filen = os.path.expanduser(grid.filename[field])
- off = grid._offset[field]
- inFile = open(filen, 'rb')
- inFile.seek(off)
- header = inFile.readline()
- header.strip()
-
- """
- if grid._paranoid:
- mylog.warn("Castro Native reader: Paranoid read mode.")
- header_re = re.compile(fab_header_pattern)
- bytesPerReal, endian, start, stop, centerType, nComponents = \
- headerRe.search(header).groups()
-
- # we will build up a dtype string, starting with endian.
- # @todo: this code is ugly.
- bytesPerReal = int(bytesPerReal)
- if bytesPerReal == int(endian[0]):
- dtype = '<'
- elif bytesPerReal == int(endian[-1]):
- dtype = '>'
- else:
- raise ValueError("FAB header is neither big nor little endian. Perhaps the file is corrupt?")
-
- dtype += ('f%i' % bytesPerReal) # always a floating point
-
- # determine size of FAB
- start = na.array(map(int, start.split(',')))
- stop = na.array(map(int, stop.split(',')))
-
- gridSize = stop - start + 1
-
- error_count = 0
- if (start != grid.start).any():
- print "Paranoia Error: Cell_H and %s do not agree on grid start." % grid.filename
- error_count += 1
- if (stop != grid.stop).any():
- print "Paranoia Error: Cell_H and %s do not agree on grid stop." % grid.filename
- error_count += 1
- if (gridSize != grid.ActiveDimensions).any():
- print "Paranoia Error: Cell_H and %s do not agree on grid dimensions." % grid.filename
- error_count += 1
- if bytesPerReal != grid.hierarchy._bytesPerReal:
- print "Paranoia Error: Cell_H and %s do not agree on bytes per real number." % grid.filename
- error_count += 1
- if (bytesPerReal == grid.hierarchy._bytesPerReal and dtype != grid.hierarchy._dtype):
- print "Paranoia Error: Cell_H and %s do not agree on endianness." % grid.filename
- error_count += 1
-
- if error_count > 0:
- raise RunTimeError("Paranoia unveiled %i differences between Cell_H and %s." % (error_count, grid.filename))
- else:
- """
- start = grid.start_index
- stop = grid.stop_index
- dtype = grid.hierarchy._dtype
+ offset1 = grid._offset[field]
+ # one field has nElements * bytesPerReal bytes and is located
+ # nElements * bytesPerReal * field_index from the offset location
bytesPerReal = grid.hierarchy._bytesPerReal
+ fieldname = yt_to_nyx_fields_dict.get(field, field)
+ field_index = grid.field_indexes[fieldname]
nElements = grid.ActiveDimensions.prod()
+ offset2 = int(nElements*bytesPerReal*field_index)
- # one field has nElements * bytesPerReal bytes and is located
- # nElements * bytesPerReal * field_index from the offset location
- if yt_to_nyx_fields_dict.has_key(field):
- fieldname = yt_to_nyx_fields_dict[field]
- else:
- fieldname = field
- field_index = grid.field_indexes[fieldname]
- inFile.seek(int(nElements*bytesPerReal*field_index),1)
- field = na.fromfile(inFile, count=nElements, dtype=dtype)
- field = field.reshape(grid.ActiveDimensions[::-1]).swapaxes(0,2)
+ dtype = grid.hierarchy._dtype
+ field = na.empty(nElements, dtype=grid.hierarchy._dtype)
+ read_and_seek(filen, offset1, offset2, field, nElements * bytesPerReal)
+ field = field.reshape(grid.ActiveDimensions, order='F')
# @todo: we can/should also check against the max and min in the header
# file
- inFile.close()
return field
def _read_data_slice(self, grid, field, axis, coord):
diff -r 8608363b3d609d754c9f27a01e717dccc09b8ba5 -r f9e18f610a3ff3fa3eb5463277aad44ca6b2a8d4 yt/frontends/orion/io.py
--- a/yt/frontends/orion/io.py
+++ b/yt/frontends/orion/io.py
@@ -111,7 +111,7 @@
field_index = grid.field_indexes[fieldname]
inFile.seek(int(nElements*bytesPerReal*field_index),1)
field = na.fromfile(inFile,count=nElements,dtype=dtype)
- field = field.reshape(grid.ActiveDimensions[::-1]).swapaxes(0,2)
+ field = field.reshape(grid.ActiveDimensions, order='F')
# we can/should also check against the max and min in the header file
diff -r 8608363b3d609d754c9f27a01e717dccc09b8ba5 -r f9e18f610a3ff3fa3eb5463277aad44ca6b2a8d4 yt/utilities/_amr_utils/fortran_reader.pyx
--- a/yt/utilities/_amr_utils/fortran_reader.pyx
+++ b/yt/utilities/_amr_utils/fortran_reader.pyx
@@ -28,6 +28,7 @@
cimport cython
from stdio cimport fopen, fclose, FILE
+cimport libc.stdlib as stdlib
#cdef inline int imax(int i0, int i1):
#if i0 > i1: return i0
@@ -48,6 +49,21 @@
int fseek(FILE *stream, long offset, int whence)
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
long ftell(FILE *stream)
+ char *fgets(char *s, int size, FILE *stream)
+
+ at cython.boundscheck(False)
+ at cython.wraparound(False)
+def read_and_seek(char *filename, int offset1, int offset2,
+ np.ndarray buffer, int bytes):
+ cdef FILE *f = fopen(filename, "rb")
+ cdef void *buf = <void *> buffer.data
+ cdef char line[1024]
+ cdef size_t n = 1023
+ fseek(f, offset1, SEEK_SET)
+ fgets(line, n, f)
+ fseek(f, offset2, SEEK_CUR)
+ fread(buf, 1, bytes, f)
+ fclose(f)
@cython.boundscheck(False)
@cython.wraparound(False)
Repository URL: https://bitbucket.org/yt_analysis/yt/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
More information about the yt-svn
mailing list