• No se han encontrado resultados

Simulación de modelos evolutivos en cáncer: nuevos modelos de crecimiento

N/A
N/A
Protected

Academic year: 2022

Share "Simulación de modelos evolutivos en cáncer: nuevos modelos de crecimiento"

Copied!
64
0
0

Texto completo

(1)

Escuela Politécnica Superior

20 21

Trabajo fn de grado

Simulación de modelos evolutivos en cáncer

www .uam.es

Alberto González Klein

Escuela Politécnica Superior Universidad Autónoma de Madrid C\Francisco Tomás y Valiente nº 11

Universidad Autónoma de Madrid

(2)
(3)

UNIVERSIDAD AUTÓNOMA DE MADRID

ESCUELA POLITÉCNICA SUPERIOR

Grado en Ingeniería Informática

TRABAJO FIN DE GRADO

Simulación de modelos evolutivos en cáncer

Nuevos modelos de crecimiento

Autor: Alberto González Klein Tutor: Ramón Díaz Uriarte

mayo 2021

(4)

Todos los derechos reservados.

Queda prohibida, salvo excepción prevista en la Ley, cualquier forma de reproducción, distribución comunicación pública y transformación de esta obra sin contar con la autorización de los titulares de la propiedad intelectual.

La infracción de los derechos mencionados puede ser constitutiva de delito contra la propiedad intelectual (arts. 270 y sgts. del Código Penal).

DERECHOS RESERVADOS

© 19 de mayo de 2021 por UNIVERSIDAD AUTÓNOMA DE MADRID Francisco Tomás y Valiente, no 1

Madrid, 28049 Spain

Alberto González Klein

Simulación de modelos evolutivos en cáncer Alberto González Klein

IMPRESO EN ESPAÑA – PRINTED IN SPAIN

(5)

Resumen

El cáncer actualmente es una de las enfermedades más mortales del mundo. Sin embargo, gracias al avance de la tecnología, se ha mejorado su detección y tratamiento.

Una herramienta para ayudar a la detección del cáncer es el paquete OncoSimulR de R, el cual permite realizar simulaciones de crecimiento tumoral utilizando algoritmos matemáticos. El usuario puede especifcar diversos modos de interacciones entre tipos de células, como relaciones de orden o epistasia, e incluso introducir explícitamente las tasas de nacimiento de las células.

En este trabajo se va a incorporar nueva funcionalidad a este paquete, permitiendo a los usuarios especifcar tasas de muerte de los distintos genotipos que se especifquen, así como mantener la población total aproximadamente constante. De esta forma se mejorará la usabilidad y la fexibilidad del paquete, permitiendo a los usuarios utilizar modelos de crecimiento prácticamente arbitrarios. Además, se realizará una revisión de los algoritmos existentes que permitan simular procesos estocásticos, destacando sus diferencias.

Una vez incorporada la nueva funcionalidad, se comprobará su correcto funcionamiento. Para ello se desarrollará una batería de tests que compruebe la salida de las funciones en todos los posibles casos, además de los errores que se deben detectar para garantizar su correcto funcionamiento. Esta es una tarea fundamental a la par que complicada, ya que no se conoce completamente el resultado de los tests debido a la estocasticidad. Por tanto, se deben identifcar casos clave que nos indiquen que el funcionamiento es correcto. Además de los nuevos tests incoporados, se utilizarán tests previamente presentes en el paquete para garantizar que la incoporación de la nueva funcionalidad no cause errores en otras partes del paquete.

Posteriormente, se propocionará un conjunto de resultados y ejemplos en los que utilizar la funcio- nalidad desarrollada. Por último, se expondrán las conclusiones obtenidas a lo largo de la elaboración de este trabajo, así como posibles líneas de trabajo futuro.

Palabras clave

cáncer, simulación, genotipo, tasa de nacimiento, tasa de muerte, proceso de Moran, evolución

v

(6)
(7)

Abstract

Nowadays, cancer is one of the deadliest diseases in the world. However, thanks to the progress in technology, its detection and treatment has improved.

A tool to help detect cancer is the R package OncoSimulR, which allows the user to simulate tumoral growth using mathematical algorithms. The user can specify a variety of types of interactions between cells, like order effects or epistasis, and even introduce explicitly the birth rates of the cells.

In this project new functionality is going to be added to this package, allowing the users to specify death rates of the different introduced genotypes. In addition, constant population size simulations are going to be implemented. This changes will improve the usability and fexibility of the package, allowing users to specify almost arbitrary growth models. Previously, a revision about the existing algorithms to simulate stochastic processes is going to be performed, highlighting the differences between them.

Once the functionality is included, its correct behaviour will be tested. In order to do that, a test set that checks the output of the functions in all of the possible cases will be developed. This task is both crucial and complicated, due to the uncertainty of the output because of the stochasticity. Because of this, we have to identify key cases that indicate us the correct functioning. Additionally, the errors that must be detected in order to guarantee the proper functioning of the package will be also tested. A existing battery of tests will also be used to guarantee that the new functionality does not interfere with other parts of the package.

Then, some results and examples that can be reproduced using the developed functionality will be shown. Lastly, the conclusions obtained during the elaboration of this project will be presented along with some possible lines of future work.

Keywords

cancer, simulation, genotype, birth rate, death rate, Moran process, evolution

vii

(8)
(9)

Índice

1 Introducción 1

1.1 Motivación del proyecto . . . 1

1.2 Objetivos y enfoque . . . 2

1.3 Organización de la memoria . . . 3

2 Estado del arte 5 2.1 Modelización y conceptos previos . . . 5

2.2 Algoritmos de simulación existentes . . . 6

2.2.1 Direct Method y First Reaction Method de Gillespie . . . 6

2.2.2 Next Reaction Method de Gibson y Bruck . . . 7

2.2.3 BNB de Mather et al. . . 9

2.3 OncoSimulR . . . 11

2.3.1 Funcionalidad disponible en OncoSimulR . . . 12

3 Diseño e implementación 17 3.1 Cambios sobre los parámetros actuales . . . 17

3.2 Especifcación de tasas de muerte . . . 18

3.2.1 allFitnessEffects . . . 18

3.2.2 evalAllGenotypes . . . 19

3.2.3 oncoSimulIndiv . . . 20

3.3 Modelo con población total aproximadamente constante . . . 21

4 Integración y pruebas 23 4.1 Integración . . . 23

4.2 Pruebas . . . 24

4.2.1 Comprobaciones sobre las especifcaciones con tasas de muerte . . . 24

4.2.2 Comprobaciones sobre las evaluaciones de tasas de muertes . . . 25

4.2.3 Comprobaciones sobre las simulaciones con el modelo arbitrario . . . 25

4.2.4 Comprobaciones sobre las simulaciones con el modelo constante . . . 25

5 Resultados y ejemplos 27 5.1 Modelos ecológicos . . . 27

5.2 Proceso de Moran . . . 30

5.2.1 Halcones y palomas . . . 31

5.3 Cáncer de mama . . . 33

ix

(10)

5.3.1 Cáncer controlado . . . 36 5.3.2 Cáncer no metastásico . . . 36 5.3.3 Cáncer metastásico . . . 37

6 Conclusiones y trabajo futuro 39

Bibliografía 41

Apéndices 43

A Código para reproducir el ejemplo de los halcones y las palomas 45 B Código para reproducir la simulación del cáncer de mama 47

