// Define Integer Variables int n_tropo = 2000; int wall = 0; int [] Status = new int[n_tropo]; int [] Status_Chap = new int[n_tropo]; int [] count = new int[n_tropo]; int [] stop = new int[n_tropo]; // Define Float Variables float [][] position = new float [4][n_tropo]; float [][] velocity = new float[4][n_tropo]; float [][] positionNew = new float [4][n_tropo]; float [][] velocityNew = new float [4][n_tropo]; float [][] force = new float [4][n_tropo]; float [] dist_ij = new float [n_tropo]; float [] tropodist = new float [n_tropo]; float gsx = 0; float ts_er = .002; // Timestep for motion in the rough endoplasmic reticulum float w_w = 100; float r_join = 0.02; float r_release = 0.02; PImage b; void setup() { size(600, 800); colorMode(RGB); background(255); frameRate(30); b = loadImage("Background.jpg"); // Status Values are 0 for a new, unitialized tropoelastin, and 1 for an existing tropoelastin for (int i = 0; i < n_tropo; i++) { Status[i] = 0; Status_Chap[i] = 0; count[i] = 0; stop[i]=1; } } // Routine to initialize color, position, and velocity of creatures void init_tropo (int i) { // Initialize Position of Tropoelastin in ER float pX = random(0,1); float pY = random(0.837,1); position[0][i] = pX; position[1][i] = pY; // Initialize Velocity of Tropoelastin in ER float vX = random(-1,1); float vY = random(-1,1); velocity[0][i] = vX; velocity[1][i] = vY; // Set status to Initialized Status[i] = 1; } void init_chap (int i) { // Initialize Position of Chaperone in ER float pX = random(0,1); float pY = random(0.837,1); position[2][i] = pX; position[3][i] = pY; // Initialize Velocity of Chaperone in ER float vX = random(-1,1); float vY = random(-1,1); velocity[2][i] = vX; velocity[3][i] = vY; // Set status to Initialized Status_Chap[i] = 1; } void draw_bounds() { line(0,height*0.837,width,height*0.837); // ER to GA Boundary Line line(0,height*0.498,width,height*0.498); // GA to CM Boundary Line line(0,height*0.41,width,height*0.41); // CM to ECM Boundary Line line(0,height*0.29,width,height*0.29); // ECM to Fiber Boundary Line } void draw_tropo (int i) { if (Status[i] == 1 || Status[i] == 4) { fill(255,0,0); // Fill Red } if (Status[i] == 2 || Status[i] == 5) { fill(0,0,128); // Fill Blue } noStroke(); ellipse(width*position[0][i],height*position[1][i],10,10); } void draw_chap (int i) { fill(34,139,24); // Fill Green noStroke(); rect(width*position[2][i],height*position[3][i],20,10); } void draw() { background(255); image(b, 0, 0); for (int i = 0; i< n_tropo; i++) { if (Status[i] == 0) { init_tropo(i); init_chap(i); } } for (int i = 0; i< n_tropo; i++) { draw_tropo(i); draw_chap(i); draw_bounds(); // Define the Wander Force float f_wX = random(-1,1); float f_wY = random(-1,1); // Define total force force[0][i] = stop[i]*(w_w*f_wX); force[1][i] = stop[i]*(w_w*f_wY); force[2][i] = stop[i]*(w_w*f_wX); force[3][i] = stop[i]*(w_w*f_wY); velocityNew[0][i] = velocity[0][i] + (ts_er*force[0][i]); velocityNew[1][i] = velocity[1][i] + (ts_er*force[1][i]); velocityNew[2][i] = velocity[2][i] + (ts_er*force[2][i]); velocityNew[3][i] = velocity[3][i] + (ts_er*force[3][i]); float velTermX = (velocity[0][i] + velocityNew[0][i])/2; float velTermY = (velocity[1][i] + velocityNew[1][i])/2; float chapvelTermX = (velocity[2][i] + velocityNew[2][i])/2; float chapvelTermY = (velocity[3][i] + velocityNew[3][i])/2; positionNew[0][i] = position[0][i] + ts_er*velTermX; positionNew[1][i] = position[1][i] + ts_er*velTermY; positionNew[2][i] = position[2][i] + ts_er*chapvelTermX; positionNew[3][i] = position[3][i] + ts_er*chapvelTermY; // Set position at wall to negate velocity for tropo if (positionNew[0][i] >= 1 && velocityNew[0][i] > 0) { velocityNew[0][i] *= -1; } if (positionNew[0][i] <= 0 && velocityNew[0][i] < 0) { velocityNew[0][i] *= -1; } if (wall == 0) { if (positionNew[1][i] >= 1 && velocityNew[1][i] > 0) { velocityNew[1][i] *= -1; } if (positionNew[1][i] <= 0.837 && velocityNew[1][i] < 0) { velocityNew[1][i] *= -1; } } if (wall == 1 && Status[i] == 2) { if (positionNew[1][i] >= 0.837 && velocityNew[1][i] > 0) { velocityNew[1][i] *= -1; } if (positionNew[1][i] <= 0.498 && velocityNew[1][i] < 0) { velocityNew[1][i] *= -1; } } if (wall == 2 && Status[i] !=4) { if (positionNew[1][i] >= 0.41 && velocityNew[1][i] > 0) { velocityNew[1][i] *= -1; } if (positionNew[1][i] <= 0.31 && velocityNew[1][i] < 0) { velocityNew[1][i] *= -1; } } if (Status[i] == 4) { if (positionNew[1][i] >= 0.29 && velocityNew[1][i] > 0) { velocityNew[1][i] *= -1; } if (positionNew[1][i] <= 0 && velocityNew[1][i] < 0) { velocityNew[1][i] *= -1; } } // Set position at wall to negate velocity for chap if (positionNew[2][i] >= 1 && velocityNew[2][i] > 0) { velocityNew[2][i] *= -1; } if (positionNew[2][i] <= 0 && velocityNew[2][i] < 0) { velocityNew[2][i] *= -1; } if (wall == 0) { if (positionNew[3][i] >= 1 && velocityNew[3][i] > 0) { velocityNew[3][i] *= -1; } if (positionNew[3][i] <= 0.837 && velocityNew[3][i] < 0) { velocityNew[3][i] *= -1; } } if (wall == 1 && Status_Chap[i] == 2) { if (positionNew[3][i] >= 0.837 && velocityNew[3][i] > 0) { velocityNew[3][i] *= -1; } if (positionNew[3][i] <= 0.498 && velocityNew[3][i] < 0) { velocityNew[3][i] *= -1; } } if (wall == 2) { if (positionNew[3][i] >= 0.41 && velocityNew[3][i] > 0) { velocityNew[3][i] *= -1; } if (positionNew[3][i] <= 0.31 && velocityNew[3][i] < 0) { velocityNew[3][i] *= -1; } } if (Status_Chap[i] == 4) { if (positionNew[3][i] >= 0.29 && velocityNew[3][i] > 0) { velocityNew[3][i] *= -1; } if (positionNew[3][i] <= 0 && velocityNew[3][i] < 0) { velocityNew[3][i] *= -1; } } // Implement Velocity Clamping // implement velocity clamping if (velocityNew[0][i] < -1) { velocityNew[0][i] = -1; } if (velocityNew[0][i] > 1) { velocityNew[0][i] = 1; } if (velocityNew[1][i] < -1) { velocityNew[1][i] = -1; } if (velocityNew[1][i] > 1) { velocityNew[1][i] = 1; } if (velocityNew[2][i] < -1) { velocityNew[2][i] = -1; } if (velocityNew[2][i] > 1) { velocityNew[2][i] = 1; } if (velocityNew[3][i] < -1) { velocityNew[3][i] = -1; } if (velocityNew[3][i] > 1) { velocityNew[3][i] = 1; } position[0][i] = positionNew[0][i]; // tropo x position[1][i] = positionNew[1][i]; // tropo y velocity[0][i] = velocityNew[0][i]; // tropo x velocity[1][i] = velocityNew[1][i]; // tropo y if (Status_Chap[i] == 1) { position[2][i] = positionNew[2][i]; // chap x position[3][i] = positionNew[3][i]; // chap y velocity[2][i] = velocityNew[2][i]; // chap x velocity[3][i] = velocityNew[3][i]; // chap y } if (Status_Chap[i] == 2) { position[2][i] = position[0][i]; // chap x = tropo x position[3][i] = position[1][i]; // chap y = tropo y velocity[2][i] = velocity[0][i]; // chap x = tropo x velocity[3][i] = velocity[1][i]; // chap y = tropo y } } // Calculate Distance Between Tropo and Chaperone for (int i = 0; i < n_tropo; i++) { for (int j = 0; j < n_tropo; j++) { float dX = position[0][i] - position[2][j]; float dY = position[1][i] - position[3][j]; dist_ij[j] = sqrt(sq(dX)+sq(dY)); if (count[j] == 0 && dist_ij[j] <= r_join) { count[j] += 1; Status[j] = 2; Status_Chap[j] = 2; position[0][i] = position[2][j]; position[1][i] = position[3][j]; } } } gsx += 4; for (int i = 0; i < 6; i++) { for (int j = 0; j < n_tropo; j++) { float dX = position[2][j] - (gsx+i*100-7)/width; float dY = position[3][j] - 0.31; float distance = sqrt(sq(dX)+sq(dY)); if (distance < r_release) { position[2][j] = gsx+i*100-7; position[3][j] = 0.31; Status[j] = 4; Status_Chap[j] = 4; } } if (gsx+i*100 > width) { gsx = 0; } stroke(0); line(gsx+i*100,0.29*height,gsx+i*100,0.31*height); noStroke(); fill(148,0,211); rect(gsx+i*100-7,0.31*height,14,14); } for (int i = 0; i < n_tropo; i++) { for (int j = 0; j < n_tropo; j++) { if (Status[i] == 4 && Status[j] ==4) { if (position[1][i] < 0.2 ) { float dX = position[0][i] - position[0][j]; float dY = position[1][i] - position[1][j]; tropodist[i] = sqrt(sq(dX)+sq(dY)); if (abs(tropodist[i]-0.05)< 0.03) { velocity[0][i] = 0; velocity[1][i] = 0; velocity[0][j] = 0; velocity[1][j] = 0; stop[i]=0; stop[j]=0; Status[i]=5; Status[j]=5; } } } } } saveFrame(); } // end draw void keyPressed() { if (key == 'e' || key == 'E') { wall = 0; } if (key == 'g' || key == 'G') { wall = 1; } if (key == 'm' || key == 'M') { wall = 2; } }