From 521c3cf165802640089978155b5aa2b8143b2bad Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 20 Apr 2022 01:01:08 -0400 Subject: [PATCH 1/7] commented code Added general descriptions to methods and parameters. Included step by step description of methods. --- SproutingAssay/sproutAgent.java | 198 +++++++++++++++----------- SproutingAssay/sproutGrid.java | 244 ++++++++++++++++++-------------- 2 files changed, 251 insertions(+), 191 deletions(-) diff --git a/SproutingAssay/sproutAgent.java b/SproutingAssay/sproutAgent.java index adccd2f..f93f7e1 100644 --- a/SproutingAssay/sproutAgent.java +++ b/SproutingAssay/sproutAgent.java @@ -14,17 +14,18 @@ public class sproutAgent extends AgentSQ2D { // DO NOT MODIFY FOR PARAMETERS - public static int HEAD_CELL = 0; - public static int BODY_CELL = 1; - public static int MAP_PARTICLE = 2; - public static int HEPARIN_MAP = 3; + public static int HEAD_CELL = 0; // integer representing type HEAD cell + public static int BODY_CELL = 1; // integer representing type BODY cell + public static int MAP_PARTICLE = 2; // integer representing type MAP_PARTICLE + public static int HEPARIN_MAP = 3; // integer representing type HEPARIN_MAP particle // public static int HEAD_CELL_COLOR = Util.RED; - public static int HEAD_CELL_COLOR = Util.GREEN; // so that you can see head cell locations - public static int BODY_CELL_COLOR = Util.RED; + public static int HEAD_CELL_COLOR = Util.GREEN; // head cells are green for visualization + public static int BODY_CELL_COLOR = Util.RED; // body cells color public static int MAP_PARTICLE_COLOR = Util.RGB(128.0 / 255, 128.0 / 255, 128.0 / 255); // normal MAP; public static int HEPARIN_MAP_COLOR = Util.RGB(0.0 / 255, 0.0 / 255, 217.0 / 255); // Heparin MAP; + // take all parameters for the sproutGrid class. public static double VESSEL_VEGF_INTAKE = sproutGrid.VESSEL_VEGF_INTAKE; public final static int VESSEL_GROWTH_DELAY = sproutGrid.VESSEL_GROWTH_DELAY; public final static double VEGF_SENSITIVITY = sproutGrid.VEGF_SENSITIVITY; @@ -41,41 +42,43 @@ public class sproutAgent extends AgentSQ2D { public final static double HIGH_BRANCHING_PROBABILITY= sproutGrid.HIGH_BRANCHING_PROBABILITY; public final static double REQUIRED_VEGF_GRADIENT_DIFFERENCE = sproutGrid.REQUIRED_VEGF_GRADIENT_DIFFERENCE; - int color; - int type; - int length = 0; - int target; - double migration_rate = sproutGrid.MIGRATION_RATE; - double branching_probability; - int since_last_growth; - int elongation_length; - int ticks_since_direction_change; - int since_last_branch; - public static boolean start_vessel_growth = true; // is set to true when vessels begin to invade - boolean heparin_particle_release_VEGF = true; + int color; // color of cell in visulaization + int type; // cell type (HEAD, BODY, MAP_PARTICLE, HEPARIN_MAP) + int length = 0; // length of the vessel (since starting location) + int target; // simulates elongation direction: cells will pursue a target coordinate in the direction of the highest VEGF concentration + double migration_rate = sproutGrid.MIGRATION_RATE; // endothelial cell migration rate + double branching_probability; // probability that this cell will branch (set by BRANCHING_PROBABILITY in sproutGrid class) + int since_last_growth; // Works to realize a "migration rate". A cell can only elongate one pixel every X ticks, determined by MIGRATION_RATE. This stores the time since its last 1 pixel elongation. + int elongation_length; // threshold length which determines when an endothelial cell must find a new direction to migrate (based on highest VEGF concentration) + int ticks_since_direction_change; // // Works to realize a "persistency time". A cell must persist in 1 direction for X time, determined by PERSISTENCY_TIME. This stores the time since the cell's last redirection. + int since_last_branch; // endothelial cells may branch to more frequently than BRANCH_DELAY_TIME. This stores how long it has been since the vessel's last branch. + public static boolean start_vessel_growth = false; // vessels will not elongate unless start_vessel_growth is true. It is set to true after VESSEL_GROWTH_DELAY has passed. +// boolean heparin_particle_release_VEGF = true; /** * Gets the location with the highest VEGF concentration within the cell's radius of sight - * - * @return returns the location of highest concentration of VEGF (if there are multiple, then it will return a random one) + * @return returns the location of highest concentration of VEGF (if there are multiple highest, then it will return a random one of them) */ public int HighestConcentrationVEGF() { assert G != null; int VEGF_options = G.MapEmptyHood(G.VEGFHood, Isq()); // gets the cell's range of detecting VEGF + // Get the locations around the cell with highest concentration VEGF double maxConcentration = -1; // holds the max concentration so far (initially -1) ArrayList maxConcentrationLocations = new ArrayList<>(); // holds the coordinates for the locations of highest concentration for (int i = 0; i < VEGF_options; i++) { // Iterates through all nearby coordinates - double test_concentration = G.VEGF.Get(G.VEGFHood[i]); // gets the concentration at a point (test concentration) - if ((test_concentration > maxConcentration) && (test_concentration > VEGF_SENSITIVITY)) { // if the concentration here is larger than the max so far (maxConcentration) + double test_concentration = G.VEGF.Get(G.VEGFHood[i]); // gets the concentration at the nearby coordinate (called test_concentration) + if ((test_concentration > maxConcentration) && (test_concentration > VEGF_SENSITIVITY)) { // if the concentration here is larger than the max so far (called maxConcentration), maxConcentration = test_concentration; // then set that concentration as the new max maxConcentrationLocations.clear(); // clear the old locations of highest concentration maxConcentrationLocations.add(G.VEGFHood[i]); // add this location to the list of highest concentrations - } else if (test_concentration == maxConcentration) { // if the test concentration is equal to the current max concentration - maxConcentrationLocations.add(G.VEGFHood[i]); // just add the coordinate to the running list of locations of highest concentration + } else if (test_concentration == maxConcentration) { // if the test_concentration is equal to the current max concentration + maxConcentrationLocations.add(G.VEGFHood[i]); // add the coordinate to the running list of locations of highest concentration } } + + // if there were no highest concentrations, or if the concentration is 0, then return 0 (meaning highest VEGF coordinate was not found) if (maxConcentrationLocations.size() < 1) { // if there were no locations of highest concentration at all return 0; } else if (maxConcentration <= 0) { // if max concentration was 0 @@ -86,46 +89,48 @@ public int HighestConcentrationVEGF() { } /** - * Given an int location of a target, this function will find best location for next cell duplication to move towards this location + * Given the location of a target as an int, this function will find best location for next cell duplication to move towards this location + * (i.e. gives the next location for the cell to migrate towards VEGF, chemotaxis) * - * @param target location of nearest VEGF - * @return int location to grow closer to target + * @param target location in the direction of the highest VEGF concentration + * @return int location that allows the vessel to grow closer to target (highest VEGF direction) */ public int HoodClosestToTarget(int target) { - int minDistance = Integer.MAX_VALUE; // gets updated with each location check (holds the minimum distance of a coordinate to the target) - ArrayList mincoordint = new ArrayList<>(); // closest points that are in the cell neighborhood (as an int) + int minDistance = Integer.MAX_VALUE; // holds the minimum distance of a coordinate to the target (gets updated with each location check) + ArrayList mincoordint = new ArrayList<>(); // keeps track of the candidates for the best migration location toward the target assert G != null; - int options = G.MapEmptyHood(G.divHood, Isq()); // open areas around cell + int options = G.MapEmptyHood(G.divHood, Isq()); // open areas around cell are found + // find open areas (since cells can only migrate to empty areas) for (int i = 0; i < options; i++) { // iterate thorough the open areas - int MAPcount = 0; // tally of MAP present + int MAPcount = 0; // tally of how many MAP/HEP_MAP present for (sproutAgent cell : G.IterAgents(G.divHood[i])) { // iterate through all the cells at that coordinate - if ((cell.type == MAP_PARTICLE) || (cell.type == HEPARIN_MAP)) { // if there is MAP GEL there + if ((cell.type == MAP_PARTICLE) || (cell.type == HEPARIN_MAP)) { // if there is MAP/HEP_MAP there MAPcount++; // then keep track that there was a particle there. - break; + break; // and stop looking, since this space is occupied } } if (MAPcount == 0) { // If there were no occlusions with MAP particles, then check to see if it is close to the target point - int[] hoodPoint = {G.ItoX(G.divHood[i]), G.ItoY(G.divHood[i])}; // This is the location of the point in question (neighborhood point - // gets the distance from neighborhood point to target + int[] hoodPoint = {G.ItoX(G.divHood[i]), G.ItoY(G.divHood[i])}; // this is the location that we are checking is/isn't a valid migration location + + // get the distance from the candidate migration point to target int dist = Math.abs((int) Math.hypot(G.ItoX(target) - hoodPoint[0], G.ItoY(target) - hoodPoint[1])); - // keeps a list of the neighborhood points closest to the VEGF - if (dist < minDistance) { // if the neighborhood point distance is closer than the one before, then... + if (dist < minDistance) { // if the candidate point's distance is closer than the current minimum distance, then minDistance = dist; // the minimum distance is updated to the new closest distance - mincoordint.clear();// the old list is cleared + mincoordint.clear();// the old list of candidates is cleared mincoordint.add(G.I(hoodPoint[0], hoodPoint[1])); // and the new closest point is added to the empty list } else if (dist == minDistance) { // But, if the point is just as close as the ones on the list - mincoordint.add(G.I(hoodPoint[0], hoodPoint[1])); // it is added to the list of the hood points that are just as close + mincoordint.add(G.I(hoodPoint[0], hoodPoint[1])); // it is added to the list of the candidate points that are just as close } } } - if (mincoordint.size() == 0) { // if there are no sufficiently strong VEGF nearby, then... + if (mincoordint.size() == 0) { // if there are no best locations to migrate, then return 0; // return 0 } - return mincoordint.get((int) (Math.random() * mincoordint.size())); // otherwise, return a random hood point on the list + return mincoordint.get((int) (Math.random() * mincoordint.size())); // otherwise, return a random point on the list of minimum distance coordinates } /** @@ -146,12 +151,12 @@ public void Init(int type) { this.color = MAP_PARTICLE_COLOR; // normal MAP } else if (type == HEPARIN_MAP) { this.color = HEPARIN_MAP_COLOR; // Heparin MAP - this.heparin_particle_release_VEGF = true; +// this.heparin_particle_release_VEGF = true; } } /** - * Initializes a vessel cell, but passes on arrival state to next generations. + * Initializes a vessel cell. * * @param type type of cell/particle * @param length the current length of the vessel @@ -167,11 +172,15 @@ public void InitVessel(int type, int length) { } /** - * Initializes a cell with color and type, + * Initializes a vessel cell with extra parameters allowing for implementation of migration rate * - * @param type type of cell/particle - * @param length the current length of the vessel - * @param target the location where the vessel is growing towards + * @param type The celltype of the cell to be initialized + * @param length The current length of the vessel up to this cell + * @param target The target that the vessel is growing towards (highest concentration of VEGF) + * @param since_last_elongation the time since the cell has grown a pixel (used to implement migration rate) + * @param ticks_since_direction_change the amount of time since the vessel has last changed direction + * @param elongation_length the current length since last direction change (current length traveled in current target direction) + * @param since_last_branch the time since the last the the vessel has branched */ public void InitVesselMigrationRate(int type, int length, int target, int since_last_elongation, int ticks_since_direction_change, int elongation_length, int since_last_branch) { this.type = type; @@ -185,14 +194,14 @@ public void InitVesselMigrationRate(int type, int length, int target, int since_ } /** - * Calls cell to consume appropriate amount of VEGF + * Calls vessel cells to consume appropriate amount of VEGF specified by VESSEL_VEGF_INTAKE */ public void ConsumeVEGF() { assert G != null; if ((G.VEGF.Get(Isq()) >= 0) && ((type == HEAD_CELL) || (type == BODY_CELL))) { // Head cells and body cells consume VEGF G.VEGF.Add(Isq(), -VESSEL_VEGF_INTAKE); - if (G.VEGF.Get(Isq()) < 0){ - G.VEGF.Set(Isq(), 0); + if (G.VEGF.Get(Isq()) < 0){ // if the VEGF concentration is less than 0, + G.VEGF.Set(Isq(), 0); // then set it to zero. } } } @@ -202,23 +211,30 @@ public void ConsumeVEGF() { */ public void CheckStartVesselGrowth() { assert G != null; - if (G.GetTick() == VESSEL_GROWTH_DELAY) { // If the VESSEL_GROWTH_DELAY has passed, then vessels can begin to grow - start_vessel_growth = true; + if (G.GetTick() >= VESSEL_GROWTH_DELAY && !start_vessel_growth) { // If the VESSEL_GROWTH_DELAY has passed and start_vessel_growth is false, then, + start_vessel_growth = true; // vessels can begin to grow +// System.out.println(G.GetTick()); // can be used to check what tick the vessels begin to grow (keep in mind that these are ticks, and not hours) } } + /** + * Replicates media exchange, simulating HEP_MAP sequestering and release of VEGF provided by fresh media, exchanged + * as specificed by MEDIA_EXCHANGE_SCHEDULE + */ public void ExchangeMedia(){ assert G != null; - if (G.GetTick()%MEDIA_EXCHANGE_SCHEDULE_TICKS == 0){ - if (type == HEPARIN_MAP){ - G.VEGF.Set(Isq(), HEP_MAP_VEGF_RELEASE); + if (G.GetTick()%MEDIA_EXCHANGE_SCHEDULE_TICKS == 0){ // if the current tick is a multiple of MEDIA_EXCHANGE_SCHEDULE_TICKS, then, + if (type == HEPARIN_MAP){ // if the cell is of type HEPARIN_MAP + G.VEGF.Set(Isq(), HEP_MAP_VEGF_RELEASE); // set the particle to release VEGF as prescribed by HEP_MAP_VEGF_RELEASE } } } /** - * Performs vessel elongation more analogous to that specified in Mehdizadeh et al. Functions by growth rate + * Performs vessel elongation analogous to that specified in Mehdizadeh et al. The vessel will elongate towards the + * highest concentration VEGF. This function incorporates elongation, chemotaxis, and branching. (see comments for + * function details) */ public void VesselGrowthByRate() { // checks of G is null (just for safely) @@ -229,16 +245,18 @@ public void VesselGrowthByRate() { return; } + // if the persistency time has not been reached, then increment it by 1 if (ticks_since_direction_change <= PERSISTENCY_TIME) { ticks_since_direction_change += 1; } + // if the time since last branch has not been reached, then increment it by 1 if (since_last_branch <= BRANCH_DELAY_TIME){ since_last_branch += 1; } // Makes the vessel grow at a certain rate (i.e. 30 microns/hr) (this is NOT elongation length!!!) - if (since_last_growth < migration_rate){ // if it's not yet time to migrate, then don't migrate yet. + if (since_last_growth < migration_rate){ // if it's not yet time to migrate, then don't migrate yet and stop any cell activity. since_last_growth += 1; return; } @@ -248,28 +266,31 @@ public void VesselGrowthByRate() { return; } - if (start_vessel_growth) { - int cellDivLocation; // stores the int version of the location where the cell will grow to + if (start_vessel_growth) { // if VESSEL_GROWTH_DELAY has passed + + int cellDivLocation; // (stores the the location where the cell will grow to) + + // if persistency time has been reached, and the elongation length has been reached, then find a new direction to migrate. if ((( ticks_since_direction_change >= PERSISTENCY_TIME) && (elongation_length >= MAX_ELONGATION_LENGTH)) || (target == 0)){ int highestConcentrationCoord = HighestConcentrationVEGF(); // find new target location: the location in the sight radius with the highest VEGF highestConcentrationCoord = CalculateTargetScaleTargetCoord(highestConcentrationCoord); // find a point in the same direction, but very far away, so you won't reach it: want to persist in that direction cellDivLocation = HoodClosestToTarget(highestConcentrationCoord); // and find the closest adjacent coordinate in the direction towards the highestConcentrationCoord if ((highestConcentrationCoord > 0) && (cellDivLocation > 0) && (G.PopAt(cellDivLocation) == 0)){ // If there is a location of highest concentration and there is an open adjacent spot... (the values will be 0 if none were found) - if (!(G.VEGF.Get(Isq()) + REQUIRED_VEGF_GRADIENT_DIFFERENCE <= G.VEGF.Get(cellDivLocation))){ + if (!(G.VEGF.Get(Isq()) + REQUIRED_VEGF_GRADIENT_DIFFERENCE <= G.VEGF.Get(cellDivLocation))){ // check if there is enough difference in VEGF between current location and target growth spot, (if not, then end) return; } - G.NewAgentSQ(cellDivLocation).InitVesselMigrationRate(HEAD_CELL, this.length + 1, highestConcentrationCoord, since_last_growth, 0, 1, since_last_branch); // make a new head cell at cellDivLocation + G.NewAgentSQ(cellDivLocation).InitVesselMigrationRate(HEAD_CELL, this.length + 1, highestConcentrationCoord, since_last_growth, 0, 1, since_last_branch); // make a new head cell at cellDivLocation (vessel elongates) InitVessel(BODY_CELL, this.length); // and make the old cell a body cell } // branching if(G.rng.Double() < branching_probability && since_last_branch > BRANCH_DELAY_TIME){ // if the cell happens to branch (branching probability is a parameter of the cell, and is modified by a function CalculateBranchingProbability) - // the options for branching locations around the cell + // find the options for branching locations around the cell int options = MapEmptyHood(G.divHood); if (options >= 1) { // if there is an open nearby location, then branch there - cellDivLocation = G.divHood[G.rng.Int(options)]; - if (G.PopAt(cellDivLocation) == 0){ - if (!(G.VEGF.Get(Isq()) + REQUIRED_VEGF_GRADIENT_DIFFERENCE <= G.VEGF.Get(cellDivLocation))){ + cellDivLocation = G.divHood[G.rng.Int(options)]; // choose a random empty location + if (G.PopAt(cellDivLocation) == 0){ // if there are no agents at that location + if (!(G.VEGF.Get(Isq()) + REQUIRED_VEGF_GRADIENT_DIFFERENCE <= G.VEGF.Get(cellDivLocation))){ // if there is not a large enough difference of VEGF between the current location and the branching location, then do not branch. Otherwise, return; } G.NewAgentSQ(cellDivLocation).InitVesselMigrationRate(HEAD_CELL, this.length + 1, 0, 0, this.ticks_since_direction_change =0, 1, 0); // make a new head cell at the branching location @@ -277,40 +298,49 @@ public void VesselGrowthByRate() { } } } - } else if (elongation_length < MAX_ELONGATION_LENGTH){ //added else if - // if not at max length and not at it's target location, then it has a target that it needs to get to. + } else if (elongation_length < MAX_ELONGATION_LENGTH){ // if the cell has not yet reached it's max elongation length, then continue to elongate cellDivLocation = HoodClosestToTarget(target); // find an open adjacent location closest to the target - if (G.PopAt(cellDivLocation) == 0) { - if (!(G.VEGF.Get(Isq()) + REQUIRED_VEGF_GRADIENT_DIFFERENCE <= G.VEGF.Get(cellDivLocation))){ + if (G.PopAt(cellDivLocation) == 0) { // double check that there are no other agents at that location + if (!(G.VEGF.Get(Isq()) + REQUIRED_VEGF_GRADIENT_DIFFERENCE <= G.VEGF.Get(cellDivLocation))){ // if the VEGF concentration difference between the current location and the elongation location is insufficient, then stop. Else, return; } - G.NewAgentSQ(cellDivLocation).InitVesselMigrationRate(HEAD_CELL, this.length + 1, target, since_last_growth, ticks_since_direction_change, elongation_length + 1, since_last_branch); // make a new cell there LP Question: how do I make ticks_since_direction change= 0 + G.NewAgentSQ(cellDivLocation).InitVesselMigrationRate(HEAD_CELL, this.length + 1, target, since_last_growth, ticks_since_direction_change, elongation_length + 1, since_last_branch); // make a new cell there InitVessel(BODY_CELL, this.length); // make the old cell a body cell } } } } + /** + * This function takes in a target coordinate of a cell and views it in relation with that cell. It then treats it + * a vector, and scales the coordinate such that it is 10 times further, but still in the same direction + * in relation to the cell. + * @param targetCoord the original coordinate target of a cell + * @return a coordinate in the same direction, but scaled to be a larger distance than the original target. + */ public int CalculateTargetScaleTargetCoord(int targetCoord){ assert G != null; - int scale = 10; - int target_x = G.ItoX(targetCoord); - int target_y = G.ItoY(targetCoord); - int current_x = Xsq(); - int current_y = Ysq(); - int scaled_vector_x = scale*(target_x-current_x); - int scaled_vector_y = scale*(target_y-current_y); - int[] new_target = {(scaled_vector_x+current_x),(scaled_vector_y+current_y)}; - while (!G.In(new_target[0], new_target[1])){ + int scale = 10; // initialize scale factor + int target_x = G.ItoX(targetCoord); // the target X coordinate + int target_y = G.ItoY(targetCoord); // the target y coordinate + int current_x = Xsq(); // the current X coordinate of the cell + int current_y = Ysq(); // the current y coordinate of the cell + int scaled_vector_x = scale*(target_x-current_x); // takes the difference of the target and current x coordinates and scales the difference by the scale factor + int scaled_vector_y = scale*(target_y-current_y); // takes the difference of the target and current y coordinates and scales the difference by the scale factor + int[] new_target = {(scaled_vector_x+current_x),(scaled_vector_y+current_y)}; // reapplies the scaled to the current x and y coordinates + while (!G.In(new_target[0], new_target[1])){ // if the scale is too large, then repeat the steps but for a smaller scale value scale -= 1; scaled_vector_x = scale*(target_x-current_x); scaled_vector_y = scale*(target_y-current_y); new_target[0] = scaled_vector_x+current_x; new_target[1] = (scaled_vector_y+current_y); } - return G.I(new_target[0], new_target[1]); + return G.I(new_target[0], new_target[1]); // return the scaled coordinate } + /** + * Based on the current quantity of VEGF at the location of the cell, the relative branching probability is applied to the cell + */ public void CalculateBranchingProbability(){ assert G != null; if (G.VEGF.Get(Isq()) < LOW_MED_VEGF_THRESHOLD){ @@ -322,9 +352,12 @@ public void CalculateBranchingProbability(){ } } + /** + * Implements VEGF degradation such that at every 90 ticks, VEGF degrades at prescribed VEGF_DEGRADATION_RATE + */ public void VEGFDegrade() { assert G != null; - if (G.VEGF.Get(Isq()) >= 0 && G.GetTick()%90 == 0) { // VEGF degrades + if (G.VEGF.Get(Isq()) >= 0 && G.GetTick()%90 == 0) { // VEGF degrades every 90 ticks G.VEGF.Add(Isq(), -(G.VEGF.Get(Isq()))* VEGF_DEGRADATION_RATE); //G.VEGF.Add(Isq(), - VEGF_DEGRADATION_RATE); if (G.VEGF.Get(Isq()) < 0){ @@ -334,7 +367,8 @@ public void VEGFDegrade() { } /** - * Steps an agent, can be used on all implemented agents + * Calls all functions for a single time tick. This function is called in sproutGrid to initiate all cells to take + * action at each tick. */ public void StepCell() { diff --git a/SproutingAssay/sproutGrid.java b/SproutingAssay/sproutGrid.java index 2816668..8bd90f7 100644 --- a/SproutingAssay/sproutGrid.java +++ b/SproutingAssay/sproutGrid.java @@ -28,50 +28,51 @@ public class sproutGrid extends AgentGrid2D { // BATCH RUNS - public final static boolean BATCH_RUN = true; + public final static boolean BATCH_RUN = true; // sets whether a single trial run is performed or a batch run. Only BATCH RUNS use trials. + // NOTE: if single trial run, will only run on the first percentage in HEPARIN_PERCENTAGES public final static boolean EXPORT_DATA = true; public final static boolean EXPORT_TIME_DATA = true; // (note that EXPORT_DATA must also be true as well to export time data) public final static boolean EXPORT_HEAD_CELL_DISTANCE_DATA = true; // (note that EXPORT_DATA must also be true as well to export distance data) - public final static int TRIALS = 500; - public final static double[] HEPARIN_PERCENTAGES = {0.28}; - public final static double FOLD_CHANGE_SAMPLE_TIME = 0.25 ; // every ___ hours + public final static int TRIALS = 500; // number of trials (only for BATCH RUNS) + public final static double[] HEPARIN_PERCENTAGES = {0.28}; // percent HEPARIN ISLANDS that will be inilialized in the scaffold + public final static double FOLD_CHANGE_SAMPLE_TIME = 0.25 ; // sampling interval for fold change data export (HOURS) //public final static double[] DIFFUSION_COEFFICIENT = new double[]{0.01, 0.04, 0.07, 0.10, 0.13}; // VESSEL PARAMETERS FIXED! - public static final int CULTURE_RADIUS_MICRONS = 140; // radius of the initial spheroid in microns - public final static int SIGHT_RADIUS_MICRONS = 20; // how far a EC can sense in microns - public final static double PERSISTENCY_TIME_HOURS = 3; // time between a EC changes direction in hours - public static final int MAX_ELONGATION_LENGTH_MICRONS = 40; // microns - public final static int MIGRATION_RATE_MICRONS_PER_HOUR = 30; // microns/hr - public final static double BRANCH_DELAY_TIME_HOURS = 6; // minimum time between branching (hours) + public static final int CULTURE_RADIUS_MICRONS = 140; // radius of the initial assay spheroid (MICRONS) + public final static int SIGHT_RADIUS_MICRONS = 20; // how far a EC can sense (MICRONS) + public final static double PERSISTENCY_TIME_HOURS = 3; // time between changes direction for EC migration (HOURS) + public static final int MAX_ELONGATION_LENGTH_MICRONS = 40; // max elongation length of a EC (MICRONS) + public final static int MIGRATION_RATE_MICRONS_PER_HOUR = 30; // rate of elongation for EC head cells (MICRONS/HOUR) + public final static double BRANCH_DELAY_TIME_HOURS = 6; // required delay time between EC branching in (HOURS) // VESSEL PARAMETERS NEEDING PARAMETERIZED AND SENSITIVITY ANALYSIS - public final static double VEGF_SENSITIVITY = 0.03; // 0.03 baseline minimum VEGF to attract cell growth - public static double VESSEL_VEGF_INTAKE = 0.001; // percent of how much of the present VEGF is consumed when a blood vessel is nearby - public final static double INITIAL_PERCENT_HEAD_CELLS = 0.07; // probability of initializing an off branch from wound site - public final static double VEGF_DEGRADATION_RATE = 0.5;// - public final static double REQUIRED_VEGF_GRADIENT_DIFFERENCE = 0.005; // Difference required between a location and the next division location in order to elongate + public final static double VEGF_SENSITIVITY = 0.03; // minimal VEGF required to be sensed by EC (0.03 baseline minimum VEGF to attract cell growth) + public static double VESSEL_VEGF_INTAKE = 0.001; // percent of how much of the current VEGF is consumed when a blood vessel is present in a cell + public final static double INITIAL_PERCENT_HEAD_CELLS = 0.07; // probability during spheroid initiation that any edge cell of the spheroid will be of type HEAD + public final static double VEGF_DEGRADATION_RATE = 0.5; // rate at which VEGF degrades + public final static double REQUIRED_VEGF_GRADIENT_DIFFERENCE = 0.005; // Difference of VEGF concentration required between a HEAD cell's location and its next division location in order to elongate // BRANCHING PROBABILITY AND THRESHOLDS_ PROBABILITIES NEED PARAMETERIZED BUT COULD STAY FIXED public final static double LOW_BRANCHING_PROBABILITY= 0.4; // probability of branching while VEGF is under LOW_MED_VEGF_THRESHOLD - public final static double LOW_MED_VEGF_THRESHOLD = 0.05; + public final static double LOW_MED_VEGF_THRESHOLD = 0.05; // the threshold between LOW and MED branching probability public final static double MED_BRANCHING_PROBABILITY= 0.55; // probability of branching while VEGF is between LOW_MED_VEGF_THRESHOLD and MED_HIGH_VEGF_THRESHOLD - public final static double MED_HIGH_VEGF_THRESHOLD = 0.25; + public final static double MED_HIGH_VEGF_THRESHOLD = 0.25; // the threshold between MED and HIGH branching probability public final static double HIGH_BRANCHING_PROBABILITY= 0.9; // probability of branching while VEGF is above MED_HIGH_VEGF_THRESHOLD // MAP GEL PARAMETERS - FIXED - public final static int MAP_RADIUS_MICRONS = 40; // microns - public final static double MAP_SPACING_MICRONS = 15; // microns - public final static double HEP_MAP_VEGF_RELEASE = 1; // how much VEGF to add per media exchange + public final static int MAP_RADIUS_MICRONS = 40; // radius of MAP particles (MICRONS) + public final static double MAP_SPACING_MICRONS = 15; // minimum space between the edges of two MAP particles (MICRONS) + public final static double HEP_MAP_VEGF_RELEASE = 1; // amount of VEGF added per media exchange public final static double MEDIA_EXCHANGE_SCHEDULE_HOURS = 0.3571; // exchange media to refresh VEGF every __ hours //public final static double HEPARIN_PERCENTAGES = 0.1; // percentage of heparin particles // MAIN METHOD PARAMETERS - FIXED - public final static int x_MICRONS = 4000; // microns - public final static int y_MICRONS = 4000; // microns - public final static int SCALE_FACTOR = 2; - public final static int TICK_PAUSE = 1; - public final static int RUNTIME_HOURS = 24; // how long will the simulation run? - public final static double VESSEL_GROWTH_DELAY_HOURS = 2; + public final static int x_MICRONS = 4000; // x dimension of the wound-space (MICRONS) + public final static int y_MICRONS = 4000; // y dimension of the wound-space (MICRONS) + public final static int SCALE_FACTOR = 2; // for visualization: changes the scale of the pixels + public final static int TICK_PAUSE = 1; // for model runtime: changes the amount of time between each tick + public final static int RUNTIME_HOURS = 24; // the timeframe that the simulation models (HOURS) + public final static double VESSEL_GROWTH_DELAY_HOURS = 2; // the delay between model start and vessel growth // DIFFUSION - NEEDS PARAMETERIZED public final static double DIFFUSION_COEFFICIENT = 0.733; // diffusion coefficient @@ -86,23 +87,23 @@ public class sproutGrid extends AgentGrid2D { // vessels public static final int CULTURE_RADIUS = CULTURE_RADIUS_MICRONS/ MICRONS_PER_PIXEL; - public final static int SIGHT_RADIUS = SIGHT_RADIUS_MICRONS/ MICRONS_PER_PIXEL; // radius to detect VEGF + public final static int SIGHT_RADIUS = SIGHT_RADIUS_MICRONS/ MICRONS_PER_PIXEL; public static final int MAX_ELONGATION_LENGTH = MAX_ELONGATION_LENGTH_MICRONS/ MICRONS_PER_PIXEL; public final static double MIGRATION_RATE = 1/((MIGRATION_RATE_MICRONS_PER_HOUR/(double) MICRONS_PER_PIXEL)*(1/(double)TICKS_PER_HOUR)); // convert to "elongate every ___ ticks" public final static double PERSISTENCY_TIME = PERSISTENCY_TIME_HOURS * TICKS_PER_HOUR; public final static int BRANCH_DELAY_TIME = (int)(BRANCH_DELAY_TIME_HOURS * TICKS_PER_HOUR); // particles - public final static int MAP_RADIUS = MAP_RADIUS_MICRONS/ MICRONS_PER_PIXEL; // radius of MAP particle - public final static double MAP_SPACING = (double)(MAP_RADIUS_MICRONS)/ MICRONS_PER_PIXEL + MAP_SPACING_MICRONS/ MICRONS_PER_PIXEL; // spacing radius between MAP gel centers + public final static int MAP_RADIUS = MAP_RADIUS_MICRONS/ MICRONS_PER_PIXEL; + public final static double MAP_SPACING = (double)(MAP_RADIUS_MICRONS)/ MICRONS_PER_PIXEL + MAP_SPACING_MICRONS/ MICRONS_PER_PIXEL; public final static double MEDIA_EXCHANGE_SCHEDULE_TICKS = MEDIA_EXCHANGE_SCHEDULE_HOURS*TICKS_PER_HOUR; // grid - public final static int x = x_MICRONS/ MICRONS_PER_PIXEL; // microns - public final static int y = y_MICRONS/ MICRONS_PER_PIXEL; // microns + public final static int x = x_MICRONS/ MICRONS_PER_PIXEL; + public final static int y = y_MICRONS/ MICRONS_PER_PIXEL; // runtime - public final static int TIMESTEPS = RUNTIME_HOURS*TICKS_PER_HOUR; // how long will the simulation run? + public final static int TIMESTEPS = RUNTIME_HOURS*TICKS_PER_HOUR; public final static int VESSEL_GROWTH_DELAY = (int)(VESSEL_GROWTH_DELAY_HOURS*TICKS_PER_HOUR); public final static int FOLD_CHANGE_SAMPLE_TICKS = (int)(FOLD_CHANGE_SAMPLE_TIME*TICKS_PER_HOUR); // take a sample every ____ ticks @@ -110,14 +111,15 @@ public class sproutGrid extends AgentGrid2D { ////////////////////////////////////////////// MISC VARIABLES //////////////////////////////////////////////// - public static int HEAD_CELL = sproutAgent.HEAD_CELL; - public static int BODY_CELL = sproutAgent.BODY_CELL; + public static int HEAD_CELL = sproutAgent.HEAD_CELL; // Head cell type + public static int BODY_CELL = sproutAgent.BODY_CELL; // Body cell type Rand rng = new Rand(); - int[] divHood = Util.VonNeumannHood(false); // neighborhood for division - int[] VEGFHood = Util.CircleHood(false, SIGHT_RADIUS); // how far can you see VEGF + int[] divHood = Util.VonNeumannHood(false); // neighborhood for division: cells can only divide/elongate to adjacent cells (cardinal directions) + int[] VEGFHood = Util.CircleHood(false, SIGHT_RADIUS); // the range that cells can see VEGF concentrations (for chemotaxis) int[] MAP_rad = Util.CircleHood(true, MAP_RADIUS); // radius of MAP particles - int[] MAP_space = Util.CircleHood(true, MAP_SPACING); // "cushion" between MAP particles + int[] MAP_space = Util.CircleHood(true, MAP_SPACING); // "cushion" between MAP particles (dictates the the area around the center of a MAP particle of + // of radius equal to MAP_RADIUS + MAP_SPACING) PDEGrid2D VEGF; // Initialize PDE Grid @@ -141,7 +143,7 @@ public class sproutGrid extends AgentGrid2D { /** - * Heparin Grid constructor + * Heparin Grid constructor. The grid created will be the vessel where all agents will reside. * @param x x dimension of grid * @param y y dimension of grid */ @@ -152,7 +154,14 @@ public sproutGrid(int x, int y) { // Constructor for the agent grid /** - * Steps all cells + * Calls each cell to take actions by calling the StepCell() method of the sproutAgent class. + * The sproutAgent class will then dictate what actions each cell will take depending on cell + * type and its environment. + * + * The tick timer is incremented to advance the time. + * + * This function also calls the VEGF diffusion to iterate and update. (without this, no diffusion + * would occur.) */ public void StepCells(){ // steps all the cells for (sproutAgent endoCell : this) { @@ -165,10 +174,11 @@ public void StepCells(){ // steps all the cells /** - * Draws the PDE window - * @param windows the window to draw the PDE in + * Draws the PDE window. This function provides purely visual functionality + * by visualizing PDE diffusion of VEGF + * @param windows the window that the visualization will be drawn in */ - public void DrawPDE(GridWindow windows){ // draws the PDE window + public void DrawPDE(GridWindow windows){ for (int i = 0; i < length; i++) { windows.SetPix(i,Util.HeatMapBGR(VEGF.Get(i))); } @@ -176,10 +186,11 @@ public void DrawPDE(GridWindow windows){ // draws the PDE window /** - * Draws the cell model - * @param win the window to draw the cell model in + * Draws the cell model. This function provides visual functionality + * by visualizing the agents (all cells and particles). + * @param win the window that the visualization will be drawn in */ - public void DrawModel(GridWindow win){ // Draws the Agent model + public void DrawModel(GridWindow win){ for (int i = 0; i < length; i++) { int color = Util.BLACK; if (GetAgent(i) != null) { @@ -192,7 +203,7 @@ public void DrawModel(GridWindow win){ // Draws the Agent model /** - * Replaces Dist function, which DOES NOT WORK with initVesselsCircleCulture + * Replaces native Dist function which DOES NOT WORK with initVesselsCircleCulture * @param x1 first x coord * @param y1 first y coord * @param x2 second x coord @@ -206,27 +217,27 @@ public int distance(double x1, double y1, double x2, double y2){ /** - * Initializes the vessels at both side of the wound - * @param model the model to draw the vessels in + * Initializes the spheroid for the assay + * @param model the model to initialize the vessels in */ public void initVesselsCircleCulture(sproutGrid model) { - int center = I((Xdim()/2), (Ydim()/2)); - for (int i = 0; i < (model.Xdim()*model.Ydim()); i++) { + int center = I((Xdim()/2), (Ydim()/2)); // determines the center, where the spheroid will be placed + for (int i = 0; i < (model.Xdim()*model.Ydim()); i++) { // iterates through all coordinates double dist = distance(ItoX(i), ItoY(i), ItoX(center), ItoY(center)); - if (dist < (CULTURE_RADIUS)) { - if (dist > (CULTURE_RADIUS - 2)){ - if (Math.random() < INITIAL_PERCENT_HEAD_CELLS) { // may be head cells or body cells + if (dist < (CULTURE_RADIUS)) { // if the distance for a coordinate is within CULTURE_RADIUS of the center + if (dist > (CULTURE_RADIUS - 2)){ // and if the cell is on the edge of the spheroid, then + if (Math.random() < INITIAL_PERCENT_HEAD_CELLS) { model.NewAgentSQ(i).InitVessel(sproutAgent.HEAD_CELL, 0); } } else if (dist > (CULTURE_RADIUS-3)){ - if (Math.random() < INITIAL_PERCENT_HEAD_CELLS) { // may be head cells or body cells + if (Math.random() < INITIAL_PERCENT_HEAD_CELLS) { // the cell may be initialized as type HEAD or BODY model.NewAgentSQ(i).InitVessel(sproutAgent.HEAD_CELL, 0); } else { model.NewAgentSQ(i).InitVessel(sproutAgent.BODY_CELL, 0); } - } else { - model.NewAgentSQ(i).InitVessel(sproutAgent.BODY_CELL, 0); + } else { // else (if it is in within CULTURE_RADIUS but not on the edge), then + model.NewAgentSQ(i).InitVessel(sproutAgent.BODY_CELL, 0); // the cell will be of type BODY } } } @@ -234,23 +245,23 @@ public void initVesselsCircleCulture(sproutGrid model) { /** - * Initializes MAP particles as full sized MAP particles - * @param model model to draw the particles in + * Initializes MAP particles and Heparin microislands into the model in HCP pattern with + * proper spacing as dictated by MAP_space + * @param model model to initialize the particles in */ public void initMAPParticles(sproutGrid model, double Heparin_Percent){ - // Iterate through every coordinate in the grid - for (int i = 0; i < x*y; i++) { + for (int i = 0; i < x*y; i++) { // Iterate through every coordinate in the grid int cellType = sproutAgent.MAP_PARTICLE; // assume that it will be a MAP particle double chance = Math.random(); if (chance < Heparin_Percent){ // if chosen probability dictates that it will he a heparin microIsland cellType = sproutAgent.HEPARIN_MAP;// then its type will be changed to heparin microIsland } - int occlusions = MapOccupiedHood(MAP_space, i); // Check a radius around the chosen coordinate equal to the radius of the MAP particle with proper spacing + int occlusions = MapOccupiedHood(MAP_space, i); // for the coordinate selected, check for occlusions (other cells) in area of radius MAP_space around it int open = MapEmptyHood(MAP_rad, i); if (occlusions == 0) { // if there are no occlusions - for (int j = 0; j < open; j++){ // then make the MAP particle (or Heparin microIsland) + for (int j = 0; j < open; j++){ // then initialize the particle at that location (checking that all particles stay within the window) if (0 < MAP_rad[j] && MAP_rad[j] < x*y){ model.NewAgentSQ(MAP_rad[j]).Init(cellType); } @@ -259,15 +270,20 @@ public void initMAPParticles(sproutGrid model, double Heparin_Percent){ } } - + + /** + * Counts the total number of pixels which have a vessel present + * (used in calculating fold change and total vessel length) + * @return the total number of pixels that are occupied by vessels + */ public int countVessels() { - int vessel_unit_counter = 0; // total vessel length calculated by taking the number of vessel units and multiplying by conversion factor - for (int x_coord = 0; x_coord < x; x_coord++) { + int vessel_unit_counter = 0; + for (int x_coord = 0; x_coord < x; x_coord++) { // iterates through all coordinates for (int y_coord = 0; y_coord < y; y_coord++) { Iterable agents = IterAgents(x_coord, y_coord); for (sproutAgent agent : agents) { - if (agent.type == HEAD_CELL || agent.type == BODY_CELL){ - vessel_unit_counter ++; + if (agent.type == HEAD_CELL || agent.type == BODY_CELL){ // if one of the coordinates is a vessel + vessel_unit_counter ++; // tally and continue break; } } @@ -278,7 +294,8 @@ public int countVessels() { /** - * Collects the data for export + * Collects data stored in a static variable, CSV. + * ExportData uses this collected information to export to a CSV file. */ public void CollectData(double heparinPercentage){ // vessel cells, MAP Particle, and Heparin MAP Data @@ -335,9 +352,7 @@ public void CollectData(double heparinPercentage){ CSV.append(MEDIA_EXCHANGE_SCHEDULE_HOURS); - // TIME DATA - if (EXPORT_TIME_DATA){ if (TIME_CSV.length() == 0){ TIME_CSV.append("Time (hours), "); @@ -351,11 +366,9 @@ public void CollectData(double heparinPercentage){ TIME_CSV.append(TimeFoldChange).append(","); } TIME_CSV.append("\n"); - } // HEAD CELL DISTANCE DATA - if (EXPORT_HEAD_CELL_DISTANCE_DATA){ if (HEAD_CSV.length() == 0){ HEAD_CSV.append("Final Head Cell Distances (microns) ").append("\n"); @@ -365,11 +378,14 @@ public void CollectData(double heparinPercentage){ HEAD_CSV.append(distance).append(","); } HEAD_CSV.append("\n"); - } - } + + /** + * Calculates final head cell distances from the center of the wound. + * @return an array of distances of each head cell to the center of the model + */ public ArrayList FinalHeadCellDistance(){ // Head cell distances ArrayList head_cell_distances = new ArrayList<>(); @@ -392,8 +408,9 @@ public ArrayList FinalHeadCellDistance(){ /** - * Exports data to SproutingAssayData file: arrival time, endothelial cells coordinates, MAP and HepMAP coordinates - * @throws IOException error in data export + * Exports data to a file labeled with run and date information to directory "SproutingAssayData" located in the + * sprouting assay folder. + * @throws IOException if errors */ public void ExportData() throws IOException { Timestamp timestamp = new Timestamp(System.currentTimeMillis()); @@ -433,12 +450,17 @@ public void ExportData() throws IOException { } - + /** + * Initializes the headings for the CSV file. + */ public void Initialize_CSV(){ CSV.append("Heparin Percentage (%), Total Vessel Length (microns), Fold Change (%), VEGF sensitivity, Diffusion Coefficient, VEGF Sensitivity, Vessel Growth Delay, Initial percent head cells, VEGF intake, hours, vegfdegradation, low-med thres, med-high thres, vegf loaded, media exchange"); } + /** + * Calculates and stores the fold change af intervals specified by FOLD_CHANGE_SAMPLE_TIME + */ public void CalculateFoldChangeOverTime(){ if (GetTick()%FOLD_CHANGE_SAMPLE_TICKS == 0){ FCTime.add(((double)GetTick())/TICKS_PER_HOUR); @@ -448,6 +470,9 @@ public void CalculateFoldChangeOverTime(){ } } + /** + * Clears the foldChangeOverTime variable between model runs. + */ public void ClearFoldChange() { this.foldChangeOverTime.clear(); } @@ -460,75 +485,76 @@ public void ClearFoldChange() { public static void main(String[] args) throws IOException { - GridWindow gridWin = new GridWindow("Endothelial Cells",x, y, SCALE_FACTOR); // window for agents - GridWindow VEGFWin = new GridWindow("VEGF Diffusion", x, y, SCALE_FACTOR); // window for diffusion + GridWindow gridWin = new GridWindow("Endothelial Cells",x, y, SCALE_FACTOR); // instantiates window for agents + GridWindow VEGFWin = new GridWindow("VEGF Diffusion", x, y, SCALE_FACTOR); // instantiates window for diffusion - sproutGrid model = new sproutGrid(x, y); // initialize agent grid + sproutGrid model = new sproutGrid(x, y); // instantiates agent grid - Path fileName= Path.of("SproutingAssay\\SproutingAssayData"); + Path fileName= Path.of("SproutingAssay\\SproutingAssayData"); // sets Data export location File SproutingAssayDatafile = new File(String.valueOf(fileName)); - if (EXPORT_DATA && !SproutingAssayDatafile.exists()) { + if (EXPORT_DATA && !SproutingAssayDatafile.exists()) { // create a data export file if necessary if (!SproutingAssayDatafile.mkdir()) { throw new IOException("SproutingAssayData folder not made"); } } - if (!BATCH_RUN){ + if (!BATCH_RUN){ // if the run is not a batch run // Initialize - model.initVesselsCircleCulture(model); - model.initMAPParticles(model, HEPARIN_PERCENTAGES[0]); + model.initVesselsCircleCulture(model); // initialize the spheroid + model.initMAPParticles(model, HEPARIN_PERCENTAGES[0]); // initialize the MAP particles around the spheroid - model.Initialize_CSV(); - model.initialCultureSize= model.countVessels(); // used for the initial vessel count in fold change - for (int i = 0; i < TIMESTEPS; i++){ + model.Initialize_CSV(); // initialize the CSV + model.initialCultureSize= model.countVessels(); // keep track of the initial vessel count of spheroid (used in calculating fold change) + for (int i = 0; i < TIMESTEPS; i++){ // while the model runs (for each tick) // pause gridWin.TickPause(TICK_PAUSE); // how fast the simulation runs // model step - model.StepCells(); // step the cells + model.StepCells(); // prompt the cells to take action // draw model.DrawPDE(VEGFWin); // draw the PDE window model.DrawModel(gridWin); // draw the agent window - model.CalculateFoldChangeOverTime(); + model.CalculateFoldChangeOverTime(); // calculate fold change if necessary } - if (EXPORT_DATA){ - model.CollectData(HEPARIN_PERCENTAGES[0]); - model.ExportData(); + if (EXPORT_DATA){ // if data export is set to TRUE, + model.CollectData(HEPARIN_PERCENTAGES[0]); // then collect data + model.ExportData(); // and export it. } - } else { - model.Initialize_CSV(); + } else { // If this is a batch run, + model.Initialize_CSV(); // initialie the CSV - for (double heparinPercentage : HEPARIN_PERCENTAGES) { // For each percentage listen in HEPARIN_PERCENTAGES - for (int trial = 0; trial < TRIALS; trial++) { // perform the amount of trials specified in TRIALS + for (double heparinPercentage : HEPARIN_PERCENTAGES) { // For each percentage listed in HEPARIN_PERCENTAGES + for (int trial = 0; trial < TRIALS; trial++) { // perform the amount of trials specified in TRIALS (for each trial...) // initialize - model.Reset(); // reset the model - model.ResetTick(); // reset the time tick - model.ClearFoldChange(); + model.Reset(); // reset the model for the next trial + model.ResetTick(); // reset the time tick for the next trial + model.ClearFoldChange(); // reset the fold change variable for the next trial model.VEGF = new PDEGrid2D(x, y); // initialize the diffusion grid - model.initVesselsCircleCulture(model); // initialize vessels + model.initVesselsCircleCulture(model); // initialize spheroid model.initMAPParticles(model, heparinPercentage); // initialize MAP particles + sproutAgent.start_vessel_growth = false; - model.initialCultureSize= model.countVessels(); // used for the initial vessel count in fold change - for (int i = 0; i < TIMESTEPS; i++){ + model.initialCultureSize= model.countVessels(); // keep track of the initial vessel count of spheroid (used in calculating fold change) + for (int i = 0; i < TIMESTEPS; i++){ // while the model runs (for each tick...) // pause gridWin.TickPause(TICK_PAUSE); // how fast the simulation runs // model step - model.StepCells(); // step the cells + model.StepCells(); // prompt the cells to take action // draw model.DrawPDE(VEGFWin); // draw the PDE window model.DrawModel(gridWin); // draw the agent window - model.CalculateFoldChangeOverTime(); + model.CalculateFoldChangeOverTime(); // calculate fold change if necessary } - if (EXPORT_DATA){ - model.CollectData(heparinPercentage); + if (EXPORT_DATA){ // if data export is set to TRUE, + model.CollectData(heparinPercentage); // then collect data } } } - if (EXPORT_DATA){ - model.ExportData(); + if (EXPORT_DATA){ // If data export is TRUE, + model.ExportData(); // Export all data when finished. } } } From 22ec25560cc166172d9bbf23e551190208dfd450 Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 24 Apr 2022 22:57:27 -0400 Subject: [PATCH 2/7] finalized code --- SproutingAssay/sproutAgent.java | 83 +++++++++++++-------------------- SproutingAssay/sproutGrid.java | 8 +--- 2 files changed, 33 insertions(+), 58 deletions(-) diff --git a/SproutingAssay/sproutAgent.java b/SproutingAssay/sproutAgent.java index f93f7e1..09d5cc3 100644 --- a/SproutingAssay/sproutAgent.java +++ b/SproutingAssay/sproutAgent.java @@ -27,7 +27,6 @@ public class sproutAgent extends AgentSQ2D { // take all parameters for the sproutGrid class. public static double VESSEL_VEGF_INTAKE = sproutGrid.VESSEL_VEGF_INTAKE; - public final static int VESSEL_GROWTH_DELAY = sproutGrid.VESSEL_GROWTH_DELAY; public final static double VEGF_SENSITIVITY = sproutGrid.VEGF_SENSITIVITY; public final static int MAX_ELONGATION_LENGTH = sproutGrid.MAX_ELONGATION_LENGTH; public final static double PERSISTENCY_TIME = sproutGrid.PERSISTENCY_TIME; @@ -52,8 +51,6 @@ public class sproutAgent extends AgentSQ2D { int elongation_length; // threshold length which determines when an endothelial cell must find a new direction to migrate (based on highest VEGF concentration) int ticks_since_direction_change; // // Works to realize a "persistency time". A cell must persist in 1 direction for X time, determined by PERSISTENCY_TIME. This stores the time since the cell's last redirection. int since_last_branch; // endothelial cells may branch to more frequently than BRANCH_DELAY_TIME. This stores how long it has been since the vessel's last branch. - public static boolean start_vessel_growth = false; // vessels will not elongate unless start_vessel_growth is true. It is set to true after VESSEL_GROWTH_DELAY has passed. -// boolean heparin_particle_release_VEGF = true; /** @@ -206,17 +203,6 @@ public void ConsumeVEGF() { } } - /** - * Determines whether the endothelial cells should begin dividing, according to VESSEL_GROWTH_DELAY - */ - public void CheckStartVesselGrowth() { - assert G != null; - if (G.GetTick() >= VESSEL_GROWTH_DELAY && !start_vessel_growth) { // If the VESSEL_GROWTH_DELAY has passed and start_vessel_growth is false, then, - start_vessel_growth = true; // vessels can begin to grow -// System.out.println(G.GetTick()); // can be used to check what tick the vessels begin to grow (keep in mind that these are ticks, and not hours) - } - } - /** * Replicates media exchange, simulating HEP_MAP sequestering and release of VEGF provided by fresh media, exchanged * as specificed by MEDIA_EXCHANGE_SCHEDULE @@ -266,54 +252,52 @@ public void VesselGrowthByRate() { return; } - if (start_vessel_growth) { // if VESSEL_GROWTH_DELAY has passed - int cellDivLocation; // (stores the the location where the cell will grow to) + int cellDivLocation; // (stores the the location where the cell will grow to) - // if persistency time has been reached, and the elongation length has been reached, then find a new direction to migrate. - if ((( ticks_since_direction_change >= PERSISTENCY_TIME) && (elongation_length >= MAX_ELONGATION_LENGTH)) || (target == 0)){ - int highestConcentrationCoord = HighestConcentrationVEGF(); // find new target location: the location in the sight radius with the highest VEGF - highestConcentrationCoord = CalculateTargetScaleTargetCoord(highestConcentrationCoord); // find a point in the same direction, but very far away, so you won't reach it: want to persist in that direction - cellDivLocation = HoodClosestToTarget(highestConcentrationCoord); // and find the closest adjacent coordinate in the direction towards the highestConcentrationCoord - if ((highestConcentrationCoord > 0) && (cellDivLocation > 0) && (G.PopAt(cellDivLocation) == 0)){ // If there is a location of highest concentration and there is an open adjacent spot... (the values will be 0 if none were found) - if (!(G.VEGF.Get(Isq()) + REQUIRED_VEGF_GRADIENT_DIFFERENCE <= G.VEGF.Get(cellDivLocation))){ // check if there is enough difference in VEGF between current location and target growth spot, (if not, then end) - return; - } - G.NewAgentSQ(cellDivLocation).InitVesselMigrationRate(HEAD_CELL, this.length + 1, highestConcentrationCoord, since_last_growth, 0, 1, since_last_branch); // make a new head cell at cellDivLocation (vessel elongates) - InitVessel(BODY_CELL, this.length); // and make the old cell a body cell + // if persistency time has been reached, and the elongation length has been reached, then find a new direction to migrate. + if ((( ticks_since_direction_change >= PERSISTENCY_TIME) && (elongation_length >= MAX_ELONGATION_LENGTH)) || (target == 0)){ + int highestConcentrationCoord = HighestConcentrationVEGF(); // find new target location: the location in the sight radius with the highest VEGF + highestConcentrationCoord = CalculateTargetScaleTargetCoord(highestConcentrationCoord); // find a point in the same direction, but very far away, so you won't reach it: want to persist in that direction + cellDivLocation = HoodClosestToTarget(highestConcentrationCoord); // and find the closest adjacent coordinate in the direction towards the highestConcentrationCoord + if ((highestConcentrationCoord > 0) && (cellDivLocation > 0) && (G.PopAt(cellDivLocation) == 0)){ // If there is a location of highest concentration and there is an open adjacent spot... (the values will be 0 if none were found) + if (!(G.VEGF.Get(Isq()) + REQUIRED_VEGF_GRADIENT_DIFFERENCE <= G.VEGF.Get(cellDivLocation))){ // check if there is enough difference in VEGF between current location and target growth spot, (if not, then end) + return; } + G.NewAgentSQ(cellDivLocation).InitVesselMigrationRate(HEAD_CELL, this.length + 1, highestConcentrationCoord, since_last_growth, 0, 1, since_last_branch); // make a new head cell at cellDivLocation (vessel elongates) + InitVessel(BODY_CELL, this.length); // and make the old cell a body cell + } - // branching - if(G.rng.Double() < branching_probability && since_last_branch > BRANCH_DELAY_TIME){ // if the cell happens to branch (branching probability is a parameter of the cell, and is modified by a function CalculateBranchingProbability) - // find the options for branching locations around the cell - int options = MapEmptyHood(G.divHood); - if (options >= 1) { // if there is an open nearby location, then branch there - cellDivLocation = G.divHood[G.rng.Int(options)]; // choose a random empty location - if (G.PopAt(cellDivLocation) == 0){ // if there are no agents at that location - if (!(G.VEGF.Get(Isq()) + REQUIRED_VEGF_GRADIENT_DIFFERENCE <= G.VEGF.Get(cellDivLocation))){ // if there is not a large enough difference of VEGF between the current location and the branching location, then do not branch. Otherwise, - return; - } - G.NewAgentSQ(cellDivLocation).InitVesselMigrationRate(HEAD_CELL, this.length + 1, 0, 0, this.ticks_since_direction_change =0, 1, 0); // make a new head cell at the branching location - InitVessel(BODY_CELL, this.length); // make the old cell a body cell + // branching + if(G.rng.Double() < branching_probability && since_last_branch > BRANCH_DELAY_TIME){ // if the cell happens to branch (branching probability is a parameter of the cell, and is modified by a function CalculateBranchingProbability) + // find the options for branching locations around the cell + int options = MapEmptyHood(G.divHood); + if (options >= 1) { // if there is an open nearby location, then branch there + cellDivLocation = G.divHood[G.rng.Int(options)]; // choose a random empty location + if (G.PopAt(cellDivLocation) == 0){ // if there are no agents at that location + if (!(G.VEGF.Get(Isq()) + REQUIRED_VEGF_GRADIENT_DIFFERENCE <= G.VEGF.Get(cellDivLocation))){ // if there is not a large enough difference of VEGF between the current location and the branching location, then do not branch. Otherwise, + return; } + G.NewAgentSQ(cellDivLocation).InitVesselMigrationRate(HEAD_CELL, this.length + 1, 0, 0, this.ticks_since_direction_change =0, 1, 0); // make a new head cell at the branching location + InitVessel(BODY_CELL, this.length); // make the old cell a body cell } } - } else if (elongation_length < MAX_ELONGATION_LENGTH){ // if the cell has not yet reached it's max elongation length, then continue to elongate - cellDivLocation = HoodClosestToTarget(target); // find an open adjacent location closest to the target - if (G.PopAt(cellDivLocation) == 0) { // double check that there are no other agents at that location - if (!(G.VEGF.Get(Isq()) + REQUIRED_VEGF_GRADIENT_DIFFERENCE <= G.VEGF.Get(cellDivLocation))){ // if the VEGF concentration difference between the current location and the elongation location is insufficient, then stop. Else, - return; - } - G.NewAgentSQ(cellDivLocation).InitVesselMigrationRate(HEAD_CELL, this.length + 1, target, since_last_growth, ticks_since_direction_change, elongation_length + 1, since_last_branch); // make a new cell there - InitVessel(BODY_CELL, this.length); // make the old cell a body cell + } + } else if (elongation_length < MAX_ELONGATION_LENGTH){ // if the cell has not yet reached it's max elongation length, then continue to elongate + cellDivLocation = HoodClosestToTarget(target); // find an open adjacent location closest to the target + if (G.PopAt(cellDivLocation) == 0) { // double check that there are no other agents at that location + if (!(G.VEGF.Get(Isq()) + REQUIRED_VEGF_GRADIENT_DIFFERENCE <= G.VEGF.Get(cellDivLocation))){ // if the VEGF concentration difference between the current location and the elongation location is insufficient, then stop. Else, + return; } + G.NewAgentSQ(cellDivLocation).InitVesselMigrationRate(HEAD_CELL, this.length + 1, target, since_last_growth, ticks_since_direction_change, elongation_length + 1, since_last_branch); // make a new cell there + InitVessel(BODY_CELL, this.length); // make the old cell a body cell } } } /** * This function takes in a target coordinate of a cell and views it in relation with that cell. It then treats it - * a vector, and scales the coordinate such that it is 10 times further, but still in the same direction + * a vector, and scales the coordinate such that it is multiple times further, but still in the same direction * in relation to the cell. * @param targetCoord the original coordinate target of a cell * @return a coordinate in the same direction, but scaled to be a larger distance than the original target. @@ -381,9 +365,6 @@ public void StepCell() { // calculate branching probability CalculateBranchingProbability(); - // check if endothelial cells will divide yet - CheckStartVesselGrowth(); - // Elongate VesselGrowthByRate(); diff --git a/SproutingAssay/sproutGrid.java b/SproutingAssay/sproutGrid.java index 8bd90f7..e7813c7 100644 --- a/SproutingAssay/sproutGrid.java +++ b/SproutingAssay/sproutGrid.java @@ -72,7 +72,6 @@ public class sproutGrid extends AgentGrid2D { public final static int SCALE_FACTOR = 2; // for visualization: changes the scale of the pixels public final static int TICK_PAUSE = 1; // for model runtime: changes the amount of time between each tick public final static int RUNTIME_HOURS = 24; // the timeframe that the simulation models (HOURS) - public final static double VESSEL_GROWTH_DELAY_HOURS = 2; // the delay between model start and vessel growth // DIFFUSION - NEEDS PARAMETERIZED public final static double DIFFUSION_COEFFICIENT = 0.733; // diffusion coefficient @@ -104,7 +103,6 @@ public class sproutGrid extends AgentGrid2D { // runtime public final static int TIMESTEPS = RUNTIME_HOURS*TICKS_PER_HOUR; - public final static int VESSEL_GROWTH_DELAY = (int)(VESSEL_GROWTH_DELAY_HOURS*TICKS_PER_HOUR); public final static int FOLD_CHANGE_SAMPLE_TICKS = (int)(FOLD_CHANGE_SAMPLE_TIME*TICKS_PER_HOUR); // take a sample every ____ ticks @@ -324,9 +322,6 @@ public void CollectData(double heparinPercentage){ //vegf sensitivity CSV.append(VEGF_SENSITIVITY).append(","); - //vessel growth delay - CSV.append(VESSEL_GROWTH_DELAY_HOURS).append(","); - //initial percent head cells CSV.append(INITIAL_PERCENT_HEAD_CELLS).append(","); @@ -454,7 +449,7 @@ public void ExportData() throws IOException { * Initializes the headings for the CSV file. */ public void Initialize_CSV(){ - CSV.append("Heparin Percentage (%), Total Vessel Length (microns), Fold Change (%), VEGF sensitivity, Diffusion Coefficient, VEGF Sensitivity, Vessel Growth Delay, Initial percent head cells, VEGF intake, hours, vegfdegradation, low-med thres, med-high thres, vegf loaded, media exchange"); + CSV.append("Heparin Percentage (%), Total Vessel Length (microns), Fold Change (%), VEGF sensitivity, Diffusion Coefficient, VEGF Sensitivity, Initial percent head cells, VEGF intake, hours, vegfdegradation, low-med thres, med-high thres, vegf loaded, media exchange"); } @@ -534,7 +529,6 @@ public static void main(String[] args) throws IOException { model.VEGF = new PDEGrid2D(x, y); // initialize the diffusion grid model.initVesselsCircleCulture(model); // initialize spheroid model.initMAPParticles(model, heparinPercentage); // initialize MAP particles - sproutAgent.start_vessel_growth = false; model.initialCultureSize= model.countVessels(); // keep track of the initial vessel count of spheroid (used in calculating fold change) for (int i = 0; i < TIMESTEPS; i++){ // while the model runs (for each tick...) From 74d1b4c601c427e0f8ba436637f63f876b94e2e3 Mon Sep 17 00:00:00 2001 From: lpruett Date: Thu, 28 Apr 2022 10:01:34 -0400 Subject: [PATCH 3/7] Commented_LP --- SproutingAssay/sproutAgent.java | 12 ++++----- SproutingAssay/sproutGrid.java | 47 +++++++++++++++++---------------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/SproutingAssay/sproutAgent.java b/SproutingAssay/sproutAgent.java index 09d5cc3..f91f13d 100644 --- a/SproutingAssay/sproutAgent.java +++ b/SproutingAssay/sproutAgent.java @@ -1,7 +1,8 @@ /* GRIFFIN LAB -ALEX TAING, UNDERGRADUATE -FALL 2020 +LAUREN PRUETT, ALEX TAING +UNIVERSITY OF VIRGINIA +2D Hybrid Model Sprouting Angiogenesis Publication 2022 */ package SproutingAssay; @@ -41,7 +42,7 @@ public class sproutAgent extends AgentSQ2D { public final static double HIGH_BRANCHING_PROBABILITY= sproutGrid.HIGH_BRANCHING_PROBABILITY; public final static double REQUIRED_VEGF_GRADIENT_DIFFERENCE = sproutGrid.REQUIRED_VEGF_GRADIENT_DIFFERENCE; - int color; // color of cell in visulaization + int color; // color of cell in visualization int type; // cell type (HEAD, BODY, MAP_PARTICLE, HEPARIN_MAP) int length = 0; // length of the vessel (since starting location) int target; // simulates elongation direction: cells will pursue a target coordinate in the direction of the highest VEGF concentration @@ -196,7 +197,7 @@ public void InitVesselMigrationRate(int type, int length, int target, int since_ public void ConsumeVEGF() { assert G != null; if ((G.VEGF.Get(Isq()) >= 0) && ((type == HEAD_CELL) || (type == BODY_CELL))) { // Head cells and body cells consume VEGF - G.VEGF.Add(Isq(), -VESSEL_VEGF_INTAKE); + G.VEGF.Add(Isq(), -VESSEL_VEGF_INTAKE); //Endothelial cell internalizes VEGF if (G.VEGF.Get(Isq()) < 0){ // if the VEGF concentration is less than 0, G.VEGF.Set(Isq(), 0); // then set it to zero. } @@ -341,9 +342,8 @@ public void CalculateBranchingProbability(){ */ public void VEGFDegrade() { assert G != null; - if (G.VEGF.Get(Isq()) >= 0 && G.GetTick()%90 == 0) { // VEGF degrades every 90 ticks + if (G.VEGF.Get(Isq()) >= 0 && G.GetTick()%90 == 0) { // VEGF degrades every 90 ticks consistent with half life of 90 min G.VEGF.Add(Isq(), -(G.VEGF.Get(Isq()))* VEGF_DEGRADATION_RATE); - //G.VEGF.Add(Isq(), - VEGF_DEGRADATION_RATE); if (G.VEGF.Get(Isq()) < 0){ G.VEGF.Set(Isq(), 0); } diff --git a/SproutingAssay/sproutGrid.java b/SproutingAssay/sproutGrid.java index e7813c7..1d6b87c 100644 --- a/SproutingAssay/sproutGrid.java +++ b/SproutingAssay/sproutGrid.java @@ -1,7 +1,8 @@ /* GRIFFIN LAB -ALEX TAING, UNDERGRADUATE -FALL 2020 +LAUREN PRUETT, ALEX TAING +UNIVERSITY OF VIRGINIA +2D Sprouting Angiogenesis ABM - Publication 2022 */ package SproutingAssay; @@ -33,10 +34,10 @@ public class sproutGrid extends AgentGrid2D { public final static boolean EXPORT_DATA = true; public final static boolean EXPORT_TIME_DATA = true; // (note that EXPORT_DATA must also be true as well to export time data) public final static boolean EXPORT_HEAD_CELL_DISTANCE_DATA = true; // (note that EXPORT_DATA must also be true as well to export distance data) - public final static int TRIALS = 500; // number of trials (only for BATCH RUNS) - public final static double[] HEPARIN_PERCENTAGES = {0.28}; // percent HEPARIN ISLANDS that will be inilialized in the scaffold + public final static int TRIALS = 100; // number of trials (only for BATCH RUNS) + public final static double[] HEPARIN_PERCENTAGES = {0.1}; // percent HEPARIN ISLANDS that will be inilialized in the scaffold public final static double FOLD_CHANGE_SAMPLE_TIME = 0.25 ; // sampling interval for fold change data export (HOURS) - //public final static double[] DIFFUSION_COEFFICIENT = new double[]{0.01, 0.04, 0.07, 0.10, 0.13}; + // VESSEL PARAMETERS FIXED! public static final int CULTURE_RADIUS_MICRONS = 140; // radius of the initial assay spheroid (MICRONS) @@ -46,25 +47,25 @@ public class sproutGrid extends AgentGrid2D { public final static int MIGRATION_RATE_MICRONS_PER_HOUR = 30; // rate of elongation for EC head cells (MICRONS/HOUR) public final static double BRANCH_DELAY_TIME_HOURS = 6; // required delay time between EC branching in (HOURS) - // VESSEL PARAMETERS NEEDING PARAMETERIZED AND SENSITIVITY ANALYSIS - public final static double VEGF_SENSITIVITY = 0.03; // minimal VEGF required to be sensed by EC (0.03 baseline minimum VEGF to attract cell growth) - public static double VESSEL_VEGF_INTAKE = 0.001; // percent of how much of the current VEGF is consumed when a blood vessel is present in a cell + // VESSEL PARAMETERS FOR SENSITIVITY ANALYSIS + public final static double VEGF_SENSITIVITY = 0.025; // minimal VEGF required to be sensed by EC (0.03 baseline minimum VEGF to attract cell growth) (RELATIVE UNITS) + public static double VESSEL_VEGF_INTAKE = 0.001; // amount of the current VEGF that is consumed when a blood vessel is present in a grid cell (RELATIVE UNITS) + public final static double VEGF_DEGRADATION_RATE = 0.5; // Fraction of VEGF that is degraded every 90 minutes in accordance with VEGFs half life + public final static double REQUIRED_VEGF_GRADIENT_DIFFERENCE = 0.005; // Difference of VEGF concentration required between a HEAD cell's location and its next division location in order to elongate (RELLATIVE UNITS) + + // BRANCHING PROBABILITY AND THRESHOLDS_ PROBABILITIES public final static double INITIAL_PERCENT_HEAD_CELLS = 0.07; // probability during spheroid initiation that any edge cell of the spheroid will be of type HEAD - public final static double VEGF_DEGRADATION_RATE = 0.5; // rate at which VEGF degrades - public final static double REQUIRED_VEGF_GRADIENT_DIFFERENCE = 0.005; // Difference of VEGF concentration required between a HEAD cell's location and its next division location in order to elongate - // BRANCHING PROBABILITY AND THRESHOLDS_ PROBABILITIES NEED PARAMETERIZED BUT COULD STAY FIXED public final static double LOW_BRANCHING_PROBABILITY= 0.4; // probability of branching while VEGF is under LOW_MED_VEGF_THRESHOLD - public final static double LOW_MED_VEGF_THRESHOLD = 0.05; // the threshold between LOW and MED branching probability + public final static double LOW_MED_VEGF_THRESHOLD = 0.05; // the threshold between LOW and MED branching probability (RELATIVE UNITS) public final static double MED_BRANCHING_PROBABILITY= 0.55; // probability of branching while VEGF is between LOW_MED_VEGF_THRESHOLD and MED_HIGH_VEGF_THRESHOLD - public final static double MED_HIGH_VEGF_THRESHOLD = 0.25; // the threshold between MED and HIGH branching probability + public final static double MED_HIGH_VEGF_THRESHOLD = 0.25; // the threshold between MED and HIGH branching probability (RELATIVE UNITS) public final static double HIGH_BRANCHING_PROBABILITY= 0.9; // probability of branching while VEGF is above MED_HIGH_VEGF_THRESHOLD // MAP GEL PARAMETERS - FIXED public final static int MAP_RADIUS_MICRONS = 40; // radius of MAP particles (MICRONS) public final static double MAP_SPACING_MICRONS = 15; // minimum space between the edges of two MAP particles (MICRONS) - public final static double HEP_MAP_VEGF_RELEASE = 1; // amount of VEGF added per media exchange - public final static double MEDIA_EXCHANGE_SCHEDULE_HOURS = 0.3571; // exchange media to refresh VEGF every __ hours - //public final static double HEPARIN_PERCENTAGES = 0.1; // percentage of heparin particles + public final static double HEP_MAP_VEGF_RELEASE = 1; // amount of VEGF added per media exchange (RELATIVE UNITS) (NOTE: This is based on percentage of hep particles - HEP% * HEP_MAP_VEGF_RELEASE = 0.1) + public final static double MEDIA_EXCHANGE_SCHEDULE_HOURS = 1; // exchange media to refresh VEGF every X hours // MAIN METHOD PARAMETERS - FIXED public final static int x_MICRONS = 4000; // x dimension of the wound-space (MICRONS) @@ -73,18 +74,18 @@ public class sproutGrid extends AgentGrid2D { public final static int TICK_PAUSE = 1; // for model runtime: changes the amount of time between each tick public final static int RUNTIME_HOURS = 24; // the timeframe that the simulation models (HOURS) - // DIFFUSION - NEEDS PARAMETERIZED - public final static double DIFFUSION_COEFFICIENT = 0.733; // diffusion coefficient + // DIFFUSION + public final static double DIFFUSION_COEFFICIENT = 0.733; // diffusion coefficient (UNITLESS) ///////////////////////////////////////////// CONVERSIONS //////////////////////////////////////////////////// - // FACTORS + // SCALING FACTORS public final static int MICRONS_PER_PIXEL = 10; // 1 pixel represents 10 microns public final static int TICKS_PER_HOUR = 60; // 1 tick represents 1 minute - // vessels + // vessel unit conversions public static final int CULTURE_RADIUS = CULTURE_RADIUS_MICRONS/ MICRONS_PER_PIXEL; public final static int SIGHT_RADIUS = SIGHT_RADIUS_MICRONS/ MICRONS_PER_PIXEL; public static final int MAX_ELONGATION_LENGTH = MAX_ELONGATION_LENGTH_MICRONS/ MICRONS_PER_PIXEL; @@ -92,7 +93,7 @@ public class sproutGrid extends AgentGrid2D { public final static double PERSISTENCY_TIME = PERSISTENCY_TIME_HOURS * TICKS_PER_HOUR; public final static int BRANCH_DELAY_TIME = (int)(BRANCH_DELAY_TIME_HOURS * TICKS_PER_HOUR); - // particles + // particle unit conversions public final static int MAP_RADIUS = MAP_RADIUS_MICRONS/ MICRONS_PER_PIXEL; public final static double MAP_SPACING = (double)(MAP_RADIUS_MICRONS)/ MICRONS_PER_PIXEL + MAP_SPACING_MICRONS/ MICRONS_PER_PIXEL; public final static double MEDIA_EXCHANGE_SCHEDULE_TICKS = MEDIA_EXCHANGE_SCHEDULE_HOURS*TICKS_PER_HOUR; @@ -166,7 +167,7 @@ public void StepCells(){ // steps all the cells endoCell.StepCell(); } IncTick(); - VEGF.DiffusionADI(DIFFUSION_COEFFICIENT); + VEGF.DiffusionADI(DIFFUSION_COEFFICIENT); //Alternating Direction Implicit Method Diffusion VEGF.Update(); } @@ -313,7 +314,7 @@ public void CollectData(double heparinPercentage){ // Head cell data ArrayList headCellDistances = FinalHeadCellDistance(); - //Changing coefficient + //grid size CSV.append(x_MICRONS).append(","); // diffusion coefficient From fd6fdcbb4b7ebfe37cb257e101c2e39643d69fbd Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 28 Apr 2022 18:58:39 -0400 Subject: [PATCH 4/7] update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index cc05ddb..047f953 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ HAL/ out/ EndoData/ SproutingAssayData/ +Model3D_Data/ # .jar files HalColorSchemes.jar From bca6016f54a5ccf43cccf0f240f284d111653bde Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 28 Apr 2022 21:50:50 -0400 Subject: [PATCH 5/7] update readme for publication --- README.md | 99 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 5b3849b..8872ec7 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,71 @@ -# HAL2020-ATaing - -Welcome to my GitHub! This repository is for the models of endothelial cell growth with Heparin-MAP particles I've made at my time here at Griffin Lab. All code on this repo uses the HAL library, and can be installed below: - -http://halloworld.org/start_here.html - -Getting the model working: - -1) Install IntelliJ -2) Install the HAL library -2) Clone the repository (i.e. download the zip file by clicking the green "Code" button) and extract the files -3) From the HAL library, copy the file HAL and HalColorSchemes.jar and place them within the AngiogenesisModel file together with the other files in the repository -4) Open IntelliJ, ctrl + shift + a to bring up the search menu and find "Import Project from Existing Sources" then select AngiogenesisModel. (If currently in another project and not on IntelliJ "recent projects page", select File, then close project to be brought back to the project selection window.) -5) Click accept for default options. NOTE: If IntelliJ warns about overriding the .idea file, select OK. -6) Open any .java in the repository using IntelliJ and select "File" then "Project Structure" then "Libraries" -7) Select the minus button above the long vertical columns to delete all the current libraries. Click OK on the warnings. Then, select the plus sign, select Java, and navigate to the ...HAL\lib file and select OK. -8) Repeat the last part of step 7 with HalColorSchemes.jar. You may get an extra popup box. Here you will want to select "jar Directory" -NOTE: this may seem like you just added the libraries you removed, but these steps eliminate an error with programs that use the OpenGL3DWindow class. -9) Select Apply, then OK. -10) Click "Add Configuration" located in the top right corner between the hammer button and the play button -11) In the opened window, click the plus sign in the upper left corner to open a dropdown menu. Select application. -12) Name the application (suggested, Wound Grid) -13) Under the "Build and Run" header, select select the main class called "VascularModel.woundGrid_2D" by clicking on the file icon at the end of the first input box. -14) Select OK. Now the program can be run by selecting the play button in the top right corner. - -Enjoy! - -Fall 2020 \ No newline at end of file +# Agent Based Model of Vessel Growth through Heparin Islands MAP Gel + +Lauren Pruett1, Alex Taing1, Neharika Singh1, Donald Griffin, PhD1,2,* + +1Department of Biomedical Engineering
+2Department of Chemical Engineering + +*Corresponding Author
+Email address: dg2gf@virginia.edu
+Phone number: 434-982-6269
+ +Summary:
+This model was created to model vessel growth through Heparin Islands MAP gel, +testing different ratios of MAP gel to Heparin Islands MAP Gel optimize healing +outcomes. This model simulates angiogenesis from a spherical culture through +surrounding Heparin islands MAP gel. + +To start using this model, complete installation and setup. + +Installation: +1) Install and set up IntelliJ using default settings. +2) Install, set up, and log into GitHub Desktop using default settings. +3) Navigate to http://halloworld.org/index.html in your browser and click "DOWNLOAD". You will be navigated to a GitHub repository. +4) To clone this repository, click on the green "Code" button then select "Open with GitHub Desktop". You GitHub Desktop will open. If your browser asks for permissions, allow them. +5) Once GitHub Desktop opens, edit the Local Path to where you would like the library will be installed on your computer. It will be in a file called "HAL-master". _Remember this location for set-up_. +6) Click "Clone". This will install HAL's library on your computer in your specified location. +7) Navigate to this model's repository at _INSERT REPO LINK HERE_ in your browser. +8) To clone this repository, click on the green "Code" button then select "Open with GitHub Desktop". You GitHub Desktop will open. If your browser asks for permissions, allow them. +9) Once GitHub Desktop opens, edit the Local Path to where you would like the library will be installed on your computer. It will be in a file called "AngiogenesisModel". _Remember this location for set-up_. + +Set-up: + +1) Navigate to the file were the HAL library was cloned to, called "HAL-master". Locate the file where the model was cloned to, called "AngiogenesisModel". +2) Inside "HAL-master", find the folder called "HAL" and the file called "HalColorSchemes.jar". Copy both into the folder called "AngiogenesisModel". +3) Open IntelliJ. If this is your first time opening IntelliJ, press _ctrl + shift + a_ to bring up the search menu. Find "Import Project from Existing Sources" by searching "existing". Then, select the "AngiogenesisModel" folder. Else, if you are currently in another project and not on the IntelliJ "recent projects page", select File then close project to be brought back to the project selection window before completing this step. +4) Click accept for default options, stopping when you see "Please select project SDK".
_Note_: If IntelliJ warns about overriding the .idea file, select OK. +5) When you reach "Please select project SDK", click the plus button and download either an SDK with version number 15 or 16. Once installation finishes, select that new JDK (e.g openjdk-15) in the left window. +6) Click next/create/accept for following options until set-up completes. +7) After loading, you will be greeted by the ReadMe. Find the project file tree in the left window. Select the file "SproutingAssay", then open the file "sproutGrid". +8) Navigate to "File" in the top left of the screen, followed by "Project Structure", then "libraries". +9) Select the minus button to delete all the current libraries. Click OK on all warnings. +10) Select the plus sign, then select Java. Navigate to the file "lib" located inside the folder "HAL", which itself is inside our "AngiogenesisModel" folder. After selecting "lib", select OK, then OK on the popup window if one shows. +11) Once again, select the plus sign, then select Java. Navigate to the file called "HalColorSchemes.jar" located directly inside the "AngiogenesisModel " folder. After selecting "HalColorSchemes.jar", select OK. On the following popup box, select "Jar Directory", then OK.
+ _Note_: this may seem like you just added the libraries you removed, but these steps eliminate an error with programs that use the OpenGL3DWindow class. +12) Select OK on the "Project Structure" window. +13) Click "Add Configuration" located in the top right corner between the hammer button and the play button. +14) In the opened window, click the plus sign in the upper left corner to open a dropdown menu. Select application. +15) Name the application (suggested, Wound Grid). +16) Under the "Build and Run" header, select the main class called "sproutGrid" by clicking on the file icon at the end of the first input box and searching for "sproutGrid". +17) Select OK. Now the program can be run by selecting the play button in the top right corner.
+_Note_: If an error occurs, carefully complete steps 10 and 11 once more and try running the program again. + +
+ +Acknowledgements:

