0

Working on a personal project that draws two lines, each dashed (ls='--') for the first two x-axis markings, then it is a solid line...thinking about writing a tutorial since I've found no information on this. Anyhow, the trick I'm stumped at, is to figure how many points are used to make the line for the first two x-axis markings, so I can properly turn off the solid line up to that point. I'm using the Line.set_dashes() method to turn off the solid line, and I'm making an individual (non-connected) copy and setting the linestyle to dash. This causes the lines to be drawn on top of each other, and the solid to take precedence when ON. However, the Line.set_dashes() takes "points" as arguments. I figured out where, but as you see, the second line has different angles, thus length, so this point is further along the line. Maybe there's a better way to set the line to two styles?

Here is an example plot --> https://flic.kr/p/rin6Z5

r = getPostData(wall)

if len(newTimes) < LIMIT:
    LIMIT = len(newTimes)
yLim = int(round(max(r['Likes'].max(), r['Shares'].max()) * 1.2))
xLim = LIMIT
L1A = plt.Line2D(range(LIMIT), r['Likes'], color='b', ls='--')
L1B = plt.Line2D(range(LIMIT), r['Likes'], label='Likes', color='b')
L2A = plt.Line2D(range(LIMIT), r['Shares'], color='r', ls='--')
L2B = plt.Line2D(range(LIMIT), r['Shares'], label='Shares', color='r')
LNull = plt.Line2D(range(LIMIT), r['Shares'], ls='--', label='Recent Data\n(Early collection)', color='k')
dashes = [1,84,7000,1]
dashesNull=[1,7000]
fig = plt.figure()
ax = fig.add_subplot(111, ylim=(0,yLim), xlim=(0,xLim))
ax.add_line(L1A)
ax.add_line(L1B)
ax.add_line(L2A)
ax.add_line(L2B)
ax.add_line(LNull)
ax.legend(bbox_to_anchor=(1.5,1))
L1B.set_dashes(dashes)
L2B.set_dashes(dashes)
LNull.set_dashes(dashesNull)
2
  • Why don't you use ax.plot? I think it would be much simpler to control the display by limiting the data you pass to each plot. Commented Apr 22, 2015 at 1:39
  • honest answer, I just completed the matplotlib tutorial a week ago. Can you elude? Commented Apr 22, 2015 at 17:00

2 Answers 2

2

I would write your self a helper function, something like:

import numpy as np
import matplotlib.pyplot as plt

def split_plot(ax, x, y, low, high, inner_style, outer_style):
    """
    Split styling of line based on the x-value

    Parameters
    ----------
    x, y : ndarray
        Data, must be same length

    low, high : float
        The low and high threshold values, points for `low < x < high` are
        styled using `inner_style` and points for `x < low or x > high` are
        styled using `outer_style`

    inner_style, outer_style : dict
        Dictionary of styles that can be passed to `ax.plot`

    Returns
    -------
    lower, mid, upper : Line2D
        The artists for the lower, midddle, and upper ranges

    vline_low, vline_hi : Line2D
        Vertical lines at the thresholds

    hspan : Patch
        Patch over middle region
    """

    low_mask = x < low
    high_mask = x > high
    mid_mask = ~np.logical_or(low_mask, high_mask)

    low_mask[1:] |= low_mask[:-1]
    high_mask[:-1] |= high_mask[1:]

    lower, = ax.plot(x[low_mask], y[low_mask], **outer_style)
    mid, = ax.plot(x[mid_mask], y[mid_mask], **inner_style)
    upper, = ax.plot(x[high_mask], y[high_mask], **outer_style)

    # add vertical lines
    vline_low = ax.axvline(low, color='k', ls='--')
    vline_high = ax.axvline(high,  color='k', ls='--')

    hspan = ax.axvspan(low, high, color='b', alpha=.25)

    return lower, mid, upper, vline_low, vline_high, hspan

Which can obviously be generalized to take 3 line style dictionaries and style information for the vertical lines and the span. You use it like:

inner_style = {'color': 'r', 'lw': 5, 'ls':'--'}
outer_style = {'color': 'r', 'lw': 1, 'ls':'-'}

x = np.linspace(0, 2*np.pi, 1024)
y = np.sin(x)

low = np.pi / 2
high = 3*np.pi / 2

fig, ax = plt.subplots()

lower, mid, upper, vl_low, vl_high, hsp = split_plot(ax, x, y, low, high, inner_style, outer_style)
plt.show()

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

thank you tcaswell, i will try something similar, you've given me alot to munch on! I'm assuming I'll be marking yours as the answer.
thanks again, I came up def splitLine(ax, x, y, splitNum, style1, style2): '''ax = an axis x = an array of x coordinates for 2D Line y = an array of y coordinates for 2D Line splitNum = index number to split Line by x tick style1 = dictionary for left part of Line style2 = dictionary for right part of Line ''' split = x[splitNum] low_mask = x <= split upper_mask = x >= split lower, = ax.plot(x[low_mask], y[low_mask], **style1) upper, = ax.plot(x[upper_mask], y[upper_mask], **style2) return lower, upper
0

enter image description here

i thought so too, anyhow, the resulting code is now...

def splitLine(ax, x, y, splitNum, style1, style2):
    '''Creates a two styled line given;
    ax = an axis
    x  = an array of x coordinates for 2D Line
    y  = an array of y coordinates for 2D Line
    splitNum = index number to split Line by x tick
    style1 = dictionary for left part of Line
    style2 = dictionary for right part of Line
    '''
    split = x[splitNum]
    low_mask = x <= split
    upper_mask = x >= split

    lower, = ax.plot(x[low_mask], y[low_mask], **style1)
    upper, = ax.plot(x[upper_mask], y[upper_mask], **style2)

    return lower, upper


r = getPostData(wall)



earlyLike  = {'color': 'r', 'lw': 1, 'ls': '--'}
agedLike   = {'color': 'r', 'lw': 2, 'ls': '-', 'label': 'Likes'}
earlyShare = {'color': 'b', 'lw': 1, 'ls': '--'}
agedShare  = {'color': 'b', 'lw': 2, 'ls': '-', 'label': 'Shares'}

fig, ax = plt.subplots()

splitLine(ax, np.array(range(LIMIT)), np.array(r['Likes']), 1, earlyLike, agedLike)
splitLine(ax, np.array(range(LIMIT)), np.array(r['Shares']), 1, earlyShare, agedShare)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.