Guest User

Untitled

a guest
Jan 20th, 2018
39
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package ductsim;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.Arrays;
  5. import java.util.Collections;
  6. import java.util.List;
  7. import java.util.concurrent.ThreadLocalRandom;
  8.  
  9. /**
  10.  * DuctSec.java
  11.  *
  12.  * Representación del ducto completo como un conjunto de secciones 2D (SliceSec.java)
  13.  *
  14.  * @author Santiago Zaldívar Lavalle
  15.  */
  16.  
  17. public class DuctSec {
  18.    
  19.     public class Coordinate
  20.     {
  21.         public int x;
  22.         public int y;
  23.         public int z;
  24.        
  25.         public Coordinate(int x, int y, int z)
  26.             { this.x = x; this.y = y; this.z = z; }
  27.         public boolean equals(Coordinate c)
  28.             { return (this.x == c.x) && (this.y == c.y) &&(this.z == c.z); }
  29.     }
  30.    
  31.     public static final int BASAL          = 1;
  32.     public static final int PROG_STEM      = 2;
  33.     public static final int PROG_BIPOTENT  = 3;
  34.     public static final int PROG_MYOEPI    = 4;
  35.     public static final int PROG_LUMEPI    = 5;
  36.     public static final int MYOEPI         = 6;
  37.     public static final int LUMEPI         = 7;
  38.  
  39.     private static final int gene_length   = 32;
  40.    
  41.     private static int     length;
  42.     private static int     radius;
  43.     private static int     diameter;
  44.     private static boolean HGP;           // Indica presencia o no de HGP
  45.     private static int     capacity;      // Capacidad total del ducto
  46.     private static int     stem_capacity; // Capacidad de las dos capas principales del ducto
  47.  
  48.     private static final int mutation_rate = 5; // Representado como mutation_rate/1000
  49.  
  50.     private static int     generation_number;
  51.     private static boolean stem_initialized;  // Indica si se han colocado las células madre
  52.     private static boolean initialized;       // Indica si se ha inicializado el ducto
  53.     private static Integer[] index_array;
  54.  
  55.     private static int total_population;            // Contadores de población
  56.     private static int dysfunctional_population;
  57.     private static int total_reproductions;         // Contadores de reproducción
  58.     private static int dysfunctional_reproductions;
  59.     private static int stem_counter;                // Contadores de mutación
  60.     private static int bipotent_counter;
  61.     private static int proglumepi_counter;
  62.     private static int lumepi_counter;
  63.     private static int mut_stem_counter;
  64.     private static int mut_bipotent_counter;
  65.     private static int mut_proglumepi_counter;
  66.     private static int mut_lumepi_counter;
  67.    
  68.     private static boolean DCIS_achieved;   // Indica si se ha alcanzado DCIS o no
  69.     private static int     DCIS_generation; // Generación en que se generó DCIS
  70.  
  71.     /**
  72.      * Representamos el ducto como un vector de secciones
  73.      */
  74.     private static int[][][] duct;
  75.    
  76.     /**
  77.      * Constructor del ducto
  78.      *
  79.      * @param l Longitud del ducto (número de secciones)
  80.      * @param r Radio del ducto
  81.      * @param h Presencia o no de HGP
  82.      */
  83.     public DuctSec(int l, int r, boolean h)
  84.     {
  85.         this.duct = new int[l][r*2][r*2];
  86.         length   = l;
  87.         radius   = r;
  88.         HGP      = h;
  89.         diameter = r*2;
  90.         capacity = 0;
  91.         stem_capacity = 0;
  92.        
  93.         generation_number = 0;
  94.         stem_initialized  = false;
  95.         initialized       = false;
  96.    
  97.         DCIS_achieved   = false;
  98.         DCIS_generation = 0;
  99.         index_array = new Integer[length];
  100.        
  101.         for(int z=0 ; z<length ; z++)
  102.         {
  103.             index_array[z] = z;
  104.             for(int x=0 ; x<=(r/2) ; x++)
  105.             {
  106.                 for(int y=x ; y<=r ; y++)
  107.                 {
  108.                     if (get_point_radius(x,y) == r)
  109.                     {
  110.                         generate_cells_8way(z, y, x, BASAL);
  111.                     }
  112.                 }
  113.             }
  114.         }
  115.  
  116.         for(int i=0 ; i<diameter ; i++)
  117.         {
  118.             for(int j=0 ; j<diameter ; j++)
  119.             {
  120.                 if(get_point_radius(i,j) < radius)
  121.                     capacity++;
  122.                 if(get_point_radius(i,j) == radius-1 || get_point_radius(i,j) == radius-2)
  123.                     stem_capacity++;
  124.             }
  125.         }
  126.         capacity *= length;
  127.         stem_capacity *= length;
  128.     }
  129.    
  130.     public int get_generation_number()           { return generation_number; }
  131.     public int get_length()                      { return length; }
  132.     public int get_radius()                      { return radius; }
  133.     public int get_diameter()                    { return diameter; }
  134.     public int get_capacity()                    { return capacity; }
  135.     public int[][] get_slice(int z)              { return duct[z]; }
  136.    
  137.     public int get_dysfunctional_population()    { return dysfunctional_population; }
  138.     public int get_total_population()            { return total_population; }
  139.     public int get_dysfunctional_reproductions() { return dysfunctional_reproductions; }
  140.     public int get_total_reproductions()         { return total_reproductions; }
  141.    
  142.     public int DCIS_achieved()
  143.     {
  144.         if(!DCIS_achieved)
  145.             return 0;
  146.         else
  147.             return DCIS_generation;
  148.     }
  149.    
  150.     // [OPT] Cambiar las llamadas a función por acceso directo a la matriz
  151.     // duct.[c.z][c.y][c.x] o algo así
  152.     // en realidad para lo que se usa da igual
  153.     public int  get_cell (Coordinate co)       { return duct[co.z][co.y][co.x]; }
  154.     public void set_cell(Coordinate co, int c) {   this.duct[co.z][co.y][co.x] = c; }
  155.     public void erase_cell(Coordinate co)      {   this.duct[co.z][co.y][co.x] = 0; }
  156.    
  157.     public void generate_cells_8way(int z, int y, int x, int type)
  158.     {
  159.         int r = radius;
  160.         duct[z][x][y] = Cell(type);
  161.         duct[z][x][2*r-y] = Cell(type);
  162.         duct[z][2*r-x][y] = Cell(type);
  163.         duct[z][2*r-x][2*r-y] = Cell(type);
  164.         // simetría diagonal
  165.         duct[z][y][x] = Cell(type);
  166.         duct[z][y][2*r-x] = Cell(type);
  167.         duct[z][2*r-y][x] = Cell(type);
  168.         duct[z][2*r-y][2*r-x] = Cell(type);
  169.     }
  170.  
  171.     public static int get_point_radius(int x, int y)
  172.     {
  173.         // [ALT]: Fórmula que se ajuste al círculo que se ve en el paper
  174.         return (int)(Math.sqrt((x-radius)*(x-radius)+(y-radius)*(y-radius))+1);
  175.     }
  176.  
  177.         public int Cell (int type)
  178.     {
  179.         return type * (int)1e8;
  180.     }
  181.    
  182.     public int get_cell_type(int c)
  183.     {
  184.         return c/(int)1e8;
  185.     }
  186.  
  187.     public int get_gene_housekeeping(int c)
  188.     {
  189.         return (c % (int)1e8) / (int)1e6;
  190.     }
  191.  
  192.     public int get_gene_protooncogene(int c)
  193.     {
  194.         return (c % (int)1e6) / (int)1e4;
  195.     }
  196.  
  197.     public int get_gene_supressor(int c)
  198.     {
  199.         return (c % (int)1e4) / (int)1e2;
  200.     }
  201.  
  202.     public int get_gene_apoptosis(int c)
  203.     {
  204.         return c % (int)1e2;
  205.     }
  206.    
  207.     public int set_cell_type(int c, int type)
  208.     {
  209.         return (c % (int)1e8) + type * (int)1e8;
  210.     }
  211.    
  212.     // Muta 10% del genoma
  213.     public int mutate_HGP(int c)
  214.     {
  215.         int counter = (int)((((float)gene_length) / 100f) * 10f);
  216.         return c += counter * (int)1e6 + counter * (int)1e4 + counter * (int)1e2 + counter;
  217.     }
  218.  
  219.     // Mutation Rate representado como por mil, no por cien
  220.     public int mutate(int c, int mutation_rate)
  221.     {
  222.         int hk_c = gene_length - get_gene_housekeeping(c);
  223.         int po_c = gene_length - get_gene_protooncogene(c);
  224.         int sp_c = gene_length - get_gene_supressor(c);
  225.         int ap_c = gene_length - get_gene_apoptosis(c);
  226.        
  227.         for(int i=0 ; i < hk_c ; i++)
  228.         {
  229.             if(ThreadLocalRandom.current().nextInt(1, 1001) <= mutation_rate)
  230.                 c += (int)1e6;
  231.         }
  232.         for(int i=0 ; i < po_c ; i++)
  233.         {
  234.             if(ThreadLocalRandom.current().nextInt(1, 1001) <= mutation_rate)
  235.                 c += (int)1e4;
  236.         }
  237.         for(int i=0 ; i < sp_c ; i++)
  238.         {
  239.             if(ThreadLocalRandom.current().nextInt(1, 1001) <= mutation_rate)
  240.                 c += (int)1e2;
  241.         }
  242.         for(int i=0 ; i < ap_c ; i++)
  243.         {
  244.             if(ThreadLocalRandom.current().nextInt(1, 1001) <= mutation_rate)
  245.                 c += 1;
  246.         }
  247.        
  248.         return c;
  249.     }
  250.    
  251.     // Método que usamos para ver si la célula es cancerígena según el paper
  252.     public boolean is_considered_cancerous(int c)
  253.     {
  254.         return //get_gene_housekeeping(c)() >= 16 ||
  255.                get_gene_protooncogene(c) >= 16 ||
  256.                //get_gene_supressor(c)() >= 16 ||
  257.                get_gene_apoptosis(c)     >= 16;
  258.     }
  259.    
  260.     public int get_mutations(int c)
  261.     {
  262.         return get_gene_housekeeping(c)  +
  263.                get_gene_protooncogene(c) +
  264.                get_gene_supressor(c)     +
  265.                get_gene_apoptosis(c);
  266.     }
  267.    
  268.     public boolean is_dysfunctional(int c)
  269.     {
  270.         return get_gene_housekeeping(c)  >= 16 ||
  271.                get_gene_protooncogene(c) >= 16 ||
  272.                get_gene_supressor(c)     >= 16 ||
  273.                get_gene_apoptosis(c)     >= 16;
  274.     }
  275.  
  276.     public boolean housekeeping_is_dysfunctional(int c)
  277.     {
  278.         return get_gene_housekeeping(c) >= 16;
  279.     }
  280.    
  281.     public boolean protooncogene_is_dysfunctional(int c)
  282.     {
  283.         return get_gene_protooncogene(c) >= 16;
  284.     }
  285.        
  286.     public boolean supressor_is_dysfunctional(int c)
  287.     {
  288.         return get_gene_supressor(c)>= 16;
  289.     }
  290.        
  291.     public boolean apoptosis_is_dysfunctional(int c)
  292.     {
  293.         return get_gene_apoptosis(c) >= 16;
  294.     }
  295.  
  296.     public List<Float> mutations_stats()
  297.     {
  298.         List<Float> result = new ArrayList<>();
  299.         result.add((float)mut_stem_counter/(float)stem_counter);
  300.         result.add((float)mut_bipotent_counter/(float)bipotent_counter);
  301.         result.add((float)mut_proglumepi_counter/(float)proglumepi_counter);
  302.         result.add((float)mut_lumepi_counter/(float)lumepi_counter);
  303.         return result;
  304.     }
  305.  
  306.     public void update_counters(Coordinate c)
  307.     {  
  308.         switch(get_cell_type(get_cell(c)))
  309.         {
  310.             case PROG_STEM:
  311.                 stem_counter++;
  312.                 mut_stem_counter += get_mutations(get_cell(c));
  313.                 break;
  314.             case PROG_BIPOTENT:
  315.                 bipotent_counter++;
  316.                 mut_bipotent_counter += get_mutations(get_cell(c));
  317.                 break;
  318.             case PROG_LUMEPI:
  319.                 proglumepi_counter++;
  320.                 mut_proglumepi_counter += get_mutations(get_cell(c));
  321.                 break;
  322.             case LUMEPI:
  323.                 lumepi_counter++;
  324.                 mut_lumepi_counter += get_mutations(get_cell(c));
  325.                 break;
  326.         }
  327.     }
  328.    
  329.  
  330.    
  331.     /**
  332.      * @param c Coordenada
  333.      * @return true si la coordenada c se encuentra dentro del array ducto
  334.      *         (no necesariamente dentro de la membrana basal)
  335.      *         false en caso contrario
  336.      */
  337.     public boolean coordinate_is_inbounds(Coordinate c)
  338.     {
  339.         return (c.x >= 0) && (c.x < diameter) &&
  340.                (c.y >= 0) && (c.y < diameter) &&
  341.                (c.z >= 0) && (c.z < length);
  342.     }
  343.    
  344.     /**
  345.      * @param c Coordenada
  346.      * @return ArrayList de Coordenadas con todos los vecinos (vecindad Moore 3D) de la cordenada c
  347.      */
  348.     private List<Coordinate> get_neighbors(Coordinate c)
  349.     {
  350.         List<Coordinate> neighbors = new ArrayList<>();
  351.         int x = c.x;
  352.         int y = c.y;
  353.         int z = c.z;
  354.         // Las 6 coordenadas "principales" (vecindad directa)
  355.         neighbors.add(new Coordinate(x,   y,   z-1));
  356.         neighbors.add(new Coordinate(x,   y,   z+1));
  357.         neighbors.add(new Coordinate(x,   y-1, z));
  358.         neighbors.add(new Coordinate(x-1, y,   z));
  359.         neighbors.add(new Coordinate(x+1, y,   z));
  360.         neighbors.add(new Coordinate(x,   y+1, z));
  361.         // Vecinos diagonales
  362.         neighbors.add(new Coordinate(x-1, y-1, z-1)); // diagonal
  363.         neighbors.add(new Coordinate(x,   y-1, z-1)); // diagonal
  364.         neighbors.add(new Coordinate(x+1, y-1, z-1)); // diagonal
  365.         neighbors.add(new Coordinate(x-1, y,   z-1)); // diagonal
  366.         neighbors.add(new Coordinate(x+1, y,   z-1)); // diagonal
  367.         neighbors.add(new Coordinate(x-1, y+1, z-1)); // diagonal
  368.         neighbors.add(new Coordinate(x,   y+1, z-1)); // diagonal
  369.         neighbors.add(new Coordinate(x+1, y+1, z-1)); // diagonal
  370.         neighbors.add(new Coordinate(x-1, y-1, z+1)); // diagonal
  371.         neighbors.add(new Coordinate(x,   y-1, z+1)); // diagonal
  372.         neighbors.add(new Coordinate(x+1, y-1, z+1)); // diagonal
  373.         neighbors.add(new Coordinate(x-1, y,   z+1)); // diagonal
  374.         neighbors.add(new Coordinate(x+1, y,   z+1)); // diagonal
  375.         neighbors.add(new Coordinate(x-1, y+1, z+1)); // diagonal
  376.         neighbors.add(new Coordinate(x,   y+1, z+1)); // diagonal
  377.         neighbors.add(new Coordinate(x+1, y+1, z+1)); // diagonal
  378.         neighbors.add(new Coordinate(x-1, y-1, z));   // diagonal      
  379.         neighbors.add(new Coordinate(x+1, y-1, z));   // diagonal      
  380.         neighbors.add(new Coordinate(x-1, y+1, z));   // diagonal  
  381.         neighbors.add(new Coordinate(x+1, y+1, z));   // diagonal
  382.  
  383.         return neighbors;
  384.     }
  385.    
  386.  
  387.     /**
  388.      * @param cell_coord
  389.      * @return Devuelve una coordenada aleatoria que cumple las siguientes condiciones:
  390.      *          - Es vecina de cell_coord
  391.      *          - Se encuentra dentro de la membrana basal
  392.      *          - Está vacía (no está ocupada por una célula)
  393.      *         Si tal coordenada no existe, devuelve null
  394.      */
  395.     private Coordinate get_vacant_neighbor(Coordinate cell_coord)
  396.     {
  397.         List<Coordinate> neighbors = get_neighbors(cell_coord);
  398.         Collections.shuffle(neighbors);
  399.         for(int i=0 ; i < neighbors.size() ; i++)
  400.         {
  401.             Coordinate aux_coord = neighbors.get(i);
  402.             if(coordinate_is_inbounds(aux_coord) == true &&
  403.                get_cell(aux_coord) == 0 &&
  404.                get_point_radius(aux_coord.x, aux_coord.y) < radius)
  405.             {
  406.                 return neighbors.get(i);
  407.             }
  408.         }
  409.         return null;
  410.     }
  411.  
  412.     /**
  413.      * @param cell_coord Coordenada a la que se va a migrar
  414.      * @param old_coord  Coordenada desde la que se migra
  415.      * @return true si cell_coord tiene alguna célula vecina aparte de old_coord
  416.      *         false en caso contrario
  417.      */
  418.     private boolean has_adjadcent_neighbor(Coordinate cell_coord, Coordinate old_coord)
  419.     {
  420.         List<Coordinate> neighbors = get_neighbors(cell_coord);
  421.         for(int i=0 ; i < neighbors.size() ; i++)
  422.         {
  423.             Coordinate aux_coord = neighbors.get(i);
  424.             if(coordinate_is_inbounds(aux_coord) == true &&
  425.                get_cell(aux_coord) != 0 &&
  426.                !aux_coord.equals(old_coord))
  427.             {
  428.                 return true;
  429.             }
  430.         }
  431.         return false;
  432.     }
  433.    
  434.     private boolean reproduce(Coordinate current_cell_coord)
  435.     {  
  436.         List<Coordinate> neighbors = get_neighbors(current_cell_coord);
  437.         Collections.shuffle(neighbors);
  438.         int current_cell_type = get_cell_type(get_cell(current_cell_coord));
  439.        
  440.         /*
  441.         INIT:   Allow progenitor cells to reproduce into vacant neighboring lattice points
  442.                 without cells according to progenitor hierarchy
  443.         NORMAL: if an adjacent neighboring point is vacant and does not break the bi-layer
  444.                 ductal structure (Fig. 3C), the cell reproduces
  445.         */
  446.  
  447.         /* [ALT]: (a) Permitir que una célula mioepitelial se reproduzca en el sitio que sea, y luego
  448.                       se corrija ésto en la migración, o bien
  449.                   (b) Permitir que sólo se genere una célula en un sitio que le 'corresponde' [actual]
  450.         */
  451.  
  452.         int max_radius = radius-1;
  453.         int min_radius = radius-2;
  454.        
  455.         if(current_cell_type == PROG_LUMEPI)
  456.             max_radius--;
  457.         if(current_cell_type == PROG_MYOEPI)
  458.             min_radius++;
  459.        
  460.         Coordinate new_cell_coord = null;
  461.         boolean end_flag = false;
  462.         for(int i=0 ; i<neighbors.size() ; i++)
  463.         {
  464.             // Condiciones: la célula está inbounds, vacía, y entre min_radius y max_radius (inclusive)
  465.             new_cell_coord = neighbors.get(i);
  466.             if(coordinate_is_inbounds(new_cell_coord) == true &&
  467.                get_cell(new_cell_coord) == 0 &&
  468.                // (b)
  469.                get_point_radius(new_cell_coord.x, new_cell_coord.y) <= max_radius &&
  470.                get_point_radius(new_cell_coord.x, new_cell_coord.y) >= min_radius)
  471.                // (a)
  472.                //get_point_radius(new_cell_coord.x, new_cell_coord.y) <= radius &&
  473.                //get_point_radius(new_cell_coord.x, new_cell_coord.y) >= radius-2)                 
  474.             {
  475.                 end_flag = true;
  476.                 break;
  477.             }
  478.         }
  479.        
  480.         if(end_flag == false)
  481.         {
  482.             return false;
  483.         }
  484.  
  485.         int parent = get_cell(current_cell_coord);
  486.         int new_cell = parent;
  487.         switch (get_cell_type(parent))
  488.         {
  489.             // [OPT] Creo que los switch se compilan como una cadena de if-else;
  490.             // por lo que es mejor poner la opción más común primero
  491.             case PROG_LUMEPI:
  492.                 new_cell = set_cell_type(new_cell, LUMEPI);
  493.                 break;
  494.             case PROG_BIPOTENT:
  495.                 // [ALT] Decidimos qué tipo de célula va a generar una bipotente en base a
  496.                 // la posición en que se va a generar
  497.                 if (get_point_radius(new_cell_coord.x, new_cell_coord.y) == radius-1)
  498.                     new_cell = set_cell_type(new_cell, PROG_MYOEPI);
  499.                 else
  500.                     new_cell = set_cell_type(new_cell, PROG_LUMEPI);
  501.                 break;
  502.             case PROG_STEM:
  503.                 new_cell = set_cell_type(new_cell, PROG_BIPOTENT);
  504.                 break;
  505.             case PROG_MYOEPI:
  506.                 new_cell = set_cell_type(new_cell, MYOEPI);
  507.                 break;
  508.             default:
  509.                 break;
  510.         }
  511.         // Mutamos tanto madre como hija
  512.         parent = mutate(parent, mutation_rate);
  513.         new_cell = mutate(new_cell, mutation_rate);
  514.         set_cell(current_cell_coord, parent);
  515.         set_cell(new_cell_coord, new_cell);
  516.        
  517.         return true;
  518.     }
  519.    
  520.     private boolean cancerous_reproduce(Coordinate current_cell_coord)
  521.     {  
  522.         Coordinate new_cell_coord = null;
  523.         Coordinate pushed_position = null;
  524.  
  525.         List<Coordinate> neighbors = get_neighbors(current_cell_coord);
  526.         Collections.shuffle(neighbors);
  527.         boolean end_flag = false;
  528.         for (int i=0 ; i<neighbors.size() ; i++)
  529.         {
  530.             pushed_position = null;
  531.             new_cell_coord = neighbors.get(i);
  532.  
  533.             if (coordinate_is_inbounds(new_cell_coord) == true)
  534.             {
  535.                 if (get_cell(new_cell_coord) == 0 &&
  536.                     get_point_radius(new_cell_coord.x, new_cell_coord.y) < radius)
  537.                 {
  538.                     end_flag = true;
  539.                     break;
  540.                 }
  541.                 // [ALT] Sólo empujamos células LUMEPI (?)
  542.                 if (get_point_radius(new_cell_coord.x, new_cell_coord.y) < radius &&
  543.                     (pushed_position = get_vacant_neighbor(new_cell_coord)) != null)
  544.                 {
  545.                     end_flag = true;
  546.                     break;
  547.                 }
  548.             }  
  549.         }
  550.  
  551.         if(end_flag == false)
  552.         {
  553.             return false;
  554.         }
  555.        
  556.         if(pushed_position != null)
  557.         {
  558.             int pushed_cell = get_cell(new_cell_coord);
  559.             set_cell(pushed_position, pushed_cell);
  560.             erase_cell(new_cell_coord);
  561.         }
  562.        
  563.         int parent = get_cell(current_cell_coord);
  564.         int new_cell = parent;
  565.         switch (get_cell_type(parent))
  566.         {
  567.             case PROG_LUMEPI:
  568.                 new_cell = set_cell_type(new_cell, LUMEPI);
  569.                 break;
  570.             case PROG_BIPOTENT:
  571.                 if (get_point_radius(new_cell_coord.x, new_cell_coord.y) == radius-1)
  572.                     new_cell = set_cell_type(new_cell, PROG_MYOEPI);
  573.                 else
  574.                     new_cell = set_cell_type(new_cell, PROG_LUMEPI);
  575.                 break;
  576.             case PROG_STEM:
  577.                 new_cell = set_cell_type(new_cell, PROG_BIPOTENT);
  578.                 break;
  579.             case PROG_MYOEPI:
  580.                 new_cell = set_cell_type(new_cell, MYOEPI);
  581.                 break;
  582.  
  583.             default:
  584.                 break;
  585.         }
  586.         parent =   mutate(parent, mutation_rate);
  587.         new_cell = mutate(new_cell, mutation_rate);
  588.         set_cell(current_cell_coord, parent);
  589.         set_cell(new_cell_coord, new_cell);
  590.        
  591.         return true;
  592.     }
  593.    
  594.     private boolean hormonal_reproduce(Coordinate current_cell_coord)
  595.     {
  596.         List<Coordinate> neighbors = get_neighbors(current_cell_coord);
  597.         Collections.shuffle(neighbors);
  598.        
  599.         int current_cell_type = get_cell_type(get_cell(current_cell_coord));
  600.         Coordinate new_cell_coord = null;
  601.        
  602.         boolean end_flag = false;
  603.         Coordinate pushed_position = null;
  604.         for (int i=0 ; i<neighbors.size() ; i++)
  605.         {
  606.             new_cell_coord = neighbors.get(i);
  607.             if (coordinate_is_inbounds(new_cell_coord) != false &&
  608.                 get_point_radius(new_cell_coord.x, new_cell_coord.y) < radius &&
  609.                 get_cell(new_cell_coord) != 0 &&
  610.                 (pushed_position = get_vacant_neighbor(new_cell_coord)) != null
  611.                )
  612.             {
  613.                 end_flag = true;
  614.                 break;
  615.             }
  616.         }
  617.  
  618.         if(end_flag == false)
  619.         {
  620.             return false;
  621.         }
  622.  
  623.         int pushed_cell = get_cell(new_cell_coord);
  624.         set_cell(pushed_position, pushed_cell);
  625.         erase_cell(new_cell_coord);
  626.        
  627.         int parent = get_cell(current_cell_coord);
  628.         int new_cell = parent;
  629.         switch (get_cell_type(parent))
  630.         {
  631.             case PROG_LUMEPI:
  632.                 new_cell = set_cell_type(new_cell, LUMEPI);
  633.                 break;
  634.             case PROG_BIPOTENT:
  635.                 if (get_point_radius(new_cell_coord.x, new_cell_coord.y) == radius-1)
  636.                     new_cell = set_cell_type(new_cell, PROG_MYOEPI);
  637.                 else
  638.                     new_cell = set_cell_type(new_cell, PROG_LUMEPI);
  639.                 break;
  640.             case PROG_STEM:
  641.                 new_cell = set_cell_type(new_cell, PROG_BIPOTENT);
  642.                 break;
  643.             case PROG_MYOEPI:
  644.                 new_cell = set_cell_type(new_cell, MYOEPI);
  645.                 break;
  646.             default:
  647.                 break;
  648.         }
  649.         parent   = mutate(parent, mutation_rate);
  650.         new_cell = mutate(new_cell, mutation_rate);
  651.         set_cell(current_cell_coord, parent);
  652.         set_cell(new_cell_coord, new_cell);
  653.        
  654.         return true;
  655.     }
  656.    
  657.     private boolean migrate(Coordinate current_cell_coord)
  658.     {
  659.         List<Coordinate> neighbors = get_neighbors(current_cell_coord);
  660.         Collections.shuffle(neighbors);
  661.        
  662.         int current_cell = get_cell(current_cell_coord);
  663.         int current_cell_type = get_cell_type(current_cell);
  664.        
  665.         int max_radius = radius-1;
  666.         // [ALT]: No permitimos que una célula migre hacia "dentro"; siempre hacia un punto en el mismo radio
  667.         // que el punto en el que está, o mayor
  668.         int min_radius = get_point_radius(current_cell_coord.x, current_cell_coord.y);
  669.        
  670.         /*
  671.         if(get_cell(current_cell_coord).apoptosis_is_dysfunctional())
  672.         {
  673.             // WARN: Arreglar la migración de células cancerígenas (asegurar que migran a un lugar conectado
  674.             // con el nucleo principal de poblacion)
  675.             //min_radius = 0;
  676.         }
  677.         */
  678.         if(current_cell_type == PROG_LUMEPI || current_cell_type == LUMEPI)
  679.             max_radius = radius-2;
  680.             //if(current_cell_type == PROG_MYOEPI || current_cell_type == MYOEPI)
  681.                 //min_radius = radius-1;
  682.         Coordinate new_cell_coord = null;
  683.         boolean end_flag = false;
  684.         for (int i=0 ; i<neighbors.size() ; i++)
  685.         {
  686.             new_cell_coord = neighbors.get(i);
  687.             if (coordinate_is_inbounds(new_cell_coord) == true &&
  688.                 get_cell(new_cell_coord) == 0 &&
  689.                 get_point_radius(new_cell_coord.x, new_cell_coord.y) <= max_radius &&
  690.                 get_point_radius(new_cell_coord.x, new_cell_coord.y) >= min_radius &&
  691.                 has_adjadcent_neighbor(new_cell_coord, current_cell_coord))
  692.             {
  693.                 end_flag = true;
  694.                 break;
  695.             }
  696.        
  697.         }
  698.        
  699.         if(end_flag == false)
  700.         {
  701.             return false;
  702.         }
  703.        
  704.         erase_cell(current_cell_coord);
  705.         set_cell(new_cell_coord, current_cell);
  706.        
  707.         return true;
  708.     }
  709.  
  710.     private void init_routine_stem()
  711.     {
  712.         if(radius == 1)
  713.             return;
  714.        
  715.         // 1. Draw the BASAL membrane by designating outer boundary points in a cylindrical orientation
  716.        
  717.         /* Hecho en constructor de SliceSec */
  718.        
  719.         // 2. Place STEM CELLS within the basal membrane
  720.         //    (less than 5% of the population - 200 for a 24,000 cell pop. => [ ~ 0.84% ])
  721.        
  722.         // [ALT]: Con nuestro modelo de radio, las células que forman las dos capas iniciales son 20,800 contra las
  723.         //        24,000 del paper.
  724.         float stem_cells_percentage = 1f;  // Porcentaje del total de células que queremos que sean células madre
  725.         int n_stem_cells = (int)((((float)stem_capacity) / 100) * stem_cells_percentage);
  726.        
  727.         if(n_stem_cells == 0)
  728.             n_stem_cells = 1;
  729.        
  730.         int chosen_x, chosen_y, chosen_z;
  731.         // Elegimos posición de células madre por polling de puntos aleatorios
  732.         for(int counter = 1 ; counter <= n_stem_cells ; counter++)
  733.         {
  734.             // Elegir SliceSec aleatorio
  735.             chosen_z = ThreadLocalRandom.current().nextInt(0, length);
  736.             // Recorrer slice, elegir punto aleatorio hasta encontrar uno de radio r-1
  737.             do {
  738.                 chosen_x = ThreadLocalRandom.current().nextInt(0, diameter);
  739.                 chosen_y = ThreadLocalRandom.current().nextInt(0, diameter);
  740.             } while (get_point_radius(chosen_x, chosen_y) != radius-1 ||
  741.                      get_cell(new Coordinate(chosen_x, chosen_y, chosen_z)) != 0);
  742.            
  743.             // Establecer nueva célula basal
  744.             Coordinate new_coordinate = new Coordinate(chosen_x, chosen_y, chosen_z);
  745.             int new_stem_cell = Cell(PROG_STEM);
  746.            
  747.             // 3. If HGP, mutate all genes in all stem cells by 10%
  748.             // (ver método en Cell.java)
  749.             if(HGP)
  750.             {
  751.                 // [ALT]: Mutación determinista (mutar 10% del genoma) o estocástica (mutar con 10% de probabilidad) ?
  752.                 new_stem_cell = mutate_HGP(new_stem_cell);
  753.             }
  754.             set_cell(new_coordinate, new_stem_cell);
  755.         }
  756.         total_population += n_stem_cells;
  757.         stem_initialized = true;
  758.     }
  759.    
  760.     private void init_routine()
  761.     {
  762.         boolean end_flag = true; // Indica si la inicialización del ducto ha acabado
  763.        
  764.         if(!stem_initialized)
  765.         {
  766.             init_routine_stem();
  767.             return;
  768.         }
  769.        
  770.         Integer[] index_array_aux = new Integer[index_array.length];
  771.         System.arraycopy(index_array, 0, index_array_aux, 0, index_array.length);
  772.         Collections.shuffle(Arrays.asList(index_array_aux));
  773.         // Iteramos sobre todas las coordenadas posibles (abierto a optimizaciones)
  774.         for(int z_i = 0 ; z_i < index_array_aux.length ; z_i++) {
  775.             int z = index_array_aux[z_i];
  776.             for(int y=0 ; y<diameter ; y++) {
  777.                 for(int x=0 ; x<diameter ; x++) {
  778.                     Coordinate current_cell_coord = new Coordinate(x,y,z);
  779.  
  780.                     // Si la coordenada no contiene ninguna célula o una célula basal, pasamos a la siguiente
  781.                     if(get_cell(current_cell_coord) == 0 || get_cell_type(get_cell(current_cell_coord)) == BASAL)
  782.                         continue;
  783.  
  784.                     total_population++;
  785.                     if(is_dysfunctional(get_cell(current_cell_coord)))
  786.                         dysfunctional_population++;
  787.  
  788.                     int current_cell_type = get_cell_type(get_cell(current_cell_coord));
  789.                     // 4. Allow PROGENITOR cells to REPRODUCE into VACANT NEIGHBORING lattice points WITHOUT CELLS
  790.                     //    according to progenitor hierarchy
  791.                     if (current_cell_type == PROG_STEM     ||
  792.                         current_cell_type == PROG_BIPOTENT ||
  793.                         current_cell_type == PROG_MYOEPI   ||
  794.                         current_cell_type == PROG_LUMEPI)
  795.                     {
  796.                         if (reproduce(current_cell_coord) == true)
  797.                         {
  798.                             end_flag = false;
  799.                             total_reproductions++;
  800.                         }
  801.                     }
  802.                     update_counters(current_cell_coord);
  803.                     // 5. Allow NON-STEM cells to MIGRATE 1 point to a VACANT NEIGHBORING lattice point consistent
  804.                     //    with the bi-layer ductal structure
  805.                     if(current_cell_type != PROG_STEM)
  806.                     {
  807.                         if (migrate(current_cell_coord) == true)
  808.                             end_flag = false;
  809.                     }
  810.                 }
  811.             }
  812.         }  
  813.         initialized = end_flag;
  814.     }
  815.    
  816.     private void normal_routine()
  817.     {
  818.         //Collections.shuffle(Arrays.asList(index_array));
  819.         // Iteramos sobre todas las coordenadas posibles (abierto a optimizaciones)
  820.         for(int z_i = 0 ; z_i < length ; z_i++) {
  821.             int z = index_array[z_i];
  822.             for(int y=0 ; y<diameter ; y++) {
  823.                 for(int x=0 ; x<diameter ; x++) {
  824.                     Coordinate current_cell_coord = new Coordinate(x,y,z);
  825.  
  826.                     if(get_cell(current_cell_coord) == 0 || get_cell_type(get_cell(current_cell_coord)) == BASAL)
  827.                         continue;
  828.  
  829.                     int current_cell = get_cell(current_cell_coord);       
  830.                     total_population++;
  831.  
  832.                     if(is_dysfunctional(current_cell))
  833.                         dysfunctional_population++;
  834.  
  835.                     // Para Graph1
  836.                     if(!DCIS_achieved && is_considered_cancerous(current_cell))
  837.                     {
  838.                         DCIS_achieved = true;
  839.                         DCIS_generation = generation_number;
  840.                     }
  841.  
  842.                     // 1. If housekeeping or apoptosis genes are dysfunctional (50% mutated), mark the cell for death
  843.                     // 3. If dead, remove from lattice
  844.                     if(housekeeping_is_dysfunctional(current_cell) ||
  845.                           (protooncogene_is_dysfunctional(current_cell) &&
  846.                            !supressor_is_dysfunctional(current_cell)    &&
  847.                            !apoptosis_is_dysfunctional(current_cell)))
  848.                     {
  849.                         erase_cell(current_cell_coord);
  850.                         continue;
  851.                     }
  852.  
  853.                     // 2. If apoptosis genes are functional and cell is not adjacent to the basal membrane
  854.                     //    or a myoepithelial cell, mark the cell for death
  855.                     // 3. If dead, remove from lattice
  856.                     if(!apoptosis_is_dysfunctional(current_cell) &&
  857.                        get_point_radius(current_cell_coord.x, current_cell_coord.y) < radius-2)
  858.                     {
  859.                         erase_cell(current_cell_coord);
  860.                         continue;
  861.                     }
  862.  
  863.                     // 4. Progenitor cells may reproduce into neighboring positions according to
  864.                     //    progenitor hierarchy for three reasons:
  865.                     int current_cell_type = get_cell_type(get_cell(current_cell_coord));
  866.                     if (current_cell_type == PROG_STEM     ||
  867.                         current_cell_type == PROG_BIPOTENT ||
  868.                         current_cell_type == PROG_MYOEPI   ||
  869.                         current_cell_type == PROG_LUMEPI)
  870.                     {
  871.                         // Cancerous reproduction—if the cell has a dysfunctional (50%) protooncogene
  872.                         // and tumor suppressor gene, cell reproduces into any vacant neighboring lattice
  873.                         // point or by pushing a neighboring cell to a vacant lattice point and reproducing
  874.                         if(protooncogene_is_dysfunctional(current_cell) &&
  875.                            supressor_is_dysfunctional(current_cell))
  876.                         {
  877.                             if (cancerous_reproduce(current_cell_coord));
  878.                             {
  879.                                 total_reproductions++;
  880.                                 if (is_considered_cancerous(current_cell))
  881.                                     dysfunctional_reproductions++;
  882.                             }
  883.                         }
  884.                         else
  885.                         {
  886.                             // Hormonal reproduction—if cell is stochastically chosen (1% chance), cell
  887.                             // pushes a adjcance neighboring cell to a vacant lattice point and reproduces
  888.                             // [ALT]: No permitimos rep. hormonal de MYOEPI para que no haya MYOEPIs en la capa LUMEPI
  889.                             if(current_cell_type != PROG_MYOEPI && ThreadLocalRandom.current().nextInt(1, 101) == 1)
  890.                             {
  891.                                 if (hormonal_reproduce(current_cell_coord))
  892.                                 {
  893.                                     total_reproductions++;
  894.                                     if (is_considered_cancerous(current_cell))
  895.                                         dysfunctional_reproductions++;
  896.                                 }
  897.                             }
  898.                             else
  899.                             {
  900.                                 // Normal reproduction—if an adjacent neighboring point is vacant and does
  901.                                 // not break the bi-layer ductal structure (Fig. 3C), the cell reproduces
  902.                                 if (reproduce(current_cell_coord))
  903.                                 {
  904.                                     total_reproductions++;
  905.                                     if (is_considered_cancerous(current_cell))
  906.                                         dysfunctional_reproductions++;
  907.                                 }
  908.                             }
  909.                         }
  910.                     }
  911.                     update_counters(current_cell_coord);
  912.                     // 5. Allow non-stem cells to migrate one point to a vacant neighboring lattice point
  913.                     //    consistent with the bi-layer ductal structure (Fig. 3C)
  914.                     if(current_cell_type != PROG_STEM)
  915.                     {
  916.                         migrate(current_cell_coord);
  917.                     }
  918.                 }
  919.             }
  920.         }
  921.     }
  922.    
  923.     protected void next_generation()
  924.     {
  925.         total_population = 0;
  926.         dysfunctional_population = 0;
  927.         total_reproductions = 0;
  928.         dysfunctional_reproductions = 0;
  929.  
  930.         stem_counter = 0;
  931.         bipotent_counter = 0;
  932.         proglumepi_counter = 0;
  933.         lumepi_counter = 0;
  934.         mut_stem_counter = 0;
  935.         mut_bipotent_counter = 0;
  936.         mut_proglumepi_counter = 0;
  937.         mut_lumepi_counter = 0;
  938.        
  939.         if (initialized)
  940.         {
  941.             normal_routine();
  942.         }
  943.         else
  944.         {
  945.             init_routine();
  946.         }
  947.         generation_number++;
  948.     }
  949.  
  950.     protected void execute(int nGens)
  951.     {
  952.         for(int i=0 ; i<nGens ; i++)
  953.         {
  954.             next_generation();
  955.         }
  956.     }
  957. }
RAW Paste Data