+HAL: http://halloworld.org/index.html
+Bravo RR, Baratchart E, West J, Schenck RO, Miller AK, Gallaher J, et al. (2020) Hybrid Automata Library: A flexible platform for hybrid modeling with real-time visualization. PLoS Comput Biol 16(3): e1007635. https://doi.org/10.1371/journal.pcbi.1007635 +
+
+Mehdizadeh, H., Sumo, S., Bayrak, E. S., Brey, E. M. & Cinar, A. Three-dimensional modeling of angiogenesis in porous biomaterial scaffolds. Biomaterials 34, 2875–2887 (2013). +
+
+Nandi, S. & Brown, A. C. Characterizing Cell Migration Within Three-dimensional In Vitro Wound Environments. JoVE (Journal of Visualized Experiments) e56099 (2017) doi:10.3791/56099. +
+
+Pruett, L., Ellis, R., McDermott, M., Roosa, C. & Griffin, D. Spatially heterogeneous epidermal growth factor release from microporous annealed particle (MAP) hydrogel for improved wound closure. Journal of Materials Chemistry B (2021) doi:10.1039/D1TB00715G. +
+
+This project was supported by the UVA Double Hoo grant.
+L. Pruett is funded by NIH F31HL154731
+This work was partially supported by NIH R01 10297936
From bd395602cf2631abb39417c029aa8abf229ae382 Mon Sep 17 00:00:00 2001 From: lpruett <60302077+lpruett@users.noreply.github.com> Date: Fri, 29 Apr 2022 10:07:27 -0400 Subject: [PATCH 6/7] Update README.md --- README.md | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 8872ec7..7239b8c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Agent Based Model of Vessel Growth through Heparin Islands MAP Gel -Lauren Pruett1, Alex Taing1, Neharika Singh1, Donald Griffin, PhD1,2,* +Lauren Pruett1, Alex Taing1, Neharika Singh1, Shayn Peirce, PhD,1, Donald Griffin, PhD1,2,* 1Department of Biomedical Engineering
2Department of Chemical Engineering @@ -10,10 +10,10 @@ Email address: dg2gf@virginia.edu
Phone number: 434-982-6269
Summary:
-This model was created to model vessel growth through Heparin Islands MAP gel, -testing different ratios of MAP gel to Heparin Islands MAP Gel optimize healing -outcomes. This model simulates angiogenesis from a spherical culture through -surrounding Heparin islands MAP gel. +A hybrid agent-based model was developed to simulate endothelial cell migration from a spheroid in a MAP scaffold with heparin microislands. +The goal of this model is to optimize the raio of heparin microislands in a MAP scaffold to promote angiogenesis. +Heparin microislands in the MAP scaffold were first described here: +Pruett, L. J., Jenkins, C. H., Singh, N. S., Catallo, K. J., Griffin, D. R., Heparin Microislands in Microporous Annealed Particle Scaffolds for Accelerated Diabetic Wound Healing. Adv. Funct. Mater. 2021, 31, 2104337. https://doi.org/10.1002/adfm.202104337 To start using this model, complete installation and setup. @@ -57,14 +57,6 @@ HAL: http://halloworld.org/index.html
Bravo RR, Baratchart E, West J, Schenck RO, Miller AK, Gallaher J, et al. (2020) Hybrid Automata Library: A flexible platform for hybrid modeling with real-time visualization. PLoS Comput Biol 16(3): e1007635. https://doi.org/10.1371/journal.pcbi.1007635