x

(11)

Listas

Lista de códigos

2.1 Cabecera de la funciónallFitnessEffectsoriginal . . . 12

2.2 Cabecera de la funciónevalAllGenotypesoriginal . . . 13

2.3 Cabecera de la funciónevalGenotypeFDFitnessEcuationoriginal . . . 13

2.4 Ejemplo de ejecución de la funciónevalAllGenotypes. . . 13

2.5 Cabecera de la funciónoncoSimulIndivoriginal . . . 14

2.6 Ejemplo de ejecución de la funciónoncoSimulIndiv . . . 15

3.1 Cabecera de la funciónallFitnessEffectsmodifcada . . . 19

3.2 Cabecera de la funciónevalRGenotypeoriginal . . . 19

3.3 Cabecera de la funciónevalRGenotypemodifcada . . . 19

3.4 Cabecera de la funciónevalGenotypeFDFitnessEcuationmodifcada . . . 20

3.5 Cabecera de la funciónupdateBirthDeathRates . . . 20

3.6 Cabecera de la nueva funciónupdateRatesArbitrary . . . 21

3.7 Cabecera de la nueva funciónupdateRatesConstant. . . 22

5.1 Código para simular un modelo predador-presa con capacidad de carga . . . 28

5.2 Código para simular un modelo predador-presa sin capacidad de carga . . . 29

A.1 Creación de la tabla de tasas de halcones y palomas . . . 45

A.2 Equilibrio entre halcones y palomas . . . 45

A.3 Los halcones eliminan las palomas . . . 46

A.4 Las palomas dominan a los halcones . . . 46

B.1 Creación de la tabla de tasas en el cáncer de mama . . . 47

B.2 Evaluación de distintas situaciones para comprobar las tasas . . . 48

B.3 Simulación de un cáncer controlado . . . 48

B.4 Simulación de un cáncer no metastásico . . . 49

B.5 Simulación de un cáncer metastásico . . . 49

Lista de ecuaciones

3.1 Parámetro para mantener la población total constante . . . 22

5.1 Ecuaciones de Lotka-Volterra con capacidad de carga . . . 27

xi

(12)

5.2 Modelo predador-presa clásico . . . 28

Lista de fguras

1.1 Mortalidad mundial dividida por causas . . . 1

2.1 Ejecución de ejemplo de oncoSimulIndiv . . . 16

5.1 Simulación del modelo predador-presa con capacidad de carga . . . 29

5.2 Comparación del modelo predador-presa simulado con el teórico . . . 30

5.3 Resultado de equilibrio entre halcones y palomas . . . 32

5.4 Resultado en el que los halcones eliminan a las palomas . . . 32

5.5 Resultado en el que las palomas dominan a los halcones . . . 33

5.6 Simulación de un cáncer de mama que está controlado . . . 36

5.7 Simulación de un cáncer de mama no metastásico . . . 37

5.8 Simulación de un cáncer de mama metastásico . . . 37

Lista de tablas

2.1 Fitness evaluado tras la ejecución deevalAllGenotypes . . . 14

2.2 Poblaciones fnales tras ejecución deoncoSimulIndiv. . . 16

5.1 Tasas de nacimiento y muerte del modelo predador-presa con capacidad de carga . . . 28

5.2 Tasas de nacimiento y muerte del modelo predador-presa . . . 30

5.3 Tasas de nacimiento del ejemplo clásico de halcones y palomas . . . 31

5.4 Tabla de benefcios de los distintos tipos de células en un cáncer de mama . . . 34

5.5 Tasas de nacimiento y muerte de los distintos tipos de células de un cáncer de mama 34 5.6 Evaluación de las tasas en ausencia de macrófagos . . . 35

5.7 Evaluación de las tasas en presencia de macrófagos . . . 35

5.8 Evaluación de las tasas en presencia de macrófagos y células cancerosas . . . 35

xii

(13)

1

Introduccion ´

A lo largo de este capítulo, se van a proporcionar algunas razones por las que la realización de este Trabajo de Fin de Grado es relevante. Además, se detallarán los objetivos perseguidos a lo largo del proyecto, así como la estructuración de esta memoria.

1.1. Motivación del proyecto

El cáncer actualmente se trata de la segunda enfermedad con mayor tasa de mortalidad del mundo [1]. Durante los últimos años se han llevado a cabo grandes avances en la detección y tratamiento de esta enfermedad gracias a la ayuda de la tecnología [2]. A pesar de todo, el número de casos y la mortalidad no ha parado de crecer en estos últimos años, por lo que sigue existiendo una necesidad de investigar y desarrollar mecanismos de prevención.

(a) 2010 (b) 2017

Figura 1.1: Mortalidad mundial dividida por causas

Hoy en día existen muchas incógnitas acerca del cáncer y, además, todos conocemos alguna per- sona que lo haya sufrido o alguna historia acerca de alguien que haya fallecido debido a él. Por ello, es una enfermedad muy presente en nuestra sociedad y que infunde un cierto temor, ya que a día de hoy no hay una forma de prevenirla al 100 %. Existen muchos tipos de cánceres, como el cáncer

1

(14)

Introduccion´

de mama, de colon, de próstata, etc. Sin embargo, todos tienen un comportamiento parecido: un con- junto de células adquieren la capacidad de multiplicarse descontroladamente e invadir tejidos y otros órganos [3].

Las células que tienen un comportamiento normal se convierten en cancerígenas debido a los agentes carcinógenos, como por ejemplo las radiaciones ultravioletas del sol. Las células expuestas a estos agentes pueden mutar, es decir, su material genético puede verse alterado. Estas mutaciones pueden causar un aumento en la tasa de división y una disminución en la tasa de mortalidad de las células afectadas. Además, si estas células tienen la capacidad de dividirse transmitirán la mutación a sus descendientes. A estas células se les denomina células iniciadas. La aparición del cáncer se produce al darse mutaciones de forma continua y acumulada.

Teniendo en cuenta esto, el poder simular la dinámica evolutiva resultante de distintas mutaciones en determinados genes puede ser un método para predecir la aparición del cáncer.

1.2. Objetivos y enfoque

De forma previa a la realización de este trabajo, hemos llevado a cabo una revisión de los algoritmos a emplear, así como el contexto biológico de los mismos. El objetivo principal de este estudio previo es la comprensión del algortimo de simulación estocástica BNB de Mather et al. [4] y sus ventajas respecto a sus predecesores, como el First Reaction Method de Gillespie [5] o el Next Reaction Method de Gibson y Brucks [6].

Una vez comprendidos estos algoritmos, se procederá a implementar nueva funcionalidad en el paquete de R OncoSimulR. Actualmente, en el paquete se permite la especifcación de las tasas de nacimiento de los distintos genotipos, pero no tasas de muerte. Sin embargo, en ocasiones resulta más natural especifcar ambas tasas. Por tanto, la implementación de esta funcionalidad resulta interesante y se realizará como primera parte de este trabajo. La tasa de muerte puede depender de la frecuencia o no de los genotipos, permitiendo así que el usuario pueda especifcar modelos prácticamente arbitra- rios. Además, se incorporará la posibilidad de mantener la población total aproximadamente constante, lo cual nos permitirá ampliar el tipo de modelos que OncoSimulR puede simular, como los procesos de Moran.

