exeqpdal 0.1.0a1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. exeqpdal-0.1.0a1/.github/workflows/ci.yml +44 -0
  2. exeqpdal-0.1.0a1/.github/workflows/publish.yml +72 -0
  3. exeqpdal-0.1.0a1/.gitignore +149 -0
  4. exeqpdal-0.1.0a1/CHANGELOG.md +42 -0
  5. exeqpdal-0.1.0a1/CONTRIBUTING.md +77 -0
  6. exeqpdal-0.1.0a1/LICENSE +34 -0
  7. exeqpdal-0.1.0a1/PKG-INFO +184 -0
  8. exeqpdal-0.1.0a1/README.md +148 -0
  9. exeqpdal-0.1.0a1/docs/examples.md +171 -0
  10. exeqpdal-0.1.0a1/docs/exeqpdal_dev.md +318 -0
  11. exeqpdal-0.1.0a1/docs/publishing.md +68 -0
  12. exeqpdal-0.1.0a1/docs/troubleshooting.md +400 -0
  13. exeqpdal-0.1.0a1/exeqpdal/__init__.py +151 -0
  14. exeqpdal-0.1.0a1/exeqpdal/apps/__init__.py +30 -0
  15. exeqpdal-0.1.0a1/exeqpdal/apps/info.py +151 -0
  16. exeqpdal-0.1.0a1/exeqpdal/apps/pipeline_apps.py +178 -0
  17. exeqpdal-0.1.0a1/exeqpdal/apps/translate.py +89 -0
  18. exeqpdal-0.1.0a1/exeqpdal/core/__init__.py +26 -0
  19. exeqpdal-0.1.0a1/exeqpdal/core/config.py +269 -0
  20. exeqpdal-0.1.0a1/exeqpdal/core/executor.py +280 -0
  21. exeqpdal-0.1.0a1/exeqpdal/core/pipeline.py +309 -0
  22. exeqpdal-0.1.0a1/exeqpdal/exceptions.py +82 -0
  23. exeqpdal-0.1.0a1/exeqpdal/py.typed +2 -0
  24. exeqpdal-0.1.0a1/exeqpdal/stages/__init__.py +27 -0
  25. exeqpdal-0.1.0a1/exeqpdal/stages/base.py +184 -0
  26. exeqpdal-0.1.0a1/exeqpdal/stages/filters.py +468 -0
  27. exeqpdal-0.1.0a1/exeqpdal/stages/readers.py +236 -0
  28. exeqpdal-0.1.0a1/exeqpdal/stages/writers.py +163 -0
  29. exeqpdal-0.1.0a1/exeqpdal/types/__init__.py +17 -0
  30. exeqpdal-0.1.0a1/exeqpdal/types/dimensions.py +187 -0
  31. exeqpdal-0.1.0a1/pyproject.toml +149 -0
  32. exeqpdal-0.1.0a1/quickstart.py +192 -0
  33. exeqpdal-0.1.0a1/tests/conftest.py +368 -0
  34. exeqpdal-0.1.0a1/tests/test_apps_info.py +210 -0
  35. exeqpdal-0.1.0a1/tests/test_apps_pipeline_apps.py +183 -0
  36. exeqpdal-0.1.0a1/tests/test_apps_translate.py +184 -0
  37. exeqpdal-0.1.0a1/tests/test_copc_workflows.py +315 -0
  38. exeqpdal-0.1.0a1/tests/test_data_laz/DATASET.md +71 -0
  39. exeqpdal-0.1.0a1/tests/test_denoising_workflows.py +424 -0
  40. exeqpdal-0.1.0a1/tests/test_docs_examples.py +184 -0
  41. exeqpdal-0.1.0a1/tests/test_edge_cases.py +176 -0
  42. exeqpdal-0.1.0a1/tests/test_executor_real.py +320 -0
  43. exeqpdal-0.1.0a1/tests/test_integration_workflows.py +526 -0
  44. exeqpdal-0.1.0a1/tests/test_laz_to_database_writers.py +144 -0
  45. exeqpdal-0.1.0a1/tests/test_laz_to_raster_writers.py +117 -0
  46. exeqpdal-0.1.0a1/tests/test_laz_to_special_writers.py +105 -0
  47. exeqpdal-0.1.0a1/tests/test_laz_to_standard_writers.py +167 -0
  48. exeqpdal-0.1.0a1/tests/test_laz_to_text_writers.py +162 -0
  49. exeqpdal-0.1.0a1/tests/test_performance_benchmarks.py +439 -0
  50. exeqpdal-0.1.0a1/tests/test_pipeline_execution.py +170 -0
  51. exeqpdal-0.1.0a1/tests/test_spatial_operations.py +375 -0
  52. exeqpdal-0.1.0a1/tests/unit/test_config.py +48 -0
  53. exeqpdal-0.1.0a1/tests/unit/test_filter_factory.py +35 -0
  54. exeqpdal-0.1.0a1/tests/unit/test_pipeline.py +121 -0
  55. exeqpdal-0.1.0a1/tests/unit/test_reader_factory.py +41 -0
  56. exeqpdal-0.1.0a1/tests/unit/test_stage_base.py +89 -0
  57. exeqpdal-0.1.0a1/tests/unit/test_types_and_exceptions.py +52 -0
  58. exeqpdal-0.1.0a1/tests/unit/test_writer_factory.py +49 -0
@@ -0,0 +1,44 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+
9
+ jobs:
10
+ test:
11
+ name: Lint, type check, tests
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - name: Checkout repository
15
+ uses: actions/checkout@v5
16
+
17
+ - name: Set up Python
18
+ uses: actions/setup-python@v6
19
+ with:
20
+ python-version: "3.12"
21
+ cache: "pip"
22
+
23
+ - name: Install dependencies
24
+ run: |
25
+ python -m pip install --upgrade pip
26
+ pip install -e ".[dev]"
27
+
28
+ - name: Ruff format
29
+ run: ruff format . --check
30
+
31
+ - name: Ruff check
32
+ run: ruff check .
33
+
34
+ - name: Mypy
35
+ run: mypy exeqpdal
36
+
37
+ - name: Pytest (unit)
38
+ run: pytest -m "not integration" tests/
39
+
40
+ - name: Build package
41
+ run: |
42
+ rm -rf dist/
43
+ python -m build
44
+ twine check dist/*
@@ -0,0 +1,72 @@
1
+ name: Publish
2
+
3
+ on:
4
+ release:
5
+ types:
6
+ - published
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ build:
11
+ name: Build distribution
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - name: Checkout repository
15
+ uses: actions/checkout@v5
16
+
17
+ - name: Set up Python
18
+ uses: actions/setup-python@v6
19
+ with:
20
+ python-version: "3.12"
21
+ cache: "pip"
22
+
23
+ - name: Install dependencies
24
+ run: |
25
+ python -m pip install --upgrade pip
26
+ pip install -e ".[dev]"
27
+
28
+ - name: Ruff format
29
+ run: ruff format . --check
30
+
31
+ - name: Ruff check
32
+ run: ruff check .
33
+
34
+ - name: Mypy
35
+ run: mypy exeqpdal
36
+
37
+ - name: Pytest (unit)
38
+ run: pytest -m "not integration" tests/
39
+
40
+ - name: Build distribution
41
+ run: |
42
+ rm -rf dist/
43
+ python -m build
44
+ twine check dist/*
45
+
46
+ - name: Upload distribution artifact
47
+ uses: actions/upload-artifact@v4
48
+ with:
49
+ name: dist
50
+ path: dist/
51
+
52
+ publish:
53
+ name: Publish to PyPI
54
+ needs: build
55
+ runs-on: ubuntu-latest
56
+ environment:
57
+ name: pypi
58
+ url: https://pypi.org/project/exeqpdal/
59
+ permissions:
60
+ id-token: write
61
+ contents: read
62
+ steps:
63
+ - name: Download distribution artifact
64
+ uses: actions/download-artifact@v5
65
+ with:
66
+ name: dist
67
+ path: dist/
68
+
69
+ - name: Publish release
70
+ uses: pypa/gh-action-pypi-publish@release/v1
71
+ with:
72
+ packages-dir: dist/
@@ -0,0 +1,149 @@
1
+ # Python Artifacts
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+
7
+ # Build & Packaging Outputs
8
+ .Python
9
+ *.egg
10
+ *.egg-info/
11
+ *.manifest
12
+ *.spec
13
+ *.zip
14
+ .eggs/
15
+ .installed.cfg
16
+ MANIFEST
17
+ build/
18
+ builds/
19
+ develop-eggs/
20
+ dist/
21
+ downloads/
22
+ eggs/
23
+ lib/
24
+ lib64/
25
+ parts/
26
+ sdist/
27
+ share/python-wheels/
28
+ var/
29
+ wheels/
30
+
31
+ # Dependency Management
32
+ .pdm-build/
33
+ .pdm-python
34
+ .pdm.toml
35
+ Pipfile.lock
36
+ poetry.lock
37
+ uv.lock
38
+ __pypackages__/
39
+
40
+ # Virtual Environments
41
+ .env
42
+ .venv/
43
+ ENV/
44
+ env/
45
+ env.bak/
46
+ venv/
47
+ venv.bak/
48
+
49
+ # Testing & Coverage
50
+ .coverage
51
+ .coverage.*
52
+ .hypothesis/
53
+ .nox/
54
+ .pytest_cache/
55
+ .tox/
56
+ .cache
57
+ cover/
58
+ coverage.*
59
+ coverage.xml
60
+ htmlcov/
61
+ nosetests.xml
62
+ *.cover
63
+ *.py,cover
64
+
65
+ # Type Checkers & Linters
66
+ .dmypy.json
67
+ .mypy_cache/
68
+ .pyre/
69
+ .pytype/
70
+ .ruff_cache/
71
+ dmypy.json
72
+
73
+ # Editor & IDE Settings
74
+ .vscode/
75
+
76
+ # Jupyter / IPython Artifacts
77
+ .ipynb_checkpoints
78
+ ipython_config.py
79
+ profile_default/
80
+
81
+ # Logs & Temporary Files
82
+ *.log
83
+ *~
84
+ .*.swp
85
+ pip-delete-this-directory.txt
86
+ pip-log.txt
87
+
88
+ # Framework & Task Queue State
89
+ celerybeat-schedule
90
+ celerybeat.pid
91
+ db.sqlite3
92
+ db.sqlite3-journal
93
+ instance/
94
+ local_settings.py
95
+ .scrapy
96
+ .webassets-cache
97
+
98
+ # Documentation Outputs
99
+ docs/_build/
100
+ /site
101
+
102
+ # Translations
103
+ *.mo
104
+ *.pot
105
+
106
+ # Miscellaneous Python
107
+ *.sage.py
108
+
109
+ # PyPI Credentials
110
+ .pypirc
111
+
112
+ # QGIS Plugin Artifacts
113
+ *_ui.py
114
+ *.qgs~
115
+ *.qgz~
116
+ resources.py
117
+ symbology-style.db
118
+
119
+ # Operating System Artifacts
120
+ .DS_Store
121
+
122
+ # Project-Specific Artifacts
123
+ .archive/
124
+ */.archive/
125
+ **/.archive/
126
+ .backup/
127
+ */.backup/
128
+ **/.backup/
129
+ .conf/
130
+ .pwsh/
131
+ .python-version
132
+ .specify/
133
+ AGENTS.m
134
+ AGENTS.md
135
+ CLAUDE.md
136
+ GEMINI.md
137
+ logs/
138
+
139
+ # Workflow Automation
140
+ .claude/
141
+ .gemini/
142
+ .remote-workflow/
143
+ docs/claude/
144
+ docs/gemini/
145
+
146
+ # LAZ-to-writers Test Outputs
147
+ tests/laz_to_writers/outputs/*
148
+ !tests/laz_to_writers/outputs/.gitkeep
149
+ !tests/laz_to_writers/outputs/README.md
@@ -0,0 +1,42 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and
6
+ [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.1.0a1] - 2025-10-16
11
+
12
+ `exeqpdal 0.1.0a1` is under active development and has not yet been published to PyPI.
13
+
14
+ ### Added
15
+ - Pipeline orchestration with the `Pipeline` class, including `validate`, metadata access, and point
16
+ count parsing.
17
+ - Stage factories covering the most frequently used PDAL drivers (~40 readers, 80+ filters, 25
18
+ writers).
19
+ - High-level wrappers for PDAL CLI applications: `info`, `translate`/`convert`, `merge`, `split`,
20
+ `tile`, and `tindex`.
21
+ - PDAL discovery and configuration utilities (`set_pdal_path`, `get_pdal_version`, `validate_pdal`,
22
+ `set_verbose`).
23
+ - Custom exception hierarchy (`PDALError`, `PipelineError`, `PDALExecutionError`, etc.).
24
+ - Packaging metadata with `py.typed` for downstream type checkers.
25
+
26
+ ### Testing
27
+ - Pytest suite covering pipeline assembly, stage factories, and application wrappers.
28
+ - Integration tests gated by `@pytest.mark.integration` and the `EXEQPDAL_TEST_DATA` fixture
29
+ directory.
30
+ - Strict typing enforced via `mypy --strict`.
31
+
32
+ ### Tooling
33
+ - Added GitHub Actions for CI (`ci.yml`) and publishing (`publish.yml`), plus a release guide
34
+ (`docs/publishing.md`) and supporting development dependencies.
35
+
36
+ ### Known Limitations
37
+ - `Pipeline.arrays` is not yet implemented and currently returns an empty list.
38
+ - Stage factories do not yet expose every PDAL driver; unsupported stages can be invoked with custom
39
+ JSON.
40
+ - First PyPI upload is still pending while the initial alpha stabilises.
41
+
42
+ ---
@@ -0,0 +1,77 @@
1
+ # Contributing to exeqpdal
2
+
3
+ Thank you for your interest in contributing to `exeqpdal`! All contributions are welcome, from bug reports to new features.
4
+
5
+ ## Development Setup
6
+
7
+ 1. Fork and clone the repository:
8
+
9
+ ```bash
10
+ git clone https://github.com/YOUR-USERNAME/exeqpdal.git
11
+ cd exeqpdal
12
+ ```
13
+
14
+ 2. Create a virtual environment and install dependencies. We recommend
15
+ [`uv`](https://github.com/astral-sh/uv):
16
+
17
+ ```bash
18
+ uv pip install -e ".[dev]"
19
+ ```
20
+
21
+ When `uv` is not available, fall back to standard tooling:
22
+
23
+ ```bash
24
+ python -m venv .venv
25
+ source .venv/bin/activate
26
+ pip install -e ".[dev]"
27
+ ```
28
+
29
+ 3. Verify the toolchain by running the default formatting, linting, typing, and test commands:
30
+
31
+ ```bash
32
+ ruff format .
33
+ ruff check .
34
+ mypy exeqpdal
35
+ pytest tests/
36
+ ```
37
+
38
+ Integration tests require the PDAL CLI and LAZ/COPC test datasets in `tests/test_data_laz/`.
39
+ Tests automatically skip when PDAL or test data are unavailable. Add `-m "not integration"`
40
+ to skip integration tests entirely.
41
+
42
+ ## Development Workflow
43
+
44
+ - Create a new branch for your changes.
45
+ - Make your changes and add tests for them.
46
+ - Make sure all tests pass, including the linters and type checkers:
47
+
48
+ ```bash
49
+ ruff format .
50
+ ruff check .
51
+ mypy exeqpdal
52
+ pytest tests/
53
+ ```
54
+
55
+ Use `pytest -m "not integration"` to skip tests requiring PDAL and test datasets. Keep test
56
+ outputs (especially under `tests/laz_to_writers/outputs/`) out of commits.
57
+
58
+ - Commit your changes using the existing Conventional Commit prefixes (for example,
59
+ `fix: handle PDAL path lookup`) and push them to your fork.
60
+ - Open a pull request that explains the scenario, any data prerequisites, and how you validated the
61
+ change.
62
+
63
+ ## Release Management
64
+
65
+ Maintainers preparing a PyPI upload should follow the checklist in `docs/publishing.md`. It covers
66
+ versioning, changelog updates, local validation (`ruff`, `mypy`, `pytest`, `python -m build`), and
67
+ the GitHub Actions workflow that publishes releases through PyPI's Trusted Publisher integration.
68
+
69
+ ## Code Style
70
+
71
+ This project uses `ruff` for both formatting and linting with the settings defined in
72
+ `pyproject.toml`. Four-space indentation, 100-character lines, and double-quoted strings are applied
73
+ by `ruff format`.
74
+
75
+ ## License
76
+
77
+ By contributing to this project, you agree that your contributions will be licensed under the MIT License.
@@ -0,0 +1,34 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 exeqpdal contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ This project includes software developed by the PDAL project (https://pdal.io/).
26
+ Copyright (c) 2025, Hobu, Inc. (howard@hobu.co)
27
+ All rights reserved.
28
+
29
+ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
30
+
31
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
32
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
33
+
34
+ IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,184 @@
1
+ Metadata-Version: 2.4
2
+ Name: exeqpdal
3
+ Version: 0.1.0a1
4
+ Summary: Python API for executing PDAL CLI commands with native syntax support
5
+ Project-URL: Homepage, https://github.com/elgorrion/exeqpdal
6
+ Project-URL: Documentation, https://github.com/elgorrion/exeqpdal#readme
7
+ Project-URL: Repository, https://github.com/elgorrion/exeqpdal
8
+ Project-URL: Bug Tracker, https://github.com/elgorrion/exeqpdal/issues
9
+ Project-URL: Changelog, https://github.com/elgorrion/exeqpdal/blob/main/CHANGELOG.md
10
+ Project-URL: Source Code, https://github.com/elgorrion/exeqpdal
11
+ Author-email: ElGorrion <elgorrion.eu@gmail.com>
12
+ License: MIT
13
+ License-File: LICENSE
14
+ Keywords: geospatial,lidar,pdal,pointcloud,qgis
15
+ Classifier: Development Status :: 3 - Alpha
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Intended Audience :: Science/Research
18
+ Classifier: License :: OSI Approved :: MIT License
19
+ Classifier: Natural Language :: English
20
+ Classifier: Operating System :: OS Independent
21
+ Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: Scientific/Engineering :: GIS
24
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
+ Classifier: Typing :: Typed
26
+ Requires-Python: >=3.12
27
+ Requires-Dist: numpy>=1.26.4
28
+ Provides-Extra: dev
29
+ Requires-Dist: build>=1.3.0; extra == 'dev'
30
+ Requires-Dist: mypy>=1.18.2; extra == 'dev'
31
+ Requires-Dist: pytest-cov>=7.0.0; extra == 'dev'
32
+ Requires-Dist: pytest>=8.4.2; extra == 'dev'
33
+ Requires-Dist: ruff>=0.14.0; extra == 'dev'
34
+ Requires-Dist: twine>=6.2.0; extra == 'dev'
35
+ Description-Content-Type: text/markdown
36
+
37
+ # exeqpdal
38
+
39
+ Alpha-stage, typed Python API for driving the PDAL command-line interface (CLI).
40
+
41
+ `exeqpdal` focuses on being a reliable subprocess wrapper around the PDAL CLI so that Python
42
+ projects – including QGIS plugins – can assemble and run PDAL pipelines without shipping
43
+ C++ bindings. The current release series is `0.1.0a*` and is still stabilising APIs and
44
+ coverage.
45
+
46
+ ## Features
47
+
48
+ - **Pythonic pipelines** – build PDAL JSON using `Reader`, `Filter`, and `Writer`
49
+ factories chained with the `|` operator, then execute with `Pipeline`.
50
+ - **CLI-first design** – no native extensions; every operation delegates to the PDAL
51
+ executable via `subprocess.run`.
52
+ - **Strict typing** – the package ships `py.typed`, is developed under `mypy --strict`,
53
+ and exposes typed factory helpers.
54
+ - **Convenience apps** – wrappers for PDAL tools such as `info`, `translate`, `merge`, `split`,
55
+ `tile`, and `tindex`.
56
+ - **Broad stage coverage** – factories currently expose ~40 readers, 80+ filters, and 25 writers.
57
+ Coverage is expanding; unsupported drivers can still be addressed through custom JSON.
58
+ - **QGIS-friendly** – automatic PDAL discovery checks PATH, `PDAL_EXECUTABLE`, and
59
+ common QGIS 3.4x Windows installs.
60
+
61
+ ## Prerequisites
62
+
63
+ - Python 3.12+
64
+ - PDAL CLI installed and accessible (system PATH, `PDAL_EXECUTABLE`, or detected in QGIS on
65
+ Windows)
66
+
67
+ ## Installation
68
+
69
+ The first public alpha will be published to PyPI using GitHub Actions. Once the release is
70
+ live, you can install it directly (include `--pre` while the project is in alpha):
71
+
72
+ ```bash
73
+ pip install --pre exeqpdal
74
+ ```
75
+
76
+ Until the package is uploaded, install from a local clone:
77
+
78
+ ```bash
79
+ # From the project root
80
+ pip install -e .
81
+
82
+ # Or install with development extras
83
+ uv pip install -e ".[dev]"
84
+ ```
85
+
86
+ ## Quick Start
87
+
88
+ ### Convert a File
89
+
90
+ ```python
91
+ import exeqpdal as pdal
92
+
93
+ pdal.translate("input.las", "output.laz")
94
+ ```
95
+
96
+ ### Filter Ground Points
97
+
98
+ ```python
99
+ import exeqpdal as pdal
100
+
101
+ pipeline = (
102
+ pdal.Reader.las("input.las")
103
+ | pdal.Filter.range(limits="Classification[2:2]")
104
+ | pdal.Writer.las("ground_only.las")
105
+ )
106
+ pipeline.execute()
107
+ ```
108
+
109
+ ### Get File Information
110
+
111
+ ```python
112
+ from exeqpdal import info
113
+
114
+ info_data = info("input.las", stats=True)
115
+ print(info_data)
116
+ ```
117
+
118
+ For more examples, see the [examples documentation](docs/examples.md).
119
+
120
+ ## Supported Components
121
+
122
+ Factory helpers cover the most commonly used PDAL readers, writers, and filters. For the
123
+ definitive driver reference, consult the
124
+ [PDAL documentation](https://pdal.io/en/stable/stages/stages.html). If a driver is
125
+ missing, you can still run it by injecting raw dictionaries into a `Pipeline`.
126
+
127
+ ## Error Handling
128
+
129
+ `exeqpdal` raises custom exceptions to surface PDAL CLI failures and configuration issues.
130
+
131
+ ```python
132
+ import exeqpdal as pdal
133
+
134
+ try:
135
+ pipeline = pdal.Pipeline(
136
+ pdal.Reader.las("non_existent_file.las") | pdal.Writer.las("output.las")
137
+ )
138
+ pipeline.execute()
139
+ except pdal.PipelineError as exc:
140
+ print(f"Pipeline execution failed: {exc}")
141
+ ```
142
+
143
+ ## Configuration
144
+
145
+ ### Custom PDAL Path
146
+
147
+ If PDAL is not in your system's PATH, you can set the path to the `pdal` executable manually:
148
+
149
+ ```python
150
+ import exeqpdal as pdal
151
+
152
+ pdal.set_pdal_path("/path/to/your/pdal")
153
+ ```
154
+
155
+ ### Verbose Output
156
+
157
+ Enable verbose output to see the PDAL command being executed and its output:
158
+
159
+ ```python
160
+ import exeqpdal as pdal
161
+
162
+ pdal.set_verbose(True)
163
+ ```
164
+
165
+ ## Project Status & Limitations
166
+
167
+ - `Pipeline.arrays` is not yet implemented – it currently returns an empty list even after
168
+ execution.
169
+ - Integration tests use six LAZ/COPC test datasets in `tests/test_data_laz/` covering various
170
+ scenarios (filtered/non-filtered data, small/mid/large sizes, LAS/COPC formats). Tests
171
+ automatically skip when PDAL or test data are unavailable. See `tests/test_data_laz/DATASET.md`
172
+ for dataset details.
173
+ - Stage coverage is broad but incomplete. Missing drivers can be added by extending the factory
174
+ modules or by building custom JSON.
175
+
176
+ ## License
177
+
178
+ `exeqpdal` is licensed under the MIT License.
179
+
180
+ This project is a wrapper around the PDAL command-line tool, which is licensed under the
181
+ BSD license. When using `exeqpdal`, you are also using PDAL, and you should be aware of
182
+ its license.
183
+
184
+ If you are using `exeqpdal` in a QGIS plugin, you should also be aware of the QGIS license (GPLv2+).