Skip to main content
Instead of writing JSON strings, you can construct pipelines programmatically using Python objects. This approach provides better IDE support, type checking, and code reusability.

Building pipelines with Stage objects

A pipeline constructed with the pipe operator is equivalent to a JSON pipeline:
import pdal
pipeline = pdal.Reader("1.2-with-color.las") | pdal.Filter.sort(dimension="X")
This creates the same pipeline as the JSON example in the basic usage guide.

Stage types

PDAL Python provides three types of stages:
  • pdal.Reader - Reads data from files or sources
  • pdal.Filter - Transforms or filters point cloud data
  • pdal.Writer - Writes data to files or destinations

Creating stages

Stages accept keyword arguments that correspond to PDAL stage options:
# Reader with filename as positional argument
reader = pdal.Reader("input.las")

# Filter with options as keyword arguments
filter_stage = pdal.Filter.sort(dimension="X")

# Writer with multiple options
writer = pdal.Writer.las(
    filename="output.las",
    offset_x="auto",
    offset_y="auto",
    scale_x=0.01
)
The filename option for Readers and Writers, and the type option for Filters can be passed as the first positional argument.

Using the pipe operator

The pipe operator (|) connects stages together to form a pipeline:
pipeline = pdal.Reader("1.2-with-color.las") | pdal.Filter.sort(dimension="X")
You can chain multiple stages:
pipeline = reader | filter1 | filter2 | writer

Pipe operator combinations

The pipe operator works with various combinations:
# Stage | Stage
pipeline = stage1 | stage2

# Stage | Pipeline
pipeline = stage1 | existing_pipeline

# Pipeline | Stage
pipeline = existing_pipeline | stage1

# Pipeline | Pipeline
pipeline = pipeline1 | pipeline2
Every application of the pipe operator creates a new Pipeline instance.

Updating pipelines in-place

To update an existing pipeline without creating a new one, use the in-place pipe operator (|=):
# update pipeline in-place
pipeline = pdal.Pipeline()
pipeline |= stage
pipeline |= pipeline2

Stage factory methods

The Reader, Filter, and Writer classes provide static methods for all PDAL drivers. For example:
# These are equivalent
pdal.Filter.head(count=100)
pdal.Filter(type="filters.head", count=100)
These methods are auto-generated by introspecting PDAL, and include docstrings with available options:
>>> help(pdal.Filter.head)
Help on function head in module pdal.pipeline:

head(**kwargs)
    Return N points from beginning of the point cloud.

    user_data: User JSON
    log: Debug output filename
    option_file: File from which to read additional options
    where: Expression describing points to be passed to this filter
    where_merge='auto': If 'where' option is set, describes how skipped points should be merged with kept points in standard mode.
    count='10': Number of points to return from beginning.  If 'invert' is true, number of points to drop from the beginning.
    invert='false': If true, 'count' specifies the number of points to skip from the beginning.

Creating pipelines from stages

You can create a Pipeline instance in several ways:
# From a JSON string
pipeline = pdal.Pipeline(json_string)

# From a sequence of stages
pipeline = pdal.Pipeline([stage1, stage2])

# From a single stage
pipeline = stage.pipeline()

# Empty pipeline
pipeline = pdal.Pipeline()

Stage inputs

The inputs option allows you to specify stages that feed into the current stage:
stage = pdal.Filter.merge(inputs=[stage1, stage2])
Inputs can be either:
  • String tags of other stages
  • Stage instances themselves

Build docs developers (and LLMs) love