El paquete OncoSimulR [7] hace uso de R, C++ y Rcpp [8] (para llamar a código de C++ desde R), por lo que estudiar y aprender estos lenguajes y el paquete Rcpp será una tarea fundamental. Por tanto, los objetivos se pueden resumir en los siguientes puntos:

Comprender los algoritmos existentes de simulación estocástica para procesos de interacción y mutación de genes.

Comprender la funcionalidad actual del paquete OncoSimulR.

Aprender R a un nivel básico, además de comprender como se estructura un paquete.

Simulación de modelos evolutivos en cáncer 2

(15)

1.3. Organizacion´ de la memoria

Aprender cómo funciona la librería Rcpp para comunicar R y C++.

Incorporar nueva funcionalidad al paquete que permita hacer uso de modelos más generales y complejos.

Documentar debidamente los cambios realizados, así como proporcionar una batería de tests para probar la nueva funcionalidad.

1.3. Organización de la memoria

En primer lugar, se explicarán los algoritmos existentes actualmente y el algoritmo que está imple- mentado en el paquete OncoSimulR, discutiendo las ventajas y desventajas de cada uno. Además, se describirá brevemente OncoSimulR, detallando las secciones que se han modifcado a lo largo de este trabajo para su posterior explicación. A continuación, se incluirá la sección que trata sobre el diseño y la implementación del trabajo, explicando las decisiones tomadas durante el proceso. Seguidamente, habrá una sección acerca de la integración y las pruebas realizadas, dedicando especial atención a la compatibilidad entre versiones del paquete. Por último, se encontrará una sección acerca de los resultados obtenidos y las aplicaciones del trabajo realizado, haciendo uso de gráfcas y ejemplos descriptivos.

Alberto González Klein 3

(16)
(17)

2

Estado del arte

2.1. Modelización y conceptos previos

La modelización es una rama de las matemáticas muy utilizada hoy en día, gracias al auge de la tecnología. Los ejemplos más conocidos acerca de modelización matemática son los modelos ecoló- gicos, como el modelo Lotka-Volterra, o la dinámica de fuidos. Sin embargo, casi cualquier fenómeno que pueda ser observado y medido puede ser modelizado.

Habitualmente el proceso de modelización comienza con la observación de un suceso que nos interese simular (este interés puede ser méramente teórico). Al observarlo, identifcaremos variables que cuantifquen distintas partes de este suceso. Por ejemplo, en el caso del modelo predador-presa distinguimos dos poblaciones, el predador y la presa, cuya relación está afectada por una tasa de predación. Una vez que contamos con las variables que cuantifcan el suceso, nos gustaría describir cómo cambian estas variables a lo largo del tiempo y cómo interactúan entre sí. Para ello, hacemos uso de las ecuaciones que modelan el fenómeno.

Existen modelos que pueden ser estudiados analíticamente. Sin embargo, hay otros modelos más complejos que requieren de simulaciones para observar su comportamiento. En el caso del cáncer se dan interacciones complejas con tamaños de poblaciones muy altos, por lo que el estudio analítico se hace una tarea imposible. Si queremos simular el crecimiento de un tumor, nuestras variables serían las células. En cada momento, una célula podrá mutar o no, dependiendo de una tasa de mutación (la cual podría ser o fja o variable). El número de células mutadas será el componente principal a la hora de determinar la presencia del cáncer en un organismo. Estas células en cada instante de tiempo pueden morir, permanecer estables o proliferar. Por tanto, necesitamos un modelo matématico para simular esta población de células mutadas. Cada célula contará con unos genes determinados.

Al conjunto de genes mutados que contienen las células lo denominaremos genotipo.

Ciertas mutaciones pueden conferir a los genotipos que los posean una mayor ventaja biológica frente a otro genotipo, de forma que sea más propenso a sobrevivir y reproducirse. El número que utilizamos para cuantifcar estas diferencias en el crecimiento de las poblaciones se denomina ftness [9]. Cuanto mayor sea el ftness de un genotipo, mayor será su tasa de crecimiento.

5

(18)

Estado del arte

2.2. Algoritmos de simulación existentes

Existen muchos tipos de simulación posibles. En nuestro caso, realizaremos simulación estocástica en tiempo continuo.

2.2.1. Direct Method y First Reaction Method de Gillespie

Gillespie en 1977 [5] propone una alternativa al modelo clásico determinista, en el que el tiempo es un proceso continuo totalmente predecible gobernado a través de un conjunto de ecuaciones diferen- ciales. En su lugar utiliza un modelo estocástico, donde la evolución del tiempo se considera que es un camino aleatorio en el que gobierna una única ecuación diferencial, la ecuación maestra o master equation. El problema existente hasta la fecha era el hecho de que la master equation habitualmente se trataba de una ecuación matemáticamente imposible de resolver. Sin embargo, Gillespie propone dos algoritmos con los que poder realizar cálculos exactos en el ámbito de la simulación estocástica sin tener que tratar con la master equation.

El concepto básico detrás de estos algoritmos consiste en, a partir de un estado inicial, realizar interacciones aleatoriamente para generar una trayectoria legal (utilizando las distribuciones de pro- babilidad adecuadas), en lugar de resolver la irresoluble master equation para obtener la probabilidad de todas las trayectorias de un proceso de interacción entre varios elementos. Los algoritmos son los siguientes:

Direct Method

En este algoritmo lo que nos preguntamos para un sistema en un estado determinado es qué interacción va a ser la próxima que ocurra y cuándo va a ocurrir.

Los pasos del algoritmo son los siguientes:

1.– Inicializamos las poblaciones y el tiempot = 0.

2.– Calculamos la probabilidad de que se produzca cada una de las interacciones posibles. A cada una de estas probabilidades las denominaremosai, dondeiindexa las interacciones.

3.– Escogemos una interacciónµ de acuerdo a la distribución de probabilidad dada por:

P (Inter = µ) = aµ X aj j

4.– Escogemos el tiempo en el que se lleva a cabo la interacción (τ) de acuerdo a una distribución exponencial, de parámetroP j aj , es decir:

X P

j aj )

P (τ ) = ( aj )e−τ (

j

Simulación de modelos evolutivos en cáncer 6

(19)

2.2. Algoritmos de simulacion´ existentes

5.– Actualizamos las poblaciones de acuerdo a la interacción que ha ocurrido y cambiamos el tiempo actual a t = t + τ.

6.– Volvemos al paso 2.

Como se puede observar, se trata de un algoritmo bastante sencillo, en el que en cada iteración debemos que generar dos números aleatorios. La complejidad temporal viene determinada por el número de interacciones posibles en el cálculo de losai en el paso 2 y en el cálculo deP j aj en el paso 4.

First Reaction Method

En este algoritmo, generamos los tiempos en los que ocurrirían cada una de las interacciones supo- niendo que no suceda otra reacción previamente. A este tiempo para la interacciónµ lo denotaremos comoτµ. Los pasos del algoritmo son los siguientes:

1.– Inicializamos las poblaciones y el tiempot = 0.

2.– Calculamos la probabilidad de que se produzca cada una de las interacciones posibles. A cada una de estas probabilidades las denominaremosai, dondei indexa las interacciones.

3.– Para cada interaccióni, generamosτi, de acuerdo a una distribución exponencial de parámetroai, es decir:

−τiai

Pi) = aie

4.– Escogemos la interacciónµ cuyoτµ sea menor.

