Skip to content

Pipelines

Overview

Pipeline classes provide pre-configured workflows for extracting traits from SLEAP root predictions. Each pipeline is optimized for specific plant types and root architectures, combining multiple trait computation functions into a single fit_series() call.

Key features:

  • Pre-built trait computation workflows
  • Optimized for different plant types (dicots, monocots)
  • Automatic handling of multiple root types
  • JSON/CSV export capabilities
  • Consistent API across all pipelines

When to use pipelines:

  • You want a complete set of traits without manual computation
  • You're analyzing a specific plant type (dicot, monocot, etc.)
  • You need standardized, reproducible trait extraction
  • You want easy export to CSV/JSON for downstream analysis

Which Pipeline Should I Use?

graph TD
    A[Start] --> B{Plant Type?}
    B -->|Dicot| C{Multiple Plants?}
    B -->|Monocot| D{Plant Age?}

    C -->|Single| E[DicotPipeline]
    C -->|Multiple| F[MultipleDicotPipeline]

    D -->|Young| G[YoungerMonocotPipeline]
    D -->|Mature| H[OlderMonocotPipeline]

    B -->|Primary Only| I{Multiple Plants?}
    I -->|Single| J[PrimaryRootPipeline]
    I -->|Multiple| K[MultiplePrimaryRootPipeline]

    B -->|Lateral Only| L[LateralRootPipeline]

Quick Decision Guide:

Plant Type Root System Pipeline
Dicot (single plant) Primary + Lateral DicotPipeline
Dicot (multiple plants) Primary + Lateral MultipleDicotPipeline
Monocot (young) Crown roots YoungerMonocotPipeline
Monocot (mature) Crown roots OlderMonocotPipeline
Any (single plant) Primary only PrimaryRootPipeline
Any (multiple plants) Primary only MultiplePrimaryRootPipeline
Any Lateral only LateralRootPipeline

Quick Example

import sleap_roots as sr

# Load plant data
series = sr.Series.load(
    "arabidopsis_1",
    h5_path="data.h5",
    primary_path="primary.slp",
    lateral_path="lateral.slp"
)

# Run pipeline
pipeline = sr.DicotPipeline()
traits = pipeline.fit_series(series)

# Access traits
print(f"Primary root length: {traits['primary_length']}")
print(f"Lateral root count: {traits['lateral_count']}")

# Export to CSV
import pandas as pd
df = pd.DataFrame([traits])
df.to_csv("traits.csv", index=False)

DicotPipeline

DicotPipeline

Bases: Pipeline

Pipeline for computing traits for dicot plants (primary + lateral roots).

Attributes:

Name Type Description
img_height int

Image height.

root_width_tolerance float

Difference in projection norm between right and left side.

n_scanlines int

Number of scan lines, np.nan for no interaction.

network_fraction float

Length found in the lower fraction value of the network.

Overview

For analyzing dicot plants with both primary and lateral roots (e.g., Arabidopsis, canola, soybean).

Root System: Primary root + Lateral roots Plant Count: Single plant per series Use Case: Most common dicot analysis workflow

Computed Traits

Primary Root Traits: - primary_length - Total primary root length - primary_angle - Angle relative to gravity - primary_tip_x, primary_tip_y - Tip coordinates

Lateral Root Traits: - lateral_count - Number of lateral roots - lateral_lengths - Individual lateral root lengths - lateral_angles - Individual lateral root angles - lateral_base_xs, lateral_base_ys - Base point coordinates - lateral_tip_xs, lateral_tip_ys - Tip point coordinates - base_length - Length of lateral root zone on primary - base_ct_density - Lateral root density

Network Traits: - network_length - Total root system length - network_width_depth_ratio - W:D ratio - network_distribution - Root distribution metrics - network_solidity - Compactness measure - convhull_area, convhull_perimeter - Convex hull features

Example

import sleap_roots as sr

# Load dicot plant
series = sr.Series.load(
    "arabidopsis_1",
    h5_path="data.h5",
    primary_path="primary.slp",
    lateral_path="lateral.slp"
)

# Run pipeline
pipeline = sr.DicotPipeline()
traits = pipeline.fit_series(series)

# Access specific traits
print(f"Primary length: {traits['primary_length']:.2f} px")
print(f"Lateral count: {traits['lateral_count']}")
print(f"Total network length: {traits['network_length']:.2f} px")
print(f"W:D ratio: {traits['network_width_depth_ratio']:.2f}")

# Export
import json
with open("traits.json", "w") as f:
    json.dump(traits, f, indent=2, cls=sr.NumpyArrayEncoder)

See Also:


MultipleDicotPipeline

MultipleDicotPipeline

Bases: Pipeline

Pipeline for computing traits for multiple dicot plants.

Overview

For analyzing multiple dicot plants in the same field of view.

Root System: Primary root + Lateral roots (per plant) Plant Count: Multiple plants per series Use Case: High-throughput screening, population studies

Computed Traits

Same as DicotPipeline but computed per plant: - Traits are arrays where each element = one plant - Allows comparison between plants in same image - Handles varying numbers of lateral roots per plant

