8000 Merge pull request #25120 from anntzer/mxn · matplotlib/matplotlib@f3938be · GitHub
[go: up one dir, main page]

Skip to content

Commit f3938be

Browse files
authored
Merge pull request #25120 from anntzer/mxn
Consistently document shapes as (M, N), not MxN.
2 parents faf88bf + c5483f7 commit f3938be

File tree

13 files changed

+90
-113
lines changed

13 files changed

+90
-113
lines changed

examples/lines_bars_and_markers/scatter_custom_symbol.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@
3535
# %%
3636
# Using a custom path
3737
# -------------------
38-
# Alternatively, one can also pass a custom path of N vertices as a Nx2 array
39-
# of x, y values as *marker*.
38+
# Alternatively, one can also pass a custom path of N vertices as a (N, 2)
39+
# array of x, y values as *marker*.
4040

4141
# unit area ellipse
4242
rx, ry = 3., 1.
@@ -45,7 +45,7 @@
4545
verts = np.column_stack([rx / area * np.cos(theta), ry / area * np.sin(theta)])
4646

4747
x, y, s, c = np.random.rand(4, 30)
48-
s *= 10**2.
48+
s *= 100
4949

5050
fig, ax = plt.subplots()
5151
ax.scatter(x, y, s, c, marker=verts)

lib/matplotlib/axes/_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2495,7 +2495,7 @@ def update_datalim(self, xys, updatex=True, updatey=True):
24952495
----------
24962496
xys : 2D array-like
24972497
The points to include in the data limits Bbox. This can be either
2498-
a list of (x, y) tuples or a Nx2 array.
2498+
a list of (x, y) tuples or a (N, 2) array.
24992499
25002500
updatex, updatey : bool, default: True
25012501
Whether to update the x/y limits.

lib/matplotlib/colors.py

