Skip to content

Commit

Permalink
Merge pull request #113 from OnroerendErfgoed/main
Browse files Browse the repository at this point in the history
main (0.4.0) to develop
  • Loading branch information
dieuska authored Oct 3, 2024
2 parents 7a81e61 + b799fb6 commit fcf2280
Show file tree
Hide file tree
Showing 19 changed files with 155 additions and 94 deletions.
17 changes: 17 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,24 @@
- Bugfixing:
- adding a safe_equals-function to catch GEOsException bug [#71]

# 0.4.0

! Not Backwards compatable !

- Refactoring:
- Possibility for parallel processing [#97]
- Changed Aligner constants to init-settings [#83]
- Refactored ID-handling so strings,integers,... can be used as ID[#110]
- Cleaned examples [#100]

- Functionalities:
- Added evaluation-attributes to evaluate()-function [#99]
- processing-remarks available in geojson-output [#103]
- Added warning when input/output changed from polygon/multipolygon [#107]

- Bugfixing:
- Bugfix on version_date [#96]
- Bugfix on disappearing features [#105]



Expand Down
2 changes: 1 addition & 1 deletion brdr/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.3.0"
__version__ = "0.4.0"
23 changes: 13 additions & 10 deletions brdr/aligner.py
Original file line number Diff line number Diff line change
Expand Up @@ -623,10 +623,7 @@ def predictor(
diffs_dict,
)

def evaluate(
self,
ids_to_evaluate=None, base_formula_field= FORMULA_FIELD_NAME
):
def evaluate(self, ids_to_evaluate=None, base_formula_field=FORMULA_FIELD_NAME):
"""
Compares and evaluate input-geometries (with formula). Attributes are added to evaluate and decide if new
Expand Down Expand Up @@ -657,7 +654,7 @@ def evaluate(
props = self._evaluate(
id_theme=theme_id,
geom_predicted=dict_predictions_results[dist]["result"],
base_formula_field=base_formula_field,
base_formula_field=base_formula_field,
)
dict_predictions_evaluated[theme_id][dist] = dict_affected_predictions[
theme_id
Expand All @@ -670,7 +667,11 @@ def evaluate(
for theme_id, geom in dict_unaffected.items():
dict_predictions_evaluated[theme_id] = {}
prop_dictionary[theme_id] = {relevant_distance: {}}
props = self._evaluate(id_theme=theme_id, geom_predicted=geom,base_formula_field=base_formula_field)
props = self._evaluate(
id_theme=theme_id,
geom_predicted=geom,
base_formula_field=base_formula_field,
)
props[EVALUATION_FIELD_NAME] = Evaluation.NO_CHANGE_6
dict_predictions_evaluated[theme_id][relevant_distance] = {"result": geom}
prop_dictionary[theme_id][relevant_distance] = props
Expand Down Expand Up @@ -840,9 +841,9 @@ def get_results_as_geojson(
): # and not (theme_id in prop_dictionary and relevant_distance in prop_dictionary[theme_id] and NEW_FORMULA_FIELD_NAME in prop_dictionary[theme_id][relevant_distance]):
result = process_results["result"]
formula = self.get_brdr_formula(result)
prop_dictionary[theme_id][relevant_distance][
FORMULA_FIELD_NAME
] = json.dumps(formula)
prop_dictionary[theme_id][relevant_distance][FORMULA_FIELD_NAME] = (
json.dumps(formula)
)
return get_series_geojson_dict(
dict_series,
crs=self.CRS,
Expand Down Expand Up @@ -1354,7 +1355,9 @@ def _postprocess_preresult(
"remark": remark,
}

def _evaluate(self, id_theme, geom_predicted,base_formula_field=FORMULA_FIELD_NAME):
def _evaluate(
self, id_theme, geom_predicted, base_formula_field=FORMULA_FIELD_NAME
):
"""
function that evaluates a predicted geometry and returns a properties-dictionary
"""
Expand Down
4 changes: 3 additions & 1 deletion brdr/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
MULTI_SINGLE_ID_SEPARATOR = "*$*"

PREFIX_FIELDNAME = "brdr_"
BASE_FORMULA_FIELD_NAME = PREFIX_FIELDNAME + "base_formula"# for use in grb_actualisation
BASE_FORMULA_FIELD_NAME = (
PREFIX_FIELDNAME + "base_formula"
) # for use in grb_actualisation
FORMULA_FIELD_NAME = PREFIX_FIELDNAME + "formula"
EVALUATION_FIELD_NAME = PREFIX_FIELDNAME + "evaluation"
DIFF_PERCENTAGE_FIELD_NAME = PREFIX_FIELDNAME + "diff_percentage"
Expand Down
16 changes: 9 additions & 7 deletions brdr/geometry_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from shapely.prepared import prep


def buffer_neg_pos(geometry, buffer_value,mitre_limit=5):
def buffer_neg_pos(geometry, buffer_value, mitre_limit=5):
"""
Computes two buffers accordingly: one with a negative buffer value and another with
a positive buffer value. This function can be used the check where relevant areas
Expand Down Expand Up @@ -56,18 +56,18 @@ def buffer_neg_pos(geometry, buffer_value,mitre_limit=5):
buffer(
geometry,
-buffer_value,
#quad_segs=QUAD_SEGMENTS,
# quad_segs=QUAD_SEGMENTS,
join_style="mitre",
mitre_limit=mitre_limit,
),
buffer_value,
#quad_segs=QUAD_SEGMENTS,
# quad_segs=QUAD_SEGMENTS,
join_style="mitre",
mitre_limit=mitre_limit,
)


def buffer_neg(geometry, buffer_value,mitre_limit=5):
def buffer_neg(geometry, buffer_value, mitre_limit=5):
"""
Computes the negative buffer of a given geometric object.
Expand All @@ -94,13 +94,13 @@ def buffer_neg(geometry, buffer_value,mitre_limit=5):
return buffer(
geometry,
-buffer_value,
#quad_segs=QUAD_SEGMENTS,
# quad_segs=QUAD_SEGMENTS,
join_style="mitre",
mitre_limit=mitre_limit,
)


def buffer_pos(geometry, buffer_value,mitre_limit=5):
def buffer_pos(geometry, buffer_value, mitre_limit=5):
"""
Computes the positive buffer of a given geometric object.
Expand All @@ -127,7 +127,7 @@ def buffer_pos(geometry, buffer_value,mitre_limit=5):
return buffer(
geometry,
buffer_value,
#quad_segs=QUAD_SEGMENTS,
# quad_segs=QUAD_SEGMENTS,
join_style="mitre",
mitre_limit=mitre_limit,
)
Expand Down Expand Up @@ -506,9 +506,11 @@ def fill_and_remove_gaps(input_geometry, buffer_value):
ix_part = ix_part + 1
return cleaned_geometry


def safe_unary_union(geometries):
return make_valid(unary_union(geometries))


def get_bbox(geometry):
"""
Get the BBOX (string) of a shapely geometry
Expand Down
7 changes: 5 additions & 2 deletions brdr/grb.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
LAST_VERSION_DATE,
DATE_FORMAT,
VERSION_DATE,
FORMULA_FIELD_NAME, BASE_FORMULA_FIELD_NAME,
FORMULA_FIELD_NAME,
BASE_FORMULA_FIELD_NAME,
)
from brdr.constants import DOWNLOAD_LIMIT
from brdr.constants import GRB_BUILDING_ID
Expand Down Expand Up @@ -434,7 +435,9 @@ def update_to_actual_grb(
actual_aligner.relevant_distances = (
np.arange(0, max_distance_for_actualisation * 100, 10, dtype=int) / 100
)
dict_evaluated, prop_dictionary = actual_aligner.evaluate(ids_to_evaluate=affected,base_formula_field=BASE_FORMULA_FIELD_NAME)
dict_evaluated, prop_dictionary = actual_aligner.evaluate(
ids_to_evaluate=affected, base_formula_field=BASE_FORMULA_FIELD_NAME
)

return actual_aligner.get_results_as_geojson(
resulttype=AlignerResultType.EVALUATED_PREDICTIONS,
Expand Down
4 changes: 3 additions & 1 deletion brdr/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ def load_data(self):
],
DATE_FORMAT,
)
self.data_dict_properties[key][VERSION_DATE] = datetime.strftime(date,DATE_FORMAT)
self.data_dict_properties[key][VERSION_DATE] = datetime.strftime(
date, DATE_FORMAT
)

return self.data_dict, self.data_dict_properties, self.data_dict_source

Expand Down
52 changes: 34 additions & 18 deletions examples/example_evaluate.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,61 +16,77 @@
"""
EXAMPLE of the 'evaluate()-function of 'brdr': This function evaluates thematic objects with a former brdr_formula and compares them with an actual formula; and adds evaluation-properties to the result
"""
#initiate a base Aligner, to align thematic objects on an older version of the parcels (year 2022)
# initiate a base Aligner, to align thematic objects on an older version of the parcels (year 2022)
base_aligner = Aligner()
#Load thematic data
# Load thematic data
loader = GeoJsonFileLoader("themelayer.geojson", "theme_identifier")
base_aligner.load_thematic_data(loader)
base_year = "2022"
name_formula = "base_formula"
#Load reference data
# Load reference data
base_aligner.load_reference_data(
GRBFiscalParcelLoader(year=base_year, aligner=base_aligner)
)
relevant_distance = 2
#Align the thematic object on the parcelborders of 2022, to simulate a base-situation
# Align the thematic object on the parcelborders of 2022, to simulate a base-situation
base_process_result = base_aligner.process(relevant_distance=2)

#Collect the base-situation (base-geometries and the brdr_formula from that moment
# Collect the base-situation (base-geometries and the brdr_formula from that moment
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_result[key] = base_process_result[key][relevant_distance][
"result"
]
thematic_dict_formula[key] = {
name_formula: json.dumps(base_aligner.get_brdr_formula(thematic_dict_result[key]))
name_formula: json.dumps(
base_aligner.get_brdr_formula(thematic_dict_result[key])
)
}
print(key + ": " + thematic_dict_result[key].wkt)
print(key + ": " + str(thematic_dict_formula[key]))

#(OPTIONAL) Check for changes in the period 2022-now of the reference-parcels (GRB/Flanders-specific function)
# (OPTIONAL) Check for changes in the period 2022-now of the reference-parcels (GRB/Flanders-specific function)
affected, unaffected = get_affected_by_grb_change(
dict_thematic = thematic_dict_result,
dict_thematic=thematic_dict_result,
grb_type=GRBType.ADP,
date_start=date(2022, 1, 1),
date_end=date.today(),
one_by_one=False,
)
if len(affected)==0:
if len(affected) == 0:
print("No affected dicts")
exit()
print("Affected_IDs: " + str(affected))

#Start an aligner to align thematic objects on the actual parcels
# Start an aligner to align thematic objects on the actual parcels
actual_aligner = Aligner(relevant_distances=np.arange(0, 200, 10, dtype=int) / 100)
#Load the thematic objects (aligned on 2022) and also give the brdr_formula from 2022 as property
# Load the thematic objects (aligned on 2022) and also give the brdr_formula from 2022 as property
actual_aligner.load_thematic_data(
DictLoader(data_dict=thematic_dict_result, data_dict_properties=thematic_dict_formula)
DictLoader(
data_dict=thematic_dict_result, data_dict_properties=thematic_dict_formula
)
)
#Load reference data; the actual parcels
# Load reference data; the actual parcels
actual_aligner.load_reference_data(
GRBActualLoader(grb_type=GRBType.ADP, partition=1000, aligner=actual_aligner)
)
#Use the EVALUATE-function
dict_evaluated, prop_dictionary = actual_aligner.evaluate(ids_to_evaluate=affected,base_formula_field=name_formula)
# Use the EVALUATE-function
dict_evaluated, prop_dictionary = actual_aligner.evaluate(
ids_to_evaluate=affected, base_formula_field=name_formula
)

# SHOW the EVALUATED results
fc = actual_aligner.get_results_as_geojson(resulttype=AlignerResultType.EVALUATED_PREDICTIONS,formula=True, attributes=True)
fc = actual_aligner.get_results_as_geojson(
resulttype=AlignerResultType.EVALUATED_PREDICTIONS,
formula=True,
attributes=True,
)
print(fc["result"])

for feature in fc["result"]["features"]:
print(feature["properties"][actual_aligner.name_thematic_id] + ": " + feature["properties"][EVALUATION_FIELD_NAME])
print(
feature["properties"][actual_aligner.name_thematic_id]
+ ": "
+ feature["properties"][EVALUATION_FIELD_NAME]
)
3 changes: 1 addition & 2 deletions examples/example_geojsonloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#EXAMPLE of a Geojson, aligned by 'brdr'
"""


# Initiate brdr
aligner = Aligner()
# Load thematic data
Expand Down Expand Up @@ -56,7 +55,7 @@
# Example how to use the Aligner
dict_results = aligner.process(relevant_distance=6)

#show results
# show results
aligner.save_results("output/")
show_map(dict_results, aligner.dict_thematic, aligner.dict_reference)
print_brdr_formula(dict_results, aligner)
5 changes: 2 additions & 3 deletions examples/example_grbspecificloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
"Polygon ((172283.76869662097305991 174272.85233648214489222, 172276.89871930953813717 174278.68436246179044247, 172274.71383684969623573 174280.57171753142029047, 172274.63047763772192411 174280.64478165470063686, 172272.45265833073062822 174282.52660570573061705, 172269.33533191855531186 174285.22093996312469244, 172265.55258252174826339 174288.49089696351438761, 172258.77032718938426115 174294.22654021997004747, 172258.63259260458289646 174294.342757155187428, 172254.93673790179309435 174288.79932878911495209, 172248.71360730109154247 174279.61860501393675804, 172248.96566232520854101 174279.43056782521307468, 172255.25363882273086347 174274.73737183399498463, 172257.08298882702365518 174273.37133203260600567, 172259.32325354730710387 174271.69890458136796951, 172261.65807284769834951 174269.9690355472266674, 172266.35596220899606124 174266.4871726930141449, 172273.34350050613284111 174261.30863015633076429, 172289.60360219911672175 174249.35944479051977396, 172293.30328181147342548 174246.59864199347794056, 172297.34760522318538278 174253.10583685990422964, 172289.53060952731175348 174259.6846851697191596, 172292.86485871637705714 174265.19099397677928209, 172283.76869662097305991 174272.85233648214489222))"
)
}
#EXAMPLE to use a GRBSpecificLoader, that retrieves the parcels for a specific data, based on the 2 fiscal parcel-situations of the year before and after
#Based on the date, the referencelayer will be different
# EXAMPLE to use a GRBSpecificLoader, that retrieves the parcels for a specific data, based on the 2 fiscal parcel-situations of the year before and after
# Based on the date, the referencelayer will be different
date = "2023-05-03"
date = "2023-08-03"
loader = DictLoader(thematic_dict)
Expand All @@ -31,4 +31,3 @@
inputtype=AlignerInputType.REFERENCE,
)
write_geojson(os.path.join("output/", "grb_adp_" + date + ".geojson"), fc)

2 changes: 1 addition & 1 deletion examples/example_onroerenderfgoed.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# Initiate brdr
aligner = Aligner()
# Load thematic data from Onroerend Erfgoed
loader = OnroerendErfgoedLoader( objectids = [131635] , oetype=OEType.AO)
loader = OnroerendErfgoedLoader(objectids=[131635], oetype=OEType.AO)
aligner.load_thematic_data(loader)
# Load reference data: The actual GRB-parcels
loader = GRBActualLoader(grb_type=GRBType.ADP, partition=1000, aligner=aligner)
Expand Down
22 changes: 13 additions & 9 deletions examples/example_parcel_change_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
from datetime import datetime

from brdr.aligner import Aligner
from brdr.constants import EVALUATION_FIELD_NAME, RELEVANT_DISTANCE_FIELD_NAME, FORMULA_FIELD_NAME
from brdr.constants import (
EVALUATION_FIELD_NAME,
RELEVANT_DISTANCE_FIELD_NAME,
FORMULA_FIELD_NAME,
)
from brdr.grb import GRBFiscalParcelLoader
from brdr.grb import update_to_actual_grb
from brdr.oe import OnroerendErfgoedLoader
Expand Down Expand Up @@ -49,7 +53,7 @@
+ str(len(base_aligner.dict_thematic))
)
base_aligner.load_reference_data(
GRBFiscalParcelLoader(year=base_year, aligner=base_aligner,partition=1000)
GRBFiscalParcelLoader(year=base_year, aligner=base_aligner, partition=1000)
)
print("Reference-data loaded")
# Exclude objects bigger than specified area
Expand All @@ -59,9 +63,7 @@
if base_aligner.dict_thematic[key].area > excluded_area:
keys_to_exclude.append(key)
counter_excluded = counter_excluded + 1
print(
"geometrie excluded; bigger than " + str(excluded_area) + ": " + key
)
print("geometrie excluded; bigger than " + str(excluded_area) + ": " + key)
for x in keys_to_exclude:
del base_aligner.dict_thematic[x]

Expand All @@ -85,15 +87,17 @@
max_distance_for_actualisation=max_distance_for_actualisation,
)

write_geojson(os.path.join("output/", "parcel_change_detector_with.geojson"), fcs["result"])
write_geojson(
os.path.join("output/", "parcel_change_detector_with.geojson"), fcs["result"]
)


counter_equality = 0
counter_equality_by_alignment = 0
counter_difference = 0
counter_no_change = 0
#TODO: counter_difference collects al the 'TO_CHECK's' but these are multiple proposals, so clean up the stats
#TODO: Move this as general output from the updater?
# TODO: counter_difference collects al the 'TO_CHECK's' but these are multiple proposals, so clean up the stats
# TODO: Move this as general output from the updater?
for feature in fcs["result"]["features"]:
if EVALUATION_FIELD_NAME in feature["properties"].keys():
ev = feature["properties"][EVALUATION_FIELD_NAME]
Expand All @@ -104,7 +108,7 @@
elif ev.startswith("equal") and rd > 0:
counter_equality_by_alignment = counter_equality_by_alignment + 1
elif ev.startswith("no_change"):
counter_no_change= counter_no_change + 1
counter_no_change = counter_no_change + 1
else:
counter_difference = counter_difference + 1

Expand Down
Loading

0 comments on commit fcf2280

Please sign in to comment.