source: DPPP/kml/csml2kml/python/pylonsstack/pylonsstack/controllers/csmlGrapher.py @ 3281

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/DPPP/kml/csml2kml/python/pylonsstack/pylonsstack/controllers/csmlGrapher.py@3281
Revision 3281, 5.9 KB checked in by mkochan, 13 years ago (diff)

Modified csmlGrapher do read in a single PointSeries? feature only from GeoServer?. Also allows reading station XML, but this is only kept until it is decided whether it has a place in the framework.

Line 
1# Pylons-specific imports
2import logging
3from pylonsstack.lib.base import *
4
5# Other imports
6import csml
7import Image
8import pylab
9from pylab import *
10from datetime import datetime, timedelta
11import re
12import urllib
13from cStringIO import StringIO
14from tempfile import NamedTemporaryFile
15from cElementTree import Element, ElementTree, XML
16
17log = logging.getLogger(__name__)
18
19# [TODO] . Add correct labeling of time axis
20#        . Comments
21#        . Add security (especially checking of input parameters).
22#        . Add configurable URL for the data source web service (preferably explicitly on localhost)
23class CsmlgrapherController(BaseController):
24
25    def plot(self):
26        '''
27        Handler for plotting a specific PointSeries feature given by URL parameter "feature_id".
28        Retrieves the data from a web service, which should preferably run on the same machine.
29
30        Request parameters:    EITHER "feature_id" OR "station_id"
31        where:
32                               feature_id    Unique identifier of a requested CSML PointSeries feature.
33                               station_id    Unique identifier of a requested station.
34
35        Response:              If feature_id is supplied, an image/png of the time series for the CSML PointSeries feature;
36                               if station_id is supplied, nothing.
37        '''
38        def _plot_feature(feature):
39            '''
40            Plot a PointSeries feature using matplotlib, into a temporary file
41            '''
42            (lon, lat) = map(float, feature.location.CONTENT.split())
43            print 'Feature "%s" (%s) at: (%f,%f)' % (feature.id, feature.description.CONTENT, lon, lat)
44
45            times=feature.value.pointSeriesDomain.timePositionList.CONTENT.split()
46            print 'All times (%s of them): '% len(times)
47            print times
48           
49            #!span = dates.date2num(times[-1]) - dates.date2num(times[0])
50            #!print 'The span is ' + span + ' days.'
51            elapsed_times = map(pylab.matplotlib.dates.datestr2num, times)
52            #!(tickLocator, tickFormatter) = dates.date_ticker_factory(span, 5)
53           
54            print 'All times (%s of them) as days since 01-01-0001 UTC: '% len(elapsed_times)
55            print elapsed_times
56
57            # We may need to do this for bodc data (i.e. not inline data)
58            # vals=feature.value.rangeSet.valueArray.valueComponent.insertedExtract.components.getDataFromChunks(0,19)
59
60            # We use this for inline data:
61            ql = feature.value.rangeSet.quantityList
62            vals = map(float, ql.CONTENT.split())
63            print 'Measurement values (%s of them):\n%s' % (len(vals), repr(vals))
64
65            # Determine the units of measurement
66            uom=ql.uom.title()
67            if ql.uom.islower():
68                uom = uom.lower()
69            if ql.uom.isupper():
70                uom = uom.upper()
71            print 'Units of measurement: %s' % uom
72
73            # Plot the figure
74            clf()
75            #!plot_date(elapsed_times, vals, '-', xdate=True, lw=2)
76            plot(elapsed_times, vals, '-', lw=2)
77            xlabel('Time since start [days]')
78            ylabel('Values [%s]' % uom)
79            title('Plot of "%s" (%s)' % (feature.id, feature.description.CONTENT))
80            grid(True)
81
82            # Save the figure to a temporary file
83            tempFile = NamedTemporaryFile(suffix='.png')
84            savefig(tempFile.name)
85           
86            return tempFile
87
88        def _set_response(tempFile):
89            '''
90            Set the WSGI response to an image, containing image read from a temporary location.
91            '''
92            img = Image.open(tempFile.name)
93            buf = StringIO()
94            img.save(buf, 'PNG')
95            response.content_type = 'image/png'
96            response.content = buf.getvalue()
97           
98        def wget(url):
99            content = None
100            try:
101                socket = urllib.urlopen(url)               # open a socket (actually a file-like object)
102                content = socket.read()                    # read the text in
103            finally:
104                try:
105                    socket.close()
106                except NameError:
107                    pass  # socket undefined -- no need to close
108            return content
109
110        #-------------------------------------------------------------------------------------------------------------------
111
112        # get feature ID from HTTP request
113        feature_id = None; station_id = None
114        try:
115            feature_id = request.params['feature_id']
116            gml_id = feature_id
117        except KeyError:
118            try:
119                station_id = request.params['station_id']
120                gml_id = station_id
121            except KeyError:
122                raise HTTPBadRequest('exactly one of the parameters "feature_id" and "station_id" must be supplied.')
123
124        # Get response from GeoServer and parse it into an ElementTree
125        geoServerURL = 'http://bond.badc.rl.ac.uk:8089/dummyGeoServer/GetStationCSMLFeatures?gml_id=' + gml_id
126        geoSrResponse = wget(geoServerURL)
127        tree = ElementTree(XML(geoSrResponse))
128
129        if station_id:
130
131            # --- [NOTE] Keeping until ruled as obsolete ---
132
133            # Parse in the feature collection
134            fc = csml.parser.CSMLFeatureCollection()
135            fc.fromXML(tree.getroot())
136
137        else:
138           
139            # Parse in the feature directly
140            feature = csml.parser.PointSeriesFeature()
141            feature.fromXML(tree.getroot())
142
143        if not feature:
144            raise HTTPNotFound('Feature not found')
145           
146        try:
147            tempFile = _plot_feature(feature)              # plot the feature into a temporary file
148            _set_response(tempFile)                        # set WSGI response as an image containing the plot
149        finally:
150            try:
151                tempFile.close()
152            except NameError:
153                pass  # tempFile undefined -- no need to close
Note: See TracBrowser for help on using the repository browser.