def draw_cellcycle(annotations, totalCompartments=100, phases=OrderedDict([('G1', 0), ('S', 45), ('G2', 65), ('M', 85)]), ax=None, innerAnnotRing=.5): """ annotations => pd.Series with genes in index and peak time values >>> ax = draw_cellcycle() """ xytransform = lambda r, t: (r * np.cos(2 * np.pi * (360 - t) / 360), r * np .sin(2 * np.pi * (360 - t) / 360)) if ax: fig = ax.get_figure() else: fig, ax = plt.subplots() padding = .1 innerRadius = .8 ax.axis('off') ax.set_xlim((-1 - padding, 1 + padding)) ax.set_ylim((-1 - padding, 1 + padding)) ax.add_patch(ptch.Circle(xy=(0, 0), radius=1, fill=False, lw=2)) ax.add_patch(ptch.Circle(xy=(0, 0), radius=innerRadius, fill=False, lw=2)) compartments = np.arange(0, 360, 360 / totalCompartments) - 90 phaseStart = list(phases.values()) for i, p in enumerate(phases): ax.add_patch( ptch.PathPatch(ptch.Path([ xytransform(1, compartments[phases[p]]), xytransform(innerRadius, compartments[phases[p]]) ]), color='k', lw=5)) anAngle = np.mean( (compartments[phaseStart[i]], compartments[phaseStart[i + 1]] if i + 1 < len(phases) else 360 - 90)) ax.annotate(p, xytransform(np.mean((1, innerRadius)), anAngle), va='center', ha='center') for p, grp in annotations.groupby(by=annotations): ax.add_patch( ptch.PathPatch(ptch.Path([ xytransform(1, compartments[p]), xytransform(innerRadius, compartments[p]) ]), color='r', lw=3)) ax.annotate(','.join(grp.index), xytransform( (1 + padding) if len(grp) == 1 else innerAnnotRing, compartments[p]), va='center', ha='center', rotation=180 - compartments[p]) return ax
def _recompute_path(self): """Recompute the full path forming the "tick" arrowed wedge. This method overwrites "mpatches.Wedge._recompute_path" in the super-class. """ if self.direction not in [-1, +1]: return mpatches.Wedge._recompute_path(self) theta1, theta2 = self.theta1, self.theta2 arrow_angle = min(5, abs(theta2 - theta1) / 2) normalized_arrow_width = self.width / 2.0 / self.radius if self.direction == +1: angle_start_arrow = theta1 + arrow_angle arc = mpatches.Path.arc(angle_start_arrow, theta2) outer_arc = arc.vertices[::-1] * (1 + normalized_arrow_width) inner_arc = arc.vertices * (1 - normalized_arrow_width) arrow_vertices = [ outer_arc[-1], np.array( [np.cos(np.deg2rad(theta1)), np.sin(np.deg2rad(theta1))]), inner_arc[0], ] else: angle_start_arrow = theta2 - arrow_angle arc = mpatches.Path.arc(theta1, angle_start_arrow) outer_arc = arc.vertices * (self.radius + self.width / 2.0) / self.radius inner_arc = (arc.vertices[::-1] * (self.radius - self.width / 2.0) / self.radius) arrow_vertices = [ outer_arc[-1], np.array( [np.cos(np.deg2rad(theta2)), np.sin(np.deg2rad(theta2))]), inner_arc[0], ] p = np.vstack([outer_arc, arrow_vertices, inner_arc]) path_vertices = np.vstack([p, inner_arc[-1, :], (0, 0)]) path_codes = np.hstack([ arc.codes, 4 * [mpatches.Path.LINETO], arc.codes[1:], mpatches.Path.LINETO, mpatches.Path.CLOSEPOLY, ]) path_codes[len(arc.codes)] = mpatches.Path.LINETO # Shift and scale the wedge to the final location. path_vertices *= self.r path_vertices += np.asarray(self.center) self._path = mpatches.Path(path_vertices, path_codes)
def add_chord(ax, R, angle_a, angle_b, color, width): # cartesian coordinates of endpoint a x_a = R*np.cos(angle_a); y_a = R * np.sin(angle_a) # cartesian coordinates of endpoint b x_b = R * np.cos(angle_b); y_b = R * np.sin(angle_b) chord_1 = patches.PathPatch(patches.Path([[x_a, y_a], [x_b, y_b]], [patches.Path.MOVETO, patches.Path.LINETO]), edgecolor = color, lw = width, fill = False) return ax.add_patch(chord_1)
def mapSpots(self): # Create new flux array spottedFlux = self.unspottedFlux * np.ones(self.unspottedFlux.shape) # Map Spots for i, spot in enumerate(self.spots): # Get polygon spotPoly = spot.poly # Transform spot coords from Geodetic coord system to rotated projection spot_vs = self.rotated_proj.transform_points( self.geodetic_proj, spotPoly.vertices[:, 0], spotPoly.vertices[:, 1])[:, 0:2] # Split poly to avoid issues at boundary polys = splitPoly(spot_vs, 180) for poly in polys: # Get vertices of spot/tissot polygon spot_vs = poly.get_xy() # Mask in rotated projection (use mpl.Path.clip_to_bbox function) spot_path = patches.Path(spot_vs).clip_to_bbox( Bbox([[self.lon1, self.lat1], [self.lon2, self.lat2]])) # If spot in visible area calculate flux change if len(spot_path.vertices): # Transform masked path to orth projection as this is coordinate space LD grid is in spot_vs = self.orth_proj.transform_points( self.rotated_proj, spot_path.vertices[:, 0], spot_path.vertices[:, 1])[:, 0:2] spot_path = patches.Path(spot_vs) # Find pixels contained in mask and multiply by spot brightnesss mask = self.maskPixels(spot_path) spottedFlux[mask] = spottedFlux[mask] * spot.brightness return spottedFlux
def _gen_axes_path(self): """ Create the path that defines the outline of the projection """ lim = self._limit verts = [ (-lim * 2, -lim), # left, bottom (-lim * 2, lim), # left, top (lim * 2, lim), # right, top (lim * 2, -lim), # right, bottom (-lim * 2, -lim) ] # close path return patches.Path(verts, closed=True)
def plot_sample_chords(ax, solution_coord_a, solution_coord_b, R): M = len(solution_coord_b) assert(M == len(solution_coord_b)) # construct the chords from the coordinates of their endpoints chords_A = [patches.PathPatch(patches.Path([solution_coord_a[i], solution_coord_b[i]], [patches.Path.MOVETO, patches.Path.LINETO]), edgecolor = "blue", lw = 0.5, fill = False) for i in range(M)] _tmp = ax.set(xlim = (-R - 0.01, R + 0.01), ylim = (-R - 0.01, R + 0.01), aspect = 1) # plot the chords for chord in chords_A: _tmp = ax.add_patch(chord) return _tmp
def build_connected_path2(P, verbose=0, model='H'): r""" Takes a path P consisting of a list of segments (not necessarily in correct order) and constructs a connected path. """ from sage.all import deepcopy ## This is the only place where we allow for coddes to be = 1 (i.e. starting a path) if len(P) == 0: return P print "P=", P print "P0=", P[0] ## Begin by locating left most path if model == 'H': xmin = P[0].vertices.min() else: xmin = None imin = 0 for i in range(0, len(P)): try: if model == 'H': testmin = P[i].vertices.min() else: v = P[i].vertices[0] w = (CC(v[1], -v[0]) - CC(0, 1)) / (CC(v[0], v[1]) - CC(1, 0)) testmin = w.real() for v in P[i].vertices: if v[1] == 0 and v[0] == 1.0: # correspond to infinity continue w = (CC(v[1], -v[0]) - CC(0, 1)) / (CC(v[0], v[1]) - CC(1, 0)) if w.real() < testmin: testmin = w.real() if verbose > 0: print "testmin[{0}]={1}".format(P[i], testmin) if xmin == None: xmin = testmin if testmin < xmin: imin = i xmin = testmin if verbose > 0: print "xmin=", xmin except AttributeError: pass codes = deepcopy(P[imin].codes) for j in range(len(codes)): if codes[j] == 10: codes[j] = 4 # if codes[j]==79: # codes[j]=0 pt = patches.Path(P[imin].vertices, codes) res = [pt] used = [imin] current = imin if verbose > 0: print "left most path is nr. {0}".format(imin) ii = 0 x, y = P[imin].A eps = 1e-12 fc = 'orange' lw = 2 while len(res) < len(P) and ii < len(P): ii += 1 if verbose > 0: print "ii=", ii print "current=", current if ii == len(P): x1, y1 = P[current].A if verbose > 0: print "x,y=", x, y print "x1,y1=", x1, y1 if x == x1 and y == y1: x, y = P[current].B ii = 0 if verbose > 0: print "x,y=", x, y print "res=", res for j in range(len(P)): if verbose > 0: print "++++++++++++++++++++++++++++++++++++++j=", j if j in used: continue if not hasattr(P[j], "vertices"): used.append(j) continue xx, yy = P[j].A #vertices[0] #if verbose>0:p # print "xx,yy(0)=",xx,yy #if abs(xx-x) > eps or abs(yy-y) > eps: # xx,yy = P[j].B if abs(xx - x) < eps and abs(yy - y) < eps: if verbose > 0: print "connect prevsious segment with {0}".format(j) print "segment =", P[j] #print "xx=x,yy=y" vertices = P[j].vertices codes = deepcopy(P[j].codes) if not isinstance(vertices, list): vertices = vertices.tolist() if not isinstance(codes, list): codes = codes.tolist() for jjj in range(len(codes)): if codes[jjj] == 10: if j < 3: codes[jjj] = 2 else: codes[jjj] = 4 #print "vertex=",vertices[jjj] if model == 'D' and abs(vertices[jjj][0] + 0.34 ) < 1e-2 and abs(vertices[jjj][1] + 0.52) < 1e-2: print "==========Changing to 2" codes[jjj] = 2 if ii < len(P) and model == 'H': vertices.pop() codes.pop() if verbose > 0 and j == 3: print "vertices=", vertices print "codes=", codes pt = patches.Path(vertices, codes) res.append(pt) used.append(j) current = j x, y = P[j].A #vertices[-1] break xx, yy = P[j].B #vertices[-1] #if verbose>0: # print "xx,yy(-1)=",xx,yy if abs(xx - x) < eps and abs(yy - y) < eps: if verbose > 0: print "connect previous segment with {0} reversed".format( j) print "segment =", P[j] vertices = P[j].vertices codes = deepcopy(P[j].codes) if not isinstance(vertices, list): vertices = vertices.tolist() vertices.reverse() if not isinstance(codes, list): codes = codes.tolist() if codes[0] <> 1 and codes[-1] == 1: codes.reverse() for jjj in range(len(codes)): if codes[jjj] == 10: if j == 2 and (jjj == 7 or jjj == 8): #print "THIS IS HERE!" codes[jjj] = 3 else: codes[jjj] = 3 if verbose > 0 and j == 2: print "vertices=", vertices print "codes=", codes #for jjj in range(len(vertices)-1): # print "dy/dx({0},{1})={2}".format(jjj,jjj+1,(vertices[jjj][1]-vertices[jjj+1][1])/(vertices[jjj][0]-vertices[jjj+1][0])) # if model=='D' and abs(vertices[jjj][0]+0.098)<1e-3 and abs(vertices[jjj][1]+0.328)<1e-2: # print "Changing to 2" # codes[jjj]=2 if codes[0] <> 1: raise ValueError, "Startpoint of path needs a code 1. got {0}".format( codes[0]) #print "codes[0]=",codes[0] #print "codes[-1]=",codes[-1] if ii < len(P) and model == 'H': vertices.pop() codes.pop() pt = patches.Path(vertices, codes) res.append(pt) used.append(j) current = j x, y = P[j].vertices[0] break if len(used) < len(P): print "Could not connect all paths!" res = patches.Path.make_compound_path(*res) # Now we have to make this into a closed path. #codes = [max(res.codes[j],13) for j in range(len(res.codes))] for i in range(len(res.codes)): if res.codes[i] == 1 and i > 0: res.codes[i] = 2 if '1.3' in matplotlib.__version__: res.codes[-1] = 13 else: res.codes[-1] = patches.Path.CLOSEPOLY if verbose > 0: print "vertices=", res.vertices print "codes=", res.codes #return patches.PathPatch(res) #res.codes = codes return res
from matplotlib import transforms from matplotlib.path import Path from matplotlib.patches import PathPatch fig, ax = plt.subplots() # Path = mpatches.Path path_data = [ (Path.MOVETO, (1000, 1000)), (Path.LINETO, (2000, 1000)), (Path.LINETO, (2000, 2000)), (Path.LINETO, (1000, 2000)), (Path.CLOSEPOLY, (1000, 1000)), ] codes, verts = zip(*path_data) path = mpatches.Path(verts, codes) patch = mpatches.PathPatch(path, facecolor='r', alpha=0.5) ax.add_patch(patch) path_data = [ (Path.MOVETO, (0, 0)), (Path.LINETO, (2500, 0)), (Path.LINETO, (2500, 400)), (Path.LINETO, (0, 400)), (Path.CLOSEPOLY, (0, 0)), ] codes, verts = zip(*path_data) path = mpatches.Path(verts, codes) trans = transforms.Affine2D().rotate_deg_around(0, 0, 30) + ax.transData
def hex_animate(i): if i != seasons[0]: ax.clear() frame = frames[i] df = frame['data'] df_t = df.copy() scale = frame['params']['scale'] show_misses = frame['params']['show_misses'] hex_grid = frame['params']['hex_grid'] scale_factor = frame['params']['scale_factor'] min_factor = frame['params']['min_factor'] if scale == 'P_PPS': # - error if highest val is 1 df_t['P_PPS'] = df_t['P_PPS']/3 if not show_misses: df_t = df_t[df_t['SHOT_MADE'] == 1].copy() hexbin = ax.hexbin(df_t['X'], df_t['Y'], C=df_t[scale].values , gridsize=hex_grid, edgecolors='black',cmap=cm.get_cmap('RdYlBu_r'), extent=[-275, 275, -50, 425] , reduce_C_function=np.sum) # - color hexbin2 = ax.hexbin(df_t['X'], df_t['Y'], C=df_t[scale].values, gridsize=hex_grid, edgecolors='black', cmap=cm.get_cmap('RdYlBu_r'), extent=[-275, 275, -50, 425], reduce_C_function=np.mean) if chart_params['title'] is not None: ax.set_title(chart_params['title'], pad=10, fontdict={'fontsize': chart_params['title_size'], 'fontweight':'semibold'}) court_elements = draw_court() for element in court_elements: ax.add_patch(element) img = plt.imread("basketball-floor-texture.png") ax.imshow(img,zorder=0, extent=[-275, 275, -50, 425]) ax.set_xlim(-250,250) ax.set_ylim(422.5, -47.5) ax.axis(False) if chart_params['context'] is not None: # - If multiple lines then add context size to second variable for each additional line ax.text(0, 435 + (chart_params['context_size'] * chart_params['context'].count('\n')), s=chart_params['context'], fontsize=chart_params['context_size'], ha='center') # - gets the color for the legend on the bottom left using the first season of data offsets = hexbin.get_offsets() orgpath = hexbin.get_paths()[0] verts = orgpath.vertices values1 = hexbin.get_array() values1 = np.array([scale_factor if i > scale_factor else 0 if i < min_factor else i for i in values1]) values1 = ((values1 - 1.0)/(scale_factor-1.0))*(1.0-.4) + .4 values2 = hexbin2.get_array() patches = [] for offset, val in zip(offsets,values1): v1 = verts*val + offset path = mpatches.Path(v1, orgpath.codes) patch = mpatches.PathPatch(path) patches.append(patch) pc = PatchCollection(patches, cmap=cm.get_cmap('RdYlBu_r'), edgecolors='black') if scale == 'PCT_DIFF': if pc.get_clim()[0] is None: bottom = abs(df_t[scale].min()) top = abs(df_t[scale].max()) else: top = abs(pc.get_clim()[1]) bottom = abs(pc.get_clim()[0]) m = min(top, bottom) # - Need one extreme of the comparison to be at least 1.5 percent off from average if m < .025: m = .025 pc.set_clim([-1 * m, m]) # - pps is .4 to 1.something elif scale in ['P_PPS', 'L_PPS']: # - for 2: 20% to 60% # - for 3: 13% to 40% pc.set_clim([0.13333, .4]) else: pc.set_clim([-.05,.05]) pc.set_array(values2) ax.add_collection(pc) hexbin.remove() hexbin2.remove() ax.text(200, 375, str(frame['season']) + "-" + str(frame['season'] + 1)[2:] + ' season', horizontalalignment='center', fontsize=12, bbox=dict(facecolor=background_color, boxstyle='round')) return hexbin,