<?xml version="1.0" encoding="utf-8"?>
<section version="5.0"
         xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd"
         xml:id="particles.modifiers.cluster_analysis"
         xmlns="http://docbook.org/ns/docbook"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:xs="http://www.w3.org/2001/XMLSchema"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xmlns:xi="http://www.w3.org/2001/XInclude"
         xmlns:ns="http://docbook.org/ns/docbook">
  <title>Cluster analysis</title>

  <para>
  
    <informalfigure>
      <informaltable frame="none">
        <tgroup cols="2">
          <tbody>
            <row valign="bottom">
              <entry>Input:</entry>
              <entry>Output:</entry>
            </row>
            <row valign="top">
              <entry>
		        <mediaobject><imageobject>
		        <imagedata fileref="images/modifiers/cluster_analysis_example_input.png" format="PNG" />
		        </imageobject></mediaobject>
              </entry>
              <entry>
		        <mediaobject><imageobject>
		        <imagedata fileref="images/modifiers/cluster_analysis_example_output.png" format="PNG" />
		        </imageobject></mediaobject>
              </entry>
            </row>
          </tbody>
        </tgroup>
      </informaltable>
    </informalfigure>
      
    <informalfigure><screenshot><mediaobject><imageobject>
       <imagedata fileref="images/modifiers/cluster_analysis_panel.png" format="PNG" />
    </imageobject></mediaobject></screenshot></informalfigure>
  
    This modifier decomposes a particle system into disconnected sets of particles (clusters) based on a distance criterion.
  </para>
  
  <para>
    A cluster is defined as a set of connected particles, each of which is within the cutoff distance of one or more 
    other particles from the same cluster. Thus, any two particles from the same cluster are connected by a 
    continuous path consisting only of steps which are shorter than the given cutoff distance.    
    Conversely, two particles will not belong to the same cluster if 
    there is no continuous path on the neighbor network leading from one particle to the other.
  </para>
  <para>
    If a particle possesses no neighbors within the cutoff distance, then it will form a 1-particle cluster.
  </para>

  <para>
     The modifier outputs its results to the <literal>Cluster</literal> particle property, which stores the
     cluster each particle has been assigned to. Cluster IDs range from 1 to <emphasis>N</emphasis>, where <emphasis>N</emphasis> 
     is the number of clusters found by the modifier.
  </para>

  <simplesect>
    <title>Parameters</title>
    <variablelist>
      <varlistentry>
        <term>Cutoff distance</term>
        <listitem>
          <para>The distance threshold up to which two particles are considered direct neighbors and assigned to the same cluster.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Use only selected particles</term>
        <listitem>
          <para>If this option is active, the clustering algorithm is restricted to selected
          particles. Unselected particles will be treated as if they do not exist and will be assigned
          the cluster ID 0. 
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Sort clusters by size</term>
        <listitem>
          <para>Enables the sorting of clusters by size (in descending order). Cluster ID 1 will be the largest cluster, 
          cluster ID 2 the second largest, and so on.
          </para>
        </listitem>
      </varlistentry>
    </variablelist>
  </simplesect>
  
  <simplesect>
    <title>Exporting the output of the clustering algorithm</title>
    <variablelist>
      <varlistentry>
        <term>Number of clusters</term>
        <listitem>
          <para>To export the total number of clusters to a text file (possibly as a function of simulation time), use OVITO's
          standard <link linkend="usage.export">file export function</link>. Choose the output file format <emphasis>Calculation Results Text File</emphasis>
          and select the <code>ClusterAnalysis.cluster_count</code> attribute for export. 
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Particles of each cluster</term>
        <listitem>
          <para>To export the list of particles belonging to each invidual cluster, also use OVITO's
          standard <link linkend="usage.export">file export function</link>. Choose e.g. <emphasis>XYZ</emphasis> as the output file format
          and select the <code>Cluster</code> property for export. This will produce a text file containing the
          cluster ID assigned to each particle.
          </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>Cluster sizes</term>
        <listitem>
          <para>Computing and exporting the size of each cluster (i.e. the number of particles) requires a simple Python script.
          The following example script can be executed using the <menuchoice><guimenu>Scripting</guimenu><guimenuitem>Run Script File</guimenuitem></menuchoice>
          menu function after manually applying the <emphasis>Cluster Analysis</emphasis> modifier:</para>
    <para><programlisting>from ovito import *
import numpy

output_filepath = "cluster_sizes.txt"
output = dataset.selected_node.compute()
cluster_sizes = numpy.bincount(output.particle_properties['Cluster'].array)
numpy.savetxt(output_filepath, cluster_sizes)
    </programlisting></para>
    <para>
      Please  copy/paste the above script to a text editor and save it as <code>.py</code> file. Don't forget to adjust the output file path as needed. The script makes use
      of the <link xlink:href="http://docs.scipy.org/doc/numpy/reference/generated/numpy.bincount.html#numpy.bincount"><code>bincount()</code></link> Numpy function to count the 
      number of particles belonging to each cluster. Note that the array returned by this function includes cluster ID 0, which is not assigned by the modifier
      and therefore typically has size zero. For more information on OVITO's scripting interface, see <link linkend="usage.scripting">this page</link>.
    </para>
    <para>
      It is possible to perform the file export for every frame in a simulation sequence by adding a <code>for</code>-loop to the script:</para>
<para><programlisting>from ovito import *
import numpy

for frame in range(dataset.anim.last_frame + 1):
    output_filepath = "cluster_sizes.%i.txt" % frame
    output = dataset.selected_node.compute(frame)
    cluster_sizes = numpy.bincount(output.particle_properties['Cluster'].array)
    numpy.savetxt(output_filepath, cluster_sizes)
    </programlisting></para>
        </listitem>
      </varlistentry>
    </variablelist>
  </simplesect>
  
</section>
