@@ -72,6 +72,117 @@ def segment_hits(cx, cy, x, y, radius):
72
72
#print points,lines
73
73
return np .concatenate ((points , lines ))
74
74
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
+
75
186
76
187
class Line2D (Artist ):
77
188
"""
@@ -612,87 +723,8 @@ def draw(self, renderer):
612
723
# subsample the markers if markevery is not None
613
724
markevery = self .get_markevery ()
614
725
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 )
696
728
else :
697
729
subsampled = tpath
698
730
0 commit comments