Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/pkgdown.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }}
env:
GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
MOBILITY_DATABASE: ${{ secrets.MOBILITY_DATABASE }}
permissions:
contents: write
steps:
Expand Down
45 changes: 33 additions & 12 deletions R/query_mobilitydatabase.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#' Query Mobility Database API for GTFS feeds
#
#'
#' @param token String. Access token.
#' @param access_token String. (Optional when refresh_token) Access token.
#' @param refresh_token String. (Optional when access_token) Refresh token.
#' @param bounding_filter_method. String. (Default `partially_enclosed`) Filtering method to use with the dataset_latitudes and dataset_longitudes parameters.
#' @param limit. Integer. (Default 10) The number of items to be returned.
#' @param offset. Integer. (Default 0) Offset of the first item to return.
Expand All @@ -12,7 +13,9 @@
#' @param is_official. Boolean. (Optional) Default `FALSE`. If TRUE, only return official feeds.
#'
#' @details
#' This method queries \href{https://mobilitydatabase.org/}{Mobility Database} API, allowing to get a list of GTFS feeds documented at this platform. To use it, an access token must be provided. It can be obtained for free at Mobility Database website.\cr\cr
#' This method queries \href{https://mobilitydatabase.org/}{Mobility Database} API, allowing to get a list of GTFS feeds documented at this platform.
#' To use it, an access or a refresh token must be provided.
#' It can be obtained for free at Mobility Database website.\cr\cr
#' For more details on the parameters, refer to \url{https://mobilitydata.github.io/mobility-feed-api/SwaggerUI/index.html#/feeds/getGtfsFeeds}.\cr\cr
#' Some useful columns of the returned data.frame (refer to the API documentation for a full list) are:
#' \itemize{
Expand All @@ -26,15 +29,15 @@
#'
#' @examples
#' \dontrun{
#' feeds <- GTFShift::query_mobilitydatabase(myToken, country_code="PT", is_official=TRUE)
#' feeds <- GTFShift::query_mobilitydatabase(refresh_token="myToken", country_code="PT", is_official=TRUE)
#' }
#'
#' @import httr
#' @import dplyr
#' @importFrom gtfsrouter extract_gtfs gtfs_transfer_table
#'
#' @export
query_mobilitydatabase <- function(token,
query_mobilitydatabase <- function(access_token = NA,
refresh_token = NA,
bounding_filter_method = "partially_enclosed",
limit = 10,
offset = 0,
Expand All @@ -43,16 +46,34 @@ query_mobilitydatabase <- function(token,
municipality = NA,
bbox = NA,
is_official = NA

) {

# Validate parameters
if (is.na(access_token) && is.na(refresh_token)) {
stop("No token provided! At least one of the access or refresh tokens must be provided as an argument.")
}

# If refresh token, get access token from API
if (is.na(access_token) && !is.na(refresh_token)) {
body <- sprintf('{"refresh_token": "%s"}', refresh_token)
response <- POST(
"https://api.mobilitydatabase.org/v1/tokens",
add_headers(`Content-Type` = "application/json"),
body = body
)
content <- content(response, as = "parsed")
if(http_error(response)) {
stop(sprintf("Mobility database bad response: %s", http_status(response)))
}
access_token <- content$access_token
}

# Query mobility database
url <- "https://api.mobilitydatabase.org/v1/gtfs_feeds"

params <- list(
bounding_filter_method=bounding_filter_method,
limit = limit,
offset = offset
)
params <- list(bounding_filter_method = bounding_filter_method,
limit = limit,
offset = offset)
if (!is.na(country_code)) params["country_code"] = country_code
if (!is.na(subdivision_name)) params["subdivision_name"] = subdivision_name
if (!is.na(municipality)) params["municipality"] = municipality
Expand All @@ -67,7 +88,7 @@ query_mobilitydatabase <- function(token,
query = params,
add_headers(
`accept` = "application/json",
`Authorization` = sprintf("Bearer %s", token)
`Authorization` = sprintf("Bearer %s", access_token)
)
)

Expand Down
15 changes: 12 additions & 3 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ template:
bootstrap: 5

reference:
- title: Read
- title: Get GTFS feeds
contents:
- load_feed
- query_mobilitydatabase
- title: Filter
contents:
- starts_with("filter_")
Expand All @@ -17,7 +18,15 @@ reference:
contents:
- unify
- starts_with("create_")
- title: External data
- title: Open Street Maps
contents:
- starts_with("query_")
- starts_with("osm_")
articles:
- title: Articles
navbar: ~
contents:
- download
- filter
- unify
- analyse
- osm
13 changes: 9 additions & 4 deletions man/query_mobilitydatabase.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions vignettes/analyse.Rmd
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
title: "Analyse GTFS feeds"
title: "4. Analyse GTFS feeds"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Analyse GTFS feeds}
%\VignetteIndexEntry{4. Analyse GTFS feeds}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
Expand Down
116 changes: 30 additions & 86 deletions vignettes/download.Rmd
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
title: "Download transit data"
title: "1. Getting transit data"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Download transit data}
%\VignetteIndexEntry{1. Getting transit data}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
Expand Down Expand Up @@ -32,12 +32,28 @@ library(tidytransit)

# Introduction

Performing analysis over transit requires data on the operation and infrastructure.
GTFShift includes some built in methods that can you assist gathering it.
Performing analysis over transit requires data on the operation and infrastructure. [GTFS](https://gtfs.org/) is an open standard that offers this information in a simple and complete way.

# Download GTFS files
GTFShift includes some built in methods that can assist gathering it, explored in this article.

## Use open catalogues
# Read a GTFS file

GTFShift makes use of several R packages to implement its features, but most of it is built upon [tidytransit](https://r-transit.github.io/tidytransit/), so all the methods that accept a GTFS object should be a `tidygtfs` object.

To create it, you can either use `GTFShift::load_feed` or the tidytransit method, `tidytransit::read_gtfs`. Actually, `GTFShift::load_feed` is an extension of the last, with the additional features of scanning the feed for any integrity errors and fixing them automatically, as well as the option to store it locally.

```{r eval = FALSE}
# Using tidytransit
gtfs <- tidytransit::load_feed("https://operator.com/gtfs.zip")

# Using GTFShift
gtfs <- GTFShift::load_feed("https://operator.com/gtfs.zip")
```


# Find GTFS feeds

## Using open catalogues

The gathering of the GTFS files can be simplified by using public archives like [mobilitydatabase.org](https://mobilitydatabase.org/) or [transit.land](https://www.transit.land/).

Expand All @@ -46,30 +62,19 @@ It queries the `/v1/gtfs_feeds` API endpoint, returning a list of GTFS feeds wit

To use it, an access token must be provided. It can be obtained for free at Mobility Database [website](https://mobilitydatabase.org/account).


```{r eval=FALSE, message=FALSE, warning=FALSE}
```{r}
# usethis::edit_r_environ() # to set MOBILITY_DATABASE variable for this code chunk to work

feeds = GTFShift::query_mobilitydatabase(Sys.getenv("MOBILITY_DATABASE"),
country_code="PT")
```

```r
feeds <- GTFShift::query_mobilitydatabase(refresh_token = Sys.getenv("MOBILITY_DATABASE"), country_code="PT")

feeds[1:4, c("provider", "status", "producer_url")]
#> provider status
#> 1 A Onda - Mobilidade Urbana active
#> 2 Apanha-me! - Transportes Urbanos active
#> 3 Carris Metropolitana active
#> 4 Cascais Próxima, E.M., S.A. active
#> producer_url
#> 1 https://drive.google.com/uc?export=download&id=1aPfsxHqopxxcjV8HlRzImzxh_a6zRxGp
#> 2 https://drive.google.com/uc?export=download&id=1w92h129CWNSoImBRZQOWT6KRPzSFwJ42
#> 3 https://api.carrismetropolitana.pt/gtfs
#> 4 https://drive.google.com/uc?export=download&id=13ucYiAJRtu-gXsLa02qKJrGOgDjbnUWX

gtfs <- GTFShift::load_feed(feeds[c(1), ]$producer_url)
summary(gtfs)
```

## Use GTFShift incorporated database for Portugal

## Using GTFShift incorporated database for Portugal

This library offers a small database with a compilation of GTFS files for Portuguese operators. It is a CSV file, available at `extdata/gtfs_sources_pt.csv`, and has the following attributes:

Expand All @@ -84,70 +89,9 @@ This library offers a small database with a compilation of GTFS files for Portug
data = read.csv(system.file("extdata", "gtfs_sources_pt.csv", package = "GTFShift"))
summary(data)
data[1:4,]
```

## Download and validate integrity

`GTFShift` library offers a method to download and fix any integrity violations at GTFS files: `load_feed()`.
It fixes inconsistencies on the `stop_times.txt` and missing `shapes.txt` files and returns a tidygtfs object, that can be used in any other method of GTFShift or tidyrtransit packages.

```{r message=TRUE, warning=TRUE}
# DOWNLOAD GTFS and store it locally
gtfs = GTFShift::load_feed(data[data$ID=="cp",]$URL)
gtfs <- GTFShift::load_feed(data[c(1), ]$URL)
summary(gtfs)
```

# Download bus lanes

Bus lanes can improve bus transit operation. Understanding their spatial distribution is important to study operation dynamics.
`osm_bus_lanes` allows to obtain the bus lanes network on OpenStreetMaps for a given area.

```{r}
aml = sf::st_read("https://github.com/U-Shift/MQAT/raw/refs/heads/main/geo/MUNICIPIOSgeo.gpkg", quiet = TRUE)
lisboa = aml |> dplyr::filter(Concelho == "Lisboa") |> sf::st_bbox()

bus_lanes = GTFShift::osm_bus_lanes(lisboa)

mapview::mapview(bus_lanes, layer.name = "Bus lanes")
```



# Get centerlines for OSM road network

Performing an aggregated analysis for the spatial distribution of the route frequencies might be easier if the routes are projected over a simplified road network (refer to [vignette("analyse")](./analyse.html#improve-visualization-with-network_overline) for more details).

`osm_centerlines()` allows to generate this simplification by creating the centerlines for the road network exported from Open Street Maps, using Python [neatnet](https://uscuni.org/neatnet/) package.

<div style="display: flex; gap: 20px; overflow-x: auto;">
<div style="flex: 1 1 0; min-width: 288px; max-width: 100%;">

### Original network

```{r original_network}
library(osmdata)

road_osm = opq("Arroios, Lisboa, Portugal") |>
add_osm_feature(key = "highway", value = c("motorway", "trunk", "primary", "secondary", "tertiary", "residential", "unclassified", "living_street")) |>
add_osm_feature(key = "area", value = "!yes") |>
osmdata_sf() |>
osm_poly2line()

road_osm = road_osm$osm_lines

mapview::mapview(road_osm)
```

</div>
<div style="flex: 1 1 0; min-width: 288px; max-width: 100%;">

### Simplified network

```{r simplified_network}
centerlines = GTFShift::osm_centerlines(place="Arroios, Lisboa, Portugal")

mapview::mapview(centerlines)
```

</div>
</div>
4 changes: 2 additions & 2 deletions vignettes/filter.Rmd
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
title: "Filter GTFS feeds"
title: "2. Filter GTFS feeds"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{Filter GTFS feeds}
%\VignetteIndexEntry{2. Filter GTFS feeds}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
Expand Down
Loading
Loading