Commit df76a0f3 authored by amichaut's avatar amichaut
Browse files

bugfix in make_plot_config call and ensure voronoi axis lim constant

parent 0468262e
%% 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
/opt/miniconda3/lib/python3.8/site-packages/napari/_qt/__init__.py:37: UserWarning:
napari was tested with QT library `>=5.12.3`.
The version installed is 5.9.7. Please report any issues with this
specific QT version at https://github.com/Napari/napari/issues.
warn(message=warn_message)
_ _ _
| |_ _ __ __ _ ___| | __ __ _ _ __ __ _| |_ _ _______ _ __
| __| '__/ _` |/ __| |/ / / _` | '_ \ / _` | | | | |_ / _ \ '__|
| |_| | | (_| | (__| < | (_| | | | | (_| | | |_| |/ / __/ |
\__|_| \__,_|\___|_|\_\ \__,_|_| |_|\__,_|_|\__, /___\___|_|
|___/
Track Analyzer - Quantification and visualization of tracking data.
Developed and maintained by Arthur Michaut: arthur.michaut@gmail.com
<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: (708x512) pixels with 195 time steps
You have loaded a 3D image: (300x1387) pixels with 50 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: