Skip to content

plot_piecewise: show jumps of sign, Heaviside, floor, ceiling and frac, and holes - #62

Open
inayatku wants to merge 4 commits into
Davide-sd:masterfrom
inayatku:piecewise-jump-functions
Open

inayatku wants to merge 4 commits into
Davide-sd:masterfrom
inayatku:piecewise-jump-functions

Conversation

@inayatku

@inayatku inayatku commented Oct 4, 2026 •

Copy link
Copy Markdown

plot_piecewise draws filled and empty dots at the ends of the pieces of a Piecewise expression. Functions with jumps that are not written as Piecewise were drawn with vertical lines and no dots. Removable discontinuities were not shown.

This PR:

  • rewrites sign, Heaviside, floor, ceiling and frac as Piecewise over the plotting range before the pieces are processed. floor, ceiling and frac are rewritten only when their argument is linear in the plotting variable and the range covers at most 100 integer steps;
  • removes from the domain the points where the expression is undefined but both one-sided limits are finite (zeros of a polynomial denominator). These points get empty dots: the hole of (x**2 - 1)/(x - 1) at x = 1, sin(x)/x at x = 0, and the two ends of Abs(x)/x at x = 0;
  • does not join the curve across a vertical asymptote, a point where a one-sided limit is infinite, such as x = 1 for 1/(x - 1): the plotting range is split there. If ylim is not given, the y-limits are taken from the values that are not close to the vertical asymptotes, so that the two branches near a pole do not look like one vertical line;
  • fixes the offset at the open ends of pieces shorter than one unit (separate commit). offset *= e gave a negative offset, so the piece was evaluated outside its interval, and the empty dot could be NaN. For example, Piecewise((sqrt(1/2 - x), x < 1/2), (1, True)) lost its empty dot at x = 1/2.

Before and after, with plot_piecewise(expr, (x, a, b)):

Before:

before

After:

after

Tests: five new tests in tests/plot_functions/test_functions_2d.py. With the change, tests/graphics, tests/plot_functions, tests/test_series.py, tests/test_utils.py and tests/backends/test_matplotlib.py give 563 passed, 206 skipped and 4 xfailed (558 passed before, the same skips and xfails). The existing doctest examples of plot_piecewise give the same output, except the last one, where 1/x is now split at x = 0.

Related SymPy issues: sympy/sympy#17738 and sympy/sympy#26328.

SymPy's limit does not return for sin(x)/x + Heaviside(x - 1) at x = 0,
so plot_piecewise hung on this expression. Rewrite sign, Heaviside,
floor, ceiling and frac as Piecewise first, and look for the holes of a
Piecewise in each piece, inside the set where the piece applies.
@inayatku

Copy link
Copy Markdown
Author

Hi @Davide-sd, a gentle reminder about this pull request. The CI workflows are waiting for approval, since this is my first contribution here. The first commit (the offset *= 10**e fix in _process_piecewise) is independent of the rest. I can move it to a separate pull request if that makes the review easier. Thank you for your time.

@Davide-sd

Copy link
Copy Markdown
Owner

Hello @inayatku , thanks for this PR. Sorry for the late reply, busy weeks for me. I just launched the CI run...

The plotting range is split at the vertical asymptotes that are inside a
piece, so that 1/(x - 1) is no longer drawn with a vertical line at
x = 1. Vertical asymptotes are the singular points where a one-sided
limit is infinite.

If there are vertical asymptotes in the plotting range and ylim is not
given, the y-limits are taken from the values that are not close to
them, so that the two branches near a pole do not look like one
vertical line.
@inayatku

Copy link
Copy Markdown
Author

I added a commit: plot_piecewise no longer joins the curve across a vertical asymptote. The 1/(x - 1) panel of the "after" image showed a vertical line at x = 1. The description and the image are updated. With this commit, the local test run gives 563 passed, 206 skipped and 4 xfailed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants