Points within a circle - numpy

I am trying to find the points within a circle by using numpy.where():
coord=[]
x=np.random.randint(1000, size=1000)
y=np.random.randint(1000, size=1000)
coord.append(x)
coord.append(y)
neighbouring_points= np.where(np.roots((coord[0]-coord[0][10])**2 + (coord[1]-coord[1][10])**2)<=0.01,)
#protein_coordinates[0],
#protein_coordinates[1],)
#np.delete(protein_coordinates[0],protein_coordinates[0][10]),
#np.delete(protein_coordinates[1],protein_coordinates[1][10]))
plt.scatter(coord[0],coord[1], color='blue')
The result is that all points are selected and not only those satisfying the condition, I have also tried to add x,y alongside the condition to satisfy:
coord=[]
x=np.random.randint(1000, size=1000)
y=np.random.randint(1000, size=1000)
coord.append(x) #easier to plot than "protein_coordinates.append([x,y])"
coord.append(y)
neighbouring_points= np.where(np.roots((coord[0]-coord[0][10])**2 + (coord[1]-coord[1][10])**2)<=0.01,
coord[0],
coord[1],)
In this last case I get the error:
ValueError: operands could not be broadcast together with shapes (999,) (1000,) (1000,)
I have fixed the error by removing the centre of the circle, but the code still does not work.
Any suggestion on how to fix it?

you are not using the correct formula for the circle. Use np.sqrt() instead of np.roots
you are not correctly plotting your points. Use
idx = neighbouring_points[0]
plt.scatter(coord[0][idx], coord[1][idx])
your radius is probably too small. So inside of np.where check for something like <= 400 instead. Otherwise you only get back your central point at coord[0][10], coord[1][10]
If your central point is too close to the board of your 1000x1000 square, you also wont get a full circle. You can fix that by choosing your central to be i.e. 500,500 in your circle equation
So in total:
import numpy as np
import matplotlib.pyplot as plt
coord=[]
x=np.random.randint(1000, size=1000)
y=np.random.randint(1000, size=1000)
coord.append(x)
coord.append(y)
neighbouring_points = np.where(np.sqrt((coord[0]-500)**2 + (coord[1]-500)**2)<=400,)
idx = neighbouring_points[0]
plt.scatter(coord[0][idx],coord[1][idx], color='blue')

Related

How do I use colourmaps with variable alpha in a Seaborn kdeplot without seeing the contour lines?

