Pure python WMS

Overview

Ogcserver

Python WMS implementation using Mapnik.

Depends

Mapnik >= 0.7.0 (and python bindings)
Pillow
PasteScript
WebOb

You will need to install Mapnik separately.

All the remaining dependencies should be installed cleanly with the command below.

Install

Run the following command inside this directory (the directory that also contains the 'setup.py' file):

sudo python setup.py install

Testing

Run the local http server with the sample data:

ogcserver demo/map.xml

Viewing http://localhost:8000/ in a local browser should show a welcome message like 'Welcome to the OGCServer'

Now you should be able to access a map tile with a basic WMS request like:

http://localhost:8000/?LAYERS=__all__&STYLES=&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&SRS=EPSG%3A3857&BBOX=-20037508.34,-20037508.34,20037508.3384,20037508.3384&WIDTH=256&HEIGHT=256
Comments
  • Problems with OGCServer

    Problems with OGCServer

    Hello,

    i hope this is the correct place for my problem.

    I used the OGCServer as a CGI Script (your wms.py) and i think the paths are set correctly. But when i want to run the Server i have several Problems.

    • When I start a GetMap Request in version 1.1.1, i get a blank Map. The Requestparameter that i used will work without problems with the UMN Mapserver. So i think the BBox and the projection are correctly set. My XML File from that i read will also be found form the OGCServer and shows Map with nik2img.py.

    What do i wrong to show a map in the Browser.

    • When I start a GetMap Request in Version 1.3.0 i get an internal ServerError. And the Apache Log shows the following:

    Traceback (most recent call last):
    File "/usr/lib/cgi-bin/wms.py", line 29, in <module>
    fcgi.Server({fcgi.FCGI_RESPONDER: OGCServerHandler}).run()
    File "/usr/local/lib/python2.6/dist-packages/jon/fcgi.py", line 514, in run
    self.handler_types[FCGI_RESPONDER]).process()
    File "/usr/local/lib/python2.6/dist-packages/jon/cgi.py", line 476, in process
    handler.traceback(self)
    File "/usr/local/lib/python2.6/dist-packages/ogcserver/cgiserver.py", line 87, in traceback
    eh = ExceptionHandler130(self.debug)
    TypeError: __init__() takes at least 3 arguments (2 given)

    • When I start the wms.py from console i get nearly the same error with a diffrent Version:

    Traceback (most recent call last):
    File "/usr/lib/cgi-bin/wms.py", line 29, in <module>
    fcgi.Server({fcgi.FCGI_RESPONDER: OGCServerHandler}).run()
    File "/usr/local/lib/python2.6/dist-packages/jon/fcgi.py", line 514, in run
    self.handler_types[FCGI_RESPONDER]).process()
    File "/usr/local/lib/python2.6/dist-packages/jon/cgi.py", line 476, in process
    handler.traceback(self)
    File "/usr/local/lib/python2.6/dist-packages/ogcserver/cgiserver.py", line 87, in traceback
    eh = ExceptionHandler111(self.debug)
    TypeError: __init__() takes at least 3 arguments (2 given)

    Could you help me to solve these Problems?

    (Sorry for my bad English)

    opened by Witchmaster 15
  • Weirdness with styles

    Weirdness with styles

    There's something kind of odd with styles in OGCServer. In loadXML in BaseWMSFactory you have an if / else branch on style_count, the number of styles for a layer in the xml file. Zero raises an error; after that you distinct between style_count == 1 and style_count > 1.

    Ignoring meta styles for now, if a layer has 1 style only, you add this style to both props layer.wmsdefaultstyle and layer.wmsextrastyles, by calling register_layer as follows:

    self.register_layer(lyr_, style_name, extrastyles=(style_name,))
    

    When requesting a map, a style must be contained in layer.wmsextrastyles to be a valid candidate for the STYLE WMS parameter (if not, you raise an exception). Since the layer's style has been added to both layer.wmsdefaultstyle and layer.wmsextrastyles, you can add this style to your request's STYLE parameter or not - you always get the same result and no exception.

    The problem with these single-style layers comes with the GetCapabilities request. You advertise styles for a layer only, if there are extra styles present. However, you write out the default style and all extra styles. As a result, for single-style layers, the layer's default style occurs twice in the capabilities document. According to OGC, default styles may be omitted from the capabilities response.

    With multi-style layers, things go different. You create an xxx_aggregates style, that is used as the layer's default style. The actual styles go into extra styles. As with all layers, both default and extra styles are published in the capabilities document. However, since the advertised xxx_aggregates default style is not part of extra styles, you'll get an exception, if you actually include it in you STYLES parameter.

    IMO, only extra styles should be advertised in the capabilities document. Single-style layers should not add their style name to layer.wmsextrastyles. Then, these problems could be fixed with only two modifications: (actually three, since there is wms111 and wms130)

    First, change WMS.py, line 128 from

    self.register_layer(lyr_, style_name, extrastyles=(style_name,))
    

    to

    self.register_layer(lyr_, style_name, extrastyles=())
    

    Then, change in both wms111.py, line 211 and wms130.py, line 234 from

    for extrastyle in [layer.wmsdefaultstyle] + list(layer.wmsextrastyles):
    

    to

    for extrastyle in list(layer.wmsextrastyles):
    

    However, after that, it is no longer possible to explicitly request the default style through the STYLE parameter for any layer (currently it's possible for single-style layers).

    Carsten

    opened by cklein05 9
  • Added support for load_map_from_string in BaseWMSFactory.loadXML method (2)

    Added support for load_map_from_string in BaseWMSFactory.loadXML method (2)

    Hi, This pull request adds possibility to load mapnik XML configuration from string using load_map_from_string function. There is a check if 'xmlfile' is existing file (os.path.isfile) - if not 'load_map_from_string' will be used. This is second pull request after #26 - earlier I've add wrong checkig - sorry for that.

    Regards Piotr Pociask

    opened by p0cisk 9
  • Reverse layer list in GetCapabilities if user agent is an ArcGIS client

    Reverse layer list in GetCapabilities if user agent is an ArcGIS client

    When using the wms service in ArcMap, the layers will be requested top-down (first in xml is drawn last). Reversing the layer list in the GetCapabilities response could be a quick way of solving this.

    'HTTP_USER_AGENT': 'ArcGIS Client Using WinInet'

    opened by manelclos 8
  • Add LatLonBoundingBox for root layer

    Add LatLonBoundingBox for root layer

    Adds a LatLonBoundingBox element to the root layer in the GetCapabilities response for WMS 1.1.1, and an equivalent EX_GeographicBoundingBox element for WMS 1.3.0.

    According to the WMS 1.1.1 (section 7.1.4.5.6) specification:

    "Every Layer shall have exactly one element that is either stated explicitly or inherited from a parent Layer."

    The 1.3.0 spec contains a similar section (7.2.4.6.6).

    We have a customer with a WMS client (DigPro) that is kind of picky and apparently refuses to work correctly if this element is missing.

    opened by perliedman 7
  • OGCserver does not work properly through a reverse proxy in WSGI mode

    OGCserver does not work properly through a reverse proxy in WSGI mode

    OGCserver does not work properly through a reverse proxy in WSGI mode as it binds SERVER_NAME, SERVER_PORT and PATH_INFO. There should be 'onlineresource' parameter in ogcserver.conf in '[server]' group.

    patch available: http://trac.mapnik.org/ticket/316

    opened by springmeyer 5
  • Requesting __all__ layers vs. wms_name

    Requesting __all__ layers vs. wms_name

    Hi there,

    currently there may be two concurrent names that designate 'getting all layers' from OGCServer; one is 'all' and the other one may be what was configured for wms_name under the [map] section in the config file. The latter defaults to 'all', so if no other name was specified, the root layer node in the capabilities document, which actually is a group in WMS terms, is named 'all'. According to WMS specs, requesting a named group layer should actually return all its child layers in the order as they appear in the caps document. So, if wms_name is left to its default name 'all' (the name of the root layer node), everything works as expected and satisfies WMS standards and also allows clients to get the whole map "as seen by Mapnik", that is something like the "real" Mapnik map.

    However, since in _buildMap the token 'all' is still hard-coded, things get odd if someone configures a different name for wms_name. The configured name is not valid in the LAYERS parameter and throws a 'LayerNotDefined' exception. Still one has to request for 'all'.

    One obvious solution is to replace the hard-coded 'all' token in _buildMap with the name configured for wms_name. Easy as that. However, since this is closely related to WMS groups, things may be more complicated.

    In code, the comments at the 'all' branch in _buildMap state, that this is intended to provide a map like plain Mapnik does. Call it the "real" Mapnik map. Since all layers under the root layer node (group) are actually in Mapnik order, this "real" Mapnik view of the map exactly matches the root layer group according to WMS. However, I we add support for additional WMS groups, these two maps may be different.

    Also the currently implemented meta layers, that expose all named rules of a style as separate layers in the form <layer_name>:<named_rule_1>-<named_rule_2> breaks this concept and makes the WMS root layer group define a map different from the "real" Mapnik map.

    BTW, the meta layers based on named rules feature is poorly implemented; since a layer's abstract text is preferred over its name (which is mostly an empty string), most of these meta layers are actually named :<named_rule_1>-<named_rule_2> (with no layer name). Is this a permanent feature or is it just a quick hack like the Haiti stuff?

    So, how to deal with the problems of wms_name and 'all' highly depends on what other WMS features we plan to implement, notably meta layers for named rules and WMS groups.

    If we agree to guarantee, that there will always be only one root layer group that only contains the "real" Mapnik layers (that is, no WMS groups and removing the mete layers based on named rules), we should actually replace the hard-coded 'all' in _buildMap with wms_name. Additionally, we should provide a better integration of this single (and only) root layer group. Notably we should support requests like LAYERS=buildings,streets,all,rivers etc. That's easy to achieve.

    If we agree to support arbitrary WMS layer groups and like to keep the meta layers based to named rules, we must keep wms_name and 'all' separated. We'll likely need a new configuration file type for WMS groups. Most suitable will be a hierarchical format, like XML or JSON. Maybe we still keep a key/value base config file and go for an additional hierarchical groups.conf file. Then, we should treat the root layer group as a regular group and so replace wms_name by the new regular group definition syntax. However, since I want to get rid of the term 'all' (some commercial clients have problems with these double underscores), I'd like to make this extra non-WMS backdoor for getting plain Mapnik maps configurable as well.

    Carsten

    opened by cklein05 4
  • Map background is white by default

    Map background is white by default

    When making a GetMap request without explicitly specifying the bgcolor parameter, it appears my map always get a white background, although my mapnik XML specifies a background-color attribute.

    This is an example URL I use: http://myhost/?service=WMS&version=1.1.0&request=GetMap&layers=__all__&bbox=-195609.547531264,5911221.52277581,1130387.38250057,7988952.8814813&width=326&height=512&srs=EPSG:3006&format=image/png&styles=

    While trying to debug this by emulating what OGCServer does, I have a bit of a hard time actually finding where the problem lies, since the configuration seems to load the background color setting properly:

    from ogcserver.WMS import BaseWMSFactory
    from ogcserver.common import WMSBaseServiceHandler
    from ogcserver.wms111 import ServiceHandler
    from ogcserver.configparser import SafeConfigParser
    
    conf = SafeConfigParser()
    conf.readfp(open('../../conf/ogcserver.conf'))
    
    f = BaseWMSFactory()
    f.loadXML("lmv-bright.xml")
    
    wms = ServiceHandler(conf, f, "")
    
    m = wms._buildMap({"crs":"epsg:3006", "bbox":[-195609.547531264,5911221.52277581,1130387.38250057,7988952.8814813], "width":326, "height":512, "layers":["__all__"]})
    
    m.background
    >>> Color(R=167,G=207,B=242,A=255)   # <--- expected, and not white
    

    Is this a OGCServer issue, or is it something with my setup/request that would trigger this behaviour?

    opened by perliedman 4
  • QGIS annoyance due to explicit port in Caps response

    QGIS annoyance due to explicit port in Caps response

    QGIS trunk says: r13995 Advertised GetMap URL

    http://tile2.dbsgeo.com:80/?

    is different from GetCapabilities URL

    http://tile2.dbsgeo.com/?

    This might be an server configuration error. Should the URL be used

    opened by springmeyer 4
  • Import error on mapnik ogcserver

    Import error on mapnik ogcserver

    I've been trying to setup OGCServer on Ubuntu 12.014 and I seem to be having issues integrating WSGI.

    I installed Mapnik 2.2.0 & python-mapnik packages. Then installed PIL & jonpy based on the doc here: https://github.com/mapnik/OGCServer/tree/master/docs

    I setup OGCServer from the main branch as described in the readme. The test server works correctly for the demo.xml & I'm able to see the map.

    I'm running into an error on:

    from mapnik import ogcserver Traceback (most recent call last): File "", line 1, in ImportError: cannot import name ogcserver

    Because of this i'm not able to proceed setting up WSGI integration. Can anyone let me know where I went wrong ? or any further guide to setup WSGI ?

    Thank You

    opened by roboguy 3
  • Using Mapnik 2.3 transparent images look wrong

    Using Mapnik 2.3 transparent images look wrong

    The default for Mapnik 2.3 is to return png8 when calling im.tostring('png'). Needs a way to define format returned (png8, png24 or png32)

    https://github.com/mapnik/mapnik/issues/2110

    opened by manelclos 3
  • python3 error

    python3 error

    ubuntu20.04 python3.8

    There are some errors when I run ogcserver...

    Traceback (most recent call last): File "/usr/local/bin/ogcserver", line 4, in import('pkg_resources').run_script('ogcserver==0.1.1', 'ogcserver') File "/usr/local/lib/python3.8/dist-packages/pkg_resources/init.py", line 666, in run_script self.require(requires)[0].run_script(script_name, ns) File "/usr/local/lib/python3.8/dist-packages/pkg_resources/init.py", line 1469, in run_script script_code = compile(script_text, script_filename, 'exec') File "/usr/local/lib/python3.8/dist-packages/ogcserver-0.1.1-py3.8.egg/EGG-INFO/scripts/ogcserver", line 48 print "Listening at %s:%s...." % (host,port) ^ SyntaxError: invalid syntax

    opened by guyanf 1
  • Support for Layer Groups, Layer Meta-Information and External Layers

    Support for Layer Groups, Layer Meta-Information and External Layers

    _This comment is not yet complete. It covers a complex topic and I try to be very clear and correct, which takes some time. I will continue writing on it as time permits. This remark will be removed upon completion._

    Introduction

    There are some ideas of extending the features of OGCServer. Notably, these features are configurable named layer groups published through the capabilities documents, providing much more map and layer specific meta-information in the capabilities documents as well as support for providing external layers. The latter may come from other WMS servers, so this will make OGCServer a cascading WMS server. This also includes introducing a new, maybe additional, configuration file with a hierarchical structure, most likely in JSON format.

    Let me first please define some basic specifications for supporting layer groups and other layer meta-information and for having a new, maybe JSON style, configuration file.

    Configuration Files

    After thinking about it, I do not recommend to completely replace the current configuration file ogcserver.conf with the new hierarchical wms.json or layers.json file. There are many plain (non hierarchical) and mostly internal or technical configuration options, that are not suitable for being stored in a JSON file. At current, this only applies to the module and to the maxage option. However, some of my next PRs will introduce some more of these basic configuration options.

    Most of these basic options are OGCServer and implementation specific, so these need additional documentation (in contrast to WMS layer meta-information for example, which are explained by WMS specs). Since JSON basically has no support for inline comments, storing these in a file with a plain old configuration file format (like of the current ogcserver.conf file) is preferred.

    Furthermore, for my understanding, all these new features, like layer groups, layer meta-information and external layers, shall be optional. That is, the server must also work without these configurations, by using proper default values. So, moving these into one ore more separate configuration file(s), which must not be present, is probably a good idea.

    opened by cklein05 0
  • Deleting 'service' and 'version' from request parameters

    Deleting 'service' and 'version' from request parameters

    In all request entry functions, notably 'call' in wsgi.py and modserver.py and 'process' in cgiserver.py, you delete 'service' and 'version' parameters from reqparams. However, in the exception handler you get the version from reqparams in order to determine whether to create a 1.1.1 or a 1.3.0 exception. Since 'version' has been deleted, you end up constantly returning 1.1.1 exceptions even if VERSION=1.3.0 was specified on the request.

    Since I do not see any problems with having both 'service' and 'version' in reqparams around, I recommend NOT deleting these entries after the service handler was setup. If you agree, I will include this in one of my upcoming pull requests (likely in the XML-prettifying PR).

    opened by cklein05 2
  • More suitable HTTP status codes for service exceptions

    More suitable HTTP status codes for service exceptions

    Hi there,

    All types of exception reports currently are returned with a HTTP status code of 404 Not Found. Actually, that's not ideal, since in case of an error ("Oh, I'm getting no map images...!"), most people will likely issue some test requests in a web browser. Since most modern browsers just do not show the response for a 404, you need Wireshark (or similar) to actually read the service exception.

    You could either constantly use status code 200 OK for all responses (that's what GeoServer does, for example) or try using the codes recommended by OGC's 'Web Services Common Standard', which basically are 400 Bad Request and 501 Not Implemented.

    For the latter solution, obviously there is more work to be done. You could probably pass the HTTP status code as a (new) last parameter to OGCException and use it in the handler accordingly. If you actually go that far, you could also add support for the 'locator' attribute for version 1.3.0 exception reports (also with an additional argument to ctor of OGCException).

    At least for the self.debug == true case, in which you switch to the HTML handler, returning 200 OK would be helpful; the same seems to be true for IN_IMAGE and BLANK handlers. So, using different status codes for different exceptions, actually only applies to XML and - maybe - HTML formats.

    Although not that familiar with Python (coming form Java, C++, VB etc.), I could likely implement these changes if you like (and one or two more, see upcoming issues). I need to use OGCServer in a production environment (Apache httpd, mod_wsgi etc.), but I'm really not a fan of creating my personal local branches.

    However, I've read Dane Springmeyer's post "Inventory and evaluate merge of refactoring done for haiti instance", so I'm not quite sure whether the latest version is the one to implement these changes on. Maybe you should first clean up the code? Oh, the ticket is from 2010... As far as I've seen, the Haiti stuff is still there... Are still movong on with this?

    Thanks in advance for any helpful reply, Carsten

    opened by cklein05 1
  • Avoid hitting length limit for GET requests

    Avoid hitting length limit for GET requests

    When serving WMS for stylesheets with many layers, and layers with long names, its easy to hit the limit for length of GET requests for a given browser.

    A "meta layers" hack was added to work around this problem for a haiti deployment of the ogcserver: https://github.com/mapnik/OGCServer/blob/master/ogcserver/common.py#L384 and this needs to be removed and proper support added.

    opened by springmeyer 2
Pure Python NetCDF file reader and writer

Pyncf Pure Python NetCDF file reading and writing. Introduction Inspired by the pyshp library, which provides simple pythonic and dependency free data

Karim Bahgat 14 Sep 30, 2022
pure-Python (Numpy optional) 3D coordinate conversions for geospace ecef enu eci

Python 3-D coordinate conversions Pure Python (no prerequistes beyond Python itself) 3-D geographic coordinate conversions and geodesy. API similar to

Geospace code 292 Dec 29, 2022
This is a simple python code to get IP address and its location using python

IP address & Location finder @DEV/ED : Pavan Ananth Sharma Dependencies: ip2geotools Note: use pip install ip2geotools to install this in your termin

Pavan Ananth Sharma 2 Jul 5, 2022
GeoIP Legacy Python API

MaxMind GeoIP Legacy Python Extension API Requirements Python 2.5+ or 3.3+ GeoIP Legacy C Library 1.4.7 or greater Installation With pip: $ pip instal

MaxMind 230 Nov 10, 2022
Python bindings and utilities for GeoJSON

geojson This Python library contains: Functions for encoding and decoding GeoJSON formatted data Classes for all GeoJSON Objects An implementation of

Jazzband 765 Jan 6, 2023
Geocoding library for Python.

geopy geopy is a Python client for several popular geocoding web services. geopy makes it easy for Python developers to locate the coordinates of addr

geopy 3.8k Dec 30, 2022
Python Data. Leaflet.js Maps.

folium Python Data, Leaflet.js Maps folium builds on the data wrangling strengths of the Python ecosystem and the mapping strengths of the Leaflet.js

null 6k Jan 2, 2023
Python tools for geographic data

GeoPandas Python tools for geographic data Introduction GeoPandas is a project to add support for geographic data to pandas objects. It currently impl

GeoPandas 3.5k Jan 3, 2023
Python interface to PROJ (cartographic projections and coordinate transformations library)

pyproj Python interface to PROJ (cartographic projections and coordinate transformations library). Documentation Stable: http://pyproj4.github.io/pypr

null 832 Dec 31, 2022
Python bindings and utilities for GeoJSON

geojson This Python library contains: Functions for encoding and decoding GeoJSON formatted data Classes for all GeoJSON Objects An implementation of

Jazzband 763 Dec 26, 2022
Documentation and samples for ArcGIS API for Python

ArcGIS API for Python ArcGIS API for Python is a Python library for working with maps and geospatial data, powered by web GIS. It provides simple and

Esri 1.4k Dec 30, 2022
PySAL: Python Spatial Analysis Library Meta-Package

Python Spatial Analysis Library PySAL, the Python spatial analysis library, is an open source cross-platform library for geospatial data science with

Python Spatial Analysis Library 1.1k Dec 18, 2022
Simple, concise geographical visualization in Python

Geographic visualizations for HoloViews. Build Status Coverage Latest dev release Latest release Docs What is it? GeoViews is a Python library that ma

HoloViz 445 Jan 2, 2023
A package built to support working with spatial data using open source python

EarthPy EarthPy makes it easier to plot and manipulate spatial data in Python. Why EarthPy? Python is a generic programming language designed to suppo

Earth Lab 414 Dec 23, 2022
:earth_asia: Python Geocoder

Python Geocoder Simple and consistent geocoding library written in Python. Table of content Overview A glimpse at the API Forward Multiple results Rev

Denis 1.5k Jan 2, 2023
Python package for earth-observing satellite data processing

Satpy The Satpy package is a python library for reading and manipulating meteorological remote sensing data and writing it to various image and data f

PyTroll 882 Dec 27, 2022
Use Mapbox GL JS to visualize data in a Python Jupyter notebook

Location Data Visualization library for Jupyter Notebooks Library documentation at https://mapbox-mapboxgl-jupyter.readthedocs-hosted.com/en/latest/.

Mapbox 620 Dec 15, 2022
python toolbox for visualizing geographical data and making maps

geoplotlib is a python toolbox for visualizing geographical data and making maps data = read_csv('data/bus.csv') geoplotlib.dot(data) geoplotlib.show(

Andrea Cuttone 976 Dec 11, 2022
geemap - A Python package for interactive mapping with Google Earth Engine, ipyleaflet, and ipywidgets.

A Python package for interactive mapping with Google Earth Engine, ipyleaflet, and folium

Qiusheng Wu 2.4k Dec 30, 2022