####################################################################################
#
# STEPS - STochastic Engine for Pathway Simulation
# Copyright (C) 2007-2026 Okinawa Institute of Science and Technology, Japan.
# Copyright (C) 2003-2006 University of Antwerp, Belgium.
#
# See the file AUTHORS for details.
# This file is part of STEPS.
#
# STEPS is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3,
# as published by the Free Software Foundation.
#
# STEPS is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#################################################################################
###
from . import blenderloader
from . import groups
from . import objects
from . import state
[docs]
class StateDependentVesicles(objects.BlenderVesicles, state.StateDependentSeparateObjects):
"""Subclass of BlenderVesicles that allows to dynamically change material of vesicles
See :py:class:`StateDependentSeparateObjects` for information about material set and update
functions.
The `state` parameter given to both functions is a dictionary that contains the following values:
+-----------------+-------------------------------------+-----------------------------------------+
| Name | Example | Description |
+=================+=====================================+=========================================+
| | :: | |
| | | |
| idx | 45 | Index of the specific vesicle |
+-----------------+-------------------------------------+-----------------------------------------+
| | :: | |
| | | |
| position | [x, y, z] | 3D position of the vesicle in cartesian |
| | | coordinates |
+-----------------+-------------------------------------+-----------------------------------------+
| | :: | |
| | | |
| name | 'Ves1' | Name of the vesicle type in STEPS |
+-----------------+-------------------------------------+-----------------------------------------+
| | :: | |
| | | |
| surface_species | {'S1':[ | Dictionary of species name to list |
| | (r1, theta1, phi1), | of spherical coordinate positions |
| | (r2, theta2, phi2), | relative to the vesicle |
| | ...], ...} | |
+-----------------+-------------------------------------+-----------------------------------------+
| | :: | |
| | | |
| inside_species | {'S1': 10, ...} | Dictionary of species name to count |
+-----------------+-------------------------------------+-----------------------------------------+
| | :: | |
| | | |
| link_species | {'L1': | Dictionary of link species name to |
| | {123: { | dictionary of specific link species |
| | 'position': [r, theta, phi] | to 3D position in relative spherical |
| | 'link': 456}, | coordinates and corresponding link |
| | ...}, ...} | species |
+-----------------+-------------------------------------+-----------------------------------------+
| | :: | 3D position of the path point to which |
| | | the vesicle is bound. None if not bound |
| on_path | [x, y, z] | |
+-----------------+-------------------------------------+-----------------------------------------+
Example::
def redBoundVesicles(scene, depg, material, state):
bsdf = material.node_tree.nodes['Principled BSDF']
if 'L1' in state['link_species']:
bsdf.inputs['Emission Color'].default_value = (1, 0, 0, 1) # Red
else:
bsdf.inputs['Emission Color'].default_value = (0, 1, 0, 1) # Green
parameters = {'Ves1': StateDependentVesicles, 'updateMaterialFunc': redBoundVesicles}
loader = HDF5BlenderLoader(parameters=parameters, ...)
This example will display all vesicles that have link species ``'L1'`` on their surface as red
and all other vesicles as green.
"""
stateClasses = [groups.LinkSpeciesGroup, groups.VesicleGroup]
def _signalUpdatedState(self, caller, scene, depg):
if isinstance(caller, groups.VesicleGroup):
for idx, pos, specIn, specSurf, pathPos in caller.getVesStateInfo(self._name):
dct = self._stateDict.setdefault(idx, self._getDefaultDict())
dct['idx'] = idx
dct['position'] = pos
dct['name'] = self._name
dct['inside_species'] = specIn
dct['surface_species'] = specSurf
dct['on_path'] = pathPos
elif isinstance(caller, groups.LinkSpeciesGroup):
for lspecTpe, lspecDct in caller.state.items():
for lsIdx, ((vesTpe, vesIdx), lsPos, lsLink) in lspecDct.items():
if vesTpe == self._name:
dct = self._stateDict.setdefault(vesIdx, self._getDefaultDict()).setdefault(
'link_species', {})
lsDct = {'position': lsPos, 'link': lsLink}
dct.setdefault(lspecTpe, {}).setdefault(lsIdx, lsDct)
def _getDefaultDict(self):
return {
'idx': None,
'position': None,
'name': None,
'surface_species': {},
'inside_species': {},
'link_species': {},
'on_path': None,
}
[docs]
class StateDependentRafts(objects.BlenderRafts, state.StateDependentSeparateObjects):
"""Subclass of BlenderRafts that allows to dynamically change material of rafts
See :py:class:`StateDependentSeparateObjects` for information about material set and update
functions.
The ``state`` parameter given to both functions is a dictionary that contains the following values:
+-----------------+----------------------------+--------------------------------------+
| Name | Example | Description |
+=================+============================+======================================+
| | :: | |
| | | |
| idx | 45 | Index of the specific raft |
+-----------------+----------------------------+--------------------------------------+
| | :: | |
| | | |
| position | [x, y, z] | 3D position of the raft in cartesian |
| | | coordinates |
+-----------------+----------------------------+--------------------------------------+
| | :: | |
| | | |
| name | 'Raft1' | Name of the raft type in STEPS |
+-----------------+----------------------------+--------------------------------------+
| | :: | |
| | | |
| surface_species | {'S1': 0, 'S2':5, ...} | Dictionary of species name to counts |
+-----------------+----------------------------+--------------------------------------+
Example::
def redS1Rafts(scene, depg, material, state):
bsdf = material.node_tree.nodes['Principled BSDF']
if 'S1' in state['surface_species']:
bsdf.inputs['Emission Color'].default_value = (1, 0, 0, 1) # Red
else:
bsdf.inputs['Emission Color'].default_value = (0, 1, 0, 1) # Green
parameters = {'Raft1': StateDependentRafts, 'updateMaterialFunc': redS1Rafts}
loader = HDF5BlenderLoader(parameters=parameters, ...)
This example will display all rafts that have species ``'S1'`` on their surface as red
and all other rafts as green.
"""
stateClasses = [groups.RaftGroup]
def _signalUpdatedState(self, caller, scene, depg):
for raftIdx, pos, counts in caller.getRaftStateInfo(self._name):
dct = self._stateDict.setdefault(raftIdx, self._getDefaultDict())
dct['idx'] = raftIdx
dct['position'] = pos
dct['name'] = self._name
dct['surface_species'] = counts
def _getDefaultDict(self):
return {'idx': None, 'position': None, 'name': None, 'surface_species': {}}
[docs]
class StateDependentMesh(objects.STEPSMeshObject, state.StateDependentObject):
"""Subclass of STEPSMeshObject that allows to dynamically change the material of a mesh
See :py:class:`StateDependentObject` for information about material set and update functions.
The `state` parameter given to both functions is a dictionary that contains the following values:
+------------+---------+-----------------+
| Name | Example | Description |
+============+=========+=================+
| time | 0.23 | Simulation time |
+------------+---------+-----------------+
Example::
def meshEmission(scene, depg, material, state):
bsdf = material.node_tree.nodes['Principled BSDF']
if 0.001 <= state['time'] < 0.002:
if 'S1' in state['surface_species']:
bsdf.inputs['Emission Strength'].default_value = 5
else:
bsdf.inputs['Emission Strength'].default_value = 0
parameters = {'Membrane': StateDependentMesh, 'updateMaterialFunc': meshEmission}
loader = HDF5BlenderLoader(parameters=parameters, ...)
This example will increase the mesh emission strength between 1 and 2ms to visually convey e.g.
a current injection.
"""
stateClasses = [blenderloader.HDF5BlenderLoader]
def _signalUpdatedState(self, caller, scene, depg):
self._currState['time'] = caller.state['time']