2.5. Reading data: JSON & GeoJSON¶
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, read_json_network, read_json_schedule
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:
geojson
{
"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 ] } }
]
}
And the links should follow this format:
geojson
{
"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 ] ] } }
]
}
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