Secretion / SecretionLocalFlex Plugin

Related:

Download the sample code here, then watch the video from the latest workshop to follow along:

Workshop Tutorial Video

Secretion “by cell type” can and should be handled by the appropriate PDE solver. To implement secretion from individual cells using Python, we first add the secretion plugin in CC3DML:

<Plugin Name="Secretion"/>

or as:

<Plugin Name="SecretionLocalFlex"/>

The inclusion of the above code in the CC3DML will allow users to implement secretion for individual cells from Python.

Note

Secretion for individual cells invoked via Python will be called only once per MCS.

Warning

Although the secretion plugin can be used to implement secretion by cell type, we strongly advise against doing so. Defining secretion by cell type in the Secretion plugin will lead to performance degradation on multi-core machines. Please see the section below for more information if you are still interested in using secretion by cell type inside the Secretion plugin.

Typical use of secretion from Python is demonstrated best in the example below:

class SecretionSteppable(SecretionBasePy):
    def __init__(self, _simulator, _frequency=1):
        SecretionBasePy.__init__(self, _simulator, _frequency)

    def step(self, mcs):
        attrSecretor = self.get_field_secretor("ATTR")
        for cell in self.cellList:
            if cell.type == 3:
                attrSecretor.secreteInsideCell(cell, 300)
                attrSecretor.secreteInsideCellAtBoundary(cell, 300)
                attrSecretor.secreteOutsideCellAtBoundary(cell, 500)
                attrSecretor.secreteInsideCellAtCOM(cell, 300)
            elif cell.type == 2:
                attrSecretor.secreteInsideCellConstantConcentration(cell, 300)

Note

Instead of using SteppableBasePy class we are using SecretionBasePy class. This ensures that the secretion plugin will be performed before diffusion by calling the Python secretion steppable before each Monte Carlo Step.

There is no magic to SecretionBasePy - if you still want to use SteppableBasePy as a base class for secretion do so, but remember that you need to set flag:

self.runBeforeMCS=1

to ensure that your new steppable will run before each MCS. See example below for alternative implementation of SecretionSteppable using SteppableBasePy as a base class:

class SecretionSteppable(SteppableBasePy):
    def __init__(self,_simulator,_frequency=1):
        SteppableBasePy.__init__(self,_simulator, _frequency)
        self.runBeforeMCS=1
    def step(self,mcs):
        attrSecretor=self.get_field_secretor("ATTR")
        for cell in self.cellList:
            if cell.type==3:
                attrSecretor.secreteInsideCell(cell,300)
                attrSecretor.secreteInsideCellAtBoundary(cell,300)
                attrSecretor.secreteOutsideCellAtBoundary(cell,500)
                attrSecretor.secreteOutsideCellAtBoundaryOnContactwith(cell,500,[2,3])
                attrSecretor.secreteInsideCellAtCOM(cell,300)
                attrSecretor.uptakeInsideCellAtCOM(cell,300,0.2)
            elif cell.type==2:
                attrSecretor.secreteInsideCellConstantConcentration(cell,300)

The secretion of individual cells is handled through FieldSecretor objects. FieldSecretor concept is quite convenient because the amount of Python coding is quite small. To secrete a chemical from a cell, we first create a field secretor object:

attrSecretor = self.get_field_secretor("ATTR")

which allows us to manipulate how much which cells secrete into the ``ATTR` field.

Then, we pick a cell, and using this field secretor, we simulate secretion of chemical ATTR by a cell:

attrSecretor.secreteInsideCell(cell,300)

Secretion functions use the following syntax:

secrete*(cell, amount)
#or...
secrete*(cell, amount, list_of_cell_types)

Note

The list_of_cell_types is used only for functions which implement such functionality i.e. secreteInsideCellAtBoundaryOnContactWith and secreteOutsideCellAtBoundaryOnContactWith

Uptake functions use the following syntax:

uptake*(cell, max_amount, relative_uptake, list_of_cell_types)
#or...
uptake*(cell, max_amount, relative_uptake)

Note

The list_of_cell_types is used only for functions which implement such functionality i.e. uptakeInsideCellAtBoundaryOnContactWith and uptakeOutsideCellAtBoundaryOnContactWith

Note

Important: The uptake works as follows: when available concentration is greater than max_amount, then max_amount is subtracted from current_concentration, otherwise we subtract relative_uptake*current_concentration.

As you may infer from above, the modes 1-5 require tracking of pixels belonging to cell and pixels belonging to cell boundary. If you are not using those secretion modes you may disable pixel tracking by including:

<DisablePixelTracker/>

or

<DisableBoundaryPixelTracker/>

as shown in the example below:

<Plugin Name="Secretion">

    <DisablePixelTracker/>
    <DisableBoundaryPixelTracker/>

    <Field Name="ATTR" ExtraTimesPerMC=”2”>
        <Secretion Type="Bacterium">200</Secretion>
        <SecretionOnContact Type="Medium" SecreteOnContactWith="B">300</SecretionOnContact>
        <ConstantConcentration Type="Bacterium">500</ConstantConcentration>
    </Field>
</Plugin>

Note

Make sure that fields into which you will be secreting chemicals exist. They are usually fields defined in PDE solvers. When using secretion plugin you do not need to specify SecretionData section for the PDE solvers.

When implementing e.g. secretion inside cell when the cell is in contact with other cell we use neighbor tracker and a short script in the spirit of the below snippet:

for cell in self.cellList:
    attrSecretor = self.get_field_secretor("ATTR")
    for neighbor, commonSurfaceArea in self.getCellNeighborDataList(cell):
        if neighbor.type in [self.WALL]:
            attrSecretor.secreteInsideCell(cell, 300)