Monday, November 16, 2020

Texture analysis by DiRDiP

Imagine you have a set of points evolving in time. It can be the center of colloidal particles in a suspension, of cell nuclei in a tissue, of bubbles in a foam, of people in a crowd. You also have a way of defining which point is bonded to which one. Two people are bonded if they hold hands. Two nuclei are bonded if their respective cell membranes touch. Two bubbles are bonded if they share a soap film. Two colloidal particles are bonded if they are within a certain distance from each other.

And now you make this dynamical, with people moving and handshaking around, bubbles deforming to flow through a funnel, colloidal suspension beeing sheared, tissue trying to fix the scar of a scalpel cut. Your points are moving and your bonds can stretch, rotate, break or be born.

A set of 9 positions with bonds between them, evolving in time. The positions can move, the bonds can appear (green) or disappear (red).

How would you characterize this mess? How to make statistically significant observations of such an ensemble of discreet events? How to deduce anything about the response properties of your system? 

One way is to translate the original discreet description of the evolution of the system (discreet points moving and discreet bonds deforming, appearing or disappearing) into a continuous description in terms of strain field. Even better, in terms of strain fields: the reversible part of the strain that correspond to the bonds that deform without breaking on one hand, and on the other hand the irreversible part of the strain that corresponds to the bonds that appear or disappear.

I've just released a piece of code that does just that.

It's based on a great method published by François Graner and Benjamin Dollet in 2008 that allow to go from the set of point to the mechanical properties of the system. This paper is great, pedestrian and extremely clear on every detail. I really recommend the read if you know a bit about strain tensors and continuous mechanics.

Unfortunately, the original implementation of this analysis in Delphi was lost and later implementations in Matlab were never brought to releasable form. That is why I reimplemented everything in Python - I hope in a clean enough way - so that others will be tempted to use this method. 

This new implementation relies only on Numpy and Numba for optimized calculations, and on Matplotlib to display the results. 
 
I've cooked up examples to show how to use Trackpy results stored in Pandas dataframes as positions and how scipy.spatial can be used to define bonds.
 
Following the title of the original paper, the code is named DiRDiP, for Discrete Rearranging Disordered Patterns.
 
The code can be cited using the DOI provided by Zenodo: 
Mathieu Leocmach, DiRDiP, https://doi.org/10.5281/zenodo.4276047 (2020)


What the code takes as input

  • Two arrays of coordinates at two different times. The dimensionality is arbitray, but for most applications 2D and 3D will be enough.
  • Two sets of bonds, each linking positions at one of the two times.
  • A grid on which to compute the continuous description. I've implemented the rectilinear grid in any dimension, the regular grid in any dimension, and the polar grid in 2D. Implementing other grids (spherical, cylindrical, etc) would be rather easy.

What the code outputs

Arrays of matrices, one matrix per grid element. Exemple of matrices (as defined in the paper):
  • statistical velocity gradient
  • statistical rotation rate
  • statistical topological rearrangement rate

There is a submodule dedicated to displaying such arrays of matrices in Matplotlib.

What the code does not do

  • Localize interesting points and link their positions in time. Use Trackpy for that, or what fits to your problem.
  • Decide which points are linked together. This dependes so much on the physics or biology of your system. Some possible geometrical criteria are implemented in scipy.spatial, like Voronoi neighbourhood, k-nearest neighbours, distance criterion, etc.
  • Decide how to average the results to obtain statistical significance. But you know, averaging numpy arrays is pretty easy. For example, if you have a seady state, you may want to average in time the arrays resulting from two successive time steps. If you have a spatial symmetry or invariance in your system, you may want to exploit it.

What I am proud of

  • Unit tests
  • Documentation of each function
  • Some examples

What it still lack to be perfect

  • A tutorial
  • A generated documentation 
  • More users

Saturday, March 14, 2020

Tracking contacts

Recently, I am trying to figure out how to detect topological changes in a gel network as it breaks. In other words, I am tracking contacts as a network is loosing its connectivity.

As the schools and universities are closing, as I am myself practicing social distancing, the irony is not lost on me.

My immediate and regular contacts are my wife and children, my parents and family living in the same city, my colleagues, the members of my akido club, the parents I meet at the bus stop, friends I see for games, and more distantly the people on the market, at the canteen and in public transportation.

This last one is limited to a minimum since I am mostly commuting by bicycle. I won't meet other parents now that schools are closed. Social distancing means for me: not going to aikido (the club will close anyway), moving games online, not meeting my parents and family in person. I will also work from home as much as possible, including avoiding the canteen. The two PhD students I advise are warned and we have ways to communicate online.

We'll get through this responsibly, limiting damage to public health and our research. That said, I'll go back to my network analysis on Monday, with 3 kids at home.

Wednesday, January 29, 2020

TexMaker and input method

I write in LaTeX very often, either online via Overleaf, of locally on Texmaker.

Recently, I have to write a report in French, so I need to type accented characters, including "ê". On a french keyboard, one has to type the "dead key" "^" and then the key for "e". But when I did so in Texmaker, I only got the "e", not "ê", as if I did not push on the dead key "^". It was pretty general, since I could not even get the accent alone like in "\^{e}" or on any other letter â, û, î, ô, etc. Since everything was working fine on all other applications, it must be a Texmaker problem.

To make a long story, full of googling and forum and tials and errors, short, I discovered that is was a conflict between Qt (the graphical layer powering the interface of Texmaker) and ibus, the input method switcher I was using to write either in French or in Japanese.

The workaround I found was to install another input method switcher: fcitx.

Now I confess, this blog post is more a note for me to remember the procedure. But it may help others.

So, things are explained on this page.
  1. One need to have fcitx and fcitx-mozc installed
  2. Type in the terminal im-config and select fcitx, validate
  3. reboot (closing the session is not sufficient)
  4. A keyboard icon shows up (on top bar for me). Right click, configure. Ask for your default keyboard (French for me). Validate and close.
  5. Right click again on the keyboard icon, configure. Now you have access to all input methods, including mozc. Add mozc. 
  6. Selecting mosc on the list, click on the bottom icon showing some tools. In the menu, select the layout of your physical keyboard (French AZERTY for me). Validate and close.
Now, I might be a bit optimistic in this procedure because I actually tried much more things. Maybe between step 2 is actually more complex:
  1. Disable ibus for Gnome
    sudo dpkg-divert --package im-config --rename /usr/bin/ibus-daemon
  2. Reboot
  3. Type in the terminal im-config and select fcitx, validate
  4. Reboot
  5. (maybe) Enable back ibus for Gnome
    sudo dpkg-divert --package im-config --rename --remove /usr/bin/ibus-daemon
  6. Reboot