Example

import sleap_roots as sr

# Load multiple dicot plants
series = sr.Series.load(
    "canola_multipl e",
    h5_path="data.h5",
    primary_path="primary.slp",
    lateral_path="lateral.slp"
)

# Run pipeline
pipeline = sr.MultipleDicotPipeline()
traits = pipeline.fit_series(series)

# Traits are arrays (one value per plant)
import numpy as np
print(f"Number of plants: {len(traits['primary_length'])}")
print(f"Mean primary length: {np.nanmean(traits['primary_length']):.2f} px")
print(f"Lateral counts per plant: {traits['lateral_count']}")

# Per-plant analysis
for i, length in enumerate(traits['primary_length']):
    lat_count = traits['lateral_count'][i]
    print(f"Plant {i}: primary={length:.1f}px, laterals={lat_count}")

See Also:


YoungerMonocotPipeline

YoungerMonocotPipeline

Bases: Pipeline

Pipeline for computing traits for young monocot plants (primary + crown roots).

Attributes:

Name Type Description
img_height int

Image height.

n_scanlines int

Number of scan lines, np.nan for no interaction.

network_fraction float

Lower fraction value. Defaults to 2/3.

Overview

For analyzing young monocot plants with emerging crown root systems (e.g., rice, wheat, maize at early stages).

Root System: Crown roots Plant Count: Single plant per series Use Case: Early-stage monocot seedlings

Computed Traits

Crown Root Traits (per root): - crown_lengths - Individual crown root lengths - crown_angles - Individual crown root angles - crown_tip_xs, crown_tip_ys - Tip coordinates

Network Traits: - network_length - Total crown root length - network_width_depth_ratio - W:D ratio - network_distribution - Root distribution - convhull_area, convhull_perimeter - Spatial metrics

Example

import sleap_roots as sr

# Load young monocot
series = sr.Series.load(
    "rice_seedling",
    h5_path="data.h5",
    crown_path="crown.slp"
)

# Run pipeline
pipeline = sr.YoungerMonocotPipeline()
traits = pipeline.fit_series(series)

# Analyze crown roots
import numpy as np
crown_lengths = traits['crown_lengths']
print(f"Number of crown roots: {len(crown_lengths)}")
print(f"Mean crown root length: {np.nanmean(crown_lengths):.2f} px")
print(f"Crown root angles: {traits['crown_angles']}")

See Also:


OlderMonocotPipeline

OlderMonocotPipeline

Bases: Pipeline

Pipeline for computing traits for older monocot plants (crown roots only).

Attributes:

Name Type Description
img_height int

Image height.

n_scanlines int

Number of scan lines, np.nan for no interaction.

network_fraction float

Lower fraction value. Defaults to 2/3.

Overview

For analyzing mature monocot plants with established crown root systems.

Root System: Crown roots (mature) Plant Count: Single plant per series Use Case: Later-stage monocot plants with complex root architecture

Computed Traits

Similar to YoungerMonocotPipeline with additional metrics for mature root systems: - More robust network analysis - Additional spatial distribution metrics - Optimized for denser root systems

Example

import sleap_roots as sr

# Load mature monocot
series = sr.Series.load(
    "wheat_mature",
    h5_path="data.h5",
    crown_path="crown.slp"
)

# Run pipeline
pipeline = sr.OlderMonocotPipeline()
traits = pipeline.fit_series(series)

# Analyze mature root system
print(f"Network length: {traits['network_length']:.2f} px")
print(f"W:D ratio: {traits['network_width_depth_ratio']:.2f}")
print(f"Root system solidity: {traits['network_solidity']:.3f}")

See Also:


PrimaryRootPipeline

PrimaryRootPipeline

Bases: Pipeline

Pipeline for computing traits for a single primary root.

Overview

For analyzing plants with only primary root (no laterals tracked).

Root System: Primary root only Plant Count: Single plant per series Use Case: Primary root-focused analysis, plants before lateral emergence

Computed Traits

Primary Root Traits: - primary_length - Total primary root length - primary_angle - Gravitropic angle - primary_tip_x, primary_tip_y - Tip position - curve_index - Root curvature measure

Example

import sleap_roots as sr

# Load plant with primary root only
series = sr.Series.load(
    "early_seedling",
    h5_path="data.h5",
    primary_path="primary.slp"
)

# Run pipeline
pipeline = sr.PrimaryRootPipeline()
traits = pipeline.fit_series(series)

# Analyze primary root
print(f"Primary length: {traits['primary_length']:.2f} px")
print(f"Gravitropic angle: {traits['primary_angle']:.1f}°")
print(f"Curvature index: {traits['curve_index']:.3f}")

See Also:


MultiplePrimaryRootPipeline

MultiplePrimaryRootPipeline

Bases: Pipeline

Pipeline for computing traits for multiple primary roots.

Overview

For analyzing multiple plants, each with a primary root.

Root System: Primary roots (one per plant) Plant Count: Multiple plants per series Use Case: High-throughput primary root phenotyping

Computed Traits

