/* finds the nearest stem cell */
struct distance_result distance_to_nearest_stem_cell(double x1, 
												     double y1, 
												     double z1)
{
	/*double x2, y2, z2;*/
	struct distance_result res;
	
	res.nearest_distance = -1.0;
	res.nearest_xy = -1.0;
	res.nearest_z  = -1.0;
			
	location_message = get_first_location_message();
	while(location_message)
	{
	    double x2 = location_message->x;
	    double y2 = location_message->y;
		double z2 = location_message->z;
	
		if (location_message->type == K_TYPE_STEM) {
	    	double distance_check = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2));
			if (res.nearest_distance == -1.0 || distance_check < res.nearest_distance) {
				res.nearest_distance = distance_check;	
				res.nearest_xy = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
				res.nearest_z  = fabs(z1-z2);
			}
		}
		location_message = get_next_location_message(location_message);
	}
	
	return res;
}
Esempio n. 2
0
__FLAME_GPU_FUNC__ int inputdata(xmachine_memory_Circle* xmemory, xmachine_message_location_list* location_messages, xmachine_message_location_PBM* partition_matrix)
{

  float x1, y1, z1, x2, y2, z2, fx, fy, fz, toLocX, toLocY, toLocZ;
  float separation;
  float k;
  x1 = xmemory->x;
  fx = 0.0;
  y1 = xmemory->y;
  fy = 0.0;
  z1 = xmemory->z;
  fz = 0.0;
    
  // Loop through all messages 
  xmachine_message_location* location_message = get_first_location_message(location_messages, partition_matrix, (float)xmemory->x, (float)xmemory->y, (float)xmemory->z);
  while(location_message)
  {
      if((location_message->id != xmemory->id))
      {
          x2 = location_message->x;
          y2 = location_message->y;
          z2 = location_message->z;
          
          toLocX = x2-x1;
          toLocY = y2-y1;
          toLocZ = z2-z1;
          if(toLocX!=0.0f||toLocY!=0.0f||toLocZ!=0.0f)
          {
            // Deep (expensive) check 
            separation = sqrt(toLocX*toLocX + toLocY*toLocY + toLocZ*toLocZ);
            if(separation < INTERACTION_RADIUS2)
            {
              k = (separation < INTERACTION_RADIUS) ? REPULSION_FORCE : ATTRACTION_FORCE;
              toLocX = (separation < INTERACTION_RADIUS) ? -toLocX : toLocX;
              toLocY = (separation < INTERACTION_RADIUS) ? -toLocY : toLocY;
              toLocZ = (separation < INTERACTION_RADIUS) ? -toLocZ : toLocZ;
              toLocX /= separation;//Normalize (without recalculating separation)
              toLocY /= separation;//Normalize (without recalculating separation)
              toLocZ /= separation;//Normalize (without recalculating separation)
              separation = (separation < INTERACTION_RADIUS) ? separation : (INTERACTION_RADIUS2 - separation);
              fx += k * separation * toLocX;
              fy += k * separation * toLocY;
              fz += k * separation * toLocZ;
            }
          }
      }
      //Move onto next message to check 
      location_message = get_next_location_message(location_message, location_messages, partition_matrix);
  }
  xmemory->fx = fx;
  xmemory->fy = fy;
  xmemory->fz = fz;
  
  return 0;
}
Esempio n. 3
0
/** \fn inputdata()
 * \brief Read all messages from other agents
 */
int inputdata()
{
	xmachine_memory_Circle * xmemory = current_xmachine->xmachine_Circle;
	double x1, y1, x2, y2;
    double deep_distance_check, separation_distance;
    double k;
    double eps=1.0e-15;
    xmemory->fx = 0.0;
    xmemory->fy = 0.0;
    x1 = xmemory->x;
    y1 = xmemory->y;
    
    /* Loop through all messages */
	location_message = get_first_location_message();
    while(location_message)
    {
        if((location_message->id != xmemory->id))
        {
            x2 = location_message->x;
            y2 = location_message->y;
            /* Deep (expensive) check */
            deep_distance_check = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
            separation_distance = (deep_distance_check - xmemory->radius - xmemory->radius);
            if(separation_distance < xmemory->radius)
            {
                if(separation_distance > 0.0) k = ka;
                else k = kr;
		if(fabs(deep_distance_check) >0){
	                xmemory->fx += k*(separation_distance)*((x2-x1)/deep_distance_check);
        	        xmemory->fy += k*(separation_distance)*((y2-y1)/deep_distance_check);
		}
		else {
			printf("Agents coincident!\n");
			printf("sep dist=%f deep_dist=%f\n",separation_distance,deep_distance_check);
	                xmemory->fx += k*rand()*eps;
        	        xmemory->fy += k*rand()*eps;
			printf("fx=%f fy=%f rand=%d\n",xmemory->fx,xmemory->fy,rand());
		}
            }
        }
        /* Move onto next message to check */
        location_message = get_next_location_message(location_message);
    }
	
	return 0;
}
int migrate_start()
{
	xmachine_memory_keratinocyte * xmemory = current_xmachine->xmachine_keratinocyte;
	
	/* these are the 'current' parameters*/
	double x1, y1, dir1, motility1;
	/* these will be the 'new' parameters*/
	double x2, y2, z2, dir2, motility2;
	
	/* only TAs and HACATs can move*/
	if (get_type() == K_TYPE_TA || get_type() == K_TYPE_HACAT)
	{
		/* these are the 'current' parameters*/
		x1 = get_x();
		y1 = get_y();
		dir1 = get_dir();
		motility1 = get_motility();
		
		/* if rnd less than 0.1, then changed direction within +/- 45 degrees*/
		if (rnd() < 0.1) { 
			dir1 += PI * rnd()/4.0; 
		} 
		x1 += motility1 * cos(dir1);
		y1 += motility1 * sin(dir1);
		
		/* check if we're about to bump into a stationary cell*/
		location_message = get_first_location_message();
		while(location_message)
		{
			x2        = location_message->x;
			y2        = location_message->y;
			z2        = location_message->z;
			dir2      = location_message->dir;
			motility2 = location_message->motility;
			
			/* check if we're on the base of the dish and other cell is stationary*/
			if (on_substrate_surface(z2) && motility2 == 0)
			{
				/* find distance*/
				double distance_check = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
				if (distance_check != 0 && distance_check < K_WIDTH)
				{
					dir1 -= PI;
					
					/* reverse direction*/
					if (dir1 > 2 * PI)
					{
						dir1 -= 2 * PI;	
					}
					
					x1 = get_x() + motility1 * cos(dir1);
					y1 = get_y() + motility1 * sin(dir1);    					
				}
				
			}
			
			location_message = get_next_location_message(location_message);	
		}
			
		/* update memory with new parameters*/
		set_x(x1);
		set_y(y1);
		set_dir(dir1);
		set_motility(motility1);
		
		/* check we've not gone over the edge of the dish!*/
		/* if so, reverse direction*/
		if (xmemory->x > substrate_width) { 
			xmemory->x   = substrate_width - xmemory->motility *rnd(); 
			xmemory->dir = PI + PI * (rnd()-0.5)/4.0; 
		} 
		if (xmemory->x < 0) { 
			xmemory->x   = xmemory->motility *rnd();
			xmemory->dir = PI * (rnd()-0.5)/4.0; 
		} 
		if (xmemory->y > substrate_width) { 
			xmemory->y   = substrate_width -xmemory->motility *rnd(); 
			xmemory->dir = (3.0 * PI/2.0) + PI * (rnd()-0.5)/4.0; 
		} 
		if (xmemory->y < 0) { 
			xmemory->y   = xmemory->motility * rnd();
			xmemory->dir = (PI/2.0) + PI * (rnd()-0.5)/4.0; 	
		} 
	}
	
	add_location_unresolved_message(ID, TYPE, DIR, MOTILITY, 1000.0, X, Y, Z);
	
	return 0;
}
int differentiate()
{
	int num_stem_neighbours;
	double x1 = get_x();
	double y1 = get_y();
	double z1 = get_z();

	if (get_type() == K_TYPE_STEM)
	{
		
		
		/* For stem cells, we check if the colony is too big and if they are on the edge.*/
		/* If so, they differentiate into TA cells.	*/
		if (on_colony_edge(get_num_stem_bonds()))
		{
			
			num_stem_neighbours = 0;
			
			location_message = get_first_location_message();
			while(location_message)
			{
				double x2 = location_message->x;
				double y2 = location_message->y;
				double z2 = location_message->z;
			
				if (location_message->type == K_TYPE_STEM)
				{
					double distance_check = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2));
					
					double max_distance = K_WIDTH * (get_max_stem_colony_size(calcium_level) / 2.0);
					
					if (distance_check < max_distance)
					{
						num_stem_neighbours++;
					}
				}
				location_message = get_next_location_message(location_message);
			}
			
			//printf("num_stem_neighbours = %d max_colony_size = %f \n", num_stem_neighbours, get_max_stem_colony_size(calcium_level));
			
			if (num_stem_neighbours > get_max_stem_colony_size(calcium_level))
			{
				set_type(K_TYPE_TA);
			}
		}
		
		//printf("num_stem_bonds = %d num_stem_neighbours = %d\n", get_num_stem_bonds(), num_stem_neighbours);
		
		/* If the cell stratifies, it also differentiates into a TA cell*/
		if (!on_substrate_surface(get_z()))
		{
			set_type(K_TYPE_TA);
		}
	} else if (get_type() == K_TYPE_TA) {
		/* If the TA cell is too far from the stem cell centre, it differentiates into in a committed cell.*/
		struct distance_result nearest = distance_to_nearest_stem_cell(get_x(), get_y(), get_z());
		
		Boolean do_diff = check_distance(nearest, 
									 get_ta_to_comm_diff_major_axis(calcium_level), 
									 get_ta_to_comm_diff_minor_axis(calcium_level), 
									 get_diff_noise_factor());
		
			
		if (do_diff) {
			set_type(K_TYPE_COMM);	  
		
		/* If it has been in G0 for a certain period, it also differentiates.*/
		} else if (get_contact_inhibited_ticks() >= MAX_TO_G0_CONTACT_INHIBITED_TICKS) {
			set_type(K_TYPE_COMM);	
		}
		
	} else if (get_type() == K_TYPE_COMM) {
		/* after a period as a committed cell, it dies for good - differentiation into a corneocyte*/
		
		set_dead_ticks(get_dead_ticks()+1);
		if (get_dead_ticks() > MAX_DEAD_TICKS) {
			set_type(K_TYPE_CORN);
		}
	} else if (get_type() == K_TYPE_HACAT) {

		if (get_contact_inhibited_ticks() >= MAX_TO_G0_CONTACT_INHIBITED_TICKS) {
			set_type(K_TYPE_COMM);	
		}
	}

	/* corneocytes also spread a 'death' signal - i.e. they can make cells around them differentiate*/
	/* into corneocytes.*/
	if (get_type() != K_TYPE_CORN) {
		int num_corn_neighbours = 0;
		double prob = 0;
		
		location_message = get_first_location_message();
		while(location_message)
		{
			double x2 = location_message->x;
			double y2 = location_message->y;
			double z2 = location_message->z;
		
			if (location_message->type == K_TYPE_CORN) {
				double distance_check = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2));
				if (distance_check != 0) {
					if (distance_check - K_WIDTH <= FORCE_IRADIUS) {
						num_corn_neighbours ++;
					}
				}
			}
			location_message = get_next_location_message(location_message);
		}	
		
		prob = num_corn_neighbours * num_corn_neighbours * 0.01;
		
		if (rnd() < prob) {
			/* jump through another hoop*/
			if (rnd() < 0.01) {
				set_type(K_TYPE_CORN);	
			}
		}
	}
	
	return 0;
}
/* push cells apart or attract them */
void resolve_forces(int iteration)
{
	double x1 = get_x();
	double y1 = get_y();
	double z1 = get_z();
	int type1 = get_type();
	
	int num_xy_bonds   = 0;
	int num_z_bonds    = 0;
	int num_stem_bonds = 0;
	
	set_force_x(0.0);
	set_force_y(0.0);
	set_force_z(0.0);
	
	location_message = get_first_location_message();

	while (location_message) {	
		//if (location_message->iteration == iteration){

		    double x2 = location_message->x;
		    double y2 = location_message->y;
		    double z2 = location_message->z;
		    int type2 = location_message->type;
		    
		    double distance_check = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2)  + (z1-z2)*(z1-z2));
			
			/*if (distance_check != 0.0)*/
			if (distance_check > 0.001 )
			{
				double force;
				double separation_distance = (distance_check - K_WIDTH);
		        if (separation_distance <= FORCE_IRADIUS) {
		
					if (z2 >= z1) {
						if (z2 - z1 > (K_WIDTH/2)) {
							num_z_bonds ++;					
						}  else {
							num_xy_bonds ++;	
						}
					}
		
					if (location_message->type == K_TYPE_STEM) {
						num_stem_bonds ++;	
					}         	
		        	
		            if (separation_distance > 0.0) {
		            	force = FORCE_MATRIX[type1][type2];         	
		            } else {
		            	force = FORCE_REP;
		            }
		            
		            if (on_substrate_surface(z1)) {
		            	force *= DOWNWARD_FORCE[get_type()];
		            }
		                        
					force *= FORCE_DAMPENER;                        
		                        
		            set_force_x(get_force_x() + 
		            		force * (separation_distance)*((x2-x1)/distance_check));
		            set_force_y(get_force_y() + 
		            		force * (separation_distance)*((y2-y1)/distance_check));
		            set_force_z(get_force_z() + 
		            		force * (separation_distance)*((z2-z1)/distance_check));
		            		
		    	}
		    }
		//}
		location_message = get_next_location_message(location_message);
	}
	
	/* attraction force to substrate*/
	if (z1 <= (K_WIDTH * 1.5)) {
		set_force_z(get_force_z() - SUBSTRATE_FORCE[type1]);
	}
	
	set_num_xy_bonds(num_xy_bonds);
	set_num_z_bonds(num_z_bonds);
	set_num_stem_bonds(num_stem_bonds);
	
	x1 += get_force_x();
	y1 += get_force_y();
	z1 += get_force_z();
	
	if (x1 < 0) {
		x1 = 0;
	}
	
	if (y1 < 0) {
		y1 = 0;
	}
	
	if (z1 < 0) {
		z1 = 0;	
	}	
	
	if (x1 > substrate_width) {
		x1 = substrate_width;
	}
	
	if (y1 > substrate_width) {
		y1 = substrate_width;
	}
	
	set_x(x1); 
	set_y(y1); 
	set_z(z1);		
}