{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# How To: Choose a Detection Algorithm\n", "\n", "PhenoTypic offers multiple detectors, each suited to different plate\n", "conditions. This guide compares the most commonly used options on the\n", "same plate image so you can pick the right one." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2026-04-21T02:50:30.878450Z", "start_time": "2026-04-21T02:50:30.857262Z" } }, "outputs": [], "source": [ "from phenotypic.data import load_yeast_plate\n", "from phenotypic.enhance import GaussianBlur, CLAHE\n", "from phenotypic.detect import (\n", " OtsuDetector, TriangleDetector, HysteresisDetector,\n", " WatershedDetector, RoundPeaksDetector,\n", ")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2026-04-21T02:50:30.902220Z", "start_time": "2026-04-21T02:50:30.890965Z" } }, "outputs": [], "source": [ "def detect_and_count(detector):\n", " \"\"\"Apply enhancement + detector to a fresh plate, return (result, count).\"\"\"\n", " plate = load_yeast_plate()\n", " plate = GaussianBlur(sigma=2.0).apply(plate)\n", " plate = CLAHE(clip_limit=0.01).apply(plate)\n", " plate = detector.apply(plate)\n", " return plate, plate.num_objects" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## OtsuDetector\n", "\n", "Global threshold, fast. Best for clean plates with uniform illumination\n", "and bimodal histograms." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2026-04-21T02:50:37.442396Z", "start_time": "2026-04-21T02:50:30.904831Z" } }, "outputs": [], "source": [ "result, count = detect_and_count(OtsuDetector())\n", "print(f\"OtsuDetector: {count} colonies\")\n", "result.show(overlay=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## TriangleDetector\n", "\n", "Better than Otsu when one peak dominates — e.g., few colonies on a large\n", "plate." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2026-04-21T02:50:44.568414Z", "start_time": "2026-04-21T02:50:37.449634Z" } }, "outputs": [], "source": [ "result, count = detect_and_count(TriangleDetector())\n", "print(f\"TriangleDetector: {count} colonies\")\n", "result.show(overlay=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## HysteresisDetector\n", "\n", "Uses two thresholds (low and high) to capture colonies with soft edges.\n", "Pixels above `high` are colony; pixels between `low` and `high` are\n", "colony only if connected to a high-confidence pixel." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2026-04-21T02:50:51.136923Z", "start_time": "2026-04-21T02:50:44.573733Z" } }, "outputs": [], "source": [ "result, count = detect_and_count(HysteresisDetector(low=\"mean\", high=\"otsu\"))\n", "print(f\"HysteresisDetector: {count} colonies\")\n", "result.show(overlay=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## WatershedDetector\n", "\n", "Region-growing approach that separates touching colonies. Best for dense\n", "plates where colonies overlap." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2026-04-21T02:50:59.438961Z", "start_time": "2026-04-21T02:50:51.142064Z" } }, "outputs": [], "source": [ "result, count = detect_and_count(WatershedDetector())\n", "print(f\"WatershedDetector: {count} colonies\")\n", "result.show(overlay=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## RoundPeaksDetector\n", "\n", "Peak-finding approach optimized for round colonies in grid plates. Fast\n", "and accurate when colonies are circular and well-spaced." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "ExecuteTime": { "end_time": "2026-04-21T02:51:11.972064Z", "start_time": "2026-04-21T02:50:59.445085Z" } }, "outputs": [], "source": [ "result, count = detect_and_count(RoundPeaksDetector())\n", "print(f\"RoundPeaksDetector: {count} colonies\")\n", "result.show(overlay=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Comparison Summary\n", "\n", "| Detector | Best for | Speed |\n", "|----------|----------|-------|\n", "| `OtsuDetector` | Clean plates, bimodal histograms | Fast |\n", "| `TriangleDetector` | Few colonies on large plates | Fast |\n", "| `HysteresisDetector` | Soft-edged or faint colonies | Fast |\n", "| `WatershedDetector` | Touching/clustered colonies | Moderate |\n", "| `RoundPeaksDetector` | Round colonies in grid plates | Fast |" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.11.0" } }, "nbformat": 4, "nbformat_minor": 4 }