phenotypic.measure#

Feature extraction from detected fungal colonies.

Computes per-colony and grid-level metrics describing growth, morphology, and appearance on agar plates. Measurements span bounds, size/integrated intensity, shape descriptors, texture, color, and grid-level statistics such as spatial spread and linear gradients. Results are returned as pandas DataFrames ready for analysis.

class phenotypic.measure.MeasureBounds(*args, **kwargs)[source]#

Bases: MeasureFeatures

Extract bounding box coordinates and centroids of detected colonies.

Compute the axis-aligned bounding box and centroid (geometric and intensity-weighted) for each detected colony. These spatial measurements form the foundation for region-of-interest extraction, grid alignment assessment, and neighbor-distance calculations.

Returns:

pd.DataFrame: Object-level spatial data with columns:

  • Label: unique object identifier.

  • CenterRR, CenterCC: geometric centroid coordinates.

  • IntensityWeightedCenterRR, IntensityWeightedCenterCC: intensity-weighted centroid coordinates (skimage centroid_weighted).

  • DistWeightedCenterRR, DistWeightedCenterCC: row/column of the per-object distance-transform maximum (deepest interior point — robust to thin filamentous extensions).

  • MinRR, MinCC: top-left corner of bounding box.

  • MaxRR, MaxCC: bottom-right corner of bounding box.

Best For:
  • Computing centroids for aligning colonies to expected grid positions in arrayed assays.

  • Extracting region-of-interest crops for downstream intensity, color, or texture analysis.

  • Assessing colony positioning relative to plate edges or well boundaries.

Consider Also:
See Also:

Tutorial 7: Measuring and Exporting for a walkthrough of measuring and exporting colony data.

Category: BBOX#

Name

Description

CenterRR

The row coordinate of the center of the bounding box.

MinRR

The smallest row coordinate of the bounding box.

MaxRR

The largest row coordinate of the bounding box.

CenterCC

The column coordinate of the center of the bounding box.

MinCC

The smallest column coordinate of the bounding box.

MaxCC

The largest column coordinate of the bounding box.

IntensityWeightedCenterRR

The intensity-weighted center row coordinate of the object (skimage centroid_weighted).

IntensityWeightedCenterCC

The intensity-weighted center column coordinate of the object (skimage centroid_weighted).

DistWeightedCenterRR

Row coordinate of the per-object Euclidean-distance-transform maximum (deepest interior point of the object mask). Robust to thin filamentous extensions that pull intensity-weighted centroids off-body.

DistWeightedCenterCC

Column coordinate of the per-object Euclidean-distance-transform maximum (deepest interior point of the object mask). Robust to thin filamentous extensions that pull intensity-weighted centroids off-body.

__del__()#

Automatically stop tracemalloc when the object is deleted.

measure(image, include_meta=False)#

Execute the measurement operation on a detected-object image.

This is the main public API method for extracting measurements. It handles: input validation, parameter extraction via introspection, calling the subclass-specific _operate() method, optional metadata merging, and exception handling.

How it works (for users):

  1. Pass your processed Image (with detected objects) to measure()

  2. The method calls your subclass’s _operate() implementation

  3. Results are validated and returned as a pandas DataFrame

  4. If include_meta=True, image metadata (filename, grid info) is merged in

How it works (for developers):

When you subclass MeasureFeatures, you only implement _operate(). This measure() method automatically:

  • Extracts __init__ parameters from your instance (introspection)

  • Passes matched parameters to _operate() as keyword arguments

  • Validates the Image has detected objects (objmap)

  • Wraps exceptions in OperationFailedError with context

  • Merges grid/object metadata if requested

Parameters:
  • image (Image) – A PhenoTypic Image object with detected objects (must have non-empty objmap from a prior detection operation).

  • include_meta (bool, optional) – If True, merge image metadata columns (filename, grid position, etc.) into the results DataFrame. Defaults to False.

Returns:

Measurement results with structure:

  • First column: OBJECT.LABEL (integer IDs from image.objmap[:])

  • Remaining columns: Measurement values (float, int, or string)

  • One row per detected object

If include_meta=True, additional metadata columns are prepended before OBJECT.LABEL (e.g., Filename, GridRow, GridCol).

Return type:

pd.DataFrame

Raises:

OperationFailedError – If _operate() raises any exception, it is caught and re-raised as OperationFailedError with details including the original exception type, message, image name, and operation class. This provides consistent error handling across all measurers.

Notes

  • This method is the main entry point; do not override in subclasses

  • Subclasses implement _operate() only, not this method

  • Automatic memory profiling is available via logging configuration

  • Image must have detected objects (image.objmap should be non-empty)

Examples

Basic measurement extraction:

>>> from phenotypic import Image
>>> from phenotypic.measure import MeasureSize
>>> from phenotypic.detect import OtsuDetector
>>> # Load and detect
>>> image = Image('plate.jpg')
>>> image = OtsuDetector().operate(image)
>>> # Extract measurements
>>> measurer = MeasureSize()
>>> df = measurer.measure(image)
>>> print(df.head())

Include metadata in measurements:

>>> # With image metadata (filename, grid info)
>>> df_with_meta = measurer.measure(image, include_meta=True)
>>> print(df_with_meta.columns)
# Output: ['Filename', 'GridRow', 'GridCol', 'OBJECT.LABEL',
#          'Area', 'IntegratedIntensity', ...]
class phenotypic.measure.MeasureColor(white_chroma_max: float = 4.0, chroma_min: float = 8.0, include_XYZ: bool = False)[source]#

Bases: MeasureFeatures

Measure colony color statistics across multiple perceptual color spaces.

Extract per-colony color features from CIE XYZ, chromaticity (xy), CIE Lab (perceptually uniform), and HSV color spaces. For each channel the standard statistical suite is computed (min, Q1, mean, median, Q3, max, std dev, coefficient of variation), plus Lab chroma estimates.

Args:
white_chroma_max: Lab chroma threshold below which a colony is

classified as achromatic (white). Default: 4.0.

chroma_min: Minimum chroma value retained in analysis; colonies

below this are treated as colorless. Default: 8.0.

include_XYZ: Compute CIE XYZ tristimulus statistics (slower).

Default: False.

Returns:

pd.DataFrame: Object-level color statistics with column groups:

  • ColorXYZ (X, Y, Z) – only when include_XYZ=True.

  • Colorxy (x, y chromaticity).

  • ColorLab (L*, a*, b*, ChromaEstimated).

  • ColorHSV (Hue, Saturation, Brightness).

  • Each channel has Min, Q1, Mean, Median, Q3, Max, StdDev, CoeffVar sub-columns.

Best For:
  • Distinguishing pigmented colonies (carotenoid, melanin) from colorless ones to stratify phenotypes by pigmentation profile.

  • Detecting sectoring and growth heterogeneity via high within-colony color variance.

  • Cross-plate comparison of colony pigmentation using perceptually uniform Lab distances.

Consider Also:
  • MeasureIntensity for grayscale-only brightness and variability statistics.

  • MeasureColorComposition for proportion-based color classification of colony pixels.

  • MeasureTexture for surface-roughness features that complement color metrics.

See Also:

Tutorial 7: Measuring and Exporting for a walkthrough of measuring and exporting colony data. Measurement Metrics and Their Biological Meaning for interpreting color metrics in a biological context.

Category: ColorXYZ#

Name

Description

CieXMin

The minimum X value of the object in CIE XYZ color space

CieXQ1

The lower quartile (Q1) X value of the object in CIE XYZ color space

CieXMean

The mean X value of the object in CIE XYZ color space

CieXMedian

The median X value of the object in CIE XYZ color space

CieXQ3

The upper quartile (Q3) X value of the object in CIE XYZ color space

CieXMax

The maximum X value of the object in CIE XYZ color space

CieXStdDev

The standard deviation of the X value of the object in CIE XYZ color space

CieXCoeffVar

The coefficient of variation of the X value of the object in CIE XYZ color space

CieYMin

The minimum Y value of the object in CIE XYZ color space

CieYQ1

The lower quartile (Q1) Y value of the object in CIE XYZ color space

CieYMean

The mean Y value of the object in CIE XYZ color space

CieYMedian

The median Y value of the object in CIE XYZ color space

CieYQ3

The upper quartile (Q3) Y value of the object in CIE XYZ color space

CieYMax

The maximum Y value of the object in CIE XYZ color space

CieYStdDev

The standard deviation of the Y value of the object in CIE XYZ color space

CieYCoeffVar

The coefficient of variation of the Y value of the object in CIE XYZ color space

CieZMin

The minimum Z value of the object in CIE XYZ color space

CieZQ1

The lower quartile (Q1) Z value of the object in CIE XYZ color space

CieZMean

The mean Z value of the object in CIE XYZ color space

CieZMedian

The median Z value of the object in CIE XYZ color space

CieZQ3

The upper quartile (Q3) Z value of the object in CIE XYZ color space

CieZMax

The maximum Z value of the object in CIE XYZ color space

CieZStdDev

The standard deviation of the Z value of the object in CIE XYZ color space

CieZCoeffVar

The coefficient of variation of the Z value of the object in CIE XYZ color space

Category: Colorxy#

Name

Description

xMin

The minimum chromaticity x coordinate of the object

xQ1

The lower quartile (Q1) chromaticity x coordinate of the object

xMean

The mean chromaticity x coordinate of the object

xMedian

The median chromaticity x coordinate of the object

xQ3

The upper quartile (Q3) chromaticity x coordinate of the object

xMax

The maximum chromaticity x coordinate of the object

xStdDev

The standard deviation of the chromaticity x coordinate of the object

xCoeffVar

The coefficient of variation of the chromaticity x coordinate of the object

yMin

The minimum chromaticity y coordinate of the object

yQ1

The lower quartile (Q1) chromaticity y coordinate of the object

yMean

The mean chromaticity y coordinate of the object

yMedian

The median chromaticity y coordinate of the object

yQ3

The upper quartile (Q3) chromaticity y coordinate of the object

yMax

The maximum chromaticity y coordinate of the object

yStdDev

The standard deviation of the chromaticity y coordinate of the object

yCoeffVar

The coefficient of variation of the chromaticity y coordinate of the object

Category: ColorLab#

Name

Description

L*Min

The minimum L* value of the object

L*Q1

The lower quartile (Q1) L* value of the object

L*Mean

The mean L* value of the object

L*Median

The median L* value of the object

L*Q3

The upper quartile (Q3) L* value of the object

L*Max

The maximum L* value of the object

L*StdDev

The standard deviation of the L* value of the object

L*CoeffVar

The coefficient of variation of the L* value of the object

a*Min

The minimum a* value of the object

a*Q1

The lower quartile (Q1) a* value of the object

a*Mean

The mean a* value of the object

a*Median

The median a* value of the object

a*Q3

The upper quartile (Q3) a* value of the object

a*Max

The maximum a* value of the object

a*StdDev

The standard deviation of the a* value of the object

a*CoeffVar

The coefficient of variation of the a* value of the object

b*Min

The minimum b* value of the object

b*Q1

The lower quartile (Q1) b* value of the object

b*Mean

The mean b* value of the object

b*Median

The median b* value of the object

b*Q3

The upper quartile (Q3) b* value of the object

b*Max

The maximum b* value of the object

b*StdDev

The standard deviation of the b* value of the object

b*CoeffVar

The coefficient of variation of the b* value of the object

ChromaEstimatedMean

The mean chroma estimation of the object calculated using \(\(sqrt(a^{*}_{mean}^2 + b^{*}_{mean})^2}\)

ChromaEstimatedMedian

The median chroma estimation of the object using \(\sqrt({a*_{median}^2 + b*_{median})^2}\)

Category: ColorHSV#

Name

Description

HueMin

The minimum hue of the object

HueQ1

The lower quartile (Q1) hue of the object

HueMean

The mean hue of the object

HueMedian

The median hue of the object

HueQ3

The upper quartile (Q3) hue of the object

HueMax

The maximum hue of the object

HueStdDev

The standard deviation of the hue of the object

HueCoeffVar

The coefficient of variation of the hue of the object

SaturationMin

The minimum saturation of the object

SaturationQ1

The lower quartile (Q1) saturation of the object

SaturationMean

The mean saturation of the object

SaturationMedian

The median saturation of the object

SaturationQ3

The upper quartile (Q3) saturation of the object

SaturationMax

The maximum saturation of the object

SaturationStdDev

The standard deviation of the saturation of the object

SaturationCoeffVar

The coefficient of variation of the saturation of the object

BrightnessMin

The minimum brightness of the object

BrightnessQ1

The lower quartile (Q1) brightness of the object

BrightnessMean

The mean brightness of the object

BrightnessMedian

The median brightness of the object

BrightnessQ3

The upper quartile (Q3) brightness of the object

BrightnessMax

The maximum brightness of the object

BrightnessStdDev

The standard deviation of the brightness of the object

BrightnessCoeffVar

The coefficient of variation of the brightness of the object

Parameters:
__del__()#

Automatically stop tracemalloc when the object is deleted.

measure(image, include_meta=False)#

Execute the measurement operation on a detected-object image.

This is the main public API method for extracting measurements. It handles: input validation, parameter extraction via introspection, calling the subclass-specific _operate() method, optional metadata merging, and exception handling.

How it works (for users):

  1. Pass your processed Image (with detected objects) to measure()

  2. The method calls your subclass’s _operate() implementation

  3. Results are validated and returned as a pandas DataFrame

  4. If include_meta=True, image metadata (filename, grid info) is merged in

How it works (for developers):

When you subclass MeasureFeatures, you only implement _operate(). This measure() method automatically:

  • Extracts __init__ parameters from your instance (introspection)

  • Passes matched parameters to _operate() as keyword arguments

  • Validates the Image has detected objects (objmap)

  • Wraps exceptions in OperationFailedError with context

  • Merges grid/object metadata if requested

Parameters:
  • image (Image) – A PhenoTypic Image object with detected objects (must have non-empty objmap from a prior detection operation).

  • include_meta (bool, optional) – If True, merge image metadata columns (filename, grid position, etc.) into the results DataFrame. Defaults to False.

Returns:

Measurement results with structure:

  • First column: OBJECT.LABEL (integer IDs from image.objmap[:])

  • Remaining columns: Measurement values (float, int, or string)

  • One row per detected object

If include_meta=True, additional metadata columns are prepended before OBJECT.LABEL (e.g., Filename, GridRow, GridCol).

Return type:

pd.DataFrame

Raises:

OperationFailedError – If _operate() raises any exception, it is caught and re-raised as OperationFailedError with details including the original exception type, message, image name, and operation class. This provides consistent error handling across all measurers.

Notes

  • This method is the main entry point; do not override in subclasses

  • Subclasses implement _operate() only, not this method

  • Automatic memory profiling is available via logging configuration

  • Image must have detected objects (image.objmap should be non-empty)

Examples

Basic measurement extraction:

