Skip to content

Commit

Permalink
Merge pull request #21 from openforis/master
Browse files Browse the repository at this point in the history
fix the grid builder
  • Loading branch information
12rambau authored Nov 23, 2021
2 parents a1f2073 + 07b800c commit 4c0a4b4
Show file tree
Hide file tree
Showing 22 changed files with 338 additions and 361 deletions.
13 changes: 13 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
default_language_version:
python: python3

repos:
- repo: https://github.com/psf/black
rev: 8a59528c2d8ae1ef5f366039c728614aaf1a470b
hooks:
- id: black
- id: black-jupyter
- repo: https://github.com/kynan/nbstripout
rev: 0.5.0
hooks:
- id: nbstripout
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Vector file manager

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Black badge](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)

## About

This module is a 2 step wrapper to upload AOI to Google Earth Engine

![results](./doc/img/full_input.png)
Expand Down
8 changes: 4 additions & 4 deletions about_ui.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
"source": [
"from sepal_ui import sepalwidgets as sw\n",
"\n",
"#create the Html body of your about section \n",
"ig_about = sw.TileAbout('utils/about.md')\n",
"# create the Html body of your about section\n",
"ig_about = sw.TileAbout(\"utils/about.md\")\n",
"\n",
"#create a disclaimer\n",
"# create a disclaimer\n",
"ig_disclaimer = sw.TileDisclaimer()"
]
},
Expand All @@ -21,7 +21,7 @@
"metadata": {},
"outputs": [],
"source": [
"#will only be displayed if voila is launch from this tile\n",
"# will only be displayed if voila is launch from this tile\n",
"ig_about"
]
},
Expand Down
18 changes: 9 additions & 9 deletions component/message/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@

from sepal_ui.translator import Translator

# the sepal_ui allows you to create a translation interface
# at the moment this variable is not yet available but it's a good practice to build your app translatio-ready
# the sepal_ui allows you to create a translation interface
# at the moment this variable is not yet available but it's a good practice to build your app translatio-ready

# first select the language env variable to load the destination locale
# it will default to en
lang = 'en'
if 'CUSTOM_LANGUAGE' in os.environ:
lang = os.environ['CUSTOM_LANGUAGE']
lang = "en"
if "CUSTOM_LANGUAGE" in os.environ:
lang = os.environ["CUSTOM_LANGUAGE"]

