Skip to content

Commit eb546b4

Browse files
eudoxososcargus
authored andcommitted
Added path.sketch_seed to rcParams
Seed can be manually set for path.sketch by modifying the value of rcParams path.sketch_seed or by passing a seed value to xkcd or Artist.set_sketch . Seed will also have a rolling(auto incrementing) behaviour. Co-Authored-By: Oscar Gustafsson <8114497+oscargus@users.noreply.github.com> Co-Authored-By: eudoxos <1029876+eudoxos@users.noreply.github.com>
1 parent 835220b commit eb546b4

File tree

25 files changed

+259
-28
lines changed

25 files changed

+259
-28
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Seed for ``path.sketch`` will have a rolling (auto incrementing) behaviour
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
4+
The seed for the internal Pseudo number generator will now have an auto changing behavior.
5+
This means that the C code of every artist will get a different seed every time it is called
6+
and this will be done in a deterministic manner.
7+
8+
Two figures sketched with the same parameters and different seed will look different from one another.
9+
10+
``Artist.get_sketch_params()`` will now return a 4-tuple instead of a 3-tuple consisting of
11+
(scale, length, randomness, seed) of the form (float, float, float, int).
12+
13+
See 'What's new' on how to set a value to the seed and its behaviour.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
``sketch_seed`` parameter for rcParams
2+
--------------------------------------
3+
4+
`~matplotlib.rcParams` now has a new parameter ``path.sketch_seed``.
5+
Its default value is 0 and accepted values are any non negative integer.
6+
This allows the user to set the seed for the internal pseudo random number generator in one of three ways.
7+
8+
1) Directly changing the rcParam:
9+
10+
rcParams['path.sketch_seed'] = 20
11+
12+
2) Passing a value to the new *seed* parameter of `~matplotlib.pyplot.xkcd` function:
13+
14+
plt.xkcd(seed=20)
15+
16+
3) Passing a value to the new *seed* parameter of matplotlib.artist.set_sketch_params function:
17+
18+
ln = plt.plot(x, y)
19+
ln[0].set_sketch_params(seed = 20)
20+
21+
The seed will also have a changing characteristic for every artist which will be done in a deterministic manner.
22+
23+
24+
.. plot::
25+
:include-source: true
26+
27+
import matplotlib.pyplot as plt
28+
from matplotlib import rcParams
29+
30+
with plt.xkcd():
31+
rcParams['path.sketch_seed']=0
32+
rcParams['path.sketch']=(2,120,40)
33+
pat,txt=plt.pie([10,20,30,40],wedgeprops={'edgecolor':'black'})
34+
plt.legend(pat,['first','second','third','fourth'],loc='best')
35+
plt.title("seed = 0")
36+
plt.show()
37+
38+
.. plot::
39+
:include-source: true
40+
41+
import matplotlib.pyplot as plt
42+
from matplotlib import rcParams
43+
44+
fig, ax = plt.subplots()
45+
x = np.linspace(0.7, 1.42, 100)
46+
y = x ** 2
47+
ln = ax.plot(x, y, color='black')
48+
ln[0].set_sketch_params(100, 100, 20, 40)
49+
plt.title("seed = 40")
50+
plt.show()
51+
52+
.. plot::
53+
:include-source: true
54+
55+
import matplotlib.pyplot as plt
56+
from matplotlib import rcParams
57+
58+
with plt.xkcd(seed=19680801):
59+
import matplotlib
60+
from matplotlib import gridspec
61+
62+
rcParams['path.sketch']=(2,120,40)
63+
64+
pat,txt=plt.pie([10,20,30,40],wedgeprops={'edgecolor':'black'})
65+
plt.legend(pat,['first','second','third','fourth'],loc='best')
66+
plt.title("seed = 19680801")
67+
plt.show()

lib/matplotlib/artist.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ def __init__(self):
209209
self._gid = None
210210
self._snap = None
211211
self._sketch = mpl.rcParams['path.sketch']
212+
self._sketch_seed = mpl.rcParams['path.sketch_seed']
212213
self._path_effects = mpl.rcParams['path.effects']
213214
self._sticky_edges = _XYPair([], [])
214215
self._in_layout = True
@@ -681,7 +682,8 @@ def get_sketch_params(self):
681682
"""
682683
return self._sketch
683684

684-
def set_sketch_params(self, scale=None, length=None, randomness=None):
685+
def set_sketch_params(self, scale=None, length=None, randomness=None,
686+
seed=None):
685687
"""
686688
Set the sketch parameters.
687689
@@ -701,12 +703,21 @@ def set_sketch_params(self, scale=None, length=None, randomness=None):
701703
The PGF backend uses this argument as an RNG seed and not as
702704
described above. Using the same seed yields the same random shape.
703705
704-
.. ACCEPTS: (scale: float, length: float, randomness: float)
706+
seed : int, optional
707+
Seed for the internal pseudo-random number generator.
708+
709+
.. versionadded:: 3.8
710+
711+
.. ACCEPTS: (scale: float, length: float, randomness: float, seed: int)
705712
"""
713+
if seed is not None:
714+
self._sketch_seed = seed
715+
706716
if scale is None:
707717
self._sketch = None
708718
else:
709-
self._sketch = (scale, length or 128.0, randomness or 16.0)
719+
self._sketch = (scale, length or 128.0, randomness or 16.0,
720+
self._sketch_seed)
710721
self.stale = True
711722

712723
def set_path_effects(self, path_effects):

lib/matplotlib/artist.pyi

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,12 +76,13 @@ class Artist:
7676
def set_gid(self, gid: str | None) -> None: ...
7777
def get_snap(self) -> bool | None: ...
7878
def set_snap(self, snap: bool | None) -> None: ...
79-
def get_sketch_params(self) -> tuple[float, float, float] | None: ...
79+
def get_sketch_params(self) -> tuple[float, float, float, int] | None: ...
8080
def set_sketch_params(
8181
self,
8282
scale: float | None = ...,
8383
length: float | None = ...,
8484
randomness: float | None = ...,
85+
seed: int | None = ...,
8586
) -> None: ...
8687
def set_path_effects(self, path_effects: list[AbstractPathEffect]) -> None: ...
8788
def get_path_effects(self) -> list[AbstractPathEffect]: ...

lib/matplotlib/backend_bases.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,19 @@ def _draw_disabled(self):
754754

755755
return _setattr_cm(self, **no_ops)
756756

757+
@property
758+
def _seed_increment(self):
759+
"""
760+
seed increment for renderer.
761+
It is used to implement the rolling characteristic for seed
762+
"""
763+
self.__seed_increment += 1
764+
return self.__seed_increment
765+
766+
@_seed_increment.setter
767+
def _seed_increment(self, value):
768+
self.__seed_increment = value
769+
757770

758771
class GraphicsContextBase:
759772
"""An abstract base class that provides color, line styles, etc."""
@@ -1062,7 +1075,8 @@ def get_sketch_params(self):
10621075
"""
10631076
return self._sketch
10641077

