Skip to content

Commit

Permalink
Predicate and programmable filters
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Ramsey committed Jun 24, 2013
1 parent ab5f008 commit 66c71c9
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 0 deletions.
94 changes: 94 additions & 0 deletions doc/pipeline/filters.predicate.txt
@@ -0,0 +1,94 @@
.. _filters.predicate:

filters.predicate
=================

Like the ref:`filters.programmable` filter, the predicate filter applies a `Python`_ function to a stream of points. Points can be retained/removed from the stream by setting true/false values into a special "Mask" dimension in the output point array.

.. code-block:: python

import numpy as np

def filter(ins,outs):
cls = ins['Classification']

keep_classes = [1,2]

# Use the first test for our base array.
keep = np.equal(cls, keep_classes[0])

# For 1:n, test each predicate and join back
# to our existing predicate array
for k in range(1,len(keep_classes)):
t = np.equal(cls, keep_classes[k])
keep = keep + t

outs['Mask'] = keep
return True

The example above sets the "mask" to true for points that are in classifications 1 or 2 and to false otherwise, causing points that are not classified 1 or 2 to be dropped from the point stream.

Example
-------

.. code-block:: xml

<?xml version="1.0" encoding="utf-8"?>
<Pipeline version="1.0">
<Writer type="drivers.las.writer">
<Option name="filename">
file-cropped.las
</Option>
<Filter type="filters.predicate">
<Option name="function">filter</Option>
<Option name="module">anything</Option>
<Option name="source">

import numpy as np

import numpy as np

def filter(ins,outs):
cls = ins['Classification']

keep_classes = [1,2]

# Use the first test for our base array.
keep = np.equal(cls, keep_classes[0])

# For 1:n, test each predicate and join back
# to our existing predicate array
for k in range(1,len(keep_classes)):
t = np.equal(cls, keep_classes[k])
keep = keep + t

outs['Mask'] = keep
return True

</Option>
<Reader type="drivers.las.reader">
<Option name="filename">
file-input.las
</Option>
</Reader>
</Filter>
</Writer>
</Pipeline>


Options
-------

script
When reading a function from a separate `Python`_ file, the file name to read from. [Example: functions.py]

module
The Python module that is holding the function to run. [Required]

function
The function to call.



.. _Python: http://python.org
.. _NumPy: http://www.numpy.org/
79 changes: 79 additions & 0 deletions doc/pipeline/filters.programmable.txt
@@ -0,0 +1,79 @@
.. _filters.programmable:

filters.programmable
====================

The programmable filter takes a stream of points and applies a `Python`_ function to each point in the stream.

The function must have two `NumPy`_ arrays as arguments, `ins` and `outs`. The `ins` array represents input points, the `outs` array represents output points. Each array contains all the dimensions of the point schema, for a number of points (depending on how large a point buffer the pipeline is processing at the time, a run-time consideration). Individual arrays for each dimension can be read from the input point and written to the output point.

This example scales the Z value by a factor of ten (of course, you could also use :ref:`filters.scaling` to achieve the same result.

.. code-block:: python

import numpy as np

def multiply_z(ins,outs):
Z = ins['Z']
Z = Z * 10.0
outs['Z'] = Z
return True

Note that the function always returns `True`. If the function returned `False`, an error would be thrown and the translation shut down.

To filter points based on a `Python`_ function, use the :ref:`filters.predicate` filter.

Example
-------

.. code-block:: xml

<?xml version="1.0" encoding="utf-8"?>
<Pipeline version="1.0">
<Writer type="drivers.las.writer">
<Option name="filename">
file-cropped.las
</Option>
<Filter type="filters.programmable">
<Option name="function">classify</Option>
<Option name="module">anything</Option>
<Option name="source">

import numpy as np

def classify(ins,outs):

# Classify all high first-returns
high = np.greater(ins['Z'],1000)
first_return = np.equal(ins['ReturnNumber'],1)
class = np.logical_and(high, first_return)
outs['Classification'] = class

return True

</Option>
<Reader type="drivers.las.reader">
<Option name="filename">
file-input.las
</Option>
</Reader>
</Filter>
</Writer>
</Pipeline>


Options
-------

script
When reading a function from a separate `Python`_ file, the file name to read from. [Example: functions.py]

module
The Python module that is holding the function to run. [Required]

function
The function to call.


.. _Python: http://python.org
.. _NumPy: http://www.numpy.org/
2 changes: 2 additions & 0 deletions doc/pipeline/index.txt
Expand Up @@ -27,5 +27,7 @@ Filters
filters.crop
filters.decimation
filters.inplacereprojection
filters.predicate
filters.programmable


0 comments on commit 66c71c9

Please sign in to comment.