Library / SDK
pysal/momepy avatar
pysal/momepy

momepy measures urban form instead of leaving it to ad hoc scripts

Urban Morphology Measuring Toolkit

638 stars75 forksPythonBSD-3-Clause

At a glance

What is it?
momepy is a PySAL library for urban morphometrics that turns building footprints and street networks into measures of dimension, shape, spatial distribution, intensity, diversity and connectivity, and it warns that its geospatial dependency stack is the hard part of installing it.
Who is it for?
momepy fits a spatial analyst who already works with GeoPandas and needs a consistent, citable set of urban form measures rather than a per-project pile of ad hoc area and length calculations, and who can manage a conda environment.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 10 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A library for the shape of a city, not for maps

momepy stands for Morphological Measuring in Python, and it is described as a library for quantitative analysis of urban form, urban morphometrics. It is part of PySAL, the Python Spatial Analysis Library, and it is built on top of GeoPandas, other PySAL modules, and networkX.

That stack placement is the important structural fact. momepy is not a standalone toolbox with its own geometry engine, its own spatial index and its own file format. It sits on the modern Python geospatial stack, which means the objects it works on are GeoPandas GeoDataFrames and networkX graphs, and the contiguity and weight structures come from libpysal, the same machinery the rest of the spatial econometrics ecosystem uses.

The consequence is that a morphometric measure can be computed on data that other parts of the analysis already hold, and the result can be joined back onto the same frame. The alternative, which most research code actually follows, is a directory of scripts that each load a shapefile, compute a measure with a different implementation, and write a column. momepy's stated aim is a wide range of tools for a systematic and exhaustive analysis of urban form.

The focus is stated too: it works with a wide range of elements while remaining focused on building footprints and street networks. Those two are the data sources that most urban form research starts from, and the fact that the library names them as its focus rather than claiming universality is a good sign about its scope discipline.

Seven families of measures, from dimensions to connectivity

The functionality list in the README is organised by what is being measured, and reading it is the fastest way to understand the library's scope.

Measuring dimensions covers the dimensions of morphological elements, their parts, and aggregated structures. Measuring shapes quantifies the shapes of geometries representing a wide range of morphological features. Capturing spatial distribution handles both the distribution of elements of one kind and the relationships between different kinds of element. Computing density and other types of intensity characters is the density side. Calculating diversity covers various aspects of urban form, which is where the entropy and similarity measures live. Capturing connectivity applies to urban street networks specifically. And generating relational elements of urban form, such as morphological tessellation, is the step that creates the objects the other measures operate on.

That last item is the one that makes the rest possible, and it deserves more attention than the list gives it. A morphometric analysis starts by deciding what counts as an element. A building footprint is an element, a street segment is an element, and a block or a plot is a derived element created by tessellating the plane. Momepy can produce those derived elements, which means the same measure can be applied to a different definition of the city, as long as the definition is expressed as a tessellation.

The two examples the README gives show the style of use. A diversity measure is assigned to a tessellation, taking a column of areas and a contiguity structure:

py
tessellation['area_simpson'] = momepy.simpson(tessellation.area, contiguity_k3)

and a graph measure is computed on a street network in one call:

py
G = momepy.straightness_centrality(G)

Both are single expressions on objects the analyst already has, and both return a value that lands back in the same frame or graph. That is the whole ergonomics of the library: a measure is a function from geometry to a number, with the contiguity structure passed in explicitly.

Contiguity is passed in, not guessed

The contiguity argument in the diversity example is not a detail, it is the design.

In urban morphometrics, a measure of diversity over an area has to know which areas count as neighbours. Whether two blocks are contiguous depends on whether they share a boundary, whether that boundary is a street or a wall, and whether the contact is at a point or along an edge. Those are choices, and a library that silently picks one produces numbers that cannot be compared with anything else.

momepy takes the contiguity structure as an argument, which means the analyst constructs it deliberately, most likely with a libpysal contiguity builder such as the one referenced in the example as contiguity_k3, where k3 denotes a higher-order queen contiguity. The same contiguity can then be reused across measures, which is what makes results internally consistent within an analysis.

This is a genuine difference of approach from the hand-rolled alternative. In a script collection, contiguity is often rebuilt inside each measure function, with slightly different parameters, and the resulting columns end up not comparable with each other. Passing it in makes the choice visible in the code and forces one decision per analysis.

The same principle appears on the network side, where a street network is a networkX graph and the graph measures operate on it directly. Straightness centrality is the example in the README, and the graph is both the input and the output, so the measures are composed rather than recomputed from scratch.

Installing it: conda-forge first, and expect dependency friction

The installation section offers two routes, and the order matters.

sh
conda install -c conda-forge momepy

That is the recommended route, from conda-forge. The alternative is PyPI:

sh
pip install momepy

And then the sentence that a user should not skip: momepy depends on the Python geospatial stack, which might cause some dependency issues. That warning is the honest part of the documentation, and it is worth understanding why it exists rather than hoping it does not apply to you.

The dependency set is modern and heavy. The project requires Python 3.12 or later, and depends on geopandas 1.1 or later, libpysal 4.12.1 or later, networkx 3.4 or later, numpy 2.0 or later, pandas 2.3 or later, shapely 2.1 or later, packaging and tqdm 4.67 or later. Every one of those is a package with compiled extensions or with a strict numerical stack of its own, and the floors are high enough that an older scientific Python environment on the same machine will not satisfy them.

The conditional extras carry the same character. The plus group adds esda, inequality, mapclassify, numba 0.60 or later, osmnx, rioxarray and neatnet, and the tests group adds pytest with coverage and doctest plugins.

The practical guidance is to install into a clean conda environment from conda-forge, and to read the detailed installation instructions in the documentation before doing anything else. This is a library whose installation is the hard part and whose use is comparatively simple.

What the optional extras are actually for

The plus extra is worth unpacking, because the names hint at what momepy does not do itself.

esda is the PySAL module for exploratory spatial data analysis, and inequality brings measures of spatial inequality. mapclassify provides the classification schemes used to turn a continuous measure into categories, which is how a distribution of morphometric values becomes a map of, say, building sizes. osmnx pulls street networks from OpenStreetMap, which matters because a street network is one of the two data sources momepy focuses on and obtaining one is otherwise a substantial chore. neatnet is a library for cleaning and preparing network topology, which is where a graph acquired from a map needs work before graph measures mean anything. numba brings just-in-time compilation for the numeric hot paths. rioxarray handles raster data, which is the route to the satellite imagery and remote sensing side of urban analysis.

The pattern is consistent. momepy deliberately does not absorb these dependencies, so the core stays installable and the heavy or specialised tools are opt-in. That is a good trade for a research library, and it also means a user who needs one of these should install it deliberately rather than discover it missing at the point where a function refuses to run.

One other structural detail in the packaging is worth noticing. The version is dynamic, taken from setuptools_scm, so the version number is derived from the git tags rather than written into the file. That is why the repository also carries an asv.conf.json, the configuration for asv, the airspeed velocity benchmarking tool, since a library with numerical performance characteristics benefits from tracking its own benchmark suite over releases.

Citation, funding and the people behind it

The project asks to be cited with a specific paper, published in the Journal of Open Source Software, by Fleischmann in 2019, titled momepy: Urban Morphology Measuring Toolkit, volume 4 issue 43, article 1807, with a DOI. The README even includes the BibTeX entry:

bibtex
@article{fleischmann_2019,
    author={Fleischmann, Martin},
    title={momepy: Urban Morphology Measuring Toolkit},
    journal={Journal of Open Source Software},
    year={2019},
    volume={4},
    number={43},
    pages={1807},
    DOI={10.21105/joss.01807}
}

The repository also carries both a CITATION.cff file and a CITATION.md, so a citation tool and a human reader get what they need.

Maintenance is named rather than implied. The package is currently maintained by @martinfleis and @jGaboardi, and the copyright line reads 2018 onwards, Martin Fleischmann and PySAL Developers. The licence is BSD 3-Clause, which is a permissive licence with a short notice obligation and no copyleft requirement on the code that uses it.

Funding is listed too, and it explains a good deal about why the library exists in its current shape. The Axel and Margaret Ax:son Johnson Foundation funded it as part of the Urban Form Resilience Project with the University of Strathclyde in Glasgow, UK Research and Innovation funded it through an Economic and Social Research Council grant on learning an urban grammar from satellite data through AI, and Charles University funded it through the Primus programme on socioeconomic and cultural factors in urban structure in Central Europe.

Those grants also hint at the direction of the work, since two of them are about resilience and about learning structure from data, and the releases show the pace. Version 1.0.0 came out on 2026-07-02, preceded by 0.11.0 on 2025-12-23 and 0.10.0 on 2025-04-18, and the last push to the repository was on 2026-10-13. The 1.0 mark is recent, so the API stability it implies is new.

Editorial conclusion

momepy fits a spatial analyst who already works with GeoPandas and needs a consistent, citable set of urban form measures rather than a per-project pile of ad hoc area and length calculations, and who can manage a conda environment. It is the wrong tool for a project that only needs simple descriptive statistics, since the dependency stack is the actual cost, and it is the wrong tool if you need results that are directly comparable to a specific published study without checking which measure definition that study used. Before adopting it, read the installation instructions rather than the two-line install, confirm your environment can satisfy the Python 3.12 floor and the geopandas, libpysal and shapely versions, and cite the JOSS paper rather than the tool informally.

Frequently asked questions

How do I install momepy?

The recommended route is conda install -c conda-forge momepy, with pip install momepy as the PyPI alternative. The README warns that momepy depends on the Python geospatial stack, which might cause dependency issues, and points to the detailed installation instructions in the documentation.

What does momepy measure?

Dimensions of morphological elements and their parts, shapes of geometries, spatial distribution of elements and relationships between kinds of elements, density and other intensity characters, diversity of urban form, connectivity of urban street networks, and the generation of relational elements such as morphological tessellation.

What does momepy depend on?

Python 3.12 or later, with geopandas 1.1, libpysal 4.12.1, networkx 3.4, numpy 2.0, pandas 2.3, shapely 2.1, packaging and tqdm 4.67 as required dependencies, and esda, inequality, mapclassify, numba, osmnx, rioxarray and neatnet in the optional plus group.

What is momepy a part of and what does it build on?

Momepy is part of PySAL, the Python Spatial Analysis Library, and is built on top of GeoPandas, other PySAL modules, and networkX. It works with GeoPandas GeoDataFrames and networkX graphs and focuses on building footprints and street networks.

How should I cite momepy?

Use the Journal of Open Source Software paper, Fleischmann, M. (2019), momepy: Urban Morphology Measuring Toolkit, 4(43), p. 1807, doi 10.21105/joss.01807. The repository also carries CITATION.cff and CITATION.md for the same reference.

Official sources

  1. License: BSD-3-Clause
  2. Project website
  3. pysal/momepy on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pysal-momepy.svg)](https://hysenlabs.com/projects/pysal-momepy)

Was this useful?