Commit 32b1eaee authored by amichaut's avatar amichaut
Browse files

map_config supports missing keys and load default ones

parent e5fa5bfd
%% Cell type:code id: tags:
``` python
import os
import os.path as osp
import pickle
import napari
from skimage import io
from skimage.color import rgb2gray
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
import seaborn as sns
import pandas as pd
import warnings
import ipywidgets as widgets
from ipywidgets import HBox, VBox, interact, interact_manual, TwoByTwoLayout, GridspecLayout, Label, AppLayout
from ipyfilechooser import FileChooser
from IPython.display import HTML, Markdown, display, clear_output
from traitlets import traitlets
from track_analyzer import prepare as tpr
from track_analyzer import plotting as tpl
from track_analyzer import calculate as tca
from track_analyzer.scripts.analyze_tracks import traj_analysis
from track_analyzer.scripts.analyze_maps import map_analysis
warnings.filterwarnings('ignore')
%matplotlib inline
def printmd(string):
display(Markdown(string))
cwd = os.getcwd() # working directory
plot_param = tpl.make_plot_config() # some config parameters
color_list = plot_param['color_list'] # a list of colors often used
# Hide code
HTML('''<script>
code_show=true;
function code_toggle() {
if (code_show){
$('div.input').hide();
} else {
$('div.input').show();
}
code_show = !code_show
}
$( document ).ready(code_toggle);
</script>
<form action="javascript:code_toggle()"><input type="submit" value="Click here to toggle on/off the raw code."></form>''')
```
%% Output
<IPython.core.display.HTML object>
%% Cell type:markdown id: tags:
# Preparation module
## Loading data
%% Cell type:code id: tags:
``` python
#choose positions file
fc_table = FileChooser(cwd)
fc_table.use_dir_icons = True
fc_table.title = '<b>Tracking data file</b>'
sep_wid = widgets.Dropdown(options=[',',';', 'tab', ' '],value=',',description='column separator:',style={'description_width': 'initial'})
header_wid = widgets.Dropdown(options=['yes','no'],value='yes',description='first row = column names?',style={'description_width': 'initial'})
printmd("""**Browse your file system to the table of tracked data (only .txt and .csv are supported)**""")
display(fc_table,sep_wid,header_wid)
```
%% Output
**Browse your file system to the table of tracked data (only .txt and .csv are supported)**
%% Cell type:code id: tags:
``` python
# get position file path
data_dir = fc_table.selected_path
data_file = fc_table.selected
#data_dir = '/Users/amichaut/Desktop/Fluo-N3DH-CE/'
#data_file = "/Users/amichaut/Desktop/Fluo-N3DH-CE/positions.csv"
if data_file is None:
raise Exception("**ERROR: no data table has been selected**")
# choose image file
printmd("""**(Optional) Browse your file system to the image file**
You can plot your data on your image. The image can be a single image or a stack (a 2D time series or a 3D time series).
Only tif images are supported. """)
fc_im = FileChooser(data_dir)
fc_im.use_dir_icons = True
fc_im.title = '<b>Image file</b>'
display(fc_im)
```
%% Output
**(Optional) Browse your file system to the image file**
You can plot your data on your image. The image can be a single image or a stack (a 2D time series or a 3D time series).
Only tif images are supported.
%% Cell type:code id: tags:
``` python
# get image file path
im_file = fc_im.selected
#im_file = "/Users/amichaut/Desktop/Fluo-N3DH-CE/stack.tif"
# analyze image
y_size,x_size = [512,512] #default size of an image to inialize the make info widget
image = tpr.get_image(data_dir,filename=im_file,verbose=True)
if image['image_size'] is not None:
y_size,x_size = image['image_size']
# swap z and t dimensions if needed
check_swap_wid = False # bool to retrieve swap_wid value if necessary
if image['t_dim'] is not None and image['z_dim'] is not None:
check_swap_wid=True
printmd("If there is an error between t and z dimension, you can swap these dimensions")
swap_wid = widgets.ToggleButton(value=False,description='Swap z and t')
display(swap_wid)
# refresh database and info if needed
database_fn=osp.join(data_dir,'data_base.p')
info_fn=osp.join(data_dir,'info.txt')
printmd("---")
if osp.exists(database_fn):
printmd('The database already exists, do you want to refresh it?')
refresh_db_wid=widgets.ToggleButton(value=False,description='Refresh database')
display(refresh_db_wid)
if osp.exists(info_fn):
printmd("The info.txt file already exists, do you want to refresh it?")
refresh_info_wid=widgets.ToggleButton(value=False,description='Refresh info')
display(refresh_info_wid)
```
%% Output
You have loaded a 3D image: (500x500) pixels with 25 time steps
---
The database already exists, do you want to refresh it?
The info.txt file already exists, do you want to refresh it?
%% Cell type:code id: tags:
``` python
printmd("**Don't forget to run this cell!**") # no output cell, make it visible
#swap z and t
if check_swap_wid:
if swap_wid.value:
t_dim = image['t_dim']
z_dim = image['z_dim']
image['t_dim'] = z_dim
image['z_dim'] = t_dim
printmd("**z and t swapped!**")
im = io.imread(image['image_fn'])
printmd("4D image with {} time steps and {} z slices".format(im.shape[image['t_dim']],im.shape[image['z_dim']]))
del im # free memory
# retrieve refresh widgets values
refresh_db=refresh_db_wid.value if osp.exists(database_fn) else True
refresh_info=refresh_info_wid.value if osp.exists(info_fn) else True
# get info
if refresh_info:
length_unit_wid=widgets.Dropdown(options=['um', 'mm', 'au'],value='um',description='Length unit:',style={'description_width': 'initial'})
time_unit_wid=widgets.Dropdown(options=['min', 's', 'hr', 'au'],value='min',description='Time unit:',style={'description_width': 'initial'})
length_sc_wid=widgets.BoundedFloatText(value=1.0,min=0,max=1e4,description='Pixel size:',style={'description_width': 'initial'})
z_sc_wid=widgets.BoundedFloatText(value=0,min=0,max=1e4,description='z step:',style={'description_width': 'initial'})
time_sc_wid=widgets.BoundedFloatText(value=1.0,min=0,max=1e4,description='Frame interval:',style={'description_width': 'initial'})
width_wid=widgets.BoundedIntText(value=x_size,min=0,max=1e4,description='Image width (px):',style={'description_width': 'initial'})
height_wid=widgets.BoundedIntText(value=y_size,min=0,max=1e4,description='Image height (px):',style={'description_width': 'initial'})
left_box = VBox([length_unit_wid, time_unit_wid,width_wid])
right_box = VBox([length_sc_wid, time_sc_wid,height_wid])
box = HBox([left_box, right_box])
printmd("**Information about the data**")
display(box)
printmd("In the data table, are the positions given in pixels or in the length unit (given above)?")
table_unit_wid=widgets.Dropdown(options=['px', 'unit'],value='px',description='Data unit:',style={'description_width': 'initial'})
display(table_unit_wid)
printmd("If the lengthscale in z is different from the xy lengthscale, enter the z step (in length unit). If not, leave it to zero.")
display(z_sc_wid)
wid_list = [length_unit_wid,time_unit_wid,length_sc_wid,time_sc_wid,width_wid,height_wid,table_unit_wid,z_sc_wid]
param_names = ['length_unit','time_unit','lengthscale','timescale','image_width','image_height','table_unit','z_step']
```
%% Output
**Don't forget to run this cell!**
%% Cell type:code id: tags:
``` python
printmd("**Don't forget to run this cell!**") # no output cell, make it visible
# save info as txt file
if refresh_info:
info = {}
with open(info_fn,'w+') as f:
for couple in zip(param_names,wid_list):
info[couple[0]]=couple[1].value
f.write('{}:{}\n'.format(couple[0],couple[1].value))
else:
info=tpr.get_info(data_dir)
```
%% Output
**Don't forget to run this cell!**
%% Cell type:code id: tags:
``` python
printmd("**Don't forget to run this cell!**") # no output cell, make it visible
# Set columns identity
if refresh_db:
sep = sep_wid.value if sep_wid.value !='tab' else '\t'
header = None if header_wid.value=='no' else 0
df = pd.read_csv(data_file,sep=sep,header=header)
printmd("**Here are the first rows of the input data table**")
display(df.head(10))
```
%% Output
**Don't forget to run this cell!**
%% Cell type:code id: tags:
``` python
printmd("**Don't forget to run this cell!**") # no output cell, make it visible
if refresh_db:
wid_list = []
left_list=[]
right_list=[]
param_list = ['x','y','z','frame','track','none']
# display the df columns as two columns of widgets
for i,col in enumerate(df.columns):
wid=widgets.Dropdown(options=param_list,value='none',description='column {}:'.format(col),style={'description_width': 'initial'})
wid_list.append(wid)
if i<len(df.columns)/2:
left_list.append(wid)
else:
right_list.append(wid)
printmd("**Select the columns to be used in the analysis: track,frame,x,y,(z). Leave to 'none' the other ones.**")
left_box = VBox(left_list)
right_box = VBox(right_list)
display(HBox([left_box, right_box]))
# deal with gaps in trajectories
printmd("""**Some tracking softwares support to miss objects at some frames. This results in tracks with gaps.
However, this analysis pipeline requires to have continuous tracks. How do you want to handle tracks with gaps:
fill the gaps by linear interpolation or split the track in different tracks?**""")
split_wid=widgets.Dropdown(options=['interpolate','split'],value='interpolate',description='gap resolution:'.format(col),style={'description_width': 'initial'})
display(split_wid)
```
%% Output
**Don't forget to run this cell!**
%% Cell type:code id: tags:
``` python
printmd("**Don't forget to run this cell!**") # no output cell, make it visible
if refresh_db:
col_values = [wid.value for wid in wid_list]
for param_ in ['x','y','frame','track']: # mandatory columns
if param_ not in col_values:
print("Warning: you MUST select a column for "+param_)
df.columns=col_values # rename columns
# ditch none columns
col_values=np.array(col_values)
new_cols=col_values[col_values!='none']
df=df[new_cols]
# retrieve split traj widget value
split_traj=True if split_wid.value=='split' else False
#get dimension
dim_list = ['x','y','z'] if 'z' in df.columns else ['x','y']
# coordinates origin
printmd("""**Do you want to set a custom origin to the coordinates?**""")
printmd("""Select a new origin by drawing on the image (you can choose which dimension to reset)""")
ori_onimage_wid=widgets.ToggleButton(value=False,description='Select on image')
reset_dim_wid=widgets.SelectMultiple(options=dim_list,value=['x','y'],description='Dimensions to reset',style={'description_width': 'initial'})
display(HBox([ori_onimage_wid,reset_dim_wid]))
printmd("""Or directly type in the new origin (in px)""")
origin_coord_wid_list=[]
for dim in dim_list:
origin_coord_wid_list.append(widgets.FloatSlider(value=0,min=0,max=df[dim].max(),step=0.1,description=dim,style={'description_width': 'initial'}))
display(HBox(origin_coord_wid_list))
# axes signs
printmd("""**Do you want to invert the axes?**
Default orientation: x: left->right, y: top->bottom, z: slice number""")
invert_axes_wid=widgets.SelectMultiple(options=dim_list,value=[],description='Axes to invert',style={'description_width': 'initial'})
display(invert_axes_wid)
```
%% Output
**Don't forget to run this cell!**
%% Cell type:code id: tags:
``` python
printmd("**Don't forget to run this cell!**") # no output cell, make it visible
if refresh_db:
if not ori_onimage_wid.value:
origin_coord={}
all_zeros=True
for d,wid in enumerate(origin_coord_wid_list):
origin_coord[dim_list[d]]=wid.value
if wid.value>0:
all_zeros=False
if all_zeros: # if no change of origin
origin_coord = False
set_origin_ = origin_coord
else:
set_origin_ = True
#remove None tracks
df = df[df['track']!='None'] # remove
data = tpr.get_data(data_dir,df=df,refresh=refresh_db,split_traj=split_traj,
set_origin_=set_origin_,image=image,reset_dim=reset_dim_wid.value,invert_axes=invert_axes_wid.value)
else:
# reload from database
data = tpr.get_data(data_dir,df=None,refresh=refresh_db)
# useful variables
df = data['df']
lengthscale = data['lengthscale']
timescale = data['timescale']
dim = data['dim']
dimensions = data['dimensions']
```
%% Output
**Don't forget to run this cell!**
%% Cell type:code id: tags:
``` python
# general plotting configuration
printmd("## General plotting configuration")
fig_w_wid = widgets.BoundedIntText(value=plot_param['figsize'][0],min=0,max=20,
description='Figure width (inches):',style={'description_width': 'initial'})
fig_h_wid = widgets.BoundedIntText(value=plot_param['figsize'][1],min=0,max=20,
description='Figure height (inches):',style={'description_width': 'initial'})
fig_dpi_wid = widgets.BoundedIntText(value=plot_param['dpi'],min=50,max=1e4,
description='Figure resolution (dpi):',style={'description_width': 'initial'})
fig_format_wid = widgets.Dropdown(options=['.png','.svg'],value='.png',
description='Figure format',style={'description_width': 'initial'})
despine_wid = widgets.ToggleButton(value=plot_param['despine'],
description='despine figure')
replace_color_wid = widgets.BoundedIntText(value=0,min=0,max=20,
description='Number of colors:',style={'description_width': 'initial'})
add_replace_wid = widgets.Dropdown(options=['add','replace'],value='add',
description='add or replace?',style={'description_width': 'initial'})
invert_yaxis_wid = widgets.ToggleButton(value=True,description='y axis origin: top')
export_data_pts_wid = widgets.ToggleButton(value=True,description='export data points')
display(HBox([fig_w_wid,fig_h_wid]),fig_dpi_wid,fig_format_wid,despine_wid)
printmd('Do you want to add/replace the first default colors used for plotting? Give the number of colors you want to select:')
display(HBox([replace_color_wid,add_replace_wid]))
printmd('How do you want to display the y-axis (standard orientation: origin at top)')
display(invert_yaxis_wid)
printmd('Do you want to export the data points of your plots as .csv files?')
display(export_data_pts_wid)
```
%% Output
## General plotting configuration
Do you want to add/replace the first default colors used for plotting? Give the number of colors you want to select:
How do you want to display the y-axis (standard orientation: origin at top)
Do you want to export the data points of your plots as .csv files?
%% Cell type:code id: tags:
``` python
printmd("**Don't forget to run this cell!**") # no output cell, make it visible
# replace colors
color_wid_list=[]
for i in range(replace_color_wid.value):
color_wid=widgets.ColorPicker(description='Pick color #{}'.format(i),value=color_list[i])
color_wid_list.append(color_wid)
display(*color_wid_list)
```
%% Output
**Don't forget to run this cell!**
%% Cell type:code id: tags:
``` python
printmd("**Don't forget to run this cell!**") # no output cell, make it visible
# retreive plotting configuration
color_list_=list(color_list)
new_color_list = [color_wid_list[i].value for i in range(replace_color_wid.value)]
if add_replace_wid.value=='replace':
color_list_[:replace_color_wid.value]=new_color_list
else:
color_list_=new_color_list+color_list_
plot_param={'figsize':(fig_w_wid.value,fig_h_wid.value),
'dpi':fig_dpi_wid.value,
'color_list':color_list_,
'format':fig_format_wid.value,
'despine':despine_wid.value,
'invert_yaxis':invert_yaxis_wid.value,
'export_data_pts':export_data_pts_wid.value
}
```
%% Output
**Don't forget to run this cell!**
%% Cell type:markdown id: tags:
# Filter data
%% Cell type:code id: tags:
``` python
z_step = info['z_step']
if z_step == 0:
z_step = lengthscale # if z_step not given, same as lengthscale
printmd('**View trajectories on a Napari viewer before plotting**')
printmd('If not working, please check Napari installation: https://napari.org/')
viewer_wid = widgets.Button(value=True, description='Show viewer!')
viewer_wid.on_click(lambda obj: tpl.view_traj(df, image=image, z_step=info['z_step']))
display(viewer_wid)
```
%% Output
**View trajectories on a Napari viewer before plotting**
If not working, please check Napari installation: https://napari.org/
%% Cell type:code id: tags:
``` python
printmd("Your data can be filtered into subsets. How many subsets do you want to analyze?")
subset_num_wid = widgets.BoundedIntText(value=1,min=1,max=10,description='Number of subsets:',style={'description_width': 'initial'})
display(subset_num_wid)
printmd("If you define several subsets, do you want to analyze them separately or together?")
printmd("If analyzed together, subsets will be plotted together. If analyzed separately, each subset will be plotted on individual plots.")
separate_widget = widgets.ToggleButtons(options=['separately', 'together'], description='Analysis',style={'description_width': 'initial'})
display(separate_widget)
```
%% Output
Your data can be filtered into subsets. How many subsets do you want to analyze?
If you define several subsets, do you want to analyze them separately or together?
If analyzed together, subsets will be plotted together. If analyzed separately, each subset will be plotted on individual plots.
%% Cell type:code id: tags:
``` python
# prepare default values for initializing widgets
xlim = [df['x'].min(), df['x'].max()] # maybe use image dimensions instead
ylim = [df['y'].min(), df['y'].max()]
zlim = [df['z'].min(), df['z'].max()] if 'z' in df.columns else []
frame_list = df['frame'].unique()
frame_min = df['frame'].min()
frame_max = df['frame'].max()
# cropping widget lists
xlim_wid_list = []
ylim_wid_list = []
zlim_wid_list = []
drawer_wid_list = []
frame_subset_wid_list = []
min_length_wid_list = []
max_length_wid_list = []
name_wid_list = []
# retrieve drawer coordinates
class LoadedButton(widgets.Button):
"""A button that can holds a value as a attribute."""
def __init__(self, value=None, *args, **kwargs):
super(LoadedButton, self).__init__(*args, **kwargs)
# Create the value attribute.
self.add_traits(value=traitlets.Any(value))
def get_image_coord(ex):
"""Call get_coordinates, display instruction and store coordinates in widget value """
ex.value = tpr.get_coordinates(image,verbose=False,interactive=False)
# create a set of filtering widget for each subset
for i in range(subset_num_wid.value):
printmd("""### Subset #{}""".format(i + 1))
# subset name
printmd("""You can give it a custom name that will be used for saving data""")
name_wid = widgets.Text(value='', placeholder='optional', description='Subset name:',
style={'description_width': 'initial'})
name_wid_list.append(name_wid)
display(name_wid)
# spatial filtering
xlim_wid = widgets.FloatRangeSlider(value=xlim, min=xlim[0], max=xlim[1], step=1,
description='x range (px):', style={'description_width': 'initial'})
ylim_wid = widgets.FloatRangeSlider(value=ylim, min=ylim[0], max=ylim[1], step=1,
description='y range (px):', style={'description_width': 'initial'})
if len(zlim) > 0:
zlim_wid = widgets.FloatRangeSlider(value=zlim, min=zlim[0], max=zlim[1], step=1,
description='z range (px):', style={'description_width': 'initial'})
drawer_wid = LoadedButton(description="Draw ROI", value={})
drawer_wid.on_click(get_image_coord)
# store widgets
xlim_wid_list.append(xlim_wid)
ylim_wid_list.append(ylim_wid)
drawer_wid_list.append(drawer_wid)
if len(zlim) > 0:
zlim_wid_list.append(zlim_wid)
else:
zlim_wid_list.append(None)
#display
printmd("**Crop a region**")
printmd("You can draw it on the image or select it with the slider (values in pixels)."
"If you do both, only the drawn region will be kept. If you select several regions on the image"
", they will be divided into several subsets")
printmd("Draw using the rectangle shape, hit ENTER while you're done. Then close the image viewer. "
"If you want more details about the email viewer please visit https://napari.org/")
if len(zlim) > 0:
display(VBox([drawer_wid, HBox([xlim_wid, ylim_wid, zlim_wid])]))
else:
display(VBox([drawer_wid, HBox([xlim_wid, ylim_wid])]))
# time filtering
frame_subset_wid = widgets.IntRangeSlider(value=[frame_min, frame_max], min=frame_min, max=frame_max, step=1,
description='Frame subset:', style={'description_width': 'initial'})
min_length_wid = widgets.IntSlider(value=frame_min, min=frame_min, max=frame_max + 1, step=1,
description='Minimum traj length:', style={'description_width': 'initial'})
max_length_wid = widgets.IntSlider(value=frame_max + 1, min=frame_min, max=frame_max + 1, step=1,
description='Maximum traj length:', style={'description_width': 'initial'})
# store widgets
frame_subset_wid_list.append(frame_subset_wid)
min_length_wid_list.append(min_length_wid)
max_length_wid_list.append(max_length_wid)
# display
printmd("**Select data based on trajectories duration or frame subset**")
display(HBox([frame_subset_wid, min_length_wid, max_length_wid]))
```
%% Output
### Subset #1
You can give it a custom name that will be used for saving data
**Crop a region**
You can draw it on the image or select it with the slider (values in pixels).If you do both, only the drawn region will be kept. If you select several regions on the image, they will be divided into several subsets
Draw using the rectangle shape, hit ENTER while you're done. Then close the image viewer. If you want more details about the email viewer please visit https://napari.org/
**Select data based on trajectories duration or frame subset**
%% Cell type:code id: tags:
``` python
# retrieve filters values
def retrieve_region_wid_values(drawer_wid,xlim_wid,ylim_wid,zlim_wid):
"""
Get values of region selection giving priority to drawer widgets over sliders
"""
# xylim
use_sliders = False
drawer_value = drawer_wid.value
if drawer_value: #if not empty
if len(drawer_value['rectangle']) > 0:
#get list of xlim, ylim in case of several ROIs selected
xlim_list = [r['xlim'] for r in drawer_value['rectangle']]
ylim_list = [r['ylim'] for r in drawer_value['rectangle']]
else:
use_sliders = True
else:
use_sliders = True
if use_sliders:
xlim_list = [xlim_wid.value]
ylim_list = [ylim_wid.value]
# zlim
if zlim_wid is None:
zlim = None
else:
zlim = zlim_wid.value
return xlim_list, ylim_list, zlim
filters=[]
for i in range(subset_num_wid.value):
xlim_list, ylim_list, zlim_ = retrieve_region_wid_values(drawer_wid_list[i],
xlim_wid_list[i],
ylim_wid_list[i],
zlim_wid_list[i])
# if several subsets get values of xlim, ylim, while keeping other filters constant
for j in range(len(xlim_list)):
#name
if len(xlim_list) > 1: # if several subsets, modify name: name_number if name is empty: number
name = name_wid_list[i].value + '_{}'.format(j) if name_wid_list[i].value != '' else '{}'.format(j)
else:
name = name_wid_list[i].value
# initialize filter dict
default_filter = tpr.init_filters(data_dir=None, export_to_config=False)
filt_ = default_filter['filters_list'][0]
# fill info
filt_['xlim'] = xlim_list[j]
filt_['ylim'] = ylim_list[j]
filt_['zlim'] = zlim_
filt_['frame_subset'] = frame_subset_wid_list[i].value
filt_['min_traj_len'] = min_length_wid_list[i].value
filt_['max_traj_len'] = max_length_wid_list[i].value
filt_['name'] = name
# add to filter list
filters.append(filt_)
printmd("**Select specific trajectories**")
printmd("You can select specific sets of trajectories. "
"This tool can be useful to perform fate mapping or retrospective mapping. "
"If you selected several subsets before, this specific set will be applied to all of the subsets."
)
printmd("How many sets of trajectories do you want to select?")
set_num_wid = widgets.BoundedIntText(value=0,min=0,max=10,description='Number of sets:',style={'description_width': 'initial'})
display(set_num_wid)
#or by selecting trajectories in a specific region at a specific frame. "
#just by giving a list of ids,
```
%% Output
**Select specific trajectories**
You can select specific sets of trajectories. This tool can be useful to perform fate mapping or retrospective mapping. If you selected several subsets before, this specific set will be applied to all of the subsets.
How many sets of trajectories do you want to select?
%% Cell type:code id: tags:
``` python
printmd("**Don't forget to run this cell!**") # no output cell, make it visible
# select specific trajectories
# track selection widget lists
track_name_wid_list = []
track_xlim_wid_list = []
track_ylim_wid_list = []
track_zlim_wid_list = []
track_drawer_wid_list = []
track_frame_subset_wid_list = []
track_list_wid_list = []
for i in range(set_num_wid.value):
printmd("""### Set #{}""".format(i + 1))
# subset name
printmd("""You can give it a custom name that will be used for saving data""")
track_name_wid = widgets.Text(value='', placeholder='optional', description='Set name:',
style={'description_width': 'initial'})
track_name_wid_list.append(track_name_wid)
display(track_name_wid)
track_list_wid = widgets.Text(value='', placeholder='comma separated ids', description='Id list:')
track_xlim_wid = widgets.FloatRangeSlider(value=xlim, min=xlim[0], max=xlim[1], step=1,
description='x range (px):', style={'description_width': 'initial'})
track_ylim_wid = widgets.FloatRangeSlider(value=ylim, min=ylim[0], max=ylim[1], step=1,
description='y range (px):', style={'description_width': 'initial'})
if len(zlim) > 0:
track_zlim_wid = widgets.FloatRangeSlider(value=zlim, min=zlim[0], max=zlim[1], step=1,
description='z range (px):', style={'description_width': 'initial'})
track_frame_subset_wid = widgets.IntRangeSlider(value=[frame_min, frame_max], min=frame_min, max=frame_max, step=1,
description='Frame intervalle:', style={'description_width': 'initial'})
track_drawer_wid = LoadedButton(description="Draw ROI", value={})
track_drawer_wid.on_click(get_image_coord)
# store widgets
track_list_wid_list.append(track_list_wid)
track_xlim_wid_list.append(track_xlim_wid)
track_ylim_wid_list.append(track_ylim_wid)
track_drawer_wid_list.append(track_drawer_wid)
track_frame_subset_wid_list.append(track_frame_subset_wid)
if len(zlim) > 0:
track_zlim_wid_list.append(track_zlim_wid)
else:
track_zlim_wid_list.append(None)
#display
printmd("Give a list of ids or select trajectories in a specific region during a specific frame intervalle using the viewer.")
printmd("Use the ids given by the track analyzer, you need to generate the database once to access them, "
"(visualizing the trajectories with the printed labels can be helpful)")
if len(zlim) > 0:
display(VBox([track_list_wid,track_drawer_wid, HBox([track_xlim_wid, track_ylim_wid, track_zlim_wid]),track_frame_subset_wid]))
else:
display(VBox([track_list_wid,track_drawer_wid, HBox([track_xlim_wid, track_ylim_wid]),track_frame_subset_wid]))
```
%% Output
**Don't forget to run this cell!**
%% Cell type:code id: tags:
``` python
printmd("**Don't forget to run this cell!**") # no output cell, make it visible
if set_num_wid.value == 0:
new_filters = list(filters)
else:
new_filters = []
# for each set of filters, copy them to new sets of filters modified by the trajectory filters
for filt in filters:
for i in range(set_num_wid.value):
# trajectory list selection
track_list_val = track_list_wid_list[i].value
if track_list_val == '':
track_list_val = None
else:
try:
track_list_val = [int(e) for e in track_list_val.split(',')]
except:
print("ERROR: a value in the list is not a number")
track_list_val = None
# ROI selection
track_xlim_list, track_ylim_list, track_zlim_ = retrieve_region_wid_values(track_drawer_wid_list[i],
track_xlim_wid_list[i],
track_ylim_wid_list[i],
track_zlim_wid_list[i])
# if several sets, get values of xlim, ylim, while keeping other filters constant
for j in range(len(track_xlim_list)):
ROI = {'xlim': track_xlim_list[j],
'ylim': track_ylim_list[j],
'zlim': track_zlim_,
'frame_lim': track_frame_subset_wid_list[i].value}
#name
if len(track_xlim_list) > 1: # if several subsets, modify name
name = track_name_wid_list[i].value + '_{}'.format(j)
else:
name = track_name_wid_list[i].value
# add new filters to existing filters
new_filt = dict(filt) # make copy of old filters
new_filt['track_list'] = track_list_val
new_filt['track_ROI'] = ROI
if new_filt['name'] == '':
new_filt['name'] = name # name = setname
else:
if name != '':
new_filt['name'] += '_' + name # name = subsetname_setname
# store in a new list of filters
new_filters.append(new_filt)
printmd('You set {} subsets. Edit their names and order to be plotted if needed.'.format(len(new_filters)))
filt_names_wid_list = []
order_wid_list = []
for i,filt in enumerate(new_filters):
print(filt)
name_wid = widgets.Text(value=filt['name'], placeholder='optional', description='Subset name:',
style={'description_width': 'initial'})
filt_names_wid_list.append(name_wid)
# using numbering starting at 1 for users
order_wid = widgets.BoundedIntText(value=i+1,min=1,max=len(new_filters)+1,description='order',style={'description_width': 'initial'})
order_wid_list.append(order_wid)
display(HBox([name_wid,order_wid]))
```
%% Output
**Don't forget to run this cell!**
You set 1 subsets. Edit their names and order to be plotted if needed.
{'xlim': (23.649625039146787, 473.9442918374955), 'ylim': (46.07000789821272, 503.5204302803229), 'zlim': (26.33786765959565, 473.508789049432), 'min_traj_len': 0, 'max_traj_len': 25, 'frame_subset': (0, 24), 'track_list': None, 'track_ROI': None, 'name': ''}
%% Cell type:code id: tags:
``` python
printmd("**Don't forget to run this cell!**") # no output cell, make it visible
order_list = [] # list for subsets indices
for i in range(len(new_filters)):
new_filters[i]['name'] = filt_names_wid_list[i].value
order_list.append(order_wid_list[i].value - 1) # using numbering starting at 1 for users
if any(x not in order_list for x in range(len(new_filters))): # check if all indices have been set
print("Warning: the ordering is wrong. Reverting to default order.")
order_list = [x for x in range(len(new_filters))]
order_list_ = [new_filters[i]['name'] for i in order_list] # order_list of names
filters_dict = {'subset': separate_widget.value,
'filters_list': new_filters,
'subset_order': order_list_,}
```
%% Output
**Don't forget to run this cell!**
%% Cell type:markdown id: tags:
# Trajectory analysis module
%% Cell type:code id: tags:
``` python
# prepare default values for widgets
if data['dim'] == 2:
color_code_list = ['t', 'group', 'random', 'none']
# if several subset plotted together, color code default: ROI
if len(filters_dict['filters_list']) and filters_dict['subset'] == 'together':
color_code_default = 'group'
else:
color_code_default = 'random'
elif data['dim'] == 3:
color_code_list = ['z', 't', 'group', 'random', 'none']
# if several subset plotted together, color code default: ROI
if len(filters_dict['filters_list']) and filters_dict['subset'] == 'together':
color_code_default = 'group'
else:
color_code_default = 'z'
### Section 1
printmd('### Plotting options')
printmd("**1. Trajectory plotting**")
## TAB 1
# widgets
traj_module_wid = widgets.ToggleButton(value=True, description='Run module')
show_axis_wid = widgets.Checkbox(value=False, description='show axes')
bkg_wid = widgets.Checkbox(value=False, description='hide background image')
show_tail_wid = widgets.Checkbox(value=True, description='show trajectory tail')
marker_size_wid = widgets.FloatSlider(value=1., min=0, max=20, steps=0.1,
description='Relative size of dots and lines:',
style={'description_width': 'initial'})
hide_lab_wid = widgets.Checkbox(value=True, description='hide track label')
lab_size_wid = widgets.IntSlider(value=6, min=0, max=100, description='Track label size (pt):',
style={'description_width': 'initial'})
color_code_wid = widgets.Dropdown(options=color_code_list, value=color_code_default, description='color code',
style={'description_width': 'initial'})
colormap_wid = widgets.Dropdown(options=['plasma', 'viridis', 'cividis', 'jet'], value='plasma', description='colormap',
style={'description_width': 'initial'})
lab_1 = Label('Plot trajectories frame by frame')
# layout
left_box_1 = VBox([show_axis_wid,bkg_wid, show_tail_wid, hide_lab_wid])
right_box_1 = VBox([lab_size_wid, marker_size_wid, color_code_wid, colormap_wid])
tab_1_ = HBox([left_box_1, right_box_1])
tab_1 = VBox([lab_1, traj_module_wid, tab_1_])
## TAB 2
# widgets
xrange = np.abs(df['x_scaled'].max() - df['x_scaled'].min())
yrange = np.abs(df['y_scaled'].max() - df['y_scaled'].min())
xlim = [df['x_scaled'].min() - xrange, df['x_scaled'].max() + xrange] # define custom xlim with wider boundaries
ylim = [df['y_scaled'].min() - yrange, df['y_scaled'].max() + yrange] # define custom ylim with wider boundaries
all_traj_module_wid = widgets.ToggleButton(value=True, description='Run module')
hide_lab_wid_2 = widgets.Checkbox(value=True, description='hide track label')
center_wid = widgets.Checkbox(value=True, description='center origin')
setlim_wid = widgets.Checkbox(value=False, description='set custom axis limits')
lab_size_wid_2 = widgets.IntSlider(value=6, min=0, max=100, description='Track label size (pt):',
style={'description_width': 'initial'})
color_code_wid_2 = widgets.Dropdown(options=color_code_list, value=color_code_default, description='color code',
style={'description_width': 'initial'})
colormap_wid2 = widgets.Dropdown(options=['plasma', 'viridis', 'cividis', 'jet'], value='plasma',
description='colormap',
style={'description_width': 'initial'})
xlim_wid = widgets.FloatRangeSlider(value=xlim, min=xlim[0], max=xlim[1], step=1,
description='x range ({}):'.format(info['length_unit']),
style={'description_width': 'initial'})
ylim_wid = widgets.FloatRangeSlider(value=ylim, min=ylim[0], max=ylim[1], step=1,
description='y range ({}):'.format(info['length_unit']),
style={'description_width': 'initial'})
lab_2 = Label('Plot total trajectories')
# layout
left_box_2 = VBox([hide_lab_wid_2, center_wid, setlim_wid])
right_box_2 = VBox([lab_size_wid_2, color_code_wid_2, colormap_wid2, xlim_wid, ylim_wid])
tab_2_ = HBox([left_box_2, right_box_2])
tab_2 = VBox([lab_2, all_traj_module_wid, tab_2_])
# display Section 1
tab_titles = ['Plot frame by frame', 'Plot total trajectories']
tab = widgets.Tab()
tab.children = [tab_1, tab_2]
for i in range(len(tab_titles)):
tab.set_title(i, tab_titles[i])
display(tab)
### Section 2
printmd("**2. Parameter plotting**")
param_module_wid = widgets.ToggleButton(value=True, description='Run module')
display(param_module_wid)
printmd("*Two kinds of parameters can be plotted: instantaneous parameters (measured at each time point), and parameters calculated over a whole track.*")
printmd("*You can plot histograms of single parameters or scatter plots of a couple of parameters (e.g. v vs y)*")
printmd(
"How many instantaneous parameters (histogram or couples) do you want to plot? (enter 0 if you don't want to plot parameters)")
param_hist_num_wid = widgets.BoundedIntText(value=1, min=0, max=20, description='Number of histograms:',
style={'description_width': 'initial'})
param_couple_num_wid = widgets.BoundedIntText(value=3, min=0, max=20, description='Number of couples:',
style={'description_width': 'initial'})
display(HBox([param_hist_num_wid, param_couple_num_wid]))
printmd(
"How many whole-trajectory parameters (histogram or couples) do you want to plot? (enter 0 if you don't want to plot parameters)")
tparam_hist_num_wid = widgets.BoundedIntText(value=1, min=0, max=20, description='Number of histograms:',
style={'description_width': 'initial'})
tparam_couple_num_wid = widgets.BoundedIntText(value=3, min=0, max=20, description='Number of couples:',
style={'description_width': 'initial'})
display(HBox([tparam_hist_num_wid, tparam_couple_num_wid]))
### Section 3
printmd("**3. Mean Squared Displacement (MSD) analysis**")
MSD_module_wid = widgets.ToggleButton(value=True, description='Run module')
display(MSD_module_wid)
printmd("You can either plot the MSD, or/and fit it with a random walk model")
MSD_mode_wid = widgets.Dropdown(options=['only plot MSD', 'plot MSD and fit'], value='plot MSD and fit',
description='Choose analysis: ',
style={'description_width': 'initial'})
display(MSD_mode_wid)
printmd("***")
printmd("*Plotting section*")
printmd(
"Plot MSD altogether or as single plots. For a large number of tracks, plotting single MSDs can be long... Consider not plotting them.")
all_MSD_plot_wid = widgets.ToggleButton(value=True, description='plot MSD altogether')
single_MSD_plot_wid = widgets.ToggleButton(value=False, description='single MSD plots')
logplot_wid_x = widgets.Checkbox(value=True, description='x axis')
logplot_wid_y = widgets.Checkbox(value=True, description='y axis')
alpha_lab = Label('For all MSD plots, set the transparency (0=transparent, 1=opaque)')
alpha_wid = widgets.FloatSlider(value=0.2, min=0, max=1, steps=0.01, description='transparency',
style={'description_width': 'initial'})
display(HBox([all_MSD_plot_wid, single_MSD_plot_wid]))
display(HBox([Label('log plot: '), logplot_wid_x, logplot_wid_y]))
display(HBox([alpha_lab, alpha_wid]))
printmd("***")
printmd("*Fitting section*")
printmd("The MSD can be fitted with three different random walk models")
MSD_wid = widgets.Dropdown(options=['random walk', 'biased random walk', 'persistent random walk'], value='random walk',
description='Choose model: ',
style={'description_width': 'initial'})
display(MSD_wid)
dim_wid = widgets.Dropdown(options=['2D', '3D'], value='2D', description='dimension: ',
style={'description_width': 'initial'})
fitrange_wid = widgets.IntSlider(value=5 * timescale, min=0, max=df['t'].max(), step=1,
description='Maximum lag time ({})'.format(info['time_unit']),
style={'description_width': 'initial'})
printmd("Perform MSD analysis in 2D (along the xy dimensions) or 3D")
display(dim_wid)
printmd(
"Fitting MSDs can be difficult (at long lag times the calculation is very noisy because of the poor statistics). It is often necessary to restrict the fit to short lag times. ")
display(fitrange_wid)
### Section 4
printmd("**4. Voronoi analysis**")
vor_module_wid = widgets.ToggleButton(value=True, description='Run module')
display(vor_module_wid)
# plotting parameters
vor_show_axis_wid = widgets.Checkbox(value=False, description='show axes')
vor_bkg_wid = widgets.Checkbox(value=False, description='hide background image')
vor_plot_wid = widgets.Checkbox(value=True, description='plot diagram')
vor_area_wid = widgets.Checkbox(value=True, description='show cell area')
vor_area_thr_wid = widgets.BoundedFloatText(value=3, min=0, max=100, step=0.1,
description='Max area threshold:',
style={'description_width': 'initial'})
vor_cmap_wid = widgets.Dropdown(options=['plasma', 'viridis', 'cividis', 'jet'], value='plasma', description='colormap',
style={'description_width': 'initial'})
display(HBox([VBox([vor_show_axis_wid, vor_bkg_wid, vor_plot_wid]),VBox([vor_area_wid, vor_area_thr_wid, vor_cmap_wid])]))
```
%% Output
### Plotting options
**1. Trajectory plotting**
**2. Parameter plotting**
*Two kinds of parameters can be plotted: instantaneous parameters (measured at each time point), and parameters calculated over a whole track.*
*You can plot histograms of single parameters or scatter plots of a couple of parameters (e.g. v vs y)*
How many instantaneous parameters (histogram or couples) do you want to plot? (enter 0 if you don't want to plot parameters)
How many whole-trajectory parameters (histogram or couples) do you want to plot? (enter 0 if you don't want to plot parameters)
**3. Mean Squared Displacement (MSD) analysis**
You can either plot the MSD, or/and fit it with a random walk model
***
*Plotting section*
Plot MSD altogether or as single plots. For a large number of tracks, plotting single MSDs can be long... Consider not plotting them.
***
*Fitting section*
The MSD can be fitted with three different random walk models
Perform MSD analysis in 2D (along the xy dimensions) or 3D
Fitting MSDs can be difficult (at long lag times the calculation is very noisy because of the poor statistics). It is often necessary to restrict the fit to short lag times.
**4. Voronoi analysis**
%% Cell type:code id: tags:
``` python
printmd("**Don't forget to run this cell!**") # no output cell, make it visible
## Get additional information about parameters plotting
# get MSD parameters
if not MSD_module_wid.value:
MSD_fit = False
else:
if MSD_mode_wid.value == 'only plot MSD':
MSD_fit = None
else:
MSD_model_dict = {'random walk': 'pure_diff', 'biased random walk': 'biased_diff',
'persistent random walk': 'PRW'}
MSD_fit = MSD_model_dict[MSD_wid.value]
# prepare parameters lists
if param_module_wid.value:
dimensions = ['x', 'y'] if data['dim'] == 2 else ['x', 'y', 'z']
scaled_dimensions = [dim + '_scaled' for dim in dimensions]
vel = ['v' + dim for dim in dimensions]
acc = ['a' + dim for dim in dimensions]
params = ['track', 't'] + dimensions + scaled_dimensions + vel + acc + ['v', 'a']
params_track = ['track', 'track_length', 't'] + dimensions + scaled_dimensions + vel + acc + ['v', 'a']
# add MSD output to track parameters
if MSD_fit is not None and MSD_fit is not False:
MSD_param = 'P' if MSD_fit == 'PRW' else 'D'
params_track += [MSD_param]
# add voronoi output to instantaneous parameters
if vor_module_wid.value:
params += ['area']
params_track += ['area']
# default
default_param = 'v'
default_xparam = ['x', 'y', 't']
# histogram widgets
param_hist_wid_list = []
tparam_hist_wid_list = []
for i in range(param_hist_num_wid.value):
w = widgets.Dropdown(options=params, value=default_param, description='parameter',
style={'description_width': 'initial'})
param_hist_wid_list.append(w)
box_1 = VBox(param_hist_wid_list)
for i in range(tparam_hist_num_wid.value):
w = widgets.Dropdown(options=params_track, value=default_param, description='parameter',
style={'description_width': 'initial'})
tparam_hist_wid_list.append(w)
box_2 = VBox(tparam_hist_wid_list)
# couples widgets
xparam_wid_list = []
yparam_wid_list = []
for i in range(param_couple_num_wid.value):
x = widgets.Dropdown(options=params, value=default_xparam[i % len(default_xparam)], description='x parameter',
style={'description_width': 'initial'})
y = widgets.Dropdown(options=params, value=default_param, description='y parameter',
style={'description_width': 'initial'})
xparam_wid_list.append(x)
yparam_wid_list.append(y)
left3 = VBox(xparam_wid_list)
right3 = VBox(yparam_wid_list)
box_3 = HBox([left3, right3])
t_xparam_wid_list = []
t_yparam_wid_list = []
for i in range(tparam_couple_num_wid.value):
x = widgets.Dropdown(options=params_track, value=default_xparam[i % len(default_xparam)],
description='x parameter',
style={'description_width': 'initial'})
y = widgets.Dropdown(options=params_track, value=default_param, description='y parameter',
style={'description_width': 'initial'})
t_xparam_wid_list.append(x)
t_yparam_wid_list.append(y)
left4 = VBox(t_xparam_wid_list)
right4 = VBox(t_yparam_wid_list)
box_4 = HBox([left4, right4])
acc1 = widgets.Accordion(children=[box_1, box_2])
acc2 = widgets.Accordion(children=[box_3, box_4])
acc_titles = ['Instantaneous parameters', 'Whole_trajectory parameters']
for i in range(len(acc_titles)):
acc1.set_title(i, acc_titles[i])
acc2.set_title(i, acc_titles[i])
# layout
tab_titles = ['Parameter histograms', 'Parameter couples']
tab = widgets.Tab()
tab.children = [acc1, acc2]
for i in range(len(tab_titles)):
tab.set_title(i, tab_titles[i])
display(tab)
```
%% Output
**Don't forget to run this cell!**
%% Cell type:code id: tags:
``` python
printmd("**Don't forget to run this cell!**") # no output cell, make it visible
# Prepare config
traj_config = tpr.make_traj_config(export_config=False)
#traj_config_
traj_config["traj_config_"]["run"] = traj_module_wid.value
traj_config["traj_config_"]["color_code"] = color_code_wid.value
traj_config["traj_config_"]["cmap"] = colormap_wid.value
traj_config["traj_config_"]["lab_size"] = lab_size_wid.value
traj_config["traj_config_"]["size_factor"] = marker_size_wid.value
traj_config["traj_config_"]["show_tail"] = show_tail_wid.value
traj_config["traj_config_"]["hide_labels"] = hide_lab_wid.value
traj_config["traj_config_"]["no_bkg"] = bkg_wid.value
traj_config["traj_config_"]["show_axis"] = show_axis_wid.value
#total_traj_config
traj_config["total_traj_config"]["run"] = all_traj_module_wid.value
traj_config["total_traj_config"]["color_code"] = 'none' if color_code_wid_2.value=='unique' else color_code_wid_2.value
traj_config["total_traj_config"]["cmap"] = colormap_wid2.value
traj_config["total_traj_config"]["lab_size"] = lab_size_wid_2.value
traj_config["total_traj_config"]["center_origin"] = center_wid.value
traj_config["total_traj_config"]["hide_labels"] = hide_lab_wid_2.value
traj_config["total_traj_config"]["set_axis_lim"] = xlim_wid.value+ylim_wid.value if setlim_wid.value else None
# scatter_config and hist_config
plot_param_hist_=[]
plot_t_param_hist_=[]
plot_param_vs_param_=[]
plot_track_param_vs_param_=[]
if param_module_wid.value:
for i in range(param_hist_num_wid.value):
plot_param_hist_.append(param_hist_wid_list[i].value)
for i in range(tparam_hist_num_wid.value):
plot_t_param_hist_.append(tparam_hist_wid_list[i].value)
for i in range(param_couple_num_wid.value):
plot_param_vs_param_.append([xparam_wid_list[i].value,yparam_wid_list[i].value])
for i in range(tparam_couple_num_wid.value):
plot_track_param_vs_param_.append([t_xparam_wid_list[i].value,t_yparam_wid_list[i].value])
if len(plot_param_hist_)>0 or len(plot_t_param_hist_)>0:
traj_config["hist_config"]["run"] = True
traj_config["hist_config"]["var_list"] = plot_param_hist_
traj_config["hist_config"]["mean_var_list"] = plot_t_param_hist_
else:
traj_config["hist_config"]["run"] = False
if len(plot_param_vs_param_)>0 or len(plot_track_param_vs_param_)>0:
traj_config["scatter_config"]["run"] = True
traj_config["scatter_config"]["couple_list"] = plot_param_vs_param_
traj_config["scatter_config"]["mean_couple_list"] = plot_track_param_vs_param_
else:
traj_config["scatter_config"]["run"] = False
# MSD_config
traj_config["MSD_config"]["run"] = MSD_module_wid.value
traj_config["MSD_config"]["MSD_model"] = MSD_fit
traj_config["MSD_config"]["dim"] = 2 if dim_wid.value == '2D' else 3
traj_config["MSD_config"]["fitrange"] = [None,fitrange_wid.value]
traj_config["MSD_config"]["plot_all_MSD"] = all_MSD_plot_wid.value
traj_config["MSD_config"]["plot_single_MSD"] = single_MSD_plot_wid.value
traj_config["MSD_config"]["logplot_x"] = logplot_wid_x.value
traj_config["MSD_config"]["logplot_y"] = logplot_wid_y.value
traj_config["MSD_config"]["alpha"] = alpha_wid.value
# Voronoi_config
traj_config["voronoi_config"]["run"] = vor_module_wid.value
traj_config["voronoi_config"]["plot"] = vor_plot_wid.value
traj_config["voronoi_config"]["vlim"] = None # custom vlim not supported for now
traj_config["voronoi_config"]["cmap"] = vor_cmap_wid.value
traj_config["voronoi_config"]["compute_local_area"] = vor_module_wid.value # compute by default if module run
traj_config["voronoi_config"]["show_local_area"] = vor_area_wid.value
traj_config["voronoi_config"]["area_threshold"] = vor_area_thr_wid.value
traj_config["voronoi_config"]["no_bkg"] = vor_bkg_wid.value
traj_config["voronoi_config"]["show_axis"] = vor_show_axis_wid.value
```
%% Output
**Don't forget to run this cell!**
%% Cell type:code id: tags:
``` python
printmd("**RUN THE ANALYSIS HERE!**") # no output cell, make it visible
df_list = traj_analysis(data_dir=data_dir,
data=data,
image=image,
filters=filters_dict,
plot_config=plot_param,
traj_config=traj_config)
```
%% Output
**RUN THE ANALYSIS HERE!**
Analyzing subset #1, named: 10
Plotting trajectories...
Plotting total trajectories
MSD analysis...
Plotting parameters histograms...
Plotting whole-track histograms...
Plotting couples of parameters...
Plotting couples of whole-track parameters...
%% Cell type:markdown id: tags:
# Map analysis module
### Plot maps of data calculated over a regular grid (velocity, acceleration, divergence, curl, vector means)
%% Cell type:code id: tags:
``` python
# 1. Make grids
info = tpr.get_info(data_dir)
w = info['image_width']
h = info['image_height']
image_size = [w, h]
image_aspect_ratio = h / w
lengthscale = info['lengthscale']
# widgets
x_num_init = 10
y_num_init = int(x_num_init * image_aspect_ratio)
cell_size_init = w / (x_num_init + 1)
cell_size_sc_init = (w * lengthscale) / (x_num_init + 1)
def update_by_xnum(*args):
y_num_wid.value = int(x_num_wid.value * image_aspect_ratio)
cell_size_wid.value = w / (x_num_wid.value + 1)
cell_size_scaled_wid.value = (w * lengthscale) / (x_num_wid.value + 1)
def update_by_cell_size(*args):
x_num_wid.value = int(w / cell_size_wid.value) - 1
y_num_wid.value = int(h / cell_size_wid.value) - 1
cell_size_scaled_wid.value = cell_size_wid.value * lengthscale
def update_by_cell_size_sc(*args):
x_num_wid.value = int(w * lengthscale / cell_size_scaled_wid.value) - 1
y_num_wid.value = int(h * lengthscale / cell_size_scaled_wid.value) - 1
cell_size_wid.value = cell_size_scaled_wid.value / lengthscale
orig_list = ['center', "left-bottom", "center-bottom", "right-bottom", "right-center", "right-top", "center-top",
"left-top", "left-center"]
x_num_wid = widgets.IntSlider(value=x_num_init, min=1, max=1000, description='Number of cells along x axis:',
style={'description_width': 'initial'})
y_num_wid = widgets.IntSlider(value=y_num_init, min=1, max=1000, description='Number of cells along y axis:',
style={'description_width': 'initial'}, disabled=True)
cell_size_wid = widgets.FloatSlider(value=cell_size_init, min=1e-3, max=min(w, h), description='Cell size in (px):',
style={'description_width': 'initial'})
cell_size_scaled_wid = widgets.FloatSlider(value=cell_size_sc_init, min=1e-3, max=min(w * lengthscale, h * lengthscale),
description='Cell size in ({}):'.format(info['length_unit']),
style={'description_width': 'initial'})
orig_wid = widgets.Dropdown(options=orig_list, value='center', description='grid position: ',
style={'description_width': 'initial'})
plot_grid_wid = widgets.Button(value=True, description='Show grid')
x_num_wid.observe(update_by_xnum, names='value')
cell_size_wid.observe(update_by_cell_size, names='value')
cell_size_scaled_wid.observe(update_by_cell_size_sc, names='value')
def btn_eventhandler(obj):
# clear_output()
info = tpr.get_info(data_dir)
image_size = [info['image_width'], info['image_height']]
tpr.make_grid(image_size, x_num=x_num_wid.value, origin=orig_wid.value, plot_grid=True)
plot_grid_wid.on_click(btn_eventhandler) # or use interact instead
# layout
grid_1 = GridspecLayout(3, 2)
left = [x_num_wid, cell_size_wid, cell_size_scaled_wid]
right = [y_num_wid, orig_wid, plot_grid_wid]
for i in range(3):
grid_1[i, 0] = left[i]
grid_1[i, 1] = right[i]
# 2. Map params
temp_avg_wid = widgets.BoundedIntText(value=0, min=0, max=100, description='Temporal average:',
style={'description_width': 'initial'})
arrow_size_wid = widgets.BoundedFloatText(value=1., min=0, max=100, description='Relative size of arrows:',
style={'description_width': 'initial'})
export_wid = widgets.Checkbox(value=True, description='export fields')
bkg_wid = widgets.Checkbox(value=False, description='hide background image')
# layout
grid_2 = GridspecLayout(2, 2)
left = [temp_avg_wid, arrow_size_wid]
right = [bkg_wid, export_wid]
for i in range(2):
grid_2[i, 0] = left[i]
grid_2[i, 1] = right[i]
# 3. Scalar fields
scalar_fields = ['vx', 'vy', 'vz', 'v', 'ax', 'ay', 'az', 'a', 'div', 'curl', 'v_mean', 'a_mean'] if dim == 3 else [
'vx', 'vy', 'v', 'ax', 'ay', 'a', 'div', 'curl', 'v_mean', 'a_mean']
left_3 = [Label('Field to plot')]
center_3 = [Label('Plotting limits')]
right_3 = [Label('Color map')]
for i, f in enumerate(scalar_fields):
if f in ['div', 'curl', 'v_mean', 'a_mean']:
vlim = [1e-4, 1e4]
disabled = True
else:
vlim = [df[f].min(), df[f].max()]
disabled = False
cmap = 'plasma' if f not in ['div', 'curl'] else 'bwr'
left_3.append(widgets.ToggleButton(value=True, description=f))
center_3.append(widgets.FloatRangeSlider(value=vlim, min=vlim[0], max=vlim[1], disabled=disabled))
right_3.append(widgets.Dropdown(options=['plasma', 'viridis', 'bwr'], value=cmap))
box_3 = AppLayout(header=None,
left_sidebar=VBox(left_3),
center=VBox(center_3),
right_sidebar=VBox(right_3),
pane_widths=[1, 2, 2],
footer=None)
# 4. Vector fields
scalar_fields_ = ['none'] + scalar_fields
vector_fields = ['v', 'a']
vf_4 = [Label('Vector field to plot')]
sf_4 = [Label('plot on scalar field')]
vl_4 = [Label('Plotting limits')]
cm_4 = [Label('Color map')]
for i, f in enumerate(vector_fields):
vf_4.append(widgets.ToggleButton(value=True, description=f))
sf_4.append(widgets.Dropdown(options=scalar_fields_, value=f))
vl_4.append(widgets.FloatRangeSlider(value=[0, 1], min=1e-4, max=1e4))
cm_4.append(widgets.Dropdown(options=['plasma', 'viridis', 'bwr'], value='plasma'))
def update_v_by_on_map_wid(*args):
f = sf_4[1].value
if f in ['div', 'curl', 'v_mean', 'a_mean']:
vlim = [1e-4, 1e4]
disabled = True
else:
vlim = [df[f].min(), df[f].max()]
disabled = False
cmap = 'plasma' if f not in ['div', 'curl'] else 'bwr'
vl_4[1].value = vlim
cm_4[1].value = cmap
def update_a_by_on_map_wid(*args):
f = sf_4[2].value
if f in ['div', 'curl', 'v_mean', 'a_mean']:
vlim = [1e-4, 1e4]
disabled = True
else:
vlim = [df[f].min(), df[f].max()]
disabled = False
cmap = 'plasma' if f not in ['div', 'curl'] else 'bwr'
vl_4[2].value = vlim
cm_4[2].value = cmap
sf_4[1].observe(update_v_by_on_map_wid, names='value')
sf_4[2].observe(update_a_by_on_map_wid, names='value')
box_4 = AppLayout(header=None,
left_sidebar=VBox(vf_4),
center=VBox(sf_4),
right_sidebar=HBox([VBox(vl_4), VBox(cm_4)]),
pane_widths=[1, 1, 4],
footer=None)
# 5. Vector mean
vector_fields = ['v', 'a']
fields_5 = [Label('Field to average')]
dim_5 = [Label('Dimensions to average')]
vlim_5 = [Label('Plotting limits')]
cmap_5 = [Label('Color map')]
for i, f in enumerate(vector_fields):
cmap = 'plasma'
vlim = [df[f].min(), df[f].max()]
fields_5.append(widgets.ToggleButton(value=True, description=f))
dim_5.append(widgets.Dropdown(options=[('x,y,z', ['x', 'y', 'z']),
('x,y', ['x', 'y']),
('x,z', ['x', 'z']),
('y,z', ['y', 'z'])],
value=['x', 'y', 'z']))
vlim_5.append(widgets.FloatRangeSlider(value=vlim, min=vlim[0], max=vlim[1]))
cmap_5.append(widgets.Dropdown(options=['plasma', 'viridis', 'bwr'], value=cmap))
box_5 = AppLayout(header=None,
left_sidebar=VBox(fields_5),
center=VBox(dim_5),
right_sidebar=HBox([VBox(vlim_5), VBox(cmap_5)]),
pane_widths=[1, 2, 6],
footer=None)
# layout
accordion = widgets.Accordion(children=[box_3, box_4, box_5])
acc_titles = ['Scalar fields', 'Vector fields', 'Vector mean']
for i in range(len(acc_titles)):
accordion.set_title(i, acc_titles[i])
tab_titles = ['Make grids', 'Map parameters', 'Fields to plot']
tab = widgets.Tab()
tab.children = [grid_1, grid_2, accordion]
for i in range(len(tab_titles)):
tab.set_title(i, tab_titles[i])
display(tab)
```
%% Output
%% Cell type:code id: tags:
``` python
printmd("**Don't forget to run this cell!**") # no output cell, make it visible
## Prepare config
map_config = tpr.make_map_config(export_config=False)
# grid_param
map_config["grid_param"] = {'x_num':None,
'y_num':None,
'cell_size':cell_size_wid.value, #use only cell size in pixel so there is no conflict in definition
'scaled':False,
'origin':orig_wid.value,
'plot_grid':False}
# map_param
map_config["map_param"]["no_bkg"] = bkg_wid.value
map_config["map_param"]["size_factor"] = arrow_size_wid.value
map_config["map_param"]["export_field"] = export_wid.value
map_config["map_param"]["temporal_average"] = temp_avg_wid.value
# scalar_fields
scalar_fields_dict={}
for i,f in enumerate(scalar_fields):
if left_3[i+1].value:
#scalar_fields_dict[f]={'vlim':center_3[i+1].value,'cmap':cmap}
scalar_fields_dict[f]={'vlim':None,'cmap':right_3[i+1].value}
map_config["scalar_fields"] = scalar_fields_dict
#4. vector_fields
vector_fields_dict={}
for i,f in enumerate(vector_fields):
if vf_4[i+1].value:
#vector_fields_dict[f]={'plot_on':sf_4[i+1].value,'vlim':vl_4[i+1].value,'cmap':cmap}
vector_fields_dict[f]={'plot_on':sf_4[i+1].value,'vlim':None,'cmap':cm_4[i+1].value}
map_config["vector_fields"] = vector_fields_dict
#5. vector_mean
vector_mean_dict={}
for i,f in enumerate(vector_fields):
if fields_5[i+1].value:
#vector_mean_dict[f]={'dimensions':dim_5[i+1].value,'vlim':vlim_5[i+1].value,'cmap':cmap}
f_ = f+'_mean'
vector_mean_dict[f_]={'dimensions':dim_5[i+1].value,'vlim':None,'cmap':cmap_5[i+1].value}
map_config["vector_mean"] = vector_mean_dict
```
%% Output
**Don't forget to run this cell!**
%% Cell type:code id: tags:
``` python
config_dir = osp.join(data_dir,'config_2')
for key in map_config.keys():
fn = osp.join(config_dir, key + '.csv')
tpr.write_dict(map_config[key], fn)
```
%% Cell type:code id: tags:
``` python
printmd("**RUN THE ANALYSIS HERE!**") # no output cell, make it visible
fdata=map_analysis(data_dir=data_dir,
data=data,
image=image,
filters=filters_dict,
plot_config=plot_param,
map_config=map_config)
```
%% Output
**RUN THE ANALYSIS HERE!**
WARNING: no data for this frame subset. Returning unfiltered database
WARNING: no data for this frame subset. Returning unfiltered database
Analyzing subset 1
Analyzing subset 2 89n 189ting vz 64
plotting a 189n 189ting a 22plotting a 33
plotting vx 24
%% Cell type:markdown id: tags:
# Comparator module
### This module allows you to compare datasets you have already analyzed by pooling them together on the same plots
You can browse your file system to any dataset (even though they don't belong to the same raw data). However, currently, data conversion from datasets with different units *is not supported*. The units will be the one of the first selected datasets.
You can compare datasets or just pool them together.
Data will be saved in root folder of the first selected dataset (the folder containing the position file, info.txt, database.p, etc.)
%% Cell type:code id: tags:
``` python
printmd("**You can either compare datasets (each one have a specific color on plots) or only pool them together (they all have the same color)**")
plotting_mode_wid=widgets.ToggleButtons(options=['compare','pool'],description='Datasets plotting:',style={'description_width': 'initial'})
display(plotting_mode_wid)
printmd("**Give the number of datasets you want to analyze**")
ds_num_wid=widgets.BoundedIntText(value=0,min=0,max=10,description='Number of datasets:',style={'description_width': 'initial'})
display(ds_num_wid)
```
%% Output
**You can either compare datasets (each one have a specific color on plots) or only pool them together (they all have the same color)**
**Give the number of datasets you want to analyze**
%% Cell type:code id: tags:
``` python
fc_list=[]
name_wid_list=[]
rows=[]
init_dir=data_dir if 'data_dir' in locals() else cwd
for i in range(ds_num_wid.value):
lab=widgets.Label("Dataset #{}".format(i))
fc = FileChooser(init_dir)
fc.use_dir_icons = True
fc.title = '<b>Choose the folder you want to analyze <b>'
fc_list.append(fc)
name=widgets.Text(value='',placeholder='optional',description='Dataset name:',style={'description_width': 'initial'})
name_wid_list.append(name)
rows.append(HBox([lab,fc,name]))
display(VBox(rows))
```
%% Output
%% Cell type:code id: tags:
``` python
# get datasets
data_dir_list=[]
name_list=[]
for i in range(ds_num_wid.value):
data_dir_=fc_list[i].selected_path
if data_dir_ is None:
continue
else:
name=name_wid_list[i].value
if name=='':
name=osp.split(data_dir_)[1]
data_dir_list.append(data_dir_)
name_list.append(name)
# datadir is the datadir of the first dataset
data_dir=osp.sep.join(data_dir_list[0].split(osp.sep)[:-2]) #the main dir is two levels up
if not osp.exists(osp.join(data_dir,'info.txt')):
raise Exception("""ERROR: your first dataset root directory doesn't contain an info file, which is required. Aborting...\n
root director: {}""".format(data_dir))
# number of plot kinds
printmd("**Parameters plotting section**")
printmd("You can plot histograms or boxplots of single parameters or scatter plots of a couple of parameters (e.g. v vs y)")
param_module_wid=widgets.ToggleButton(value=True,description='Run module')
display(param_module_wid)
printmd("How many instantaneous parameters (histogram or couples) do you want to plot? (enter 0 if you don't want to plot parameters)")
param_hist_num_wid=widgets.BoundedIntText(value=1,min=0,max=10,description='Number of histograms:',style={'description_width': 'initial'})
param_box_num_wid=widgets.BoundedIntText(value=1,min=0,max=10,description='Number of boxplots:',style={'description_width': 'initial'})
param_couple_num_wid=widgets.BoundedIntText(value=1,min=0,max=10,description='Number of couples:',style={'description_width': 'initial'})
display(HBox([param_hist_num_wid,param_box_num_wid,param_couple_num_wid]))
printmd("How many whole-trajectory parameters (histogram or couples) do you want to plot? (enter 0 if you don't want to plot parameters)")
tparam_hist_num_wid=widgets.BoundedIntText(value=1,min=0,max=10,description='Number of histograms:',style={'description_width': 'initial'})
tparam_box_num_wid=widgets.BoundedIntText(value=1,min=0,max=10,description='Number of boxplots:',style={'description_width': 'initial'})
tparam_couple_num_wid=widgets.BoundedIntText(value=1,min=0,max=10,description='Number of couples:',style={'description_width': 'initial'})
display(HBox([tparam_hist_num_wid,tparam_box_num_wid,tparam_couple_num_wid]))
printmd("***")
printmd("**MSD section**")
MSD_plot_wid=widgets.ToggleButton(value=True,description='plot MSD')
logplot_wid_x=widgets.Checkbox(value=True,description='x axis')
logplot_wid_y=widgets.Checkbox(value=True,description='y axis')
alpha_lab=Label('For all MSD plots, set the transparency (0=transparent, 1=opaque)')
alpha_wid=widgets.FloatSlider(value=0.2,min=0,max=1,steps=0.01,description='transparency',style={'description_width': 'initial'})
display(MSD_plot_wid)
display(HBox([Label('log plot: '),logplot_wid_x,logplot_wid_y]))
display(HBox([alpha_lab,alpha_wid]))
```
%% Output
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-48-21d9e77d3c2b> in <module>
14
15 # datadir is the datadir of the first dataset
---> 16 data_dir=osp.sep.join(data_dir_list[0].split(osp.sep)[:-2]) #the main dir is two levels up
17 if not osp.exists(osp.join(data_dir,'info.txt')):
18 raise Exception("""ERROR: your first dataset root directory doesn't contain an info file, which is required. Aborting...\n
IndexError: list index out of range
%% Cell type:code id: tags:
``` python
if param_module_wid.value:
### prepare parameters lists
if 'data' not in locals():
data=tpr.get_data(data_dir)
dimensions=['x','y'] if data['dim']==2 else ['x','y','z']
scaled_dimensions=[dim+'_scaled' for dim in dimensions]
vel=['v'+dim for dim in dimensions]
acc=['a'+dim for dim in dimensions]
params=['track','t']+dimensions+scaled_dimensions+vel+acc+['v','a']
#get whole_track param
params_track=[]
for data_dir_ in data_dir_list:
fn=osp.join(data_dir_,'track_prop.csv')
if not osp.exists(fn):
raise Exception("ERROR: No data to compare in {}. Aborting...".format(data_dir_))
df_prop=pd.read_csv(fn,index_col=0)
params_track=params_track+list(df_prop.columns)