The number 1.67845714e-12 is an important result from my physics project. I want to plot graphs where the y-axis limit revolves around this result as a scaling factor.
In the following example:
import numpy as np
import matplotlib.pyplot as plt
plt.ion()
import random
x = np.arange(0,100)
y = np.zeros(len(x))
for i in range(len(x)):
y[i] = 1.67845714e-12*random.random() - (4.20e-14)*x[i]
plt.ylim(float(-3*1.67845714e-12), float(3*1.67845714e-12)) #The important line
plt.plot(x,y)
The resulting plot has a y-axis going from -5*e-12
to 5*e-12
, instead of a y-axis going from -3*1.67845714e-12
to 3*1.67845714e-12
How can I get Matplotlib to display the step of 1.67845714e-12
on the top left corner of the graph with a scale of -3 to 3 displayed on the y axis like I intended? And if this is impossible because for example, the step is too long, can I give my step a nickname (such as "Result") to make this work?
I've tried using other commands like ax.set_yticks()
, ax=plt.gta()
or ax.set_ylim()
but nothing I've searched seems to work.
I am trying to answer based on what I understood you wanted to do. As I see it, you want to have a y
axis from -3*1.67845714e-12
up until 3*1.67845714e-12
but each step/tick would be of size 1.67845714e-12
.
Note I created a variable named scalingFactor
to hold 1.67845714e-12
. I think this answers one of your questions. You can use it then instead of writing the whole number.
Ok, to generate the ticks so you can use numpy.arange(inf, sup, step)
function. It returns evenly spaced values within a given interval [inf;sup)
. So we are going to generate ticks from -3*scalingFactor
up until 3*scalingFactor
using a 1.67845714e-12
step. You may notice in the code that sup=4*scalingFactor
. It is because numpy.arange()
exclude the upper limit of the interval.
To get the whole number on the axis and not rounded, you can force it to have 8 decimal places using plt.gca().yaxis.set_major_formatter(mtick.FormatStrFormatter('%.8e'))
. This function formats the labels for the ticks of the axis and it uses in this case this string format %.8e
.
import numpy as np
import matplotlib.pyplot as plt
plt.ion()
import random
import matplotlib.ticker as mtick
x = np.arange(0,100)
y = np.zeros(len(x))
scalingFactor = 1.67845714e-12
for i in range(len(x)):
y[i] = scalingFactor*random.random() - (4.20e-14)*x[i]
inf = -3*scalingFactor
sup = 4*scalingFactor
plt.plot(x, y)
plt.ylim(inf, sup)
plt.yticks(np.arange(inf, sup, scalingFactor))
plt.subplots_adjust(left=0.24) # Squash the plot from the left so the ticks labels can be seen
plt.gca().yaxis.set_major_formatter(mtick.FormatStrFormatter('%.8e'))
plt.show()
Outputs
EDIT: Well, I was actually, in fact, struggling with what you wanted cause I've never needed to do that. However I came up with a very ad-hoc solution for your problem based on what you needed cause it seems all of your data would be in that range and you wanted a scaling factor of 1.67845714e-12
.
There are formatter classes that can format tick values and handle offset value (the scale value on top left corner). So we can create a ModScalarFormatter
that inherits from ScalarFormatter
and override some functions to set manually the offset and ticks we want without letting matplotlib
computing it:
import numpy as np
import matplotlib.pyplot as plt
plt.ion()
import random
import math
import matplotlib.ticker as mtick
class ModScalarFormatter(mtick.ScalarFormatter):
def __init__(self, useOffset=None, useMathText=None, useLocale=None):
mtick.ScalarFormatter.__init__(self, useOffset, useMathText, useLocale)
# Create the ticks we want
self.ticks = [i for i in range(-3, 4)]
def _set_offset(self, text):
self.offset = text # Set the offset text we want
def get_offset(self, txt=''):
return self.offset # Return the offset value
def __call__(self, x, pos=None):
# The __call__ returns the tick on position `pos` from the
# ticks we specified
return self.ticks[pos]
x = np.arange(0,100)
y = np.zeros(len(x))
scalingFactor = 1.67845714e-12
for i in range(len(x)):
y[i] = scalingFactor*random.random() - (4.20e-14)*x[i]
inf = -3*scalingFactor
sup = 3*scalingFactor
plt.plot(x, y)
plt.yticks(np.linspace(inf, sup, 7))
# Create and use a Custom Scalar Formatter Class
sf = ModScalarFormatter(useOffset=1.67845714e-12)
plt.gca().yaxis.set_major_formatter(sf)
plt.ylim(inf, sup)
plt.show()
NOTE : I am pretty sure there should be a more elegant way to achieve this, but this is my way of helping you with and ad-hoc solution for your specific problem.
Hope this helps.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.