>>> from phenotypic import Image
>>> from phenotypic.measure import MeasureSize
>>> from phenotypic.detect import OtsuDetector
>>> # Load and detect
>>> image = Image('plate.jpg')
>>> image = OtsuDetector().operate(image)
>>> # Extract measurements
>>> measurer = MeasureSize()
>>> df = measurer.measure(image)
>>> print(df.head())

Include metadata in measurements:

>>> # With image metadata (filename, grid info)
>>> df_with_meta = measurer.measure(image, include_meta=True)
>>> print(df_with_meta.columns)
# Output: ['Filename', 'GridRow', 'GridCol', 'OBJECT.LABEL',
#          'Area', 'IntegratedIntensity', ...]
class phenotypic.measure.MeasureGridLinRegStats(section_num: int | None = None)[source]#

Bases: GridMeasureFeatures

Evaluate grid alignment quality using row-wise and column-wise linear regression.

Fit linear regressions to colony centroid positions along each row and column of the grid, then compute per-colony residual error (Euclidean distance between observed and predicted centroid). High residual errors flag off-grid growth, misdetections, or plate warping.

Args:
section_num: Grid section index to restrict measurements to.

None measures across the entire grid. Default: None.

Returns:

pd.DataFrame: Per-object metrics indexed by object label:

  • RowM, RowB: row regression slope and intercept.

  • ColM, ColB: column regression slope and intercept.

  • PredRR, PredCC: predicted centroid from regression.

  • ResidualError: Euclidean distance between actual and predicted centroid.

Best For:
  • Identifying colonies that grew outside their designated grid position on arrayed plates.

  • Detecting systematic rotation or shear across the plate to validate grid detection quality.

  • Filtering or weighting colonies by positional confidence before downstream phenotypic analysis.

Consider Also:
See Also:

Tutorial 7: Measuring and Exporting for a walkthrough of grid-level measurements.

Category: GRID_LINREG_STATS#

Name

Description

RowM

Slope of row-wise linear regression fit across column positions. Measures systematic drift in row alignment. Values near 0 indicate horizontal rows; non-zero values suggest rotational misalignment or systematic row curvature across the plate.

RowB

Intercept of row-wise linear regression fit. Represents the expected row coordinate when column position is 0. Combined with slope, defines the expected row trend line for quality assessment and position prediction.

ColM

Slope of column-wise linear regression fit across row positions. Measures systematic drift in column alignment. Values near 0 indicate vertical columns; non-zero values suggest rotational misalignment or systematic column curvature across the plate.

ColB

Intercept of column-wise linear regression fit. Represents the expected column coordinate when row position is 0. Combined with slope, defines the expected column trend line for quality assessment and position prediction.

PredRR

Predicted row coordinate from column-wise linear regression. Uses the column position and column regression parameters (ColM, ColB) to estimate where the row coordinate should be if the grid were perfectly aligned. Used for calculating residual errors and detecting misaligned colonies.

PredCC

Predicted column coordinate from row-wise linear regression. Uses the row position and row regression parameters (RowM, RowB) to estimate where the column coordinate should be if the grid were perfectly aligned. Used for calculating residual errors and detecting misaligned colonies.

ResidualError

Euclidean distance between the actual colony centroid and the predicted position from linear regression. Quantifies how far each colony deviates from the expected grid pattern. High values indicate misdetections, off-grid growth, or local plate warping. Used by refinement operations to filter outliers and select the most plausible colony per grid cell.

Parameters:

section_num (Optional[int])

__del__()#

Automatically stop tracemalloc when the object is deleted.

measure(image)#

Compute grid edges and assign each detected object to a grid cell.

Parameters:

image – Image with detected objects.

Returns:

DataFrame with grid assignments (ROW_NUM, COL_NUM, ROW_MAJOR_IDX).

class phenotypic.measure.MeasureGridSpatial(*args, **kwargs)[source]#

Bases: GridMeasureFeatures

Measure edge-to-edge distances to neighbors in adjacent grid cells.

For each detected colony, identify the nearest object in the left, right, above, and below grid cells and compute the minimum bounding-box edge-to-edge distance. Edge and corner colonies report NaN for directions beyond the plate boundary.

Returns:

pd.DataFrame: Object-level neighbor measurements with columns:

  • Label: unique object identifier.

  • LeftNeighborObjLabel, LeftDistance.

  • RightNeighborObjLabel, RightDistance.

  • AboveNeighborObjLabel, AboveDistance.

  • UnderNeighborObjLabel, UnderDistance.

  • NaN where no neighbor exists in a given direction.

Best For:
  • Quantifying colony spacing and crowding to assess nutrient competition risk on arrayed plates.

  • Flagging closely spaced colonies that may cross-contaminate.

  • Enabling neighbor-aware paired statistical comparisons for competition or cooperation studies.

Consider Also:
See Also:

Tutorial 7: Measuring and Exporting for a walkthrough of grid-level measurements.

Category: GRID_SPATIAL#

Name

Description

LeftNeighborObjLabel

The object label of the left neighbor colony

LeftDistance

The distance of the left neighbor colony calculated using euclidean distance between bounding boxes

RightNeighborObjLabel

The object label of the right neighbor colony

RightDistance

The distance of the right neighbor colony calculated using euclidean distance between bounding boxes

AboveNeighborObjLabel

The object label of the above neighbor colony

AboveDistance

The distance of the above neighbor colony calculated using euclidean distance between bounding boxes

UnderNeighborObjLabel

The object label of the under neighbor colony

UnderDistance

The distance of the under neighbor colony calculated using euclidean distance between bounding boxes

__del__()#

Automatically stop tracemalloc when the object is deleted.

measure(image)#

Compute grid edges and assign each detected object to a grid cell.

Parameters:

image – Image with detected objects.

Returns:

DataFrame with grid assignments (ROW_NUM, COL_NUM, ROW_MAJOR_IDX).

class phenotypic.measure.MeasureGridSpread(*args, **kwargs)[source]#

Bases: GridMeasureFeatures

Quantify within-well colony dispersion using pairwise centroid distances.

Compute the sum of squared pairwise Euclidean distances between all colony centroids in each grid section. High values indicate multiple dispersed objects within a single well – a sign of over-segmentation, fragmented growth, or invasive spreading.

Returns:

pd.DataFrame: Section-level statistics sorted by spread (descending) with columns:

  • count: number of colonies detected in the section.

  • ObjectSpread: sum of squared pairwise Euclidean distances between colony centroids in the section.

Best For:
  • Detecting over-segmented wells where multiple objects were found instead of a single cohesive colony.

  • Identifying invasive or spreading growth that extends beyond the designated grid position.

  • Flagging wells with questionable data quality for manual review or exclusion from downstream analysis.

Consider Also:
See Also:

Tutorial 7: Measuring and Exporting for a walkthrough of grid-level measurements.

Category: GRID_SPREAD#

Name

Description

ObjectSpread

Sum of squared pairwise Euclidean distances between all unique colony pairs within a grid section. Quantifies spatial dispersion of colonies in a grid cell. Higher values indicate greater spread from the section center, suggesting over-segmentation, multi-detections, or colonies growing beyond expected boundaries. Used to identify problematic grid sections requiring refinement or quality review.

__del__()#

Automatically stop tracemalloc when the object is deleted.

measure(image)#

Compute grid edges and assign each detected object to a grid cell.

Parameters:

image – Image with detected objects.

Returns:

DataFrame with grid assignments (ROW_NUM, COL_NUM, ROW_MAJOR_IDX).

