Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Allow linear scaling for marker sizes in scatter#25259

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
chahak13 wants to merge10 commits intomatplotlib:main
base:main
Choose a base branch
Loading
fromchahak13:scatter_markersize
Open
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletionsci/mypy-stubtest-allowlist.txt
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -105,6 +105,10 @@ matplotlib.collections.Collection.set_linewidths
matplotlib.collections.Collection.set_ls
matplotlib.collections.Collection.set_lw
matplotlib.collections.Collection.set_transOffset
matplotlib.collections._CollectionWithSizes.get_markersize
matplotlib.collections._CollectionWithSizes.get_s
matplotlib.collections._CollectionWithSizes.set_markersize
matplotlib.collections._CollectionWithSizes.set_s
matplotlib.lines.Line2D.get_aa
matplotlib.lines.Line2D.get_c
matplotlib.lines.Line2D.get_ds
Expand Down
5 changes: 5 additions & 0 deletionsdoc/users/next_whats_new/scatter_markersize.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
``markersize`` and ``markerscale`` added to scatter
---------------------------------------------------
``markersize`` is new alias for ``s`` in scatter that can be used to set the size of
the markers. The marker sizes can now also be set using a linear scale using the
``markerscale`` parameter.
21 changes: 18 additions & 3 deletionslib/matplotlib/axes/_axes.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -4476,7 +4476,7 @@ def invalid_shape_exception(csize, xsize):
@_docstring.interpd
def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None,
vmin=None, vmax=None, alpha=None, linewidths=None, *,
edgecolors=None, plotnonfinite=False, **kwargs):
edgecolors=None, plotnonfinite=False,markerscale=2,**kwargs):
"""
A scatter plot of *y* vs. *x* with varying marker size and/or color.

Expand DownExpand Up@@ -4568,6 +4568,12 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None,
or ``nan``). If ``True`` the points are drawn with the *bad*
colormap color (see `.Colormap.set_bad`).

Copy link
Member

@timhoffmtimhoffmFeb 22, 2024
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I would not call this*scale, because it could be interpreted as "linear scaling factor" - and we do this e.g. atmutation_scale inhttps://matplotlib.org/devdocs/api/_as_gen/matplotlib.patches.FancyArrowPatch.html#matplotlib.patches.FancyArrowPatch. Suggestion:markerscaling or maybe justscaling - I have some sympathy to push this down tocollectionWithSizes later. Ascaling parameter would be meaningful there so that we have consistent naming and don't need to translate the markerscaling kwarg. Also, I believescatter(..., scaling=...) is clear enough.

Also, 1 and 2 are not very telling as values. How about "linear"/"quadratic" or "linear"/"square" or "length"/"area"?

Edit: There seems to be a mismatch between the discussion and code whether to push the scaling down to CollectionWithSizes. I've written the above under the impression that pushing down should not (yet?) be done in this PR. - Rethinking, I claim that pushing down is very much to be preferred - not being able to reflect the high-level scaling concept in the underlying artists would be a major shortcoming. I'm +1 on implementing this immediately in CollectionWithSizes.

markerscale : 1 or 2, optional, default: 2
Scaling factor used to set the size as points or points**2.
Default value is set as 2 to set the size values as points**2.

.. versionadded:: 3.9

Returns
-------
`~matplotlib.collections.PathCollection`
Expand DownExpand Up@@ -4607,9 +4613,17 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None,
if x.size != y.size:
raise ValueError("x and y must be the same size")

if s is not None and 'markersize' in kwargs:
raise ValueError(
"Only one of `s` or `markersize` should be passed. "
"Please refer to the docs for more details about usage.")

if s is None:
s = (20 if mpl.rcParams['_internal.classic_mode'] else
mpl.rcParams['lines.markersize'] ** 2.0)
if 'markersize' not in kwargs:
s = (20 if mpl.rcParams['_internal.classic_mode'] else
mpl.rcParams['lines.markersize'] ** 2.0)
else:
s = kwargs.pop('markersize')
s = np.ma.ravel(s)
if (len(s) not in (1, x.size) or
(not np.issubdtype(s.dtype, np.floating) and
Expand DownExpand Up@@ -4696,6 +4710,7 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None,

collection = mcoll.PathCollection(
(path,), scales,
markerscale=markerscale,
facecolors=colors,
edgecolors=edgecolors,
linewidths=linewidths,
Expand Down
1 change: 1 addition & 0 deletionslib/matplotlib/axes/_axes.pyi
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -411,6 +411,7 @@ class Axes(_AxesBase):
*,
edgecolors: Literal["face", "none"] | ColorType | Sequence[ColorType] | None = ...,
plotnonfinite: bool = ...,
markerscale: int = ...,
data=...,
**kwargs
) -> PathCollection: ...
Expand Down
47 changes: 40 additions & 7 deletionslib/matplotlib/collections.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -930,6 +930,9 @@ def update_from(self, other):
self.stale = True


@_api.define_aliases({
"sizes": ["s", "markersize"]
})
class _CollectionWithSizes(Collection):
"""
Base class for collections that have an array of sizes.
Expand All@@ -938,16 +941,35 @@ class _CollectionWithSizes(Collection):

def get_sizes(self):
"""
Return the sizes ('areas') of the elements in the collection.
Return the sizes of the elements in the collection.

The sizes of the elements in the collection will be returned in
the last set scale of the markers, i.e. if the markerscale was
set to 1 then the sizes are set in points and if markerscale was
set to 2 then the sizes returned are such that the marker size is
in points**2.

Returns
-------
array
The 'area' of each element.
The 'size' of each element.
"""
return self._sizes