-Mehdizadeh, H., Sumo, S., Bayrak, E. S., Brey, E. M. & Cinar, A. Three-dimensional modeling of angiogenesis in porous biomaterial scaffolds. Biomaterials 34, 2875–2887 (2013). -
-
-Nandi, S. & Brown, A. C. Characterizing Cell Migration Within Three-dimensional In Vitro Wound Environments. JoVE (Journal of Visualized Experiments) e56099 (2017) doi:10.3791/56099. -
-
-Pruett, L., Ellis, R., McDermott, M., Roosa, C. & Griffin, D. Spatially heterogeneous epidermal growth factor release from microporous annealed particle (MAP) hydrogel for improved wound closure. Journal of Materials Chemistry B (2021) doi:10.1039/D1TB00715G. -

This project was supported by the UVA Double Hoo grant.
L. Pruett is funded by NIH F31HL154731
From 7bfdd3a01b7db0f35bb9f02c39aa79b3855408d7 Mon Sep 17 00:00:00 2001 From: lpruett <60302077+lpruett@users.noreply.github.com> Date: Fri, 29 Apr 2022 10:09:04 -0400 Subject: [PATCH 7/7] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7239b8c..b93dd56 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Agent Based Model of Vessel Growth through Heparin Islands MAP Gel +# 2D Hybrid Agent Based Model of Endothelial Cell Migration in MAP Hydrogel with Heparin Microislands -Lauren Pruett1, Alex Taing1, Neharika Singh1, Shayn Peirce, PhD,1, Donald Griffin, PhD1,2,* +Lauren Pruett1, Alex Taing1, Neharika Singh1, Shayn Peirce, PhD1, Donald Griffin, PhD1,2,* 1Department of Biomedical Engineering
2Department of Chemical Engineering