Kaynağa Gözat

temporal framework: Adding dry run to map algebra (merge from relbr72)

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@69312 15284696-431f-4ddb-bdfa-cd5b030d7da7
Soeren Gebbert 8 yıl önce
ebeveyn
işleme
6048d12c0c

+ 107 - 78
lib/python/temporal/temporal_algebra.py

@@ -737,9 +737,15 @@ class TemporalAlgebraParser(object):
         ('left', 'AND', 'OR', 'T_COMP_OPERATOR'), #2
         ('left', 'AND', 'OR', 'T_COMP_OPERATOR'), #2
         )
         )
 
 
-    def __init__(self, pid=None, run = True, debug = False, spatial = False,
-                        null = False, register_null = False,  nprocs = 1):
+    def __init__(self, pid=None, run=True, debug=False, spatial=False,
+                 null=False, register_null=False, dry_run=False,  nprocs=1):
         self.run = run
         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
+        self.process_chain_dict["processes"] = []
+        self.process_chain_dict["insert"] = []
+        self.process_chain_dict["update"] = []
+        self.process_chain_dict["remove"] = []
         self.debug = debug
         self.debug = debug
         self.pid = pid
         self.pid = pid
         # Intermediate vector map names
         # Intermediate vector map names
@@ -768,11 +774,11 @@ class TemporalAlgebraParser(object):
              space time datasets in the expression to generate the map lists.
              space time datasets in the expression to generate the map lists.
 
 
              This function will analyze the expression to detect space time datasets
              This function will analyze the expression to detect space time datasets
-             and computes the common granularity from all granularities.
+             and computes the common granularity from all granularities of the input space time datasets.
 
 
              This granularity is then be used to generate the map lists. Hence, all
              This granularity is then be used to generate the map lists. Hence, all
              maps from all STDS will have equidistant temporal extents. The only meaningful
              maps from all STDS will have equidistant temporal extents. The only meaningful
-             temporal relation is "equal".
+             temporal relation is therefore "equal".
 
 
              :param expression: The algebra expression to analyze
              :param expression: The algebra expression to analyze
 
 
@@ -848,8 +854,19 @@ class TemporalAlgebraParser(object):
 
 
         return True
         return True
 
 
-    def parse(self, expression, stdstype = 'strds', maptype = 'rast',  mapclass = RasterDataset,
-                      basename = None, overwrite=False):
+    def parse(self, expression, stdstype='strds',
+              maptype='rast',  mapclass=RasterDataset,
+              basename=None, overwrite=False):
+        """Parse the algebra expression and run the computation
+
+        :param expression:
+        :param stdstype:
+        :param maptype:
+        :param mapclass:
+        :param basename:
+        :param overwrite:
+        :return: The process chain dictionary
+        """
         self.lexer = TemporalAlgebraLexer()
         self.lexer = TemporalAlgebraLexer()
         self.lexer.build()
         self.lexer.build()
         self.parser = yacc.yacc(module=self, debug=self.debug)
         self.parser = yacc.yacc(module=self, debug=self.debug)
@@ -863,6 +880,8 @@ class TemporalAlgebraParser(object):
         self.expression = expression
         self.expression = expression
         self.parser.parse(expression)
         self.parser.parse(expression)
 
 
+        return self.process_chain_dict
+
     def generate_map_name(self):
     def generate_map_name(self):
         """Generate an unique  map name and register it in the objects map list
         """Generate an unique  map name and register it in the objects map list
 
 
@@ -878,8 +897,9 @@ class TemporalAlgebraParser(object):
         self.names[name] = name
         self.names[name] = name
         return name
         return name
 
 
-    def generate_new_map(self, base_map, bool_op = 'and', copy = True,  rename = True,
-                                              remove = False):
+    def generate_new_map(self, base_map, bool_op='and',
+                         copy=True,  rename=True,
+                         remove=False):
         """Generate a new map using the spatio-temporal extent of the base map
         """Generate a new map using the spatio-temporal extent of the base map
 
 
            :param base_map: This map is used to create the new map
            :param base_map: This map is used to create the new map
@@ -988,7 +1008,7 @@ class TemporalAlgebraParser(object):
                 other map list and given temporal operator.
                 other map list and given temporal operator.
 
 
             :param maplist: List of map objects for which relations has been build
             :param maplist: List of map objects for which relations has been build
-                                        correctely.
+                                        correctly.
             :param topolist: List of strings of temporal relations.
             :param topolist: List of strings of temporal relations.
             :param temporal: The temporal operator specifying the temporal
             :param temporal: The temporal operator specifying the temporal
                                             extent operation (intersection, union, disjoint
                                             extent operation (intersection, union, disjoint
@@ -1002,26 +1022,26 @@ class TemporalAlgebraParser(object):
             # Loop over temporal related maps and create overlay modules.
             # Loop over temporal related maps and create overlay modules.
             tbrelations = map_i.get_temporal_relations()
             tbrelations = map_i.get_temporal_relations()
             # Generate an intermediate map for the result map list.
             # Generate an intermediate map for the result map list.
-            map_new = self.generate_new_map(base_map=map_i, bool_op = 'and',
-                                                                        copy = True,  rename = True)
+            map_new = self.generate_new_map(base_map=map_i, bool_op='and',
+                                            copy=True,  rename=True)
             # Combine temporal and spatial extents of intermediate map with related maps.
             # Combine temporal and spatial extents of intermediate map with related maps.
             for topo in topolist:
             for topo in topolist:
                 if topo in tbrelations.keys():
                 if topo in tbrelations.keys():
                     for map_j in (tbrelations[topo]):
                     for map_j in (tbrelations[topo]):
                         if temporal == 'r':
                         if temporal == 'r':
                             # Generate an intermediate map for the result map list.
                             # Generate an intermediate map for the result map list.
-                            map_new = self.generate_new_map(base_map=map_i, bool_op = 'and',
-                                                                                        copy = True,  rename = True)
+                            map_new = self.generate_new_map(base_map=map_i, bool_op='and',
+                                                            copy=True,  rename=True)
                         # Create overlayed map extent.
                         # Create overlayed map extent.
-                        returncode = self.overlay_map_extent(map_new, map_j, 'and', \
-                                                                temp_op = temporal)
+                        returncode = self.overlay_map_extent(map_new, map_j, 'and',
+                                                             temp_op=temporal)
                         # Stop the loop if no temporal or spatial relationship exist.
                         # Stop the loop if no temporal or spatial relationship exist.
                         if returncode == 0:
                         if returncode == 0:
                             break
                             break
                         # Append map to result map list.
                         # Append map to result map list.
                         elif returncode == 1:
                         elif returncode == 1:
-                            print(map_new.get_id() + " " + str(map_new.get_temporal_extent_as_tuple()))
-                            print(map_new.condition_value)
+                            # print(map_new.get_id() + " " + str(map_new.get_temporal_extent_as_tuple()))
+                            # print(map_new.condition_value)
                             # print(map_new.cmd_list)
                             # print(map_new.cmd_list)
                             # resultlist.append(map_new)
                             # resultlist.append(map_new)
                             resultdict[map_new.get_id()] = map_new
                             resultdict[map_new.get_id()] = map_new
@@ -1079,10 +1099,10 @@ class TemporalAlgebraParser(object):
                 m.inputs["type"].value = map_type
                 m.inputs["type"].value = map_type
                 m.inputs["name"].value = stringlist
                 m.inputs["name"].value = stringlist
                 m.flags["f"].value = True
                 m.flags["f"].value = True
-                print(m.get_bash())
+                # print(m.get_bash())
                 m.run()
                 m.run()
 
 
-    def check_stds(self, input, clear = False,  stds_type = None,  check_type=True):
+    def check_stds(self, input, clear=False,  stds_type=None,  check_type=True):
         """ Check if input space time dataset exist in database and return its map list.
         """ Check if input space time dataset exist in database and return its map list.
 
 
             :param input: Name of space time data set as string or list of maps.
             :param input: Name of space time data set as string or list of maps.
@@ -1115,7 +1135,8 @@ class TemporalAlgebraParser(object):
                 if self.use_granularity:
                 if self.use_granularity:
                     # We create the maplist out of the map array from none-gap objects
                     # We create the maplist out of the map array from none-gap objects
                     maplist = []
                     maplist = []
-                    map_array = stds.get_registered_maps_as_objects_by_granularity(gran=self.granularity,  dbif=self.dbif)
+                    map_array = stds.get_registered_maps_as_objects_by_granularity(gran=self.granularity,
+                                                                                   dbif=self.dbif)
                     for entry in map_array:
                     for entry in map_array:
                         # Ignore gap objects
                         # Ignore gap objects
                         if entry[0].get_id() is not None:
                         if entry[0].get_id() is not None:
@@ -1838,13 +1859,13 @@ class TemporalAlgebraParser(object):
         # Get topology of then statement map list in relation to the other maplist
         # Get topology of then statement map list in relation to the other maplist
         # and assign boolean values of the maplist to the thenlist.
         # and assign boolean values of the maplist to the thenlist.
         containlist = self.perform_temporal_selection(thenlist, maplist,
         containlist = self.perform_temporal_selection(thenlist, maplist,
-                                                        assign_val = True,
-                                                        topolist = topolist)
+                                                      assign_val=True,
+                                                      topolist=topolist)
         # Inverse selection of maps from thenlist and assigning False values.
         # Inverse selection of maps from thenlist and assigning False values.
         #excludelist = self.perform_temporal_selection(thenlist, maplist,
         #excludelist = self.perform_temporal_selection(thenlist, maplist,
-         #                                               assign_val = True,
-          #                                              inverse = True,
-          #                                              topolist = topolist)
+        #                                              assign_val = True,
+        #                                              inverse = True,
+        #                                              topolist = topolist)
         # Combining the selection and inverse selection list.
         # Combining the selection and inverse selection list.
         resultlist = containlist# + excludelist
         resultlist = containlist# + excludelist
 
 
@@ -1895,10 +1916,6 @@ class TemporalAlgebraParser(object):
             resultlist = self.eval_map_list(tvarexpr, thenlist, topolist)
             resultlist = self.eval_map_list(tvarexpr, thenlist, topolist)
         elif len(tvarexpr) % 2 != 0:
         elif len(tvarexpr) % 2 != 0:
             # Define variables for map list comparisons.
             # Define variables for map list comparisons.
-            left_obj = []
-            operator = []
-            right_obj =[]
-            count = 0
             #self.msgr.fatal("Condition list is not complete. Elements missing")
             #self.msgr.fatal("Condition list is not complete. Elements missing")
             for iter in range(len(tvarexpr)):
             for iter in range(len(tvarexpr)):
                 expr = tvarexpr[iter]
                 expr = tvarexpr[iter]
@@ -2017,14 +2034,16 @@ class TemporalAlgebraParser(object):
         """
         """
         if self.run:
         if self.run:
             dbif, connected = init_dbif(self.dbif)
             dbif, connected = init_dbif(self.dbif)
-            map_stds_type = None
             map_type = None
             map_type = None
             if isinstance(t[3], list):
             if isinstance(t[3], list):
                 num = len(t[3])
                 num = len(t[3])
                 count = 0
                 count = 0
                 register_list = []
                 register_list = []
                 if num > 0:
                 if num > 0:
-                    process_queue = pymod.ParallelModuleQueue(int(self.nprocs))
+
+                    if self.dry_run is False:
+                        process_queue = pymod.ParallelModuleQueue(int(self.nprocs))
+
                     for map_i in t[3]:
                     for map_i in t[3]:
                         # Test if temporal extents have been changed by temporal
                         # Test if temporal extents have been changed by temporal
                         # relation operators (i|r).
                         # relation operators (i|r).
@@ -2032,28 +2051,27 @@ class TemporalAlgebraParser(object):
                             maps_stds_type = map_i.get_new_stds_instance(None).get_type()
                             maps_stds_type = map_i.get_new_stds_instance(None).get_type()
                             map_type = map_i.get_type()
                             map_type = map_i.get_type()
                             if maps_stds_type != self.stdstype:
                             if maps_stds_type != self.stdstype:
-                                self.msgr.warning(_("The resulting space time dataset type <%(a)s> is "\
-                                                                "different from the requested type <%(b)s>"\
-                                                                %({"a":maps_stds_type,  "b":self.stdstype})))
+                                self.msgr.warning(_("The resulting space time dataset type <%(a)s> is "
+                                                    "different from the requested type <%(b)s>"
+                                                    %({"a":maps_stds_type,  "b":self.stdstype})))
                         else:
                         else:
                             map_type_2 = map_i.get_type()
                             map_type_2 = map_i.get_type()
                             if map_type != map_type_2:
                             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."))
+                                                  "resulting space time dataset have different types."))
 
 
-                        map_i_extent = map_i.get_temporal_extent_as_tuple()
-                        map_test = map_i.get_new_instance(map_i.get_id())
-                        map_test.select(dbif)
-                        map_test_extent = map_test.get_temporal_extent_as_tuple()
-                        if map_test_extent != map_i_extent:
+                        map_a_extent = map_i.get_temporal_extent_as_tuple()
+                        map_b = map_i.get_new_instance(map_i.get_id())
+                        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
                             # Create new map with basename
                             newident = self.basename + "_" + str(count)
                             newident = self.basename + "_" + str(count)
                             map_result = map_i.get_new_instance(newident + "@" + self.mapset)
                             map_result = map_i.get_new_instance(newident + "@" + self.mapset)
 
 
-                            if map_test.map_exists() and self.overwrite == False:
-                                self.msgr.fatal("Error raster maps with basename %s exist. "\
-                                                        "Use --o flag to overwrite existing file" \
-                                                        %(mapname))
+                            if map_b.map_exists() and self.overwrite == False:
+                                self.msgr.fatal("Error raster maps with basename %s exist. "
+                                                "Use --o flag to overwrite existing file"%map_i.get_id())
 
 
                             map_result.set_temporal_extent(map_i.get_temporal_extent())
                             map_result.set_temporal_extent(map_i.get_temporal_extent())
                             map_result.set_spatial_extent(map_i.get_spatial_extent())
                             map_result.set_spatial_extent(map_i.get_spatial_extent())
@@ -2062,34 +2080,36 @@ class TemporalAlgebraParser(object):
                             register_list.append(map_result)
                             register_list.append(map_result)
 
 
                             # Copy the map
                             # Copy the map
+                            m = copy.deepcopy(self.m_copy)
+                            m.flags["overwrite"].value = self.overwrite
+
                             if map_i.get_type() == 'raster':
                             if map_i.get_type() == 'raster':
-                                m = copy.deepcopy(self.m_copy)
                                 m.inputs["raster"].value = map_i.get_id(),  newident
                                 m.inputs["raster"].value = map_i.get_id(),  newident
-                                m.flags["overwrite"].value = self.overwrite
-                                process_queue.put(m)
                             elif map_i.get_type() == 'raster3d':
                             elif map_i.get_type() == 'raster3d':
-                                m = copy.deepcopy(self.m_copy)
                                 m.inputs["raster_3d"].value = map_i.get_id(),  newident
                                 m.inputs["raster_3d"].value = map_i.get_id(),  newident
-                                m.flags["overwrite"].value = self.overwrite
-                                process_queue.put(m)
                             elif map_i.get_type() == 'vector':
                             elif map_i.get_type() == 'vector':
-                                m = copy.deepcopy(self.m_copy)
                                 m.inputs["vector"].value = map_i.get_id(),  newident
                                 m.inputs["vector"].value = map_i.get_id(),  newident
-                                m.flags["overwrite"].value = self.overwrite
+
+                            # Add the process description to the dict
+                            self.process_chain_dict["processes"].append(m.get_dict())
+
+                            if self.dry_run is False:
                                 process_queue.put(m)
                                 process_queue.put(m)
                         else:
                         else:
                             register_list.append(map_i)
                             register_list.append(map_i)
-                        count  += 1
+
+                        count += 1
 
 
                     # Wait for running processes
                     # Wait for running processes
-                    process_queue.wait()
+                    if self.dry_run is False:
+                        process_queue.wait()
 
 
                     # Open connection to temporal database.
                     # Open connection to temporal database.
                     # Create result space time dataset based on the map stds type
                     # Create result space time dataset based on the map stds type
-                    resultstds = open_new_stds(t[1],maps_stds_type, \
-                                                             'absolute', t[1], t[1], \
-                                                             'mean', self.dbif, \
-                                                             overwrite = self.overwrite)
+                    resultstds = open_new_stds(t[1],maps_stds_type,
+                                               'absolute', t[1], t[1],
+                                               'mean', self.dbif,
+                                               overwrite=self.overwrite)
                     for map_i in register_list:
                     for map_i in register_list:
                         # Get meta data from grass database.
                         # Get meta data from grass database.
                         map_i.load()
                         map_i.load()
@@ -2102,29 +2122,39 @@ class TemporalAlgebraParser(object):
                                 if not self.register_null:
                                 if not self.register_null:
                                     self.removable_maps[map_i.get_name()] = map_i
                                     self.removable_maps[map_i.get_name()] = map_i
                                     continue
                                     continue
+
+                            start, end = map_i.get_temporal_extent_as_tuple()
+
                             if map_i.is_in_db(dbif) and self.overwrite:
                             if map_i.is_in_db(dbif) and self.overwrite:
                                 # Update map in temporal database.
                                 # Update map in temporal database.
-                                map_i.update_all(dbif)
+                                self.process_chain_dict["update"].append((map_i.get_name(), str(start), str(end)))
+                                if self.dry_run is False:
+                                    map_i.update_all(dbif)
                             elif map_i.is_in_db(dbif) and self.overwrite == False:
                             elif map_i.is_in_db(dbif) and self.overwrite == False:
                                 # Raise error if map exists and no overwrite flag is given.
                                 # Raise error if map exists and no overwrite flag is given.
                                 self.msgr.fatal("Error map %s exist in temporal database. "
                                 self.msgr.fatal("Error map %s exist in temporal database. "
-                                                        "Use overwrite flag.  : \n%s" \
-                                                        %(map_i.get_map_id(), cmd.popen.stderr))
+                                                        "Use overwrite flag."%map_i.get_map_id())
                             else:
                             else:
                                 # Insert map into temporal database.
                                 # Insert map into temporal database.
-                                map_i.insert(dbif)
+                                self.process_chain_dict["insert"].append((map_i.get_name(), str(start), str(end)))
+                                if self.dry_run is False:
+                                    map_i.insert(dbif)
                         # Register map in result space time dataset.
                         # Register map in result space time dataset.
-                        success = resultstds.register_map(map_i, dbif)
-                    resultstds.update_from_registered_maps(dbif)
+                        if self.dry_run is False:
+                            success = resultstds.register_map(map_i, dbif)
+                    if self.dry_run is False:
+                        resultstds.update_from_registered_maps(dbif)
                 elif num == 0:
                 elif num == 0:
-                    self.msgr.warning("Empty result space time dataset. "\
-                                                  "No map has been registered in %s"  %(t[1] ))
+                    self.msgr.warning("Empty result space time dataset. "
+                                      "No map has been registered in %s"%(t[1]))
                     # Open connection to temporal database.
                     # Open connection to temporal database.
                     # Create result space time dataset.
                     # Create result space time dataset.
-                    resultstds = open_new_stds(t[1], self.stdstype, \
-                                                             'absolute', t[1], t[1], \
-                                                             'mean', dbif, \
-                                                             overwrite = self.overwrite)
+                    if self.dry_run is False:
+                        resultstds = open_new_stds(t[1], self.stdstype,
+                                                   'absolute', t[1], t[1],
+                                                   'mean', dbif,
+                                                   overwrite=self.overwrite)
+
             if connected:
             if connected:
                 dbif.close()
                 dbif.close()
             t[0] = t[3]
             t[0] = t[3]
