pysal / momepy

Urban Morphology Measuring Toolkit
https://docs.momepy.org
BSD 3-Clause "New" or "Revised" License
493 stars 59 forks source link

Adding SNDi to momepy #275

Open amorfinv opened 3 years ago

amorfinv commented 3 years ago

Hello,

It would be great if momepy could include a function to calculate the Street-Network Disconnectedness index (SNDi) from this paper. The authors (Christopher Barrington-Leigh and Adam Millard-Ball) already have open-source code code in gitlab. However, it was not built to interface with an OSMnx graph.

The momepy function would take an OSMnx graph as an argument and return the SNDi. This supporting document explains the method to calculate the SNDi in detail. They provide this table gives to give an overview of all the different metrics image

They then did a principal component analysis (PCA) of the whole world's street-network (GADM dataset) and decided on 13 distinct aggregate metrics for the SNDi:

Pages 4-9 of the supporting document go into detail about how exactly the metrics are calculated. The authors first calculated each of these metrics for the whole-world and get a mean and standard deviation that is used to scale for smaller geographic regions. These are not in the documentation, but they are found in the code:

Screen Shot 2021-05-19 at 9 24 52 AM

With these values, they came up with component loadings for the PCA:

image

Note that they only use PCA1 for the SNDI. So to calculate the PCA for a certain geographic region need:

The formula for PCA1 of a certain region is then:

Screen Shot 2021-05-19 at 9 30 01 AM

With the PCA1 it is easy to calculate the SNDi as you just need to add 3

SNDi = PCA1 + 3

Please see PDF for below for reference:

SNDi_procedure.pdf

Please let me know if something is unclear.

Also, from what I read in the supporting information, the nodal density is not actually used in the SNDi calculation. However, it is used for classifying cities if I read correctly. And it seems like the aggregate measures only take drivable streets (no bicycle, walking, or service edges). However, I am still a bit confused about this part (see page 36 of the supporting document) so I will need to do more reading.

martinfleis commented 3 years ago

Hi,

this looks like a great addition. We would need to add individual functions computing circuity etc and then one using them all to compute SNDi.

I have no capacity to work on that, so if you'd like to try implementing some bits towards this goal, you're very welcome to do so. It is also possible that some of them are already implemented but I'd need to check their definitions.

amorfinv commented 3 years ago

Hey @martinfleis,

I was hoping to get to this at some point but I am quite busy right now. Unsure when I will be able to do this. I will let you know whenever I start making some progress.

-Andres

amorfinv commented 3 years ago

Started getting the ball rolling on this. I think it should be easy. Main challenge I am facing is figuring out how to merge edges that contain degree-2 nodes. I think this is what the authors do. I am currently able to do it for directed graphs so I hope it will be easy to apply to undirected graphs.

martinfleis commented 3 years ago

You mean like we do in momepy.remove_false_nodes or differently? http://docs.momepy.org/en/latest/generated/momepy.remove_false_nodes.html

amorfinv commented 3 years ago

I think that is exactly it!

amorfinv commented 3 years ago

Hello,

So I pretty much finished all the metrics except circuity. For the sinuosity metric, I slightly updated momepy.Linearity to include an aggregated measure.

Is there anything in momepy that would work to calculate circuity? There is osmnx.stats.circuity_av in osmnx that I can use for inspiration.

-Andres

update:

I found these distance matrix functions that make things into numpy arrays. So I think I will just use this.

shortest path distance matrix nx.floyd_warshall_numpy euclidean distance matrix libpysal.cg.distance_matrix

martinfleis commented 3 years ago

Hi, great!

We could adapt what we have in Linearity to get circuity I guess but if you have NumPy version already that may be faster :).

amorfinv commented 3 years ago

finished a version 1...however results are quite off haha..so trying to see what I did wrong

martinfleis commented 3 years ago

Feel free to push it as a draft PR, we can have a look as well.