I have a scatter plot
that gets sorted into 4 Bins
. These are separated by two arcs
and a line
in the middle (see figure belo
This is a version where I sort it into ellipses. As the OP is using simple geometric shapes one can test this with a simple formula, i.e. not "asking" the patch. I generalized it for n arcs with the small disadvantage that bin numbering is not from left to right, but this can be taken care of elsewhere. Output is of type
[ [ [x,y], [x,y],...], ... ]
i.e. a list of x,y for each bins. Numbering here is from -3 to 3 though, with 0 being outside.
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
def in_ellipse( xy, x0y0ab):
x, y = xy
x0, y0 = x0y0ab[0]
a = x0y0ab[1]/2. ## as the list of ellipses takes width and not semi axis
b = x0y0ab[2]/2.
return ( x - x0 )**2 / a**2+ ( y - y0 )**2 / b**2 < 1
def sort_into_bins( xy, mainE, eList ):
binCntr = 0
xyA = (np.abs(xy[0]),xy[1]) ## all positive
if in_ellipse( xyA, mainE ):
binCntr +=1
for ell in eList:
if in_ellipse( xyA, ell ):
break
binCntr +=1
binCntr=np.copysign( binCntr, xy[0] )
return int( binCntr )
X = 200 * np.random.random(150) - 100
Y = 140 * np.random.random(150) - 70 + 60
fig, ax = plt.subplots()
ax.set_xlim(-100,100)
ax.set_ylim(-40,140)
ax.grid(False)
BIN_23_X = 0
mainEllipse = [ np.array([0, 60]), 160, 130 ]
allEllipses = [ [ np.array([60,60]), 70., 110. ], [ np.array([60,60]), 100, 160 ] ]
Halfway = mpl.lines.Line2D((BIN_23_X,BIN_23_X), (0,125), color = '#808080', lw = 1.5, alpha = 0.8, zorder = 1)
Oval = mpl.patches.Ellipse( mainEllipse[0], mainEllipse[1], mainEllipse[2], lw = 3, edgecolor = '#808080', facecolor = '#808080', alpha = 0.2)
ax.add_patch(Oval)
ax.add_line(Halfway)
for ell in allEllipses:
arc = mpl.patches.Arc( ell[0] , ell[1], ell[2], angle = 0, color = '#808080', lw = 2, linestyle=':')
ax.add_patch( arc )
arc = mpl.patches.Arc( ell[0] * np.array([ -1, 1 ]), ell[1], ell[2], angle = 0, color = '#808080', lw = 2, linestyle=':')
ax.add_patch( arc )
binDict = dict()
for x,y in zip(X,Y):
binDict[( x,y)]=sort_into_bins( (x,y), mainEllipse, allEllipses )
rowEval=[]
for s in range(-3,4):
rowEval+=[[]]
for key, val in binDict.iteritems():
rowEval[ val + 3 ]+=[key]
for s in range(-3,4):
plt.scatter( *zip( *rowEval[ s + 3 ] ) )
plt.show()
showing
Note that I used the fact of symmetry with respect to x=0. If the ellipses are shifted with respect to x the code has to be modified a little. Also note that the order in which the ellipses are provided matters!