marceloprates / prettymaps

A small set of Python functions to draw pretty maps from OpenStreetMap data. Based on osmnx, matplotlib and shapely libraries.
GNU Affero General Public License v3.0
11.04k stars 516 forks source link

Railways #61

Open Stelorio opened 2 years ago

Stelorio commented 2 years ago

I have a problem to get Railways to display on the map at all.

I used this code for my railway

       'railway': {
            'custom_filter': '["rail|light_rail|subway|tram|disused|construction|abandoned|monorail|narrow_gauge"]',
            'width': {
                'rail': 7,
                'light_rail': 5
                'subway': 5,
                'tram': 4,
                'disused': 4,
                'construction': 3,
                'abandoned': 3,
                'monorail': 3,
                'narrow_gauge': 3,
            },
        'circle': False,
        'dilate': dilate
        },

and kwargs

'railway': {'fc': '#2F3737', 'ec': '#475657', 'alpha': 1, 'lw': 0, 'zorder': 6}

I tried to map this area which has plenty of different kinds of railway

https://www.openstreetbrowser.org/#railway-infrastructure/w178925635&map=18/52.42969/13.25519&categories=railway-infrastructure

It will not display anything at all for that area. Did anyone got railways working or is that feature not implemented (yet)

G21-Goose commented 2 years ago

Hi, Try changing custom_filter to:

'custom_filter': '["railway"~"rail|light_rail|subway|tram|disused|construction|abandoned|monorail|narrow_gauge"]'

Some more infomration that may be useful:

The filters work by having a key on the left (e.g. "railway") followed by how you want it to filter (exactly equal = or using regular expressions with ~) and then the value(s) you want to match for. In this case | is "or" for regex, so you need to use ~. So the custom filter matches anything where the key "railway" matches rail or light_rail or subway etc.

To get this information you can go to OSM and zoom close to the area you are wanting to look at and either right click on the area and "Query features" or open "layers" on the side bar and tick "Map Data" (this approach can be laggy, especially if you are zoomed out), so you can then click on what you are interested in.

Also, just in case you run into the same issue as I did, when using custom_filter sometimes not all the results are shown if they aren't all connected #33 , so you can also add 'retain_all': True to your layer configuration. Some people #8 have also had to use large 'dilate' or 'buffer' values to get all the train lines to show up (I have used a 'buffer' value of about 3000 normally with no dilate, but you'll get very similar results no matter what you use (I think) when it comes to railways).

If you want to only have trains that are above ground you can also cascade multiple filters, the second filter here removes anything where tunnel==yes:

custom_filter'["railway"~"rail"]["tunnel"!="yes"]'

Hopefully this is useful to you and anyone else who is trying to plot railways.

quickcoffee commented 2 years ago

Hi I faced a similar situation, where railways were not plotted and tried the custom_filter by @G21-Goose. Unfortunately this now just throws an error: KeyError: 'railway' Any idea what’s going wrong there? To me it sounds like it can't find any railway objects for the specified radius? But there is a railway in the location I'm trying to plot.

G21-Goose commented 2 years ago

Hi @quickcoffee, can you give me the location you are trying?

This shows the railways around the area @Stelorio was trying.

from prettymaps import *
from matplotlib import pyplot as plt

# Style parameters
palette = ['#433633', '#FF5E5B']
background_c = '#F2F4CB'
buffer = 500
circle = False

# Setup figure
figsize=(10,10)
fig, ax = plt.subplots(figsize = figsize, constrained_layout = True)

# Plot
layers = plot(
    (52.43128, 13.26008), radius = 1000,
    ax = ax,
    layers = {
        'perimeter': {'circle': circle,'dilate':10},
        'streets': {
            'width': {
                'trunk':5,
                'primary': 4,
                'secondary': 3,
                'tertiary': 2,
                'residential': 2,
                'footway': 1,
                'pedestrian': 1,
                'unclassified': 2
            },
            'circle': circle,
            'buffer': buffer
        },
        'railway':{
            'custom_filter': '["railway"~"rail|light_rail|subway|tram|disused|construction|abandoned|monorail|narrow_gauge"]',
            'width':2,
            'circle':circle,
            'buffer':3000,
            'retain_all':True
        },

        'building': {
            'tags': {
                'building': True,
                'railway':'platform'
            },
            'circle': circle,
            'buffer': buffer
        },
    },
    drawing_kwargs = {
        'background': {'fc': '#F2F4CB', 'ec': '#dadbc1', 'hatch': 'ooo...', 'zorder': -1},
        'perimeter': {'fill': False, 'ec':'#2F3737', 'lw': 10, 'zorder': 4},
        'streets': {'fc': '#2F3737', 'ec': '#475657', 'alpha': 1, 'lw': 0, 'zorder': 1},
        'railway': {'fc': '#FF0000', 'ec': '#FF0000', 'alpha': 1, 'lw': 0, 'zorder': 2},
        'building': {'palette': palette, 'ec': '#2F3737', 'lw': .5, 'zorder': 3},
    },
    osm_credit = {'x': .02, 'y': .01, 'color': '#2F3737'}
)

# Set bounds
xmin, ymin, xmax, ymax = layers['perimeter'].bounds
dx, dy = xmax-xmin, ymax-ymin
ax.set_xlim(xmin-.06*dx, xmax+.06*dx)
ax.set_ylim(ymin-.06*dy, ymax+.02*dy)

plt.savefig('./prints/berlin.png')

image

quickcoffee commented 2 years ago

@G21-Goose I tried for 48.32826, 11.45587 and 'radius': 2000

Thanks to your code I found the issue: I specified different widths for the railway types and I assume some of them were not present in the area of interest and therefore I got the KeyError 'width': { 'rail': 7, 'light_rail': 5, 'subway': 5, 'tram': 4, 'disused': 4, 'construction': 3, 'abandoned': 3, 'monorail': 3, 'narrow_gauge': 3, }, Might be a good idea to either return a better error message or to simply ignore (and maybe return a warning instead) missing keys with a specified width?