Skip to content

Commit

Permalink
Merge branch 'main' into gmodeler-pygrass
Browse files Browse the repository at this point in the history
  • Loading branch information
landam authored Jan 24, 2024
2 parents a018ec3 + e276098 commit 795d0e6
Show file tree
Hide file tree
Showing 12 changed files with 376 additions and 311 deletions.
2 changes: 1 addition & 1 deletion db/db.execute/db.execute.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ <h2>NOTES</h2>
<em><a href="db.connect.html">db.connect</a></em>, they are taken as default
values and do not need to be specified each time.
<p>
If you have a large number of SQL commands to process, it is much much
If you have a large number of SQL commands to process, it is much
faster to place all the SQL statements into a text file and
use <b>input</b> file parameter than it is to process each statement
individually in a loop. If multiple instruction lines are given, each
Expand Down
22 changes: 11 additions & 11 deletions gui/wxpython/gmodeler/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def __init__(

self.pythonPanel = PythonPanel(parent=self)

self._gconsole = GConsole(guiparent=self)
self._gconsole = GConsole(guiparent=self, giface=giface)
self.goutput = GConsoleWindow(
parent=self, giface=giface, gconsole=self._gconsole
)
Expand Down Expand Up @@ -1054,11 +1054,12 @@ def GetOptData(self, dcmd, layer, params, propwin):
# arrange data items
if data_items:
dc = wx.ClientDC(self.canvas)
p = 360 / len(data_items)
r = 200
p = 180 / (len(data_items) - 1) if len(data_items) > 1 else 0
rx = 200
ry = 100
alpha = 270 * (math.pi / 180)
for data in data_items:
data.Move(dc, x + r * math.sin(alpha), y + r * math.cos(alpha))
data.Move(dc, x + rx * math.sin(alpha), y + ry * math.cos(alpha))
alpha += p * (math.pi / 180)
data.Show(True)

Expand Down Expand Up @@ -1349,14 +1350,13 @@ def GetNewShapePos(self, yoffset=50):
:return: x,y
"""
diagram = self.GetDiagram()
if diagram.GetShapeList():
last = diagram.GetShapeList()[-1]
y = last.GetY() + last.GetBoundingBoxMin()[1]
else:
y = 20
ymax = 20
for item in self.GetDiagram().GetShapeList():
y = item.GetY() + item.GetBoundingBoxMin()[1]
if y > ymax:
ymax = y

return (self.GetSize()[0] // 2, y + yoffset)
return (self.GetSize()[0] // 2, ymax + yoffset)

def GetShapesSelected(self):
"""Get list of selected shapes"""
Expand Down
6 changes: 3 additions & 3 deletions gui/wxpython/gui_core/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1250,7 +1250,7 @@ def __init__(self, parent, model, showChoice=True, showTip=False, **kwargs):

if self._showTip:
self._searchTip = StaticWrapText(
parent=self, id=wx.ID_ANY, label="Choose a tool", size=(-1, 35)
parent=self, id=wx.ID_ANY, label="Choose a tool", size=(-1, 40)
)

if self._showChoice:
Expand Down Expand Up @@ -1315,9 +1315,9 @@ def OnSearchModule(self, event):
self._searchChoice.SetSelection(0)
self.OnSelectModule()

label = _("%d tools match") % len(commands)
label = _("{} tools matched").format(len(commands))
if self._showTip:
self._searchTip.SetLabel(label)
self._searchTip.SetLabel(self._searchTip.GetLabel() + " [{}]".format(label))

self.showNotification.emit(message=label)

Expand Down
5 changes: 2 additions & 3 deletions lib/display/r_raster.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,9 @@ int D_open_driver(void)
drv = (p && G_strcasecmp(p, "png") == 0) ? PNG_Driver()
: (p && G_strcasecmp(p, "ps") == 0) ? PS_Driver()
: (p && G_strcasecmp(p, "html") == 0) ? HTML_Driver()
:
:
#ifdef USE_CAIRO
(p && G_strcasecmp(p, "cairo") == 0) ? Cairo_Driver()
: Cairo_Driver();
Cairo_Driver();
#else
PNG_Driver();
#endif
Expand Down
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
13 changes: 12 additions & 1 deletion python/grass/temporal/stds_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,18 @@ def import_stds(
gscript.fatal(_("Unable to find projection file <%s>") % proj_file_name)

msgr.message(_("Extracting data..."))
tar.extractall(path=directory)
# Extraction filters were added in Python 3.12,
# and backported to 3.8.17, 3.9.17, 3.10.12, and 3.11.4
# See https://docs.python.org/3.12/library/tarfile.html#tarfile-extraction-filter
# and https://peps.python.org/pep-0706/
# In Python 3.12, using `filter=None` triggers a DepreciationWarning,
# and in Python 3.14, `filter='data'` will be the default
if hasattr(tarfile, "data_filter"):
tar.extractall(path=directory, filter="data")
else:
# Remove this when no longer needed
gscript.warning(_("Extracting may be unsafe; consider updating Python"))
tar.extractall(path=directory)
tar.close()

# We use a new list file name for map registration
Expand Down
Loading

0 comments on commit 795d0e6

Please sign in to comment.