1065-
def set_sketch_params(self, scale=None, length=None, randomness=None):
1078+
def set_sketch_params(self, scale=None, length=None, randomness=None,
1079+
seed=None):
10661080
"""
10671081
Set the sketch parameters.
10681082
@@ -1076,10 +1090,19 @@ def set_sketch_params(self, scale=None, length=None, randomness=None):
10761090
The length of the wiggle along the line, in pixels.
10771091
randomness : float, default: 16
10781092
The scale factor by which the length is shrunken or expanded.
1093+
seed : int, optional
1094+
Seed for the internal pseudo-random number generator.
1095+
1096+
.. versionadded:: 3.8
10791097
"""
1098+
10801099
self._sketch = (
10811100
None if scale is None
1082-
else (scale, length or 128., randomness or 16.))
1101+
else (scale,
1102+
length or rcParams['path.sketch'][1],
1103+
randomness or rcParams['path.sketch'][2],
1104+
seed or rcParams['path.sketch_seed'])
1105+
)
10831106

10841107

10851108
class TimerBase:

lib/matplotlib/backend_bases.pyi

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,10 @@ class RendererBase:
136136
def stop_rasterizing(self) -> None: ...
137137
def start_filter(self) -> None: ...
138138
def stop_filter(self, filter_func) -> None: ...
139+
@property
140+
def _seed_increment(self) -> int: ...
141+
@_seed_increment.setter
142+
def _seed_increment(self, value: int) -> None: ...
139143

140144
class GraphicsContextBase:
141145
def __init__(self) -> None: ...
@@ -180,6 +184,7 @@ class GraphicsContextBase:
180184
scale: float | None = ...,
181185
length: float | None = ...,
182186
randomness: float | None = ...,
187+
seed:int | None = ...,
183188
) -> None: ...
184189

185190
class TimerBase:

lib/matplotlib/backends/backend_pgf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,7 @@ def _print_pgf_path(self, gc, path, transform, rgbFace=None):
575575
# and has a separate "scale" argument for the amplitude.
576576
# -> Use "randomness" as PRNG seed to allow the user to force the
577577
# same shape on multiple sketched lines
578-
scale, length, randomness = sketch_params
578+
scale, length, randomness, seed = sketch_params
579579
if scale is not None:
580580
# make matplotlib and PGF rendering visually similar
581581
length *= 0.5

lib/matplotlib/figure.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
Artist, allow_rasterization, _finalize_rasterization)
4646
from matplotlib.backend_bases import (
4747
DrawEvent, FigureCanvasBase, NonGuiException, MouseButton, _get_renderer)
48+
4849
import matplotlib._api as _api
4950
import matplotlib.cbook as cbook
5051
import matplotlib.colorbar as cbar
@@ -3141,6 +3142,7 @@ def draw(self, renderer):
31413142

31423143
artists = self._get_draw_artists(renderer)
31433144
try:
3145+
renderer._seed_increment = 0
31443146
renderer.open_group('figure', gid=self.get_gid())
31453147
if self.axes and self.get_layout_engine() is not None:
31463148
try:

lib/matplotlib/lines.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -823,7 +823,8 @@ def draw(self, renderer):
823823
gc.set_foreground(ec_rgba, isRGBA=True)
824824
if self.get_sketch_params() is not None:
825825
scale, length, randomness = self.get_sketch_params()
826-
gc.set_sketch_params(scale/2, length/2, 2*randomness)
826+
seed = self._sketch_seed
827+
gc.set_sketch_params(scale/2, length/2, 2*randomness, seed)
827828

828829
marker = self._marker
829830

lib/matplotlib/mpl-data/matplotlibrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,7 @@
677677
# - *randomness* is the factor by which the length is
678678
# randomly scaled.
679679
#path.effects:
680+
#path.sketch_seed: 0 # seed for the internal pseudo number generator.
680681

681682

682683
## ***************************************************************************

0 commit comments

Comments
 (0)