From 77e20a4d4c82202c9c8d69444360728f1d6dae8d Mon Sep 17 00:00:00 2001 From: allison-li-1016 Date: Wed, 12 Nov 2025 22:03:57 +0000 Subject: [PATCH 1/5] initial push of files --- .../agent/module/PatchModuleCytotoxicity.java | 16 ++++++++++++ src/arcade/patch/command.patch.xml | 1 + src/arcade/patch/sim/PatchSimulation.java | 25 +++++++++++++++++++ .../patch/sim/output/PatchOutputSaver.java | 24 ++++++++++++++++++ 4 files changed, 66 insertions(+) diff --git a/src/arcade/patch/agent/module/PatchModuleCytotoxicity.java b/src/arcade/patch/agent/module/PatchModuleCytotoxicity.java index f302193a2..35ddf5cf0 100644 --- a/src/arcade/patch/agent/module/PatchModuleCytotoxicity.java +++ b/src/arcade/patch/agent/module/PatchModuleCytotoxicity.java @@ -1,5 +1,7 @@ package arcade.patch.agent.module; +import java.util.HashMap; +import java.util.Map; import ec.util.MersenneTwisterFast; import arcade.core.sim.Simulation; import arcade.core.util.Parameters; @@ -7,6 +9,8 @@ import arcade.patch.agent.cell.PatchCellCART; import arcade.patch.agent.cell.PatchCellTissue; import arcade.patch.agent.process.PatchProcessInflammation; +import arcade.patch.env.location.PatchLocation; +import arcade.patch.sim.PatchSimulation; import static arcade.patch.util.PatchEnums.Domain; import static arcade.patch.util.PatchEnums.State; @@ -68,6 +72,18 @@ public void step(MersenneTwisterFast random, Simulation sim) { tissueCell.setState(State.APOPTOTIC); granzyme--; inflammation.setInternal("granzyme", granzyme); + + // Log cytotoxicity event + PatchSimulation patchSim = (PatchSimulation) sim; + Map eventData = new HashMap<>(); + eventData.put("t-cell-id", cell.getID()); + eventData.put("tissue-cell-id", target.getID()); + eventData.put("tissue-cell-type", target.getPop()); + eventData.put("type", "lysis"); + eventData.put("timestamp", (int) ((PatchSimulation) sim).getSchedule().getTime()); + eventData.put( + "tissue-location", ((PatchLocation) target.getLocation()).getCoordinate()); + patchSim.logEvent(eventData); } } diff --git a/src/arcade/patch/command.patch.xml b/src/arcade/patch/command.patch.xml index 4902b6289..2fda14ff3 100644 --- a/src/arcade/patch/command.patch.xml +++ b/src/arcade/patch/command.patch.xml @@ -1,4 +1,5 @@ + diff --git a/src/arcade/patch/sim/PatchSimulation.java b/src/arcade/patch/sim/PatchSimulation.java index a98b60158..151c54f09 100644 --- a/src/arcade/patch/sim/PatchSimulation.java +++ b/src/arcade/patch/sim/PatchSimulation.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Set; import com.google.gson.reflect.TypeToken; import sim.engine.Schedule; @@ -55,6 +57,9 @@ public abstract class PatchSimulation extends SimState implements Simulation { /** Cell ID tracker. */ int id; + /** List to store events throughout the simulation. */ + private final List> events; + /** Location factory instance for the simulation. */ public final PatchLocationFactory locationFactory; @@ -81,6 +86,7 @@ public PatchSimulation(long seed, Series series) { this.locationFactory = makeLocationFactory(); this.cellFactory = makeCellFactory(); this.latticeFactory = makeLatticeFactory(); + this.events = new ArrayList<>(); } @Override @@ -214,6 +220,25 @@ public Set getAllLocations() { return locations; } + /** + * Log an event to the simulation's event list. + * + * @param eventType the type of event + * @param eventData the event data + */ + public void logEvent(Map event) { + events.add(event); + } + + /** + * Get the list of events logged during the simulation. + * + * @return the list of events + */ + public List> getEvents() { + return new ArrayList<>(events); + } + /** * Called at the start of the simulation to set up agents and environment and schedule actions * and components as needed. diff --git a/src/arcade/patch/sim/output/PatchOutputSaver.java b/src/arcade/patch/sim/output/PatchOutputSaver.java index 0a3447d8f..5cab846c7 100644 --- a/src/arcade/patch/sim/output/PatchOutputSaver.java +++ b/src/arcade/patch/sim/output/PatchOutputSaver.java @@ -1,5 +1,7 @@ package arcade.patch.sim.output; +import java.util.List; +import java.util.Map; import com.google.gson.Gson; import arcade.core.env.component.Component; import arcade.core.sim.Series; @@ -17,6 +19,9 @@ public final class PatchOutputSaver extends OutputSaver { /** {@code true} to save lattices, {@code false} otherwise. */ public boolean saveLattice; + /** {@code true} to save events, {@code false} otherwise. */ + public boolean saveEvents; + /** * Creates an {@code PatchOutputSaver} for the series. * @@ -61,6 +66,22 @@ public void saveLayers(int tick) { write(patch, format(json, FORMAT_ELEMENTS)); } + /** + * Save the collection of events to a JSON. + * + * @param tick the simulation tick + */ + public void saveEventsToFile(int tick) { + if (saveEvents) { + List> events = ((PatchSimulation) sim).getEvents(); + if (!events.isEmpty()) { + String json = gson.toJson(events); + String path = prefix + String.format("_%06d.EVENTS.json", tick); + write(path, format(json, FORMAT_ELEMENTS)); + } + } + } + @Override public void save(int tick) { super.save(tick); @@ -70,5 +91,8 @@ public void save(int tick) { if (saveLattice) { saveLayers(tick); } + if (saveEvents) { + saveEventsToFile(tick); + } } } From 3dea6578af0cd2a0b791e57ba104b4907bb8754f Mon Sep 17 00:00:00 2001 From: allison-li-1016 Date: Wed, 12 Nov 2025 23:14:10 +0000 Subject: [PATCH 2/5] adding event logging to saver --- src/arcade/patch/PatchARCADE.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/arcade/patch/PatchARCADE.java b/src/arcade/patch/PatchARCADE.java index 115823a6b..1759df94b 100644 --- a/src/arcade/patch/PatchARCADE.java +++ b/src/arcade/patch/PatchARCADE.java @@ -34,6 +34,7 @@ public OutputSaver getSaver(Series series) { PatchOutputSaver saver = new PatchOutputSaver(series); saver.saveGraph = settings.contains("SAVE_GRAPH"); saver.saveLattice = settings.contains("SAVE_LAYERS"); + saver.saveEvents = settings.contains("SAVE_EVENTS"); return saver; } } From e1a4e553ba07d0cab72dfa0389d355939f03d78b Mon Sep 17 00:00:00 2001 From: allison-li-1016 Date: Thu, 13 Nov 2025 00:23:11 +0000 Subject: [PATCH 3/5] editing javadoc to have correct method parameter descriptions for logEvent method --- src/arcade/patch/sim/PatchSimulation.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/arcade/patch/sim/PatchSimulation.java b/src/arcade/patch/sim/PatchSimulation.java index 151c54f09..0881dbd7f 100644 --- a/src/arcade/patch/sim/PatchSimulation.java +++ b/src/arcade/patch/sim/PatchSimulation.java @@ -223,8 +223,7 @@ public Set getAllLocations() { /** * Log an event to the simulation's event list. * - * @param eventType the type of event - * @param eventData the event data + * @param event logging information corresponding to the event */ public void logEvent(Map event) { events.add(event); From 07922e96a5adbab93854f9826ca4ef908b9d29bf Mon Sep 17 00:00:00 2001 From: allison-li-1016 Date: Thu, 13 Nov 2025 00:37:03 +0000 Subject: [PATCH 4/5] editing tests to accomodate for new event logging --- .../agent/module/PatchModuleCytotoxicityTest.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/arcade/patch/agent/module/PatchModuleCytotoxicityTest.java b/test/arcade/patch/agent/module/PatchModuleCytotoxicityTest.java index 352bd47fd..fed9cc0f8 100644 --- a/test/arcade/patch/agent/module/PatchModuleCytotoxicityTest.java +++ b/test/arcade/patch/agent/module/PatchModuleCytotoxicityTest.java @@ -8,6 +8,8 @@ import arcade.patch.agent.cell.PatchCellCART; import arcade.patch.agent.cell.PatchCellTissue; import arcade.patch.agent.process.PatchProcessInflammation; +import arcade.patch.env.location.Coordinate; +import arcade.patch.env.location.PatchLocation; import arcade.patch.sim.PatchSimulation; import arcade.patch.util.PatchEnums.State; import static org.mockito.Mockito.*; @@ -24,6 +26,8 @@ public class PatchModuleCytotoxicityTest { private PatchSimulation sim; + private PatchLocation mockLocation; + private MersenneTwisterFast randomMock; @BeforeEach @@ -31,6 +35,8 @@ public final void setUp() { mockCell = mock(PatchCellCART.class); mockTarget = mock(PatchCellTissue.class); mockInflammation = mock(PatchProcessInflammation.class); + mockLocation = mock(PatchLocation.class); + sim = mock(PatchSimulation.class); randomMock = mock(MersenneTwisterFast.class); Parameters parameters = mock(Parameters.class); @@ -41,6 +47,13 @@ public final void setUp() { when(mockCell.getProcess(any())).thenReturn(mockInflammation); when(mockInflammation.getInternal("granzyme")).thenReturn(1.0); when(mockCell.getBoundTarget()).thenReturn(mockTarget); + when(mockCell.getID()).thenReturn(1); + when(mockTarget.getID()).thenReturn(1); + when(mockTarget.getPop()).thenReturn(1); + when(mockTarget.getLocation()).thenReturn(mockLocation); + + when(mockLocation.getCoordinate()).thenReturn(mock(Coordinate.class)); + when(sim.getSchedule().getTime()).thenReturn(0.0); action = new PatchModuleCytotoxicity(mockCell); } From fa7744d202d03651704b435a17271035703118a1 Mon Sep 17 00:00:00 2001 From: allison-li-1016 Date: Thu, 13 Nov 2025 00:40:57 +0000 Subject: [PATCH 5/5] mocking objects correctly so the code can compile --- .../patch/agent/module/PatchModuleCytotoxicityTest.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/arcade/patch/agent/module/PatchModuleCytotoxicityTest.java b/test/arcade/patch/agent/module/PatchModuleCytotoxicityTest.java index fed9cc0f8..ea0e563e0 100644 --- a/test/arcade/patch/agent/module/PatchModuleCytotoxicityTest.java +++ b/test/arcade/patch/agent/module/PatchModuleCytotoxicityTest.java @@ -3,6 +3,7 @@ import java.lang.reflect.Field; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import sim.engine.Schedule; import ec.util.MersenneTwisterFast; import arcade.core.util.Parameters; import arcade.patch.agent.cell.PatchCellCART; @@ -28,6 +29,8 @@ public class PatchModuleCytotoxicityTest { private PatchLocation mockLocation; + private Schedule mockSchedule; + private MersenneTwisterFast randomMock; @BeforeEach @@ -36,6 +39,7 @@ public final void setUp() { mockTarget = mock(PatchCellTissue.class); mockInflammation = mock(PatchProcessInflammation.class); mockLocation = mock(PatchLocation.class); + mockSchedule = mock(Schedule.class); sim = mock(PatchSimulation.class); randomMock = mock(MersenneTwisterFast.class); @@ -53,7 +57,8 @@ public final void setUp() { when(mockTarget.getLocation()).thenReturn(mockLocation); when(mockLocation.getCoordinate()).thenReturn(mock(Coordinate.class)); - when(sim.getSchedule().getTime()).thenReturn(0.0); + when(sim.getSchedule()).thenReturn(mockSchedule); + when(mockSchedule.getTime()).thenReturn(0.0); action = new PatchModuleCytotoxicity(mockCell); }