14
14
_add_errorbars , _bar_wrapper , _barh_wrapper , _boxplot_wrapper ,
15
15
_cmap_changer , _cycle_changer ,
16
16
_fill_between_wrapper , _fill_betweenx_wrapper ,
17
- _hist_wrapper , _plot_wrapper , _scatter_wrapper ,
17
+ _hist_wrapper , _parametric_wrapper , _plot_wrapper , _scatter_wrapper ,
18
18
_standardize_1d , _standardize_2d ,
19
19
_text_wrapper , _violinplot_wrapper ,
20
20
colorbar_wrapper , legend_wrapper ,
@@ -1506,6 +1506,7 @@ def panel_axes(self, side, **kwargs):
1506
1506
side = self ._loc_translate (side , 'panel' )
1507
1507
return self .figure ._add_axes_panel (self , side , ** kwargs )
1508
1508
1509
+ @_parametric_wrapper
1509
1510
@_standardize_1d
1510
1511
@_cmap_changer
1511
1512
def parametric (
@@ -1522,15 +1523,19 @@ def parametric(
1522
1523
1523
1524
Parameters
1524
1525
----------
1525
- *args : (y,) or (x,y )
1526
+ *args : (y,), (x, y), or (x, y, values )
1526
1527
The coordinates. If `x` is not provided, it is inferred from `y`.
1527
- cmap : colormap spec, optional
1528
- The colormap specifier, passed to `~proplot.constructor.Colormap`.
1529
1528
values : list of float
1530
1529
The parametric values used to map points on the line to colors
1531
- in the colormap.
1530
+ in the colormap. This can also be passed as a third positional argument.
1531
+ cmap : colormap spec, optional
1532
+ The colormap specifier, passed to `~proplot.constructor.Colormap`.
1533
+ cmap_kw : dict, optional
1534
+ Keyword arguments passed to `~proplot.constructor.Colormap`.
1532
1535
norm : normalizer spec, optional
1533
1536
The normalizer, passed to `~proplot.constructor.Norm`.
1537
+ norm_kw : dict, optional
1538
+ Keyword arguments passed to `~proplot.constructor.Norm`.
1534
1539
interp : int, optional
1535
1540
If greater than ``0``, we interpolate to additional points
1536
1541
between the `values` coordinates. The number corresponds to the
@@ -1552,74 +1557,35 @@ def parametric(
1552
1557
The parametric line. See `this matplotlib example \
1553
1558
<https://matplotlib.org/gallery/lines_bars_and_markers/multicolored_line>`__.
1554
1559
"""
1555
- # First error check
1556
- # WARNING: So far this only works for 1D *x* and *y* coordinates.
1557
- # Cannot draw multiple colormap lines at once
1558
- if values is None :
1559
- raise ValueError ('Requires a "values" keyword arg.' )
1560
- if len (args ) not in (1 , 2 ):
1561
- raise ValueError (f'Requires 1-2 arguments, got { len (args )} .' )
1562
- y = np .array (args [- 1 ]).squeeze ()
1563
- x = np .arange (
1564
- y .shape [- 1 ]) if len (args ) == 1 else np .array (args [0 ]).squeeze ()
1565
- values = np .array (values ).squeeze ()
1566
- if x .ndim != 1 or y .ndim != 1 or values .ndim != 1 :
1567
- raise ValueError (
1568
- f'x ({ x .ndim } d), y ({ y .ndim } d), and values ({ values .ndim } d)'
1569
- ' must be 1-dimensional.'
1570
- )
1571
- if len (x ) != len (y ) or len (x ) != len (values ) or len (y ) != len (values ):
1572
- raise ValueError (
1573
- f'{ len (x )} xs, { len (y )} ys, but { len (values )} '
1574
- ' colormap values.'
1575
- )
1576
-
1577
- # Interpolate values to allow for smooth gradations between values
1578
- # (interp=False) or color switchover halfway between points
1579
- # (interp=True). Then optionally interpolate the colormap values.
1580
- if interp > 0 :
1581
- x , y , values = [], [], []
1582
- xorig , yorig , vorig = x , y , values
1583
- for j in range (xorig .shape [0 ] - 1 ):
1584
- idx = slice (None )
1585
- if j + 1 < xorig .shape [0 ] - 1 :
1586
- idx = slice (None , - 1 )
1587
- x .extend (
1588
- np .linspace (xorig [j ], xorig [j + 1 ], interp + 2 )[idx ].flat
1589
- )
1590
- y .extend (
1591
- np .linspace (yorig [j ], yorig [j + 1 ], interp + 2 )[idx ].flat
1592
- )
1593
- values .extend (
1594
- np .linspace (vorig [j ], vorig [j + 1 ], interp + 2 )[idx ].flat
1595
- )
1596
- x , y , values = np .array (x ), np .array (y ), np .array (values )
1597
-
1598
1560
# Get x/y coordinates and values for points to the 'left' and 'right'
1599
1561
# of each joint
1562
+ x , y = args # standardized by parametric wrapper
1563
+ interp # avoid U100 unused argument error (arg is handled by wrapper)
1600
1564
coords = []
1601
1565
levels = edges (values )
1602
1566
for j in range (y .shape [0 ]):
1603
1567
if j == 0 :
1604
1568
xleft , yleft = [], []
1605
1569
else :
1606
- xleft = [(x [j - 1 ] + x [j ]) / 2 , x [j ]]
1607
- yleft = [(y [j - 1 ] + y [j ]) / 2 , y [j ]]
1570
+ xleft = [0.5 * (x [j - 1 ] + x [j ]), x [j ]]
1571
+ yleft = [0.5 * (y [j - 1 ] + y [j ]), y [j ]]
1608
1572
if j + 1 == y .shape [0 ]:
1609
1573
xright , yright = [], []
1610
1574
else :
1611
1575
xleft = xleft [:- 1 ] # prevent repetition when joined with right
1612
1576
yleft = yleft [:- 1 ]
1613
- xright = [x [j ], (x [j + 1 ] + x [j ]) / 2 ]
1614
- yright = [y [j ], (y [j + 1 ] + y [j ]) / 2 ]
1577
+ xright = [x [j ], 0.5 * (x [j + 1 ] + x [j ])]
1578
+ yright = [y [j ], 0.5 * (y [j + 1 ] + y [j ])]
1615
1579
pleft = np .stack ((xleft , yleft ), axis = 1 )
1616
1580
pright = np .stack ((xright , yright ), axis = 1 )
1617
1581
coords .append (np .concatenate ((pleft , pright ), axis = 0 ))
1582
+ coords = np .array (coords )
1618
1583
1619
1584
# Create LineCollection and update with values
1585
+ # NOTE: Default capstyle is butt but this may look weird with vector graphics
1620
1586
hs = mcollections .LineCollection (
1621
- np . array ( coords ) , cmap = cmap , norm = norm ,
1622
- linestyles = '-' , capstyle = 'butt' , joinstyle = 'miter'
1587
+ coords , cmap = cmap , norm = norm ,
1588
+ linestyles = '-' , capstyle = 'butt' , joinstyle = 'miter' ,
1623
1589
)
1624
1590
hs .set_array (np .array (values ))
1625
1591
hs .update ({
0 commit comments