Skip to content

About

AI-powered well log analysis tool for interpreting subsurface geological data and supporting automated formation characterization.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

13 Commits

Folders and files

Repository files navigation

AI_WELL_LOG

Interpretación automatizada de registros de pozos

Aplicación de evaluación petrofísica determinística a partir de archivos LAS, con soporte multiidioma (Español, English, Français).

🌐 Disponible en: aiwelllog.streamlit.app


Características

Lectura y control de calidad

  • Lectura de LAS desde memoria, sin archivos temporales
  • Saneamiento de valores nulos no declarados en la cabecera (-9999, -999.25, ...)
  • Lectura de la unidad de profundidad declarada y conversión de metros a pies
  • Detección automática de escalas erróneas: NPHI en unidades de porosidad, RHOB en kg/m³, DT en µs/m, CALI en mm
  • Validación por rangos físicos de cada curva
  • Control de calidad de hoyo: descarta la densidad donde el calibre indica derrumbe, y señala la costra de lodo (CALI < BS) como indicio de permeabilidad
  • Mapeo flexible de curvas, incluidas las familias de resistividad AIT-H, AIT, laterolog e inducción

Cálculo petrofísico

  • Volumen de arcilla: Larionov (terciario y preterciario), lineal, Clavier, Stieber, triángulo neutrón-densidad y CGR sin uranio
  • Porosidad: leída sobre la línea de matriz del crossplot neutrón-densidad (carta CP-1), con matriz de interpretación seleccionable por el usuario
  • Saturación de agua: Archie, Simandoux e Indonesia (Poupon-Leveaux)
  • Permeabilidad: Kozeny-Carman, Timur y Coates, con calibración de la constante contra datos de núcleo
  • Litología: clasificación por densidad de matriz aparente y PEF
  • Evaluación composicional: volúmenes minerales resolviendo LOG = Σ Vmin·LOGmin + Φ·LOGfl
  • Net to Gross: jerarquía Gross → Net Rock → Reservorio → Net Pay, en espesor real

Visualización y reportes

  • Registro de 8 tracks con escalas según la matriz y ventana de profundidad ajustable
  • Crossplots neutrón-densidad, RHOMAA–UMAA y M–N
  • Perfil apilado de volúmenes minerales
  • Exportación a PDF, Excel y CSV, individual y consolidada por lotes
  • Procesamiento simultáneo de varios pozos con referencia de GR común al lote

Instalación

La versión de referencia es Python 3.11: es sobre la que está verificado el conjunto de dependencias que documenta la cabecera de requirements.txt. En versiones más nuevas la resolución puede no ser la misma.

git clone https://github.com/ErickFMR777/AI_Well_Log.git
cd AI_Well_Log
pip install -r requirements.txt

Si tu Python del sistema no es 3.11, la vía más limpia es uv, que instala un intérprete propio y lo aísla en un entorno virtual sin tocar el del sistema ni requerir permisos de administrador:

uv python install 3.11
uv venv --python 3.11
uv pip install -r requirements.txt

Uso

streamlit run app/main.py

Se abre en http://localhost:8501.

Si usaste el entorno de uv, actívalo antes (.venv\Scripts\activate en Windows, source .venv/bin/activate en Linux y macOS).

Si el puerto 8501 está ocupado —lo reserva el devcontainer aunque no esté sirviendo—, añade --server.port 8502.

El comando debe ejecutarse desde la raíz del repositorio: Streamlit añade el directorio del script (app/) al sys.path, que es lo que permite resolver modules.*.

También hay un devcontainer listo (.devcontainer/) que instala las dependencias y arranca la app automáticamente.


Estructura

app/
  main.py                 Interfaz: i18n, estilos, panel de control y renderizado
  modules/
    petrofisica.py        Constantes, WellConfig, saneamiento y calculadores
    las_io.py             Lectura de LAS, unidades, nulos y mapeo de curvas
    pipeline.py           Orquestación del cálculo de un pozo
    plotting.py           Registro de 8 tracks y crossplots
    pdf_export.py         Reporte PDF individual y bloques reutilizables
    pdf_batch_export.py   Reporte PDF consolidado
.streamlit/config.toml    Tema y ajustes de servidor
requirements.txt          Dependencias con topes de versión mayor
CLAUDE.md                 Notas de arquitectura e invariantes del cálculo

El flujo es las_io.load_well → pipeline.process_loaded_well → renderizado y exportación. Toda la petrofísica vive en los módulos; main.py solo orquesta y presenta.


Metodología

No se usa machine learning, y es una decisión deliberada

No hay redes neuronales, ni clustering, ni clasificadores entrenados. No existe scikit-learn, TensorFlow ni PyTorch en las dependencias, ni una sola llamada a fit, predict o train en el código.

