Skip to content

Commit 68623d7

Browse files
authored
Upload base MiMICS files
1 parent 43e5467 commit 68623d7

File tree

3 files changed

+939
-0
lines changed

3 files changed

+939
-0
lines changed

MiMICS/MIMICS.java

Lines changed: 384 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,384 @@
1+
// MIMICS JAVA CLASS: AGENT-BASED MODEL AND REACTION-DIFFUSION MODEL
2+
package MIMICS;
3+
4+
// IMPORT HAL PACKAGES
5+
import HAL.GridsAndAgents.*;
6+
import HAL.Rand;
7+
import HAL.Tools.FileIO;
8+
import HAL.Util;
9+
import static HAL.Util.*;
10+
11+
// IMPORT JAVA PACKAGES
12+
import java.io.BufferedWriter;
13+
import java.io.FileWriter;
14+
import java.io.IOException;
15+
import java.util.ArrayList;
16+
import java.util.Random;
17+
18+
// CREATE CELL3D AGENT CLASS
19+
class Cell3D extends SphericalAgent3D<Cell3D, MIMICS>
20+
{
21+
Random r = new Random();
22+
Rand rn = new Rand();
23+
// DEFINE AGENT ATTRIBUTES
24+
double mass; // BIOMASS
25+
double forceSum;// AGENT SUM OF FORCES
26+
double angle; // AGENT ANGLE
27+
int index; // AGENT INDEX
28+
double growth_rate; // AGENT GROWTH RATE
29+
int metabolic_state; // AGENT METABOLIC STATE
30+
double t_switch_0; // AGENT TRACKING TIME TO SWITCH TO METABOLIC STATE 0
31+
double t_switch_1; // AGENT TRACKING TIME TO SWITCH TO METABOLIC STATE 1
32+
33+
// METHODS TO INITIALIZE AN AGENT
34+
public void Init(double mass,double angle, int state, int index, double t_switch_0, double t_switch_1) {
35+
// INITIALIZE VALUES OF AGENT ATTRIBUTES
36+
this.mass = mass;
37+
this.angle = angle;
38+
this.radius = G.RADIUS;
39+
this.index = index;
40+
this.metabolic_state = state;
41+
this.t_switch_0 = t_switch_0/ 2;
42+
this.t_switch_1 = t_switch_1/ 2;
43+
}
44+
45+
// METHOD TO CALCULATE SHOVING FORCES BETWEEN AGENTS
46+
double ForceCalc(double overlap, Cell3D other){
47+
if(overlap<0) {
48+
return 0; // IF NO AGENT OVERLAP, RETURN 0
49+
}
50+
return G.FORCE_SCALER*overlap; // SCALE OVERLAP (HOOKE'S LAW)
51+
}
52+
53+
// METHOD TO PERFORM SHOVING FORCES BETWEEN AGENTS
54+
public void CalcMove(){
55+
forceSum=SumForces(G.RADIUS,this::ForceCalc);
56+
}
57+
58+
// METHOD TO MOVE AGENTS
59+
public void MoveDiv(){
60+
ForceMove();
61+
ApplyFriction(this.G.FRICTION);
62+
}
63+
64+
// METHOD TO SIMULATE AGENT BIOMASS DIVISION
65+
public int Biomass_Divide(int pop, double initial_biomass, double max_biomass) {
66+
int birth_counter =0; // VARIABLE TO KEEP TRACK OF NUMBER OF CELL DIVISIONS TO UPDATE AGENT INDEX
67+
68+
// PERFORM BIOMASS DIVISION FOR AGENTS WITH HIGH BIOMASS
69+
if (this.mass > max_biomass) {
70+
Random r = new Random();
71+
double new_mass = initial_biomass + (max_biomass - initial_biomass)/2 * r.nextDouble(); // CALCULATE DAUGHTER AGENT BIOMASS
72+
73+
this.mass = this.mass - new_mass; // UPDATE MOTHER AGENT BIOMASS
74+
double angle2 = this.angle + -10 + (int) (Math.random() * ((10 - (-10)) + 1)); //CALCULATE DAUGHTER AGENT ANGLE
75+
76+
// CALCULATE DAUGHTER AGENT X,Y,Z COORDINATES
77+
double dx= 1 + (1 - 0.5) * r.nextDouble();
78+
double dy= 1 + (1 - 0.5) * r.nextDouble();
79+
dx= dx * Math.cos(angle);
80+
dy= dy * Math.sin(angle); ;
81+
double dz = 0;
82+
double neg_pos_x = Math.random();
83+
double neg_pos_y = Math.random();
84+
if (neg_pos_x > 0.5){
85+
dx = -dx;
86+
}
87+
if (neg_pos_y > 0.5){
88+
dy = -dy;
89+
}
90+
if (Math.random()>0.5 & this.Zpt()<20) {
91+
Random randomno = new Random();
92+
dz = randomno.nextGaussian()*0.1+0.6;
93+
if (dz < 0){
94+
dz = 0.4;
95+
}
96+
}
97+
98+
// GENERATE DAUGHTER AGENT
99+
G.NewAgentPTSafe(this.Xsq()+dx,this.Ysq()+dy,this.Zsq()+dz).Init(new_mass,angle2, this.metabolic_state, pop , this.t_switch_0, this.t_switch_1);
100+
birth_counter = birth_counter + 1; // UPDATE BIRTH COUNTER
101+
}
102+
return birth_counter;
103+
}
104+
105+
}
106+
107+
// MIMICS MODEL CLASS
108+
public class MIMICS extends AgentGrid3D<Cell3D> {
109+
public MIMICS(int xdim, int ydim, int zdim) {
110+
super(xdim, ydim, zdim, Cell3D.class);
111+
} // CREATE MIMICS CLASS
112+
Rand rn = new Rand();
113+
114+
// CREATE ARRAY LISTS FOR AGENT NEIGHBORS
115+
ArrayList<Cell3D> neighborList = new ArrayList<>();
116+
ArrayList<Cell3D> neighborList2 = new ArrayList<>();
117+
ArrayList<double[]> neighborInfo = new ArrayList<>();
118+
AgentList<Cell3D> cells = new AgentList<>();
119+
int[] vnHood2d = MooreHood(false); // AGENT 2D NEIGHBORHOOD
120+
121+
// INITIALIZE MAXIMUM CELL INDEX
122+
int max_cell_index = 0;
123+
124+
// INITIALIZE ARRAYS CONTAINING METABOLITE PDE GRIDS
125+
ArrayList<PDEGrid3D> carbon_metabolites = new ArrayList<PDEGrid3D>(); // CARBON METABOLITE PDE GRIDS
126+
ArrayList<PDEGrid3D> gas_metabolites = new ArrayList<PDEGrid3D>(); // GAS METABOLITE PDE GRIDS
127+
128+
// DEFINE AGENT PARAMETERS USED FOR FORCE CALCULATIONS
129+
double RADIUS; // AGENT RADIUS
130+
double FORCE_SCALER; // FORCE SCALAR
131+
double FRICTION; // FRICTION SCALAR
132+
133+
// METHOD TO SAVE AGENT INFORMATION AT A DESIRED SIMULATION TIME POINT
134+
public void Save_Cell_Info(int time, int rep,int pop, String file_name) throws IOException {
135+
double[][] output = new double[pop][11]; // OUTPUT MATRIX: [ROWS: EACH AGENT, COLUMNS: AGENT ATTRIBUTES]
136+
int c = 0; // INITIALIZE OUTPUT MATRIX ROW INDEX
137+
for (Cell3D cell : this) { // ITERATE OVER EACH AGENT
138+
double x = cell.Xpt(); double y = cell.Ypt(); double z = cell.Zpt(); // AGENT X,Y,Z COORDINATES
139+
// ASSIGN VALUES TO OUTPUT MATRIX
140+
output[c][0] = time;
141+
output[c][1] = cell.index;
142+
output[c][2] = x;
143+
output[c][3] = y;
144+
output[c][4] = z;
145+
output[c][5] = cell.metabolic_state;
146+
output[c][6] = cell.mass;
147+
output[c][7] = cell.growth_rate;
148+
output[c][8] = gas_metabolites.get(0).Get(x, y, z);
149+
output[c][9] = carbon_metabolites.get(0).Get(x, y, z);
150+
output[c][10] = rep;
151+
c = c+1;
152+
}
153+
154+
if (time == 0) { // INITIALIZE A NEW CSV OUTPUT FILE IF TIME STEP = 0
155+
StringBuilder sb = new StringBuilder(); // INITIALIZE STRING BUILDER
156+
157+
// ASSIGN COLUMN TITLES (correspond to the order of attributes in the output matrix above)
158+
sb.append("time"); sb.append(",");
159+
sb.append("cell index"); sb.append(",");
160+
sb.append("xcor"); sb.append(",");
161+
sb.append("ycor"); sb.append(",");
162+
sb.append("zcor"); sb.append(",");
163+
sb.append("metabolic_state"); sb.append(",");
164+
sb.append("biomass"); sb.append(",");
165+
sb.append("growth_rate"); sb.append(",");
166+
sb.append("oxygen"); sb.append(",");
167+
sb.append("glucose"); sb.append(",");
168+
sb.append("job_num"); sb.append('\n');
169+
170+
// ADD AGENT OUTPUTS TO STRING BUILDER FOR CSV FILE
171+
for (int j = 0; j < pop; j++) { // ITERATE OVER EACH AGENT
172+
for (int i = 0; i < 11; i++) { // ITERATE OVER EACH OUTPUT METRIC
173+
sb.append(output[j][i]); sb.append(","); }
174+
sb.append('\n'); }
175+
176+
// WRITE OUTPUT TO NEW CSV
177+
BufferedWriter br = new BufferedWriter(new FileWriter(file_name));
178+
br.write(sb.toString());
179+
br.close();
180+
}
181+
182+
if (time != 0) { // APPEND OUTPUT MATRIX TO EXISTING CSV IF TIME IS NOT ZERO
183+
StringBuilder sb = new StringBuilder();
184+
for (int j = 0; j < pop; j++) { // ITERATE OVER EACH AGENT
185+
for (int i = 0; i < 11; i++) { // ITERATE OVER EACH OUTPUT METRIC
186+
sb.append(output[j][i]); sb.append(","); }
187+
sb.append('\n');
188+
}
189+
// APPEND OUTPUT TO EXISTING CSV
190+
BufferedWriter br = new BufferedWriter(new FileWriter(file_name,true));
191+
br.write(sb.toString());
192+
br.close();
193+
}
194+
}
195+
196+
// METHOD TO SAVE METABOLITE CONCENTRATION INFORMATION
197+
public void Save_Met_Info(int time, int rep, String file_name) throws IOException {
198+
double[][] output = new double[xDim * yDim* zDim][7]; // METABOLITE ARRAY: [rows: 3D metabolite grid location, columns: output metrics]
199+
int c = 0; // INITIALIZE OUTPUT MATRIX ROW INDEX
200+
// ITERATE OVER EACH PATCH LOCATION IN METABOLITE GRID
201+
for (int x = 0; x < xDim; x++) {
202+
for (int z = 0; z < zDim; z++) {
203+
for (int y = 0; y < yDim; y++) {
204+
output[c][0] = x;
205+
output[c][1] = y;
206+
output[c][2] = z;
207+
output[c][3] = gas_metabolites.get(0).Get(x, y, z);
208+
output[c][4] = carbon_metabolites.get(0).Get(x, y, z);
209+
output[c][5] = time;
210+
output[c][6] = rep;
211+
c = c + 1;
212+
}
213+
}
214+
}
215+
216+
if (time == 0) { // INITIALIZE NEW CSV OUTPUT FILE IF TIME STEP = 0
217+
BufferedWriter br = new BufferedWriter(new FileWriter(file_name));
218+
StringBuilder sb = new StringBuilder();
219+
// ASSIGN OUTPUT TITLES (correspond to the order of metrics in output matrix above)
220+
sb.append("xcor");
221+
sb.append(",");
222+
sb.append("ycor");
223+
sb.append(",");
224+
sb.append("zcor");
225+
sb.append(",");
226+
sb.append("oxygen");
227+
sb.append(",");
228+
sb.append("glucose");
229+
sb.append(",");
230+
sb.append("time");
231+
sb.append(",");
232+
sb.append("job_num"); sb.append('\n');
233+
234+
// SAVE OUTPUT MATRIX TO STRING BUILDER AND WRITE TO NEW CSV FILE
235+
for (int j = 0; j < xDim * yDim * zDim; j++) { // ITERATE OVER EACH LOCATION IN 3D METABOLITE GRID
236+
for (int i = 0; i < 7; i++) { // ITERATE OVER EACH METRIC
237+
sb.append(output[j][i]);
238+
sb.append(",");
239+
}
240+
sb.append('\n');
241+
}
242+
br.write(sb.toString());
243+
br.close();
244+
}
245+
246+
if (time != 0) { // IF TIME IS NOT ZERO, APPEND TO EXISTING CSV FILE
247+
BufferedWriter br = new BufferedWriter(new FileWriter(file_name, true));
248+
StringBuilder sb = new StringBuilder();
249+
250+
for (int j = 0; j < xDim * yDim * zDim; j++) { // ITERATE OVER EACH LOCATION IN 3D METABOLITE GRID
251+
for (int i = 0; i < 7; i++) {
252+
sb.append(output[j][i]);
253+
sb.append(",");
254+
}
255+
sb.append('\n');
256+
}
257+
br.write(sb.toString());
258+
br.close();
259+
}
260+
}
261+
262+
// METHOD TO INITIALIZE METABOLITE CONCENTRATIONS IN ALL LOCATIONS IN METABOLITE PDE GRID
263+
public void Initialize_Metabolites(int num_met_gas, double[] initial_gas_concentrations, int num_met_carbon,double[] initial_carbon_concentrations) {
264+
// INITIALIZE GAS METABOLITE CONCENTRATIONS
265+
for (int m = 0; m < num_met_gas; m++) {
266+
gas_metabolites.get(m).SetAll(initial_gas_concentrations[m]); // UNITS: mM
267+
gas_metabolites.get(m).Update();
268+
}
269+
// INITIALIZE CARBON METABOLITE CONCENTRATIONS
270+
for (int m = 0; m < num_met_carbon; m++) {
271+
carbon_metabolites.get(m).SetAll(initial_carbon_concentrations[m]); // UNITS: mM
272+
carbon_metabolites.get(m).Update();
273+
}
274+
}
275+
276+
// METHOD TO DIFFUSE GASES
277+
public void Gas_Diffuse(int num_met_gas,double[] initial_gas_concentration, double[] D_gas, int num_gas_step) {
278+
for (int i = 0; i < num_gas_step; i++) { // PERFORM GAS DIFFUSION FOR A DISCRETE NUMBER OF TIME STEPS
279+
// SET AREAS WITHOUT AGENTS TO A CONSTANT CONCENTRATION
280+
for (int x = 0; x < xDim; x++) {
281+
for (int z = 0; z < zDim; z++) {
282+
for (int y = 0; y < yDim ; y++) {
283+
if (GetAgent(x, y, z) == null) {
284+
int[] vnHood3d = Util.MooreHood3D(false);
285+
int ct = MapEmptyHood(vnHood3d, x, y, z);
286+
int ct_max = MapHood(vnHood3d, x, y, z);
287+
if (ct == ct_max) {
288+
for (int m = 0; m < num_met_gas; m++) {
289+
gas_metabolites.get(m).Set(x, y, z, initial_gas_concentration[m]);
290+
}
291+
}
292+
}
293+
}
294+
}
295+
}
296+
for (int m = 0; m < num_met_gas; m++) {
297+
gas_metabolites.get(m).Update(); // UPDATE METABOLITE CONCENTRATIONS
298+
gas_metabolites.get(m).DiffusionADI(D_gas[m]); // DIFFUSE METABOLITE CONCENTRATIONS
299+
gas_metabolites.get(m).Update(); // UPDATE METABOLITE CONCENTRATIONS
300+
}
301+
}
302+
}
303+
304+
305+
// METHOD TO DIFFUSE CARBON SUBSTRATES
306+
public void Carbon_Diffuse(int num_met_carbon,double[] initial_carbon_concentration,double[] D_carbon, int num_carbon_step) {
307+
for (int i = 0; i < num_carbon_step; i++) { // PERFORM CARBON DIFFUSION FOR A DISCRETE NUMBER OF TIME STEPS
308+
// SET AREAS WITHOUT AGENTS TO A CONSTANT CONCENTRATION
309+
for (int x = 0; x < xDim; x++) {
310+
for (int z = 0; z < zDim; z++) {
311+
for (int y = 0; y < yDim; y++) {
312+
if (GetAgent(x, y, z) == null) {
313+
int[] vnHood3d = Util.MooreHood3D(false);
314+
int ct = MapEmptyHood(vnHood3d, x, y, z);
315+
int ct_max = MapHood(vnHood3d, x, y, z);
316+
if (ct == ct_max) {
317+
for (int m = 0; m < num_met_carbon; m++) {
318+
carbon_metabolites.get(m).Set(x, y, z, initial_carbon_concentration[m]);
319+
}
320+
}
321+
}
322+
}
323+
}
324+
}
325+
for (int m = 0; m < num_met_carbon; m++) {
326+
carbon_metabolites.get(m).Update(); // UPDATE METABOLITE CONCENTRATIONS
327+
carbon_metabolites.get(m).DiffusionADI(D_carbon[m]); // DIFFUSE METABOLITE CONCENTRATIONS
328+
carbon_metabolites.get(m).Update(); // UPDATE METABOLITE CONCENTRATIONS
329+
}
330+
}
331+
}
332+
333+
// METHOD TO PERFORM AGENT METHODS
334+
public void StepCells(double initial_biomass,double max_biomass,int dead_state) {
335+
CleanAgents(); // CLEAN REMOVED AGENTS IF NECESSARY
336+
// ITERATE OVER EACH AGENT
337+
for (Cell3D cell : this) {
338+
if (cell.metabolic_state != dead_state) { // IF THE CELL IS NOT DEAD
339+
340+
// PERFORM AGENT BIOMASS DIVISION
341+
int birth_counter = cell.Biomass_Divide(max_cell_index,initial_biomass,max_biomass);
342+
343+
// RESET MAXIMUM CELL INDEX (USED TO ASSIGN NEW CELL INDEX TO DAUGHTER CELLS) IF DIVISION EVENT OCCURED
344+
if (birth_counter > 0) {
345+
max_cell_index = max_cell_index + 1;
346+
}
347+
348+
// PERFORM CELL MECHANICS
349+
for (int i = 0; i < 5; i++) {
350+
cell.CalcMove();
351+
cell.MoveDiv();
352+
}
353+
}
354+
}
355+
CleanAgents(); // CLEAN REMOVED AGENTS IF NECESSARY
356+
}
357+
358+
// METHOD TO RANDOMLY INITIALIZE AGENTS
359+
public void Initialize_Random(int b0, double initial_biomass, double max_biomass) {
360+
max_cell_index = b0; // SET MAXIMUM CELL INDEX
361+
for (int j = 0; j <= max_cell_index-1; j++) { // j DEFINES THE AGENT INDEX
362+
double x = rn.Double(xDim); // X-COORDINATE
363+
double y = rn.Double(yDim); // Y-COORDINATE
364+
Random r = new Random();
365+
double old_mass = initial_biomass + (max_biomass - initial_biomass) * r.nextDouble(); // SET AGENT BIOMASS
366+
int angle = rn.Int(360); // INITIALIZE CELL ANGLE
367+
int metabolic_state = 0; // INITIALIZE METABOLIC MODEL STATE
368+
NewAgentPT(x, y, 0).Init(old_mass,angle, metabolic_state, j, 0, 0);
369+
}
370+
}
371+
372+
// METHOD TO CALL MAIN METHOD
373+
static int count = 0;
374+
public static void mainCaller() throws IOException, NoSuchFieldException, IllegalAccessException {
375+
count++;
376+
while (count == 1) {
377+
main(null);
378+
}
379+
}
380+
381+
public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException {
382+
mainCaller(); // MAIN METHOD USED EXTERNALLY IN MIMICS GATEWAY CLASS
383+
}
384+
}

0 commit comments

Comments
 (0)