{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Tutorial 1: Your First Plate Image\n", "\n", "Welcome to PhenoTypic! In this tutorial, you will load your first agar plate image,\n", "display it interactively, inspect its basic properties, and explore the **accessor\n", "pattern** that gives you different views of the same plate.\n", "\n", "**What you will learn:**\n", "\n", "1. Load a plate image using `load_yeast_plate()`\n", "2. Display it interactively with `.dash()`\n", "3. Inspect basic properties: `.shape`, `.bit_depth`, `.name`, and `.dtype`\n", "4. Explore the accessor pattern: `.rgb[:]`, `.gray[:]`, `.detect_mat[:]`\n", "5. Understand what each accessor provides and when you would use it" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Imports\n", "\n", "Start by importing PhenoTypic and the sample data loader. The convention is to\n", "import the library as `pht`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from phenotypic.data import load_yeast_plate" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load a Plate Image\n", "\n", "PhenoTypic ships with several sample plate images so you can start experimenting\n", "right away. `load_yeast_plate()` returns a **GridImage** of *Rhodotorula* yeast\n", "colonies arranged in a standard 96-well grid (8 rows by 12 columns).\n", "\n", "A `GridImage` is PhenoTypic's main data structure for arrayed colony plates -- it\n", "behaves like a regular `Image` but also knows about the grid layout of wells." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plate = load_yeast_plate()\n", "print(type(plate))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You now have a `GridImage` object stored in `plate`. Everything you need -- pixel\n", "data, metadata, accessors, and visualization methods -- lives on this single object." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Display the Plate\n", "\n", "The quickest way to see your plate is with `.dash()`. This renders the full-color\n", "image inline. Take a look at the *Rhodotorula* colonies -- you should see a grid of\n", "round, pigmented spots on a light agar background." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plate.dash();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Nice work -- you have just visualized your first plate image!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Inspect Basic Properties\n", "\n", "Before processing a plate, it helps to know what you are working with. Let's\n", "inspect a few key properties.\n", "\n", "- **`.shape`** -- the dimensions of the image array (height, width, channels)\n", "- **`.bit_depth`** -- bits per pixel (8 means values 0--255; 16 means 0--65 535)\n", "- **`.name`** -- a human-readable identifier for the image\n", "- **`.rgb.dtype`** -- the NumPy data type of the underlying pixel array" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"Shape: \", plate.shape)\n", "print(\"Bit depth:\", plate.bit_depth)\n", "print(\"Name: \", plate.name)\n", "print(\"Dtype: \", plate.rgb.dtype)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The shape tells you the image height and width in pixels, plus the number of\n", "color channels (3 for an RGB image). The bit depth and dtype confirm the\n", "precision of the pixel values. These properties are useful for sanity-checking\n", "your data before you feed it into a processing pipeline." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## The Accessor Pattern\n", "\n", "PhenoTypic uses an **accessor pattern** to give you different representations of\n", "the same plate image. Instead of calling separate functions, you access views\n", "through dot-notation attributes on the image object.\n", "\n", "The three primary accessors are:\n", "\n", "| Accessor | What it provides | Typical use |\n", "|---|---|---|\n", "| `.rgb` | Full-color pixel data | Visualization, color analysis |\n", "| `.gray` | Luminance-weighted grayscale | Intensity-based measurements |\n", "| `.detect_mat` | Detection matrix (enhanced grayscale) | Colony detection and segmentation |\n", "\n", "Each accessor supports NumPy-style slicing with `[:]` to retrieve the underlying\n", "array, and has its own `.dash()` method for quick visualization. Let's explore\n", "each one." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### RGB Accessor\n", "\n", "The `.rgb` accessor holds the full-color image data. Use `.rgb[:]` to get the\n", "raw NumPy array (shape: height x width x 3), or `.rgb.dash()` to display it.\n", "This is the same view you saw with `plate.dash()` earlier." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "rgb_array = plate.rgb[:]\n", "print(\"RGB array shape:\", rgb_array.shape)\n", "print(\"RGB array dtype:\", rgb_array.dtype)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plate.rgb.dash();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Grayscale Accessor\n", "\n", "The `.gray` accessor provides a luminance-weighted grayscale version of the\n", "plate. The conversion uses perceptual weights so bright colonies appear bright\n", "and dark agar appears dark, matching what your eye expects.\n", "\n", "The array has shape (height, width) -- a single channel -- with `float32` values." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "gray_array = plate.gray[:]\n", "print(\"Grayscale array shape:\", gray_array.shape)\n", "print(\"Grayscale array dtype:\", gray_array.dtype)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plate.gray.dash();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Detection Matrix Accessor\n", "\n", "The `.detect_mat` accessor is where the magic happens. The detection matrix is\n", "the grayscale representation that PhenoTypic's **detectors** actually work on.\n", "When you apply **enhancers** to a plate image, they modify the detection matrix\n", "while leaving the RGB and grayscale data untouched.\n", "\n", "This separation is a key design decision: you can aggressively preprocess the\n", "detection matrix to improve colony segmentation without corrupting the original\n", "color data that you need for accurate measurements later.\n", "\n", "Right now, before any enhancers have run, the detection matrix looks identical\n", "to the grayscale image." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "detect_array = plate.detect_mat[:]\n", "print(\"Detection matrix shape:\", detect_array.shape)\n", "print(\"Detection matrix dtype:\", detect_array.dtype)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "plate.detect_mat.dash();" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Right now it looks just like the grayscale view -- and that is expected. Once\n", "you start applying enhancers (contrast stretching, background subtraction, etc.),\n", "the detection matrix will diverge from the raw grayscale, making colonies easier\n", "for detectors to find." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Summary\n", "\n", "Congratulations -- you have loaded your first plate image, explored its\n", "properties, and seen the three key image representations that PhenoTypic\n", "provides:\n", "\n", "- **`.rgb`** -- full-color pixel data for visualization and color analysis\n", "- **`.gray`** -- luminance-weighted grayscale for intensity work\n", "- **`.detect_mat`** -- the detection matrix that enhancers modify and detectors consume\n", "\n", "You now have a solid foundation for working with plate images in PhenoTypic.\n", "\n", "**Next up:** In [Tutorial 2: Detecting Colonies](02_detecting_colonies.ipynb),\n", "you will use this plate to detect and segment individual colonies." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "name": "python", "version": "3.12.0" } }, "nbformat": 4, "nbformat_minor": 4 }