Lines changed: 16 additions & 16 deletions
Returns
Original file line numberDiff line numberDiff line change
@@ -1110,8 +1110,8 @@ class ListedColormap(Colormap):
11101110
Parameters
11111111
----------
11121112
colors : list, array
1113-
List of Matplotlib color specifications, or an equivalent Nx3 or Nx4
1114-
floating point array (*N* RGB or RGBA values).
1113+
Sequence of Matplotlib color specifications (color names or RGB(A)
1114+
values).
11151115
name : str, optional
11161116
String to identify the colormap.
11171117
N : int, optional
@@ -2370,8 +2370,8 @@ def shade(self, data, cmap, norm=None, blend_mode='overlay', vmin=None,
23702370
"overlay". Note that for most topographic surfaces,
23712371
"overlay" or "soft" appear more visually realistic. If a
23722372
user-defined function is supplied, it is expected to
2373-
combine an MxNx3 RGB array of floats (ranging 0 to 1) with
2374-
an MxNx1 hillshade array (also 0 to 1). (Call signature
2373+
combine an (M, N, 3) RGB array of floats (ranging 0 to 1) with
2374+
an (M, N, 1) hillshade array (also 0 to 1). (Call signature
23752375
``func(rgb, illum, **kwargs)``) Additional kwargs supplied
23762376
to this function will be passed on to the *blend_mode*
23772377
function.
@@ -2404,7 +2404,7 @@ def shade(self, data, cmap, norm=None, blend_mode='overlay', vmin=None,
24042404
24052405
-------
24062406
`~numpy.ndarray`
2407-
An MxNx4 array of floats ranging between 0-1.
2407+
An (M, N, 4) array of floats ranging between 0-1.
24082408
"""
24092409
if vmin is None:
24102410
vmin = data.min()
@@ -2445,8 +2445,8 @@ def shade_rgb(self, rgb, elevation, fraction=1., blend_mode='hsv',
24452445
defaults to "hsv". Note that for most topographic surfaces,
24462446
"overlay" or "soft" appear more visually realistic. If a
24472447
user-defined function is supplied, it is expected to combine an
2448-
MxNx3 RGB array of floats (ranging 0 to 1) with an MxNx1 hillshade
2449-
array (also 0 to 1). (Call signature
2448+
(M, N, 3) RGB array of floats (ranging 0 to 1) with an (M, N, 1)
2449+
hillshade array (also 0 to 1). (Call signature
24502450
``func(rgb, illum, **kwargs)``)
24512451
Additional kwargs supplied to this function will be passed on to
24522452
the *blend_mode* function.
@@ -2512,9 +2512,9 @@ def blend_hsv(self, rgb, intensity, hsv_max_sat=None, hsv_max_val=None,
25122512
Parameters
25132513
----------
25142514
rgb : `~numpy.ndarray`
2515-
An MxNx3 RGB array of floats ranging from 0 to 1 (color image).
2515+
An (M, N, 3) RGB array of floats ranging from 0 to 1 (color image).
25162516
intensity : `~numpy.ndarray`
2517-
An MxNx1 array of floats ranging from 0 to 1 (grayscale image).
2517+
An (M, N, 1) array of floats ranging from 0 to 1 (grayscale image).
25182518
hsv_max_sat : number, default: 1
25192519
The maximum saturation value that the *intensity* map can shift the
25202520
output image to.
@@ -2531,7 +2531,7 @@ def blend_hsv(self, rgb, intensity, hsv_max_sat=None, hsv_max_val=None,
25312531
Returns
25322532
-------
25332533
`~numpy.ndarray`
2534-
An MxNx3 RGB array representing the combined images.
2534+
An (M, N, 3) RGB array representing the combined images.
25352535
"""
25362536
# Backward compatibility...
25372537
if hsv_max_sat is None:
@@ -2574,14 +2574,14 @@ def blend_soft_light(self, rgb, intensity):
25742574
Parameters
25752575
----------
25762576
rgb : `~numpy.ndarray`
2577-
An MxNx3 RGB array of floats ranging from 0 to 1 (color image).
2577+
An (M, N, 3) RGB array of floats ranging from 0 to 1 (color image).
25782578
intensity : `~numpy.ndarray`
2579-
An MxNx1 array of floats ranging from 0 to 1 (grayscale image).
2579+
An (M, N, 1) array of floats ranging from 0 to 1 (grayscale image).
25802580
25812581
Returns
25822582
-------
25832583
`~numpy.ndarray`
2584-
An MxNx3 RGB array representing the combined images.
2584+
An (M, N, 3) RGB array representing the combined images.
25852585
"""
25862586
return 2 * intensity * rgb + (1 - 2 * intensity) * rgb**2
25872587

@@ -2592,14 +2592,14 @@ def blend_overlay(self, rgb, intensity):
25922592
Parameters
25932593
----------
25942594
rgb : `~numpy.ndarray`
2595-
An MxNx3 RGB array of floats ranging from 0 to 1 (color image).
2595+
An (M, N, 3) RGB array of floats ranging from 0 to 1 (color image).
25962596
intensity : `~numpy.ndarray`
2597-
An MxNx1 array of floats ranging from 0 to 1 (grayscale image).
2597+
An (M, N, 1) array of floats ranging from 0 to 1 (grayscale image).
25982598
25992599
Returns
26002600
-------
26012601
ndarray
2602-
An MxNx3 RGB array representing the combined images.
2602+
An (M, N, 3) RGB array representing the combined images.
26032603
"""
26042604
low = 2 * intensity * rgb
26052605
high = 1 - 2 * (1 - intensity) * (1 - rgb)

lib/matplotlib/lines.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,9 +1031,7 @@ def get_path(self):
10311031
return self._path
10321032

10331033
def get_xydata(self):
1034-
"""
1035-
Return the *xy* data as a Nx2 numpy array.
1036-
"""
1034+
"""Return the *xy* data as a (N, 2) array."""
10371035
if self._invalidy or self._invalidx:
10381036
self.recache()
10391037
return self._xy

lib/matplotlib/patches.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,14 +1081,16 @@ def __str__(self):
10811081
@_api.make_keyword_only("3.6", name="closed")
10821082
def __init__(self, xy, closed=True, **kwargs):
10831083
"""
1084-
*xy* is a numpy array with shape Nx2.
1085-
1086-
If *closed* is *True*, the polygon will be closed so the
1087-
starting and ending points are the same.
1084+
Parameters
1085+
----------
1086+
xy : (N, 2) array
10881087
1089-
Valid keyword arguments are:
1088+
closed : bool, default: True
1089+
Whether the polygon is closed (i.e., has identical start and end
1090+
points).
10901091
1091-
%(Patch:kwdoc)s
1092+
**kwargs
1093+
%(Patch:kwdoc)s
10921094
"""
10931095
super().__init__(**kwargs)
10941096
self._closed = closed

lib/matplotlib/path.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ class Path:
2828
2929
The underlying storage is made up of two parallel numpy arrays:
3030
31-
- *vertices*: an Nx2 float array of vertices
31+
- *vertices*: an (N, 2) float array of vertices
3232
- *codes*: an N-length uint8 array of path codes, or None
3333
3434
These two arrays always have the same length in the first
@@ -210,9 +210,7 @@ def _update_values(self):
210210

211211
@property
212212
def vertices(self):
213-
"""
214-
The list of vertices in the `Path` as an Nx2 numpy array.
215-
"""
213+
"""The vertices of the `Path` as an (N, 2) array."""
216214
return self._vertices
217215

218216
@vertices.setter
@@ -684,7 +682,7 @@ def interpolated(self, steps):
684682
def to_polygons(self, transform=None, width=0, height=0, closed_only=True):
685683
"""
686684
Convert this path to a list of polygons or polylines. Each
687-
polygon/polyline is an Nx2 array of vertices. In other words,
685+
polygon/polyline is an (N, 2) array of vertices. In other words,
688686
each polygon has no ``MOVETO`` instructions or curves. This
689687
is useful for displaying in backends that do not support
690688
compound paths or Bézier curves.

lib/matplotlib/streamplot.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def streamplot(axes, x, y, u, v, density=1, linewidth=None, color=None,
5757
See `~matplotlib.patches.FancyArrowPatch`.
5858
minlength : float
5959
Minimum length of streamline in axes coordinates.
60-
start_points : Nx2 array
60+
start_points : (N, 2) array
6161
Coordinates of starting points for the streamlines in data coordinates
6262
(the same coordinates as the *x* and *y* arrays).
6363
zorder : float

lib/matplotlib/transforms.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ def count_contains(self, vertices):
584584
585585
Parameters
586586
----------
587-
vertices : Nx2 Numpy array.
587+
vertices : (N, 2) array
588588
"""
589589
if len(vertices) == 0:
590590
return 0
@@ -769,7 +769,7 @@ def __init__(self, points, **kwargs):
769769
Parameters
770770
----------
771771
points : `~numpy.ndarray`
772-
A 2x2 numpy array of the form ``[[x0, y0], [x1, y1]]``.
772+
A (2, 2) array of the form ``[[x0, y0], [x1, y1]]``.
773773
"""
774774
super().__init__(**kwargs)
775775
points = np.asarray(points, float)
@@ -1485,13 +1485,13 @@ def transform(self, values):
14851485
----------
14861486
values : array
14871487
The input values as NumPy array of length :attr:`input_dims` or
1488-
shape (N x :attr:`input_dims`).
1488+
shape (N, :attr:`input_dims`).
14891489
14901490
Returns
14911491
-------
14921492
array
14931493
The output values as NumPy array of length :attr:`output_dims` or
1494-
shape (N x :attr:`output_dims`), depending on the input.
1494+
shape (N, :attr:`output_dims`), depending on the input.
14951495
"""
14961496
# Ensure that values is a 2d array (but remember whether
14971497
# we started with a 1d or 2d array).
@@ -1511,8 +1511,8 @@ def transform(self, values):
15111511
elif ndim == 2:
15121512
return res
15131513
raise ValueError(
1514-
"Input values must have shape (N x {dims}) "
1515-
"or ({dims}).".format(dims=self.input_dims))
1514+
"Input values must have shape (N, {dims}) or ({dims},)"
1515+
.format(dims=self.input_dims))
15161516

15171517
def transform_affine(self, values):
15181518
"""
@@ -1530,13 +1530,13 @@ def transform_affine(self, values):
15301530
----------
15311531
values : array
15321532
The input values as NumPy array of length :attr:`input_dims` or
1533-
shape (N x :attr:`input_dims`).
1533+
shape (N, :attr:`input_dims`).
15341534
15351535
Returns
15361536
-------
15371537
array
15381538
The output values as NumPy array of length :attr:`output_dims` or
1539-
shape (N x :attr:`output_dims`), depending on the input.
1539+
shape (N, :attr:`output_dims`), depending on the input.
15401540
"""
15411541
return self.get_affine().transform(values)
15421542

@@ -1555,13 +1555,13 @@ def transform_non_affine(self, values):
15551555
----------
15561556
values : array
15571557
The input values as NumPy array of length :attr:`input_dims` or
1558-
shape (N x :attr:`input_dims`).
1558+
shape (N, :attr:`input_dims`).
15591559
15601560
Returns
15611561
-------
15621562
array
15631563
The output values as NumPy array of length :attr:`output_dims` or
1564-
shape (N x :attr:`output_dims`), depending on the input.
1564+
shape (N, :attr:`output_dims`), depending on the input.
15651565
"""
15661566
return values
15671567

src/_backend_agg_wrapper.cpp

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -459,14 +459,16 @@ PyRendererAgg_draw_gouraud_triangle(PyRendererAgg *self, PyObject *args)
459459

460460
if (points.dim(0) != 3 || points.dim(1) != 2) {
461461
PyErr_Format(PyExc_ValueError,
462-
"points must be a 3x2 array, got %" NPY_INTP_FMT "x%" NPY_INTP_FMT,
462+
"points must have shape (3, 2), "
463+
"got (%" NPY_INTP_FMT ", %" NPY_INTP_FMT ")",
463464
points.dim(0), points.dim(1));
464465
return NULL;
465466
}
466467

467468
if (colors.dim(0) != 3 || colors.dim(1) != 4) {
468469
PyErr_Format(PyExc_ValueError,
469-
"colors must be a 3x4 array, got %" NPY_INTP_FMT "x%" NPY_INTP_FMT,
470+
"colors must have shape (3, 4), "
471+
"got (%" NPY_INTP_FMT ", %" NPY_INTP_FMT ")",
470472
colors.dim(0), colors.dim(1));
471473
return NULL;
472474
}
@@ -497,24 +499,16 @@ PyRendererAgg_draw_gouraud_triangles(PyRendererAgg *self, PyObject *args)
497499
&trans)) {
498500
return NULL;
499501
}
500-
501-
if (points.size() != 0 && (points.dim(1) != 3 || points.dim(2) != 2)) {
502-
PyErr_Format(PyExc_ValueError,
503-
"points must be a Nx3x2 array, got %" NPY_INTP_FMT "x%" NPY_INTP_FMT "x%" NPY_INTP_FMT,
504-
points.dim(0), points.dim(1), points.dim(2));
502+
if (points.size() && !check_trailing_shape(points, "points", 3, 2)) {
505503
return NULL;
506504
}
507-
508-
if (colors.size() != 0 && (colors.dim(1) != 3 || colors.dim(2) != 4)) {
509-
PyErr_Format(PyExc_ValueError,
510-
"colors must be a Nx3x4 array, got %" NPY_INTP_FMT "x%" NPY_INTP_FMT "x%" NPY_INTP_FMT,
511-
colors.dim(0), colors.dim(1), colors.dim(2));
505+
if (colors.size() && !check_trailing_shape(colors, "colors", 3, 4)) {
512506
return NULL;
513507
}
514-
515508
if (points.size() != colors.size()) {
516509
PyErr_Format(PyExc_ValueError,
517-
"points and colors arrays must be the same length, got %" NPY_INTP_FMT " and %" NPY_INTP_FMT,
510+
"points and colors arrays must be the same length, got "
511+
"%" NPY_INTP_FMT " points and %" NPY_INTP_FMT "colors",
518512
points.dim(0), colors.dim(0));
519513
return NULL;
520514
}

src/_path.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ void get_path_collection_extents(agg::trans_affine &master_transform,
394394
extent_limits &extent)
395395
{
396396
if (offsets.size() != 0 && offsets.dim(1) != 2) {
397-
throw std::runtime_error("Offsets array must be Nx2");
397+
throw std::runtime_error("Offsets array must have shape (N, 2)");
398398
}
399399

400400
size_t Npaths = paths.size();

src/mplutils.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,33 @@ inline int prepare_and_add_type(PyTypeObject *type, PyObject *module)
6262
return 0;
6363
}
6464

65+
#ifdef __cplusplus // not for macosx.m
66+
// Check that array has shape (N, d1) or (N, d1, d2). We cast d1, d2 to longs
67+
// so that we don't need to access the NPY_INTP_FMT macro here.
68+
69+
template<typename T>
70+
inline bool check_trailing_shape(T array, char const* name, long d1)
71+
{
72+
if (array.dim(1) != d1) {
73+
PyErr_Format(PyExc_ValueError,
74+
"%s must have shape (N, %ld), got (%ld, %ld)",
75+
name, d1, array.dim(0), array.dim(1));
76+
return false;
77+
}
78+
return true;
79+
}
80+
81+
template<typename T>
82+
inline bool check_trailing_shape(T array, char const* name, long d1, long d2)
83+
{
84+
if (array.dim(1) != d1 || array.dim(2) != d2) {
85+
PyErr_Format(PyExc_ValueError,
86+
"%s must have shape (N, %ld, %ld), got (%ld, %ld, %ld)",
87+
name, d1, d2, array.dim(0), array.dim(1), array.dim(2));
88+
return false;
89+
}
90+
return true;
91+
}
92+
#endif
93+
6594
#endif

0 commit comments

Comments
 (0)
0