Todo resultado sale de ecuaciones petrofísicas publicadas, evaluadas sobre las curvas del archivo. Esto es una ventaja, no una carencia: cada número es trazable hasta la fórmula que lo produjo y el parámetro que se le pasó, se reproduce exactamente con los mismos datos de entrada, y no depende de un conjunto de entrenamiento ajeno a tu cuenca. Un modelo entrenado no ofrece ninguna de las tres cosas.

Lo que sí se usa, y conviene nombrar con propiedad:

Técnica Dónde Para qué
Ecuaciones deterministas Archie, Simandoux, Indonesia, Larionov, Clavier, Stieber, Kozeny-Carman, Timur, Coates Saturación, arcillosidad, permeabilidad
Estadística robusta gr_reference (P2/P98), modal_matrix (moda), estimate_shale_point (P90), estimate_swirr (P10) Referencias tomadas del propio pozo, resistentes a picos de herramienta
Filtro de mediana smooth_curve Suavizado que respeta los vacíos de la curva
Inversión lineal solve_composicional Sistema 4×4 resuelto por profundidad para obtener volúmenes minerales
Geometría baricéntrica calc_vsh_neutron_density Vsh por el triángulo neutrón-densidad
Clasificación por umbrales físicos classify_lithology Litología según PEF y densidad de matriz aparente
Regresión por mínimos cuadrados calibrate_kozeny Único ajuste contra datos: la constante de Kozeny frente a núcleos, en espacio logarítmico

calibrate_kozeny es lo más cercano a "aprender de los datos" que hay en la app, y es una regresión de un solo parámetro contra mediciones de núcleo que aportas tú.

Del archivo LAS a la línea del registro

Las curvas no se leen por posición sino por nombre, y no se dibujan en crudo. Entre el archivo y el píxel hay seis pasos, en este orden exacto (las_io.load_well):

  1. Saneamiento de nulos — se anulan los centinelas que lasio no reconoce. La librería solo honra el NULL declarado en la cabecera, así que un archivo que mezcle -999.25 declarado con -9999 sin declarar entregaría el segundo como dato válido y contaminaría cada promedio y percentil posterior.
  2. Profundidad y su unidad real — se lee la unidad declarada en ~Curve o ~Well y se convierte a pies, que es la unidad canónica interna. Un archivo métrico tratado como pies arrastra un error de factor 3,28 a espesores, ejes y tablas.
  3. Mapeo de alias a nombres estándar — CURVE_ALIASES traduce más de 40 mnemónicos. La resistividad profunda puede llamarse RT, ILD, LLD, AHT90, AT90, RLA5… y si su familia falta, el pozo se queda sin saturación en silencio.
  4. Corrección de escalas — se detectan por mediana los desfases de orden de magnitud: NPHI en unidades de porosidad, RHOB en kg/m³, DT en µs/m, CALI en mm.
  5. Rangos físicos — fuera del rango admisible el valor pasa a nulo, no a un número plausible.
  6. Control de calidad de hoyo — donde el calibre indica derrumbe se anulan RHOB, NPHI y PEF. La herramienta de densidad es de patín: en un hoyo derrumbado mide lodo, no roca.

Solo entonces se dibuja. Lo que ves en el registro es la curva saneada, no la del archivo, y por eso la app muestra en el Paso 1 qué correcciones aplicó.

Los 8 tracks:

# Track Escala Detalle
1 GR 0 a máx(150, P99) API Relleno amarillo por debajo de 75 API
2 RHOB Según matriz, eje invertido 2,95→1,95 en caliza · 2,65→1,65 en arenisca
3 NPHI Según matriz, eje invertido 0,45→−0,15 en caliza · 0,60→0,00 en arenisca
4 Resistividad Logarítmica RT, RM, RXOS, RMC y RMUD con estilo propio
5 PHI_E v/v Sombreado según el cutoff de porosidad
6 VSH v/v Sombreado según el cutoff de arcillosidad
7 Net Pay Bandera Distingue "no cumple" de "no evaluable"
8 Litología Color Paleta única en LITHO_COLORS

Las escalas de RHOB y NPHI dependen de la matriz (ESCALAS_MATRIZ). Presentar un neutrón en unidades caliza sobre la escala de arenisca desplaza visualmente el cruce densidad-neutrón y hace que un intervalo de gas parezca agua, o al revés.

Una misma función, build_8track_figure, genera la figura de la pantalla y la de los dos PDF, y lee sus cutoffs de la configuración del pozo. No hay una segunda implementación que pueda desincronizarse.

Cómo se llega al modelo geológico