5.– Actualizamos las poblaciones de acuerdo a la interacción que ha ocurrido y cambiamos el tiempo actual a t = t + τµ.

6.– Volvemos al paso 2.

En este caso generamosr números aleatorios en cada iteración, donder es el número de interac- ciones posibles, y la complejidad temporal es proporcional ar para calcular losai en el paso 2 y para identifcar el menorτi.

2.2.2. Next Reaction Method de Gibson y Bruck

Observamos que en el First Reaction Method generamosr números aleatorios, pero solo utiliza- mos uno por iteración, por lo que parece que estamos “desaprovechando”r − 1 números que hemos generado. Además en el paso 2 recalculamos todos losai, cuando puede que no todos hayan cambia- do. El algoritmo desarrollado por Gibson y Bruck [6] juega con esta idea y trata de reutilizar el mayor número posible de valores por iteración.

Además, realizan una optimización muy elegante del algoritmo mediante el uso de dos estructuras de datos: los grafos de dependencias y las colas de prioridad indexadas. A continuación se defnen brevemente estos conceptos y se contextualizan, para una mayor comprensión del algoritmo.

Alberto González Klein 7

(20)

Estado del arte

Grafo de dependencias

En una interacción o reacción, hay un conjunto de elementos que son los que interaccionan o reaccionan y un conjunto de elementos que se obtienen tras la interacción o reacción. Para una reacciónµ denotaremos a los conceptos anteriores comoReactivos(µ) yP roductos(µ), respectivamente. Consideramos también el conjunto de poblaciones o sustancias que modifcan el valoraµ,DependeDe(aµ), y el conjunto de poblaciones o sustan- cias que son modifcadas tras la reacciónµ,Af ecta(µ). Con estos ingredientes podemos construir un grafo de dependencias en nuestro contexto.

SeaR un conjunto de reacciones. SeaG(V, E) un grafo dirigido, conV = R y con una arista dirigida devi a vj si y solo siAf ecta(vi) ∩ DependeDe(avj ) 6= ∅. EntoncesGes un grafo de dependencias del conjunto de reaccionesR.

Un grafo de dependencias construido de la forma especifcada nos dice quéai hay que modifcar cuando se da una reacción. Por tanto, nos permite recalcular el número mínimo posible deai. Normal- mente, este grafo es disperso, por lo que se actualizarán pocosai en cada iteración. Esto nos indica la necesidad de una estructura de datos que sea muy efciente al manejar una cantidad pequeña de actualizaciones

Colas de prioridad indexadas

Una cola de prioridad indexada está compuesta de unminheap en el que cada nodo es un par interacción-tiempo (donde el tiempo es el calculado asumiendo que no ocurre ninguna interacción antes) con una estructura de cola de prioridad habitual, donde la prioridad es el tiempo, y, además, un diccionario en el que se relaciona cada interacción con su posición en la cola de prioridad.

Al utilizar esta estructura para guardar losai y losτi, conseguimos que las operaciones que reali- zamos con estos valores sean mucho más rápida. La indexación es necesaria para optimizar la actua- lización de los valores: el grafo de dependencias nos dice queai hemos de actualizar y, por tanto, que τi, y con la indexación encontramos en tiempo constante en la cola de prioridad dónde se encuentra la interaccióni para modifcar el valor.

Next Reaction Method

Los pasos del algoritmo son los siguientes:

1.– Inicializamos las poblaciones, el tiempot = 0 y generamos en grafo de dependenciasG. 2.– Calculamos la probabilidad de que se produzca cada una de las interacciones posibles,ai.

3.– Para cada interaccióni, generamosτi, de acuerdo a una distribución exponencial de parámetroai, es decir:

−τiai

P (τi) = aie

4.– Guardamos losτi en una cola de prioridad indexadaP . 5.– Escogemos la interacciónµ cuyoτµ guardado enP sea menor.

6.– Actualizamos las poblaciones de acuerdo a la interacción que ha ocurrido y cambiamos el tiempo actual a t = τµ.

7.– Por cada arista(µ, α) en el grafo de dependenciasG, actualizamosaα, actualizamosτα y reemplazamos

Simulación de modelos evolutivos en cáncer 8

(21)

2.2. Algoritmos de simulacion´ existentes

los valoresτα antiguos con los nuevos enP. Para calcularτα tomamos dos casos:

aα,viejo

Siα =6 µ,τα = aα,nuevo α − t) + t.

Siα = µ, generamos un número aleatorioρsiguiendo una distribución exponencial de parámetro aµ y actualizamosτµ = ρ + t.

8.– Volvemos al paso 5.

Los 4 primeros pasos del algoritmo se ejecutan una única vez. El paso 5 se ejecuta en tiempo constante, gracias a las propiedades de las colas de prioridad. El paso 6 dependerá del número de productos que haya en la reacción que, como suele ser despreciable respecto del número de reaccio- nesr, no lo tomaremos en cuenta a la hora de analizar la complejidad temporal. El paso 7 se ejecutará una vez por cada arista(µ, α) de G. Supongamos que hayk aristas de ese tipo (k << r). Actualizar losk aα no requiere más que operaciones elementales, al igual que actualizar losτα (en el caso de queα = µ, generar un número aleatorio puede ser algo más lento, pero a la hora del análisis temporal es indiferente). Actualizar la cola de prioridad indexadaP con los nuevosτα requiere a lo sumo2 log(r) operaciones. Por tanto, la complejidad temporal de este algoritmo seríaO(log(r)), ya que parar muy grande,k es despreciable.

Observamos que existe una clara mejora en cuanto a la efciencia comparado con sus predeceso- res, aunque esta velocidad depende del conjunto de interacciones que consideremos (ya que estamos asumiendo que el grafo de dependencias es disperso) y de la efciencia al generar números aleatorios.

2.2.3. BNB de Mather et al.

Mather et al. [4], inspirados por las técnicas presentadas por Gibson y Brucks en su Next Reaction Method, crean un algoritmo para la simulación de dinámicas evolutivas de una población de múltiples especies sometidas a muerte, mutación y reproducción asexual.

Binomial-Negative Binomial algorithm (BNB)

El nombre BNB proviene de la necesidad de hacer uso de distribuciones binomiales y binomiales negativas a lo largo del algoritmo para actualizar las poblaciones. Este algoritmo es exacto únicamente en el caso de que las tasas de nacimiento, muerte y mutación no cambien después de que se produzca una mutación. Si estas tasas cambian, se puede aplicar una versión aproximada de este algoritmo. En los anteriores algoritmos actualizábamos el estado del sistema en el momento en el que una reacción o interacción ocurría. En este algoritmo, lo haremos cuando ocurra una mutación, que es la “reacción”

más lenta.

Alberto González Klein 9

(22)

Estado del arte

Los pasos del algoritmo son los siguientes:

1.– Inicializamos el sistema conN clases de especies dependiendo del genotipo en tiempot = 0. Especifcamos las poblaciones de todas las clases,ni coni = 1, . . . , N. Cada clase tiene sus propias tasas de nacimiento (gi), muerte (γi) y mutación (µi).

2.– Para cada clase, generamosN números aleatoriosri uniformemente distribuidos entre 0 y 1. Por cada i = 1, . . . , N generamos un tiempoti de acuerdo a la siguiente ecuación:

" #

1 ri 1/ni (R − W + 2gi) − W − R + 2γi

ti = ln ,

R ri 1/ni (−R − W + 2gi) − W + R + 2γi

dondeR = (gp i − γi)2 + (2gi + 2γi + µ) yW = gi + γi + µi. Este número existe solo sí se satiface que

R − W + 2γR + W − 2gii ni < r ≤ 1.

Si esto no se cumple, entoncesti =.

3.– Encontramos el tiempo más pequeño de mutacióntm = min(ti) y la clase correspondiente,im. Actualiza- mos el tiempot = t + tm.

4.– Actualizamos la población de la clase mutada,im, utilizando dos números aleatorios, uno binomial y otro binomial negativo, de acuerdo al siguiente algoritmo:

4.1.– Generamos un número aleatoriom˜ siguiendo una distribución binomial, con probabilidad de éxito1ppE (t) ynim − 1 términos.

M (t)

4.2.– Generamos la nueva población de la clase mutada,n˜:n˜ = m˜ + 1 + NB( ˜˜ m, pB (t)), donde N B( ˜˜ m, pB (t)) es una binomial negativa de ordenm˜ y probabilidad de éxitopB (t).

5.– Actualizamos la población de todas las otras clases, de acuerdo al siguiente algoritmo:

5.1.– Generamos un número aleatoriom˜ siguiendo una distribución binomial, con probabilidad de

γi(1−pM (t)) RC(t)+2γiS(t)−W S(t)

éxito1ppE (t) yni términos, dondepE (t) = ypM (t) = .

M (t) W −γi−gipM (t) RC(t)−2gi S(t)+W S(t)

5.2.– Sim˜ = 0, entonces la población de la clase está extinta yn˜ = 0.

˜ ˜

5.3.– Sino, generamos la nueva población de la clase,n˜:n˜ = m˜ +N B( ˜m, pB (t)), dondeN B( ˜m, pB (t))

gipE (t)

es una binomial negativa de ordenm˜ y probabilidad de éxitopB (t)ypB (t) = γ

i .

6.– Seleccionamos la mutación específca que ocurre. Si la mutación genera un miembro de una clase no exis- tente, creamos una nueva clase,N +1, connN +1 = 1 y sus propias tasasgN +1,γN +1 yµN +1. Sino, añadimos 1 a la clase existente que corresponda.

7.– Una o varias de las clases no mutadas pueden haberse extinguido, por lo que debemos eliminarlas de la lista y reducir el número de clases como corresponda.

8.– Volvemos al paso 2 hasta que el algoritmo haya terminado.

Se pueden utilizar numerosas condiciones de parada dependiendo de nuestras necesidades, como el número de iteraciones o un tiempo máximo.

El algoritmo aquí presentado es el utilizado en el paqueteOncoSimulR. Observamos que el al- goritmo es signifcativamente más complejo que los presentados anteriormente. Entonces, ¿por qué utilizar este algoritmo que en apariencia es menos efciente? La clave reside en que solamente ac- tualizamos las poblaciones en caso de que ocurra una mutación. Por tanto, si la tasa de mutación es bastante menor a las tasas de nacimiento y muerte, este algoritmo será más efciente que los otros. Co-

Simulación de modelos evolutivos en cáncer 10

(23)

2.3. OncoSimulR

mo nuestra motivación inicial es utilizarlo para la simulación de cáncer, donde se cumple este requisito, se convierte en la mejor opción.

2.3. OncoSimulR

El paquete sobre el que trata este Trabajo de Fin de Grado es OncoSimulR [7] [10] . Este paquete ha sido desarrollado por Ramón Díaz Uriarte, profesor titular del Departamento de Bioquímica de la Universidad Autónoma de Madrid.

Este proyecto está escrito en R, por ser el lenguaje predominante en el sector bioinformático, aun- que también contiene código en C++ para conseguir mayor efciencia en la ejecución del algoritmo BNB. El paquete pertenece a Bioconductor, un proyecto open source en el que están contenidos di- versos paquetes escritos en R que proporcionan funcionalidades relacionadas con la bioinformática.

El objetivo original de OncoSimulR era la simulación de la progresión tumoral. Sin embargo, con la funcionalidad actual se puede conseguir mucho más que eso. Hoy en día, se trata de proporcionar una mayor fexibilidad al usuario a la hora de especifcar los genes y las interacciones entre ellos, para así conseguir simular modelos prácticamente arbitrarios. El trabajo aquí presentado está orientado a este objetivo.

Una funcionalidad que posee OncoSimulR es la de permitir al usuario especifcar el ftness de cada genotipo explicitamente. Este ftness puede ser una constante o depender de la frecuencia de otros genotipos. OncoSimulR permite al usuario simular de acuerdo a tres modelos: exponencial, McFarland y Bozic. En el modelos exponencial y de McFarland se tiene una tasa de muerte fjada y el usuario especifca las tasas de nacimiento a través del ftness. Por otro lado, el modelo de Bozic utiliza el ftness introducido por el usuario como tasa de muerte y tiene una tasa de nacimiento fjada. El término ftness es un poco ambiguo en el paquete, ya que en algunos modelos se utiliza como tasa de nacimiento y en el modelo de Bozic se utiliza como tasa de muerte. Pero, ¿y si el usuario no quiere ceñirse a ninguno de los modelos disponibles y quiere especifcar uno propio? Esta es la funcionalidad principal que se ha desarrollado y que se explicará en las próximas secciones.

Alberto González Klein 11

(24)

Estado del arte

2.3.1. Funcionalidad disponible en OncoSimulR

Para realizar una simulación primero tenemos que especifcar el ftness. Esto se consigue mediante la funciónallFitnessEffects.

Código 2.1: Cabecera de la funciónallFitnessEffectsoriginal

function allFitnessE˙ects(rT = NULL, epistasis = NULL,

orderE˙ects = NULL, noIntGenes = NULL, geneToModule = NULL, drvNames = NULL, genotFitness = NULL, keepInput = TRUE, frequencyDependentFitness = FALSE, frequencyType = NA)

Algunos de los argumentos que puede recibir esta función son:

• epistasis: Permite al usuario especifcar si se produce epistasia entre los genes, es decir, si la expresión de uno o más genes dependen de la expresión de otro gen. Esto se traduce en nuestro caso en que un gen mutado puede ganar o perder ftness si muta otro gen.

• orderEffects: Permite al usuario especifcar relaciones de orden entre distintos genes. Una relación de orden entre dos genes se cumple, digamosA > B, cuando la mutaciónA se ha producido antes que la mutaciónB.

• noIntGenes: Permite al usuario especifcar el ftness de los genes que no están relacionados con otros genes.

• genotFitness: Permite al usuario especifcar un mapeado explícito de los genotipos con sus tasas de naci- miento o ftness.

Estos parámetros proporcionan al usuario la capacidad de expresar una amplia gama de tipos de interacciones entre genes y su ftness. Un argumento en el que nos vamos a centrar especialmente es genotFitness, que es el más fexible al permitir mapeos arbitrarios de genotipo a ftness.

