public
Description: Imports data from the NASA Shuttle Radar Topography Mission into a PostGIS database (and other databases in the futue).
Homepage: http://wiki.openstreetmap.org/index.php/Route_altitude_profiles_SRTM#SRTM_import
Clone URL: git://github.com/Sjors/srtm2postgis.git
Insert one tile in database

* Use Psycopg2 for insert in stead of PyGreSQL. PyGreSQL crashed my Postgres 
server for some reason.

* Call Postgres COPY command through a sub process, because the
  Psycopg2 method hangs.

* Insert a tile into the database.

* Create a smaller test tile to speed up the tests

* Read tile from database

* Verify that inserted tile is the same as the read file
Sjors (author)
Fri May 30 20:38:43 -0700 2008
commit  03ea05a94b087b61503ef1b5cb74b8076c972ad9
tree    653e76dce2980514bd91e352b7ca6c8d6348d5f5
parent  4d2c916c74a31fe822a5465bc66b0b9af6ecf453
...
1
2
 
3
4
5
 
 
6
7
8
...
19
20
21
 
22
23
24
25
 
 
 
 
26
27
28
...
31
32
33
34
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
36
37
38
39
40
 
 
41
42
43
44
45
 
 
46
47
...
1
 
2
3
4
5
6
7
8
9
10
...
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
38
39
40
 
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
 
 
 
 
 
149
150
151
 
 
 
 
152
153
154
 
0
@@ -1,8 +1,10 @@
0
 # Read srtm data files and put them in the database.
0
-import pg
0
+import pg, psycopg2
0
 from osgeo import gdal, gdal_array
0
 import database 
0
 import sys
0
+import re
0
+from math import sqrt
0
 
0
 # Main functions
0
 
0
@@ -19,10 +21,15 @@ def createTableAltitude(db):
0
       PRIMARY KEY ( lat, lon ) \
0
     ); \
0
   ")
0
+  return True
0
   
0
 def connectToDatabase(database):
0
     return pg.DB(dbname=database.db,host='localhost', user=database.db_user, passwd=database.db_pass)
0
       
0
+def connectToDatabasePsycopg2(database):
0
+    conn = psycopg2.connect("dbname='" + database.db + "' host='localhost' user='" + database.db_user + "' password='" + database.db_pass + "'")
0
+    return conn.cursor()
0
+      
0
 
0
 def dropAllTables(db):
0
     db.query("DROP TABLE IF EXISTS altitude;")
0
@@ -31,17 +38,117 @@ def checkDatabaseEmpty(db):
0
     # Test is the test database is as we expect it after setUp:
0
     return db.get_tables() == ['information_schema.sql_features', 'information_schema.sql_implementation_info', 'information_schema.sql_languages', 'information_schema.sql_packages', 'information_schema.sql_parts', 'information_schema.sql_sizing', 'information_schema.sql_sizing_profiles', 'public.geometry_columns', 'public.spatial_ref_sys']
0
 
0
-db = connectToDatabase(database) 
0
+def insertTileIntoDatabase(cur, db_name, tile, lat0, lon0):
0
+  # I use the Psycopg2 connection, with its copy_to and 
0
+  # copy_from commands, which use the more efficient COPY command. 
0
+  # This method requires a temporary file.
0
+  
0
+  # First we write the data into a temporary file.
0
+  f = open('/tmp/tempcopy', 'w')
0
+  for row in range(len(tile) - 1):
0
+    for col in range(len(tile) - 1):
0
+      f.write(str(lat0 - float(row)/1200.) + "\t" + str(lon0 + float(col)/1200.) + "\t" + str(tile[row][col] ) + "\n")
0
+  
0
+
0
+  f.close() 
0
+
0
+  # Now we read the data from the temporary file and put it in the
0
+  # altitude table.
0
+
0
+  f = open('/tmp/tempcopy', 'r')
0
+  #cur.copy_from(f, 'altitude') 
0
+  
0
+  # Unfortunately the copy_from() command hangs on my computer for
0
+  # some reason, so we try something else. See also:
0
+  # http://lists.initd.org/pipermail/psycopg/2007-October/005684.html
0
+
0
+  import subprocess
0
+
0
+  #psqlcmd = os.path.join('c:\\', 'Program Files', 'PostgreSQL', '8.2',
0
+  #'bin', 'psql')
0
+  
0
+  psqlcmd = "/usr/bin/psql"
0
+
0
+  p = subprocess.Popen('psql ' + db_name +  ' -c "COPY altitude FROM STDIN;"', stdin=f, shell=True);
0
+  p.wait()
0
+
0
+  f.close
0
+        
0
+def readTileFromDatabase(db, lat0, lon0):
0
+  sql = db.query(" \
0
+    SELECT \
0
+      alt \
0
+    FROM altitude \
0
+    WHERE \
0
+      lat <= " + str(lat0) + "\
0
+      AND lat > " + str(lat0 -1) + "\
0
+      AND lon >= " + str(lon0) + "\
0
+      AND lon < " + str(lon0 + 1) + "\
0
+    ORDER BY lat DESC, lon ASC \
0
+  ")
0
+  res = sql.getresult()
0
+  
0
+  # Now turn the result into a 2D array
0
+
0
+  tile = []
0
+  
0
+  # Calculate tile width (should be 1200, or 10 for test tiles)
0
+  tile_width = int(sqrt(len(res)))
0
+  i = 0
0
+  for x in range(tile_width):
0
+    row = []
0
+    for y in range(tile_width):
0
+      row.append(int(res[i][0]))
0
+      i = i + 1
0
+
0
+    tile.append(row)
0
+  
0
+  return tile
0
+        
0
+def getLatLonFromFileName(name):
0
+  # Split up in lat and lon:
0
+  p = re.compile('[NSEW]\d*')
0
+  [lat_str, lon_str] = p.findall(name)
0
+
0
+  # North or south?
0
+  if lat_str[0] == "N":
0
+    lat = int(lat_str[1:])
0
+  else: 
0
+    lat = -int(lat_str[1:])
0
+  
0
+  # East or west?
0
+  if lon_str[0] == "E":
0
+    lon = int(lon_str[1:])
0
+  else: 
0
+    lon = -int(lon_str[1:])
0
+
0
+  return [lat,lon]
0
+
0
+if __name__ == '__main__':
0
+  db = connectToDatabase(database) 
0
+
0
+  # Does the user want to empty the database first?
0
+  if 'empty' in sys.argv:
0
+    print "Deleting tables from databse..." 
0
+    dropAllTables(db)
0
+    print "Done..."
0
+
0
+  # Make sure the database is empty before we start:
0
+  if not checkDatabaseEmpty(db):
0
+    print "Database is not empty. Run 'read_data empty' to empty it first."
0
+    exit()
0
+  
0
+  # Second database connection with psychopg2 
0
+  db_psycopg2 = connectToDatabasePsycopg2(database)
0
+
0
+  createTableAltitude(db)
0
+
0
+  # Pick a tile
0
+  tile = loadTile('S11E119')
0
 
0
-# Does the user want to empty the database first?
0
-if 'empty' in sys.argv:
0
-  print "Deleting tables from databse..." 
0
-  dropAllTables(db)
0
-  print "Done..."
0
+  print( "Get lat and lon from filename...")
0
+  [lat,lon] = getLatLonFromFileName("S11E119")
0
 
0
-# Make sure the database is empty before we start:
0
-if not checkDatabaseEmpty(db):
0
-  print "Database is not empty. Run 'read_data empty' to empty it first."
0
-  exit()
0
+  print("Insert data...")
0
+  insertTileIntoDatabase(db_psycopg2, "srtm" , tile, lat, lon)
0
 
0
-createTableAltitude(db)
...
53
54
55
56
 
57
58
59
...
63
64
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
67
68
...
53
54
55
 
56
57
58
59
...
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
0
@@ -53,7 +53,7 @@ class TestDatabase(unittest.TestCase):
0
     self.assert_(True)
0
 
0
   def testDatabaseEmpty(self):
0
-    self.assert_(checkDatabaseEmpty(db))
0
+    self.assert_(checkDatabaseEmpty(self.db))
0
   
0
   def testTableAltitudeExists(self):
0
     # Call function to create table
0
@@ -63,6 +63,37 @@ class TestDatabase(unittest.TestCase):
0
     
0
     self.assert_('public.altitude' in tables) 
0
 
0
+  def testGetLatLonFromFileName(self):
0
+    self.assertEqual([-11,119], getLatLonFromFileName("S11E119"))
0
+    self.assertEqual([11,119], getLatLonFromFileName("N11E119"))
0
+    self.assertEqual([11,-119], getLatLonFromFileName("N11W119"))
0
+    self.assertEqual([-11,-119], getLatLonFromFileName("S11W119"))
0
+  
0
+  def testInsertTileIntoDatabase(self):
0
+    # Create table
0
+    self.assert_(createTableAltitude(self.db))
0
+    # Load example tile
0
+    tile = loadTile('S37E145')
0
+    tile = tile[0:11][0:11]
0
+    # Get lat and lon from filename
0
+    [lat,lon] = getLatLonFromFileName("S37E145")
0
+
0
+    # Make the tile smaller, so this will be faster:
0
+    # 11x11 tile: only the top-left 10x10 tile will be stored in the
0
+    # database.
0
+
0
+    # Insert tile into database
0
+    # We use psycopg2 for the connection in this case.
0
+    db_psycopg2 = connectToDatabasePsycopg2(database_test)
0
+    insertTileIntoDatabase(db_psycopg2, "srtm_test" , tile, lat, lon)
0
+
0
+    # Check if the tile is indeed in the database
0
+    tile_back = readTileFromDatabase(self.db, lat, lon)
0
+    print tile_back
0
+    for i in range(len(tile) - 1):
0
+      for j in range(len(tile) - 1):
0
+        self.assert_(tile_back[i][j] == tile[i][j])
0
+
0
   def tearDown(self):
0
     # Drop all tables that might have been created:
0
     dropAllTables(self.db);

Comments