{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 5) Pedestrian Flow over Multiple Pairs of Origins and Destinations. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Two main advantages of using UNA in python are automation and scallability. In this section, we'll se how we can automate estimating flows over multiple pairs of origins and destinations. A task that takes a lot of time if done on a GUI software. We will create a pairing table: a table that define what origin, destination, and parameters are used to generate flow in each pair." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import madina as md\n", "import madina.una.tools as una\n", "import pandas as pd\n", "import os\n", "import multiprocessing\n", "from pathlib import Path" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We will be using the sample data from Somerville, MA provided in the folder `Cities/Somerville/Data`. The data files must all be in thw same CRS, and all must be clipped to the same analysis area. We want to store all the results in a folder called `Cities/Somerville/Simulations/Baseline`" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "data_folder = os.path.join(\"Cities\", \"Somerville\", \"Data\")\n", "output_folder = os.path.join(\"Cities\", \"Somerville\", \"Simulations\", \"Baseline\")\n", "Path(output_folder).mkdir(parents=True, exist_ok=True) ## create the output folder if it doesn't exist" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Then, We identify the pairs of origins and destinations we want to simulate. Assign each pair a `Flow_Name`: This name would be used to store the corresponding flow as a column/attribute in the network file. We then we name the `Origin_File` and `Origin_Name` for each origin in the pair, we also specify an `Origin_Weight`: an attribute/column in the origin layer. if we didn't want to assign a weight for a given origin, we use the keyword `Count` to indicate that all origins weight the same. We do the same for destinations where we specify `Destination_File`, `Destination_Name` and `Destination_Weight`" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Flow_NameOrigin_FileOrigin_NameOrigin_WeightDestination_FileDestination_NameDestination_Weight
0Bus_Subwaybus.geojsonBusLineCountsubway.geojsonSubwayCount
1Homes_Subwayhomes.geojsonHomesRES_2020Bsubway.geojsonSubwayCount
2Jobs_Subwayjobs.geojsonJobsEMPNUMsubway.geojsonSubwayCount
3Amenities_Amenitiesamenities.geojsonAmenitiesCountamenities.geojsonAmenitiesCount
4CensusBlock_ParksCensusBlock.geojsonCensusBlockPOP20parks.geojsonParksCount
5Institutions_Subwayinstitutions.geojsonInstitutionsCountsubway.geojsonSubwayCount
\n", "
" ], "text/plain": [ " Flow_Name Origin_File Origin_Name Origin_Weight \\\n", "0 Bus_Subway bus.geojson Bus LineCount \n", "1 Homes_Subway homes.geojson Homes RES_2020B \n", "2 Jobs_Subway jobs.geojson Jobs EMPNUM \n", "3 Amenities_Amenities amenities.geojson Amenities Count \n", "4 CensusBlock_Parks CensusBlock.geojson CensusBlock POP20 \n", "5 Institutions_Subway institutions.geojson Institutions Count \n", "\n", " Destination_File Destination_Name Destination_Weight \n", "0 subway.geojson Subway Count \n", "1 subway.geojson Subway Count \n", "2 subway.geojson Subway Count \n", "3 amenities.geojson Amenities Count \n", "4 parks.geojson Parks Count \n", "5 subway.geojson Subway Count " ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pairing_table = pd.DataFrame(\n", " {\n", " 'Flow_Name': ['Bus_Subway', 'Homes_Subway', 'Jobs_Subway', 'Amenities_Amenities', 'CensusBlock_Parks', 'Institutions_Subway'],\n", " 'Origin_File': ['bus.geojson', 'homes.geojson', 'jobs.geojson', 'amenities.geojson', 'CensusBlock.geojson', 'institutions.geojson'],\n", " 'Origin_Name': ['Bus', 'Homes', 'Jobs', 'Amenities', 'CensusBlock', 'Institutions'],\n", " 'Origin_Weight': ['LineCount', 'RES_2020B', 'EMPNUM', 'Count', 'POP20', 'Count'],\n", " 'Destination_File': ['subway.geojson', 'subway.geojson', 'subway.geojson', 'amenities.geojson', 'parks.geojson', 'subway.geojson'],\n", " 'Destination_Name': ['Subway', 'Subway', 'Subway', 'Amenities', 'Parks', 'Subway'],\n", " 'Destination_Weight': ['Count', 'Count', 'Count', 'Count', 'Count', 'Count']\n", " }\n", ")\n", "pairing_table" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "All OD pair flows should be estimated using the same network. Each pair could potentially use a different network cost if for example, we eanted to account for different percieved distances to different demographics or trip types.in this example, we will use the same network and percieved distance. In our pairing table, we specify a `Network_File` and a `Network_Cost`: a column that contains numerical values." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Flow_NameOrigin_FileOrigin_NameOrigin_WeightDestination_FileDestination_NameDestination_WeightNetwork_FileNetwork_Cost
0Bus_Subwaybus.geojsonBusLineCountsubway.geojsonSubwayCountnetwork.geojsonPercLen
1Homes_Subwayhomes.geojsonHomesRES_2020Bsubway.geojsonSubwayCountnetwork.geojsonPercLen
2Jobs_Subwayjobs.geojsonJobsEMPNUMsubway.geojsonSubwayCountnetwork.geojsonPercLen
3Amenities_Amenitiesamenities.geojsonAmenitiesCountamenities.geojsonAmenitiesCountnetwork.geojsonPercLen
4CensusBlock_ParksCensusBlock.geojsonCensusBlockPOP20parks.geojsonParksCountnetwork.geojsonPercLen
5Institutions_Subwayinstitutions.geojsonInstitutionsCountsubway.geojsonSubwayCountnetwork.geojsonPercLen
\n", "
" ], "text/plain": [ " Flow_Name Origin_File Origin_Name Origin_Weight \\\n", "0 Bus_Subway bus.geojson Bus LineCount \n", "1 Homes_Subway homes.geojson Homes RES_2020B \n", "2 Jobs_Subway jobs.geojson Jobs EMPNUM \n", "3 Amenities_Amenities amenities.geojson Amenities Count \n", "4 CensusBlock_Parks CensusBlock.geojson CensusBlock POP20 \n", "5 Institutions_Subway institutions.geojson Institutions Count \n", "\n", " Destination_File Destination_Name Destination_Weight Network_File \\\n", "0 subway.geojson Subway Count network.geojson \n", "1 subway.geojson Subway Count network.geojson \n", "2 subway.geojson Subway Count network.geojson \n", "3 amenities.geojson Amenities Count network.geojson \n", "4 parks.geojson Parks Count network.geojson \n", "5 subway.geojson Subway Count network.geojson \n", "\n", " Network_Cost \n", "0 PercLen \n", "1 PercLen \n", "2 PercLen \n", "3 PercLen \n", "4 PercLen \n", "5 PercLen " ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pairing_table['Network_File'] = 'network.geojson'\n", "pairing_table['Network_Cost'] = 'PercLen'\n", "pairing_table" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After specifying origins, destinations and the network, we need to specify parameters for the betweenness function. In many cases, you want to use the same parameter for all pairs:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Flow_NameOrigin_FileOrigin_NameOrigin_WeightDestination_FileDestination_NameDestination_WeightNetwork_FileNetwork_CostRadius...DecayDecay_ModeBetaClosest_destinationElastic_WeightsKNN_WeightPlateauTurnsTurn_ThresholdTurn_Penalty
0Bus_Subwaybus.geojsonBusLineCountsubway.geojsonSubwayCountnetwork.geojsonPercLen800...Trueexponent0.001FalseFalseNoneNoneFalseNoneNone
1Homes_Subwayhomes.geojsonHomesRES_2020Bsubway.geojsonSubwayCountnetwork.geojsonPercLen800...Trueexponent0.001FalseFalseNoneNoneFalseNoneNone
2Jobs_Subwayjobs.geojsonJobsEMPNUMsubway.geojsonSubwayCountnetwork.geojsonPercLen800...Trueexponent0.001FalseFalseNoneNoneFalseNoneNone
3Amenities_Amenitiesamenities.geojsonAmenitiesCountamenities.geojsonAmenitiesCountnetwork.geojsonPercLen800...Trueexponent0.001FalseFalseNoneNoneFalseNoneNone
4CensusBlock_ParksCensusBlock.geojsonCensusBlockPOP20parks.geojsonParksCountnetwork.geojsonPercLen800...Trueexponent0.001FalseFalseNoneNoneFalseNoneNone
5Institutions_Subwayinstitutions.geojsonInstitutionsCountsubway.geojsonSubwayCountnetwork.geojsonPercLen800...Trueexponent0.001FalseFalseNoneNoneFalseNoneNone
\n", "

6 rows × 21 columns

\n", "
" ], "text/plain": [ " Flow_Name Origin_File Origin_Name Origin_Weight \\\n", "0 Bus_Subway bus.geojson Bus LineCount \n", "1 Homes_Subway homes.geojson Homes RES_2020B \n", "2 Jobs_Subway jobs.geojson Jobs EMPNUM \n", "3 Amenities_Amenities amenities.geojson Amenities Count \n", "4 CensusBlock_Parks CensusBlock.geojson CensusBlock POP20 \n", "5 Institutions_Subway institutions.geojson Institutions Count \n", "\n", " Destination_File Destination_Name Destination_Weight Network_File \\\n", "0 subway.geojson Subway Count network.geojson \n", "1 subway.geojson Subway Count network.geojson \n", "2 subway.geojson Subway Count network.geojson \n", "3 amenities.geojson Amenities Count network.geojson \n", "4 parks.geojson Parks Count network.geojson \n", "5 subway.geojson Subway Count network.geojson \n", "\n", " Network_Cost Radius ... Decay Decay_Mode Beta Closest_destination \\\n", "0 PercLen 800 ... True exponent 0.001 False \n", "1 PercLen 800 ... True exponent 0.001 False \n", "2 PercLen 800 ... True exponent 0.001 False \n", "3 PercLen 800 ... True exponent 0.001 False \n", "4 PercLen 800 ... True exponent 0.001 False \n", "5 PercLen 800 ... True exponent 0.001 False \n", "\n", " Elastic_Weights KNN_Weight Plateau Turns Turn_Threshold Turn_Penalty \n", "0 False None None False None None \n", "1 False None None False None None \n", "2 False None None False None None \n", "3 False None None False None None \n", "4 False None None False None None \n", "5 False None None False None None \n", "\n", "[6 rows x 21 columns]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pairing_table['Radius'] = 800\n", "pairing_table['Detour'] = 1.15\n", "pairing_table['Decay'] = True\n", "pairing_table['Decay_Mode'] = 'exponent'\n", "pairing_table['Beta'] = 0.001\n", "pairing_table['Closest_destination'] = False\n", "pairing_table['Elastic_Weights'] = False\n", "pairing_table['KNN_Weight'] = None\n", "pairing_table['Plateau'] = None\n", "pairing_table['Turns'] = False\n", "pairing_table['Turn_Threshold'] = None\n", "pairing_table['Turn_Penalty'] = None\n", "pairing_table" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If for instance, we needed to set specific parameters, for instance, we want to set the search radius for the pair \"Bus_Subway\" to 400 instead of 800:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Flow_NameOrigin_FileOrigin_NameOrigin_WeightDestination_FileDestination_NameDestination_WeightNetwork_FileNetwork_CostRadius...DecayDecay_ModeBetaClosest_destinationElastic_WeightsKNN_WeightPlateauTurnsTurn_ThresholdTurn_Penalty
0Bus_Subwaybus.geojsonBusLineCountsubway.geojsonSubwayCountnetwork.geojsonPercLen400...Trueexponent0.001FalseFalseNoneNoneFalseNoneNone
1Homes_Subwayhomes.geojsonHomesRES_2020Bsubway.geojsonSubwayCountnetwork.geojsonPercLen800...Trueexponent0.001FalseFalseNoneNoneFalseNoneNone
2Jobs_Subwayjobs.geojsonJobsEMPNUMsubway.geojsonSubwayCountnetwork.geojsonPercLen800...Trueexponent0.001FalseFalseNoneNoneFalseNoneNone
3Amenities_Amenitiesamenities.geojsonAmenitiesCountamenities.geojsonAmenitiesCountnetwork.geojsonPercLen800...Trueexponent0.001FalseFalseNoneNoneFalseNoneNone
4CensusBlock_ParksCensusBlock.geojsonCensusBlockPOP20parks.geojsonParksCountnetwork.geojsonPercLen800...Trueexponent0.001FalseFalseNoneNoneFalseNoneNone
5Institutions_Subwayinstitutions.geojsonInstitutionsCountsubway.geojsonSubwayCountnetwork.geojsonPercLen800...Trueexponent0.001FalseFalseNoneNoneFalseNoneNone
\n", "

6 rows × 21 columns

\n", "
" ], "text/plain": [ " Flow_Name Origin_File Origin_Name Origin_Weight \\\n", "0 Bus_Subway bus.geojson Bus LineCount \n", "1 Homes_Subway homes.geojson Homes RES_2020B \n", "2 Jobs_Subway jobs.geojson Jobs EMPNUM \n", "3 Amenities_Amenities amenities.geojson Amenities Count \n", "4 CensusBlock_Parks CensusBlock.geojson CensusBlock POP20 \n", "5 Institutions_Subway institutions.geojson Institutions Count \n", "\n", " Destination_File Destination_Name Destination_Weight Network_File \\\n", "0 subway.geojson Subway Count network.geojson \n", "1 subway.geojson Subway Count network.geojson \n", "2 subway.geojson Subway Count network.geojson \n", "3 amenities.geojson Amenities Count network.geojson \n", "4 parks.geojson Parks Count network.geojson \n", "5 subway.geojson Subway Count network.geojson \n", "\n", " Network_Cost Radius ... Decay Decay_Mode Beta Closest_destination \\\n", "0 PercLen 400 ... True exponent 0.001 False \n", "1 PercLen 800 ... True exponent 0.001 False \n", "2 PercLen 800 ... True exponent 0.001 False \n", "3 PercLen 800 ... True exponent 0.001 False \n", "4 PercLen 800 ... True exponent 0.001 False \n", "5 PercLen 800 ... True exponent 0.001 False \n", "\n", " Elastic_Weights KNN_Weight Plateau Turns Turn_Threshold Turn_Penalty \n", "0 False None None False None None \n", "1 False None None False None None \n", "2 False None None False None None \n", "3 False None None False None None \n", "4 False None None False None None \n", "5 False None None False None None \n", "\n", "[6 rows x 21 columns]" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pairing_table.at[0, 'Radius'] = 400\n", "pairing_table" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Once the input data is prepared, and the pairing table is complete, we have everything we need to calculate the betweenness flow for the six pairs of origins, destinations and their parameters" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-----------------------Done generating flow: Bus_Subway -----------------------\n", "-----------------------Done generating flow: Homes_Subway -----------------------\n", "-----------------------Done generating flow: Jobs_Subway -----------------------\n", "-----------------------Done generating flow: Amenities_Amenities -----------------------\n", "-----------------------Done generating flow: CensusBlock_Parks -----------------------\n", "-----------------------Done generating flow: Institutions_Subway -----------------------\n", "-----------------------Done Generating all flows-----------------------\n" ] } ], "source": [ "# Creating a Zonal object to be used as a workspace.\n", "somerville = md.Zonal()\n", "\n", "# Loading the network file, as specified in the first pair.\n", "somerville.load_layer(\n", " name='streets',\n", " source=os.path.join(data_folder, pairing_table.at[0, \"Network_File\"])\n", ")\n", "\n", "# Going on a loop over rows of the pairing table\n", "for pairing_idx, pairing in pairing_table.iterrows():\n", " \n", " if (pairing_idx == 0) or (pairing_table.at[pairing_idx, 'Network_Cost'] != pairing_table.at[pairing_idx-1, 'Network_Cost']):\n", " # Setting up a street network if this is the first pairing, or if the network weight changed from previous pairing\n", " somerville.create_street_network(\n", " source_layer='streets', \n", " node_snapping_tolerance=0.00001,\n", " weight_attribute=None if pairing['Network_Cost'] == \"Geometric\" else pairing['Network_Cost'], # set weight attribute to None if the keyword 'Geometric\" was used, otherwise, use the provided attribute.\n", " )\n", " else:\n", " # if not creating a new network, clear nodes from the existing.\n", " somerville.clear_nodes()\n", "\n", "\n", " # if turn penalty is applied, update turn parameters in case they change across pairs\n", " if pairing['Turns']:\n", " somerville.set_turn_parameters(\n", " turn_penalty_amount=pairing['Turn_Penalty'], \n", " turn_threshold_degree=pairing['Turn_Threshold'],\n", " )\n", "\n", "\n", "\n", " # Loading layers, if they're not already loaded.\n", " if pairing[\"Origin_Name\"] not in somerville.layers:\n", " somerville.load_layer(\n", " name=pairing[\"Origin_Name\"],\n", " source=os.path.join(data_folder, pairing[\"Origin_File\"])\n", " )\n", "\n", " if pairing[\"Destination_Name\"] not in somerville.layers:\n", " somerville.load_layer(\n", " name=pairing[\"Destination_Name\"],\n", " source=os.path.join(data_folder, pairing[\"Destination_File\"])\n", " )\n", "\n", " \n", " # Inserting origin and destination nodes.\n", " somerville.insert_node(\n", " layer_name=pairing['Origin_Name'], \n", " label='origin', \n", " weight_attribute=pairing['Origin_Weight'] if pairing['Origin_Weight'] != \"Count\" else None\n", " )\n", " somerville.insert_node(\n", " layer_name=pairing['Destination_Name'], \n", " label='destination', \n", " weight_attribute=pairing['Destination_Weight'] if pairing['Destination_Weight'] != \"Count\" else None\n", " )\n", "\n", "\n", " # create a network graph\n", " somerville.create_graph()\n", "\n", " # run the betweenness tool by passing arguments from the current pair in the loop.\n", " una.betweenness(\n", " zonal=somerville,\n", " search_radius=pairing['Radius'],\n", " detour_ratio=pairing['Detour'],\n", " decay=False if pairing['Elastic_Weights'] else pairing['Decay'], # elastic weight already reduces origin weight factoring in decay. if this pairing uses elastic weights, don't apply decay\n", " decay_method=pairing['Decay_Mode'],\n", " beta=pairing['Beta'],\n", " num_cores=multiprocessing.cpu_count(), #uses the maximum available number of cores. \n", " closest_destination=pairing['Closest_destination'],\n", " elastic_weight=pairing['Elastic_Weights'],\n", " knn_weight=pairing['KNN_Weight'],\n", " knn_plateau=pairing['Plateau'], \n", " turn_penalty=pairing['Turns'],\n", " save_betweenness_as=pairing['Flow_Name'], \n", " save_reach_as='reach_'+pairing['Flow_Name'], \n", " save_gravity_as='gravity_'+pairing['Flow_Name'],\n", " save_elastic_weight_as='elastic_weight_'+pairing['Flow_Name'] if pairing['Elastic_Weights'] else None, # saving elastic weights if they were used. \n", " )\n", " print (\"-----------------------Done generating flow: \", pairing['Flow_Name'], \"-----------------------\")\n", "\n", "# Save saving origin results (reach, gravity are saved to the origin layer)\n", "for origin_layer in pairing_table['Origin_Name'].unique():\n", " somerville[origin_layer].gdf.to_file(os.path.join(output_folder, origin_layer+'.geojson'), driver='GeoJSON', engine='pyogrio')\n", "\n", "# saving network results, betweenness flows are saved to the network layer.\n", "somerville['streets'].gdf.to_file(os.path.join(output_folder, pairing_table.at[0, \"Network_File\"]+'.geojson'), driver='GeoJSON', engine='pyogrio')\n", "print(\"-----------------------Done Generating all flows-----------------------\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The loop above, once done, would generate betweenness flows for all specified six pairs. These flows are useful to recognize critical paths between a given pair of origins and destinations, or could be used to train a pedestrian flow prediction model if training pedestrain counts are available. " ] } ], "metadata": { "kernelspec": { "display_name": "madina_dev", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.0" } }, "nbformat": 4, "nbformat_minor": 2 }