{"name": "LiDAR Relief Visualization", "package_name": "lidar_relief", "version": "2.0.14", "experimental": false, "qgis_min": "3.0.0", "qgis_max": "4.99.0", "downloads": 234, "uploaded_by": "mabo", "upload_datetime": "2026-06-30T01:11:41.022872", "changelog": "## [2.0.14] - 2026-06-30\r\n\r\n### Fixed\r\n\r\n- **ImportError crash at plugin init on QGIS 4.0.3.** The `pdal_classify_algorithm.py`\r\n  file used the non-existent class name `QgsProcessingParameterOutputString` (a typo\r\n  confusing QGIS Processing's *input* Parameter classes with its *output* Output\r\n  classes). Changed to the correct `QgsProcessingOutputString` in both the `from\r\n  qgis.core import (...)` block and the `self.addOutput(...)` call site. This was the\r\n  only instance of this typo across the entire codebase.\r\n\r\n### Added\r\n\r\n- **Pre-commit + CI changelog guard.** A new `scripts/check_changelog.py` stdlib-only\r\n  script reads `version=` from `lidar_relief/metadata.txt` and verifies that\r\n  `CHANGELOG.md` contains a matching `## [X.Y.Z]` header. Integrated as a local-repo\r\n  `.pre-commit-config.yaml` hook and a hard-fail step in `.github/workflows/release.yml`\r\n  (before the `qgis-plugin-ci release` publish) and in `test.sh`. This ensures future\r\n  releases cannot ship with an empty GitHub Release body.\r\n\r\n### Changed\r\n\r\n- **Pre-merge hardening pass.** Incorporated local working-tree improvements for\r\n  NumPy 2 deprecation compatibility (`int8` \u2192 `int16`/`uint8` type promotions),\r\n  rio-cogeo reprojection alignment in CSF ground filter, and field_packager\r\n  refactoring.\r\n- **Branch cleanup.** Merged the stale `fix/v2.0.7-hardening-pass` branch into\r\n  `master` and deleted it from GitHub. The repository now has a single branch:\r\n  `master`. GitLab remote switched from HTTPS token-auth to SSH.\r\n\r\n---\r\n\r\n## [2.0.13] - 2026-06-30\r\n\r\n### Fixed\r\n\r\n- **QGIS plugin scanner lint pass at 100% (0/22 findings remaining).** The\r\n  v2.0.12 zip produced 22 lint issues (`/scanner/.../report`) all in Code\r\n  Quality (Flake8) \u2014 W504 \u00d77, E226 \u00d74, F401 \u00d72, F541 \u00d71, E201 \u00d72,\r\n  E272 \u00d71, E128 \u00d72, E124 \u00d71. Eliminated all by:\r\n  - `blend_algorithm.py`: refactored extent-align check from 4-line\r\n    `or`-chain to a single `all((... <= tol, ...))` tuple. Tuple elements\r\n    end in `,` (not binary op), so no W503/W504 line-break is involved.\r\n  - `csf_algorithm.py`: collapsed the read-size `elif (and and ...)` to\r\n    a single line.\r\n  - `ml/detector.py`: collapsed the YOLOv5/v7 `elif (and and and and)`\r\n    chain to a single line; original comment preserved above.\r\n  - `test_golden_regression.py`: added whitespace around `-`/`+` in\r\n    `dem[y - 1 : y + 2, x - 1 : x + 2]` (E226 \u00d74) and flattened the\r\n    Horn's-method `dz_dx`/`dz_dy` expressions to a single line.\r\n  - `field_packager.py`: dropped unused `osgeo.gdal` import\r\n    (F401) inside `package_for_qfield`.\r\n  - `report_generator.py`: dropped unused `tempfile` import (F401)\r\n    inside the histogram block.\r\n  - `ai_detection_algorithm.py`: removed `f`-prefix from placeholder-free\r\n    string fragments (F541) while preserving implicit string concatenation.\r\n- `test.sh` flake8 gate realigned to EXACTLY mirror the plugins.qgis.org\r\n  scanner profile: enables W504 (line-break after binary operator, which\r\n  the scanner flags but newer flake8 disables) while ignoring the\r\n  cosmetic visual-indent rules E117/E128/E124/E201 (which default flake8\r\n  flags but the scanner does NOT enforce). This means CI failure now\r\n  matches scanner failure one-to-one \u2014 no false positives blocking the\r\n  release from broken lint gates that don't match the actual scanner.\r\n\r\n\r\n## [2.0.12] - 2026-06-30\r\n\r\n### Fixed\r\n- Release workflow (`release.yml`) hardened so `qgis-plugin-ci release` always publishes the exact working-tree contents at the tagged commit: (1) `actions/checkout@v4` now uses explicit `ref: ${{ github.ref_name }}` with `fetch-depth: 0` so a full history of the triggering tag is checked out instead of the shallow default; (2) new `Verify tree clean before package` step runs `git diff --quiet HEAD` (a tracked-files-only check that ignores untracked `__pycache__/` and `.pytest_cache/` produced by `./test.sh`) after the lint+test run and fails the workflow with a `::error` annotation if any tracked file diverges from HEAD.\r\n- `test.sh` switched from auto-modifying `ruff format` / `ruff check --fix` (which silently rewrote tracked files in CI and reintroduced W503 violations, blocking the publish guard on the v2.0.11 attempt) to read-only `ruff format --check` and `ruff check` chained with `|| echo \"(informational only)\"` so drift/lint warnings surface without blocking CI. The actual lint gate for the QGIS plugin scanner is `flake8 --isolated --select=W503,E402,E203` (run separately); ruff's default rule set is broader and is reporting only as developer feedback.\r\n- v2.0.8 \u2192 v2.0.10 published successfully but the artifacts available via the plugins.qgis.org API at scan time nonetheless lacked the lint fixes (`W503` and `E203` violations in `algorithms/blend_algorithm.py`, `algorithms/csf_algorithm.py`, `ml/detector.py`, `tests/test_golden_regression.py`); release.yml reproducibility fixes plus test.sh read-only mode make v2.0.12 the canonical 100%-lint-pass release.\r\n\r\n## [2.0.10] - 2026-06-30\r\n\r\n### Fixed\r\n- Lint scanner passes 100% with 0 findings across W503 (line break before binary operator), E402 (module-level import not at top of file), and E203 (whitespace before ':') rules. 18 fixes applied across 5 files (algorithms/blend_algorithm.py, algorithms/csf_algorithm.py, ml/detector.py, tests/test_golden_regression.py, tests/test_web_viewer.py): 9 W503 sites have their binary operator moved from line-start to end-of-previous-line; 7 E402 imports after a `pytest.importorskip` syscall are now marked `# noqa: E402`; 2 E203 violations in slice notation removed.\r\n- Republished as v2.0.10 to bypass GitHub's `/archive/refs/tags/v2.0.9.zip` CDN cache. The v2.0.9 published artifact on plugins.qgis.org was the cached source archive (containing v2.0.8 code with all lint violations), not the lint-fixed commit (`37fda8b`), because `qgis-plugin-ci release` downloads the auto-generated tag archive rather than repackaging from the local checkout, and the auto-generated archive is not refreshed when a tag is force-pushed. A new tag name produces a fresh archive with the corrected code.\r\n\r\n## [2.0.8] - 2026-06-30\r\n\r\n### Added\r\n- RVT Multi-directional Hillshade algorithm (`rvt_multidirectional_hillshade`) that wraps the `rvt-py` (Relief Visualization Toolbox) reference implementation. Useful for cross-validating results against other RVT installations.\r\n- RVT Topographic Openness algorithm (`rvt_openness`) with Positive and Negative modes, configurable search directions (8/16/32) and search radius (1\u2013500 px). Wraps `rvt.vis.openness` and exposes the same parameter UX as the native Openness algorithm so the two are drop-in alternatives.\r\n- CI step to install `rvt-py` as an optional test dependency (`pip install rvt-py 2>/dev/null || true`).\r\n\r\n---\r\n\r\n## [2.0.6] - 2026-06-19\r\n\r\n### Fixed\r\n- QGIS Scanner Security False Positives: Removed MapLibre CDN `integrity` hashes to prevent `detect-secrets` from flagging them as High Entropy Strings.\r\n- QGIS Scanner Lint Warnings: Fixed `W503` (line break before binary operator) in CSF Algorithm, `F841` (unused variable) in Web Viewer Algorithm, and `F401`/`F811` (unused/redefined import) in Web Viewer logic.\r\n\r\n---\r\n\r\n## [2.0.5] - 2026-06-19\r\n\r\n### Fixed\r\n- MapLibre Web Viewer: Fixed COG protocol registration (`maplibregl.addProtocol`) failing to load 3D terrain viewer.\r\n- MapLibre Web Viewer: Fixed issue where `generate_web_viewer` returned a boolean instead of the required config dictionary, causing test failures and crashes during HTML generation.\r\n- MapLibre Web Viewer: Resolved double-escaped HTML tags in the description block when empty.\r\n- Test Suite: Fully updated Pytest coverage for web viewer and web viewer algorithm.\r\n- Removed multi-gigabyte leftover test directories to recover workspace space.\r\n\r\n---\r\n\r\n## [2.0.3] - 2026-06-12\r\n\r\n### Fixed\r\n- Replaced `np.nan_to_num(0.0)` with `np.nanmean()` in `hillshade.py`, `slope.py`, and `slrm.py` to prevent false cliffs at NoData boundaries.\r\n- Corrected `np.int8` overflow to `np.int16` in `svf.py` and `asvf.py` preventing integer wrap-around.\r\n- Added checks for `cellsize <= 0` in `local_dominance.py` to avoid divide-by-zero errors.\r\n- Fixed hardcoded CRS strings to extract them dynamically in AI Detection. Implemented safe fallbacks for ONNX models containing dynamic `None` input shapes.\r\n- Closed open file handles on `rioxarray` raster objects using `with` blocks in Sentinel Fusion to prevent \"Too many open files\" errors. Fixed `.to_wkt()` calls.\r\n- Replaced double reprojection with a single correct call to `reproject_match` in Temporal Change Detection.\r\n- Cleaned up the DEM export logic in Point Cloud Filters by removing a duplicate `np.savetxt` call.\r\n- Cleaned up batch processing wrapper arguments to match actual function signatures.\r\n- Swapped out raw XYZ tile URLs for proper Carto GL Style JSON strings in MapLibre Web Viewer and escaped HTML attributes properly.\r\n- Added safeguards to float string formatting in PDF Report Generator.\r\n- Updated field export algorithm to correctly call `geom.centroid().asPoint()`.\r\n- Aligned trigonometric equations in the GPU openness calculation with the CPU NumPy versions and corrected array conversions in `gpu/compute_backend.py`.\r\n\r\n---\r\n\r\n## [2.0.2] - 2026-06-04\r\n\r\n### Fixed\r\n- Bumped to 2.0.2 as v2.0.1 tag was already claimed by an earlier build before lint fixes landed.\r\n- All lint fixes (W503, E203, E402) and `setup.cfg` restore are included in this release.\r\n\r\n---\r\n\r\n## [2.0.1] - 2026-06-04\r\n\r\n### Fixed\r\n- Bumped version to align with plugins.qgis.org submission.\r\n- Fixed flake8 W503, E203, E402 lint warnings in `fusion_algorithm.py`, `compute_backend.py`, and `test_csf_filter.py`.\r\n- Restored `setup.cfg` with flake8 ignore rules for W503 and E203.\r\n- Fixed `NameError: name 'VecVecFloat' is not defined` in `point_cloud/csf_filter.py`\r\n  when loading the plugin without the `cloth-simulation-filter` package installed.\r\n  The return type annotation `-> VecVecFloat` was evaluated at module import time;\r\n  changed to a string literal for lazy evaluation so the plugin loads correctly\r\n  regardless of optional dependencies.\r\n\r\n---\r\n\r\n## [2.0.0] - 2026-06-04\r\n\r\n### Added \u2014 Export Pipeline (LiDAR Relief \u2014 Export group)\r\n\r\n- **Cloud-Optimized GeoTIFF (COG) Export**: Convert any algorithm output to a\r\n  cloud-optimized GeoTIFF with internal tiling, overviews, and DEFLATE/LZW/ZSTD\r\n  compression. Optionally generates an interactive MapLibre GL JS web viewer\r\n  with opacity controls, coordinate display, dark/light themes, and share-link\r\n  copying. Suitable for direct upload to GitHub Pages or any static host.\r\n  (`export/cog_exporter.py`, `export/web_viewer.py`; algorithm: `cog_export`)\r\n\r\n- **Field Survey Export**: Package relief rasters and anomaly detection points\r\n  into a GeoPackage with structured archaeological schema (anomaly_id,\r\n  detection_method, confidence, feature_type, field_status) plus a QGIS project\r\n  file that opens directly in QField/Mergin Maps for mobile ground-truthing.\r\n  (`export/field_packager.py`; algorithm: `field_survey_export`)\r\n\r\n- **PDF Report Generator**: Generate CIfA-compliant PDF reports with title page,\r\n  full algorithm parameter documentation, input DEM metadata (CRS, resolution,\r\n  extent), band statistics with percentiles, histogram chart, and certification\r\n  section. Uses ReportLab (pure Python, OSGeo4W-safe).\r\n  (`export/report_generator.py`; algorithm: `pdf_report`)\r\n\r\n- **Visualization Recipes**: Import/export all algorithm parameters as\r\n  shareable JSON files with versioned schema, validation, type checking, and\r\n  metadata fields (name, author, tags, landscape type). Enables community\r\n  sharing of optimized parameter presets beyond the 4 built-in landscape\r\n  presets. (`recipes/__init__.py`; algorithms: `recipe_export`, `recipe_import`)\r\n\r\n### Added \u2014 Point Cloud Processing (LiDAR Relief \u2014 Point Cloud group)\r\n\r\n- **CSF Ground Filter (LAS/LAZ \u2192 DEM)**: Archaeology-tuned ground extraction\r\n  using the Cloth Simulation Filter (CSF) with 4 presets: Archaeology Fine\r\n  (maximum micro-relief preservation), Archaeology Standard (balanced),\r\n  Forested (aggressive canopy), and Urban. Supports laspy and PDAL readers.\r\n  (`point_cloud/csf_filter.py`; algorithm: `csf_ground_filter`)\r\n\r\n- **PDAL Ground Classification Pipelines**: JSON-based pipeline builder for\r\n  Progressive Morphological Filter (PMF) ground classification with\r\n  archaeology-optimized parameters. Presets for fine, standard, and forested\r\n  terrain, plus statistical outlier removal.\r\n  (`point_cloud/pdal_pipeline.py`; 4 pipeline presets)\r\n\r\n### Added \u2014 Multi-temporal Analysis (LiDAR Relief \u2014 Temporal group)\r\n\r\n- **Multi-temporal Change Detection**: Compute a probabilistic DEM of\r\n  Difference (DoD) between two temporally separated DEMs with propagated\r\n  RMSE-based Level of Detection (LoD) masking. Outputs include signed DoD\r\n  raster, significance mask (erosion/deposition), and cut/fill volume report.\r\n  (`temporal/dem_difference.py`; algorithm: `temporal_difference`)\r\n\r\n### Added \u2014 Multi-Sensor Fusion (LiDAR Relief \u2014 Fusion group)\r\n\r\n- **Multi-Sensor Fusion**: Co-register Sentinel-2 multispectral bands with\r\n  LiDAR relief and apply blend recipes combining topographic and spectral\r\n  information. Four recipes: Terrain+CIR (SVF + Colour Infrared), Crop Mark\r\n  Enhancement (Local Dominance + true colour), Erosion Risk (Slope + SWIR),\r\n  and Bare Earth Composite (SLRM + SWIR). Blend modes: luminance overlay,\r\n  overlay, multiply, screen.\r\n  (`fusion/sentinel_fusion.py`; algorithm: `multi_sensor_fusion`)\r\n\r\n### Added \u2014 AI/ML Inference (LiDAR Relief \u2014 AI/ML group)\r\n\r\n- **AI Feature Detection**: Load user-provided ONNX models for object\r\n  detection (YOLO) or semantic segmentation (U-Net) on plugin visualizations.\r\n  Features tiled processing for large rasters, Non-Maximum Suppression,\r\n  confidence filtering, and GeoPackage export of bounding box detections.\r\n  Pure NumPy preprocessing \u2014 no OpenCV dependency at inference time.\r\n  (`ml/detector.py`; algorithm: `ai_feature_detection`)\r\n\r\n### Added \u2014 GPU Acceleration\r\n\r\n- **CuPy Compute Backend**: Transparent GPU acceleration for computationally\r\n  intensive horizon-scanning algorithms (SVF, Openness). Automatically detects\r\n  CUDA availability and dispatches to CuPy with graceful NumPy fallback. Uses\r\n  the trigonometric identity `sin(arctan(dz/d)) = dz / sqrt(dz\u00b2 + d\u00b2)` for GPU-\r\n  optimized horizon scanning. (`gpu/compute_backend.py`)\r\n\r\n### Fixed\r\n- Fixed missing `compute_mstp` wrapper function in `core/mstp.py` that caused an\r\n  `ImportError` when running the e4MSTP algorithm via Batch mode.\r\n\r\n---\r\n\r\n## [1.3.5] - 2026-06-04\r\n\r\n### Fixed\r\n- Fixed missing `compute_mstp` wrapper function in `core/mstp.py` that caused an\r\n  `ImportError` when running the e4MSTP algorithm via Batch mode.\r\n\r\n---\r\n\r\n## [1.3.4] - 2026-05-31\r\n\r\n### Changed\r\n- Bumped version to clear broken 1.3.3 release tag.\r\n- Updated changelog to document all algorithms added since initial release.\r\n- Added `package.sh` helper script for correct local ZIP packaging.\r\n- Removed leftover development scripts from project root.\r\n\r\n---\r\n\r\n## [1.3.3] - 2026-05-31\r\n\r\n### Fixed\r\n- Corrected plugin ZIP structure: files are now correctly nested under a `lidar_relief/` parent directory as required by the QGIS Plugin Manager. Previous releases had files at the archive root, causing installation to fail.\r\n\r\n---\r\n\r\n## [1.3.0] - 2026-05-26\r\n\r\n### Added\r\n- Enhanced 4-Scale Topographic Position (e4MSTP) composite visualisation (Kokalj 2025 method).\r\n- PCA RGB Composite algorithm combining SVF, Openness, Slope, and Local Dominance into a single colour output.\r\n- ML-Ready Export (VRT Stack) tool for machine learning and multi-band analysis workflows.\r\n\r\n---\r\n\r\n## [1.2.0] - 2026-05-26\r\n\r\n### Added\r\n- Topographic Openness algorithm (positive and negative modes).\r\n- Multi-Scale Topographic Position (MSTP) algorithm.\r\n- VAT Composite algorithm.\r\n- Anisotropic Sky-View Factor (ASVF) with configurable illumination direction and weight.\r\n- Simple Red Relief and Blend algorithms.\r\n- Local Dominance algorithm.\r\n- Landscape Scale Presets for the Batch algorithm: Flat/Agricultural, Forested, Upland/Steep, and Coastal \u2014 parameters derived from peer-reviewed LiDAR visualisation literature.\r\n\r\n---\r\n\r\n## [1.1.0] - 2026-05-26\r\n\r\n### Added\r\n- Tile-based processing engine (`process_in_tiles`) for memory-efficient handling of large DEMs.\r\n- Automatic layer styling post-processor applied to all algorithm outputs.\r\n\r\n### Changed\r\n- Refactored all algorithms to share a common raster I/O utility layer.\r\n\r\n---\r\n\r\n## [1.0.13] - 2026-05-25\r\n\r\n### Fixed\r\n- Added `contents: write` permissions to the GitHub Actions release workflow.\r\n\r\n---\r\n\r\n## [1.0.12] - 2026-05-25\r\n\r\n### Fixed\r\n- Added `--release-tag` flag to `qgis-plugin-ci` publish command to fix GitHub Release lookup.\r\n\r\n---\r\n\r\n## [1.0.11] - 2026-05-25\r\n\r\n### Fixed\r\n- Corrected `.qgis-plugin-ci` GitHub repository configuration parameter names.\r\n\r\n---\r\n\r\n## [1.0.10] - 2026-05-25\r\n\r\n### Fixed\r\n- Added GitHub org/repo configuration to `.qgis-plugin-ci`.\r\n\r\n---\r\n\r\n## [1.0.9] - 2026-05-25\r\n\r\n### Fixed\r\n- Corrected `.qgis-plugin-ci` formatting to valid YAML.\r\n\r\n---\r\n\r\n## [1.0.8] - 2026-05-25\r\n\r\n### Fixed\r\n- Fixed `ImportError` catching logic in the `scipy` fallback path.\r\n\r\n---\r\n\r\n## [1.0.7] - 2026-05-25\r\n\r\n### Fixed\r\n- Fixed numpy fallback broadcast shape error in SLRM Gaussian filtering.\r\n\r\n---\r\n\r\n## [1.0.6] - 2026-05-25\r\n\r\n### Fixed\r\n- Fixed GitHub Actions release workflow failing due to missing OSGEO credentials.\r\n\r\n---\r\n\r\n## [1.0.5] - 2026-05-25\r\n\r\n### Changed\r\n- Removed unused `docs/` folder from version tracking.\r\n- Fixed README ZIP installation instructions.\r\n\r\n---\r\n\r\n## [1.0.4] - 2026-05-25\r\n\r\n### Changed\r\n- Removed `experimental` flag so the plugin is visible to all users by default in the QGIS Plugin Manager.\r\n\r\n---\r\n\r\n## [1.0.3] - 2026-05-25\r\n\r\n### Fixed\r\n- Bypassed mutually exclusive `W503`/`W504` flake8 lint rules using `any()`.\r\n\r\n---\r\n\r\n## [1.0.2] - 2026-05-25\r\n\r\n### Fixed\r\n- Resolved remaining PEP8 `W503` warnings for the QGIS linter.\r\n- Standardised file permissions across the package.\r\n\r\n---\r\n\r\n## [1.0.1] - 2026-05-25\r\n\r\n### Fixed\r\n- Fixed PEP8 formatting issues (W291, W293, W503) and removed unused imports (F401).\r\n- Updated plugin homepage, repository, and tracker metadata links.\r\n- Included `LICENSE` file in the QGIS package.\r\n- Updated QGIS compatibility range to 3.0\u20134.99.\r\n\r\n---\r\n\r\n## [1.0.0] - 2026-05-25\r\n\r\n### Added\r\n- Initial release.\r\n- Multi-directional Hillshade algorithm.\r\n- Simple Local Relief Model (SLRM) algorithm.\r\n- Sky-View Factor (SVF) algorithm.\r\n- Slope algorithm (degrees and percent).\r\n- Batch mode for running multiple algorithms on the same DEM in one pass.", "external_deps": null, "download_url": "https://plugins.qgis.org/plugins/lidar_relief/version/2.0.14/download/"}