8000 MNT : centralize pt -> step logic · matplotlib/matplotlib@67b8c0c · GitHub
[go: up one dir, main page]

Skip to content

Commit 67b8c0c

Browse files
committed
MNT : centralize pt -> step logic
Added 3 public functions for converting points -> steps for the 3 step locations + 1 private function for input validation
1 parent d1147bf commit 67b8c0c

File tree

2 files changed

+219
-1
lines changed

2 files changed

+219
-1
lines changed

lib/matplotlib/cbook.py

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2406,6 +2406,152 @@ def get_instancemethod(self):
24062406
return getattr(self.parent_obj, self.instancemethod_name)
24072407

24082408

2409+
def _step_validation(x, *args):
2410+
"""
2411+
Helper function of `pts_to_*step` functions
2412+
2413+
This function does all of the normalization required to the
2414+
input and generate the template for output
2415+
2416+
2417+
"""
2418+
args = tuple(np.asanyarray(y) for y in args)
2419+
x = np.asanyarray(x)
2420+
if x.ndim != 1:
2421+
raise ValueError("x must be 1 dimenional")
2422+
if len(args) == 0:
2423+
raise ValueError("At least one Y value must be passed")
2424+
2425+
return np.vstack((x, ) + args)
2426+
2427+
2428+
def pts_to_prestep(x, *args):
2429+
"""
2430+
Covert continuous line to pre-steps
2431+
2432+
Given a set of N points convert to 2 N -1 points
2433+
which when connected linearly give a step function
2434+
which changes values at the begining the intervals.
2435+
2436+
Parameters
2437+
----------
2438+
x : array
2439+
The x location of the steps
2440+
2441+
y1, y2, ... : array
2442+
Any number of y arrays to be turned into steps.
2443+
All must be the same length as ``x``
2444+
2445+
Returns
2446+
-------
2447+
x, y1, y2, .. : array
2448+
The x and y values converted to steps in the same order
2449+
as the input. If the input is length ``N``, each of these arrays
2450+
will be length ``2N + 1``
2451+
2452+
2453+
Example
2454+
-------
2455+
2456+
>> x_s, y1_s, y2_s = pts_to_prestep(x, y1, y2)
2457+
"""
2458+
# do normalization
2459+
vertices = _step_validation(x, *args)
2460+
# create the output array
2461+
steps = np.zeros((vertices.shape[0], 2 * len(x) - 1), np.float)
2462+
# do the to step conversion logic
2463+
steps[0, 0::2], steps[0, 1::2] = vertices[0, :], vertices[0, :-1]
2464+
steps[1:, 0::2], steps[1:, 1:-1:2] = vertices[1:, :], vertices[1:, 1:]
2465+
# convert 2D array back to tuple
2466+
return tuple(steps)
2467+
2468+
2469+
def pts_to_poststep(x, *args):
2470+
"""
2471+
Covert continuous line to pre-steps
2472+
2473+
Given a set of N points convert to 2 N -1 points
2474+
which when connected linearly give a step function
2475+
which changes values at the begining the intervals.
2476+
2477+
Parameters
2478+
----------
2479+
x : array
2480+
The x location of the steps
2481+
2482+
y1, y2, ... : array
2483+
Any number of y arrays to be turned into steps.
2484+
All must be the same length as ``x``
2485+
2486+
Returns
2487+
-------
2488+
x, y1, y2, .. : array
2489+
The x and y values converted to steps in the same order
2490+
as the input. If the input is length ``N``, each of these arrays
2491+
will be length ``2N + 1``
2492+
2493+
2494+
Example
2495+
-------
2496+
2497+
>> x_s, y1_s, y2_s = pts_to_prestep(x, y1, y2)
2498+
"""
2499+
# do normalization
2500+
vertices = _step_validation(x, *args)
2501+
# create the output array
2502+
steps = ma.zeros((vertices.shape[0], 2 * len(x) - 1), np.float)
2503+
# do the to step conversion logic
2504+
steps[0, ::2], steps[0, 1:-1:2] = vertices[0, :], vertices[0, 1:]
2505+
steps[1:, 0::2], steps[1:, 1::2] = vertices[1:, :], vertices[1:, :-1]
2506+
2507+
# convert 2D array back to tuple
2508+
return tuple(steps)
2509+
2510+
2511+
def pts_to_midstep(x, *args):
2512+
"""
2513+
Covert continuous line to pre-steps
2514+
2515+
Given a set of N points convert to 2 N -1 points
2516+
which when connected linearly give a step function
2517+
which changes values at the begining the intervals.
2518+
2519+
Parameters
2520+
----------
2521+
x : array
2522+
The x location of the steps
2523+
2524+
y1, y2, ... : array
2525+
Any number of y arrays to be turned into steps.
2526+
All must be the same length as ``x``
2527+
2528+
Returns
2529+
-------
2530+
x, y1, y2, .. : array
2531+
The x and y values converted to steps in the same order
2532+
as the input. If the input is length ``N``, each of these arrays
2533+
will be length ``2N + 1``
2534+
2535+
2536+
Example
2537+
-------
2538+
2539+
>> x_s, y1_s, y2_s = pts_to_prestep(x, y1, y2)
2540+
"""
2541+
# do normalization
2542+
vertices = _step_validation(x, *args)
2543+
# create the output array
2544+
steps = ma.zeros((vertices.shape[0], 2 * len(x)), np.float)
2545+
steps[0, 1:-1:2] = 0.5 * (vertices[0, :-1] + vertices[0, 1:])
2546+
steps[0, 2::2] = 0.5 * (vertices[0, :-1] + vertices[0, 1:])
2547+
steps[0, 0] = vertices[0, 0]
2548+
steps[0, -1] = vertices[0, -1]
2549+
steps[1:, 0::2], steps[1:, 1::2] = vertices[1:, :], vertices[1:, :]
2550+
2551+
# convert 2D array back to tuple
2552+
return tuple(steps)
2553+
2554+
24092555
# Numpy > 1.6.x deprecates putmask in favor of the new copyto.
24102556
# So long as we support versions 1.6.x and less, we need the
24112557
# following local version of putmask. We choose to make a

lib/matplotlib/tests/test_cbook.py

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
import numpy as np
99
from numpy.testing.utils import (assert_array_equal, assert_approx_equal,
1010
assert_array_almost_equal)
11-
from nose.tools import assert_equal, assert_not_equal, raises, assert_true
11+
from nose.tools import (assert_equal, assert_not_equal, raises, assert_true,
12+
assert_raises)
1213

1314
import matplotlib.cbook as cbook
1415
import matplotlib.colors as mcolors
@@ -304,3 +305,74 @@ def test_callback_complete(self):
304305

305306
def dummy(self):
306307
pass
308+
309+
310+
def test_to_prestep():
311+
x = np.arange(4)
312+
y1 = np.arange(4)
313+
y2 = np.arange(4)[::-1]
314+
315+
xs, y1s, y2s = cbook.pts_to_prestep(x, y1, y2)
316+
317+
x_target = np.asarray([0, 0, 1, 1, 2, 2, 3], dtype='float')
318+
y1_target = np.asarray([0, 1, 1, 2, 2, 3, 3], dtype='float')
319+
y2_target = np.asarray([3, 2, 2, 1, 1, 0, 0], dtype='float')
320+
321+
assert_array_equal(x_target, xs)
322+
assert_array_equal(y1_target, y1s)
323+
assert_array_equal(y2_target, y2s)
324+
325+
xs, y1s = cbook.pts_to_prestep(x, y1)
326+
assert_array_equal(x_target, xs)
327+
assert_array_equal(y1_target, y1s)
328+
329+
330+
def test_to_poststep():
331+
x = np.arange(4)
332+
y1 = np.arange(4)
333+
y2 = np.arange(4)[::-1]
334+
335+
xs, y1s, y2s = cbook.pts_to_poststep(x, y1, y2)
336+
337+
x_target = np.asarray([0, 1, 1, 2, 2, 3, 3], dtype='float')
338+
y1_target = np.asarray([0, 0, 1, 1, 2, 2, 3], dtype='float')
339+
y2_target = np.asarray([3, 3, 2, 2, 1, 1, 0], dtype='float')
340+
341+
assert_array_equal(x_target, xs)
342+
assert_array_equal(y1_target, y1s)
343+
assert_array_equal(y2_target, y2s)
344+
345+
xs, y1s = cbook.pts_to_poststep(x, y1)
346+
assert_array_equal(x_target, xs)
347+
assert_array_equal(y1_target, y1s)
348+
349+
350+
def test_to_midstep():
351+
x = np.arange(4)
352+
y1 = np.arange(4)
353+
y2 = np.arange(4)[::-1]
354+
355+
xs, y1s, y2s = cbook.pts_to_midstep(x, y1, y2)
356+
357+
x_target = np.asarray([0, .5, .5, 1.5, 1.5, 2.5, 2.5, 3], dtype='float')
358+
y1_target = np.asarray([0, 0, 1, 1, 2, 2, 3, 3], dtype='float')
359+
y2_target = np.asarray([3, 3, 2, 2, 1, 1, 0, 0], dtype='float')
360+
361+
assert_array_equal(x_target, xs)
362+
assert_array_equal(y1_target, y1s)
363+
assert_array_equal(y2_target, y2s)
364+
365+
xs, y1s = cbook.pts_to_midstep(x, y1)
366+
assert_array_equal(x_target, xs)
367+
assert_array_equal(y1_target, y1s)
368+
369+
370+
def test_step_fails():
371+
assert_raises(ValueError, cbook._step_validation,
372+
np.arange(12).reshape(3, 4), 'a')
373+
assert_raises(ValueError, cbook._step_validation,
374+
np.arange(12), 'a')
375+
assert_raises(ValueError, cbook._step_validation,
376+
np.arange(12))
377+
assert_raises(ValueError, cbook._step_validation,
378+
np.arange(12), np.arange(3))

0 commit comments

Comments
 (0)
0