class phenotypic.measure.MeasureIntensity(*args, **kwargs)[source]#

Bases: MeasureFeatures

Measure grayscale intensity statistics of detected colonies.

Compute per-colony intensity metrics from the grayscale channel: integrated intensity, percentiles (min, Q1, median, Q3, max), standard deviation, coefficient of variation, and area-normalized density. These statistics reflect colony optical density, biomass accumulation, and internal heterogeneity.

Returns:

pd.DataFrame: Object-level intensity statistics with columns:

  • Label, IntegratedIntensity, MinimumIntensity, MaximumIntensity, MeanIntensity, MedianIntensity.

  • LowerQuartileIntensity, UpperQuartileIntensity, InterquartileRangeIntensity.

  • StandardDeviationIntensity, CoefficientVarianceIntensity.

  • Density (integrated intensity / area), ConvexDensity (integrated intensity / convex area).

Best For:
  • Tracking colony growth over time via integrated intensity as an optical-density proxy.

  • Detecting metabolically stressed or slow-growing colonies through low mean intensity.

  • Identifying sectored or chimeric colonies by high within-colony intensity variance.

  • Automated colony picking based on biomass thresholds.

Consider Also:
  • MeasureSize for lightweight area and integrated intensity without full statistics.

  • MeasureColor for multi-channel color statistics when pigmentation is relevant.

  • MeasureTexture for surface-roughness features that complement intensity metrics.

See Also:

Tutorial 7: Measuring and Exporting for a walkthrough of measuring and exporting colony data. Measurement Metrics and Their Biological Meaning for interpreting intensity metrics in a biological context.

Category: INTENSITY#

Name

Description

IntegratedIntensity

The sum of the object’s pixels

Density

The ratio of the object’s intensity to the max possible intensity of the object

ConvexDensity

The ratio of the objects intensity to the max possible intensity of the object’s convex hull

MinimumIntensity

The minimum intensity of the object

MaximumIntensity

The maximum intensity of the object

MeanIntensity

The mean intensity of the object

MedianIntensity

The median intensity of the object

StandardDeviationIntensity

The standard deviation of the object

CoefficientVarianceIntensity

The coefficient of variation of the object

LowerQuartileIntensity

The lower quartile intensity of the object

UpperQuartileIntensity

The upper quartile intensity of the object

InterquartileRangeIntensity

The interquartile range of the object

__del__()#

Automatically stop tracemalloc when the object is deleted.

measure(image, include_meta=False)#

Execute the measurement operation on a detected-object image.

This is the main public API method for extracting measurements. It handles: input validation, parameter extraction via introspection, calling the subclass-specific _operate() method, optional metadata merging, and exception handling.

How it works (for users):

  1. Pass your processed Image (with detected objects) to measure()

  2. The method calls your subclass’s _operate() implementation

  3. Results are validated and returned as a pandas DataFrame

  4. If include_meta=True, image metadata (filename, grid info) is merged in

How it works (for developers):

When you subclass MeasureFeatures, you only implement _operate(). This measure() method automatically:

  • Extracts __init__ parameters from your instance (introspection)

  • Passes matched parameters to _operate() as keyword arguments

  • Validates the Image has detected objects (objmap)

  • Wraps exceptions in OperationFailedError with context

  • Merges grid/object metadata if requested

Parameters:
  • image (Image) – A PhenoTypic Image object with detected objects (must have non-empty objmap from a prior detection operation).

  • include_meta (bool, optional) – If True, merge image metadata columns (filename, grid position, etc.) into the results DataFrame. Defaults to False.

Returns:

Measurement results with structure:

  • First column: OBJECT.LABEL (integer IDs from image.objmap[:])

  • Remaining columns: Measurement values (float, int, or string)

  • One row per detected object

If include_meta=True, additional metadata columns are prepended before OBJECT.LABEL (e.g., Filename, GridRow, GridCol).

Return type:

pd.DataFrame

Raises:

OperationFailedError – If _operate() raises any exception, it is caught and re-raised as OperationFailedError with details including the original exception type, message, image name, and operation class. This provides consistent error handling across all measurers.

Notes

  • This method is the main entry point; do not override in subclasses

  • Subclasses implement _operate() only, not this method

  • Automatic memory profiling is available via logging configuration

  • Image must have detected objects (image.objmap should be non-empty)

Examples

Basic measurement extraction:

>>> from phenotypic import Image
>>> from phenotypic.measure import MeasureSize
>>> from phenotypic.detect import OtsuDetector
>>> # Load and detect
>>> image = Image('plate.jpg')
>>> image = OtsuDetector().operate(image)
>>> # Extract measurements
>>> measurer = MeasureSize()
>>> df = measurer.measure(image)
>>> print(df.head())

Include metadata in measurements:

>>> # With image metadata (filename, grid info)
>>> df_with_meta = measurer.measure(image, include_meta=True)
>>> print(df_with_meta.columns)
# Output: ['Filename', 'GridRow', 'GridCol', 'OBJECT.LABEL',
#          'Area', 'IntegratedIntensity', ...]
class phenotypic.measure.MeasureShape(*args, **kwargs)[source]#

Bases: MeasureFeatures

Measure comprehensive morphological characteristics of detected colonies.

Extract geometric metrics from each colony shape: area, perimeter, circularity, convex hull properties, width-based measures, Feret diameters, eccentricity, and best-fit ellipse parameters. The output DataFrame provides a full morphological profile for phenotypic classification and growth-pattern analysis.

Returns:

pd.DataFrame: Object-level morphological measurements with columns:

  • Label, Area, Perimeter, Circularity, Compactness, ConvexArea, Solidity, Extent, BboxArea.

  • MeanRadius, MedianRadius, MaxRadius (distance-transform based).

  • MinFeretDiameter, MaxFeretDiameter (caliper diameters).

  • MajorAxisLength, MinorAxisLength, Eccentricity, Orientation.

Best For:
  • Distinguishing colony morphotypes (smooth circular wild-type vs wrinkled, branching, or invasive mutants).

  • Assessing growth symmetry and directionality via eccentricity and orientation.

  • Detecting invasive or spreading growth through low solidity values.

  • Morphological clustering for automated strain identification.

Consider Also:
  • MeasureSize for a lightweight area-only measurement when full morphology is not needed.

  • MeasureTexture for surface roughness and pattern features that complement shape metrics.

  • MeasureBounds for bounding box and centroid data without shape statistics.

See Also:

Tutorial 7: Measuring and Exporting for a walkthrough of measuring and exporting colony data. Measurement Metrics and Their Biological Meaning for interpreting shape metrics in a biological context.

Category: SHAPE#

Name

Description

Area

Total number of pixels occupied by the microbial colony. Represents colony biomass and growth extent on agar plates. Larger areas typically indicate more robust growth or longer incubation times.

Perimeter

Total length of the colony’s outer boundary in pixels. Measures colony edge complexity and surface irregularity. Smooth, circular colonies have shorter perimeters relative to their area compared to irregular or filamentous colonies.

Circularity

Calculated as \(\frac{4\pi*\text{Area}}{\text{Perimeter}^2}\). Measures how closely a colony approximates a perfect circle (value = 1). Values < 1 indicate irregular colony morphology, which may result from genetic mutations, environmental stress, or mixed microbial populations on agar plates.

ConvexArea

Area of the smallest convex polygon that completely contains the colony. Represents the colony’s “filled-in” appearance if all indentations and holes were removed. Useful for detecting colony spreading patterns or invasive growth characteristics.

MedianRadius

