Skip to content

Commit

Permalink
temporal: Update STDS metadata from DB (#3350)
Browse files Browse the repository at this point in the history
* compute granularity from time tuples

* update metadata from DB

* black

* flake8

* more flake8

* address test-failures

* address test-failures

* address more test-failures

* handle empty maps list

* handle empty maps list

* fix temporal relation remove unnecessary loop

* add docs, function to get function

* add docs, function to get function

* dont check data structure in loop

* check empty list

* remove DB version check

* implement suggstions from review

* Update python/grass/temporal/abstract_space_time_dataset.py

Co-authored-by: Edouard Choinière <27212526+echoix@users.noreply.github.com>

* implement suggstions from review

* reduce looping

* order time units in dict

* Update python/grass/temporal/temporal_granularity.py

Co-authored-by: Edouard Choinière <27212526+echoix@users.noreply.github.com>

* Update python/grass/temporal/temporal_granularity.py

Co-authored-by: Edouard Choinière <27212526+echoix@users.noreply.github.com>

* Update python/grass/temporal/temporal_granularity.py

Co-authored-by: Edouard Choinière <27212526+echoix@users.noreply.github.com>

* Update python/grass/temporal/temporal_granularity.py

Co-authored-by: Edouard Choinière <27212526+echoix@users.noreply.github.com>

* Update python/grass/temporal/temporal_granularity.py

Co-authored-by: Edouard Choinière <27212526+echoix@users.noreply.github.com>

* use sets of granularity units

* handle max_days, typos

---------

Co-authored-by: Edouard Choinière <27212526+echoix@users.noreply.github.com>
  • Loading branch information
ninsbl and echoix committed Jan 23, 2024
1 parent cbef14a commit 0c73ced
Show file tree
Hide file tree
Showing 3 changed files with 289 additions and 286 deletions.
155 changes: 69 additions & 86 deletions python/grass/temporal/abstract_space_time_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
The abstract_space_time_dataset module provides the AbstractSpaceTimeDataset
class that is the base class for all space time datasets.
(C) 2011-2013 by the GRASS Development Team
(C) 2011-2024 by the GRASS Development Team
This program is free software under the GNU General Public
License (>=v2). Read the file COPYING that comes with GRASS
for details.
Expand All @@ -18,15 +18,18 @@ class that is the base class for all space time datasets.
from .core import (
init_dbif,
get_sql_template_path,
get_tgis_metadata,
get_current_mapset,
get_tgis_db_version_from_metadata,
)
from .abstract_dataset import AbstractDataset, AbstractDatasetComparisonKeyStartTime
from .abstract_dataset import (
AbstractDataset,
AbstractDatasetComparisonKeyStartTime,
)
from .temporal_granularity import (
check_granularity_string,
compute_absolute_time_granularity,
compute_relative_time_granularity,
get_time_tuple_function,
)
from .spatio_temporal_relationships import (
count_temporal_topology_relationships,
Expand Down Expand Up @@ -441,45 +444,38 @@ def get_map_time(self):
def count_temporal_types(self, maps=None, dbif=None):
"""Return the temporal type of the registered maps as dictionary
The map list must be ordered by start time
The map list can be a list of AbstractDataset or database rows.
It must be ordered by start time
The temporal type can be:
- point -> only the start time is present
- interval -> start and end time
- invalid -> No valid time point or interval found
:param maps: A sorted (start_time) list of AbstractDataset objects
:param maps: A sorted (start_time) list of AbstractDataset objects or database rows
:param dbif: The database interface to be used
"""

tcount = {"point": 0, "interval": 0, "invalid": 0}

if maps is None:
maps = self.get_registered_maps_as_objects(
where=None, order="start_time", dbif=dbif
)
maps = self.get_registered_maps(where=None, order="start_time", dbif=dbif)

time_invalid = 0
time_point = 0
time_interval = 0
if not maps:
return tcount

tcount = {}
for i in range(len(maps)):
# Check for point and interval data
if maps[i].is_time_absolute():
start, end = maps[i].get_absolute_time()
if maps[i].is_time_relative():
start, end, unit = maps[i].get_relative_time()
get_time_tuple = get_time_tuple_function(maps)

for map_reference in maps:
# Check for point and interval data
start, end = get_time_tuple(map_reference)
if start is not None and end is not None:
time_interval += 1
tcount["interval"] += 1
elif start is not None and end is None:
time_point += 1
tcount["point"] += 1
else:
time_invalid += 1

tcount["point"] = time_point
tcount["interval"] = time_interval
tcount["invalid"] = time_invalid
tcount["invalid"] += 1

return tcount

Expand Down Expand Up @@ -1517,79 +1513,66 @@ def get_registered_maps_as_objects(
"contains": maps that contain (fully cover) the provided spatial extent
:return: The ordered map object list,
In case nothing found None is returned
In case nothing is found, an empty list is returned
"""

dbif, connection_state_changed = init_dbif(dbif)

obj_list = []

# Older temporal databases have no bottom and top columns
# in their views so we need a work around to set the full
# spatial extent as well

rows = get_tgis_metadata(dbif)
db_version = 0

if rows:
for row in rows:
if row["key"] == "tgis_db_version":
db_version = int(float(row["value"]))

# use all columns
rows = self.get_registered_maps(
None, where, order, dbif, spatial_extent, spatial_relation
)

if rows is not None:
has_bt_columns = False
has_semantic_label = False
first_row = True
for row in rows:
if first_row:
first_row = False
# check keys in first row
# note that 'if "bottom" in row' does not work
# because row is not a dict but some db backend object
if "bottom" in row.keys() and "top" in row.keys():
has_bt_columns = True
if "semantic_label" in row.keys():
has_semantic_label = True

map = self.get_new_map_instance(row["id"])
# time
if self.is_time_absolute():
map.set_absolute_time(row["start_time"], row["end_time"])
elif self.is_time_relative():
map.set_relative_time(
row["start_time"],
row["end_time"],
self.get_relative_time_unit(),
)
# space
# The fast way
if has_bt_columns:
map.set_spatial_extent_from_values(
west=row["west"],
east=row["east"],
south=row["south"],
top=row["top"],
north=row["north"],
bottom=row["bottom"],
)
# The slow work around
else:
map.spatial_extent.select(dbif)
if rows:
# Older temporal databases have no bottom and top columns
# in their views so we need a work around to set the full
# spatial extent as well

# check keys in first row
# note that 'if "bottom" in row' does not work
# because row is not a dict but some db backend object
has_bt_columns = "bottom" in rows[0].keys()
has_semantic_label = "semantic_label" in rows[0].keys()
else:
return obj_list

# labels
if (
has_semantic_label
and row["semantic_label"] is not None
and row["semantic_label"] != "None"
):
map.metadata.set_semantic_label(row["semantic_label"])
for row in rows:
map = self.get_new_map_instance(row["id"])
# time
if self.is_time_absolute():
map.set_absolute_time(row["start_time"], row["end_time"])
elif self.is_time_relative():
map.set_relative_time(
row["start_time"],
row["end_time"],
self.get_relative_time_unit(),
)
# space
# The fast way
if has_bt_columns:
map.set_spatial_extent_from_values(
west=row["west"],
east=row["east"],
south=row["south"],
top=row["top"],
north=row["north"],
bottom=row["bottom"],
)
# The slow work around
else:
map.spatial_extent.select(dbif)

# labels
if (
has_semantic_label
and row["semantic_label"] is not None
and row["semantic_label"] != "None"
):
map.metadata.set_semantic_label(row["semantic_label"])

obj_list.append(copy.copy(map))
obj_list.append(copy.copy(map))

if connection_state_changed:
dbif.close()
Expand Down Expand Up @@ -2872,7 +2855,7 @@ def update_from_registered_maps(self, dbif=None):
dbif.execute_transaction(sql, mapset=self.base.mapset)

# Count the temporal map types
maps = self.get_registered_maps_as_objects(dbif=dbif)
maps = self.get_registered_maps(order="start_time", dbif=dbif)
tlist = self.count_temporal_types(maps)

if tlist["interval"] > 0 and tlist["point"] == 0 and tlist["invalid"] == 0:
Expand Down
3 changes: 0 additions & 3 deletions python/grass/temporal/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,9 +352,6 @@ def __init__(
max,
)

if get_tgis_db_version_from_metadata() > 2:
self.set_semantic_label(semantic_label)

def set_semantic_label(self, semantic_label):
"""Set the semantic label identifier"""
self.D["semantic_label"] = semantic_label
Expand Down

0 comments on commit 0c73ced

Please sign in to comment.