Lab book for Zebrafish experiments

May 18, 2014

About this labbook

Filed under: Uncategorized — alperezescudero @ 5:30 pm

This blog contains an electronic labbook edited by Sara Arganda, Alfonso Pérez-Escudero and Julián Vicente-Page, while working at de Polavieja Lab at the Cajal Institute (Consejo Superior de Investigaciones Científicas, Madrid, Spain).

While most of the work described here is related to zebrafish, there is also a lot of work related to other species (especially theoretical work). The title is therefore not very informative, but we have grown fond of it.

As any labbook, it is not meant to be understandable by anybody outside the laboratory, we make it public for the sake of transparency. It is mainly written in English, but some parts are in Spanish.

The work described here resulted in several publications. Not all the work on these publications is reflected here, because not all authors contributed to this labbook. We note under each paper the categories of this blog that refer to it (note that some categories refer to more than one paper).


Collective Animal Behavior from Bayesian Estimation and Probability Matching
A. Pérez-Escudero, G.G. de Polavieja
PLoS Comput Biol 7(11): e1002282 (2011)
pdf | web | journal cover
Categories: Bayesian theory, Bayesian Theory – Paper figures, Social Decision Making,

A common rule for decision-making in animal collectives across species
S. Arganda, A. Pérez-Escudero & G.G. de Polavieja
Proc Natl Acad Sci USA vol. 109 no. 50 20508-20513 (2012)
pdf | web
Categories: Ants, Bayesian theory, Bayesian Theory – Paper figuresComputational models, Data reminder, Social Decision Making, Experiments, Fish reproduction, Fishes lines, Lab notes, Protocols, Set-up, Social Decision Making, Social Transitions – Paper figures, Stickleback-NewModel, Weber

Estimation models describe well collective decisions among three options
A. Pérez-Escudero, N. Miller, A.T. Hartnett, S. Garnier, I.D. Couzin, G.G. de Polavieja
Proc Natl Acad Sci USA vol. 110 no. 37 E3466-E3467 (2013)
pdf | web
Categories: Miller et al (Social cohesion)

idTracker: Tracking individuals in a group by automatic identification of unmarked animals
A. Pérez-Escudero, J. Vicente-Page, R.C. Hinz, S. Arganda, G.G. de Polavieja
Nature Methods
(in press, doi:10.1038/nmeth.2994)
Categories: Experiments, Fish recognition, Set-up, Tracking, Tracking – Paper figures, Tracking – Spiders, Tracking – ThesisFigures, Tracking – VideoAbstract, TrackingAnts, TrackingDrosophila, TrackingLarvaDroso, TrackingLarvas, TrackingRaton


February 23, 2014

Validation of the 8-females Drosophila video with interpolation

Filed under: Tracking — alperezescudero @ 9:14 pm

Name of this file: Cuaderno20140223T144509.m


ans =


Load data

