Changeset 3693


Ignore:
Timestamp:
27/03/08 18:39:42 (11 years ago)
Author:
mkochan
Message:

Extended csmlGrapher to allow multiple datasets (that is, data served from multiple WFSs).

Location:
DPPP/kml/csml2kml/python
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • DPPP/kml/csml2kml/python/csml2kml/csml2kml/Station.py

    r3654 r3693  
    33''' 
    44 
     5import utils 
    56from ET import XML 
    67from matplotlib import dates     # a very good date/time module from matplotviz -- allows years < 1970 
     
    2122    @type lat: float 
    2223    @type features: C{NPStationFeature} list 
    23  
    2424    ''' 
    2525 
     
    9393        @type stationElement: C{cElementTree.Element} 
    9494        ''' 
     95 
    9596        (featureTypeElement, featureIdElement,  
    9697         collectBeginDateElement, collectEndDateElement) = stationFeatureElement.getchildren() 
    9798        self.featureType = featureTypeElement.text 
    9899        self.featureId = featureIdElement.text 
    99         self.collectBeginDate = dates.dateutil.parser.parse(collectBeginDateElement.text) 
    100         self.collectEndDate = dates.dateutil.parser.parse(collectEndDateElement.text) 
     100        self.collectBeginDate = utils.parseTimestamp(collectBeginDateElement.text) 
     101        self.collectEndDate = utils.parseTimestamp(collectEndDateElement.text) 
    101102 
    102103    def __repr__(self): 
  • DPPP/kml/csml2kml/python/csml2kml/csml2kml/tests/testUtils.py

    r3684 r3693  
    11import csml2kml.utils 
    22 
    3 print 'Script loaded. Testing utils.wget() only.' 
     3print 'Script loaded.\nTesting utils.parseTimestamp().' 
     4 
     5print csml2kml.utils.parseTimestamp('2001-12-31T24:00:00') 
     6print csml2kml.utils.parseTimestamp('2001-12-31T24:00:00Z') 
     7print csml2kml.utils.parseTimestamp('2001-12-31T23:59:59') 
     8 
     9print '\nTesting utils.wget().' 
    410n = 10 
    511print 'Retrieving ' + str(n) + ' times.' 
  • DPPP/kml/csml2kml/python/csml2kml/csml2kml/utils.py

    r3684 r3693  
    33''' 
    44 
     5import re 
    56import urllib2 
     7from matplotlib import dates 
    68 
    79class UrlRetrievalError(Exception): 
     
    2931            pass                         # in case socket has not even been opened 
    3032    return content 
     33 
     34def parseTimestamp(timestamp): 
     35    ''' 
     36    Wraps the function dates.dateutil.parser.parse, while interpreting timestamps 
     37    like "31-12-2006T24:00:00" correctly as "1-1-2007T00:00:00"  
     38    (as matplotviz.dates.dateutil.parser.parse cannot parse timestams with hour other than 0..23). 
     39    @param timestamp: The timestamp 
     40    @type timestamp: C{str} 
     41    @return: Corresponding datetime 
     42    @rtype: C{dates.datetime.datetime} 
     43    ''' 
     44    mo = re.match('(.+)24\:00\:00(Z?)', timestamp) 
     45    if mo: 
     46        oneDayBackTimestamp = mo.group(1) + '00:00:00' + mo.group(2) 
     47        oneDay = dates.datetime.timedelta(1) 
     48        return dates.dateutil.parser.parse(oneDayBackTimestamp) + oneDay 
     49    else: 
     50        return dates.dateutil.parser.parse(timestamp) 
  • DPPP/kml/csml2kml/python/csml2kmlpylon/csml2kmlpylon/config/midas.csml2kmlpylon.conf.xml

    r3657 r3693  
    11<GrapherWebService> 
    2   <DisplayIntervalStart>1-1-2003</DisplayIntervalStart> 
    3   <DisplayIntervalEnd>31-1-2003</DisplayIntervalEnd> 
    4   <GeoServerURL>http://bond.badc.rl.ac.uk:8084/geoserver/wfs</GeoServerURL> 
     2  <DisplayIntervalStart>1-5-2006</DisplayIntervalStart> 
     3  <DisplayIntervalEnd>1-6-2006</DisplayIntervalEnd> 
    54  <ServedFromURL>http://superglue.badc.rl.ac.uk:8084/csmlGrapher</ServedFromURL> 
     5  <Dataset id="midas" name="MIDAS"> 
     6    <GeoServerURL>http://bond.badc.rl.ac.uk:8084/geoserver/wfs</GeoServerURL> 
     7  </Dataset> 
     8  <Dataset id="ecn" name="ECN"> 
     9    <GeoServerURL>http://dppp.nerc-lancaster.ac.uk:8080/geoserver/wfs</GeoServerURL> 
     10  </Dataset> 
    611</GrapherWebService> 
  • DPPP/kml/csml2kml/python/csml2kmlpylon/csml2kmlpylon/controllers/csmlGrapher.py

    r3657 r3693  
    2323class CsmlgrapherController(BaseController): 
    2424 
     25    class Dataset: 
     26        ''' 
     27        An auxiliary storage class describing a dataset of csml2kml.Station's; 
     28        this describes what URL the data is I{retrievable} from, as opposed to this class actually storing any data. 
     29        E.g. MIDAS and ECN are different datasets (each has a WFS URL from which it is being accessible). 
     30        ''' 
     31        def __init__(self, id, name, geoServerUrl): 
     32            self.id = id 
     33            self.name = name 
     34            self.geoServerUrl = geoServerUrl 
     35 
    2536    def __call__(self, environ, start_response): 
    2637        ''' 
    27         Initialise the web service by overriding a method that always get called upon controller construction. 
     38        Initialise the web service by overriding a method that always gets called upon controller construction. 
    2839        More specifically, read in the config file. 
    2940        ''' 
     
    3748        grapherConfig = (ElementTree().parse(configFileName)) 
    3849 
    39         # Set the configurable variables 
     50        # Initialise the datasets from the config file. 
     51        self.datasets = {} 
     52        datasetElements = grapherConfig.findall('Dataset') 
     53        for datasetElement in datasetElements: 
     54            id = datasetElement.get('id') 
     55            self.datasets[id] = self.Dataset(id, datasetElement.get('name'), datasetElement.find('GeoServerURL').text) 
     56 
     57        # Set other configurable variables 
    4058        self.displayIntervalStart = dates.dateutil.parser.parse(grapherConfig.find('DisplayIntervalStart').text) 
    4159        self.displayIntervalEnd = dates.dateutil.parser.parse(grapherConfig.find('DisplayIntervalEnd').text) 
    42         self.geoServerUrl = grapherConfig.find('GeoServerURL').text 
    4360        self.servedFromUrl = grapherConfig.find('ServedFromURL').text 
     61 
     62        print 'Config file parse finished.' 
    4463 
    4564        # Call the __call__ method of the parent class  
     
    5069        return repr(datetime.day) + '-' + monthCodes[datetime.month-1] + '-' + repr(datetime.year) 
    5170 
    52     def _retrieveCsmlPointSeriesFeature(self, station_name, feature_id): 
     71    def _retrieveCsmlPointSeriesFeature(self, dataset, station_name, feature_id): 
    5372        ''' 
    5473        @return: A C{PointSeriesFeature} object representing the single CSML feature if the feature was found; 
     
    5776        @throws: A C{LookupError} exception with a message if there is no response from the server. 
    5877        ''' 
    59          
    60         # Prepare the request for the GeoServer. 
    61         geoServerRequestUrl = urllib.quote(self.geoServerUrl + '?request=getfeature&service=wfs&version=1.1.0&typename=csml:PointSeriesFeature&filter=<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml"><ogc:And><ogc:PropertyIsEqualTo><ogc:PropertyName>gml:description</ogc:PropertyName><ogc:Literal>'+ station_name +'</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>csml:parameter/swe:Phenomenon/gml:name</ogc:PropertyName><ogc:Literal>'+ feature_id +'</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsBetween><ogc:PropertyName>csml:value/csml:PointSeriesCoverage/csml:pointSeriesDomain/csml:TimeSeries/csml:timePositionList</ogc:PropertyName><ogc:LowerBoundary><ogc:Literal>'+ self._datetimeToGeoServerDate(self.displayIntervalStart) +'</ogc:Literal></ogc:LowerBoundary><ogc:UpperBoundary><ogc:Literal>'+ self._datetimeToGeoServerDate(self.displayIntervalEnd) +'</ogc:Literal></ogc:UpperBoundary></ogc:PropertyIsBetween></ogc:And></ogc:Filter>', '/._:?&=') 
     78       
     79        # Prepare the request for the dataset's GeoServer 
     80        geoServerRequestUrl = urllib.quote(dataset.geoServerUrl + '?request=getfeature&service=wfs&version=1.1.0&typename=csml:PointSeriesFeature&filter=<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml"><ogc:And><ogc:PropertyIsEqualTo><ogc:PropertyName>gml:description</ogc:PropertyName><ogc:Literal>'+ station_name +'</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsEqualTo><ogc:PropertyName>csml:parameter/swe:Phenomenon/gml:name</ogc:PropertyName><ogc:Literal>'+ feature_id +'</ogc:Literal></ogc:PropertyIsEqualTo><ogc:PropertyIsBetween><ogc:PropertyName>csml:value/csml:PointSeriesCoverage/csml:pointSeriesDomain/csml:TimeSeries/csml:timePositionList</ogc:PropertyName><ogc:LowerBoundary><ogc:Literal>'+ self._datetimeToGeoServerDate(self.displayIntervalStart) +'</ogc:Literal></ogc:LowerBoundary><ogc:UpperBoundary><ogc:Literal>'+ self._datetimeToGeoServerDate(self.displayIntervalEnd) +'</ogc:Literal></ogc:UpperBoundary></ogc:PropertyIsBetween></ogc:And></ogc:Filter>', '/._:?&=') 
    6281 
    6382        # Acquire the GeoServer response and parse it into a CSMLFeatureCollection object 
     
    92111 
    93112        Request parameters: 
     113                               dataset_id      Unique identifier of the dataset to use. 
    94114                               feature_id      Unique identifier of the requested CSML PointSeries feature. 
    95115                               station_name    Name of the requested station. 
     
    97117        Response:              An image/png of the time series for the CSML PointSeries feature. 
    98118        ''' 
    99         def _plot_feature(feature): 
     119        def _plot_feature(feature, dataset): 
    100120            ''' 
    101121            Plot a PointSeries feature using matplotlib, into a temporary file 
     
    174194            xlabel('Times between %s and %s ' % (start_date.strftime(time_format), end_date.strftime(time_format))) 
    175195            ylabel('Values [%s]' % uom) 
    176             title('"%s" (%s)' % (feature.id, feature.description.CONTENT)) 
     196            title('"%s:%s" (%s station %s)' % (dataset.id, feature.id, dataset.name, feature.description.CONTENT)) 
    177197            grid(True) 
    178198 
     
    197217        # Get parameters from the request object 
    198218        try: 
     219            dataset_id = str(request.params['dataset_id'])     # convert back from Unicode 
    199220            feature_id = str(request.params['feature_id'])     # convert back from Unicode 
    200221            station_name = str(request.params['station_name']) # convert back from Unicode  
    201222        except KeyError: 
    202             raise HTTPBadRequest('Parameters "feature_id" and "station_name" must be supplied.') 
    203  
    204         # Try to retrieve the csmlPointSeriesFeature object 
    205         try: 
    206             csmlPointSeriesFeature = self._retrieveCsmlPointSeriesFeature(station_name, feature_id) 
     223            raise HTTPBadRequest('Parameters "dataset_id", "feature_id" and "station_name" must be supplied.') 
     224 
     225        # Try to retrieve the csmlPointSeriesFeature object from the appropriate dataset 
     226        try: 
     227            dataset = self.datasets[dataset_id] 
     228            csmlPointSeriesFeature = self._retrieveCsmlPointSeriesFeature(dataset, station_name, feature_id) 
    207229        except LookupError, e: 
    208230            errorMessage = e.args[0] 
     
    214236        # Try to plot the feature into a temporary file, and put the contents of that file into the response 
    215237        try: 
    216             tempFile = _plot_feature(csmlPointSeriesFeature)    # plot the feature into a temporary file 
    217             _set_response(tempFile)                             # set the response as an image containing the plot 
     238            tempFile = _plot_feature(csmlPointSeriesFeature, dataset)    # plot the feature into a temporary file 
     239            _set_response(tempFile)                                      # set the response as an image containing the plot 
    218240        finally: 
    219241            try: 
     
    226248        Handler for generating a list of CSML features per station, with dynamic links to the plot service. 
    227249        Request parameters: 
     250                               dataset_id      Unique identifier of the dataset to use. 
    228251                               station_name    Name of the requested station. 
    229252                                
     
    233256        # Get parameters from the request object 
    234257        try: 
    235             station_name = str(request.params['station_name']) # convert back from Unicode  
     258            dataset_id = str(request.params['dataset_id'])      # convert back from Unicode  
     259            station_name = str(request.params['station_name'])  # convert back from Unicode  
    236260        except KeyError: 
    237             raise HTTPBadRequest('Parameter "station_name" must be supplied.') 
     261            raise HTTPBadRequest('Parameters "dataset_id" and "station_name" must be supplied.') 
     262 
     263        # Identify the appropriate dataset. 
     264        dataset = self.datasets[dataset_id] 
    238265 
    239266        # Prepare the request for the GeoServer -- to return a collection of np:Station, containing a single np:Station, 
    240267        # which contains a list of CSML features. 
    241         geoServerRequestUrl = urllib.quote(self.geoServerUrl + '?request=getFeature&service=wfs&version=1.1.0&typename=np:Station&filter=<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml"><ogc:PropertyIsEqualTo><ogc:PropertyName>stationName</ogc:PropertyName><ogc:Literal>' + station_name + '</ogc:Literal></ogc:PropertyIsEqualTo></ogc:Filter>', '/._:?&=') 
     268        geoServerRequestUrl = urllib.quote(dataset.geoServerUrl + '?request=getFeature&service=wfs&version=1.1.0&typename=np:Station&filter=<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml"><ogc:PropertyIsEqualTo><ogc:PropertyName>stationName</ogc:PropertyName><ogc:Literal>' + station_name + '</ogc:Literal></ogc:PropertyIsEqualTo></ogc:Filter>', '/._:?&=') 
    242269 
    243270        # Acquire the GeoServer response and parse it into a WFSStationCollection object 
     271         
     272        print geoServerRequestUrl 
    244273        geoServerResponse = wget(geoServerRequestUrl) 
    245274        if not geoServerResponse: 
     
    268297                featureNameElement = SubElement(rowElement, 'td') 
    269298                anchorElement = SubElement(featureNameElement, 'a') 
    270                 linkToGrapher = self.servedFromUrl + '/plot?station_name=' + station_name + '&feature_id=' + stationFeature.featureId 
     299                linkToGrapher = self.servedFromUrl + '/plot?dataset_id=' + dataset_id + '&station_name=' + station_name + '&feature_id=' + stationFeature.featureId 
    271300                anchorElement.set('href', linkToGrapher) 
    272301                anchorElement.text = stationFeature.featureId 
Note: See TracChangeset for help on using the changeset viewer.