temporal_raster_base_algebra.py 77 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055
  1. """@package grass.temporal
  2. Temporal raster algebra
  3. (C) 2013 by the GRASS Development Team
  4. This program is free software under the GNU General Public
  5. License (>=v2). Read the file COPYING that comes with GRASS
  6. for details.
  7. :authors: Thomas Leppelt and Soeren Gebbert
  8. .. code-block:: python
  9. >>> p = TemporalRasterAlgebraLexer()
  10. >>> p.build()
  11. >>> p.debug = True
  12. >>> expression = 'R = A {+,equal,l} B'
  13. >>> p.test(expression)
  14. R = A {+,equal,l} B
  15. LexToken(NAME,'R',1,0)
  16. LexToken(EQUALS,'=',1,2)
  17. LexToken(NAME,'A',1,4)
  18. LexToken(T_ARITH2_OPERATOR,'{+,equal,l}',1,6)
  19. LexToken(NAME,'B',1,18)
  20. >>> expression = 'R = A {*,equal|during,r} B'
  21. >>> p.test(expression)
  22. R = A {*,equal|during,r} B
  23. LexToken(NAME,'R',1,0)
  24. LexToken(EQUALS,'=',1,2)
  25. LexToken(NAME,'A',1,4)
  26. LexToken(T_ARITH1_OPERATOR,'{*,equal|during,r}',1,6)
  27. LexToken(NAME,'B',1,25)
  28. >>> expression = 'R = A {+,equal|during} B'
  29. >>> p.test(expression)
  30. R = A {+,equal|during} B
  31. LexToken(NAME,'R',1,0)
  32. LexToken(EQUALS,'=',1,2)
  33. LexToken(NAME,'A',1,4)
  34. LexToken(T_ARITH2_OPERATOR,'{+,equal|during}',1,6)
  35. LexToken(NAME,'B',1,23)
  36. """
  37. from __future__ import print_function
  38. import copy
  39. import grass.pygrass.modules as pymod
  40. from grass.exceptions import FatalError
  41. from .temporal_algebra import (
  42. TemporalAlgebraLexer,
  43. TemporalAlgebraParser,
  44. GlobalTemporalVar,
  45. )
  46. from .core import init_dbif
  47. from .abstract_dataset import AbstractDatasetComparisonKeyStartTime
  48. from .factory import dataset_factory
  49. from .open_stds import open_new_stds
  50. from .spatio_temporal_relationships import SpatioTemporalTopologyBuilder
  51. from .space_time_datasets import Raster3DDataset, RasterDataset
  52. from .temporal_granularity import compute_absolute_time_granularity
  53. from .datetime_math import create_suffix_from_datetime
  54. from .datetime_math import create_time_suffix
  55. from .datetime_math import create_numeric_suffix
  56. class TemporalRasterAlgebraLexer(TemporalAlgebraLexer):
  57. """Lexical analyzer for the GRASS GIS temporal algebra"""
  58. def __init__(self):
  59. TemporalAlgebraLexer.__init__(self)
  60. # Supported r.mapcalc functions.
  61. mapcalc_functions = {
  62. "exp": "EXP",
  63. "log": "LOG",
  64. "sqrt": "SQRT",
  65. "abs": "ABS",
  66. "cos": "COS",
  67. "acos": "ACOS",
  68. "sin": "SIN",
  69. "asin": "ASIN",
  70. "tan": "TAN",
  71. "double": "DOUBLE",
  72. "float": "FLOATEXP",
  73. "int": "INTEXP",
  74. "isnull": "ISNULL",
  75. "isntnull": "ISNTNULL",
  76. "null": "NULL",
  77. "exist": "EXIST",
  78. }
  79. # Functions that defines single maps with time stamp and without temporal extent.
  80. map_functions = {"map": "MAP"}
  81. # This is the list of token names.
  82. raster_tokens = (
  83. "MOD",
  84. "DIV",
  85. "MULT",
  86. "ADD",
  87. "SUB",
  88. "T_ARITH1_OPERATOR",
  89. "T_ARITH2_OPERATOR",
  90. "L_SPAREN",
  91. "R_SPAREN",
  92. )
  93. # Build the token list
  94. tokens = (
  95. TemporalAlgebraLexer.tokens
  96. + raster_tokens
  97. + tuple(mapcalc_functions.values())
  98. + tuple(map_functions.values())
  99. )
  100. # Regular expression rules for simple tokens
  101. t_MOD = r"[\%]"
  102. t_DIV = r"[\/]"
  103. t_MULT = r"[\*]"
  104. t_ADD = r"[\+]"
  105. t_SUB = r"[-]"
  106. t_T_ARITH1_OPERATOR = r"\{[\%\*\/][,]?[a-zA-Z\| ]*([,])?([lrudi]|left|right|union|disjoint|intersect)?\}"
  107. t_T_ARITH2_OPERATOR = (
  108. r"\{[+-][,]?[a-zA-Z\| ]*([,])?([lrudi]|left|right|union|disjoint|intersect)?\}"
  109. )
  110. t_L_SPAREN = r"\["
  111. t_R_SPAREN = r"\]"
  112. # Parse symbols
  113. def temporal_symbol(self, t):
  114. # Check for reserved words
  115. if t.value in TemporalRasterAlgebraLexer.time_functions.keys():
  116. t.type = TemporalRasterAlgebraLexer.time_functions.get(t.value)
  117. elif t.value in TemporalRasterAlgebraLexer.datetime_functions.keys():
  118. t.type = TemporalRasterAlgebraLexer.datetime_functions.get(t.value)
  119. elif t.value in TemporalRasterAlgebraLexer.conditional_functions.keys():
  120. t.type = TemporalRasterAlgebraLexer.conditional_functions.get(t.value)
  121. elif t.value in TemporalRasterAlgebraLexer.mapcalc_functions.keys():
  122. t.type = TemporalRasterAlgebraLexer.mapcalc_functions.get(t.value)
  123. elif t.value in TemporalRasterAlgebraLexer.map_functions.keys():
  124. t.type = TemporalRasterAlgebraLexer.map_functions.get(t.value)
  125. else:
  126. t.type = "NAME"
  127. return t
  128. class TemporalRasterBaseAlgebraParser(TemporalAlgebraParser):
  129. """The temporal algebra class"""
  130. # Get the tokens from the lexer class
  131. tokens = TemporalRasterAlgebraLexer.tokens
  132. # Setting equal precedence level for select and hash operations.
  133. precedence = (
  134. ("left", "T_SELECT_OPERATOR", "T_SELECT", "T_NOT_SELECT"), # 1
  135. ("left", "ADD", "SUB", "T_ARITH2_OPERATOR", "T_HASH_OPERATOR", "HASH"), # 2
  136. (
  137. "left",
  138. "AND",
  139. "OR",
  140. "T_COMP_OPERATOR",
  141. "MOD",
  142. "DIV",
  143. "MULT",
  144. "T_ARITH1_OPERATOR",
  145. ),
  146. )
  147. def __init__(
  148. self,
  149. pid=None,
  150. run=True,
  151. debug=False,
  152. spatial=False,
  153. register_null=False,
  154. dry_run=False,
  155. nprocs=1,
  156. time_suffix=None,
  157. ):
  158. TemporalAlgebraParser.__init__(
  159. self,
  160. pid=pid,
  161. run=run,
  162. debug=debug,
  163. spatial=spatial,
  164. register_null=register_null,
  165. dry_run=dry_run,
  166. nprocs=nprocs,
  167. time_suffix=time_suffix,
  168. )
  169. def check_null(self, t):
  170. try:
  171. int(t)
  172. return t
  173. except ValueError:
  174. return "null()"
  175. def build_spatio_temporal_topology_list(
  176. self,
  177. maplistA,
  178. maplistB=None,
  179. topolist=["EQUAL"],
  180. assign_val=False,
  181. count_map=False,
  182. compare_bool=False,
  183. compare_cmd=False,
  184. compop=None,
  185. aggregate=None,
  186. new=False,
  187. convert=False,
  188. operator_cmd=False,
  189. ):
  190. """Build temporal topology for two space time data sets, copy map objects
  191. for given relation into map list.
  192. :param maplistA: List of maps.
  193. :param maplistB: List of maps.
  194. :param topolist: List of strings of temporal relations.
  195. :param assign_val: Boolean for assigning a boolean map value based on
  196. the map_values from the compared map list by
  197. topological relationships.
  198. :param count_map: Boolean if the number of topological related maps
  199. should be returned.
  200. :param compare_bool: Boolean for comparing boolean map values based on
  201. related map list and compariosn operator.
  202. :param compare_cmd: Boolean for comparing command list values based on
  203. related map list and compariosn operator.
  204. :param compop: Comparison operator, && or ||.
  205. :param aggregate: Aggregation operator for relation map list, & or |.
  206. :param new: Boolean if new temporary maps should be created.
  207. :param convert: Boolean if conditional values should be converted to
  208. r.mapcalc command strings.
  209. :param operator_cmd: Boolean for aggregate arithmetic operators implicitly
  210. in command list values based on related map lists.
  211. :return: List of maps from maplistA that fulfil the topological relationships
  212. to maplistB specified in topolist.
  213. >>> # Create two list of maps with equal time stamps
  214. >>> from datetime import datetime
  215. >>> import grass.temporal as tgis
  216. >>> tgis.init(True)
  217. >>> l = tgis.TemporalAlgebraParser()
  218. >>> mapsA = []
  219. >>> mapsB = []
  220. >>> for i in range(10):
  221. ... idA = "a%i@B"%(i)
  222. ... mapA = tgis.RasterDataset(idA)
  223. ... mapA.uid = idA
  224. ... mapA.map_value = True
  225. ... idB = "b%i@B"%(i)
  226. ... mapB = tgis.RasterDataset(idB)
  227. ... mapB.uid = idB
  228. ... mapB.map_value = False
  229. ... check = mapA.set_absolute_time(datetime(2000,1,i+1),
  230. ... datetime(2000,1,i + 2))
  231. ... check = mapB.set_absolute_time(datetime(2000,1,i+6),
  232. ... datetime(2000,1,i + 7))
  233. ... mapsA.append(mapA)
  234. ... mapsB.append(mapB)
  235. >>> resultlist = l.build_spatio_temporal_topology_list(mapsA, mapsB)
  236. >>> for map in resultlist:
  237. ... print(map.get_id())
  238. a5@B
  239. a6@B
  240. a7@B
  241. a8@B
  242. a9@B
  243. """
  244. print(
  245. topolist,
  246. assign_val,
  247. count_map,
  248. compare_bool,
  249. compare_cmd,
  250. compop,
  251. aggregate,
  252. new,
  253. convert,
  254. operator_cmd,
  255. )
  256. # Check the topology definitions and return the list of temporal and spatial
  257. # topological relations that must be fulfilled
  258. temporal_topo_list, spatial_topo_list = self._check_topology(topolist=topolist)
  259. resultdict = {}
  260. # Create temporal topology for maplistA to maplistB.
  261. tb = SpatioTemporalTopologyBuilder()
  262. # Build spatio-temporal topology
  263. if len(spatial_topo_list) > 0:
  264. # Dictionary with different spatial variables used for topology builder.
  265. spatialdict = {"strds": "2D", "stvds": "2D", "str3ds": "3D"}
  266. tb.build(maplistA, maplistB, spatial=spatialdict[self.stdstype])
  267. else:
  268. tb.build(maplistA, maplistB)
  269. # Iterate through maps in maplistA and search for relationships given
  270. # in topolist.
  271. for map_i in maplistA:
  272. if assign_val:
  273. self.assign_bool_value(map_i, temporal_topo_list, spatial_topo_list)
  274. elif compare_bool:
  275. self.compare_bool_value(
  276. map_i, compop, aggregate, temporal_topo_list, spatial_topo_list
  277. )
  278. elif compare_cmd:
  279. self.compare_cmd_value(
  280. map_i,
  281. compop,
  282. aggregate,
  283. temporal_topo_list,
  284. spatial_topo_list,
  285. convert,
  286. )
  287. elif operator_cmd:
  288. self.operator_cmd_value(
  289. map_i, compop, temporal_topo_list, spatial_topo_list
  290. )
  291. temporal_relations = map_i.get_temporal_relations()
  292. spatial_relations = map_i.get_spatial_relations()
  293. for temporal_topology in temporal_topo_list:
  294. if temporal_topology.upper() in temporal_relations.keys():
  295. if (
  296. self._check_spatial_topology_entries(
  297. spatial_topo_list, spatial_relations
  298. )
  299. is True
  300. ):
  301. if count_map:
  302. relationmaplist = temporal_relations[
  303. temporal_topology.upper()
  304. ]
  305. gvar = GlobalTemporalVar()
  306. gvar.td = len(relationmaplist)
  307. if "map_value" in dir(map_i):
  308. map_i.map_value.append(gvar)
  309. else:
  310. map_i.map_value = gvar
  311. # Use unique identifier, since map names may be equal
  312. resultdict[map_i.uid] = map_i
  313. # map_i.print_info()
  314. resultlist = resultdict.values()
  315. # Sort list of maps chronological.
  316. resultlist = sorted(resultlist, key=AbstractDatasetComparisonKeyStartTime)
  317. return resultlist
  318. def build_command_string(self, map_i, relmap, operator=None, cmd_type=None):
  319. """This function build the r.mapcalc command string for conditionals,
  320. spatial variable combinations and boolean comparisons.
  321. For Example: 'if(a1 == 1, b1, c2)' or 'exist(a1) && sin(b1)'
  322. :param map_i: map object with temporal extent and built relations.
  323. :param relmap: map object with defined temporal relation to map_i.
  324. :param operator: String representing operator between two spatial variables
  325. (&&,||,+,-,*,/).
  326. :param cmd_type: map object with defined temporal relation to map_i:
  327. condition, conclusion or operator.
  328. :return: the resulting command string for conditionals or spatial variable
  329. combinations
  330. """
  331. def sub_cmdstring(map_i):
  332. """This function search for command string in a map object and
  333. return substitute string (contained commandstring or map name)"""
  334. if "cmd_list" in dir(map_i):
  335. map_sub = map_i.cmd_list
  336. elif (
  337. "map_value" in dir(map_i)
  338. and len(map_i.map_value) > 0
  339. and map_i.map_value[0].get_type() == "timediff"
  340. ):
  341. map_sub = map_i.map_value[0].get_type_value()[0]
  342. else:
  343. try:
  344. map_sub = map_i.get_id()
  345. except:
  346. map_sub = map_i
  347. return map_sub
  348. # Check for type of operation, conditional or spatial variable combination
  349. # and Create r.mapcalc expression string for the operation.
  350. cmdstring = ""
  351. if cmd_type == "condition":
  352. conditionsub = sub_cmdstring(map_i)
  353. conclusionsub = sub_cmdstring(relmap)
  354. cmdstring = "if(%s, %s)" % (conditionsub, conclusionsub)
  355. elif cmd_type == "conclusion":
  356. thensub = sub_cmdstring(map_i)
  357. elsesub = sub_cmdstring(relmap)
  358. cmdstring = "%s, %s" % (thensub, elsesub)
  359. elif cmd_type == "operator":
  360. leftsub = sub_cmdstring(map_i)
  361. rightsub = sub_cmdstring(relmap)
  362. if operator is None:
  363. self.msgr.fatal(
  364. "Error: Can't build command string for map %s, operator is missing"
  365. % (map_i.get_map_id())
  366. )
  367. cmdstring = "(%s %s %s)" % (leftsub, operator, rightsub)
  368. return cmdstring
  369. def compare_cmd_value(
  370. self,
  371. map_i,
  372. compop,
  373. aggregate,
  374. temporal_topo_list=["EQUAL"],
  375. spatial_topo_list=[],
  376. convert=False,
  377. ):
  378. """Function to evaluate two map lists with boolean values by boolean
  379. comparison operator.
  380. R = A && B
  381. R = if(A < 1 && B > 1, A, B)
  382. R = if(A < 1 {&&,equal|equivalent} B > 1, A, B)
  383. Extended temporal algebra version with command
  384. list builder for temporal raster algebra.
  385. :param map_i: Map object with temporal extent.
  386. :param temporal_relations: List of temporal relation to map_i.
  387. :param temporal_topo_list: List of strings for given temporal relations.
  388. :param compop: Comparison operator, && or ||.
  389. :param aggregate: Aggregation operator for relation map list, & or |.
  390. :param convert: Boolean if conditional values should be converted to
  391. r.mapcalc command strings.
  392. :return: Map object with conditional value that has been evaluated by
  393. comparison operators.
  394. """
  395. # Build command list list with elements from related maps and given relation operator.
  396. if convert and "condition_value" in dir(map_i):
  397. if map_i.condition_value != []:
  398. cmdstring = str(int(map_i.condition_value[0]))
  399. map_i.cmd_list = cmdstring
  400. if "cmd_list" in dir(map_i):
  401. leftcmd = map_i.cmd_list
  402. cmd_value_list = [leftcmd]
  403. count = 0
  404. temporal_relations = map_i.get_temporal_relations()
  405. for topo in temporal_topo_list:
  406. if topo.upper() in temporal_relations.keys():
  407. relationmaplist = temporal_relations[topo.upper()]
  408. if count == 0 and "cmd_list" in dir(map_i):
  409. cmd_value_list.append(compop)
  410. cmd_value_list.append("(")
  411. for relationmap in relationmaplist:
  412. if (
  413. self._check_spatial_topology_relation(
  414. spatial_topo_list, map_i, relationmap
  415. )
  416. is True
  417. ):
  418. if convert and "condition_value" in dir(relationmap):
  419. if relationmap.condition_value != []:
  420. cmdstring = str(int(relationmap.condition_value[0]))
  421. relationmap.cmd_list = cmdstring
  422. if "cmd_list" in dir(relationmap):
  423. if count > 0:
  424. cmd_value_list.append(aggregate + aggregate)
  425. cmd_value_list.append(relationmap.cmd_list)
  426. count = count + 1
  427. if self.debug:
  428. print(
  429. "compare_cmd_value",
  430. map_i.get_id(),
  431. relationmap.get_id(),
  432. relationmap.cmd_list,
  433. )
  434. if count > 0:
  435. cmd_value_list.append(")")
  436. cmd_value_str = "".join(map(str, cmd_value_list))
  437. # Add command list to result map.
  438. map_i.cmd_list = cmd_value_str
  439. print(cmd_value_str)
  440. return cmd_value_str
  441. def operator_cmd_value(
  442. self, map_i, operator, temporal_topo_list=["EQUAL"], spatial_topo_list=[]
  443. ):
  444. """Function to evaluate two map lists by given arithmetic operator.
  445. :param map_i: Map object with temporal extent.
  446. :param operator: Arithmetic operator, +-*/%.
  447. :param temporal_topo_list: List of strings for given temporal relations.
  448. :param spatial_topo_list: List of strings for given spatial relations.
  449. :return: Map object with command list with operators that has been
  450. evaluated by implicit aggregation.
  451. """
  452. temporal_relations = map_i.get_temporal_relations()
  453. spatial_relations = map_i.get_spatial_relations()
  454. # Build comandlist list with elements from related maps and given relation operator.
  455. leftcmd = map_i
  456. cmdstring = ""
  457. for topo in temporal_topo_list:
  458. if topo.upper() in temporal_relations.keys():
  459. relationmaplist = temporal_relations[topo.upper()]
  460. for relationmap in relationmaplist:
  461. if (
  462. self._check_spatial_topology_relation(
  463. spatial_topo_list, map_i, relationmap
  464. )
  465. is True
  466. ):
  467. # Create r.mapcalc expression string for the operation.
  468. cmdstring = self.build_command_string(
  469. leftcmd, relationmap, operator=operator, cmd_type="operator"
  470. )
  471. leftcmd = cmdstring
  472. if self.debug:
  473. print(
  474. "operator_cmd_value",
  475. map_i.get_id(),
  476. operator,
  477. relationmap.get_id(),
  478. )
  479. # Add command list to result map.
  480. map_i.cmd_list = cmdstring
  481. print("map command string", cmdstring)
  482. return cmdstring
  483. def set_temporal_extent_list(
  484. self,
  485. maplist,
  486. topolist=["EQUAL"],
  487. temporal="l",
  488. cmd_bool=False,
  489. cmd_type=None,
  490. operator=None,
  491. ):
  492. """Change temporal extent of map list based on temporal relations to
  493. other map list and given temporal operator.
  494. :param maplist: List of map objects for which relations has been build
  495. correctly.
  496. :param topolist: List of strings of temporal relations.
  497. :param temporal: The temporal operator specifying the temporal
  498. extent operation (intersection, union, disjoint
  499. union, right reference, left reference).
  500. :param cmd_bool: Boolean if command string should be merged for related maps.
  501. :param cmd_type: map object with defined temporal relation to map_i:
  502. condition, conclusion or operator.
  503. :param operator: String defining the type of operator.
  504. :return: Map list with specified temporal extent and optional command string.
  505. """
  506. resultdict = {}
  507. temporal_topo_list, spatial_topo_list = self._check_topology(topolist=topolist)
  508. for map_i in maplist:
  509. # Loop over temporal related maps and create overlay modules.
  510. tbrelations = map_i.get_temporal_relations()
  511. # Generate an intermediate map for the result map list.
  512. map_new = self.generate_new_map(
  513. base_map=map_i, bool_op="and", copy=True, rename=True
  514. )
  515. # Combine temporal and spatial extents of intermediate map with related maps.
  516. for topo in topolist:
  517. if topo in tbrelations.keys():
  518. for map_j in tbrelations[topo]:
  519. if (
  520. self._check_spatial_topology_relation(
  521. spatial_topo_list, map_i, map_j
  522. )
  523. is True
  524. ):
  525. if temporal == "r":
  526. # Generate an intermediate map for the result map list.
  527. map_new = self.generate_new_map(
  528. base_map=map_i,
  529. bool_op="and",
  530. copy=True,
  531. rename=True,
  532. )
  533. # Create overlaid map extent.
  534. returncode = self.overlay_map_extent(
  535. map_new, map_j, "and", temp_op=temporal
  536. )
  537. # Stop the loop if no temporal or spatial relationship exist.
  538. if returncode == 0:
  539. break
  540. # Append map to result map list.
  541. elif returncode == 1:
  542. # print(map_new.cmd_list)
  543. # resultlist.append(map_new)
  544. if cmd_bool:
  545. # Create r.mapcalc expression string for the operation.
  546. cmdstring = self.build_command_string(
  547. map_i,
  548. map_j,
  549. operator=operator,
  550. cmd_type=cmd_type,
  551. )
  552. # Conditional append of module command.
  553. map_new.cmd_list = cmdstring
  554. # Write map object to result dictionary.
  555. resultdict[map_new.uid] = map_new
  556. if returncode == 0:
  557. break
  558. # Append map to result map list.
  559. # if returncode == 1:
  560. # resultlist.append(map_new)
  561. # Get sorted map objects as values from result dictionary.
  562. resultlist = resultdict.values()
  563. resultlist = sorted(resultlist, key=AbstractDatasetComparisonKeyStartTime)
  564. return resultlist
  565. def build_condition_cmd_list(
  566. self,
  567. iflist,
  568. thenlist,
  569. elselist=None,
  570. condition_topolist=["EQUAL"],
  571. conclusion_topolist=["EQUAL"],
  572. temporal="l",
  573. null=False,
  574. ):
  575. """This function build the r.mapcalc command strings for spatial conditionals.
  576. For Example: 'if(a1 == 1, b1, c2)'
  577. :param iflist: Map list with temporal extents and command list.
  578. :param thenlist: Map list with temporal extents and command list or numeric string.
  579. :param elselist: Map list with temporal extents and command list or numeric string.
  580. :param condition_topolist: List of strings for given temporal relations between
  581. conditions and conclusions.
  582. :param conclusion_topolist: List of strings for given temporal relations between
  583. conditions (then and else).
  584. :param temporal: The temporal operator specifying the temporal
  585. extent operation (intersection, union, disjoint
  586. union, right reference, left reference).
  587. :param null: Boolean if null map support should be activated.
  588. :return: map list with resulting command string for given condition type.
  589. """
  590. resultlist = []
  591. # First merge conclusion command maplists or strings.
  592. # Check if alternative conclusion map list is given.
  593. if all([isinstance(thenlist, list), isinstance(elselist, list)]):
  594. # Build conclusion command map list.
  595. conclusiontopolist = self.build_spatio_temporal_topology_list(
  596. thenlist, elselist, conclusion_topolist
  597. )
  598. conclusionlist = self.set_temporal_extent_list(
  599. conclusiontopolist,
  600. topolist=conclusion_topolist,
  601. temporal=temporal,
  602. cmd_bool=True,
  603. cmd_type="conclusion",
  604. )
  605. # Check if any conclusion is a numeric statements.
  606. elif any([isinstance(thenlist, str), isinstance(elselist, str)]):
  607. conclusionlist = []
  608. # Check if only alternative conclusion is a numeric statements.
  609. if all([isinstance(thenlist, list), isinstance(elselist, str)]):
  610. listinput = thenlist
  611. numinput = elselist
  612. for map_i in listinput:
  613. # Create r.mapcalc expression string for the operation.
  614. cmdstring = self.build_command_string(
  615. map_i, numinput, cmd_type="conclusion"
  616. )
  617. # Conditional append of module command.
  618. map_i.cmd_list = cmdstring
  619. # Append map to result map list.
  620. conclusionlist.append(map_i)
  621. # Check if only direct conclusion is a numeric statements.
  622. elif all([isinstance(thenlist, str), isinstance(elselist, list)]):
  623. listinput = elselist
  624. numinput = thenlist
  625. for map_i in listinput:
  626. # Create r.mapcalc expression string for the operation.
  627. cmdstring = self.build_command_string(
  628. numinput, map_i, cmd_type="conclusion"
  629. )
  630. # Conditional append of module command.
  631. map_i.cmd_list = cmdstring
  632. # Append map to result map list.
  633. conclusionlist.append(map_i)
  634. elif all([isinstance(thenlist, str), isinstance(elselist, str)]):
  635. conclusionlist = thenlist + "," + elselist
  636. else:
  637. # The direct conclusion is used.
  638. conclusionlist = thenlist
  639. # Use the conclusion map or string to merge it with the condition and
  640. # return maplist.
  641. if isinstance(conclusionlist, str):
  642. resultlist = []
  643. for map_i in iflist:
  644. # Create r.mapcalc expression string for the operation.
  645. cmdstring = self.build_command_string(
  646. map_i, conclusionlist, cmd_type="condition"
  647. )
  648. # Conditional append of module command.
  649. map_i.cmd_list = cmdstring
  650. # Append map to result map list.
  651. resultlist.append(map_i)
  652. return resultlist
  653. elif isinstance(conclusionlist, list):
  654. # Build result command map list between conditions and conclusions.
  655. print("build_condition_cmd_list", condition_topolist)
  656. conditiontopolist = self.build_spatio_temporal_topology_list(
  657. iflist, conclusionlist, topolist=condition_topolist
  658. )
  659. resultlist = self.set_temporal_extent_list(
  660. conditiontopolist,
  661. topolist=condition_topolist,
  662. temporal="r",
  663. cmd_bool=True,
  664. cmd_type="condition",
  665. )
  666. return resultlist
  667. def p_statement_assign(self, t):
  668. # This function executes the processing of raster/raster3d algebra
  669. # that was build based on the expression
  670. """
  671. statement : stds EQUALS expr
  672. """
  673. if self.run:
  674. # Create the process queue for parallel mapcalc processing
  675. if self.dry_run is False:
  676. process_queue = pymod.ParallelModuleQueue(int(self.nprocs))
  677. if isinstance(t[3], list):
  678. granularity = None
  679. if len(t[3]) > 0 and self.time_suffix == "gran":
  680. map_i = t[3][0]
  681. if map_i.is_time_absolute() is True:
  682. granularity = compute_absolute_time_granularity(t[3])
  683. # The first loop is to check if the raster maps exists in the database
  684. # Compute the size of the numerical suffix
  685. num = len(t[3])
  686. register_list = []
  687. leadzero = len(str(num))
  688. for i in range(num):
  689. map_i = t[3][i]
  690. # Create new map with basename
  691. newident = create_numeric_suffix(
  692. self.basename, i, "%0" + str(leadzero)
  693. )
  694. if (
  695. map_i.is_time_absolute() is True
  696. and self.time_suffix
  697. and granularity is not None
  698. and self.time_suffix == "gran"
  699. ):
  700. suffix = create_suffix_from_datetime(
  701. map_i.temporal_extent.get_start_time(), granularity
  702. )
  703. newident = "{ba}_{su}".format(ba=self.basename, su=suffix)
  704. # If set use the time suffix to create the map name
  705. elif (
  706. map_i.is_time_absolute() is True
  707. and self.time_suffix
  708. and self.time_suffix == "time"
  709. ):
  710. suffix = create_time_suffix(map_i)
  711. newident = "{ba}_{su}".format(ba=self.basename, su=suffix)
  712. # Check if resultmap names exist in GRASS database.
  713. newident = newident + "@" + self.mapset
  714. if self.stdstype == "strds":
  715. new_map = RasterDataset(newident)
  716. else:
  717. new_map = Raster3DDataset(newident)
  718. if new_map.map_exists() and self.overwrite is False:
  719. self.msgr.fatal(
  720. "Error maps with basename %s exist. "
  721. "Use --o flag to overwrite existing file" % newident
  722. )
  723. # The second loop creates the resulting raster maps
  724. count = 0
  725. map_test_list = []
  726. for map_i in t[3]:
  727. # Create new map with basename
  728. newident = create_numeric_suffix(
  729. self.basename, count, "%0" + str(leadzero)
  730. )
  731. if (
  732. map_i.is_time_absolute() is True
  733. and self.time_suffix
  734. and granularity is not None
  735. and self.time_suffix == "gran"
  736. ):
  737. suffix = create_suffix_from_datetime(
  738. map_i.temporal_extent.get_start_time(), granularity
  739. )
  740. newident = "{ba}_{su}".format(ba=self.basename, su=suffix)
  741. # If set use the time suffix to create the map name
  742. elif (
  743. map_i.is_time_absolute() is True
  744. and self.time_suffix
  745. and self.time_suffix == "time"
  746. ):
  747. suffix = create_time_suffix(map_i)
  748. newident = "{ba}_{su}".format(ba=self.basename, su=suffix)
  749. if "cmd_list" in dir(map_i):
  750. # Build r.mapcalc module and execute expression.
  751. # Change map name to given basename.
  752. # Create deepcopy of r.mapcalc module.
  753. new_map = map_i.get_new_instance(newident + "@" + self.mapset)
  754. new_map.set_temporal_extent(map_i.get_temporal_extent())
  755. new_map.set_spatial_extent(map_i.get_spatial_extent())
  756. map_test_list.append(new_map)
  757. m = copy.deepcopy(self.m_mapcalc)
  758. m_expression = newident + "=" + map_i.cmd_list
  759. m.inputs["expression"].value = str(m_expression)
  760. m.flags["overwrite"].value = self.overwrite
  761. if self.debug:
  762. print(m.get_bash())
  763. self.process_chain_dict["processes"].append(m.get_dict())
  764. if self.dry_run is False:
  765. process_queue.put(m)
  766. elif map_i.map_exists():
  767. # Copy map if it exists b = a
  768. new_map = map_i.get_new_instance(newident + "@" + self.mapset)
  769. new_map.set_temporal_extent(map_i.get_temporal_extent())
  770. new_map.set_spatial_extent(map_i.get_spatial_extent())
  771. map_test_list.append(new_map)
  772. m = copy.deepcopy(self.m_mapcalc)
  773. m_expression = newident + "=" + map_i.get_map_id()
  774. m.inputs["expression"].value = str(m_expression)
  775. m.flags["overwrite"].value = self.overwrite
  776. if self.debug:
  777. print(m.get_bash())
  778. self.process_chain_dict["processes"].append(m.get_dict())
  779. if self.dry_run is False:
  780. process_queue.put(m)
  781. else:
  782. self.msgr.error(_("Error computing map <%s>" % map_i.get_id()))
  783. count += 1
  784. if self.dry_run is False:
  785. process_queue.wait()
  786. for map_i in map_test_list:
  787. register_list.append(map_i)
  788. # Open connection to temporal database.
  789. dbif, unused = init_dbif(self.dbif)
  790. # Create result space time dataset.
  791. if self.dry_run is False:
  792. resultstds = open_new_stds(
  793. t[1],
  794. self.stdstype,
  795. "absolute",
  796. t[1],
  797. t[1],
  798. "mean",
  799. self.dbif,
  800. overwrite=self.overwrite,
  801. )
  802. for map_i in register_list:
  803. # Put the map into the process dictionary
  804. start, end = map_i.get_temporal_extent_as_tuple()
  805. self.process_chain_dict["register"].append(
  806. (map_i.get_name(), str(start), str(end))
  807. )
  808. if self.dry_run is False:
  809. # Get meta data from grass database.
  810. map_i.load()
  811. # Do not register empty maps if not required
  812. # In case of a null map continue, do not register null maps
  813. if (
  814. map_i.metadata.get_min() is None
  815. and map_i.metadata.get_max() is None
  816. ):
  817. if not self.register_null:
  818. self.removable_maps[map_i.get_name()] = map_i
  819. continue
  820. if map_i.is_in_db(dbif) and self.overwrite:
  821. # Update map in temporal database.
  822. if self.dry_run is False:
  823. map_i.update_all(dbif)
  824. elif map_i.is_in_db(dbif) and self.overwrite is False:
  825. # Raise error if map exists and no overwrite flag is given.
  826. self.msgr.fatal(
  827. "Error raster map %s exist in temporal database. "
  828. "Use overwrite flag." % map_i.get_map_id()
  829. )
  830. else:
  831. # Insert map into temporal database.
  832. if self.dry_run is False:
  833. map_i.insert(dbif)
  834. # Register map in result space time dataset.
  835. if self.dry_run is False:
  836. success = resultstds.register_map(map_i, dbif)
  837. if self.dry_run is False:
  838. resultstds.update_from_registered_maps(dbif)
  839. self.process_chain_dict["STDS"]["name"] = t[1]
  840. self.process_chain_dict["STDS"]["stdstype"] = self.stdstype
  841. self.process_chain_dict["STDS"]["temporal_type"] = "absolute"
  842. dbif.close()
  843. t[0] = register_list
  844. # Remove intermediate maps
  845. self.remove_maps()
  846. def p_expr_spmap_function(self, t):
  847. # Add a single map.
  848. # Only the spatial extent of the map is evaluated.
  849. # Temporal extent is not existing.
  850. # Examples:
  851. # R = map(A)
  852. """
  853. mapexpr : MAP LPAREN stds RPAREN
  854. """
  855. if self.run:
  856. # Check input map.
  857. input = t[3]
  858. if not isinstance(input, list):
  859. # Check for mapset in given stds input.
  860. if input.find("@") >= 0:
  861. id_input = input
  862. else:
  863. id_input = input + "@" + self.mapset
  864. # Create empty map dataset.
  865. map_i = dataset_factory(self.maptype, id_input)
  866. # Check for occurrence of space time dataset.
  867. if map_i.map_exists() is False:
  868. raise FatalError(
  869. _("%s map <%s> not found in GRASS spatial database")
  870. % (map_i.get_type(), id_input)
  871. )
  872. else:
  873. # Select dataset entry from database.
  874. map_i.select(dbif=self.dbif)
  875. # Create command list for map object.
  876. cmdstring = "(%s)" % (map_i.get_map_id())
  877. map_i.cmd_list = cmdstring
  878. # Return map object.
  879. t[0] = cmdstring
  880. else:
  881. t[0] = "map(" + t[3] + ")"
  882. if self.debug:
  883. print("map(" + t[3] + ")")
  884. def p_arith1_operation(self, t):
  885. # A % B
  886. # A / B
  887. # A * B
  888. # A % td(B)
  889. # A * td(B)
  890. # A / td(B)
  891. """
  892. expr : stds MOD stds
  893. | expr MOD stds
  894. | stds MOD expr
  895. | expr MOD expr
  896. | stds DIV stds
  897. | expr DIV stds
  898. | stds DIV expr
  899. | expr DIV expr
  900. | stds MULT stds
  901. | expr MULT stds
  902. | stds MULT expr
  903. | expr MULT expr
  904. | stds MOD t_td_var
  905. | expr MOD t_td_var
  906. | stds DIV t_td_var
  907. | expr DIV t_td_var
  908. | stds MULT t_td_var
  909. | expr MULT t_td_var
  910. """
  911. # Check input stds.
  912. maplistA = self.check_stds(t[1])
  913. maplistB = self.check_stds(t[3])
  914. topolist = self.build_spatio_temporal_topology_list(maplistA, maplistB)
  915. if self.run:
  916. resultlist = []
  917. for map_i in topolist:
  918. # Generate an intermediate map for the result map list.
  919. map_new = self.generate_new_map(
  920. base_map=map_i, bool_op="and", copy=True
  921. )
  922. # Loop over temporal related maps and create overlay modules.
  923. tbrelations = map_i.get_temporal_relations()
  924. count = 0
  925. for map_j in tbrelations["EQUAL"]:
  926. # Create overlaid map extent.
  927. returncode = self.overlay_map_extent(
  928. map_new, map_j, "and", temp_op="l"
  929. )
  930. # Stop the loop if no temporal or spatial relationship exist.
  931. if returncode == 0:
  932. break
  933. if count == 0:
  934. # Set map name.
  935. name = map_new.get_id()
  936. else:
  937. # Generate an intermediate map
  938. name = self.generate_map_name()
  939. # Create r.mapcalc expression string for the operation.
  940. cmdstring = self.build_command_string(
  941. map_i, map_j, operator=t[2], cmd_type="operator"
  942. )
  943. # Conditional append of module command.
  944. map_new.cmd_list = cmdstring
  945. count += 1
  946. # Append map to result map list.
  947. if returncode == 1:
  948. resultlist.append(map_new)
  949. t[0] = resultlist
  950. if self.debug:
  951. for map in resultlist:
  952. print(map.cmd_list)
  953. def p_arith1_operation_numeric1(self, t):
  954. # A % 1
  955. # A / 4
  956. # A * 5
  957. # A % map(b1)
  958. # A * map(b2)
  959. # A / map(b3)
  960. """
  961. expr : stds MOD number
  962. | expr MOD number
  963. | stds DIV number
  964. | expr DIV number
  965. | stds MULT number
  966. | expr MULT number
  967. | stds MOD numberstr
  968. | expr MOD numberstr
  969. | stds DIV numberstr
  970. | expr DIV numberstr
  971. | stds MULT numberstr
  972. | expr MULT numberstr
  973. | stds MOD mapexpr
  974. | expr MOD mapexpr
  975. | stds DIV mapexpr
  976. | expr DIV mapexpr
  977. | stds MULT mapexpr
  978. | expr MULT mapexpr
  979. """
  980. # Check input stds.
  981. maplist = self.check_stds(t[1])
  982. if self.run:
  983. resultlist = []
  984. for map_i in maplist:
  985. mapinput = map_i.get_id()
  986. # Create r.mapcalc expression string for the operation.
  987. if "cmd_list" in dir(map_i):
  988. cmdstring = "(%s %s %s)" % (map_i.cmd_list, t[2], t[3])
  989. else:
  990. cmdstring = "(%s %s %s)" % (mapinput, t[2], t[3])
  991. # Conditional append of module command.
  992. map_i.cmd_list = cmdstring
  993. # Append map to result map list.
  994. resultlist.append(map_i)
  995. t[0] = resultlist
  996. if self.debug:
  997. for map in resultlist:
  998. print(map.cmd_list)
  999. def p_arith1_operation_numeric2(self, t):
  1000. # 1 % A
  1001. # 4 / A
  1002. # 5 * A
  1003. # map(b1) % A
  1004. # map(b4) / A
  1005. # map(b5) * A
  1006. """
  1007. expr : number MOD stds
  1008. | number MOD expr
  1009. | number DIV stds
  1010. | number DIV expr
  1011. | number MULT stds
  1012. | number MULT expr
  1013. | numberstr MOD stds
  1014. | numberstr MOD expr
  1015. | numberstr DIV stds
  1016. | numberstr DIV expr
  1017. | numberstr MULT stds
  1018. | numberstr MULT expr
  1019. | mapexpr MOD stds
  1020. | mapexpr MOD expr
  1021. | mapexpr DIV stds
  1022. | mapexpr DIV expr
  1023. | mapexpr MULT stds
  1024. | mapexpr MULT expr
  1025. """
  1026. # Check input stds.
  1027. maplist = self.check_stds(t[3])
  1028. if self.run:
  1029. resultlist = []
  1030. for map_i in maplist:
  1031. mapinput = map_i.get_id()
  1032. # Create r.mapcalc expression string for the operation.
  1033. if "cmd_list" in dir(map_i):
  1034. cmdstring = "(%s %s %s)" % (t[1], t[2], map_i.cmd_list)
  1035. else:
  1036. cmdstring = "(%s %s %s)" % (t[1], t[2], mapinput)
  1037. # Conditional append of module command.
  1038. map_i.cmd_list = cmdstring
  1039. # Append map to result map list.
  1040. resultlist.append(map_i)
  1041. t[0] = resultlist
  1042. if self.debug:
  1043. for map in resultlist:
  1044. print(map.cmd_list)
  1045. def p_arith2_operation(self, t):
  1046. # A + B
  1047. # A - B
  1048. # A + td(B)
  1049. # A - td(B)
  1050. """
  1051. expr : stds ADD stds
  1052. | expr ADD stds
  1053. | stds ADD expr
  1054. | expr ADD expr
  1055. | stds SUB stds
  1056. | expr SUB stds
  1057. | stds SUB expr
  1058. | expr SUB expr
  1059. | stds ADD t_td_var
  1060. | expr ADD t_td_var
  1061. | expr SUB t_td_var
  1062. | stds SUB t_td_var
  1063. """
  1064. # Check input stds.
  1065. maplistA = self.check_stds(t[1])
  1066. maplistB = self.check_stds(t[3])
  1067. topolist = self.build_spatio_temporal_topology_list(maplistA, maplistB)
  1068. if self.run:
  1069. resultlist = []
  1070. for map_i in topolist:
  1071. # Generate an intermediate map for the result map list.
  1072. map_new = self.generate_new_map(
  1073. base_map=map_i, bool_op="and", copy=True
  1074. )
  1075. # Loop over temporal related maps and create overlay modules.
  1076. tbrelations = map_i.get_temporal_relations()
  1077. count = 0
  1078. for map_j in tbrelations["EQUAL"]:
  1079. # Create overlaid map extent.
  1080. returncode = self.overlay_map_extent(
  1081. map_new, map_j, "and", temp_op="l"
  1082. )
  1083. # Stop the loop if no temporal or spatial relationship exist.
  1084. if returncode == 0:
  1085. break
  1086. if count == 0:
  1087. # Set map name.
  1088. name = map_new.get_id()
  1089. else:
  1090. # Generate an intermediate map
  1091. name = self.generate_map_name()
  1092. # Create r.mapcalc expression string for the operation.
  1093. cmdstring = self.build_command_string(
  1094. map_i, map_j, operator=t[2], cmd_type="operator"
  1095. )
  1096. # Conditional append of module command.
  1097. map_new.cmd_list = cmdstring
  1098. count += 1
  1099. # Append map to result map list.
  1100. if returncode == 1:
  1101. resultlist.append(map_new)
  1102. t[0] = resultlist
  1103. if self.debug:
  1104. for map in resultlist:
  1105. print(map.cmd_list)
  1106. def p_arith2_operation_numeric1(self, t):
  1107. # A + 2
  1108. # A - 3
  1109. # A + map(b4)
  1110. # A - map(b5)
  1111. """
  1112. expr : stds ADD number
  1113. | expr ADD number
  1114. | stds SUB number
  1115. | expr SUB number
  1116. | stds ADD numberstr
  1117. | expr ADD numberstr
  1118. | stds SUB numberstr
  1119. | expr SUB numberstr
  1120. | stds ADD mapexpr
  1121. | expr ADD mapexpr
  1122. | stds SUB mapexpr
  1123. | expr SUB mapexpr
  1124. """
  1125. # Check input stds.
  1126. maplist = self.check_stds(t[1])
  1127. if self.run:
  1128. resultlist = []
  1129. for map_i in maplist:
  1130. mapinput = map_i.get_id()
  1131. # Create r.mapcalc expression string for the operation.
  1132. if "cmd_list" in dir(map_i):
  1133. cmdstring = "(%s %s %s)" % (map_i.cmd_list, t[2], t[3])
  1134. else:
  1135. cmdstring = "(%s %s %s)" % (mapinput, t[2], t[3])
  1136. # Conditional append of module command.
  1137. map_i.cmd_list = cmdstring
  1138. # Append map to result map list.
  1139. resultlist.append(map_i)
  1140. t[0] = resultlist
  1141. if self.debug:
  1142. for map in resultlist:
  1143. print(map.cmd_list)
  1144. def p_arith2_operation_numeric2(self, t):
  1145. # 2 + A
  1146. # 3 - A
  1147. # map(b2) + A
  1148. # map(b3) - A
  1149. """
  1150. expr : number ADD stds
  1151. | number ADD expr
  1152. | number SUB stds
  1153. | number SUB expr
  1154. | numberstr ADD stds
  1155. | numberstr ADD expr
  1156. | numberstr SUB stds
  1157. | numberstr SUB expr
  1158. | mapexpr ADD stds
  1159. | mapexpr ADD expr
  1160. | mapexpr SUB stds
  1161. | mapexpr SUB expr
  1162. """
  1163. # Check input stds.
  1164. maplist = self.check_stds(t[3])
  1165. if self.run:
  1166. resultlist = []
  1167. for map_i in maplist:
  1168. mapinput = map_i.get_id()
  1169. # Create r.mapcalc expression string for the operation.
  1170. if "cmd_list" in dir(map_i):
  1171. cmdstring = "(%s %s %s)" % (t[1], t[2], map_i.cmd_list)
  1172. else:
  1173. cmdstring = "(%s %s %s)" % (t[1], t[2], mapinput)
  1174. # Conditional append of module command.
  1175. map_i.cmd_list = cmdstring
  1176. # Append map to result map list.
  1177. resultlist.append(map_i)
  1178. t[0] = resultlist
  1179. if self.debug:
  1180. for map in resultlist:
  1181. print(map.cmd_list)
  1182. def p_arith1_operation_relation(self, t):
  1183. # A {*, equal, l} B
  1184. # A {*, equal, l} td(B)
  1185. # A {*, equal, l} B {/, during, r} C
  1186. # A {*, equal, l} B {/, equal, l} C {/, during, r} D
  1187. """
  1188. expr : stds T_ARITH1_OPERATOR stds
  1189. | expr T_ARITH1_OPERATOR stds
  1190. | stds T_ARITH1_OPERATOR expr
  1191. | expr T_ARITH1_OPERATOR expr
  1192. | stds T_ARITH1_OPERATOR t_td_var
  1193. | expr T_ARITH1_OPERATOR t_td_var
  1194. """
  1195. if self.run:
  1196. # Check input stds.
  1197. maplistA = self.check_stds(t[1])
  1198. maplistB = self.check_stds(t[3])
  1199. relations, temporal, function, aggregate = self.eval_toperator(
  1200. t[2], optype="raster"
  1201. )
  1202. # Build conditional values based on topological relationships.
  1203. complist = self.build_spatio_temporal_topology_list(
  1204. maplistA,
  1205. maplistB,
  1206. topolist=relations,
  1207. operator_cmd=True,
  1208. compop=function,
  1209. )
  1210. # Set temporal extent based on topological relationships.
  1211. resultlist = self.set_temporal_extent_list(
  1212. complist, topolist=relations, temporal=temporal
  1213. )
  1214. t[0] = resultlist
  1215. if self.debug:
  1216. for map in resultlist:
  1217. print(map.cmd_list)
  1218. def p_arith2_operation_relation(self, t):
  1219. # A {+, equal, l} B
  1220. # A {+, equal, l} td(b)
  1221. # A {+, equal, l} B {-, during, r} C
  1222. # A {+, equal, l} B {+, equal, l} C {-, during, r} D
  1223. """
  1224. expr : stds T_ARITH2_OPERATOR stds
  1225. | expr T_ARITH2_OPERATOR stds
  1226. | stds T_ARITH2_OPERATOR expr
  1227. | expr T_ARITH2_OPERATOR expr
  1228. | stds T_ARITH2_OPERATOR t_td_var
  1229. | expr T_ARITH2_OPERATOR t_td_var
  1230. """
  1231. if self.run:
  1232. # Check input stds.
  1233. maplistA = self.check_stds(t[1])
  1234. maplistB = self.check_stds(t[3])
  1235. relations, temporal, function, aggregate = self.eval_toperator(
  1236. t[2], optype="raster"
  1237. )
  1238. # Build conditional values based on topological relationships.
  1239. complist = self.build_spatio_temporal_topology_list(
  1240. maplistA,
  1241. maplistB,
  1242. topolist=relations,
  1243. operator_cmd=True,
  1244. compop=function,
  1245. )
  1246. # Set temporal extent based on topological relationships.
  1247. resultlist = self.set_temporal_extent_list(
  1248. complist, topolist=relations, temporal=temporal
  1249. )
  1250. t[0] = resultlist
  1251. if self.debug:
  1252. for map in resultlist:
  1253. print(map.cmd_list)
  1254. def p_arith_operation_numeric_string(self, t):
  1255. # 1 + 1
  1256. # 1 - 1
  1257. # 1 * 1
  1258. # 1 / 1
  1259. # 1 % 1
  1260. """
  1261. numberstr : number ADD number
  1262. | number SUB number
  1263. | number DIV number
  1264. | number MULT number
  1265. | number MOD number
  1266. """
  1267. numstring = "(%s %s %s)" % (t[1], t[2], t[3])
  1268. t[0] = numstring
  1269. if self.debug:
  1270. print(numstring)
  1271. def p_mapcalc_function(self, t):
  1272. # Supported mapcalc functions.
  1273. """
  1274. mapcalc_arith : ABS
  1275. | LOG
  1276. | SQRT
  1277. | EXP
  1278. | COS
  1279. | ACOS
  1280. | SIN
  1281. | ASIN
  1282. | TAN
  1283. | DOUBLE
  1284. | FLOATEXP
  1285. | INTEXP
  1286. """
  1287. t[0] = t[1]
  1288. if self.debug:
  1289. print(t[1])
  1290. def p_mapcalc_operation1(self, t):
  1291. # sin(A)
  1292. # log(B)
  1293. """
  1294. expr : mapcalc_arith LPAREN stds RPAREN
  1295. | mapcalc_arith LPAREN expr RPAREN
  1296. """
  1297. # Check input stds.
  1298. maplist = self.check_stds(t[3])
  1299. if self.run:
  1300. resultlist = []
  1301. for map_i in maplist:
  1302. # Create r.mapcalc expression string for the operation.
  1303. if "cmd_list" in dir(map_i):
  1304. cmdstring = "%s(%s)" % (t[1].lower(), map_i.cmd_list)
  1305. else:
  1306. cmdstring = "%s(%s)" % (t[1].lower(), map_i.get_id())
  1307. # Set new command list for map.
  1308. map_i.cmd_list = cmdstring
  1309. # Append map with updated command list to result list.
  1310. resultlist.append(map_i)
  1311. t[0] = resultlist
  1312. if self.debug:
  1313. for map in resultlist:
  1314. print(map.cmd_list)
  1315. def p_mapexpr_operation(self, t):
  1316. # sin(map(a))
  1317. """
  1318. mapexpr : mapcalc_arith LPAREN mapexpr RPAREN
  1319. """
  1320. # Check input stds.
  1321. mapstring = t[3]
  1322. if self.run:
  1323. cmdstring = "%s(%s)" % (t[1].lower(), mapstring)
  1324. t[0] = cmdstring
  1325. if self.debug:
  1326. print(mapstring)
  1327. def p_s_var_expr_1(self, t):
  1328. # isnull(A)
  1329. """
  1330. s_var_expr : ISNULL LPAREN stds RPAREN
  1331. | ISNULL LPAREN expr RPAREN
  1332. """
  1333. # Check input stds.
  1334. maplist = self.check_stds(t[3])
  1335. if self.run:
  1336. resultlist = []
  1337. for map_i in maplist:
  1338. # Create r.mapcalc expression string for the operation.
  1339. if "cmd_list" in dir(map_i):
  1340. cmdstring = "%s(%s)" % (t[1].lower(), map_i.cmd_list)
  1341. else:
  1342. cmdstring = "%s(%s)" % (t[1].lower(), map_i.get_id())
  1343. # Set new command list for map.
  1344. map_i.cmd_list = cmdstring
  1345. # Append map with updated command list to result list.
  1346. resultlist.append(map_i)
  1347. t[0] = resultlist
  1348. if self.debug:
  1349. for map in resultlist:
  1350. print(map.cmd_list)
  1351. def p_s_var_expr_2(self, t):
  1352. # isntnull(A)
  1353. """
  1354. s_var_expr : ISNTNULL LPAREN stds RPAREN
  1355. | ISNTNULL LPAREN expr RPAREN
  1356. """
  1357. # Check input stds.
  1358. maplist = self.check_stds(t[3])
  1359. if self.run:
  1360. resultlist = []
  1361. for map_i in maplist:
  1362. # Create r.mapcalc expression string for the operation.
  1363. if "cmd_list" in dir(map_i):
  1364. cmdstring = "!isnull(%s)" % (map_i.cmd_list)
  1365. else:
  1366. cmdstring = "!isnull(%s)" % (map_i.get_id())
  1367. # Set new command list for map.
  1368. map_i.cmd_list = cmdstring
  1369. # Append map with updated command list to result list.
  1370. resultlist.append(map_i)
  1371. t[0] = resultlist
  1372. if self.debug:
  1373. for map in resultlist:
  1374. print(map.cmd_list)
  1375. def p_s_var_expr_3(self, t):
  1376. # A <= 2
  1377. """
  1378. s_var_expr : stds comp_op number
  1379. | expr comp_op number
  1380. """
  1381. # Check input stds.
  1382. maplist = self.check_stds(t[1])
  1383. if self.run:
  1384. resultlist = []
  1385. for map_i in maplist:
  1386. # Create r.mapcalc expression string for the operation.
  1387. if "cmd_list" in dir(map_i):
  1388. cmdstring = "%s %s %s" % (map_i.cmd_list, t[2], t[3])
  1389. else:
  1390. cmdstring = "%s %s %s" % (map_i.get_id(), t[2], t[3])
  1391. # Set new command list for map.
  1392. map_i.cmd_list = cmdstring
  1393. # Append map with updated command list to result list.
  1394. resultlist.append(map_i)
  1395. t[0] = resultlist
  1396. if self.debug:
  1397. for map in resultlist:
  1398. print(map.cmd_list)
  1399. def p_s_var_expr_4(self, t):
  1400. # exist(B)
  1401. """
  1402. s_var_expr : EXIST LPAREN stds RPAREN
  1403. | EXIST LPAREN expr RPAREN
  1404. """
  1405. # Check input stds.
  1406. maplist = self.check_stds(t[3])
  1407. if self.run:
  1408. resultlist = []
  1409. for map_i in maplist:
  1410. # Create r.mapcalc expression string for the operation.
  1411. if "cmd_list" in dir(map_i):
  1412. cmdstring = "%s" % (map_i.cmd_list)
  1413. else:
  1414. cmdstring = "%s" % (map_i.get_id())
  1415. # Set new command list for map.
  1416. map_i.cmd_list = cmdstring
  1417. # Append map with updated command list to result list.
  1418. resultlist.append(map_i)
  1419. t[0] = resultlist
  1420. if self.debug:
  1421. for map in resultlist:
  1422. print(map.cmd_list)
  1423. def p_s_var_expr_comp(self, t):
  1424. # A <= 2 || B == 10
  1425. # A < 3 && A > 1
  1426. """
  1427. s_var_expr : s_var_expr AND AND s_var_expr
  1428. | s_var_expr OR OR s_var_expr
  1429. """
  1430. if self.run:
  1431. # Check input stds.
  1432. s_var_exprA = self.check_stds(t[1])
  1433. s_var_exprB = self.check_stds(t[4])
  1434. relations = ["EQUAL"]
  1435. temporal = "l"
  1436. function = t[2] + t[3]
  1437. aggregate = t[2]
  1438. # Build conditional values based on topological relationships.
  1439. complist = self.build_spatio_temporal_topology_list(
  1440. s_var_exprA,
  1441. s_var_exprB,
  1442. topolist=relations,
  1443. compare_cmd=True,
  1444. compop=function,
  1445. aggregate=aggregate,
  1446. )
  1447. # Set temporal extent based on topological relationships.
  1448. resultlist = self.set_temporal_extent_list(
  1449. complist, topolist=relations, temporal=temporal
  1450. )
  1451. t[0] = resultlist
  1452. if self.debug:
  1453. for map in resultlist:
  1454. print(map.cmd_list)
  1455. def p_s_var_expr_comp_op(self, t):
  1456. # A <= 2 {||} B == 10
  1457. # A < 3 {&&, equal} A > 1
  1458. """
  1459. s_var_expr : s_var_expr T_COMP_OPERATOR s_var_expr
  1460. """
  1461. if self.run:
  1462. # Check input stds.
  1463. s_var_exprA = self.check_stds(t[1])
  1464. s_var_exprB = self.check_stds(t[3])
  1465. # Evaluate temporal comparison operator.
  1466. relations, temporal, function, aggregate = self.eval_toperator(
  1467. t[2], optype="boolean"
  1468. )
  1469. # Build conditional values based on topological relationships.
  1470. complist = self.build_spatio_temporal_topology_list(
  1471. s_var_exprA,
  1472. s_var_exprB,
  1473. topolist=relations,
  1474. compare_cmd=True,
  1475. compop=function,
  1476. aggregate=aggregate,
  1477. )
  1478. # Set temporal extent based on topological relationships.
  1479. resultlist = self.set_temporal_extent_list(
  1480. complist, topolist=relations, temporal=temporal
  1481. )
  1482. t[0] = resultlist
  1483. if self.debug:
  1484. for map in resultlist:
  1485. print(map.cmd_list)
  1486. def p_s_expr_condition_if(self, t):
  1487. # if(s_var_expr, B)
  1488. # if(A == 1, B)
  1489. """
  1490. expr : IF LPAREN s_var_expr COMMA stds RPAREN
  1491. | IF LPAREN s_var_expr COMMA expr RPAREN
  1492. | IF LPAREN ts_var_expr COMMA stds RPAREN
  1493. | IF LPAREN ts_var_expr COMMA expr RPAREN
  1494. """
  1495. ifmaplist = self.check_stds(t[3])
  1496. thenmaplist = self.check_stds(t[5])
  1497. resultlist = self.build_condition_cmd_list(
  1498. ifmaplist,
  1499. thenmaplist,
  1500. elselist=None,
  1501. condition_topolist=["EQUAL"],
  1502. conclusion_topolist=["EQUAL"],
  1503. temporal="r",
  1504. null=False,
  1505. )
  1506. t[0] = resultlist
  1507. if self.debug:
  1508. for map in resultlist:
  1509. print(map.cmd_list)
  1510. def p_s_numeric_condition_if(self, t):
  1511. # if(s_var_expr, 1)
  1512. # if(A == 5, 10)
  1513. """
  1514. expr : IF LPAREN s_var_expr COMMA number RPAREN
  1515. | IF LPAREN s_var_expr COMMA NULL LPAREN RPAREN RPAREN
  1516. | IF LPAREN ts_var_expr COMMA number RPAREN
  1517. | IF LPAREN ts_var_expr COMMA NULL LPAREN RPAREN RPAREN
  1518. """
  1519. ifmaplist = self.check_stds(t[3])
  1520. resultlist = []
  1521. # Select input for r.mapcalc expression based on length of PLY object.
  1522. if len(t) == 7:
  1523. numinput = str(t[5])
  1524. elif len(t) == 9:
  1525. numinput = str(t[5] + t[6] + t[7])
  1526. # Iterate over condition map list.
  1527. for map_i in ifmaplist:
  1528. # Create r.mapcalc expression string for the operation.
  1529. cmdstring = self.build_command_string(map_i, numinput, cmd_type="condition")
  1530. # Conditional append of module command.
  1531. map_i.cmd_list = cmdstring
  1532. # Append map to result map list.
  1533. resultlist.append(map_i)
  1534. t[0] = resultlist
  1535. if self.debug:
  1536. for map in resultlist:
  1537. print(map.cmd_list)
  1538. def p_s_expr_condition_if_relation(self, t):
  1539. # if({equal||during}, s_var_expr, A)
  1540. """
  1541. expr : IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA stds RPAREN
  1542. | IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA expr RPAREN
  1543. | IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA stds RPAREN
  1544. | IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA expr RPAREN
  1545. """
  1546. relations, temporal, function, aggregation = self.eval_toperator(
  1547. t[3], optype="relation"
  1548. )
  1549. ifmaplist = self.check_stds(t[5])
  1550. thenmaplist = self.check_stds(t[7])
  1551. resultlist = self.build_condition_cmd_list(
  1552. ifmaplist,
  1553. thenmaplist,
  1554. elselist=None,
  1555. condition_topolist=relations,
  1556. conclusion_topolist=["EQUAL"],
  1557. temporal="r",
  1558. null=False,
  1559. )
  1560. t[0] = resultlist
  1561. if self.debug:
  1562. for map in resultlist:
  1563. print(map.cmd_list)
  1564. def p_s_expr_condition_elif(self, t):
  1565. # if(s_var_expr, A, B)
  1566. """
  1567. expr : IF LPAREN s_var_expr COMMA stds COMMA stds RPAREN
  1568. | IF LPAREN s_var_expr COMMA stds COMMA expr RPAREN
  1569. | IF LPAREN s_var_expr COMMA expr COMMA stds RPAREN
  1570. | IF LPAREN s_var_expr COMMA expr COMMA expr RPAREN
  1571. | IF LPAREN ts_var_expr COMMA stds COMMA stds RPAREN
  1572. | IF LPAREN ts_var_expr COMMA stds COMMA expr RPAREN
  1573. | IF LPAREN ts_var_expr COMMA expr COMMA stds RPAREN
  1574. | IF LPAREN ts_var_expr COMMA expr COMMA expr RPAREN
  1575. """
  1576. # Check map list inputs.
  1577. ifmaplist = self.check_stds(t[3])
  1578. thenmaplist = self.check_stds(t[5])
  1579. elsemaplist = self.check_stds(t[7])
  1580. # Create conditional command map list.
  1581. resultlist = self.build_condition_cmd_list(
  1582. ifmaplist,
  1583. thenmaplist,
  1584. elselist=elsemaplist,
  1585. condition_topolist=["EQUAL"],
  1586. conclusion_topolist=["EQUAL"],
  1587. temporal="r",
  1588. null=False,
  1589. )
  1590. t[0] = resultlist
  1591. if self.debug:
  1592. for map in resultlist:
  1593. print(map.cmd_list)
  1594. def p_s_numeric_condition_elif(self, t):
  1595. # if(s_var_expr, 1, 2)
  1596. # if(A == 5, 10, 0)
  1597. """
  1598. expr : IF LPAREN s_var_expr COMMA number COMMA number RPAREN
  1599. | IF LPAREN s_var_expr COMMA NULL LPAREN RPAREN COMMA number RPAREN
  1600. | IF LPAREN s_var_expr COMMA number COMMA NULL LPAREN RPAREN RPAREN
  1601. | IF LPAREN s_var_expr COMMA NULL LPAREN RPAREN COMMA NULL LPAREN RPAREN RPAREN
  1602. | IF LPAREN ts_var_expr COMMA number COMMA number RPAREN
  1603. | IF LPAREN ts_var_expr COMMA NULL LPAREN RPAREN COMMA number RPAREN
  1604. | IF LPAREN ts_var_expr COMMA number COMMA NULL LPAREN RPAREN RPAREN
  1605. | IF LPAREN ts_var_expr COMMA NULL LPAREN RPAREN COMMA NULL LPAREN RPAREN RPAREN
  1606. """
  1607. ifmaplist = self.check_stds(t[3])
  1608. # Select input for r.mapcalc expression based on length of PLY object.
  1609. if len(t) == 9:
  1610. numthen = t[5]
  1611. numelse = t[7]
  1612. elif len(t) == 11 and t[6] == "(":
  1613. numthen = t[5] + t[6] + t[7]
  1614. numelse = t[9]
  1615. elif len(t) == 11 and t[6] == ",":
  1616. numthen = t[5]
  1617. numelse = t[7] + t[8] + t[9]
  1618. elif len(t) == 13:
  1619. numthen = t[5] + t[6] + t[7]
  1620. numelse = t[9] + t[10] + t[11]
  1621. numthen = str(numthen)
  1622. numelse = str(numelse)
  1623. print(numthen + " " + numelse)
  1624. # Create conditional command map list.
  1625. resultlist = self.build_condition_cmd_list(
  1626. ifmaplist,
  1627. numthen,
  1628. numelse,
  1629. condition_topolist=["EQUAL"],
  1630. conclusion_topolist=["EQUAL"],
  1631. temporal="r",
  1632. null=False,
  1633. )
  1634. t[0] = resultlist
  1635. if self.debug:
  1636. for map in resultlist:
  1637. print(map.cmd_list)
  1638. def p_s_numeric_expr_condition_elif(self, t):
  1639. # if(s_var_expr, 1, A)
  1640. # if(A == 5 && C > 5, A, null())
  1641. """
  1642. expr : IF LPAREN s_var_expr COMMA number COMMA stds RPAREN
  1643. | IF LPAREN s_var_expr COMMA NULL LPAREN RPAREN COMMA stds RPAREN
  1644. | IF LPAREN s_var_expr COMMA number COMMA expr RPAREN
  1645. | IF LPAREN s_var_expr COMMA NULL LPAREN RPAREN COMMA expr RPAREN
  1646. | IF LPAREN s_var_expr COMMA stds COMMA number RPAREN
  1647. | IF LPAREN s_var_expr COMMA stds COMMA NULL LPAREN RPAREN RPAREN
  1648. | IF LPAREN s_var_expr COMMA expr COMMA number RPAREN
  1649. | IF LPAREN s_var_expr COMMA expr COMMA NULL LPAREN RPAREN RPAREN
  1650. | IF LPAREN ts_var_expr COMMA number COMMA stds RPAREN
  1651. | IF LPAREN ts_var_expr COMMA NULL LPAREN RPAREN COMMA stds RPAREN
  1652. | IF LPAREN ts_var_expr COMMA number COMMA expr RPAREN
  1653. | IF LPAREN ts_var_expr COMMA NULL LPAREN RPAREN COMMA expr RPAREN
  1654. | IF LPAREN ts_var_expr COMMA stds COMMA number RPAREN
  1655. | IF LPAREN ts_var_expr COMMA stds COMMA NULL LPAREN RPAREN RPAREN
  1656. | IF LPAREN ts_var_expr COMMA expr COMMA number RPAREN
  1657. | IF LPAREN ts_var_expr COMMA expr COMMA NULL LPAREN RPAREN RPAREN
  1658. """
  1659. ifmaplist = self.check_stds(t[3])
  1660. # Select input for r.mapcalc expression based on length of PLY object.
  1661. if len(t) == 9:
  1662. if isinstance(t[5], int):
  1663. theninput = str(t[5])
  1664. elseinput = self.check_stds(t[7])
  1665. elif isinstance(t[7], int):
  1666. theninput = self.check_stds(t[5])
  1667. elseinput = str(t[7])
  1668. elif len(t) == 11:
  1669. if t[5] == "null":
  1670. theninput = str(t[5] + t[6] + t[7])
  1671. elseinput = self.check_stds(t[9])
  1672. elif t[7] == "null":
  1673. theninput = self.check_stds(t[5])
  1674. elseinput = str(t[7] + t[8] + t[9])
  1675. # Create conditional command map list.
  1676. resultlist = self.build_condition_cmd_list(
  1677. ifmaplist,
  1678. theninput,
  1679. elseinput,
  1680. condition_topolist=["EQUAL"],
  1681. conclusion_topolist=["EQUAL"],
  1682. temporal="r",
  1683. null=False,
  1684. )
  1685. t[0] = resultlist
  1686. if self.debug:
  1687. for map in resultlist:
  1688. print(map.cmd_list)
  1689. def p_s_numeric_expr_condition_elif_relation(self, t):
  1690. # if({during},s_var_expr, 1, A)
  1691. # if({during}, A == 5, A, null())
  1692. """
  1693. expr : IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA number COMMA stds RPAREN
  1694. | IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA NULL LPAREN RPAREN COMMA stds RPAREN
  1695. | IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA number COMMA expr RPAREN
  1696. | IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA NULL LPAREN RPAREN COMMA expr RPAREN
  1697. | IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA stds COMMA number RPAREN
  1698. | IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA stds COMMA NULL LPAREN RPAREN RPAREN
  1699. | IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA expr COMMA number RPAREN
  1700. | IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA expr COMMA NULL LPAREN RPAREN RPAREN
  1701. | IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA number COMMA stds RPAREN
  1702. | IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA NULL LPAREN RPAREN COMMA stds RPAREN
  1703. | IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA number COMMA expr RPAREN
  1704. | IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA NULL LPAREN RPAREN COMMA expr RPAREN
  1705. | IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA stds COMMA number RPAREN
  1706. | IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA stds COMMA NULL LPAREN RPAREN RPAREN
  1707. | IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA expr COMMA number RPAREN
  1708. | IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA expr COMMA NULL LPAREN RPAREN RPAREN
  1709. """
  1710. relations, temporal, function, aggregation = self.eval_toperator(
  1711. t[3], optype="relation"
  1712. )
  1713. ifmaplist = self.check_stds(t[5])
  1714. # Select input for r.mapcalc expression based on length of PLY object.
  1715. if len(t) == 11:
  1716. if isinstance(t[7], int):
  1717. theninput = str(t[7])
  1718. elseinput = self.check_stds(t[9])
  1719. elif isinstance(t[9], int):
  1720. theninput = self.check_stds(t[7])
  1721. elseinput = str(t[9])
  1722. elif len(t) == 13:
  1723. if t[7] == "null":
  1724. theninput = str(t[7] + t[8] + t[9])
  1725. elseinput = self.check_stds(t[11])
  1726. elif t[9] == "null":
  1727. theninput = self.check_stds(t[7])
  1728. elseinput = str(t[9] + t[10] + t[11])
  1729. # Create conditional command map list.
  1730. resultlist = self.build_condition_cmd_list(
  1731. ifmaplist,
  1732. theninput,
  1733. elseinput,
  1734. condition_topolist=relations,
  1735. conclusion_topolist=["EQUAL"],
  1736. temporal="r",
  1737. null=False,
  1738. )
  1739. t[0] = resultlist
  1740. if self.debug:
  1741. for map in resultlist:
  1742. print(map.cmd_list)
  1743. def p_s_expr_condition_elif_relation(self, t):
  1744. # if({equal||during}, s_var_expr, A, B)
  1745. """
  1746. expr : IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA stds COMMA stds RPAREN
  1747. | IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA stds COMMA expr RPAREN
  1748. | IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA expr COMMA stds RPAREN
  1749. | IF LPAREN T_REL_OPERATOR COMMA s_var_expr COMMA expr COMMA expr RPAREN
  1750. | IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA stds COMMA stds RPAREN
  1751. | IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA stds COMMA expr RPAREN
  1752. | IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA expr COMMA stds RPAREN
  1753. | IF LPAREN T_REL_OPERATOR COMMA ts_var_expr COMMA expr COMMA expr RPAREN
  1754. """
  1755. relations, temporal, function, aggregation = self.eval_toperator(
  1756. t[3], optype="relation"
  1757. )
  1758. ifmaplist = self.check_stds(t[5])
  1759. thenmaplist = self.check_stds(t[7])
  1760. elsemaplist = self.check_stds(t[9])
  1761. # Create conditional command map list.
  1762. resultlist = self.build_condition_cmd_list(
  1763. ifmaplist,
  1764. thenmaplist,
  1765. elsemaplist,
  1766. condition_topolist=relations,
  1767. conclusion_topolist=["EQUAL"],
  1768. temporal="r",
  1769. null=False,
  1770. )
  1771. t[0] = resultlist
  1772. if self.debug:
  1773. for map in resultlist:
  1774. print(map.cmd_list)
  1775. def p_ts_var_expr1(self, t):
  1776. # Combination of spatial and temporal conditional expressions.
  1777. # Examples:
  1778. # A <= 2 || start_date <= 2013-01-01
  1779. # end_date > 2013-01-15 && A > 10
  1780. # IMPORTANT: Only the intersection of map lists in conditionals are
  1781. # exported.
  1782. """
  1783. ts_var_expr : s_var_expr AND AND t_var_expr
  1784. | t_var_expr AND AND s_var_expr
  1785. | t_var_expr OR OR s_var_expr
  1786. | s_var_expr OR OR t_var_expr
  1787. | ts_var_expr AND AND s_var_expr
  1788. | ts_var_expr AND AND t_var_expr
  1789. | ts_var_expr OR OR s_var_expr
  1790. | ts_var_expr OR OR t_var_expr
  1791. | s_var_expr AND AND ts_var_expr
  1792. | t_var_expr AND AND ts_var_expr
  1793. | s_var_expr OR OR ts_var_expr
  1794. | t_var_expr OR OR ts_var_expr
  1795. """
  1796. if self.run:
  1797. # Check input stds.
  1798. s_var_exprA = self.check_stds(t[1])
  1799. s_var_exprB = self.check_stds(t[4])
  1800. relations = ["EQUAL"]
  1801. temporal = "l"
  1802. function = t[2] + t[3]
  1803. aggregate = t[2]
  1804. # Build conditional values based on topological relationships.
  1805. complist = self.build_spatio_temporal_topology_list(
  1806. s_var_exprA,
  1807. s_var_exprB,
  1808. topolist=relations,
  1809. compare_cmd=True,
  1810. compop=function,
  1811. aggregate=aggregate,
  1812. convert=True,
  1813. )
  1814. # Set temporal extent based on topological relationships.
  1815. resultlist = self.set_temporal_extent_list(
  1816. complist, topolist=relations, temporal=temporal
  1817. )
  1818. t[0] = resultlist
  1819. def p_hash_operation(self, t):
  1820. # Calculate the number of maps within an interval of another map from a
  1821. # second space time dataset.
  1822. # A # B
  1823. # A {equal,r#} B
  1824. """
  1825. expr : t_hash_var
  1826. """
  1827. # Check input stds.
  1828. maplist = self.check_stds(t[1])
  1829. if self.run:
  1830. resultlist = []
  1831. for map_i in maplist:
  1832. for obj in map_i.map_value:
  1833. if isinstance(obj, GlobalTemporalVar):
  1834. n_maps = obj.td
  1835. mapinput = map_i.get_id()
  1836. # Create r.mapcalc expression string for the operation.
  1837. cmdstring = "(%s)" % (n_maps)
  1838. # Append module command.
  1839. map_i.cmd_list = cmdstring
  1840. # Append map to result map list.
  1841. resultlist.append(map_i)
  1842. t[0] = resultlist
  1843. if self.debug:
  1844. for map in resultlist:
  1845. print(map.cmd_list)
  1846. if __name__ == "__main__":
  1847. import doctest
  1848. doctest.testmod()