Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matplotlib half black and half white circle

I would like to place a half black, half white circle of radius R at the origin of a matplotlib plot. I'm aware that there exists a Circle class, but I don't know how to specify that the left half of the circle should be white and the right half should be black. (An ideal solution would allow me to specify the orientation of the circle -- e.g. I should be able to rotate it so that for example the top could be white and the bottom black).

like image 506
mgilson Avatar asked Mar 10 '13 18:03

mgilson


People also ask

What does %Matplotlib mean in Python?

What Does Matplotlib Mean? Matplotlib is a plotting library available for the Python programming language as a component of NumPy, a big data numerical handling resource. Matplotlib uses an object oriented API to embed plots in Python applications.

What is %Matplotlib inline?

%matplotlib inline turns on “inline plotting”, where plot graphics will appear in your notebook. This has important implications for interactivity: for inline plotting, commands in cells below the cell that outputs a plot will not affect the plot.

How do I plot black and white in matplotlib?

To plot black-and-white binary map in matplotlib, we can create and add two subplots to the current figure using subplot() method, where nrows=1 and ncols=2. To display the data as a binary map, we can use greys colormap in imshow() method.

What does PLT IOFF () do?

ioff() Function: The ioff() function in pyplot module of matplotlib library is used to turn the interactive mode off.


2 Answers

The easiest way is to use two Wedges. (This doesn't automatically rescale the axes, but that's easy to add, if you'd like.)

As a quick example:

import matplotlib.pyplot as plt
from matplotlib.patches import Wedge

def main():
    fig, ax = plt.subplots()
    dual_half_circle((0.5, 0.5), radius=0.3, angle=90, ax=ax)
    ax.axis('equal')
    plt.show()

def dual_half_circle(center, radius, angle=0, ax=None, colors=('w','k'),
                     **kwargs):
    """
    Add two half circles to the axes *ax* (or the current axes) with the 
    specified facecolors *colors* rotated at *angle* (in degrees).
    """
    if ax is None:
        ax = plt.gca()
    theta1, theta2 = angle, angle + 180
    w1 = Wedge(center, radius, theta1, theta2, fc=colors[0], **kwargs)
    w2 = Wedge(center, radius, theta2, theta1, fc=colors[1], **kwargs)
    for wedge in [w1, w2]:
        ax.add_artist(wedge)
    return [w1, w2]

main()

enter image description here

If you'd like it to always be at the origin, you can specify the transform to be ax.transAxes, and turn clipping off.

E.g.

import matplotlib.pyplot as plt
from matplotlib.patches import Wedge

def main():
    fig, ax = plt.subplots()
    dual_half_circle(radius=0.1, angle=90, ax=ax)
    ax.axis('equal')
    plt.show()

def dual_half_circle(radius, angle=0, ax=None, colors=('w','k'), **kwargs):
    """
    Add two half circles to the axes *ax* (or the current axes) at the lower
    left corner of the axes with the specified facecolors *colors* rotated at
    *angle* (in degrees).
    """
    if ax is None:
        ax = plt.gca()
    kwargs.update(transform=ax.transAxes, clip_on=False)
    center = (0, 0)
    theta1, theta2 = angle, angle + 180
    w1 = Wedge(center, radius, theta1, theta2, fc=colors[0], **kwargs)
    w2 = Wedge(center, radius, theta2, theta1, fc=colors[1], **kwargs)
    for wedge in [w1, w2]:
        ax.add_artist(wedge)
    return [w1, w2]

main()

However, this will make the "circularity" of the circle depend on aspect ratio of the outline of the axes. (You can get around that in a couple of ways, but it gets more complex. Let me know if that's what you had in mind and I can show a more elaborate example.) I also may have misunderstood what you meant "at the origin".

like image 72
Joe Kington Avatar answered Oct 23 '22 16:10

Joe Kington


You can use the unicode half filled circle (U+25D0) if you have a font with this symbol. Oddly, this isn't in STIX (included with matplotlib), but I know it's in DejaVu Sans, so I'll use it from there.

enter image description here

import matplotlib.pyplot as plt
import matplotlib.font_manager
from numpy import *

path = '/full/path/to/font/DejaVuSans.ttf'
f0 = matplotlib.font_manager.FontProperties()    
f0.set_file(path)

plt.figure()
plt.xlim(-1.2,1.2)
plt.ylim(-1.2,1.2)

for angle in arange(0, 2*pi, 2*pi/10):
    x, y = cos(angle), sin(angle)
    plt.text(x, y, u'\u25D0', fontproperties=f0, rotation=angle*(180/pi), size=30)

plt.show()
like image 7
tom10 Avatar answered Oct 23 '22 17:10

tom10