how to multiply axis values by a factor of 100 - matplotlib

Both x and y scale values in this plot should be multiplied by 100.So that x-axis and y-axis values should be 0 2500 5000 7500 10000 12500 15000 17500 20000
My plot remains unchanged even after multiplying the data by that factor.
Input data https://www.file.io/GAYM/download/dDB51UAJdAG5
My code
import matplotlib.pyplot as plt
import numpy as np
data=np.loadtxt("input.txt")
plt.imshow(100*data,cmap='jet', interpolation='none')
plt.show()

Multiplying the data doesn't help because your data only includes the pixel values but not the coordinates.
A quick and dirty hack is to modify the tick formatter:
def formatter(x, pos):
del pos
return str(x*100)
ax.xaxis.set_major_formatter(formatter)
ax.yaxis.set_major_formatter(formatter)
A more proper way is to use the extent keyword argument as explained in this tutorial but I don't have time right now to tailor that to turn that into an answer to your question. Maybe someone else (or you) does.

Related

How to show min and max values at the end of the axes

I generate plots like below:
from pylab import *
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker
import matplotlib.ticker as ticker
rcParams['axes.linewidth'] = 2 # set the value globally
rcParams['font.size'] = 16# set the value globally
rcParams['font.family'] = ['DejaVu Sans']
rcParams['mathtext.fontset'] = 'stix'
rcParams['legend.fontsize'] = 24
rcParams['axes.prop_cycle'] = cycler(color=['grey','b','g','r','orange'])
rc('lines', linewidth=2, linestyle='-',marker='o')
rcParams['axes.xmargin'] = 0
rcParams['axes.ymargin'] = 0
t = arange(0,21,1)
v = 2.0
s = v*t
plt.figure(figsize=(12, 4))
plt.plot(t,s,label='$s=%1.1f\cdot t$'%v)
plt.title('Wykres drogi w czasie $s=v\cdot t$')
plt.xlabel('Czas $t$, s')
plt.ylabel('Droga $s$, m')
plt.autoscale(enable=True, axis='both', tight=None)
legend(loc='best')
plt.xlim(min(t),max(t))
plt.ylim(min(s),max(s))
plt.grid()
plt.show()
When I am changing the value t = arange(0,21,1) for example to t = arange(0,20,1) which gives me for example on the x axis max value= 19.0 my max value dispirs from the x axis. The same situation is of course with y axis.
My question is how to force matplotlib to produce always plots where on the axes are max values just at the end of the axes like should be always for my purposes or should be possible to chose like an option?
Imiage from my program in Fortan I did some years ago
Matplotlib is more efficiens that I use it but there should be an opition like that (the picture above).
In this way I can always observe max min in text windows or do take addiional steps to make sure about max min values. I would like to read them from axes and the question is ...Are there such possibilites in mathplotlib ??? If not I will close the post.
Axes I am thinking about more or less
I see two ways to solve the problem.
Set the axes automatic limit mode to round numbers
In the rcParams you can do this with
rcParams['axes.autolimit_mode'] = 'round_numbers'
And turn off the manual axes limits with min and max
plt.xlim(min(t),max(t))
plt.ylim(min(s),max(s))
This will produce the image below. Still, the extreme values of the axes are shown at the nearest "round numbers", but the user can approximately catch the data range limits. If you need the exact value to be displayed, you can see the second solution which cannot be directly used from the rcParams.
or – Manually generate axes ticks
This solution implies explicitly asking for a given number of ticks. I guess there is a way to automatize it depending on the axes size etc. But if you are dealing with more or less every time the same graph size, you can decide a fixed number of ticks manually. This can be done with
plt.xlim(min(t),max(t))
plt.ylim(min(s),max(s))
plt.xticks(np.linspace(t.min(), t.max(), 7)) # arbitrary chosen
plt.yticks(np.linspace(s.min(), s.max(), 5)) # arbitrary chosen
generated the image below, quite similar to your image example.

Add more deciamals to matplotlib chart?