Median distance from colony center to edge across all directions. Provides a robust measure of typical colony size that is less sensitive to outliers than mean width. Particularly useful for colonies with uneven growth or sectoring.

MeanRadius

Average distance from colony center to edge across all directions. Represents overall colony expansion rate. In arrayed growth assays, this correlates with microbial fitness and growth kinetics under controlled conditions.

MaxRadius

Maximum distance from colony center to edge across all directions. Represents the furthest extent of colony growth from its center. In arrayed microbial assays, this measurement helps identify asymmetric growth patterns or colonies extending toward neighboring positions.

MinFeretDiameter

Minimum caliper diameter - the shortest distance between two parallel tangent lines touching opposite sides of the colony. Represents the narrowest dimension of the colony regardless of orientation. Useful for detecting elongated or irregular colony morphologies and measuring colony width.

MaxFeretDiameter

Maximum caliper diameter - the longest distance between two parallel tangent lines touching opposite sides of the colony. Represents the maximum dimension of the colony regardless of orientation. Often exceeds major axis length for irregular shapes and helps quantify maximum colony extent.

Eccentricity

Measure of colony elongation, ranging from 0 (perfect circle) to 1 (highly elongated). Values near 0 indicate compact, radially symmetric growth typical of healthy bacterial colonies, while higher values may suggest directional growth, motility, or environmental gradients on the agar surface.

Solidity

Ratio of actual colony area to its convex hull area (Area/ConvexArea). Values near 1 indicate compact, solid colonies with minimal indentations. Lower values (< 0.9) may indicate invasive growth, colony spreading, or the presence of clearing zones around colonies.

Extent

Ratio of colony area to its bounding box area (ObjectArea/BboxArea). Measures how efficiently the colony fills its allocated space. Compact colonies have higher extent values, while spread-out or irregular colonies have lower values.

BboxArea

Area of the smallest rectangle that completely contains the colony. Represents the total spatial shape of the colony including any empty space. In high-throughput assays, this helps assess colony positioning and potential interference with neighboring colonies.

MajorAxisLength

Length of the longest axis of the ellipse that best fits the colony shape. Represents the maximum colony dimension. In arrayed microbial growth, this measurement helps identify colonies that have grown beyond their intended grid positions.

MinorAxisLength

Length of the shortest axis of the ellipse that best fits the colony shape. Represents the minimum colony dimension. Together with major axis length, this helps characterize colony aspect ratio and growth anisotropy.

Compactness

Calculated as \(\frac{\text{Perimeter}^2}{4\pi*\text{Area}}\). Inverse of circularity (ranges from 1 for perfect circles to higher values for irregular shapes). Measures colony shape complexity - compact, circular colonies have values near 1, while irregular or filamentous colonies have much higher values.

Orientation

Angle (in radians) between the colony’s major axis and the horizontal axis. Measures colony alignment and growth directionality. Random orientations are typical for most bacterial colonies, while consistent orientations may indicate environmental gradients or mechanical stresses during plating.

__del__()#

Automatically stop tracemalloc when the object is deleted.

measure(image, include_meta=False)#

Execute the measurement operation on a detected-object image.

This is the main public API method for extracting measurements. It handles: input validation, parameter extraction via introspection, calling the subclass-specific _operate() method, optional metadata merging, and exception handling.

How it works (for users):

  1. Pass your processed Image (with detected objects) to measure()

  2. The method calls your subclass’s _operate() implementation

  3. Results are validated and returned as a pandas DataFrame

  4. If include_meta=True, image metadata (filename, grid info) is merged in

How it works (for developers):

When you subclass MeasureFeatures, you only implement _operate(). This measure() method automatically:

  • Extracts __init__ parameters from your instance (introspection)

  • Passes matched parameters to _operate() as keyword arguments

  • Validates the Image has detected objects (objmap)

  • Wraps exceptions in OperationFailedError with context

  • Merges grid/object metadata if requested

Parameters:
  • image (Image) – A PhenoTypic Image object with detected objects (must have non-empty objmap from a prior detection operation).

  • include_meta (bool, optional) – If True, merge image metadata columns (filename, grid position, etc.) into the results DataFrame. Defaults to False.

Returns:

Measurement results with structure:

  • First column: OBJECT.LABEL (integer IDs from image.objmap[:])

  • Remaining columns: Measurement values (float, int, or string)

  • One row per detected object

If include_meta=True, additional metadata columns are prepended before OBJECT.LABEL (e.g., Filename, GridRow, GridCol).

Return type:

pd.DataFrame

Raises:

OperationFailedError – If _operate() raises any exception, it is caught and re-raised as OperationFailedError with details including the original exception type, message, image name, and operation class. This provides consistent error handling across all measurers.

Notes

  • This method is the main entry point; do not override in subclasses

  • Subclasses implement _operate() only, not this method

  • Automatic memory profiling is available via logging configuration

  • Image must have detected objects (image.objmap should be non-empty)

Examples

Basic measurement extraction:

>>> from phenotypic import Image
>>> from phenotypic.measure import MeasureSize
>>> from phenotypic.detect import OtsuDetector
>>> # Load and detect
>>> image = Image('plate.jpg')
>>> image = OtsuDetector().operate(image)
>>> # Extract measurements
>>> measurer = MeasureSize()
>>> df = measurer.measure(image)
>>> print(df.head())

Include metadata in measurements:

>>> # With image metadata (filename, grid info)
>>> df_with_meta = measurer.measure(image, include_meta=True)
>>> print(df_with_meta.columns)
# Output: ['Filename', 'GridRow', 'GridCol', 'OBJECT.LABEL',
#          'Area', 'IntegratedIntensity', ...]
class phenotypic.measure.MeasureSize(*args, **kwargs)[source]#

Bases: MeasureFeatures

Measure colony area and integrated intensity as lightweight size proxies.

Extract two fundamental size metrics per detected colony: pixel area (biomass extent) and integrated grayscale intensity (total brightness, a proxy for optical density). This is a convenience class for rapid size assessment without the overhead of full shape or intensity statistical analysis.

Returns:

pd.DataFrame: Object-level size measurements with columns:

  • Label: unique object identifier.

  • Area: number of pixels occupied by the colony.

  • IntegratedIntensity: sum of grayscale pixel values (proxy for biomass / optical density).

Best For:
  • Quick quality-control screening of colony size distributions.

  • Time-course growth tracking via area at successive time points.

  • Filtering colonies by minimum size to exclude debris or aborted growth before downstream measurement.

Consider Also:
  • MeasureShape for comprehensive morphological metrics (circularity, convex hull, Feret diameters).

  • MeasureIntensity for full intensity statistics (percentiles, variance, coefficient of variation).

  • MeasureGridSpread for detecting multi-object wells in arrayed assays.

See Also:

Tutorial 7: Measuring and Exporting for a walkthrough of measuring and exporting colony data. Measurement Metrics and Their Biological Meaning for interpreting size metrics in a biological context.

Category: SIZE#

Name

Description

Area

Total number of pixels occupied by the microbial colony.Larger areas typically indicate more robust growth or longer incubation times.

IntegratedIntensity

The sum of the object's grayscale pixels. Calculated as$sum{pixel values}*area$

__del__()#

Automatically stop tracemalloc when the object is deleted.

measure(image, include_meta=False)#

Execute the measurement operation on a detected-object image.

This is the main public API method for extracting measurements. It handles: input validation, parameter extraction via introspection, calling the subclass-specific _operate() method, optional metadata merging, and exception handling.

