Skip to content

Commit 1f4708b

Browse files
committed
Fix collection offsets
1 parent 57db5a7 commit 1f4708b

File tree

2 files changed

+45
-37
lines changed

2 files changed

+45
-37
lines changed

lib/matplotlib/collections.py

Lines changed: 14 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -194,20 +194,18 @@ def __init__(self,
194194
else:
195195
self._joinstyle = None
196196

197+
# default to zeros
197198
self._offsets = np.zeros((1, 2))
198-
# save if offsets passed in were none...
199-
self._offsetsNone = offsets is None
200-
self._uniform_offsets = None
199+
201200
if offsets is not None:
202201
offsets = np.asanyarray(offsets, float)
203202
# Broadcast (2,) -> (1, 2) but nothing else.
204203
if offsets.shape == (2,):
205204
offsets = offsets[None, :]
206-
if transOffset is not None:
207-
self._offsets = offsets
208-
self._transOffset = transOffset
209-
else:
210-
self._uniform_offsets = offsets
205+
self._offsets = offsets
206+
207+
if transOffset is not None:
208+
self._transOffset = transOffset
211209

212210
self._path_effects = None
213211
self.update(kwargs)
@@ -229,6 +227,9 @@ def get_offset_transform(self):
229227
t = t._as_mpl_transform(self.axes)
230228
return t
231229

230+
def set_offset_transform(self, transOffset):
231+
self._transOffset = transOffset
232+
232233
def get_datalim(self, transData):
233234
# Calculate the data limits and return them as a `.Bbox`.
234235
#
@@ -248,8 +249,8 @@ def get_datalim(self, transData):
248249

249250
transform = self.get_transform()
250251
transOffset = self.get_offset_transform()
251-
if (not self._offsetsNone and
252-
not transOffset.contains_branch(transData)):
252+
hasOffsets = np.any(self._offsets) # True if any non-zero offsets
253+
if (hasOffsets and not transOffset.contains_branch(transData)):
253254
# if there are offsets but in some coords other than data,
254255
# then don't use them for autoscaling.
255256
return transforms.Bbox.null()
@@ -279,7 +280,7 @@ def get_datalim(self, transData):
279280
self.get_transforms(),
280281
transOffset.transform_non_affine(offsets),
281282
transOffset.get_affine().frozen())
282-
if not self._offsetsNone:
283+
if hasOffsets:
283284
# this is for collections that have their paths (shapes)
284285
# in physical, axes-relative, or figure-relative units
285286
# (i.e. like scatter). We can't uniquely set limits based on
@@ -542,20 +543,12 @@ def set_offsets(self, offsets):
542543
offsets = np.asanyarray(offsets, float)
543544
if offsets.shape == (2,): # Broadcast (2,) -> (1, 2) but nothing else.
544545
offsets = offsets[None, :]
545-
# This decision is based on how they are initialized above in __init__.
546-
if self._uniform_offsets is None:
547-
self._offsets = offsets
548-
else:
549-
self._uniform_offsets = offsets
546+
self._offsets = offsets
550547
self.stale = True
551548

552549
def get_offsets(self):
553550
"""Return the offsets for the collection."""
554-
# This decision is based on how they are initialized above in __init__.
555-
if self._uniform_offsets is None:
556-
return self._offsets
557-
else:
558-
return self._uniform_offsets
551+
return self._offsets
559552

560553
def _get_default_linewidth(self):
561554
# This may be overridden in a subclass.
@@ -1441,9 +1434,6 @@ def set_segments(self, segments):
14411434
seg = np.asarray(seg, float)
14421435
_segments.append(seg)
14431436

1444-
if self._uniform_offsets is not None:
1445-
_segments = self._add_offsets(_segments)
1446-
14471437
self._paths = [mpath.Path(_seg) for _seg in _segments]
14481438
self.stale = True
14491439

@@ -1474,19 +1464,6 @@ def get_segments(self):
14741464

14751465
return segments
14761466

1477-
def _add_offsets(self, segs):
1478-
offsets = self._uniform_offsets
1479-
Nsegs = len(segs)
1480-
Noffs = offsets.shape[0]
1481-
if Noffs == 1:
1482-
for i in range(Nsegs):
1483-
segs[i] = segs[i] + i * offsets
1484-
else:
1485-
for i in range(Nsegs):
1486-
io = i % Noffs
1487-
segs[i] = segs[i] + offsets[io:io + 1]
1488-
return segs
1489-
14901467
def _get_default_linewidth(self):
14911468
return mpl.rcParams['lines.linewidth']
14921469

lib/matplotlib/tests/test_collections.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,3 +1048,34 @@ def test_get_segments():
10481048
readback, = lc.get_segments()
10491049
# these should comeback un-changed!
10501050
assert np.all(segments == readback)
1051+
1052+
1053+
def test_set_offsets_late():
1054+
identity = mtransforms.IdentityTransform()
1055+
sizes = [2]
1056+
1057+
null = mcollections.CircleCollection(sizes=sizes)
1058+
1059+
init = mcollections.CircleCollection(sizes=sizes, offsets=(10, 10))
1060+
1061+
late = mcollections.CircleCollection(sizes=sizes)
1062+
late.set_offsets((10, 10))
1063+
1064+
# Bbox.__eq__ doesn't compare bounds
1065+
null_bounds = null.get_datalim(identity).bounds
1066+
init_bounds = init.get_datalim(identity).bounds
1067+
late_bounds = late.get_datalim(identity).bounds
1068+
1069+
# offsets and transform are applied when set after initialization
1070+
assert null_bounds != init_bounds
1071+
assert init_bounds == late_bounds
1072+
1073+
1074+
def test_set_offset_transform():
1075+
skew = mtransforms.Affine2D().skew(2, 2)
1076+
init = mcollections.Collection([], transOffset=skew)
1077+
1078+
late = mcollections.Collection([])
1079+
late.set_offset_transform(skew)
1080+
1081+
assert skew == init.get_offset_transform() == late.get_offset_transform()

0 commit comments

Comments
 (0)