Interpolation between two values using python - numpy

I am trying to perform a linear interpolation in Python from a graph which have coordinate values say (x1,y1) and (x2,y2). According to my values I will get a straight line in the graph as in this figure
My aim is at 10^6(x-axis value) should give me the value of the parameter on y-axis but presently i am getting the extrapolate value not on the line.
Required Output:OUtput needed
I tried with below Code
import matplotlib.pyplot as plt
import math
import numpy as np
x = np.array([1, 10000000])
y = np.array([0.65, 0.25])
BK = np.asarray(np.interp(0.7,x,y))
print("aa:",BK)
plt.xscale("log")
plt.plot(x,y)
plt.plot(1000000,BK, marker="o",markersize=10)
plt.plot([1000000,1000000,0],[0,BK,BK], "b--", linewidth=1)
plt.xlim(1, 100000000)
plt.ylim(0, 1)
plt.show()

Note that the line drawn in the chart is completely unrelated to the data because it is a line in the chart, not in data coordinates. An interpolation of that line hence has zero meaning!
If you still want to interpolate that line you first need to transform to logspace:
import matplotlib.pyplot as plt
import numpy as np
x = np.array([1, 10000000])
y = np.array([0.65, 0.25])
xinp = 1e6
BK = np.asarray(np.interp(np.log(xinp), np.log(x), y))
print("aa:",BK)
plt.xscale("log")
plt.plot(x,y)
plt.plot(xinp, BK, marker="o",markersize=10)
plt.plot([1000000,1000000,0],[0,BK,BK], "b--", linewidth=1)
plt.xlim(1, 100000000)
plt.ylim(0, 1)
plt.show()

Related

same colorbar/colormap for all subplots [duplicate]

I want to make 4 imshow subplots but all of them share the same colormap. Matplotlib automatically adjusts the scale on the colormap depending on the entries of the matrices. For example, if one of my matrices has all entires as 10 and the other one has all entries equal to 5 and I use the Greys colormap then one of my subplots should be completely black and the other one should be completely grey. But both of them end up becoming completely black. How to make all the subplots share the same scale on the colormap?
To get this right you need to have all the images with the same intensity scale, otherwise the colorbar() colours are meaningless. To do that, use the vmin and vmax arguments of imshow(), and make sure they are the same for all your images.
E.g., if the range of values you want to show goes from 0 to 10, you can use the following:
import pylab as plt
import numpy as np
my_image1 = np.linspace(0, 10, 10000).reshape(100,100)
my_image2 = np.sqrt(my_image1.T) + 3
plt.subplot(1, 2, 1)
plt.imshow(my_image1, vmin=0, vmax=10, cmap='jet', aspect='auto')
plt.subplot(1, 2, 2)
plt.imshow(my_image2, vmin=0, vmax=10, cmap='jet', aspect='auto')
plt.colorbar()
When the ranges of data (data1 and data2) sets are unknown and you want to use the same colour bar for both/all plots, find the overall minimum and maximum to use as vmin and vmax in the call to imshow:
import numpy as np
import matplotlib.pyplot as plt
fig, axes = plt.subplots(nrows=1, ncols=2)
# generate randomly populated arrays
data1 = np.random.rand(10,10)*10
data2 = np.random.rand(10,10)*10 -7.5
# find minimum of minima & maximum of maxima
minmin = np.min([np.min(data1), np.min(data2)])
maxmax = np.max([np.max(data1), np.max(data2)])
im1 = axes[0].imshow(data1, vmin=minmin, vmax=maxmax,
extent=(-5,5,-5,5), aspect='auto', cmap='viridis')
im2 = axes[1].imshow(data2, vmin=minmin, vmax=maxmax,
extent=(-5,5,-5,5), aspect='auto', cmap='viridis')
# add space for colour bar
fig.subplots_adjust(right=0.85)
cbar_ax = fig.add_axes([0.88, 0.15, 0.04, 0.7])
fig.colorbar(im2, cax=cbar_ax)
It may be that you don't know beforehand the ranges of your data, but you may know that somehow they are compatible. In that case, you may prefer to let matplotlib choose those ranges for the first plot and use the same range for the remaining plots. Here is how you can do it. The key is to get the limits with properties()['clim']
import numpy as np
import matplotlib.pyplot as plt
my_image1 = np.linspace(0, 10, 10000).reshape(100,100)
my_image2 = np.sqrt(my_image1.T) + 3
fig, axes = plt.subplots(nrows=1, ncols=2)
im = axes[0].imshow(my_image1)
clim=im.properties()['clim']
axes[1].imshow(my_image2, clim=clim)
fig.colorbar(im, ax=axes.ravel().tolist(), shrink=0.5)
plt.show()

