Metadata-Version: 2.4
Name: rasterama
Version: 0.1.2
Summary: Headless tile downloader and GeoTIFF/BigTIFF raster stitcher.
Author: Rasterama Contributors
Project-URL: Homepage, https://pypi.org/project/rasterama/
Project-URL: Repository, https://pypi.org/project/rasterama/
Project-URL: PyMapStitcher Store, https://apps.microsoft.com/search?query=PyMapStitcher
Project-URL: PyMapStitcher Search, https://apps.microsoft.com/search?query=Py%20Map%20Stitcher
Keywords: raster,geotiff,bigtiff,tiles,webmercator,gis
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Scientific/Engineering :: GIS
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.31
Requires-Dist: Pillow>=10.0
Requires-Dist: tifffile>=2024.0
Requires-Dist: numpy>=1.24
Provides-Extra: cuda
Requires-Dist: cupy-cuda12x>=13.0; extra == "cuda"
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == "dev"
Requires-Dist: twine>=5.0; extra == "dev"
Requires-Dist: pytest>=8.0; extra == "dev"

# rasterama

`rasterama` is a headless Python core package and command-line tool for raster
map stitching. It downloads XYZ-style map tiles, decodes them, and streams them
into georeferenced TIFF/BigTIFF output without requiring a GUI.

The package was prepared from the reusable non-GUI parts of a PyMapStitcher
prototype. The PySide/WebEngine user interface is intentionally not included in
this core package.

## Important usage notice

Only use tile servers and map providers where you have permission to download,
cache, process, and stitch tiles. Many public services restrict automated or
bulk downloading. `rasterama` is a technical tool; it does not grant rights to
third-party imagery or map data.

## Related links

- PyPI project page after upload: <https://pypi.org/project/rasterama/>
- TestPyPI project page after test upload: <https://test.pypi.org/project/rasterama/>
- Microsoft Store search for PyMapStitcher: <https://apps.microsoft.com/search?query=PyMapStitcher>
- Microsoft Store protocol search: `ms-windows-store://search/?query=PyMapStitcher`
- Microsoft Store search for "Py Map Stitcher": <https://apps.microsoft.com/search?query=Py%20Map%20Stitcher>

Note: at packaging time I could not verify a stable public Microsoft Store
product-detail URL for PyMapStitcher. The links above intentionally point to
Microsoft Store search pages, so they stay useful even if the product ID changes.

## Features

- Headless operation: no PySide, no Qt, no WebEngine.
- CLI command `rasterama`.
- Python API via `import rasterama`.
- XYZ tile math for Web Mercator tile grids.
- Bing QuadKey support.
- URL template expansion for `{x}`, `{y}`, `{z}`, `{q}`, `{quadkey}`, `{s}`,
  `{snum}`, `{rnd}` and legacy NoniMapView-style placeholders.
- Tile download with retries, timeout, rate limiting, and custom headers.
- PNG/JPEG tile decoding with Pillow.
- Direct streaming into GeoTIFF/BigTIFF using `tifffile.memmap`.
- Embedded EPSG:3857 GeoTIFF tags.
- Sidecar `.tfw` and `.prj` support for single-tile TIFF export.
- Optional CUDA/CuPy chunk compositing.
- Built-in provider presets for common tile URL templates.

## Installation

From a local checkout:

```powershell
pip install .
```

From a wheel:

```powershell
pip install .\dist\rasterama-0.1.2-py3-none-any.whl
```

Optional NVIDIA/CuPy support:

```powershell
pip install "rasterama[cuda]"
```

For development and packaging:

```powershell
pip install "rasterama[dev]"
```

## CLI overview

After installation the console command is:

```powershell
rasterama --help
```

Available subcommands:

```text
rasterama bounds
rasterama stitch
rasterama tile-url
rasterama tile-tif
rasterama quadkey
rasterama presets
```

### `rasterama bounds`

Estimate the tile range, image dimensions, tile count, and raw TIFF payload size
for a geographic bounding box.

```powershell
rasterama bounds --bbox 50.1 8.5 50.2 8.6 --zoom 18
```

Arguments:

- `--bbox SOUTH WEST NORTH EAST`: geographic bounding box in lon/lat degrees.
- `--zoom Z`: XYZ/Web Mercator zoom level.
- `--url-template TEMPLATE`: optional template, mostly for consistency.
- `--preset NAME`: optional preset name.
- `--json`: print machine-readable JSON.

Example JSON output:

```powershell
rasterama bounds --bbox 50.1 8.5 50.2 8.6 --zoom 18 --json
```

### `rasterama stitch`

Download tiles and stream them into a georeferenced TIFF/BigTIFF.

```powershell
rasterama stitch `
  --url-template "https://server.example/{z}/{x}/{y}.png" `
  --bbox 50.1 8.5 50.2 8.6 `
  --zoom 18 `
  --output out.tif
```

