#606 Sphere Voxelization

Merged Tommy Waltmann tommy-waltmann Pseudo commit used to compare (37abafd...dea8fbf)
Missing base report.

Unable to compare commits because the base of the pull request did not upload a coverage report.

Changes found in between 37abafd...dea8fbf (pseudo...base) which prevent comparing this pull request.


@@ -190,12 +190,12 @@
Loading
190 190
    the grid cell from the center of the Gaussian. The resulting data is a
191 191
    regular grid of particle densities that can be used in standard algorithms
192 192
    requiring evenly spaced point, such as Fast Fourier Transforms. The
193 -
    dimensions of the image (grid) are set in the constructor, and can either
194 -
    be set equally for all dimensions or for each dimension independently.
193 +
    dimensions of the grid are set in the constructor, and can either be set
194 +
    equally for all dimensions or for each dimension independently.
195 195
196 196
    Args:
197 -
        width (int or list or tuple):
198 -
            The number of bins to make the image in each direction (identical
197 +
        width (int or Sequence[int]):
198 +
            The number of bins to make the grid in each dimension (identical
199 199
            in all dimensions if a single integer value is provided).
200 200
        r_max (float):
201 201
            Distance over which to blur.
@@ -244,7 +244,7 @@
Loading
244 244
    @_Compute._computed_property
245 245
    def density(self):
246 246
        """(:math:`w_x`, :math:`w_y`, :math:`w_z`) :class:`numpy.ndarray`: The
247 -
        image grid with the Gaussian density."""
247 +
        grid with the Gaussian density contributions from each point."""
248 248
        if self.box.is2D:
249 249
            return np.squeeze(freud.util.make_managed_numpy_array(
250 250
                &self.thisptr.getDensity(), freud.util.arr_type_t.FLOAT))
@@ -264,9 +264,8 @@
Loading
264 264
265 265
    @property
266 266
    def width(self):
267 -
        """int or list or tuple: The number of bins to make the image in each
268 -
        direction (identical in all dimensions if a single integer value is
269 -
        provided)."""
267 +
        """tuple[int]: The number of bins in the grid in each dimension
268 +
        (identical in all dimensions if a single integer value is provided)."""
270 269
        cdef vec3[uint] width = self.thisptr.getWidth()
271 270
        return (width.x, width.y, width.z)
272 271
@@ -301,6 +300,115 @@
Loading
301 300
            return None
302 301
303 302
303 +
cdef class SphereVoxelization(_Compute):
304 +
    R"""Computes a grid of voxels occupied by spheres.
305 +
306 +
    This class constructs a grid of voxels. From a given set of points and a
307 +
    desired radius, a set of spheres are created. The voxels are assigned a
308 +
    value of 1 if their center is contained in one or more spheres and 0
309 +
    otherwise. The dimensions of the grid are set in the constructor, and can
310 +
    either be set equally for all dimensions or for each dimension
311 +
    independently.
312 +
313 +
    Args:
314 +
        width (int or Sequence[int]):
315 +
            The number of bins to make the grid in each dimension (identical
316 +
            in all dimensions if a single integer value is provided).
317 +
        r_max (float):
318 +
            Sphere radius.
319 +
    """
320 +
    cdef freud._density.SphereVoxelization * thisptr
321 +
322 +
    def __cinit__(self, width, r_max):
323 +
        cdef vec3[uint] width_vector
324 +
        if isinstance(width, int):
325 +
            width_vector = vec3[uint](width, width, width)
326 +
        elif isinstance(width, Sequence) and len(width) == 2:
327 +
            width_vector = vec3[uint](width[0], width[1], 1)
328 +
        elif isinstance(width, Sequence) and len(width) == 3:
329 +
            width_vector = vec3[uint](width[0], width[1], width[2])
330 +
        else:
331 +
            raise ValueError("The width must be either a number of bins or a "
332 +
                             "sequence indicating the widths in each spatial "
333 +
                             "dimension (length 2 in 2D, length 3 in 3D).")
334 +
335 +
        self.thisptr = new freud._density.SphereVoxelization(width_vector,
336 +
                                                             r_max)
337 +
338 +
    def __dealloc__(self):
339 +
        del self.thisptr
340 +
341 +
    @_Compute._computed_property
342 +
    def box(self):
343 +
        """:class:`freud.box.Box`: Box used in the calculation."""
344 +
        return freud.box.BoxFromCPP(self.thisptr.getBox())
345 +
346 +
    def compute(self, system):
347 +
        R"""Calculates the voxelization of spheres about the specified points.
348 +
349 +
        Args:
350 +
            system:
351 +
                Any object that is a valid argument to
352 +
                :class:`freud.locality.NeighborQuery.from_system`.
353 +
        """
354 +
        cdef freud.locality.NeighborQuery nq = \
355 +
            freud.locality.NeighborQuery.from_system(system)
356 +
        self.thisptr.compute(nq.get_ptr())
357 +
        return self
358 +
359 +
    @_Compute._computed_property
360 +
    def voxels(self):
361 +
        """(:math:`w_x`, :math:`w_y`, :math:`w_z`) :class:`numpy.ndarray`: The
362 +
        voxel grid indicating overlap with the computed spheres."""
363 +
        data = freud.util.make_managed_numpy_array(
364 +
            &self.thisptr.getVoxels(), freud.util.arr_type_t.UNSIGNED_INT)
365 +
        if self.box.is2D:
366 +
            return np.squeeze(data)
367 +
        else:
368 +
            return data
369 +
370 +
    @property
371 +
    def r_max(self):
372 +
        """float: Sphere radius used for voxelization."""
373 +
        return self.thisptr.getRMax()
374 +
375 +
    @property
376 +
    def width(self):
377 +
        """tuple[int]: The number of bins in the grid in each dimension
378 +
        (identical in all dimensions if a single integer value is provided)."""
379 +
        cdef vec3[uint] width = self.thisptr.getWidth()
380 +
        return (width.x, width.y, width.z)
381 +
382 +
    def __repr__(self):
383 +
        return ("freud.density.{cls}({width}, {r_max})").format(
384 +
            cls=type(self).__name__,
385 +
            width=self.width,
386 +
            r_max=self.r_max)
387 +
388 +
    def plot(self, ax=None):
389 +
        """Plot voxelization.
390 +
391 +
        Args:
392 +
            ax (:class:`matplotlib.axes.Axes`, optional): Axis to plot on. If
393 +
                :code:`None`, make a new figure and axis.
394 +
                (Default value = :code:`None`)
395 +
396 +
        Returns:
397 +
            (:class:`matplotlib.axes.Axes`): Axis with the plot.
398 +
        """
399 +
        import freud.plot
400 +
        if not self.box.is2D:
401 +
            return None
402 +
        return freud.plot.density_plot(self.voxels, self.box, ax=ax)
403 +
404 +
    def _repr_png_(self):
405 +
        try:
406 +
            import freud.plot
407 +
            return freud.plot._ax_to_bytes(self.plot())
408 +
        except (AttributeError, ImportError):
409 +
            return None
410 +
411 +
304 412
cdef class LocalDensity(_PairCompute):
305 413
    R"""Computes the local density around a particle.
306 414

Unable to process changes.

No base report to compare against.

61 Commits

Hiding 3 contexual commits
+41
+42
-1
Hiding 3 contexual commits Hiding 25 contexual commits
-32
+1
-33
Hiding 3 contexual commits
Hiding 1 contexual commits Hiding 1 contexual commits
Hiding 3 contexual commits
+1
+1
+28
+29
-1
Hiding 10 contexual commits
+3
-30
-1
+34
Pull Request Base Commit
Files Coverage
freud 92.96%
Project Totals (16 files) 92.96%
Loading