"""@package grass.temporal
Temporal raster algebra
(C) 2013 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.
:authors: Thomas Leppelt and Soeren Gebbert
.. code-block:: python
>>> p = TemporalRasterAlgebraLexer()
>>> p.build()
>>> p.debug = True
>>> expression = "R = A {+,equal,l} B"
>>> p.test(expression)
R = A {+,equal,l} B
LexToken(NAME,'R',1,0)
LexToken(EQUALS,'=',1,2)
LexToken(NAME,'A',1,4)
LexToken(T_ARITH2_OPERATOR,'{+,equal,l}',1,6)
LexToken(NAME,'B',1,18)
>>> expression = "R = A {*,equal|during,r} B"
>>> p.test(expression)
R = A {*,equal|during,r} B
LexToken(NAME,'R',1,0)
LexToken(EQUALS,'=',1,2)
LexToken(NAME,'A',1,4)
LexToken(T_ARITH1_OPERATOR,'{*,equal|during,r}',1,6)
LexToken(NAME,'B',1,25)
>>> expression = "R = A {+,equal|during} B"
>>> p.test(expression)
R = A {+,equal|during} B
LexToken(NAME,'R',1,0)
LexToken(EQUALS,'=',1,2)
LexToken(NAME,'A',1,4)
LexToken(T_ARITH2_OPERATOR,'{+,equal|during}',1,6)
LexToken(NAME,'B',1,23)
"""
from __future__ import annotations
import copy
import grass.pygrass.modules as pymod
from grass.exceptions import FatalError
from .abstract_dataset import AbstractDatasetComparisonKeyStartTime
from .core import init_dbif
from .datetime_math import (
create_numeric_suffix,
create_suffix_from_datetime,
create_time_suffix,
)
from .factory import dataset_factory
from .open_stds import open_new_stds
from .space_time_datasets import Raster3DDataset, RasterDataset
from .spatio_temporal_relationships import SpatioTemporalTopologyBuilder
from .temporal_algebra import (
GlobalTemporalVar,
TemporalAlgebraLexer,
TemporalAlgebraParser,
)
from .temporal_granularity import compute_absolute_time_granularity
[docs]class TemporalRasterAlgebraLexer(TemporalAlgebraLexer):
"""Lexical analyzer for the GRASS GIS temporal algebra"""
def __init__(self) -> None:
TemporalAlgebraLexer.__init__(self)
# Supported r.mapcalc functions.
mapcalc_functions = {
"exp": "EXP",
"log": "LOG",
"sqrt": "SQRT",
"abs": "ABS",
"cos": "COS",
"acos": "ACOS",
"sin": "SIN",
"asin": "ASIN",
"tan": "TAN",
"double": "DOUBLE",
"float": "FLOATEXP",
"int": "INTEXP",
"isnull": "ISNULL",
"isntnull": "ISNTNULL",
"null": "NULL",
"exist": "EXIST",
}
# Functions that defines single maps with time stamp and without temporal extent.
map_functions = {"map": "MAP"}
# This is the list of token names.
raster_tokens = (
"MOD",
"DIV",
"MULT",
"ADD",
"SUB",
"T_ARITH1_OPERATOR",
"T_ARITH2_OPERATOR",
"L_SPAREN",
"R_SPAREN",
)
# Build the token list
tokens = (
TemporalAlgebraLexer.tokens
+ raster_tokens
+ tuple(mapcalc_functions.values())
+ tuple(map_functions.values())
)
# Regular expression rules for simple tokens
t_MOD = r"[\%]"
t_DIV = r"[\/]"
t_MULT = r"[\*]"
t_ADD = r"[\+]"
t_SUB = r"[-]"
t_T_ARITH1_OPERATOR = r"\{[\%\*\/][,]?[a-zA-Z\| ]*([,])?([lrudi]|left|right|union|disjoint|intersect)?\}" # noqa: E501
t_T_ARITH2_OPERATOR = (
r"\{[+-][,]?[a-zA-Z\| ]*([,])?([lrudi]|left|right|union|disjoint|intersect)?\}"
)
t_L_SPAREN = r"\["
t_R_SPAREN = r"\]"
# Parse symbols
[docs] def temporal_symbol(self, t):
# Check for reserved words
if t.value in TemporalRasterAlgebraLexer.time_functions.keys():
t.type = TemporalRasterAlgebraLexer.time_functions.get(t.value)
elif t.value in TemporalRasterAlgebraLexer.datetime_functions.keys():
t.type = TemporalRasterAlgebraLexer.datetime_functions.get(t.value)
elif t.value in TemporalRasterAlgebraLexer.conditional_functions.keys():
t.type = TemporalRasterAlgebraLexer.conditional_functions.get(t.value)
elif t.value in TemporalRasterAlgebraLexer.mapcalc_functions.keys():
t.type = TemporalRasterAlgebraLexer.mapcalc_functions.get(t.value)
elif t.value in TemporalRasterAlgebraLexer.map_functions.keys():
t.type = TemporalRasterAlgebraLexer.map_functions.get(t.value)
else:
t.type = "NAME"
return t
[docs]class TemporalRasterBaseAlgebraParser(TemporalAlgebraParser):
"""The temporal algebra class"""
# Get the tokens from the lexer class
tokens = TemporalRasterAlgebraLexer.tokens
# Setting equal precedence level for select and hash operations.
precedence = (
("left", "T_SELECT_OPERATOR", "T_SELECT", "T_NOT_SELECT"), # 1
("left", "ADD", "SUB", "T_ARITH2_OPERATOR", "T_HASH_OPERATOR", "HASH"), # 2
(
"left",
"AND",
"OR",
"T_COMP_OPERATOR",
"MOD",
"DIV",
"MULT",
"T_ARITH1_OPERATOR",
),
)
def __init__(
self,
pid: int | None = None,
run: bool = True,
debug: bool = False,
spatial: bool = False,
register_null: bool = False,
dry_run: bool = False,
nprocs: int = 1,
time_suffix=None,
) -> None:
TemporalAlgebraParser.__init__(
self,
pid=pid,
run=run,
debug=debug,
spatial=spatial,
register_null=register_null,
dry_run=dry_run,
nprocs=nprocs,
time_suffix=time_suffix,
)
[docs] def check_null(self, t):
try:
int(t)
return t
except ValueError:
return "null()"
[docs] def build_spatio_temporal_topology_list(
self,
maplistA,
maplistB=None,
topolist=["EQUAL"],
assign_val: bool = False,
count_map: bool = False,
compare_bool: bool = False,
compare_cmd: bool = False,
compop=None,
aggregate=None,
new: bool = False,
convert: bool = False,
operator_cmd: bool = False,
):
"""Build temporal topology for two space time data sets, copy map objects
for given relation into map list.
:param maplistA: List of maps.
:param maplistB: List of maps.
:param topolist: List of strings of temporal relations.
:param assign_val: Boolean for assigning a boolean map value based on
the map_values from the compared map list by
topological relationships.
:param count_map: Boolean if the number of topological related maps
should be returned.
:param compare_bool: Boolean for comparing boolean map values based on
related map list and compariosn operator.
:param compare_cmd: Boolean for comparing command list values based on
related map list and compariosn operator.
:param compop: Comparison operator, && or ||.
:param aggregate: Aggregation operator for relation map list, & or |.
:param new: Boolean if new temporary maps should be created.
:param convert: Boolean if conditional values should be converted to
r.mapcalc command strings.
:param operator_cmd: Boolean for aggregate arithmetic operators implicitly
in command list values based on related map lists.
:return: List of maps from maplistA that fulfil the topological relationships
to maplistB specified in topolist.
>>> # Create two list of maps with equal time stamps
>>> from datetime import datetime
>>> import grass.temporal as tgis
>>> tgis.init(True)
>>> l = tgis.TemporalAlgebraParser()
>>> mapsA = []
>>> mapsB = []
>>> for i in range(10):
... idA = "a%i@B" % (i)
... mapA = tgis.RasterDataset(idA)
... mapA.uid = idA
... mapA.map_value = True
... idB = "b%i@B" % (i)
... mapB = tgis.RasterDataset(idB)
... mapB.uid = idB
... mapB.map_value = False
... check = mapA.set_absolute_time(
... datetime(2000, 1, i + 1), datetime(2000, 1, i + 2)
... )
... check = mapB.set_absolute_time(
... datetime(2000, 1, i + 6), datetime(2000, 1, i + 7)
... )
... mapsA.append(mapA)
... mapsB.append(mapB)
...
>>> resultlist = l.build_spatio_temporal_topology_list(mapsA, mapsB)
>>> for map in resultlist:
... print(map.get_id())
...
a5@B
a6@B
a7@B
a8@B
a9@B
"""
if self.debug:
print(
topolist,
assign_val,
count_map,
compare_bool,
compare_cmd,
compop,
aggregate,
new,
convert,
operator_cmd,
)
# Check the topology definitions and return the list of temporal and spatial
# topological relations that must be fulfilled
temporal_topo_list, spatial_topo_list = self._check_topology(topolist=topolist)
resultdict = {}
# Create temporal topology for maplistA to maplistB.
tb = SpatioTemporalTopologyBuilder()
# Build spatio-temporal topology
if len(spatial_topo_list) > 0:
# Dictionary with different spatial variables used for topology builder.
spatialdict = {"strds": "2D", "stvds": "2D", "str3ds": "3D"}
tb.build(maplistA, maplistB, spatial=spatialdict[self.stdstype])
else:
tb.build(maplistA, maplistB)
# Iterate through maps in maplistA and search for relationships given
# in topolist.
for map_i in maplistA:
if assign_val:
self.assign_bool_value(map_i, temporal_topo_list, spatial_topo_list)
elif compare_bool:
self.compare_bool_value(
map_i, compop, aggregate, temporal_topo_list, spatial_topo_list
)
elif compare_cmd:
self.compare_cmd_value(
map_i,
compop,
aggregate,
temporal_topo_list,
spatial_topo_list,
convert,
)
elif operator_cmd:
self.operator_cmd_value(
map_i, compop, temporal_topo_list, spatial_topo_list
)
temporal_relations = map_i.get_temporal_relations()
spatial_relations = map_i.get_spatial_relations()
for temporal_topology in temporal_topo_list:
if temporal_topology.upper() in temporal_relations.keys():
if (
self._check_spatial_topology_entries(
spatial_topo_list, spatial_relations
)
is True
):
if count_map:
relationmaplist = temporal_relations[
temporal_topology.upper()
]
gvar = GlobalTemporalVar()
gvar.td = len(relationmaplist)
if "map_value" in dir(map_i):
map_i.map_value.append(gvar)
else:
map_i.map_value = gvar
# Use unique identifier, since map names may be equal
resultdict[map_i.uid] = map_i
# map_i.print_info()
resultlist = resultdict.values()
# Sort list of maps chronological.
return sorted(resultlist, key=AbstractDatasetComparisonKeyStartTime)
[docs] def build_command_string(self, map_i, relmap, operator=None, cmd_type=None):
"""This function build the r.mapcalc command string for conditionals,
spatial variable combinations and boolean comparisons.
For Example: 'if(a1 == 1, b1, c2)' or 'exist(a1) && sin(b1)'
:param map_i: map object with temporal extent and built relations.
:param relmap: map object with defined temporal relation to map_i.
:param operator: String representing operator between two spatial variables
(&&,||,+,-,*,/).
:param cmd_type: map object with defined temporal relation to map_i:
condition, conclusion or operator.
:return: the resulting command string for conditionals or spatial variable
combinations
"""
def sub_cmdstring(map_i):
"""This function search for command string in a map object and
return substitute string (contained commandstring or map name)"""
if "cmd_list" in dir(map_i):
map_sub = map_i.cmd_list
elif (
"map_value" in dir(map_i)
and len(map_i.map_value) > 0
and map_i.map_value[0].get_type() == "timediff"
):
map_sub = map_i.map_value[0].get_type_value()[0]
else:
try:
map_sub = map_i.get_id()
except AttributeError:
map_sub = map_i
return map_sub
# Check for type of operation, conditional or spatial variable combination
# and Create r.mapcalc expression string for the operation.
cmdstring = ""
if cmd_type == "condition":
conditionsub = sub_cmdstring(map_i)
conclusionsub = sub_cmdstring(relmap)
cmdstring = "if(%s, %s)" % (conditionsub, conclusionsub)
elif cmd_type == "conclusion":
thensub = sub_cmdstring(map_i)
elsesub = sub_cmdstring(relmap)
cmdstring = "%s, %s" % (thensub, elsesub)
elif cmd_type == "operator":
leftsub = sub_cmdstring(map_i)
rightsub = sub_cmdstring(relmap)
if operator is None:
self.msgr.fatal(
"Error: Can't build command string for map %s, operator is missing"
% (map_i.get_map_id())
)
cmdstring = "(%s %s %s)" % (leftsub, operator, rightsub)
return cmdstring
[docs] def compare_cmd_value(
self,
map_i,
compop,
aggregate,
temporal_topo_list=["EQUAL"],
spatial_topo_list=[],
convert: bool = False,
):
"""Function to evaluate two map lists with boolean values by boolean
comparison operator.
R = A && B
R = if(A < 1 && B > 1, A, B)
R = if(A < 1 {&&,equal|equivalent} B > 1, A, B)
Extended temporal algebra version with command
list builder for temporal raster algebra.
:param map_i: Map object with temporal extent.
:param temporal_relations: List of temporal relation to map_i.
:param temporal_topo_list: List of strings for given temporal relations.
:param compop: Comparison operator, && or ||.
:param aggregate: Aggregation operator for relation map list, & or |.
:param convert: Boolean if conditional values should be converted to
r.mapcalc command strings.
:return: Map object with conditional value that has been evaluated by
comparison operators.
"""
# Build command list list with elements from related maps and given relation
# operator.
if convert and "condition_value" in dir(map_i):
if map_i.condition_value != []:
cmdstring = str(int(map_i.condition_value[0]))
map_i.cmd_list = cmdstring
if "cmd_list" in dir(map_i):
leftcmd = map_i.cmd_list
cmd_value_list = [leftcmd]
count = 0
temporal_relations = map_i.get_temporal_relations()
for topo in temporal_topo_list:
if topo.upper() in temporal_relations.keys():
relationmaplist = temporal_relations[topo.upper()]
if count == 0 and "cmd_list" in dir(map_i):
cmd_value_list.extend((compop, "("))
for relationmap in relationmaplist:
if (
self._check_spatial_topology_relation(
spatial_topo_list, map_i, relationmap
)
is True
):
if convert and "condition_value" in dir(relationmap):
if relationmap.condition_value != []:
cmdstring = str(int(relationmap.condition_value[0]))
relationmap.cmd_list = cmdstring
if "cmd_list" in dir(relationmap):
if count > 0:
cmd_value_list.append(aggregate + aggregate)
cmd_value_list.append(relationmap.cmd_list)
count += 1
if self.debug:
print(
"compare_cmd_value",
map_i.get_id(),
relationmap.get_id(),
relationmap.cmd_list,
)
if count > 0:
cmd_value_list.append(")")
cmd_value_str = "".join(map(str, cmd_value_list))
# Add command list to result map.
map_i.cmd_list = cmd_value_str
if self.debug:
print(cmd_value_str)
return cmd_value_str
[docs] def operator_cmd_value(
self, map_i, operator, temporal_topo_list=["EQUAL"], spatial_topo_list=[]
):
"""Function to evaluate two map lists by given arithmetic operator.
:param map_i: Map object with temporal extent.
:param operator: Arithmetic operator, +-*/%.
:param temporal_topo_list: List of strings for given temporal relations.
:param spatial_topo_list: List of strings for given spatial relations.
:return: Map object with command list with operators that has been
evaluated by implicit aggregation.
"""
temporal_relations = map_i.get_temporal_relations()
# Build comandlist list with elements from related maps and given relation
# operator.
leftcmd = map_i
cmdstring = ""
for topo in temporal_topo_list:
if topo.upper() in temporal_relations.keys():
relationmaplist = temporal_relations[topo.upper()]
for relationmap in relationmaplist:
if (
self._check_spatial_topology_relation(
spatial_topo_list, map_i, relationmap
)
is True
):
# Create r.mapcalc expression string for the operation.
cmdstring = self.build_command_string(
leftcmd, relationmap, operator=operator, cmd_type="operator"
)
leftcmd = cmdstring
if self.debug:
print(
"operator_cmd_value",
map_i.get_id(),
operator,
relationmap.get_id(),
)
# Add command list to result map.
map_i.cmd_list = cmdstring
if self.debug:
print("map command string", cmdstring)
return cmdstring
[docs] def set_temporal_extent_list(
self,
maplist,
topolist=["EQUAL"],
temporal="l",
cmd_bool: bool = False,
cmd_type=None,
operator=None,
):
"""Change temporal extent of map list based on temporal relations to
other map list and given temporal operator.
:param maplist: List of map objects for which relations has been build
correctly.
:param topolist: List of strings of temporal relations.
:param temporal: The temporal operator specifying the temporal
extent operation (intersection, union, disjoint
union, right reference, left reference).
:param cmd_bool: Boolean if command string should be merged for related maps.
:param cmd_type: map object with defined temporal relation to map_i:
condition, conclusion or operator.
:param operator: String defining the type of operator.
:return: Map list with specified temporal extent and optional command string.
"""
resultdict = {}
temporal_topo_list, spatial_topo_list = self._check_topology(topolist=topolist)
for map_i in maplist:
# Loop over temporal related maps and create overlay modules.
tbrelations = map_i.get_temporal_relations()
# Generate an intermediate map for the result map list.
map_new = self.generate_new_map(
base_map=map_i, bool_op="and", copy=True, rename=True
)
# Combine temporal and spatial extents of intermediate map with related
# maps.
for topo in topolist:
if topo in tbrelations.keys():
for map_j in tbrelations[topo]:
if (
self._check_spatial_topology_relation(
spatial_topo_list, map_i, map_j
)
is True
):
if temporal == "r":
# Generate an intermediate map for the result map list.
map_new = self.generate_new_map(
base_map=map_i,
bool_op="and",
copy=True,
rename=True,
)
# Create overlaid map extent.
returncode = self.overlay_map_extent(
map_new, map_j, "and", temp_op=temporal
)
# Stop the loop if no temporal or spatial relationship
# exist.
if returncode == 0:
break
# Append map to result map list.
if returncode == 1:
# print(map_new.cmd_list)
# resultlist.append(map_new)
if cmd_bool:
# Create r.mapcalc expression string for the
# operation.
cmdstring = self.build_command_string(
map_i,
map_j,
operator=operator,
cmd_type=cmd_type,
)
# Conditional append of module command.
map_new.cmd_list = cmdstring
# Write map object to result dictionary.
resultdict[map_new.uid] = map_new
if returncode == 0:
break
# Append map to result map list.
# if returncode == 1:
# resultlist.append(map_new)
# Get sorted map objects as values from result dictionary.
resultlist = resultdict.values()
return sorted(resultlist, key=AbstractDatasetComparisonKeyStartTime)
[docs] def build_condition_cmd_list(
self,
iflist,
thenlist,
elselist=None,
condition_topolist=["EQUAL"],
conclusion_topolist=["EQUAL"],
temporal="l",
null: bool = False,
):
"""This function build the r.mapcalc command strings for spatial conditionals.
For Example: 'if(a1 == 1, b1, c2)'
:param iflist: Map list with temporal extents and command list.
:param thenlist: Map list with temporal extents and command list or numeric
string.
:param elselist: Map list with temporal extents and command list or numeric
string.
:param condition_topolist: List of strings for given temporal relations between
conditions and conclusions.
:param conclusion_topolist: List of strings for given temporal relations between
conditions (then and else).
:param temporal: The temporal operator specifying the temporal
extent operation (intersection, union, disjoint
union, right reference, left reference).
:param null: Boolean if null map support should be activated.
:return: map list with resulting command string for given condition type.
"""
resultlist = []
# First merge conclusion command maplists or strings.
# Check if alternative conclusion map list is given.
if all([isinstance(thenlist, list), isinstance(elselist, list)]):
# Build conclusion command map list.
conclusiontopolist = self.build_spatio_temporal_topology_list(
thenlist, elselist, conclusion_topolist
)
conclusionlist = self.set_temporal_extent_list(
conclusiontopolist,
topolist=conclusion_topolist,
temporal=temporal,
cmd_bool=True,
cmd_type="conclusion",
)
# Check if any conclusion is a numeric statements.
elif any([isinstance(thenlist, str), isinstance(elselist, str)]):
conclusionlist = []
# Check if only alternative conclusion is a numeric statements.
if all([isinstance(thenlist, list), isinstance(elselist, str)]):
listinput = thenlist
numinput = elselist
for map_i in listinput:
# Create r.mapcalc expression string for the operation.
cmdstring = self.build_command_string(
map_i, numinput, cmd_type="conclusion"
)
# Conditional append of module command.
map_i.cmd_list = cmdstring
# Append map to result map list.
conclusionlist.append(map_i)
# Check if only direct conclusion is a numeric statements.
elif all([isinstance(thenlist, str), isinstance(elselist, list)]):
listinput = elselist
numinput = thenlist
for map_i in listinput:
# Create r.mapcalc expression string for the operation.
cmdstring = self.build_command_string(
numinput, map_i, cmd_type="conclusion"
)
# Conditional append of module command.
map_i.cmd_list = cmdstring
# Append map to result map list.
conclusionlist.append(map_i)
elif all([isinstance(thenlist, str), isinstance(elselist, str)]):
conclusionlist = thenlist + "," + elselist
else:
# The direct conclusion is used.
conclusionlist = thenlist
# Use the conclusion map or string to merge it with the condition and
# return maplist.
if isinstance(conclusionlist, str):
resultlist = []
for map_i in iflist:
# Create r.mapcalc expression string for the operation.
cmdstring = self.build_command_string(
map_i, conclusionlist, cmd_type="condition"
)
# Conditional append of module command.
map_i.cmd_list = cmdstring
# Append map to result map list.
resultlist.append(map_i)
return resultlist
if isinstance(conclusionlist, list):
# Build result command map list between conditions and conclusions.
if self.debug:
print("build_condition_cmd_list", condition_topolist)
conditiontopolist = self.build_spatio_temporal_topology_list(
iflist, conclusionlist, topolist=condition_topolist
)
return self.set_temporal_extent_list(
conditiontopolist,
topolist=condition_topolist,
temporal="r",
cmd_bool=True,
cmd_type="condition",
)
[docs] def p_statement_assign(self, t) -> None:
# This function executes the processing of raster/raster3d algebra
# that was build based on the expression
"""
statement : stds EQUALS expr
"""
if self.run:
# Create the process queue for parallel mapcalc processing
if self.dry_run is False:
process_queue = pymod.ParallelModuleQueue(int(self.nprocs))
if isinstance(t[3], list):
granularity = None
if len(t[3]) > 0 and self.time_suffix == "gran":
map_i = t[3][0]
if map_i.is_time_absolute() is True:
granularity = compute_absolute_time_granularity(t[3])
# The first loop is to check if the raster maps exists in the database
# Compute the size of the numerical suffix
num = len(t[3])
register_list = []
leadzero = len(str(num))
for i in range(num):
map_i = t[3][i]
# Create new map with basename
newident = create_numeric_suffix(
self.basename, i, "%0" + str(leadzero)
)
if (
map_i.is_time_absolute() is True
and self.time_suffix
and granularity is not None
and self.time_suffix == "gran"
):
suffix = create_suffix_from_datetime(
map_i.temporal_extent.get_start_time(), granularity
)
newident = "{ba}_{su}".format(ba=self.basename, su=suffix)
# If set use the time suffix to create the map name
elif (
map_i.is_time_absolute() is True
and self.time_suffix
and self.time_suffix == "time"
):
suffix = create_time_suffix(map_i)
newident = "{ba}_{su}".format(ba=self.basename, su=suffix)
# Check if resultmap names exist in GRASS database.
newident = newident + "@" + self.mapset
if self.stdstype == "strds":
new_map = RasterDataset(newident)
else:
new_map = Raster3DDataset(newident)
if new_map.map_exists() and self.overwrite is False:
self.msgr.fatal(
"Error maps with basename %s exist. "
"Use --o flag to overwrite existing file" % newident
)
# The second loop creates the resulting raster maps
count = 0
map_test_list = []
for map_i in t[3]:
# Create new map with basename
newident = create_numeric_suffix(
self.basename, count, "%0" + str(leadzero)
)
if (
map_i.is_time_absolute() is True
and self.time_suffix
and granularity is not None
and self.time_suffix == "gran"
):
suffix = create_suffix_from_datetime(
map_i.temporal_extent.get_start_time(), granularity
)
newident = "{ba}_{su}".format(ba=self.basename, su=suffix)
# If set use the time suffix to create the map name
elif (
map_i.is_time_absolute() is True
and self.time_suffix
and self.time_suffix == "time"
):
suffix = create_time_suffix(map_i)
newident = "{ba}_{su}".format(ba=self.basename, su=suffix)
if "cmd_list" in dir(map_i):
# Build r.mapcalc module and execute expression.
# Change map name to given basename.
# Create deepcopy of r.mapcalc module.
new_map = map_i.get_new_instance(newident + "@" + self.mapset)
new_map.set_temporal_extent(map_i.get_temporal_extent())
new_map.set_spatial_extent(map_i.get_spatial_extent())
map_test_list.append(new_map)
m = copy.deepcopy(self.m_mapcalc)
m_expression = newident + "=" + map_i.cmd_list
m.inputs["expression"].value = str(m_expression)
m.flags["overwrite"].value = self.overwrite
if self.debug:
print(m.get_bash())
self.process_chain_dict["processes"].append(m.get_dict())
if self.dry_run is False:
process_queue.put(m)
elif map_i.map_exists():
# Copy map if it exists b = a
new_map = map_i.get_new_instance(newident + "@" + self.mapset)
new_map.set_temporal_extent(map_i.get_temporal_extent())
new_map.set_spatial_extent(map_i.get_spatial_extent())
map_test_list.append(new_map)
m = copy.deepcopy(self.m_mapcalc)
m_expression = newident + "=" + map_i.get_map_id()
m.inputs["expression"].value = str(m_expression)
m.flags["overwrite"].value = self.overwrite
if self.debug:
print(m.get_bash())
self.process_chain_dict["processes"].append(m.get_dict())
if self.dry_run is False:
process_queue.put(m)
else:
self.msgr.error(_("Error computing map <%s>") % map_i.get_id())
count += 1
if self.dry_run is False:
process_queue.wait()
for map_i in map_test_list:
register_list.append(map_i)
# Open connection to temporal database.
dbif, unused = init_dbif(self.dbif)
# Create result space time dataset.
if self.dry_run is False:
resultstds = open_new_stds(
t[1],
self.stdstype,
"absolute",
t[1],
t[1],
"mean",
self.dbif,
overwrite=self.overwrite,
)
for map_i in register_list:
# Put the map into the process dictionary
start, end = map_i.get_temporal_extent_as_tuple()
self.process_chain_dict["register"].append(
(map_i.get_name(), str(start), str(end))
)
if self.dry_run is False:
# Get meta data from grass database.
map_i.load()
# Do not register empty maps if not required
# In case of a null map continue, do not register null maps
if (
map_i.metadata.get_min() is None
and map_i.metadata.get_max() is None
):
if not self.register_null:
self.removable_maps[map_i.get_name()] = map_i
continue
if map_i.is_in_db(dbif) and self.overwrite:
# Update map in temporal database.
if self.dry_run is False:
map_i.update_all(dbif)
elif map_i.is_in_db(dbif) and self.overwrite is False:
# Raise error if map exists and no overwrite flag is given.
self.msgr.fatal(
"Error raster map %s exist in temporal database. "
"Use overwrite flag." % map_i.get_map_id()
)
elif self.dry_run is False:
# Insert map into temporal database.
map_i.insert(dbif)
# Register map in result space time dataset.
if self.dry_run is False:
resultstds.register_map(map_i, dbif)
if self.dry_run is False:
resultstds.update_from_registered_maps(dbif)
self.process_chain_dict["STDS"]["name"] = t[1]
self.process_chain_dict["STDS"]["stdstype"] = self.stdstype
self.process_chain_dict["STDS"]["temporal_type"] = "absolute"
dbif.close()
t[0] = register_list
# Remove intermediate maps
self.remove_maps()
[docs] def p_expr_spmap_function(self, t):
# Add a single map.
# Only the spatial extent of the map is evaluated.
# Temporal extent is not existing.
# Examples:
# R = map(A)
"""
mapexpr : MAP LPAREN stds RPAREN
"""
if self.run:
# Check input map.
input = t[3]
if not isinstance(input, list):
# Check for mapset in given stds input.
id_input = input if input.find("@") >= 0 else input + "@" + self.mapset
# Create empty map dataset.
map_i = dataset_factory(self.maptype, id_input)
# Check for occurrence of space time dataset.
if map_i.map_exists() is False:
raise FatalError(
_("%s map <%s> not found in GRASS spatial database")
% (map_i.get_type(), id_input)
)
# Select dataset entry from database.
map_i.select(dbif=self.dbif)
# Create command list for map object.
cmdstring = "(%s)" % (map_i.get_map_id())
map_i.cmd_list = cmdstring
# Return map object.
t[0] = cmdstring
else:
t[0] = "map(" + t[3] + ")"
if self.debug:
print("map(" + t[3] + ")")
[docs] def p_arith1_operation(self, t) -> None:
# A % B
# A / B
# A * B
# A % td(B)
# A * td(B)
# A / td(B)
"""
expr : stds MOD stds
| expr MOD stds
| stds MOD expr
| expr MOD expr
| stds DIV stds
| expr DIV stds
| stds DIV expr
| expr DIV expr
| stds MULT stds
| expr MULT stds
| stds MULT expr
| expr MULT expr
| stds MOD t_td_var
| expr MOD t_td_var
| stds DIV t_td_var
| expr DIV t_td_var
| stds MULT t_td_var
| expr MULT t_td_var
"""
# Check input stds.
maplistA = self.check_stds(t[1])
maplistB = self.check_stds(t[3])
topolist = self.build_spatio_temporal_topology_list(maplistA, maplistB)
if self.run:
resultlist = []
for map_i in topolist:
# Generate an intermediate map for the result map list.
map_new = self.generate_new_map(
base_map=map_i, bool_op="and", copy=True
)
# Loop over temporal related maps and create overlay modules.
tbrelations = map_i.get_temporal_relations()
count = 0
for map_j in tbrelations["EQUAL"]:
# Create overlaid map extent.
returncode = self.overlay_map_extent(
map_new, map_j, "and", temp_op="l"
)
# Stop the loop if no temporal or spatial relationship exist.
if returncode == 0:
break
if count == 0:
# Set map name.
map_new.get_id()
else:
# Generate an intermediate map
self.generate_map_name()
# Create r.mapcalc expression string for the operation.
cmdstring = self.build_command_string(
map_i, map_j, operator=t[2], cmd_type="operator"
)
# Conditional append of module command.
map_new.cmd_list = cmdstring
count += 1
# Append map to result map list.
if returncode == 1:
resultlist.append(map_new)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_arith1_operation_numeric1(self, t) -> None:
# A % 1
# A / 4
# A * 5
# A % map(b1)
# A * map(b2)
# A / map(b3)
"""
expr : stds MOD number
| expr MOD number
| stds DIV number
| expr DIV number
| stds MULT number
| expr MULT number
| stds MOD numberstr
| expr MOD numberstr
| stds DIV numberstr
| expr DIV numberstr
| stds MULT numberstr
| expr MULT numberstr
| stds MOD mapexpr
| expr MOD mapexpr
| stds DIV mapexpr
| expr DIV mapexpr
| stds MULT mapexpr
| expr MULT mapexpr
"""
# Check input stds.
maplist = self.check_stds(t[1])
if self.run:
resultlist = []
for map_i in maplist:
mapinput = map_i.get_id()
# Create r.mapcalc expression string for the operation.
if "cmd_list" in dir(map_i):
cmdstring = "(%s %s %s)" % (map_i.cmd_list, t[2], t[3])
else:
cmdstring = "(%s %s %s)" % (mapinput, t[2], t[3])
# Conditional append of module command.
map_i.cmd_list = cmdstring
# Append map to result map list.
resultlist.append(map_i)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_arith1_operation_numeric2(self, t) -> None:
# 1 % A
# 4 / A
# 5 * A
# map(b1) % A
# map(b4) / A
# map(b5) * A
"""
expr : number MOD stds
| number MOD expr
| number DIV stds
| number DIV expr
| number MULT stds
| number MULT expr
| numberstr MOD stds
| numberstr MOD expr
| numberstr DIV stds
| numberstr DIV expr
| numberstr MULT stds
| numberstr MULT expr
| mapexpr MOD stds
| mapexpr MOD expr
| mapexpr DIV stds
| mapexpr DIV expr
| mapexpr MULT stds
| mapexpr MULT expr
"""
# Check input stds.
maplist = self.check_stds(t[3])
if self.run:
resultlist = []
for map_i in maplist:
mapinput = map_i.get_id()
# Create r.mapcalc expression string for the operation.
if "cmd_list" in dir(map_i):
cmdstring = "(%s %s %s)" % (t[1], t[2], map_i.cmd_list)
else:
cmdstring = "(%s %s %s)" % (t[1], t[2], mapinput)
# Conditional append of module command.
map_i.cmd_list = cmdstring
# Append map to result map list.
resultlist.append(map_i)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_arith2_operation(self, t) -> None:
# A + B
# A - B
# A + td(B)
# A - td(B)
"""
expr : stds ADD stds
| expr ADD stds
| stds ADD expr
| expr ADD expr
| stds SUB stds
| expr SUB stds
| stds SUB expr
| expr SUB expr
| stds ADD t_td_var
| expr ADD t_td_var
| expr SUB t_td_var
| stds SUB t_td_var
"""
# Check input stds.
maplistA = self.check_stds(t[1])
maplistB = self.check_stds(t[3])
topolist = self.build_spatio_temporal_topology_list(maplistA, maplistB)
if self.run:
resultlist = []
for map_i in topolist:
# Generate an intermediate map for the result map list.
map_new = self.generate_new_map(
base_map=map_i, bool_op="and", copy=True
)
# Loop over temporal related maps and create overlay modules.
tbrelations = map_i.get_temporal_relations()
count = 0
for map_j in tbrelations["EQUAL"]:
# Create overlaid map extent.
returncode = self.overlay_map_extent(
map_new, map_j, "and", temp_op="l"
)
# Stop the loop if no temporal or spatial relationship exist.
if returncode == 0:
break
if count == 0:
# Set map name.
map_new.get_id()
else:
# Generate an intermediate map
self.generate_map_name()
# Create r.mapcalc expression string for the operation.
cmdstring = self.build_command_string(
map_i, map_j, operator=t[2], cmd_type="operator"
)
# Conditional append of module command.
map_new.cmd_list = cmdstring
count += 1
# Append map to result map list.
if returncode == 1:
resultlist.append(map_new)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_arith2_operation_numeric1(self, t) -> None:
# A + 2
# A - 3
# A + map(b4)
# A - map(b5)
"""
expr : stds ADD number
| expr ADD number
| stds SUB number
| expr SUB number
| stds ADD numberstr
| expr ADD numberstr
| stds SUB numberstr
| expr SUB numberstr
| stds ADD mapexpr
| expr ADD mapexpr
| stds SUB mapexpr
| expr SUB mapexpr
"""
# Check input stds.
maplist = self.check_stds(t[1])
if self.run:
resultlist = []
for map_i in maplist:
mapinput = map_i.get_id()
# Create r.mapcalc expression string for the operation.
if "cmd_list" in dir(map_i):
cmdstring = "(%s %s %s)" % (map_i.cmd_list, t[2], t[3])
else:
cmdstring = "(%s %s %s)" % (mapinput, t[2], t[3])
# Conditional append of module command.
map_i.cmd_list = cmdstring
# Append map to result map list.
resultlist.append(map_i)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_arith2_operation_numeric2(self, t) -> None:
# 2 + A
# 3 - A
# map(b2) + A
# map(b3) - A
"""
expr : number ADD stds
| number ADD expr
| number SUB stds
| number SUB expr
| numberstr ADD stds
| numberstr ADD expr
| numberstr SUB stds
| numberstr SUB expr
| mapexpr ADD stds
| mapexpr ADD expr
| mapexpr SUB stds
| mapexpr SUB expr
"""
# Check input stds.
maplist = self.check_stds(t[3])
if self.run:
resultlist = []
for map_i in maplist:
mapinput = map_i.get_id()
# Create r.mapcalc expression string for the operation.
if "cmd_list" in dir(map_i):
cmdstring = "(%s %s %s)" % (t[1], t[2], map_i.cmd_list)
else:
cmdstring = "(%s %s %s)" % (t[1], t[2], mapinput)
# Conditional append of module command.
map_i.cmd_list = cmdstring
# Append map to result map list.
resultlist.append(map_i)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_arith1_operation_relation(self, t) -> None:
# A {*, equal, l} B
# A {*, equal, l} td(B)
# A {*, equal, l} B {/, during, r} C
# A {*, equal, l} B {/, equal, l} C {/, during, r} D
"""
expr : stds T_ARITH1_OPERATOR stds
| expr T_ARITH1_OPERATOR stds
| stds T_ARITH1_OPERATOR expr
| expr T_ARITH1_OPERATOR expr
| stds T_ARITH1_OPERATOR t_td_var
| expr T_ARITH1_OPERATOR t_td_var
"""
if self.run:
# Check input stds.
maplistA = self.check_stds(t[1])
maplistB = self.check_stds(t[3])
relations, temporal, function, aggregate = self.eval_toperator(
t[2], optype="raster"
)
# Build conditional values based on topological relationships.
complist = self.build_spatio_temporal_topology_list(
maplistA,
maplistB,
topolist=relations,
operator_cmd=True,
compop=function,
)
# Set temporal extent based on topological relationships.
resultlist = self.set_temporal_extent_list(
complist, topolist=relations, temporal=temporal
)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_arith2_operation_relation(self, t) -> None:
# A {+, equal, l} B
# A {+, equal, l} td(b)
# A {+, equal, l} B {-, during, r} C
# A {+, equal, l} B {+, equal, l} C {-, during, r} D
"""
expr : stds T_ARITH2_OPERATOR stds
| expr T_ARITH2_OPERATOR stds
| stds T_ARITH2_OPERATOR expr
| expr T_ARITH2_OPERATOR expr
| stds T_ARITH2_OPERATOR t_td_var
| expr T_ARITH2_OPERATOR t_td_var
"""
if self.run:
# Check input stds.
maplistA = self.check_stds(t[1])
maplistB = self.check_stds(t[3])
relations, temporal, function, aggregate = self.eval_toperator(
t[2], optype="raster"
)
# Build conditional values based on topological relationships.
complist = self.build_spatio_temporal_topology_list(
maplistA,
maplistB,
topolist=relations,
operator_cmd=True,
compop=function,
)
# Set temporal extent based on topological relationships.
resultlist = self.set_temporal_extent_list(
complist, topolist=relations, temporal=temporal
)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_arith_operation_numeric_string(self, t) -> None:
# 1 + 1
# 1 - 1
# 1 * 1
# 1 / 1
# 1 % 1
"""
numberstr : number ADD number
| number SUB number
| number DIV number
| number MULT number
| number MOD number
"""
numstring = "(%s %s %s)" % (t[1], t[2], t[3])
t[0] = numstring
if self.debug:
print(numstring)
[docs] def p_mapcalc_function(self, t) -> None:
# Supported mapcalc functions.
"""
mapcalc_arith : ABS
| LOG
| SQRT
| EXP
| COS
| ACOS
| SIN
| ASIN
| TAN
| DOUBLE
| FLOATEXP
| INTEXP
"""
t[0] = t[1]
if self.debug:
print(t[1])
[docs] def p_mapcalc_operation1(self, t) -> None:
# sin(A)
# log(B)
"""
expr : mapcalc_arith LPAREN stds RPAREN
| mapcalc_arith LPAREN expr RPAREN
"""
# Check input stds.
maplist = self.check_stds(t[3])
if self.run:
resultlist = []
for map_i in maplist:
# Create r.mapcalc expression string for the operation.
if "cmd_list" in dir(map_i):
cmdstring = "%s(%s)" % (t[1].lower(), map_i.cmd_list)
else:
cmdstring = "%s(%s)" % (t[1].lower(), map_i.get_id())
# Set new command list for map.
map_i.cmd_list = cmdstring
# Append map with updated command list to result list.
resultlist.append(map_i)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_mapexpr_operation(self, t) -> None:
# sin(map(a))
"""
mapexpr : mapcalc_arith LPAREN mapexpr RPAREN
"""
# Check input stds.
mapstring = t[3]
if self.run:
cmdstring = "%s(%s)" % (t[1].lower(), mapstring)
t[0] = cmdstring
if self.debug:
print(mapstring)
[docs] def p_s_var_expr_1(self, t) -> None:
# isnull(A)
"""
s_var_expr : ISNULL LPAREN stds RPAREN
| ISNULL LPAREN expr RPAREN
"""
# Check input stds.
maplist = self.check_stds(t[3])
if self.run:
resultlist = []
for map_i in maplist:
# Create r.mapcalc expression string for the operation.
if "cmd_list" in dir(map_i):
cmdstring = "%s(%s)" % (t[1].lower(), map_i.cmd_list)
else:
cmdstring = "%s(%s)" % (t[1].lower(), map_i.get_id())
# Set new command list for map.
map_i.cmd_list = cmdstring
# Append map with updated command list to result list.
resultlist.append(map_i)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_s_var_expr_2(self, t) -> None:
# isntnull(A)
"""
s_var_expr : ISNTNULL LPAREN stds RPAREN
| ISNTNULL LPAREN expr RPAREN
"""
# Check input stds.
maplist = self.check_stds(t[3])
if self.run:
resultlist = []
for map_i in maplist:
# Create r.mapcalc expression string for the operation.
if "cmd_list" in dir(map_i):
cmdstring = "!isnull(%s)" % (map_i.cmd_list)
else:
cmdstring = "!isnull(%s)" % (map_i.get_id())
# Set new command list for map.
map_i.cmd_list = cmdstring
# Append map with updated command list to result list.
resultlist.append(map_i)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_s_var_expr_3(self, t) -> None:
# A <= 2
"""
s_var_expr : stds comp_op number
| expr comp_op number
"""
# Check input stds.
maplist = self.check_stds(t[1])
if self.run:
resultlist = []
for map_i in maplist:
# Create r.mapcalc expression string for the operation.
if "cmd_list" in dir(map_i):
cmdstring = "%s %s %s" % (map_i.cmd_list, t[2], t[3])
else:
cmdstring = "%s %s %s" % (map_i.get_id(), t[2], t[3])
# Set new command list for map.
map_i.cmd_list = cmdstring
# Append map with updated command list to result list.
resultlist.append(map_i)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_s_var_expr_4(self, t) -> None:
# exist(B)
"""
s_var_expr : EXIST LPAREN stds RPAREN
| EXIST LPAREN expr RPAREN
"""
# Check input stds.
maplist = self.check_stds(t[3])
if self.run:
resultlist = []
for map_i in maplist:
# Create r.mapcalc expression string for the operation.
if "cmd_list" in dir(map_i):
cmdstring = "%s" % (map_i.cmd_list)
else:
cmdstring = "%s" % (map_i.get_id())
# Set new command list for map.
map_i.cmd_list = cmdstring
# Append map with updated command list to result list.
resultlist.append(map_i)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_s_var_expr_comp(self, t) -> None:
# A <= 2 || B == 10
# A < 3 && A > 1
"""
s_var_expr : s_var_expr AND AND s_var_expr
| s_var_expr OR OR s_var_expr
"""
if self.run:
# Check input stds.
s_var_exprA = self.check_stds(t[1])
s_var_exprB = self.check_stds(t[4])
relations = ["EQUAL"]
temporal = "l"
function = t[2] + t[3]
aggregate = t[2]
# Build conditional values based on topological relationships.
complist = self.build_spatio_temporal_topology_list(
s_var_exprA,
s_var_exprB,
topolist=relations,
compare_cmd=True,
compop=function,
aggregate=aggregate,
)
# Set temporal extent based on topological relationships.
resultlist = self.set_temporal_extent_list(
complist, topolist=relations, temporal=temporal
)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_s_var_expr_comp_op(self, t) -> None:
# A <= 2 {||} B == 10
# A < 3 {&&, equal} A > 1
"""
s_var_expr : s_var_expr T_COMP_OPERATOR s_var_expr
"""
if self.run:
# Check input stds.
s_var_exprA = self.check_stds(t[1])
s_var_exprB = self.check_stds(t[3])
# Evaluate temporal comparison operator.
relations, temporal, function, aggregate = self.eval_toperator(
t[2], optype="boolean"
)
# Build conditional values based on topological relationships.
complist = self.build_spatio_temporal_topology_list(
s_var_exprA,
s_var_exprB,
topolist=relations,
compare_cmd=True,
compop=function,
aggregate=aggregate,
)
# Set temporal extent based on topological relationships.
resultlist = self.set_temporal_extent_list(
complist, topolist=relations, temporal=temporal
)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_s_expr_condition_if(self, t) -> None:
# if(s_var_expr, B)
# if(A == 1, B)
"""
expr : IF LPAREN s_var_expr COMMA stds RPAREN
| IF LPAREN s_var_expr COMMA expr RPAREN
| IF LPAREN ts_var_expr COMMA stds RPAREN
| IF LPAREN ts_var_expr COMMA expr RPAREN
"""
ifmaplist = self.check_stds(t[3])
thenmaplist = self.check_stds(t[5])
resultlist = self.build_condition_cmd_list(
ifmaplist,
thenmaplist,
elselist=None,
condition_topolist=["EQUAL"],
conclusion_topolist=["EQUAL"],
temporal="r",
null=False,
)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_s_numeric_condition_if(self, t) -> None:
# if(s_var_expr, 1)
# if(A == 5, 10)
"""
expr : IF LPAREN s_var_expr COMMA number RPAREN
| IF LPAREN s_var_expr COMMA NULL LPAREN RPAREN RPAREN
| IF LPAREN ts_var_expr COMMA number RPAREN
| IF LPAREN ts_var_expr COMMA NULL LPAREN RPAREN RPAREN
"""
ifmaplist = self.check_stds(t[3])
resultlist = []
# Select input for r.mapcalc expression based on length of PLY object.
if len(t) == 7:
numinput = str(t[5])
elif len(t) == 9:
numinput = str(t[5] + t[6] + t[7])
# Iterate over condition map list.
for map_i in ifmaplist:
# Create r.mapcalc expression string for the operation.
cmdstring = self.build_command_string(map_i, numinput, cmd_type="condition")
# Conditional append of module command.
map_i.cmd_list = cmdstring
# Append map to result map list.
resultlist.append(map_i)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_s_expr_condition_if_relation(self, t) -> None:
# if({equal||during}, s_var_expr, A)
"""
expr : IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA stds RPAREN
| IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA expr RPAREN
| IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA stds RPAREN
| IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA expr RPAREN
"""
relations, temporal, function, aggregation = self.eval_toperator(
t[3], optype="relation"
)
ifmaplist = self.check_stds(t[5])
thenmaplist = self.check_stds(t[7])
resultlist = self.build_condition_cmd_list(
ifmaplist,
thenmaplist,
elselist=None,
condition_topolist=relations,
conclusion_topolist=["EQUAL"],
temporal="r",
null=False,
)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_s_expr_condition_elif(self, t) -> None:
# if(s_var_expr, A, B)
"""
expr : IF LPAREN s_var_expr COMMA stds COMMA stds RPAREN
| IF LPAREN s_var_expr COMMA stds COMMA expr RPAREN
| IF LPAREN s_var_expr COMMA expr COMMA stds RPAREN
| IF LPAREN s_var_expr COMMA expr COMMA expr RPAREN
| IF LPAREN ts_var_expr COMMA stds COMMA stds RPAREN
| IF LPAREN ts_var_expr COMMA stds COMMA expr RPAREN
| IF LPAREN ts_var_expr COMMA expr COMMA stds RPAREN
| IF LPAREN ts_var_expr COMMA expr COMMA expr RPAREN
"""
# Check map list inputs.
ifmaplist = self.check_stds(t[3])
thenmaplist = self.check_stds(t[5])
elsemaplist = self.check_stds(t[7])
# Create conditional command map list.
resultlist = self.build_condition_cmd_list(
ifmaplist,
thenmaplist,
elselist=elsemaplist,
condition_topolist=["EQUAL"],
conclusion_topolist=["EQUAL"],
temporal="r",
null=False,
)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_s_numeric_condition_elif(self, t) -> None:
# if(s_var_expr, 1, 2)
# if(A == 5, 10, 0)
"""
expr : IF LPAREN s_var_expr COMMA number COMMA number RPAREN
| IF LPAREN s_var_expr COMMA NULL LPAREN RPAREN COMMA number RPAREN
| IF LPAREN s_var_expr COMMA number COMMA NULL LPAREN RPAREN RPAREN
| IF LPAREN s_var_expr COMMA NULL LPAREN RPAREN COMMA NULL LPAREN RPAREN RPAREN
| IF LPAREN ts_var_expr COMMA number COMMA number RPAREN
| IF LPAREN ts_var_expr COMMA NULL LPAREN RPAREN COMMA number RPAREN
| IF LPAREN ts_var_expr COMMA number COMMA NULL LPAREN RPAREN RPAREN
| IF LPAREN ts_var_expr COMMA NULL LPAREN RPAREN COMMA NULL LPAREN RPAREN RPAREN
""" # noqa: E501
ifmaplist = self.check_stds(t[3])
# Select input for r.mapcalc expression based on length of PLY object.
if len(t) == 9:
numthen = t[5]
numelse = t[7]
elif len(t) == 11 and t[6] == "(":
numthen = t[5] + t[6] + t[7]
numelse = t[9]
elif len(t) == 11 and t[6] == ",":
numthen = t[5]
numelse = t[7] + t[8] + t[9]
elif len(t) == 13:
numthen = t[5] + t[6] + t[7]
numelse = t[9] + t[10] + t[11]
numthen = str(numthen)
numelse = str(numelse)
if self.debug:
print(numthen + " " + numelse)
# Create conditional command map list.
resultlist = self.build_condition_cmd_list(
ifmaplist,
numthen,
numelse,
condition_topolist=["EQUAL"],
conclusion_topolist=["EQUAL"],
temporal="r",
null=False,
)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_s_numeric_expr_condition_elif(self, t) -> None:
# if(s_var_expr, 1, A)
# if(A == 5 && C > 5, A, null())
"""
expr : IF LPAREN s_var_expr COMMA number COMMA stds RPAREN
| IF LPAREN s_var_expr COMMA NULL LPAREN RPAREN COMMA stds RPAREN
| IF LPAREN s_var_expr COMMA number COMMA expr RPAREN
| IF LPAREN s_var_expr COMMA NULL LPAREN RPAREN COMMA expr RPAREN
| IF LPAREN s_var_expr COMMA stds COMMA number RPAREN
| IF LPAREN s_var_expr COMMA stds COMMA NULL LPAREN RPAREN RPAREN
| IF LPAREN s_var_expr COMMA expr COMMA number RPAREN
| IF LPAREN s_var_expr COMMA expr COMMA NULL LPAREN RPAREN RPAREN
| IF LPAREN ts_var_expr COMMA number COMMA stds RPAREN
| IF LPAREN ts_var_expr COMMA NULL LPAREN RPAREN COMMA stds RPAREN
| IF LPAREN ts_var_expr COMMA number COMMA expr RPAREN
| IF LPAREN ts_var_expr COMMA NULL LPAREN RPAREN COMMA expr RPAREN
| IF LPAREN ts_var_expr COMMA stds COMMA number RPAREN
| IF LPAREN ts_var_expr COMMA stds COMMA NULL LPAREN RPAREN RPAREN
| IF LPAREN ts_var_expr COMMA expr COMMA number RPAREN
| IF LPAREN ts_var_expr COMMA expr COMMA NULL LPAREN RPAREN RPAREN
"""
ifmaplist = self.check_stds(t[3])
# Select input for r.mapcalc expression based on length of PLY object.
if len(t) == 9:
if isinstance(t[5], int):
theninput = str(t[5])
elseinput = self.check_stds(t[7])
elif isinstance(t[7], int):
theninput = self.check_stds(t[5])
elseinput = str(t[7])
elif len(t) == 11:
if t[5] == "null":
theninput = str(t[5] + t[6] + t[7])
elseinput = self.check_stds(t[9])
elif t[7] == "null":
theninput = self.check_stds(t[5])
elseinput = str(t[7] + t[8] + t[9])
# Create conditional command map list.
resultlist = self.build_condition_cmd_list(
ifmaplist,
theninput,
elseinput,
condition_topolist=["EQUAL"],
conclusion_topolist=["EQUAL"],
temporal="r",
null=False,
)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_s_numeric_expr_condition_elif_relation(self, t) -> None:
# if({during},s_var_expr, 1, A)
# if({during}, A == 5, A, null())
"""
expr : IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA number COMMA stds RPAREN
| IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA NULL LPAREN RPAREN COMMA stds RPAREN
| IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA number COMMA expr RPAREN
| IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA NULL LPAREN RPAREN COMMA expr RPAREN
| IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA stds COMMA number RPAREN
| IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA stds COMMA NULL LPAREN RPAREN RPAREN
| IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA expr COMMA number RPAREN
| IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA expr COMMA NULL LPAREN RPAREN RPAREN
| IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA number COMMA stds RPAREN
| IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA NULL LPAREN RPAREN COMMA stds RPAREN
| IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA number COMMA expr RPAREN
| IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA NULL LPAREN RPAREN COMMA expr RPAREN
| IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA stds COMMA number RPAREN
| IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA stds COMMA NULL LPAREN RPAREN RPAREN
| IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA expr COMMA number RPAREN
| IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA expr COMMA NULL LPAREN RPAREN RPAREN
""" # noqa: E501
relations, temporal, function, aggregation = self.eval_toperator(
t[3], optype="relation"
)
ifmaplist = self.check_stds(t[5])
# Select input for r.mapcalc expression based on length of PLY object.
if len(t) == 11:
if isinstance(t[7], int):
theninput = str(t[7])
elseinput = self.check_stds(t[9])
elif isinstance(t[9], int):
theninput = self.check_stds(t[7])
elseinput = str(t[9])
elif len(t) == 13:
if t[7] == "null":
theninput = str(t[7] + t[8] + t[9])
elseinput = self.check_stds(t[11])
elif t[9] == "null":
theninput = self.check_stds(t[7])
elseinput = str(t[9] + t[10] + t[11])
# Create conditional command map list.
resultlist = self.build_condition_cmd_list(
ifmaplist,
theninput,
elseinput,
condition_topolist=relations,
conclusion_topolist=["EQUAL"],
temporal="r",
null=False,
)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_s_expr_condition_elif_relation(self, t) -> None:
# if({equal||during}, s_var_expr, A, B)
"""
expr : IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA stds COMMA stds RPAREN
| IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA stds COMMA expr RPAREN
| IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA expr COMMA stds RPAREN
| IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA expr COMMA expr RPAREN
| IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA stds COMMA stds RPAREN
| IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA stds COMMA expr RPAREN
| IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA expr COMMA stds RPAREN
| IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA expr COMMA expr RPAREN
"""
relations, temporal, function, aggregation = self.eval_toperator(
t[3], optype="relation"
)
ifmaplist = self.check_stds(t[5])
thenmaplist = self.check_stds(t[7])
elsemaplist = self.check_stds(t[9])
# Create conditional command map list.
resultlist = self.build_condition_cmd_list(
ifmaplist,
thenmaplist,
elsemaplist,
condition_topolist=relations,
conclusion_topolist=["EQUAL"],
temporal="r",
null=False,
)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
[docs] def p_ts_var_expr1(self, t) -> None:
# Combination of spatial and temporal conditional expressions.
# Examples:
# A <= 2 || start_date <= 2013-01-01
# end_date > 2013-01-15 && A > 10
# IMPORTANT: Only the intersection of map lists in conditionals are
# exported.
"""
ts_var_expr : s_var_expr AND AND t_var_expr
| t_var_expr AND AND s_var_expr
| t_var_expr OR OR s_var_expr
| s_var_expr OR OR t_var_expr
| ts_var_expr AND AND s_var_expr
| ts_var_expr AND AND t_var_expr
| ts_var_expr OR OR s_var_expr
| ts_var_expr OR OR t_var_expr
| s_var_expr AND AND ts_var_expr
| t_var_expr AND AND ts_var_expr
| s_var_expr OR OR ts_var_expr
| t_var_expr OR OR ts_var_expr
"""
if self.run:
# Check input stds.
s_var_exprA = self.check_stds(t[1])
s_var_exprB = self.check_stds(t[4])
relations = ["EQUAL"]
temporal = "l"
function = t[2] + t[3]
aggregate = t[2]
# Build conditional values based on topological relationships.
complist = self.build_spatio_temporal_topology_list(
s_var_exprA,
s_var_exprB,
topolist=relations,
compare_cmd=True,
compop=function,
aggregate=aggregate,
convert=True,
)
# Set temporal extent based on topological relationships.
resultlist = self.set_temporal_extent_list(
complist, topolist=relations, temporal=temporal
)
t[0] = resultlist
[docs] def p_hash_operation(self, t) -> None:
# Calculate the number of maps within an interval of another map from a
# second space time dataset.
# A # B
# A {equal,r#} B
"""
expr : t_hash_var
"""
# Check input stds.
maplist = self.check_stds(t[1])
if self.run:
resultlist = []
for map_i in maplist:
for obj in map_i.map_value:
if isinstance(obj, GlobalTemporalVar):
n_maps = obj.td
# Create r.mapcalc expression string for the operation.
cmdstring = "(%s)" % (n_maps)
# Append module command.
map_i.cmd_list = cmdstring
# Append map to result map list.
resultlist.append(map_i)
t[0] = resultlist
if self.debug:
for map in resultlist:
print(map.cmd_list)
if __name__ == "__main__":
import doctest
doctest.testmod()