Python version: 3.6.4 (Anaconda on Windows)
Seaborn: 0.8.1
Matplotlib: 2.1.2
I'm trying to create a 2D Kernel Density plot using Seaborn but I want each step in the colourmap to have a different alpha value. I had a look at this question to create a matplotlib colourmap with alpha values: Add alpha to an existing matplotlib colormap.
I have a problem in that the lines between contours are visible. The result I get is here:
I thought that I had found the answer when I found this question: Hide contour linestroke on pyplot.contourf to get only fills. I tried the method outlined in the answer (using set_edgecolor("face") but it did not work in this case. That question also seemed to be related to vector graphics formats and I am just writing out a PNG.
Here is my script:
import numpy as np
import seaborn as sns
import matplotlib.colors as cols
import matplotlib.pyplot as plt
def alpha_cmap(cmap):
my_cmap = cmap(np.arange(cmap.N))
# Set a square root alpha.
x = np.linspace(0, 1, cmap.N)
my_cmap[:,-1] = x ** (0.5)
my_cmap = cols.ListedColormap(my_cmap)
return my_cmap
xs = np.random.uniform(size=100)
ys = np.random.uniform(size=100)
kplot = sns.kdeplot(data=xs, data2=ys,
cmap=alpha_cmap(plt.cm.viridis),
shade=True,
shade_lowest=False,
n_levels=30)
plt.savefig("example_plot.png")
Guided by some comments on this question I have tried some other methods that have been successful when this problem has come up. Based on this question (Matplotlib Contourf Plots Unwanted Outlines when Alpha < 1) I have tried altering the plot call to:
sns.kdeplot(data=xs, data2=ys,
cmap=alpha_cmap(plt.cm.viridis),
shade=True,
shade_lowest=False,
n_levels=30,
antialiased=True)
With antialiased=True the lines between contours are replaced by a narrow white line:
I have also tried an approach similar to this question - Pyplot pcolormesh confused when alpha not 1. This approach is based on looping over the PathCollections in kplot.collections and tuning the parameters of the edges so that they become invisible. I have tried adding this code and tweaking the linewidth -
for thing in kplot.collections:
thing.set_edgecolor("face")
thing.set_linewidth(0.01)
fig.canvas.draw()
This results in a mix of white and dark lines - .
I believe that I will not be able to tune the line width to make the lines disappear because of the variable width of the contour bands.
Using both methods (antialiasing + linewidth) makes this version, which looks cool but isn't quite what I want:
I also found this question - Changing Transparency of/Remove Contour Lines in Matplotlib
This one suggests overplotting a second plot with a different number of contour levels on the same axis, like:
kplot = sns.kdeplot(data=xs, data2=ys,
ax=ax,
cmap=alpha_cmap(plt.cm.viridis),
shade=True,
shade_lowest=False,
n_levels=30,
antialiased=True)
kplot = sns.kdeplot(data=xs, data2=ys,
ax=ax,
cmap=alpha_cmap(plt.cm.viridis),
shade=True,
shade_lowest=False,
n_levels=35,
antialiased=True)
This results in:
This is better, and almost works. The problem here is I need variable (and non-linear) alpha throughout the colourmap. The variable banding and lines seem to be a result of the combinations of alpha when contours are plotted over each other. I also still see some clear/white lines in the result.

Cartopy AzimuthalEquidistant projection: zooming into a region and coastlines

I am trying to plot some data on an AzimuthalEquidistant projection using cartopy. However, it gives me a couple of problems. First the coastlines no longer show for this type of projection. Not sure if this is my code or a Cartopy problem. I also notice that if I use a ccrs.PlateCarree() transform in the pcolormesh command the coastlines do show but then, presumably, my data is on the wrong type of prejection?
Second I would prefer if the axis boarder was circular after plotting the data, is it possible to use set_extent or some similar function to do this?
The code below should reproduce the problems, the circle shows how I would like the boarder to look.
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import matplotlib.patches as mpatches
clat = 55.0
clon = -8.0
lons = np.arange(clon-15,clon+16,0.5)
lats = np.arange(clat-15,clat+16,0.5)
d = np.random.rand(lons.shape[0],lats.shape[0])
trans = ccrs.AzimuthalEquidistant(central_latitude=clat, central_longitude=clon)
ax = plt.axes(projection=trans)
ax.coastlines(resolution='10m')
CB=ax.pcolormesh(lons-0.25, lats-0.25, d.T,
cmap=plt.cm.viridis, alpha=0.5,
transform=trans)#ccrs.PlateCarree())
p1 = mpatches.Circle((clon,clat), radius=15, color='k', lw=5, fill=False,
transform=trans)
ax.add_patch(p1)
If the data you are plotting is in latitude/longitude coordinates then the correct value for the transform keyword is indeed ccrs.PlateCarree(). This is common gotcha for new users. The transform argument tells cartopy what coordinates your data are in, and is completely independent of the projection you want to plot onto.
To make the plot circular you'll need to set the boundary yourself. The Cartopy documentation have a couple of examples of this: http://scitools.org.uk/cartopy/docs/latest/examples/always_circular_stereo.html and http://scitools.org.uk/cartopy/docs/latest/examples/star_shaped_boundary.html.

plt.imshow(Z,norm=logNorm()) gives grey outline when Z=0

Sorry for no pictures, but this code reproduces the problem:
x=np.random.randn(1000)
y=np.random.randn(1000)
h,_,_=np.histogram2d(x,y)
plt.imshow(h, norm=LogNorm(), cmap=plt.cm.Greys)
I would expect a smooth white transition from very small values to 0 values, but there seems to be a blurred border I'd like to get rid of. Is there any way to do this?
This is to be expected because values less or equal to zero are masked and then positive values are normalized. That might mean that LogNorm is not the best option for you, but if you insist on using it you can try adding the minimum positive value to the histogram. In your case it would be 1 but let's do it more general for, say, normed histograms.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
x = np.random.randn(1000)
y = np.random.randn(1000)
h, _, _ = np.histogram2d(x, y)
im = plt.imshow(h, norm=LogNorm(), cmap=plt.cm.Greys,
interpolation='bilinear')
plt.colorbar(im)
im = plt.imshow(h + np.min(h[h > 0]), norm=LogNorm(), cmap=plt.cm.Greys,
interpolation='bilinear')
plt.colorbar(im)
Note that this change won't affect bilinear interpolation but might affect other interpolation algorithms. To ensure that interpolation is not affected you would have to create a custom subclass of Normalize.
The above figures were made using matplotlib 2.0.0rc1 which applies color mapping after interpolation. If you use a previous version you will see even more artifacts in the first figure.

Using pd.cut to create bins for a graph, but bin values are not coming out as expected

Here is the code I'm running:
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
titanic = sns.load_dataset("titanic")
y =titanic.groupby([titanic.fare//1,'sex']).survived.mean().reset_index() #grouping by 'fare' rounded to an integer and 'sex' and then getting the survivability
x =pd.cut(y.fare, (0,17,35,70,300,515)) #I'm not sure if my format is correct but this is how I cut up the fare values
y['Fare_bins']= x # adding the newly created bins to a new column "Fare_bins' in original dataframe.
#graphing with seaborn
sns.set(style="whitegrid")
g = sns.factorplot(x='Fare_bins', y= 'survived', col = 'sex', kind ='bar' ,data= y,
size=4, aspect =2.5 , palette="muted")
g.despine(left=True)
g.set_ylabels("Survival Probability")
g.set_xlabels('Fare')
plt.show()
The problem I'm having is that Fare_values are showing up as (0,17].
The left side is a circle bracket and the right side is square bracket.
If possible I would like to have something like this:
(0-17) or [0-17]
Next, there seems to be a gap between each bar plot. I was expecting them to be adjoined. There are two graphs being represented, so I don't expect of the bars to be ajoined, but the first 5 bars(first graph)should be connected and the last 5 bars to eachother(second graph).
How can I go about fixing these two issues?
It seems I can add labels.
Just by adding labels to the "cut" method parameters, I can display the Fare_values as I want.
x =pd.cut(y.fare, (0,17,35,70,300,515), labels = ('(0-17)', '(17-35)', '(35-70)', '(70-300)','(300-515)') )
As for the brackets showing around the fare_value groups,
according to the documentation:
right : bool, optional
Indicates whether the bins include the rightmost edge or not. If right == True (the default), then the bins [1,2,3,4] indicate (1,2], (2,3], (3,4].
Still not sure if it's possible to join the bars though.

How can I draw axes with a 45 degree rotation?

I have a set of 7x4 plots arranged in a grid using subplot. I now want to add diagonal axes on top of these.
I know you can superpose axes on top of previously made subplots by setting the background to 'none':
ax = fig.add_subplot(111)
ax.set_axis_bgcolor('none')
But I can't find a rotated axis thing. Currently I'm trying to use a top view 3D axes, but I'm far from a usable solution there.
I'm willing to accept drawing the axis+ticks by hand, if this is the only way possible.
EDIT: using the floating_axis module, I was able to draw rotated (and sheared) axes, but unable to edit the ticks, which is very necessary for what I need. The following snippet demonstrates adding a floating_axis to an existing figure fig. Any manipulation of the axes' ticks fails.
from matplotlib.transforms import Affine2D
import mpl_toolkits.axisartist.floating_axes as floating_axes
trafo = Affine2D().skew_deg(-10,-10).rotate_deg(45)
grid_helper = floating_axes.GridHelperCurveLinear(trafo, extremes=(0, 4, 0, 4))
artistax = floating_axes.FloatingSubplot(fig, 111, grid_helper=grid_helper)
artistax.set_axis_bgcolor('none')
artistax.axis["top"].set_visible(False)
artistax.axis["right"].set_visible(False)
fig.add_subplot(artistax)