Drehen Sie eine Matrix mit Matplotlib
Mir rotierende anxn Matrix (n = 20, obwohl es ändern könnte) 30 Grad nach rechts Matplotlib der Verwendung von Transformationsmethoden.
Der Fehler wird angezeigt, weil die Rotation von oben und nicht von unten erfolgt. Ich habe versucht, den Index durch np.flip()oder ax.imshow(origin = 'lower')aber auch das Dreieck umzukehren, daher muss ich herausfinden, wie der Transformationsursprungspunkt festgelegt wird .
Auf jeden Fall möchte ich Folgendes erhalten :
Beachten Sie, dass die kleinen Quadrate, die der Diagonalmatrix entsprechen, in Dreiecke umgewandelt werden. Könnte das gemacht werden? Vielleicht durch eine Imshow-Methode, die ein halbes Pixel zurückgibt? Der Rest der Pixel würde gleich bleiben (deformierte kleine Quadrate).
Hier ist der Code zum Generieren der Matrix ( Startpunkt ):
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms
matrix = np.random.rand(20,20)
# Generate a boolean matrix (same shape than 'matrix') and select lower triangle values:
condition = np.tril(np.ones((matrix.shape))).astype(np.bool)
triangle = np.where(condition, matrix, np.nan)
fig, ax = plt.subplots(figsize = (8,8))
ax.imshow(triangle, cmap = 'Spectral')
Und hier ist der Code, der versucht, ihn zu drehen :
im = ax.imshow(matrix, cmap = 'Spectral')
im.set_transform(mtransforms.Affine2D().skew(30, 0) + ax.transData)
ax.plot(transform = trans_data)
Ich verwende keine Triangle-Klasse von Matplotlib, da das ternäre Diagramm während einer Interpolationsoperation dargestellt wird und ich die ursprünglichen Matrixwerte darstellen möchte.
Ich würde mich sehr über die Hilfe von jemandem freuen. Vielen Dank im Voraus.
Antworten
Anstatt den Ursprung der Schräglauftransformation zu ändern, können Sie sie mit einer Übersetzung in x-Richtung verketten, um die gewünschte Transformation zu erzielen.
Beachten Sie, dass die skewTransformation einen Winkel im Bogenmaß hat (Sie haben sie mit Grad verwendet). Es gibt eine äquivalente skew_degTransformation, wenn Sie in Grad arbeiten möchten, aber hier arbeite ich nur im Bogenmaß.
Beachten Sie auch, dass Sie ein gleichschenkliges Dreieck mit einer Basis und einer Höhe von 20 haben möchten (oder was auch immer Sie für N wählen). Der gewünschte Winkel beträgt nicht 30 Grad, sondern tatsächlich Arctan (1/2) (= 26,56) Grad).
Der Betrag, den Sie in x-Richtung übersetzen müssen, beträgt xtrans = N * np.tan(angle).
Sie können Transformationen in matplotlib einfach verketten. Hier können wir zuerst verzerren und dann übersetzen:
mtransforms.Affine2D().skew(-angle, 0).translate(xtrans, 0)
Beachten Sie, dass dieses Skript für jeden Wert von N funktioniert.
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms
N = 20
matrix = np.random.rand(N, N)
# Generate a boolean matrix (same shape than 'matrix') and select lower triangle values:
condition = np.tril(np.ones((matrix.shape))).astype(np.bool)
triangle = np.where(condition, matrix, np.nan)
fig, ax = plt.subplots(figsize = (8,8))
im = ax.imshow(triangle, cmap = 'Spectral')
angle = np.arctan(1/2)
xtrans = N * np.tan(angle)
im.set_transform(mtransforms.Affine2D().skew(-angle, 0).translate(xtrans, 0) + ax.transData)
ax.set_xlim(-0.5, N + 0.5)
plt.show()
Für N = 20
Und für N = 30
Ich erhalte endlich ein gleichseitiges Dreieck, das die y-Achse skaliert. Hier zeige ich den Code.
Daher ermöglicht es die Umwandlung einer Matrix in ein gleichseitiges Dreieck , was meine vorherige Frage beantwortet:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms
import matplotlib
bins = 50
Z = np.random.rand(bins, bins)
# Generate a boolean matrix (same shape than 'matrix') and select lower triangle values:
condition = np.tril(np.ones((Z.shape))).astype(np.bool)
Z = np.where(condition, Z, np.nan)
fig, ax = plt.subplots(figsize = (8,8))
im = ax.imshow(Z, cmap = 'Spectral')
# Required angles (in Rad)
alpha = np.arctan(1/2) # 26 deg angle, in radians.
beta = np.arctan(np.pi/6) # 30 deg angle, in radians.
# Coefficients:
xtrans = np.sin(beta) * bins
scale_y = np.cos(beta)
# Transformation:
im.set_transform(mtransforms.Affine2D().skew (-alpha, 0)
.scale (1,scale_y)
.translate (xtrans, 0)
+ ax.transData)
ax.set_ylim(bins,-5)
ax.set_xlim(-5,bins)
plt.show()