def plot_situation(tracks, n_tracks=6*3, n_dcs=50, tcz_volume=0.524e9/400, min_distance=0, min_distance_std=200/10, zoom=1, t_detail=None, save=False, context='notebook'): """Plot some T cell tracks, DC positions and T cell zone volume""" sns.set(style='ticks', context=context) _ = plt.figure(figsize=(8, 5.5)) gs = gridspec.GridSpec(2,3) space_ax = plt.subplot(gs[:,:-1], projection='3d') time_ax = plt.subplot(gs[0,-1]) reach_ax = plt.subplot(gs[1,-1]) plt.locator_params(nbins=6) space_ax.set_title('{} T Cell Tracks & {} DCs'.format(n_tracks, n_dcs)) n_conditions = len(tracks['Condition'].unique()) palette = itertools.cycle(sns.color_palette()) if min_distance_std != 0: moved_tracks = tracks.copy() for id in tracks['Track_ID'].unique(): moved_tracks.loc[moved_tracks['Track_ID'] == id, ['X', 'Y', 'Z']] += \ np.random.randn(3)*min_distance_std else: moved_tracks = tracks for i, (cond, cond_tracks) in enumerate(moved_tracks.groupby('Condition')): choice = np.random.choice(cond_tracks['Track_ID'].unique(), n_tracks/n_conditions) chosen_tracks = cond_tracks[cond_tracks['Track_ID'].isin(choice)] for _, track in chosen_tracks.groupby(track_identifiers(chosen_tracks)): if t_detail: track = track[track['Time'] <= t_detail*60] if n_conditions > 1: color = sns.color_palette(n_colors=i+1)[-1] else: color = next(palette) space_ax.plot(track['X'].values, track['Y'].values, track['Z'].values, color=color) tcz_radius = (3*tcz_volume/(4*np.pi))**(1/3) ratio = (min_distance/tcz_radius)**3 r = tcz_radius*(ratio + (1 - ratio)*np.random.rand(n_dcs))**(1/3) theta = np.random.rand(n_dcs)*2*np.pi phi = np.arccos(2*np.random.rand(n_dcs) - 1) dcs = pd.DataFrame({ 'X': r*np.sin(theta)*np.sin(phi), 'Y': r*np.cos(theta)*np.sin(phi), 'Z': r*np.cos(phi)}) space_ax.scatter(dcs['X'], dcs['Y'], dcs['Z'], c='y') r = (3*tcz_volume/(4*np.pi))**(1/3) for i in ['x', 'y', 'z']: circle = Circle((0, 0), r, fill=False, linewidth=2) space_ax.add_patch(circle) art3d.pathpatch_2d_to_3d(circle, z=0, zdir=i) time_ax.set_xlabel('Time within Lymph Node [h]') time_ax.set_ylabel('Probab. Density') reach_ax.set_xlabel(r'Maximal Reach [$\mu$m]') reach_ax.set_ylabel('Probab. Density') def residence_time(track): return track['Time'].diff().mean()/60*len( track[np.linalg.norm(track[['X', 'Y', 'Z']], axis=1) < r]) for i, (cond, cond_tracks) in enumerate(moved_tracks.groupby('Condition')): color = sns.color_palette(n_colors=i+1)[-1] residence_times = [residence_time(track) for _, track in cond_tracks.groupby('Track_ID')] if not all(time == residence_times[0] for time in residence_times): sns.distplot(residence_times, kde=False, norm_hist=True, ax=time_ax, label=cond, color=color) max_reaches = [max(np.linalg.norm(track[['X', 'Y', 'Z']], axis=1)) for _, track in cond_tracks.groupby('Track_ID')] sns.distplot(max_reaches, kde=False, norm_hist=True, ax=reach_ax, label=cond, color=color) time_ax.set_yticks([]) time_ax.axvline(np.median(residence_times), c='0', ls=':') sns.despine(ax=time_ax) reach_ax.set_yticks([]) reach_ax.legend() reach_ax.axvline(tcz_radius, c='0', ls=':') sns.despine(ax=reach_ax) equalize_axis3d(space_ax, zoom) plt.tight_layout() if save == True: save = 'situation.png' if save: plt.savefig(save, dpi=300) else: plt.show()
def plot_tracks(raw_tracks, summary=None, draw_turns=True, n_tracks=25, condition='Condition', context='notebook', save=False): """Plot tracks""" tracks = raw_tracks.copy() _uniquize_tracks(tracks) if type(summary) == pd.core.frame.DataFrame: skip_steps = int(next(word for column in summary.columns for word in column.split() if word.isdigit())) if summary is not None and draw_turns: alpha = 0.33 else: alpha = 1 if condition not in tracks.columns: tracks[condition] = 'Default' n_conditions = len(tracks[condition].unique()) sns.set(style='ticks', context=context) fig = plt.figure(figsize=(12,12)) if 'Z' in tracks.columns: ax = fig.add_subplot(111, projection='3d') else: ax = fig.add_subplot(111, aspect='equal') labels = [] for i, (cond, cond_tracks) in enumerate(tracks.groupby(condition)): if summary is not None and draw_turns: cond_summary = summary[summary[condition] == cond] max_turn_column = next(column for column in summary.columns if column.startswith('Max. Turn')) if len(cond_tracks['Track_ID'].unique()) > n_tracks/n_conditions: choice = cond_summary.sort_values(max_turn_column, ascending=False)\ ['Track_ID'][:int(n_tracks/n_conditions)] cond_tracks = cond_tracks[cond_tracks['Track_ID'].isin(choice)] elif len(cond_tracks['Track_ID'].unique()) > n_tracks/n_conditions: choice = np.random.choice(cond_tracks['Track_ID'].unique(), n_tracks/n_conditions, replace=False) cond_tracks = cond_tracks[cond_tracks['Track_ID'].isin(choice)] color = sns.color_palette(n_colors=i+1)[-1] for j, (_, track) in enumerate(cond_tracks.groupby(track_identifiers(cond_tracks))): labels.append(cond) track_id = track['Track_ID'].iloc[0] if 'Z' in tracks.columns: ax.plot(track['X'].values, track['Y'].values, track['Z'].values, color=color, alpha=alpha, label=track_id, picker=5) else: ax.plot(track['X'].values, track['Y'].values, color=color, alpha=alpha, label=track_id, picker=5) if summary is not None and draw_turns: turn_time = cond_summary[cond_summary['Track_ID'] == track_id]['Turn Time'] turn_loc = track.index.get_loc( track[np.isclose(track['Time'], turn_time.values[0])].index.values[0]) turn_times = track['Time'][turn_loc - 1:turn_loc + skip_steps] turn = track[track['Time'].isin(turn_times)] if 'Z' in tracks.columns: ax.plot(turn['X'].values, turn['Y'].values, turn['Z'].values, color=color) else: ax.plot(turn['X'].values, turn['Y'].values, color=color) def on_pick(event): track_id = event.artist.get_label() if summary is not None: print(summary[summary['Track_ID'] == float(track_id)] [['Track_ID', 'Condition', 'Mean Velocity', 'Track Duration']]) else: print('Track_ID: ' + track_id) fig.canvas.mpl_connect('pick_event', on_pick) if 'Z' in tracks.columns: equalize_axis3d(ax) else: sns.despine() handles, _ = ax.get_legend_handles_labels() unique_entries = OrderedDict(zip(labels, handles)) ax.legend(unique_entries.values(), unique_entries.keys()) plt.tight_layout() if save: conditions = [cond.replace('= ', '') for cond in tracks[condition].unique()] plt.savefig('Tracks' + '-'.join(conditions) + '.png', dpi=300) else: plt.show()