Functions & Usage#

Syntax#

The Python interface is mostly wrapper around the C++ classes and functions. In general the Python and C++ codes are almost identical, with as only differences:

  • The C++ xt::xarray are numpy.ndarray in Python.

  • The syntax :: in Python in simply a ..

For example:

GooseEYE::Ensemble ensemble({51, 51});

In Python is

ensemble = GooseEYE.Ensemble([51, 51])

Python only functions#

Overview#

GooseEYE.Structure(compute_variance, shape, ...)

Compute the ensemble average structure factor:

Details#

GooseEYE.ClusterLabeller(shape, periodic: bool = True, **kwargs)#

Allocate a cluster labeller.

Parameters:
  • shape – The shape of the image.

  • periodic – Whether the image is periodic.

Returns:

A cluster labeller.

class GooseEYE.Structure(compute_variance: bool = True, shape: tuple[int] = None, dtype: DTypeLike = <class 'numpy.float64'>)#

Compute the ensemble average structure factor:

\[S(\vec{q}) = \langle \hat{u}(\vec{q}) \hat{u}(\vec{q}) \rangle\]

Implementation#

Thereby,

\[\vec{q} = \sum_{i = 1}^d q_i \vec{e}_i\]

The frequencies along a direction i are organised as follows (see docs):

q = [0, 1, ...,   n/2-1,     -n/2, ..., -1] / n  # if n is even
q = [0, 1, ..., (n-1)/2, -(n-1)/2, ..., -1] / n  # if n is odd

with n the number of data points in direction i. For example,

  • if n = 6 (even):

    q = [0, 1, 2, -3, -2, -1] / 6
    
  • if n = 7 (odd):

    q = [0, 1, 2, 3, -3, -2, -1] / 7
    

In one dimension, computing a single sample \(s = \hat{u}(q) \hat{u}(-q)\) thus corresponds to:

  • If n is even:

    e = n / 2  # (e.g. 3 if n = 6)
    s[0] = uhat[0] * uhat[0]
    s[1:e] = uhat[1:e] * np.flip(uhat[e+1:])  # e.g. uhat([1, 2]) * uhat([5, 4])
    s[e+1:] = uhat[e+1:] * np.flip(uhat[1:e]) = np.flip(s[1:e])
    s[e] = np.NaN  # e.g. s[3] = np.NaN if n = 6, as q = -3 / 6 exists, but not q = 3 / 6
    
  • If n is odd:

    e = (n - 1) / 2 + 1  # (e.g. 4 if n = 7)
    s[0] = uhat[0] * uhat[0]
    s[1:e] = uhat[1:e] * np.flip(uhat[e:])  # e.g. uhat([1, 2, 3]) * uhat([6, 5, 4])
    s[e:] = uhat[e:] * np.flip(uhat[1:e]) = np.flip(s[1:e])
    

In the for the general case:

e = n // 2 if n % 2 == 0 else n // 2 + 1
s = e + 1 if n % 2 == 0 else e
s[0] = uhat[0] * uhat[0]
s[1:e] = uhat[1:e] * np.flip(uhat[s:])
s[s:] = uhat[s:] * np.flip(uhat[1:e]) = np.flip(s[1:e])
if n % 2 == 0:
    s[e] = np.NaN

Note

This class stores all frequencies. As a consequence, their are a number of duplicate entries in the raw data. See below for suggested plotting without these duplicates.

Suggested plotting#

  • In one dimensions:

    q = structure.qnorm
    s = structure.mean()[:q.size]
    ax.plot(q[1:], s[1:], marker=".")
    

    Or to apply a common correction:

    q = 2 * np.sin(np.pi * data.qnorm)
    s = structure.mean()[:q.size]
    ax.plot(q[1:], s[1:], marker=".")
    
    ax.set_xlabel(r"$2 \sin(q / 2)$")
    ax.set_ylabel(r"$\langle \hat{u}(q) \hat{u}(-q) \rangle$")
    
  • In two dimensions:

    q = structure.qnorm
    s = structure.mean()[:q.shape[0], :q.shape[1]]
    ax.plot(q[1:, 0], s[1:, 0], marker=".")
    
param compute_variance:

Whether to compute the variance.

param shape:

The shape of the data.

param dtype:

The data type.

add_sample(data: ArrayLike)#

Add a sample. :param data: The sample.

q(axis: int = None)#

The frequency (along a given axis).

Parameters:

axis – The axis (if dimension > 1).

Returns:

Frequency (in selected direction) of each entry in first, second, … mean(), ….

property qnorm#

Norm of the frequency of the structure factor.

Note

There are a number of duplicate entries in the raw data (and in the norm of the frequency). This property has these duplicates removed. To get the corresponding data or averages:

q = structure.qnorm

if q.dim == 1:
    m = structure.mean()[:q.size]
elif q.dim == 2:
    m = structure.mean()[:q.shape[0], :q.shape[1]]
Returns:

Norm of the frequency.