Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add histogram plotting workshop exercise
- Loading branch information
Showing
8 changed files
with
203 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pdal pipeline c:/Users/hobu/PDAL/exercises/python/histogram.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"pipeline":[ | ||
{ | ||
"filename":"c:/Users/hobu/PDAL/exercies/python/athletic-fields.laz" | ||
}, | ||
{ | ||
"type":"filters.programmable", | ||
"function":"make_plot", | ||
"module":"anything", | ||
"pdalargs":"{\"filename\":\"histogram.png\"}", | ||
"script":"c:/Users/hobu/PDAL/exercies/python/histogram.py" | ||
}, | ||
{ | ||
"type":"writers.null" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# import numpy | ||
import numpy as np | ||
|
||
# import matplotlib stuff and make sure to use the | ||
# AGG renderer. | ||
import matplotlib | ||
matplotlib.use('Agg') | ||
import matplotlib.pyplot as plt | ||
import matplotlib.mlab as mlab | ||
|
||
# This only works for Python 3. Use | ||
# StringIO for Python 2. | ||
from io import BytesIO | ||
|
||
# The make_plot function will do all of our work. The | ||
# filters.programmable filter expects a function name in the | ||
# module that has at least two arguments -- "ins" which | ||
# are numpy arrays for each dimension, and the "outs" which | ||
# the script can alter/set/adjust to have them updated for | ||
# further processing. | ||
def make_plot(ins, outs): | ||
|
||
# figure position and row will increment | ||
figure_position = 1 | ||
row = 1 | ||
|
||
fig = plt.figure(figure_position, figsize=(6, 8.5), dpi=300) | ||
|
||
for key in ins: | ||
dimension = ins[key] | ||
ax = fig.add_subplot(len(ins.keys()), 1, row) | ||
|
||
# histogram the current dimension with 30 bins | ||
n, bins, patches = ax.hist( dimension, 30, | ||
normed=0, | ||
facecolor='grey', | ||
alpha=0.75, | ||
align='mid', | ||
histtype='stepfilled', | ||
linewidth=None) | ||
|
||
# Set plot particulars | ||
ax.set_ylabel(key, size=10, rotation='horizontal') | ||
ax.get_xaxis().set_visible(False) | ||
ax.set_yticklabels('') | ||
ax.set_yticks((),) | ||
ax.set_xlim(min(dimension), max(dimension)) | ||
ax.set_ylim(min(n), max(n)) | ||
|
||
# increment plot position | ||
row = row + 1 | ||
figure_position = figure_position + 1 | ||
|
||
# We will save the PNG bytes to a BytesIO instance | ||
# and the nwrite that to a file. | ||
output = BytesIO() | ||
plt.savefig(output,format="PNG") | ||
|
||
# a module global variable, called 'pdalargs' is available | ||
# to filters.programmable and filters.predicate modules that contains | ||
# a dictionary of arguments that can be explicitly passed into | ||
# the module by the user. We passed in a filename arg in our `pdal pipeline` call | ||
if 'filename' in pdalargs: | ||
filename = pdalargs['filename'] | ||
else: | ||
filename = 'histogram.png' | ||
|
||
# open up the filename and write out the | ||
# bytes of the PNG stored in the BytesIO instance | ||
o = open(filename, 'wb') | ||
o.write(output.getvalue()) | ||
o.close() | ||
|
||
|
||
# filters.programmable scripts need to | ||
# return True to tell the filter it was successful. | ||
return True | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
.. _workshop-histogram: | ||
|
||
Plotting a histogram | ||
================================================================================ | ||
|
||
.. include:: ../../includes/substitutions.rst | ||
|
||
Exercise | ||
-------------------------------------------------------------------------------- | ||
|
||
PDAL doesn't provide every possible analysis option, but it strives to make it | ||
convenient to link PDAL to other places with substantial functionality. One of | ||
those is the Python/Numpy universe, which is accessed through PDAL's | ||
:ref:`python` bindings and the :ref:`filters.programmable` and | ||
:ref:`filters.predicate` filters. These tools allow you to manipulate point | ||
cloud data with convenient Python tools rather than constructing substantial | ||
C/C++ software to achieve simple tasks, compute simple statistics, or | ||
investigate data quality issues. | ||
|
||
This exercise uses PDAL to create a histogram plot of all of the dimensions of | ||
a file. `matplotlib`_ is a Python package for plotting graphs and figures, and | ||
we can use it in combination with the :ref:`python` bindings for PDAL to create | ||
a nice histogram. These histograms can be useful diagnostics in an analysis | ||
pipeline. We will combine a Python script to make a histogram plot with a | ||
:ref:`pipeline_command`. | ||
|
||
|
||
.. note:: | ||
|
||
Python allows you to enhance and build functionality that you can use | ||
in the context of other :ref:`pipeline` operations. | ||
|
||
|
||
PDAL Pipeline | ||
................................................................................ | ||
|
||
We're going to create a PDAL :ref:`pipeline` to tell PDAL to run our Python | ||
script in a :ref:`filters.programmable` stage. | ||
|
||
|
||
.. literalinclude:: ./histogram.json | ||
:linenos: | ||
|
||
.. note:: | ||
|
||
This pipeline is available in your workshop materials in the | ||
``./exercies/python/histogram.json`` file. | ||
|
||
|
||
Python script | ||
................................................................................ | ||
|
||
The following Python script will do the actual work of creating the histogram | ||
plot with `matplotlib`_. Store it as ``histogram.py`` next to the | ||
``histogram.json`` :ref:`pipeline` file above. The script is mostly regular | ||
Python except for the ``ins`` and ``outs`` arguments to the function -- those | ||
are special arguments that PDAL expects to be a dictionary of Numpy | ||
dictionaries. | ||
|
||
.. note:: | ||
|
||
This Python file is available in your workshop materials in the | ||
``./exercies/python/histogram.py`` file. | ||
|
||
.. literalinclude:: ./histogram.py | ||
:linenos: | ||
:emphasize-lines: 34-40 | ||
|
||
Run ``pdal pipeline`` | ||
................................................................................ | ||
|
||
.. literalinclude:: ./histogram-command.txt | ||
:linenos: | ||
|
||
Output | ||
................................................................................ | ||
|
||
.. image:: ../../images/python-histogram-command.png | ||
:target: ../../../_images/python-histogram-command.png | ||
|
||
.. image:: ../../images/python-histogram.png | ||
:target: ../../../_images/python-histogram.png | ||
|
||
Notes | ||
-------------------------------------------------------------------------------- | ||
|
||
.. index:: histogram, Python, matplotlib, Numpy | ||
|
||
1. :ref:`writers.null` simply swallows the output of the pipeline. We | ||
don't need to write any data. | ||
|
||
2. The ``pdalargs`` JSON needs to be escaped because a valid Python | ||
dictionary entry isn't always valid JSON. | ||
|
||
|
||
.. _`matplotlib`: https://matplotlib.org/ |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters