Matplotlib.backend_bases¶

Matplotlib.backend_bases¶ Техника

I want to make a plot with square root scale using Python:

square root scale graph

However, I have no idea how to make it. Matplotlib allows to make log scale but in this case I need something like power function scale.

asked Feb 16, 2017 at 15:21

michal_2am's user avatar

You can make your own ScaleBase class to do this. I have modified the example from here (which made a square-scale, not a square-root-scale) for your purposes. Also, see the documentation here.

Note that to do this properly, you should probably also create your own custom tick locator; I haven’t done that here though; I just manually set the major and minor ticks using ax.set_yticks().

import matplotlib.scale as mscale
import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms
import matplotlib.ticker as ticker
import numpy as np

class SquareRootScale(mscale.ScaleBase):
    """
    ScaleBase class for generating square root scale.
    """
 
    name = 'squareroot'
 
    def __init__(self, axis, **kwargs):
        # note in older versions of matplotlib (<3.1), this worked fine.
        # mscale.ScaleBase.__init__(self)

        # In newer versions (>=3.1), you also need to pass in `axis` as an arg
        mscale.ScaleBase.__init__(self, axis)
 
    def set_default_locators_and_formatters(self, axis):
        axis.set_major_locator(ticker.AutoLocator())
        axis.set_major_formatter(ticker.ScalarFormatter())
        axis.set_minor_locator(ticker.NullLocator())
        axis.set_minor_formatter(ticker.NullFormatter())
 
    def limit_range_for_scale(self, vmin, vmax, minpos):
        return  max(0., vmin), vmax
 
    class SquareRootTransform(mtransforms.Transform):
        input_dims = 1
        output_dims = 1
        is_separable = True
 
        def transform_non_affine(self, a): 
            return np.array(a)**0.5
 
        def inverted(self):
            return SquareRootScale.InvertedSquareRootTransform()
 
    class InvertedSquareRootTransform(mtransforms.Transform):
        input_dims = 1
        output_dims = 1
        is_separable = True
 
        def transform(self, a):
            return np.array(a)**2
 
        def inverted(self):
            return SquareRootScale.SquareRootTransform()
 
    def get_transform(self):
        return self.SquareRootTransform()
 
mscale.register_scale(SquareRootScale)

fig, ax = plt.subplots(1)

ax.plot(np.arange(0, 9)**2, label='$y=x^2$')
ax.legend()

ax.set_yscale('squareroot')
ax.set_yticks(np.arange(0,9,2)**2)
ax.set_yticks(np.arange(0,8.5,0.5)**2, minor=True)

plt.show()

enter image description here

answered Feb 16, 2017 at 16:44

tmdavison's user avatar

12 gold badges185 silver badges164 bronze badges

This is old, but I made a quick-fix because i didn’t want to bother with creating a custom tick-locator. If you are making a lot of plots with custom scales that is probably the way to go. Just plotting the function with the scale you want, then setting the ticks and changing the labels is quicker if you just need a plot or two.

Nx = 100
x = np.linspace(0,50,Nx)
y = np.sqrt(x)

fig, ax = plt.subplots(1, 1)

plt.plot(np.sqrt(x), y)
ax.set_xticks([np.sqrt(x[i]) for i in range(0, Nx, Nx // 10)])
ax.set_xticklabels([str(round(x[i],0))[:-2] for i in range(0, Nx, Nx // 10)])
plt.xlabel('x')
plt.ylabel(r'y = $\sqrt{x}$')
plt.grid()
plt.show()

produces the plot

Дополнительно:  Синий светодиод моргает три раза в режиме охраны / StarLine A93, A63, A39, A36 / StarLine

enter image description here

answered Oct 18, 2021 at 9:19

Vegard Gjeldvik Jervell's user avatar

x = np.arange(2, 15, 2)
y = x * x

fig = plt.figure()
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)

ax1.plot(x,y)

ax2.plot(x, np.sqrt(y))
ax2.set_yticks([2,4,6,8,10,12,14])
ax2.set_yticklabels(['4','16','36','64','100','144','196'])

answered Feb 16, 2017 at 17:10

Jan Kuiken's user avatar

Jan Kuiken

16 silver badges17 bronze badges

Use matplotlib.scale.FuncScale. It’s essentially a one liner, taking the scale function and its inverse. You can add custom ticks and etc later, if you want it to look good:

import matplotlib
import matplotlib.pyplot as plt

# Start a figure.
ax: plt.Axes
fig: plt.Figure
fig, ax = plt.subplots(1, 1)

# Set the y axis scale of the figure to a sqrt scale.
func = lambda e: e**0.5
inv_func = lambda e: e**2
ax.set_yscale(matplotlib.scale.FuncScale(ax, (func, inv_func)))

# Demonstrate.
xs = [1, 2, 3, 4, 5]
ys = [1, 4, 64, 16, 25]
ax.plot(xs, ys)
plt.show()

enter image description here

answered May 29 at 23:06

Craig Gidney's user avatar

Craig Gidney

5 gold badges68 silver badges136 bronze badges

Matplotlib now offers a powlaw norm. Thus setting power to 0.5 should do the trick!

C.f. Matplotlib Powerlaw norm

And their example:

"""
Demonstration of using norm to map colormaps onto data in non-linear ways.
"""

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from matplotlib.mlab import bivariate_normal

N = 100
X, Y = np.mgrid[-3:3:complex(0, N), -2:2:complex(0, N)]

'''
PowerNorm: Here a power-law trend in X partially obscures a rectified
sine wave in Y. We can remove gamma to 0.5 should do the trick using  PowerNorm.
'''
X, Y = np.mgrid[0:3:complex(0, N), 0:2:complex(0, N)]
Z1 = (1 + np.sin(Y * 10.)) * X**(2.)

fig, ax = plt.subplots(2, 1)

pcm = ax[0].pcolormesh(X, Y, Z1, norm=colors.PowerNorm(gamma=1./2.),
                       cmap='PuBu_r')
fig.colorbar(pcm, ax=ax[0], extend='max')

pcm = ax[1].pcolormesh(X, Y, Z1, cmap='PuBu_r')
fig.colorbar(pcm, ax=ax[1], extend='max')
fig.show()

answered Jun 4, 2018 at 9:06

Sebastiano1991's user avatar

1 gold badge10 silver badges25 bronze badges

This a simple way to graph sqrt(x)

import numpy as np
from matplotlib import pyplot as plt

plt.rcParams["figure.dpi"] = 140

fig, ax = plt.subplots()
ax.spines["left"].set_position("zero")
ax.spines["bottom"].set_position("zero")
ax.spines["right"].set_color("none")
ax.spines["top"].set_color("none")
ax.xaxis.set_ticks_position("bottom")
ax.yaxis.set_ticks_position("left")

origin = [0, 0]

# 45
plt.plot(
    np.linspace(0, 1, 1000),
    np.sqrt(np.linspace(0, 1, 1000)),
    color="k",
)

ax.set_aspect("equal")
plt.xlim(-0.25, 1)
plt.ylim(0, 1)
plt.yticks(ticks=np.linspace(0, 1, 6))
plt.show()

sqrt(x)

answered Oct 21, 2020 at 23:30

Дополнительно:  Пропала Панель задач на Рабочем столе Windows 10: почему исчезла и как вернуть

Daniel Cárdenas's user avatar

Я делаю 2d — программу, которая стоит график движения тела, брошенного под углом к горизонту. Для этого я использую Tkinter и Matplotlib.

Я никак не могу найти способ вывести Canvas(холст) tkinter и график так, чтобы холст был слева, а график — справа (и консоль интерактивного управления просмотром графика — также справа — под графиком, а не под всем приложением).

При этом мне важно, чтобы всё было упаковано методом grid. Пока мне удалось собрать их упаковщиком pack().

введите сюда описание изображения

from tkinter import *

from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)
# Implement the default Matplotlib key bindings.
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
import numpy as np
from math import *

root = Tk()
root.title("Embedding in Tk")

canvas0 = Canvas(root, width = 500, height = 500,
                bg = 'blue', bd = 0,
                borderwidth = 0,
                highlightthickness = 0) 
#canvas0.grid(row=0, column=1, pady=0) 
#Входные и расчётные данные
#U = float(input("U = "))
#a = float(input("a = "))
U = 200
a = 30
PI = 3.14
a1 = (PI * float(a)) / 180
g = 9.8
L = U*U*sin(2*a1)/g 

fig = Figure(figsize=(6, 5), dpi=100) #Размеры графика

x = np.linspace(0, L, 100)

fig.add_subplot(111).plot(x, x*sin(a1)/cos(a1)-x*x*9.8/2/U/U/cos(a1)/cos(a1)) #111 - положение



canvas = FigureCanvasTkAgg(fig, master=root)  # A tk.DrawingArea.
canvas.draw()
canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)

toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)

canvas0.pack(side=TOP, fill=BOTH, expand=1)

I am trying to plot a ROOT 2D histogram with rootpy and matplotlib.

The code I use for this is:

from rootpy.io import File
from rootpy.plotting import Hist
import rootpy.plotting.root2matplotlib as rplt
import matplotlib.pyplot as plt
inputFile = File('mydata.root', 'read')
h_response = inputFile.myfolder.response

plt.figure(figsize=(16, 10), dpi=100)
rplt.hist(h_response, label='response matrix')
h_response.Draw()
plt.xlabel('reconstructed $E_{\mathrm{T}}^{miss}$')
plt.ylabel('Generated $E_{\mathrm{T}}^{miss}$')
plt.title('Response Matrix')
plt.savefig('ResponseMatrix.png')

However, this leaves me with the error msg:

Traceback (most recent call last):
  File "/storage/Dropbox/Workspace/Analysis/DailyPythonScripts/src/unfolding.py", line 66, in <module>
    rplt.hist(h_response, label='response matrix')
  File "/usr/local/lib/python2.7/dist-packages/rootpy-0.7.0_a0-py2.7-linux-x86_64.egg/rootpy/plotting/root2matplotlib.py", line 140, in hist
    snap_zero=snap_zero)
  File "/usr/local/lib/python2.7/dist-packages/rootpy-0.7.0_a0-py2.7-linux-x86_64.egg/rootpy/plotting/root2matplotlib.py", line 82, in _set_bounds
    ywidth = ymax - ymin
TypeError: unsupported operand type(s) for -: 'list' and 'list'

Obviously I am using the wrong rootpy2matplotlib module, so I had a look:
The module provides: hist, bar and errorbar functions — no specific for >= 2D.

Дополнительно:  SD-карта не отображается в проводнике Windows 10

Am I missing something? Is there an easy workaround?

PS: I would like to tag this question with a ‘rootpy’ tag, but it is not possible. So I apologise, since this question is quite specific.

Оцените статью
Master Hi-technology
Добавить комментарий