How it works (for users):

  1. Pass your processed Image (with detected objects) to measure()

  2. The method calls your subclass’s _operate() implementation

  3. Results are validated and returned as a pandas DataFrame

  4. If include_meta=True, image metadata (filename, grid info) is merged in

How it works (for developers):

When you subclass MeasureFeatures, you only implement _operate(). This measure() method automatically:

  • Extracts __init__ parameters from your instance (introspection)

  • Passes matched parameters to _operate() as keyword arguments

  • Validates the Image has detected objects (objmap)

  • Wraps exceptions in OperationFailedError with context

  • Merges grid/object metadata if requested

Parameters:
  • image (Image) – A PhenoTypic Image object with detected objects (must have non-empty objmap from a prior detection operation).

  • include_meta (bool, optional) – If True, merge image metadata columns (filename, grid position, etc.) into the results DataFrame. Defaults to False.

Returns:

Measurement results with structure:

  • First column: OBJECT.LABEL (integer IDs from image.objmap[:])

  • Remaining columns: Measurement values (float, int, or string)

  • One row per detected object

If include_meta=True, additional metadata columns are prepended before OBJECT.LABEL (e.g., Filename, GridRow, GridCol).

Return type:

pd.DataFrame

Raises:

OperationFailedError – If _operate() raises any exception, it is caught and re-raised as OperationFailedError with details including the original exception type, message, image name, and operation class. This provides consistent error handling across all measurers.

Notes

  • This method is the main entry point; do not override in subclasses

  • Subclasses implement _operate() only, not this method

  • Automatic memory profiling is available via logging configuration

  • Image must have detected objects (image.objmap should be non-empty)

Examples

Basic measurement extraction:

>>> from phenotypic import Image
>>> from phenotypic.measure import MeasureSize
>>> from phenotypic.detect import OtsuDetector
>>> # Load and detect
>>> image = Image('plate.jpg')
>>> image = OtsuDetector().operate(image)
>>> # Extract measurements
>>> measurer = MeasureSize()
>>> df = measurer.measure(image)
>>> print(df.head())

Include metadata in measurements:

>>> # With image metadata (filename, grid info)
>>> df_with_meta = measurer.measure(image, include_meta=True)
>>> print(df_with_meta.columns)
# Output: ['Filename', 'GridRow', 'GridCol', 'OBJECT.LABEL',
#          'Area', 'IntegratedIntensity', ...]
class phenotypic.measure.MeasureSymmetricZones(n_annuli: int = 100, pelt_penalty: float = 5.0, symmetry_threshold: float = 0.6666666666666666, n_angular_bins: int = 6, smoothing_window: int = 3, method: Literal['distance', 'intensity'] = 'distance', tau_core: float = 0.9, tau_sparse: float = 0.5, bright_intensity_fraction: float = 0.5, intensity_source: Literal['gray', 'detect_mat'] = 'gray')[source]#

Bases: MeasureFeatures

Measure colony radial expansion and angular symmetry from the object mask alone.

Quantifies each colony by four scalars derived directly from its binary mask and distance-from-inoculum map — no skeletonization, no branch tracing, no runner outlier flagging. The headline output is SymmetricRadius, the first radius past the inoculum core at which the per-annulus circular mean resultant length of mask-boundary pixels drops below a tunable symmetry threshold. CoreRadius (PELT changepoint on the radial density profile, identical algorithm to MeasureRadialExpansion) anchors the measurement; MeanExpansion and MaxExpansion summarise how far growth reached past that core.

Args:
n_annuli: Number of equal-area annuli used for the radial density

profile and angular analysis. Defaults to 100.

pelt_penalty: PELT penalty controlling changepoint sensitivity for

core detection. Defaults to 5.0.

symmetry_threshold: Minimum angular coverage (fraction of angular

bins occupied) for growth to be considered symmetric. Defaults to 4/6 (~0.667); with 6 angular bins this means at least 4 of 6 60-degree sectors must contain mask pixels.

n_angular_bins: Number of angular bins used to compute the

per-annulus angular coverage diagnostic. Defaults to 36 (10 degree resolution).

smoothing_window: Moving-average window (in annuli) applied to the

angular R̄ profile before the threshold test. Defaults to 3.

method: Inoculum centre estimator — "distance" uses the peak

of the Euclidean distance transform, "intensity" uses the intensity-weighted centroid. Defaults to "distance".

tau_core: Minimum bright-pixel fraction required for an annulus

to be classified as inoculum core in the per-angle outward walk. Defaults to 0.9.

tau_sparse: Minimum bright-pixel fraction required for an annulus

to be classified as dense branching (the outer edge of the dense zone). Defaults to 0.5.

bright_intensity_fraction: Fraction of the core’s median intensity

used as the bright/background threshold for zone segmentation. Defaults to 0.5.

intensity_source: Image array used for the brightness comparison

"gray" uses the grayscale, "detect_mat" uses the detection matrix. Defaults to "gray".

Returns:

pd.DataFrame: Object-level radial symmetry measurements with columns:

  • ObjectLabel: unique object identifier.

  • SymmetricRadius_CoreRadius: inoculum core radius (pixels).

  • SymmetricRadius_SymmetricRadius: first radius past the core where R̄ exceeds the symmetry threshold (pixels).

  • SymmetricRadius_MeanExpansion: mean boundary-pixel distance beyond the core (pixels, clamped at 0).

  • SymmetricRadius_MaxExpansion: maximum mask-pixel distance beyond the core (pixels, clamped at 0).

  • SymmetricRadius_CoreEndRadius: mean per-angle core boundary radius from the bright-fraction outward walk (pixels).

  • SymmetricRadius_DenseEndRadius: mean per-angle outer radius of the dense branching zone (pixels).

  • SymmetricRadius_SparseEndRadius: mean per-angle outer radius of the sparse branching zone, capped at the symmetric envelope (pixels).

  • SymmetricRadius_CoreArea: pixel^2 area of the inoculum core zone integrated across the 360-sector polar polygon.

  • SymmetricRadius_DenseArea: pixel^2 area of the dense branching zone (annular region between core and dense boundaries).

  • SymmetricRadius_SparseArea: pixel^2 area of the sparse branching zone (annular region between dense and outer boundaries).

Best For:
  • Summarising colony-level radial growth with a single symmetry figure of merit.

  • Distinguishing uniformly-expanding colonies from those with sectors, lopsided growth, or directional bias.

  • Comparing wild-type versus mutant expansion phenotypes when the biological question is about the colony envelope, not individual hyphae.

  • Time-course assays where runner counts are noisy but colony extent is informative.

Consider Also:
  • MeasureRadialExpansion when you need per-branch statistics (branch counts, outlier runner detection) rather than a single symmetry scalar.

  • MeasureShape for general morphological descriptors (circularity, eccentricity) that do not require radial analysis.

  • MeasureBounds for lightweight bounding-box data without any radial pipeline.

See Also:

Tutorial 7: Measuring and Exporting for a walkthrough of measuring and exporting colony data.

Category: SYMMETRIC_RADIUS#

Name

Description

CoreRadius

Radius of the dense inoculum core, determined by PELT changepoint detection on the radial mask-density profile centered on the inoculum. Growth measurements are reported relative to this boundary.

SymmetricRadius

Radial distance from the inoculum centroid at which colony growth ceases to be angularly uniform. Computed as the first radius past the core where the smoothed per-annulus circular mean resultant length of mask-boundary pixels exceeds the symmetry threshold. Equals the colony outer envelope when growth remains symmetric throughout.

MeanExpansion

