Skip to content

Commit 2ddd9d1

Browse files
author
Emma Ai
committed
classify landcover level34 by class def and code csv
1 parent 7125060 commit 2ddd9d1

13 files changed

+179
-975
lines changed

odc/stats/plugins/_registry.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ def import_all():
4040
# TODO: make that more automatic
4141
modules = [
4242
"odc.stats.plugins.lc_treelite_cultivated",
43-
"odc.stats.plugins.lc_level3",
4443
"odc.stats.plugins.lc_treelite_woody",
4544
"odc.stats.plugins.lc_tf_urban",
4645
"odc.stats.plugins.lc_level34",

odc/stats/plugins/_utils.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import re
2+
import operator
13
import dask
24
from osgeo import gdal, ogr, osr
35

@@ -42,3 +44,99 @@ def rasterize_vector_mask(
4244
return dask.array.ones(dst_shape, name=False)
4345

4446
return dask.array.from_array(mask.reshape(dst_shape), name=False)
47+
48+
49+
OPERATORS = {
50+
">": operator.gt,
51+
">=": operator.ge,
52+
"<": operator.lt,
53+
"<=": operator.le,
54+
"==": operator.eq,
55+
"!=": operator.ne,
56+
}
57+
58+
BRACKETS = {
59+
"[": operator.ge, # Inclusive lower bound
60+
"(": operator.gt, # Exclusive lower bound
61+
"]": operator.le, # Inclusive upper bound
62+
")": operator.lt, # Exclusive upper bound
63+
}
64+
65+
66+
def parse_rule(rule):
67+
"""
68+
Parse a single condition or range condition.
69+
Supports range notations like '[]', '[)', '(]', and '()',
70+
and treats standalone numbers as '=='.
71+
"""
72+
# Special case for 255 (rule doesn't apply)
73+
if (rule == "255") | (rule == "nan"):
74+
return None
75+
76+
# Check for range conditions like '[a, b)' or '(a, b]'
77+
range_pattern = r"([\[\(])(-?\d+\.?\d*),\s*(-?\d+\.?\d*)([\]\)])"
78+
match = re.match(range_pattern, rule)
79+
if match:
80+
# Extract the bounds and the bracket types
81+
lower_bracket, lower_value, upper_value, upper_bracket = match.groups()
82+
return [
83+
(BRACKETS[lower_bracket], float(lower_value)),
84+
(BRACKETS[upper_bracket], float(upper_value)),
85+
]
86+
87+
ordered_operators = sorted(OPERATORS.items(), key=lambda x: -len(x[0]))
88+
89+
# Single condition (no range notation, no explicit operator)
90+
for op_str, op_func in ordered_operators:
91+
if op_str in rule:
92+
value = float(rule.replace(op_str, "").strip())
93+
return [(op_func, value)]
94+
95+
# Default to equality (==) if no operator is found
96+
return [(operator.eq, int(rule.strip()))]
97+
98+
99+
def generate_numexpr_expressions(rules_df, final_class_column, previous):
100+
"""
101+
Generate a list of numexpr-compatible expressions for classification rules.
102+
:param rules_df: DataFrame containing the classification rules
103+
:param final_class_column: Name of the column containing the final class values
104+
:return: List of expressions (one for each rule)
105+
"""
106+
expressions = []
107+
108+
for _, rules in rules_df.iterrows():
109+
conditions = []
110+
111+
for col in rules.index:
112+
if col == final_class_column:
113+
continue
114+
subconditions = parse_rule(rules[col])
115+
if subconditions is None: # Skip rule if it's None
116+
continue
117+
for op_func, value in subconditions:
118+
if op_func is operator.eq:
119+
conditions.append(f"({col}=={value})")
120+
elif op_func is operator.gt:
121+
conditions.append(f"({col}>{value})")
122+
elif op_func is operator.ge:
123+
conditions.append(f"({col}>={value})")
124+
elif op_func is operator.lt:
125+
conditions.append(f"({col}<{value})")
126+
elif op_func is operator.le:
127+
conditions.append(f"({col}<={value})")
128+
elif op_func is operator.ne:
129+
conditions.append(f"({col}!={value})")
130+
131+
if not conditions:
132+
continue
133+
134+
condition = "&".join(conditions)
135+
136+
final_class = rules[final_class_column]
137+
expressions.append(f"where({condition}, {final_class}, {previous})")
138+
139+
expressions = list(set(expressions))
140+
expressions = sorted(expressions, key=len)
141+
142+
return expressions

odc/stats/plugins/l34_utils/__init__.py

Whitespace-only changes.

odc/stats/plugins/l34_utils/l4_bare_gradation.py

Lines changed: 0 additions & 46 deletions
This file was deleted.

odc/stats/plugins/l34_utils/l4_cultivated.py

Lines changed: 0 additions & 98 deletions
This file was deleted.

0 commit comments

Comments
 (0)