Arguments:

- `--bbox SOUTH WEST NORTH EAST`: area to download.
- `--zoom Z`: XYZ/Web Mercator zoom level.
- `--output FILE`: output `.tif` or `.tiff` path.
- `--url-template TEMPLATE`: custom tile URL template.
- `--preset NAME`: use one of the built-in presets instead of a custom URL.
- `--workers N`: parallel download workers; default `8`.
- `--rate-limit-ms N`: delay per request in milliseconds; default `50`.
- `--retries N`: retries per tile; default `3`.
- `--timeout N`: HTTP timeout in seconds; default `20`.
- `--chunk-size N`: chunk width/height in tiles; default `64`.
- `--header Name=Value`: extra HTTP header; can be repeated.
- `--cuda`: enable optional CUDA/CuPy stitching.
- `--cuda-max-chunk-mb N`: max GPU chunk buffer size; default `1024`.
- `--cuda-boost`: intentionally keep GPU busy with background CUDA work.
- `--cuda-load-size N`: CUDA boost matrix size; default `1536`.

Preset example:

```powershell
rasterama stitch `
  --preset esri-world-imagery `
  --bbox 50.1 8.5 50.2 8.6 `
  --zoom 18 `
  --output esri_area.tif
```

Custom headers example:

```powershell
rasterama stitch `
  --url-template "https://tiles.example.com/{z}/{x}/{y}.png" `
  --bbox 50.1 8.5 50.2 8.6 `
  --zoom 18 `
  --output out.tif `
  --header "Authorization=Bearer YOUR_TOKEN" `
  --header "Referer=https://example.com"
```

### `rasterama tile-url`

Expand one tile URL template for a concrete `x`, `y`, `z`.

```powershell
rasterama tile-url --template "https://server.example/{z}/{x}/{y}.png" --x 137261 --y 88677 --z 18
```

Arguments:

- `--template TEMPLATE`: tile URL template.
- `--preset NAME`: use a built-in preset.
- `--x X`: tile x coordinate.
- `--y Y`: tile y coordinate.
- `--z Z`: tile zoom level.

### `rasterama tile-tif`

Download one tile and write it as a georeferenced TIFF with `.tfw` and `.prj`
sidecar files.

```powershell
rasterama tile-tif `
  --url-template "https://server.example/{z}/{x}/{y}.png" `
  --x 137261 `
  --y 88677 `
  --z 18 `
  --output tile.tif
```

Arguments:

- `--url-template TEMPLATE`: custom tile URL template.
- `--preset NAME`: use a built-in preset.
- `--x X`: tile x coordinate.
- `--y Y`: tile y coordinate.
- `--z Z`: tile zoom level.
- `--output FILE`: output TIFF path.
- `--rate-limit-ms N`: delay per request in milliseconds.
- `--retries N`: retries per tile.
- `--timeout N`: HTTP timeout in seconds.
- `--header Name=Value`: extra HTTP header; can be repeated.

### `rasterama quadkey`

Calculate a Bing QuadKey from `x`, `y`, `z`.

```powershell
rasterama quadkey --x 3 --y 5 --z 3
```

### `rasterama presets`

List included provider presets.

```powershell
rasterama presets
rasterama presets --verbose
```

Current preset names:

- `custom`
- `google-satellite`
- `google-hybrid`
- `bing-satellite`
- `bing-hybrid`
- `esri-world-imagery`
- `osm-mapnik`
- `opentopomap`
- `cartodb-positron`

## URL template placeholders

Supported placeholders:

- `{x}`: XYZ tile x coordinate.
- `{y}`: XYZ tile y coordinate.
- `{z}`: zoom level.
- `{q}` and `{quadkey}`: Bing QuadKey.
- `{rnd}`: random integer from `0` to `3`.
- `{snum}`: subdomain number from `0` to `3`.
- `{s}`: subdomain letter from `a`, `b`, `c`.
- `*GMX*`, `*GMY*`, `*ZM1*`, `*IZM*`, `*RND*`, `*LAN*`, `*LAN-LAN*`:
  legacy placeholders used by older map profile formats.

## Python API quickstart

```python
from pathlib import Path

from rasterama import StitchConfig, calculate_plan, stitch_tiles

cfg = StitchConfig(
    url_template="https://server.example/{z}/{x}/{y}.png",
    output_file=Path("out.tif"),
    z=18,
    min_lat=50.1,
    min_lon=8.5,
    max_lat=50.2,
    max_lon=8.6,
    workers=8,
    rate_limit_ms=50,
)

plan = calculate_plan(cfg)
print(plan.total_tiles, plan.width, plan.height)

result = stitch_tiles(cfg, log_cb=print)
print(result.output_file)
```

## Public functions and classes

The package exports the most common API from `rasterama.__init__`:

- `Bounds`
- `StitchConfig`
- `StitchResult`
- `TileJob`
- `TilePlan`
- `calculate_plan`
- `stitch_tiles`
- `clamp_lat`
- `expand_url`
- `lonlat_to_tile`
- `tile_bounds_for_bbox`
- `tile_to_lonlat`
- `tile_to_quadkey`

Additional module-level functions:

### `rasterama.tiles`

- `clamp_lat(lat)`
- `lonlat_to_tile(lon, lat, z)`
- `tile_to_lonlat(x, y, z)`
- `tile_bounds_for_bbox(min_lat, min_lon, max_lat, max_lon, z)`
- `tile_to_quadkey(x, y, z)`
- `expand_url(template, x, y, z)`
- `project_tiles_dir(output_file)`
- `project_sqlite_dir(output_file)`
- `project_single_tiff_dir(output_file)`
- `safe_cache_path(cache_dir, z, x, y)`
- `default_tile_tif_dir(output_file, z)`
- `safe_tile_tif_path(tile_tif_dir, z, x, y)`

### `rasterama.geo`

- `lonlat_to_webmercator(lon, lat)`
- `tile_webmercator_bounds(x, y, z)`
- `mosaic_webmercator_bounds(x_min, y_min, x_max, y_max, z)`
- `write_worldfile_and_prj(tif_path, width, height, bounds_3857)`
- `geotiff_extratags_epsg3857(width, height, bounds_3857)`

### `rasterama.imageops`

- `make_blank_tile()`
- `decode_tile(data)`
- `tile_bytes_to_numpy_rgb(data)`
- `save_tile_as_tif(data, out_path, z, x, y)`

### `rasterama.download`

- `download_one(job, cfg, stop_event=None)`

### `rasterama.stitch`

- `iter_chunks(x_min, y_min, x_max, y_max, chunk_size)`
- `iter_chunk_jobs(cx0, cy0, cx1, cy1, z, x_min, y_min)`
- `iter_tile_jobs(x_min, y_min, x_max, y_max, z)`
- `calculate_plan(cfg)`
- `stitch_tiles(cfg, progress_cb=None, log_cb=None, stop_event=None)`

### `rasterama.tiff`

- `format_bytes(num)`
- `ensure_enough_disk_space(path, required_bytes, log_cb)`
- `open_direct_bigtiff(output_file, width, height, bounds_3857, log_cb)`

### `rasterama.cuda`

- `init_cupy_cuda(log_cb=None)`
- `CudaUtilizationBooster`
- `cuda_preprocess_tile(cp, tile_arr)`

### `rasterama.presets`

- `MAP_PRESETS`
- `preset_url(name)`

### `rasterama.cli`

- `build_parser()`
- `main(argv=None)`

## Data models

### `Bounds`

Geographic bounding box in `south`, `west`, `north`, `east` order. Includes
`from_sequence()` and `validate()`.

### `TileJob`

Represents one tile download/write job:

- `x`
- `y`
- `z`
- `col`
- `row`

### `TilePlan`

Calculated output plan:

- `x_min`, `y_min`, `x_max`, `y_max`
- `cols`, `rows`
- `width`, `height`
- `total_tiles`
- `raw_bytes`
- `bounds_3857`

### `StitchConfig`

Main runtime configuration:

- `url_template`
- `output_file`
- `z`
- `min_lat`, `min_lon`, `max_lat`, `max_lon`
- `workers`
- `rate_limit_ms`
- `retries`
- `timeout`
- `headers`
- `chunk_size`
- `use_cuda_stitch`
- `cuda_max_chunk_mb`
- `cuda_utilization_boost`
- `cuda_load_matrix_size`

### `StitchResult`

Returned by `stitch_tiles()`:

- `output_file`
- `plan`
- `processed`
- `errors`
- `stopped`
- `pixel_size`
- `tile_size`

## Build

From the project folder:

```powershell
python -m pip install --upgrade build twine
python -m build
python -m twine check dist/*
```

## Upload to PyPI

Use an API token from PyPI. The username for token-based upload is always
`__token__`.

```powershell
$wheel = ".\dist\rasterama-0.1.2-py3-none-any.whl"
python -m twine check $wheel
python -m twine upload --username __token__ --password "pypi-YOUR_TOKEN_HERE" $wheel
```

For a safer PowerShell token prompt, see `README_UPLOAD.txt` in the upload
bundle generated for this package.

## Current limitations

- Output CRS is EPSG:3857 / Web Mercator.
- The core package does not include the old PySide GUI.
- There is no persistent resume cache in this first core package release.
- Missing or failed tiles are counted as errors; successful tiles continue to be
  streamed into the output.
- Provider presets are convenience templates, not usage permission.

## License

Add the final project license before public release if this package will be
distributed beyond private/internal use.