Mean distance of mask-boundary pixels from the inoculum centroid, measured from the core boundary outward. Captures the typical radial extent of growth past the inoculum, averaged over all angular directions.

MaxExpansion

Maximum distance of any mask pixel from the inoculum centroid, measured from the core boundary outward. Captures the farthest extent of growth past the inoculum.

CoreEndRadius

Mean radius of the inoculum core boundary derived from the per-angle bright/background ratio walk. Each of 360 1° angular sectors finds the outer edge of the contiguous core run (bright fraction >= tau_core); the reported value is the mean across sectors. Compare with CoreRadius (the global PELT changepoint) — close agreement indicates a well-formed core.

DenseEndRadius

Mean outer radius of the dense branching zone, where mask-bright pixels dominate (bright fraction >= tau_sparse). Per-angle radii are capped at the SymmetricRadius and angularly median-smoothed before averaging.

SparseEndRadius

Mean outer radius of the sparse branching zone (= colony envelope inside the symmetric growth front). Equals min(objmask outer envelope, SymmetricRadius) per angle, averaged across 360 sectors.

CoreArea

Pixel^2 area of the inoculum core zone, integrated across the 360-sector polar polygon defined by the per-angle core radii.

DenseArea

Pixel^2 area of the dense branching zone, the annular region between the per-angle core boundary and dense-branching boundary.

SparseArea

Pixel^2 area of the sparse branching zone, the annular region between the per-angle dense boundary and the symmetric-envelope outer boundary.

Parameters:
  • n_annuli (int)

  • pelt_penalty (float)

  • symmetry_threshold (float)

  • n_angular_bins (int)

  • smoothing_window (int)

  • method (Literal['distance', 'intensity'])

  • tau_core (float)

  • tau_sparse (float)

  • bright_intensity_fraction (float)

  • intensity_source (Literal['gray', 'detect_mat'])

__del__()#

Automatically stop tracemalloc when the object is deleted.

inspect(image: Image | None = None, base_layer: Literal['rgb', 'gray', 'detect_mat'] = 'gray')[source]#

Plate-level diagnostic overlay for symmetric-radius measurement.

Parameters:
  • image (Image | None) – Detected Image with objmap/objmask. If None, the image cached by the most recent measure() call is reused.

  • base_layer (Literal['rgb', 'gray', 'detect_mat']) – Which image array to use as the plotly background.

Returns:

Panel Column layout with a single zoomable plotly figure containing toggleable overlay layers.

measure(image, include_meta=False)#

Execute the measurement operation on a detected-object image.

This is the main public API method for extracting measurements. It handles: input validation, parameter extraction via introspection, calling the subclass-specific _operate() method, optional metadata merging, and exception handling.

How it works (for users):

  1. Pass your processed Image (with detected objects) to measure()

  2. The method calls your subclass’s _operate() implementation

  3. Results are validated and returned as a pandas DataFrame

  4. If include_meta=True, image metadata (filename, grid info) is merged in

How it works (for developers):

When you subclass MeasureFeatures, you only implement _operate(). This measure() method automatically:

  • Extracts __init__ parameters from your instance (introspection)

  • Passes matched parameters to _operate() as keyword arguments

  • Validates the Image has detected objects (objmap)

  • Wraps exceptions in OperationFailedError with context

  • Merges grid/object metadata if requested

Parameters:
  • image (Image) – A PhenoTypic Image object with detected objects (must have non-empty objmap from a prior detection operation).

  • include_meta (bool, optional) – If True, merge image metadata columns (filename, grid position, etc.) into the results DataFrame. Defaults to False.

Returns:

Measurement results with structure:

  • First column: OBJECT.LABEL (integer IDs from image.objmap[:])

  • Remaining columns: Measurement values (float, int, or string)

  • One row per detected object

If include_meta=True, additional metadata columns are prepended before OBJECT.LABEL (e.g., Filename, GridRow, GridCol).

Return type:

pd.DataFrame

Raises:

OperationFailedError – If _operate() raises any exception, it is caught and re-raised as OperationFailedError with details including the original exception type, message, image name, and operation class. This provides consistent error handling across all measurers.

Notes

  • This method is the main entry point; do not override in subclasses

  • Subclasses implement _operate() only, not this method

  • Automatic memory profiling is available via logging configuration

  • Image must have detected objects (image.objmap should be non-empty)

Examples

Basic measurement extraction:

>>> from phenotypic import Image
>>> from phenotypic.measure import MeasureSize
>>> from phenotypic.detect import OtsuDetector
>>> # Load and detect
>>> image = Image('plate.jpg')
>>> image = OtsuDetector().operate(image)
>>> # Extract measurements
>>> measurer = MeasureSize()
>>> df = measurer.measure(image)
>>> print(df.head())

Include metadata in measurements:

>>> # With image metadata (filename, grid info)
>>> df_with_meta = measurer.measure(image, include_meta=True)
>>> print(df_with_meta.columns)
# Output: ['Filename', 'GridRow', 'GridCol', 'OBJECT.LABEL',
#          'Area', 'IntegratedIntensity', ...]
class phenotypic.measure.MeasureTexture(scale: int | List[int] = 5, quant_lvl: Literal[8, 16, 32, 64] = 32, enhance: bool = False, warn: bool = False)[source]#

Bases: MeasureFeatures

Measure colony surface texture using Haralick features from gray-level co-occurrence matrices.

Compute 13 second-order Haralick texture features per colony at one or more pixel-offset scales, across four directional angles (0, 45, 90, 135 degrees), plus direction-averaged values. These features quantify surface roughness, regularity, and directional patterns that distinguish colony morphotypes.

Args:
scale: Pixel offset(s) for the co-occurrence matrix. A single

integer or list of integers. Small values (1–2) capture fine texture; large values (5–10) capture coarse patterns. Default: 5.

quant_lvl: Number of gray-level bins for quantization. Accepted

values: 8, 16, 32, 64. Lower values are faster; higher values preserve texture nuance but are more noise-sensitive. Default: 32.

enhance: Rescale each colony’s intensity to [0, 1] before

computing Haralick features. Improves contrast in low-variance regions but can bias cross-colony comparisons. Default: False.

warn: Emit warnings when Haralick computation fails for

individual colonies (typically very small objects). Default: False.

Returns:

pd.DataFrame: Object-level texture measurements with columns:

  • Label: unique object identifier.

  • 13 Haralick features x 4 angles = 52 directional columns per scale (e.g., Contrast-deg000-scale05).

  • 13 direction-averaged columns per scale (e.g., Contrast-avg-scale05).

References:

[1] R. M. Haralick, K. Shanmugam, and I. Dinstein, “Textural features for image classification,” IEEE Trans. Syst., Man, Cybern., vol. SMC-3, no. 6, pp. 610–621, Nov. 1973.

Best For:
  • Distinguishing smooth wild-type colonies from rough, wrinkled, or sporulated mutants.

  • Assessing mycelial organization in filamentous fungi (radial vs cottony growth).

  • Multi-feature phenotypic clustering when combined with size, shape, and color measurements.

Consider Also:
  • MeasureShape for geometric morphology metrics (circularity, Feret diameters) that complement texture.

  • MeasureIntensity for brightness statistics without spatial co-occurrence information.

  • MeasureColor for pigmentation-based phenotyping.

See Also:

Tutorial 7: Measuring and Exporting for a walkthrough of measuring and exporting colony data. Measurement Metrics and Their Biological Meaning for interpreting texture metrics in a biological context.

Category: TEXTURE#

Name

Description

AngularSecondMoment

