8000 pulled the markevery logic out of the main draw function. · matplotlib/matplotlib@f53c286 · GitHub
[go: up one dir, main page]

Skip to content

Commit f53c286

Browse files
tacaswellrtrwalker
authored andcommitted
pulled the markevery logic out of the main draw function.
1 parent 009cff0 commit f53c286

File tree

1 file changed

+113
-81
lines changed

1 file changed

+113
-81
lines changed

lib/matplotlib/lines.py

Lines changed: 113 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,117 @@ def segment_hits(cx, cy, x, y, radius):
7272
#print points,lines
7373
return np.concatenate((points, lines))
7474

75+
def _mark_every_path(markevery, tpath, affine, ax_transform):
76+
"""
77+
Helper function that sorts out how to deal the input
78+
`markevery` and returns the points where markers should be drawn.
79+
80+
Takes in the `markevery` value and the line path and returns the
81+
sub-sampled path.
82+
"""
83+
# pull out the two bits of data we want from the path
84+
codes, verts = tpath.codes, tpath.vertices
85+
86+
def _slice_or_none(in_v, slc):
87+
'''
88+
Helper function to cope with `codes` being an
89+
ndarray or `None`
90+
'''
91+
if in_v is None:
92+
return None
93+
return in_v[slc]
94+
95+
# if just a float, assume starting at 0.0 and make a tuple
96+
if isinstance(markevery, float):
97+
markevery = (0.0, markevery)
98+
# if just an int, assume starting at 0 and make a tuple
99+
elif isinstance(markevery, int):
100+
markevery = (0, markevery)
101+
102+
if isinstance(markevery, tuple):
103+
if len(markevery) != 2:
104+
raise ValueError('`markevery` is a tuple but its '
105+
'len is not 2; '
106+
'markevery=%s' % (markevery,))
107+
start, step = markevery
108+
# if step is an int, old behavior
109+
if isinstance(step, int):
110+
#tuple of 2 int is for backwards compatibility,
111+
if not(isinstance(start, int)):
112+
raise ValueError('`markevery` is a tuple with '
113+
'len 2 and second element is an int, but '
114+
'the first element is not an int; '
115+
'markevery=%s' % (markevery,))
116+
# just return, we are done here
117+
118+
return Path(verts[slice(start, None, step)],
119+
_slice_or_none(codes, slice(start, None, step)))
120+
121+
elif isinstance(step, float):
122+
if not (isinstance(start, int) or
123+
isinstance(start, float)):
124+
raise ValueError('`markevery` is a tuple with '
125+
'len 2 and second element is a float, but '
126+
'the first element is not a float or an '
127+
'int; '
128+
'markevery=%s' % (markevery,))
129+
#calc cumulative distance along path (in display
130+
# coords):
131+
disp_coords = affine.transform(tpath.vertices)
132+
delta = np.empty((len(disp_coords), 2),
133+
dtype=float)
134+
delta[0, :] = 0.0
135+
delta[1:, :] = (disp_coords[1:, :] -
136+
disp_coords[:-1, :])
137+
delta = np.sum(delta**2, axis=1)
138+
delta = np.sqrt(delta)
139+
delta = np.cumsum(delta)
140+
#calc distance between markers along path based on
141+
# the axes bounding box diagonal being a distance
142+
# of unity:
143+
scale = ax_transform.transform(
144+
np.array([[0, 0], [1, 1]]))
145+
scale = np.diff(scale, axis=0)
146+
scale = np.sum(scale**2)
147+
scale = np.sqrt(scale)
148+
marker_delta = np.arange(start * scale,
149+
delta[-1],
150+
step * scale)
151+
#find closest actual data point that is closest to
152+
# the theoretical distance along the path:
153+
inds = np.abs(delta[np.newaxis, :] -
154+
marker_delta[:, np.newaxis])
155+
inds = inds.argmin(axis=1)
156+
inds = np.unique(inds)
157+
# return, we are done here
158+
return Path(verts[inds],
159+
_slice_or_none(codes, inds))
160+
else:
161+
raise ValueError('`markevery` is a tuple with '
162+
'len 2, but its second element is not an int '
163+
'or a float; '
164+
'markevery=%s' % (markevery,))
165+
166+
elif isinstance(markevery, slice):
167+
# mazol tov, it's already a slice, just return
168+
return Path(verts[markevery],
169+
_slice_or_none(codes, markevery))
170+
171+
elif iterable(markevery):
172+
#fancy indexing
173+
try:
174+
return Path(verts[markevery],
175+
_slice_or_none(codes, markevery))
176+
177+
except (ValueError, IndexError):
178+
raise ValueError('`markevery` is iterable but '
179+
'not a valid form of numpy fancy indexing; '
180+
'markevery=%s' % (markevery,))
181+
else:
182+
raise ValueError('Value of `markevery` is not '
183+
'recognized; '
184+
'markevery=%s' % (markevery,))
185+
75186

