def draw_circle(ax, x, y, color, scale=0.1, line_weight=1.0, zorder=2): path = Path(Path.unit_circle().vertices * scale, Path.unit_circle().codes) trans = matplotlib.transforms.Affine2D().translate(x, y) t_path = path.transformed(trans) patch = patches.PathPatch( t_path, facecolor=color.value, lw=line_weight, zorder=zorder) ax.add_patch(patch) return
def _slot_path(): # Returns a Path for a filled unit circle with a vertical rectangle removed. circle = Path.unit_circle() vertical_bar = _vertical_bar_path() vertices = np.concatenate([circle.vertices[:-1], vertical_bar.vertices[-2::-1]]) codes = np.concatenate([circle.codes[:-1], vertical_bar.codes[:-1]]) return Path(vertices, codes)
def __init__(self, xy, width, height, angle=0.0, **kwargs): """ *xy* center of ellipse *width* length of horizontal axis *height* length of vertical axis *angle* rotation in degrees (anti-clockwise) Valid kwargs are: %(Patch)s """ Patch.__init__(self, **kwargs) self.center = xy self.width, self.height = width, height self.angle = angle self._path = Path.unit_circle() self._patch_transform = transforms.IdentityTransform() self._recompute_transform()
def __init__(self, xy, width, height, scale=1.0, angle=0.0, **kwargs): """ *xy* center of ellipse *width* total length (diameter) of horizontal axis *height* total length (diameter) of vertical axis *angle* rotation in degrees (anti-clockwise) Valid kwargs are: %(Patch)s """ patches.Patch.__init__(self, **kwargs) self.center = xy self.width, self.height = width, height self.scale = scale self.angle = angle self._path = Path.unit_circle() # Note: This cannot be calculated until this is added to an Axes self._patch_transform = transforms.IdentityTransform()
def make_cities_marker(length, flip_y=True): from matplotlib.path import Path from matplotlib.textpath import TextPath from matplotlib.font_manager import FontProperties circle = Path.unit_circle() scale = math.sqrt(length * 0.8) / 4.0 + (0.4 if length > 1 else 0) circle = circle.transformed(mpl.transforms.Affine2D().scale(scale, scale)) if length <= 1: verts = circle.vertices codes = circle.codes else: text = str(length) fp = FontProperties(family="DejaVu Sans", style="oblique") textPath = TextPath((0, 0), text, size=1 if length <= 9 else 1.2, prop=fp) textPath = textPath.transformed(mpl.transforms.Affine2D().scale( 1, -1 if flip_y else 1).translate( -len(text) / 2.5 if len(text) > 1 else -0.2, 0.3)) verts = np.concatenate([circle.vertices, textPath.vertices]) codes = np.concatenate([circle.codes, textPath.codes]) combined_marker = Path(verts, codes) return combined_marker
def test_readonly_path(): path = Path.unit_circle() def modify_vertices(): path.vertices = path.vertices * 2.0 assert_raises(AttributeError, modify_vertices)
def test_contains_points_negative_radius(): path = Path.unit_circle() points = [(0.0, 0.0), (1.25, 0.0), (0.9, 0.9)] expected = [True, False, False] assert np.all(path.contains_points(points, radius=-0.5) == expected)
def __init__(self, center, radius, matrix, **kwargs): Patch.__init__(self, **kwargs) path = Path.unit_circle() self.radius = radius self._code3d = path.codes self._segment3d = center + radius * (path.vertices @ matrix.T) self._path2d = Path(np.zeros((0, 2)))
def _ring_path(): # Returns a Path for a hollow ring. # The outer radius is 1, the inner radius is 1 - _THICKNESS. circle = Path.unit_circle() inner_radius = 1.0 - _THICKNESS vertices = np.concatenate([circle.vertices[:-1], circle.vertices[-2::-1] * inner_radius]) codes = np.concatenate([circle.codes[:-1], circle.codes[:-1]]) return Path(vertices, codes)
def test_readonly_path(): path = Path.unit_circle() def modify_vertices(): path.vertices = path.vertices * 2.0 with pytest.raises(AttributeError): modify_vertices()
def test_tickedstroke(): fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(12, 4)) path = Path.unit_circle() patch = patches.PathPatch(path, facecolor='none', lw=2, path_effects=[ path_effects.withTickedStroke(angle=-90, spacing=10, length=1) ]) ax1.add_patch(patch) ax1.axis('equal') ax1.set_xlim(-2, 2) ax1.set_ylim(-2, 2) ax2.plot( [0, 1], [0, 1], label=' ', path_effects=[path_effects.withTickedStroke(spacing=7, angle=135)]) nx = 101 x = np.linspace(0.0, 1.0, nx) y = 0.3 * np.sin(x * 8) + 0.4 ax2.plot(x, y, label=' ', path_effects=[path_effects.withTickedStroke()]) ax2.legend() nx = 101 ny = 105 # Set up survey vectors xvec = np.linspace(0.001, 4.0, nx) yvec = np.linspace(0.001, 4.0, ny) # Set up survey matrices. Design disk loading and gear ratio. x1, x2 = np.meshgrid(xvec, yvec) # Evaluate some stuff to plot g1 = -(3 * x1 + x2 - 5.5) g2 = -(x1 + 2 * x2 - 4) g3 = .8 + x1**-3 - x2 cg1 = ax3.contour(x1, x2, g1, [0], colors=('k', )) plt.setp(cg1.collections, path_effects=[path_effects.withTickedStroke(angle=135)]) cg2 = ax3.contour(x1, x2, g2, [0], colors=('r', )) plt.setp(cg2.collections, path_effects=[path_effects.withTickedStroke(angle=60, length=2)]) cg3 = ax3.contour(x1, x2, g3, [0], colors=('b', )) plt.setp(cg3.collections, path_effects=[path_effects.withTickedStroke(spacing=7)]) ax3.set_xlim(0, 4) ax3.set_ylim(0, 4)
def test_contains_points_negative_radius(): path = Path.unit_circle() points = [(0.0, 0.0), (1.25, 0.0), (0.9, 0.9)] expected = [True, False, False] result = path.contains_points(points, radius=-0.5) assert result.dtype == np.bool assert np.all(result == expected)
def elliptical_spine(cls, axes, center, xrad, yrad, **kwargs): ''' (staticmethod) Returns an elliptical :class: `Spine`. ''' path = Path.unit_circle() spine_type = 'circle' # since aspect = 2 and axes rect is 0-1, 0-1 result = cls(axes, spine_type, path, **kwargs) set_patch_ellipse(result, center, xrad, yrad) return result
def epilog(k1, k2): marker = Path.unit_circle() for d in _epilog.values(): plot(d['coords'][columns[k1]-5], d['coords'][columns[k2]-5], marker=marker, markersize=7, markeredgecolor='white', markeredgewidth=2, markerfacecolor=d['color'])
def transmute(self, x0, y0, width, height, mutation_size): # padding # pad = mutation_size * self.pad cx, cy = x0 + .5 * width, y0 + .5 * height # center # width and height with padding added. # width, height = width + 2.*pad, height + 2.*pad, # get radius # radius = (width**2 + height**2)**.5 * .5 radius = VISUAL_PLAYER_RADIUS cir_path = Path.unit_circle() vertices = radius * cir_path.vertices + (cx, cy) # a path of the circle path = Path(vertices, cir_path.codes) return path
def make_custom_marker(text, flip_y=False): from matplotlib.path import Path from matplotlib.textpath import TextPath from matplotlib.font_manager import FontProperties textPath = TextPath((0, 4), text, size=3) textPath = textPath.transformed(mpl.transforms.Affine2D().translate( -1 * len(text), 0)) circle = Path.unit_circle() triangle = Path([[0, 0], [1, 0], [0.5, 0.5], [0, 0]], [Path.MOVETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY]) triangle = triangle.transformed(mpl.transforms.Affine2D().translate( -0.5, 0).scale(3, -4).translate(0, 3)) verts = np.concatenate( [circle.vertices, textPath.vertices, triangle.vertices]) codes = np.concatenate([circle.codes, textPath.codes, triangle.codes]) combined_marker = Path(verts, codes) combined_marker = combined_marker.transformed( mpl.transforms.Affine2D().scale(1000, -1000 if flip_y else 1000)) return combined_marker
def __init__(self, xy, radius, **kwargs): """ xy : array_like center of two circles radius : scalar size of each circle Valid kwargs are: %(Patch)s """ Patch.__init__(self, **kwargs) self.center = xy self.radius = radius self.width = 4. # two x unit circle (i.e. from +1 to -1) self.height = 2. # one x unit circle path = copy(Path.unit_circle()) n_pts = path.vertices.shape[0] path.vertices = np.tile(path.vertices, [2,1]) path.vertices[:n_pts,0] -= 1 path.vertices[n_pts:,0] += 1 path.codes = np.tile(path.codes, [2]) self._path = path # Note: This cannot be calculated until this is added to an Axes self._patch_transform = transforms.IdentityTransform()
CLOUD_COVER = { 0: [_ring_path()], 1: [_ring_path(), _vertical_bar_path()], 2: [_ring_path(), _wedge_fix(Path.wedge(0, 90))], 3: [_ring_path(), _wedge_fix(Path.wedge(0, 90)), _vertical_bar_path()], 4: [_ring_path(), Path.unit_circle_righthalf()], 5: [_ring_path(), Path.unit_circle_righthalf(), _left_bar_path()], 6: [_ring_path(), _wedge_fix(Path.wedge(-180, 90))], 7: [_slot_path()], 8: [Path.unit_circle()], 9: [_ring_path(), _slash_path(), _backslash_path()], } """ A dictionary mapping WMO cloud cover codes to their corresponding symbol. See http://www.wmo.int/pages/prog/www/DPFS/documents/485_Vol_I_en_colour.pdf Part II, Appendix II.4, Graphical Representation of Data, Analyses and Forecasts """ def _convert_paths_to_patches(): # Convert the symbols defined as lists-of-paths into patches.
fig, ax = plt.subplots(figsize = (5, 5)) lim = -5.8, 5.7 ax.set(xlim = lim, ylim = lim) marker_obj = m.MarkerStyle('$?$') path = marker_obj.get_path().transformed(marker_obj.get_transform()) path._vertices = np.array(path._vertices)*8 #To make it larger path._vertices[4] = [0,0]#This is where the vertices close full_codes = path.codes full_vertices = path._vertices mark_vertices = full_vertices[5:] mark_codes = full_codes[5:] circ_path = Path.unit_circle() circ_verts = circ_path._vertices*0.65+[0.1, -3] circ_codes = circ_path.codes ##print(circ_verts) ##print(circ_codes) new_vertices = np.append(circ_verts, mark_vertices, axis=0)-[0,0.5] new_codes = np.append(circ_codes, mark_codes, axis = 0) """All this stuff that is commented out was used to make this path. when ? was used to create the path. The little dot under the ? was shown as a square, not a circle. So I had to modify the geometric descriptors of the patch to make it look better. DO NOT ATTEMPT THIS ON IMPORTANT FILES"""
def make(n, side_len, circ_rad, theta, ishift=0, jshift=0, sigma_smooth=0., sigma_noise=0., rs=None): """ Create an illusory triangle contour [1] image with random size and orientation. [1]: https://en.wikipedia.org/wiki/Illusory_contours Parameters ---------- n: int Image shape will be (n,n) side_len: float Side length of the triangle in pixels. circ_rad: float Radius of the circles at the vertices of the triangle in pixels. theta: float (radians) Rotation of the triangle. Zero points the triangle to the right. ishift,jshift: integers Translate the center of the triangle by ishift and jshift. sigma_smooth: float Gaussian smoothing parameter (make image borders more diffuse). sigma_noise: float Additive noise amplitude. rs: numpy.random.RandomState, default=None Include for reproducible results. """ if circ_rad > 0.5*side_len: raise ValueError(("Circle radius should be less " "than one half the side length.")) # Triangle height. height = 0.5*np.sqrt(3)*side_len # Distance from center of triangle to a vertex. tri_rad = (2.0/3.0)*height # Rotation factor for triangle vertices. w = (2.0/3.0)*np.pi # Get extent of triangle plus outer circles for validation. extent = np.zeros((3,2)) for i in range(3): x = (tri_rad+circ_rad)*np.cos(i*w+theta) + n/2 + jshift y = (tri_rad+circ_rad)*np.sin(i*w+theta) + n/2 - ishift extent[i] = n-y,x for e in extent: if e[0] < 0 or e[0] > n-1: raise ValueError(("Extent of triangle plus circles exceeds" "image dimensions along axis 0.")) if e[1] < 0 or e[1] > n-1: raise ValueError(("Extent of triangle plus circles exceeds" "image dimensions along axis 1.")) vertices = np.zeros((3,2)) for i in range(3): x = tri_rad*np.cos(i*w+theta) + n/2 + jshift y = tri_rad*np.sin(i*w+theta) + n/2 - ishift vertices[i] = n-y,x tri_path = mpath(np.append(vertices, vertices[-1].reshape(1,2), axis=0), codes=[mpath.MOVETO, mpath.LINETO, mpath.LINETO, mpath.CLOSEPOLY]) ii,jj = np.indices((n,n)) coords = np.c_[ii.flatten(), jj.flatten()] triangle = tri_path.contains_points(coords).reshape(n,n) ucircle = mpath.unit_circle() circles = np.zeros((n,n), dtype=np.bool) for v in vertices: circle = mpath(vertices=ucircle.vertices*circ_rad + v, codes=ucircle.codes) circles = np.logical_or(circles, circle.contains_points(coords).reshape(n,n)) image = (~np.logical_and(circles, ~triangle)).astype(np.float) rs = rs if rs is not None else np.random.RandomState() if sigma_smooth > 0: image = gaussian_filter(image, sigma_smooth) if sigma_noise > 0: image += sigma_noise*rs.randn(n,n) return image, triangle
def test_contains_points_negative_radius(): path = Path.unit_circle() points = [(0.0, 0.0), (1.25, 0.0), (0.9, 0.9)] result = path.contains_points(points, radius=-0.5) np.testing.assert_equal(result, [True, False, False])
# GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # """ Specialized markers """ from matplotlib.path import Path import numpy as np """The Earth symbol (circle and cross).""" earth = Path.unit_circle() verts = np.concatenate([earth.vertices, [[-1, 0], [1, 0], [0, -1], [0, 1]]]) codes = np.concatenate([earth.codes, [Path.MOVETO, Path.LINETO] * 2]) earth = Path(verts, codes) del verts, codes def reticle(inner=0.5, outer=1.0, angle=0.0): """ Create a reticle (crosshairs) marker. Parameters ---------- inner : float Distance from the origin to the inside of the crosshairs.
def __init__(self, hatch, density): path = Path.unit_circle() self.shape_vertices = path.vertices self.shape_codes = path.codes Shapes.__init__(self, hatch, density)
from matplotlib.markers import MarkerStyle import numpy as np %matplotlib widget px = np.random.rand(10) py = np.random.rand(10) offsets = np.ma.column_stack([px, py]) #%% 1 fig, ax = plt.subplots() reduction = 50 c = Path.unit_circle() c = c.transformed(Affine2D().scale(0.5 * reduction)) collection = PathCollection( (c,), offsets=offsets, transOffset = ax.transData, edgecolor='black', facecolor=(0, 0, 0, .0125), linewidth=1 ) collection.set_transform(IdentityTransform()) ax.add_collection( collection ) #%% 2
# but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # """ Specialized markers """ __all__ = ('earth', 'reticle') from matplotlib.path import Path import numpy as np """The Earth symbol (circle and cross).""" earth = Path.unit_circle() verts = np.concatenate([earth.vertices, [[-1, 0], [1, 0], [0, -1], [0, 1]]]) codes = np.concatenate([earth.codes, [Path.MOVETO, Path.LINETO] * 2]) earth = Path(verts, codes) del verts, codes def reticle(inner=0.5, outer=1.0, angle=0.0): """ Create a reticle (crosshairs) marker. Parameters ---------- inner : float Distance from the origin to the inside of the crosshairs.
return res draw_map = {} def draw_circle(ax, x, y, color, scale=0.1): path = Path(unit_circle.vertices * scale, unit_circle.codes) trans = matplotlib.transforms.Affine2D().translate(x, y) t_path = path.transformed(trans) patch = patches.PathPatch(t_path, facecolor=color.value, lw=line_weight, zorder=2) a = ax.add_patch(patch) ma = MonosaccharidePatch(saccharide_shape=(a,)) return ma # return (a,) draw_map[ResidueShape.circle] = draw_circle unit_circle = Path.unit_circle() def draw_square(ax, x, y, color, scale=0.1): square_verts = np.array([ (0.5, 0.5), (0.5, -0.5), (-0.5, -0.5), (-0.5, 0.5), (0.5, 0.5), (0., 0.), ]) * 2 square_codes = [ Path.MOVETO, Path.LINETO, Path.LINETO,
# but will then be redundant and should be removed. wedge_path.vertices[0] = 0 wedge_path.vertices[-2:] = 0 return wedge_path CLOUD_COVER = { 0: [_ring_path()], 1: [_ring_path(), _vertical_bar_path()], 2: [_ring_path(), _wedge_fix(Path.wedge(0, 90))], 3: [_ring_path(), _wedge_fix(Path.wedge(0, 90)), _vertical_bar_path()], 4: [_ring_path(), Path.unit_circle_righthalf()], 5: [_ring_path(), Path.unit_circle_righthalf(), _left_bar_path()], 6: [_ring_path(), _wedge_fix(Path.wedge(-180, 90))], 7: [_slot_path()], 8: [Path.unit_circle()], 9: [_ring_path(), _slash_path(), _backslash_path()], } """ A dictionary mapping WMO cloud cover codes to their corresponding symbol. See http://www.wmo.int/pages/prog/www/DPFS/documents/485_Vol_I_en_colour.pdf Part II, Appendix II.4, Graphical Representation of Data, Analyses and Forecasts """ def _convert_paths_to_patches(): # Convert the symbols defined as lists-of-paths into patches. for code, symbol in CLOUD_COVER.iteritems(): CLOUD_COVER[code] = _make_merged_patch(symbol)