it-swarm.com.de

platzierung und Größe der Matplotlib-Farbleiste

Ich verwende quadmesh, um eine einfache polare Projektionsdarstellung zu erstellen. Hier ist ein minimales Skript, das im Grunde das produziert, was ich versuche:

from __future__ import unicode_literals
import numpy as np
import matplotlib.pyplot as plt

def make_plot(data,fig,subplot):
    nphi,nt = data.shape
    phi_coords = np.linspace(0,np.pi*2,nphi+1) - np.pi/2.
    theta_coords = np.linspace(0,np.radians(35),nt+1)

    ax = fig.add_subplot(subplot,projection='polar')
    ax.set_thetagrids((45,90,135,180,225,270,315,360),(9,12,15,18,21,24,3,6))
    ax.set_rgrids(np.arange(10,35,10),fmt='%s\u00b0')  

    theta,phi = np.meshgrid(phi_coords,theta_coords)
    quadmesh = ax.pcolormesh(theta,phi,data)
    ax.grid(True)
    fig.colorbar(quadmesh,ax=ax)
    return fig,ax


a = np.zeros((360,71)) + np.arange(360)[:,None]
b = np.random.random((360,71))
fig = plt.figure()
t1 = make_plot(a,fig,121)
t2 = make_plot(b,fig,122)
fig.savefig('test.png')

Das obige Skript erstellt eine Zeichnung, die folgendermaßen aussieht:

enter image description here

Ich möchte die Farbbalken an:

  1. Überlappen Sie nicht die 6 Etiketten.
  2. so skaliert sein, dass sie ungefähr die gleiche Höhe wie die Zeichnung haben.

Gibt es einen Trick, um dies richtig zu machen? (Beachten Sie, dass dieses Layout nicht das einzige ist, das ich verwenden werde - z. B. kann ich ein 1x2-Layout oder ein 4x4-Layout verwenden ... Es scheint, als sollte es eine Möglichkeit geben, die Farbleiste auf die gleiche Höhe wie das zu skalieren zugehöriges Grundstück ...)

12
mgilson

Diese Kombination (und Werte in der Nähe dieser Werte) scheint für mich "magisch" zu sein, um die Farbleiste auf die Grafik zu skalieren, unabhängig von der Größe der Anzeige.

plt.colorbar(im,fraction=0.046, pad=0.04)
17
bejota

Sie können dies mit einer Kombination der Warnungen pad, shrink und aspect tun:

from __future__ import unicode_literals
import numpy as np
import matplotlib.pyplot as plt

def make_plot(data,fig,subplot):
    nphi,nt = data.shape
    phi_coords = np.linspace(0,np.pi*2,nphi+1) - np.pi/2.
    theta_coords = np.linspace(0,np.radians(35),nt+1)

    ax = fig.add_subplot(subplot,projection='polar')
    ax.set_thetagrids((45,90,135,180,225,270,315,360),(9,12,15,18,21,24,3,6))
    ax.set_rgrids(np.arange(10,35,10),fmt='%s\u00b0')  

    theta,phi = np.meshgrid(phi_coords,theta_coords)
    quadmesh = ax.pcolormesh(theta,phi,data)
    ax.grid(True)
    cb = fig.colorbar(quadmesh,ax=ax, shrink=.5, pad=.2, aspect=10)
    return fig,ax,cb


a = np.zeros((360,71)) + np.arange(360)[:,None]
b = np.random.random((360,71))
fig = plt.figure()
t1 = make_plot(a,fig,121)
t2 = make_plot(b,fig,122)

figure.colorbar doc

Der beste Wert für diese Parameter hängt vom Seitenverhältnis der Achsen ab.

Die Größe der Achsen scheint nicht mit dem Polardiagramm verkleinert zu sein. Daher gibt es in der 1x2-Anordnung über und unter dem Diagramm viel Platz, die Teil des Achsenobjekts sind, jedoch leer sind. Die Größe des Farbbalkens ist von der rechteckigen Größe und nicht von der runden Größe abgezogen, weshalb die Standardwerte nicht gut funktionieren. Es gibt wahrscheinlich eine Möglichkeit, die Schrumpfverpackung zu machen, aber ich weiß nicht, wie ich das machen soll.

Eine alternative Methode besteht darin, Ihre Figur zu zwingen, das richtige Seitenverhältnis zu sein, z.

fig.set_size_inches(10, 4) # for 1x2
fig.set_size_inches(4, 10) # for 2x1

dadurch werden die Unterdiagramme quadratisch, sodass die Standardwerte mehr oder weniger funktionieren.

13
tacaswell

Die automatische Skalierung des Farbbalkens ist bekanntermaßen schwierig. Der Versuch, die am Ende von diese Seite beschriebene Umgehung anzuwenden, funktionierte für mich weder bei Ihrem Beispiel noch bei meinen Versuchen, ein Axes3D-Objekt zu verwenden. Ein Blick auf die Aufrufsignatur für das colorbarNAME_ , das axSchlüsselwortargument ist das "Objekt, aus dem Platz für eine neue Farbleistenachse gestohlen wird." Dies erklärt, warum der Farbbalken die 6 überlappt. Wir müssen also ein doppeltes Axesbeibehalten. Leider müssen die zusätzlichen Achsen gepflegt werden, was die Position von Hand hackt. Ich habe folgendes zusammengeschustert:

#!/usr/bin/env python
from __future__ import unicode_literals
import numpy as np
import matplotlib.pyplot as plt

fig = plt.figure()

N, M = 360, 71
phi_coords = np.linspace(0, np.pi*2, M+1) -np.pi/2
theta_coords = np.linspace(0, np.radians(35), N+1)
theta, phi = np.meshgrid(phi_coords, theta_coords)

# Original method
a = np.zeros((N,M)) + np.arange(N)[:,None]
ax1 = fig.add_subplot(1,2,1, projection="polar")
ax1.set_thetagrids((45,90,135,180,225,270,315,360),(9,12,15,18,21,24,3,6))
ax1.set_rgrids(np.arange(10,35,10),fmt='%s\u00b0')  
quadmesh = ax1.pcolormesh(theta, phi, a)
fig.colorbar(quadmesh,ax=ax1)

# Use ``add_axes`` to make a ``cax``
b = np.random.random((N,M))
ax2 = fig.add_subplot(1,2,2, projection="polar")
ax2.set_thetagrids((45,90,135,180,225,270,315,360),(9,12,15,18,21,24,3,6))
ax2.set_rgrids(np.arange(10,35,10),fmt='%s\u00b0')  
quadmesh = ax2.pcolormesh(theta, phi, b)
# <hack>
# Hack to force the drawing of the image.
print(ax2.get_position())
import tempfile
with tempfile.SpooledTemporaryFile() as fid:
    fig.savefig(fid, format="png")

# </hack>
# Now the axes has been scaled to the final size.
bbox = ax2.get_position()
print(bbox)
cax = fig.add_axes(
        [bbox.xmax*1.03, bbox.ymin, bbox.width*0.08, bbox.height]
    )
fig.colorbar(quadmesh,cax=cax)

fig.savefig('test.png')

Das linke Bild ist das gleiche wie das Original, aber das rechte Bild hat den Farbbalken gegenüber dem Polardiagramm und die Höhe des Balkens stimmt mit dem Polardiagramm überein. Wie Sie sehen können, musste ich die Figur zwingen, zu zeichnen, um die Größe der Achse für die linke Hand zu bestimmen. Wenn Sie das erneute Zeichnen nicht erzwingen, basiert die Größe des Farbbalkens auf der ursprünglichen Achsengröße, und Sie erhalten dieselbe Größenachse wie die linke. Zu diesem Zeitpunkt habe ich keine Möglichkeit gefunden, dem Axesfür die Farbleiste mitzuteilen, dass der Haupt Axesautomatisch auf Änderungen in der Größe verfolgt wird.

0
Keith Prussing