[GRASS-SVN] r72478 - in grass/trunk: lib/python/temporal lib/python/temporal/testsuite temporal/t.rast.algebra temporal/t.rast.algebra/testsuite

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Mar 21 12:11:24 PDT 2018


Author: huhabla
Date: 2018-03-21 12:11:23 -0700 (Wed, 21 Mar 2018)
New Revision: 72478

Modified:
   grass/trunk/lib/python/temporal/aggregation.py
   grass/trunk/lib/python/temporal/core.py
   grass/trunk/lib/python/temporal/datetime_math.py
   grass/trunk/lib/python/temporal/extract.py
   grass/trunk/lib/python/temporal/temporal_algebra.py
   grass/trunk/lib/python/temporal/temporal_raster_algebra.py
   grass/trunk/lib/python/temporal/temporal_raster_base_algebra.py
   grass/trunk/lib/python/temporal/testsuite/unittests_temporal_raster_algebra.py
   grass/trunk/temporal/t.rast.algebra/t.rast.algebra.py
   grass/trunk/temporal/t.rast.algebra/testsuite/test_raster_algebra.py
Log:
temporal algebra: Added suffix option for time and granularity based raster map names


Modified: grass/trunk/lib/python/temporal/aggregation.py
===================================================================
--- grass/trunk/lib/python/temporal/aggregation.py	2018-03-21 18:34:20 UTC (rev 72477)
+++ grass/trunk/lib/python/temporal/aggregation.py	2018-03-21 19:11:23 UTC (rev 72478)
@@ -23,7 +23,7 @@
 from .space_time_datasets import RasterDataset
 from .datetime_math import create_suffix_from_datetime
 from .datetime_math import create_time_suffix
-from .datetime_math import create_numeric_suffic
+from .datetime_math import create_numeric_suffix
 from .core import get_current_mapset, get_tgis_message_interface, init_dbif
 from .spatio_temporal_relationships import SpatioTemporalTopologyBuilder, \
     create_temporal_relation_sql_where_statement
@@ -290,7 +290,7 @@
                 suffix = create_time_suffix(granule)
                 output_name = "{ba}_{su}".format(ba=basename, su=suffix)
             else:
-                output_name = create_numeric_suffic(basename, count + int(offset),
+                output_name = create_numeric_suffix(basename, count + int(offset),
                                                     time_suffix)
 
             map_layer = RasterDataset("%s@%s" % (output_name,

Modified: grass/trunk/lib/python/temporal/core.py
===================================================================
--- grass/trunk/lib/python/temporal/core.py	2018-03-21 18:34:20 UTC (rev 72477)
+++ grass/trunk/lib/python/temporal/core.py	2018-03-21 19:11:23 UTC (rev 72478)
@@ -563,6 +563,8 @@
     msgr.debug(1, "Initiate the temporal database")
                   #"\n  traceback:%s"%(str("  \n".join(traceback.format_stack()))))
 
+    msgr.debug(1, ("Raise on error id: %s"%str(raise_on_error)))
+
     ciface = get_tgis_c_library_interface()
     driver_string = ciface.get_driver_name()
     database_string = ciface.get_database_name()

Modified: grass/trunk/lib/python/temporal/datetime_math.py
===================================================================
--- grass/trunk/lib/python/temporal/datetime_math.py	2018-03-21 18:34:20 UTC (rev 72477)
+++ grass/trunk/lib/python/temporal/datetime_math.py	2018-03-21 19:11:23 UTC (rev 72478)
@@ -931,12 +931,13 @@
         return "{st}_{en}".format(st=sstring, en=estring)
     return sstring
 
-def create_numeric_suffic(base, count, zeros):
+
+def create_numeric_suffix(base, count, zeros):
     """Create a string based on count and number of zeros decided by zeros
 
        :param base: the basename for new map
        :param count: a number
-       :param zeros: a string containing the expected number, coming from suffix option
+       :param zeros: a string containing the expected number, coming from suffix option like "%05"
     """
     spli = zeros.split('%')
     if len(spli) == 2:

Modified: grass/trunk/lib/python/temporal/extract.py
===================================================================
--- grass/trunk/lib/python/temporal/extract.py	2018-03-21 18:34:20 UTC (rev 72477)
+++ grass/trunk/lib/python/temporal/extract.py	2018-03-21 19:11:23 UTC (rev 72478)
@@ -15,7 +15,7 @@
 from .open_stds import open_old_stds, check_new_stds, open_new_stds
 from .datetime_math import create_suffix_from_datetime
 from .datetime_math import create_time_suffix
-from .datetime_math import create_numeric_suffic
+from .datetime_math import create_numeric_suffix
 from multiprocessing import Process
 import grass.script as gscript
 from grass.exceptions import CalledModuleError
@@ -103,7 +103,7 @@
                     suffix = create_time_suffix(old_map)
                     map_name = "{ba}_{su}".format(ba=base, su=suffix)
                 else:
-                    map_name = create_numeric_suffic(base, count, time_suffix)
+                    map_name = create_numeric_suffix(base, count, time_suffix)
 
                 # We need to modify the r(3).mapcalc expression
                 if type != "vector":

Modified: grass/trunk/lib/python/temporal/temporal_algebra.py
===================================================================
--- grass/trunk/lib/python/temporal/temporal_algebra.py	2018-03-21 18:34:20 UTC (rev 72477)
+++ grass/trunk/lib/python/temporal/temporal_algebra.py	2018-03-21 19:11:23 UTC (rev 72478)
@@ -465,7 +465,12 @@
 from spatio_temporal_relationships import SpatioTemporalTopologyBuilder
 from .datetime_math import time_delta_to_relative_time, string_to_datetime
 from abstract_space_time_dataset import AbstractSpaceTimeDataset
+from .temporal_granularity import compute_absolute_time_granularity
 
+from .datetime_math import create_suffix_from_datetime
+from .datetime_math import create_time_suffix
+from .datetime_math import create_numeric_suffix
+
 ##############################################################################
 
 class TemporalAlgebraLexer(object):
@@ -751,7 +756,7 @@
         )
 
     def __init__(self, pid=None, run=True, debug=False, spatial=False,
-                 register_null=False, dry_run=False, nprocs=1):
+                 register_null=False, dry_run=False, nprocs=1, time_suffix=None):
         self.run = run
         self.dry_run = dry_run              # Compute the processes and output but Do not start the processes
         self.process_chain_dict = {}        # This dictionary stores all processes, as well as the maps to register and remove
@@ -777,6 +782,7 @@
         self.m_copy = pymod.Module('g.copy')
         self.nprocs = nprocs
         self.use_granularity = False
+        self.time_suffix = time_suffix
 
         # Topology lists
         self.temporal_topology_list = ["EQUAL", "FOLLOWS", "PRECEDES", "OVERLAPS", "OVERLAPPED", \
@@ -2160,11 +2166,13 @@
 ###########################################################################
 
     def p_statement_assign(self, t):
-        # The expression should always return a list of maps.
+        # The expression should always return a list of maps
+        # This function starts all the work and is the last one that is called from the parser
         """
         statement : stds EQUALS expr
 
         """
+
         if self.run:
             dbif, connected = init_dbif(self.dbif)
             map_type = None
@@ -2174,6 +2182,17 @@
                 register_list = []
                 if num > 0:
 
+                    # Compute the granularity for suffix creation
+                    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])
+
+                    # compute the size of the numerical suffix
+                    num = len(t[3])
+                    leadzero = len(str(num))
+
                     if self.dry_run is False:
                         process_queue = pymod.ParallelModuleQueue(int(self.nprocs))
 
@@ -2189,7 +2208,7 @@
                         else:
                             map_type_2 = map_i.get_type()
                             if map_type != map_type_2:
-                                self.msgr.fatal(_("Maps that should be registered in the "\
+                                self.msgr.fatal(_("Maps that should be registered in the "
                                                   "resulting space time dataset have different types."))
                         count += 1
 
@@ -2201,8 +2220,21 @@
                         map_b.select(dbif)
                         map_b_extent = map_b.get_temporal_extent_as_tuple()
                         if map_a_extent != map_b_extent:
+
                             # Create new map with basename
-                            newident = self.basename + "_" + str(count)
+                            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)
+
                             map_result = map_i.get_new_instance(newident + "@" + self.mapset)
 
                             if map_result.map_exists() and self.overwrite == False:
@@ -2254,7 +2286,6 @@
                         start, end = map_i.get_temporal_extent_as_tuple()
                         self.process_chain_dict["register"].append((map_i.get_name(), str(start), str(end)))
 
-                        # Check if temporal extents have changed and a new map was created
                         if hasattr(map_i, "is_new") is True:
                             # Do not register empty maps if not required
                             # In case of a null map continue, do not register null maps

Modified: grass/trunk/lib/python/temporal/temporal_raster_algebra.py
===================================================================
--- grass/trunk/lib/python/temporal/temporal_raster_algebra.py	2018-03-21 18:34:20 UTC (rev 72477)
+++ grass/trunk/lib/python/temporal/temporal_raster_algebra.py	2018-03-21 19:11:23 UTC (rev 72478)
@@ -72,11 +72,12 @@
     """The temporal raster algebra class"""
 
     def __init__(self, pid=None, run=False, debug=True, spatial=False,
-                 register_null=False, dry_run=False, nprocs=1):
+                 register_null=False, dry_run=False, nprocs=1, time_suffix=None):
 
         TemporalRasterBaseAlgebraParser.__init__(self, pid=pid, run=run, debug=debug,
                                                  spatial=spatial, register_null=register_null,
-                                                 dry_run=dry_run, nprocs=nprocs)
+                                                 dry_run=dry_run, nprocs=nprocs,
+                                                 time_suffix=time_suffix)
 
         if spatial is True:
             self.m_mapcalc = pymod.Module('r.mapcalc', region="union", run_=False)

