root/spike/wktraster/scripts/rtreader.py

Revision 5558, 5.2 KB (checked in by jorgearevalo, 22 months ago)

Small bug fixed in testcore: CHECK_EQUALS_DOUBLE instead of CHECK_EQUALS.
Added extra debug info in rtreader.py and rt_pg.c (to help fixing

RASTER_dumpAsWKTPolygons function)

  • Property svn:keywords set to
    Id
    Revision
Line 
1#! /usr/bin/env python
2#
3# $Id$
4#
5# A simple driver to read RASTER field data directly from PostGIS/WKTRaster.
6#
7# Copyright (C) 2009 Mateusz Loskot <mateusz@loskot.net>
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program; if not, write to the Free Software
21# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22#
23###############################################################################
24#
25# Requirements: psycopg2
26#
27# WARNING: Tha main purpose of the RasterReader is to test and debug
28# WKT Raster implementation. It is not supposed to be an efficient
29# performance killer, by no means.
30#
31###############################################################################
32import psycopg2
33import sys
34
35###############################################################################
36# RASTER driver (read-only)
37
38class RasterError(Exception):
39    def __init__(self, msg):
40        self.msg = msg
41    def __str__(self):
42        return self.msg
43
44class RasterReader(object):
45    """Reader of RASTER data stored in specified column and row (where) in a table"""
46
47    # Constructors
48
49    def __init__(self, connstr, table, column, where = ""):
50        self._connstr = connstr
51        self._conn = None
52        self._table = table
53        self._column = column
54        self._where = where
55        self._sizes = None
56        self._types = None
57        self._logging = False
58        # Connect and read RASTER header
59        self._setup()
60
61    # Public properties
62
63    logging = property(fset = lambda self, v: setattr(self, '_logging', v))
64    db = property(fget = lambda self: self._get_db())
65    table = property(fget = lambda self: self._table)
66    column = property(fget = lambda self: self._column)
67    width = property(fget = lambda self: self._get_width())
68    height = property(fget = lambda self: self._get_height())
69    num_bands = property(fget = lambda self: self._get_num_bands())
70    pixel_types = property(fget = lambda self: self._get_pixel_types())
71
72    # Public methods
73
74    def get_value(self, band, x, y):
75        return self._query_value(band, x, y)
76
77    # Private methods
78
79    def _log(self, m):
80        if self._logging:
81            sys.stderr.write('[rtreader] ' + str(m) + '\n')
82
83    def _get_db(self):
84        n = filter(lambda db: db[:6] == 'dbname', self._connstr.split())[0].split('=')[1]
85        return n.strip('\'').strip()
86
87    def _get_width(self):
88        return self._query_raster_size(0)
89
90    def _get_height(self):
91        return self._query_raster_size(1)
92
93    def _get_num_bands(self):
94        return self._query_raster_size(2)
95
96    def _get_pixel_types(self):
97        return self._query_pixel_types()
98
99    def _setup(self):
100        self._connect()
101
102    def _connect(self):
103        try:
104            if self._conn is None:
105                self._conn = psycopg2.connect(self._connstr)
106        except Exception, e:
107            raise RasterError("Falied to connect to %s: %s" % (self._connstr, e))
108
109    def _query_single_row(self, sql):
110        assert self._conn is not None
111        #self._log(sql)
112
113        try:
114            cur = self._conn.cursor()
115            cur.execute(sql)
116        except Exception, e:
117            raise RasterError("Failed to execute query %s: %s" % (sql,
118                        e))
119
120        row = cur.fetchone()
121        if row is None:
122            raise RasterError("No tupes returned for query: %s" % sql)
123        return row
124
125    def _query_value(self, band, x, y):
126        sql = 'SELECT st_value(%s, %d, %d, %d) FROM %s' % \
127                 (self._column, band, x, y, self._table)
128        if len(self._where) > 0:
129            sql += ' WHERE %s' % self._where
130
131        row = self._query_single_row(sql)
132        if row is None:
133            raise RasterError("Value of pixel %dx%d of band %d is none" %(x, y, band))
134        return row[0]
135   
136    def _query_raster_size(self, dim, force = False):
137        if self._sizes is None or force is True:
138            sql = 'SELECT st_width(%s), st_height(%s), st_numbands(%s) FROM %s' % \
139                     (self._column, self._column, self._column, self._table)
140            if len(self._where) > 0:
141                sql += ' WHERE %s' % self._where
142               
143            self._log(sql)
144            self._sizes = self._query_single_row(sql)
145
146        if self._sizes is None:
147            raise RasterError("Falied to query %dx%d of band %d is none" %(x, y, band))
148        return self._sizes[dim]
149
150    def _query_pixel_types(self):
151
152        types = []
153        sql = 'SELECT '
154        for i in range(0, self.num_bands):
155            if i != 0:
156                sql += ','
157            nband = i + 1
158            sql += ' st_bandpixeltype(%s, %d) ' % (self._column, nband)
159        sql += ' FROM ' + self._table
160        return self._query_single_row(sql)
Note: See TracBrowser for help on using the browser.