@@ -2214,14 +2244,13 @@ class TemporalAlgebraParser(object):
                 # Check for occurrence of space time dataset.
                 # Check for occurrence of space time dataset.
                 if map_i.map_exists() == False:
                 if map_i.map_exists() == False:
                     raise FatalError(_("%s map <%s> not found in GRASS spatial database") %
                     raise FatalError(_("%s map <%s> not found in GRASS spatial database") %
-                        (map_i.get_type(), id_input))
+                                      (map_i.get_type(), id_input))
                 else:
                 else:
                     # Select dataset entry from database.
                     # Select dataset entry from database.
                     map_i.select(dbif=self.dbif)
                     map_i.select(dbif=self.dbif)
             else:
             else:
-                raise FatalError(_("Wrong map type <%s> . TMAP only supports single "\
-                                             "maps that are registered in the temporal GRASS database")\
-                                              %(map_i.get_type()))
+                raise FatalError(_("Wrong map type. TMAP only supports single "
+                                   "maps that are registered in the temporal GRASS database"))
             # Return map object.
             # Return map object.
             t[0] = [map_i]
             t[0] = [map_i]
         else:
         else:
@@ -2466,7 +2495,6 @@ class TemporalAlgebraParser(object):
 
 
             t[0] = resultlist
             t[0] = resultlist
 
 
-
         if self.debug:
         if self.debug:
             print(t[1], t[3],  t[5], t[6])
             print(t[1], t[3],  t[5], t[6])
 
 
@@ -2591,7 +2619,7 @@ class TemporalAlgebraParser(object):
             maplistA     = self.check_stds(t[1])
             maplistA     = self.check_stds(t[1])
             maplistB     = self.check_stds(t[3])
             maplistB     = self.check_stds(t[3])
             # Evaluate temporal operator.
             # Evaluate temporal operator.
-            operators  = self.eval_toperator(t[2],  optype = 'select')
+            operators  = self.eval_toperator(t[2],  optype='select')
             # Check for negative selection.
             # Check for negative selection.
             if operators[2] == "!:":
             if operators[2] == "!:":
                 negation = True
                 negation = True
@@ -2599,7 +2627,8 @@ class TemporalAlgebraParser(object):
                 negation = False
                 negation = False
             # Perform selection.
             # Perform selection.
             selectlist = self.perform_temporal_selection(maplistA, maplistB,
             selectlist = self.perform_temporal_selection(maplistA, maplistB,
-                         topolist = operators[0], inverse = negation)
+                                                         topolist=operators[0],
+                                                         inverse=negation)
             selectlist = self.set_granularity(selectlist, maplistB, operators[1],
             selectlist = self.set_granularity(selectlist, maplistB, operators[1],
                 operators[0])
                 operators[0])
             # Return map list.
             # Return map list.
@@ -2647,7 +2676,7 @@ class TemporalAlgebraParser(object):
             thenlist     = self.check_stds(t[7])
             thenlist     = self.check_stds(t[7])
             # Get temporal conditional statement.
             # Get temporal conditional statement.
             tvarexpr     = t[5]
             tvarexpr     = t[5]
-            topolist     = self.eval_toperator(t[3],  optype = 'relation')[0]
+            topolist     = self.eval_toperator(t[3],  optype='relation')[0]
             thencond     = self.build_condition_list(tvarexpr, thenlist, topolist)
             thencond     = self.build_condition_list(tvarexpr, thenlist, topolist)
             thenresult   = self.eval_condition_list(thencond)
             thenresult   = self.eval_condition_list(thencond)
             # Clear the map and conditional values of the map list.
             # Clear the map and conditional values of the map list.

+ 34 - 20
lib/python/temporal/temporal_raster_base_algebra.py

@@ -530,13 +530,16 @@ class TemporalRasterBaseAlgebraParser(TemporalAlgebraParser):
     ###########################################################################
     ###########################################################################
 
 
     def p_statement_assign(self, t):
     def p_statement_assign(self, t):
