-
Notifications
You must be signed in to change notification settings - Fork 3
CARCADE Refactor 3: Treat Action (+params and tests) #175
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
allison-li-1016
wants to merge
38
commits into
main
Choose a base branch
from
allison/carcade-refactor-treat
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 14 commits
Commits
Show all changes
38 commits
Select commit
Hold shift + click to select a range
5e6d5eb
adding initial classes
allison-li-1016 99fabb5
adding treat action parameters
allison-li-1016 0d1c6b6
linting, removing unnecessary param
allison-li-1016 3bb4786
renaming silly var names
allison-li-1016 f354383
adding option for default
allison-li-1016 9bf8920
renaming variable so it does not literally match the field name
allison-li-1016 92c6151
adding javadoc comments
allison-li-1016 b5e75ec
editing javadoc of the class to be for Treat rather than remove
allison-li-1016 e72f787
I think this was causing issues?
allison-li-1016 37357f2
if/else statement silliness
allison-li-1016 34a1d64
addressing linter comments in test class
allison-li-1016 3404f20
BRUH the indvidiual import statements
allison-li-1016 da46f7e
removing frivolous method
allison-li-1016 f80d49d
removing frivolous comment
allison-li-1016 f870fac
Merge branch 'main' into allison/carcade-refactor-treat
allison-li-1016 b8caa60
removing switch statement to if/else
allison-li-1016 acb5965
we have a parameter for max confluency
allison-li-1016 8e31666
fixing tests
allison-li-1016 cbdae06
changing test to use parameter
allison-li-1016 66287ca
removing the need for 4 lists
allison-li-1016 4fc613c
adding options to treatment
allison-li-1016 77a713c
refactor code into helper methods
allison-li-1016 2b8607b
now the action can actually be run on input files
allison-li-1016 fb816ef
not hardcoding cell codes
allison-li-1016 996c004
add case for edge case
allison-li-1016 f774218
add exception for illegal cell types
allison-li-1016 190d1b2
reverting exception
allison-li-1016 f4ea633
fixing tests, adding edgecase checking
allison-li-1016 5063ced
the tests should be working now
allison-li-1016 0c12f03
removing ratio option so that treat is more similar to insert
allison-li-1016 0c25a1d
refactoring methods such that Treat can now take multiple populations…
allison-li-1016 0f57c6d
I am now not hardcoding the subcoordinates
allison-li-1016 da6240a
cleaning up tests
allison-li-1016 db340a9
cleaning up linting issues
allison-li-1016 3e8d6c0
correctly fetching max density from populations
allison-li-1016 027fa79
editing test to accomadate parameter change
allison-li-1016 128d66f
Merge remote-tracking branch 'origin/main' into allison/carcade-refac…
allison-li-1016 6ae5839
revising locations list, making variable final
allison-li-1016 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,370 @@ | ||
| package arcade.patch.agent.action; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Objects; | ||
| 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.env.location.LocationContainer; | ||
| import arcade.core.sim.Series; | ||
| import arcade.core.sim.Simulation; | ||
| import arcade.core.util.Graph; | ||
| import arcade.core.util.MiniBox; | ||
| import arcade.core.util.Utilities; | ||
| import arcade.patch.agent.cell.PatchCell; | ||
| import arcade.patch.agent.cell.PatchCellCART; | ||
| import arcade.patch.agent.cell.PatchCellContainer; | ||
| import arcade.patch.agent.cell.PatchCellTissue; | ||
| import arcade.patch.env.component.PatchComponentSites; | ||
| import arcade.patch.env.component.PatchComponentSitesGraph; | ||
| import arcade.patch.env.component.PatchComponentSitesGraph.SiteEdge; | ||
| import arcade.patch.env.component.PatchComponentSitesGraphRect; | ||
| import arcade.patch.env.component.PatchComponentSitesGraphTri; | ||
| import arcade.patch.env.component.PatchComponentSitesPattern; | ||
| import arcade.patch.env.component.PatchComponentSitesSource; | ||
| import arcade.patch.env.grid.PatchGrid; | ||
| import arcade.patch.env.location.Coordinate; | ||
| import arcade.patch.env.location.CoordinateXYZ; | ||
| import arcade.patch.env.location.PatchLocation; | ||
| import arcade.patch.env.location.PatchLocationContainer; | ||
| import arcade.patch.sim.PatchSeries; | ||
| import arcade.patch.sim.PatchSimulation; | ||
| import arcade.patch.util.PatchEnums.Ordering; | ||
|
|
||
| /** | ||
| * Implementation of {@link Action} for inserting T cell agents. | ||
| * | ||
| * <p>The action is stepped once after {@code TIME_DELAY}. The {@code TreatAction} will add CAR | ||
| * T-cell agents of specified dose and ratio next to source points or vasculature. | ||
| */ | ||
| public class PatchActionTreat implements Action { | ||
|
|
||
| /** Delay before calling the helper (in minutes). */ | ||
| private final int delay; | ||
|
|
||
| /** Total number of CAR T-cells to treat with. */ | ||
| private final int dose; | ||
|
|
||
| /** List of fraction of each population to treat with. CD4 to CD8 ratio. */ | ||
| private final double treatFrac; | ||
|
|
||
| /** Maximum damage value at which T-cells can spawn next to in source or pattern source. */ | ||
| private double maxDamage; | ||
|
|
||
| /** Minimum radius value at which T- cells can spawn next to in graph source. */ | ||
| private final double minDamageRadius; | ||
|
|
||
| /** Number of agent positions per lattice site. */ | ||
| private int latPositions; | ||
|
|
||
| /** Coordinate system used for simulation. */ | ||
| private final String coord; | ||
|
|
||
| /** List of populations. */ | ||
| private final ArrayList<MiniBox> populations; | ||
|
|
||
| /** parameters. */ | ||
| MiniBox parameters; | ||
|
|
||
| /** Maximum confluency of cells in any location. */ | ||
| final int maxConfluency; | ||
|
|
||
| /** | ||
| * Creates an {@code Action} to add agents after a delay. | ||
| * | ||
| * @param series the simulation series | ||
| * @param parameters the component parameters dictionary | ||
| */ | ||
| public PatchActionTreat(Series series, MiniBox parameters) { | ||
| this.delay = parameters.getInt("TIME_DELAY"); | ||
| this.dose = parameters.getInt("DOSE"); | ||
| this.treatFrac = parameters.getDouble("RATIO"); | ||
| this.maxDamage = parameters.getDouble("MAX_DAMAGE_SEED"); | ||
| this.minDamageRadius = parameters.getDouble("MIN_RADIUS_SEED"); | ||
| this.maxConfluency = 54; | ||
allison-li-1016 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| this.parameters = parameters; | ||
|
|
||
| this.coord = | ||
allison-li-1016 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ((PatchSeries) series).patch.get("GEOMETRY").equalsIgnoreCase("HEX") | ||
| ? "Hex" | ||
| : "Rect"; | ||
| if (coord.equals("Hex")) { | ||
| latPositions = 9; | ||
| } | ||
| if (coord.equals("Rect")) { | ||
| latPositions = 16; | ||
| } | ||
|
|
||
| populations = new ArrayList<>(); | ||
| } | ||
|
|
||
| @Override | ||
| public void schedule(Schedule schedule) { | ||
| schedule.scheduleOnce(delay, Ordering.ACTIONS.ordinal(), this); | ||
| } | ||
|
|
||
| @Override | ||
| public void register(Simulation sim, String population) { | ||
| populations.add(sim.getSeries().populations.get(population)); | ||
| } | ||
|
|
||
| /** | ||
| * Steps the action to insert cells of the treatment population(s). | ||
| * | ||
| * @param simstate the MASON simulation state | ||
| */ | ||
| public void step(SimState simstate) { | ||
allison-li-1016 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| PatchSimulation sim = (PatchSimulation) simstate; | ||
| String type = "null"; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would strongly prefer if you didn't do this. |
||
| PatchGrid grid = (PatchGrid) sim.getGrid(); | ||
| PatchComponentSites comp = (PatchComponentSites) sim.getComponent("SITES"); | ||
|
|
||
| ArrayList<LocationContainer> locs = sim.getLocations(); | ||
|
|
||
| ArrayList<Location> siteLocs0 = new ArrayList<Location>(); | ||
allison-li-1016 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ArrayList<Location> siteLocs1 = new ArrayList<Location>(); | ||
| ArrayList<Location> siteLocs2 = new ArrayList<Location>(); | ||
| ArrayList<Location> siteLocs3 = new ArrayList<Location>(); | ||
| ArrayList<Location> siteLocs = new ArrayList<Location>(); | ||
|
|
||
| // Determine type of sites component implemented. | ||
| if (comp instanceof PatchComponentSitesSource) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should all happen at the abstraction level of PatchComponentSites |
||
| type = "source"; | ||
| } else if (comp instanceof PatchComponentSitesPattern) { | ||
| type = "pattern"; | ||
| } else if (comp instanceof PatchComponentSitesGraph) { | ||
| type = "graph"; | ||
| } | ||
|
|
||
| // Find sites without specified level of damage based on component type. | ||
| switch (type) { | ||
| case "source": | ||
| case "pattern": | ||
| double[][][] damage; | ||
| boolean[][][] sitesLat; | ||
|
|
||
| if (type.equals("source")) { | ||
allison-li-1016 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| damage = ((PatchComponentSitesSource) comp).getDamage(); | ||
| sitesLat = ((PatchComponentSitesSource) comp).getSources(); | ||
| } else { | ||
| damage = ((PatchComponentSitesPattern) comp).getDamage(); | ||
| sitesLat = ((PatchComponentSitesPattern) comp).getPatterns(); | ||
| } | ||
|
|
||
| // Iterate through list of locations and remove locations not next to a site. | ||
| for (LocationContainer l : locs) { | ||
| PatchLocationContainer contain = (PatchLocationContainer) l; | ||
| PatchLocation loc = | ||
| (PatchLocation) | ||
| contain.convert( | ||
| sim.locationFactory, | ||
| sim.cellFactory.createCellForPopulation( | ||
| 0, populations.get(0).getInt("CODE"))); | ||
| CoordinateXYZ coordinate = (CoordinateXYZ) loc.getSubcoordinate(); | ||
| int z = coordinate.z; | ||
| if (sitesLat[z][coordinate.x][coordinate.y] | ||
| && damage[z][coordinate.x][coordinate.y] <= this.maxDamage) { | ||
| addLocationsIntoList(grid, loc, siteLocs0, siteLocs1, siteLocs2, siteLocs3); | ||
| } | ||
| } | ||
| break; | ||
|
|
||
| case "graph": | ||
| Graph graph = ((PatchComponentSitesGraph) comp).getGraph(); | ||
| Bag allEdges = new Bag(graph.getAllEdges()); | ||
| PatchComponentSitesGraph graphSites = (PatchComponentSitesGraph) comp; | ||
|
|
||
| for (Object edgeObj : allEdges) { | ||
| SiteEdge edge = (SiteEdge) edgeObj; | ||
| Bag allEdgeLocs = new Bag(); | ||
| if (Objects.equals(coord, "Hex")) { | ||
| allEdgeLocs.add( | ||
| ((PatchComponentSitesGraphTri) graphSites) | ||
| .getSpan(edge.getFrom(), edge.getTo())); | ||
| } else { | ||
| allEdgeLocs.add( | ||
| ((PatchComponentSitesGraphRect) graphSites) | ||
| .getSpan(edge.getFrom(), edge.getTo())); | ||
| } | ||
|
|
||
| for (Object locObj : allEdgeLocs) { | ||
| Location loc = (Location) locObj; | ||
| if (locs.contains(loc)) { | ||
| if (edge.getRadius() >= minDamageRadius) { | ||
| addLocationsIntoList( | ||
| grid, loc, siteLocs0, siteLocs1, siteLocs2, siteLocs3); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| break; | ||
|
|
||
| default: | ||
| throw new IllegalArgumentException( | ||
| "Invalid component type: " | ||
| + type | ||
| + ". Must be of type source, pattern, or graph."); | ||
| } | ||
|
|
||
| Utilities.shuffleList(siteLocs3, sim.random); | ||
| Utilities.shuffleList(siteLocs2, sim.random); | ||
| Utilities.shuffleList(siteLocs1, sim.random); | ||
| Utilities.shuffleList(siteLocs0, sim.random); | ||
| siteLocs.addAll(siteLocs3); | ||
| siteLocs.addAll(siteLocs2); | ||
| siteLocs.addAll(siteLocs1); | ||
| siteLocs.addAll(siteLocs0); | ||
| insert(siteLocs, simstate); | ||
| } | ||
|
|
||
| /** | ||
| * Helper method to sort locations into lists. | ||
| * | ||
| * @param grid the simulation grid | ||
| * @param loc the current location being looked at | ||
| * @param siteLocs0 the list of locations with 0 agents | ||
| * @param siteLocs1 the list of locations with 1 agent | ||
| * @param siteLocs2 the list of locations with 2 agents | ||
| * @param siteLocs3 the list of locations with 3 agents | ||
| */ | ||
| private void addLocationsIntoList( | ||
| PatchGrid grid, | ||
| Location loc, | ||
| ArrayList<Location> siteLocs0, | ||
| ArrayList<Location> siteLocs1, | ||
| ArrayList<Location> siteLocs2, | ||
| ArrayList<Location> siteLocs3) { | ||
| Bag bag = new Bag(grid.getObjectsAtLocation(loc)); | ||
| int numAgents = bag.numObjs; | ||
|
|
||
| if (numAgents == 0) { | ||
| for (int p = 0; p < latPositions; p++) { | ||
| siteLocs0.add(loc); | ||
| } | ||
| } else if (numAgents == 1) { | ||
| for (int p = 0; p < latPositions; p++) { | ||
| siteLocs1.add(loc); | ||
| } | ||
| } else if (numAgents == 2) { | ||
| for (int p = 0; p < latPositions; p++) { | ||
| siteLocs2.add(loc); | ||
| } | ||
| } else { | ||
| for (int p = 0; p < latPositions; p++) { | ||
| siteLocs3.add(loc); | ||
| } | ||
| } | ||
| // Remove break statement if more than one per hex can appear | ||
| // with break statement, each location can only be added to list once | ||
| // without it, places with more vasc sites get added more times to list | ||
| // break; | ||
| } | ||
|
|
||
| /** | ||
| * Helper method to add cells into the grid. | ||
| * | ||
| * @param coordinates the locations to insert the cells | ||
| * @param simstate the simulation state | ||
| */ | ||
| private void insert(ArrayList<Location> coordinates, SimState simstate) { | ||
| PatchSimulation sim = (PatchSimulation) simstate; | ||
| PatchGrid grid = (PatchGrid) sim.getGrid(); | ||
| Utilities.shuffleList(coordinates, sim.random); | ||
|
|
||
| int cd4Code = 0; | ||
| int cd8Code = 0; | ||
|
|
||
| for (MiniBox population : populations) { | ||
allison-li-1016 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| String className = population.get("CLASS"); | ||
allison-li-1016 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if (className.equals("cart_cd4")) { | ||
| cd4Code = population.getInt("CODE"); | ||
| } | ||
| if (className.equals("cart_cd8")) { | ||
| cd8Code = population.getInt("CODE"); | ||
| } | ||
| } | ||
|
|
||
| for (int i = 0; i < dose; i++) { | ||
|
|
||
| int id = sim.getID(); | ||
|
|
||
| int pop = cd4Code; | ||
|
|
||
| if (sim.random.nextDouble() > treatFrac) { | ||
| pop = cd8Code; | ||
| } | ||
|
|
||
| PatchLocation loc = ((PatchLocation) coordinates.remove(0)); | ||
| Coordinate coordinate = loc.getCoordinate(); | ||
|
|
||
| while (!coordinates.isEmpty() && !checkLocationSpace(loc, grid)) { | ||
| loc = (PatchLocation) coordinates.remove(0); | ||
| } | ||
|
|
||
| if (coordinates.isEmpty()) { | ||
| break; | ||
| } | ||
|
|
||
| PatchLocationContainer locationContainer = new PatchLocationContainer(id, coordinate); | ||
| PatchCellContainer cellContainer = sim.cellFactory.createCellForPopulation(id, pop); | ||
| Location location = locationContainer.convert(sim.locationFactory, cellContainer); | ||
| PatchCell cell = | ||
| (PatchCell) cellContainer.convert(sim.cellFactory, location, sim.random); | ||
| grid.addObject(cell, location); | ||
| cell.schedule(sim.getSchedule()); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Helper method to check if location is available. | ||
| * | ||
| * @param grid the simulation grid | ||
| * @param loc the current location being looked at | ||
| * @return boolean indicating if location is free | ||
| */ | ||
| protected boolean checkLocationSpace(Location loc, PatchGrid grid) { | ||
allison-li-1016 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| boolean available; | ||
| int locMax = this.maxConfluency; | ||
| double locVolume = ((PatchLocation) loc).getVolume(); | ||
| double locArea = ((PatchLocation) loc).getArea(); | ||
|
|
||
| Bag bag = new Bag(grid.getObjectsAtLocation(loc)); | ||
| int n = bag.numObjs; // number of agents in location | ||
|
|
||
| if (n == 0) { | ||
| // no cells in location | ||
| available = true; | ||
| } else if (n >= locMax) { | ||
| // location already full | ||
| available = false; | ||
| } else { | ||
| available = true; | ||
| double totalVol = PatchCell.calculateTotalVolume(bag); | ||
| double currentHeight = totalVol / locArea; | ||
|
|
||
| if (totalVol > locVolume) { | ||
| available = false; | ||
| } | ||
|
|
||
| for (Object cellObj : bag) { | ||
| PatchCell cell = (PatchCell) cellObj; | ||
| if (cell instanceof PatchCellCART) { | ||
| totalVol = | ||
| PatchCell.calculateTotalVolume(bag) | ||
| + parameters.getDouble("T_CELL_VOL_AVG"); | ||
| currentHeight = totalVol / locArea; | ||
| } | ||
| if (cell instanceof PatchCellTissue) { | ||
| if (currentHeight > cell.getCriticalHeight()) { | ||
| available = false; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return available; | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.