Browse Source

Implemented input file with newline separated map names support in r.series. r.series now supports two input methods, file and input. Using option file is slower but avoids the open file descriptor limit. Temporal module tr.series is now ready to analyze ten-thousends of maps using r.series. Implemented tests for r.series and tr.series.

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@48638 15284696-431f-4ddb-bdfa-cd5b030d7da7
Soeren Gebbert 14 years ago
parent
commit
0092169701

+ 15 - 1
lib/python/temporal/abstract_datasets.py

@@ -107,7 +107,9 @@ class abstract_dataset(object):
 	self.metadata.insert(dbif)
 
     def update(self, dbif=None):
-	"""Update temporal dataset entry of database from the internal structure"""
+	"""Update temporal dataset entry of database from the internal structure
+	   excluding None variables
+	"""
 	self.base.update(dbif)
 	if self.is_time_absolute():
 	    self.absolute_time.update(dbif)
@@ -116,6 +118,18 @@ class abstract_dataset(object):
 	self.spatial_extent.update(dbif)
 	self.metadata.update(dbif)
 
+    def update_all(self, dbif=None):
+	"""Update temporal dataset entry of database from the internal structure
+	   and include None varuables.
+	"""
+	self.base.update_all(dbif)
+	if self.is_time_absolute():
+	    self.absolute_time.update_all(dbif)
+        if self.is_time_relative():
+	    self.relative_time.update_all(dbif)
+	self.spatial_extent.update_all(dbif)
+	self.metadata.update_all(dbif)
+
     def print_self(self):
 	"""Print the content of the internal structure to stdout"""
 	self.base.print_self()

+ 111 - 20
raster/r.series/main.c

@@ -107,22 +107,25 @@ int main(int argc, char *argv[])
     struct GModule *module;
     struct
     {
-	struct Option *input, *output, *method, *quantile, *range;
+	struct Option *input, *file, *output, *method, *quantile, *range;
     } parm;
     struct
     {
 	struct Flag *nulls;
     } flag;
+    FILE *in = NULL;
     int i;
     int num_inputs;
+    int num_lines;
     struct input *inputs;
     int num_outputs;
     struct output *outputs;
     struct History history;
     DCELL *values, *values_tmp;
     int nrows, ncols;
-    int row, col;
+    int row, col, count;
     double lo, hi;
+    char buf[GNAME_MAX];
 
     G_gisinit(argv[0]);
 
@@ -135,6 +138,12 @@ int main(int argc, char *argv[])
 	  "in the input raster map layers.");
 
     parm.input = G_define_standard_option(G_OPT_R_INPUTS);
+    parm.input->required = NO;
+
+    parm.file = G_define_standard_option(G_OPT_F_INPUT);
+    parm.file->key = "file";
+    parm.file->description = _("Input file with raster map names, separated by new lines");
+    parm.file->required = NO;
 
     parm.output = G_define_standard_option(G_OPT_R_OUTPUT);
     parm.output->multiple = YES;
@@ -172,24 +181,94 @@ int main(int argc, char *argv[])
 	lo = atof(parm.range->answers[0]);
 	hi = atof(parm.range->answers[1]);
     }
