Este repositorio contiene el flujo de trabajo completo para:
- Convertir archivos de genotipos (
.csv) a formato STRUCTURE (.str). - Ejecutar ezstructure/fastStructure para inferir clusters genéticos.
- Generar gráficos de barras de ancestría (estilo STRUCTURE).
- Realizar un análisis AMOVA sencillo en Python para evaluar estructura poblacional entre dos grupos.
La estructura está pensada para datos de individuos (g101BR–g129BR), pero los scripts permiten reutilizarse con otros archivos ubicados en la carpeta data/.
gen-structure-analysis/
├─ data/
│ ├─ Input_Naturales_1row.csv
│ ├─ input_2row_fil.csv
├─ scripts/
│ ├─ crear_str_desde_1row_filtrado.py
│ ├─ crear_str_desde_2row.py
│ ├─ plot_structure.py
│ ├─ amova_manual.py
├─ env/
│ └─ (opcional: notas sobre pyenv / venv)
├─ requirements.txt
├─ README.md
Los scripts están probados con Python 3.11 en Linux/WSL.
# Dependencias para compilar Python
sudo apt update
sudo apt install -y build-essential curl git libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget llvm libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
# Instalar pyenv
curl https://pyenv.run | bashAgregar al final de ~/.bashrc:
export PATH="$HOME/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"Recargar el shell:
source ~/.bashrcInstalar Python 3.11 (ejemplo 3.11.9) y usarlo en el proyecto:
cd gen-structure-analysis
pyenv install 3.11.9
pyenv local 3.11.9cd gen-structure-analysis
# Crear entorno virtual
python -m venv venv311
# Activar entorno
source venv311/bin/activate # Linux / WSL / macOS
# venv311\Scripts\activate # Windows (PowerShell / CMD)Cuando el entorno está activo, el prompt muestra algo como (venv311).
Crear un fichero requirements.txt con, por ejemplo:
numpy<2
pandas
matplotlib
scipy
cython
ezstructure
Instalar todo:
pip install -r requirements.txtNota:
ezstructurees un wrapper moderno defastStructure. Puede compilar extensiones en C, así que la instalación puede tardar un poco.
Colocar los CSV originales en la carpeta data/:
-
data/Input_Naturales_1row.csv- Formato: una fila por SNP
- Columnas:
Mark,g101BR,g102BR, ...,g129BR - Genotipos codificados como
0,1,2o-(missing).
-
data/input_2row_fil.csv- Formato: dos filas por SNP (alelo 1 y alelo 2).
- Columnas:
Mark,g101BR,g102BR, ...,g129BR - Valores:
0,1oNaN/-para missing.
Los scripts permiten usar otros archivos siempre que respeten este esquema de columnas.
Todos los scripts se ubican en la carpeta scripts/. A continuación se describe qué hace cada uno y sus parámetros.
Convierte un archivo 1-row por SNP a formato STRUCTURE (.str), filtrando SNPs donde todos los individuos están en missing.
cd scripts
python crear_str_desde_1row_filtrado.py- Entrada por defecto:
../data/Input_Naturales_1row.csv - Salida por defecto:
nat_filtrado.str(enscripts/)
python crear_str_desde_1row_filtrado.py --input ../data/otro_archivo_1row.csv --output-prefix otro_prefixGenera: otro_prefix.str
Convierte un archivo 2-row por SNP a .str, usando directamente las dos filas como alelo 1 y alelo 2.
cd scripts
python crear_str_desde_2row.py- Entrada por defecto:
../data/input_2row_fil.csv - Salida por defecto:
2row.str
python crear_str_desde_2row.py --input ../data/otro_archivo_2row.csv --output-prefix otro2rowGenera: otro2row.str
Una vez creado el .str, desde scripts/ se puede ejecutar, por ejemplo:
# Para el archivo 1-row filtrado
ezstructure -K 2 --input nat_filtrado --output nat_k2 --format str
ezstructure -K 3 --input nat_filtrado --output nat_k3 --format str
ezstructure -K 4 --input nat_filtrado --output nat_k4 --format str
# Para el archivo 2-row
ezstructure -K 2 --input 2row --output 2row_k2 --format str
ezstructure -K 3 --input 2row --output 2row_k3 --format str
ezstructure -K 4 --input 2row --output 2row_k4 --format strEsto genera archivos .meanQ con las proporciones de ancestría por individuo y por cluster.
Genera gráficos de barras de ancestría (estilo STRUCTURE) a partir de un archivo .meanQ de ezstructure.
cd scripts
python plot_structure.py --meanq ../results/nat_k2.2.meanQ --output ../results/nat_k2_barplot.png --csv ../data/Input_Naturales_1row.csvParámetros:
--meanq: ruta al archivo.meanQ.--output: ruta del PNG de salida.--csv: archivo CSV original desde donde se obtienen los nombres de individuos.
Si no se pasan argumentos, se pueden configurar valores por defecto dentro del script (por ejemplo, apuntando a nat_k2.2.meanQ y Input_Naturales_1row.csv).
El script:
- Lee la matriz Q (
N_individuos x K). - Lee los nombres de individuos del CSV (todas las columnas excepto
Mark). - Crea un gráfico de barras apiladas donde:
- eje X: individuos,
- eje Y: proporción de ancestría,
- cada color: un cluster (K).
Implementa un AMOVA simple en Python, sin scikit-bio, usando una matriz de distancias euclidianas entre individuos.
Suposición de grupos por defecto:
- Grupo1: individuos con IDs que contienen números 101–114 (por ejemplo
g101BR–g114BR) - Grupo2: individuos con IDs que contienen números 115–129 (por ejemplo
g115BR–g129BR)
cd scripts
python amova_manual.py- Entrada por defecto:
../data/Input_Naturales_1row.csv
python amova_manual.py --input ../data/otro_archivo_1row.csvImportante: el script asume que los nombres de columnas de individuos contienen un número (ej.
g101BR) y usa ese número para asignar individuos a Grupo1 o Grupo2. Si se usan otros IDs, será necesario adaptar la lógica de agrupación dentro del script.
El script:
- Lee el CSV de genotipos.
- Elimina SNPs completamente missing.
- Imputa valores missing por la media del SNP.
- Calcula una matriz de distancias euclidianas entre individuos.
- Calcula:
SS_totalSS_withinSS_between- ΦST = SS_between / SS_total
- Realiza 999 permutaciones de las etiquetas de grupo para estimar un p-value.
Ejemplo de salida:
SNPs totales en archivo: 14193
SNPs después de eliminar filas todo-missing: 14110
Individuos y grupos asignados:
g101BR: Grupo1
...
g129BR: Grupo2
===== RESULTADOS AMOVA MANUAL =====
ΦST (Phi_ST): 0.134708
P-value (perm 999): 0.000000
SS_total: 44353.741
SS_within: 38378.941
SS_between: 5974.800
Interpretación típica:
- ΦST ≈ 0.135 → estructura poblacional moderada entre Grupo1 y Grupo2.
- p-value ≈ 0.000 → la diferenciación genética es altamente significativa.
Algunas ideas para expandir este repositorio:
- Agregar un script de PCA genético a partir de la misma matriz de genotipos.
- Generar heatmaps y dendrogramas de la matriz de distancias.
- Permitir que el script
amova_manual.pyreciba un archivo externo de definición de poblaciones (por ejemplo,poblaciones.csv) en lugar de agrupar por rango de IDs. - Añadir notebooks (
.ipynb) con análisis exploratorio y visualización avanzada.
Este pipeline combina:
- Preprocesamiento de genotipos en Python.
- ezstructure/fastStructure para inferencia de estructura poblacional.
- Un AMOVA manual basado en distancias euclidianas y permutaciones.
Puede servir como plantilla para analizar estructura genética en otros conjuntos de datos con formato similar.