Skip to content

Usage: 2.5. Reading Data: JSON & GeoJSON

Kasia Kozlowska edited this page Jul 14, 2022 · 2 revisions

Reading JSON & GeoJSON data

Available as a jupyter notebook or wiki page.

GeNet lets you read JSON data into a Networn graph and PT Schedule, or GeoJSON into Network Graph.

For JSON inputs the network JSON file should follow this format:

{
  "nodes": {
    "unique_node_ID": {
      "id": "unique_node_ID",
      "y": y_spatial_coordinate,
      "x": x_spatial_coordinate
    }
  },
  "links": {
    "unique_link_ID": {
      "id": "unique_link_ID",
      "from": "unique_source_node_ID",
      "to": "unique_target_node_ID",
      "freespeed": 4.166666666666667,
      "permlanes": 1,
      "modes": "car,bus,walk",
      "geometry": "kevj`maB_`la`}`@{ooxA`k~rH", (encoded polyline, otherwise assumed to be straight line between source and target node)
      "length": 52.765151087870265,
      "capacity": 600.0
      "attributes": {  # (optional MATSim link attributes)
        "osm:way:access": {
          "name": "osm:way:access",
          "class": "java.lang.String",
          "text": "permissive"
        },
        "osm:way:id": { # simple form that assumes the java type
          "OSM_ID"
        },
      },
    }
  }
}
from genet import read_json_network, read_json_schedule, read_json
n = read_json_network('../example_data/example_json/network.json', 'epsg:27700')
2022-07-14 15:31:04,968 - Reading Network from ../example_data/example_json/network.json
2022-07-14 15:31:05,058 - Added 4 nodes
2022-07-14 15:31:05,067 - Added 2 links

The JSON Schedule should follow this format:

{
  "schedule": {
    "stops": {
      "unique_stop_ID": {
        "id": "unique_stop_ID",
        "name": "Stop Name", (optional but useful)
        "x": y_spatial_coordinate,
        "y": x_spatial_coordinate,
        "linkRefId": "netowrk_link_ID", (reference to a link in the network graph)
      }
    },
    "services": {
      "unique_service_ID": {
        "id": "unique_service_ID",
        "name": "N55", (optional but useful)
        "routes": {
          "unique_route_ID": {
            "id": "unique_route_ID",
            "route_short_name": "N55", (optional but useful)
            "mode": "bus", (PT mode)
            "trips": {
              "trip_id": [
                "unique_trip_ID"
              ],
              "trip_departure_time": [
                "HH:MM:SS" (departure time for the trip)
              ],
              "vehicle_id": [
                "unique_vehicle_ID"
              ]
            },
            "arrival_offsets": [ (arrival offsets from trip departure time for each stop in route)
              "00:00:00",
              "00:02:20"
            ],
            "departure_offsets": [ (departure offsets from trip departure time for each stop in route)
              "00:00:00",
              "00:02:20"
            ],
            "route_long_name": "", (optional but useful)
            "route": [ (network route for the route)
              "1",
              "10"
            ],
            "ordered_stops": [
              "unique_stop_ID_1",
              "unique_stop_ID_2"
            ]
          }
        }
      }
    },
    "minimal_transfer_times": {
      "unique_stop_ID_1": {
        "stop": "unique_stop_ID_2",
        "transferTime": 100.0
      },
      "unique_stop_ID_2": {
        "stop": "unique_stop_ID_1",
        "transferTime": 100.0
      }
    }
  },
  "vehicles": {
    "vehicle_types": {
      "bus": {
        "capacity": {
          "seats": {
            "persons": "70"
          },
          "standingRoom": {
            "persons": "0"
          }
        },
        "length": {
          "meter": "18.0"
        },
        "width": {
          "meter": "2.5"
        },
        "accessTime": {
          "secondsPerPerson": "0.5"
        },
        "egressTime": {
          "secondsPerPerson": "0.5"
        },
        "doorOperation": {
          "mode": "serial"
        },
        "passengerCarEquivalents": {
          "pce": "2.8"
        }
      }
    },
    "vehicles": {
      "veh_0_bus": {
        "type": "bus"
      }
    }
  }
}

the references to the network: linkRefId and route can be left out. That network will not work with MATSim. GeNet can snap and route PT services and fill in those blanks, though not at scale.

s = read_json_schedule('../example_data/example_json/schedule.json', 'epsg:27700')
2022-07-14 15:31:05,075 - Reading Schedule from ../example_data/example_json/schedule.json

If you have both json inputs for a network you can also read both the network json and schedule json at the same time.

n = read_json(
    network_path='../example_data/example_json/network.json', 
    schedule_path='../example_data/example_json/schedule.json',
    epsg='epsg:27700'
)
2022-07-14 15:31:05,119 - Reading Network from ../example_data/example_json/network.json
2022-07-14 15:31:05,281 - Added 4 nodes
2022-07-14 15:31:05,354 - Added 2 links
2022-07-14 15:31:05,360 - Reading Schedule from ../example_data/example_json/schedule.json

Given GeoJson, you can create a Network graph. Two files are expected, one for nodes and one for links.

The nodes should follow this format:

{
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:EPSG::27700" } },
"features": [
{ "type": "Feature", "properties": {"id": "25508485", "x": 528489.467895946, "y": 182206.20303669578, "lon": -0.14930198709481451, "lat": 51.524162533239284, "s2_id": 5221390301001263407 }, "geometry": { "type": "Point", "coordinates": [ 528489.467895945999771, 182206.203036695776973 ] } }
]
}
Loading

And the links should follow this format:

{
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:EPSG::27700" } },
"features": [
{ "type": "Feature", "properties": {"id": "1", "from": "25508485", "to": "21667818", "freespeed": 4.166666666666667, "capacity": 600.0, "permlanes": 1.0, "oneway": "1", "modes": "car", "s2_from": 5221390301001263407, "s2_to": 5221390302696205321, "attributes": { "osm:way:access": { "name": "osm:way:access", "class": "java.lang.String", "text": "permissive" }, "osm:way:highway": { "name": "osm:way:highway", "class": "java.lang.String", "text": "unclassified" }, "osm:way:id": "26997928" }, 
"osm:way:name": { "name": "osm:way:name", "class": "java.lang.String", "text": "Brunswick Place" } }, "length": 52.765151087870265 }, "geometry": { "type": "LineString", "coordinates": [ [ 528489.467895945999771, 182206.203036695776973 ], [ 528504.134284314350225, 182155.743513659806922 ] ] } }
]
}
Loading

Note that additional, nested attributes can take a long form:

"osm:way:name": { "name": "osm:way:name", "class": "java.lang.String", "text": "Brunswick Place" }

or a simple form that assumed data types:

"osm:way:name": "Brunswick Place" 
from genet import read_geojson_network
n = read_geojson_network(
    '../example_data/example_geojson/network_nodes.geojson', 
    '../example_data/example_geojson/network_links.geojson', 
    'epsg:27700')
2022-07-14 15:31:05,419 - Reading Network nodes from ../example_data/example_geojson/network_nodes.geojson
2022-07-14 15:31:05,520 - Reading Network links from ../example_data/example_geojson/network_links.geojson
2022-07-14 15:31:05,613 - Added 4 nodes
2022-07-14 15:31:05,622 - Added 2 links

The GeoJSONs carry a projection for their geometry. The epsg passed in the method above is for the Network, the links will inherit the geometry stored in the geojson but project it (if not already in the correct projection) to match the Network's projection