Simple question and I tried a quick search before posting but could not find. I am trying to do a chart and axis Y consists of price.
However Y is scaled like attached image and has only 1 decimal. How do I make y axis more precise with 2 decimals and more entries with increment of 0.01?
::Update with code::
# Make the plot
fig, ax = plt.subplots(figsize=(48,32))
ax.scatter(x=times, y=tidy['Price'], c=colors, s=tidy['Volume'] / 4000, alpha=0.4)
ax.ticklabel_format(axis='y', style='plain')
ax.set(
xlabel='Time',
xlim=(xmin, xmax),
ylabel='Price'
)
ax.xaxis.set_major_formatter(DateFormatter('%H:%M'))
One method to increase the number of decimals is to use a formatter for your axis:
from matplotlib.ticker import FormatStrFormatter
ax.yaxis.set_major_formatter(FormatStrFormatter('%.2f'))
However, this method will not increase the number of ticks on your axis. You can set the yticks with .01 increments using the following but you might end up over-saturating the axis might want to increase the increment size.
ax.set_yticks(np.arange(108.30,108.71,.01))

Cubic spline interpolation drops out halfway

I am trying to make a cubic spline interpolation and for some reason, the interpolation drops off in the middle of it. It's very mysterious and I can't find any mention of similar occurrences anywhere online.
This is for my dissertation so I have excluded some labels etc. to keep it obscure intentionally, but all the relevant code is as follows. For context, this is an astronomy related plot.
from scipy.interpolate import CubicSpline
import numpy as np
import matplotlib.pyplot as plt
W = np.array([0.435,0.606,0.814,1.05,1.25,1.40,1.60])
sum_all = np.array([sum435,sum606,sum814,sum105,sum125,sum140,sum160])
sum_can = np.array([sumc435,sumc606,sumc814,sumc105,sumc125,sumc140,sumc160])
fall = CubicSpline(W,sum_all)
newallx=np.arange(0.435,1.6,0.001)
newally=fall(newallx)
fcan = CubicSpline(W,sum_can)
newcanx=np.arange(0.435,1.6,0.001)
newcany=fcan(newcanx)
#----plot
plt.plot(newallx,newally)
plt.plot(newcanx,newcany)
plt.plot(W,sum_all,marker='o',color='r',linestyle='')
plt.plot(W,sum_can,marker='o',color='b',linestyle='')
plt.yscale("log")
plt.ylabel("Flux S$_v$ [erg s$^-$$^1$ cm$^-$$^2$ Hz$^-$$^1$]")
plt.xlabel("Wavelength [n$\lambda$]")
plt.show()
The plot that I get from that comes out like this, with a clear gap in the interpolation:
And in case you are wondering, these are the values in the sum_all and sum_can arrays (I assume it doesn't matter, but just in case you want the numbers to plot it yourself):
sum_all:
[ 3.87282732e+32 8.79993191e+32 1.74866333e+33 1.59946687e+33
9.08556547e+33 6.70458731e+33 9.84832359e+33]
can_all:
[ 2.98381061e+28 1.26194810e+28 3.30328780e+28 2.90254609e+29
3.65117723e+29 3.46256846e+29 3.64483736e+29]
The gap happens between [0.606,1.26194810e+28] and [0.814,3.30328780e+28]. If I change the intervals from 0.001 to something higher, it's obvious that the plot doesn't actually break off but merely dips below 0 on the y-axis (but the plot is continuous). So why does it do that? Surely that's not a correct interpolation? Just looking with our eyes, that's clearly not a well-interpolated connection between those two points.
Any tips or comments would be extremely appreciated. Thank you so much in advance!
The reason for the breakdown can be better observed on a linear scale.
We see that the spline actually passes below 0, which is undefined on a log scale.
So I would suggest to first take the logarithm of the data, perform the spline interpolation on the logarithmically scaled data, and then scale back by the 10th power.
from scipy.interpolate import CubicSpline
import numpy as np
import matplotlib.pyplot as plt
W = np.array([0.435,0.606,0.814,1.05,1.25,1.40,1.60])
sum_all = np.array([ 3.87282732e+32, 8.79993191e+32, 1.74866333e+33, 1.59946687e+33,
9.08556547e+33, 6.70458731e+33, 9.84832359e+33])
sum_can = np.array([ 2.98381061e+28, 1.26194810e+28, 3.30328780e+28, 2.90254609e+29,
3.65117723e+29, 3.46256846e+29, 3.64483736e+29])
fall = CubicSpline(W,np.log10(sum_all))
newallx=np.arange(0.435,1.6,0.001)
newally=fall(newallx)
fcan = CubicSpline(W,np.log10(sum_can))
newcanx=np.arange(0.435,1.6,0.01)
newcany=fcan(newcanx)
plt.plot(newallx,10**newally)
plt.plot(newcanx,10**newcany)
plt.plot(W,sum_all,marker='o',color='r',linestyle='')
plt.plot(W,sum_can,marker='o',color='b',linestyle='')
plt.yscale("log")
plt.ylabel("Flux S$_v$ [erg s$^-$$^1$ cm$^-$$^2$ Hz$^-$$^1$]")
plt.xlabel("Wavelength [n$\lambda$]")
plt.show()

matplotlib: preventing a few very large (or small) values to affect my contour

in plotting the data some times there are a few very large (or very small) numbers which, if not taken care of, will affect the contour in a bad way. a solution is to take out the 10% highest and lowest data out of the contour color grading and considering them as less than and more than. the following figure shows the idea:
the two arrow shapes on the top and the bottom of the bar support this idea. any value above 14 will be shown in white and any value below -2 will be shown in black color. how is it possible in matplotlib?
How can I define:
- to put the 5% of highest values and 5% of lowest values in two categories shown in the triangular parts in both ends of the bar? (Should I define it the contour operation or are there other ways?)
- what if I want to give certain values instead of the percentage? for instance, ask to put any value above 14 on the white triangule and any value below -2 as black areas?
Thank you so much for your help.
Taken from http://matplotlib.org/examples/api/colorbar_only.html. You can play with it and you will see if it could solve your problem.
import matplotlib.pyplot as plt
from matplotlib import mpl
import numpy as np
x = np.linspace(-1,1,100)
X,Y = np.meshgrid(x,x)
Z = np.exp(-X**2-Y**2)
vmin = 0.3 #Lower value
vmax = 0.9 #Upper value
bounds = np.linspace(vmin,vmax,4)
cmap = mpl.colors.ListedColormap([(0,0,0),(0.5,0.5,0.5),(0,1,0),(1,1,1)])
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
plt.imshow(Z,cmap=cmap,interpolation='nearest',vmin=vmin,vmax=vmax)
ax = plt.colorbar().ax
cb = mpl.colorbar.ColorbarBase(ax, norm=norm,
extend='both',
cmap=cmap)
cmap.set_over([0,0,1])
cmap.set_under([1,0,0])
plt.show()

matplotlib intelligent axis labels for timedelta

I have a simple dataset of X and Y values I am plotting in matplotlib. The independent variable in my data is a duration/timedelta (e.g. 60 seconds, 2 hours, 24 hours, 10 days), which in my input data is always represented as an integer number of seconds. My question is, does matplotlib have any way of setting the duration axis labels intelligently, in a human readable form?
For example, at the small end of the scale, it would be desirable to show say 30 seconds simply as "30 seconds". At the large end of the scale, it would be nicer to show "10 days" rather than 864000 seconds. Somewhere in between, it would be better to have the labels read in "minutes" and "hours". Does matplotlib have any automated way of inferring something approximately human readable for durations spanning several orders of magnitude?
Ideally whatever approach I use should generalize to datasets that span different duration timescales, rather than a plot that is individually tailored to one input dataset.
Could you provide an example? Is this what you want:
import datetime
import numpy as np
import pylab as plt
import matplotlib
fig = plt.figure()
ax = fig.add_subplot(111)
x = np.linspace(0, 300) # 5 minutes
y = np.random.random(len(x))
ax.plot(x, y)
def timeTicks(x, pos):
d = datetime.timedelta(seconds=x)
return str(d)
formatter = matplotlib.ticker.FuncFormatter(timeTicks)
ax.xaxis.set_major_formatter(formatter)
plt.show()
It uses pythons timedelta. With 864000 seconds the above will result in "10 days, 10:00:00". You can of course stuff more advanced formatting into the timeTicks() function above.