Same as PrimaryRootPipeline but as arrays (one value per plant).

Example

import sleap_roots as sr

# Load multiple plants
series = sr.Series.load(
    "primary_array",
    h5_path="data.h5",
    primary_path="primary.slp"
)

# Run pipeline
pipeline = sr.MultiplePrimaryRootPipeline()
traits = pipeline.fit_series(series)

# Per-plant analysis
import numpy as np
n_plants = len(traits['primary_length'])
print(f"Analyzed {n_plants} plants")
print(f"Mean length: {np.nanmean(traits['primary_length']):.2f} px")
print(f"Mean angle: {np.nanmean(traits['primary_angle']):.1f}°")

# Compare plants
for i in range(n_plants):
    print(f"Plant {i}: {traits['primary_length'][i]:.1f} px, {traits['primary_angle'][i]:.1f}°")

See Also:


LateralRootPipeline

LateralRootPipeline

Bases: Pipeline

Pipeline just for computing traits for lateral roots.

Overview

For analyzing lateral roots independently (without primary root context).

Root System: Lateral roots only Plant Count: Single plant per series Use Case: Lateral root-specific studies, cases where primary isn't tracked

Computed Traits

Lateral Root Traits: - lateral_count - Number of lateral roots - lateral_lengths - Individual lateral lengths - lateral_angles - Individual lateral angles - lateral_tip_xs, lateral_tip_ys - Tip coordinates

Example

import sleap_roots as sr

# Load lateral roots only
series = sr.Series.load(
    "lateral_study",
    h5_path="data.h5",
    lateral_path="lateral.slp"
)

# Run pipeline
pipeline = sr.LateralRootPipeline()
traits = pipeline.fit_series(series)

# Analyze laterals
import numpy as np
print(f"Lateral count: {traits['lateral_count']}")
print(f"Mean lateral length: {np.nanmean(traits['lateral_lengths']):.2f} px")
print(f"Lateral angles: {traits['lateral_angles']}")

See Also:


Pipeline Comparison

Trait Coverage

Trait Category Dicot Multiple Dicot Younger Monocot Older Monocot Primary Multiple Primary Lateral
Primary Root ✓ ✓ - - ✓ ✓ -
Lateral Roots ✓ ✓ - - - - ✓
Crown Roots - - ✓ ✓ - - -
Network Metrics ✓ ✓ ✓ ✓ - - -
Convex Hull ✓ ✓ ✓ ✓ - - -
Multi-Plant - ✓ - - - ✓ -

Performance Considerations

Trait extraction performance (measured on GitHub Actions Ubuntu 22.04 runners):

  • Single plant pipelines: ~0.1-0.5s per plant
  • DicotPipeline, YoungerMonocotPipeline, OlderMonocotPipeline
  • PrimaryRootPipeline, LateralRootPipeline
  • Multiple plant pipelines: ~0.5-2s depending on plant count
  • MultipleDicotPipeline, MultiplePrimaryRootPipeline

Performance testing: All pipelines have automated benchmarks in the test suite. See Benchmarking Guide for details on running performance tests locally.

Note: Actual performance depends on: - Number and complexity of roots in the image - Plant developmental stage (more roots = longer processing) - Hardware specifications (CPU, memory) - Frame count in the series (72 frames is typical)


Advanced Usage

Custom Trait Filtering

import sleap_roots as sr

series = sr.Series.load("plant", primary_path="p.slp", lateral_path="l.slp")
pipeline = sr.DicotPipeline()
all_traits = pipeline.fit_series(series)

# Extract only length-related traits
length_traits = {
    k: v for k, v in all_traits.items()
    if 'length' in k
}

# Extract only lateral traits
lateral_traits = {
    k: v for k, v in all_traits.items()
    if 'lateral' in k
}

Batch Processing

import sleap_roots as sr
from pathlib import Path

# Load all plants
plants = sr.load_series_from_slps(
    "data/experiment1/",
    primary_pattern="*primary*.slp",
    lateral_pattern="*lateral*.slp"
)

# Process with pipeline
pipeline = sr.DicotPipeline()
results = []

for series in plants:
    try:
        traits = pipeline.fit_series(series)
        traits['plant_id'] = series.series_name
        results.append(traits)
    except Exception as e:
        print(f"Failed on {series.series_name}: {e}")

# Export to CSV
import pandas as pd
df = pd.DataFrame(results)
df.to_csv("batch_results.csv", index=False)
print(f"Processed {len(results)} plants")

Combining with Quality Control

import sleap_roots as sr

series = sr.Series.load(
    "plant1",
    primary_path="primary.slp",
    lateral_path="lateral.slp"
)

# Set QC expectations
series.expected_count(primary=1, lateral=5)

# Only process if QC passes
if not series.qc_fail():
    pipeline = sr.DicotPipeline()
    traits = pipeline.fit_series(series)
    print("✓ Traits computed successfully")
else:
    print("✗ QC failed - skipping trait computation")

  • Series - Loading data for pipelines
  • Trait Modules - Individual trait computation functions used by pipelines
  • Summary - Exporting pipeline results

See Also