def add_letter(ax: Axes = None, offset: float = 0, offset2: float = 0, letter: str = None): """ add a letter indicating which subplot it is to the given figure """ global letter_index from matplotlib.transforms import Affine2D, ScaledTranslation # get the axes if ax is None: ax = plt.gca() # get the figure fig = ax.figure # get the font properties for figure letters font = get_letter_font_prop() # if no letter is given if letter is None: # use the letter_format from the font letter = font.letter_format # and add a letter given the current letter_index letter = letter.replace("a", chr(ord("a") + letter_index)) letter = letter.replace("A", chr(ord("A") + letter_index)) # increase the letter index letter_index += 1 # add a transform that gives the coordinates relative to the left top corner of the axes in cm transform = Affine2D().scale(1 / 2.54, 1 / 2.54) + fig.dpi_scale_trans + ScaledTranslation(0, 1, ax.transAxes) # add a text a the given position ax.text(-0.5+offset, offset2, letter, fontproperties=font, transform=transform, ha="center", va="bottom", picker=True)
def plot( self, ax: Axes, text_kw=None, shift=dict(units="dots", x=15), **kwargs ) -> List[Artist]: if text_kw is None: text_kw = {} if "projection" in ax.__dict__ and "transform" not in kwargs: from cartopy.crs import PlateCarree from matplotlib.transforms import offset_copy kwargs["transform"] = PlateCarree() geodetic_transform = PlateCarree()._as_mpl_transform(ax) text_kw["transform"] = offset_copy(geodetic_transform, **shift) if "color" not in kwargs: kwargs["color"] = "black" if "s" not in text_kw: text_kw["s"] = getattr(self, "callsign", "") cumul: List[Artist] = [] cumul.append(ax.scatter(self.longitude, self.latitude, **kwargs)) cumul.append(ax.text(self.longitude, self.latitude, **text_kw)) return cumul
def plot( self, ax: Axes, text_kw=None, shift=None, **kwargs ) -> List[Artist]: # coverage: ignore if shift is None: # flake B006 shift = dict(units="dots", x=15) if text_kw is None: text_kw = {} else: # since we may modify it, let's make a copy text_kw = {**text_kw} if "projection" in ax.__dict__ and "transform" not in kwargs: from cartopy.crs import PlateCarree from matplotlib.transforms import offset_copy kwargs["transform"] = PlateCarree() geodetic_transform = PlateCarree()._as_mpl_transform(ax) text_kw["transform"] = offset_copy(geodetic_transform, **shift) if "color" not in kwargs: kwargs["color"] = "black" if "s" not in text_kw: if hasattr(self, "callsign"): text_kw["s"] = getattr(self, "callsign") # noqa: B009 if hasattr(self, "name"): text_kw["s"] = getattr(self, "name") # noqa: B009 cumul: List[Artist] = [] cumul.append(ax.scatter(self.longitude, self.latitude, **kwargs)) cumul.append(ax.text(self.longitude, self.latitude, **text_kw)) return cumul
def draw_from_point_to_bbox(parent_axes: Axes, insert_axes: Axes, point: Sequence, loc=1, **kwargs): """ add a box connector from a point to an axes """ from mpl_toolkits.axes_grid1.inset_locator import TransformedBbox, BboxConnector, Bbox rect = TransformedBbox(Bbox([point, point]), parent_axes.transData) # rect = TransformedBbox(Bbox([[1, 0], [1, 0]]), parent_axes.transData) p1 = BboxConnector(rect, insert_axes.bbox, loc, **kwargs) parent_axes.add_patch(p1) p1.set_clip_on(False) return p1
def mark_inset_pos(parent_axes: Axes, inset_axes: Axes, loc1: Union[int, Sequence[int]], loc2: Union[int, Sequence[int]], point: Sequence, **kwargs): """ add a box connector where the second axis is shrinked to a point """ kwargs["lw"] = 0.8 ax_new = plt.axes(inset_axes.get_position()) ax_new.set_xlim(point[0], point[0]) ax_new.set_ylim(point[1], point[1]) mark_inset(parent_axes, ax_new, loc1, loc2, **kwargs) plt.xticks([]) plt.yticks([]) ax_new.set_zorder(inset_axes.get_zorder() - 1)
def draw_from_point_to_point(parent_axes: Axes, insert_axes: Axes, point1: Sequence, point2: Sequence, **kwargs): """ add a box connector from a point in on axes to a point in another axes """ from mpl_toolkits.axes_grid1.inset_locator import TransformedBbox, BboxConnector, Bbox rect = TransformedBbox(Bbox([point1, point1]), parent_axes.transData) rect2 = TransformedBbox(Bbox([point2, point2]), insert_axes.transData) # rect = TransformedBbox(Bbox([[1, 0], [1, 0]]), parent_axes.transData) loc = 1 p1 = BboxConnector(rect, rect2, loc, **kwargs) parent_axes.add_patch(p1) p1.set_clip_on(False) return p1
def despine(ax: Axes = None, complete: bool = False): """ despine the given axes """ if not ax: ax = plt.gca() ax.spines['right'].set_visible(False) ax.spines['top'].set_visible(False) if complete: ax.spines['left'].set_visible(False) ax.spines['bottom'].set_visible(False) ax.set_xticks([]) ax.set_yticks([]) else: # Only show ticks on the left and bottom spines ax.yaxis.set_ticks_position('left') ax.xaxis.set_ticks_position('bottom')
def format_plot_4(plt_4: Axes) -> None: """Adjust all properties of plot 4 to make it look nice. Add the x & y ticks, format those ticks, set the title, and place the text on the plot for the empty text plot. Parameters ---------- plt_4 : `Axes` The object that describes the graph """ plt_4.text(0.5, 0.5, "CGP Grey Electoral College Spreadsheet graphed.", transform=plt_4.transAxes, fontsize=20, horizontalalignment="center") plt_4.axis("off")
def mark_inset(parent_axes: Axes, inset_axes: Axes, loc1: Union[int, Sequence[int]] = 1, loc2: Union[int, Sequence[int]] = 2, **kwargs): """ like the mark_inset function from matplotlib, but loc can also be a tuple """ from mpl_toolkits.axes_grid1.inset_locator import TransformedBbox, BboxPatch, BboxConnector try: loc1a, loc1b = loc1 except: loc1a = loc1 loc1b = loc1 try: loc2a, loc2b = loc2 except: loc2a = loc2 loc2b = loc2 rect = TransformedBbox(inset_axes.viewLim, parent_axes.transData) pp = BboxPatch(rect, fill=False, **kwargs) parent_axes.add_patch(pp) pp.set_clip_on(False) p1 = BboxConnector(inset_axes.bbox, rect, loc1=loc1a, loc2=loc1b, **kwargs) inset_axes.add_patch(p1) p1.set_clip_on(False) p2 = BboxConnector(inset_axes.bbox, rect, loc1=loc2a, loc2=loc2b, **kwargs) inset_axes.add_patch(p2) p2.set_clip_on(False) return pp, p1, p2
def plot_history(history: dict, lbl: str, ax1: Axes, ax2: Axes, color: str) -> Tuple[Axes, Axes]: """ 根據給定的history畫圖,左為loss vs epoch,右為accuracy vs epoch Args: history (dict): keras中的history dict lbl (str): 該history對應的legend ax1 (Axes) 物件,畫線圖 (loss vs epoch) ax2 (Axes) 物件,畫線圖 (accuracy vs epoch) color (str) : 該history對應的顏色 Returns: Tuple[Axes, Axes] : 畫好線的Axes物件 """ acc_keyword = ['acc', 'accuracy'] val_acc_keyword = ['val_acc', 'val_accuracy'] ax1.plot(history['loss'], label=f'{lbl}_train', c=color) ax1.plot(history['val_loss'], label=f'{lbl}_val', c=color, linestyle='--') ax1.set_ylabel('Loss') ax1.set_xlabel('Epoch') ######### [START] for differenct keras version acc keywords ############# try: # 'acc' for keras 2.1.6 ax2.plot(history[acc_keyword[0]], label=f'{lbl}_train', c=color) ax2.plot(history[val_acc_keyword[0]], label=f'{lbl}_val', c=color, linestyle='--') except KeyError: # 'accuracy' for keras > 2.1.6 ax2.plot(history[acc_keyword[1]], label=f'{lbl}_train', c=color) ax2.plot(history[val_acc_keyword[1]], label=f'{lbl}_val', c=color, linestyle='--') ######### [END] for differenct keras version acc keywords ############# ax2.set_ylabel('accuracy') ax2.set_xlabel('Epoch') return ax1, ax2
def format_plot_1(plt_1: Axes, x_vals: List[int], state_info_list: List[StateInfo]) -> PlotProps: """Adjust all properties of plot 1 to make it look nice. Add the x & y ticks, format those ticks, set the title, draw the mean line, and place the text on the plot for the pop_per_rep plot. Parameters ---------- plt_1 : `Axes` The object that describes the graph x_vals : `List[int]` The list of ints that shows the states' positions state_info_list : `List[StateInfo]` Continually updated list of state calculation info Returns ------- `PlotProps` A tuple of the plotted bars, text, and line objects """ state_names = extract_state_names(state_info_list) pop_per_rep_list = extract_pop_per_rep(state_info_list) plt_1_bars: BarContainer = plt_1.bar(x_vals, pop_per_rep_list, align="center") plt_1.set_xticks(x_vals) plt_1.set_xticklabels(state_names, rotation="vertical") y_formatter = FuncFormatter(comma_format_int()) plt_1.set_ylabel("People/Representative") plt_1.set_yscale("log") plt_1.get_yaxis().set_major_formatter(y_formatter) plt_1.set_title("People per representative per state") plt_1.grid(axis="y", which="major", lw=2) plt_1.grid(axis="y", which="minor", lw=0.75) plt_1.grid(axis="x", lw=0.75) mean_pop_per_seat: float = np.mean(pop_per_rep_list) std_dev_pop_per_seat: float = np.std(pop_per_rep_list) range_pop_per_seat: float = max(pop_per_rep_list) - min(pop_per_rep_list) geo_mean_pop_per_seat: float = geometric_mean(pop_per_rep_list) res_dict: PlotTextDict = {} res_dict["seat_txt"] = plt_1.text(0.25, 0.75, f"Seat# 1", transform=plt_1.transAxes) res_dict["state_txt"] = plt_1.text(0.15, 0.85, "State: ", transform=plt_1.transAxes) res_dict["mean_txt"] = plt_1.text(0.45, 0.75, f"Mean: {mean_pop_per_seat:,.2f}", transform=plt_1.transAxes) res_dict["std_dev_txt"] = plt_1.text( 0.35, 0.85, f"Std. Dev. {std_dev_pop_per_seat:,.2f}", transform=plt_1.transAxes) res_dict["range_txt"] = plt_1.text(0.70, 0.75, f"Range: {range_pop_per_seat:,.2f}", transform=plt_1.transAxes) res_dict["geo_mean_txt"] = plt_1.text( 0.6, 0.85, f"Geo. Mean: {geo_mean_pop_per_seat:,.2f}", transform=plt_1.transAxes) mean_line: Line2D = plt_1.axhline(y=mean_pop_per_seat, xmin=0.0, xmax=1.0, color="r") return (plt_1_bars, mean_line, res_dict)
def format_plot_3(plt_3: Axes, x_vals: List[int], state_info_list: List[StateInfo]) -> BarContainer: """Adjust all properties of plot 3 to make it look nice. Add the x & y ticks, format those ticks, set the title, and place the text on the plot for the priority num plot. Parameters ---------- plt_3 : `Axes` The object that describes the graph x_vals : `List[int]` The list of ints that shows the states' position's state_info_list : `List[StateInfo]` Continually updated list of state calculation info Returns ------- `BarContainer` The objects describing the plotted bars """ state_names = extract_state_names(state_info_list) priority_list = extract_priority(state_info_list) plt_3_bars: BarContainer = plt_3.bar(x_vals, priority_list, align="center", color="g") plt_3.set_xticks(x_vals) plt_3.set_xticklabels(state_names, rotation="vertical") y_formatter: FuncFormatter = FuncFormatter(comma_format_int()) plt_3.set_ylabel("Priority value") plt_3.set_yscale("log") plt_3.get_yaxis().set_major_formatter(y_formatter) plt_3.text(0.3, 0.9, "Highlighted, is the state with the highest priority value", transform=plt_3.transAxes) plt_3.grid(axis="y", which="major", lw=2) plt_3.grid(axis="y", which="minor", lw=0.75) plt_3.grid(axis="x", lw=0.75) plt_3.set_title("Priority values per state") return plt_3_bars
def format_plot_2(plt_2: Axes, x_vals: List[int], state_info_list: List[StateInfo]) -> BarContainer: """Adjust all properties of plot 2 to make it look nice. Add the x & y ticks, format those ticks, set the title, and place the text on the plot for the number of reps plot. Parameters ---------- plt_2 : `Axes` The object that describes the graph x_vals : `List[int]` The list of ints that shows the states' position's state_info_list : `List[StateInfo]` Continually updated list of state calculation info Returns ------- `BarContainer` The objects describing the plotted bars """ state_names = extract_state_names(state_info_list) reps_list = extract_reps(state_info_list) plt_2_bars: BarContainer = plt_2.bar(x_vals, reps_list, align="center", color="r") plt_2.set_xticks(x_vals) plt_2.set_xticklabels(state_names, rotation="vertical") y_axis = plt_2.get_yaxis() minor_loc = MultipleLocator(5) y_axis.set_minor_locator(minor_loc) plt_2.set_ylabel("Representatives") plt_2.set_ylim(top=60, bottom=0) plt_2.grid(axis="y", which="major", lw=2) plt_2.grid(axis="y", which="minor", lw=0.75) plt_2.grid(axis="x", lw=0.75) plt_2.set_title("Representatives per state") return plt_2_bars
def update(frameNum: int, img: mltimg.AxesImage, grid: np.ndarray, N: int, ax: mltax.Axes, G: int): newGrid = grid.copy() visited = np.zeros(N * N).reshape(N, N) counters = np.zeros(len(BEINGS)) reported = [] global FRAME if frameNum == 1: print("SUCCESS Simulation begins.") # implementation of the rules of Life for i in range(N): for j in range(N): rareCase = False myNeighbours = checkNeighbours(i, j, grid) me = int(grid[i][j]) if myNeighbours == 0: rareCase = True if me != 0 and myNeighbours < 2: # underpopulation newGrid[i][j] = 0 if me != 0 and (myNeighbours == 2 or myNeighbours == 3): # next generation newGrid[i][j] = 255 if me != 0 and myNeighbours > 3: # overpopulation newGrid[i][j] = 0 if me != 255 and myNeighbours == 3: # reproduction newGrid[i][j] = 255 # count Life patterns if not checked already if int(visited[i][j]) == 0: res, visited = countLife(i, j, grid, visited, rareCase) # if something detected, count it if len(res) > 0: reported.append(res) counters[int(res[0])] += 1 global TOTAL_COUNTERS TOTAL_COUNTERS[int(res[0])] += 1 # update total counters for seeds and others num, visited = countOthers(grid, visited) global TOTAL_OTHERS TOTAL_OTHERS += num global TOTAL_LIVES TOTAL_LIVES += len(reported) # report the count at every frame handleReport("------ Generation {0} ------\n".format(FRAME)) handleReport("Total Life Beings: {0}\n".format(len(reported))) handleReport("Total Other Beings: {0}\n".format(num)) handleReport("+++++++++++++++++++++++++++\n") for i in range(len(BEINGS)): handleReport("{n}: {v}\n".format(n=BEINGS_STR[i], v=int(counters[i]))) handleReport("+++++++++++++++++++++++++++\n") for j in range(len(reported)): handleReport("{i}. {n} at {y}, {x}\n".format( i=j + 1, n=BEINGS_STR[reported[j][0]], y=reported[j][1], x=reported[j][2])) # at last, calculate percentage of appearance if frameNum == (G - 1): handleReport("======= Incidence % =======\n") if TOTAL_LIVES == 0 and TOTAL_OTHERS == 0: TOTAL_LIVES = 1 # to avoid div by zero for i in range(len(BEINGS)): handleReport("{n}: {v} %\n".format( n=BEINGS_STR[i], v=round( (TOTAL_COUNTERS[i] / (TOTAL_LIVES + TOTAL_OTHERS)) * 100.0, 2))) handleReport("{n}: {v} %\n".format( n="others", v=round((TOTAL_OTHERS / (TOTAL_LIVES + TOTAL_OTHERS)) * 100.0, 2))) handleReport("", True) print("SUCCESS Simulation Report is now available.") # update data ax.set_title("Conway's Game of Life\nGeneration = {0}".format(frameNum + 1)) img.set_data(newGrid) img.set_cmap('binary') grid[:] = newGrid[:] FRAME += 1 return img,
def plot_data_since(data_adaptor: DataAdaptor, type_: ValueType, countries: Iterable[str], ax: Axes, start: Optional[int] = None, legend: bool = False) -> None: data_country = data_adaptor.get_time_series_for_country( type_, countries, start) time_data = data_country.index.days if start else data_country.index ax.plot(time_data, data_country[countries]) if legend: ax.legend(countries) ax.set_yscale("log") if start: ax.set_xlim(-1.0, data_country.index.days.max()) ax.set_ylim(start, data_country.max().max()) ax.set_ylabel(type_.value) if start: ax.set_xlabel(f"Days since {start} {type_.value}") else: ax.set_xlabel("Date")
def draw_samples(self, ax: Axes): ax.scatter([s[1] for s in self._samples], [s[0] for s in self._samples], s=1, c='red')
def plot_delta_since(data_adaptor: DataAdaptor, type_: ValueType, countries: Iterable[str], ax: Axes, rolling: int = 1, start: Optional[int] = None, legend: bool = False) -> None: data_country = data_adaptor.get_time_delta_for_country( type_, countries, start, rolling) data_country[data_country <= 0] = np.NAN if start: data_country = data_country[data_country.index.days >= 0] time_data = data_country.index.days if start else data_country.index ax.plot(time_data, data_country[countries]) if legend: ax.legend(countries) ax.set_yscale("log") ax.set_ylim(data_country.min().min(), data_country.max().max()) ylabel = f"{type_.value} per day" if rolling > 1: ylabel += f" ({rolling} day moving average)" ax.set_ylabel(ylabel) if start: ax.set_xlabel(f"Days since {start} {type_.value}") else: ax.set_xlabel("Date")
def prettifyLife(ax: mltax.Axes, N: int) -> None: if N <= 50: ax.grid() ax = plt.gca() ax.set_xticks(np.arange(-.5, N - 1, 1)) ax.set_yticks(np.arange(-.51, N - 1, 1)) ax.set_xticklabels(np.arange(0, N, 1)) ax.set_yticklabels(np.arange(0, N, 1)) elif N > 50 and N < 80: ax.grid() ax = plt.gca() labels = [" " for x in range(N)] plt.xticks(np.arange(-.5, N - 1, 1), labels) plt.yticks(np.arange(-.51, N - 1, 1), labels)