Source code for reVX.setbacks.setbacks

# -*- coding: utf-8 -*-
"""
Setback exclusion computation classes
"""
import logging

from reVX.setbacks.base import AbstractBaseSetbacks, BUFFERS, FEATURE_FILTERS


logger = logging.getLogger(__name__)


def _format_str(in_str):
    """Format a string like regulation class does. """
    return in_str.strip().lower().replace("-", " ").replace("_", " ")


def _camel_case_str(in_str):
    """Format a string into CamelCase"""
    return _format_str(in_str).title().replace(" ", "")


[docs]def setbacks_calculator(feature_type, buffer_type="default", feature_filter_type="centroid", feature_subtypes_to_exclude=None, num_features_per_worker=10_000): """Generate a setback calculator for a particular feature. Parameters ---------- feature_type : str | list String or list of strings that represent how this feature is distinguished in the local regulations file. In particular, this string (or list of strings) should match the values under the ``Feature Type`` column of the setback regulations file corresponding to this feature. For example, specifying ``feature_type="property line"`` would mean that this setback calculator looks for ``"property line"`` regulations (i.e. parcel setbacks) in the input regulations file. This input is case insensitive (i.e. "ROADS", "Roads", "roads", and "rOAds" are all equivalent), and spaces, dashes, and underscores are interchangeable (i.e. "property line", "property_line", and "property-line" are all equivalent). buffer_type : str, optional Name of the buffer type to use for this setback calculation. See :attr:`~reVX.setbacks.base.BUFFERS` for all available options - this input must be a key from that dictionary. In most cases, the default positive buffer is suitable. By default, ``"default"``. feature_filter_type : str, optional Name of the feature filter type to use for this setback calculation. Typically, features like structures or parcels are filtered using "centroid", which only applies setback regulations to features whose centroid is within the county with the ordinance. On the other hand, features such as roads, railroads transmission lines, etc., are filtered using "clip", which clips the feature to the county boundaries before applying a setback. This value must be a key in the :attr:`~reVX.setbacks.base.FEATURE_FILTERS` dictionary. By default, ``"centroid"``. feature_subtypes_to_exclude : list | set, optional A list of strings specifying the feature subtypes that should be excluded from the local regulations calculation. By default, ``None``. num_features_per_worker : int, optional Number of features each worker (CPU processor) on a node processes. By default, ``10,000``. Returns ------- class A class object that can be used to instantiate the setbacks calculator. The initializer parameters are identical to that of :class:`~reVX.setbacks.base.AbstractBaseSetbacks`. """ if isinstance(feature_type, str): feature_type = [feature_type] camel_case_feature = "".join(map(_camel_case_str, sorted(feature_type))) feature_type = set(map(_format_str, feature_type)) if buffer_type not in BUFFERS: msg = ("Unknown buffer type specified: {!r}. Must be one of {}" .format(buffer_type, list(BUFFERS))) logger.error(msg) raise ValueError(msg) if feature_filter_type not in FEATURE_FILTERS: msg = ("Unknown feature filter type specified: {!r}. Must be one of {}" .format(feature_filter_type, list(FEATURE_FILTERS))) logger.error(msg) raise ValueError(msg) feature_subtypes_to_exclude = set(feature_subtypes_to_exclude or set()) num_features_per_worker = int(max(0, num_features_per_worker) or 10_000) class_name = "{}Setbacks".format(camel_case_feature) class_attrs = {"FEATURE_TYPES": feature_type, "FEATURE_SUBTYPES_TO_EXCLUDE": feature_subtypes_to_exclude, "BUFFER_TYPE": buffer_type, "FEATURE_FILTER_TYPE": feature_filter_type, "NUM_FEATURES_PER_WORKER": num_features_per_worker} return type(class_name, (AbstractBaseSetbacks,), class_attrs)
SETBACK_SPECS = { "parcel": { "feature_type": "property line", "buffer_type": "parcel", "feature_filter_type": "centroid", "feature_subtypes_to_exclude": None, "num_features_per_worker": 10_000, }, "rail": { "feature_type": "railroads", "buffer_type": "default", "feature_filter_type": "clip", "feature_subtypes_to_exclude": None, "num_features_per_worker": 10_000, }, "road": { "feature_type": ['roads', 'highways', 'highways 111'], "buffer_type": "default", "feature_filter_type": "clip", "feature_subtypes_to_exclude": None, "num_features_per_worker": 10_000, }, "structure": { "feature_type": "structures", "buffer_type": "default", "feature_filter_type": "centroid", "feature_subtypes_to_exclude": ["Occupied Community Buildings"], "num_features_per_worker": 10_000, }, "transmission": { "feature_type": "transmission", "buffer_type": "default", "feature_filter_type": "clip", "feature_subtypes_to_exclude": None, "num_features_per_worker": 10_000, }, "water": { "feature_type": "water", "buffer_type": "default", "feature_filter_type": "clip", "feature_subtypes_to_exclude": None, "num_features_per_worker": 700, }, } """Default Setback Calculator Specifications. These calculators are available by default. To use them, simply match the key in this dictionary with your dataset path. """ SETBACKS = {key: setbacks_calculator(**kwargs) for key, kwargs in SETBACK_SPECS.items()}