Search code examples
pythonmatplotlibplotlogarithm

Is there an easy way to use logarithmic scale on matplotlib plots displaying data via a custom function (wedge)?


I am plotting data using wedges (same would apply for patches/circles/etc). This works nicely, but I want to plot the data logarithmic.

For ordinary plots, there is

plt.yscale('log')
plt.xscale('log')

but this is not working here, and results in :

ValueError: Data has no positive values, and therefore can not be log-scaled.

I could of course transform all my data to log and adjust xticks and yticks accordingly, but I wondered, if there is an matplotlib automated way for that.

See the working part of my code below:

import matplotlib.pylot as plt
from matplotlib.patches import Wedge
import seaborn as sns
import numpy as np

from matplotlib.patches import Wedge
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]


fig, ax = plt.subplots(figsize=(30,15))
for i in range(10):
    dual_half_circle((100*i, 100*i), radius=10, angle=90, ax=ax,colors=('r','b'))
plt.xlim(0,1000)
plt.ylim(0,1000)
plt.show()

Thanks for your help!


Solution

  • The error results from your x and y limits. Choose a value above 0 and everything should be fine.


    Adjusted code:

    import matplotlib.pyplot as plt
    from matplotlib.patches import Wedge
    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]
    
    
    _, ax = plt.subplots(figsize=(30, 15))
    for i in range(10):
        dual_half_circle((100*i, 100*i), radius=10, angle=90, ax=ax,colors=('r', 'b'))
    plt.xlim(1, 1000)
    plt.ylim(1, 1000)
    plt.xscale('log')
    plt.yscale('log')
    plt.show()
    

    Result:

    enter image description here