Intro Python DIGITAL
Intro Python DIGITAL
Python para
geociencias
Introducción a
Python para
geociencias
Germán A. Prieto
Prefacio v
Capı́tulo 1
Software e instalación 1
1. Instalación de Python con Anaconda . . . . . . . . . . . . . . . . . . . . . . 3
2. Cómo usar Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2.1. Scripts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.2. Jupyter Notebooks y Colab . . . . . . . . . . . . . . . . . . . . . . . . 5
3. Instalación de paquetes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Capı́tulo 2
Primeros pasos en Python 9
1. Primer programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
1.1. Explicación del primer programa . . . . . . . . . . . . . . . . . . . 12
1.2. Alternativas para el primer programa . . . . . . . . . . . . . . . . 13
2. Multiplicar dos números enteros . . . . . . . . . . . . . . . . . . . . . . . . . 14
3. For loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.1. Una tabla trigonométrica con for loops . . . . . . . . . . . . . . . . 18
3.2. Posibles variaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
4. Funciones del módulo math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
i
Contenido
5. Sobre formatos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Capı́tulo 3
Interacción con Python 25
1. Entrada con el teclado . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2. For y while loops, condicionales if . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.1. Escoger entre for y while loops . . . . . . . . . . . . . . . . . . . . . . . 34
3. Múltiples condicionales if, elif, else . . . . . . . . . . . . . . . . . . . . . . . . 35
4. Ejemplo: máximo común divisor . . . . . . . . . . . . . . . . . . . . . . . . . 38
Capı́tulo 4
Funciones del usuario 45
1. Funciones dentro del programa . . . . . . . . . . . . . . . . . . . . . . . . . . 47
2. Funciones con más salidas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3. Modules & packages propios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
3.1. Los module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
3.2. Los packages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
4. Ajustando el path para módulos propios . . . . . . . . . . . . . . . . . . . 62
Capı́tulo 5
Arreglos: vectores y matrices 67
1. Arreglos numéricos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
1.1. Los números primos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
1.2. Arreglos 1D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
1.3. Arreglos 2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
1.4. Aritmética en arreglos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
2. Arreglos dentro de funciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
3. Una aplicación a tsunamis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
4. Strings y arreglos de caracteres . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
4.1. Arreglos de caracteres . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
ii
Contenido
Capı́tulo 6
Lectura y generación de archivos 101
1. Cómo leer un archivo de texto . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
2. I/O de datos en Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
2.1. Lectura de archivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
2.2. Guardar archivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
3. I/O veloz en Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
4. Archivos de texto plano o binarios . . . . . . . . . . . . . . . . . . . . . . . . 122
Capı́tulo 7
Gráficas de datos 125
1. Concepto de gráficas orientada a objetos . . . . . . . . . . . . . . . . . . . 127
2. Gráficas 1D/2D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
3. Gráficas 2D/3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141
Capı́tulo 8
Mapas con Cartopy y PyGMT 151
1. Cartopy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
1.1. Mapa global . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
1.2. Proyecciones esféricas y topografı́a . . . . . . . . . . . . . . . . . . 156
1.3. Mapas con fronteras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
1.4. Mapas con colores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
1.5. Rı́os y fronteras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
1.6. ¿Cómo incluir datos propios? . . . . . . . . . . . . . . . . . . . . . . 166
2. PyGMT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
2.1. Mapa global . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
2.2. Proyecciones esféricas y topografı́a . . . . . . . . . . . . . . . . . . 171
2.3. Mapas con fronteras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
2.4. Mapas con colores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
2.5. Rı́os y fronteras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
2.6. ¿Cómo incluir datos propios? . . . . . . . . . . . . . . . . . . . . . . 181
3. ¿Cuál escoger? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
iii
Contenido
Capı́tulo 9
Números complejos 187
1. Números complejos en Python . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
1.1. División de números complejos . . . . . . . . . . . . . . . . . . . . 192
1.2. Otras operaciones con complejos . . . . . . . . . . . . . . . . . . . 192
2. Arreglos de números complejos . . . . . . . . . . . . . . . . . . . . . . . . . . 194
3. Fractales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
Bibliografı́a 203
Índice 209
iv
Prefacio
¿Para qué un nuevo libro de Python? ¿Y en español? A pesar de que hay textos
disponibles, y muchos ejemplos en la web que sirven para aprender de mane-
ra individual, este libro tiene un objetivo especı́fico: es una introducción a la
programación con Python para el principiante en computación. Muchos de los
libros disponibles se concentran en las capacidades, caracterı́sticas y estruc-
tura de los códigos de Python, pero no contienen una guı́a para que el lector
aprenda cómo programar.
Este libro es a la vez una introducción a Python y una guı́a de cómo pro-
gramar. Es un libro adecuado para el geocientı́fico experto que quiere incur-
sionar en la programación, el profesional recién egresado que busca aplicar
métodos computacionales en su trabajo, o el estudiante de pregrado y posgra-
do que siente deficiencias en aspectos computacionales, y que no encuentra
cursos aplicados que puedan ser útiles en el desarrollo de sus estudios y de su
futura carrera. Hay pocas referencias con estas caracterı́sticas, y en español la
disponibilidad es aún menor. Este texto busca cubrir la demanda del público
geocientı́fico en Latinoamérica, y el gran número de estudiantes de pregrado
y posgrado en Geologı́a.
El objetivo de este libro es que sea fácilmente entendible, y que le propor-
cione al lector las herramientas básicas que requiere para poder buscar solu-
ciones a problemas numéricos en geociencias. De este modo, el libro no busca
v
Prefacio
vi
Prefacio
vii
Capı́tulo 1
Software e
instalación
Introducción a Python para geociencias
Python puede ser instalado en cualquier sistema operativo, por ejemplo, por
medio de una de las plataformas de distribución mas populares: Anaconda.
Anaconda es una distribución libre y abierta de Python y R, y funciona como
un administrador de paquetes, haciendo muy sencillo organizar, instalar y ac-
tualizar software. Anaconda contiene las librerı́as más comunes para compu-
tación cientı́fica y generación de gráficas de alta calidad, y permite la admi-
nistración de virtual environments (entornos virtuales), e incluye Jupyter Note-
books. De forma alternativa, Google ofrece Colaboratory o Colab
( colab.research.google.com), con el cual se pueden ejecutar notebooks en la nu-
be con servidores de gran potencia.
3
Software e instalación
>>> 2 + 3
5
>>>
2.1. Scripts
Una segunda opción para interactuar con Python es a través de archivos de
texto o scripts, los cuales pueden tener una serie de comandos que Python va a
leer, interpretar y ejecutar en el orden dado por el script. Este archivo puede ser
reutilizado; sin embargo, la retroalimentación de Python solo se da cuando se
ejecute el script.
Estos scripts deben ser archivos de texto plano, cuyo nombre debe terminar
con .py. No es buena idea nombrar los archivos con espacios, es preferible usar
conectores, por ejemplo un programa.py en vez de un programa.py. Para editar
4
Introducción a Python para geociencias
estos archivos, se puede usar editores de texto plano como Vi, Emacs, Gedit o
plataformas de desarrollo como Spyder, muchos incluidos en Anaconda.
Para ejecutar el programa en la terminal, utilizar:
5
Software e instalación
O, en su defecto (macs):
> jupyter-notebook
3. Instalación de paquetes
Aunque el objetivo de la Introducción a Python para geociencias es aprender a pro-
gramar en Python, y no es una introducción a paquetes especı́ficos de Python
para geociencias, sı́ es necesario el uso de paquetes adicionales de Python,
dentro de los que se incluyen los siguientes:
6
Introducción a Python para geociencias
NumPy
SciPy
Pandas
Jupyter
Matplotlib
GMT y PyGMT
Cartopy
Su instalación se puede hacer a través del Anaconda prompt. Para mayor fa-
cilidad, se incluye un archivo geopython.yml que permite la creación de un envi-
ronment de Python que contiene los paquetes necesarios para todos los ejem-
plos de este libro. Se recomienda crear estos ambientes donde se instalan los
paquetes que se van a utilizar, y que no afectan el comportamiento de otros
ambientes, ni de la instalación base de Python. En tanto, para correr la insta-
lación del environment, digitar:
En tal caso, se asume que se parte por estar situado en el fichero que con-
tiene el archivo geopython.yml, o se debe indicar la ubicación exacta del archivo.
A su vez, para activar y usar el environment, se usa:
7
Software e instalación
conda deactivate
geopython.yml
name: geopython
channels:
- conda-forge
- defaults
dependencies:
- python=3.7
- numpy
- scipy
- pandas
- ipython
- jupyterlab
- jupyter
- pip
- matplotlib
- netcdf4
- packaging
- gmt
- pygmt
- obspy=1.1
- pyasdf
- cartopy
8
Capı́tulo 2
Primeros pasos en
Python
Introducción a Python para geociencias
1. Primer programa
El primer programa que escribiremos en Python es, el clásico, ¡hola mundo!.
Para crear este script en Python, requerimos de un editor de texto plano (Vi,
Jed, Emacs, Gedit. . . elija su favorito). El archivo creado debe tener la exten-
sión .py y lo llamamos hola.py. Si está corriendo Jupyter Notebooks, lo que se
muestra a continuación debe estar dentro de una celda de código. En ambos
casos, el código contiene:
hola.py
hola1.py
¡Hola Mundo!
11
Primeros pasos en Python
"""
esto es un docstring, es documentación.
No es ejecutado por Python
"""
12
Introducción a Python para geociencias
hola3.py
# Asignar variable x
x = "¡Hola Mundo!"
# Imprimir
print(x)
hola4.py
x = "¡Hola"
y = "Mundo"
z = "!"
print(x+" "+y+z)
Cabe anotar que en este último ejemplo, realizamos una operación para pe-
gar o concatenar variables de caracteres. Con el fin de separar las palabras entre
las variables x y y, se pone un espacio. El resultado de estos dos programas
(hola3.py y hola4.py) es idéntico al primer ejemplo, hola.py.
13
Primeros pasos en Python
a = 2
b = 3
c = a*b
print(a,"x",b," = ",c)
El programa usa tres variables, las letras a, b y c. Las variables pueden te-
ner nombres largos, pero no pueden tener espacios. Si quiere unir palabras
use raya al piso, . El primer caracter de una variable debe ser una letra, el res-
to puede ser una combinación de letras, números y . No se recomienda usar
puntos o sı́mbolos de menos (-). A diferencia de Fortran o C, Python define de
manera automática si un número es entero o real, aunque si el usuario ası́ lo
prefiere, puede definir la variable como número entero:
a = int(2)
b = int(3)
14
Introducción a Python para geociencias
c = ab
real elev.py
a = 2.01
b = 3.2
c = a**b
3. For loops
Cualquier lenguaje de programación debe permitir realizar una serie de ope-
raciones de manera repetida. Esto significa permitir realizar un loop o bucle
para una serie de valores de una variable. En C o Matlab, esto se lleva a cabo
con un for loop, en Fortran se hace con un do loop. En Python se usa el for.
A continuación, un ejemplo simple para generar la tabla de multiplicar del
7 (7 × 0, 7 × 1, 7 × 2, etc.):
mult table.py
x = 7 # la tabla del 7
15
Primeros pasos en Python
7 x 0 = 0
7 x 1 = 7
...
7 x 8 = 56
7 x 9 = 63
El for loop es un comando que ejecuta una serie de comandos (que deben
estar indentados). El número de veces o la forma como los ejecuta depende
del código, a saber:
for y in range(10):
import numpy as np
x = 7 # la tabla del 7
i = np.arange(10)
16
Introducción a Python para geociencias
import numpy as np
i = np.arange(10)
La lı́nea con el comando for debe terminar con dos puntos (:).
17
Primeros pasos en Python
import math
import numpy as np
i = np.arange(90)
# Haga un loop
for ang in i:
theta = ang/180.*math.pi # transformar ángulo
ctheta = math.cos(theta)
stheta = math.sin(theta)
ttheta = math.tan(theta)
print(ang, ctheta, stheta, ttheta)
El resultado es:
0 1.0 0.0 0.0
1 0.99984769515... 0.017452406437... 0.0174550649282...
2 0.99939082701... 0.034899496702... 0.034920769491...
...
88 0.034899496702... 0.99939082701... 28.6362532829...
89 0.01745240643... 0.99984769515... 57.2899616307...
import math
18
Introducción a Python para geociencias
π
θ=α
180
Aunque el anterior resultado es correcto, la tabla que se muestra no es fácil
de leer. De tal modo, para mejorar el formato de salida del resultado, se usa el
siguiente procedimiento:
trigtable2.py
import math
import numpy as np
i = np.arange(90)
for ang in i :
theta = float(ang/180.*math.pi)
ctheta = math.cos(theta)
stheta = math.sin(theta)
ttheta = math.tan(theta)
19
Primeros pasos en Python
for ang in i :
theta = float(ang/180.*math.pi)
ctheta = math.cos(theta)
...
Esta toma sucesivamente los valores del arreglo i, es decir en cada iteración
0, 1, 2, ..., 88, 89. A partir de ese valor, se define el ángulo theta en radianes,
usando la función float. Es decir, theta asume valores sucesivos de 0.0, 1.0, 2.0,
..., 88.0, 89.0 en cada iteración, convertidos a radianes. Recomiendo siempre
realizar las iteraciones sobre un vector de números enteros (i), ya que errores
de redondeo pueden evitar que se llegue exactamente hasta 89.0.
Dentro de cada for loop, se calculan los cosenos, senos y tangentes del ángulo
theta. Por último, en cada loop se muestran los resultados:
20
Introducción a Python para geociencias
trigtable3.py
i = np.arange(90)
for ang in i :
theta = float(ang/180.*pi)
ctheta = cos(theta)
stheta = sin(theta)
ttheta = tan(theta)
# Imprima al resultado
print(fmt
%(ang, ctheta, stheta, ttheta))
En ellas, se importan todas las funciones dentro del módulo math, de tal
forma que no hay necesidad de llamarlos con math.cos, sino directamente con
cos. Además, se puede definir una variable fmt, que tiene los caracteres que de-
finen el formato de salida. Esto es útil cuando se van a utilizar comandos print
en múltiples casos dentro de un programa. El módulo math tiene guardado el
valor de π en la variable pi.
21
Primeros pasos en Python
pi valor de pi=3.14159265...
e valor de la constante e=2.718281...
tau valor de 2*pi, tau=6.2831...
22
Introducción a Python para geociencias
5. Sobre formatos
Python permite desplegar en la terminal los números y caracteres en diferen-
tes formatos. Acá algunos ejemplos útiles:
Problemas
1. Escriba un programa de Python que imprima una frase célebre.
x sinh(x) cosh(x)
23
Primeros pasos en Python
4. Genere una tabla de multiplicar para los números del 1 al 9, es decir, 1x1,
1x2, ..., 1x10, la siguiente lı́nea, 2x1, 2x2, 2x10, y ası́ hasta el 9.
i = 0, xi = 1.01
i = 1, xi = xi−1 (i + 1)
i = 2, ···
24
Capı́tulo 3
Interacción con
Python
Introducción a Python para geociencias
Hasta el momento, todos los ejemplos han sido de programas que no requieren
o solicitan información del usuario. Aquello impone la limitación de que el
programa es estático, y siempre se va a comportar de la misma manera. Por
ejemplo, el programa multint.py (sección 2) siempre dará como resultado 6, y
si queremos hacer una multiplicación diferente, es necesario escribir un nuevo
programa.
27
Interacción con Python
c = a*b
print(a,"x",b," = ",c)
28
Introducción a Python para geociencias
Este código tiene dos llamadas para pedirle al usuario que digite los núme-
ros a multiplicar. También es importante notar lo que sucede al poner el si-
guiente código:
29
Interacción con Python
usuariomult2.py
c = a*b
print(a,"x",b," = ",c)
El ejemplo anterior muestra que el comando input permite digitar una se-
rie de caracteres. Si esos caracteres están separados por espacios, se pueden
asignar a múltiples variables con el comando intxt.split(). Sin embargo, si el
usuario digita tres números (en vez de dos), se genera un error. ¿Puede el lec-
tor pensar en alguna alternativa para evitar este error?
30
Introducción a Python para geociencias
for i in range(1000):
intxt = input(’Digite dos enteros (0 0 para) ’)
a,b = intxt.split()
a = int(a)
b = int(b)
if (a==0 and b==0):
break
c = a*b
print(a,"x",b," = ",c)
Este código puede no ser el mas óptimo. Python no permite hacer loops de
manera indefinida (un infinito número de veces), ası́ que debemos indicar que
lo haga en un rango definido (hasta 1000 veces en nuestro ejemplo). Sin em-
bargo, no serı́a muy práctico que el usuario tuviera que hacer la operación mil
veces para que el programa termine. Por esa razón, existen los condiciona-
les, de modo que al cumplirse cierta condición (que ambos números sean 0
31
Interacción con Python
en nuestro ejemplo), el programa hace un break que le ordena salir del for loop.
Cabe destacar que el código dentro del loop está indentado.
El programa le seguirá pidiendo al usuario los dos números, e imprimien-
do el resultado, hasta que el usuario lo detenga. Para detener el programa, los
dos números deben ser cero (0), como es evaluado con el siguiente condicional:
.eq. == == == == es igual
.ne. /= != ~= != no es igual
.or. .or. || | or o
32
Introducción a Python para geociencias
En Python, el for loop procesa cada elemento dentro de una secuencia, ası́
que puede ser usado en cualquier secuencia de datos de diferente tipo (arreglos,
strings, listas, tuples, etc.). A la variable del loop (i, en este ejemplo) se le asigna
en cada iteración el valor correspondiente, y el cuerpo (indentado) dentro del
loop es ejecutado. La forma general de un for loop en Python es la siguiente:
Debe anotarse que los comandos tienen un encabezado (header) que termi-
na con dos puntos (:), y un cuerpo con una serie de comandos indentados. La
indentación puede ser de uno, dos, o cualquier número de espacios, pero estos
siempre deben tener la misma longitud.
Asimismo, en lenguajes modernos, se tiene la opción de utilizar un while
loop, en lugar de un for loop. El while es un comando compuesto que tiene un
encabezado y un cuerpo, con el siguiente formato general:
while expresión_lógica:
Comandos a ejecutar
a=None
b=None
while (a!=0 or b!=0):
intxt = input(’Digite dos enteros (0 0 termina) ’)
a,b = intxt.split()
a = int(a)
b = int(b)
33
Interacción con Python
c = a*b
print(a,"x",b," = ",c)
Cabe señalar que, para iniciar el while loop, es necesario tener definidas las
variables a y b, para que el programa pueda realizar la verificación del condi-
cional la primera vez.
El primer caso se conoce como una iteración definida, mientras que el segun-
do caso es conocido como iteración indefinida, ya que no sabemos de antemano
cuántas iteraciones son requeridas.
34
Introducción a Python para geociencias
if (expresión_lógica):
(bloque de código)
elif (expresión_lógica):
(bloque de código)
elif (expresión_lógica):
(bloque de código)
...
else:
(bloque de código)
Cada bloque de código puede tener tantas lı́neas y comandos como se re-
quiera. Además, puede haber tantos bloques de condiciones elif (else if) como
se requiera, y máximo un else. Cuando una condición se cumple, ese bloque
de código se ejecuta, sin seguir mirando las otras condiciones posteriores. Es
decir, el orden de los condicionales importa (Python no revisa lo que sigue). El
último else será ejecutado si ninguna condición anterior es verdadera.
El siguiente programa muestra un ejemplo en el que el usuario debe adi-
vinar un número entre 1 y 999, y el programa le informa en cada intento si el
número introducido por el usuario es mayor o menor que el número que se
busca. Adicionalmente, se cuenta el número total de intentos del usuario.
adivine entero.py
import numpy as np
35
Interacción con Python
number = np.random.randint(1,1000)
# Empiece el juego
guess = int(input(’Adivine número del 1 al 999: ’))
guesses = 1
36
Introducción a Python para geociencias
85 es muy bajo
Adivine otra vez: 88
88 es muy alto
Adivine otra vez: 87
x = None
while (x!=0.0):
x = float(input("Digite un número real y positivo "))
if (x<0.0):
print("Número negativo")
continue
else:
y = np.sqrt(x)
print(’sqrt(’,x,’) = ’,y)
37
Interacción con Python
La tarea es buscar entre todos los valores posibles, cuáles son un común
divisor y cuál de estos es el mayor.
38
Introducción a Python para geociencias
gcf.py
a = None
b = None
while (a!=0 or b!=0):
txt = input(’Digite dos enteros (0 0 termina)’)
a,b = txt.split()
a = int(a)
b = int(b)
amin = min(a,b)
if (amin<1):
print(’Sólo se aceptan números > 0’)
break
mcd = 1
for j in range(2,amin+1):
if (a%j==0 and b%j==0):
mcd = j
39
Interacción con Python
Vale la pena destacar que este programa no es muy eficiente si los núme-
ros investigados son muy grandes, pero funciona muy bien para números pe-
queños. Algunas cosas nuevas en este programa son:
Problemas
1. Modifique el programa gfc.py para calcular el mı́nimo común múltiplo
(least common multiple en inglés) de dos números enteros.
40
Introducción a Python para geociencias
a ∗ x2 + b ∗ x + c = 0,
rand ej.py
for i in range(20):
a = np.random.random()
print (a)
41
Interacción con Python
0 1009
1 1048
2 1001
3 1038
4 1008
5 959
6 993
7 925
8 1017
9 1002
42
Introducción a Python para geociencias
Tcrust = 25
Tmantle = 2900
Tocore = 2250
Ticore = 1196
P =g∗ρ∗h
43
Capı́tulo 4
Funciones del
usuario
Introducción a Python para geociencias
Es más fácil usar partes del programa en otros programas (sin necesidad
de tener múltiples copias del mismo código).
def guess_number(number):
""" Función para adivinar un número
Función que hace el trabajo de interactuar
con el usuario y evaluar si adivinó el número.
Entrada: number - entero, que el usuario no conoce
47
Funciones del usuario
guess = int(input(’Adivine un
número: 1 al 999: ’))
while guess!=number:
guesses = guesses + 1
if (guess>number):
print(guess," es muy alto")
elif (guess<number):
print(guess," es muy bajo")
guess = int(input("Adivine otra vez: "))
return guesses
#-------------------------------------
# El programa principal
#-------------------------------------
import numpy as np
48
Introducción a Python para geociencias
def guess_number(number):
...
return guesses
nguess = guess_number(rnum)
49
Funciones del usuario
El ejercicio del máximo común divisor (MCD) se puede separar en dos partes.
La primera está encargada de la interacción con el usuario (pedirle los núme-
ros, etc.). La segunda, de calcular el MCD. La última la podemos poner como
una función.
gcf2.py
Observe que, en este caso, se define la función para calcular el MCD que
recibe dos números de entrada (x,y), y devuelve al programa la variable mcd.
50
Introducción a Python para geociencias
def gcf(x,y):
...
return mcd
def sph_azi(flat1,flon1,flat2,flon2):
"""
SPH_AZI computes distance and azimuth between
2 points on the sphere
51
Funciones del usuario
Notes:
(1) applies to geocentric not geographic lat,lon
on Earth
(2) This routine is accurate depending on the
precision of the real numbers used. Python
should be accurate to real(8) precision. For
greater accuracy, perform a separate calculation
for close ranges using Cartesian geometry.
"""
# Perform calculation
delta = 0.
azi = 0.
52
Introducción a Python para geociencias
raddeg=mt.pi/180.
theta1=(90.-flat1)*raddeg
theta2=(90.-flat2)*raddeg
phi1=flon1*raddeg
phi2=flon2*raddeg
stheta1=mt.sin(theta1)
stheta2=mt.sin(theta2)
ctheta1=mt.cos(theta1)
ctheta2=mt.cos(theta2)
cang=stheta1*stheta2*mt.cos(phi2-phi1)+
ctheta1*ctheta2
ang=mt.acos(cang)
delta=ang/raddeg
sang = mt.sqrt(1.-cang*cang)
caz = (ctheta2-ctheta1*cang)/(sang*stheta1)
saz = -stheta2*mt.sin(phi1-phi2)/sang
az = mt.atan2(saz,caz)
azi = az/raddeg
#------------------------------------------------
# Programa principal
#------------------------------------------------
53
Funciones del usuario
lat1 = None
lon1 = None
lat2 = None
lon2 = None
while (lat1!=0. or lon1!=0. or lat2!=0. or lon2!=0.):
intxt = input(’Digite lat/lon del primer punto ’)
lat1,lon1 = intxt.split()
lat1 = float(lat1)
lon1 = float(lon1)
delta,azi = sph_azi(lat1,lon1,lat2,lon2)
print(’Distancia y acimut: %6.2f %7.2f ’
%(delta, azi))
54
Introducción a Python para geociencias
En este caso, los valores de lat/lon son pasados a la función sph azi, la cual
devuelve las variables delta y azi. Es importante siempre poner nombres a las
funciones que sean claros, y que no repitan nombres de rutinas o variables ya
existentes en Python.
También es esencial siempre documentar de forma clara lo que hace ca-
da función, explicando las variables de entrada y de salida, y si la rutina tiene
problemas de precisión, o cualquier otro potencial problema o limitación. Asi-
mismo, aunque lo que se muestra para la función como documentación parece
ser demasiada información, tenga en cuenta que en el futuro cualquier usua-
rio va a tener una gran cantidad de funciones que puede utilizar, y es impor-
tante entender claramente qué hace cada función, y cómo se llama desde un
programa. Esto puede ahorrarle al usuario mucho tiempo en el futuro.
De igual modo, la documentación busca además que el usuario o cualquier
otra persona pueda utilizar la función sin necesidad de mirar el código. Por
ejemplo, es claro que el azimuth es calculado desde el punto 1 al punto 2, y no
al contrario.
Además, explicar las limitaciones de la función puede evitar que se use de
manera errónea. En distancias muy cortas, el programa puede tener limitacio-
nes, y devuelve un resultado que no es correcto, y el usuario puede no entender
esto. La documentación advierte que otra función deberá ser usada.
Por último, note que la función busca ser robusta en casos particulares, co-
mo en cuanto a que los dos puntos tengan las mismas coordenadas (distancia
y azimuth es cero), o estén en los polos.
55
Funciones del usuario
import numpy as np
def kepler_3ra(a,M=1.98847e30):
"""
Función que usa la expresión de la 3ra ley de
Kepler, para calcular el periodo para completar
una órbita.
Entradas:
a - distancia en km del satélite con respecto
al centro del cuerpo (planeta, Sol, etc)
M - Masa del cuerpo (default - Masa del Sol)
Salidas:
T - Periodo para completar una órbita, en
segundos
"""
import numpy as np
G = 6.67430e-11 # m^3kg^-1s^-2
56
Introducción a Python para geociencias
a_m = a * 1000.0 # in m
return T
def kepler_3ra(a,M=1.98847e30):
kepler_3ra(a,M):
o
kepler_3ra(a):
import kepler
57
Funciones del usuario
T_days = T_earth/86400
58
Introducción a Python para geociencias
Con este, se importan de manera directa las funciones del módulo math,
como el coseno y el seno (ver ejemplos en el capı́tulo anterior). Esto es consi-
derado una mala práctica en Python. Usar el comando import *, hace que en-
tender el código y saber a qué módulo pertenece una función sea más difı́cil.
Lo descrito no sucede con un comando como el siguiente:
59
Funciones del usuario
En este caso, ¿pertenece la función sqrt a modu? ¿O hace parte de las fun-
ciones propias de Python? ¿O tal vez la definió antes? El siguiente ejemplo es
mejor, aunque no ideal para la importación:
import modu
x = modu.sqrt(4) # sqrt es de modu
60
Introducción a Python para geociencias
equivale a evitar exceso de texto o llenar espacio con comandos sin separa-
ción, pero eso tampoco significa que se deba llegar al extremo de oscurecer el
código.
import pack.modu
61
Funciones del usuario
código (recuerde que Python ejecuta código lı́nea por linea; por consiguiente,
el orden en el que se importan los módulos importa).
Finalmente, es relevante el procedimiento adecuado para evitar tener códi-
gos muy cargados de texto. Por ejemplo, si se quiere importar un módulo que
se encuentra en un árbol de directorios complejo:
import pack1.subpack2.subsubpack3.modu
[...]
x = pack1.subpack2.subsubpack3.modu.sin(x)
En este caso, para usar la función sin, se requiere mucho texto, lo cual hace
el código difı́cil de leer. Una mejor opción es nombrar las funciones dentro de
un módulo con un emcabezado más corto o apodo (mod), como se muestra en
el siguiente caso:
import sys
[...]
print(sys.path)
62
Introducción a Python para geociencias
>>> [’’,
’/opt/local/.../lib/python35.zip’,
’/opt/local/.../lib/python3.5’,
’/opt/local/.../lib/python3.5/plat-darwin’,
’/opt/local/.../lib/python3.5/lib-dynload’,
’/opt/local/.../lib/python3.5/site-packages’]
import sys
sys.path.append(’/path/to/dir’)
print(sys.path)
>>> [’’,
’/opt/local/.../lib/python35.zip’,
’/opt/local/.../lib/python3.5’,
[...]
’/opt/local/.../lib/python3.5/site-packages’
’/path/to/dir’]
Sin embargo, esta opción solo altera el path durante la ejecución del pro-
grama. La próxima vez que Python sea ejecutado, el path vuelve a su default.
Para adicionar el folder de manera permanente en el path, se debe adicionar
la dirección del folder al PYTHONPATH. En sistemas operativos OS y Linux,
esta adición se hace en el archivo .bashrc, ası́:
63
Funciones del usuario
export PYTHONPATH="${PYTHONPATH}:/my/other/path"
4.0.1. Windows
En ambiente Windows, para adicionar un folder al path, se requiere iniciar el
Anaconda Prompt. Primero, es necesario saber si el entorno ya tiene definido el
PYTHONPATH. Esto se puede ver digitando lo siguiente:
> set
64
Introducción a Python para geociencias
Problemas
1. Modifique el programa del problema 6 para calcular la presión litosféri-
ca, con una función propia dentro del programa.
3. Cree una función propia (dentro de su package propio o dentro del pro-
grama) en Python, la cual calcule el volumen y la circunferencia de una
esfera, si el usuario proporciona el radio. Haga un programa principal
que le solicite el radio al usuario, y haga que este sea estable, que no
acepte números negativos, y que imprima el resultado.
65
Capı́tulo 5
Arreglos: vectores
y matrices
Introducción a Python para geociencias
list, como su nombre lo indica, es una lista de valores. Cada valor está numera-
do, empezando en cero; el primer valor está en la posición 0, el segundo
en la posición 1, etc. Se pueden remover valores de una lista, adicionar
valores a la lista, etc. Además, los valores dentro de una lista pueden ser
de diferente tipo; por ejemplo, números y palabras.
tuples, que son similares a las listas, pero no se puede cambiar su valor. Los
valores que se les ponen a los tuples no pueden ser cambiados dentro del
programa. En tanto, la numeración es igual a la de las listas, empezando
en cero. Un posible uso corresponde a los nombres de los meses del año,
que no cambiarán.
69
Arreglos: vectores y matrices
listas, pero solo aceptan un tipo de entrada (números enteros, reales, o com-
plejos, por ejemplo). Ası́, para la creación y el manejo de estos arreglos, vamos
a utilizar los módulos de NumPy, que se importan a través de:
import numpy as np
1. Arreglos numéricos
Vamos a crear los arreglos numéricos en Python con los módulos de NumPy,
un paquete para análisis numérico.
import numpy as np
a = np.array([1, 2, 3, 4, 5])
print(a)
[1 2 3 4 5]
a[0]
a[4]
1
5
70
Introducción a Python para geociencias
71
Arreglos: vectores y matrices
99 0 98
100 0 99
72
Introducción a Python para geociencias
ccccv
8 1 7
9 1 8
...
99 1 98
100 1 99
primos.py
import numpy as np
maxnum = 100
prime = np.zeros(maxnum)
prime[0] = 1 # el 1 no es primo
maxi = int(np.floor(np.sqrt(maxnum)))
for ipos in range(1,maxi):
if (prime[ipos]==0):
inum = ipos+1. # 2, 3, 4, ...
maxj = int(np.floor(maxnum/inum))
for j in range(2,maxj+1):
imult = inum*j # x2, x3, x4
prime[imult-1] = 1 # posición, i-1
nprime = 0
for ipos in range(maxnum):
if (prime[ipos]==0):
73
Arreglos: vectores y matrices
nprime += 1
print("%4i" %(ipos+1))
2
3
5
...
89
97
# primos encontrados 25
Explicación
El programa comienza definiendo un arreglo prime lleno de ceros:
maxnum = 100
prime = np.zeros(maxnum)
prime[0] = 1
El siguiente paso busca eliminar los números que no sean primos, usando
dos loops. El primer loop evalúa la posición en el arreglo prime; si es 0, entonces
dicha posición representa un número primo, ası́:
74
Introducción a Python para geociencias
elimina todos sus múltiplos (inum x 2, inum x 3, ...), asignando a la posición del
arreglo prime el valor de 1, ası́:
for j in range(2,maxj+1):
imult = inum*j
prime[imult-1] = 1
Cabe mencionar que los múltiplos se calculan con inum*j, pero su posición
es imult-1, porque Python comienza a contar desde j=0. Es importante anotar
además que solo se requiere evaluar todos los números hasta 10 (la raı́z cua-
drada de 100), porque los factores más grandes ya han sido eliminados. Las va-
riables maxi y maxj se definen para no tener posiciones mayores a maxnum=100
en este caso.
Cuando el programa termina de revisar los números hasta el 100, imprime
el número de la posición en el arreglo prime que continúe siendo 0:
Podemos contar los espacios que tienen 0 (total de primos entre 2 y 100), y
además podemos saber qué números son primos (por su posición).
El programa anterior imprime cada número primo en una lı́nea, lo cual hace
que el resultado sea muy largo si queremos más números primos (podemos
imaginar lo que sucederı́a si resulta haber 1000 primos).
En ese sentido, la siguiente función (definición) retoma el código primos.py,
pero busca los números primos, y devuelve únicamente los números primos
encontrados en un arreglo. De esa manera, no imprime los resultados, solo re-
torna un arreglo con los números primos y el número total de números primos.
El despliegue de los resultados debe ejecutarse en otro paso, con la ventaja de
saber de antemano el número total de primos encontrados.
75
Arreglos: vectores y matrices
primos subs.py
def primos_vector(maxnum):
"""
prime_vector(maxnum)
Función que busca números primos entre 2 y maxnum,
y los ubica en un arreglo. El programa es muy lento
si se buscan primos muy grandes.
Entradas:
maxnum - entero, buscar hasta maxnum
Salidas:
pvec - vector con números primos, en orden
nprime - primos encontrados
"""
import numpy as np
prime = np.zeros(maxnum,dtype=int)
prime[0] = 1
max1 = int(np.floor(np.sqrt(maxnum)))
for ipos in range(1,max1):
if (prime[ipos]==0):
inum = ipos+1
max2 = int(np.floor(maxnum/inum))
for j in range(2,max2+1):
imult = inum*j
prime[imult-1] = 1
76
Introducción a Python para geociencias
pcnt = 0
for ipos in range(maxnum):
if (prime[ipos]==0):
pcnt = pcnt + 1
inum = ipos + 1
pvec[pcnt-1] = inum
return pvec,nprime
primes,nprime = primos_vector(1000)
print ("# primos encontrados ", nprime)
print (primes)
[ 2 3 ... 59 61
67 71 ... 149 151
...
829 839 ... 947 953
967 971 ... 991 997]
77
Arreglos: vectores y matrices
primos3.py
primes,nprime = primos_vector(1000)
print ("# primos encontrados ", nprime)
nprint = 0
for i in range(1,nprime):
nprint = nprint + 1
if (nprint%10==0 ):
print ("%4i" % (primes[i]))
else:
print ("%4i" % (primes[i]),end="")
print(’’)
En tal caso, el comando hace lo mismo que el comando print, pero no genera
un salto de lı́nea. El código revisa si ya se han desplegado 10 números primos
(con el contador nprint), y permite que haya un salto de lı́nea.
78
Introducción a Python para geociencias
1.2. Arreglos 1D
Los valores de un arreglo se pueden asignar uno a la vez, o todos a la vez, con
comandos sencillos, como en el siguiente programa:
testarreglos.py
import numpy as np
Se da el siguiente resultado:
x = [1 2 3]
y = [1. 1. 1.]
79
Arreglos: vectores y matrices
z = [2. 2. 2.]
x = [ 1 15 3]
y = [2. 2. 2.]
z = [1. 1. 1.]
1.3. Arreglos 2D
Python puede generar arreglos en 2 dimensiones (o más) utilizando NumPy. A
continuación, se presenta un programa que muestra algunas caracterı́sticas
de arreglos en 2D:
testmatriz.py
import numpy as np
y = np.empty([2, 3])
print(’Empty Y, float ’)
print(y)
x = np.zeros([2,3],dtype=int)
print(’Zeros X enteros’)
print(x)
x[0,:] = [1, 2, 3]
80
Introducción a Python para geociencias
x[1,:] = [4, 5, 6]
print(’X unidades’)
print (x)
x = x + 1
print(’X mas 1’)
print(x)
Empty Y
[[4.9e-324 9.9e-324 1.5e-323]
[2.0e-323 2.5e-323 3.0e-323]]
Zeros X
[[0 0 0]
[0 0 0]]
X unidades
[[1 2 3]
[4 5 6]]
X mas 1
[[2 3 4]
[5 6 7]]
Matriz compleja
[[1.+0.j 2.+0.j]
[3.+0.j 4.+0.j]]
81
Arreglos: vectores y matrices
import numpy as np
c = a + 1
print("a + 1 = ", c)
c = 2 * a
print("2 * a = ", c)
c = a * a
print("a * a = ", c)
print(’’)
c = np.sqrt(a)
print("sqrt(a) = ", c)
c = np.sin(a)
print("sin(a) = ", c)
c = np.exp(a)
82
Introducción a Python para geociencias
print("exp(a) = ", c)
print(’’)
print("a = ", a)
print("b = ", b)
c = a + b
print("a + b = ", c)
c = a * b
print("a * b = ", c)
print(’’)
x = np.sum(a)
print("sum(a) = ", x)
c = a
c[3:5] = 0.0
print ("a con dos ceros al final", c )
x = np.dot(a,b)
print ("a dot b = ", x)
print(’\nMedia Cuadrática’)
rms = np.sqrt(np.sum((a-np.sum(a))**2)/len(a))
print ("rms = %6.2f " %(rms))
83
Arreglos: vectores y matrices
a = [1. 2. 3. 4. 5.]
a + 1 = [2. 3. 4. 5. 6.]
2 * a = [ 2. 4. 6. 8. 10.]
a * a = [ 1. 4. 9. 16. 25.]
a = [1. 2. 3. 4. 5.]
b = [2. 2. 2. 2. 2.]
a + b = [3. 4. 5. 6. 7.]
a * b = [ 2. 4. 6. 8. 10.]
sum(a) = 15.0
a con dos ceros al final [1. 2. 3. 0. 0.]
a dot b = 12.0
Media Cuadrática
RMS = 4.94
matrixmath.py
import numpy as np
b = np.empty( [3,2])
b[:, 0] = [9.4, -6.2, 0.5 ]
84
Introducción a Python para geociencias
print("Matrix a")
print(a)
print("Matrix b")
print(b)
c = np.matmul(a, b)
print ("matmul(a,b)")
print (c)
c = np.matmul(b,a)
print ("matmul(b,a)")
print (c)
c = a + np.transpose(b)
print("Matrix a + transpose(b)")
print(c)
85
Arreglos: vectores y matrices
Matrix a
[[-5.1 3.8 4.2]
[ 9.7 1.3 -1.3]]
Matrix b
[[ 9.4 -5.1]
[-6.2 3.3]
[ 0.5 -2.2]]
matmul(a,b)
[[-69.4 29.31]
[ 82.47 -42.32]]
matmul(b,a)
[[-97.41 29.09 46.11]
[ 63.63 -19.27 -30.33]
[-23.89 -0.96 4.96]]
Valor max de a 9.7
Posición del max of a (1, 0)
Max(a) con su posición 9.7
Matrix a + transpose(b)
[[ 4.3 -2.4 4.7]
[ 4.6 4.6 -3.5]]
a shape (2, 3)
b shape (3, 2)
a size 6
b size 6
86
Introducción a Python para geociencias
x2,xsum = analisis(x,n)
def arr_trab(x):
"""
Función para análisis de unos datos en vector
Input: x = array of given size, with numbers
n = size of the array
87
Arreglos: vectores y matrices
n = np.size(x)
x_mu = np.mean(x)
y = x-x_mu
y_var = np.var(y)
return y,x_mu,y_var
array2fun.py
import numpy as np
mu = 25
sigma = 3.0
a = np.random.normal(mu,sigma,5)
n = np.size(a)
print(’Arreglo original ’)
print (a)
[b,x_mean,x_var] = arr_trab(a)
88
Introducción a Python para geociencias
Arreglo original
[26.73 27.62 30.35 25.50 24.22]
Arreglo corregido (demeaned)
[-0.14 0.73 3.46385312 -1.38 -2.66]
Prom(x) = 26.88
Var(x) = 4.31
L = V T,
1
F = V E = ρgh2 V,
8
89
Arreglos: vectores y matrices
import numpy as np
g = 9.8 # m/s^2
depth = 5000 # m
T = 1800 # s, 30 min
h = 1 # m wave height
rho = 1 # kg/m3
V = np.sqrt(g*depth)
L = V*T
print(’Para un tsunami’)
print(’ Prof. del océano = %4.1f m’ %depth)
print(’ Periodo = %4.1f min’ %(T/60))
print(’ Altura Ola (h) = %4.1f m’ %(h))
print(’’)
90
Introducción a Python para geociencias
depth = np.array((2000,1000,500,100,50,25,10))
V = np.sqrt(g*depth)
L = V*T
h = np.sqrt(8*F/(V * rho * g))
ndep = len(depth)
print(’’)
print(’Prof(m) V(km/s) L(km) h(m)’)
for i in range(ndep):
print(’ %4i %5.1f %5.1f %5.1f’
%(depth[i],V[i]/1000*3600,L[i]/1000,h[i]))
Para un tsunami
Prof. del océano = 5000.0 m
Periodo = 30.0 min
Altura Ola (h) = 1.0 m
91
Arreglos: vectores y matrices
a = "¡Hola Mundo!"
b = "Python"
Cabe señalar que todo lo que esté entre comillas va a pertenecer al string,
incluidos los espacios en blanco. Para determinar el número de caracteres en
un string, utilizamos el siguiente procedimiento:
len(a)
len(b)
a[0] = ’¡’
a[0:5] = ’¡Hola’
b[0:6] = ’Python’
a[0:6]+b = ’¡Hola Python’
92
Introducción a Python para geociencias
a[0:5] = ’¡Holo’
>>> TypeError: ’str’ object does not support ...
char oper.py
a = "¡Hola Mundo!"
b = "Python"
c = a[0:6] + b # concatenation
print(c)
c = b*2 # Repetition
print(c)
# Find characters
i = a.find("ello")
print (i)
# Remove blanks
c = " "+a+b+" "
print(c)
d = c.strip()
print(d)
93
Arreglos: vectores y matrices
if (a.find("onal")>-1 or a.find("ich")>-1
or a.find("rist")>-1):
print("El portugués me gusta pero, y ¿Pelé?")
elif (a.find("Leo")>-1 or a.find("essi")>-1):
print("Lo único que le falta es el Mundial")
elif (a.find("arad")>-1 or a.find("iego")>-1 or
a.find("rmand")>-1 or a.find("elus")>-1):
print("De acuerdo, el de la Mano de Dios")
else:
print("Claro, Pelé siempre será el mejor")
94
Introducción a Python para geociencias
lista caracter.py
# lista_char.py
# Uso de listas de strings de caracteres
lista.append("Plutón")
Otras funciones sobre listas incluyen list.remove() y list.pop() para retirar ele-
mentos, o list.sort(), list.reverse() para reordenarlos, entre muchos más.
95
Arreglos: vectores y matrices
Problemas
2x2 matrix
[[ 2. 3.]
[ 7. 5.]]
3x3 matrix
[[ 17. 19. 23.]
[ 13. 2. 3.]
[ 11. 7. 5.]]
4x4 matrix
[[ 17. 19. 23. 29.]
[ 13. 2. 3. 31.]
[ 11. 7. 5. 37.]
[ 53. 47. 43. 41.]]
96
Introducción a Python para geociencias
qsort.py
def quicksort(arr_in):
"""
Función que realiza un quicksort
Entradas
arr_in - arreglo con números, no organizado
Salidas:
arr - arreglo, pero organizado
"""
import numpy as np
if (arr_in.ndim>1):
print("Arreglo con dimensiones erradas")
return None
for j in range(2,n+1):
ibreak = 0
A = arr[j-1]
for i in range(j-1,0,-1):
if (arr[i-1] <= A):
arr[i] = A
ibreak = 1
break
arr[i]=arr[i-1]
if (ibreak==0):
arr[0] = A
return arr
97
Arreglos: vectores y matrices
C = np.random.normal(0,1,51)
Por convención, los ejes principales están organizados de tal forma que
Ası́, buscamos obtener (lo más cercano posible a) un tensor τ R con los
esfuerzos de cizalla τxy = τyx = 0. Para rotar el tensor un ángulo α
debe realizar la operación matricial:
τ R = Rτ RT ,
98
Introducción a Python para geociencias
donde " #
cos(α) − sin(α)
R=
sin(α) cos(α)
99
Capı́tulo 6
Lectura y
generación de
archivos
Introducción a Python para geociencias
Hasta ahora, todos los ejemplos en el libro usan entradas del usuario con el
teclado, y, como salida, se despliega en pantalla el resultado. Esto es útil pa-
ra trabajos pequeños, pero cuando se quiere analizar grandes cantidades de
datos, es relevante poder importarlos a Python. Estos datos pueden estar en
tablas de Excel, de Matlab, o en archivos de texto plano (ASCII), o pueden pro-
venir de un equipo de campo o del laboratorio. En este capı́tulo, se busca en-
tender cómo abrir, leer y escribir series de datos. Python tiene paquetes para
leer datos de varias fuentes, incluyendo Excel, Matlab y otros, pero para el ob-
jetivo de este libro, solo nos concentraremos en leer archivos de texto plano.
Tengamos en cuenta que tanto Matlab como excel pueden exportar los datos
en dicho formato.
fname = ’test_file.dat’
103
Lectura y generación de archivos
# lectura completa
print(’Lectura de archivo: en una variable’)
f = open(fname, ’r’)
text = f.read()
print(text)
f = open(fname, ’r’)
104
Introducción a Python para geociencias
sobrescrito), mientras ’a’ adiciona al archivo al final, y ’r+’ abre el archivo para
leer y escribir. Para archivos binarios, se usa ’b’. El modo de lectura es opcional;
si no se utiliza, Python asume ’r’.
En la primera forma de lectura, el archivo se lee de manera secuencial (lı́nea
por lı́nea) con el siguiente procedimiento:
for line in f:
print(line, end=’’)
Ası́, se imprime cada lı́nea. Python lee el archivo lı́nea por lı́nea, hasta llegar
a la última, y se detiene el for loop.
En el segundo tipo de lectura del archivo, se lee el archivo completo, y cada
lı́nea se pone en un elemento de una lista.
f_list = list(f)
text = f.read()
print(text)
105
Lectura y generación de archivos
La primera lı́nea
La 2da lı́nea
Es la tercera
Cuarta lı́nea
106
Introducción a Python para geociencias
read data.py
import numpy as np
...
# Figura de columnas 1 vs 2, 1, vs 3
...
107
Lectura y generación de archivos
Arriba, se le ordena a loadtxt leer los datos como floats, como números reales.
En tanto, lı́neas con comentarios se marcan como #, y no son leı́das, a la vez que
las columnas están separadas por comas (tı́pico de archivos .csv), se salta una
lı́nea que puede ser el encabezado, y solo se leen la primera y tercera columna.
Cabe anotar que todos los comandos a excepción del nombre del archivo, son
opcionales, y Python tiene valores predeterminados para las variables opcio-
nales. Por ejemplo, las columnas por defecto están separadas por espacios, y
los valores se asumen como float.
108
Introducción a Python para geociencias
En este caso, la lectura del archivo se puede llevar a cabo saltando el encabe-
zado, como se muestra a continuación:
read data2.py
import numpy as np
# Cargar datos
data = np.loadtxt(fname,skiprows=1)
y = data[:, 2]/data[:,1]
# Figura
...
Hay archivos más complejos cuya lectura requiere mayor trabajo. Un ejem-
plo es un archivo que contiene los identificadores de las estaciones de la Red
Sismológica Nacional de Colombia (RSNC), incluyendo latitudes, longitudes
y elevaciones (se puede consultar en sgc.gov). Dicho archivo tiene el siguiente
formato:
109
Lectura y generación de archivos
En este ejemplo, las diferentes columnas están separadas por espacios (el
número de espacios puede variar).
NumPy tiene una función que en principio puede leer este tipo de archi-
vos np.genfromtxt(). Sin embargo, aquı́ presentamos el paquete Pandas. Este
paquete tiene la capacidad de leer archivos planos, mixtos (caracteres y núme-
ros), e incluso archivos de Excel y Matlab. A continuación, un ejemplo de cómo
leer el archivo anterior:
110
Introducción a Python para geociencias
read stations.py
import numpy as np
import pandas as pd
fname = ’data/rsnc.dat’
data = pd.read_csv(fname, delim_whitespace=True,
header=None)
print(’Estructura de Pandas’)
print(data)
sta = data.iloc[:,0].to_numpy()
lat = data.iloc[:,1].to_numpy()
lon = np.array(data[2])
Estructura de Pandas
0 1 2 3
0 APAC 7.900 -76.580 195.0
1 ARGC 9.585 -74.246 117.9
2 BBAC 2.022 -77.247 1716.0
.. ... ... ... ...
66 YOT 3.983 -76.345 1059.0
67 ZAR 7.492 -74.858 200.0
[68 rows x 4 columns]
111
Lectura y generación de archivos
sta = data.iloc[:,0].to_numpy()
lat = data.iloc[:,1].to_numpy()
lon = np.array(data[2])
112
Introducción a Python para geociencias
import pandas as pd
De este modo, se le indica al código que no hay encabezado, y que los sepa-
radores entre columnas están marcados por espacios libres (pueden ser tabs,
comas, etc.). Lo curioso de Pandas es que tiene su propia estructura (llamada
DataFrame), que es una especie de arreglo, pero que puede tener diferentes ti-
pos de elementos (str, int, float, etc.).
113
Lectura y generación de archivos
Guardar un nuevo archivo test.dat con las dos columnas originales, y una
tercera columna con el producto.
import numpy as np
fin = ’data/another_data.dat’
fout = ’dout/test.dat’
data = np.loadtxt(fin)
114
Introducción a Python para geociencias
En este caso, la variable fin es el nombre del archivo que se quiere abrir.
Si el archivo no existe, Python generará un error. Posteriormente, los valores
dentro del archivo son leı́dos con el siguiente comando:
data = np.loadtxt(fin)
x = data[:,0][:,None]
y = data[:,1][:,None]
M = np.hstack((x,y,z))
print(’Tama~
no arreglos X, Y, X*Y’)
print(np.shape(x), np.shape(y), np.shape(z))
print(’Tama~
no arreglo M’)
print(np.shape(M))
Y se obtiene:
Tama~
no arreglos X, Y y X*Y
(21, 1) (21, 1) (21,1)
Tama~
no arreglo M
(21, 3)
115
Lectura y generación de archivos
np.savetxt(fout, data_out,fmt="%5.2f")
Entrada
3.6809 -1.6855
3.4113 -2.5989
...
6.6905 -3.0042
Salida
3.6809 -1.6855 -6.2042
3.4113 -2.5989 -8.8656
...
6.6905 -3.0042 -20.0996
116
Introducción a Python para geociencias
es con los códigos hasta ahora descritos, o utilizando otro tipo de formatos
binario, como muestra el programa testio.py. El programa, además, vuelve a
leer los archivos, e imprime el tiempo que demora realizando dicha operación.
testio.py
import numpy as np
import time
# tama~
no de matriz
m= 100000
n= 10
a = np.ones((m,n))*1.1
# Guardar datos
f1 = ’dout/fout_testio.bin’
f2 = "dout/fout_testio.npy"
f3 = "dout/fout_testio.dat"
print(’Tiempo requerido para guardar’)
# formato binario
start = time.time()
a.tofile(f1)
print (’Binario: %8.5f segundos.’ %(time.time()-start))
117
Lectura y generación de archivos
np.savetxt(f3, a)
print (’text: %8.5f segundos.’ %(time.time()-start))
#---------------------------------------------
# Cargar datos
print(’’)
print(’Tiempo requerido para cargar’)
# formato binario
start = time.time()
b1 = np.fromfile(f1,dtype=’float’)
b1 = b1.reshape(m,n)
print (’Binario: %8.5f segundos.’ %(time.time()-start))
118
Introducción a Python para geociencias
Observemos cómo al usar archivos de texto, la lectura puede ser muy de-
morada. Ası́, el aumento de velocidad es de 55 veces, comparando el forma-
to binario al ASCII. Los archivos, además, ocupan espacios de memoria del
computador muy distintos:
7.6M fout_testio.bin
7.6M fout_testio.npy
24M fout_testio.dat
np.savez(outfile, x, y)
Ası́, se guardan los arreglos x y y, los cuales después se pueden cargar con:
npzfile = np.load(outfile)
119
Lectura y generación de archivos
testio2.py
import numpy as np
m= 100000
n= 10
a = np.ones((m,n))*1.1
y = np.random.rand(n)
x = np.random.rand(m)
z = 1.5
print(’Variables guardadas’)
print(’Shape de a, x, y, size(z)’)
print(np.shape(a),np.shape(x),np.shape(y),np.size(z))
print(’’)
120
Introducción a Python para geociencias
print(’’)
npfile2 = np.load("fout_testio2b.npz")
n1 = npfile2.f.arr_3
m1 = npfile2.f.arr_4
x1 = npfile2.f.arr_1
y1 = npfile2.f.arr_2
a1 = npfile2.f.arr_0
z1 = npfile2.f.arr_5
print(’Variables cargadas 2’)
print(npfile2.files)
print(’Shape de a, x, y, size(z)’)
print(np.shape(a1),np.shape(x1),
np.shape(y1),np.size(z1))
Variables guardadas
Shape de a, x, y, size(z)
(100000, 10) (100000,) (10,) 1
Variables cargadas
Shape de a, x, y, size(z)
(100000, 10) (100000,) (10,) 1
Variables cargadas 2
[’arr_0’, ’arr_1’, ’arr_2’, ’arr_3’, ’arr_4’, ’arr_5’]
Shape de a, x, y, size(z)
(100000, 10) (100000,) (10,) 1
121
Lectura y generación de archivos
Sin embargo, es una buena idea guardar las variables con un nombre que
pueda ser recordado al cargar el archivo de nuevo, ası́:
np.savez(fname, a=a,x=x,y=y,m=m,n=n)
m = npzfile.f.m
x = npzfile.f.x
122
Introducción a Python para geociencias
Problemas
1. Escriba un programa que lea un archivo de texto plano que contenga
cinco números por lı́nea. Calcule el promedio de los cinco números, y
luego sustraiga el promedio de cada uno de los cinco números origina-
les. Guarde un nuevo archivo con los valores con el promedio removido
(demeaned). Permita que el usuario pueda especificar el nombre del ar-
chivo de entrada y salida.
Por ejemplo, partamos de un caso en el que el archivo de entrada es el
siguiente:
10 20 30 40 50
1 2 3 4 5
2 4 6 8 10
5 5 5 5 5
123
Lectura y generación de archivos
124
Capı́tulo 7
Gráficas de datos
Introducción a Python para geociencias
127
Gráficas de datos
import numpy as np
import matplotlib.pyplot as plt
# cargue los datos de Poli
fname = ’data/poli_2016.dat’
data = np.loadtxt(fname,usecols=[4,5,6])
plt.semilogy(data[:,0],data[:,1],’o’)
plt.show()
128
Introducción a Python para geociencias
import numpy as np
import matplotlib.pyplot as plt
...
fig = plt.figure()
ax = fig.add_subplot(111)
ax.semilogy(data[:,0],data[:,1],’o’)
plt.show()
fig = plt.figure()
ax = fig.add_subplot(111)
De esta manera, se tiene completo control de los dos objetos figure y axes, y es
claro que cualquier comando será aplicado al objeto ax, que pertenece a fig.
Además, a menos que se especifique con un nuevo plt.subplots, la figura activa
(current figure) será la variable fig. Ası́, se pueden crear tantos axes o subplots
en una sola figura como se requiera. Para simplificar las cosas, los términos
axes y subplots refieren a lo mismo de ahora en adelante, y son tratados como
sinónimos.
Con el objetivo de generar una figura con varios subplots, lo cual puede ser
común en el trabajo de investigación, veamos el siguiente ejemplo:
129
Gráficas de datos
Figura 7.2. Resultado de correr first plot.py, con idéntico producto a la figura
7.1.
two subplots.py
import numpy as np
import matplotlib.pyplot as plt
fig,ax = plt.subplots(nrows=1,ncols=2)
print(ax)
[<AxesSubplot:> <AxesSubplot:>]
El programa genera una figura fig y dos subplots, en este caso, ax[0] y ax[1],
que están organizados en una fila y dos columnas. Una alternativa para sepa-
rar los dos subplots es:
fig,(ax1,ax2) = plt.subplots(nrows=1,ncols=2)
130
Introducción a Python para geociencias
Figura 7.3. Resultado de correr two subplots.py, donde se crean dos subplots
vacı́os.
four subplots.py
131
Gráficas de datos
2. Gráficas 1D/2D
En muchas ocasiones, para una publicación, por ejemplo, se requiere compa-
rar varias curvas o series de datos. Esto se puede hacer en una sola figura, mos-
trando cada curva con diferentes caracterı́sticas (lı́neas continuas, punteadas,
de puntos, con diferentes sı́mbolos, etc.).
En el programa plot lines.py, se busca desplegar en una figura varios arre-
glos de datos. Dicho programa muestra la forma de generar diferentes tipos
de lı́neas, la leyenda, y cómo solicitar lı́mites mı́nimos y máximos en los ejes.
Por último, cómo se puede guardar la figura en un archivo digital, que en este
caso es un .png. Otros formatos incluyen .ps, .eps, .pdf, .svg, etc. En los siguien-
tes ejemplos, los comandos plt.savefig y plt.show() no se muestran para evitar
ocupar demasiado espacio.
El programa plot lines.py carga un arreglo con las funciones Slepian (usadas
en análisis de series de tiempo y métodos de Fourier) y sus valores propios
[36, 28]), disponibles en el archivo slepian.npz. Los objetivos son:
132
Introducción a Python para geociencias
plot lines.py
import numpy as np
import matplotlib.pyplot as plt
fdat = np.load(’data/slepian.npz’)
x = fdat.f.x
dpss = fdat.f.dpss
v = fdat.f.v
fig,ax = plt.subplots(figsize=(8,7))
ax.plot(x,dpss[:,0],marker=’^’,linestyle=’ ’,label=v[0])
ax.plot(x,dpss[:,1],":",label=v[1])
ax.plot(x,dpss[:,2],"--",label=v[2])
ax.plot(x,dpss[:,3],marker=’.’,label=v[3])
ax.plot(x,dpss[:,4],’-s’,label=v[4])
ax.set_xlabel(’tiempo’)
ax.set_ylabel(’Amplitud’)
ax.set_title(’Funciones Slepian y su concentración’)
ax.set_ylim((-0.22, 0.22))
ax.legend()
plt.savefig(’outfig.pdf’)
plt.show()
133
Gráficas de datos
0.15
0.10
0.05
Amplitud
0.00
0.05
0.10
0.9999999997225858
0.15 0.999999973614479
0.9999988338804353
0.9999684273773817
0.20 0.9994209970175959
0 20 40 60 80 100
Tiempo
ax.plot(x,dpss[:,0],marker=’^’,linestyle=’ ’)
El comando anterior grafica triángulos sin una linea que las una, mientras
que la segunda columna se solicita ası́:
ax.plot(x,dpss[:,1],’:’)
Acá, se obtiene una lı́nea punteada (no continua). Los colores en este caso
son automáticamente seleccionados por Python, que tiene una secuencia de
colores especificada (azul, amarillo, verde, rojo, etc.). En tanto, los formatos
de las lı́neas y de los markers son muy variados, y están por fuera del objetivo
134
Introducción a Python para geociencias
ax.set_xlabel(’tiempo’)
ax.set_ylabel(’Amplitud’)
ax.set_title(’Funciones Slepian y su concentración’)
ax.set_ylim((-0.22, 0.22))
ax.legend()
ax.set_ylim((-0.22, 0.22))
plt.savefig(fname)
Acá, el formato para guardar la figura puede ser .ps, .eps, .png, .svg, etc. In-
cluso la leyenda puede tener un formato más amigable:
ax.plot(x,dpss[:,1],’:’,
label=r’$\lambda_1$=%12.10f ’%(v[1]))
De este modo, la variable v[1] tiene un formato especı́fico (con diez decimales
y doce espacios en total).
En Notebooks, no es necesario usar un comando para que la figura sea des-
plegada en la pantalla, pero si se quiere desplegar la figura corriendo el pro-
grama en Python, se debe pedir con el siguiente comando:
135
Gráficas de datos
plt.show()
En tanto, el código plot errorbar.py lee el archivo y genera una figura con dos
subplots de M0 vs. fc en el primer panel y de M0 vs. τ en el segundo, incluyendo
sus barras de error. Tengamos en cuenta que:
A su vez, el código plot errorbar.py muestra otra forma de trabajar con los
módulos de gráficas de Python. Observemos que primero se crea una figura
con subpaneles plt.subplots, donde se genera una variable axs que se usa para
136
Introducción a Python para geociencias
producir las figuras de cada subpanel, usando ax1 = axs[0] para el primer panel,
y ax2 = axs[1] para el segundo panel.
plot errorbar.py
import numpy as np
import matplotlib.pyplot as plt
# Cargar datos
fname = "data/source_error.dat"
data = np.loadtxt(fname,skiprows=1)
M0 = data[:,2]
M0_err = data[:,3:5].T
fc = data[:,5]
fc_err = data[:,6:8].T
tau = data[:,8]
tau_err = data[:,9:11].T
# La figura
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(8,6))
ax1.errorbar(M0, fc,xerr=M0_err, yerr=fc_err,fmt=’o’)
ax1.set_ylim([1 , 100])
ax1.set_xlim(1e10, 1e15)
ax1.set_yscale(’log’)
ax1.set_xscale(’log’)
ax1.grid(which=’both’)
ax1.xaxis.tick_top()
ax1.xaxis.set_label_position("top")
ax1.set_xlabel(’Seismic Moment (N.m)’);
ax1.set_ylabel(’Corner frequency (Hz)’)
137
Gráficas de datos
ax2.set_yscale(’log’)
ax2.set_xscale(’log’)
ax2.set_ylim([0.5 , 200])
ax2.set_xlim(1e10, 1e15)
ax2.set_xlabel(’Seismic Moment (N.m)’);
ax2.set_ylabel(’Stress Drop (MPa)’);
Una vez cargados los datos, se generan la figura y sus dos subplots en una
sola columna y dos filas:
138
Introducción a Python para geociencias
Asimismo, en el ejemplo, las barras de error son asimétricas, dado que los
arreglos xerr tienen dimensiones (2,N) para describir la extensión de la barra
de error con los lı́mites inferior y superior. Si la barra es simétrica, xerr puede
ser un arreglo (N,), y si todas las barras son de igual longitud para todos los
puntos, xerr puede ser un número.
El programa además le solicita a Python que la gráfica sea elaborada en
escala logarı́tmica en ambos ejes:
ax1.set_yscale(’log’)
ax1.set_xscale(’log’)
ax1.grid(which=’both’)
ax1.xaxis.tick_top()
ax1.xaxis.set_label_position("top")
139
Gráficas de datos
De forma similar se puede mover al lado derecho para el eje y, con los si-
guientes comandos:
ax1.yaxis.tick_right
ax1.yaxis.set_label_position("right")
2.0.2. Histogramas
En algunos casos, es necesario mostrar la distribución de una serie de datos,
para estudiar si estos tienen una distribución normal (gaussiana), o de otro
tipo. El programa plot histogram.py genera un histograma a partir de datos de
caı́da del esfuerzo y esfuerzo aparente de más de 400 terremotos profundos a
nivel mundial [25]. Los datos están en el archivo poli 2016.dat.
plot histogram.py
fname = ’data/poli_2016.dat’
data = np.loadtxt(fname,usecols=[5,6])
# figura
fig, ax = plt.subplots()
ax.hist(np.log10(data[:,0]),bins=10,
label=’Stress Drop’)
ax.hist(np.log10(data[:,1]),bins=bins,
label=’Apparent Stress’)
140
Introducción a Python para geociencias
ax.set_xlim(5, 8)
ax.set_xticks((5,6,7,8))
ax.set_xticklabels(labels)
ax.set_xlabel(’Stress Drop/Apparent Stress (MPa)’)
ax.set_ylabel(’Count’)
ax.set_yticks([])
plt.legend()
hist(X,bins=10)
hist(X,bins=np.linspace(5,8.5,20))
Acá, el usuario puede definir los lı́mites de cada banda, en este caso entre 5
y 8.5 con 20 barras de igual espesor. Cabe señalar que se retiraron los marca-
dores del eje y a propósito con el siguiente comando:
ax.set_yticks([])
3. Gráficas 2D/3D
En geociencias, muchas veces se toman datos en la superficie de la Tierra, y se
busca mostrarlos en mapa o en sección cruzada, o en figura 3D. Sin embargo,
es importante tener en cuenta que las figuras en 3D muchas veces no son muy
útiles para mostrar los datos. En los siguientes ejemplos, se muestran varias
formas de presentar unos datos z tomados en la posición x y y, donde z puede
representar topografı́a, anomalı́as geofı́sicas, contenido de SiO2 , etc.
141
Gráficas de datos
142
Introducción a Python para geociencias
plot scatter.py
import matplotlib.colors as cm
import matplotlib.pyplot as plt
import numpy as np
fdat = np.load("data/rand_matrix.npz")
x = fdat.f.x
y = fdat.f.y
z = fdat.f.z
im2 = ax2.scatter(x,y,z*40+15,c=z,norm=cm.LogNorm(),
cmap=’terrain’,edgecolor=’k’)
ax2.set_title(’Log color scale’)
plt.colorbar(im2,ax=ax2)
fig2 = plt.figure(figsize=(8,8))
ax = fig2.add_subplot(111, projection=’3d’)
ax.plot_trisurf(x,y,np.log10(z))
ax.set_title(’Tri-Surf log10(Z)’)
ax.set_xlabel(’X’)
ax.set_ylabel(’Y’)
ax.set_zlabel(’log(Z)’)
ax.view_init(45, 135)
...
143
Gráficas de datos
im1 = ax1.scatter(x,y,z*40+15,c=z,cmap=’terrain’)
plt.colorbar(im1,ax=ax1)
Ası́, el tercer valor z*40+2 representa el tamaño del sı́mbolo (en puntos), y
c=z determina el color del sı́mbolo de acuerdo con la escala de colores definida
en cmap=’terrain’. Además, Matplotlib ofrece una gran gama de paletas de colo-
res que se pueden consultar en su página de referencia. Cabe señalar además
que posteriormente se define un nuevo objeto im1= ax1.scatter el cual es nece-
sario para asignarle el colorbar a la gráfica correspondiente.
El segundo subplot es idéntico al primero, excepto porque la escala de colo-
res que representa la variable z es logarı́tmica:
im2 = ax2.scatter(x,y,z*40+2,c=z,
norm=cm.LogNorm(), cmap=’terrain’)
ax = fig.add_subplot(111, projection=’3d’)
ax.plot_trisurf(x,y,np.log10(z))
144
Introducción a Python para geociencias
0.5
1.0 10 2
1.5
2.0
10 3
3 2 1 0 1 2 3
plot trisurf, se ordena a Python que genere la superficie. En figuras 3D, es po-
sible cambiar el ángulo de vista de la figura con el siguiente comando:
ax.view_init(45, 135)
Acá, el primer valor representa el ángulo de elevación del observador (en gra-
dos) y el segundo representa el azimut (con respecto a x, también en grados).
145
Gráficas de datos
Tri-Surf log10(Z)
0.5
0.0
0.5
log(Z)
1.0
1.5
2.0
2.5
3.0
3 2.0
2 1.5
1.0
1 0.5
0 0.0
X 0.5 Y
1
1.0
2 1.5
3 2.0
plot contour.py
146
Introducción a Python para geociencias
import numpy as np
fdat = np.load("data/grid_matrix.npz")
...
fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot(111, projection=’3d’)
surf = ax.plot_surface(x, y, np.log10(z),cmap=’ocean’)
ax.view_init(45, 135)
Las curvas de nivel en este caso son negras (colors=’k’), y se le puede dar for-
mato a la nomenclatura (fmt=).
El segundo subplot también es una figura de contornos pero, en este caso,
usa una paleta de colores:
147
Gráficas de datos
fig.colorbar(im2,ax=ax2)
Figura de contornos
2.0
1.5
-02
1e+001e-
1e
01
1.0
0.5 1e-
01
0.0
0.5
1.0
1e-03
1.5
2.0
Contornos rellenos
2.0 101
1.5
100
1.0
0.5 10 1
0.0
0.5 10 2
1.0
10 3
1.5
2.0 10 4
3 2 1 0 1 2 3
148
Introducción a Python para geociencias
ax = fig.add_subplot(111, projection=’3d’)
surf = ax.plot_surface(x, y, np.log10(z),cmap=’ocean’)
ax.view_init(45, 135)
Superficie log10(Z)
0.5
0.0
0.5
log(Z)
1.0
1.5
2.0
2.5
3.0
3 2.0
2 1.5
1.0
1 0.5
0 0.0
X 0.5 Y
1
1.0
2 1.5
3 2.0
149
Gráficas de datos
Problemas
1. Descargar el archivo chap7 data.dat y generar archivos con formato .png.
x = v0 tcos(θ),
1
y = v0 tsin(θ) − gt2 ,
2
donde t es el tiempo, v0 es la velocidad inicial, g es la aceleración de la
gravedad ( 9.8 m/s2 ), (x, y), la posición en el tiempo t, y θ es el ángulo
de disparo con respecto a la horizontal.
Genere dos figuras de dos disparos con diferentes ángulos, mostrando
mediante una lı́nea punteada la trayectoria del movimiento parabólico
de cada uno y, en forma de puntos (o triángulos), la posición (x, y) cada
tiempo t (por ejemplo, cada segundo). Es decir, no se deben graficar todos
los puntos, solo cada cinco o diez puntos.
150
Capı́tulo 8
Mapas con Cartopy
y PyGMT
Introducción a Python para geociencias
153
Mapas con Cartopy y PyGMT
plegar esta información; sin embargo, está fuera del enfoque introductorio de
este libro. Asimismo, para mostrar las ventajas y desventajas de ambos paque-
tes, se presentan los códigos implementados para generar los mismos mapas.
Es decisión personal de cada usuario escoger el paquete que más le guste, o
usar ambos, dependiendo de lo que quiera hacer.
Para la generación de un mapa (en Cartopy y PyGMT o cualquier otro paque-
te), se debe hacer una proyección para aplanar el globo terráqueo sobre una
superficie (la pantalla del computador o una hoja de papel), lo cual requiere
una transformación sistemática de latitud y longitud en la esfera a (x,y) en un
plano. Es inevitable además que toda proyección de la esfera sobre el plano
distorsione la superficie. Dependiendo de lo que se quiera, algunas distorsio-
nes son aceptables y otras no, de modo que es importante saber qué tipo de
proyección se quiere utilizar [35, 16].
1. Cartopy
fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(projection=proj0)
ax.coastlines()
ax.set_xticks([-180,-120,-60,0,60,120,180], crs=proj0)
ax.set_yticks([-90,-60,-30,0,30,60,90],crs=proj0)
154
Introducción a Python para geociencias
proj0 = ccrs.PlateCarree(central_longitude=180.0)
...
ax1 = fig.add_subplot(111,projection=proj0)
ax.coastlines()
ax.set_xticks([-180,-120,-60,0,60,120,180], crs=proj0)
ax.set_yticks([-90,-60,-30,0,30,60,90], crs=proj0)
155
Mapas con Cartopy y PyGMT
proj = ccrs.Orthographic(central_longitude=-90.0)
fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(111,projection=proj)
ax.stock_img()
ax.gridlines(linewidth=1.0)
En estos casos, el mapa puede estar centrado en alguna longitud deseada con
central longitude, y funciona de forma similar para la latitud.
156
Introducción a Python para geociencias
proj = ccrs.Mollweide(central_longitude=-90.0)
ax.gridlines(linewidth=1.0)
157
Mapas con Cartopy y PyGMT
fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(111,projection=proj)
ax.set_extent(reg)
ax.coastlines()
ax.add_feature(cfeature.BORDERS,linestyle=’:’)
...
Notemos que el código tiene la misma estructura que los anteriores, excep-
to por la región que se define con el siguiente comando:
158
Introducción a Python para geociencias
Figura 8.4. Mapa de Suramérica con fronteras polı́ticas usando Cartopy con
el código cartomap03.py.
159
Mapas con Cartopy y PyGMT
fig = plt.figure(figsize=(12,10))
ax1 = fig.add_subplot(2, 1, 1, projection=proj)
ax1.set_extent(reg1)
ax1.add_feature(cfeature.LAND)
ax1.add_feature(cfeature.OCEAN,color=’lightblue’)
ax1.coastlines(resolution=’50m’)
ax1.plot([-130, -130, -120, -120, -130],
[46, 52, 52, 46, 46],
color=’red’, linestyle=’--’,
transform=ccrs.PlateCarree(),)
160
Introducción a Python para geociencias
fig = plt.figure(figsize=(12,10))
ax1 = fig.add_subplot(2,1,1, projection=proj)
...
ax2 = fig.add_subplot(2,1,2, projection=proj)
Entonces, para la primera región (la grande), se incluyen features de región te-
rrestre y región oceánica, las lı́neas de costa; y se puede adicionar un cuadro
que muestre la zona o región más pequeña:
ax1.add_feature(cfeature.LAND)
ax1.add_feature(cfeature.OCEAN,color=’lightblue’)
ax1.coastlines(resolution=’50m’)
...
ax1.plot([-130, -130, -120, -120, -130],
[46, 52, 52, 46, 46],
color=’red’, linestyle=’--’,
transform=ccrs.PlateCarree(),)
161
Mapas con Cartopy y PyGMT
Figura 8.5. Dos mapas que separan la parte oceánica y la parte terrestre con
Cartopy, mediante el código cartomap04.py.
box = ax2.get_position()
box.x0 = box.x0 - 0.01
box.x1 = box.x1 - 0.125
162
Introducción a Python para geociencias
proj4 = ccrs.Mercator()
fig = plt.figure(figsize=(12,10))
163
Mapas con Cartopy y PyGMT
ax = fig.add_subplot(1, 2, 1, projection=proj4)
ax.set_extent([-85, -60, -6, 13])
ax2 = ...
# Adicionar rios
...
ax2.add_feature(rivers,edgecolor=’blue’,
facecolor=’none’)
...
countries = cfeature.NaturalEarthFeature(
category=’cultural’,
name = ’admin_0_boundary_lines_land’,
scale=’10m’,
facecolor=’none’, )
states = cfeature.NaturalEarthFeature(
category=’cultural’,
name = ’admin_1_states_provinces’,
scale=’10m’,
facecolor=’none’,)
164
Introducción a Python para geociencias
rivers = cfeature.NaturalEarthFeature(
’physical’,
’rivers_lake_centerlines’,
’10m’,)
coast = cfeature.GSHHSFeature(scale=’i’,
levels= [1],
edgecolor=’k’,)
165
Mapas con Cartopy y PyGMT
"""
cartomap06.py
Con topo, y estaciones lat/lon
...
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
wms_server = "https://ows.terrestris.de/osm/service?"
proj = ccrs.Mercator()
fig = plt.figure(figsize=(12,10),dpi=800)
ax = fig.add_subplot(121,projection=proj)
ax.set_extent([-85, -65, -5, 15])
# Adicionar topografı́a
166
Introducción a Python para geociencias
ax.add_wms(wms_server,
layers=["SRTM30-Colored-Hillshade"])
ax.plot(lon,lat,’k^’,label=’Estaciones’,
transform=ccrs.Geodetic())
ax.legend()
ax2 = fig.add_subplot(122,projection=proj)
ax2.set_extent([-76, -70, 9, 12])
ax2.add_wms(wms_server,
...)
ax2.plot(lon,lat,’k^’,transform=ccrs.Geodetic())
167
Mapas con Cartopy y PyGMT
wms_server = "https://ows.terrestris.de/osm/service?"
proj = ccrs.Mercator()
fig = plt.figure(figsize=(12,10),dpi=800)
ax = fig.add_subplot(121,projection=proj)
ax.set_extent([-85, -65, -5, 15])
# Adicionar topografı́a
ax.add_wms(wms_server,
layers=["SRTM30-Colored-Hillshade"],
)
168
Introducción a Python para geociencias
ax.plot(lon,lat,’k^’,
transform=ccrs.Geodetic(),
label=’Estaciones’
)
...
ax2.plot(lon,lat,’k^’,transform=ccrs.Geodetic())
2. PyGMT
El paquete de PyGMT no está basado en Matplotlib y, dado que se sustenta en
GMT, las figuras que se producen tienen el formato PS o postscript, dado que
este no tiene la capacidad de interacción, que sı́ tiene Cartopy. Sin embargo,
PyGMT permite guardarlas en formato PDF.
import pygmt
# Proyección Cilı́ndrica
proj = ’Cyl_stere/180/0/8i’
fig = pygmt.Figure()
fig.coast(
region=’g’,
projection=proj,
169
Mapas con Cartopy y PyGMT
shorelines=True,
water=False,
land=False,
frame=True,)
fig.savefig(’../figs/chap08_map07.pdf’)
fig.show()
proj = ’Cyl_stere/180/0/8i’
fig = pygmt.Figure()
170
Introducción a Python para geociencias
fig.coast(
region=’g’,
projection=proj,
shorelines=True,
water=False,
land=False,
frame=True,
)
fig.show()
fig.savefig(’nombre.pdf’)
171
Mapas con Cartopy y PyGMT
gmtmap02.py
import pygmt
proj = ’G-70/0/4.5i’
fig = pygmt.Figure()
fig.grdimage(
’@earth_relief_30m’,
region=’g’,
projection=proj,
cmap=’globe’,
shading=True,)
fig.show()
proj = ’Moll/-70/4.5i’
fig.grdimage(
’@earth_relief_30m’,
region=’g’, projection=proj,
cmap=’globe’, shading=True,)
172
Introducción a Python para geociencias
Figura 8.9. Mapa con proyección esférica con PyGMT por medio del código
gmtmap02.py.
Figura 8.10. Mapa con proyección elı́ptica con PyGMT por medio del
código gmtmap02.py, usando proj = ’Moll/-70/4.5i’.
173
Mapas con Cartopy y PyGMT
Para bajas resoluciones (non-tiled) [’01d’, ’30m’, ’20m’, ’15m’, ’10m’, ’06m’]
Para altas resoluciones (tiled) [’05m’, ’04m’, ’03m’, ’02m’, ’01m’, ’30s’, ’15s’,
’03s’, ’01s’]
import pygmt
fig = pygmt.Figure()
fig.coast(
region=reg,
projection=proj,
174
Introducción a Python para geociencias
shorelines=True,
frame=True,
resolution=’l’,
borders=1,)
fig.show()
Este mapa usa las mismas herramientas anteriores; sin embargo, median-
te el comando coast se pueden solicitar, además de las costas, los lı́mites polı́ti-
cos con borders=1. En este caso, el número 1 representa las fronteras polı́ticas
de los paı́ses. Para departamentos o estados, el código es 2, y, en algunos casos,
el 3 puede mostrar fronteras entre condados. Para incluir varios lı́mites polı́ti-
cos (paises, estados/provincias/departamentos, etc.), usamos borders=[1,2,3], y
si se desea mayor control del formato (color y tipo de lineas), se puede utilizar
el siguiente comando:
Además, se define la resolución del shapefile que tiene las lı́neas de costa con
resolution=’l’, que, en este caso, por ser un mapa general, usamos con baja re-
solución (l=low). Hay cinco niveles de resolución (con un cambio de 80 % entre
niveles):
c: crude
l: low (default)
i: intermediate
h: high
f: full
175
Mapas con Cartopy y PyGMT
176
Introducción a Python para geociencias
import pygmt
fig = pygmt.Figure()
fig.coast(
region=reg1,
projection=’M8i’,
shorelines=True,
water=’lightblue’,
land=’grey’,
frame=True
)
fig.plot([-130, -120, -120, -130, -130],
[ 46, 46, 52, 52, 46],
pen="2p,red,-"
)
pygmt.config(MAP_FRAME_TYPE="plain")
fig.shift_origin(xshift=’0.2i’,yshift=’0.1i’)
fig.coast(
region=reg2,
projection=’M4i’,
177
Mapas con Cartopy y PyGMT
shorelines=True,
water=’lightblue’,
land=’grey’,
frame=’f’
)
fig.show()
Figura 8.12. Dos mapas que separan la región oceánica y la región terrestre
con PyGMT, creados por medio del código gmtmap04.py.
fig = pygmt.Figure()
fig.coast(
...
)
fig.shift_origin(xshift=’0.2i’,yshift=’0.1i’)
178
Introducción a Python para geociencias
Ası́, usando la misma figura, fig, se redefine el origen. GMT genera las fi-
guras en el orden en que se programa; es decir, si se hace primero la figura
pequeña y luego la grande, la grande estará encima y no se verán las dos.
Ambas figuras tienen el mismo patrón, y la región acuática y la terrestre se
colorean con el siguiente comando:
fig.coast(...,
water=’lightblue’,
land=’grey’,
frame=’f’)
Tenga en cuenta que el parámetro frame define si hay un cajón que encierre
la figura, y si tiene o no valores en los ejes x o y. Para generar un frame más sen-
cillo en el subplot pequeño, como el mostrado en la figura 8.12, se debe cambiar
la configuración default de PyGMT con el siguiente comando:
pygmt.config(MAP_FRAME_TYPE="plain")
import pygmt
reg = [-85, -60, -6, 13]
proj = ’M4i’
fig = pygmt.Figure()
fig.coast(
179
Mapas con Cartopy y PyGMT
region=reg,
projection=proj,
shorelines=True,
frame=’f’, resolution=’l’,
borders=[’1/1p,black’,’2/1p,gray’],
water=’lightblue’,
land="white",)
Para extraer la información del shapefile de fronteras y rı́os, dentro del co-
mando coast, se utiliza el siguiente procedimiento:
fig.coast(...
borders=[’1/1p,black’,’2/1p,gray’],
water=’lightblue’,
land="white",)
fig.coast(...
rivers= [’1/blue’,’2/blue’,’3/blue’],
...)
180
Introducción a Python para geociencias
borders=[’1/1p,black’,’2/1p,gray’]
O bien:
rivers= [’1/blue’,’2/blue’,’3/blue’,’4/blue’]
181
Mapas con Cartopy y PyGMT
gmtmap06.py
import pygmt
fname = ’data/rsnc.dat’
...
reg = [-85, -65, -5, 15]
reg2 = [-76, -70, 9, 12]
proj = ’M6i’
fig = pygmt.Figure()
pygmt.config(MAP_FRAME_TYPE="plain")
fig.grdimage(
’@earth_relief_05m’,
region=reg,
projection=proj,
cmap=’etopo1’,
shading=True,)
fig.coast(
region=reg,
...)
fig.plot(lon,lat,
style=’t0.15i’,
color=’black’,
label=’Estaciones’,)
fig.legend()
fig.shift_origin(xshift=’4.5i’,yshift=’1.5i’)
fig.grdimage(
’@earth_relief_15s’,
region=reg2,
projection=proj,
cmap=’etopo1’,
182
Introducción a Python para geociencias
shading=True,)
fig.coast(
region=reg2,
...
fig.plot(lon,lat,
...
fig.show()
fig.grdimage(
’@earth_relief_05m’,
...
cmap=’etopo1’,
shading=True,)
183
Mapas con Cartopy y PyGMT
fig.grdimage(
’@earth_relief_15s’,
...)
fig.plot(lon,lat,
style=’t0.2i’,
color=’black’,
label=’Estaciones’,)
3. ¿Cuál escoger?
Antes de contestar, es importante recordar que ambos paquetes están en etapa
de desarrollo. Por consiguiente, en el futuro, pueden mejorar mucho o hacerse
muy complicados. En la actividad de investigación y presentación de resulta-
dos puede haber muchas cosas que se quiere hacer cuando se desea desplegar
información en mapas. Asimismo, en los ejemplos mostrados en este libro,
se usó en ambos casos información de shapefiles y tiles disponibles; por con-
siguiente, no se discute cómo incluir datos que el usuario pueda tener. Con
ello se alude a información de shapefiles de carreteras o caminos, o grillas (por
ejemplo, en formato NetCDF), con datos que el usuario haya tomado en campo
(gravimetrı́a, sı́smica, etc.).
184
Introducción a Python para geociencias
Problemas
Para cada problema elija el paquete de mapas que prefiera.
185
Mapas con Cartopy y PyGMT
186
Capı́tulo 9
Números
complejos
Introducción a Python para geociencias
z = x + iy, (9.1)
o bien:
i2 = −1
Para el número complejo z, se tiene una parte real x = Re(z), y una parte
imaginaria y = Im(z). Tengamos en cuenta que la variable y es una variable
real. El complejo conjugado de z, se define ası́:
z ∗ = x − iy (9.2)
189
Números complejos
z = complex(2,3)
z = 2+3j
190
Introducción a Python para geociencias
Acá, j se usa en vez de i en Matlab. Algunos ejemplos básicos del uso de núme-
ros complejos en Python son los siguientes:
complejo1.py
x = 1
z0 = 2j
z1 = 3 + 4j
print(’Real , x)
print((’Imaginario’, z0)
print((’Complejo’, z1)
print(’Parte real e imag de z1 = ’,z1.real, z1.imag)
Real 1
Imaginario 2j
Complejo (3+4j)
Parte real e imag de z1 = 3.0 4.0
El anterior código muestra cómo Python despliega los números reales (x), ima-
ginarios (z0) o complejos (z1). Abajo, mostramos dos formas de definir el mis-
mo número complejo:
complejo2.py
z0 = complex(2,3)
z = 2+3j
print(z, z0)
(2+3j) (2+3j)
191
Números complejos
z0 = 3j
z1 = 5-2j
z2 = z0/z1
print(z2)
(-0.206...+0.517...j)
# testcomplex.py
import numpy as np
192
Introducción a Python para geociencias
zreal = np.random.randint(1,5)
zimag = np.random.randint(1,5)
a = complex(float(zreal),float(zimag))
b = complex(2,1)
c = a*b
csq = np.sqrt(c)
csin = np.sin(c)
cexp = np.exp(c)
Cabe anotar que para imprimir de una manera amable el número complejo
de salida, se puede solicitar un formato especı́fico, de este modo:
# complejo a = (1+3j)
# complejo b = (2+1j)
c = a x b = (-1+7j)
|c| = 7.07
sqrt(c) = (1.74, 2.01j)
sin(c) = (-461.39, 296.26j)
exp(c) = (0.28, 0.24j)
193
Números complejos
array complex.py
# array_complex.py
import numpy as np
print (’matmul(a*a.T)’)
print(c)
c = np.matmul(a,np.conjugate(b))
print (’matmul(a*conj(a.T))’)
print(c)
c = np.matmul(a,np.conjugate(b))
194
Introducción a Python para geociencias
print (’sqrt(c)’)
np.set_printoptions(precision=3)
print(np.sqrt(c))
3. Fractales
En geociencias, los fractales y el concepto de autosimilitud tienen múltiples
aplicaciones [38, 32], incluyendo terremotos [29], fallas y fracturas [5], geo-
biologı́a [13], geomorfologı́a [23], y muchos otros campos [2].
Recomendamos buscar en internet imágenes de fractales. Para generar es-
te tipo de figuras, se requiere del manejo de números complejos. La idea
195
Números complejos
básica detrás del cálculo de fractales es que hay ciertas funciones complejas
que, cuando se calculan de manera repetida, pueden converger (siendo esta-
bles), o divergir. El que diverjan o no es muy sensible a pequeños cambios en el
valor del número complejo que inicia el cálculo, de ahı́ su uso en teorı́a del caos,
por ejemplo [39]. Esa transición entre divergencia o estabilidad se observa en
ciertas regiones en el plano complejo.
Uno de los sets más famosos es el conjunto de Mandelbrot, el cual es relati-
vamente fácil de generar en un programa de computador. Para generar este
conjunto, empezamos considerando un número complejo c, al cual se le aplica
el siguiente algoritmo:
196
Introducción a Python para geociencias
mandel set.py
def mandel1(x0=-0.21503361460851339,
y0=0.67999116792639069,
dx=0.2):
import numpy as np
# defina la grilla
nx = 300
x = np.linspace(x0-dx,x0+dx,nx)
y = np.linspace(y0-dx,y0+dx,nx)
dat = np.zeros((nx,nx))
197
Números complejos
for iy in range(nx):
cr = x[ix]
ci = y[iy]
c = complex(cr,ci)
z = complex(0.0,0.0)
for it in range(1000):
z = c + z*z
if (abs(z)>2.0):
break
dat[ix,iy] = it+1
dat = np.transpose(dat)
dat = np.log10(dat)
return dat
Primero, la función define la grilla, con 300 puntos para el eje real (x), y
300 para el eje imaginario (y), para un total de 90 000 puntos, para generar
la matriz dat, donde se va a guardar el número de iteraciones necesarias para
que |z| > 2.
# defina la grilla
nx = 300
x = np.linspace(x0-dx,x0+dx,nx)
y = np.linspace(y0-dx,y0+dx,nx)
dat = np.zeros((nx,nx))
Después, para cada posición en la matriz dat (for loops de ix y iy), se define
el valor de c:
cr = x[ix]
ci = y[iy]
c = complex(cr,ci)
198
Introducción a Python para geociencias
z = complex(0.0,0.0)
for it in range(1000):
z = c + z*z
if (abs(z)>2.0):
break
x0 = −0.21503361460851339
y0 = 0.67999116792639069,
con rangos de la grilla cada vez menores. En otras palabras, se muestran dife-
rentes acercamientos (zooms) alrededor del mismo punto, en los que se mues-
tran caracterı́sticas de la estructura del conjunto de Mandelbrot autosimilares.
Un programa ejemplo que usa la función mandel set.py para generar una
figura (un solo panel de la figura 9.2) del conjunto de Mandelbrot se muestra
a continuación:
plot mandel.py
import numpy as np
import matplotlib.pyplot as plt
import mandel_set
x0 =-0.21503361460851339
199
Números complejos
y0 = 0.67999116792639069
dx = 0.4
fig = plt.figure(figsize=(10,10))
dat = mandel1(x0,y0,dx)
nx = np.shape(dat)[0]
ax = fig.add_subplot(3,3,i+1)
im = ax.imshow(dat,cmap=’twilight_shifted’,
animated=True)
ax.set_title(f’Escala: {2*dx:.1e}’)
ax.set_xticks([])
ax.set_yticks([])
plt.show()
Problemas
1. Escriba un programa para evaluar la precisión en la definición de un
número complejo en Python, usando la siguiente formula:
200
Introducción a Python para geociencias
201
Números complejos
202
Bibliografı́a
[1] JM. Aiken, C. Aiken, and F. Cotton, A python library for teaching computation
to seismology students, Seismological Research Letters 89 (2018), no. 3,
1165–1171.
[2] CC. Barton, R. Paul, and L. Pointe, Fractals in the earth sciences, Springer
Science & Business Media, 1995.
[4] WG. Blumberg, KT. Halbert, TA. Supinie, PT. Marsh, RL. Thompson, and
JA. Hart, Sharppy: An open-source sounding analysis toolkit for the atmospheric
sciences, Bulletin of the American Meteorological Society 98 (2017), no. 8,
1625–1636.
[5] E. Bonnet, O. Bour, NE. Odling, P. Davy, I. Main, P. Cowie, and B. Berko-
witz, Scaling of fracture systems in geological media, Reviews of Geophysics
39 (2001), no. 3, 347–383.
[6] GA. Cox, WJ. Brown, L. Billingham, and R. Holme, Magpysv: A python pac-
kage for processing and denoising geomagnetic observatory data, Geochemistry,
Geophysics, Geosystems 19 (2018), no. 9, 3347–3363.
203
Bibliografı́a
[7] FK. Dannemann Dugick, S. van der Lee, GA. Prieto, SN. Dybing, L. Toney,
and HM. Cole, Roses: Remote online sessions for emerging seismologists, Seism.
Res. Lett. 92 (2021), no. 4, 2657–2667.
[9] AK. Dewdney, Beauty and profundity, the mandelbrot set and a flock of its
cousins called julia, Scientific American 257 (1987), no. 5, 118–122.
[10] G. Ekström, GA. Abers, and SC. Webb, Determination of surface-wave phase
velocities across usarray from noise and aki’s spectral formulation, Geophysical
Research Letters 36 (2009), no. 18.
[11] VG. Gabriel, Theory of complex numbers in structural geology, Eos, Transac-
tions American Geophysical Union 35 (1954), no. 2, 310–319.
[13] JP. Grotzinger and DH. Rothman, An abiotic model for stromatolite morpho-
genesis, Nature 383 (1996), no. 6599, 423–425.
[14] CR. Harris, KJ. Millman, SJ. van der Walt, R. Gommers, P. Virtanen,
D. Cournapeau, E. Wieser, J. Taylor, S. Berg, NJ. Smith, et al., Array pro-
gramming with numpy, Nature 585 (2020), no. 7825, 357–362.
[15] NJ. Higham, BibTeX: A Versatile Tool for LaTeX Users, SIAM News 27 (1994),
no. 1, 10–19.
[16] B. Jenny, B. Šavrič, ND. Arnold, BE. Marston, and CA. Preppernau, A guide
to selecting map projections for world and hemisphere maps, Choosing a map
projection, Springer, 2017, pp. 213–228.
[17] C. Jiang and MA. Denolle, Noisepy: A new high-performance python tool for
ambient-noise seismology, Seismological Research Letters 91 (2020), no. 3,
1853–1866.
204
Bibliografı́a
[18] J. Kam, PCD. Milly, and KA. Dunne, Monthly time series of precipitation, air
temperature, and net radiation for 2,673 gaged river basins worldwide: U.s. geolo-
gical survey data release, Tech. report, USGS, 2018.
[20] H. Kopka and PW. Daly, A Guide to LaTeX2e. Document Preparation for Begin-
ners and Advanced Users, fourth ed., Addison-Wesley Publishing Company,
2004.
[23] B. Mandelbrot, How long is the coast of britain? Statistical self-similarity and
fractional dimension, Science 156 (1967), no. 3775, 636–638.
[24] Met Office, Cartopy: a cartographic python library with a matplotlib interface,
Exeter, Devon, 2010-2015.
[25] P. Poli and GA. Prieto, Global rupture parameters for deep and intermediate-
depth earthquakes, Journal of Geophysical Research: Solid Earth 121 (2016),
no. 12, 8871–8887.
[26] GA. Prieto, The multitaper spectrum analysis package in python, Seismological
Research Letters 93 (2022), no. 3, 1922–1929.
[27] GA. Prieto, JF. Lawrence, and GC. Beroza, Anelastic earth structure from the
coherency of the ambient seismic field, Journal of Geophysical Research: Solid
Earth 114 (2009), no. B7.
[28] GA. Prieto, RL. Parker, and FL. Vernon, A fortran 90 library for multitaper
spectrum analysis, Computers & Geosciences 35 (2009), no. 8, 1701–1710.
205
Bibliografı́a
[29] GA. Prieto, PM. Shearer, FL. Vernon, and D. Kilb, Earthquake source scaling
and self-similarity estimation from stacking p and s spectra, Journal of Geophy-
sical Research: Solid Earth 109 (2004), no. B8.
[30] GA. Prieto, DJ. Thomson, FL. Vernon, PM. Shearer, and RL. Parker, Con-
fidence intervals for earthquake source parameters, Geophysical Journal Inter-
national 168 (2007), no. 3, 1227–1234.
[31] BR. Röbke and A. Vött, The tsunami phenomenon, Progress in Oceano-
graphy 159 (2017), 296–322.
[32] CH. Scholz and BB. Mandelbrot, Fractals in geophysics, Springer, 1989.
[34] H. Shen, Interactive notebooks: Sharing the code, Nature News 515 (2014),
no. 7525, 151.
[35] JP. Snyder, Map projections used by the us geological survey, Tech. report, US
Government Printing Office, 1982.
[38] DL. Turcotte, Fractals in geology and geophysics, Pure and applied Geophy-
sics 131 (1989), no. 1, 171–196.
[41] L. Uieda and P. Wessel, Pygmt: Accessing the generic mapping tools from pyt-
hon, AGU Fall Meeting Abstracts, vol. 2019, 2019, pp. NS21B–0813.
206
Bibliografı́a
[42] P. Wessel, JF. Luis, L. Uieda, R. Scharroo, F. Wobbe, WHF. Smith, and
D. Tian, The generic mapping tools version 6, Geochemistry, Geophysics,
Geosystems 20 (2019), no. 11, 5556–5564.
207
Índice
209
Índice
210
Introducción a Python para geociencias
fue editado por el Centro Editorial de la Facultad
de Ciencias, Universidad Nacional de Colombia,
sede Bogotá. Se utilizaron como fuentes principales
Baskerllive y Fira Sans. Bogotá D. C.