Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 22 additions & 10 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
ci-cd:
- .github/**/*
- changed-files:
- any-glob-to-any-file:
- .github/**

dependencies:
- requirements.txt
- requirements/*.txt
- changed-files:
- any-glob-to-any-file:
- requirements.txt
- requirements/*.txt

documentation:
- docs/**/*
- changed-files:
- any-glob-to-any-file:
- docs/**

enhancement:
- src/**/*
- changed-files:
- any-glob-to-any-file:
- src/**

quality:
- tests/**/*
- changed-files:
- any-glob-to-any-file:
- tests/**

tooling:
- .gitignore
- .pre-commit-config.yaml
- setup.cfg
- pyproject.toml
- changed-files:
- any-glob-to-any-file:
- .gitignore
- .pre-commit-config.yaml
- setup.cfg
- pyproject.toml
13 changes: 5 additions & 8 deletions .github/workflows/pr-auto-labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@ name: "🏷 PR Labeler"
on:
- pull_request

permissions:
contents: read
pull-requests: write

jobs:
triage:
labeler:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v5
with:
repo-token: "${{ secrets.GITHUB_TOKEN }}"
- uses: actions/labeler@v5
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 1.5.2

### [Added]

* Outil TMSIZER : possibilité de préciser une aire prédéinie à la place de la bbox et un niveau à la place des dimensions pour l'écriture d'une heatmap (une tuile du niveau correspondra à un pixel)

## 1.5.1

### [Added]
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,22 @@ Conversions possibles (paramètres obligatoires en gras, paramètres facultatifs
| Format en entrée | Options d'entrée | Format en sortie | Options de sortie | Description |
|------------------|------------------|------------------|---------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
| GETTILE_PARAMS | *`levels=<id>[,<id> ...]`*,*`layers=<id>[,<id> ...]`* | COUNT | | Compte le nombre de GetTile dans les URLs en entrée utilisant le TMS pivot et les éventuels niveaux et couches fournies |
| GETTILE_PARAMS | *`levels=<id>[,<id> ...]`*,*`layers=<id>[,<id> ...]`* | HEATMAP | **`bbox=<xmin>,<ymin>,<xmax>,<ymax>`**, **`dimensions=<width>x<height>`** | Génère une carte de chaleur des tuiles interrogées sur la zone demandée et sur les éventuels niveau et couche fournis |
| GETTILE_PARAMS | *`levels=<id>[,<id> ...]`*,*`layers=<id>[,<id> ...]`* | HEATMAP | **`bbox=<xmin>,<ymin>,<xmax>,<ymax> or area=<id>`**, **`dimensions=<width>x<height> or level=<id>`** | Génère une carte de chaleur des tuiles interrogées sur la zone demandée et sur les éventuels niveaux et couches fournies. Si un niveau est fourni en sortie, on calera la bbox et les résolutions pour avoir un pixel correpondant à l'étendue d'une tuile du niveau. Certaines aires sont prédéfinies pour certaines projections du TMS |
| GEOMETRY | **`format=<WKT\|GeoJSON\|WKB>`**,**`level=<id>`** | GETTILE_PARAMS | | Génére les paramètres de requête GetTile des tuiles du niveau fourni intersectant les géométries en entrée |

Aires prédéfinies pour une carte de chaleur :

* `EPSG:3857`
* `FXX` (France métropolitaine)

Exemple (GETTILE_PARAMS -> HEATMAP) :

`tmsizer -i logs.txt --tms PM -io levels=15,14 -io layer=LAYER.NAME1,LAYER.NAME2,LAYER.NAME3 -if GETTILE_PARAMS -of HEATMAP -oo bbox=65000,6100000,665000,6500000 -oo dimensions=600x400 -o heatmap.tif`

Exemple (GETTILE_PARAMS -> HEATMAP) avec une aire prédéfinie et une correspondance pixel-niveau:

`tmsizer -i logs.txt --tms PM -if GETTILE_PARAMS -of HEATMAP -oo area=FXX -oo level=15 -o heatmap.tif`

## Compiler la suite d'outils

```sh
Expand Down
12 changes: 10 additions & 2 deletions README.pypi.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,18 @@ Availables conversions (mandatory options in bold, optionnal options in italic)
| Input format | Input options | Output format | Output options | Description |
|----------------|---------------------------------------------------|----------------|---------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|
| GETTILE_PARAMS | *`levels=<id>[,<id> ...]`*,*`layers=<id>[,<id> ...]`* | COUNT | | Count the GetTiles requests using the pivot TMS and optionnally the provided level and layer |
| GETTILE_PARAMS | *`levels=<id>[,<id> ...]`*,*`layers=<id>[,<id> ...]`* | HEATMAP | **`bbox=<xmin>,<ymin>,<xmax>,<ymax>`**, **`dimensions=<width>x<height>`** | Create an heat map of requested tiles on the provided area, optionnaly filtering with provided level and layer |
| GETTILE_PARAMS | *`levels=<id>[,<id> ...]`*,*`layers=<id>[,<id> ...]`* | HEATMAP | **`bbox=<xmin>,<ymin>,<xmax>,<ymax> or area=<id>`**, **`dimensions=<width>x<height> or level=<id>`** | Create an heat map of requested tiles on the provided area, optionnaly filtering with provided level and layer |
| GEOMETRY | **`format=<WKT\|GeoJSON\|WKB>`**,**`level=<id>`** | GETTILE_PARAMS | | Generate GetTile query parameters for tiles intersecting input geometries for the provided level |

Available areas for a heatmap :

* `EPSG:3857`
* `FXX` (European France)

Example (GETTILE_PARAMS -> HEATMAP) :

`tmsizer -i logs.txt --tms PM -io levels=15,14 -io layer=LAYER.NAME1,LAYER.NAME2,LAYER.NAME3 -if GETTILE_PARAMS -of HEATMAP -oo bbox=65000,6100000,665000,6500000 -oo dimensions=600x400 -o heatmap.tif`

Example (GETTILE_PARAMS -> HEATMAP) with predefined area and pixel-level superposition:

`tmsizer -i logs.txt --tms PM -io levels=15,14 -io layer=LAYER.NAME1,LAYER.NAME2,LAYER.NAME3 -if GETTILE_PARAMS -of HEATMAP -oo bbox=65000,6100000,665000,6500000 -oo dimensions=600x400 -o heatmap.tif`
`tmsizer -i logs.txt --tms PM -if GETTILE_PARAMS -of HEATMAP -oo area=FXX -oo level=15 -o heatmap.tif`
56 changes: 52 additions & 4 deletions src/rok4_tools/tmsizer_utils/processors/reduce.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ class HeatmapProcessor(Processor):

input_formats_allowed = ["POINT"]

areas = {
"EPSG:3857": {
"FXX": [-649498, 5048729, 1173394, 6661417]
}
}

def __init__(self, input: Processor, **options):
"""Constructor method

Expand All @@ -107,7 +113,7 @@ def __init__(self, input: Processor, **options):

self.__input = input

try:
if "bbox" in options:
try:
self.__bbox = [float(c) for c in options["bbox"].split(",")]
self.__bbox = tuple(self.__bbox)
Expand All @@ -117,6 +123,18 @@ def __init__(self, input: Processor, **options):
if len(self.__bbox) != 4 or self.__bbox[0] >= self.__bbox[2] or self.__bbox[1] >= self.__bbox[3]:
raise ValueError(f"Option 'bbox' have to be provided with format <xmin>,<ymin>,<xmax>,<ymax> (floats, min < max)")

elif "area" in options:
try:
self.__bbox = self.areas[self.tms.srs][options["area"]]
except KeyError as e:
if self.tms.srs in self.areas:
raise ValueError(f"Area '{options['area']}' is not available for the TMS coordinates system ({self.tms.srs}): available areas are {', '.join(self.areas[self.tms.srs].keys())}")
else :
raise ValueError(f"No defined areas for the TMS coordinates system ({self.tms.srs})")
else:
raise KeyError(f"Option 'bbox' or 'area' is required for a heatmap processing")

if "dimensions" in options:
try:
self.__dimensions = [int(d) for d in options["dimensions"].split("x")]
self.__dimensions = tuple(self.__dimensions)
Expand All @@ -130,9 +148,39 @@ def __init__(self, input: Processor, **options):
(self.__bbox[2] - self.__bbox[0]) / self.__dimensions[0],
(self.__bbox[3] - self.__bbox[1]) / self.__dimensions[1]
)
elif "level" in options:
level = self.tms.get_level(options["level"])
if level is None:
raise ValueError(f"The provided level '{options['dimensions']}' (to have one pixel per tile) is not in the TMS")

# On va caler la bbox pour qu'elle coïncide avec les limites de tuiles du niveau demandé
(col_min, row_min, col_max, row_max) = level.bbox_to_tiles(self.__bbox)

# Calage du coin en bas à gauche
(xmin, ymin, xmax, ymax) = level.tile_to_bbox(col_min, row_max)
self.__bbox[0] = xmin
self.__bbox[1] = ymin

# Calage du coin en haut à droite
(xmin, ymin, xmax, ymax) = level.tile_to_bbox(col_max, row_min)
self.__bbox[2] = xmax
self.__bbox[3] = ymax

self.__resolutions = (
xmax - xmin,
ymax - ymin
)

self.__dimensions = (
int((self.__bbox[2] - self.__bbox[0]) / self.__resolutions[0]),
int((self.__bbox[3] - self.__bbox[1]) / self.__resolutions[1])
)

else:
raise KeyError(f"Option 'dimensions' or 'level' is required for a heatmap processing")

except KeyError as e:
raise KeyError(f"Option {e} is required for a heatmap processing")
if self.__dimensions[0] > 10000 or self.__dimensions[1] > 10000:
raise ValueError(f"Heatmap dimensions have to be less than 10 000 x 10 000: here it's {self.__dimensions}")

def process(self) -> Iterator[MemoryFile]:
"""Read point coordinates from the input processor and accumule them as a heat map
Expand Down Expand Up @@ -194,4 +242,4 @@ def process(self) -> Iterator[MemoryFile]:
yield memfile

def __str__(self) -> str:
return f"HeatmapProcessor : {self._processed} hits on image with dimensions {self.__dimensions} and bbox {self.__bbox}"
return f"HeatmapProcessor : {self._processed} hits on image with dimensions {self.__dimensions} and bbox {self.__bbox} (resolutions {self.__resolutions})"
Loading