Modified: grass/trunk/lib/python/temporal/temporal_raster_base_algebra.py
===================================================================
--- grass/trunk/lib/python/temporal/temporal_raster_base_algebra.py	2018-03-21 18:34:20 UTC (rev 72477)
+++ grass/trunk/lib/python/temporal/temporal_raster_base_algebra.py	2018-03-21 19:11:23 UTC (rev 72478)
@@ -58,8 +58,13 @@
 from .open_stds import open_new_stds
 from spatio_temporal_relationships import SpatioTemporalTopologyBuilder
 from .space_time_datasets import Raster3DDataset, RasterDataset
+from .temporal_granularity import compute_absolute_time_granularity
 
+from .datetime_math import create_suffix_from_datetime
+from .datetime_math import create_time_suffix
+from .datetime_math import create_numeric_suffix
 
+
 ##############################################################################
 
 class TemporalRasterAlgebraLexer(TemporalAlgebraLexer):
@@ -156,7 +161,8 @@
     def __init__(self, pid=None, run=True,
                  debug=False, spatial=False,
                  register_null=False,
-                 dry_run=False, nprocs=1):
+                 dry_run=False, nprocs=1,
+                 time_suffix=None):
 
         TemporalAlgebraParser.__init__(self,
                                        pid=pid,
@@ -165,7 +171,8 @@
                                        spatial=spatial,
                                        register_null=register_null,
                                        dry_run=dry_run,
-                                       nprocs=nprocs)
+                                       nprocs=nprocs,
+                                       time_suffix=time_suffix)
 
     def check_null(self, t):
         try:
@@ -631,23 +638,66 @@
                 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])
-                count = 0
                 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.
-                    map_name = self.basename + "_" + str(i).zfill(leadzero) + "@" + self.mapset
+                    newident = newident + "@" + self.mapset
+
                     if self.stdstype == "strds":
-                        new_map = RasterDataset(map_name)
+                        new_map = RasterDataset(newident)
                     else:
-                        new_map = Raster3DDataset(map_name)
+                        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"%map_name)
+                                        "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]:
-                    newident = self.basename + "_" + str(count).zfill(leadzero)
+
+                    # 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.

Modified: grass/trunk/lib/python/temporal/testsuite/unittests_temporal_raster_algebra.py
===================================================================
--- grass/trunk/lib/python/temporal/testsuite/unittests_temporal_raster_algebra.py	2018-03-21 18:34:20 UTC (rev 72477)
+++ grass/trunk/lib/python/temporal/testsuite/unittests_temporal_raster_algebra.py	2018-03-21 19:11:23 UTC (rev 72478)
@@ -75,7 +75,6 @@
 
         D = tgis.open_old_stds("R", type="strds")
         D.select()
-        maplist = D.get_registered_maps_as_objects()
         self.assertEqual(D.metadata.get_number_of_maps(), 2)
         self.assertEqual(D.metadata.get_min_min(), 2)
         self.assertEqual(D.metadata.get_max_max(), 3)
@@ -114,7 +113,8 @@
         self.assertEqual(D.get_granularity(),  u'1 day')
 
     def test_simple_arith_hash_1(self):
-        """Simple arithmetic test including the hash operator
+        """Simple arithmetic test including the hash operator using the granularity option
+        for map name creation
 
         R = A + (A {#, equal,l} A)
 
@@ -128,11 +128,23 @@
         r4 = a4 + 1
 
         """
-        tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True)
+        tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True, time_suffix="gran")
         tra.parse(expression='R = A + (A {#, equal,l} A)', basename="r", overwrite=True)
 
         D = tgis.open_old_stds("R", type="strds")
         D.select()
+        # r_2001_01_01
+        # r_2001_01_02
+        # r_2001_01_03
+        # r_2001_01_04
+
+        maps = D.get_registered_maps_as_objects()
+        count = 1
+        for map in maps:
+            map_name = "r_2001_01_0%i"%count
+            self.assertEqual(map.get_name(), map_name)
+            count += 1
+
         self.assertEqual(D.metadata.get_number_of_maps(), 4)
         self.assertEqual(D.metadata.get_min_min(), 2)
         self.assertEqual(D.metadata.get_max_max(), 5)
@@ -142,7 +154,7 @@
 
 
     def test_simple_arith_td_1(self):
-        """Simple arithmetic test
+        """Simple arithmetic test with time suffix option
 
         R = A + td(A)
 
@@ -156,11 +168,25 @@
         r4 = a4 + 1
 
         """
-        tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True)
+        tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True, time_suffix="time")
         tra.parse(expression='R = A + td(A)', basename="r", overwrite=True)
 