-        # The expression should always return a list of maps.
+        # This function executes the processing of raster/raster3d algebra
+        # that was build based on the expression
         """
         """
         statement : stds EQUALS expr
         statement : stds EQUALS expr
         """
         """
         if self.run:
         if self.run:
             # Create the process queue for parallel mapcalc processing
             # Create the process queue for parallel mapcalc processing
-            process_queue = pymod.ParallelModuleQueue(int(self.nprocs))
+            if self.dry_run is False:
+                process_queue = pymod.ParallelModuleQueue(int(self.nprocs))
+
             if isinstance(t[3], list):
             if isinstance(t[3], list):
                 num = len(t[3])
                 num = len(t[3])
                 count = 0
                 count = 0
@@ -550,8 +553,8 @@ class TemporalRasterBaseAlgebraParser(TemporalAlgebraParser):
                     else:
                     else:
                         new_map = Raster3DDataset(map_name)
                         new_map = Raster3DDataset(map_name)
                     if new_map.map_exists() and self.overwrite == False:
                     if new_map.map_exists() and self.overwrite == False:
-                        self.msgr.fatal("Error maps with basename %s exist. Use --o flag to overwrite existing file" \
-                                            %(map_name))
+                        self.msgr.fatal("Error maps with basename %s exist. "
+                                        "Use --o flag to overwrite existing file"%map_name)
                 map_test_list = []
                 map_test_list = []
                 for map_i in t[3]:
                 for map_i in t[3]:
                     newident = self.basename + "_" + str(count)
                     newident = self.basename + "_" + str(count)
@@ -569,7 +572,9 @@ class TemporalRasterBaseAlgebraParser(TemporalAlgebraParser):
                         m_expression = newident + "=" + map_i.cmd_list
                         m_expression = newident + "=" + map_i.cmd_list
                         m.inputs["expression"].value = str(m_expression)
                         m.inputs["expression"].value = str(m_expression)
                         m.flags["overwrite"].value = self.overwrite
                         m.flags["overwrite"].value = self.overwrite
-                        process_queue.put(m)
+
+                        if self.dry_run is False:
+                            process_queue.put(m)
 
 
                     elif map_i.map_exists():
                     elif map_i.map_exists():
                         # Copy map if it exists
                         # Copy map if it exists
@@ -582,14 +587,16 @@ class TemporalRasterBaseAlgebraParser(TemporalAlgebraParser):
                         m_expression = newident + "=" + map_i.get_map_id()
                         m_expression = newident + "=" + map_i.get_map_id()
                         m.inputs["expression"].value = str(m_expression)
                         m.inputs["expression"].value = str(m_expression)
                         m.flags["overwrite"].value = self.overwrite
                         m.flags["overwrite"].value = self.overwrite
-                        print(m.get_bash())
-                        process_queue.put(m)
+
+                        if self.dry_run is False:
+                            process_queue.put(m)
 
 
                     else:
                     else:
-                        self.msgr.error(_("Error computing map <%s>"%(map_i.get_id()) ))
+                        self.msgr.error(_("Error computing map <%s>"%map_i.get_id()))
                     count  += 1
                     count  += 1
 
 
-                process_queue.wait()
+                if self.dry_run is False:
+                    process_queue.wait()
 
 
                 for map_i in map_test_list:
                 for map_i in map_test_list:
                     register_list.append(map_i)
                     register_list.append(map_i)
@@ -597,10 +604,12 @@ class TemporalRasterBaseAlgebraParser(TemporalAlgebraParser):
                 # Open connection to temporal database.
                 # Open connection to temporal database.
                 dbif, connect = init_dbif(self.dbif)
                 dbif, connect = init_dbif(self.dbif)
                 # Create result space time dataset.
                 # Create result space time dataset.