+    
+    if (parm.input->answer && parm.file->answer)
+        G_fatal_error("The parameter <input> and <file> are mutual exclusive");
+ 
+    if (!parm.input->answer && !parm.file->answer)
+        G_fatal_error("You need to specify input or file option");
+
+
+    /* process the input maps from the file */
+    if (parm.file->answer) {
+   
+	/* Open the input file with raster map names and count the lines */
+	in = fopen(parm.file->answer, "r");
+    
+	if(in == NULL)
+	    G_fatal_error(_("Unable to open input file <%s>"), parm.file->answer);
+    
+	num_inputs = 0;
+	num_lines = 0;
+    
+	/* Count lines in file and check the input */
+	while (fgets(buf, sizeof buf, in)) {
+	    num_lines++;
+	    /* Jump over invlaid files and empty new lines */
+	    if (strlen(buf) < 2 || G_check_input_output_name(G_chop(buf), 
+			       parm.output->answer, GR_FATAL_RETURN)) {
+		G_warning(_("Raster map <%s> is not valid"), G_chop(buf));
+		continue;
+	    }
+	    /* Count number of valid input names */
+	    num_inputs++;
+	}
 
-    /* process the input maps */
-    for (i = 0; parm.input->answers[i]; i++)
-	;
-    num_inputs = i;
+	fclose(in);
 
-    if (num_inputs < 1)
-	G_fatal_error(_("Raster map not found"));
+	if (num_inputs < 1)
+	    G_fatal_error(_("No raster map found in input file"));
 
-    inputs = G_malloc(num_inputs * sizeof(struct input));
+	inputs = G_malloc(num_inputs * sizeof(struct input));
 
-    for (i = 0; i < num_inputs; i++) {
-	struct input *p = &inputs[i];
+	/* Reopen the input file and read the map names */
+	in = fopen(parm.file->answer, "r");
 
-	p->name = parm.input->answers[i];
-	G_message(_("Reading raster map <%s>..."), p->name);
-	p->fd = Rast_open_old(p->name, "");
-	p->buf = Rast_allocate_d_buf();
+	count = 0;
+	for (i = 0; i < num_lines; i++) {
+	    fgets(buf, sizeof buf, in); 
+
+	    char *name = G_calloc(strlen(buf) + 1, sizeof(char));
+	    G_snprintf(name, strlen(buf), "%s", buf);
+
+	    /* Jump over invlaid files and empty new lines */
+	    if (strlen(buf) < 2 || G_check_input_output_name(G_chop(buf), 
+			       parm.output->answer, GR_FATAL_RETURN)) {
+	    G_free(name);
+	    continue;
+	    }
+
+	    struct input *p = &inputs[count];
+	    p->name = G_chop(name);
+	    G_message(_("Reading raster map <%s>..."), p->name);
+	    p->buf = Rast_allocate_d_buf();
+	    count++;
+	}
+    
+	if(count != num_inputs)
+	    G_fatal_error(_("An internal error occured"));
+
+	fclose(in);
+	 
+    } else {
+    
+    	for (i = 0; parm.input->answers[i]; i++)
+	    ;
+    	num_inputs = i;
+
+    	if (num_inputs < 1)
+	    G_fatal_error(_("Raster map not found"));
+
+    	inputs = G_malloc(num_inputs * sizeof(struct input));
+
+    	for (i = 0; i < num_inputs; i++) {
+	    struct input *p = &inputs[i];
+
+	    p->name = parm.input->answers[i];
+	    G_message(_("Reading raster map <%s>..."), p->name);
+	    p->fd = Rast_open_old(p->name, "");
+	    p->buf = Rast_allocate_d_buf();
+    	}
     }
 
     /* process the output maps */
@@ -233,8 +312,17 @@ int main(int argc, char *argv[])
     for (row = 0; row < nrows; row++) {
 	G_percent(row, nrows, 2);
 
-	for (i = 0; i < num_inputs; i++)
-	    Rast_get_d_row(inputs[i].fd, inputs[i].buf, row);
+	if (parm.file->answer) {
+	    /* Open the files only on run time */
+	    for (i = 0; i < num_inputs; i++) {
+		inputs[i].fd = Rast_open_old(inputs[i].name, "");
+		Rast_get_d_row(inputs[i].fd, inputs[i].buf, row);
+		Rast_close(inputs[i].fd);
+	    }
+	} else {
+	    for (i = 0; i < num_inputs; i++)
+	        Rast_get_d_row(inputs[i].fd, inputs[i].buf, row);
+	}
 
 	for (col = 0; col < ncols; col++) {
 	    int null = 0;
@@ -270,7 +358,7 @@ int main(int argc, char *argv[])
 
     G_percent(row, nrows, 2);
 
-    /* close maps */
+    /* close output maps */
     for (i = 0; i < num_outputs; i++) {
 	struct output *out = &outputs[i];
 
@@ -281,8 +369,11 @@ int main(int argc, char *argv[])
 	Rast_write_history(out->name, &history);
     }
 
-    for (i = 0; i < num_inputs; i++)
-	Rast_close(inputs[i].fd);
+    /* Close input maps */
+    if (!parm.file->answer) {
+    	for (i = 0; i < num_inputs; i++)
+	    Rast_close(inputs[i].fd);
+    }
 
     exit(EXIT_SUCCESS);
 }

+ 22 - 1
raster/r.series/r.series.html

@@ -69,6 +69,15 @@ your_username  hard    nofile          1500
 This would raise the hard limit to 1500 file. Be warned that more
 files open need more RAM.
 
+<p>
+Use the <em>file</em> option to analyze large amount of raster maps without 
+hitting open files limit and the size limit of command line arguments. 
+The computation is slower than the <em>input</em> option method. 
+For every sinlge row in the output map(s) 
+all input maps are opened and closed. The amount of RAM will rise linear
+with the number of specified input maps. The input and file options are mutual exclusive.
+Input is a text file with a new line separatetd list of raster map names. 
+
 <h2>EXAMPLES</h2>
 
 Using <em>r.series</em> with wildcards:
@@ -95,6 +104,18 @@ Example for multiple aggregates to be computed in one run (3 resulting aggregate
 r.series in=one,two out=result_avg,res_slope,result_count meth=sum,slope,count
 </pre></div>
 
+<p>
+Example to use the file option of r.series:
+<div class="code"><pre>
+cat > input.txt << EOF
+map1
+map2
+map3
+EOF
+
+r.series2 file=input.txt out=result_sum meth=sum
+</pre></div>
+
 <h2>SEE ALSO</h2>
 
 <em><a href="g.mlist.html">g.mlist</a></em>,
@@ -104,4 +125,4 @@ r.series in=one,two out=result_avg,res_slope,result_count meth=sum,slope,count
 
 Glynn Clements
 
-<p><i>Last changed: $Date$</i>
+<p><i>Last changed: $Date$</i>

+ 61 - 0
raster/r.series/test.r.series.sh

@@ -0,0 +1,61 @@
+# Test r.series basic aggregation functions with map and file inputs
+# We need to set a specific region in the
+# @preprocess step of this test. We generate
+# raster with r.mapcalc 
+# The region setting should work for UTM and LL test locations
+g.region s=0 n=80 w=0 e=120 b=0 t=50 res=10 res3=10 -p3
+
+r.mapcalc --o expr="prec_1 = 100"
+r.mapcalc --o expr="prec_2 = 200"
+r.mapcalc --o expr="prec_3 = 300"
+r.mapcalc --o expr="prec_4 = 400"
+r.mapcalc --o expr="prec_5 = 500"
+r.mapcalc --o expr="prec_6 = 600"
+
+TMP_FILE=`g.tempfile pid=1`
+# We create an input file containing errors. However, r.series should process the 
+# valid raster maps listed in this file.
+cat > $TMP_FILE << EOF
+prec_1
+prec_2
+prec_3
+
+invalid_name
+
+prec_4
+prec_5
+prec_6
+
+
+
+EOF
+
+# The first @test with map input and @precision=3
+r.series --o input=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6 output=test_1_prec_mean method=average
+r.series --o input=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6 output=test_1_prec_max method=maximum
+r.series --o input=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6 output=test_1_prec_min method=minimum
+r.series --o input=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6 output=test_1_prec_count method=count
+r.series --o input=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6 output=test_1_prec_range method=range
+r.series --o input=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6 output=test_1_prec_sum method=sum
+
+#r.out.ascii --o input=test_1_prec_mean output=test_1_prec_mean.ref dp=3
+#r.out.ascii --o input=test_1_prec_max output=test_1_prec_max.ref dp=3
+#r.out.ascii --o input=test_1_prec_min output=test_1_prec_min.ref dp=3
+#r.out.ascii --o input=test_1_prec_count output=test_1_prec_count.ref dp=3
+#r.out.ascii --o input=test_1_prec_range output=test_1_prec_range.ref dp=3
+#r.out.ascii --o input=test_1_prec_sum output=test_1_prec_sum.ref dp=3
+
+# The second @test with file input and @precision=3
+r.series --o file=$TMP_FILE output=test_2_prec_mean method=average
+r.series --o file=$TMP_FILE output=test_2_prec_max method=maximum
+r.series --o file=$TMP_FILE output=test_2_prec_min method=minimum
+r.series --o file=$TMP_FILE output=test_2_prec_count method=count
+r.series --o file=$TMP_FILE output=test_2_prec_range method=range
+r.series --o file=$TMP_FILE output=test_2_prec_sum method=sum
+
+#r.out.ascii --o input=test_2_prec_mean output=test_2_prec_mean.ref dp=3
+#r.out.ascii --o input=test_2_prec_max output=test_2_prec_max.ref dp=3
+#r.out.ascii --o input=test_2_prec_min output=test_2_prec_min.ref dp=3
+#r.out.ascii --o input=test_2_prec_count output=test_2_prec_count.ref dp=3
+#r.out.ascii --o input=test_2_prec_range output=test_2_prec_range.ref dp=3
+#r.out.ascii --o input=test_2_prec_sum output=test_2_prec_sum.ref dp=3

+ 14 - 0
raster/r.series/test_1_prec_count.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+6 6 6 6 6 6 6 6 6 6 6 6 
+6 6 6 6 6 6 6 6 6 6 6 6 
+6 6 6 6 6 6 6 6 6 6 6 6 
+6 6 6 6 6 6 6 6 6 6 6 6 
+6 6 6 6 6 6 6 6 6 6 6 6 
+6 6 6 6 6 6 6 6 6 6 6 6 
+6 6 6 6 6 6 6 6 6 6 6 6 
+6 6 6 6 6 6 6 6 6 6 6 6 

+ 14 - 0
raster/r.series/test_1_prec_max.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 

+ 14 - 0
raster/r.series/test_1_prec_mean.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 

+ 14 - 0
raster/r.series/test_1_prec_min.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 

+ 14 - 0
raster/r.series/test_1_prec_range.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+500 500 500 500 500 500 500 500 500 500 500 500 
+500 500 500 500 500 500 500 500 500 500 500 500 
+500 500 500 500 500 500 500 500 500 500 500 500 
+500 500 500 500 500 500 500 500 500 500 500 500 
+500 500 500 500 500 500 500 500 500 500 500 500 
+500 500 500 500 500 500 500 500 500 500 500 500 
+500 500 500 500 500 500 500 500 500 500 500 500 
+500 500 500 500 500 500 500 500 500 500 500 500 

+ 14 - 0
raster/r.series/test_1_prec_sum.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 
+2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 
+2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 
+2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 
+2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 
+2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 
+2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 
+2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 

+ 14 - 0
raster/r.series/test_2_prec_count.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+6 6 6 6 6 6 6 6 6 6 6 6 
+6 6 6 6 6 6 6 6 6 6 6 6 
+6 6 6 6 6 6 6 6 6 6 6 6 
+6 6 6 6 6 6 6 6 6 6 6 6 
+6 6 6 6 6 6 6 6 6 6 6 6 
+6 6 6 6 6 6 6 6 6 6 6 6 
+6 6 6 6 6 6 6 6 6 6 6 6 
+6 6 6 6 6 6 6 6 6 6 6 6 

+ 14 - 0
raster/r.series/test_2_prec_max.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 
+600 600 600 600 600 600 600 600 600 600 600 600 

+ 14 - 0
raster/r.series/test_2_prec_mean.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 
+350 350 350 350 350 350 350 350 350 350 350 350 

+ 14 - 0
raster/r.series/test_2_prec_min.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 
+100 100 100 100 100 100 100 100 100 100 100 100 

+ 14 - 0
raster/r.series/test_2_prec_range.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+500 500 500 500 500 500 500 500 500 500 500 500 
+500 500 500 500 500 500 500 500 500 500 500 500 
+500 500 500 500 500 500 500 500 500 500 500 500 
+500 500 500 500 500 500 500 500 500 500 500 500 
+500 500 500 500 500 500 500 500 500 500 500 500 
+500 500 500 500 500 500 500 500 500 500 500 500 
+500 500 500 500 500 500 500 500 500 500 500 500 
+500 500 500 500 500 500 500 500 500 500 500 500 

+ 14 - 0
raster/r.series/test_2_prec_sum.ref

@@ -0,0 +1,14 @@
+north: 80N
+south: 0
+east: 120E
+west: 0
+rows: 8
+cols: 12
+2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 
+2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 
+2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 
+2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 
+2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 
+2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 
+2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 
+2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 2100 

+ 2 - 2
temporal/tr.register/register_ECAD_maps_temp_mean_1995_2010.py

@@ -11,7 +11,7 @@ grass.run_command("t.create", type="strds", dataset=dataset, granularity="1 days
 name = "temp_mean."
 maps=""
 #for i in range(6025):
-for i in range(365):
+for i in range(5844):
     inc = i + 1
     map_name = name + str(inc)
     if i == 0:
@@ -20,4 +20,4 @@ for i in range(365):
         maps += "," + map_name
     
 # Register all maps at once
-grass.run_command("tr.register", dataset=dataset, maps=maps, start="1995-01-01", increment="1 days")
+grass.run_command("tr.register", flags="i", dataset=dataset, maps=maps, start="1995-01-01", increment="1 days")

+ 10 - 11
temporal/tr.series/test.tr.series.sh

@@ -10,12 +10,12 @@
 # The region setting should work for UTM and LL test locations
 g.region s=0 n=80 w=0 e=120 b=0 t=50 res=10 res3=10 -p3
 
-r.mapcalc --o expr="prec_1 = rand(0, 550)"
-r.mapcalc --o expr="prec_2 = rand(0, 450)"
-r.mapcalc --o expr="prec_3 = rand(0, 320)"
-r.mapcalc --o expr="prec_4 = rand(0, 510)"
-r.mapcalc --o expr="prec_5 = rand(0, 300)"
-r.mapcalc --o expr="prec_6 = rand(0, 650)"
+r.mapcalc --o expr="prec_1 = 100"
+r.mapcalc --o expr="prec_2 = 200"
+r.mapcalc --o expr="prec_3 = 300"
+r.mapcalc --o expr="prec_4 = 400"
+r.mapcalc --o expr="prec_5 = 500"
+r.mapcalc --o expr="prec_6 = 600"
 
 # The first @test
 # We create the space time raster datasets and register the raster maps with absolute time interval
@@ -25,13 +25,12 @@ t.create --v --o type=strds temporaltype=absolute dataset=precip_abs gran="1 mon
 tr.register --v dataset=precip_abs maps=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6 start="2001-01-01" increment="1 months"
 
 tr.series --o input=precip_abs method=average output=prec_average where='start_time > "2001-03-01"'
-tr.series --o input=precip_abs method=maximum output=prec_max sort=north
-tr.series --o input=precip_abs method=sum output=prec_sum
-#tr.series --o input=precip_abs method=quantile output=prec_quant quantile=0.9
+tr.series --o -t input=precip_abs method=maximum output=prec_max sort=start_time
+tr.series --o -t input=precip_abs method=sum output=prec_sum
 
 t.remove --v type=raster dataset=prec_1,prec_2,prec_3,prec_4,prec_5,prec_6
 t.remove --v type=strds dataset=precip_abs
 
 r.info prec_average
-r.info prec_max
-r.info prec_sum
+t.info type=raster dataset=prec_max
+t.info type=raster dataset=prec_sum

+ 42 - 12
temporal/tr.series/tr.series.py

@@ -55,6 +55,11 @@
 #%option G_OPT_R_OUTPUT
 #%end
 
+#%flag
+#% key: t
+#% description: Assign the space time raster dataset time interval to the output map
+#%end
+
 import grass.script as grass
 import grass.temporal as tgis
 
@@ -68,6 +73,7 @@ def main():
     method = options["method"]
     sort = options["sort"]
     where = options["where"]
+    add_time = flags["t"]
 
     # Make sure the temporal database exists
     tgis.create_temporal_database()
@@ -84,27 +90,51 @@ def main():
         grass.fatal(_("Dataset <%s> not found in temporal database") % (id))
 
     sp.select()
+    
+    if add_time:
+	if sp.is_time_absolute():
+	    start_time, end_time, tz = sp.get_absolute_time()
+	else:
+	    start_time, end_time = sp.get_relative_time()
 
     rows = sp.get_registered_maps(None, where, sort)
 
     if rows:
-        inputs = ""
+        filename = grass.tempfile(True)
+        file = open(filename, 'w')
 
-        count = 0
         for row in rows:
-            if count == 0:
-                inputs += row["id"]
-            else:
-                inputs += "," + row["id"]
-            count += 1
-
-        print inputs
+            string = "%s\n" % (row["id"])
+            file.write(string)
+        
+        file.close()
 
         if grass.overwrite() == True:
-            grass.run_command("r.series", input=inputs, output=output, overwrite=True, method=method)
+            grass.run_command("r.series", file=filename, output=output, overwrite=True, method=method)
         else:
-            grass.run_command("r.series", input=inputs, output=output, overwrite=False, method=method)
-
+            grass.run_command("r.series", file=filename, output=output, overwrite=False, method=method)
+
+    if add_time:
+	# Create the time range for the output map
+	if output.find("@") >= 0:
+	    id = output
+	else:
+	    mapset =  grass.gisenv()["MAPSET"]
+	    id = output + "@" + mapset
+
+	map = sp.get_new_map_instance(id)
+
+	map.load()
+	if sp.is_time_absolute():
+	    map.set_absolute_time(start_time, end_time, tz)
+	else:
+	    map.set_relative_time(start_time, end_time)
+
+	# Register the map in the temporal database
+	if map.is_in_db():
+	    map.update()
+	else:
+	    map.insert()    
 
 if __name__ == "__main__":
     options, flags = grass.parser()