IATE VS COVID: Countries repo¶
El propósito de este proyecto es:
Autores:
A python virtual environment is suggested to work with this project.
Requirements are listed in the project home directory file:
requirements.txt
.
Science case¶
Proposal¶
Servicio para recabar datos de tablas y hacer una predicción de diferentes parámetros relacionados con la epidemia de Covid19
Los datos a recabar son: - configuracion del experimento, a partir de parámetros ajustados a los datos disponibles - datos demográficos
Resultado: evolución con el tiempo de los siguientes parámetros, con sus respectios errores:
- Cantidad de personas infectadas
- Cantidad de camas necesarias
El experimento es probabilístico y hace uso de algoritmos de simulación
El planteo se basa en el gráfico de flujo de individuos entre los diferentes estados en que puede estar respecto de el contagio con el virus:
- I:
- Número de Infectados
- C:
- Número de Confirmados
- H:
- Número de confirmados en tratamiento domiciliario
- B:
- Número de confirmados en cama común en un centro de salud
- U:
- Número de confirmados en una unidad de terapia intensiva
- R:
- Número de confirmados con recuperación registrada
- D:
- Número de confirmados difuntos
Las relaciones entre las variables I, C y (B+H+U) están dadas por los modelos de propagación de infecciones, por ejemplo el modelo SEIR.
En este caso se hace una implementación numérica para analizar variables que no se pueden (?) analizar con el modelo, por ejemplo:
- Usar distribuciones de probabilidad para los diferentes parámetros
- Considerar la incorporación de casos importados
- Calcular la necesidad de camas
- etc (?!)
La transferencia de individuos entre los diferentes estados está determinada por dos cosas:
- La probabilidad de transferencia (f)
- El tiempo de retardo (T)
- Los parámetros propios del individuo
Por ejemplo, la probabilidad de transferencia del estado U al D es la tasa de mortalidad, y ocurre cierto tiempo después de que el paciente ingresa al estado U.
El modelo se puede representar por:
Modelo donde solo se puede pasar a D desde el estado U | Modelo donde se puede pasar de los estados H, B y U al D |
En una simulación, se puede implementar de manera muy simple el modelo considerando (pequeños) incrementos. Por ejemplo, para una variable \(W\) que depende de otras variables \(V_i,\,i=1,2,...,n\)
y si la función es lineal:
se puede integrar de manera numérica, en primera aproximación, como:
References¶
Tools to analize covid19 data
Resources¶
Data sources:
- Clean dat from OpenBlender
- Analyzing Coronavirus (Covid-19) Data Using Pandas and Plotly
- Notebook in RMOTR
- MathWorks blog
Pandemic:
Notebooks¶
Hasta ahora hay dos notebooks que son mas que nada exploratorios de los datos compilados por John Hopkins CSSE.
- world.ipynb:
- carga datos de la poblacion y area de los paises para construir una tabla con esos dos datos. Luego se usará para normalizar las curvas de contagio de los diferentes países.
- load_data.ipynb:
- Carga los datos de JHU CSSE y analiza las curvas de contagio de algunos países.
DATA¶
Los datos actualizados son leidos directamente de GitHub, no hace falta bajarlos.
Los datos sobre poblacion y area de los países:
- table-1.csv:
- source: https://en.wikipedia.org/wiki/List_of_countries_and_dependencies_by_area preprocessed with https://wikitable2csv.ggor.de/
- table-2.csv:
- source: https://en.wikipedia.org/wiki/List_of_countries_by_population_(United_Nations) preprocessed with https://wikitable2csv.ggor.de/
- world_area.csv:
- Tabla limpia con las areas
- world_population.csv:
- Tabla limpia con las poblaciones
- world.ods:
- Archivo ODS con las dos tablas (para verificar a ojo)
- pop_area.csv:
- Tabla con las columnas de poblacion y area combinadas
Getting Started¶
Getting started¶
Preparing a virtual environment¶
virtualenv MyVE
source MyVE/bin/activate
pip install -r requirements.txt
API Usage¶
- instalation through pypy not yet implemented
- make setup.py installer
- from a python script, call import cv19
This project is organized as an API to be used from a python prompt.
Steps:
- Complete the configuration of the experiment
- All the settings of the experimets are parsed from the configuration files using configparser.
Prerequisites¶
- Put data files on the
dat
directory. - Complete the names of the data files in the configuration file
Notebooks¶
Hasta ahora hay dos notebooks que son mas que nada exploratorios de los datos compilados por Johns Hopkins CSSE
- world.ipynb:
- carga datos de la poblacion y area de los paises para construir una tabla con esos dos datos. Luego se usará para normalizar las curvas de contagio de los diferentes países.
- load_data.ipynb:
- Carga los datos de JHU CSSE y analiza las curvas de contagio de algunos países.
DATA¶
Los datos actualizados son leidos directamente de GitHub, no hace falta bajarlos.
Los datos sobre poblacion y area de los países:
- table-1.csv:
- source: https://en.wikipedia.org/wiki/List_of_countries_and_dependencies_by_area preprocessed with https://wikitable2csv.ggor.de/
- table-2.csv:
- source: https://en.wikipedia.org/wiki/List_of_countries_by_population_(United_Nations) preprocessed with https://wikitable2csv.ggor.de/
- world_area.csv:
- Tabla limpia con las areas
- world_population.csv:
- Tabla limpia con las poblaciones
- world.ods:
- Archivo ODS con las dos tablas (para verificar a ojo)
- pop_area.csv:
- Tabla con las columnas de poblacion y area combinadas
Data is stored in the dat directory.
filename | contents |
---|---|
covid_df.csv | Covid-19 world data |
pop_area.csv | Population of countries |
table-1.csv | |
table-2.csv | |
table_age.csv | Age distribution table |
table_clean.csv | |
table_population_cordoba.csv | Age distribution in Cordoba |
table_population_world.csv | |
world.ods | |
world_area.csv | |
world_population.csv |
Configuration files¶
Command line usage¶
For a simple test, go to src and run:
API usage¶
To use functionalities, import the cv19
module:
import cv19
First, we must parse the configuration parameters from the .ini file.
All parameters with an assigned value must be read with the
configparser
module. The ConfigParser class is inherited in cv19.parser
.
Variables can be accessed using the names of the sections and the names of the fields. For example, conf[‘clinical’][‘bed_stay’].
conf = cv19.parser()
conf.check_file(argv)
conf.read_config_file()
conf.load_filenames()
conf.load_parameters()
Finally, the simulation is made with the cv19.InfectionCurve
class, where the function cv19.InfectionCurve.compute()
makes
the computations.
c = cv19.InfectionCurve()
t, I = c.compute(conf.p)
c.plt_IC_n(t, [I], conf.filenames.fname_infected)
Developer Documentation¶
Model implementation¶
En esta sección se describe la implementación del modelo numérico para hacer la integración de las variables.
Implementación del diagrama de flujo¶
El diagrama de flujo de las variables:
Se puede plantear como un grafo bidireccional dirigido, donde los nodos contienen los valores de las variables a medida que se hace evolucionar el sistema y las aristas contienen diferentes valores, por ejemplo las probabilidades de transición o los tiempos de retardo.
Este tipo de objeto se construye instanciando la clase
cv19.Graph
.
Ejemplo de uso:
from cv19 import Graph
g = Graph()
for i, inode in enumerate(['A','B','C','D']):
print(i)
g.add_node(inode, 0)
nms = ['x', 'y']
g.add_edge('A', 'B', nms, [1, 100])
g.add_edge('A', 'C', nms, [2, 200])
g.add_edge('B', 'D', nms, [3, 300])
g.add_edge('D', 'B', nms, [4, 400])
g.add_edge('D', 'C', nms, [5, 500])
g.add_edge('C', 'C', nms, [6, 600])
g.add_edge('B', 'D', nms, [333, 333])
g.show()
Modelo de contagios con grafos¶
Con la clase cv19.Graph
se puede crear un grafo y agragar un
estado en cada nodo, con valor inicial cero para todos los estados
menos para el estado I, que comienza con un valor de por lo menos uno:
g = Graph()
for node in ['I','C','R','H','B','U','D',]:
g.add_node(node, 0)
g.set_node('I', p.N_init)
Ahora podemos agregar en las aristas las cosas que necesitamos. Para cada arista vamos a agregar un lag y una probabilidad de transición. Para el estado I el lag es cero y la probabilidad es la tasa de transmisión. El contador del estado I disminuye cuando hay transferencias del estado I al R.
g.add_edge('I', 'I', nms, [p.R, 0])
Esto nos va a permitir actualizar el valor de I según:
En esta versión I siempre crece, asi que habría que restarle los casos que se recuperan o fallecen. Es decir, hay que incorporar la trnasición \(I \rightarrow C\).
En general, dada una variable \(V\), su variación se incrementa por todas las variables \(U\) que tienen transiciones \(U \rightarrow V\) y disminuye por todas las variables \(W\) que tienen transiciones \(I \rightarrow W\).
Por ejemplo, si tenemos un grafo como este:
La variacion del nodo V está dada por:
Aquí por ejemplo \(P(V|U_1, q)\) significa probabilidad de que haya una transición del estado \(U_1\) al estado \(V\).
Teniendo en cuenta que:
- los parámetros parseados del archivo .ini están en la lista de parámetros p,
- los tiempos de lag están en unidades de días (si no, hay que pasarlos)
- todos los infectados acusan síntomas al día p.t_incubation
resulta el código para llevar la cuenta de I así:
g = Graph()
for node in ['I','C','R','H','B','U','D',]:
g.add_node(node, 0)
nms = ['prob','lag']
g.set_node('I', p.N_init)
g.add_edge('I', 'I', nms, [p.R, 0])
g.add_edge('I', 'C', nms, [1. p.t_incubation])
t = 0.
time_steps = 0
while t < p.t_max:
time_steps = time_steps + 1
t_prev = t
t = t + p.dt
ts.append(t)
prob_II = g.get_edge('I', 'I', 'prob')
lag_II = g.get_edge('I', 'I', 'lag')
prob_IC = g.get_edge('I', 'C', 'prob')
lag_IC = g.get_edge('I', 'C', 'lag')
n_I = I[-1] + I[-lag_II] * prob_II * p.dt - \
C[-lag_IC] * prob_IC * p.dt
I.append(n_I)
Implementación de un modelo¶
Para el modelo de la figura
Las transiciones son:
estado | suma | resta |
---|---|---|
I | I | C |
C | I | B, H, U |
H | C, B, U | R, B, U |
B | C, H, U | H, U |
U | C, B, H | D, B, H |
R | H | |
D | U |
Para este modelo, la actualización de un paso temporal para I es:
donde \(\tau_{II}\) es el time lag para la transición \(I \rightarrow I\), y \(\tau_{IC}\) es el time lag para la transición \(I \rightarrow C\). Los valores P son las probabilidades de transición, es decir, \(P(C(t)|I(t-\tau_{IC}))\) es la probabilidad de que un individuo pase al estado C en el tiempo t si estaba en el estado I en el tiempo \(t-\tau_{IC}\). Por supuesto, \(P(I(t)|I(t-\tau_{II}))\) es la probabilidad de permanecer en el estado I durante el tiempo \(\tau_{II}\).
Para el contador de “confirmados”, C, tenemos que:
porque sólo se puede llegar al estado C desde el estado I, y se puede pasar desde el estado C a los estados H, B o U con diferentes probabilidades. Los tiempos de retardo desde C son cero, porque se pueden pensar a los estados H, B y U como subestados de C, es decir,
De la misma forma, para las transiciones \(B \rightarrow H\), \(B \rightarrow U\), \(H \rightarrow R\), \(H \rightarrow B\), \(H \rightarrow U\), \(U \rightarrow H\), \(U \rightarrow B\) y \(U \rightarrow D\), tenemos las siguientes relaciones:
y análogamente para los otros nodos. Como se puede ver, hay una estructura que persiste en todos los casos, y se puede escribir de manera general. Para un nodo V, la variación en un paso temporal está dada por:
Versión probabilística¶
En la version probabilística, los cambios en los valores de los estados dependen de las características de la población en esos estados. Por ejemplo, las transiciones \(B \rightarrow U\) dependen de la edad de los pacientes. El modelo anterior se puede extender para una versión probabilística de la siguiente forma:
CV19 module¶
-
class
cv19.
Graph
¶ Bases:
object
class Graph This class is used to create and manipulated graphs It makes a heavy use of the node class A graph is made of nodes and edges. This class allows to store a value for each node and different “weights” for each edge. Also, edges are directed.
Exampe of usage: g = Graph()
- for i, inode in enumerate([‘A’,’B’,’C’,’D’]):
- print(i) g.add_node(inode, 0)
nms = [‘x’, ‘y’] g.add_edge(‘A’, ‘B’, nms, [1, 100]) g.add_edge(‘A’, ‘C’, nms, [2, 200]) g.add_edge(‘B’, ‘D’, nms, [3, 300]) g.add_edge(‘D’, ‘B’, nms, [4, 400]) g.add_edge(‘D’, ‘C’, nms, [5, 500]) g.add_edge(‘C’, ‘C’, nms, [6, 600])
# A node can be connected to itself. g.add_edge(‘B’, ‘B’, nms, [333, 333])
g.show()
- vert_dict: dict
- a dict containing the vertices
- num_vertices : int
- the number of nodes (or vertices) in a graph
add_node(node, value) get_node() get_node_value() set_node() get_node_ids() get_nodes_to() get_nodes_from()
-
add_edge
(frm, to, names=[], values=0)¶ warning: does not verify if edge already exists
-
add_node
(nnode, value)¶ method: add_node
Adds a node to a graph. The node must have a value.
-
get_edge
(frm, to, field)¶
-
get_node
(n)¶ method: get_node
n: strnode: a node object
-
get_node_ids
()¶
-
get_node_value
(n)¶ method: get_node_value
n: strvalue: float
-
get_nodes_from
(nnode)¶
-
get_nodes_to
(nnode)¶
-
node_activation
(nnode, key)¶
-
node_upgrade
(nnode, key)¶
-
set_node
(n, value)¶ method: set_node
- n: str
- The ID or name of the node
- value: float
- The value to be assigned to the node
updates the Graph
-
show_connections
()¶
-
show_weights
()¶
-
class
cv19.
InfectionCurve
¶ Bases:
object
-
compute
(p)¶ InfectionCurve(self, p): computes the Infection Curve based on a probabilistic model implemented in a simulation
- Args:
- config object from ParseConfig
Raises:
- Returns:
- Time series for the curves of: - Infected - Confirmed - Recovered - Confirmed at home - Confirmed at hospital - Confirmed at ICU - Dead
-
model_SEIR
()¶
-
model_SIR
(p)¶
-
plt_IC
()¶ plots the infection curve
- Args:
- ic: time series fplot: filename for the plot
Raises:
- Returns:
- Nothing, just save the plot.
-
plt_IC_n
()¶ plots the infection curve
- Args:
- ic: time series fplot: filename for the plot
Raises:
- Returns:
- Nothing, just save the plot.
-
-
class
cv19.
node
(nnode, value)¶ Bases:
object
class node This class is used to create and manipulated nodes.
-
add_neighbor
(neighbor, names, values)¶
-
be_neighbor
(neighbor, names, values)¶
-
get_connections
()¶
-
get_id
()¶
-
get_weight
(neighbor)¶
-
-
class
cv19.
parser
(defaults=None, dict_type=<class 'collections.OrderedDict'>, allow_no_value=False, *, delimiters=('=', ':'), comment_prefixes=('#', ';'), inline_comment_prefixes=None, strict=True, empty_lines_in_values=True, default_section='DEFAULT', interpolation=<object object>, converters=<object object>)¶ Bases:
configparser.ConfigParser
parser class manipulation of parser from ini files
-
check_file
(sys_args)¶ chek_file(args): Parse paramenters for the simulation from a .ini file
- Args:
- filename (str): the file name of the map to be read
Raises:
- Returns:
- readmap: a healpix map, class ?
-
load_filenames
()¶ load_filenames(self): make filenames based on info in config file
- Args:
- None
Raises:
- Returns:
- list of filenames
-
load_parameters
()¶ load_parameters(self): load parameters from config file
- Args:
- None
Raises:
- Returns:
- list of parameters as a named tuple
-
read_config_file
()¶ chek_file(args): Parse paramenters for the simulation from a .ini file
- Args:
- filename (str): the file name of the map to be read
Raises:
- Returns:
- readmap: a healpix map, class ?
-
-
class
cv19.
table_draw
¶ Bases:
object
-
add_clean_column
(columnname, column)¶
-
load
(filename)¶
-
random_gen
(xinfname, xsupname, yname)¶ - method: random_gen
- Generates a random sample from a given probability density The probability density must be in the table, in the table_draw class.
-
save_clean_CDF
(filename)¶
-
tabular
(x, y)¶
-
test_random_gen
(nran, fplot)¶
-
To do list¶
Team work¶
- Organizar códigos. Tratar de armar un solo repositorio, e ir poniendo los códigos “limpios” en src
Development¶
Complete documentation: it is generated automatically from metacomments, using Sphinx.
Asserts:
- What to do is data files are missing
- Prevent variable overflows and division by zero
Testing¶
Make several tests to reach a good code coverage and verify if results are as expected.
Proposed tests to develop¶
- check parsing
- read a synthetic data and verify theoretical behaviour
- Check paths and files
- Verify means in statistical distributions
- Try different statistical distributions
- Compare results with other tools
Testing tools and procedures¶
In order to make testing, we should use any of the following tools:
- pytest
- hypothesis
pytest examples
“pytest will run all files of the form test_*.py or *_test.py in the current directory and its subdirectories.” So, simply go to the tst directory, and run pytest.
In the environment:
In the code (example from pytest documentation):
How to run test:
From the CLI, write:
** coverage **
Desde el entorno, instalar los paquetes coverage y pytest-cov:
Para calcular la cobertura de código, correr:
Se puede integrar el pytest con el codecov:
Documenting the project¶
Sphinx: automatic generation of documents from docstrings
This documentation has been generated using Sphinx.
In order to generate HTML docs locally, go to doc/
and run:
(python-env) make html
Editting docs
Just edit .rst files.
Generate the documentation on line in readthedocs
- log in into readthedocs account
- go to project
- build