geo
Places and the movement between them: a geography (ss.geo.geography), and movement between its places: a movement model (ss.geo.gravity, ss.geo.radiation), a matrix (ss.geo.Mobility), or a register of moves on given dates (ss.geo.register)
These exist so that a model of more than one place can be built from named places and a standard movement model. Movement applies to a model stratified by place (sir.stratify(patch=...)), whose networks then pair people within each place; a geography can also be used by a network (ssl.GeoNet), for a disease of either kind.
Used with: agents and compartments; declared and coded modules
Classes
| Name | Description |
|---|---|
| Mobility | Movement between the levels of a spatial stratification, given as a matrix |
| geography | A geography: named places with populations and positions, used as the levels of a spatial stratification |
| gravity | The gravity model of movement: the fraction of their time that a person from place i spends in place j (or, for migration, |
| radiation | The radiation model of movement (Simini et al. 2012), which has no parameters to fit: of the people from place i who travel, |
| register | A movement register: a table of moves between places on given dates, e.g. livestock sales between farms |
Mobility
geo.Mobility(matrix=None, kind=None, away=None, **kwargs)Movement between the levels of a spatial stratification, given as a matrix
People either commute (they keep their home, and spend a fraction of their time in other places, where they are exposed and expose others), visit (the same, but they are exposed to the residents of the places they go to and do not expose anyone there, as flepiMoP has it), or migrate (they relocate). Or, with kind='force', nobody moves and the force of infection does, as in LASER: with M[i,k] the movement from place i to place k, each place keeps 1 − Σ_k M[i,k] of its own force of infection and receives M[k,i] of each other place’s.
The movement models (ss.geo.gravity(), ss.geo.radiation()) take the same kind= and away= themselves, and a register of moves on given dates is ss.geo.register().
Other forms are written with the general pieces. Commuters who come back at a finite rate (Keeling and Rohani’s model 7.3) are a second spatial dimension of where people are now, with transfers between its levels at rates by home.
Note: CRN safe as agents.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| matrix | array |
the movement from each place (rows) to each place: for commuting the fraction of time spent there, and for migration the rate of moving there (a SciPy sparse array for many places, most pairs of which share no one) | None |
| kind | str |
‘commute’, ‘visit’, ‘migrate’, or ‘force’ (default ‘commute’) | None |
| away | float |
for commuting and visiting, the fraction of their time people spend away from home (for ‘force’, the fraction of each place’s force of infection that goes to the others); the movement is rescaled to give every place that fraction (to keep the differences between places, scale the matrix by hand and give no away=) |
None |
Examples
sir.stratify(patch=ss.levels(['a', 'b'], mobility=ss.geo.Mobility([[0, 0.1], [0.2, 0]])))
# LASER's coupling, with the force of infection moving: M[i,k] is the fraction of i's force that goes to k
sir.stratify(patch=ss.levels(places, mobility=ss.geo.Mobility(M, kind='force')))Methods
| Name | Description |
|---|---|
| blank | Whether an entry of a register is empty |
| by_value | A function of each entry of a column of a register, worked out once for each distinct value, since a register can have millions of rows |
| coupling | For a moving force of infection: the fraction of the force of infection of each level (columns) that each level (rows) receives, as a sparse array |
| events | The register, resolved against the levels and the timeline of a sim |
| fitted | The parameters (ss.par) in the movement, by attribute (away, and the movement model’s scale, and gravity’s source_power, dest_power, distance_power), which set the mixing when a sim is built |
| from_model | The movement of a movement model (ss.geo.gravity(), ss.geo.radiation()), with its kind and amount |
| load | Read a movement register, with a blank from or to (or a blank states) as None |
| matrix | The movement between each pair of levels, with nothing on the diagonal |
| setup | Check the kind and amount, and set them |
| time_frac | For commuting: the fraction of their time that people from each level (rows) spend in each level; rows sum to 1. A sparse array, since most pairs of places share no one |
blank
geo.Mobility.blank(v)Whether an entry of a register is empty
by_value
geo.Mobility.by_value(vals, func, missing)A function of each entry of a column of a register, worked out once for each distinct value, since a register can have millions of rows
Returns the results for the distinct values, then missing (for None and NaN), and the index of each entry’s result.
coupling
geo.Mobility.coupling(strat)For a moving force of infection: the fraction of the force of infection of each level (columns) that each level (rows) receives, as a sparse array
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| strat | Strat |
the stratification | required |
events
geo.Mobility.events(strat, sim)The register, resolved against the levels and the timeline of a sim
Returns the step at whose start each event happens, the position of the place each leaves (-1 for none) and goes to (-1 for none), the number of people, and the states it names (None for the default), in the order of the table within each step. Events before the start or after the last step are dropped, with a note. Also the distinct pairs of states and to_states (sets, in the order they first appear), and which of them each event names (set_of).
fitted
geo.Mobility.fitted()The parameters (ss.par) in the movement, by attribute (away, and the movement model’s scale, and gravity’s source_power, dest_power, distance_power), which set the mixing when a sim is built
from_model
geo.Mobility.from_model(model)The movement of a movement model (ss.geo.gravity(), ss.geo.radiation()), with its kind and amount
load
geo.Mobility.load(data)Read a movement register, with a blank from or to (or a blank states) as None
matrix
geo.Mobility.matrix(strat)The movement between each pair of levels, with nothing on the diagonal
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| strat | Strat |
the stratification | required |
setup
geo.Mobility.setup(kind=None, away=None, model=None, given=None, data=None)Check the kind and amount, and set them
time_frac
geo.Mobility.time_frac(strat)For commuting: the fraction of their time that people from each level (rows) spend in each level; rows sum to 1. A sparse array, since most pairs of places share no one
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| strat | Strat |
the stratification | required |
geography
geo.geography(
data=None,
names=None,
populations=None,
x=None,
y=None,
lat=None,
lon=None,
distances=None,
adjacency=None,
level=1,
year=None,
places=None,
)A geography: named places with populations and positions, used as the levels of a spatial stratification
A country’s administrative units come from starsim_data by name (ss.geo.geography('Kenya', level=1)): their names, populations, centroids, areas, p-codes, and which share a border. Levels 0 and 1 are bundled (for 184 countries and territories), so they need no download; level 2 is downloaded on first use.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| data | dataframe / str / list |
a country (or a list of them) by name or code, e.g. ‘Kenya’ or ‘KE’; or a table (or the name of a file holding one) with a column name, and optionally population (or pop), and x and y or lat and lon; or your own shapes, as a GeoDataFrame or a .shp, .geojson, or .gpkg file (read with geopandas), whose places are at the centroids of their shapes (in degrees, if it has a coordinate reference system) |
None |
| level | int / str |
for a country, the administrative level: 1 (the default) for its first-level units (counties, provinces, states), 2 for the next (fetched), 0 for the country itself | 1 |
| year | int |
for a country, the year of the populations (default: those bundled, for 2020; another year is fetched) | None |
| places | list |
for a country, only these units, by name, dot_name (‘Kenya:Nairobi’), or p-code |
None |
| names | list |
the name of each place (instead of data) |
None |
| populations | list |
the number of people in each place; sets the fraction of people who start in each (for a country, in place of the bundled ones), and the sizes of the places for movement between them (ss.geo.gravity, ss.geo.radiation) |
None |
| x | list |
a position for each place, in any unit of distance | None |
| y | list |
the other coordinate | None |
| lat | list |
latitudes in degrees (instead of x and y); distances are then great-circle distances in km |
None |
| lon | list |
longitudes in degrees | None |
| distances | array |
the distance between each pair of places (instead of positions) | None |
| adjacency | array |
whether each pair of places shares a border | None |
Examples
kenya = ss.geo.geography('Kenya', level=1) # Its 47 counties
towns = ss.geo.geography(names=['north', 'south', 'east'], populations=[50_000, 30_000, 20_000], x=[0, 0, 40], y=[0, 30, 0])
districts = ss.geo.geography('districts.shp') # Your own shapes, with columns name and population
S, I, R = ss.states(3)
sir = ss.Disease(infection=S >> I @ 0.3*I, recovery=ss.Transition(I, R, dur=10), init_prev=0.01)
sir.stratify(patch=ss.levels(towns, mobility=ss.geo.gravity(scale=0.01)))Methods
| Name | Description |
|---|---|
| by_place | Values in the order of the places, from an array, or a dict or series by name |
| draw | Draw the places into axes, as shapes or as points sized by population, for plot() and maps of results; returns what was drawn, whose colors map() updates |
| get_shapes | The shapes of the places to draw, if any: those the geography was made from, or for a country, its boundaries (shapes=True, which downloads them, and needs geopandas) |
| plot | Draw a map of the places, colored by a value for each place if given |
| positions | Where each place is, as x and y: the positions given, or longitudes and latitudes |
by_place
geo.geography.by_place(values)Values in the order of the places, from an array, or a dict or series by name
draw
geo.geography.draw(ax, colors=None, shapes=None, names=None)Draw the places into axes, as shapes or as points sized by population, for plot() and maps of results; returns what was drawn, whose colors map() updates
get_shapes
geo.geography.get_shapes(shapes=None)The shapes of the places to draw, if any: those the geography was made from, or for a country, its boundaries (shapes=True, which downloads them, and needs geopandas)
plot
geo.geography.plot(
values=None,
label=None,
shapes=None,
names=None,
cmap='Reds',
vmin=None,
vmax=None,
ax=None,
**kwargs,
)Draw a map of the places, colored by a value for each place if given
Places are drawn as shapes if the geography has them (it was made from shapes, or shapes=True for a country), and otherwise as points at their positions, with areas in proportion to their populations. For a map of a result over time, use the result’s map(), e.g. sim.results.sir.prevalence.map().
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| values | array / dict / series |
a value for each place, in order or by name, e.g. a summary of a result by place | None |
| label | str |
what the values are, for the color bar | None |
| shapes | bool |
whether to draw shapes (by default, if the geography has them); True for a country downloads its boundaries, which needs geopandas |
None |
| names | bool |
whether to label the places by name (by default, if there are 15 or fewer) | None |
| cmap | str |
the colormap of the values | 'Reds' |
| vmin | float |
the value at the bottom of the color scale (by default, 0, or the smallest value if it is negative) | None |
| vmax | float |
the value at the top of the color scale (by default, the largest value) | None |
| ax | Axes |
if given, draw into these axes | None |
| kwargs | dict |
passed to ss.plot_args(), e.g. figsize or filename |
Examples
towns = ss.geo.geography(names=['a', 'b', 'c'], populations=[50_000, 30_000, 20_000], x=[0, 0, 40], y=[0, 30, 0])
towns.plot() # Where the places are, and their populations
towns.plot(values=sim.results.sir.infection.by('patch').summarize(), label='Infections') # A summary of a result
ss.geo.geography('Kenya').plot(shapes=True) # Kenya's counties, with their boundariespositions
geo.geography.positions()Where each place is, as x and y: the positions given, or longitudes and latitudes
gravity
geo.gravity(
away=None,
scale=None,
kind=None,
source_power=1.0,
dest_power=1.0,
distance_power=2.0,
)The gravity model of movement: the fraction of their time that a person from place i spends in place j (or, for migration, the rate at which they move there) is scale × pop[i]^(source_power−1) × pop[j]^dest_power / distance[i,j]^distance_power
Populations and distances come from the geography of the dimension it is used on (ss.geo.geography). The model gives the shape of the movement, and away= its amount: the fraction of their time that people spend away from home, split between the other places by gravity. scale has units of distance^distance_power / pop^(source_power+dest_power−1), so no default fits both three towns and a country; give it only if it has been calibrated. With neither, people spend 10% of their time away. kind= says how people move (see ss.geo.Mobility).
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| away | float |
for commuting and visiting, the fraction of their time people spend away from home (for ‘force’, the fraction of each place’s force of infection that goes to the others; default 0.1, unless scale is given) |
None |
| scale | float |
the overall amount of movement, instead of away; for migration, the scale of the rates (required) |
None |
| kind | str |
‘commute’ (the default), ‘visit’, ‘migrate’, or ‘force’ (see ss.geo.Mobility) |
None |
| source_power | float |
the exponent of the population of the place people come from | 1.0 |
| dest_power | float |
the exponent of the population of the place they go to | 1.0 |
| distance_power | float |
the exponent of the distance between the two | 2.0 |
Examples
sir.stratify(patch=ss.levels(towns, mobility=ss.geo.gravity(away=0.1, source_power=1.0, dest_power=1.0, distance_power=2.0)))
sir.stratify(patch=ss.levels(towns, mobility=ss.geo.gravity(scale=2e-4))) # A calibrated amount
sir.stratify(patch=ss.levels(towns, mobility=ss.geo.gravity(away=0.1, kind='visit'))) # Travelers do not infect the people they visitMethods
| Name | Description |
|---|---|
| matrix | The movement between each pair of levels of a stratification, from its geography |
matrix
geo.gravity.matrix(strat)The movement between each pair of levels of a stratification, from its geography
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| strat | Strat |
the stratification, whose geography gives the populations and distances | required |
radiation
geo.radiation(away=None, scale=None, kind=None)The radiation model of movement (Simini et al. 2012), which has no parameters to fit: of the people from place i who travel, the fraction who go to place j is pop[i] × pop[j] / ((pop[i] + s) × (pop[i] + pop[j] + s)), where s is the population of the other places nearer to i than j is
It is used as ss.geo.gravity is, with the populations and distances of the geography of the dimension it is used on (ss.geo.geography): the model gives where people go, and away= how much they travel. With neither away nor scale, people spend 10% of their time away. The fractions are normalized to sum to 1 for each place, so for migration scale is the rate at which each person moves. kind= says how people move (see ss.geo.Mobility).
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| away | float |
for commuting and visiting, the fraction of their time people spend away from home (for ‘force’, the fraction of each place’s force of infection that goes to the others; default 0.1, unless scale is given) |
None |
| scale | float |
the overall amount of movement, instead of away: the fraction of their time away, or for migration the rate of moving (required) |
None |
| kind | str |
‘commute’ (the default), ‘visit’, ‘migrate’, or ‘force’ (see ss.geo.Mobility) |
None |
Examples
sir.stratify(patch=ss.levels(towns, mobility=ss.geo.radiation(away=0.1)))
sir.stratify(patch=ss.levels(towns, mobility=ss.geo.radiation(scale=2e-5, kind='migrate'))) # 2e-5 moves per person per unit of timeMethods
| Name | Description |
|---|---|
| matrix | The movement between each pair of levels of a stratification, from its geography |
matrix
geo.radiation.matrix(strat)The movement between each pair of levels of a stratification, from its geography
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| strat | Strat |
the stratification, whose geography gives the populations and distances | required |
register
geo.register(data)A movement register: a table of moves between places on given dates, e.g. livestock sales between farms
It has columns date, from, to, n, and optionally states (and to_states). Each row moves n people from one place to another; a row with no from adds them to to (births, purchases), and one with no to removes them from from (deaths, sales out of the model). The people who move or leave are chosen at random from those in states (by default, everyone); people who are added go into states (by default, the first state). With to_states, they also move from each of states to the matching one of to_states. Each event happens at the start of the first step that begins on or after its date, before that step’s transitions, and the events of a step happen in the order of the table.
Note: CRN safe as agents.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| data | str / df |
the register: a file name or a dataframe | required |
Examples
sir.stratify(herd=ss.levels(herds, mobility=ss.geo.register('movements.csv')))