[yt-svn] commit/yt: xarthisius: Merged in MatthewTurk/yt (pull request #1983)
commits-noreply at bitbucket.org
commits-noreply at bitbucket.org
Wed Feb 17 09:16:41 PST 2016
1 new commit in yt:
https://bitbucket.org/yt_analysis/yt/commits/28196e94219e/
Changeset: 28196e94219e
Branch: yt
User: xarthisius
Date: 2016-02-17 17:16:32+00:00
Summary: Merged in MatthewTurk/yt (pull request #1983)
Fix the particle deposit memoryview PR
Affected #: 6 files
diff -r 0f22947ebba119f8039037937270e295d95224a7 -r 28196e94219e1203f78a3ba94272d49e79deaee4 yt/data_objects/construction_data_containers.py
--- a/yt/data_objects/construction_data_containers.py
+++ b/yt/data_objects/construction_data_containers.py
@@ -702,11 +702,11 @@
if cls is None:
raise YTParticleDepositionNotImplemented(method)
# We allocate number of zones, not number of octs
- op = cls(self.ActiveDimensions.prod(), kernel_name)
+ op = cls(self.ActiveDimensions, kernel_name)
op.initialize()
op.process_grid(self, positions, fields)
vals = op.finalize()
- return vals.reshape(self.ActiveDimensions, order="C")
+ return vals.copy(order="C")
def write_to_gdf(self, gdf_path, fields, nprocs=1, field_units=None,
**kwargs):
diff -r 0f22947ebba119f8039037937270e295d95224a7 -r 28196e94219e1203f78a3ba94272d49e79deaee4 yt/data_objects/grid_patch.py
--- a/yt/data_objects/grid_patch.py
+++ b/yt/data_objects/grid_patch.py
@@ -327,12 +327,13 @@
if cls is None:
raise YTParticleDepositionNotImplemented(method)
# We allocate number of zones, not number of octs
- op = cls(self.ActiveDimensions.prod(), kernel_name)
+ # Everything inside this is fortran ordered, so we reverse it here.
+ op = cls(tuple(self.ActiveDimensions)[::-1], kernel_name)
op.initialize()
op.process_grid(self, positions, fields)
vals = op.finalize()
if vals is None: return
- return vals.reshape(self.ActiveDimensions, order="C")
+ return vals.transpose() # Fortran-ordered, so transpose.
def select_blocks(self, selector):
mask = self._get_selector_mask(selector)
diff -r 0f22947ebba119f8039037937270e295d95224a7 -r 28196e94219e1203f78a3ba94272d49e79deaee4 yt/frontends/artio/_artio_caller.pyx
--- a/yt/frontends/artio/_artio_caller.pyx
+++ b/yt/frontends/artio/_artio_caller.pyx
@@ -15,6 +15,7 @@
from libc.stdlib cimport malloc, free
from libc.string cimport memcpy
import data_structures
+from yt.utilities.lib.misc_utilities import OnceIndirect
cdef extern from "platform_dep.h":
void *alloca(int)
@@ -1554,6 +1555,9 @@
if fields is None:
fields = []
nf = len(fields)
+ cdef np.float64_t[::cython.view.indirect, ::1] field_pointers
+ if nf > 0: field_pointers = OnceIndirect(fields)
+ cdef np.float64_t[:] field_vals = np.empty(nf, dtype="float64")
cdef np.ndarray[np.uint8_t, ndim=1, cast=True] mask
mask = self.mask(selector, -1)
cdef np.ndarray[np.int64_t, ndim=1] domain_ind
@@ -1568,17 +1572,9 @@
continue
domain_ind[sfc - self.sfc_start] = j
j += 1
- cdef np.float64_t **field_pointers
- cdef np.float64_t *field_vals
cdef np.float64_t pos[3]
cdef np.float64_t left_edge[3]
cdef int coords[3]
- cdef np.ndarray[np.float64_t, ndim=1] tarr
- field_pointers = <np.float64_t**> alloca(sizeof(np.float64_t *) * nf)
- field_vals = <np.float64_t*>alloca(sizeof(np.float64_t) * nf)
- for i in range(nf):
- tarr = fields[i]
- field_pointers[i] = <np.float64_t *> tarr.data
cdef int dims[3]
dims[0] = dims[1] = dims[2] = 1
cdef np.int64_t offset, moff
diff -r 0f22947ebba119f8039037937270e295d95224a7 -r 28196e94219e1203f78a3ba94272d49e79deaee4 yt/geometry/particle_deposit.pxd
--- a/yt/geometry/particle_deposit.pxd
+++ b/yt/geometry/particle_deposit.pxd
@@ -138,5 +138,5 @@
cdef public int update_values
cdef void process(self, int dim[3], np.float64_t left_edge[3],
np.float64_t dds[3], np.int64_t offset,
- np.float64_t ppos[3], np.float64_t *fields,
+ np.float64_t ppos[3], np.float64_t[:] fields,
np.int64_t domain_ind)
diff -r 0f22947ebba119f8039037937270e295d95224a7 -r 28196e94219e1203f78a3ba94272d49e79deaee4 yt/geometry/particle_deposit.pyx
--- a/yt/geometry/particle_deposit.pyx
+++ b/yt/geometry/particle_deposit.pyx
@@ -19,9 +19,22 @@
from libc.stdlib cimport malloc, free
cimport cython
from libc.math cimport sqrt
+from cpython cimport PyObject
+from fp_utils cimport *
from oct_container cimport Oct, OctAllocationContainer, \
OctreeContainer, OctInfo
+from cpython.array cimport array, clone
+from cython.view cimport memoryview as cymemview
+from yt.utilities.lib.misc_utilities import OnceIndirect
+
+cdef append_axes(np.ndarray arr, int naxes):
+ if arr.ndim == naxes:
+ return arr
+ # Avoid copies
+ arr2 = arr.view()
+ arr2.shape = arr2.shape + (1,) * (naxes - arr2.ndim)
+ return arr2
cdef class ParticleDepositOperation:
def __init__(self, nvals, kernel_name):
@@ -46,15 +59,10 @@
if fields is None:
fields = []
nf = len(fields)
- cdef np.float64_t **field_pointers
- cdef np.float64_t *field_vals
+ cdef np.float64_t[::cython.view.indirect, ::1] field_pointers
+ if nf > 0: field_pointers = OnceIndirect(fields)
cdef np.float64_t pos[3]
- cdef np.ndarray[np.float64_t, ndim=1] tarr
- field_pointers = <np.float64_t**> alloca(sizeof(np.float64_t *) * nf)
- field_vals = <np.float64_t*>alloca(sizeof(np.float64_t) * nf)
- for i in range(nf):
- tarr = fields[i]
- field_pointers[i] = <np.float64_t *> tarr.data
+ cdef np.float64_t[:] field_vals = np.empty(nf, dtype="float64")
cdef int dims[3]
dims[0] = dims[1] = dims[2] = (1 << octree.oref)
cdef int nz = dims[0] * dims[1] * dims[2]
@@ -66,7 +74,7 @@
for i in range(positions.shape[0]):
# We should check if particle remains inside the Oct here
for j in range(nf):
- field_vals[j] = field_pointers[j][i]
+ field_vals[j] = field_pointers[j,i]
for j in range(3):
pos[j] = positions[i, j]
# This line should be modified to have it return the index into an
@@ -89,7 +97,7 @@
if oct == NULL or (domain_id > 0 and oct.domain != domain_id):
continue
# Note that this has to be our local index, not our in-file index.
- offset = dom_ind[oct.domain_ind - moff] * nz
+ offset = dom_ind[oct.domain_ind - moff]
if offset < 0: continue
# Check that we found the oct ...
self.process(dims, oi.left_edge, oi.dds,
@@ -107,16 +115,11 @@
if fields is None:
fields = []
nf = len(fields)
- cdef np.float64_t **field_pointers
- cdef np.float64_t *field_vals
+ cdef np.float64_t[:] field_vals = np.empty(nf, dtype="float64")
+ cdef np.float64_t[::cython.view.indirect, ::1] field_pointers
+ if nf > 0: field_pointers = OnceIndirect(fields)
cdef np.float64_t pos[3]
- cdef np.ndarray[np.float64_t, ndim=1] tarr
- field_pointers = <np.float64_t**> alloca(sizeof(np.float64_t *) * nf)
- field_vals = <np.float64_t*>alloca(sizeof(np.float64_t) * nf)
cdef np.int64_t gid = getattr(gobj, "id", -1)
- for i in range(nf):
- tarr = fields[i]
- field_pointers[i] = <np.float64_t *> tarr.data
cdef np.float64_t dds[3]
cdef np.float64_t left_edge[3]
cdef int dims[3]
@@ -127,7 +130,7 @@
for i in range(positions.shape[0]):
# Now we process
for j in range(nf):
- field_vals[j] = field_pointers[j][i]
+ field_vals[j] = field_pointers[j,i]
for j in range(3):
pos[j] = positions[i, j]
self.process(dims, left_edge, dds, 0, pos, field_vals, gid)
@@ -137,19 +140,16 @@
cdef void process(self, int dim[3], np.float64_t left_edge[3],
np.float64_t dds[3], np.int64_t offset,
- np.float64_t ppos[3], np.float64_t *fields,
+ np.float64_t ppos[3], np.float64_t[:] fields,
np.int64_t domain_ind):
raise NotImplementedError
cdef class CountParticles(ParticleDepositOperation):
- cdef np.int64_t *count # float, for ease
- cdef public object ocount
+ cdef np.int64_t[:,:,:,:] count
def initialize(self):
# Create a numpy array accessible to python
- self.ocount = np.zeros(self.nvals, dtype="int64", order='F')
- cdef np.ndarray arr = self.ocount
- # alias the C-view for use in cython
- self.count = <np.int64_t*> arr.data
+ self.count = append_axes(
+ np.zeros(self.nvals, dtype="int64", order='F'), 4)
@cython.cdivision(True)
cdef void process(self, int dim[3],
@@ -157,7 +157,7 @@
np.float64_t dds[3],
np.int64_t offset, # offset into IO field
np.float64_t ppos[3], # this particle's position
- np.float64_t *fields,
+ np.float64_t[:] fields,
np.int64_t domain_ind
):
# here we do our thing; this is the kernel
@@ -165,10 +165,12 @@
cdef int i
for i in range(3):
ii[i] = <int>((ppos[i] - left_edge[i])/dds[i])
- self.count[gind(ii[0], ii[1], ii[2], dim) + offset] += 1
+ self.count[ii[2], ii[1], ii[0], offset] += 1
def finalize(self):
- return self.ocount.astype('f8')
+ arr = np.asarray(self.count)
+ arr.shape = self.nvals
+ return arr.astype("float64")
deposit_count = CountParticles
@@ -176,18 +178,14 @@
# Note that this does nothing at the edges. So it will give a poor
# estimate there, and since Octrees are mostly edges, this will be a very
# poor SPH kernel.
- cdef np.float64_t *data
- cdef public object odata
- cdef np.float64_t *temp
- cdef public object otemp
+ cdef np.float64_t[:,:,:,:] data
+ cdef np.float64_t[:,:,:,:] temp
def initialize(self):
- self.odata = np.zeros(self.nvals, dtype="float64", order='F')
- cdef np.ndarray arr = self.odata
- self.data = <np.float64_t*> arr.data
- self.otemp = np.zeros(self.nvals, dtype="float64", order='F')
- arr = self.otemp
- self.temp = <np.float64_t*> arr.data
+ self.data = append_axes(
+ np.zeros(self.nvals, dtype="float64", order='F'), 4)
+ self.temp = append_axes(
+ np.zeros(self.nvals, dtype="float64", order='F'), 4)
@cython.cdivision(True)
cdef void process(self, int dim[3],
@@ -195,7 +193,7 @@
np.float64_t dds[3],
np.int64_t offset,
np.float64_t ppos[3],
- np.float64_t *fields,
+ np.float64_t[:] fields,
np.int64_t domain_ind
):
cdef int ii[3]
@@ -227,14 +225,14 @@
dist = idist[0] + idist[1] + idist[2]
# Calculate distance in multiples of the smoothing length
dist = sqrt(dist) / fields[0]
- self.temp[gind(i,j,k,dim) + offset] = self.sph_kernel(dist)
- kernel_sum += self.temp[gind(i,j,k,dim) + offset]
+ self.temp[k,j,i,offset] = self.sph_kernel(dist)
+ kernel_sum += self.temp[k,j,i,offset]
# Having found the kernel, deposit accordingly into gdata
for i from ib0[0] <= i <= ib1[0]:
for j from ib0[1] <= j <= ib1[1]:
for k from ib0[2] <= k <= ib1[2]:
- dist = self.temp[gind(i,j,k,dim) + offset] / kernel_sum
- self.data[gind(i,j,k,dim) + offset] += fields[1] * dist
+ dist = self.temp[k,j,i,offset] / kernel_sum
+ self.data[k,j,i,offset] += fields[1] * dist
def finalize(self):
return self.odata
@@ -242,12 +240,10 @@
deposit_simple_smooth = SimpleSmooth
cdef class SumParticleField(ParticleDepositOperation):
- cdef np.float64_t *sum
- cdef public object osum
+ cdef np.float64_t[:,:,:,:] sum
def initialize(self):
- self.osum = np.zeros(self.nvals, dtype="float64", order='F')
- cdef np.ndarray arr = self.osum
- self.sum = <np.float64_t*> arr.data
+ self.sum = append_axes(
+ np.zeros(self.nvals, dtype="float64", order='F'), 4)
@cython.cdivision(True)
cdef void process(self, int dim[3],
@@ -255,18 +251,20 @@
np.float64_t dds[3],
np.int64_t offset,
np.float64_t ppos[3],
- np.float64_t *fields,
+ np.float64_t[:] fields,
np.int64_t domain_ind
):
cdef int ii[3]
cdef int i
for i in range(3):
ii[i] = <int>((ppos[i] - left_edge[i]) / dds[i])
- self.sum[gind(ii[0], ii[1], ii[2], dim) + offset] += fields[0]
+ self.sum[ii[2], ii[1], ii[0], offset] += fields[0]
return
def finalize(self):
- return self.osum
+ sum = np.asarray(self.sum)
+ sum.shape = self.nvals
+ return sum
deposit_sum = SumParticleField
@@ -274,28 +272,20 @@
# Thanks to Britton and MJ Turk for the link
# to a single-pass STD
# http://www.cs.berkeley.edu/~mhoemmen/cs194/Tutorials/variance.pdf
- cdef np.float64_t *mk
- cdef np.float64_t *qk
- cdef np.float64_t *i
- cdef public object omk
- cdef public object oqk
- cdef public object oi
+ cdef np.float64_t[:,:,:,:] mk
+ cdef np.float64_t[:,:,:,:] qk
+ cdef np.float64_t[:,:,:,:] i
def initialize(self):
# we do this in a single pass, but need two scalar
# per cell, M_k, and Q_k and also the number of particles
# deposited into each one
# the M_k term
- self.omk= np.zeros(self.nvals, dtype="float64", order='F')
- cdef np.ndarray omkarr= self.omk
- self.mk= <np.float64_t*> omkarr.data
- # the Q_k term
- self.oqk= np.zeros(self.nvals, dtype="float64", order='F')
- cdef np.ndarray oqkarr= self.oqk
- self.qk= <np.float64_t*> oqkarr.data
- # particle count
- self.oi = np.zeros(self.nvals, dtype="float64", order='F')
- cdef np.ndarray oiarr = self.oi
- self.i = <np.float64_t*> oiarr.data
+ self.mk = append_axes(
+ np.zeros(self.nvals, dtype="float64", order='F'), 4)
+ self.qk = append_axes(
+ np.zeros(self.nvals, dtype="float64", order='F'), 4)
+ self.i = append_axes(
+ np.zeros(self.nvals, dtype="float64", order='F'), 4)
@cython.cdivision(True)
cdef void process(self, int dim[3],
@@ -303,7 +293,7 @@
np.float64_t dds[3],
np.int64_t offset,
np.float64_t ppos[3],
- np.float64_t *fields,
+ np.float64_t[:] fields,
np.int64_t domain_ind
):
cdef int ii[3]
@@ -311,35 +301,36 @@
cdef float k, mk, qk
for i in range(3):
ii[i] = <int>((ppos[i] - left_edge[i])/dds[i])
- cell_index = gind(ii[0], ii[1], ii[2], dim) + offset
- k = self.i[cell_index]
- mk = self.mk[cell_index]
- qk = self.qk[cell_index]
+ k = self.i[ii[2], ii[1], ii[0], offset]
+ mk = self.mk[ii[2], ii[1], ii[0], offset]
+ qk = self.qk[ii[2], ii[1], ii[0], offset]
#print k, mk, qk, cell_index
if k == 0.0:
# Initialize cell values
- self.mk[cell_index] = fields[0]
+ self.mk[ii[2], ii[1], ii[0], offset] = fields[0]
else:
- self.mk[cell_index] = mk + (fields[0] - mk) / k
- self.qk[cell_index] = qk + (k - 1.0) * (fields[0] - mk)**2.0 / k
- self.i[cell_index] += 1
+ self.mk[ii[2], ii[1], ii[0], offset] = mk + (fields[0] - mk) / k
+ self.qk[ii[2], ii[1], ii[0], offset] = \
+ qk + (k - 1.0) * (fields[0] - mk)**2.0 / k
+ self.i[ii[2], ii[1], ii[0], offset] += 1
def finalize(self):
# This is the standard variance
# if we want sample variance divide by (self.oi - 1.0)
- std2 = self.oqk / self.oi
- std2[self.oi == 0.0] = 0.0
+ i = np.asarray(self.i)
+ std2 = np.asarray(self.qk) / i
+ std2[i == 0.0] = 0.0
+ std2.shape = self.nvals
return np.sqrt(std2)
deposit_std = StdParticleField
cdef class CICDeposit(ParticleDepositOperation):
- cdef np.float64_t *field
+ cdef np.float64_t[:,:,:,:] field
cdef public object ofield
def initialize(self):
- self.ofield = np.zeros(self.nvals, dtype="float64", order='F')
- cdef np.ndarray arr = self.ofield
- self.field = <np.float64_t *> arr.data
+ self.field = append_axes(
+ np.zeros(self.nvals, dtype="float64", order='F'), 4)
@cython.cdivision(True)
cdef void process(self, int dim[3],
@@ -347,7 +338,7 @@
np.float64_t dds[3],
np.int64_t offset, # offset into IO field
np.float64_t ppos[3], # this particle's position
- np.float64_t *fields,
+ np.float64_t[:] fields,
np.int64_t domain_ind
):
@@ -372,29 +363,26 @@
for i in range(2):
for j in range(2):
for k in range(2):
- ii = gind(ind[0] - i, ind[1] - j, ind[2] - k, dim) + offset
- self.field[ii] += fields[0]*rdds[0][i]*rdds[1][j]*rdds[2][k]
+ self.field[ind[2] - k, ind[1] - j, ind[0] - i, offset] += \
+ fields[0]*rdds[0][i]*rdds[1][j]*rdds[2][k]
def finalize(self):
- return self.ofield
+ rv = np.asarray(self.field)
+ rv.shape = self.nvals
+ return rv
deposit_cic = CICDeposit
cdef class WeightedMeanParticleField(ParticleDepositOperation):
# Deposit both mass * field and mass into two scalars
# then in finalize divide mass * field / mass
- cdef np.float64_t *wf
- cdef public object owf
- cdef np.float64_t *w
- cdef public object ow
+ cdef np.float64_t[:,:,:,:] wf
+ cdef np.float64_t[:,:,:,:] w
def initialize(self):
- self.owf = np.zeros(self.nvals, dtype='float64', order='F')
- cdef np.ndarray wfarr = self.owf
- self.wf = <np.float64_t*> wfarr.data
-
- self.ow = np.zeros(self.nvals, dtype='float64', order='F')
- cdef np.ndarray warr = self.ow
- self.w = <np.float64_t*> warr.data
+ self.wf = append_axes(
+ np.zeros(self.nvals, dtype='float64', order='F'), 4)
+ self.w = append_axes(
+ np.zeros(self.nvals, dtype='float64', order='F'), 4)
@cython.cdivision(True)
cdef void process(self, int dim[3],
@@ -402,18 +390,22 @@
np.float64_t dds[3],
np.int64_t offset,
np.float64_t ppos[3],
- np.float64_t *fields,
+ np.float64_t[:] fields,
np.int64_t domain_ind
):
cdef int ii[3]
cdef int i
for i in range(3):
ii[i] = <int>((ppos[i] - left_edge[i]) / dds[i])
- self.w[ gind(ii[0], ii[1], ii[2], dim) + offset] += fields[1]
- self.wf[gind(ii[0], ii[1], ii[2], dim) + offset] += fields[0] * fields[1]
+ self.w[ii[2], ii[1], ii[0], offset] += fields[1]
+ self.wf[ii[2], ii[1], ii[0], offset] += fields[0] * fields[1]
def finalize(self):
- return self.owf / self.ow
+ wf = np.asarray(self.owf)
+ w = np.asarray(self.ow)
+ rv = wf / w
+ rv.shape = self.nvals
+ return rv
deposit_weighted_mean = WeightedMeanParticleField
@@ -430,7 +422,7 @@
np.float64_t dds[3],
np.int64_t offset,
np.float64_t ppos[3],
- np.float64_t *fields,
+ np.float64_t[:] fields,
np.int64_t domain_ind
):
fields[0] = domain_ind
@@ -441,19 +433,14 @@
deposit_mesh_id = MeshIdentifier
cdef class NNParticleField(ParticleDepositOperation):
- cdef np.float64_t *nnfield
- cdef np.float64_t *distfield
- cdef public object onnfield
- cdef public object odistfield
+ cdef np.float64_t[:,:,:,:] nnfield
+ cdef np.float64_t[:,:,:,:] distfield
def initialize(self):
- self.onnfield = np.zeros(self.nvals, dtype="float64", order='F')
- cdef np.ndarray arr = self.onnfield
- self.nnfield = <np.float64_t*> arr.data
-
- self.odistfield = np.zeros(self.nvals, dtype="float64", order='F')
- self.odistfield[:] = np.inf
- arr = self.odistfield
- self.distfield = <np.float64_t*> arr.data
+ self.nnfield = append_axes(
+ np.zeros(self.nvals, dtype="float64", order='F'), 4)
+ self.distfield = append_axes(
+ np.zeros(self.nvals, dtype="float64", order='F'), 4)
+ self.distfield[:] = np.inf
@cython.cdivision(True)
cdef void process(self, int dim[3],
@@ -461,14 +448,13 @@
np.float64_t dds[3],
np.int64_t offset,
np.float64_t ppos[3],
- np.float64_t *fields,
+ np.float64_t[:] fields,
np.int64_t domain_ind
):
# This one is a bit slow. Every grid cell is going to be iterated
# over, and we're going to deposit particles in it.
cdef int i, j, k
cdef int ii[3]
- cdef np.int64_t ggind
cdef np.float64_t r2
cdef np.float64_t gpos[3]
gpos[0] = left_edge[0] + 0.5 * dds[0]
@@ -477,19 +463,20 @@
for j in range(dim[1]):
gpos[2] = left_edge[2] + 0.5 * dds[2]
for k in range(dim[2]):
- ggind = gind(i, j, k, dim) + offset
r2 = ((ppos[0] - gpos[0])*(ppos[0] - gpos[0]) +
(ppos[1] - gpos[1])*(ppos[1] - gpos[1]) +
(ppos[2] - gpos[2])*(ppos[2] - gpos[2]))
- if r2 < self.distfield[ggind]:
- self.distfield[ggind] = r2
- self.nnfield[ggind] = fields[0]
+ if r2 < self.distfield[k,j,i,offset]:
+ self.distfield[k,j,i,offset] = r2
+ self.nnfield[k,j,i,offset] = fields[0]
gpos[2] += dds[2]
gpos[1] += dds[1]
gpos[0] += dds[0]
return
def finalize(self):
- return self.onnfield
+ nn = np.asarray(self.nnfield)
+ nn.shape = self.nvals
+ return nn
deposit_nearest = NNParticleField
diff -r 0f22947ebba119f8039037937270e295d95224a7 -r 28196e94219e1203f78a3ba94272d49e79deaee4 yt/utilities/lib/misc_utilities.pyx
--- a/yt/utilities/lib/misc_utilities.pyx
+++ b/yt/utilities/lib/misc_utilities.pyx
@@ -22,6 +22,13 @@
from yt.utilities.lib.fp_utils cimport fmin, fmax, i64min, i64max
from yt.geometry.selection_routines cimport _ensure_code
+from libc.stdlib cimport malloc, free
+from libc.string cimport strcmp
+
+from cython.view cimport memoryview
+from cpython cimport buffer
+
+
cdef extern from "stdlib.h":
# NOTE that size_t might not be int
void *alloca(int)
@@ -966,3 +973,128 @@
dest[i,j,k] += dsp * (overlap[0]*overlap[1]*overlap[2])
else:
dest[i,j,k] = dsp
+
+# The OnceIndirect code is from:
+# http://stackoverflow.com/questions/10465091/assembling-a-cython-memoryview-from-numpy-arrays/12991519#12991519
+# This is under the CC-BY-SA license.
+
+cdef class OnceIndirect:
+ cdef object _objects
+ cdef void** buf
+ cdef int ndim
+ cdef int n_rows
+ cdef int buf_len
+ cdef Py_ssize_t* shape
+ cdef Py_ssize_t* strides
+ cdef Py_ssize_t* suboffsets
+ cdef Py_ssize_t itemsize
+ cdef bytes format
+ cdef int is_readonly
+
+ def __cinit__(self, object rows, want_writable=True, want_format=True, allow_indirect=False):
+ """
+ Set want_writable to False if you don't want writable data. (This may
+ prevent copies.)
+ Set want_format to False if your input doesn't support PyBUF_FORMAT (unlikely)
+ Set allow_indirect to True if you are ok with the memoryview being indirect
+ in dimensions other than the first. (This may prevent copies.)
+
+ An example usage:
+
+ cdef double[::cython.view.indirect, ::1] vectors =
+ OnceIndirect([object.vector for object in objects])
+ """
+ demand = buffer.PyBUF_INDIRECT if allow_indirect else buffer.PyBUF_STRIDES
+ if want_writable:
+ demand |= buffer.PyBUF_WRITABLE
+ if want_format:
+ demand |= buffer.PyBUF_FORMAT
+ self._objects = [memoryview(row, demand) for row in rows]
+ self.n_rows = len(self._objects)
+ self.buf_len = sizeof(void*) * self.n_rows
+ self.buf = <void**>malloc(self.buf_len)
+ self.ndim = 1 + self._objects[0].ndim
+ self.shape = <Py_ssize_t*>malloc(sizeof(Py_ssize_t) * self.ndim)
+ self.strides = <Py_ssize_t*>malloc(sizeof(Py_ssize_t) * self.ndim)
+ self.suboffsets = <Py_ssize_t*>malloc(sizeof(Py_ssize_t) * self.ndim)
+
+ cdef memoryview example_obj = self._objects[0]
+ self.itemsize = example_obj.itemsize
+
+ if want_format:
+ self.format = example_obj.view.format
+ else:
+ self.format = None
+ self.is_readonly |= example_obj.view.readonly
+
+ for dim in range(self.ndim):
+ if dim == 0:
+ self.shape[dim] = self.n_rows
+ self.strides[dim] = sizeof(void*)
+ self.suboffsets[dim] = 0
+ else:
+ self.shape[dim] = example_obj.view.shape[dim - 1]
+ self.strides[dim] = example_obj.view.strides[dim - 1]
+ if example_obj.view.suboffsets == NULL:
+ self.suboffsets[dim] = -1
+ else:
+ self.suboffsets[dim] = example_obj.suboffsets[dim - 1]
+
+ cdef memoryview obj
+ cdef int i = 0
+ for obj in self._objects:
+ assert_similar(example_obj, obj)
+ self.buf[i] = obj.view.buf
+ i += 1
+
+ def __getbuffer__(self, Py_buffer* buff, int flags):
+ if (flags & buffer.PyBUF_INDIRECT) != buffer.PyBUF_INDIRECT:
+ raise Exception("don't want to copy data")
+ if flags & buffer.PyBUF_WRITABLE and self.is_readonly:
+ raise Exception("couldn't provide writable, you should have demanded it earlier")
+ if flags & buffer.PyBUF_FORMAT:
+ if self.format is None:
+ raise Exception("couldn't provide format, you should have demanded it earlier")
+ buff.format = self.format
+ else:
+ buff.format = NULL
+
+ buff.buf = <void*>self.buf
+ buff.obj = self
+ buff.len = self.buf_len
+ buff.readonly = self.is_readonly
+ buff.ndim = self.ndim
+ buff.shape = self.shape
+ buff.strides = self.strides
+ buff.suboffsets = self.suboffsets
+ buff.itemsize = self.itemsize
+ buff.internal = NULL
+
+ def __dealloc__(self):
+ free(self.buf)
+ free(self.shape)
+ free(self.strides)
+ free(self.suboffsets)
+
+cdef int assert_similar(memoryview left_, memoryview right_) except -1:
+ cdef Py_buffer left = left_.view
+ cdef Py_buffer right = right_.view
+ assert left.ndim == right.ndim
+ cdef int i
+ for i in range(left.ndim):
+ assert left.shape[i] == right.shape[i], (left_.shape, right_.shape)
+ assert left.strides[i] == right.strides[i], (left_.strides, right_.strides)
+
+ if left.suboffsets == NULL:
+ assert right.suboffsets == NULL, (left_.suboffsets, right_.suboffsets)
+ else:
+ for i in range(left.ndim):
+ assert left.suboffsets[i] == right.suboffsets[i], (left_.suboffsets, right_.suboffsets)
+
+ if left.format == NULL:
+ assert right.format == NULL, (bytes(left.format), bytes(right.format))
+ else:
+ #alternatively, compare as Python strings:
+ #assert bytes(left.format) == bytes(right.format)
+ assert strcmp(left.format, right.format) == 0, (bytes(left.format), bytes(right.format))
+ return 0
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