Visualize 1-dimensional data in a sequential colormap

I have a pandas series containing numbers ranging between 0 and 100. I want to visualise it in a horizontal bar consisting of 3 main colours.
I have tried using seaborn but all I can get is a heatmap matrix. I have also tried the below code, which is producing what I need but not in the way I need it.
x = my_column.values
y = x
t = x
fig, (ax1, ax2) = plt.subplots(1, 2)
ax1.scatter(x, y, c=t, cmap='brg')
ax2.scatter(x, y, c=t, cmap='brg')
plt.show()
What I'm looking for is something similar to the below figure, how can I achieve that using matplotlib or seaborn?
The purpose of this is not quite clear, however, the following would produce an image like the one shown in the question:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
x = np.linspace(100,0,101)
fig, ax = plt.subplots(figsize=(6,1), constrained_layout=True)
cmap = LinearSegmentedColormap.from_list("", ["limegreen", "gold", "crimson"])
ax.imshow([x], cmap=cmap, aspect="auto",
extent=[x[0]-np.diff(x)[0]/2, x[-1]+np.diff(x)[0]/2,0,1])
ax.tick_params(axis="y", left=False, labelleft=False)
plt.show()

LogFormatter tickmarks scientific format limits

I'm trying to plot over a wide range with a log-scaled axis, but I want to show 10^{-1}, 10^0, 10^1 as just 0.1, 1, 10. ScalarFormatter will change everything to integers instead of scientific notation, but I'd like most of the tickmark labels to be scientific; I'm only wanting to change a few of the labels. So the MWE is
import numpy as np
import matplotlib as plt
fig = plt.figure(figsize=[7,7])
ax1 = fig.add_subplot(111)
ax1.set_yscale('log')
ax1.set_xscale('log')
ax1.plot(np.logspace(-4,4), np.logspace(-4,4))
plt.show()
and I want the middle labels on each axis to read 0.1, 1, 10 instead of 10^{-1}, 10^0, 10^1
Thanks for any help!
When setting set_xscale('log'), you're using a LogFormatterSciNotation (not a ScalarFormatter). You may subclass LogFormatterSciNotation to return the desired values 0.1,1,10 if they happen to be marked as ticks.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import LogFormatterSciNotation
class CustomTicker(LogFormatterSciNotation):
def __call__(self, x, pos=None):
if x not in [0.1,1,10]:
return LogFormatterSciNotation.__call__(self,x, pos=None)
else:
return "{x:g}".format(x=x)
fig = plt.figure(figsize=[7,7])
ax = fig.add_subplot(111)
ax.set_yscale('log')
ax.set_xscale('log')
ax.plot(np.logspace(-4,4), np.logspace(-4,4))
ax.xaxis.set_major_formatter(CustomTicker())
plt.show()
Update: With matplotlib 2.1 there is now a new option
Specify minimum value to format as scalar for LogFormatterMathtext
LogFormatterMathtext now includes the option to specify a minimum value exponent to format as a scalar (i.e., 0.001 instead of 10-3).
This can be done as follows, by using the rcParams (plt.rcParams['axes.formatter.min_exponent'] = 2):
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['axes.formatter.min_exponent'] = 2
fig = plt.figure(figsize=[7,7])
ax = fig.add_subplot(111)
ax.set_yscale('log')
ax.set_xscale('log')
ax.plot(np.logspace(-4,4), np.logspace(-4,4))
plt.show()
This results in the same plot as above.
Note however that this limit is symmetric, it would not allow to set only 1 and 10, but not 0.1. Hence the initial solution is more generic.

