Skip to content

Instantly share code, notes, and snippets.

@NeatNit
Last active January 15, 2024 19:59
Show Gist options
  • Save NeatNit/6aab2b607ce23b81ef765de0e5bf3584 to your computer and use it in GitHub Desktop.
Save NeatNit/6aab2b607ce23b81ef765de0e5bf3584 to your computer and use it in GitHub Desktop.
Understanding Israel MOT's GTFS format

Israel's GTFS for Bus Routes

Start page: https://www.gov.il/he/departments/general/gtfs_general_transit_feed_specifications
Includes a linked PDF that explains the formats in detail.

OSM wiki: https://wiki.openstreetmap.org/wiki/GTFS
GTFM standard reference: https://gtfs.org/schedule/reference/ (not really needed as the PDF explains everything)

Here's my understanding for the parts that are relevant for OSM import:

Firstly, files are downloaded via HTTPS in this link: https://gtfs.mot.gov.il/gtfsfiles/israel-public-transportation.zip

FTP used to be available, but no longer (according to documents; I didn't check).

Bus stops

This should be relatively straighforward. Bus, train and light rail stops and stations are listed in stops.txt with lat/lon location, stop name, and ID numbers. My key takeaways (not 100% verified in the data yet):

  • stop_desc: address for the stop in Hebrew: רחוב, עיר, רציף, קומה. This field can be used to filter stations by type:
    • It's always empty for Israel Railway stops
    • Bus stops always have the headers even if there fields are empty
    • Light rail always starts with "רחוב: מסילת ברזל" (and bus stops never do)
      • all Jerusalem light rail stops have "רחוב: מסילת ברזל עיר: ירושלים רציף: קומה:"
      • light rail stops in גוש דן starts with "רחוב: מסילת ברזל קו אדום גוש דן" (city and platform vary)
  • location_type=0 are stops. location_type=1 are for central stations (תחנה מרכזית), and there are separate listings for the stops within them. So ignore location_type=1 for now
  • stop_id is an internal ID to cross-reference with the other files in the data; stop_code is the public-facing number that appears on station signs

translations.txt contains translations from Hebrew names to Arabic and English. And to Hebrew, for some reason.

How to map them

There is no single consensus for how to map bus stops in OSM. There are several proposals. As I am inexperienced with OSM, I will let the rest of the community figure out what the best way to map it is. Have a look at an example node from previous automated imports. Its edit history might also offer insights - I haven't looked much into it.

Bus routes

We may want to add to each station information about which lines stop at that station, mirroring the information on the signs at the station. This information isn't directly listed, and must be inferred from bus routes.

Extracting a bus route, and which stations belong to each route, is messier than I expected. If my understanding is correct, this is how it's set up:

routes.txt lists every bus route, without station information. Lines that go in two directions have a separate entry for each direction, and each minor route change has a separate listing as well. See the PDF for more precise information. It contains line name and number (route_short_name = line number, sometimes stuff like 86א or the like)

trips.txt has a separate entry for each occurrence the bus route has - i.e. if the bus goes 10 times in one day, trips.txt will have 10 entries, one for each. This is to be cross-referenced with other files. I didn't look too much into the details of this, e.g. how weekdays vs weekends are handled precisely.

  • (needs verification) direction_id can be ignored - each route should have a constant direction_id for all trips, and this is mirrored in route_desc of routes.txt

stop_times.txt lists: for each trip in trips.txt, for each stop the trip stops at, what time this is expected to happen. This file is 353 MB at the time of writing - the biggest file in the lot - just for the sheer number of entries.

It seems that the only way to link bus stops to routes is through this process:

  1. Pick a bus stop, get its stop_id
  2. Find all occurrences of that station in stop_times.txt, get a list of trip_ids
  3. Find each trip_id, find its route_id in trips.txt
  4. Remove duplicates
  5. For each route_id, find its number (route_short_name) in routes.txt
  6. Remove duplicates

If we want to preserve route direction, extra steps are needed. Needed e.g. when the same line number going in different directions stops at the same stop, and users want to know which alternative it is. Potentially use trip_headsign from trips.txt.

Found this https://stackoverflow.com/q/13407468 which basically confirms my conclusions above.

Previous work to look into

  • SafwatHalaby's GTFS import script (GitHub), which was used successfully in Israel in 2017-2020. It might be possible to get it back up and running, but its requirements and manual-ish workflow is something to watch out for.
    • Important note by the original developer: https://community.openstreetmap.org/t/automated-incremental-bus-stop-gtfs-updates/81124/72

      I would like to make the script completely stateless locally. This should be technically possible: Fetch latest bus stop changeset by SafwatHalaby_bot, and use that as the “old gtfs file”. This would make the script solely dependent on OSM servers, and not on any local hard drive.

      This might be a major overwrite, so while we’re at it, I would like to rewrite the script such that it does not depend on JOSM. This should make running it headless natural and pave the way for complete automation.

  • GO-Sync (gtfs-osm-sync), designed to be used by the agency (i.e. MOT) to facilitate two-way synchronization and benefit both systems. Still, it may be useful to us as users.
  • PTNA - Public Transport Network Analysis (OSM wiki
  • Tool to sync GTFS to OSM (GitLab) - only suggests edits to the user, might be a useful jumping off point

Other notes

shapes.txt shows the precise routes buses take - i.e. it shows road shape. Possibly useful for comparing with OSM roads, but I wouldn't know. Not useful for public transport mapping as far as I can tell.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment