ForEST Demo 1

This Notebook provide a brief demonstration of a domain-specific programming language For Expressing Spatial-Temporal computing called ForEST. In short, ForEST makes it easier to write programs for Geographic Information Science, because it is a programming language for GIScience. ForEST also strives to be a 'community‐owned innovation platform for GIScience research' quoted from Mark Gahegan's publication entitled 'Our GIS is too small' published in the Canadian Geographer by providing a way to express the computational components that undergird GIScience.

Let's get started

First, we will import the ForEST programming langauge.


In [2]:
# Let's pull ForEST in using import
from forest import *

In [3]:
# A choice of Engines (Multi-Processing, Tile, or the Pass (do nothing) Engine)
Config.engine=mp_engine
Config.engine=tile_engine
Config.engine=pass_engine

# Create two 10x10 rasters for demonstration purposes
r1 = Raster()
r2 = Raster()

# Print out raster 1 and it's data
print(r1)
print(r1.data)


10.0 10.0
10.0 10.0
Bob (0.000000,0.000000) [10.000000,10.000000]
[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]

In [4]:
# Modify 2 cells in raster 1

r1.data[0][0]=10
r1.data[3][3]=20

# Print out raster 1 and it's data
print(r1)
print(r1.data)


Bob (0.000000,0.000000) [10.000000,10.000000]
[[10.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0. 20.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]]

In [5]:
# Modify a few cells in raster 2

r2.data[0][0]=1
r2.data[0][1]=2
r2.data[0][2]=3
r2.data[0][3]=4

# Print out raster 2 and it's data
print(r2)
print(r2.data)


Bob (0.000000,0.000000) [10.000000,10.000000]
[[1. 2. 3. 4. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]

In [6]:
# Apply local sum and print out the results
# Notice: We can do map algebra here using ForEST!

ro = r1+r2

# You will see some PUSH/POP messages when calling LocalSum
# This is ForEST processing r1 and r2 using the data stack.

# Print out the output
print(ro)
print(ro.data)


PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
POP
POP
PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
POP
Bob (0.000000,0.000000) [10.000000,10.000000]
[[11.  2.  3.  4.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0. 20.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]]

In [7]:
# Try adding them and printing out the results again (hint they should be identical)

o = r1+r2

print(o)
print(o.data)


PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
POP
POP
PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
POP
Bob (0.000000,0.000000) [10.000000,10.000000]
[[11.  2.  3.  4.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0. 20.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]]

In [8]:
# Try adding the two results together and print them out

o2 = ro + o

print("o2",o2)
print(o2.data)


PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
POP
POP
PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
POP
o2 Bob (0.000000,0.000000) [10.000000,10.000000]
[[22.  4.  6.  8.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0. 40.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]]

In [9]:
# Subtract the first result from the second result, see what you get.

sub = ro - o

print("sub",sub)
print(sub.data)


PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
POP
POP
PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
POP
sub Bob (0.000000,0.000000) [10.000000,10.000000]
[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]

In [10]:
# Now let's try to divide them.
# Notice we should get some not-a-number (nan) results and a warning.
# This is due to the fact that o2 has some zeros.

div = ro / o2

print("div",div)
print(div.data)


PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
POP
POP
PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
POP
div Bob (0.000000,0.000000) [10.000000,10.000000]
[[0.5 0.5 0.5 0.5 nan nan nan nan nan nan]
 [nan nan nan nan nan nan nan nan nan nan]
 [nan nan nan nan nan nan nan nan nan nan]
 [nan nan nan 0.5 nan nan nan nan nan nan]
 [nan nan nan nan nan nan nan nan nan nan]
 [nan nan nan nan nan nan nan nan nan nan]
 [nan nan nan nan nan nan nan nan nan nan]
 [nan nan nan nan nan nan nan nan nan nan]
 [nan nan nan nan nan nan nan nan nan nan]
 [nan nan nan nan nan nan nan nan nan nan]]
/home/shook/Github/Forest/forest/primitives/PrimitivesRaster.py:66: RuntimeWarning: invalid value encountered in true_divide
  return np.divide(l,r)

In [11]:
# What about multiply? Yay it works too!

mul = ro * o

print("mul",mul)
print(mul.data)


PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
POP
POP
PUSH Bob (0.000000,0.000000) [10.000000,10.000000]
POP
mul Bob (0.000000,0.000000) [10.000000,10.000000]
[[121.   4.   9.  16.   0.   0.   0.   0.   0.   0.]
 [  0.   0.   0.   0.   0.   0.   0.   0.   0.   0.]
 [  0.   0.   0.   0.   0.   0.   0.   0.   0.   0.]
 [  0.   0.   0. 400.   0.   0.   0.   0.   0.   0.]
 [  0.   0.   0.   0.   0.   0.   0.   0.   0.   0.]
 [  0.   0.   0.   0.   0.   0.   0.   0.   0.   0.]
 [  0.   0.   0.   0.   0.   0.   0.   0.   0.   0.]
 [  0.   0.   0.   0.   0.   0.   0.   0.   0.   0.]
 [  0.   0.   0.   0.   0.   0.   0.   0.   0.   0.]
 [  0.   0.   0.   0.   0.   0.   0.   0.   0.   0.]]