From 340f20ab54b94f6ba32ffad2830c23be4d0ad917 Mon Sep 17 00:00:00 2001 From: aliceeeeeeeeee Date: Sun, 12 Apr 2026 21:58:16 +0200 Subject: [PATCH] adjust numbering of notebooks for protocol --- .../deformation_analysis_notebook.ipynb | 35 ++++- ...tial_features_morphometrics_notebook.ipynb | 147 +++++++++++++----- 2 files changed, 140 insertions(+), 42 deletions(-) diff --git a/src/tapenade/notebooks/deformation_analysis_notebook.ipynb b/src/tapenade/notebooks/deformation_analysis_notebook.ipynb index c1d8a25..2a55828 100644 --- a/src/tapenade/notebooks/deformation_analysis_notebook.ipynb +++ b/src/tapenade/notebooks/deformation_analysis_notebook.ipynb @@ -68,7 +68,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Load your data. If you do not have a mask, we recommend checking the `preprocessing` notebook to create one. If you don't have labels, you can use the `segmentation` notebook to create nuclei labels using StarDist3D." + "i. Load the example data" ] }, { @@ -87,6 +87,29 @@ "scale = 1/pixelsize" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "ii. Or load your data. If you do not have a mask, we recommend checking the `preprocessing` notebook to create one. If you don't have labels, you can use the `segmentation` notebook to create nuclei labels using StarDist3D." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "path_to_data = ...\n", + "\n", + "data = tifffile.imread(path_to_data / '...')\n", + "mask = tifffile.imread(path_to_data / '...')\n", + "labels = tifffile.imread(path_to_data / '...')\n", + "\n", + "pixelsize = np.array([...]) # pixelsize in um/pixel\n", + "scale = 1/pixelsize" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -144,7 +167,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Specify a scale of analysis `sigma`, which correspond to the standard deviation of the Gaussian kernel used to average the tensors.\n", + "i. Specify a scale of analysis `sigma`, which correspond to the standard deviation of the Gaussian kernel used to average the tensors.\n", "\n", "Smooth the sparse tensors signals to obtain the average tensors, defined at each centroid:" ] @@ -176,7 +199,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The function `masked_gaussian_smooth_sparse` allows you to obtain a smoothed results defined at new sparse positions, e.g on a regular grid. \n", + "ii. The function `masked_gaussian_smooth_sparse` allows you to obtain a smoothed result defined at new sparse positions, e.g on a regular grid. \n", "\n", "Here we illustrate how to compute the averaged tensors on a regular grid of step 20 pixels:" ] @@ -217,7 +240,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We recompute new average volumes at the grid positions too:" + "iii. We recompute new average volumes at the grid positions too:" ] }, { @@ -250,7 +273,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "To quantify deformation and alignment, we extract the objects' principal length from the inertia tensors, and the main eigenvalue of the true strain tensors by diagonalizing the tensors.\n", + "i. To quantify deformation and alignment, we extract the objects' principal length from the inertia tensors, and the main eigenvalue of the true strain tensors by diagonalizing the tensors.\n", "\n", "Note that we extract the principal lengths only as a pedagogical example, as we have discussed at the beginning of the notebook that the principal lengths are not suited for quantifying collective alignment." ] @@ -276,7 +299,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Vectors are formatted in an array `V` of shape `(n_objects, 2, dim_vector)`, where `V[i,0]` corresponds to the position at which the vector is defined, and `V[i,1]` corresponds to the vector itself.\n", + "ii. Vectors are formatted in an array `V` of shape `(n_objects, 2, dim_vector)`, where `V[i,0]` corresponds to the position at which the vector is defined, and `V[i,1]` corresponds to the vector itself.\n", "\n", "The angles returned are the angles between the main eigenvector and the X axis." ] diff --git a/src/tapenade/notebooks/spatial_features_morphometrics_notebook.ipynb b/src/tapenade/notebooks/spatial_features_morphometrics_notebook.ipynb index 190238d..545c644 100644 --- a/src/tapenade/notebooks/spatial_features_morphometrics_notebook.ipynb +++ b/src/tapenade/notebooks/spatial_features_morphometrics_notebook.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Spatial features analysis: morphometrics measurements\n" + "# Spatial features analysis: morphometrics measurements\n" ] }, { @@ -103,14 +103,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 0. Loading the data and choosing parameters (mandatory before computing any feature)" + "## 1. Loading the data and choosing parameters (mandatory before computing any feature)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Load example data" + "i. Load example data" ] }, { @@ -130,7 +130,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Load your data.\n", + "ii. Load your data.\n", "\n", "- For simpler interpretation of 3D fields, your mask and labels should have an isotropic pixel size, for example [1,1,1] µm/pix (ZYX)\n", "- Please input 3D data with only one channel" @@ -144,16 +144,16 @@ "source": [ "path_to_data = ...\n", "\n", - "data = tifffile.imread(Path(path_to_data) / \"...tif\")\n", - "mask = tifffile.imread(Path(path_to_data) / \"...tif\")\n", - "labels = tifffile.imread(Path(path_to_data) / \"...tif\")" + "data = tifffile.imread(Path(path_to_data) / \"...\")\n", + "mask = tifffile.imread(Path(path_to_data) / \"...\")\n", + "labels = tifffile.imread(Path(path_to_data) / \"...\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Parameters" + "iii. Choose smoothing parameter" ] }, { @@ -162,7 +162,6 @@ "metadata": {}, "outputs": [], "source": [ - "# smoothing parameter\n", "sigma=20" ] }, @@ -170,7 +169,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Adjust labels" + "iv. Adjust labels and check shapes" ] }, { @@ -192,7 +191,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Visualized image, mask and segmentation" + "v. Visualize image, mask and segmentation" ] }, { @@ -210,7 +209,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 1. Field of gene expression" + "## 2. Field of gene expression" ] }, { @@ -220,13 +219,19 @@ "Images of gene expression markers need to be normalized in 3D to remove intensity gradients linked with optical artifacts, see preprocessing_notebook.ipynb" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "i. Sanity checks on image dimensions and NaN values" + ] + }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "# 1) Sanity checks on image dimensions\n", "check(data.shape).equals(labels.shape).or_raise(\n", " Exception,\n", " f\"The shape of the selected data {data.shape} does not match the shape of the labels {labels.shape}. \\n\",\n", @@ -236,16 +241,28 @@ " f\"The shape of the selected data {data.shape} does not match the shape of the mask {mask.shape}. \\n\",\n", ")\n", "\n", - "# 2) Check for NaN values in the data\n", "if np.isnan(data).any():\n", " data[mask == 0] = 0\n", "\n", "check(np.isnan(data).any()).equals(False).or_raise(\n", " Exception,\n", " \"The image contains NaN values. \\n\",\n", - ")\n", - "\n", - "# 3) Compute the genetic field\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "ii. Compute the genetic field" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ "genetic_field_cellular = process_genetic_field_cellular(\n", "labels,\n", "data\n", @@ -259,7 +276,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Visualize results" + "iii. Napari visualization" ] }, { @@ -278,9 +295,16 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 2. Spatial position in the tissue\n", + "## 3. Spatial position in the tissue\n", "\n", - "distance to border (radial) or distance along longest axis = AP distance for gastruloids (axial)" + "distance to border (radial) or distance along longest axis = AP distance for gastruloids (axial). Designed to be correlated with other maps in the plugin napari-spatial-correlation-plotter" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "i. Compute cellular maps and smooth them with a gaussian blur\n" ] }, { @@ -304,6 +328,13 @@ ")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "ii. Napari visualization" + ] + }, { "cell_type": "code", "execution_count": null, @@ -322,14 +353,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 3. Cell density, cell density gradient magnitude and direction" + "## 4. Cell density, cell density gradient magnitude and direction" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Compute grid to plot cell density gradient" + "i. Compute grid to plot cell density gradient" ] }, { @@ -368,7 +399,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Compute cell density map and gradient" + "ii. Compute cell density map and gradient" ] }, { @@ -420,26 +451,26 @@ "metadata": {}, "outputs": [], "source": [ - "centroids = np.array([prop.centroid for prop in props])\n", "density = process_cell_density_sigma(props,mask,sigma)\n", "gradient_field, gradient_magnitude_field,napari_gradient_on_grid, density_gradient_angles = process_density_gradient(\n", " mask,\n", " density,\n", " positions_on_grid,\n", " )\n", + "\n", + "#normalization of density gradient\n", "lengths = np.linalg.norm(napari_gradient_on_grid[:, 1], axis=1)\n", "napari_gradient_on_grid[:, 1] = (\n", " napari_gradient_on_grid[:, 1] / np.median(lengths[:, None]) * 5 #*5 is just for visualization purposes\n", ")\n", - "napari_gradient_on_grid_proj = napari_gradient_on_grid[:, :, 1:]\n", - "cmap_vectors_gradient = get_napari_angles_cmap()" + "napari_gradient_on_grid_proj = napari_gradient_on_grid[:, :, 1:]\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Visualize cell density maps" + "iii. Visualize cell density maps" ] }, { @@ -458,7 +489,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Visualize cell density gradient" + "iv. Visualize cell density gradient" ] }, { @@ -467,6 +498,8 @@ "metadata": {}, "outputs": [], "source": [ + "cmap_vectors_gradient = get_napari_angles_cmap()\n", + "\n", "viewer = napari.Viewer()\n", "viewer.add_vectors(\n", " napari_gradient_on_grid,\n", @@ -497,7 +530,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 4. Volume fraction and nuclear volume" + "## 5. Volume fraction and nuclear volume" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "i. Compute volume fraction (space occupied by the nuclei in the mask) as a coarse-grained field, and nuclear volume" ] }, { @@ -518,6 +558,13 @@ ")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "ii. Napari visualization" + ] + }, { "cell_type": "code", "execution_count": null, @@ -535,7 +582,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 5. Nematic order" + "## 6. Nematic order" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "i. Compute orientational order of the nuclei at a local scale." ] }, { @@ -551,6 +605,13 @@ ")" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "ii. Napari visualization" + ] + }, { "cell_type": "code", "execution_count": null, @@ -566,16 +627,16 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 6. Nuclei ellipsoidal coefficients, oblate or prolate scores" + "## 7. Nuclei ellipsoidal coefficients, oblate or prolate scores" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Two ways of computing it :\n", - "- with two different scores, one oblate, one prolate (>0)\n", - "- with a unique score between -inf and +inf" + "i. Two ways of computing it :\n", + "- with two different scores, one for oblate, one for prolate (>0)\n", + "- with a unique score between -inf and +inf, 0 being spherical or both oblate and prolate" ] }, { @@ -596,7 +657,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Compute min and max values for visualization" + "ii. Compute min and max values for visualization" ] }, { @@ -626,7 +687,14 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## 7. Nuclei elongation" + "## 8. Nuclei elongation" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "i. Compute true strain maximum eigenvalue to characterize nuclei elongation" ] }, { @@ -642,6 +710,13 @@ " true_strain_maxeig_cellular, props, mask, sigma)\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "ii. Napari visualization" + ] + }, { "cell_type": "code", "execution_count": null,