georgeoshardo / SyMBac

Accurate segmentation of bacterial microscope images using deep learning synthetically generated image data.
https://doi.org/10.1186/s12915-022-01453-6
GNU General Public License v2.0
19 stars 9 forks source link

Cell lengths after division #41

Closed kmpape closed 10 months ago

kmpape commented 10 months ago

Hello there!

I am not sure whether this is a question or an issue, but please let me ask anyway. In cell.py, some magic is happening in create_pm_cell. I do have a question on the cell lengths after division:

new_length = self.length/2  - self.width/4 
daughter_length = self.length - new_length  - self.width/4 # = length/2

Let $\ell$ denote the length of the straight part of the cell, and $w$ its width. Then, before division, the cell has total length $L:=\ell +w$ (as noted in cell_geometry.get_vertices() - would be great to have this Def in Cell.__init__ BTW).

After division, the mother cell will have total length $L_m=\ell_m + w$, where $\ell_m:=\ell/2-w/4$, and the daughter cell $L_d=\ell_d+ w$, where $\ell_d=\ell-\ell_m -w/4=\ell-(\ell/2-w/4)-w/4=\ell/2$. But $L_m+L_d=\ell_m+ \ell_d + 2w = \ell/2-w/4+\ell/2+2w>L$.

Why did the cells grow during division? Should that not happen in the function in which you update the lengths?

kmpape commented 10 months ago

Then related, just below, you are computing the new coordinates (I renamed daughter_x and daughter_y):

new_x = self.position[0] + (self.length + self.width/2)/2 * np.cos(self.angle*2)
new_y = self.position[1] + (self.length+ self.width/2)/2 * np.sin(self.angle*2)
daughter_x = self.position[0] - (self.length+ self.width/2)/2 * np.cos(self.angle*2)
daughter_y = self.position[1] - (self.length+ self.width/2)/2 * np.sin(self.angle*2)

How did you end up with these formulae? In particular, why do you do self.angle*d? Because when I look at different timeframes the cells seem to be "jumping" around when they divide. I went through this by hand:

1705424565809 (Sorry just realised that it should say $\Delta x=\frac{L_i}{2}\dots$ and not $\Delta x=\frac{\ell_i}{2}\dots$)

Do you agree with these calculations or am I misinterpretating some variables?

So with my previous post, and assuming that the cells have equal length after division, it should be:

new_length = self.length/2  - self.width/2 
daughter_length = new_length
new_total_length = new_length+w
delta_x = new_total_length/2*np.sin(self.angle)

One could add some randomness here to let the two cells have different lengths, but still so that the lengths add up to the previous length.

kmpape commented 10 months ago

I realised that the angle might be measured from the X axis and not the Y axis as above. However, I am still puzzled by seeing a hard-coded angle of 0.8 rad (45 deg) for cell1 but then seeing it almost vertical in Napari. Can you please explain how you draw the cells? It seems like you are drawing a horizontal tube along the x-axis with semicircle caps on the left and the right, then rotating the whole structure by angle around the cell centroid. Why does it end up vertical? Thanks a lot.

georgeoshardo commented 10 months ago

Hi Idris, thanks for commenting on this. You are right there is some weird stuff happening here. I have updated the code so that the cell length is just the entire length of the cell, which makes things easier to understand now. Indeed then you can just do self.length = self.length/2, and proceed to update the x and y positions as

new_x = self.position[0] + self.length/2 *  np.cos(self.angle)
new_y = self.position[1] + self.length/2 *  np.sin(self.angle)

(I have the xy coordinate system flipped compared to your diagram, and since the new centroid must move 1/4 of the original length)

The reason for the oddity with the angle was due a mistake by me. The cell vertices are first created as pre-rotated points, they were then passed to the physics solver, with the angle supplied a second time, thus doubling the overall rotation.

As I went through cell.py I kept becoming more dissatisfied with it (e.g much of the jumping around in the simulation comes from calling the physics solver at bad times, cells accumulate energy and repulse away from one another), and have just decided to rewrite the entire thing, so I may be a bit delayed in updating this.

georgeoshardo commented 10 months ago

There is an untidy but hopefully working example notebook in https://github.com/georgeoshardo/SyMBac/blob/SyMBac_2/docs/source/examples/testing.ipynb

kmpape commented 10 months ago

Thank you very much for this.