def set_sizes(self, sizes, dpi=72.0):
def get_markerscale(self):
"""
Return the scale used for marker sizing.

.. versionadded:: 3.9

Returns
-------
int
The scale used to set the marker sizes.
"""
return self._markerscale

def set_sizes(self, sizes, dpi=72.0, markerscale=2):
"""
Set the sizes of each member of the collection.

Expand All@@ -958,22 +980,28 @@ def set_sizes(self, sizes, dpi=72.0):
value is the 'area' of the element.
dpi : float, default: 72
The dpi of the canvas.
markerscale : 1 or 2, default: 2
Scaling factor used to set the size as points (1) or points**2 (2).

.. versionadded:: 3.9
"""
self._markerscale = markerscale
if sizes is None:
self._sizes = np.array([])
self._transforms = np.empty((0, 3, 3))
else:
self._sizes = np.asarray(sizes)
self._transforms = np.zeros((len(self._sizes), 3, 3))
scale = np.sqrt(self._sizes) * dpi / 72.0 * self._factor
s = np.sqrt(self._sizes) if self._markerscale == 2 else self._sizes
scale = s * dpi / 72.0 * self._factor
self._transforms[:, 0, 0] = scale
self._transforms[:, 1, 1] = scale
self._transforms[:, 2, 2] = 1.0
self.stale = True

@artist.allow_rasterization
def draw(self, renderer):
self.set_sizes(self._sizes, self.figure.dpi)
self.set_sizes(self._sizes, self.figure.dpi, self._markerscale)
super().draw(renderer)


Expand All@@ -982,7 +1010,7 @@ class PathCollection(_CollectionWithSizes):
A collection of `~.path.Path`\s, as created by e.g. `~.Axes.scatter`.
"""

def __init__(self, paths, sizes=None, **kwargs):
def __init__(self, paths, sizes=None,markerscale=2,**kwargs):
"""
Parameters
----------
Expand All@@ -992,13 +1020,18 @@ def __init__(self, paths, sizes=None, **kwargs):
The factor by which to scale each drawn `~.path.Path`. One unit
squared in the Path's data space is scaled to be ``sizes**2``
points when rendered.
markerscale : 1 or 2, default: 2
Scaling factor used to set the size as points (1) or points**2 (2).

.. versionadded:: 3.9

**kwargs
Forwarded to `.Collection`.
"""

super().__init__(**kwargs)
self.set_paths(paths)
self.set_sizes(sizes)
self.set_sizes(sizes, markerscale=markerscale)
self.stale = True

def set_paths(self, paths):
Expand Down
11 changes: 9 additions & 2 deletionslib/matplotlib/collections.pyi
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -70,11 +70,18 @@ class Collection(artist.Artist, cm.ScalarMappable):

class _CollectionWithSizes(Collection):
def get_sizes(self) -> np.ndarray: ...
def set_sizes(self, sizes: ArrayLike | None, dpi: float = ...) -> None: ...
def set_sizes(
self, sizes: ArrayLike | None, dpi: float = ..., markerscale: int = ...
) -> None: ...
def get_markerscale(self) -> int: ...

class PathCollection(_CollectionWithSizes):
def __init__(
self, paths: Sequence[Path], sizes: ArrayLike | None = ..., **kwargs
self,
paths: Sequence[Path],
sizes: ArrayLike | None = ...,
markerscale: int = ...,
**kwargs
) -> None: ...
def set_paths(self, paths: Sequence[Path]) -> None: ...
def get_paths(self) -> Sequence[Path]: ...
Expand Down
2 changes: 2 additions & 0 deletionslib/matplotlib/pyplot.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3587,6 +3587,7 @@ def scatter(
*,
edgecolors: Literal["face", "none"] | ColorType | Sequence[ColorType] | None = None,
plotnonfinite: bool = False,
markerscale: int = 2,
data=None,
**kwargs,
) -> PathCollection:
Expand All@@ -3604,6 +3605,7 @@ def scatter(
linewidths=linewidths,
edgecolors=edgecolors,
plotnonfinite=plotnonfinite,
markerscale=markerscale,
**({"data": data} if data is not None else {}),
**kwargs,
)
Expand Down
22 changes: 22 additions & 0 deletionslib/matplotlib/tests/test_collections.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1216,3 +1216,25 @@ def test_striped_lines(fig_test, fig_ref, gapcolor):
for x, gcol, ls in zip(x, itertools.cycle(gapcolor),
itertools.cycle(linestyles)):
ax_ref.axvline(x, 0, 1, linestyle=ls, gapcolor=gcol, alpha=0.5)


@check_figures_equal(extensions=["png"])
def test_markerscale(fig_test, fig_ref):
ax_test = fig_test.add_subplot()
ax_ref = fig_ref.add_subplot()

x = np.arange(1, 6)**2

ax_test.scatter(x, x, s=x, markerscale=1)
ax_ref.scatter(x, x, s=x**2, markerscale=2)


@check_figures_equal(extensions=["png"])
def test_markersize_alias(fig_test, fig_ref):
ax_test = fig_test.add_subplot()
ax_ref = fig_ref.add_subplot()

x = np.arange(1, 6)**2

ax_test.scatter(x, x, s=x)
ax_ref.scatter(x, x, markersize=x)
4 changes: 2 additions & 2 deletionslib/mpl_toolkits/mplot3d/art3d.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -688,8 +688,8 @@ def set_3d_properties(self, zs, zdir):
self._vzs = None
self.stale = True

def set_sizes(self, sizes, dpi=72.0):
super().set_sizes(sizes, dpi)
def set_sizes(self, sizes, dpi=72.0, markerscale=2):
super().set_sizes(sizes, dpi=dpi, markerscale=markerscale)
if not self._in_draw:
self._sizes3d = sizes

Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp