def draw_timeplan(rule, labels=None, blank_color=0.9): duration = np.shape(rule)[1] time_labels = [label +1 for label in range(duration)] cMap = add_grey(cm.viridis, blank_color) fig, ax = plt.subplots(figsize=np.shape(rule)[::-1] , facecolor='#eeeeee', tight_layout=True) im = ax.pcolorfast(rule, cmap=cMap) #place and null major ticks (we still need them for the grid) ax.xaxis.set_major_locator(ticker.LinearLocator(duration+1)) ax.xaxis.set_major_formatter(ticker.NullFormatter()) #place and format minor ticks (used to substitute for centered major tick labels) ax.xaxis.set_minor_locator(ticker.IndexLocator(1,0.5)) ax.xaxis.set_minor_formatter(ticker.FixedFormatter(time_labels)) #remove all major tick lines plt.setp(ax.get_xticklines(),visible=False) #remove bottom and top small tick lines # for tick in ax.xaxis.get_minor_ticks(): # tick.tick1line.set_markersize(0) # tick.tick2line.set_markersize(0) plt.tick_params(axis='x', which='both', bottom='off', top='off') #Set only 7th minor tick label to visible ax.set_yticklabels(labels) for label in ax.xaxis.get_minorticklabels(): label.set_visible(False) for label in ax.xaxis.get_minorticklabels()[::7]: label.set_visible(True) #Set yticks to labels and add 0.5 cell height offset ax.yaxis.set(ticks=np.arange(0.5, len(labels))) #Set yticks to point outside the figure ax.get_yaxis().set_tick_params(direction='out') #Rotate ytick labels plt.setp(ax.yaxis.get_majorticklabels(), rotation=30) #Constrain yticks to left side of figure ax.yaxis.set_ticks_position('left') # create grid ax.xaxis.grid(True, which='major', color='1', linestyle='-') #delete all spines for spine in ["right", "left", "top", "bottom"]: ax.spines[spine].set_visible(False) # recolour yticks in blank image color [t.set_color(str(blank_color)) for t in ax.yaxis.get_ticklines()]
def multi_plot(reference_df, x_key, shade, saturate, padding=4, saturate_cmap="Pastel1_r", window_start="", window_end=""): """Plotting tool Mandatory Arguments: db_path -- path of db to query for data (can use tilde for home dir) category -- main category to plot on x axis (must be a class from the db) select -- list of lists which must be either 2 (for join) or 3 (for filter) elements long padding -- number of entries to padd timeplan with saturate_cmap -- string indicating the matplotlib cmap to use (http://matplotlib.org/examples/color/colormaps_reference.html) """ #truncate dates for col in reference_df.columns: if "date" in col: #the following catches None entries: try: reference_df[col] = reference_df[col].apply(lambda x: x.date()) except AttributeError: pass #GET FIRST AND LAST DATE dates = get_dates(reference_df, [shade, saturate]) if not window_start: window_start = min(dates) - timedelta(days=padding) else: window_start = datetime.strptime(window_start, "%Y,%m,%d").date() if not window_end: window_end = max(dates) + timedelta(days=padding) else: window_end = datetime.strptime(window_end, "%Y,%m,%d").date() print window_end #create generic plotting dataframe x_vals = list(set(reference_df[x_key])) datetime_index = [i for i in perdelta(window_start,window_end,timedelta(days=1))] df = pd.DataFrame(index=datetime_index, columns=x_vals) df = df.fillna(0) #set plotting params cMap = add_grey(cm.viridis, 0.9) fig_shape = (df.shape[0],df.shape[1]/1.5) #1.5 seems like a good scaling value to make cells not-too-tall and not-too-short fig, ax = plt.subplots(figsize=fig_shape , facecolor='#eeeeee', tight_layout=True) #populate frames df_ = df.copy(deep=True) for c_step, entry in enumerate(shade): for x_val in x_vals: if isinstance(entry, dict): for key in entry: start=False #unless the code below is succesful, no attempt is made to add an entry for the x_val filtered_df = reference_df[(reference_df[key] == entry[key][0])&(reference_df[x_key] == x_val)] try: start = list(set(filtered_df[entry[key][1]]))[0] except IndexError: pass if len(entry[key]) == 3: end = list(set(filtered_df[entry[key][2]]))[0] active_dates = [i for i in perdelta(start,end+timedelta(days=1),timedelta(days=1))] for active_date in active_dates: df_.set_value(active_date, x_val, df_.get_value(active_date, x_val)+c_step+1) elif start: df_.set_value(start, x_val, df_.get_value(start, x_val)+c_step+1) elif isinstance(entry, str): filtered_df = reference_df[reference_df[x_key] == x_val] active_dates = list(set(filtered_df[entry])) for active_date in active_dates: #escaping dates which are outside the date range (e.g. when specifying tighter window_end and window_start contraints) try: df_.set_value(active_date, x_val, df_.get_value(active_date, x_val)+c_step+1) except KeyError: pass im = ax.pcolorfast(df_.T, cmap=add_grey(cm.gray_r, 0.8), alpha=.5) plt.hold(True) #populate frames df_ = df.copy(deep=True) for c_step, entry in enumerate(saturate): for x_val in x_vals: if isinstance(entry, dict): for key in entry: filtered_df = reference_df[(reference_df[key] == entry[key][0])&(reference_df[x_key] == x_val)] try: start = list(set(filtered_df[entry[key][1]]))[0] try: start = start.date() except AttributeError: pass except IndexError: pass if len(entry[key]) == 3: try: end = list(set(filtered_df[entry[key][2]]))[0] active_dates = [i for i in perdelta(start,end+timedelta(days=1),timedelta(days=1))] for active_date in active_dates: df_.set_value(active_date, x_val, df_.get_value(active_date, x_val)+c_step+1) except IndexError: pass elif start: df_.set_value(start, x_val, df_.get_value(start, x_val)+c_step+1) # we need this to make sure start does not remain set for the next iteration: start=False elif isinstance(entry, str): filtered_df = reference_df[reference_df[x_key] == x_val] active_dates = list(set(filtered_df[entry])) df_.set_value(active_dates, x_val, 1) im = ax.pcolorfast(df_.T, cmap=add_grey(getattr(cm,saturate_cmap), 0.9), alpha=.5) plt.hold(True) ax = ttp_style(ax, df_) plt.ylabel(" ".join(x_key.split("_")).replace("id","ID"))