Metadata-Version: 2.4
Name: raster2pm
Version: 0.1.1
Summary: Convert raster imagery (orthomosaic, NDVI, NDRE) to PMTiles
Author-email: Samuel Appiah Kubi <appiahkubis14@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/appiahkubis14/raster2pm
Project-URL: Documentation, https://raster2pm.readthedocs.io
Project-URL: Repository, https://github.com/appiahkubis14/raster2pm.git
Project-URL: Issues, https://github.com/appiahkubis14/raster2pm/issues
Keywords: raster,pmtiles,ndvi,ndre,orthomosaic,drone,gis,geotiff
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: GIS
Classifier: Topic :: Multimedia :: Graphics :: Graphics Conversion
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: rasterio>=1.3.0
Requires-Dist: numpy>=1.20.0
Requires-Dist: matplotlib>=3.5.0
Requires-Dist: rio-pmtiles>=0.3.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: black>=23.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: mypy>=1.0; extra == "dev"
Provides-Extra: docs
Requires-Dist: mkdocs>=1.4.0; extra == "docs"
Requires-Dist: mkdocs-material>=9.0; extra == "docs"
Dynamic: license-file

﻿# raster2pm 🛰️

[![PyPI version](https://badge.fury.io/py/raster2pm.svg)](https://pypi.org/project/raster2pm/)
[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

> **raster → PMTiles** — Convert any GeoTIFF to web-optimized map tiles in one command.

Convert orthomosaics, NDVI, NDRE, and any raster imagery to PMTiles with automatic colormap application for vegetation indices.

---

## 📦 Installation

### From PyPI

\\\ash
pip install raster2pm
\\\

### From Source

\\\ash
git clone https://github.com/samuelappiah/raster2pm.git
cd raster2pm
pip install -e .
\\\

### With Development Dependencies

\\\ash
pip install raster2pm[dev]
\\\

---

## 🚀 Quick Start

### Basic RGB Orthomosaic

\\\ash
raster2pm ortho.tif -o tiles.pmtiles
\\\

### NDVI with Auto-Stretch

\\\ash
raster2pm ndvi.tif --ndvi --auto-stretch -o ndvi.pmtiles
\\\

### NDRE with Custom Colormap

\\\ash
raster2pm ndre.tif --ndre --colormap RdYlGn -o ndre.pmtiles
\\\

---

## 📖 Complete Usage Guide

### Command-Line Interface

\\\ash
raster2pm INPUT_FILE [OPTIONS]
\\\

### Input/Output Options

| Option | Description | Default |
|--------|-------------|---------|
| \-o, --output PATH\ | Output PMTiles file | \output.pmtiles\ |

### Tiling Options

| Option | Description | Default |
|--------|-------------|---------|
| \--min-zoom INT\ | Minimum zoom level | \5\ |
| \--max-zoom INT\ | Maximum zoom level | \20\ |
| \--format FORMAT\ | Tile format: PNG, JPEG, WEBP | \PNG\ |
| \--tile-size INT\ | Tile size in pixels | \256\ |
| \--resampling METHOD\ | Resampling: nearest, bilinear, cubic, cubic_spline, lanczos, average | \cubic\ |
| \--quality INT\ | JPEG/WEBP quality (0-100) | \75\ |
| \--workers INT\ | Number of parallel workers | \4\ |

### Metadata Options

| Option | Description | Default |
|--------|-------------|---------|
| \--name TEXT\ | Layer name | \"Raster Layer"\ |
| \--description TEXT\ | Layer description | \"Converted from GeoTIFF"\ |

### Behavior Options

| Option | Description |
|--------|-------------|
| \--overlay / --no-overlay\ | Create overlay tiles (default: overlay) |
| \--exclude-empty / --no-exclude-empty\ | Exclude empty tiles (default: exclude) |

### Vegetation Index Options

| Option | Description | Default |
|--------|-------------|---------|
| \--ndvi\ | Input is NDVI raster | - |
| \--ndre\ | Input is NDRE raster | - |
| \--colormap NAME\ | Matplotlib colormap: viridis, plasma, inferno, magma, RdYlGn, RdBu, ndvi_custom | \RdYlGn\ |
| \--min-value FLOAT\ | Minimum value for colormap | \-1.0\ |
| \--max-value FLOAT\ | Maximum value for colormap | \1.0\ |
| \--auto-stretch\ | Auto-stretch to p2-p98 data range | - |
| \--stretch-percentile FLOAT\ | Percentile to clip at tails | \2.0\ |

### Diagnostic Options

| Option | Description |
|--------|-------------|
| \--stats-only\ | Print statistics and exit |
| \--keep-temp\ | Keep temporary files |
| \-v, --verbose\ | Increase verbosity |
| \--version\ | Show version |

---

## 📚 Examples

### Example 1: Convert RGB Orthomosaic

\\\ash
raster2pm farm_ortho.tif -o farm_tiles.pmtiles
\\\

### Example 2: NDVI with Auto-Stretch

\\\ash
# Automatically stretches colormap to actual data range
raster2pm ndvi_map.tif --ndvi --auto-stretch -o ndvi_tiles.pmtiles
\\\

### Example 3: High-Quality WEBP Output

\\\ash
raster2pm ortho.tif --format WEBP --quality 90 -o tiles.pmtiles
\\\

### Example 4: Custom Zoom Levels

\\\ash
# Only generate zoom levels 12-18 (faster, smaller file)
raster2pm ortho.tif --min-zoom 12 --max-zoom 18 -o tiles.pmtiles
\\\

### Example 5: NDRE with Viridis Colormap

\\\ash
raster2pm ndre_map.tif --ndre --colormap viridis --auto-stretch -o ndre_tiles.pmtiles
\\\

### Example 6: Check Statistics Before Converting

\\\ash
# See data distribution before choosing colormap range
raster2pm ndvi.tif --ndvi --stats-only
\\\

**Output:**
\\\
📈 Computing data statistics (sampling ~2000 rows)...
   Valid pixels (sample) : 98.5% (196,834 pixels)
   Range                 : [-0.45, 0.92]
   Mean ± std            : 0.34 ± 0.28
   Percentiles  p2=-0.32  p10=-0.05  p25=0.12  p50=0.34  p75=0.56  p90=0.72  p98=0.85
   Value distribution:
   [-0.45 → -0.31]  ███                            2.3%
   [-0.31 → -0.18]  ██████                          5.1%
   ...
\\\

### Example 7: Manual Colormap Range

\\\ash
# Use statistics from above to set optimal range
raster2pm ndvi.tif --ndvi --min-value -0.32 --max-value 0.85 -o ndvi_tiles.pmtiles
\\\

### Example 8: JPEG Output for Smaller Files

\\\ash
raster2pm ortho.tif --format JPEG --quality 75 -o tiles_jpg.pmtiles
\\\

### Example 9: Parallel Processing

\\\ash
# Use 8 CPU cores for faster conversion
raster2pm large_ortho.tif --workers 8 -o tiles.pmtiles
\\\

### Example 10: Custom Metadata

\\\ash
raster2pm field.tif \\
  --name \"Farm Field 42 - July 2024\" \\
  --description \"RGB orthomosaic, 2cm/pixel, DJI Phantom 4\" \\
  -o farm_july.pmtiles
\\\

---

## 🐍 Python API

### Basic Usage

\\\python
from raster2pm import convert_to_pmtiles

# Basic RGB conversion
convert_to_pmtiles(\"ortho.tif\", \"output.pmtiles\")
\\\

### NDVI with Auto-Stretch

\\\python
from raster2pm import convert_to_pmtiles

convert_to_pmtiles(
    \"ndvi.tif\",
    \"ndvi.pmtiles\",
    is_ndvi=True,
    auto_stretch=True,
    colormap=\"RdYlGn\",
)
\\\

### Custom Settings

\\\python
from raster2pm import convert_to_pmtiles

convert_to_pmtiles(
    input_file=\"large_ortho.tif\",
    output_file=\"tiles.pmtiles\",
    min_zoom=12,
    max_zoom=22,
    tile_format=\"WEBP\",
    quality=85,
    resampling=\"lanczos\",
    workers=8,
    name=\"Farm Orthomosaic\",
    description=\"2cm resolution, captured July 2024\",
)
\\\

### Using Individual Components

\\\python
from raster2pm import get_raster_info, compute_vegetation_stats

# Get raster metadata
info = get_raster_info(\"ndvi.tif\")
print(f\"Size: {info['size']}\")
print(f\"Bands: {info['bands']}\")
print(f\"CRS: {info['crs']}\")

# Compute NDVI statistics
stats = compute_vegetation_stats(\"ndvi.tif\")
print(f\"NDVI range: [{stats['min']:.2f}, {stats['max']:.2f}]\")
print(f\"Mean NDVI: {stats['mean']:.2f}\")
print(f\"P50 NDVI: {stats['p50']:.2f}\")
\\\

### Apply Colormap Manually

\\\python
from raster2pm import apply_colormap_to_rgb

# Convert single-band NDVI to RGB GeoTIFF
rgb_file = apply_colormap_to_rgb(
    \"ndvi.tif\",
    colormap_name=\"RdYlGn\",
    vmin=-1.0,
    vmax=1.0,
)
print(f\"RGB file created: {rgb_file}\")
\\\

---

## 🎨 Available Colormaps

| Colormap | Description | Best For |
|----------|-------------|----------|
| \RdYlGn\ | Red-Yellow-Green | NDVI/NDRE (default) |
| \
dvi_custom\ | Red → Yellow → Green | NDVI (custom gradient) |
| \iridis\ | Blue-Green-Yellow | General scientific |
| \plasma\ | Purple-Orange-Yellow | Elevation/heat |
| \inferno\ | Black-Red-Yellow | Intensity |
| \magma\ | Black-Purple-White | Topography |
| \RdBu\ | Red-White-Blue | Anomaly detection |

---

## 📊 Understanding the Output

### Statistics

When using \--stats-only\ or \--ndvi\/\--ndre\, raster2pm computes:

- **Min/Max**: Data range
- **Mean ± Std**: Central tendency and spread
- **Percentiles**: p2, p10, p25, p50 (median), p75, p90, p98
- **Valid pixels**: Percentage of non-NoData pixels
- **ASCII histogram**: Visual distribution

### Colormap Warnings

If your data range doesn't match the colormap range, raster2pm warns you:

\\\
⚠️  Data spans 0.35 but colormap range is 2.00 — only 18% of colours used.
   The map will look nearly one colour!
   👉 Run with --auto-stretch or set:
      --min-value -0.32 --max-value 0.85
\\\

### Auto-Stretch

\--auto-stretch\ automatically sets the colormap range to your data's p2-p98 range, ensuring vibrant, informative visualizations.

---

## 🌐 Viewing PMTiles

### Online (Easiest)
Drag and drop your \.pmtiles\ file to **[pmtiles.io](https://pmtiles.io)**

### Local Server
\\\ash
# Install pmtiles CLI
npm install -g pmtiles

# Serve locally
pmtiles serve output.pmtiles

# Open http://localhost:8081
\\\

### Web Maps
\\\javascript
// MapLibre GL JS
const map = new maplibregl.Map({
  container: 'map',
  style: {
    sources: {
      'raster': {
        type: 'pmtiles',
        url: 'https://example.com/tiles.pmtiles',
      }
    }
  }
});
\\\

---

## 🔧 How It Works

1. **Reads** GeoTIFF metadata (CRS, bounds, bands)
2. **For vegetation indices**: Computes statistics, applies colormap
3. **Processes block-by-block** for memory efficiency
4. **Builds overview pyramids** for smooth zooming
5. **Converts to PMTiles** using rio-pmtiles
6. **Outputs** a single \.pmtiles\ file

---

## ⚙️ Requirements

- Python 3.8+
- rio-pmtiles
- rasterio
- numpy
- matplotlib

All installed automatically with \pip install raster2pm\.

---

## 🧪 Development

\\\ash
# Clone
git clone https://github.com/samuelappiah/raster2pm.git
cd raster2pm

# Install dev dependencies
pip install -e \".[dev]\"

# Run tests
pytest -v

# Format code
black raster2pm/
ruff check raster2pm/

# Type check
mypy raster2pm/
\\\

---

## 🤝 Contributing

Contributions welcome! Please:

1. Fork the repository
2. Create a feature branch
3. Add tests
4. Submit a pull request

---

## 📄 License

MIT © 2024 Samuel Appiah Kubi

---

## 🔗 Links

- **PyPI**: https://pypi.org/project/raster2pm/
- **GitHub**: https://github.com/samuelappiah/raster2pm
- **Issues**: https://github.com/samuelappiah/raster2pm/issues
- **PMTiles Spec**: https://github.com/protomaps/PMTiles
- **Preview**: https://pmtiles.io
