Skip to content

Commit

Permalink
Merge ccb8e98 into 1e4f02e
Browse files Browse the repository at this point in the history
  • Loading branch information
ungarj committed Jul 23, 2020
2 parents 1e4f02e + ccb8e98 commit c873412
Show file tree
Hide file tree
Showing 16 changed files with 318 additions and 209 deletions.
19 changes: 8 additions & 11 deletions README.rst
Expand Up @@ -80,22 +80,19 @@ itself.

.. code-block:: python
def execute(mp, resampling="nearest"):
def execute(mp, dem, land_polygons, resampling="nearest"):
# Open elevation model.
with mp.open("dem") as src:
# Skip tile if there is no data available or read data into a NumPy array.
if src.is_empty(1):
return "empty"
else:
dem = src.read(1, resampling=resampling)
# Skip tile if there is no data available or read data into a NumPy array.
if dem.is_empty(1):
return "empty"
else:
dem_data = dem.read(1, resampling=resampling)
# Create hillshade using a built-in hillshade function.
hillshade = mp.hillshade(dem)
hillshade = mp.hillshade(dem_data)
# Clip with polygons from vector file and return result.
with mp.open("land_polygons") as land_file:
return mp.clip(hillshade, land_file.read())
return mp.clip(hillshade, land_polygons.read())
You can then interactively inspect the process output directly on a map in a
Expand Down
19 changes: 8 additions & 11 deletions doc/source/index.rst
Expand Up @@ -61,22 +61,19 @@ vector dataset could look like this:
# content of hillshade.py
def execute(mp, resampling="nearest"):
def execute(mp, dem, land_polygons, resampling="nearest"):
# Open elevation model.
with mp.open("dem") as src:
# Skip tile if there is no data available or read data into a NumPy array.
if src.is_empty(1):
return "empty"
else:
dem = src.read(1, resampling=resampling)
# Skip tile if there is no data available or read data into a NumPy array.
if dem.is_empty(1):
return "empty"
else:
dem_data = dem.read(1, resampling=resampling)
# Create hillshade using a built-in hillshade function.
hillshade = mp.hillshade(dem)
hillshade = mp.hillshade(dem_data)
# Clip with polygons from vector file and return result.
with mp.open("land_polygons") as land_file:
return mp.clip(hillshade, land_file.read())
return mp.clip(hillshade, land_polygons.read())
Examine the result in your browser by serving the process by pointing it to
Expand Down
25 changes: 16 additions & 9 deletions mapchete/_processing.py
Expand Up @@ -87,18 +87,25 @@ def _execute(self):
process_func = get_process_func(
process_path=self.process_path, config_dir=self.config_dir
)
mp_obj = MapcheteProcess(
tile=self.tile,
params=self.process_func_params,
input=self.input,
output_params=self.output_params
)
try:
with Timer() as t:
params = [
# magic mp object
mp_obj if name == "mp"
# process input
else mp_obj.input[name] if name in mp_obj.input
# process parameter
else value
for name, value in self.process_func_params.items()
]
# Actually run process.
process_data = process_func(
MapcheteProcess(
tile=self.tile,
params=self.process_func_params,
input=self.input,
output_params=self.output_params
),
**self.process_func_params
)
process_data = process_func(*params)
except MapcheteNodataTile:
raise
except Exception as e:
Expand Down
54 changes: 49 additions & 5 deletions mapchete/config.py
Expand Up @@ -381,7 +381,7 @@ def input(self):
for k, v in raw_inputs.items():
# for files and tile directories
if isinstance(v, str):
logger.debug("load input reader for simple input %s", v)
logger.debug("load input reader for simple input %s", v)
try:
reader = load_input_reader(
dict(
Expand Down Expand Up @@ -481,10 +481,54 @@ def process_func(self):
)

def get_process_func_params(self, zoom):
return {
k: v for k, v in self.params_at_zoom(zoom).items()
if k in inspect.signature(self.process_func).parameters
}
"""
Return process function parameters for zoom.
The dictionary returned is a snapshot for given zoom which combines custom process
parameters and input datasets.
This function also checks whether parameter names are also used as input names and
raises a MapcheteConfigError if this is the case.
Parameters
----------
zoom : int
zoom level
Returns
-------
parameter map : dictionary
"""
if zoom not in self.init_zoom_levels:
raise ValueError("zoom level not available with current configuration")
process_func_params = inspect.signature(self.process_func).parameters
all_config_params = self.params_at_zoom(zoom)

# look for config parameters which map on process function parameters
inputs = set(all_config_params["input"].keys()) & set(process_func_params)
custom_params = set(all_config_params.keys()) & set(process_func_params)

# verify no parameter name intersection is configured
intersecting = custom_params & inputs
if intersecting:
raise MapcheteConfigError(
"custom parameters and inputs cannot have the same key: %s" % intersecting
)

# bring all together
return OrderedDict([
# set mp value
(k, None) if k == "mp"
# input values from configuration
else (k, all_config_params["input"][k]) if k in all_config_params["input"]
# custom values from configuration
else (k, all_config_params[k]) if k in all_config_params
# default values from process function
else (k, v.default)
for k, v in process_func_params.items()
# excludes **kwargs from process function
if v.kind != v.VAR_KEYWORD
])

def get_inputs_for_tile(self, tile):

Expand Down
42 changes: 20 additions & 22 deletions mapchete/processes/contours.py
Expand Up @@ -7,6 +7,8 @@

def execute(
mp,
dem=None,
clip=None,
resampling="nearest",
interval=100,
field='elev',
Expand All @@ -19,17 +21,14 @@ def execute(
**kwargs
):
"""
Generate hillshade from DEM.
Generate contours from DEM.
Inputs
------
Parameters
----------
dem
Input DEM.
clip (optional)
Vector data used to clip output.
Parameters
----------
resampling : str (default: 'nearest')
Resampling used when reading from TileDirectory.
interval : integer
Expand Down Expand Up @@ -64,26 +63,25 @@ def execute(
list of GeoJSON-like features
"""
# read clip geometry
if "clip" in mp.params["input"]:
clip_geom = mp.open("clip").read()
if clip is None:
clip_geom = []
else:
clip_geom = clip.read()
if not clip_geom:
logger.debug("no clip data over tile")
return "empty"
else:
clip_geom = []

with mp.open("dem",) as dem:
logger.debug("reading input raster")
dem_data = dem.read(
resampling=resampling,
matching_method=td_matching_method,
matching_max_zoom=td_matching_max_zoom,
matching_precision=td_matching_precision,
fallback_to_higher_zoom=td_fallback_to_higher_zoom
)
if dem_data.mask.all():
logger.debug("raster empty")
return "empty"
logger.debug("reading input raster")
dem_data = dem.read(
resampling=resampling,
matching_method=td_matching_method,
matching_max_zoom=td_matching_max_zoom,
matching_precision=td_matching_precision,
fallback_to_higher_zoom=td_fallback_to_higher_zoom
)
if dem_data.mask.all():
logger.debug("raster empty")
return "empty"

logger.debug("calculate hillshade")
contours = mp.contours(
Expand Down
42 changes: 20 additions & 22 deletions mapchete/processes/convert.py
Expand Up @@ -6,6 +6,8 @@

def execute(
mp,
raster=None,
clip=None,
resampling="nearest",
band_indexes=None,
td_matching_method="gdal",
Expand All @@ -21,15 +23,12 @@ def execute(
"""
Convert and optionally clip input raster data.
Inputs
------
Parameters
----------
raster
Singleband or multiband data input.
clip (optional)
Vector data used to clip output.
Parameters
----------
resampling : str (default: 'nearest')
Resampling used when reading from TileDirectory.
band_indexes : list
Expand Down Expand Up @@ -66,27 +65,26 @@ def execute(
np.ndarray
"""
# read clip geometry
if "clip" in mp.params["input"]:
clip_geom = mp.open("clip").read()
if clip is None:
clip_geom = []
else:
clip_geom = clip.read()
if not clip_geom:
logger.debug("no clip data over tile")
return "empty"
else:
clip_geom = []

with mp.open("raster",) as raster:
logger.debug("reading input raster")
raster_data = raster.read(
indexes=band_indexes,
resampling=resampling,
matching_method=td_matching_method,
matching_max_zoom=td_matching_max_zoom,
matching_precision=td_matching_precision,
fallback_to_higher_zoom=td_fallback_to_higher_zoom
)
if raster_data.mask.all():
logger.debug("raster empty")
return "empty"
logger.debug("reading input raster")
raster_data = raster.read(
indexes=band_indexes,
resampling=resampling,
matching_method=td_matching_method,
matching_max_zoom=td_matching_max_zoom,
matching_precision=td_matching_precision,
fallback_to_higher_zoom=td_fallback_to_higher_zoom
)
if raster_data.mask.all():
logger.debug("raster empty")
return "empty"

if scale_offset != 0.:
logger.debug("apply scale offset %s", scale_offset)
Expand Down
42 changes: 20 additions & 22 deletions mapchete/processes/hillshade.py
Expand Up @@ -5,6 +5,8 @@

def execute(
mp,
dem=None,
clip=None,
resampling="nearest",
azimuth=315.0,
altitude=45.0,
Expand All @@ -18,17 +20,14 @@ def execute(
**kwargs
):
"""
Extract contour lines from DEM.
Calculate hillshade from DEM.
Inputs
------
Parameters
----------
dem
Input DEM.
clip (optional)
Vector data used to clip output.
Parameters
----------
resampling : str (default: 'nearest')
Resampling used when reading from TileDirectory.
azimuth : float
Expand Down Expand Up @@ -66,26 +65,25 @@ def execute(
np.ndarray
"""
# read clip geometry
if "clip" in mp.params["input"]:
clip_geom = mp.open("clip").read()
if clip is None:
clip_geom = []
else:
clip_geom = clip.read()
if not clip_geom:
logger.debug("no clip data over tile")
return "empty"
else:
clip_geom = []

with mp.open("dem",) as dem:
logger.debug("reading input raster")
dem_data = dem.read(
resampling=resampling,
matching_method=td_matching_method,
matching_max_zoom=td_matching_max_zoom,
matching_precision=td_matching_precision,
fallback_to_higher_zoom=td_fallback_to_higher_zoom
)
if dem_data.mask.all():
logger.debug("raster empty")
return "empty"
logger.debug("reading input DEM")
dem_data = dem.read(
resampling=resampling,
matching_method=td_matching_method,
matching_max_zoom=td_matching_max_zoom,
matching_precision=td_matching_precision,
fallback_to_higher_zoom=td_fallback_to_higher_zoom
)
if dem_data.mask.all():
logger.debug("raster empty")
return "empty"

logger.debug("calculate hillshade")
hillshade = mp.hillshade(
Expand Down

0 comments on commit c873412

Please sign in to comment.