Matplotlib y una relación adecuada de plots de datos geográficos

Proceso información geográfica y presento los resultados usando matplotlib. Toda la entrada es latitud / longitud [grado]. Me convierto en x / y [metro] para mis cálculos. Y presento mis resultados en latitud / longitud. El problema es hacer que la relación de aspecto de las gráficas sea correcta: todas las gráficas son demasiado amplias. ¿Existe un procedimiento estándar para establecer la relación de aspecto correcta para que pueda dibujar mi dispersión y otros diagtwigs?
¿Usando lat / lon y el resultado tiene la forma correcta? ¿En pantalla y en papel (png)?

[Agregué esta parte más adelante] Esta es una versión reducida de mi problema. Necesito valores reales de lat / lon alrededor de los ejes y una forma precisa (cuadrada). Ahora mismo aparece ancho (2x).

import math import matplotlib.pyplot as plt import numpy as np from pylab import * w=1/math.cos(math.radians(60.0)) plt_area=[0,w,59.5,60.5] #60deg North, adjacent to the prime meridian a=np.zeros(shape=(300,300)) matshow(a, extent=plt_area) plt.grid(False) plt.axis(plt_area) fig = plt.gcf() fig.set_size_inches(8,8) fig.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9) plt.show() 

Parece que encontré la solución. Y lo encontré aquí: ¿Cómo puedo configurar la relación de aspecto en matplotlib?

 import math import matplotlib.pyplot as plt import numpy as np w=1/math.cos(math.radians(60.0)) plt_area=[0,w,59.5,60.5] #square area a=np.zeros(shape=(300,300)) fig = plt.figure() ax = fig.add_subplot(111) ax.imshow(a) plt.grid(False) ax.axis(plt_area) fig = plt.gcf() fig.set_size_inches(8,8) ax.set_aspect(w) fig.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9) plt.show() 

En matplotlib por lo general cambio el tamaño de la figura de esta manera:

 import matplotlib.pyplot as plt plt.clf() fig = plt.figure() fig_p = plt.gcf() fig_p.set_size_inches(8, 8) # x, y 

Sin embargo, esto establece las dimensiones de las dimensiones exteriores de la figura, no el área de trazado. Puede cambiar el área de trazado en relación con el tamaño de la figura dado en proporciones de las longitudes de tamaño de la figura total de x e y respectivamente:

 fig.subplots_adjust(left=0.1, right=0.9, bottom=0.1, top=0.9) 

Siempre que las relaciones relativas se mantengan simétricamente, la relación de aspecto debería ser la misma para la gráfica.

Ejemplo 1:

 plt.clf() fig = plt.figure() fig_p = plt.gcf() fig_p.set_size_inches(5, 5) # x, y for figure canvas # Relative distance ratio between origin of the figure and max extend of canvas fig.subplots_adjust(left=0.2, right=0.8, bottom=0.2, top=0.8) ax1 = fig.add_subplot(111) xdata = [rand()*10 for i in xrange(100)] ydata = [rand()*1 for i in xrange(100)] ax1.plot(xdata, ydata, '.b', ) ax1.set_xlabel('Very Large X-Label', size=30) plt.savefig('squareplot.png', dpi=96) 

$ .subplot_adjust $ sobrescribe el espacio predeterminado entre el tamaño de la figura y la extensión de la parcela

Ejemplo 2:

 fig.subplots_adjust(left=0.0, right=1.0, bottom=0.0, top=1.0) 

Área de la plot llena el tamaño de la figura por completo:

Sin espacio entre el tamaño de la figura y el área de la parcela

No intente solucionar esto fig.set_size_inches() o fig.subplots_adjust() o cambiando sus datos; en su lugar utiliza una proyección de Mercator.

Puede obtener una proyección rápida y sucia de Mercator utilizando una relación de aspecto del recíproco del coseno de la latitud media de sus datos. Esto es “bastante bueno” para los datos contenidos en aproximadamente 1 grado de latitud, que es de aproximadamente 100 km. (Debe decidir si, para su aplicación, esto es “suficientemente bueno”. Si no lo es, realmente debe considerar algunas bibliotecas de proyección geográfica serias …)

Ejemplo:

 from math import cos, radians import matplotlib.pyplot as plt import numpy as np # Helsinki 60.1708 N, 24.9375 E # Helsinki (lng, lat) hels = [24.9375, 60.1708] # a point 100 km directly north of Helsinki pt_N = [24.9375, 61.0701] # a point 100 km east of Helsinki along its parallel pt_E = [26.7455, 60.1708] coords = np.array([pt_N, hels, pt_E]) plt.figure() plt.plot(coords[:,0], coords[:,1]) # either of these will estimate the "central latitude" of your data # 1) do the plot, then average the limits of the y-axis central_latitude = sum(plt.axes().get_ylim())/2. # 2) actually average the latitudes in your data central_latitude = np.average(coords, 0)[1] # calculate the aspect ratio that will approximate a # Mercator projection at this central latitude mercator_aspect_ratio = 1/cos(radians(central_latitude)) # set the aspect ratio of the axes to that plt.axes().set_aspect(mercator_aspect_ratio) plt.show() 

Escogí Helsinki por el ejemplo, ya que en esa latitud la relación de aspecto es casi 2 … porque dos grados de longitud es aproximadamente la misma distancia que un grado de latitud.

Para ver realmente este trabajo: a) ejecute lo anterior, b) cambie el tamaño de la ventana. Luego comente la llamada a set_aspect() y haga lo mismo. En el primer caso, se mantiene la relación de aspecto correcta, en este último se obtiene un estiramiento sin sentido.

Los puntos a 100 km al norte y al este de Helsinki fueron calculados / confirmados por la EXCELENTE página que calcula las distancias entre los puntos de latencia / latencia en Movable Type Scripts