Matplotlib cmap values must be between 0-1

I am having trouble with the code below:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
from pylab import *
import sys
s = (('408b2e00', '24.21'), ('408b2e0c', '22.51'), ('4089e04a', '23.44'), ('4089e04d', '24.10'))
temp = [x[1] for x in s]
print temp
figure(figsize=(15, 8))
pts = [(886.38864047695108, 349.78744809964849), (1271.1506973277974, 187.65500904929195), (1237.272277227723, 860.38363675077176), (910.58751197700428, 816.82566805067597)]
x = map(lambda x: x[0],pts) # Extract the values from pts
y = map(lambda x: x[1],pts)
t = temp
result = zip(x,y,t)
img = mpimg.imread('floor.png')
imgplot = plt.imshow(img, cmap=cm.hot)
scatter(x, y, marker='h', c=t, s=150, vmin=-20, vmax=40)
print t
# Add cmap
colorbar()
show()
Given the temperature in s - I am trying to set the values of the cmap so I can use temperatures between -10 and 30 instead of having to used values between 1 and 0. I have set the vmin and vmax values but it still gives me the error below:
ValueError: to_rgba: Invalid rgba arg "23.44" to_rgb: Invalid rgb arg "23.44" gray (string) must be in range 0-1
I have use earlier code to simplify the problem and have been successful. This example below works and shows what I am trying to (hopefully) do:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import numpy as np
from pylab import *
figure(figsize=(15, 8))
# use ginput to select markers for the sensors
matplotlib.pyplot.hot()
markers = [(269, 792, -5), (1661, 800, 20), (1017, 457, 30)]
x,y,t = zip(*markers)
img = mpimg.imread('floor.png')
imgplot = plt.imshow(img, cmap=cm.hot)
scatter(x, y, marker='h', c=t, s=150, vmin=-10, vmax=30)
colorbar()
show()
Any ideas why only the second solution works? I am working with dynamic values i.e inputs from mysql and user selected points and so the first solution would be much easier to get working later on (the rest of that code is in this question: Full program code )
Any help would be great. Thanks!
You are handing in strings instead of floats, change this line:
temp = [float(x[1]) for x in s]
matplotlib tries to be good about guessing what you mean and lets you define gray as a string of a float between [0, 1] which is what it is trying to do with your string values (and complaining because it is not in than range).

Scatter plot with scalar data

I want to create a scatter plot with matplotlib where the data points have scalar data attached to them and are assigned a color depending on how large their attached value is relative to the other points in the set. I.e., I want something akin to a heatmap. However, I'm looking for a "discrete" heatmap, i.e. nothing should be ploted where there were no points in the original data set and, in particular, no interpolation (in space) should be performed.
Can this be done?
you can use scatter, and set the attached value to c parameter:
import numpy as np
import pylab as pl
x = np.random.uniform(-1, 1, 1000)
y = np.random.uniform(-1, 1, 1000)
z = np.sqrt(x*x+y*y)
pl.scatter(x, y, c=z)
pl.colorbar()
pl.show()
Solving this in Altair.
import numpy as np
import pylab as pl
x = np.random.uniform(-1, 1, 1000)
y = np.random.uniform(-1, 1, 1000)
z = np.sqrt(x*x+y*y)
df = pd.DataFrame({'x':x,'y':y, 'z':z})
from altair import *
Chart(df).mark_circle().encode(x='x',y='y', color='z')