El ftness especifcado por cada genotipo puede ser dependiente de la frecuencia o no. Esto viene indicado por el parámetrofrequencyDependentFitness. Si el ftness depende de la frecuencia, es decir,frequencyDependentFitness = TRUE, entonces podemos expresar dicha dependen- cia de dos formas: mediante frecuencias absolutas (con la letran) o mediante frecuencias relativas (con la letraf). El tipo de frecuencia empleada viene dada por el parámetrofrequencyType. Por ejemplo, si queremos decir que el ftness de un cierto genotipo depende de la frecuencia del genoti- po que contiene únicamente el genAlo expresaríamos como f_A, en caso de frecuencias relativas, o como n_A, en caso de frecuencias absolutas. Para expresar un genotipo escribiremos los genes mutados involucrados, separados por comas.

Además de poder utilizar este objeto para hacer simulaciones, podemos evaluarlo para comprobar si nuestra especifcación es correcta. Para ello, contamos con toda una familia de funciones depen- diendo de nuestras necesidades, pero la más útil para nosotros seráevalAllGenotypes.

Simulación de modelos evolutivos en cáncer 12

(25)

2.3. OncoSimulR

Código 2.2: Cabecera de la funciónevalAllGenotypesoriginal

function evalAllGenotypes(ftnessE˙ects,

order = FALSE, max = 256, addwt = FALSE, model = "",

spPopSizes = NULL, currentTime = 0)

Esta función evalua el ftness de todos los genotipos presentes en el objeto fitnessEffects. La evaluación se realizará mediante una llamada a C++. La función de C++ que realiza los cálculos es evalGenotypeFDFitnessEcuation.

Código 2.3: Cabecera de la funciónevalGenotypeFDFitnessEcuationoriginal

double evalGenotypeFDFitnessEcuation(const Genotype& ge, const ftnessE˙ectsAll& F,

const std::vector<Genotype>& Genotypes, const std::vector<spParamsP>& popParams, const double& currentTime)

En el código 2.4 se encuentra un ejemplo de ejecución de la función evalAllGenotypes. El output que se obtiene es la tabla 2.1.

Código 2.4: Ejemplo de ejecución de la funciónevalAllGenotypes

r <- data.frame(Genotype = c("WT", "A", "B", "A, B"), Fitness = c("1 + 1.5*f_",

"5 + 3*(f_A + f_B + f_A_B)",

"5 + 3*(f_A + f_B + f_A_B)",

"7 + 5*(f_A + f_B + f_A_B)"), stringsAsFactors = FALSE)

afe <- allFitnessE˙ects(genotFitness = r,

frequencyDependentFitness = TRUE, frequencyType = "rel")

evalAllGenotypes(afe, spPopSizes = c(5000, 2500, 2500, 500))

Alberto González Klein 13

(26)

Estado del arte

Genotype Fitness

WT 1.714286

A 6.571429

A, B 6.571429

B 9.619048

Tabla 2.1: Fitness evaluado tras la ejecución deevalAllGenotypes

Nótese el primero de los genotipos,WT. Esto denota al wildtype y representa al genotipo sin mu- taciones. En este ejemplo, el ftness depende de la frecuencia. Las frecuencias especifcadas son relativas, por lo que a partir de las poblaciones de cada uno de los genotipos especifcadas en el argu- mentospPopSizesse obtendrá qué porcentaje de la población total pertenece a cada genotipo. Este ejemplo puede ser fácilmente calculado a mano pero, ¿cómo lo hace OncoSimulR?. Para esta funcio- nalidad, hacemos uso de la librería de C++exprTK[11], ya que la parte de los cálculos es ejecutada en C++. Esta librería es ampliamente utilizada para permitir el parseo y evaluación de expresiones ma- tématicas efcientemente. En nuestro caso, la utilizaremos para evaluar las expresiones de la columna Fitness. Es una librería muy potente pero que, debido a su complejidad, aumenta signifcativamente los tiempos de compilación.

Gracias a evalAllGenotypes podemos comprobar que nos estamos comunicando correcta- mente con C++ mediante la librería Rcpp, además de comprobar el uso correcto de exprTK. Sin embargo, la función principal y más importante de este trabajo es aquella que realiza las simulaciones:

oncoSimulIndiv.

Código 2.5: Cabecera de la funciónoncoSimulIndivoriginal

function oncoSimulIndiv(fp, model = "Exp", mu = 1e-6, muEF = NULL,

sampleEvery = ifelse(model % in % c("Bozic", "Exp"), 1, 0.025), initSize = 500,

initMutant = NULL, ...)

Esta función recibe muchos más argumentos que los aquí expuestos, pero únicamente vamos a describir aquellos que resultan fundamentales para este trabajo:

• fp: ObjetofitnessEffectscreado mediante la funciónallFitnessEffectsya explicada anteriormente.

model: Modelo de crecimiento que se va a utilizar. Este modelo determina las tasas de muerte.

• mu: Tasa de mutación. Cada genotipo puede tener su propia tasa de mutación o puede haber una tasa de mutación para todos los genotipos.

• muEF: Objeto de tipomutatorEffects, similar afitnessEffects. Especifca cambios de la tasa de mu- tación en función de mutaciones en ciertos genes.

• sampleEvery: Indica los intervalos de tiempo entre actualizaciones de la población.

Simulación de modelos evolutivos en cáncer 14

(27)

2.3. OncoSimulR

• initMutant: Genotipos que están mutados inicialmente. En caso de que seaNULL, se asume que no hay mutaciones iniciales y que elWTes la única clase, hasta que se produzca una mutación.

• initSize: Poblaciones iniciales de los genotipos mutados especifcados eninitMutant.

Recordemos que esta función realiza simulaciones siguiendo el algoritmo BNB. Entonces, ¿por qué es necesario el argumentosampleEvery si habíamos explicado en la sección 2 que este algo- ritmo muestrea la población cuando se producen mutaciones? Hay que tener en cuenta que podemos especifcar ftness (tasa de nacimiento) dependiente de la frecuencia, variaciones en la tasa de mu- tación (muEF) y que hay modelos en los que la tasa de muerte no es constante, como el modelo de McFarland. Por tanto, BNB no es un algoritmo exacto. En los casos mencionados anteriormente, es conveniente actualizar las poblaciones (y por tanto las tasas) a intervalos breves, de tal forma que los errores generados por la inexactitud del algoritmo se minimicen.

En el código 2.6 tenemos un ejemplo de ejecución deoncoSimulIndiv. Las poblaciones fnales tras la simulación se encuentran recogidas en la tabla 2.2.

Código 2.6: Ejemplo de ejecución de la funciónoncoSimulIndiv

genoft <- data.frame(A = c(0, 1, 0, 1), B = c(0, 0, 1, 1), Fitness = c("3 + 5*f_",

"3 + 5*(f_ + f_1 - f_2)",

"3 + 5*(f_ + f_2 - f_1)",

"5 + 6*(f_1 + f_2 + f_1_2)")) afe <- allFitnessE˙ects(genotFitness = genoft,

frequencyDependentFitness = TRUE, frequencyType = "rel")

osi <- oncoSimulIndiv(afe,

model = "McFL", onlyCancer = FALSE, fnalTime = 200, mu = 1e-6, initSize = 5000, keepPhylog = FALSE, seed = NULL,

errorHitMaxTries = FALSE, errorHitWallTime = FALSE)

Alberto González Klein 15

(28)

Estado del arte

Genotype N

WT 8509125

A 7162

A, B 0

B 19315

Tabla 2.2: Poblaciones fnales tras ejecución deoncoSimulIndiv

Tras el periodo de simulación, estas serían las poblaciones de cada uno de los genotipos. También podemos observar la evolución de las poblaciones a lo largo del tiempo en la fgura 2.1.

