Quick introduction to GRASS GIS Temporal Framework

The GRASS GIS Temporal Framework implements temporal GIS functionality at user level and provides additionally an API to implement new spatio-temporal processing modules.

The temporal framework introduces space time datasets to represent time series of raster, 3D raster or vector maps. It provides the following functionalities:

  • Assign time stamp to maps and register maps in the temporal database
  • Modification of time stamps
  • Creation, renaming and deletion of space time datasets
  • Registration and un-registration of maps in space time datasets
  • Query of maps that are registered in space time datasets using SQL 'WHERE' statements
  • Analysis of the spatio-temporal topology of space time datasets
  • Sampling of space time datasets
  • Computation of temporal and spatial relationships between registered maps
  • Higher level functions that are shared between modules
  • Most of the functions described above are member functions of dedicated map layer and space time dataset classes.

Three related datatypes are available:

  • Space time raster datasets (strds) are designed to manage raster map time series. Modules that process strds have the naming prefix t.rast
  • Space time 3D raster datasets (str3ds) are designed to manage 3D raster map time series. Modules that process str3ds have the naming prefix t.rast3d
  • Space time vector datasets (stvds) are designed to manage vector map time series. Modules that process stvds have the naming prefix t.vect

Reference: Gebbert, S., Pebesma, E., 2014. TGRASS: A temporal GIS for field based environmental modeling. Environmental Modelling & Software 53, 1-12. http://dx.doi.org/10.1016/j.envsoft.2013.11.001


In [ ]:
import grass.temporal as tgis
import grass.script as gscript

Creating a new temporal dataset

First, we initialize temporal database:


In [ ]:
tgis.init()

Next, we create an empty space-time raster dataset. We specify its name, its type (here: strds), temporal type (absolute, relative), title and description. You can imagine a temporal dataset as a container for selected data which puts them into order, describes their space-time relationships and saves all kind of metadata. The maps themselves remain standard GRASS GIS maps.


In [ ]:
dataset_name = 'temperature'
dataset = tgis.open_new_stds(name=dataset_name, type='strds', temporaltype='absolute',
                             title="Temperature in Raleigh", descr="Created for test purposes",
                             semantic='mean', overwrite=True)

Check if the temporal dataset was created:


In [ ]:
# Print some info about the new dataset
dataset.print_shell_info()

Register maps into temporal dataset

Create a set of random maps of temperature using min and max values


In [ ]:
# monthly mean Raleigh temperature
nc_temp_data = {1:[30, 51], 2: [32, 54], 3: [40, 63], 4: [48, 72],
                5:[57, 80], 6: [66, 87], 7: [70, 90], 8: [69, 88],
                9:[62, 82], 10:[50, 73], 11:[41, 64], 12:[32, 54]}
# list of maps to add into temporal dataset
maps = []
gscript.run_command('g.region', raster='elevation')
for month, values in nc_temp_data.iteritems():
    map_name = "temp_{mon}".format(mon=month)
    gscript.run_command('r.random.surface', output=map_name, seed=values, high=values[1], overwrite=True)
    maps.append(map_name)
print maps

Now we register the created maps within the temporal dataset:


In [ ]:
tgis.register_maps_in_space_time_dataset(type='raster', name=dataset_name, maps=','.join(maps), start='2014-01-01',
                                         increment="1 month", interval=True, update_cmd_list=True)

Next we update the information of temporal dataset and print its metadata:


In [ ]:
dataset.update_from_registered_maps()
dataset.print_shell_info()

Query an existing temporal dataset

During this session you will learn how to extract values for a point from a temporal dataset.


In [ ]:
coors = (638000, 222800.0)

We get the temporal dataset object:


In [ ]:
strds = tgis.open_old_stds(dataset_name, "strds")

Now it is possible to obtain all the registered maps:


In [ ]:
rows = strds.get_registered_maps(columns="name,mapset,start_time,end_time",
                                 where=None, order="start_time")

Get useful info (as name, starting time) about registered maps and query the data using the GRASS GIS command r.what:


In [ ]:
from collections import OrderedDict
infos = OrderedDict()
for row in rows:
    name = row["name"] + "@" + row["mapset"]
    values = gscript.read_command('r.what', map=name, coordinates=coors).strip().split('|')
    infos[name] = {'date': row["start_time"], 'value': values[3]}
print infos

Write CSV file

To write out a CSV file in Python, the CSV module should be used. So, import the CSV and the tempfile modules to then create a new CSV file in the temporal directory:


In [ ]:
import csv
import tempfile
fil = tempfile.NamedTemporaryFile(delete=False)
fil.name = fil.name + '.csv'
print fil.name

Now, for each record read from the temporal dataset, the procedure stores the respective record in the CSV file:


In [ ]:
with open(fil.name, 'wb') as csvfile:
    spamwriter = csv.writer(csvfile, delimiter=';',
                            quoting=csv.QUOTE_MINIMAL)
    spamwriter.writerow(['Map_name', 'Date', 'Temp'])
    
    for mapp, vals in infos.iteritems():
        spamwriter.writerow([mapp, vals['date'].strftime('%Y-%m-%d'), vals['value']])
fil.close()

For verification, we can simply print the CSV file to the terminal using the cat shell command:


In [ ]:
!cat {fil.name}

Plot data using Matplotlib

To print the data using Matplotlib some libraries have to be imported first:


In [ ]:
%matplotlib notebook
import matplotlib.pyplot as plt
import matplotlib.dates as mdates

Next we create the list of values for the x and y axes:


In [ ]:
x = []
y = []
for mapp, vals in infos.iteritems():
    x.append(vals['date'])
    y.append(vals['value'])
print x
print y

Finally we plot the temperature values over time:


In [ ]:
# create the plot
fig, ax = plt.subplots()
# create the plot line
ax.plot(x,y, label='2014 monthly temperature', color='red')
# set the format of X axis label
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
# set the title of graph
plt.title('Monthly temperature');
# add legend and set it lower-center position
ax.legend(loc='lower center')
# fix the position/rotation of X lavel
fig.autofmt_xdate()
# set the label for X and Y axis
ax.set_xlabel('Month')
ax.set_ylabel('Fahrenheit temp')
# show the graph
plt.show()

Some other tips

Unregistering maps

To remove maps from a temporal dataset (they will not be truly deleted but just unregistered from the temporal dataset), first a map object should be created. Then, using this new dataset object, we remove the selected map(s) using the unregister_map function:


In [ ]:
remove_map = tgis.RasterDataset('temp_12@{mapset}'.format(mapset=gscript.gisenv()['MAPSET']))
dataset.unregister_map(remove_map)
dataset.update_from_registered_maps()

Deleting a temporal dataset

Removing a space time datasets from temporal database (again, the contained maps remain in GRASS GIS) can be done directly from the same object using the delete function:


In [ ]:
dataset.delete()

In [ ]: