Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 156 additions & 0 deletions docs/numpy_field_manipulation.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
NumPy Field Manipulation
==================================

NumPy-backed fields are a **new feature in CompuCell3D 4.7.0** that allows direct access to scalar or vector field data as NumPy arrays.
In comparison to traditional field manipulation, using NumPy offers easier array manipulation syntax and efficient computational performance.
The array data is shared memory between your Python code and CompuCell3D's C++ backend.

The demo **shared_numpy_fields** shows this feature in action.

Creating Shared NumPy Fields
###############################################

**padding**: adds extra layers around the field. Useful for PDE solvers.

**precision_type**: a NumPy dtype such as ``"int16"`` or ``"float32"``. The following NumPy data types are supported:

- ``int8`` (signed char)
- ``uint8`` (unsigned char)
- ``int16`` (short)
- ``uint16`` (unsigned short
- ``int32`` (int)
- ``uint32`` (unsigned int)
- ``int64`` (long long)
- ``uint64`` (unsigned long long)
- ``float32`` (float)
- ``float64`` (double)

You can create **scalar fields** using:

.. code-block:: python

self.create_shared_scalar_numpy_field("exampleScalarNumpy", padding=1)

.. code-block:: python

self.create_shared_scalar_numpy_field("exampleInt16FieldPythonNPY", precision_type="int16")

.. code-block:: python

self.create_shared_scalar_numpy_field("exampleFloat32FieldPythonNPY", precision_type="float32")

You can create **vector fields** using:

.. code-block:: python

self.create_shared_vector_numpy_field("exampleVectorNumpy")

.. code-block:: python

self.create_shared_vector_numpy_field("exampleVectorNumpy", precision_type="float32")

Accessing Fields
###############################################

Once created, these fields can be accessed directly:

.. code-block:: python

exampleScalarNumpy = self.field.exampleScalarNumpy
exampleScalarNumpy[15, 25, 0] = 5 # Assign scalar

.. code-block:: python

exampleVectorNumpy = self.field.exampleVectorNumpy
exampleVectorNumpy[15, 25, 0] = [15, 25, 0] # Assign vector

Or, to access the field and its padding, use ``raw_field``:

.. code-block:: python

cpp_array = self.raw_field.exampleScalar # Includes padding

cpp_array_user = self.field.exampleScalar # Excludes padding

**********************************************

Using Field Manager XML Helper
###############################################

NumPy fields can be created in XML too. This is just a different way of writing the syntax.

**Name**: the unique name that will be used to identify the field in XML and Python.

**Type**: ``"scalar"`` (AKA ``"concentration"``) or ``"vector"``.

**Precision**: a NumPy dtype such as ``"int16"`` or ``"float32"``.

**Example**:

.. code-block:: XML

<Steppable Type="FieldManager">
<Field Name="fibers_field_manager" Type="vector"/>
<Field Name="numpy_field_manager" Type="scalar"/>
<Field Name="cell_type_field" Type="scalar" Precision="uint8"/>
<Field Name="cell_volume_field" Type="scalar" Precision="int16"/>
</Steppable>

They can then be accessed from Python as before:

.. code-block:: python

fibers_fm = self.field.fibers_field_manager
fibers_fm[15, 25, 0, ...] = [120, 120, 0]

**********************************************

Key Differences from Standard Field API
---------------------------------------

.. raw:: html

<table>
<thead>
<tr>
<th>Feature</th>
<th>NumPy Field API</th>
</tr>
</thead>
<tbody>
<tr>
<td>Access Syntax</td>
<td>NumPy-style slicing: <code>field[x1:x2, y1:y2, z1]</code></td>
</tr>
<tr>
<td>Performance</td>
<td>Significantly faster for bulk operations using NumPy</td>
</tr>
<tr>
<td>Data Types</td>
<td>Must specify <code>dtype</code> (e.g., <code>int16</code>, <code>float32</code>)</td>
</tr>
<tr>
<td>Padding</td>
<td>Use <code>raw_field</code> to access padded data regions</td>
</tr>
<tr>
<td>In-place Editing</td>
<td>Allows slicing and assignment directly</td>
</tr>
</tbody>
</table>

**********************************************

Example Use Case: Copying Data from Standard Fields
----------------------------------------------------

The demo **shared_numpy_fields_steppables.py** shows that it's possible to edit standard field data into NumPy-backed fields using helper methods:

.. code-block:: python

self.copy_cell_attribute_field_values_to("cell_type_field", "type")
self.copy_cell_attribute_field_values_to("cell_volume_field", "id")

These populate the NumPy fields with values derived from cell attributes. However, if your workflow requires you to transfer data from NumPy arrays to cells, you should write code to do this after `copy_cell_attribute_field_values_to`.
77 changes: 77 additions & 0 deletions docs/vector_field_polarization_plugin.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
Vector Field Polarization plugin
==================================

**VectorFieldPolarization** is a CompuCell3D plugin that introduces a custom energy term to bias cellular motion based on alignment with a spatially defined vector field.
This is useful for scenarios where cells follow physical or chemical directional cues, such as fiber alignment in extracellular matrices (i.e. ECM fibers).

When enabled, the plugin favors cell movement along the local direction specified by the vector field,
thereby increasing the likelihood of copy attempts that align with the vector direction.
Unlike the Chemotaxis plugin, this plugin uses a vector field that exists independently as opposed to a chemical field that cells may interact with.

Related Demo: ``Demos/PluginDemos/VectorFieldPolarization/vector_field_polarization.cc3d``

------------------------
XML Syntax
------------------------

This will register a vector field named ``Fibers``.
CompuCell3D can only support one VectorFieldPolarization plugin at a time.

.. code-block:: xml

<Plugin Name="VectorFieldPolarization">
<Field Name="Fibers"/>
<PolarizationLambda>2.0</PolarizationLambda>
</Plugin>

------------------------
XML Attributes
------------------------

``<Field Name="..."/>`` (required):
Specifies the name of the vector field that encodes directional cues for the cells.
This field must be initialized in Python using ``self.field.<FieldName>``.
Each vector at a lattice point defines the preferred direction of movement at that point.

``<PolarizationLambda>`` (required):
A non-negative floating-point value controlling the strength of the polarization effect.
Higher values increase the influence of the vector field on cell motility.
Since we take the absolute value, the sign does not matter.

------------------------
Python Manipulation
------------------------

We can use the ``start`` function to define where the vectors point.
In this example, the cells will migrate in the negative x/y direction at specific positions.

.. code-block:: python

class VectorFieldSteppable(SteppableBasePy):
def __init__(self, frequency=10):
SteppableBasePy.__init__(self, frequency)

def start(self):
fiber_field_cpp = self.field.Fibers
fiber_field_cpp[30, 10, 0] = [-30, -10, 0]
fiber_field_cpp[20, 30, 0] = [-20, -30, 0]

This field can be updated dynamically during the simulation to reflect changing environments.

------------------------
Energy Contribution
------------------------

The plugin changes energy according:

.. math::

E = -\left| \lambda \cdot (\vec{v}_{\text{field}} \cdot \vec{d}_{\text{COM (Old cell)}}) \right| - \left| \lambda \cdot (\vec{v}_{\text{field}} \cdot \vec{d}_{\text{COM (New cell)}}) \right|

Where:

- :math:`\lambda` is the polarization coefficient (``PolarizationLambda``).
- :math:`\vec{v}_{\text{field}}` is the vector from the field at the cell’s center of mass.
- :math:`\vec{d}_{\text{COM}}` is the displacement vector resulting from a pixel copy attempt. We evaluate this for both the new cell (if it exists) and old cell (if it exists).

Since the energy contribution is negative, VectorFieldPolarization generally reduces the energy needed for cells to align in the direction specified by the vector field.