"""
Definition of friction, barrier, and costs processing JSON config file
"""
from pathlib import Path
from typing import Optional, Dict, List, Literal
from pydantic import BaseModel, DirectoryPath, FilePath
from reVX.least_cost_xmission.config import IsoMultipliers
# Terms for specifying masks. 'wet+' and 'dry+' indicated 'wet' + 'landfall'
# and 'dry' + 'landfall', respectively.
Extents = Literal['all', 'wet', 'wet+', 'landfall', 'dry+', 'dry']
[docs]class RangeConfig(BaseModel, extra='forbid'):
"""
Config for defining a range and a value to assign to cells matching that
range. Cells with values >= than 'min' and < 'max' will be assigned
'value'. One or both of 'min' and 'max' can be specified.
"""
min: float = float('-inf')
"""Minimum value to get a cost assigned (inclusive)"""
max: float = float('inf')
"""Maximum value to get a cost assigned (exclusive)"""
value: float
"""Value to assign to the range defined by `min` and `max`."""
[docs]class Rasterize(BaseModel, extra='forbid'):
"""
Rasterize a vector layer and apply a value to it.
"""
value: float
"""Value to burn in to raster"""
buffer: Optional[float] = None
"""Value to buffer by (can be negative)"""
reproject: bool = True
"""Reproject vector to raster CRS if ``True``"""
[docs]class FBLayerConfig(BaseModel, extra='forbid'):
"""
Friction and barrier layers config model. 'extent' is mandatory. 'map',
'range', and 'rasterize', and 'forced_inclusion' are exclusive, but one
must be specified. Example configs can be seen in
test_xmission_barrier_friction_builder.py in the tests directory.
"""
extent: Extents
"""Extent to apply map or range to"""
map: Optional[Dict[float, float]] = None
"""Values in raster (keys) and values to use for barrier/friction"""
range: Optional[List[RangeConfig]] = None
"""Ranges of raster values.
This input can be one or more ranges of raster values to apply to
barrier/friction. The value of overlapping ranges are added together."""
rasterize: Optional[Rasterize] = None
"""Rasterize a vector and use as a friction or barrier layer"""
forced_inclusion: bool = False
"""Force inclusion.
If `forced_inclusion` is ``True``, any cells with a value > 0 will
force the final value of corresponding cells to 0. Multiple forced
inclusions are allowed."""
[docs]class WetCosts(BaseModel, extra='forbid'):
""" Config items required to generate wet costs """
bins: List[RangeConfig]
"""Bins (ranges) for determining depth based costs"""
bathy_tiff: FilePath
"""File name of bathymetric depth GeoTIFF"""
[docs]class DryCosts(BaseModel, extra='forbid'):
""" Config items required to generate dry costs """
iso_region_tiff: FilePath
"""Filename of ISO region GeoTIFF"""
nlcd_tiff: FilePath
"""File name of NLCD GeoTiff"""
slope_tiff: FilePath
"""File name of slope GeoTiff"""
cost_configs: Optional[FilePath] = None
"""Path to json file with Xmission cost configuration values.
Path to json file contianing dictionary with Xmission cost
configuration values. Valid configuration keysare:
- "base_line_costs"
- "iso_lookup"
- "iso_multipliers"
- "land_use_classes"
- "new_substation_costs"
- "power_classes"
- "power_to_voltage"
- "transformer_costs"
- "upgrade_substation_costs"
Each of these keys should point to a dictionary or a path to
a separate json file contianing a dictionary of
configurations for each section."""
default_mults: Optional[IsoMultipliers] = None
"""Multipliers to be used for default region.
This input should be a dictionary with three keys:
- "iso": Thie key is ignored, but is required. Can set to
"default" and move on.
- "land_use": A dictionary where keys are the land use types
(e.g. "cropland", "forest", "wetland", etc.) and values are
the multipliers for those land uses.
- "slope": A dictionary where keys are the slope types/mults
(e.g. "hill_mult", "hill_slope", "mtn_mult", "mtn_slope",
etc.) and values are the slopes/multipliers.
"""
extra_tiffs: Optional[List[FilePath]] = None
"""Optional list of extra GeoTIFFs to add to cost H5 file. """
[docs]class MergeFrictionBarriers(BaseModel, extra='forbid'):
"""
Combine friction and barriers and save to H5. Multiple all barrier values
by a factor. The multiplier should be large enough that all barriers have
a higher value than any possible friction.
"""
barrier_multiplier: float = 1e6
"""Value to multiply barrier layer by during merge with friction.
The multiplier should be large enough that all barriers have
a higher value than any possible friction."""
FrictionLayers = Dict[str, FBLayerConfig]
"""Mapping of friction layers.
Keys are GeoTIFF or vector filepaths. Values are the FBLayerConfig to use for
that file."""
BarrierLayers = Dict[str, FBLayerConfig]
"""Mapping of barrier layers.
Keys are GeoTIFF or vector filepaths. Values are the FBLayerConfig to use for
that file."""
[docs]class LayerCreationConfig(BaseModel):
"""
Definition of friction, barrier, and costs processing JSON config file.
"""
template_raster_fpath: FilePath
"""Template raster GeoTIFF for shape and profile"""
h5_fpath: FilePath
"""H5 to store results in."""
layer_dir: DirectoryPath = Path('.')
"""Directory to look for GeoTIFFs in, in addition to '.'"""
masks_dir: DirectoryPath = Path('.')
"""Optional path for mask GeoTIFFs."""
ignore_masks: Optional[bool] = False
"""Optional flag to ignore masks for cost creation (useful for dry runs)"""
friction_layers: Optional[FrictionLayers] = None
"""Optional friction layer.
At least one of `friction_layers`, `barrier_layers`, `wet_costs`,
`dry_costs`, 'landfall_cost' , or `merge_friction_and_barriers` must
be defined.
"""
barrier_layers: Optional[BarrierLayers] = None
"""Optional barrier layer.
At least one of `friction_layers`, `barrier_layers`, `wet_costs`,
`dry_costs`, 'landfall_cost' , or `merge_friction_and_barriers` must
be defined.
"""
wet_costs: Optional[WetCosts] = None
"""Optional wet cost layer.
At least one of `friction_layers`, `barrier_layers`, `wet_costs`,
`dry_costs`, 'landfall_cost' , or `merge_friction_and_barriers` must
be defined.
"""
dry_costs: Optional[DryCosts] = None
"""Optional dry cost layer.
At least one of `friction_layers`, `barrier_layers`, `wet_costs`,
`dry_costs`, 'landfall_cost' , or `merge_friction_and_barriers` must
be defined.
"""
landfall_cost: Optional[float] = None
"""Cost to transition from wet to dry transmission.
If this input is specified, a landfall cost layer is created.
At least one of `friction_layers`, `barrier_layers`, `wet_costs`,
`dry_costs`, 'landfall_cost' , or `merge_friction_and_barriers` must
be defined.
"""
merge_friction_and_barriers: Optional[MergeFrictionBarriers] = None
"""Optional config to merge friction barriers.
At least one of `friction_layers`, `barrier_layers`, `wet_costs`,
`dry_costs`, 'landfall_cost' , or `merge_friction_and_barriers` must
be defined.
"""
output_tiff_dir: DirectoryPath = Path('.')
"""Directory to store output tiff files in. """