Project

Topodex: contextual geocoding for conflict and human rights corpora

A Python library that makes geocoders accountable to the document they are reading. 894M+ places resolved across nine open sources, reranked against document context, with a six-category failure taxonomy and a coherence check over everywhere a document names.

Period

2026 to present

Status

Active

Role

Author and lead developer

Areas

Python · NLP · Geocoding · Nominatim · Pleiades · OpenHistoricalMap · GeoAI

The Topodex dashboard, showing toponym input alongside document context, temporal range and an LLM-synthesised candidate toggle.
Figure

The dashboard. A toponym is never submitted alone: the document context and temporal range it came from are inputs to the resolution, not metadata attached afterwards.

  • 894M+Places resolvedToponyms reconciled across nine gazetteers that spell, transliterate and administer the same place differently.
  • 9Open geocodersNominatim, GeoNames, Wikidata, Overpass, OpenHistoricalMap, NGA GEOnet, Overture, Pleiades and Who's on First. No proprietary API required.
  • 7Scoring componentsAdministrative level, country, proximity to co-entities, temporal plausibility, name similarity, language and source importance.
  • 6Failure modesFormally classified, detected per toponym, and surfaced with evidence and a suggested correction rather than resolved silently.

The brief

A place name in a document is not a coordinate. Between the two sits a sequence of decisions, about which country, which administrative level and which historical moment, that standard geocoding tools make silently and without any awareness of what the document is about.

For most applications that silence is a minor nuisance. For research on conflict, forced displacement and modern slavery it corrupts the evidentiary record, and it does so in patterned rather than random ways. Village names repeat dozens of times within a country and the most prominent one wins. Administrative boundaries shift during a conflict, so the current map does not describe the geography the document was written in. Arabic, Burmese, Amharic and Lingala names are romanised differently across sources, degrading or failing the match. And forced labour sites, transit camps and rural detention locations are precisely the places a popularity ranking buries under the nearest city.

Topodex does not replace the gazetteers. It makes their output accountable to the document it came from, wrapping nine open sources in a disambiguation engine that reasons from context and a validator that checks whether the document’s full set of locations is geographically plausible at all.

The insight

Two ideas do most of the work, and both come from refusing to treat a toponym as an isolated lookup key.

The first is that the document already contains the evidence needed to disambiguate. Co-occurring place names constrain the plausible region. The prose implies an administrative level, since a report naming a camp is not naming a governorate. The temporal frame rules out entities that did not exist yet or no longer existed. Building a profile from those signals before querying anything turns a string into a question with constraints attached, and reranking on seven weighted components then replaces generic popularity with contextual relevance.

The second is that a document is a unit of validation, not just a container of names. A single resolution can look entirely reasonable and still be wrong, and the tell is usually its relationship to everything else the document mentions. Checking the resolved set for implausible spans, statistical outliers and contextual contradictions catches errors that no per-name confidence score can, which is why the coherence score is computed across the document rather than attached to individual results.

Making the weight budget respond to detected risk follows from both. If the profile flags a likely homonym, popularity is exactly the wrong signal to trust, so the system suppresses it and leans on proximity instead.

What it does not do

The benchmark is small. Forty-two annotated toponyms across twelve conflict zones, drawn from ICTY judgments, ReliefWeb situation reports and ACLED event data, is enough to demonstrate the failure modes and not enough to make strong claims about generalisation. The expansion target is 300 to 500 annotations across Bosnia, Sudan, the DRC, Myanmar, Haiti and historical English-language sources, and until that exists the reported numbers should be read as indicative.

It inherits gazetteer coverage. Where no open source records a place, no amount of reranking will find it, and the regions with the thinnest coverage correlate uncomfortably well with the regions this work most wants to serve.

Learned weights are promising rather than proven. The estimate that 20 to 30 corrections adapt the system to a new conflict zone comes from simulation, not from deployment. And the disambiguation profile depends on a language model, which introduces a component whose failures are harder to characterise than the six the taxonomy names. The audit trail is designed so that those failures stay visible, which is a mitigation rather than a solution.

How it works

