def city_bar_plot(self, x, y, val, name, min_city, max_city): """ Plotting bar chart at geographic coordinates of cities/municipalities """ # Calculate parameters color = self.get_color(val) val_norm = DataMngr.normalize(val, min_city, max_city) if self.stable: val_norm = DataMngr.normalize(val, self.globalmin, self.globalmax) # Drawing self.axes.bar(x=x, bottom=y, height=val_norm, width=MapChart.BAR_WIDTH, lw=0.3, color=color, edgecolor='black', align='center', alpha=MapChart.ALPHA) self.axes.plot([x - MapChart.LINE_ALIGN, x + MapChart.LINE_ALIGN], [y, y], ls='-', lw=0.5, color='black', alpha=MapChart.ALPHA) self.axes.text(x, y - MapChart.TEXT_ALIGN, name, ha='center', color='black', fontsize=8, alpha=MapChart.ALPHA) return
def normalize(self, val): """ Normalize given value """ if self.stable: val_norm = DataMngr.normalize(val, 0, self.globalmax) else: val_norm = DataMngr.normalize(val, 0, self.localmax) return val_norm
def draw_img(self, data, target_col): """ Plotting all cities/municipalities from data on given axes """ # Add date day = data.index[0] day_str = DataMngr.date_to_str(day) self.axes.text(0.96, 0.85, day_str, ha='right', transform=self.axes.transAxes, fontsize=32, alpha=0.5) if day in self.the_news.index: curr_news = self.the_news[day].split('.') lines = '.\n'.join(curr_news).strip() news_txt = '{}\n {}'.format(day_str, lines) self.axes.text(0, -0.06, news_txt, ha='left', color='black', transform=self.axes.transAxes, fontsize=10, wrap=True, \ bbox=dict(facecolor='floralwhite', edgecolor='moccasin', boxstyle='round')) # Make vertical bar plot for each city max_city = data[target_col].max() min_city = data[target_col].min() for day, city in data.iterrows(): if city[target_col] > MapChart.THRESHOLD: self.city_bar_plot(x=city[DataMngr.LONGITUDE], y=city[DataMngr.LATITUDE], val=city[target_col], name=city[DataMngr.CITY], min_city=min_city, max_city=max_city) return
def draw_map(self): """ Plotting map of Serbia """ map_data = DataMngr.load_map() map_plot = map_data.plot(color='w', edgecolor='w', ax=self.axes) return map_plot
def __init__(self, title, xlabel, ratio, bgcolor, style, stable, top, logo_alpha, width, height, dpi): # Labels and style self.title = title self.xlabel = xlabel self.ratio = ratio self.bgcolor = bgcolor self.style = style self.top = top self.logo_alpha = logo_alpha self.width = width self.height = height self.dpi = dpi self.cmap = None self.norm = None self.date_frames = None self.total_frames = None # Axes margins self.stable = stable self.xmin = None self.xmax = None self.ymin = None self.ymax = None # Figure self.fig = self.create() self.axes = self.fig.gca() self.anim = None # Data self.the_news = DataMngr.load_news() self.duration = Chart.NEWS_TIME
def draw_img(self, data, target_col): """ Drawing image of horizontal bar chart for the target column by cities/municipalities """ # Make horizontal bar plot y = data[DataMngr.CITY] width = data[target_col] maxval = width.max() bars = self.axes.barh(y, width, color=self.cmap(np.arange(len(y) - 1, -1, -1)), alpha=BarhChart.ALPHA) # Set axes self.axes.spines['top'].set_visible(False) self.axes.spines['bottom'].set_visible(False) self.axes.spines['right'].set_visible(False) self.axes.spines['left'].set_color('gray') self.axes.set_facecolor('w') self.axes.tick_params(axis='y', labelsize=8, color='gray') self.axes.xaxis.set_ticks_position('top') self.axes.xaxis.set_major_locator(MaxNLocator(5)) self.axes.tick_params(axis='x', labelsize=8, color='lightgray') self.axes.grid(axis='x', which='major', linestyle='-', linewidth=0.5, zorder=0, color='gray', alpha=0.5) # Add date day = data.index[0] day_str = DataMngr.date_to_str(day) self.axes.text(0.95, 0.1, day_str, ha='right', color='gray', transform=self.axes.transAxes, fontsize=45, alpha=BarhChart.ALPHA, \ bbox=dict(facecolor='w', edgecolor='w', boxstyle='round')) if day in self.the_news.index: curr_news = self.the_news[day].split('.') lines = '.\n'.join(curr_news).strip() news_txt = '{}\n {}'.format(day_str, lines) self.axes.text(0.45, 0.5, news_txt, ha='left', color='black', transform=self.axes.transAxes, fontsize=10, wrap=True, \ bbox=dict(facecolor='floralwhite', edgecolor='moccasin', boxstyle='round')) # Add value for each bar for bar in bars: y_pos = bar.get_y() + bar.get_height() / 2 x_pos = bar.get_width() + maxval / 200 text = '{:.2f}'.format(bar.get_width()) if self.ratio else int( bar.get_width()) self.axes.text(x_pos, y_pos, text, color='black', ha='left', va='center', fontsize=8) return
def draw_anim(self, i_frame, data, target_col): """ Drawing animation of map chart for the target column by cities/municipalities """ # New day if i_frame % self.date_frames == 0: # Update artists new_pos_art = np.argwhere(self.curr_pos == -1).flatten() new_pos = np.setdiff1d(np.arange(0, self.top, 1), self.curr_pos) exist_pos_art = np.argwhere(self.curr_pos != -1).flatten() exist_pos = self.curr_pos[exist_pos_art] old_pos = np.concatenate((exist_pos_art, new_pos_art), axis=None) now_pos = np.concatenate((exist_pos, new_pos), axis=None) bars = [''] * self.top cities = [''] * self.top lines = [''] * self.top for i, npos in enumerate(now_pos): bars[npos] = self.bars[old_pos][i] cities[npos] = self.cities[old_pos][i] lines[npos] = self.lines[old_pos][i] self.bars = np.array(bars) self.cities = np.array(cities) self.lines = np.array(lines) # Update previous data self.prev_cities = self.curr_cities.copy() self.prev_sizes = self.curr_sizes.copy() # Calculate for new day ind_day = i_frame // self.date_frames day = list(data.groups.keys())[ind_day] data = data.get_group(day) self.curr_cities = np.array( data[DataMngr.CITY].reset_index(drop=True).values) self.curr_sizes = np.array( data[target_col].reset_index(drop=True).values) self.curr_xs = np.array( data[DataMngr.LONGITUDE].reset_index(drop=True).values) self.curr_ys = np.array( data[DataMngr.LATITUDE].reset_index(drop=True).values) self.calc_positions_change(self.prev_cities, self.curr_cities) # Artist day_str = DataMngr.date_to_str(day) self.date.set_text(day_str) if day in self.the_news.index: curr_news = self.the_news[day].split('.') lines = '.\n'.join(curr_news).strip() news_txt = '{}\n {}'.format(day_str, lines) self.news.set_text(news_txt) self.duration = Chart.NEWS_TIME elif self.duration == 0: self.news.set_text('') self.duration = Chart.NEWS_TIME else: self.duration -= 1 # Info print(day_str) for i, city in enumerate(zip(self.curr_cities, self.curr_sizes)): print(i, city) print() # Update axes for first day if not self.stable and i_frame == 0: minval = data[target_col].min() maxval = data[target_col].max() self.set_local_extremes(minval, maxval) self.create_cmap(maxval) self.create_cbar() # Update val_changed = self.update_values(i_frame) self.fig.canvas.draw() self.fig.canvas.flush_events() changed = val_changed + [self.date] + [self.news] return changed
def draw_anim(self, i_frame, data, target_col): """ Drawing horizontal bar chart for the target column by cities/municipalities """ # New day if i_frame % self.date_frames == 0: # Update artists bars_ranks = np.vectorize(lambda bar: bar.get_y())(self.bars) order = np.argsort(bars_ranks, kind='mergesort') self.bars = self.bars[order] self.cities = self.cities[order] self.colors = self.colors[order] # Update previous data self.prev_cities = self.curr_cities.copy() self.prev_sizes = self.curr_sizes.copy() # Calculate for new day ind_day = i_frame // self.date_frames day = list(data.groups.keys())[ind_day] data = data.get_group(day) self.curr_cities = np.array( data[DataMngr.CITY].reset_index(drop=True).values) self.curr_sizes = np.array( data[target_col].reset_index(drop=True).values) self.calc_positions_change(self.prev_cities, self.curr_cities) # Artist day_str = DataMngr.date_to_str(day) self.date.set_text(day_str) if day in self.the_news.index: curr_news = self.the_news[day].split('.') lines = '.\n'.join(curr_news).strip() news_txt = '{}\n {}'.format(day_str, lines) self.news.set_text(news_txt) self.duration = Chart.NEWS_TIME elif self.duration == 0: self.news.set_text('') self.duration = Chart.NEWS_TIME else: self.duration -= 1 # Info print(day_str) for i, city in enumerate( zip(reversed(self.curr_cities), reversed(self.curr_sizes))): print(self.top - 1 - i, city) print() # Update axes for first day if not self.stable and i_frame == 0: maxval = data[target_col].max() self.local_max = maxval self.set_xlim(0, self.local_max) # Update pos_changed = self.update_positions(i_frame) self.fig.canvas.draw() self.fig.canvas.flush_events() changed = pos_changed + [self.date] + [self.news] return changed
def __init__(self): self.data = DataMngr.load_build_data(info=False) self.chart = None