Angular second moment (energy / uniformity). Measures the degree of local homogeneity

(Σ p(i,j)²). High values → uniform texture (e.g., smooth, yeast-like colonies with consistent mycelial density). Low values → heterogeneous surfaces (e.g., sectored, wrinkled, or mixed sporulation zones). Reflects colony surface regularity rather than brightness.

Contrast

Contrast (local intensity variation; Σ (i–j)² p(i,j)). High values indicate strong gray-level

differences (e.g., sharply defined rings, radial sectors, raised or folded regions). Low values indicate gradual tonal changes or uniformly pigmented colonies. Quantifies visual roughness and zonation amplitude.

Correlation

Linear gray-level correlation between neighboring pixels. Positive, high values suggest

structured spatial dependence (e.g., oriented radial hyphae or concentric patterns); near-zero values indicate uncorrelated, disordered growth (e.g., diffuse cottony mycelium). Sensitive to illumination gradients and directional GLCM computation.

HaralickVariance

GLCM variance (Σ (i–μ)² p(i,j)). Captures spread of co-occurring gray-level pairs, distinct

from raw intensity variance. High values → complex, multi-zone textures with variable hyphal/spore densities. Low values → consistent gray-level relationships and simpler colony surfaces.

InverseDifferenceMoment

Homogeneity (Σ p(i,j) / (1 + (i–j)²)). High values → smooth, locally uniform textures

(e.g., glabrous colonies, uniform aerial mycelium). Low values → abrupt gray-level changes (e.g., granular sporulation, wrinkled surfaces). Typically inversely correlated with Contrast.

SumAverage

Mean of gray-level sums (Σ k·p_{x+y}(k)). Reflects the average intensity combination of

neighboring pixels. In fungal colonies, can loosely parallel mean colony brightness when illumination and exposure are controlled, but remains a second-order rather than first-order intensity metric.

SumVariance

Variance of gray-level sum distribution. High values → heterogeneous brightness zones

(e.g., alternating dense/sparse or pigmented/non-pigmented regions). Low values → uniform tone across the colony. Often correlated with Contrast; use comparatively within one setup.

SumEntropy

Entropy of the gray-level sum distribution. High values → diverse brightness combinations

and irregular zonation. Low values → repetitive or periodic brightness patterns (e.g., evenly spaced rings). Indicates spatial unpredictability of summed intensities.

Entropy

Global GLCM entropy (–Σ p(i,j)·log p(i,j)). Measures total texture disorder and information

content. High values → complex, irregular colony surfaces (powdery, fuzzy, or sectored growth). Low values → simple, smooth, predictable patterns (glabrous or uniform colonies). Sensitive to gray-level quantization and image dynamic range.

DiffVariance

Variance of gray-level difference distribution. High values → mixture of smooth and textured

regions (e.g., smooth margins with wrinkled centers). Low values → consistent edge content. Highlights heterogeneity in edge magnitude across the colony.

DiffEntropy

Entropy of gray-level difference distribution. High values → irregular, unpredictable

intensity transitions (e.g., random sporulation or uneven mycelial networks). Low values → regular periodic transitions (e.g., concentric zonation). Reflects randomness of local contrast rather than its magnitude.

InfoCorrelation1

Information measure of correlation 1. Compares joint vs marginal entropies to quantify

mutual dependence between gray levels. Positive values → structured, predictable textures (e.g., organized radial growth); near-zero → independence between adjacent regions. Direction of sign varies with implementation.

InfoCorrelation2

Information measure of correlation 2 (√[1 – exp(–2 (H_xy2–H_xy))]). Always ≥ 0.

Values approaching 1 → strong spatial dependence and organized architecture (e.g., symmetric rings, radial structure). Values near 0 → random, independent patterns. Captures nonlinear organization missed by linear correlation.

Parameters:
  • scale (int | List[int])

  • quant_lvl (Literal[8, 16, 32, 64])

  • enhance (bool)

  • warn (bool)

__del__()#

Automatically stop tracemalloc when the object is deleted.

__init__(scale: int | List[int] = 5, quant_lvl: Literal[8, 16, 32, 64] = 32, enhance: bool = False, warn: bool = False)[source]#

Initializes an object with specific configurations for scale, quantization level, enhance, and warning behaviors. This constructor ensures that the ‘scale’ parameter is always stored as a list.

Parameters:
  • scale (int | List[int]) – A single integer or a list of integers representing the scale configuration. If a single integer is provided, it will be converted into a list containing that integer.

  • quant_lvl (Literal[8, 16, 32, 64]) – The quantization level. A higher level adds more computational complexity but captures more discrete texture changes. A higher value is not always more meaningful. Think of this like sensitivity to texture. Acceptable values are either 8, 16, 32, or 64.

  • enhance (bool) – A flag indicating whether to enhance the image before measuring texture. This can increase the amount of detail captured but can bias the measurements in cases where the relative variance between pixel intensities of an object is small.

  • warn (bool) – A flag indicating whether warnings should be issued.

measure(image, include_meta=False)#

Execute the measurement operation on a detected-object image.

This is the main public API method for extracting measurements. It handles: input validation, parameter extraction via introspection, calling the subclass-specific _operate() method, optional metadata merging, and exception handling.

How it works (for users):

  1. Pass your processed Image (with detected objects) to measure()

  2. The method calls your subclass’s _operate() implementation

  3. Results are validated and returned as a pandas DataFrame

  4. If include_meta=True, image metadata (filename, grid info) is merged in

How it works (for developers):

When you subclass MeasureFeatures, you only implement _operate(). This measure() method automatically:

  • Extracts __init__ parameters from your instance (introspection)

  • Passes matched parameters to _operate() as keyword arguments

  • Validates the Image has detected objects (objmap)

  • Wraps exceptions in OperationFailedError with context

  • Merges grid/object metadata if requested

Parameters:
  • image (Image) – A PhenoTypic Image object with detected objects (must have non-empty objmap from a prior detection operation).

  • include_meta (bool, optional) – If True, merge image metadata columns (filename, grid position, etc.) into the results DataFrame. Defaults to False.

Returns:

Measurement results with structure:

  • First column: OBJECT.LABEL (integer IDs from image.objmap[:])

  • Remaining columns: Measurement values (float, int, or string)

  • One row per detected object

If include_meta=True, additional metadata columns are prepended before OBJECT.LABEL (e.g., Filename, GridRow, GridCol).

Return type:

pd.DataFrame

Raises:

OperationFailedError – If _operate() raises any exception, it is caught and re-raised as OperationFailedError with details including the original exception type, message, image name, and operation class. This provides consistent error handling across all measurers.

Notes

  • This method is the main entry point; do not override in subclasses

  • Subclasses implement _operate() only, not this method

  • Automatic memory profiling is available via logging configuration

  • Image must have detected objects (image.objmap should be non-empty)

Examples

Basic measurement extraction:

>>> from phenotypic import Image
>>> from phenotypic.measure import MeasureSize
>>> from phenotypic.detect import OtsuDetector
>>> # Load and detect
>>> image = Image('plate.jpg')
>>> image = OtsuDetector().operate(image)
>>> # Extract measurements
>>> measurer = MeasureSize()
>>> df = measurer.measure(image)
>>> print(df.head())

Include metadata in measurements:

>>> # With image metadata (filename, grid info)
>>> df_with_meta = measurer.measure(image, include_meta=True)
>>> print(df_with_meta.columns)
# Output: ['Filename', 'GridRow', 'GridCol', 'OBJECT.LABEL',
#          'Area', 'IntegratedIntensity', ...]