5 stages
  1. 01

    Read the document before the gazetteer

    Each toponym gets a disambiguation profile built from the surrounding text and temporal context: the implied administrative level, co-occurring place names, language and transliteration signals, and structured risk flags. This happens before any geocoder is queried.

    The profile is what converts a bare string into a question with constraints. Standard tools skip this step, which is the root of most of what follows.

  2. 02

    Rerank on seven weighted components

    Each geocoder returns candidates, and those candidates are scored rather than accepted in rank order. Administrative level carries the most weight, then country, then mean distance to co-entities already resolved in the same document, with temporal plausibility checked against Wikidata inception and dissolution dates.

    Administrative level uses asymmetric decay, penalising over-precision more heavily than under-precision. Name similarity is floored so a transliteration variant cannot collapse an otherwise strong candidate.

  3. 03

    Let the risks reshape the weights

    Detected risk flags adjust the weight budget before scoring runs. A homonym dominance flag boosts proximity and name similarity while suppressing popularity. A temporal anachronism flag doubles the weight on temporal plausibility.

    The scoring function is not fixed. It responds to what the profile says is likely to go wrong with this particular name in this particular document.

  4. 04

    Reward agreement across sources

    A candidate confirmed independently by more than one gazetteer earns a corroboration bonus, applied outside the weighted sum: +0.04 for two sources, +0.06 for three or more. Nine backends with different coverage strengths means agreement carries real information.

    GEOnet covers conflict regions in Africa, MENA and Southeast Asia where Nominatim thins out. Overpass carries native-script name tags. Pleiades covers the classical world. Agreement across that spread is not redundancy.

  5. 05

    Check the document, not just the name

    Once every toponym in a document is resolved, the full set is tested for geographic plausibility. Locations spanning implausible distances, statistical outliers relative to the cluster, and contextual contradictions between co-occurring names each raise a flag.

    The output is a spatial coherence score from 0 to 1 for the document, plus itemised issues. This is what catches a wrong-country match that looked perfectly reasonable on its own.

Figures

Fig. 1

A resolution end to end. The chosen coordinate arrives with its ranked alternatives, a per-component score breakdown and any risk flags attached, so the decision can be inspected rather than trusted.

The ranking engine reference page listing seven scoring components with their default weights and descriptions.
Fig. 2

The seven components and their default weights, documented rather than buried. Administrative level at 0.25 and country at 0.20 carry the most, because those are the two decisions a standard geocoder makes silently and gets wrong most often.

The datasets catalogue listing all nine geocoder backends with their coverage strengths and integration types.
Fig. 3

The nine backends and where each is strong. The set is chosen for complementary coverage rather than redundancy, which is what makes corroboration between them meaningful.

Resolving the name Cambridge, showing ranked candidates, a score breakdown panel, a homonym dominance flag and the chosen result on a map.
Fig. 4

Homonym dominance, caught and mitigated. Cambridge is the friendly version of a problem that in a conflict corpus means a village in the wrong country, and the flag records both what was at risk and what the system did about it.

Fig. 5

The interface in motion. Resolution, scoring and coherence checking are presented as one continuous flow, because in practice a researcher is never resolving a single name in isolation.

Outcomes

  • A named taxonomy for how geocoding fails here

    Proximity collapse, temporal anachronism, homonym dominance, spatial incoherence, admin level mismatch and transliteration drift. Naming them makes them detectable, reportable and arguable, where previously they were just wrong coordinates nobody had a word for.

  • Geographic claims that can be challenged

    Every resolved toponym exposes its chosen coordinate, ranked alternatives, per-component scores, risk flags and coherence result. For research feeding litigation, truth commissions or policy briefs, a geographic claim that cannot be interrogated is not usable evidence.

  • Small places stop losing to large ones

    Forced labour sites, transit camps and rural detention locations are exactly what popularity-ranked geocoders bury under the nearest major city. Weighting proximity to co-entities and implied administrative level above source popularity inverts that default.

  • Weights that can be fitted to a corpus

    Scoring weights can be learned from annotated candidate pairs using a Bayesian personalised ranking objective, and researcher corrections feed back into the training pool. Preliminary simulations suggest 20 to 30 corrections adapt the weights to a new conflict zone.

Stack

Library
Python, rapidfuzz, LLM disambiguation profiling, ACLED adapter
Gazetteers
Nominatim, GeoNames, Wikidata SPARQL, OSM Overpass, OpenHistoricalMap
Specialist sources
NGA GEOnet Names Server, Overture Maps, Pleiades, Who's on First
Scoring
Seven-component weighted rerank, Corroboration bonus, Risk-adaptive weight budget, Bayesian personalised ranking
Validation
Spatial coherence scoring, Outlier detection, LLM contradiction review, Six-mode failure taxonomy
Evaluation
Mean reciprocal rank, Precision@k, Failure mode recall, Ablation over scoring components
  • Leverhulme Centre for Research on Slavery in War
  • Rights Lab
  • University of Nottingham
  • King's College London

Topodex is developed as part of the Leverhulme Centre for Research on Slavery in War, University of Nottingham, in partnership with King's College London. Funded as part of a Research Fellowship in Slavery and War.

Work like this

Start a
conversation →

Available for consulting engagements and research collaborations at this scale. Email james@jameswil.com.