load([ruta nombresegm
datosegm.directorio=[ruta nombresegm

Update tracking (resegmentation and subsequent steps)

% datosegm.ratio_bwdist=2;
% [datosegm,npixelsyotros,solapamiento,trozos,solapos,conectan,conviven,solapan,indiv]=datosegm2resegmentacion(datosegm);
% solapamiento=load_encrypt([datosegm.directorio ‘solapamiento’],datosegm.encriptar);
% load([ruta nombresegm ‘\’ ‘trozos.mat’])
% trozos=variable.trozos;
% solapos=variable.solapos;
% load([ruta nombresegm ‘\’ ‘mancha2id’])
% mancha2id=variable.mancha2id;
% idtrozos=mancha2id2idtrozos(datosegm,trozos,solapos,mancha2id);
% probtrozos=idtrozos2probtrozos(idtrozos);
% % idtrozos=trozos2id_trozos(datosegm,trozos,solapos,indvalidos,referencias,[]);
% idprobtrozos.idtrozos=idtrozos;
% idprobtrozos.probtrozos=probtrozos;
% save_encrypt([datosegm.directorio ‘idtrozos.mat’],idprobtrozos,datosegm.encriptar)
% clear idprobtrozos
% load([datosegm.directorio ‘conectanconviven.mat’])
% [mancha2pez,trozo2pez,probtrozos_relac]=probtrozos2identidades(trozos,probtrozos,conviven);
% man2pez.mancha2pez=mancha2pez;
% man2pez.trozo2pez=trozo2pez;
% man2pez.probtrozos_relac=probtrozos_relac;
% save_encrypt([datosegm.directorio ‘mancha2pez.mat’],man2pez,datosegm.encriptar)
% clear man2pez


% datosegm2smartinterp(datosegm);

Adapt validation

% load(‘F:\Hipertec_pesados\Moscas\Platogrande_8females\oldsegm_orig\mancha2pez_corregidomanual4000frames.mat’)
% mancha2pez_corr_old=mancha2pez;
% load(‘F:\Hipertec_pesados\Moscas\Platogrande_8females\oldsegm_orig\mancha2centro.mat’)
% mancha2centro_old=mancha2centro;
% np=load_encrypt([datosegm.directorio ‘npixelsyotros’],datosegm.encriptar);
% man2pez=load_encrypt([datosegm.directorio ‘mancha2pez’],datosegm.encriptar);
% [mancha2pez_corr,umbral,distancias]=relacionamancha2pez(mancha2pez_corr_old,mancha2centro_old,man2pez.mancha2pez,np.mancha2centro,8.8);
% clear variable
% variable.mancha2pez=mancha2pez_corr;
% save_encrypt([datosegm.directorio ‘mancha2pez_corregidomanual4000frames.mat’],variable,datosegm.encriptar)

Test interpolation

man2pez_orig=load_encrypt([datosegm.directorio ‘mancha2pez’],datosegm.encriptar);
compruebacorreccion(man2pez_orig.mancha2pez,mancha2pez_corr,tr.trozos,man2pez_interp.trozo2pez,[1 4000])

81 frames que tenían error se han corregido. Trozos:
27 28 31 86 87 149

0 frames de cruces que estaban asignados ya no lo están. Trozos:
0 frames que tenían error se han quedado sin identidad. Trozos:
0 frames que estaban bien se han jodido. Trozos:
0 frames que estaban bien se han quedado sin identidad. Trozos:
0 frames que estaban mal siguen mal. Trozos:

Show validation

datosegm2fig_validacion(ruta,mancha2pez_corr,[1 4000],60,)

Warning: MMREADER will be removed in a future release. Use VIDEOREADER instead.

ans =

11 14

Proporción de frames correctos: 0.999226
Proporción de trayectorias correctas (en distancia): 0.999885
Tamaño medio: 762.162

Published with MATLAB® R2013b

February 22, 2014

Validation of the new re-segmented trajectories in the video of 2 black mice (negro y canoso)

Filed under: Tracking — alperezescudero @ 9:38 pm

Name of this file: Cuaderno20140218T191430.m


ans =


load data

% ruta=’J:\Ratones\20121203\2negroscanosos\’; % Con disco duro externo en el portátil
% % ruta=’D:\Hipertec_pesados\Ratones\2negroscanosos\’; % Sin disco duro externo en el portátil

Old data (corrected)

% load([ruta ‘segm_seguridad\npixelsyotros.mat’])
% mancha2centro_old=variable.mancha2centro;
% load([ruta ‘segm_seguridad\mancha2pez_corregidomanual_30100frames.mat’])
% mancha2pez_corr_old=mancha2pez;
% clear mancha2pez

New data

% load([ruta ‘segm\npixelsyotros.mat’])
% mancha2centro=variable.mancha2centro;
% load([ruta ‘segm\mancha2pez_sinautocorr.mat’])
% mancha2pez=variable.mancha2pez;
% trozo2pez=variable.trozo2pez;
% probtrozos_relac=variable.probtrozos_relac;
% load([ruta ‘segm\trozos.mat’])
% trozos=variable.trozos;
% load([ruta ‘segm\conectanconviven.mat’])
% load([ruta ‘segm\datosegm.mat’])
% datosegm=variable;
% datosegm.directorio_videos=ruta;
% datosegm.directorio=[ruta ‘segm\’];

Find relation

% [mancha2pez_corr,umbral,distancias]=relacionamancha2pez(mancha2pez_corr_old,mancha2centro_old,mancha2centro,1);

It is normal that not 100% of the trajectory is assigned, because there are new centers due to resegmentation. But all blobs with identity have been assigned, as should be.

Extend mancha2pez to fill the fragments

Because of the resegmentation, the new fragments span for longer than the old ones. So I extend mancha2pez

% n_trozos=max(trozos(:));
% for c_trozos=1:n_trozos
% ind=trozos==c_trozos;
% pez=unique(mancha2pez_corr(ind));
% pez=pez(pez>0);
% if length(pez)>1
% disp([‘El trozo ‘ num2str(c_trozos) ‘ tiene más de una identidad’])
% elseif length(pez)==1
% mancha2pez_corr(ind)=pez;
% end
% end % c_trozos

Save the new corrected mancha2pez

% variable.mancha2pez=mancha2pez_corr;
% save([ruta ‘\segm\mancha2pez_corregidomanual_30100frames’],’variable’)


It turns out that fragment 4 was not properly corrected. Also fragments 53 and 54, that are flagged with multiple identities (the rest of fragments with multiple id’s are normal, because they are in the non-corrected region). I re-correct them.

% datosegm2muestravideo_nuevo(datosegm)

Reload mancha2pez_corr

% load([ruta ‘segm\mancha2pez_corregidomanual_30100frames.mat’])
% mancha2pez_corr=variable.mancha2pez;

Autocorrect trozo2pez using the dynamics

% trozo2pez_anul=datosegm2anulainterpolables(datosegm);
% [trozo2pez_autocorr,fijos,cambiados]=buscasaltos(trozos,trozo2pez_anul,probtrozos_relac,mancha2centro,conviven);
% clear variable
% variable.mancha2pez=NaN(size(trozos));
% for c_trozos=1:length(trozo2pez_autocorr);
% variable.mancha2pez(trozos==c_trozos)=trozo2pez_autocorr(c_trozos);
% end
% variable.trozo2pez=trozo2pez_autocorr;
% variable.probtrozos_relac=probtrozos_relac;
% save([ruta ‘segm\mancha2pez_autocorr.mat’],’variable’)

Test autocorrection

compruebacorreccion(mancha2pez,mancha2pez_corr,trozos,trozo2pez_autocorr,[1 30100])

722 frames que tenían error se han corregido. Trozos:
7 8 35 230 246 247 248

438 frames de cruces que estaban asignados ya no lo están. Trozos:
38 53 54

1236 frames que tenían error se han quedado sin identidad. Trozos:
Columns 1 through 13

1 2 36 37 53 54 71 72 102 103 231 233 235

Column 14


7 frames que estaban bien se han jodido. Trozos:

1579 frames que estaban bien se han quedado sin identidad. Trozos:
38 51 53 54 76 77 195 196 258 259 262 263

0 frames que estaban mal siguen mal. Trozos:


% [mancha2pez_interp,mancha2centro_interp]=datosegm2smartinterp(datosegm);
% clear variable
% variable.mancha2pez=mancha2pez_interp;
% variable.mancha2centro=mancha2centro_interp;
% save([ruta ‘segm\mancha2pez.mat’],’variable’)

Test interpolation

compruebacorreccion(mancha2pez,mancha2pez_corr,trozos,trozo2pez_interp,[1 30100])

1071 frames que tenían error se han corregido. Trozos:
Columns 1 through 13

35 36 37 71 72 102 103 230 231 233 236 246 247

Column 14


0 frames de cruces que estaban asignados ya no lo están. Trozos:
883 frames que tenían error se han quedado sin identidad. Trozos:
1 2 7 8 235

0 frames que estaban bien se han jodido. Trozos:
7 frames que estaban bien se han quedado sin identidad. Trozos:

4 frames que estaban mal siguen mal. Trozos:
53 54

Results of validation

datosegm2fig_validacion(ruta,mancha2pez_corr,[1 30100],220,)

Warning: MMREADER will be removed in a future release. Use VIDEOREADER instead.

ans =

1 2 4 7 8 232 235

Proporción de frames correctos: 0.980516
Proporción de trayectorias correctas (en distancia): 0.982829
Tamaño medio: 11091.8

Published with MATLAB® R2013b

February 18, 2014

Pseudobugs y cosas mejorables del tracking

Filed under: Tracking — alperezescudero @ 12:55 pm
  1. El campo indiv no siempre se rellena (parece que queda sin rellenar cuando segmbuena==0, o al menos cuando es porque la mancha es demasiado grande para construir el mapa. Esto pasa por ejemplo en el frame 391 del vídeo de 4 ratones “despeinaos” que grabó Julián). A efectos prácticos, al final queda como si indiv=0, que supongo es lo más razonable. Pero sería mejor introducir una tercera categoría de “no clasificados”.
  2. A pesar de que ya creo la variable trozo2indiv, todavía está usando al final la variable indiv, que va frame a frame. Habría que cambiarlo (lo más fácil sería reconstruir indiv, partiendo de trozo2indiv).
  3. Estaría bien mejorar la manera en la que se toman las referencias de bicho individual, no simplemente tomando frames al azar sino cogiendo grupos de trozos lo más largos posibles.
  4. Una vez mejorada la manera en la que se toman las referencias de bicho individual, estaría bien comparar con ellas todas las manchas, en vez de asumir que cuando hay tantas manchas como bichos todas serán de bicho individual (porque esto es muy poco robusto al ruido).
  5. Estaría bien hacer una segunda pasada por trozo2indiv, comprobando que todo es consistente (por ejemplo, cuando dos trozos individuales convergen en uno, este trozo no es individual).
  6. Habría que hacer una función que lea el vídeo metiendo dentro todas las complicaciones de encontrar el frame, el archivo, y todo eso (algo como datosegm2video). Así además puedo meter en ella el código que se usaría para leer desde fotografías.

February 1, 2014

Tests for a new definition of centroid

Filed under: Tracking — alperezescudero @ 11:11 am

Name of this file: Cuaderno20140131T214034.m


ans =


Collect positions

I input manually the position of the head (I click between the eyes)

% obj=VideoReader(‘D:\Hipertec_pesados\5zebrafish\5Zebrafish_nocover_22min.avi’);
% video=read(obj,[1 100]);
% X=repmat(1:datosegm.tam(2),[datosegm.tam(1) 1]);
% Y=repmat((1:datosegm.tam(1))’,[1 datosegm.tam(2)]);
% pez=1;
% for c=1:100
% hold off
% image(video(:,:,:,c))
% hold on
% plot(trajectories(c,pez,1),trajectories(c,pez,2),’r.’)
% lienzo=false(datosegm.tam);
% lienzo(segm(c).pixels{mancha2pez(c,:)==pez})=true;
% lienzo=bwdist(~lienzo);
% lienzo=lienzo>=max(lienzo(:))-3;
% x(c)=mean(X(lienzo));
% y(c)=mean(Y(lienzo));
% plot(x,y,’b.’)
% axis image
% % axis([trajectories(c,1,1)+[-margenx margenx] trajectories(c,1,2)+[-margeny margeny]])
% axis([x(c)+[-margenx margenx] y(c)+[-margeny margeny]])
% % pause(.1)
% drawnow
% % [cabeza(c,1),cabeza(c,2)]=ginput(1);
% end

Show results

‘Centroid’,‘New centroid’)

old =


new =


Not very systematic, but it seems that the distance to the head is more stable with the new centroid. So I am going to use it, instead of the old one.

Published with MATLAB® R2013b

January 11, 2014

Validation of Ctrax using the 5-zebrafish video

Filed under: Tracking — alperezescudero @ 3:08 pm

Name of this file: Cuaderno20140111T131557.m

After several trials, it seems that the best parameters in Ctrax for zebrafish videos are the following: – Default background parameters – Default background subtraction parameters – Default tracking parameters, except: Use “manually set bounds on shape”, and set all parameters with very extreme values (minimums at 0 and maximums at thousands), so that they have no effect. Except minimum size, that must be set at a reasonable value (100 for the 5-zebrafish video), to prevent the fish to be cut in several pieces when they turn. Then, check “enforce shape bounds”.


ans =


Load results of Ctrax, and build trajectories


Id 28 with 614 frames has been dropped
Id 14 with 188 frames has been dropped

Load results of tracking, and build corrected trajectories


Align both trajectories

This is necessary because the corrected trajectories come from the original video, and the ctrax from the compressed video, and resolution is different. Also, ctrax uses the lower corner as a reference, and matlab uses the upper one.

trajectories_ctrax(:,:,2)=-trajectories_ctrax(:,:,2); % Invert the y axis

m =


m =


m =


m =


m =


Relation between the individuals, frame-by-frame


Assigned 93.3822% of the blobs (67407 out of 72184)

Show results

title(‘Ctrax id”s’)
‘Relation between ctrax and corrected idTracker’)

correctos=sum(relacion==repmat(relacion(1,:),[size(relacion,1) 1]))./sum(~isnan(relacion))

correctos =

0.2206 0.3146 0.1914 0.2328 0.3260

ans =


About 25% correct frames.

Published with MATLAB® R2013b

November 29, 2013

Validation of idTracker in a video of 6 marked mice

Filed under: Tracking — alperezescudero @ 8:16 pm

Name of this file: Cuaderno20131129T175828.m

Alfonso Pérez-Escudero, Adrián Aguirre, Gonzalo G. de Polavieja


ans =


The original video is in uncompressed format. We have compressed it using Aiseesoft MTS converter and msmpeg4 codec, at maximum resolution. With this compression the 10-minutes video of 6 mice weighs about 1.5 GB. We think this is small enough to send the files in the future via FTP, so it is not necessary to test any lower quality compression.

We have extracted the trajectories of the mice using idTracker. Then, we have validated the trajectories manually by reviewing the crossings. We will compare the corrected trajectories with the original output from idTracker.

Results from validation

I measure manually the bodylength. Approx. 65 pixels. Explanation of the figure: (a) Example frame. (b) Histogram of sizes of the individuals. (c) Trajectories (black indicates mistakes). (d) Results of validation: To identify an individual in a given moment of the video, idTracker accumulates information from all the frames between two consecutive crossings of the individual. Therefore, when the animal spends a long time moving without crossing with anybody else, the identification is very reliable. We only find mistakes when an animal has two crossings in a short time. Therefore, to analyze the performance of idTracker we compute the probability of having a mistake, as a function of the distance traveled by the animal between two consecutive crossings. Box (d) shows these probabilities. Green: Probability of correct identification. Red: Probability of wrong identification. Orange: Probability of no identification. For “no identification” we mean that a fragment of trajectory that belongs to one single individual (and therefore should have been identified) could not be identified reliably.

datosegm2fig_validacion(‘D:\Hipertec_pesados\RatonesMarcelo\Comprimido’,mancha2pez_corr,[1 3000],65)

Proporción de frames correctos: 0.987844
Proporción de trayectorias correctas (en distancia): 0.98735
Tamaño medio: 523.081


Other quality indicators

idTracker tries to obtain 3000 reference images for each individual, but this high number is only achieved for long videos (usually the system works very well with fewer reference images). In this case, the software extracted 1105 reference images for each mouse. For a 10-minutes video of 6 individuals, this is an excellent result.


While we still need to analyze more videos to be sure, these results are very promising. Almost 99% of the trajectories have correct identities, with mistakes only in short fragments. This performance is similar to the one we obtain in other species.

November 22, 2013

Mark position of pipettes manually in Julián’s learning data (after re-tracking)

Filed under: Learning, Tracking — alperezescudero @ 10:26 am

Name of this file: Cuaderno20131121T203543.m


ans =

Load data

% load(‘D:\Hipertec_pesados\datoslearning_mar2012_datosesenciales.mat’)

Mark positions

% for c_grupos=1:4
% for c_trials=1:27
% if ~isempty(datos.trial_orden(c_trials,c_grupos).datosegm)
% imagesc(datos.trial_orden(c_trials,c_grupos).datosegm.videomedio)
% axis image
% colormap gray
% title([‘Group ‘ num2str(c_grupos) ‘, trial ‘ num2str(c_trials) ‘. Pipette WITH food’])
% [datos.trial_orden(c_trials,c_grupos).pos_comida(1),datos.trial_orden(c_trials,c_grupos).pos_comida(2)]=ginput(1);
% title(‘Pipette WITHOUT food’)
% [datos.trial_orden(c_trials,c_grupos).pos_nocomida(1),datos.trial_orden(c_trials,c_grupos).pos_nocomida(2)]=ginput(1);
% end
% end
% end

Save data

% save(‘D:\Hipertec_pesados\datoslearning_mar2012_datosesenciales.mat’,’datos’)

November 20, 2013

Compilation of idTracker

Filed under: Tracking — alperezescudero @ 3:36 pm

I compile a version of idTracker. I do it with the Matlab Compiler of Matlab R2012a of the laboratory computer.

Preparation of Robert’s data of territories to share them in the tracking paper

Filed under: Tracking, Tracking - Paper figures — alperezescudero @ 8:38 am

Name of this file: Cuaderno20131120T080542.m

I will remove from Robert’s variable datosrelaciones all the information not needed for the figure.


ans =

Let’s go

save F:\Hipertec\ReconocePeces\nuevos\Pesados\Territories territories

Older Posts »

Blog at


Get every new post delivered to your Inbox.