Skip to content
Merged
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
76 changes: 72 additions & 4 deletions src/arcade/potts/agent/module/PottsModuleFlyStemProliferation.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
import arcade.potts.env.location.Voxel;
import arcade.potts.sim.Potts;
import arcade.potts.sim.PottsSimulation;
import arcade.potts.util.PottsEnums.Direction;
import arcade.potts.util.PottsEnums.Phase;
import arcade.potts.util.PottsEnums.State;
import static arcade.potts.util.PottsEnums.Direction;
import static arcade.potts.util.PottsEnums.Phase;
import static arcade.potts.util.PottsEnums.State;
Expand Down Expand Up @@ -81,8 +84,15 @@ public class PottsModuleFlyStemProliferation extends PottsModuleProliferationVol
*/
final double nbContactHillN;

/*
* Boolean flag for whether the daughter cell's differentiation is determined deterministically.
*/
final boolean hasDeterministicDifferentiation;

final double initialSize;

public static final double EPSILON = 1e-8;

/**
* Creates a proliferation {@code Module} for the given {@link PottsCellFlyStem}.
*
Expand Down Expand Up @@ -127,13 +137,20 @@ public PottsModuleFlyStemProliferation(PottsCellFlyStem cell) {
nbContactHalfMax = parameters.getDouble("proliferation/NB_CONTACT_HALF_MAX");
nbContactHillN = parameters.getDouble("proliferation/NB_CONTACT_HILL_N");

String hasDeterministicDifferentiationString =
parameters.getString("proliferation/HAS_DETERMINISTIC_DIFFERENTIATION");
if (!hasDeterministicDifferentiationString.equals("TRUE")
&& !hasDeterministicDifferentiationString.equals("FALSE")) {
throw new InvalidParameterException(
"hasDeterministicDifferentiation must be either TRUE or FALSE");
}
hasDeterministicDifferentiation = hasDeterministicDifferentiationString.equals("TRUE");

initialSize = cell.getVolume();

setPhase(Phase.UNDEFINED);
}

public static final double EPSILON = 1e-8;

@Override
public void addCell(MersenneTwisterFast random, Simulation sim) {
Potts potts = ((PottsSimulation) sim).getPotts();
Expand All @@ -143,7 +160,7 @@ public void addCell(MersenneTwisterFast random, Simulation sim) {
PottsLocation2D parentLoc = (PottsLocation2D) cell.getLocation();
PottsLocation daughterLoc = (PottsLocation) parentLoc.split(random, divisionPlane);

boolean isDaughterStem = daughterStem(parentLoc, daughterLoc);
boolean isDaughterStem = daughterStem(parentLoc, daughterLoc, divisionPlane);

if (isDaughterStem) {
makeDaughterStemCell(daughterLoc, sim, potts, random);
Expand Down Expand Up @@ -301,6 +318,15 @@ public Plane getMUDDivisionPlane(PottsCellFlyStem cell) {
Direction.XY_PLANE.vector,
StemType.MUDMUT.splitDirectionRotation);
Voxel splitVoxel = getCellSplitVoxel(StemType.MUDMUT, cell, defaultNormal);
System.out.println(
"in getMUDDivisionPlane, default Normal = ("
+ defaultNormal.getX()
+ ", "
+ +defaultNormal.getY()
+ ", "
+ +defaultNormal.getZ()
+ ", "
+ ")");
return new Plane(new Double3D(splitVoxel.x, splitVoxel.y, splitVoxel.z), defaultNormal);
}

Expand Down Expand Up @@ -328,7 +354,7 @@ public static Voxel getCellSplitVoxel(
* @param loc2 the other cell location post division
* @return whether or not the daughter cell should be a stem cell
*/
public boolean daughterStem(PottsLocation loc1, PottsLocation loc2) {
private boolean daughterStemRuleBasedDifferentiation(PottsLocation loc1, PottsLocation loc2) {
if (((PottsCellFlyStem) cell).getStemType() == StemType.WT) {
return false;
} else if (((PottsCellFlyStem) cell).getStemType() == StemType.MUDMUT) {
Expand All @@ -351,6 +377,48 @@ public boolean daughterStem(PottsLocation loc1, PottsLocation loc2) {
"Invalid differentiation ruleset: " + differentiationRuleset);
}

/*
* Determines whether the daughter cell should be a neuroblast or a GMC according to the orientation.
* This is deterministic.
*
* @param divisionPlane
* @return {@code true} if the daughter should be a stem cell. {@code false} if the daughter should be a GMC.
*/
private boolean daughterStemDeterministic(Plane divisionPlane) {

Vector normalVector = divisionPlane.getUnitNormalVector();

Vector apicalAxis = ((PottsCellFlyStem) cell).getApicalAxis();
Vector expectedMUDNormalVector =
Vector.rotateVectorAroundAxis(
apicalAxis,
Direction.XY_PLANE.vector,
StemType.MUDMUT.splitDirectionRotation);
// If TRUE, the daughter should be stem. Otherwise, should be GMC
return Math.abs(normalVector.getX() - expectedMUDNormalVector.getX()) <= EPSILON
&& Math.abs(normalVector.getY() - expectedMUDNormalVector.getY()) <= EPSILON
&& Math.abs(normalVector.getZ() - expectedMUDNormalVector.getZ()) <= EPSILON;
}

/**
* Determines whether a daughter cell should remain a stem cell or differentiate into a GMC.
*
* <p>This method serves as a wrapper that delegates to either a deterministic or rule-based
* differentiation mechanism depending on the value of {@code hasDeterministicDifferentiation}.
*
* @param parentsLoc the location of the parent cell before division
* @param daughterLoc the location of the daughter cell after division
* @param divisionPlane the plane of division for the daughter cell
* @return {@code true} if the daughter should remain a stem cell; {@code false} if it should be
* a GMC
*/
public boolean daughterStem(
PottsLocation2D parentsLoc, PottsLocation daughterLoc, Plane divisionPlane) {
return hasDeterministicDifferentiation
? daughterStemDeterministic(divisionPlane)
: daughterStemRuleBasedDifferentiation(parentsLoc, daughterLoc);
}

/**
* Determines if the distance between two centroids, projected along the apical axis, is less
* than or equal to the given range.
Expand Down
1 change: 1 addition & 0 deletions src/arcade/potts/parameter.potts.xml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
<!-- ── NB and GMC critical volume options ────────────────────────── -->
<population.module module="proliferation" id="VOLUME_BASED_CRITICAL_VOLUME" value="0" description="1 → critical volume scales with daughter volume; 0 → use max (type-based) value" />
<population.module module="proliferation" id="VOLUME_BASED_CRITICAL_VOLUME_MULTIPLIER" value="2" description="if enabled, GMC critical volume = daughter_volume × multiplier" />
<population.module module="proliferation" id="HAS_DETERMINISTIC_DIFFERENTIATION" value="TRUE" description="if TRUE, differentiation is determined deterministically" />

<!-- apoptosis module parameters -->
<population.module module="apoptosis" id="RATE_EARLY" value="4" units="steps/hour" conversion="DT" description="rate of events in early apoptosis phase" />
Expand Down
Loading
Loading