Two steps of cacs_run() contact services outside R.
cacs_isochrone() asks a routing service, by default the
Open Source Routing Machine (OSRM), for the area reachable from each
site within each drive time. cacs_acs_prefetch() downloads
American Community Survey (ACS) 5-year estimates for the census tracts
of one state from the Census Bureau.
| Service | Selected with | What it needs |
|---|---|---|
| Public OSRM demo server | provider = "osrm" and
osrm_mode = "demo", the defaults |
The osrm package |
| An OSRM server that you run | provider = "osrm" and
osrm_mode = "docker" |
The osrm package and the server |
| openrouteservice | provider = "ors" |
The openrouteservice package and an openrouteservice API key |
| Census Bureau API | cacs_acs_prefetch(), which
cacs_run() calls unless acs is supplied |
A Census API key |
| No service | precomputed_isochrones and
acs, both supplied to cacs_run() |
Drive-time areas and ACS estimates that you already have |
cacs_run() passes osrm_mode,
res, and some other settings of
cacs_isochrone() through its argument
iso_args, as in
iso_args = list(osrm_mode = "docker").
cacs_acs_prefetch() downloads the estimates through the
tidycensus package, which is installed with catchmentACS. A download
needs a Census API key in the environment variable
CENSUS_API_KEY. The call below writes the key to your
.Renviron file, from which later R sessions read it:
Sys.setenv(CENSUS_API_KEY = "YOUR_KEY_HERE") sets the
key for the current session only. The key is needed only to download:
cacs_acs_prefetch() reads a result saved in the cache by an
earlier download, without a key or an internet connection. By default,
the cache keeps results only until the R session ends; the section “The
cache” below describes a cache folder that keeps them for later
sessions. If a download is needed and the key is not set,
cacs_acs_prefetch() stops with an error before any request
is sent. Estimates can be downloaded for the year values
2009 to 2024; ?cacs_acs_prefetch describes the
download.
With provider = "osrm", cacs_isochrone()
builds the areas with the osrm package, which is not installed with
catchmentACS. By default, the requests go to the public OSRM demo
server, which needs no key:
# Needs the osrm package and an internet connection.
iso <- cacs_isochrone(
sites = cacs_alabama_sites[1:3, ],
drive_times = c(5, 10, 15),
provider = "osrm",
osrm_mode = "demo",
res = 30L,
verbose = TRUE
)The osrm package pauses between requests to the demo server, which
adds about 10 seconds for each site with the default settings. When the
server reports that its limit on requests has been reached (HTTP status
429), cacs_isochrone() stops with an error; it returns no
areas and saves none in the cache, not even those built before the limit
was reached. An OSRM server that you run yourself, for example in a
Docker container, has neither the pauses nor a limit shared with other
users. osrm_mode = "docker" sends the requests to such a
server, at http://0.0.0.0:5000/ unless another address is
given in osrm.server, as below, or in the option
catchmentACS.osrm_docker_server. cacs_run()
drops osrm.server from iso_args with a
warning, so with cacs_run() the option sets the
address.
# Needs the osrm package and an OSRM server at this address.
iso <- cacs_isochrone(
sites = cacs_alabama_sites[1:3, ],
drive_times = c(5, 10, 15),
provider = "osrm",
osrm_mode = "docker",
`osrm.server` = "http://localhost:5000/",
verbose = TRUE
)The osrm package draws the areas of a site from a grid of
res by res points around it. The grid is sized
for the longest drive time, so the areas for shorter drive times rest on
fewer points. Without res, the grid has 30 by 30 points
with osrm_mode = "demo" and 70 by 70 with
osrm_mode = "docker"; a finer grid gives more detailed
areas but sends more requests. Areas built with different values of
res can differ, so giving res in the call
keeps the grid the same when osrm_mode or the options
change. ?cacs_isochrone describes the servers and the grid
in more detail.
cacs_validate_osrm_endpoint() sends one small request to
an OSRM server and returns a table with one row, in which
quota_ok is TRUE when the server answered with
HTTP status 200. ?cacs_validate_osrm_endpoint describes the
other columns and the warning given when the server’s limit on requests
has been reached. A server that cannot be reached, or does not answer
within timeout seconds, gives quota_ok = FALSE
and http_status = NA without an error.
Without server, the request goes to the public demo
server, or to the address in the osrm package’s option
osrm.server when that is set. A server that you run is
checked only when its address is given in server:
With provider = "ors", cacs_isochrone()
builds the areas with openrouteservice through the openrouteservice
package, which is not installed with catchmentACS. It needs an
openrouteservice API key. cacs_isochrone() takes the key
from its argument ors_api_key, by default the value of the
environment variable ORS_API_KEY; with
cacs_run(), the key comes from the same variable or from
iso_args = list(ors_api_key = ...). An empty key gives an
error before any request is sent. A key set in .Renviron,
like the Census key, stays out of scripts and reports.
# Needs the openrouteservice package, an API key, and an internet connection.
nzchar(Sys.getenv("ORS_API_KEY")) # TRUE when the key is set
iso <- cacs_isochrone(
sites = cacs_alabama_sites[1:3, ],
drive_times = c(5, 10, 15),
provider = "ors",
ors_api_key = Sys.getenv("ORS_API_KEY"),
verbose = TRUE
)The areas from openrouteservice and from OSRM are computed in
different ways, so they can differ for the same site and drive time. The
package’s tests exercise this path against simulated openrouteservice
responses only; the live-service tests it has cover OSRM (see
NEWS.md).
cacs_run() does not build drive-time areas when it is
given them in precomputed_isochrones, and does not download
ACS estimates when it is given them in acs.
precomputed_isochrones takes a table like the one that
cacs_isochrone() returns, and acs one like the
result of cacs_acs_prefetch().
cacs_validate_iso() and cacs_acs_validate()
check that tables made with other tools have the columns and the
coordinate reference systems that cacs_run() needs, and
cacs_acs_validate() also checks that no tract has two rows
for the same variable; they do not check the values of the estimates and
margins of error. The negative codes that the Census Bureau’s data API
puts in place of some estimates and margins of error, such as
-555555555, pass these checks. cacs_run()
treats these codes as missing values but uses any other negative value
as it is (see ?cacs_intersect_weight, which also says when
a warning is given).
The result carries a record of the call, the attribute
cacs_run_provenance, whose element
execution_path names the combination of inputs:
execution_path |
precomputed_isochrones |
acs |
Services it may contact |
|---|---|---|---|
"5-call" |
not supplied | not supplied | the routing service and the Census Bureau API |
"4-call-A" |
supplied | not supplied | the Census Bureau API |
"4-call-B" |
not supplied | supplied | the routing service |
"3-call" |
supplied | supplied | none |
The number in each value counts the steps, out of five, that
cacs_run() runs itself. The elements
bypass_iso and bypass_acs of the same record
are TRUE when the areas and the estimates, respectively,
were supplied.
The example below draws on files that ship with the package. Their drive-time areas were drawn without a routing service: each is a circle around its site, with a radius of 5 km for the 5-minute area, 10 km for 10 minutes, and 15 km for 15 minutes. The columns that name the routing service were filled in when the file was made, with values like those of an OSRM result:
example_iso <- readRDS(system.file(
"extdata", "legacy_2025_isochrones.rds", package = "catchmentACS"
))
example_iso |>
sf::st_drop_geometry() |>
count(provider, provider_requested, profile,
osm_snapshot_date, ring_topology)#> # A tibble: 1 × 6
#> provider provider_requested profile osm_snapshot_date ring_topology n
#> <chr> <chr> <chr> <chr> <chr> <int>
#> 1 osrm osrm car 2025-04-01 cumulative 60
cacs_run() copies these values into the columns
provider, profile, and
osm_snapshot_date of its result, so with areas supplied,
its argument provider is only recorded in
cacs_run_provenance and shown when the result is printed.
The ACS file holds made-up estimates for small squares, spaced apart,
that are used in place of census tracts. With both files,
cacs_run() contacts no service:
example_sites <- readRDS(system.file(
"extdata", "legacy_2025_sites.rds", package = "catchmentACS"
))
acs <- readRDS(system.file(
"extdata", "sample_alabama_subset.rds", package = "catchmentACS"
))
one_site <- "AL_SITE_07"
iso_one <- example_iso |>
filter(site_id == one_site, drive_time_min == 5L)
site_one <- example_sites |>
filter(site_id == one_site)
out <- cacs_run(
sites = site_one,
state = "AL",
year = 2023,
drive_times = 5L,
variables = unname(cacs_acs_default_vars),
provider = "osrm",
precomputed_isochrones = iso_one,
acs = acs,
weight_method = "area",
output = "long",
verbose = FALSE
)
attr(out, "cacs_run_provenance") |>
as.data.frame() |>
select(execution_path, provider, bypass_iso, bypass_acs,
weight_method, output_format)#> execution_path provider bypass_iso bypass_acs weight_method output_format
#> 1 3-call osrm TRUE TRUE area long
?cacs_run describes which other arguments are then only
recorded.
weight_method = "population", like the providers Mapbox
and r5r, is accepted but not implemented yet.
cacs_isochrone() gives its error for the two providers
after checking its other arguments and before sending any request. In
cacs_run(), weight_method = "population" gives
an error before any step runs, while the two providers give theirs at
the routing step, after the ACS estimates are downloaded unless
acs is supplied. The three errors have the class
catchmentACS_error_credential, which is also given for a
missing or refused API key (see
?catchmentACS-conditions).
Unless the cache is turned off, cacs_isochrone() and
cacs_acs_prefetch() save their results in the folder that
cacs_cache_dir() returns. A later call that matches an
earlier one reads the saved result instead of contacting the service;
the help page of each function says what must match. For the drive-time
areas, the sites themselves must match, among other things: their
coordinates and their site_id values, along with the set of
drive times, the provider, profile, osrm_mode,
and res, and the installed versions of sf, PROJ, and GEOS.
Adding one site to a run therefore builds the areas for all of the sites
again.
By default, the folder is inside the temporary folder of the R
session, which R deletes when the session ends. Saved results are kept
for later sessions when the option catchmentACS.cache_dir
or the environment variable CACS_CACHE_DIR names a folder
that lasts, for example with
options(catchmentACS.cache_dir = tools::R_user_dir("catchmentACS", "cache"))
in the R startup file. Once per session, the results in such a folder
that have not been used for 30 days are deleted; the option
catchmentACS.cache_max_age_days sets another number of days
(see ?cacs_cache_dir). cacs_set_cache(FALSE)
turns the cache off for the rest of the session, and
cacs_get_cache_state() reports the setting.
force_refresh = TRUE makes
cacs_acs_prefetch() download the estimates again and
replace the saved result, which needs the Census key; with
cacs_run(), it is given as
acs_args = list(force_refresh = TRUE). As long as they are
kept, saved drive-time areas are used again, even if the map data of the
routing service have changed since; a call with another
osm_snapshot_date builds new ones.
cacs_clear_cache() deletes saved results:
# Lists what the cache folder holds, then deletes the saved drive-time
# areas and ACS estimates.
cacs_cache_status()
cacs_clear_cache("isochrone", confirm = FALSE)
cacs_clear_cache("acs", confirm = FALSE)cacs_acs_prefetch(write_gpkg = TRUE) also saves a
downloaded result as a GeoPackage file, in the acs folder
of the cache, for use in other GIS software. It is written even when the
cache is off, but not when a saved result is read. The file is deleted
when the session ends if the cache folder is the default one. In a
folder that lasts between sessions, it is deleted together with its
saved result or, if it has none, as when the cache was off, once it is
as old as the saved results that are deleted;
cacs_clear_cache() deletes it too. To keep a copy, write
the result with sf::st_write().
cacs_intersect_weight(), the step of
cacs_run() that combines the areas with the tracts, saves
its results too, and its help page says what must match. The argument
cache_dir of cacs_run() sets the folder for
the saved results of all three functions.
Without precomputed_isochrones and acs,
cacs_run() builds the areas and downloads the estimates
itself. The routing service is chosen with provider, and
for OSRM the server with osrm_mode in
iso_args. The call below uses the example sites
cacs_alabama_sites, made-up points near Alabama city
centers:
# Needs the osrm package, a Census API key, and an internet connection.
result <- cacs_run(
sites = cacs_alabama_sites, # or your own sites
state = "AL",
year = 2023,
drive_times = c(5, 10, 15),
variables = unname(cacs_acs_default_vars),
provider = "osrm",
iso_args = list(osrm_mode = "demo"), # "docker" for a server that you run
# With "docker", the server's address is set before the call with
# options(catchmentACS.osrm_docker_server = "http://localhost:5000/")
weight_method = "area",
output = "long",
verbose = TRUE
)
summary(result)$rates_per_site_moe
attr(result, "cacs_run_provenance")