예제 #1
0
def format_figure(fig: plt.Figure,
                  title: str = None,
                  x_label: str = None,
                  y_label: str = None,
                  title_y_position: float = 0.93):
    fig.set_figwidth(12)
    fig.set_figheight(8)
    fig.set_facecolor("white")
    if title is not None:
        fig.suptitle(title,
                     y=title_y_position,
                     verticalalignment='top',
                     fontsize=24)

    axes = fig.axes
    for ax in axes:
        ax.spines['top'].set_color('white')
        ax.spines['right'].set_color('white')
        ax.set_facecolor("white")
        ax.xaxis.grid(which="both", linewidth=0.5)
        ax.yaxis.grid(which="both", linewidth=0.5)
        ax.xaxis.label.set_fontsize(18)
        ax.yaxis.label.set_fontsize(18)
        ax.title.set_fontsize(20)

    if x_label is not None:
        fig.text(0.5, 0.04, x_label, ha='center', fontdict={'size': 18})

    if y_label is not None:
        fig.text(0.04,
                 0.5,
                 y_label,
                 va='center',
                 rotation='vertical',
                 fontdict={'size': 18})
예제 #2
0
def plot_rt(fig: plt.Figure, target_df: pd.DataFrame, ax: plt.Axes,
            county_name: str) -> None:
    above = [1, 0, 0]
    middle = [1, 1, 1]
    below = [0, 0, 0]
    cmap = ListedColormap(np.r_[np.linspace(below, middle, 25),
                                np.linspace(middle, above, 25)])
    color_mapped = lambda y: np.clip(y, .5, 1.5) - .5
    target_df = target_df.loc[(
        target_df.index.get_level_values('name') == county_name)]
    start_dt = pd.to_datetime(
        target_df['Rt'].index.get_level_values('Date').min())
    index = pd.to_datetime(target_df['Rt'].index.get_level_values('Date'))
    values = target_df['Rt'].values
    # Plot dots and line
    ax.plot(index, values, c='k', zorder=1, alpha=.25)
    ax.scatter(index,
               values,
               s=40,
               lw=.5,
               c=cmap(color_mapped(values)),
               edgecolors='k',
               zorder=2)
    # Aesthetically, extrapolate credible interval by 1 day either side
    lowfn = interp1d(date2num(index),
                     target_df['90_CrI_LB'].values,
                     bounds_error=False,
                     fill_value='extrapolate')
    highfn = interp1d(date2num(index),
                      target_df['90_CrI_UB'].values,
                      bounds_error=False,
                      fill_value='extrapolate')
    extended = pd.date_range(start=start_dt - pd.Timedelta(days=3),
                             end=index[-1] + pd.Timedelta(days=1))
    ax.fill_between(extended,
                    lowfn(date2num(extended)),
                    highfn(date2num(extended)),
                    color='k',
                    alpha=.1,
                    lw=0,
                    zorder=3)
    ax.axhline(1.0, c='k', lw=1, label='$R_t=1.0$', alpha=.25)
    ax.set_title(f'{county_name}',
                 loc='left',
                 fontsize=20,
                 fontweight=0,
                 color='#375A97')
    # Formatting
    ax.xaxis.set_major_locator(mdates.MonthLocator())
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%b'))
    ax.xaxis.set_minor_locator(mdates.DayLocator())
    ax.yaxis.set_major_locator(ticker.MultipleLocator(1))
    ax.yaxis.set_major_formatter(ticker.StrMethodFormatter("{x:.1f}"))
    ax.yaxis.tick_right()
    ax.spines['left'].set_visible(False)
    ax.spines['bottom'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.margins(0)
    ax.grid(which='major', axis='y', c='k', alpha=.1, zorder=-2)
    ax.margins(0)
    ax.set_ylim(0.0, 5.0)
    ax.set_xlim(
        start_dt - pd.Timedelta(days=3),
        target_df.index.get_level_values('Date')[-1] + pd.Timedelta(days=1))
    ax.xaxis.set_major_locator(mdates.WeekdayLocator())
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%b %d'))
    fig.set_facecolor('w')
예제 #3
0
class Graph(tk.Frame):
    ax, original_xlim, original_ylim, coll, pick_id = None, None, None, None, None
    start_end_bool = -1  # 0 is start, 1 is end, -1 is None
    start_index, end_index, move_index, remove_index = 0, None, None, None
    max_time, max_speed, max_height, min_height = 0, 0, 0, 0
    data = []
    connect_ids, move_ids = [], []
    current_color_scheme = 'd'

    def __init__(self, master):
        super().__init__(master)
        self.master = master
        self.fig = Figure(figsize=(10, 7), dpi=100, tight_layout=True)
        self.fig.set_facecolor('#f0f0ed')

        self.zoom_pan = GraphInteractions.ZoomPan()
        self.master_string = tk.StringVar()

        self.canvas = FigureCanvasTkAgg(self.fig, self)
        self.canvas.draw()
        self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)

    def redraw(self, input_file_location):
        x, y, c = zip(*self.read_data(input_file_location))
        self.fig.clear()
        self.ax = self.fig.add_subplot(111, frameon=False)
        self.coll = self.ax.scatter(x, y, color=c, picker=True)
        self.end_index = len(self.data) - 1
        self.connect_ids.append(
            GraphInteractions.ZoomPan.zoom_factory(self.zoom_pan,
                                                   self.ax,
                                                   base_scale=1.3))
        self.connect_ids.extend(
            GraphInteractions.ZoomPan.pan_factory(self.zoom_pan, self.ax))
        self.original_xlim = self.ax.get_xlim()
        self.original_ylim = self.ax.get_ylim()
        self.canvas.draw()

    def redraw_color(self, x, y, c):
        self.fig.clear()
        self.ax = self.fig.add_subplot(111, frameon=False)
        self.coll = self.ax.scatter(x, y, color=c, picker=True)
        self.ax.set_xlim(self.zoom_pan.cur_xlim)
        self.ax.set_ylim(self.zoom_pan.cur_ylim)
        self.connect_ids.append(
            GraphInteractions.ZoomPan.zoom_factory(self.zoom_pan,
                                                   self.ax,
                                                   base_scale=1.3))
        self.connect_ids.extend(
            GraphInteractions.ZoomPan.pan_factory(self.zoom_pan, self.ax))
        self.canvas.draw()

    def reset_zoom(self):
        self.ax.set_xlim(self.original_xlim)
        self.ax.set_ylim(self.original_ylim)
        self.ax.figure.canvas.draw()  # force re-draw

    def reset_start(self, master_string):
        self.start_index = 0
        master_string.set("")
        self.redraw_ext()

    def reset_end(self, master_string):
        self.end_index = len(self.data) - 1
        master_string.set("")
        self.redraw_ext()

    def read_data(self, input_file_location):
        x_array = []
        y_array = []
        color_array = []
        self.data.clear()
        json_file = open(input_file_location, "r")
        file_data = json.load(json_file)
        json_file.close()
        old_time, old_x, old_y = 0, file_data['recording']['path'][0][
            'x'], file_data['recording']['path'][0]['y']
        self.max_time, self.max_speed, self.max_height, self.min_height = 0, 0, 0, file_data[
            'recording']['path'][0]['z']
        speed = 0
        for time in file_data['recording']['path']:
            x_array.append(time['x'])
            y_array.append(time['y'])
            time_div = time['t'] - old_time
            if time['t'] > self.max_time:
                self.max_time = time['t']
            if time_div != 0:
                speed = distance(time['x'], old_x, time['y'], old_y) / time_div
            if speed > self.max_speed:
                self.max_speed = speed
            if time['z'] > self.max_height:
                self.max_height = time['z']
            elif time['z'] < self.min_height:
                self.min_height = time['z']
            self.data.append(
                [time['x'], time['y'], time['t'], speed, time['z']])
            color_array.append('tab:blue')
            old_time = time['t']
            old_x, old_y = time['x'], time['y']
        return zip(x_array, y_array, color_array)

    def redraw_ext(self):
        for cid in self.connect_ids:
            self.canvas.mpl_disconnect(cid)
        self.connect_ids.clear()
        x = []
        y = []
        c = []
        for idx, row in enumerate(self.data):
            x.append(row[0])
            y.append(row[1])
            if idx == self.start_index or idx == self.end_index or idx == self.remove_index:
                c.append('tab:red')
            elif idx < self.start_index or idx > self.end_index or\
                    (self.start_index == 0 and self.end_index == len(self.data) - 1):
                c.append('tab:blue')
            elif self.start_index < idx < self.end_index:
                c.append('c')

        self.redraw_color(x, y, c)

    def redraw_simp(self):
        for cid in self.connect_ids:
            self.canvas.mpl_disconnect(cid)
        self.connect_ids.clear()
        x = []
        y = []
        c = []
        for idx, row in enumerate(self.data):
            x.append(row[0])
            y.append(row[1])
            if idx == self.move_index:
                c.append('tab:red')
            else:
                c.append('tab:blue')
        self.redraw_color(x, y, c)

    def change_color(self, event):
        if event.mouseevent.button != 1: return
        if self.start_end_bool == 0:
            self.start_index = event.ind[0]
        elif self.start_end_bool == 1:
            self.end_index = event.ind[0]
        elif self.start_end_bool == 2:
            self.remove_index = event.ind[0]
        self.redraw_ext()
        self.master_string.set(
            'x: %.4f, y: %.4f' %
            (self.data[event.ind[0]][0], self.data[event.ind[0]][1]))

    def show_time(self):
        self.current_color_scheme = 't'
        for cid in self.connect_ids:
            self.canvas.mpl_disconnect(cid)
        self.connect_ids.clear()
        x = []
        y = []
        c = []
        for idx, row in enumerate(self.data):
            x.append(row[0])
            y.append(row[1])
            gradient = row[2] / self.max_time
            c.append((0, 1 - gradient, gradient))
        self.redraw_color(x, y, c)

    def show_speed(self):
        self.current_color_scheme = 's'
        for cid in self.connect_ids:
            self.canvas.mpl_disconnect(cid)
        self.connect_ids.clear()
        x = []
        y = []
        c = []
        for idx, row in enumerate(self.data):
            x.append(row[0])
            y.append(row[1])
            gradient = row[3] / self.max_speed
            c.append((1 - gradient, gradient, 0))
        self.redraw_color(x, y, c)

    def show_height(self):
        self.current_color_scheme = 'h'
        for cid in self.connect_ids:
            self.canvas.mpl_disconnect(cid)
        self.connect_ids.clear()
        x = []
        y = []
        c = []
        for idx, row in enumerate(self.data):
            x.append(row[0])
            y.append(row[1])
            gradient = (row[4] - self.min_height) / (self.max_height -
                                                     self.min_height)
            c.append((gradient * 0.5 + 0.5, gradient * 0.8, gradient * 0.8))
        self.redraw_color(x, y, c)

    def reset_color(self):
        self.current_color_scheme = 'd'
        for cid in self.connect_ids:
            self.canvas.mpl_disconnect(cid)
        self.connect_ids.clear()
        x = []
        y = []
        c = []
        for idx, row in enumerate(self.data):
            x.append(row[0])
            y.append(row[1])
            c.append('tab:blue')
        self.redraw_color(x, y, c)

    def attach_start_stop(self, master_string_var, start_end):
        self.detach_start_stop()
        self.start_end_bool = start_end
        self.master_string = master_string_var
        self.pick_id = self.canvas.mpl_connect('pick_event', self.change_color)

    def detach_start_stop(self):
        if self.pick_id is None: return
        self.start_end_bool = -1
        self.canvas.mpl_disconnect(self.pick_id)
        for move_id in self.move_ids:
            self.canvas.mpl_disconnect(move_id)

    def attach_move_node(self):
        def on_press(event):
            if event.mouseevent.button != 1: return
            self.move_index = event.ind[0]
            self.master.move_node_location.set(
                'x: %.4f, y: %.4f' %
                (self.data[self.move_index][0], self.data[self.move_index][1]))

        def on_release(event):
            self.redraw_simp()

        def on_motion(event):
            if event.button != 1: return
            self.data[self.move_index][0] = event.xdata
            self.data[self.move_index][1] = event.ydata
            self.master.move_node_location.set(
                'x: %.4f, y: %.4f' %
                (self.data[self.move_index][0], self.data[self.move_index][1]))

            self.redraw_simp()

        self.detach_start_stop()
        self.pick_id = self.canvas.mpl_connect('pick_event', on_press)
        self.move_ids.append(
            self.canvas.mpl_connect('key_press_event', self.move_node_button))
        self.move_ids.append(
            self.canvas.mpl_connect('button_release_event', on_release))
        self.move_ids.append(
            self.canvas.mpl_connect('motion_notify_event', on_motion))

    def attach_remove_node(self, master_string):
        self.detach_start_stop()
        self.start_end_bool = 2
        self.master_string = master_string
        self.pick_id = self.canvas.mpl_connect('pick_event', self.change_color)

    def next_start(self, master_string, diff):
        self.start_index += diff
        if self.start_index < 0:
            self.start_index = 0
        self.redraw_ext()
        master_string.set(
            'x: %.4f, y: %.4f' %
            (self.data[self.start_index][0], self.data[self.start_index][1]))

    def next_end(self, master_string, diff):
        self.end_index += diff
        if self.end_index > len(self.data) - 1:
            self.end_index = len(self.data) - 1
        self.redraw_ext()
        master_string.set(
            'x: %.4f, y: %.4f' %
            (self.data[self.end_index][0], self.data[self.end_index][1]))

    def move_node_button(self, event):
        direction = ""
        if event.key == "up":
            direction = "N"
        elif event.key == "right":
            direction = "E"
        elif event.key == "down":
            direction = "S"
        elif event.key == "left":
            direction = "W"
        if direction != "":
            self.move_node(direction, float(self.master.move_entry.get()))

    def move_node(self, direction, move_distance):
        if direction == "N":
            self.data[self.move_index][1] += move_distance
        elif direction == "E":
            self.data[self.move_index][0] += move_distance
        elif direction == "S":
            self.data[self.move_index][1] -= move_distance
        elif direction == "W":
            self.data[self.move_index][0] -= move_distance
        self.master.move_node_location.set(
            'x: %.4f, y: %.4f' %
            (self.data[self.move_index][0], self.data[self.move_index][1]))
        self.redraw_simp()

    def remove_node(self):
        del self.data[self.remove_index]
        self.end_index = len(self.data) - 1
        self.redraw_ext()
        self.master_string.set(
            'x: %.4f, y: %.4f' %
            (self.data[self.remove_index][0], self.data[self.remove_index][1]))

    def apply_local_speedup(self, value):
        speedup = 1
        speed = 0
        previous_time = 0
        previous_old_time = 0
        old_x, old_y = self.data[0][0], self.data[0][1]
        for idx, row in enumerate(self.data):
            if self.start_index == idx:
                speedup = 1 - float(value) / 100
            elif self.end_index == idx:
                speedup = 1
            old_time = row[2]
            if old_time < previous_old_time:
                previous_old_time = old_time / 2
            row[2] = previous_time + (min(old_time - previous_old_time, 2) *
                                      speedup)
            time_div = row[2] - previous_time
            if row[2] > self.max_time:
                self.max_time = row[2]
            if time_div != 0:
                speed = distance(row[0], old_x, row[1], old_y) / time_div
            if speed > self.max_speed:
                self.max_speed = speed
            row[3] = speed
            previous_time = row[2]
            previous_old_time = old_time
            old_x, old_y = row[0], row[1]
            self.update_unknown()

    def update_unknown(self):
        if self.current_color_scheme == 'h':
            self.show_height()
        elif self.current_color_scheme == 's':
            self.show_speed()
        elif self.current_color_scheme == 't':
            self.show_time()
        else:
            self.reset_color()