The dataset used in this example notebook is from the Nakadake Sanroku Kiln Site Center in Japan. The data set is provided by Shinoto et al. under the CC-BY-4.0 license: DOI
Selecting a filter pipeline for a dataset
[1]:
import afwizard
The goal of this notebook is to find the best fitting filter pipeline for a given dataset (or rather a suitably copped subset there of). If you want to manually create the filter pipeline from scratch, you should read the notebook on pipeline creation instead. Here, we assume that we want to leverage existing, community-contributed filter pipelines. In a first step, we select a number of filter pipeline candidates from filter libraries. Details about how to register
additional filter libraries, can be found in the notebook on filter libraries. We use the select_pipelines_from_library function, which allows us to select any number of filter by keeping CTRL pressed while clicking additional filters. In the left most column, we see filtering criterions we can use to access the filter pipelines in our filtering libraries. The middle column contains a list of filter pipelines that match the given criteria. Clicking one of these will
select it and show its metadata in the third column. Multiple filters can be selected by keeping CTRL pressed while clicking additional filters.
[2]:
pipelines = afwizard.select_pipelines_from_library()
---------------------------------------------------------------------------
AFwizardError Traceback (most recent call last)
Cell In[2], line 1
----> 1 pipelines = afwizard.select_pipelines_from_library()
File ~/checkouts/readthedocs.org/user_builds/afwizard/conda/stable/lib/python3.11/site-packages/afwizard/apps.py:1223, in select_pipelines_from_library()
1211 def select_pipelines_from_library():
1212 """The Jupyter UI to select filtering pipelines from libraries.
1213
1214 The use of this UI is described in detail in `the notebook on filtering libraries`_.
(...)
1220 :rtype: afwizard.filter.Pipeline
1221 """
-> 1223 return select_pipeline_from_library(multiple=True)
File ~/checkouts/readthedocs.org/user_builds/afwizard/conda/stable/lib/python3.11/site-packages/afwizard/apps.py:1045, in select_pipeline_from_library(multiple)
1040 # Collect checkboxes in the selection menu
1041 library_checkboxes = [
1042 ipywidgets.Checkbox(value=True, description=library_name(lib), indent=False)
1043 for lib in get_filter_libraries()
1044 ]
-> 1045 backend_checkboxes = {
1046 name: ipywidgets.Checkbox(value=cls.enabled(), description=name, indent=False)
1047 for name, cls in Filter._filter_impls.items()
1048 if Filter._filter_is_backend[name]
1049 }
1051 # Extract all authors that contributed to the filter libraries
1052 def get_author(f):
File ~/checkouts/readthedocs.org/user_builds/afwizard/conda/stable/lib/python3.11/site-packages/afwizard/apps.py:1046, in <dictcomp>(.0)
1040 # Collect checkboxes in the selection menu
1041 library_checkboxes = [
1042 ipywidgets.Checkbox(value=True, description=library_name(lib), indent=False)
1043 for lib in get_filter_libraries()
1044 ]
1045 backend_checkboxes = {
-> 1046 name: ipywidgets.Checkbox(value=cls.enabled(), description=name, indent=False)
1047 for name, cls in Filter._filter_impls.items()
1048 if Filter._filter_is_backend[name]
1049 }
1051 # Extract all authors that contributed to the filter libraries
1052 def get_author(f):
File ~/checkouts/readthedocs.org/user_builds/afwizard/conda/stable/lib/python3.11/site-packages/afwizard/lastools.py:139, in LASToolsFilter.enabled(cls)
137 @classmethod
138 def enabled(cls):
--> 139 return lastools_is_present()
File ~/checkouts/readthedocs.org/user_builds/afwizard/conda/stable/lib/python3.11/site-packages/afwizard/lastools.py:69, in lastools_is_present()
66 return False
68 # We return True iff a prefix was set
---> 69 return get_lastools_directory() is not None
File ~/checkouts/readthedocs.org/user_builds/afwizard/conda/stable/lib/python3.11/site-packages/afwizard/lastools.py:55, in get_lastools_directory()
53 dir = os.environ.get("LASTOOLS_DIR", None)
54 if dir is not None:
---> 55 set_lastools_directory(dir)
57 return _lastools_directory
File ~/checkouts/readthedocs.org/user_builds/afwizard/conda/stable/lib/python3.11/site-packages/afwizard/lastools.py:44, in set_lastools_directory(dir)
42 except AFwizardError as e:
43 _lastools_directory = None
---> 44 raise e
File ~/checkouts/readthedocs.org/user_builds/afwizard/conda/stable/lib/python3.11/site-packages/afwizard/lastools.py:41, in set_lastools_directory(dir)
38 if dir is not None:
39 try:
40 # If this throws, we show a meaningful error where we looked for LASTools
---> 41 lasground_executable(base=dir)
42 except AFwizardError as e:
43 _lastools_directory = None
File ~/checkouts/readthedocs.org/user_builds/afwizard/conda/stable/lib/python3.11/site-packages/afwizard/lastools.py:84, in lasground_executable(base)
82 fullpath = os.path.join(base, "bin", execname)
83 if not os.path.exists(fullpath):
---> 84 raise AFwizardError(f"Executable {fullpath} was not found!")
86 return fullpath
AFwizardError: Executable /home/docs/checkouts/readthedocs.org/user_builds/afwizard/checkouts/latest/LAStools/bin/lasground_new64.exe was not found!
Next thing to do is to load a dataset as described in Working with datasets. Again, it is best to restrict the sample size to a reasonable size (e.g. by using the restrict method on the dataset) to allow a truely interactive exploration process.
[3]:
dataset = afwizard.DataSet(
filename="nkd_pcl_epsg6670.laz", spatial_reference="EPSG:6670"
)
We can then create a comparison of ground point filtering results with the goal of choosing the most fitting pipeline. Each tab shows the filtering results of one of the selected pipelines. In the left column, we can fine tune visualization and rasterization options while on the right hand side, we can fine tune the filter. The configuration options shown here have been introduced by the author of the filter pipeline for you to fine tune the results:
[4]:
best = afwizard.select_best_pipeline(dataset, pipelines=pipelines)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[4], line 1
----> 1 best = afwizard.select_best_pipeline(dataset, pipelines=pipelines)
NameError: name 'pipelines' is not defined
The newly create filter pipeline object best has the end user configuration specified in the right column baked into the filter. This means that the resulting filter is to some extent a dataset-specific specialization of the general purpose filter pipeline. To distinguish such specialized filter from more general ones, it is useful to save it into a separate filtering library as outlined in the notebook on filtering libraries, e.g. by using
set_current_filter_library to set up a filtering library for your current project before saving any filters:
[5]:
afwizard.set_current_filter_library(
"projectx", create_dirs=True, name="Filters for projext X"
)
[6]:
afwizard.save_filter(best, "bestfilter.json")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[6], line 1
----> 1 afwizard.save_filter(best, "bestfilter.json")
NameError: name 'best' is not defined