Hay una circularidad que resolver: la litología necesita la porosidad para calcular la densidad de matriz aparente, y la porosidad necesita la densidad de matriz que determina la litología. Se resuelve iterando dos veces:

  1. Matriz provisional a partir de las medianas de PEF y RHOB, solo para obtener una porosidad con la que clasificar.
  2. Clasificación punto a punto por densidad de matriz aparente ρma_ap = (ρb − φ·ρfl)/(1 − φ) combinada con PEF, cuyos umbrales son constantes físicas: arenisca 1,81 · dolomita 3,14 · anhidrita 5,05 · caliza 5,08 barns/electrón.
  3. Matriz definitiva por la MODA de esa clasificación, no por la mediana de PEF. En una secuencia mixta la distribución de PEF es bimodal y su mediana cae entre los dos modos, eligiendo una roca que casi no existe en el pozo. Contar puntos evita ese artefacto.
  4. Porosidad final con la densidad de matriz y la calibración del neutrón que corresponden a la litología de cada profundidad.

La porosidad neutrón se lee sobre la línea de matriz del crossplot densidad-neutrón (carta CP-1), resolviendo φN = (NPHI − N_ma)/(N_fl − N_ma). Un neutrón grabado en unidades caliza y leído en una arenisca subestima la porosidad unas 4 unidades; en una dolomita la sobreestima unas 7.

En paralelo, la evaluación composicional resuelve en cada profundidad

RHOB = Σ Vi·RHOBi + Φ·RHOBfl
NPHI = Σ Vi·NPHIi + Φ·NPHIfl
U    = Σ Vi·Ui    + Φ·Ufl
1    = Σ Vi       + Φ

y devuelve volúmenes minerales en lugar de una etiqueta: una arena arcillosa sale como 0,70 de cuarzo + 0,15 de arcilla + 0,15 de porosidad, no como "ARENISCA_ARCILLOSA". El fotoeléctrico entra como U y no como PEF, porque el PEF es una sección transversal por electrón y no se mezcla linealmente por volumen. La app informa cuánto volumen hubo que mover para que la solución fuera admisible: por encima de ~0,15 v/v el modelo no describe la formación, y lo dice.

Los crossplots N-D, RHOMAA–UMAA y M–N permiten verificar visualmente esa identificación mineralógica.

Cómo se llega al net pay

Cuatro niveles, cada uno subconjunto estricto del anterior, de modo que las relaciones N/G son acumulativas y comparables entre pozos:

GROSS      intervalo completo
NET ROCK   + Vsh   <= cutoff      descarta la arcilla
RESERVORIO + PHI_E >= cutoff      con capacidad de almacenar
NET PAY    + Sw    <= cutoff      con interés económico

Los tres cutoffs son ajustables desde el panel lateral (por defecto 6 % de porosidad, 50 % de Vsh y 70 % de Sw).

Lo que distingue este cálculo de uno ingenuo es que hay tres estados, no dos. Una muestra puede cumplir, no cumplir, o no ser evaluable porque le falta el dato para decidir. Las no evaluables quedan fuera del numerador y del denominador. Por eso se reportan dos porcentajes: pct_sobre_evaluable y pct_sobre_total. Rellenar los faltantes con ceros convertiría "sin dato" en un "no" definitivo y diluiría el net pay sobre tramos que ni siquiera tienen registro.

El resultado se da en espesor real (pies), obtenido del paso de muestreo mediano. Un conteo de muestras no significa nada sin él.

Cada decisión automática —matriz dominante, parámetros de Archie, constante de Kozeny, referencia de GR, matriz del neutrón— se registra con su procedencia y se muestra en la interfaz y en el PDF, de modo que lees los valores realmente usados, no los que muestran los deslizadores.


Notas de interpretación

Algunas decisiones del cálculo que conviene conocer al leer los resultados:

  • La corrección de arcilla se aplica una sola vez, de forma simétrica sobre densidad y neutrón.
  • La porosidad total alimenta la ecuación de saturación; la efectiva alimenta el net pay y la permeabilidad.
  • La matriz de interpretación se toma por defecto de la litología dominante del pozo, determinada por la moda de la clasificación punto a punto. Puede fijarse manualmente.
  • El neutrón se calibra sobre una matriz (por defecto caliza, estándar de industria). La app lee esa matriz del archivo cuando está declarada.
  • La constante de Kozeny no es universal: sin calibración contra núcleos, la permeabilidad es un orden de magnitud, no un valor absoluto.
  • Los cálculos propagan el nulo: si falta un dato necesario el resultado es nulo, nunca un valor por defecto silencioso. El net pay distingue entre "no cumple" y "no evaluable".

Requisitos

Python 3.11 (versión de referencia, sobre la que está verificado el conjunto de dependencias). Las dependencias y sus topes de versión mayor están en requirements.txt.


Referencias

La formulación sigue la práctica estándar de interpretación de registros. Los valores de referencia de minerales y los métodos de crossplot provienen del curso Análisis e Interpretación de Registros de Pozo (M. F. Barragán A., ACGGP / LITHoil, 2022).

Autor

Erick F. Mendoza Rivero (ErickFMR777)

Licencia

Todos los derechos reservados © 2026

About

AI-powered well log analysis tool for interpreting subsurface geological data and supporting automated formation characterization.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages