From 895ba12cafe9e98bb5d8e1fc3caa49e7a2de0254 Mon Sep 17 00:00:00 2001 From: allison-li-1016 Date: Mon, 23 Mar 2026 20:44:27 +0000 Subject: [PATCH 1/4] initial push of mutate action file --- .../patch/agent/action/PatchActionMutate.java | 131 ++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/arcade/patch/agent/action/PatchActionMutate.java diff --git a/src/arcade/patch/agent/action/PatchActionMutate.java b/src/arcade/patch/agent/action/PatchActionMutate.java new file mode 100644 index 000000000..55e3525f4 --- /dev/null +++ b/src/arcade/patch/agent/action/PatchActionMutate.java @@ -0,0 +1,131 @@ +package arcade.patch.agent.action; + +import java.util.ArrayList; +import sim.engine.Schedule; +import sim.engine.SimState; +import sim.util.Bag; +import arcade.core.agent.action.Action; +import arcade.core.env.location.Location; +import arcade.core.sim.Series; +import arcade.core.sim.Simulation; +import arcade.core.util.MiniBox; +import arcade.patch.agent.cell.PatchCell; +import arcade.patch.agent.cell.PatchCellContainer; +import arcade.patch.env.grid.PatchGrid; +import arcade.patch.env.location.Coordinate; +import arcade.patch.sim.PatchSeries; +import arcade.patch.sim.PatchSimulation; +import static arcade.patch.util.PatchEnums.Ordering; + +/** + * Implementation of {@link Action} for converting cells to a different class. + * + *

The action is stepped once after {@code TIME_DELAY}. The action will convert all the healthy + * cells within the radius cells of the given population. + */ +public class PatchActionMutate implements Action { + /** Time delay before calling the action [min]. */ + private final int timeDelay; + + /** Grid radius that cells are inserted into. */ + private final int insertRadius; + + /** Population code for cancer. */ + private int cancerPop; + + /** Population code for healthy cells. */ + private int healthyPop; + + /** Grid depth that cells are inserted into. */ + private final int insertDepth; + + /** + * Creates a {@link Action} for converting cell agent classes. + * + *

Loaded parameters include: + * + *

+ * + * @param series the simulation series + * @param parameters the component parameters dictionary + */ + public PatchActionMutate(Series series, MiniBox parameters) { + // Set loaded parameters. + timeDelay = parameters.getInt("TIME_DELAY"); + insertRadius = parameters.getInt("INSERT_RADIUS"); + insertDepth = ((PatchSeries) series).depth; + healthyPop = -1; + cancerPop = -1; + // grab popuation codes for healthy and cancer cells + for (String popName : series.populations.keySet()) { + if (series.populations.get(popName).get("CLASS").contains("tissue")) { + healthyPop = series.populations.get(popName).getInt("CODE"); + } else if (series.populations.get(popName).get("CLASS").contains("cancer_stem") + || series.populations.get(popName).get("CLASS").contains("cancer")) { + cancerPop = series.populations.get(popName).getInt("CODE"); + } + } + if (healthyPop == -1 || cancerPop == -1) { + throw new IllegalArgumentException( + "Please initialize both healthy and cancer populations in input file."); + } + } + + @Override + public void schedule(Schedule schedule) { + schedule.scheduleOnce(timeDelay, Ordering.ACTIONS.ordinal(), this); + } + + @Override + public void register(Simulation sim, String population) {} + + @Override + public void step(SimState simstate) { + PatchSimulation sim = (PatchSimulation) simstate; + PatchGrid grid = (PatchGrid) sim.getGrid(); + + // Get cells at center of simulation. + ArrayList coordinates = + sim.locationFactory.getCoordinates(insertRadius, insertDepth); + for (Coordinate coordinate : coordinates) { + Bag bag = (Bag) grid.getObjectAt(coordinate.hashCode()); + + if (bag == null) { + continue; + } + + for (int i = 0; i < bag.numObjs; i++) { + // Select old cell and remove from simulation. + PatchCell oldCell = (PatchCell) bag.get(i); + if (oldCell.getPop() == healthyPop) { + Location location = oldCell.getLocation(); + grid.removeObject(oldCell, oldCell.getLocation()); + oldCell.stop(); + + // Create new cell and add to simulation. + PatchCellContainer cellContainer = + new PatchCellContainer( + oldCell.getID(), + oldCell.getParent(), + cancerPop, + oldCell.getAge(), + oldCell.getDivisions(), + oldCell.getState(), + oldCell.getVolume(), + oldCell.getHeight(), + oldCell.getCriticalVolume(), + oldCell.getCriticalHeight()); + PatchCell newCell = + (PatchCell) + cellContainer.convert(sim.cellFactory, location, sim.random); + grid.addObject(newCell, location); + newCell.schedule(sim.getSchedule()); + } + } + } + } +} From 7d6ead5edbc38cf7a19cc3c342f0aaa7e8399ce7 Mon Sep 17 00:00:00 2001 From: allison-li-1016 Date: Mon, 23 Mar 2026 21:48:09 +0000 Subject: [PATCH 2/4] update javadoc descipton --- src/arcade/patch/agent/action/PatchActionMutate.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arcade/patch/agent/action/PatchActionMutate.java b/src/arcade/patch/agent/action/PatchActionMutate.java index 55e3525f4..6b1d43cd8 100644 --- a/src/arcade/patch/agent/action/PatchActionMutate.java +++ b/src/arcade/patch/agent/action/PatchActionMutate.java @@ -21,7 +21,7 @@ * Implementation of {@link Action} for converting cells to a different class. * *

The action is stepped once after {@code TIME_DELAY}. The action will convert all the healthy - * cells within the radius cells of the given population. + * tissue cells within the given radius into cancer cells. */ public class PatchActionMutate implements Action { /** Time delay before calling the action [min]. */ From fdb895b83cd22bb088cfc78fa68b275d848f99a4 Mon Sep 17 00:00:00 2001 From: allison-li-1016 Date: Mon, 23 Mar 2026 21:57:52 +0000 Subject: [PATCH 3/4] adding option in simulation files so action can actually be called --- src/arcade/patch/sim/PatchSimulationHex.java | 3 +++ src/arcade/patch/sim/PatchSimulationRect.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/arcade/patch/sim/PatchSimulationHex.java b/src/arcade/patch/sim/PatchSimulationHex.java index 6eddf28b5..fa63efbaf 100644 --- a/src/arcade/patch/sim/PatchSimulationHex.java +++ b/src/arcade/patch/sim/PatchSimulationHex.java @@ -6,6 +6,7 @@ import arcade.core.util.MiniBox; import arcade.patch.agent.action.PatchActionConvert; import arcade.patch.agent.action.PatchActionInsert; +import arcade.patch.agent.action.PatchActionMutate; import arcade.patch.agent.action.PatchActionRemove; import arcade.patch.agent.cell.PatchCellFactory; import arcade.patch.env.component.PatchComponentCycle; @@ -58,6 +59,8 @@ public Action makeAction(String actionClass, MiniBox parameters) { return new PatchActionRemove(series, parameters); case "convert": return new PatchActionConvert(series, parameters); + case "mutate": + return new PatchActionMutate(series, parameters); default: return null; } diff --git a/src/arcade/patch/sim/PatchSimulationRect.java b/src/arcade/patch/sim/PatchSimulationRect.java index 6623fefec..e6d7e0ea6 100644 --- a/src/arcade/patch/sim/PatchSimulationRect.java +++ b/src/arcade/patch/sim/PatchSimulationRect.java @@ -6,6 +6,7 @@ import arcade.core.util.MiniBox; import arcade.patch.agent.action.PatchActionConvert; import arcade.patch.agent.action.PatchActionInsert; +import arcade.patch.agent.action.PatchActionMutate; import arcade.patch.agent.action.PatchActionRemove; import arcade.patch.agent.cell.PatchCellFactory; import arcade.patch.env.component.PatchComponentCycle; @@ -58,6 +59,8 @@ public Action makeAction(String actionClass, MiniBox parameters) { return new PatchActionRemove(series, parameters); case "convert": return new PatchActionConvert(series, parameters); + case "mutate": + return new PatchActionMutate(series, parameters); default: return null; } From b0b281e5e95dc7304bc065d56822566019bdb201 Mon Sep 17 00:00:00 2001 From: allison-li-1016 Date: Thu, 26 Mar 2026 17:02:56 +0000 Subject: [PATCH 4/4] editing docstring and intuitive variable names, adding default param values for mutate action --- .../patch/agent/action/PatchActionMutate.java | 25 ++++++++++--------- src/arcade/patch/parameter.patch.xml | 4 +++ 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/arcade/patch/agent/action/PatchActionMutate.java b/src/arcade/patch/agent/action/PatchActionMutate.java index 6b1d43cd8..3df65fc25 100644 --- a/src/arcade/patch/agent/action/PatchActionMutate.java +++ b/src/arcade/patch/agent/action/PatchActionMutate.java @@ -27,8 +27,8 @@ public class PatchActionMutate implements Action { /** Time delay before calling the action [min]. */ private final int timeDelay; - /** Grid radius that cells are inserted into. */ - private final int insertRadius; + /** Grid radius where cells are mutated. */ + private final int mutateRadius; /** Population code for cancer. */ private int cancerPop; @@ -36,18 +36,18 @@ public class PatchActionMutate implements Action { /** Population code for healthy cells. */ private int healthyPop; - /** Grid depth that cells are inserted into. */ - private final int insertDepth; + /** Grid depth that cells are mutated. */ + private final int mutateDepth; /** - * Creates a {@link Action} for converting cell agent classes. + * Creates a {@link Action} for converting healthy cell agents into cancer cell agents. * *

Loaded parameters include: * *

    *
  • {@code TIME_DELAY} = time delay before calling the action - *
  • {@code INSERT_RADIUS} = grid radius that cells are inserted into - *
  • {@code INSERT_DEPTH} = grid depth that cells are inserted into + *
  • {@code MUTATE_RADIUS} = grid radius where cells are mutated + *
  • {@code MUTATE_DEPTH} = grid depth that cells are mutated *
* * @param series the simulation series @@ -56,11 +56,11 @@ public class PatchActionMutate implements Action { public PatchActionMutate(Series series, MiniBox parameters) { // Set loaded parameters. timeDelay = parameters.getInt("TIME_DELAY"); - insertRadius = parameters.getInt("INSERT_RADIUS"); - insertDepth = ((PatchSeries) series).depth; + mutateRadius = parameters.getInt("MUTATE_RADIUS"); + mutateDepth = ((PatchSeries) series).depth; healthyPop = -1; cancerPop = -1; - // grab popuation codes for healthy and cancer cells + // Grab popuation codes for healthy and cancer cells. for (String popName : series.populations.keySet()) { if (series.populations.get(popName).get("CLASS").contains("tissue")) { healthyPop = series.populations.get(popName).getInt("CODE"); @@ -90,7 +90,7 @@ public void step(SimState simstate) { // Get cells at center of simulation. ArrayList coordinates = - sim.locationFactory.getCoordinates(insertRadius, insertDepth); + sim.locationFactory.getCoordinates(mutateRadius, mutateDepth); for (Coordinate coordinate : coordinates) { Bag bag = (Bag) grid.getObjectAt(coordinate.hashCode()); @@ -101,12 +101,13 @@ public void step(SimState simstate) { for (int i = 0; i < bag.numObjs; i++) { // Select old cell and remove from simulation. PatchCell oldCell = (PatchCell) bag.get(i); + // Only remove and mutate if cell is healthy. if (oldCell.getPop() == healthyPop) { Location location = oldCell.getLocation(); grid.removeObject(oldCell, oldCell.getLocation()); oldCell.stop(); - // Create new cell and add to simulation. + // Create new cancer cell and add to simulation. PatchCellContainer cellContainer = new PatchCellContainer( oldCell.getID(), diff --git a/src/arcade/patch/parameter.patch.xml b/src/arcade/patch/parameter.patch.xml index 40824712c..30a685727 100644 --- a/src/arcade/patch/parameter.patch.xml +++ b/src/arcade/patch/parameter.patch.xml @@ -125,6 +125,10 @@ + + + +