Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

main_to_develop #93

Merged
merged 9 commits into from
Sep 19, 2024
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: 31 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,34 @@

- fixed last_version_date in aligner.get_formula()
- fixed logic of evaluate() in grb.py
- added function to transform geojson to consistent geometry-type (MultiPolygon)
- added function to transform geojson to consistent geometry-type (MultiPolygon)

# 0.3.0

! Not Backwards compatable !

- Refactoring:
- refactor the structure of the (internal) dicts: dict_series, dict_predicted. More logical and faster [#57]
- refactoring of 'formula-function': more generic [#59]
- removed deprecated loaders from codebase [#77]
- simplify the core-functionalities of Aligner: process, predict, compare [#89]
- cleanup unused functions [#81]

- Functionalities:
- Add brdr-version to formula [#66]
- predict: filter duplicate predictions [#70]
- Predictor: add a attribute (nr_calculations) that states how many predictions are found, so it can used in the
output [#69]
- Added GRB-function"update_to_actual_version", to be used in brdrQ [#64]
- Added GRBSpecificDateLoader: Alignment on GRB (parcels) on specific date [#63]
- Added OnroerendErfgoedLoader, to load OnroerendErfgoed-data [#65]
- Bugfixing:
- adding a safe_equals-function to catch GEOsException bug [#71]








2 changes: 1 addition & 1 deletion brdr/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.2.1"
__version__ = "0.3.0"
202 changes: 122 additions & 80 deletions brdr/aligner.py

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions brdr/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@

FORMULA_FIELD_NAME = "brdr_formula"
EVALUATION_FIELD_NAME = "brdr_evaluation"
NR_CALCULATION_FIELD_NAME = "brdr_nr_calculations"
RELEVANT_DISTANCE_FIELD_NAME = "brdr_relevant_distance"
LAST_VERSION_DATE = "last_version_date"
VERSION_DATE = "version_date"
Expand Down
78 changes: 51 additions & 27 deletions brdr/oe.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,17 @@ def get_oe_dict_by_ids(objectids, oetype=OEType.AO):
logging.warning("deprecated method, use OnroerendErfgoedLoader instead")
# TODO remove function
dict_thematic = {}
if oetype==OEType.AO:
if oetype == OEType.AO:
typename = "aanduidingsobjecten"
#id_property = "aanduid_id"
elif oetype==OEType.EO:
# id_property = "aanduid_id"
elif oetype == OEType.EO:
typename = "erfgoedobjecten"
#id_property = "erfgoed_id"
# id_property = "erfgoed_id"
else:
logging.warning("Undefined OE-type: " + str(oetype) + ": Empty collection returned")
return {},None
logging.warning(
"Undefined OE-type: " + str(oetype) + ": Empty collection returned"
)
return {}, None

base_url = "https://inventaris.onroerenderfgoed.be/" + typename + "/"
headers = {"Accept": "application/json"}
Expand All @@ -77,7 +79,14 @@ def get_oe_dict_by_ids(objectids, oetype=OEType.AO):
return dict_thematic


def get_collection_oe_objects(oetype=OEType.AO,objectids=None,bbox=None,limit=DOWNLOAD_LIMIT, partition=1000 ,crs=DEFAULT_CRS):
def get_collection_oe_objects(
oetype=OEType.AO,
objectids=None,
bbox=None,
limit=DOWNLOAD_LIMIT,
partition=1000,
crs=DEFAULT_CRS,
):
"""
Fetches GeoJSON data for designated heritage objects (aanduidingsobjecten) within
a bounding box.
Expand All @@ -97,65 +106,80 @@ def get_collection_oe_objects(oetype=OEType.AO,objectids=None,bbox=None,limit=DO
collection might be truncated if the total number of features exceeds
the specified limit.
"""
if oetype==OEType.AO:
if oetype == OEType.AO:
typename = "ps:ps_aandobj"
id_property = "aanduid_id"
elif oetype==OEType.EO:
elif oetype == OEType.EO:
typename = "lu:lu_wet_erfgobj_pub"
id_property = "erfgoed_id"
else:
logging.warning("Undefined OE-type: " + str(oetype) + ": Empty collection returned")
return {},None

logging.warning(
"Undefined OE-type: " + str(oetype) + ": Empty collection returned"
)
return {}, None

theme_url = (
"https://www.mercator.vlaanderen.be/raadpleegdienstenmercatorpubliek/wfs?"
"SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&"
f"TYPENAMES={typename}&"
f"SRSNAME={crs}"
"&outputFormat=application/json"

)
if objectids is not None:
filter = f"&CQL_FILTER={id_property} IN (" + ', '.join(str(o) for o in objectids) + ")"
filter = (
f"&CQL_FILTER={id_property} IN ("
+ ", ".join(str(o) for o in objectids)
+ ")"
)
theme_url = theme_url + filter
bbox_polygon = None
if bbox is not None:
bbox_polygon = box(*tuple(o for o in bbox))

return get_collection_by_partition(
theme_url, geometry=bbox_polygon, partition=partition, limit=limit, crs=crs
),id_property
return (
get_collection_by_partition(
theme_url, geometry=bbox_polygon, partition=partition, limit=limit, crs=crs
),
id_property,
)


class OnroerendErfgoedLoader(GeoJsonLoader):
def __init__(self, objectids=None, oetype=OEType.AO, bbox = None,limit=DOWNLOAD_LIMIT, partition=1000,crs=DEFAULT_CRS):
if (objectids is None and bbox is None) or (objectids is not None and bbox is not None):
def __init__(
self,
objectids=None,
oetype=OEType.AO,
bbox=None,
limit=DOWNLOAD_LIMIT,
partition=1000,
crs=DEFAULT_CRS,
):
if (objectids is None and bbox is None) or (
objectids is not None and bbox is not None
):
raise ValueError("Please provide a ID-filter OR a BBOX-filter, not both")
super().__init__()
self.objectids = objectids
self.oetype = oetype
self.bbox = bbox
self.limit= limit
self.limit = limit
self.part = partition
self.crs=crs
self.crs = crs
self.data_dict_source["source"] = "Onroerend Erfgoed"

def load_data(self):

#geom_union = buffer_pos(self.aligner.get_thematic_union(), MAX_REFERENCE_BUFFER)
collection,id_property = get_collection_oe_objects(
# geom_union = buffer_pos(self.aligner.get_thematic_union(), MAX_REFERENCE_BUFFER)
collection, id_property = get_collection_oe_objects(
oetype=self.oetype,
objectids=self.objectids,
bbox=self.bbox,
partition=self.part,
limit = self.limit,
crs = self.crs
limit=self.limit,
crs=self.crs,
)
self.id_property = id_property
self.input = dict(collection)
self.data_dict_source[VERSION_DATE] = datetime.now().strftime(DATE_FORMAT)
LOGGER.debug(f"OnroerendErfgoed-objects downloaded")
return super().load_data()


28 changes: 20 additions & 8 deletions brdr/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@
from shapely.geometry import shape
from shapely.geometry.base import BaseGeometry

from brdr.constants import MULTI_SINGLE_ID_SEPARATOR, DEFAULT_CRS, DOWNLOAD_LIMIT, RELEVANT_DISTANCE_FIELD_NAME
from brdr.constants import (
MULTI_SINGLE_ID_SEPARATOR,
DEFAULT_CRS,
DOWNLOAD_LIMIT,
RELEVANT_DISTANCE_FIELD_NAME,
NR_CALCULATION_FIELD_NAME,
)
from brdr.enums import DiffMetric
from brdr.geometry_utils import get_partitions, get_bbox
from brdr.typings import ProcessResult
Expand All @@ -33,10 +39,12 @@ def get_series_geojson_dict(
features_list_dict = {}

for theme_id, results_dict in series_dict.items():
nr_calculations = len(results_dict)
prop_dict = dict(series_prop_dict or {}).get(theme_id, {})
for relative_distance, process_result in results_dict.items():
properties = prop_dict.get(relative_distance, {})
properties[id_field] = theme_id
properties[NR_CALCULATION_FIELD_NAME] = nr_calculations
properties[RELEVANT_DISTANCE_FIELD_NAME] = relative_distance

for results_type, geom in process_result.items():
Expand Down Expand Up @@ -197,7 +205,6 @@ def polygonize_reference_data(dict_ref):
return dict_ref



def get_breakpoints_zerostreak(x, y):
"""
Determine the extremes and zero_streaks of a graph based on the derivative, and
Expand Down Expand Up @@ -302,6 +309,7 @@ def _numerical_derivative(x, y):

return derivative


def diffs_from_dict_series(
dict_series: dict[str, dict[float, ProcessResult]],
dict_thematic: dict[str, BaseGeometry],
Expand Down Expand Up @@ -464,7 +472,9 @@ def get_collection_by_partition(
else:
geoms = get_partitions(geometry, partition)
for g in geoms:
coll = get_collection(_add_bbox_to_url(url=url, crs=crs, bbox=get_bbox(g)), limit)
coll = get_collection(
_add_bbox_to_url(url=url, crs=crs, bbox=get_bbox(g)), limit
)
if collection == {}:
collection = dict(coll)
elif "features" in collection and "features" in coll:
Expand Down Expand Up @@ -499,13 +509,15 @@ def merge_process_results(
if id_theme_global not in grouped_results:
grouped_results[id_theme_global] = dict_results
else:
for rel_dist,process_result in dict_results.items():
for rel_dist, process_result in dict_results.items():
for key in process_result:
geom: BaseGeometry = process_result[key] # noqa
if geom.is_empty or geom is None:
continue
existing: BaseGeometry = grouped_results[id_theme_global][rel_dist][key] # noqa
grouped_results[id_theme_global][rel_dist][key] = unary_union( # noqa
existing: BaseGeometry = grouped_results[id_theme_global][rel_dist][
key
] # noqa
grouped_results[id_theme_global][rel_dist][key] = unary_union(
[existing, geom]
)
return grouped_results
) # noqa
return grouped_results
2 changes: 2 additions & 0 deletions examples/example_131635.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
# RESULTS
rel_dist = 2
dict_results = aligner.process(relevant_distance=rel_dist, od_strategy=4)
fcs = aligner.get_results_as_geojson()
print(fcs["result"])
# put resulting tuple in a dictionary
aligner.save_results("output/", formula=True)

Expand Down
24 changes: 12 additions & 12 deletions examples/example_evaluate.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@
GRBFiscalParcelLoader(year=base_year, aligner=base_aligner)
)
relevant_distance = 2
base_process_result = base_aligner.process(
relevant_distance=relevant_distance
)
base_process_result = base_aligner.process(relevant_distance=relevant_distance)
thematic_dict_formula = {}
thematic_dict_result = {}
for key in base_process_result:
thematic_dict_result[key] = base_process_result[key][relevant_distance]["result"]
thematic_dict_formula[key]= {FORMULA_FIELD_NAME:base_aligner.get_brdr_formula(thematic_dict_result[key])}
thematic_dict_formula[key] = {
FORMULA_FIELD_NAME: base_aligner.get_brdr_formula(thematic_dict_result[key])
}
print(key + ": " + thematic_dict_result[key].wkt)
print(key + ": " + str(thematic_dict_formula[key]))
base_aligner_result = Aligner()
Expand All @@ -51,17 +51,19 @@
print(key + ": " + value.wkt)
actual_aligner = Aligner()
loader = DictLoader(dict_affected)
actual_aligner.load_thematic_data(DictLoader(data_dict=dict_affected,data_dict_properties=thematic_dict_formula))
actual_aligner.load_thematic_data(
DictLoader(data_dict=dict_affected, data_dict_properties=thematic_dict_formula)
)
actual_aligner.load_reference_data(
GRBActualLoader(grb_type=GRBType.ADP, partition=1000, aligner=actual_aligner)
)
actual_aligner.relevant_distances = np.arange(0, 200, 10, dtype=int) / 100
dict_evaluated, prop_dictionary = actual_aligner.compare(
#thematic_dict_formula=thematic_dict_formula,
threshold_area=5,
threshold_percentage=1,
dict_unchanged=dict_unchanged,
)
# thematic_dict_formula=thematic_dict_formula,
threshold_area=5,
threshold_percentage=1,
dict_unchanged=dict_unchanged,
)

fc = get_series_geojson_dict(
dict_evaluated,
Expand All @@ -79,5 +81,3 @@
+ ": "
+ feature["properties"][EVALUATION_FIELD_NAME]
)


20 changes: 11 additions & 9 deletions examples/example_evaluate_ao.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@
GRBFiscalParcelLoader(year=base_year, aligner=base_aligner)
)
relevant_distance = 3
base_process_result = base_aligner.process(
relevant_distance=relevant_distance
)
base_process_result = base_aligner.process(relevant_distance=relevant_distance)
thematic_dict_formula = {}
thematic_dict_result = {}
for key in base_process_result:
thematic_dict_result[key] = base_process_result[key][relevant_distance]["result"]
thematic_dict_formula[key]= {FORMULA_FIELD_NAME:base_aligner.get_brdr_formula(thematic_dict_result[key])}
thematic_dict_formula[key] = {
FORMULA_FIELD_NAME: base_aligner.get_brdr_formula(thematic_dict_result[key])
}
base_aligner_result = Aligner()
base_aligner_result.load_thematic_data(DictLoader(thematic_dict_result))
dict_affected, dict_unchanged = get_geoms_affected_by_grb_change(
Expand All @@ -44,16 +44,18 @@
exit()

actual_aligner = Aligner()
actual_aligner.load_thematic_data(DictLoader(data_dict=dict_affected,data_dict_properties=thematic_dict_formula))
actual_aligner.load_thematic_data(
DictLoader(data_dict=dict_affected, data_dict_properties=thematic_dict_formula)
)
loader = GRBActualLoader(grb_type=GRBType.ADP, partition=1000, aligner=actual_aligner)
actual_aligner.load_reference_data(loader)
series = np.arange(0, 300, 10, dtype=int) / 100

dict_evaluated, prop_dictionary = actual_aligner.compare(
threshold_area=5,
threshold_percentage=1,
dict_unchanged=dict_unchanged,
)
threshold_area=5,
threshold_percentage=1,
dict_unchanged=dict_unchanged,
)

fc = get_series_geojson_dict(
dict_evaluated,
Expand Down
Loading