Wrap around continuous colormap in matplotlib [duplicate] - python
I'm looking for a good circular/cyclic colormap to represent phase angle information (where the values are restricted to the range [0, 2π] and where 0 and 2π represent the same phase angle).
Background: I'd like to visualize normal modes by plotting both the power spectral density and the relative phase information of the oscillations across the system.
I'll admit that previously I used the 'rainbow' colormap for the power plot and the 'hsv' colormap for the phase plot (see [1]). However, the use of the rainbow colormap is extremely discouraged because of its lack of perceptual linearity and ordering [2][3]. So I switched to the 'coolwarm' colormap for the power plot which I quite like. Unfortunately, the 'hsv' colormap seems to introduce the same kind of visual distortions as the 'rainbow' map (and it also doesn't go along very well with the 'coolwarm' map since it looks kind of ugly and flashy in comparison).
Does anyone have a good recommendation for an alternative circular colormap which I could use for the phase plots?
Requirements:
It needs to be circular so that the values 0 and 2π are represented by the same color.
It should not introduce any visual distortions; in particular, it should be perceptually linear (which the 'hsv' colormap doesn't seem to be). I don't believe that perceptual ordering is such a big deal for phase information, but it would of course not do any harm.
It should be visually appealing when combined with the 'coolwarm' colormap. However, I'm not dead set on 'coolwarm' and am happy to consider other options if there is another nice pair of colormaps to visualize amplitude and phase information.
Bonus points if the colormap is available (or can be easily created) for use in matplotlib.
Many thanks for any suggestions!
[1] http://matplotlib.org/examples/color/colormaps_reference.html
[2] http://www.renci.org/~borland/pdfs/RainbowColorMap_VisViewpoints.pdf
[3] http://medvis.org/2012/08/21/rainbow-colormaps-what-are-they-good-for-absolutely-nothing/
As of matplotlib version 3.0 there are built-in cyclic perceptually uniform colormaps. OK, just the one colormap for the time being, but with two choices of start and end along the cycle, namely twilight and twilight_shifted.
A short example to demonstrate how they look:
import matplotlib.pyplot as plt
import numpy as np
# example data: argument of complex numbers around 0
N = 100
re, im = np.mgrid[-1:1:100j, -1:1:100j]
angle = np.angle(re + 1j*im)
cmaps = 'twilight', 'twilight_shifted'
fig, axs = plt.subplots(ncols=len(cmaps), figsize=(9.5, 5.5))
for cmap, ax in zip(cmaps, axs):
cf = ax.pcolormesh(re, im, angle, shading='gouraud', cmap=cmap)
ax.set_title(cmap)
ax.set_xlabel(r'$\operatorname{Re} z$')
ax.set_ylabel(r'$\operatorname{Im} z$')
ax.axis('scaled')
cb = plt.colorbar(cf, ax=ax, orientation='horizontal')
cb.set_label(r'$\operatorname{Arg} z$')
fig.tight_layout()
The above produces the following figure:
These brand new colormaps are an amazing addition to the existing collection of perceptually uniform (sequential) colormaps, namely viridis, plasma, inferno, magma and cividis (the last one was a new addition in 2.2 which is not only perceptually uniform and thus colorblind-friendly, but it should look as close as possible to colorblind and non-colorblind people).
EDIT: Matplotlib has now nice cyclic color maps, see the answer of #andras-deak below. They use a similar approach to the color maps as in this answer, but smooth the edges in luminosity.
The issue with the hue-HUSL colormap is that it's not intuitive to read an angle from it. Therefore, I suggest to make your own colormap. Here's a few possibilities:
For the linear segmented colormap, we definine a few colors. The colormap is then a linear interpolation between the colors. This has visual distortions.
For the luminosity-HSLUV map, we use the HUSL ("HSLUV") space, however instead of just hue channel, we use two colors and the luminosity channel. This has distortions in the chroma, but has bright colors.
The luminosity-HPLUV map, we use the HPLUV color space (following #mwaskom's comment). This is the only way to really have no visual distortions, but the colors are not saturated
This is what they look like:
We see that in our custom colormaps, white stands for 0, blue stands for 1i, etc.
On the upper right, we see the hue-HUSL map for comparison. There, the color-angle assignments are random.
Also when plotting a more complex function, it's straightforward to read out the phase of the result when using one of our colormaps.
And here's the code for the plots:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as col
import seaborn as sns
import hsluv # install via pip
import scipy.special # just for the example function
##### generate custom colormaps
def make_segmented_cmap():
white = '#ffffff'
black = '#000000'
red = '#ff0000'
blue = '#0000ff'
anglemap = col.LinearSegmentedColormap.from_list(
'anglemap', [black, red, white, blue, black], N=256, gamma=1)
return anglemap
def make_anglemap( N = 256, use_hpl = True ):
h = np.ones(N) # hue
h[:N//2] = 11.6 # red
h[N//2:] = 258.6 # blue
s = 100 # saturation
l = np.linspace(0, 100, N//2) # luminosity
l = np.hstack( (l,l[::-1] ) )
colorlist = np.zeros((N,3))
for ii in range(N):
if use_hpl:
colorlist[ii,:] = hsluv.hpluv_to_rgb( (h[ii], s, l[ii]) )
else:
colorlist[ii,:] = hsluv.hsluv_to_rgb( (h[ii], s, l[ii]) )
colorlist[colorlist > 1] = 1 # correct numeric errors
colorlist[colorlist < 0] = 0
return col.ListedColormap( colorlist )
N = 256
segmented_cmap = make_segmented_cmap()
flat_huslmap = col.ListedColormap(sns.color_palette('husl',N))
hsluv_anglemap = make_anglemap( use_hpl = False )
hpluv_anglemap = make_anglemap( use_hpl = True )
##### generate data grid
x = np.linspace(-2,2,N)
y = np.linspace(-2,2,N)
z = np.zeros((len(y),len(x))) # make cartesian grid
for ii in range(len(y)):
z[ii] = np.arctan2(y[ii],x) # simple angular function
z[ii] = np.angle(scipy.special.gamma(x+1j*y[ii])) # some complex function
##### plot with different colormaps
fig = plt.figure(1)
fig.clf()
colormapnames = ['segmented map', 'hue-HUSL', 'lum-HSLUV', 'lum-HPLUV']
colormaps = [segmented_cmap, flat_huslmap, hsluv_anglemap, hpluv_anglemap]
for ii, cm in enumerate(colormaps):
ax = fig.add_subplot(2, 2, ii+1)
pmesh = ax.pcolormesh(x, y, z/np.pi,
cmap = cm, vmin=-1, vmax=1)
plt.axis([x.min(), x.max(), y.min(), y.max()])
cbar = fig.colorbar(pmesh)
cbar.ax.set_ylabel('Phase [pi]')
ax.set_title( colormapnames[ii] )
plt.show()
You could try the "husl" system, which is similar to hls/hsv but with better visual properties. It is available in seaborn and as a standalone package.
Here's a simple example:
import numpy as np
from numpy import sin, cos, pi
import matplotlib.pyplot as plt
import seaborn as sns
n = 314
theta = np.linspace(0, 2 * pi, n)
x = cos(theta)
y = sin(theta)
f = plt.figure(figsize=(10, 5))
with sns.color_palette("husl", n):
ax = f.add_subplot(121)
ax.plot([np.zeros_like(x), x], [np.zeros_like(y), y], lw=3)
ax.set_axis_off()
ax.set_title("HUSL space")
with sns.color_palette("hls", n):
ax = f.add_subplot(122)
ax.plot([np.zeros_like(x), x], [np.zeros_like(y), y], lw=3)
ax.set_axis_off()
ax.set_title("HLS space")
f.tight_layout()
I just realized that cmocean has a colormap for this purpose.
import cmocean
import matplotlib.pyplot as plt
import numpy as np
azimuths = np.arange(0, 361, 1)
zeniths = np.arange(40, 70, 1)
values = azimuths * np.ones((30, 361))
fig, ax = plt.subplots(subplot_kw=dict(projection='polar'))
ax.pcolormesh(azimuths*np.pi/180.0, zeniths, values, cmap=cmocean.cm.phase)
ax.set_yticks([])
plt.show()
And the result is
I like the above color maps, but wanted to bootstrap some modern color theory into them. You can get a more perceptually uniform color space by using the CIECAM02 color space.
The colorspacious package is a nice one for converting into this great color space. Using this package, I bootstrapped the above answers into a custom cmap of my own.
from colorspacious import cspace_convert
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as col
import seaborn as sns
# first draw a circle in the cylindrical JCh color space.
# the third channel is hue in degrees. First is lightness and the second chroma
color_circle = np.ones((256,3))*60
color_circle[:,1] = np.ones((256))*45
color_circle[:,2] = np.arange(0,360,360/256)
color_circle_rgb = cspace_convert(color_circle, "JCh","sRGB1")
cm = col.ListedColormap(color_circle_rgb)
##### generate data grid like in above
N=256
x = np.linspace(-2,2,N)
y = np.linspace(-2,2,N)
z = np.zeros((len(y),len(x))) # make cartesian grid
for ii in range(len(y)):
z[ii] = np.arctan2(y[ii],x) # simple angular function
fig = plt.figure()
ax = plt.gca()
pmesh = ax.pcolormesh(x, y, z/np.pi,
cmap = cm, vmin=-1, vmax=1)
plt.axis([x.min(), x.max(), y.min(), y.max()])
cbar = fig.colorbar(pmesh)
cbar.ax.set_ylabel('Phase [pi]')
If you don't want to install the colorspacious package, you can just copy and paste this list of colors, and create a colormap directly:
colors = array([[0.91510904, 0.55114749, 0.67037311],
[0.91696411, 0.55081563, 0.66264366],
[0.91870995, 0.55055664, 0.65485881],
[0.92034498, 0.55037149, 0.64702356],
[0.92186763, 0.55026107, 0.63914306],
[0.92327636, 0.55022625, 0.63122259],
[0.9245696 , 0.55026781, 0.62326754],
[0.92574582, 0.5503865 , 0.6152834 ],
[0.92680349, 0.55058299, 0.6072758 ],
[0.92774112, 0.55085789, 0.59925045],
[0.9285572 , 0.55121174, 0.59121319],
[0.92925027, 0.551645 , 0.58316992],
[0.92981889, 0.55215808, 0.57512667],
[0.93026165, 0.55275127, 0.56708953],
[0.93057716, 0.5534248 , 0.55906469],
[0.93076407, 0.55417883, 0.55105838],
[0.93082107, 0.55501339, 0.54307696],
[0.93074689, 0.55592845, 0.53512681],
[0.9305403 , 0.55692387, 0.52721438],
[0.93020012, 0.55799943, 0.51934621],
[0.92972523, 0.55915477, 0.51152885],
[0.92911454, 0.56038948, 0.50376893],
[0.92836703, 0.56170301, 0.49607312],
[0.92748175, 0.56309471, 0.48844813],
[0.9264578 , 0.56456383, 0.48090073],
[0.92529434, 0.56610951, 0.47343769],
[0.92399062, 0.56773078, 0.46606586],
[0.92254595, 0.56942656, 0.45879209],
[0.92095971, 0.57119566, 0.4516233 ],
[0.91923137, 0.5730368 , 0.44456642],
[0.91736048, 0.57494856, 0.4376284 ],
[0.91534665, 0.57692945, 0.43081625],
[0.91318962, 0.57897785, 0.42413698],
[0.91088917, 0.58109205, 0.41759765],
[0.90844521, 0.58327024, 0.41120533],
[0.90585771, 0.58551053, 0.40496711],
[0.90312676, 0.5878109 , 0.3988901 ],
[0.90025252, 0.59016928, 0.39298143],
[0.89723527, 0.5925835 , 0.38724821],
[0.89407538, 0.59505131, 0.38169756],
[0.89077331, 0.59757038, 0.37633658],
[0.88732963, 0.60013832, 0.37117234],
[0.88374501, 0.60275266, 0.36621186],
[0.88002022, 0.6054109 , 0.36146209],
[0.87615612, 0.60811044, 0.35692989],
[0.87215369, 0.61084868, 0.352622 ],
[0.86801401, 0.61362295, 0.34854502],
[0.86373824, 0.61643054, 0.34470535],
[0.85932766, 0.61926872, 0.3411092 ],
[0.85478365, 0.62213474, 0.3377625 ],
[0.85010767, 0.6250258 , 0.33467091],
[0.84530131, 0.62793914, 0.3318397 ],
[0.84036623, 0.63087193, 0.32927381],
[0.8353042 , 0.63382139, 0.32697771],
[0.83011708, 0.63678472, 0.32495541],
[0.82480682, 0.63975913, 0.32321038],
[0.81937548, 0.64274185, 0.32174556],
[0.81382519, 0.64573011, 0.32056327],
[0.80815818, 0.6487212 , 0.31966522],
[0.80237677, 0.65171241, 0.31905244],
[0.79648336, 0.65470106, 0.31872531],
[0.79048044, 0.65768455, 0.31868352],
[0.78437059, 0.66066026, 0.31892606],
[0.77815645, 0.66362567, 0.31945124],
[0.77184076, 0.66657827, 0.32025669],
[0.76542634, 0.66951562, 0.3213394 ],
[0.75891609, 0.67243534, 0.32269572],
[0.75231298, 0.67533509, 0.32432138],
[0.74562004, 0.6782126 , 0.32621159],
[0.73884042, 0.68106567, 0.32836102],
[0.73197731, 0.68389214, 0.33076388],
[0.72503398, 0.68668995, 0.33341395],
[0.7180138 , 0.68945708, 0.33630465],
[0.71092018, 0.69219158, 0.33942908],
[0.70375663, 0.69489159, 0.34278007],
[0.69652673, 0.69755529, 0.34635023],
[0.68923414, 0.70018097, 0.35013201],
[0.6818826 , 0.70276695, 0.35411772],
[0.67447591, 0.70531165, 0.3582996 ],
[0.667018 , 0.70781354, 0.36266984],
[0.65951284, 0.71027119, 0.36722061],
[0.65196451, 0.71268322, 0.37194411],
[0.64437719, 0.71504832, 0.37683259],
[0.63675512, 0.71736525, 0.38187838],
[0.62910269, 0.71963286, 0.38707389],
[0.62142435, 0.72185004, 0.39241165],
[0.61372469, 0.72401576, 0.39788432],
[0.60600841, 0.72612907, 0.40348469],
[0.59828032, 0.72818906, 0.40920573],
[0.59054536, 0.73019489, 0.41504052],
[0.58280863, 0.73214581, 0.42098233],
[0.57507535, 0.7340411 , 0.42702461],
[0.5673509 , 0.7358801 , 0.43316094],
[0.55964082, 0.73766224, 0.43938511],
[0.55195081, 0.73938697, 0.44569104],
[0.54428677, 0.74105381, 0.45207286],
[0.53665478, 0.74266235, 0.45852483],
[0.52906111, 0.74421221, 0.4650414 ],
[0.52151225, 0.74570306, 0.47161718],
[0.5140149 , 0.74713464, 0.47824691],
[0.506576 , 0.74850672, 0.48492552],
[0.49920271, 0.74981912, 0.49164808],
[0.49190247, 0.75107171, 0.4984098 ],
[0.48468293, 0.75226438, 0.50520604],
[0.47755205, 0.7533971 , 0.51203229],
[0.47051802, 0.75446984, 0.5188842 ],
[0.46358932, 0.75548263, 0.52575752],
[0.45677469, 0.75643553, 0.53264815],
[0.45008317, 0.75732863, 0.5395521 ],
[0.44352403, 0.75816207, 0.54646551],
[0.43710682, 0.758936 , 0.55338462],
[0.43084133, 0.7596506 , 0.56030581],
[0.42473758, 0.76030611, 0.56722555],
[0.41880579, 0.76090275, 0.5741404 ],
[0.41305637, 0.76144081, 0.58104704],
[0.40749984, 0.76192057, 0.58794226],
[0.40214685, 0.76234235, 0.59482292],
[0.39700806, 0.7627065 , 0.60168598],
[0.39209414, 0.76301337, 0.6085285 ],
[0.38741566, 0.76326334, 0.6153476 ],
[0.38298304, 0.76345681, 0.62214052],
[0.37880647, 0.7635942 , 0.62890454],
[0.37489579, 0.76367593, 0.63563704],
[0.37126045, 0.76370246, 0.64233547],
[0.36790936, 0.76367425, 0.64899736],
[0.36485083, 0.76359176, 0.6556203 ],
[0.36209245, 0.76345549, 0.66220193],
[0.359641 , 0.76326594, 0.66873999],
[0.35750235, 0.76302361, 0.67523226],
[0.35568141, 0.76272903, 0.68167659],
[0.35418202, 0.76238272, 0.68807086],
[0.3530069 , 0.76198523, 0.69441305],
[0.35215761, 0.7615371 , 0.70070115],
[0.35163454, 0.76103888, 0.70693324],
[0.35143685, 0.76049114, 0.71310742],
[0.35156253, 0.75989444, 0.71922184],
[0.35200839, 0.75924936, 0.72527472],
[0.3527701 , 0.75855647, 0.73126429],
[0.3538423 , 0.75781637, 0.73718884],
[0.3552186 , 0.75702964, 0.7430467 ],
[0.35689171, 0.75619688, 0.74883624],
[0.35885353, 0.75531868, 0.75455584],
[0.36109522, 0.75439565, 0.76020396],
[0.36360734, 0.75342839, 0.76577905],
[0.36637995, 0.75241752, 0.77127961],
[0.3694027 , 0.75136364, 0.77670417],
[0.37266493, 0.75026738, 0.7820513 ],
[0.37615579, 0.74912934, 0.78731957],
[0.37986429, 0.74795017, 0.79250759],
[0.38377944, 0.74673047, 0.797614 ],
[0.38789026, 0.74547088, 0.80263746],
[0.3921859 , 0.74417203, 0.80757663],
[0.39665568, 0.74283455, 0.81243022],
[0.40128912, 0.74145908, 0.81719695],
[0.406076 , 0.74004626, 0.82187554],
[0.41100641, 0.73859673, 0.82646476],
[0.41607073, 0.73711114, 0.83096336],
[0.4212597 , 0.73559013, 0.83537014],
[0.42656439, 0.73403435, 0.83968388],
[0.43197625, 0.73244447, 0.8439034 ],
[0.43748708, 0.73082114, 0.84802751],
[0.44308905, 0.72916502, 0.85205505],
[0.44877471, 0.72747678, 0.85598486],
[0.45453694, 0.72575709, 0.85981579],
[0.46036897, 0.72400662, 0.8635467 ],
[0.4662644 , 0.72222606, 0.86717646],
[0.47221713, 0.72041608, 0.87070395],
[0.47822138, 0.71857738, 0.87412804],
[0.4842717 , 0.71671065, 0.87744763],
[0.4903629 , 0.71481659, 0.88066162],
[0.49649009, 0.71289591, 0.8837689 ],
[0.50264864, 0.71094931, 0.88676838],
[0.50883417, 0.70897752, 0.88965898],
[0.51504253, 0.70698127, 0.89243961],
[0.52126981, 0.70496128, 0.8951092 ],
[0.52751231, 0.70291829, 0.89766666],
[0.53376652, 0.70085306, 0.90011093],
[0.54002912, 0.69876633, 0.90244095],
[0.54629699, 0.69665888, 0.90465565],
[0.55256715, 0.69453147, 0.90675397],
[0.55883679, 0.69238489, 0.90873487],
[0.56510323, 0.69021993, 0.9105973 ],
[0.57136396, 0.68803739, 0.91234022],
[0.57761655, 0.68583808, 0.91396258],
[0.58385872, 0.68362282, 0.91546336],
[0.59008831, 0.68139246, 0.91684154],
[0.59630323, 0.67914782, 0.9180961 ],
[0.60250152, 0.67688977, 0.91922603],
[0.60868128, 0.67461918, 0.92023033],
[0.61484071, 0.67233692, 0.921108 ],
[0.62097809, 0.67004388, 0.92185807],
[0.62709176, 0.66774097, 0.92247957],
[0.63318012, 0.66542911, 0.92297153],
[0.63924166, 0.66310923, 0.92333301],
[0.64527488, 0.66078227, 0.92356308],
[0.65127837, 0.65844919, 0.92366082],
[0.65725076, 0.65611096, 0.92362532],
[0.66319071, 0.65376857, 0.92345572],
[0.66909691, 0.65142302, 0.92315115],
[0.67496813, 0.64907533, 0.92271076],
[0.68080311, 0.64672651, 0.92213374],
[0.68660068, 0.64437763, 0.92141929],
[0.69235965, 0.64202973, 0.92056665],
[0.69807888, 0.6396839 , 0.91957507],
[0.70375724, 0.63734122, 0.91844386],
[0.70939361, 0.63500279, 0.91717232],
[0.7149869 , 0.63266974, 0.91575983],
[0.72053602, 0.63034321, 0.91420578],
[0.72603991, 0.62802433, 0.9125096 ],
[0.7314975 , 0.62571429, 0.91067077],
[0.73690773, 0.62341425, 0.9086888 ],
[0.74226956, 0.62112542, 0.90656328],
[0.74758193, 0.61884899, 0.90429382],
[0.75284381, 0.6165862 , 0.90188009],
[0.75805413, 0.61433829, 0.89932181],
[0.76321187, 0.6121065 , 0.89661877],
[0.76831596, 0.6098921 , 0.89377082],
[0.77336536, 0.60769637, 0.89077786],
[0.77835901, 0.6055206 , 0.88763988],
[0.78329583, 0.6033661 , 0.88435693],
[0.78817477, 0.60123418, 0.88092913],
[0.79299473, 0.59912616, 0.87735668],
[0.79775462, 0.59704339, 0.87363986],
[0.80245335, 0.59498722, 0.86977904],
[0.8070898 , 0.592959 , 0.86577468],
[0.81166284, 0.5909601 , 0.86162732],
[0.81617134, 0.5889919 , 0.8573376 ],
[0.82061414, 0.58705579, 0.85290625],
[0.82499007, 0.58515315, 0.84833413],
[0.82929796, 0.58328538, 0.84362217],
[0.83353661, 0.58145389, 0.83877142],
[0.8377048 , 0.57966009, 0.83378306],
[0.8418013 , 0.57790538, 0.82865836],
[0.84582486, 0.57619119, 0.82339871],
[0.84977422, 0.57451892, 0.81800565],
[0.85364809, 0.57289 , 0.8124808 ],
[0.85744519, 0.57130585, 0.80682595],
[0.86116418, 0.56976788, 0.80104298],
[0.86480373, 0.56827749, 0.79513394],
[0.86836249, 0.56683612, 0.789101 ],
[0.87183909, 0.56544515, 0.78294645],
[0.87523214, 0.56410599, 0.77667274],
[0.87854024, 0.56282002, 0.77028247],
[0.88176195, 0.56158863, 0.76377835],
[0.88489584, 0.56041319, 0.75716326],
[0.88794045, 0.55929505, 0.75044023],
[0.89089432, 0.55823556, 0.74361241],
[0.89375596, 0.55723605, 0.73668312],
[0.89652387, 0.55629781, 0.72965583],
[0.89919653, 0.55542215, 0.72253414],
[0.90177242, 0.55461033, 0.71532181],
[0.90425 , 0.55386358, 0.70802274],
[0.90662774, 0.55318313, 0.70064098],
[0.90890408, 0.55257016, 0.69318073],
[0.91107745, 0.55202582, 0.68564633],
[0.91314629, 0.55155124, 0.67804225]])
cmap = col.ListedColormap(colors)
My CMasher package contains a large collection of scientific colormaps, including cyclic ones.
Unlike twilight, which comes close to being perceptually uniform, all of CMasher's colormaps are perceptually uniform sequential.
You can take a look at all of its colormaps in its online documentation.
CMasher's policy also states that if you are not satisfied with any of the colormaps it provides, you can request for me to create one for you that you like.
Related
Radial Heatmap from data sheet
I have a file with 3 columns of data: Zenith (Z, from 0 to 90°) and Azimuth (A, from 0 to 360°). And radiance as the color variable. I need to use python with matplotlib to plot this data into something resembling this: This is my code so far (it returns an error): import matplotlib.pyplot as plt import numpy as np # `data` has the following shape: # [ # [Zenith value going from 0 to 90], # [Azimuth values (0 to 365) increasing by 1 and looping back after 365], # [radiance: floats that need to be mapped by the color value] #] data = [[6.000e+00 1.200e+01 1.700e+01 2.300e+01 2.800e+01 3.400e+01 3.900e+01 4.500e+01 5.000e+01 5.600e+01 6.200e+01 6.700e+01 7.300e+01 7.800e+01 8.400e+01 8.900e+01 3.934e+01 4.004e+01 4.054e+01 4.114e+01 4.154e+01 4.204e+01 4.254e+01 4.294e+01 4.334e+01 4.374e+01 4.414e+01 4.454e+01 4.494e+01 4.534e+01 4.564e+01 4.604e+01 4.644e+01 4.684e+01 4.714e+01 4.754e+01 4.794e+01 4.824e+01 4.864e+01 4.904e+01 4.944e+01 4.984e+01 5.014e+01 5.054e+01 5.094e+01 5.134e+01 5.174e+01 5.214e+01 5.264e+01 5.304e+01 5.344e+01 5.394e+01 5.444e+01 5.494e+01 5.544e+01 5.604e+01 5.674e+01 5.764e+01] [1.960e+02 3.600e+01 2.360e+02 7.600e+01 2.760e+02 1.160e+02 3.160e+02 1.560e+02 3.560e+02 1.960e+02 3.600e+01 2.360e+02 7.600e+01 2.760e+02 1.160e+02 3.160e+02 6.500e+00 3.400e+00 3.588e+02 2.500e+00 3.594e+02 3.509e+02 5.000e-01 6.900e+00 1.090e+01 3.478e+02 1.250e+01 1.050e+01 7.300e+00 2.700e+00 3.571e+02 3.507e+02 1.060e+01 3.200e+00 3.556e+02 3.480e+02 7.300e+00 3.597e+02 3.527e+02 1.260e+01 6.600e+00 1.200e+00 3.570e+02 3.538e+02 3.520e+02 3.516e+02 3.528e+02 3.560e+02 1.200e+00 8.800e+00 3.567e+02 1.030e+01 6.800e+00 8.300e+00 3.583e+02 3.581e+02 3.568e+02 3.589e+02] [3.580e-04 6.100e-04 3.220e-04 4.850e-04 4.360e-04 2.910e-04 1.120e-03 2.320e-04 4.300e-03 2.680e-04 1.700e-03 3.790e-04 7.460e-04 8.190e-04 1.030e-03 3.650e-03 3.050e-03 3.240e-03 3.340e-03 3.410e-03 3.490e-03 3.290e-03 3.630e-03 3.510e-03 3.320e-03 3.270e-03 3.280e-03 3.470e-03 3.720e-03 3.960e-03 3.980e-03 3.700e-03 3.630e-03 4.100e-03 4.080e-03 3.600e-03 3.990e-03 4.530e-03 4.040e-03 3.630e-03 4.130e-03 4.370e-03 4.340e-03 4.210e-03 4.100e-03 4.090e-03 4.190e-03 4.380e-03 4.460e-03 4.080e-03 4.420e-03 3.960e-03 4.230e-03 4.120e-03 4.440e-03 4.420e-03 4.370e-03 4.380e-03]] rad = data[0] azm = data[1] # From what I understand, I need to create a meshgrid from the zenith and azimuth values r, th = np.meshgrid(rad, azm) z = data[2] # This doesn't work as `pcolormesh` expects this to be a 2d array plt.subplot(projection="polar") plt.pcolormesh(th, r, z, shading="auto") plt.plot(azm, r, color="k", ls="none") plt.show() Note: my actual data goes on for 56k lines and looks like this (Ignore the 4th column): The example data above is my attempt to reduce the resolution of this massive file, so I only used 1/500 of the lines of data. This might be the wrong way to reduce the resolution, please correct me if it is! Every tutorial I've seen generate the z value from the r array generated by meshgrid. This is leaving me confused about how I would convert my z column into a 2d array that would properly map to the zenith and azimuth values. They'll use something like this: z = (r ** 2.0) / 4.0 So, taking the exact shape of r and applying a transformation to create the color.
The solution was in the data file all along. I needed to better understand what np.meshrid actually did. Turns out the data already is a 2d array, it just needed to be reshaped. I also found a flaw in the file, fixing it reduced its lines from 56k to 15k. This was small enough that I did not need to reduce the resolution. Here's how I reshaped my data, and what the solution looked like: import matplotlib.pyplot as plt import numpy as np with open("data.txt") as f: lines = np.array( [ [float(n) for n in line.split("\t")] for i, line in enumerate(f.read().splitlines()) ] ) data = [np.reshape(a, (89, 180)) for a in lines.T] rad = np.radians(data[1]) azm = data[0] z = data[2] plt.subplot(projection="polar") plt.pcolormesh(rad, azm, z, cmap="coolwarm", shading="auto") plt.colorbar() plt.show()
The simplest way to plot the given data is with a polar scatter plot. Using blue for low values and red for high values, it could look like: import matplotlib.pyplot as plt import numpy as np data = [[6.000e+00, 1.200e+01, 1.700e+01, 2.300e+01, 2.800e+01, 3.400e+01, 3.900e+01, 4.500e+01, 5.000e+01, 5.600e+01, 6.200e+01, 6.700e+01, 7.300e+01, 7.800e+01, 8.400e+01, 8.900e+01, 3.934e+01, 4.004e+01, 4.054e+01, 4.114e+01, 4.154e+01, 4.204e+01, 4.254e+01, 4.294e+01, 4.334e+01, 4.374e+01, 4.414e+01, 4.454e+01, 4.494e+01, 4.534e+01, 4.564e+01, 4.604e+01, 4.644e+01, 4.684e+01, 4.714e+01, 4.754e+01, 4.794e+01, 4.824e+01, 4.864e+01, 4.904e+01, 4.944e+01, 4.984e+01, 5.014e+01, 5.054e+01, 5.094e+01, 5.134e+01, 5.174e+01, 5.214e+01, 5.264e+01, 5.304e+01, 5.344e+01, 5.394e+01, 5.444e+01, 5.494e+01, 5.544e+01, 5.604e+01, 5.674e+01, 5.764e+01], [1.960e+02, 3.600e+01, 2.360e+02, 7.600e+01, 2.760e+02, 1.160e+02, 3.160e+02, 1.560e+02, 3.560e+02, 1.960e+02, 3.600e+01, 2.360e+02, 7.600e+01, 2.760e+02, 1.160e+02, 3.160e+02, 6.500e+00, 3.400e+00, 3.588e+02, 2.500e+00, 3.594e+02, 3.509e+02, 5.000e-01, 6.900e+00, 1.090e+01, 3.478e+02, 1.250e+01, 1.050e+01, 7.300e+00, 2.700e+00, 3.571e+02, 3.507e+02, 1.060e+01, 3.200e+00, 3.556e+02, 3.480e+02, 7.300e+00, 3.597e+02, 3.527e+02, 1.260e+01, 6.600e+00, 1.200e+00, 3.570e+02, 3.538e+02, 3.520e+02, 3.516e+02, 3.528e+02, 3.560e+02, 1.200e+00, 8.800e+00, 3.567e+02, 1.030e+01, 6.800e+00, 8.300e+00, 3.583e+02, 3.581e+02, 3.568e+02, 3.589e+02], [3.580e-04, 6.100e-04, 3.220e-04, 4.850e-04, 4.360e-04, 2.910e-04, 1.120e-03, 2.320e-04, 4.300e-03, 2.680e-04, 1.700e-03, 3.790e-04, 7.460e-04, 8.190e-04, 1.030e-03, 3.650e-03, 3.050e-03, 3.240e-03, 3.340e-03, 3.410e-03, 3.490e-03, 3.290e-03, 3.630e-03, 3.510e-03, 3.320e-03, 3.270e-03, 3.280e-03, 3.470e-03, 3.720e-03, 3.960e-03, 3.980e-03, 3.700e-03, 3.630e-03, 4.100e-03, 4.080e-03, 3.600e-03, 3.990e-03, 4.530e-03, 4.040e-03, 3.630e-03, 4.130e-03, 4.370e-03, 4.340e-03, 4.210e-03, 4.100e-03, 4.090e-03, 4.190e-03, 4.380e-03, 4.460e-03, 4.080e-03, 4.420e-03, 3.960e-03, 4.230e-03, 4.120e-03, 4.440e-03, 4.420e-03, 4.370e-03, 4.380e-03]] rad = np.radians(data[1]) azm = data[0] z = data[2] plt.subplot(projection="polar") plt.scatter(rad, azm, c=z, cmap='coolwarm') plt.colorbar() plt.show() Creating such a scatter plot with your real data gives an idea how it looks like. You might want to choose a different colormap, depending on what you want to convey. You also can choose a smaller dot size (for example plt.scatter(rad, azm, c=z, cmap='plasma', s=1, ec='none')) if there would be too many points. A simple way to create a filled image from non-gridded data uses tricontourf with 256 colors (it looks quite dull with the given data, so I didn't add an example plot): plt.subplot(projection="polar") plt.tricontourf(rad, azm, z, levels=256, cmap='coolwarm')
Separating seaborn barplot with two colors
I have the following dataset: words = ['upvoted', 'upvote', 'f***', 'reimer', 'feminists', 'censorship', 'wet', '0001f914', 'turtle', '0001f602', 'vegans', 'thumbnail', 'lobby', 'mods', 'removed', 'bitches', 'saffron', 'broadband', 'hitler', 'ass', 'deleted', 'u', 'tits', 'cheating', 'antifa', 'iâ', 'â', 'itâ', 'donâ', 'edit', 'thatâ', 'isnâ', 'doesnâ', 'didnâ', 'canâ', 'youâ', 'theyâ', 'eli5', 'weâ', 'arenâ', 'thereâ', 'hi', 'wouldnâ', '½ï', 'whatâ', 'ï', '½', 'wasnâ', 'wonâ', 'eclipse'] coefs = [ 1.00157191, 0.95931338, 0.92066619, 0.86347946, 0.83977936, 0.83912351, 0.83482245, 0.8148754 , 0.79982483, 0.79402501, 0.7687297 , 0.76765479, 0.76096785, 0.75893433, 0.75177131, 0.74486391, 0.73244163, 0.71302245, 0.70449932, 0.70346844, 0.69737316, 0.67902944, 0.6746799 , 0.67338842, 0.6678747 , -2.83723585, -2.82874502, -2.59032368, -2.52985115, -2.1811188 , -1.87094025, -1.66191757, -1.64283967, -1.62282287, -1.61855926, -1.55062817, -1.54397537, -1.39775882, -1.3492324 , -1.30638486, -1.29859752, -1.14761071, -1.0673105 , -1.06272808, -1.02998239, -0.96635257, -0.94262438, -0.91244845, -0.90765028, -0.87274524] and I would like to make a barplot with two colors, one for negative and one for positive values of the coefficient. My efforts have lead me to: sns.set(rc={'figure.figsize':(20,10)}) sns.set(font_scale = 1.5) g = sns.barplot(words,coefs, palette =sns.diverging_palette(220, 20, n=50, center = "dark")) plt.xticks(rotation=90) plt.show() But even here I cannot trully separate them, it only makes a scale of colors.
You understand seaborn coloring a bit wrongly :) Seaborn's color schemes are repeating. For example, let's use this palette: sns.diverging_palette(220, 20, n=20, center = "dark") We will get this plot: If you don't want repeating effect, you should specify a hue for each bar (if you will not do it, y will be used as hue): colors = [1 if c >= 0 else 0 for c in coefs] and send it to your bar plot: g = sns.barplot( x=words, y=coefs, hue=colors, # Here I am! palette=sns.color_palette() # Default palette is far better for it ) So you will get what you need:
Based on #vurmux answer, using hue will decenter your bars, which is noticeable in smaller plots. You can alternatively just build a list of colors and pass it to the palette argument, like this colors = ['g' if c >= 0 else 'r' for c in coefs] g = sns.barplot( x=words, y=coefs, palette=colors )
flipping and rotating numpy arrays for contour plots
Short Version: I have a 10x10 numpy array whose contour plot (plotted with pyplot.contourf) looks like this Now, I want it look something like this - assuming the plot is symmetric across X and Y axes. Long version I have a 10x10 numpy array z as a function of x and y. where x=y=np.arange(0.002,0.022,0.002). Here is what I tried import numpy as np import matplotlib.pyplot as plt z=np.array([[ 2.08273679, -0.06591932, -1.14525488, -1.49923222, -1.74361248, -1.81418446, -1.90115591, -1.94329043, -1.93130228, -1.96064259], [ 0.20180514, -0.94522815, -1.34635828, -1.58844515, -1.7528935 , -1.84438752, -1.86257547, -1.9439332 , -1.99009407, -1.94829146], [-1.09749238, -1.48234452, -1.64234357, -1.75344742, -1.83019763, -1.88547473, -1.92958533, -1.940775 , -1.95535063, -1.9629588 ], [-1.62892483, -1.70176401, -1.76263555, -1.84966414, -1.87139241, -1.91879916, -1.90796703, -1.96632612, -1.95794984, -1.94585536], [-1.71551518, -1.91806287, -1.86999609, -1.90800839, -1.92515012, -1.93386969, -1.96487487, -1.95405297, -1.97032435, -1.96087146], [-1.81904322, -1.94790171, -2. , -1.96932249, -1.91842475, -1.98101775, -1.98521938, -1.97618539, -1.95892852, -2.01410874], [-1.8138236 , -1.90877811, -1.93966404, -1.98406259, -1.95253807, -1.95867436, -1.96679456, -2.01126218, -1.99885932, -1.99369292], [-1.9927308 , -1.97658099, -1.91586737, -1.96813381, -1.98416011, -1.98639893, -1.99997964, -1.99746813, -1.98126505, -1.97767361], [-1.96406473, -1.92609437, -1.99171257, -1.94687523, -1.9823819 , -1.97786533, -2.02323228, -1.98559114, -1.99172681, -2.00881064], [-1.92470024, -1.99537152, -1.99419303, -1.97261023, -1.9673841 , -1.98801505, -2.02412735, -2.01394008, -2.01956817, -2.04963448]]) x=y=np.arange(0.002,0.022,0.002) #The following gives the plot I currently have plt.figure() plt.contourf(x,y,z) plt.show() #Tried to flip the matrix z using np.flipud and np.fliplr plt.figure() plt.contourf(x,y,z) plt.contourf(-x,y,np.fliplr(z)) plt.contourf(x,-y,np.flipud(z)) plt.contourf(-x,-y,np.flipud(np.fliplr(z))) plt.show() #Also tried to rotate the matrix z using np.rot90 plt.figure() plt.contourf(x,y,z) plt.contourf(x,-y,np.rot90(z)) plt.contourf(-x,-y,np.rot90(z,2)) plt.contourf(-x,y,np.rot90(z,3)) plt.show() I get the following plots with the above code and Ideally I would also like to fill the discontinuity at the origin by interpolation of the plot. But for starters, would like to get the orientation right. Any help is greatly appreciated.
Your problem is that, even though you negate x and y, their order stays the same, so with negative x, you go from -0.002 to -0.022, which means that the flipped z gets flipped back during the plotting. To achieve what you want, you can do the following: #either don't flip z plt.figure() plt.contourf(x,y,z) plt.contourf(-x,y,z) plt.contourf(x,-y,z) plt.contourf(-x,-y,z) plt.show() #or reverse also -x and -y: plt.figure() plt.contourf(x,y,z) plt.contourf(-x[::-1],y,np.fliplr(z)) plt.contourf(x,-y[::-1],np.flipud(z)) plt.contourf(-x[::-1],-y[::-1],np.flipud(np.fliplr(z))) plt.show() If you would have just concatenated z and the flipped z, everything would have worked as expected. plt.contourf takes care of the interpolation itself. ztotal = np.concatenate([np.fliplr(z),z],axis=1) ztotal = np.concatenate([np.flipud(ztotal),ztotal],axis=0) xtotal = np.concatenate([-x[::-1],x],axis=0) ytotal = np.concatenate([-y[::-1],y],axis=0) plt.figure() plt.contourf(xtotal,ytotal,ztotal) plt.show()
Combine results of fliplr and flipud of your array z to a new double sized array zz then plot it. You have to skip x and y in interval (-0.002; +0.002) with nan values according to your first figure: import numpy as np import matplotlib.pyplot as plt z=np.array([[ 2.08273679, -0.06591932, -1.14525488, -1.49923222, -1.74361248, -1.81418446, -1.90115591, -1.94329043, -1.93130228, -1.96064259], [ 0.20180514, -0.94522815, -1.34635828, -1.58844515, -1.7528935 , -1.84438752, -1.86257547, -1.9439332 , -1.99009407, -1.94829146], [-1.09749238, -1.48234452, -1.64234357, -1.75344742, -1.83019763, -1.88547473, -1.92958533, -1.940775 , -1.95535063, -1.9629588 ], [-1.62892483, -1.70176401, -1.76263555, -1.84966414, -1.87139241, -1.91879916, -1.90796703, -1.96632612, -1.95794984, -1.94585536], [-1.71551518, -1.91806287, -1.86999609, -1.90800839, -1.92515012, -1.93386969, -1.96487487, -1.95405297, -1.97032435, -1.96087146], [-1.81904322, -1.94790171, -2. , -1.96932249, -1.91842475, -1.98101775, -1.98521938, -1.97618539, -1.95892852, -2.01410874], [-1.8138236 , -1.90877811, -1.93966404, -1.98406259, -1.95253807, -1.95867436, -1.96679456, -2.01126218, -1.99885932, -1.99369292], [-1.9927308 , -1.97658099, -1.91586737, -1.96813381, -1.98416011, -1.98639893, -1.99997964, -1.99746813, -1.98126505, -1.97767361], [-1.96406473, -1.92609437, -1.99171257, -1.94687523, -1.9823819 , -1.97786533, -2.02323228, -1.98559114, -1.99172681, -2.00881064], [-1.92470024, -1.99537152, -1.99419303, -1.97261023, -1.9673841 , -1.98801505, -2.02412735, -2.01394008, -2.01956817, -2.04963448]]) x=y=np.linspace(-0.020,0.020,21) zz = np.empty((21,21)); zz[:,:] = np.nan zz[11:,11:] = z zz[11:,:10] = np.fliplr(z) zz[:10,:] = np.flipud(zz[11:,:]) plt.figure() plt.contourf(x,y,zz) plt.show() To fill the gap skip one point of coordinate arrays: ... x=y=np.linspace(-0.020,0.020,20) zz = np.empty((20,20)); zz[:,:] = np.nan zz[10:,10:] = z zz[10:,:10] = np.fliplr(z) zz[:10,:] = np.flipud(zz[10:,:]) ...
How to estimate the parameters of an exponential truncated power law using Python?
There is an equation of exponential truncated power law in the article below: Gonzalez, M. C., Hidalgo, C. A., & Barabasi, A. L. (2008). Understanding individual human mobility patterns. Nature, 453(7196), 779-782. like this: It is an exponential truncated power law. There are three parameters to be estimated: rg0, beta and K. Now we have got several users' radius of gyration(rg), and uploaded it onto Github: radius of gyrations.txt The following codes can be used to read data and calculate P(rg): import numpy as np # read radius of gyration from file rg = [] with open('/path-to-the-data/radius of gyrations.txt', 'r') as f: for i in f: rg.append(float(i.strip('\n'))) # calculate P(rg) rg = sorted(rg, reverse=True) rg = np.array(rg) prg = np.arange(len(sorted_data)) / float(len(sorted_data)-1) or you can directly get rg and prg data as the following: rg = np.array([ 20.7863444 , 9.40547933, 8.70934714, 8.62690145, 7.16978087, 7.02575052, 6.45280959, 6.44755478, 5.16630287, 5.16092884, 5.15618737, 5.05610068, 4.87023561, 4.66753197, 4.41807645, 4.2635671 , 3.54454372, 2.7087178 , 2.39016885, 1.9483156 , 1.78393238, 1.75432688, 1.12789787, 1.02098332, 0.92653501, 0.32586582, 0.1514813 , 0.09722761, 0. , 0. ]) prg = np.array([ 0. , 0.03448276, 0.06896552, 0.10344828, 0.13793103, 0.17241379, 0.20689655, 0.24137931, 0.27586207, 0.31034483, 0.34482759, 0.37931034, 0.4137931 , 0.44827586, 0.48275862, 0.51724138, 0.55172414, 0.5862069 , 0.62068966, 0.65517241, 0.68965517, 0.72413793, 0.75862069, 0.79310345, 0.82758621, 0.86206897, 0.89655172, 0.93103448, 0.96551724, 1. ]) I can plot the P(r_g) and r_g using the following python script: import matplotlib.pyplot as plt %matplotlib inline plt.plot(rg, prg, 'bs', alpha = 0.3) # roughly estimated params: # rg0=1.8, beta=0.15, K=5 plt.plot(rg, (rg+1.8)**-.15*np.exp(-rg/5)) plt.yscale('log') plt.xscale('log') plt.xlabel('$r_g$', fontsize = 20) plt.ylabel('$P(r_g)$', fontsize = 20) plt.show() How can I use these data of rgs to estimate the three parameters above? I hope to solve it using python.
According to #Michael 's suggestion, we can solve the problem using scipy.optimize.curve_fit def func(rg, rg0, beta, K): return (rg + rg0) ** (-beta) * np.exp(-rg / K) from scipy import optimize popt, pcov = optimize.curve_fit(func, rg, prg, p0=[1.8, 0.15, 5]) print popt print pcov The results are given below: [ 1.04303608e+03 3.02058550e-03 4.85784945e+00] [[ 1.38243336e+18 -6.14278286e+11 -1.14784675e+11] [ -6.14278286e+11 2.72951900e+05 5.10040746e+04] [ -1.14784675e+11 5.10040746e+04 9.53072925e+03]] Then we can inspect the results by plotting the fitted curve. %matplotlib inline import matplotlib.pyplot as plt plt.plot(rg, prg, 'bs', alpha = 0.3) plt.plot(rg, (rg+popt[0])**-(popt[1])*np.exp(-rg/popt[2]) ) plt.yscale('log') plt.xscale('log') plt.xlabel('$r_g$', fontsize = 20) plt.ylabel('$P(r_g)$', fontsize = 20) plt.show()
Understanding scipy deconvolve
I'm trying to understand scipy.signal.deconvolve. From the mathematical point of view a convolution is just the multiplication in fourier space so I would expect that for two functions f and g: Deconvolve(Convolve(f,g) , g) == f In numpy/scipy this is either not the case or I'm missing an important point. Although there are some questions related to deconvolve on SO already (like here and here) they do not address this point, others remain unclear (this) or unanswered (here). There are also two questions on SignalProcessing SE (this and this) the answers to which are not helpful in understanding how scipy's deconvolve function works. The question would be: How do you reconstruct the original signal f from a convoluted signal, assuming you know the convolving function g.? Or in other words: How does this pseudocode Deconvolve(Convolve(f,g) , g) == f translate into numpy / scipy? Edit: Note that this question is not targeted at preventing numerical inaccuracies (although this is also an open question) but at understanding how convolve/deconvolve work together in scipy. The following code tries to do that with a Heaviside function and a gaussian filter. As can be seen in the image, the result of the deconvolution of the convolution is not at all the original Heaviside function. I would be glad if someone could shed some light into this issue. import numpy as np import scipy.signal import matplotlib.pyplot as plt # Define heaviside function H = lambda x: 0.5 * (np.sign(x) + 1.) #define gaussian gauss = lambda x, sig: np.exp(-( x/float(sig))**2 ) X = np.linspace(-5, 30, num=3501) X2 = np.linspace(-5,5, num=1001) # convolute a heaviside with a gaussian H_c = np.convolve( H(X), gauss(X2, 1), mode="same" ) # deconvolute a the result H_dc, er = scipy.signal.deconvolve(H_c, gauss(X2, 1) ) #### Plot #### fig , ax = plt.subplots(nrows=4, figsize=(6,7)) ax[0].plot( H(X), color="#907700", label="Heaviside", lw=3 ) ax[1].plot( gauss(X2, 1), color="#907700", label="Gauss filter", lw=3 ) ax[2].plot( H_c/H_c.max(), color="#325cab", label="convoluted" , lw=3 ) ax[3].plot( H_dc, color="#ab4232", label="deconvoluted", lw=3 ) for i in range(len(ax)): ax[i].set_xlim([0, len(X)]) ax[i].set_ylim([-0.07, 1.2]) ax[i].legend(loc=4) plt.show() Edit: Note that there is a matlab example, showing how to convolve/deconvolve a rectangular signal using yc=conv(y,c,'full')./sum(c); ydc=deconv(yc,c).*sum(c); In the spirit of this question it would also help if someone was able to translate this example into python.
After some trial and error I found out how to interprete the results of scipy.signal.deconvolve() and I post my findings as an answer. Let's start with a working example code import numpy as np import scipy.signal import matplotlib.pyplot as plt # let the signal be box-like signal = np.repeat([0., 1., 0.], 100) # and use a gaussian filter # the filter should be shorter than the signal # the filter should be such that it's much bigger then zero everywhere gauss = np.exp(-( (np.linspace(0,50)-25.)/float(12))**2 ) print gauss.min() # = 0.013 >> 0 # calculate the convolution (np.convolve and scipy.signal.convolve identical) # the keywordargument mode="same" ensures that the convolution spans the same # shape as the input array. #filtered = scipy.signal.convolve(signal, gauss, mode='same') filtered = np.convolve(signal, gauss, mode='same') deconv, _ = scipy.signal.deconvolve( filtered, gauss ) #the deconvolution has n = len(signal) - len(gauss) + 1 points n = len(signal)-len(gauss)+1 # so we need to expand it by s = (len(signal)-n)/2 #on both sides. deconv_res = np.zeros(len(signal)) deconv_res[s:len(signal)-s-1] = deconv deconv = deconv_res # now deconv contains the deconvolution # expanded to the original shape (filled with zeros) #### Plot #### fig , ax = plt.subplots(nrows=4, figsize=(6,7)) ax[0].plot(signal, color="#907700", label="original", lw=3 ) ax[1].plot(gauss, color="#68934e", label="gauss filter", lw=3 ) # we need to divide by the sum of the filter window to get the convolution normalized to 1 ax[2].plot(filtered/np.sum(gauss), color="#325cab", label="convoluted" , lw=3 ) ax[3].plot(deconv, color="#ab4232", label="deconvoluted", lw=3 ) for i in range(len(ax)): ax[i].set_xlim([0, len(signal)]) ax[i].set_ylim([-0.07, 1.2]) ax[i].legend(loc=1, fontsize=11) if i != len(ax)-1 : ax[i].set_xticklabels([]) plt.savefig(__file__ + ".png") plt.show() This code produces the following image, showing exactly what we want (Deconvolve(Convolve(signal,gauss) , gauss) == signal) Some important findings are: The filter should be shorter than the signal The filter should be much bigger than zero everywhere (here > 0.013 is good enough) Using the keyword argument mode = 'same' to the convolution ensures that it lives on the same array shape as the signal. The deconvolution has n = len(signal) - len(gauss) + 1 points. So in order to let it also reside on the same original array shape we need to expand it by s = (len(signal)-n)/2 on both sides. Of course, further findings, comments and suggestion to this question are still welcome.
As written in the comments, I cannot help with the example you posted originally. As #Stelios has pointed out, the deconvolution might not work out due to numerical issues. I can, however, reproduce the example you posted in your Edit: That is the code which is a direct translation from the matlab source code: import numpy as np import scipy.signal import matplotlib.pyplot as plt x = np.arange(0., 20.01, 0.01) y = np.zeros(len(x)) y[900:1100] = 1. y += 0.01 * np.random.randn(len(y)) c = np.exp(-(np.arange(len(y))) / 30.) yc = scipy.signal.convolve(y, c, mode='full') / c.sum() ydc, remainder = scipy.signal.deconvolve(yc, c) ydc *= c.sum() fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(4, 4)) ax[0][0].plot(x, y, label="original y", lw=3) ax[0][1].plot(x, c, label="c", lw=3) ax[1][0].plot(x[0:2000], yc[0:2000], label="yc", lw=3) ax[1][1].plot(x, ydc, label="recovered y", lw=3) plt.show()