{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Tutorial 9: Diagnosing Image Quality\n", "\n", "Before building a pipeline, it helps to assess the quality of your plate\n", "images. PhenoTypic's diagnostics plotter gives you objective metrics for\n", "noise, contrast, and structure — so you can make informed decisions about\n", "which enhancers and detectors to use.\n", "\n", "**What you will learn:**\n", "\n", "1. Use `image.plot.diagnostics()` to assess plate quality\n", "2. Interpret the noise, contrast, and structure metrics\n", "3. Use quality metrics to guide pipeline design" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Imports" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2026-04-07T22:15:54.073521Z", "start_time": "2026-04-07T22:15:51.280649Z" } }, "outputs": [], "source": [ "from phenotypic.data import load_yeast_plate\n", "import matplotlib.pyplot as plt # diagnostics() returns matplotlib figures" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load the Plate" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2026-04-07T22:15:54.425900Z", "start_time": "2026-04-07T22:15:54.075565Z" } }, "outputs": [], "source": [ "plate = load_yeast_plate()\n", "plate.dash()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Run Diagnostics\n", "\n", "The `.plot.diagnostics()` method produces a multi-panel figure and returns\n", "a dictionary of quantitative metrics. This is one place where matplotlib\n", "output is expected — the diagnostics figure is a static multi-panel layout." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2026-04-07T22:17:36.604879Z", "start_time": "2026-04-07T22:17:09.528358Z" } }, "outputs": [], "source": [ "fig, metrics = plate.plot.diagnostics()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Inspect the Metrics\n", "\n", "The `metrics` dictionary contains objective measurements organized by\n", "category. Let's look at each one." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2026-04-07T22:16:25.010769Z", "start_time": "2026-04-07T22:16:24.989604Z" } }, "outputs": [], "source": [ "print(\"Available metric categories:\")\n", "for category in metrics:\n", " print(f\" {category}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Noise Metrics\n", "\n", "Noise metrics tell you how much random variation exists in the image\n", "background. High noise can confuse detectors." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2026-04-07T22:16:25.063775Z", "start_time": "2026-04-07T22:16:25.025386Z" } }, "outputs": [], "source": [ "if \"noise\" in metrics:\n", " print(\"Noise metrics:\")\n", " for key, val in metrics[\"noise\"].items():\n", " if isinstance(val, (int, float)):\n", " print(f\" {key}: {val:.4f}\")\n", " else:\n", " print(f\" {key}: {val}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- **SNR** (Signal-to-Noise Ratio) — higher is better. Values below 10\n", " suggest the image would benefit from denoising (`StableDenoise` or\n", " `GaussianBlur`).\n", "- **Correlation length** — longer correlation suggests structured noise\n", " (e.g., uneven illumination) rather than random pixel noise." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Contrast Metrics\n", "\n", "Contrast metrics measure how well colonies separate from the agar\n", "background." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2026-04-07T22:16:25.077729Z", "start_time": "2026-04-07T22:16:25.066031Z" } }, "outputs": [], "source": [ "if \"contrast\" in metrics:\n", " print(\"Contrast metrics:\")\n", " for key, val in metrics[\"contrast\"].items():\n", " if isinstance(val, (int, float)):\n", " print(f\" {key}: {val:.4f}\")\n", " else:\n", " print(f\" {key}: {val}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- **RMS contrast** — overall contrast level. Low values mean faint\n", " colonies that may need `CLAHE` to boost local contrast.\n", "- **Michelson contrast** — ratio of (max − min) / (max + min). Values\n", " close to 1.0 indicate strong colony/agar separation.\n", "- **Dynamic range** — fraction of the bit depth in use. Low dynamic\n", " range suggests the image is under-exposed." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Structure Metrics\n", "\n", "Structure metrics assess the spatial organization of the image." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2026-04-07T22:16:25.089070Z", "start_time": "2026-04-07T22:16:25.078594Z" } }, "outputs": [], "source": [ "if \"structure\" in metrics:\n", " print(\"Structure metrics:\")\n", " for key, val in metrics[\"structure\"].items():\n", " if isinstance(val, (int, float)):\n", " print(f\" {key}: {val:.4f}\")\n", " else:\n", " print(f\" {key}: {val}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- **Gradient mean** — average edge strength. Higher values mean sharper\n", " colony boundaries, which makes detection easier.\n", "- **Coherence** — consistency of edge orientation. High coherence on grid\n", " plates suggests well-organized colonies." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Other Plot Methods\n", "\n", "The `.plot` accessor offers additional visualization tools beyond\n", "diagnostics. Here are a few useful ones:\n", "\n", "- **`plate.plot.all()`** — side-by-side view of RGB, grayscale, detect_mat, and masks\n", "- **`plate.plot.size_distribution()`** — histogram of colony sizes (requires detection)\n", "- **`plate.plot.morph_progression()`** — morphological operations at increasing scales\n", "- **`plate.plot.try_thresh()`** — visual comparison of threshold methods" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2026-04-07T22:16:25.094901Z", "start_time": "2026-04-07T22:16:25.090499Z" } }, "outputs": [], "source": [ "plt.close(\"all\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Summary\n", "\n", "You now know how to assess plate image quality before committing to a\n", "pipeline:\n", "\n", "- **`plate.plot.diagnostics()`** — multi-panel figure + metrics dictionary\n", "- **Noise metrics** guide denoising decisions (SNR, correlation length)\n", "- **Contrast metrics** guide enhancement decisions (RMS contrast, dynamic range)\n", "- **Structure metrics** assess colony edge quality (gradient, coherence)\n", "\n", "Use these metrics to choose between enhancers, detectors, and prefab\n", "pipelines — rather than guessing.\n", "\n", "**Next up:** [Tutorial 10: Detecting Filamentous Fungi](10_detecting_filamentous_fungi.ipynb) —\n", "handle branching fungal morphology with PhenoTypic's specialized detector." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.11.0" } }, "nbformat": 4, "nbformat_minor": 4 }