Figura 2.1: Evolución de las poblaciones en función del tiempo

El genotipo A,Bno se aprecia apenas en la fgura, debido a la gran población de wildtype. Esta funcionalidad de poder grafcar la evolución del algoritmo resulta muy útil a la hora de analizar los resultados, como se verá más adelante.

Simulación de modelos evolutivos en cáncer 16

(29)

3

Diseno ˜ e implementacion ´

Como ya hemos introducido en la sección anterior, uno de los objetivos de este trabajo es permitir a los usuarios especifcar las tasas de muerte por genotipo, del mismo modo que se pueden especifcar las tasas de nacimiento. Conseguir este objetivo nos proporciona la opción de simular modelos prácti- camente arbitrarios y escribir de forma más intuitiva modelos que ya se podían simular anteriormente, como es el caso de los modelos ecológicos. Además, se incorporará un modelo en el que la población total se mantiene aproximadamente constante en torno a un cierto valor.

Todo el código desarrollado se encuentra en https://github.com/Albertogk/OncoSimul/tree/constant- pop-size.

3.1. Cambios sobre los parámetros actuales

Hasta ahora había un único argumento llamado ftness que era interpretado como tasa de na- cimiento en el modelo exponencial y McFarland (con tasa de muerte fjadas a 1 o en función de la densidad de la población, respectivamente) o como tasa de muerte (con tasa de nacimiento fjada a 1) en el modelo de Bozic. Esto es un mal uso de la terminología. Por tanto, consideramos necesario un renombramiento de ftness a birth rate o tasa de nacimiento. En el caso del modelo de Bozic las tasas de nacimiento especifcadas por el usuario serían en realidad tasas de muerte. Esto puede re- sultar poco intuitivo, pero si queremos añadir la posibilidad de especifcar tasas arbitrarias, es un efecto colateral. Como posibilidad en el futuro, podríamos rediseñar el modelo de Bozic para que el usuario especifque las tasas de muerte con la terminología adecuada, pero por el momento ignoraremos este modelo por ser muy poco utilizado. Esta modifcación no tiene implicaciones a nivel de funcionalidad, pero sí que causa el cambio de nombre de parámetros.

• frequencyDependentFitness se ha cambiado afrequencyDependentBirth.

ColumnaFitnessen la tabla de datosgenotFitnessse ha cambiado a columnaBirth.

Además, se han introducido cambios en todas las funciones, tanto de R como de C++, para ser consistentes con el renombramiento.

17

(30)

Diseno˜ e implementacion´

3.2. Especifcación de tasas de muerte

3.2.1. allFitnessEffects

Para permitir al usuario especifcar death rates, debemos modifcar la funciónallFitnessEffects. Recordemos que las death rates pueden depender o no de la frecuencia. Para permitir al usuario es- pecifcar esto, se han introducido dos nuevos argumentos a la funciónallFitnessEffects:

• deathSpec: Indica si en la tablagenotFitnessel usuario especifca las tasas de muerte. SideathSpec = TRUE, entonces se asume que la última columna contiene las tasas de muerte y la penúltima columna contiene las tasas de nacimiento. En caso contrario, se asume quegenotFitnessno contiene tasas de muerte y tiene el funcionamiento habitual con los modelos ya existentes.

• frequencyDependentDeath: Indica si las tasas de muerte especifcadas dependen de la frecuencia o no (obviamente sifrequencyDependentDeath = TRUE, entoncesdeathSpec = TRUE).

Uno se podría preguntar: ¿Por qué no detectar automáticamente si el usuario especifca tasas de muerte o no engenotFitnessmirando si existe una columna de nombreDeath? Primero de todo, el usuario tiene que estar seguro de lo que está especifcando. Por ejemplo, se podría detectar si las tasas dependen de la frecuencia o no viendo si son strings o números, pero esto podría desencadenar errores por parte del usuario y confusión. Además, puede ocurrir que el usuario nombre de forma distintas las columnas, ya que el nombramiento de las columnas no es algo rígido en OncoSimulR, por lo que el usuario podría confundirse en la especifcación. Por tanto, hemos llegado a la conclusión que lo más adecuado es que el usuario especifque explícitamente si desea utilizar la nueva funcionalidad o no.

Otro punto a remarcar, es que si ambas tasas dependen de la frecuencia deben compartir el tipo de frecuencias (o relativo o absoluto). En las versiones iniciales de este trabajo se añadieron parámetros para distinguir los tipos de frecuencia de ambas tasas. Sin embargo, tras la realización de algunas pruebas, nos dimos cuenta de que es confuso que la tasa de muerte esté especifcada de un modo y la de nacimiento de otro, ya que estarían en escalas distintas. Por tanto, se ha decidido que el parámetrofrequencyType, el cual ya estaba presente en la función, indique el tipo de frecuencia de ambas tasas, aunque el tipo de frecuencia se puede inferir automáticamente sin necesidad de este parámetro. Por tanto, la funciónallFitnessEffectsquedaría como se indica en el código 3.1.

Especifcar tasas de muerte es opcional. Sin embargo, siempre tienen que estar especifcadas las tasas de nacimiento. Esto es lógico, ya que los modelos implementados hasta el momento requieren que el usuario introduzca los birth rates, mientras que no hay ningún modelo que requiera exclusiva- mente los death rates (recordemos la inconsistencia con el modelo de Bozic). De esta forma, podemos mantener la funcionalidad antigua, sin apenas cambios.

Simulación de modelos evolutivos en cáncer 18

(31)

3.2. Especificacion´ de tasas de muerte

Código 3.1: Cabecera de la funciónallFitnessEffectsmodifcada

function allFitnessE˙ects(rT = NULL, epistasis = NULL,

orderE˙ects = NULL, noIntGenes = NULL, geneToModule = NULL, drvNames = NULL, genotFitness = NULL, keepInput = TRUE, frequencyDependentBirth = FALSE, frequencyDependentDeath = FALSE, deathSpec = FALSE,

frequencyType = NA)

3.2.2. evalAllGenotypes

Esta función anteriormente devolvía el ftness de cada uno de los genotipos. Ahora deberá devolver el birth rate y el death rate de cada genotipo. El cálculo de las tasas se realiza en C++ y la función que comunica R con C++ esevalRGenotype.

Código 3.2: Cabecera de la funciónevalRGenotypeoriginal

double evalRGenotype(Rcpp::IntegerVector rG, Rcpp::List rFE, Rcpp::IntegerVector spPop, bool verbose, bool prodNeg, Rcpp::CharacterVector calledBy_, double currentTime)

Esta función se llama desde R para obtener la evaluación del ftness por cada uno de los genotipos.

Como se puede observar, la función devuelve un único valor. Sin embargo, tenemos que modifcar esta función para que pueda devolver, en caso de que nos interese, dos valores: birth rate y death rate. Para ello, hay que modifcar el valor de retorno de la función como se indica en el código 3.3.

Código 3.3: Cabecera de la funciónevalRGenotypemodifcada

Rcpp::NumericVector evalRGenotype(Rcpp::IntegerVector rG, Rcpp::List rFE, Rcpp::IntegerVector spPop, bool verbose, bool prodNeg, Rcpp::CharacterVector calledBy_, double currentTime)

