Commit 88584719 authored by amichaut's avatar amichaut
Browse files

added custom variable to trajectory color coding

parent df134f7e
......@@ -141,12 +141,12 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "7a3a7b95d6f54eaeb3284f681ef79f79",
"model_id": "d2df492653224f17b9c5be966f28cfa9",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"FileChooser(path='/Users/amichaut/Documents/Work/codes/track-analyzer', filename='', title='HTML(value='<b>Tra…"
"FileChooser(path='/Users/amichaut/Desktop/data_gaelle', filename='', title='HTML(value='<b>Tracking data file<…"
]
},
"metadata": {},
......@@ -155,7 +155,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "c2ba77a1539b42c9bfafbc2eb7c60f2f",
"model_id": "7a923e81e7164bbfa57d48dd757b8b2c",
"version_major": 2,
"version_minor": 0
},
......@@ -169,7 +169,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "a1ed6e415021428198699cce35bb74f7",
"model_id": "0f0a61cdb853432886fb0b355c77f5d0",
"version_major": 2,
"version_minor": 0
},
......@@ -183,7 +183,8 @@
],
"source": [
"#choose positions file\n",
"fc_table = FileChooser(cwd)\n",
"#fc_table = FileChooser(cwd)\n",
"fc_table = FileChooser(\"/Users/amichaut/Desktop/data_gaelle\")\n",
"fc_table.use_dir_icons = True\n",
"fc_table.title = '<b>Tracking data file</b>'\n",
"\n",
......@@ -219,7 +220,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "111409a033024cf08105c766c72bd02c",
"model_id": "85a3f2cfdca445c4b2849ed06f8e9496",
"version_major": 2,
"version_minor": 0
},
......@@ -285,7 +286,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e66c3d34a62a410bbf8b7a562275ca07",
"model_id": "9c31aed00f694b2ab3c59a987c326b12",
"version_major": 2,
"version_minor": 0
},
......@@ -311,7 +312,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "f5655a77a55e42d99aa006410ae8243f",
"model_id": "51ab5bc5afb94e318837500a23dcac29",
"version_major": 2,
"version_minor": 0
},
......@@ -713,7 +714,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "d86d084297a64dacb384ae51d8d4b152",
"model_id": "1034e1c00b1d44458297a8df43fa9741",
"version_major": 2,
"version_minor": 0
},
......@@ -727,7 +728,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "3cb651958eaa4c6f8e80d79aa709fe5d",
"model_id": "5d7429135e0949b2896fed61fa32b829",
"version_major": 2,
"version_minor": 0
},
......@@ -741,7 +742,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "edd79faa8e774a68a8804d6e9cb94935",
"model_id": "f0c14e6449d04bd188cbf407c62c5da7",
"version_major": 2,
"version_minor": 0
},
......@@ -767,7 +768,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "275d2cbee37a418ca8e51042e0b13247",
"model_id": "43620f8dd8404cbeb6cfe647ec9aed81",
"version_major": 2,
"version_minor": 0
},
......@@ -793,7 +794,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "501c9441a58b4df7bfe65845715d085f",
"model_id": "c9077b286d134c968775d720c03da623",
"version_major": 2,
"version_minor": 0
},
......@@ -819,7 +820,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "2eeb5628d37144358fc41ef856ddcb11",
"model_id": "fed056c550234957883d58cfb708a63d",
"version_major": 2,
"version_minor": 0
},
......@@ -845,7 +846,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "54c9a3dbf9ae48978af90fc4c37c6a51",
"model_id": "735246a336d04fe49c808b38e6339fe6",
"version_major": 2,
"version_minor": 0
},
......@@ -871,7 +872,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e161d43591fc425fadc381f641e26ead",
"model_id": "22ae05d810804a17b8ef6e3dc1627c87",
"version_major": 2,
"version_minor": 0
},
......@@ -1056,7 +1057,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "9b4f2b8ce6f04a34b96aa2bb2a70ff48",
"model_id": "2101abe85c7547e28482a042a6a3d099",
"version_major": 2,
"version_minor": 0
},
......@@ -1109,7 +1110,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "f9d54da9da2c4af5a2b361d8c7c7c1ee",
"model_id": "5eacf2d9222246d89dca8eedae9b8084",
"version_major": 2,
"version_minor": 0
},
......@@ -1147,7 +1148,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "30b975844d634ac5a67c7354149b79af",
"model_id": "17541536f2ee4540951514cc257e8ed8",
"version_major": 2,
"version_minor": 0
},
......@@ -1204,7 +1205,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b1b0d9b12af74e3a9207ef9ac67924c4",
"model_id": "d6d9513b0a7048d794f9295cf1d3b017",
"version_major": 2,
"version_minor": 0
},
......@@ -1254,7 +1255,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e3798a8f652146ad809df9c6b31a622e",
"model_id": "6f39a1a764364808a0915de0926d48e1",
"version_major": 2,
"version_minor": 0
},
......@@ -1280,7 +1281,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b425aa161dd4434a93b91b617440ad87",
"model_id": "d2eb77e254864b58a7a2ed981cb1120f",
"version_major": 2,
"version_minor": 0
},
......@@ -1429,7 +1430,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "737c0df4b0c746b98ef5ada0f6ab82a3",
"model_id": "148784e1c24740658d48ade2187295a7",
"version_major": 2,
"version_minor": 0
},
......@@ -1620,13 +1621,13 @@
"name": "stdout",
"output_type": "stream",
"text": [
"{'xlim': (36.61438636861541, 472.0845405438229), 'ylim': (38.13919994626437, 473.7006114895953), 'zlim': (21.689340569848213, 473.7984788052534), 'min_traj_len': 0, 'max_traj_len': 25, 'frame_subset': (0, 24), 'track_list': None, 'track_ROI': None, 'name': ''}\n"
"{'xlim': (36.61438636861541, 208.61439), 'ylim': (38.13919994626437, 267.1392), 'zlim': (21.689340569848213, 375.68934), 'min_traj_len': 0, 'max_traj_len': 25, 'frame_subset': (0, 12), 'track_list': None, 'track_ROI': None, 'name': ''}\n"
]
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "ff6ac8f5c5b54bf2beabf5d69d6ee3ea",
"model_id": "79fe70f1a1dd41c89f0c64e741fdce77",
"version_major": 2,
"version_minor": 0
},
......@@ -1782,7 +1783,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "20968f4f336942248cd87055fb7a962e",
"model_id": "c14d3c64f233487586119af20eeff22d",
"version_major": 2,
"version_minor": 0
},
......@@ -1808,7 +1809,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "021dc221ce584af7ae1d24e53bd8344e",
"model_id": "79afc0cbf3404152ab81e9f2350d5080",
"version_major": 2,
"version_minor": 0
},
......@@ -1858,7 +1859,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "1d9984d1716440deada5d0a3a72c26a1",
"model_id": "1b946f086959421ab259ee8e00930127",
"version_major": 2,
"version_minor": 0
},
......@@ -1884,7 +1885,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "55841e8fa87049a28edb0737889329b5",
"model_id": "601aab23ee494f4d9dcba9ba9fe50562",
"version_major": 2,
"version_minor": 0
},
......@@ -1910,7 +1911,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "aa70f548b4084c99bf858090faa02b85",
"model_id": "812136e081d74995aa639fee7c3cf2a8",
"version_major": 2,
"version_minor": 0
},
......@@ -1936,7 +1937,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "feb42ba40aaf47d89df53326331651d6",
"model_id": "79d9733b9fd64a23b56966a273916ec2",
"version_major": 2,
"version_minor": 0
},
......@@ -1986,7 +1987,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "00706de308e140a3bcf67be232bae37d",
"model_id": "1a3ab90282554e9385d53d082311edde",
"version_major": 2,
"version_minor": 0
},
......@@ -2000,7 +2001,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "a27b624a81844316ba0781474c84b52e",
"model_id": "0e6b4cd626594cf0a322c3b870d6e5d2",
"version_major": 2,
"version_minor": 0
},
......@@ -2014,7 +2015,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "4c2a5f869c7142c38ebc16ecafe7a68c",
"model_id": "75e515dd097a49649ac59d90a84d4af2",
"version_major": 2,
"version_minor": 0
},
......@@ -2064,7 +2065,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "f18fd72ec04d4f058037b847f2d67b1f",
"model_id": "11a4650def444ddcba884f59c82c61a3",
"version_major": 2,
"version_minor": 0
},
......@@ -2090,7 +2091,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "60c59be6b8d64b3fbe3b29b6f2b7ea0a",
"model_id": "5b9cc319b29a4d7bb8d13e862aaa9c08",
"version_major": 2,
"version_minor": 0
},
......@@ -2116,7 +2117,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "e6ff05d7a4a64a1aa19cb02e60a2d450",
"model_id": "c8e3b22094a64bd7924ac8b2ea27c505",
"version_major": 2,
"version_minor": 0
},
......@@ -2142,7 +2143,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "86281860a6d648af9f305ed65d9f5fc8",
"model_id": "7a44c672f9684b92bfaf9ad69f52b179",
"version_major": 2,
"version_minor": 0
},
......@@ -2156,7 +2157,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "8fcffe77f1874f1ba8bb0a548ef7e1e2",
"model_id": "5d2500cde84b424992aa74873305280e",
"version_major": 2,
"version_minor": 0
},
......@@ -2170,7 +2171,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "d3c01c768b904276b40ac2b1ba35db46",
"model_id": "cc0b999d844543f2a3f7a9b318e1e35a",
"version_major": 2,
"version_minor": 0
},
......@@ -2196,7 +2197,7 @@
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "d40b6f51abee4181846f2042eb69e045",
"model_id": "896a0001604b473382b567846497e483",
"version_major": 2,
"version_minor": 0
},
......@@ -2211,14 +2212,14 @@
"source": [
"# prepare default values for widgets\n",
"if data['dim'] == 2:\n",
" color_code_list = ['t', 'group', 'random', 'none']\n",
" color_code_list = ['t', 'group', 'random', 'none'] + list(custom_var.keys())\n",
" # if several subset plotted together, color code default: ROI\n",
" if len(filters_dict['filters_list']) and filters_dict['subset'] == 'together':\n",
" color_code_default = 'group'\n",
" else:\n",
" color_code_default = 'random'\n",
"elif data['dim'] == 3:\n",
" color_code_list = ['z', 't', 'group', 'random', 'none']\n",
" color_code_list = ['z', 't', 'group', 'random', 'none'] + list(custom_var.keys())\n",
" # if several subset plotted together, color code default: ROI\n",
" if len(filters_dict['filters_list']) and filters_dict['subset'] == 'together':\n",
" color_code_default = 'group'\n",
......@@ -2400,7 +2401,7 @@
},
{
"cell_type": "code",
"execution_count": 22,
"execution_count": 23,
"metadata": {
"scrolled": false
},
......@@ -2416,20 +2417,6 @@
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "28df9f67f3c64bcca0453bc7a0fc7ec0",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Tab(children=(Accordion(children=(VBox(children=(Dropdown(description='parameter', index=14, options=('track',…"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
......@@ -2547,7 +2534,7 @@
},
{
"cell_type": "code",
"execution_count": 23,
"execution_count": 24,
"metadata": {
"scrolled": false
},
......@@ -2659,7 +2646,7 @@
},
{
"cell_type": "code",
"execution_count": 24,
"execution_count": 25,
"metadata": {
"scrolled": false
},
......@@ -2680,11 +2667,8 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Analyzing subset #1, named: 7\n",
"Plotting parameters histograms...\n",
"Plotting whole-track histograms...\n",
"Plotting couples of parameters...\n",
"Plotting couples of whole-track parameters...\n"
"Analyzing subset #1, named: 12\n",
"Plotting total trajectories\n"
]
}
],
......
%% 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
from track_analyzer.scripts.compare_datasets import compare_datasets
from napari.settings import get_settings
get_settings().application.ipy_interactive = False # disable interactive usage of Napari viewer (necessary for tpr.get_coordinates)
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: stream
_ _ _
| |_ _ __ __ _ ___| | __ __ _ _ __ __ _| |_ _ _______ _ __
| __| '__/ _` |/ __| |/ / / _` | '_ \ / _` | | | | |_ / _ \ '__|
| |_| | | (_| | (__| < | (_| | | | | (_| | | |_| |/ / __/ |
\__|_| \__,_|\___|_|\_\ \__,_|_| |_|\__,_|_|\__, /___\___|_|
|___/
Track Analyzer - Quantification and visualization of tracking data.
Developed and maintained by Arthur Michaut: arthur.michaut@gmail.com
%%%% Output: execute_result
<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 = FileChooser(cwd)
fc_table = FileChooser("/Users/amichaut/Desktop/data_gaelle")
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: display_data
**Browse your file system to the table of tracked data (only .txt and .csv are supported)**
%%%% Output: display_data
%%%% Output: display_data
%%%% Output: display_data
%% Cell type:code id: tags:
``` python
# get position file path
data_dir = fc_table.selected_path
data_file = fc_table.selected
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: display_data
**(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.
%%%% Output: display_data
%% 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']
get_image_size = False
else:
get_image_size = True # to call get_image again after info.txt is generated
# 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: display_data
---
%%%% Output: display_data
The database already exists, do you want to refresh it?
%%%% Output: display_data
%%%% Output: display_data
The info.txt file already exists, do you want to refresh it?
%%%% Output: display_data
%% 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: display_data
**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)
image = tpr.get_image(data_dir,filename=im_file,verbose=True)
```
%%%% Output: display_data
**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: display_data
**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_wid_list = []
left_list=[]
right_list=[]
param_list = ['discard','x','y','z','frame','track']
var_list = []
var_wid_dict = {}
custom_var_num = df.shape[1] - 5 # number of columns apart from 'x','y','z','frame','track'
for i in range(custom_var_num):
param_list.append('var_{}'.format(i+1))
var_list.append('var_{}'.format(i+1))
# display the df columns as two columns of widgets
for i,col in enumerate(df.columns):
wid = widgets.Dropdown(options=param_list,value='discard',
description='column {}:'.format(col),
style={'description_width': 'initial'})
col_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 "discard" the other ones. If you want to use custom variables, use var_i.**""")
left_box = VBox(left_list)
right_box = VBox(right_list)
display(HBox([left_box, right_box]))
# get the custom variable name and unit
HBox_list = []
for var in var_list:
wid_name = widgets.Text(value='',placeholder='Variable name')
wid_unit = widgets.Text(value='',placeholder='Variable unit')
HBox_list.append(HBox([Label(var+':'),wid_name,wid_unit]))
var_wid_dict[var] = {'name': wid_name, 'unit': wid_unit}
printmd("""**If you selected some custom variables, give their name and unit to be displayed on plots.
You can use Latex, if necessary.**""")
display(VBox(HBox_list))
# 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: display_data
**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 col_wid_list]
for param_ in ['x','y','frame','track']: # mandatory columns
if param_ not in col_values:
raise Exception("You MUST select a column for "+param_)
df.columns = col_values # rename columns
# discard non-relevant columns
col_values = np.array(col_values)
new_cols = col_values[col_values!='discard']
for c in new_cols:
if np.count_nonzero(new_cols==c) > 1: # if repeated element
raise Exception("You have selected several times the column: "+c)
df = df[new_cols]
# get names and units of custom variables
custom_var = {}
for var in var_list:
if var in new_cols:
custom_var[var] = {'name': var_wid_dict[var]['name'].value, 'unit': var_wid_dict[var]['unit'].value}
# 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: display_data
**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,custom_var=custom_var)
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']
custom_var = data['custom_var']
```
%%%% Output: display_data
**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_resfac_wid = widgets.FloatSlider(value=1,min=0.01,max=30,step=0.01,
description='Figure size factor:',style={'description_width': 'initial'})
fig_format_wid = widgets.Dropdown(options=['.png','.svg'],value='.png',
description='Single plot format',style={'description_width': 'initial'})
save_as_stack_wid = widgets.Checkbox(value=True, description='Save as tiff stack')
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]),HBox([fig_dpi_wid,fig_format_wid]),despine_wid)
printmd('Adjust figure resolution (if orginal image is too small or too large)')
display(fig_resfac_wid)
printmd('When plotting over timelapse, plot as a multidimensional tiff stack or as a series of individual image')
display(save_as_stack_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: display_data
## General plotting configuration
%%%% Output: display_data
%%%% Output: display_data
%%%% Output: display_data
%%%% Output: display_data
Adjust figure resolution (if orginal image is too small or too large)
%%%% Output: display_data
%%%% Output: display_data
When plotting over timelapse, plot as a multidimensional tiff stack or as a series of individual image
%%%% Output: display_data
%%%% Output: display_data
Do you want to add/replace the first default colors used for plotting? Give the number of colors you want to select:
%%%% Output: display_data
%%%% Output: display_data
How do you want to display the y-axis (standard orientation: origin at top)
%%%% Output: display_data
%%%% Output: display_data
Do you want to export the data points of your plots as .csv files?
%%%% Output: display_data
%% 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: display_data
**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,
'figsize_factor':fig_resfac_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,
'save_as_stack': save_as_stack_wid.value,
}
```
%%%% Output: display_data
**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/')
printmd('Warning: large image can lead to rendering issues')
if image['z_dim'] is None:
printmd('Warning: you have a 2D+t image, no 3D redering is available then.')
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: display_data
**View trajectories on a Napari viewer before plotting**
%%%% Output: display_data
If not working, please check Napari installation: https://napari.org/
%%%% Output: display_data
Warning: large image can lead to rendering issues
%%%% Output: display_data
Warning: you have a 2D+t image, no 3D redering is available then.
%%%% Output: display_data
%% 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: display_data
Your data can be filtered into subsets. How many subsets do you want to analyze?
%%%% Output: display_data
%%%% Output: display_data
If you define several subsets, do you want to analyze them separately or together?
%%%% Output: display_data
If analyzed together, subsets will be plotted together. If analyzed separately, each subset will be plotted on individual plots.
%%%% Output: display_data
%% 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,df=df,verbose=True)
# 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."
"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: display_data
### Subset #1
%%%% Output: display_data
You can give it a custom name that will be used for saving data
%%%% Output: display_data
%%%% Output: display_data
**Crop a region**
%%%% Output: display_data
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
%%%% Output: display_data
Draw using the rectangle shape, hit ENTER while you're done.If you want more details about the email viewer please visit https://napari.org/
%%%% Output: display_data
%%%% Output: display_data
**Select data based on trajectories duration or frame subset**
%%%% Output: display_data
%% 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