Tutorial 9: Diagnosing Image Quality#

Before building a pipeline, it helps to assess the quality of your plate images. PhenoTypic’s diagnostics plotter gives you objective metrics for noise, contrast, and structure — so you can make informed decisions about which enhancers and detectors to use.

What you will learn:

  1. Use PlotDiagnostics().inspect(image) to assess plate quality

  2. Interpret the noise, contrast, and structure metrics

  3. Use quality metrics to guide pipeline design

Imports#

[1]:
from phenotypic.data import load_yeast_plate
from phenotypic.plotting import PlotDetectModes, PlotDiagnostics
from phenotypic.util import ImageMetricsCalculator

Load the Plate#

[2]:
plate = load_yeast_plate()
plate.dash()

Run Diagnostics#

PlotDiagnostics.inspect() produces the primary interactive diagnostic figure. PlotDiagnostics.report() exposes the complete multi-panel report. The renderer-neutral plotting class can also be placed in a pipeline’s plots list for automatic deliverable generation.

[3]:
diagnostics = PlotDiagnostics()
fig = diagnostics.inspect(plate)
fig

Inspect the Metrics#

The metrics dictionary contains objective measurements organized by category. Let’s look at each one.

[4]:
calculator = ImageMetricsCalculator(plate.detect_mat[:])
metrics = {
    "noise": calculator.compute_noise_metrics(),
    "contrast": calculator.compute_contrast_metrics(),
    "structure": calculator.compute_structure_metrics(),
    "background": calculator.compute_background_metrics(),
}
print("Available metric categories:")
for category in metrics:
    print(f"  {category}")
Available metric categories:
  noise
  contrast
  structure
  background

Noise Metrics#

Noise metrics tell you how much random variation exists in the image background. High noise can confuse detectors.

[5]:
if "noise" in metrics:
    print("Noise metrics:")
    for key, val in metrics["noise"].items():
        if isinstance(val, (int, float)):
            print(f"  {key}: {val:.4f}")
        else:
            print(f"  {key}: {val}")
Noise metrics:
  snr: 16.8730
  sigma_mad: 0.0197
  correlation_length: 49.5000
  • SNR (Signal-to-Noise Ratio) — higher is better. Values below 10 suggest the image would benefit from denoising (StableDenoise or BlurGauss).

  • Correlation length — longer correlation suggests structured noise (e.g., uneven illumination) rather than random pixel noise.

Contrast Metrics#

Contrast metrics measure how well colonies separate from the agar background.

[6]:
if "contrast" in metrics:
    print("Contrast metrics:")
    for key, val in metrics["contrast"].items():
        if isinstance(val, (int, float)):
            print(f"  {key}: {val:.4f}")
        else:
            print(f"  {key}: {val}")
Contrast metrics:
  rms_contrast: 0.2567
  michelson: 0.4287
  dynamic_range: 0.0022
  p1: 0.2520
  p99: 0.6302
  • RMS contrast — overall contrast level. Low values mean faint colonies that may need CLAHE to boost local contrast.

  • Michelson contrast — ratio of (max − min) / (max + min). Values close to 1.0 indicate strong colony/agar separation.

  • Dynamic range — fraction of the bit depth in use. Low dynamic range suggests the image is under-exposed.

Structure Metrics#

Structure metrics assess the spatial organization of the image.

[7]:
if "structure" in metrics:
    print("Structure metrics:")
    for key, val in metrics["structure"].items():
        if isinstance(val, (int, float)):
            print(f"  {key}: {val:.4f}")
        else:
            print(f"  {key}: {val}")
Structure metrics:
  mean_coherence: 0.2913
  optimal_scale: 1.0000
  peak_response: 0.0756
  ridge_responses: [0.05793954597949425, 0.07563562746120774, 0.06950455411210275, 0.04796233905052049, 0.03477529585227895, 0.03136497347531455, 0.02972701492659689]
  scales: [0.5, 1.0, 1.5, 2.0, 3.0, 4.0, 5.0]
  ridge_method: meijering
  coherence_map: [[0.30129697 0.35774835 0.62534346 ... 0.60473526 0.3205913  0.24605078]
 [0.34643763 0.14685315 0.40441505 ... 0.37776795 0.11252798 0.32824772]
 [0.61999008 0.4066581  0.03833586 ... 0.03583923 0.40475403 0.61312193]
 ...
 [0.62721908 0.41264877 0.06658758 ... 0.06684921 0.38551051 0.6014753 ]
 [0.35916547 0.15713014 0.40117746 ... 0.41998697 0.13833183 0.31771743]
 [0.28342575 0.3452808  0.62016865 ... 0.63017814 0.35193825 0.2623285 ]]
  • Gradient mean — average edge strength. Higher values mean sharper colony boundaries, which makes detection easier.

  • Coherence — consistency of edge orientation. High coherence on grid plates suggests well-organized colonies.

Other Plot Methods#

The standalone plotting API also supports full reports and detection-mode comparisons without adding an accessor to Image:

  • ``diagnostics.report(plate)`` — complete interactive diagnostic report

  • ``PlotDetectModes().inspect(plate)`` — comparison of registered detection modes

  • ``plate.show(overlay=True)`` — static image and object overlay

  • ``plate.dash(overlay=True)`` — interactive image and object overlay

[8]:
detect_modes = PlotDetectModes()
# mode_comparison = detect_modes.inspect(plate)  # Runs every registered mode.

Summary#

You now know how to assess plate image quality before committing to a pipeline:

  • ``PlotDiagnostics().inspect(plate)`` — primary diagnostic figure

  • Noise metrics guide denoising decisions (SNR, correlation length)

  • Contrast metrics guide enhancement decisions (RMS contrast, dynamic range)

  • Structure metrics assess colony edge quality (gradient, coherence)

Use these metrics to choose between enhancers, detectors, and prefab pipelines — rather than guessing.

Next up: Tutorial 10: Detecting Filamentous Fungi — handle branching fungal morphology with PhenoTypic’s specialized detector.