Como esta función retorna directamente su valor a R, debe devolver un vector defnido en el pa- queteRcpp. Además, existe un archivo,RcppExports.cpp, el cual contiene las defniciones de las funciones de C++ que son llamadas desde R, por lo que hemos realizado cambios en este archivo para ser consistentes con las modifcaciones de la función.

Las llamadas para realizar el cálculo de la tasa de muerte son análogas a las llamadas para el cálculo de la tasa de nacimiento, por lo que podemos reutilizar la misma función:

Alberto González Klein 19

(32)

Diseno˜ e implementacion´

evalGenotypeFDFitnessEcuation. El problema es que esta función lee las ecuaciones de birth rate a partir del objeto fitnessEffects y las evalúa. Por tanto, necesitamos poder decirle a la función cuándo queremos que evalúe las ecuaciones de tasas de nacimiento y cuándo queremos las de tasa de muerte. Para ello, se ha incorporado una fag:birth.

Código 3.4: Cabecera de la funciónevalGenotypeFDFitnessEcuationmodifcada

double evalGenotypeFDFitnessEcuation(const Genotype& ge, const ftnessE˙ectsAll& F,

const std::vector<Genotype>& Genotypes, const std::vector<spParamsP>& popParams, const double& currentTime,

bool birth)

3.2.3. oncoSimulIndiv

Para realizar las simulaciones especifcando tasas de muerte, debemos crear un nuevo modelo que pueda recibir un objetofitnessEffectscon tasas de muerte, ya que los modelos ya existentes tie- nen sus propias tasas de muerte fjadas. Por tanto, se ha incorporadoArbcomo opción al parámetro modelpara indicar que se quiere utilizar un modelo arbitrario. Si se especifcamodel = “Arb”, en- tonces se requiere quedeathSpec = TRUE. Del mismo modo, sideathSpec = TRUE, entonces model = “Arb” (en un principio, sin contar con la funcionalidad explicada en la siguiente sección).

La última pregunta que queda es: ¿cómo trabaja oncoSimulIndiv con el modelo arbitrario?

Básicamente, la única diferencia respecto al resto de modelos es la tasa de muerte. Por tanto, necesi- tamos modifcar la función de C++ que trabaja con dicha tasa:updateBirthDeathRates.

Código 3.5: Cabecera de la funciónupdateBirthDeathRates

void updateBirthDeathRates(std::vector<spParamsP>& popParams, const std::vector<Genotype>& Genotypes, const ftnessE˙ectsAll& ftnessE˙ects, double& adjust_ftness_MF, const double& K,

const double& totPopSize, const double& currentTime, const TypeModel typeModel)

Esta función actualiza las tasas de nacimiento y muerte en cada iteración del algoritmo, dependien- do del modelo. Para ello, llama a funciones que se especializan en cada uno de los modelos, por lo que es necesaria la creación de una nueva función para nuestro modelo arbitrario:updateRatesArbitrary.

Simulación de modelos evolutivos en cáncer 20

(33)

3.3. Modelo con poblacion´ total aproximadamente constante

Código 3.6: Cabecera de la nueva funciónupdateRatesArbitrary

void updateRatesArbitrary(std::vector<spParamsP>& popParams, const std::vector<Genotype>& Genotypes, ftnessE˙ectsAll& ftnessE˙ects,

const double& currentTime)

En esta función se evalúan las expresiones deBirthy deDeathespecifcadas por el usuario, se actualizan las tasas y se calculan laWy laRdel algoritmo BNB.

3.3. Modelo con población total aproximadamente constante

Existen algunos modelos que requieren que la población total se mantenga constante, como los procesos de Moran. Por tanto, para ampliar el alcance de OncoSimulR, la incorporación de esta fun- cionalidad es fundamental. Este es un tema ya tratado en el TFM de Alberto Parramón [12], aunque de una forma ligeramente distinta y para un problema diferente .

La idea para conseguir que la población se mantenga constante es variar la tasa de muerte de los genotipos de tal forma que la población total sea la deseada. Para obtener el aumento necesario, debemos tener en cuenta la ecuación básica de crecimiento poblacional [9]:

(bi−di )Δt

ni(t + Δt) = ni(t)e ,

donde Δt es el tiempo transcurrido desde la última actualización de la población, bi es la tasa de nacimiento del genotipoi ydi la tasa de muerte del genotipoi. Por tanto, para llevar a cabo nuestra idea debemos añadir un valor, llamémoslo r, a la tasa de muerte de cada uno de los genotipos, es decir:

(bi−di−r)Δt

ni(t + Δt) = ni(t)e .

Por tanto, la población total sería:

X (b

i−di−r)Δt

N (t + Δt) = ni(t)e .

i

Además, queremos queN (t + Δt) = P i initSizei. DondeinitSizei es el tamaño inicial de la poblacióni. Utilizando el desarrollo de Taylor sobre la ecuación anterior obtenemos:

Alberto González Klein 21

(34)

Diseno˜ e implementacion´

X X X

initSizei = N(t + Δt) = ni(t)(1 + (bi − di − r)Δt) = N(t) + ni(t)(bi − di − r)Δt

i i i

Dividiendo porN (t) = P i ni(t):

P  P 

initSizei i ni(t)(bi − di)

i N (t) = 1 + N (t) − r Δt

Despejamosr:

P P

i ni(t)(bi − di) N(t) − iinitSizei

r = N (t) + N (t)Δt (3.1)

Por tanto, la implementación de este nuevo modelo es sencilla, teniendo en cuenta la ecuación 3.1, pero ha sido necesario incorporar un nuevo modelo como parámetro aoncoSimulIndiv:Const. Antes de decidir introducir un nuevo modelo también hemos considerado otras opciones. Como real- mente lo que hacemos es “corregir” las tasas de muerte mediante el factorr, nuestra primera aproxi- mación fue introducir una fag que indicase si se quiere hacer esta corrección o no y permitir utilizar esta funcionalidad con los modelos ya existentes. Sin embargo, descartamos este diseño por dos ra- zones fundamentales. La primera es que nos interesaría poder utilizar esta funcionalidad en el caso de que únicamente se especifcan tasas de nacimiento y no hay ninguna tasa de muerte fjada o introdu- cida por el usuario. La segunda es que se estarían “deformando” los modelos. Por ejemplo, el usuario estaría especifcando un modelo exponencial con población constante, pero el resultado que obtendría no sería nada parecido a un modelo exponencial. Por tanto, hemos considerado que la introducción de un nuevo modelo es la opción más adecuada.

En caso de que se especifque el modelo Const, el usuario podrá introducir los birth rates y, opcionalmente, los death rates. Internamente, en C++ desde la funciónupdateBirthDeathRates descrita anteriormente, se llamará a una nueva función que actualice las tasas de acuerdo a nuestro nuevo modelo:updateRatesConstant.

Código 3.7: Cabecera de la nueva funciónupdateRatesConstant

void updateRatesConstant(std::vector<spParamsP>& popParams, const std::vector<Genotype>& Genotypes, const ftnessE˙ectsAll& ftnessE˙ects, const double& cte,

const double& sampleEvery, const double& currentTime)

Esta función realizará el ajuste del death rate mediante el cálculo de lar, detallada arriba, en caso de que el usuario haya especifcado las tasas de muerte. En caso contrario, el death rate será el mismo r.

Simulación de modelos evolutivos en cáncer 22

Referencias

Documento similar