# create a ms object that will be used to translate all the messages
# the base language is english and every untranslated messages will be fallback to the english key
# complete the json file the add keys in the app
# create a ms object that will be used to translate all the messages
# the base language is english and every untranslated messages will be fallback to the english key
# complete the json file the add keys in the app
# avoid hard written messages at all cost
cm = Translator(Path(__file__).parent, lang)
cm = Translator(Path(__file__).parent, lang)
2 changes: 1 addition & 1 deletion component/message/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
},
"tile": {
"asset_lbl": "Asset name",
"nb_batch_lbl": "Select number of tiles in a batch",
"nb_batch_lbl": "Select batch size",
"btn": "Tile the AOI",
"title": "Tiling interface",
"grid_layer": "grid"
Expand Down
8 changes: 4 additions & 4 deletions component/message/test_translation.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"outputs": [],
"source": [
"# this notebook is only here to provide the position of the missing keys\n",
"# the base dict is the english one. \n",
"# the base dict is the english one.\n",
"# it should be complete\n",
"\n",
"from pathlib import Path\n",
Expand All @@ -23,8 +23,8 @@
"metadata": {},
"outputs": [],
"source": [
"# select the language you want to test \n",
"locale = 'en'"
"# select the language you want to test\n",
"locale = \"en\""
]
},
{
Expand All @@ -45,7 +45,7 @@
"outputs": [],
"source": [
"# normally there is only one key lissing ('not_tranlated')\n",
"# at the root of the file \n",
"# at the root of the file\n",
"print(ms.missing_keys())"
]
},
Expand Down
2 changes: 1 addition & 1 deletion component/parameter/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .directory import *
from .directory import *
10 changes: 4 additions & 6 deletions component/parameter/directory.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
from pathlib import Path

module_res_dir = Path('~', 'module_results').expanduser()
module_res_dir.mkdir(exist_ok = True)

down_dir = module_res_dir.joinpath('aoi')
down_dir.mkdir(exist_ok = True)

module_res_dir = Path("~", "module_results").expanduser()
module_res_dir.mkdir(exist_ok=True)

down_dir = module_res_dir.joinpath("aoi")
down_dir.mkdir(exist_ok=True)
2 changes: 1 addition & 1 deletion component/scripts/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from .utils import *
from .tiling import *
from .tiling import *
122 changes: 62 additions & 60 deletions component/scripts/tiling.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,19 @@

d.getcontext().prec = 15


def set_grid(aoi, grid_batch, grid_name, output):
"""compute a grid around a given aoi (ee.FeatureCollection) that fits the Planet Lab requirements"""
# get the shape of the aoi in EPSG:4326 proj
aoi_gdf = aoi.to_crs('EPSG:3857')

# get the shape of the aoi in EPSG:4326 proj
aoi_gdf = aoi.to_crs("EPSG:3857")

output.add_live_msg(cm.digest_aoi)

# retreive the bounding box
aoi_bb = sg.box(*aoi_gdf.total_bounds)
aoi_bb.bounds

# compute the longitude and latitude in the apropriate CRS
crs_4326 = CRS.from_epsg(4326)
crs_3857 = CRS.from_epsg(3857)
Expand All @@ -37,82 +38,83 @@ def set_grid(aoi, grid_batch, grid_name, output):
bl = proj.transform(crs_min_x, crs_min_y)
tr = proj.transform(crs_max_x, crs_max_y)

# the planet grid is constructing a 2048x2048 grid of SQUARES.
# the planet grid is constructing a 2048x2048 grid of SQUARES.
# The latitude extends is bigger (20048966.10m VS 20026376.39) so to ensure the "squariness"
# Planet lab have based the numerotation and extends of it square grid on the longitude only.
# Planet lab have based the numerotation and extends of it square grid on the longitude only.
# the extreme -90 and +90 band it thus exlucded but there are no forest there so we don't care
longitudes = np.linspace(bl[0], tr[0], 2048+1)
longitudes = np.linspace(bl[0], tr[0], 2048 + 1)

# the planet grid size cut the world in 248 squares vertically and horizontally
box_size = (tr[0]-bl[0])/2048
box_size = (tr[0] - bl[0]) / 2048


# filter with the geometry bounds
min_lon, min_lat, max_lon, max_lat = aoi_gdf.total_bounds

# filter lon and lat
lon_filter = longitudes[(longitudes > (min_lon - box_size)) & (longitudes < max_lon + box_size)]
lat_filter = longitudes[(longitudes > (min_lat - box_size)) & (longitudes < max_lat + box_size)]
# filter lon and lat
lon_filter = longitudes[
(longitudes > (min_lon - box_size)) & (longitudes < max_lon + box_size)
]
lat_filter = longitudes[
(longitudes > (min_lat - box_size)) & (longitudes < max_lat + box_size)
]

# get the index offset
# get the index offset
x_offset = np.nonzero(longitudes == lon_filter[0])[0][0]
y_offset = np.nonzero(longitudes == lat_filter[0])[0][0]

output.add_live_msg(cm.build_grid)


# count the number of batch cell in width
batch_width = (len(lat_filter) - 1) // grid_batch
# create the grid
batch = []
x = []
y = []
names = []
squares = []
for i, coords in enumerate(product(range(len(lon_filter)-1), range(len(lat_filter)-1))):

# get the x and y index
ix = coords[0]
iy = coords[1]

batch, x, y, names, squares = [], [], [], [], []
for ix, iy in product(range(len(lon_filter) - 1), range(len(lat_filter) - 1)):

# fill the grid values
batch.append(i//grid_batch)
batch_id = (ix // grid_batch) * (batch_width + 1) + (iy // grid_batch)
batch.append(batch_id)
x.append(ix + x_offset)
y.append(iy + y_offset)
names.append(f'L15-{x[-1]:4d}E-{y[-1]:4d}N.tif')
squares.append(sg.box(lon_filter[ix], lat_filter[iy], lon_filter[ix+1], lat_filter[iy+1]))

names.append(f"L15-{x[-1]:4d}E-{y[-1]:4d}N.tif")
squares.append(
sg.box(
lon_filter[ix], lat_filter[iy], lon_filter[ix + 1], lat_filter[iy + 1]
)
)

# create a buffer grid in lat-long
grid = gpd.GeoDataFrame({'batch': batch, 'x':x, 'y':y, 'names':names, 'geometry':squares}, crs='EPSG:3857')
grid = gpd.GeoDataFrame(
{"batch": batch, "x": x, "y": y, "names": names, "geometry": squares},
crs="EPSG:3857",
)

# cut the grid to the aoi extends
mask = grid.intersects(aoi_gdf.dissolve()['geometry'][0])
# cut the grid to the aoi extends
mask = grid.intersects(aoi_gdf.dissolve()["geometry"][0])
grid = grid.loc[mask]

# project back to 4326
grid = grid.to_crs('EPSG:4326')
# export the grid as a json file
path = cp.down_dir.joinpath(f'{grid_name}.geojson')
grid.to_file(path, driver='GeoJSON')
output.add_live_msg(cm.grid_complete, 'success')
grid = grid.to_crs("EPSG:4326")

# export the grid as a json file
path = cp.down_dir.joinpath(f"{grid_name}.geojson")
grid.to_file(path, driver="GeoJSON")

output.add_live_msg(cm.grid_complete, "success")

return geemap.geojson_to_ee(grid.__geo_interface__)


def preview_square(geometry, grid_size):

# get the center of the aoi
center = geometry.centroid().getInfo()['coordinates']

# create the square
square = gpd.GeoDataFrame({'geometry': [Point(center[0], center[1])]}, crs='EPSG:4326') \
.to_crs('EPSG:3857') \
.buffer(grid_size*1000) \
.envelope \
.to_crs('EPSG:4326')

center = geometry.centroid().getInfo()["coordinates"]

# create the square
square = (
gpd.GeoDataFrame({"geometry": [Point(center[0], center[1])]}, crs="EPSG:4326")
.to_crs("EPSG:3857")
.buffer(grid_size * 1000)
.envelope.to_crs("EPSG:4326")
)

return geemap.geojson_to_ee(square.__geo_interface__)






13 changes: 7 additions & 6 deletions component/scripts/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@

ee.Initialize()


def display_asset(output, asset):
"""remove the manifest from the asset name and display it to the user"""
asset = asset.replace('projects/earthengine-legacy/assets/', '')
output.add_msg(cm.asset_created.format(asset), 'success')
return asset

asset = asset.replace("projects/earthengine-legacy/assets/", "")

output.add_msg(cm.asset_created.format(asset), "success")

return asset
2 changes: 1 addition & 1 deletion component/tile/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from .download_tile import *
from .tile_tile import *
from .tile_tile import *
Loading

0 comments on commit 4c0a4b4

Please sign in to comment.