-                resultstds = open_new_stds(t[1], self.stdstype, \
-                                                         'absolute', t[1], t[1], \
-                                                         'mean', self.dbif, \
-                                                         overwrite = self.overwrite)
+
+                if self.dry_run is False:
+                    resultstds = open_new_stds(t[1], self.stdstype,
+                                               'absolute', t[1], t[1],
+                                               'mean', self.dbif,
+                                               overwrite = self.overwrite)
                 for map_i in register_list:
                 for map_i in register_list:
                     # Get meta data from grass database.
                     # Get meta data from grass database.
                     map_i.load()
                     map_i.load()
@@ -614,20 +623,25 @@ class TemporalRasterBaseAlgebraParser(TemporalAlgebraParser):
 
 
                     if map_i.is_in_db(dbif) and self.overwrite:
                     if map_i.is_in_db(dbif) and self.overwrite:
                         # Update map in temporal database.
                         # Update map in temporal database.
-                        map_i.update_all(dbif)
+                        if self.dry_run is False:
+                            map_i.update_all(dbif)
                     elif map_i.is_in_db(dbif) and self.overwrite == False:
                     elif map_i.is_in_db(dbif) and self.overwrite == False:
                         # Raise error if map exists and no overwrite flag is given.
                         # Raise error if map exists and no overwrite flag is given.
-                        self.msgr.fatal("Error raster map %s exist in temporal database. Use overwrite flag.  : \n%s" \
-                                            %(map_i.get_map_id(), cmd.popen.stderr))
+                        self.msgr.fatal("Error raster map %s exist in temporal database. "
+                                        "Use overwrite flag."%map_i.get_map_id())
                     else:
                     else:
                         # Insert map into temporal database.
                         # Insert map into temporal database.
-                        map_i.insert(dbif)
+                        if self.dry_run is False:
+                            map_i.insert(dbif)
                     # Register map in result space time dataset.
                     # Register map in result space time dataset.
-                    success = resultstds.register_map(map_i, dbif)
-                resultstds.update_from_registered_maps(dbif)
+                    if self.dry_run is False:
+                        success = resultstds.register_map(map_i, dbif)
+                if self.dry_run is False:
+                    resultstds.update_from_registered_maps(dbif)
+
                 dbif.close()
                 dbif.close()
                 t[0] = register_list
                 t[0] = register_list
-
+                # Remove intermediate maps
                 self.remove_maps()
                 self.remove_maps()
 
 
     def p_expr_spmap_function(self, t):
     def p_expr_spmap_function(self, t):

+ 14 - 2
temporal/t.select/t.select.py

@@ -40,6 +40,11 @@
 #% description: Activate spatial topology
 #% description: Activate spatial topology
 #%end
 #%end
 
 
+#%flag
+#% key: d
+#% description: Perform a dry run, compute all depenencies and module calls but don't run them
+#%end
+
 
 
 import grass.script as grass
 import grass.script as grass
 import grass.temporal as tgis
 import grass.temporal as tgis
@@ -51,6 +56,7 @@ def main():
 
 
     expression = options['expression']
     expression = options['expression']
     spatial = flags["s"]
     spatial = flags["s"]
+    dry_run = flags["d"]
     stdstype = options["type"]
     stdstype = options["type"]
 
 
     # Check for PLY istallation
     # Check for PLY istallation
@@ -61,8 +67,14 @@ def main():
         grass.fatal(_("Please install PLY (Lex and Yacc Python implementation) to use the temporal algebra modules."))
         grass.fatal(_("Please install PLY (Lex and Yacc Python implementation) to use the temporal algebra modules."))
 
 
     tgis.init(True)
     tgis.init(True)
-    p = tgis.TemporalAlgebraParser(run=True, debug=False, spatial = spatial)
-    p.parse(expression, stdstype,  overwrite=grass.overwrite)
+    p = tgis.TemporalAlgebraParser(run=True, debug=False, spatial=spatial, dry_run=dry_run)
+    pc = p.parse(expression, stdstype,  overwrite=grass.overwrite)
+
+    if dry_run is True:
+        import simplejson
+        s = simplejson.dumps(pc)
+        print(s)
+
 
 
 if __name__ == "__main__":
 if __name__ == "__main__":
     options, flags = grass.parser()
     options, flags = grass.parser()