+
         D = tgis.open_old_stds("R", type="strds")
         D.select()
+        maps = D.get_registered_maps_as_objects()
+
+        # Test for map names resulting from the time suffix option
+        #r_2001_01_01T00_00_00
+        #r_2001_01_02T00_00_00
+        #r_2001_01_03T00_00_00
+        #r_2001_01_04T00_00_00
+        count = 1
+        for map in maps:
+            map_name = "r_2001_01_0%iT00_00_00"%count
+            self.assertEqual(map.get_name(), map_name)
+            count += 1
+
         self.assertEqual(D.metadata.get_number_of_maps(), 4)
         self.assertEqual(D.metadata.get_min_min(), 2)
         self.assertEqual(D.metadata.get_max_max(), 5)

Modified: grass/trunk/temporal/t.rast.algebra/t.rast.algebra.py
===================================================================
--- grass/trunk/temporal/t.rast.algebra/t.rast.algebra.py	2018-03-21 18:34:20 UTC (rev 72477)
+++ grass/trunk/temporal/t.rast.algebra/t.rast.algebra.py	2018-03-21 19:11:23 UTC (rev 72478)
@@ -46,6 +46,15 @@
 #%end
 
 #%option
+#% key: suffix
+#% type: string
+#% description: Suffix to add at basename: set 'gran' for granularity, 'time' for the full time format, 'num' for numerical suffix with a specific number of digits (default %05)
+#% answer: num
+#% required: no
+#% multiple: no
+#%end
+
+#%option
 #% key: nprocs
 #% type: integer
 #% description: Number of r.mapcalc processes to run in parallel
@@ -85,6 +94,7 @@
     expression = options['expression']
     basename = options['basename']
     nprocs = options["nprocs"]
+    time_suffix = options["suffix"]
     spatial = flags["s"]
     register_null = flags["n"]
     granularity = flags["g"]
@@ -105,7 +115,7 @@
                                          spatial=spatial,
                                          nprocs=nprocs,
                                          register_null=register_null,
-                                         dry_run=dry_run)
+                                         dry_run=dry_run, time_suffix=time_suffix)
 
     if granularity:
         if not p.setup_common_granularity(expression=expression,  lexer = tgis.TemporalRasterAlgebraLexer()):

Modified: grass/trunk/temporal/t.rast.algebra/testsuite/test_raster_algebra.py
===================================================================
--- grass/trunk/temporal/t.rast.algebra/testsuite/test_raster_algebra.py	2018-03-21 18:34:20 UTC (rev 72477)
+++ grass/trunk/temporal/t.rast.algebra/testsuite/test_raster_algebra.py	2018-03-21 19:11:23 UTC (rev 72478)
@@ -109,8 +109,8 @@
     def test_simple_arith_td_1(self):
         """Simple arithmetic test"""
        
-        self.assertModule("t.rast.algebra", expression='R = A + td(A)', basename="r", flags="d")
-        self.assertModule("t.rast.algebra", expression='R = A + td(A)', basename="r")
+        self.assertModule("t.rast.algebra", expression='R = A + td(A)', basename="r", flags="d", suffix="time")
+        self.assertModule("t.rast.algebra", expression='R = A + td(A)', basename="r", suffix="time")
 
         D = tgis.open_old_stds("R", type="strds")
         
@@ -124,8 +124,8 @@
     def test_simple_arith_td_2(self):
         """Simple arithmetic test"""
        
-        self.assertModule("t.rast.algebra", expression='R = A / td(A)', basename="r", flags="d")
-        self.assertModule("t.rast.algebra", expression='R = A / td(A)', basename="r")
+        self.assertModule("t.rast.algebra", expression='R = A / td(A)', basename="r", flags="d", suffix="gran")
+        self.assertModule("t.rast.algebra", expression='R = A / td(A)', basename="r", suffix="gran")
 
         D = tgis.open_old_stds("R", type="strds")
         



More information about the grass-commit mailing list