diff --git a/src/arcade/core/util/EventLog.java b/src/arcade/core/util/EventLog.java new file mode 100644 index 000000000..483992965 --- /dev/null +++ b/src/arcade/core/util/EventLog.java @@ -0,0 +1,37 @@ +package arcade.core.util; + +import java.util.Map; + +/** + * Abstract class representing a logged simulation event. + * + *

{@code EventLog} objects capture specific events that occur during a simulation, recording + * when the event happened and what type of event it was. Subclasses define the specific details of + * each event type. + */ +public abstract class EventLog { + + /** The timestep at which this log was created. */ + public final int timestamp; + + /** A String identifier representing the type of event that was logged. */ + public final String eventType; + + /** + * Constructs an {@code EventLog} with the given timestamp and event type. + * + * @param timestamp the simulation timestep at which the event occurred + * @param eventType a String identifier representing the type of event + */ + public EventLog(int timestamp, String eventType) { + this.timestamp = timestamp; + this.eventType = eventType; + } + + /** + * Returns a map of key-value pairs describing the details of this event. + * + * @return a Map containing the event's details + */ + public abstract Map eventDetails(); +} diff --git a/src/arcade/patch/agent/module/PatchModuleCytotoxicity.java b/src/arcade/patch/agent/module/PatchModuleCytotoxicity.java index 6c4563206..756d2ba4a 100644 --- a/src/arcade/patch/agent/module/PatchModuleCytotoxicity.java +++ b/src/arcade/patch/agent/module/PatchModuleCytotoxicity.java @@ -1,7 +1,5 @@ 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; @@ -11,10 +9,9 @@ import arcade.patch.agent.process.PatchProcessInflammation; import arcade.patch.env.location.PatchLocation; import arcade.patch.sim.PatchSimulation; +import arcade.patch.util.LysisEventLog; import arcade.patch.util.PatchEnums.Domain; import arcade.patch.util.PatchEnums.State; -import static arcade.patch.util.PatchEnums.Domain; -import static arcade.patch.util.PatchEnums.State; /** * Implementation of {@link Module} for killing tissue agents. @@ -77,16 +74,14 @@ public void step(MersenneTwisterFast random, Simulation sim) { // Log cytotoxicity event PatchSimulation patchSim = (PatchSimulation) sim; - Map eventData = new HashMap<>(); - eventData.put("type", "lysis"); - eventData.put("timestamp", (int) ((PatchSimulation) sim).getSchedule().getTime()); - eventData.put("cell-id", cell.getID()); - eventData.put("target-cell-id", target.getID()); - eventData.put("target-cell-type", target.getPop()); - eventData.put( - "target-cell-location", - ((PatchLocation) target.getLocation()).getCoordinate()); - patchSim.logEvent(eventData); + LysisEventLog eventLog = + new LysisEventLog( + (int) sim.getSchedule().getTime(), + cell.getID(), + target.getID(), + target.getPop(), + ((PatchLocation) target.getLocation()).getCoordinate()); + patchSim.logEvent(eventLog.eventDetails()); } } diff --git a/src/arcade/patch/agent/module/PatchModuleProliferation.java b/src/arcade/patch/agent/module/PatchModuleProliferation.java index 0e6917cbb..98dead85d 100644 --- a/src/arcade/patch/agent/module/PatchModuleProliferation.java +++ b/src/arcade/patch/agent/module/PatchModuleProliferation.java @@ -1,7 +1,5 @@ package arcade.patch.agent.module; -import java.util.HashMap; -import java.util.Map; import sim.util.Bag; import ec.util.MersenneTwisterFast; import arcade.core.agent.cell.CellContainer; @@ -17,8 +15,7 @@ import arcade.patch.sim.PatchSimulation; import arcade.patch.util.PatchEnums.Domain; import arcade.patch.util.PatchEnums.State; -import static arcade.patch.util.PatchEnums.Domain; -import static arcade.patch.util.PatchEnums.State; +import arcade.patch.util.ProliferationEventLog; /** * Extension of {@link PatchModule} for proliferation. @@ -133,13 +130,10 @@ public void step(MersenneTwisterFast random, Simulation sim) { // Log proliferation event PatchSimulation patchSim = (PatchSimulation) sim; - Map eventData = new HashMap<>(); - eventData.put("type", "proliferation"); - eventData.put( - "timestamp", (int) ((PatchSimulation) sim).getSchedule().getTime()); - eventData.put("cell-id", cell.getID()); - eventData.put("cycle-length", duration); - patchSim.logEvent(eventData); + ProliferationEventLog eventLog = + new ProliferationEventLog( + (int) sim.getSchedule().getTime(), cell.getID(), duration); + patchSim.logEvent(eventLog.eventDetails()); // TODO: Update environment generator sites. } else { diff --git a/src/arcade/patch/util/LysisEventLog.java b/src/arcade/patch/util/LysisEventLog.java new file mode 100644 index 000000000..c64254ba8 --- /dev/null +++ b/src/arcade/patch/util/LysisEventLog.java @@ -0,0 +1,74 @@ +package arcade.patch.util; + +import java.util.HashMap; +import java.util.Map; +import arcade.core.util.EventLog; +import arcade.patch.env.location.Coordinate; + +/** + * Concrete implementation of {@link EventLog} for lysis events. + * + *

{@code LysisEventLog} objects are created when a CD8 CAR T-cell successfully kills a target + * tissue cell, capturing the ID, type, and location of the target cell at the time of lysis, as + * well as the ID of the CAR T-cell and the time at which lysis occurred. + */ +public class LysisEventLog extends EventLog { + + /** The event type identifier for lysis events. */ + public static final String EVENT_TYPE = "lysis"; + + /** The ID of the cell that performed the lysis. */ + public final int cellId; + + /** The ID of the cell that underwent lysis. */ + public final int targetCellId; + + /** The type of the cell that underwent lysis. */ + public final int targetCellType; + + /** The location of the cell underwent lysis, at the time of lysis. */ + public final Coordinate targetCellLocation; + + /** + * Constructs a {@code LysisEventLog} with the given event details. + * + * @param timestamp the simulation timestep at which lysis occurred + * @param cellId the ID of the cell that performed the lysis + * @param targetCellId the ID of the cell that underwent lysis + * @param targetCellType the type of the cell that underwent lysis + * @param targetCellLocation the location of the cell underwent lysis, at the time of lysis + */ + public LysisEventLog( + int timestamp, + int cellId, + int targetCellId, + int targetCellType, + Coordinate targetCellLocation) { + + super(timestamp, EVENT_TYPE); + this.cellId = cellId; + this.targetCellId = targetCellId; + this.targetCellType = targetCellType; + this.targetCellLocation = targetCellLocation; + } + + /** + * Returns a map of key-value pairs describing the details of this lysis event. + * + *

The map includes the event type, timestamp, the ID of the cell that performed lysis, and + * the ID, type, and location of the target cell that underwent lysis. + * + * @return a Map containing the lysis event's details + */ + @Override + public Map eventDetails() { + Map map = new HashMap<>(); + map.put("event-type", EVENT_TYPE); + map.put("timestamp", super.timestamp); + map.put("cell-id", cellId); + map.put("target-cell-id", targetCellId); + map.put("target-cell-type", targetCellType); + map.put("target-cell-location", targetCellLocation); + return map; + } +} diff --git a/src/arcade/patch/util/ProliferationEventLog.java b/src/arcade/patch/util/ProliferationEventLog.java new file mode 100644 index 000000000..72b7cbb35 --- /dev/null +++ b/src/arcade/patch/util/ProliferationEventLog.java @@ -0,0 +1,57 @@ +package arcade.patch.util; + +import java.util.HashMap; +import java.util.Map; +import arcade.core.util.EventLog; + +/** + * Concrete implementation of {@link EventLog} for proliferation events. + * + *

{@code ProliferationEventLog} objects are created when a cell successfully completes its cell + * cycle and divides, capturing the ID of the dividing cell and the duration of its cell cycle, as + * well as the time at which proliferation occurred. + */ +public class ProliferationEventLog extends EventLog { + + /** The event type identifier for proliferation events. */ + public static final String EVENT_TYPE = "proliferation"; + + /** The ID of the cell that proliferated. */ + public final int cellId; + + /** The duration of the cell cycle from the start of proliferation to division. */ + public final int cycleLength; + + /** + * Constructs a {@code ProliferationEventLog} with the given event details. + * + * @param timestamp the simulation timestep at which proliferation occurred + * @param cellId the ID of the cell that proliferated. + * @param cycleLength the duration of the cell cycle from the start of proliferation to + * division. + */ + public ProliferationEventLog(int timestamp, int cellId, int cycleLength) { + + super(timestamp, EVENT_TYPE); + this.cellId = cellId; + this.cycleLength = cycleLength; + } + + /** + * Returns a map of key-value pairs describing the details of this proliferation event. + * + *

The map includes the event type, timestamp, the ID of the cell that proliferated, and the + * duration of the cell cycle from the start of proliferation to division. + * + * @return a Map containing the proliferation event's details + */ + @Override + public Map eventDetails() { + Map map = new HashMap<>(); + map.put("event-type", EVENT_TYPE); + map.put("timestamp", super.timestamp); + map.put("cell-id", cellId); + map.put("cycle-length", cycleLength); + return map; + } +} diff --git a/test/arcade/core/util/EventLogTest.java b/test/arcade/core/util/EventLogTest.java new file mode 100644 index 000000000..e7319c984 --- /dev/null +++ b/test/arcade/core/util/EventLogTest.java @@ -0,0 +1,27 @@ +package arcade.core.util; + +import java.util.Map; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +public class EventLogTest { + + static class EventLogMock extends EventLog { + EventLogMock(int timestamp, String eventType) { + super(timestamp, eventType); + } + + @Override + public Map eventDetails() { + return mock(Map.class); + } + } + + @Test + public void constructor_called_setsAllFields() { + EventLog log = new EventLogMock(10, "TEST_EVENT"); + assertEquals(10, log.timestamp); + assertEquals("TEST_EVENT", log.eventType); + } +} diff --git a/test/arcade/patch/util/LysisEventLogTest.java b/test/arcade/patch/util/LysisEventLogTest.java new file mode 100644 index 000000000..af4ff5f6f --- /dev/null +++ b/test/arcade/patch/util/LysisEventLogTest.java @@ -0,0 +1,36 @@ +package arcade.patch.util; + +import java.util.Map; +import org.junit.jupiter.api.Test; +import arcade.patch.env.location.Coordinate; +import arcade.patch.env.location.CoordinateXYZ; +import static org.junit.jupiter.api.Assertions.*; + +public class LysisEventLogTest { + + private static final Coordinate COORDINATE = (Coordinate) new CoordinateXYZ(0, 1, 2); + + private static final LysisEventLog LOG = new LysisEventLog(10, 1, 2, 3, COORDINATE); + + @Test + public void constructor_called_setsAllFields() { + assertEquals(10, LOG.timestamp); + assertEquals("lysis", LOG.eventType); + assertEquals(1, LOG.cellId); + assertEquals(2, LOG.targetCellId); + assertEquals(3, LOG.targetCellType); + assertEquals(COORDINATE, LOG.targetCellLocation); + } + + @Test + public void eventDetails_containsAllFields() { + Map details = LOG.eventDetails(); + assertEquals(6, details.size()); + assertEquals("lysis", details.get("event-type")); + assertEquals(10, details.get("timestamp")); + assertEquals(1, details.get("cell-id")); + assertEquals(2, details.get("target-cell-id")); + assertEquals(3, details.get("target-cell-type")); + assertEquals(COORDINATE, details.get("target-cell-location")); + } +} diff --git a/test/arcade/patch/util/ProliferationEventLogTest.java b/test/arcade/patch/util/ProliferationEventLogTest.java new file mode 100644 index 000000000..eb780359d --- /dev/null +++ b/test/arcade/patch/util/ProliferationEventLogTest.java @@ -0,0 +1,28 @@ +package arcade.patch.util; + +import java.util.Map; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +public class ProliferationEventLogTest { + + private static final ProliferationEventLog LOG = new ProliferationEventLog(10, 1, 100); + + @Test + public void constructor_called_setsAllFields() { + assertEquals(10, LOG.timestamp); + assertEquals("proliferation", LOG.eventType); + assertEquals(1, LOG.cellId); + assertEquals(100, LOG.cycleLength); + } + + @Test + public void eventDetails_containsAllFields() { + Map details = LOG.eventDetails(); + assertEquals(4, details.size()); + assertEquals("proliferation", details.get("event-type")); + assertEquals(10, details.get("timestamp")); + assertEquals(1, details.get("cell-id")); + assertEquals(100, details.get("cycle-length")); + } +}