76187
class Line2D(Artist):
77188
"""
@@ -612,87 +723,8 @@ def draw(self, renderer):
612723
# subsample the markers if markevery is not None
613724
markevery = self.get_markevery()
614725
if markevery is not None:
615-
if isinstance(markevery, float):
616-
markevery = (0.0, markevery)
617-
if isinstance(markevery, tuple):
618-
if len(markevery) != 2:
619-
raise ValueError('`markevery` is a tuple but its '
620-
'len is not 2; '
621-
'markevery=%s' % (markevery,))
622-
start, step = markevery
623-
if isinstance(step, int):
624-
#tuple of 2 int is for backwards compatibility,
625-
if not(isinstance(start, int)):
626-
raise ValueError('`markevery` is a tuple with '
627-
'len 2 and second element is an int, but '
628-
'the first element is not an int; '
629-
'markevery=%s' % (markevery,))
630-
inds = slice(start, None, step)
631-
elif isinstance(step, float):
632-
if not (isinstance(start, int) or
633-
isinstance(start, float)):
634-
raise ValueError('`markevery` is a tuple with '
635-
'len 2 and second element is a float, but '
636-
'the first element is not a float or an '
637-
'int; '
638-
'markevery=%s' % (markevery,))
639-
#calc cumulative distance along path (in display
640-
# coords):
641-
disp_coords = affine.transform(tpath.vertices)
642-
delta = np.empty((len(disp_coords), 2),
643-
dtype=float)
644-
delta[0, :] = 0.0
645-
delta[1:, :] = (disp_coords[1:, :] -
646-
disp_coords[:-1, :])
647-
delta = np.sum(delta**2, axis=1)
648-
delta = np.sqrt(delta)
649-
delta = np.cumsum(delta)
650-
#calc distance between markers along path based on
651-
# the axes bounding box diagonal being a distance
652-
# of unity:
653-
scale = self.axes.transAxes.transform(
654-
np.array([[0, 0], [1, 1]]))
655-
scale = np.diff(scale, axis=0)
656-
scale = np.sum(scale**2)
657-
scale = np.sqrt(scale)
658-
marker_delta = np.arange(start * scale,
659-
delta[-1],
660-
step * scale)
661-
#find closest actual data point that is closest to
662-
# the theoretical distance along the path:
663-
inds = np.abs(delta[np.newaxis, :] -
664-
marker_delta[:, np.newaxis])
665-
inds = inds.argmin(axis=1)
666-
inds = np.unique(inds)
667-
else:
668-
raise ValueError('`markevery` is a tuple with '
669-
'len 2, but its second element is not an int '
670-
'or a float; '
671-
'markevery=%s' % (markevery,))
672-
elif isinstance(markevery, int):
673-
start, step = 0, markevery
674-
inds = slice(start, None, step)
675-
elif isinstance(markevery, slice):
676-
inds = markevery
677-
elif iterable(markevery):
678-
#fancy indexing
679-
inds = markevery
680-
try:
681-
tpath.vertices[inds]
682-
except (ValueError, IndexError):
683-
raise ValueError('`markevery` is iterable but '
684-
'not a valid form of numpy fancy indexing; '
685-
'markevery=%s' % (markevery,))
686-
else:
687-
raise ValueError('Value of `markevery` is not '
688-
'recognized; '
689-
'markevery=%s' % (markevery,))
690-
if tpath.codes is not None:
691-
codes = tpath.codes[inds]
692-
else:
693-
codes = None
694-
vertices = tpath.vertices[inds]
695-
subsampled = Path(vertices, codes)
726+
subsampled = _mark_every_path(markevery, tpath,
727+
affine, self.axes.transAxes)
696728
else:
697729
subsampled = tpath
698730

0 commit comments

Comments
 (0)
0