DEMutilities.postprocessing.analysistools.spatial. clusters

The clusters module implements a time-efficient algorithm to analyze (segment) clusters of spheres defined by positions x and radii r. This implementation is based upon an ‘infection’ algorithm, simulating an evolutionary progression, in which spheres are each assigned a certain ‘infect_id’, which is updated in a contact to only conserve the lowest value. The result is that each cluster ends up with a unique id. From this, cluster sizes and other information can be trivially extracted.


This module serves to replace the partially deprecated module of ClusterAnalysis, but only offers the core of its functionality. For now, the module only works with sphere (or symmetric-potential-like) particles. However, at its center is a generic contact model which does not care about the precise geometry of contact resolution. To enable more general cluster analysis detection, only this interface should be changed.

Example usage, making use of mpacts post-processing utilities:

import DEMutilities.postprocessing.analysistools.spatial.clusters as clust
import DEMutilities.postprocessing.operators.operators as op
import as ds
import numpy as np

ca = clust.ClusterAnalysis( verbose=False )
ca.AddVTKWriter()#Because why not?

a = op.AnalysisContainer()
dr = ds.DataReader( "simulation", folder='./')
x = op.GetData( a, 'spheres/x')
r = op.GetData( a, 'spheres/r')
clust_ids = op.Function( a, ca, x, r )#Notice that it can be used as a function
clust_sizes = op.Function( a, clust.CountClusterSizes, clust_ids )
mean_clust_size = op.Function( a, np.mean, clust_sizes)#Mean over clusters
mean_cs = op.Function( a, np.mean, op.Recorder( a, mean_clust_size ) )#Mean over time
op.FrameIndexPrinter( a, dr[-1].index )

a.loop( dr )
print( "Mean cluster size over time was {} spheres",format( mean_cs() ) )

In order to be able to use this module import it like this:

import DEMutilities.postprocessing.analysistools.spatial.clusters
#or assign it to a shorter name
import DEMutilities.postprocessing.analysistools.spatial.clusters as clu


class DEMutilities.postprocessing.analysistools.spatial.clusters.ClusterAnalysis(verbose=False)

Bases: object

Main class that is used to perform a cluster analysis. Internally, it sets up a ‘semi-simulation’ with a contact detector and a contact model specifically for segmenting cluster sizes efficiently, and with as little overhead as possible.

Parameters:verbose (bool) – If True, some metrics of the current cluster analysis will be reported.
ClusterAnalysis(name, parent, **kwargs)

Adds a VTK writer command in the analysis’ semi-simulation. This is neat to visualize how the segmented clusters look like, and can even be used for further post-processing.

Parameters:directory (str) – (optional) directory in which the written vtk files will appear after each segmentation.
AnalyzeClusters(x, r)

Analyze a given set of positions and radii and return both cluster ids as well as cluster sizes. In a stand-alone analysis that does not use postprocessing operators, this is the ‘go-to’ function that should be used to easily perform a cluster analysis on any kind of data.

  • x (list) – list (or equivalent) of particle positions
  • r (list) – list (or equivalent) of particle radii

a tuple containing a list of cluster ids and a list of cluster sizes


Returns the number of clusters divided by the number of cells. This is the inverse of the average cluster size, and goes to 1 for a ‘gas-like’ phase, and goes to zero for a fully percolated system of very large size.


Make a histogram of the internal list of cluster sizes. There is one bin for each cluster size so the amount of bins is the maximal cluster size.

Parameters:normalize (bool) – If True, the resulting frequencies will be normalized
Returns:sorted cluster sizes, frequencies of each cluster size

Measures the cluster sizes using the CountClusterSizes() function, and stores the results in an internal mpacts array, so that the results might be further used e.g. to write to vtk.


Actually segments the clusters, using the given internal data that is all set at this point.


Usually, this function is not called directly by the user.

SetData(x, r=None, iid=None, cs=None, v=None)

Sets the data of the current ClusterAnalysis instance. Usually, only positions x and radii r need to be set.

  • x (list) – list of positions
  • r (list) – (optional) list of radii. If not given, the spheres become ‘points’ with zero radius.
  • iid (list) – (optional) list of infect ids to start the simulation with. Only set this if you know what you are doing!
  • cs (list) – (optional) list of cluster sizes. Only set this if you know what you are doing!
  • v (list) – (optional) list of particle velocities. Only needed for some special cases.


In general, a user of ClusterAnalysis should not directly use the SetData() function.


Returns the fraction of spheres which are in a cluster of size 1, (i.e. are ‘free’)


Write a vtk output file, if a writer was ever added using AddVTKWriter().


Given a list of cluster ids, obtained from a ClusterAnalysis, compute the sizes of each cluster.

Parameters:cluster_ids (list) – A list containing the cluster_id for each particle in the analysis.


The result of this function is an array of the same length as the number of particles The value for each particle is the size of the cluster in which this particle belongs. Evidently, a ‘free’ particle will have cluster size 1.