From aa1e941273c310bfa611a00e19a633b4a225ca60 Mon Sep 17 00:00:00 2001 From: Daniel Herszenhut Date: Wed, 27 Oct 2021 17:50:12 -0300 Subject: [PATCH] fixed #29 --- DESCRIPTION | 2 +- NEWS.md | 4 +- R/get_trip_geometry.R | 52 +++++++++++++++++-------- codemeta.json | 4 +- man/get_trip_geometry.Rd | 34 ++++++++-------- tests/testthat/test-get_trip_geometry.R | 25 +++++++++++- 6 files changed, 82 insertions(+), 39 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 6109076..3594b50 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,7 +2,7 @@ Type: Package Package: gtfstools Title: General Transit Feed Specification (GTFS) Editing and Analysing Tools -Version: 0.1.0.9039 +Version: 0.1.0.9040 Authors@R: c(person(given = "Daniel", family = "Herszenhut", diff --git a/NEWS.md b/NEWS.md index 022d582..9c5e6ce 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,11 +2,12 @@ ## New features -- `get_parent_station()` - New function `convert_stops_to_sf()`. - New function `convert_shapes_to_sf()`. - New function `filter_route_type()`. - New function `filter_route_id()`. +- New function `filter_trip_id()`. +- New function `get_parent_station()` - New parameters to `read_gtfs()`: `fields`, `skip` and `encoding`. The `warnings` parameter was flagged as deprecated. - New parameters to `write_gtfs()`: `files`, `standard_only` and `as_dir`. They substitute the previously existent `optional` and `extra`, which were flagged as deprecated. The `warnings` parameter was flagged as deprecated too. - Not exported: `copy_gtfs_diff_field_class()`, `convert_from_standard()`, `convert_to_standard()` @@ -15,6 +16,7 @@ - The `get_trip_speed()` and `set_trip_speed()` examples, tests and vignette bits now only run if `{lwgeom}` is installed. `{lwgeom}` is an `{sf}` "soft" dependency required by these functions, and is listed in `Suggests`. However, package checks would fail not so gracefully if it wasn't installed, which is now fixed. - Fixed a bug in which the `crs` passed to `get_trip_geometry()` would be assigned to the result without actually reprojecting it. +- Changed the behaviour of `get_trip_geometry()` to not raise an error when the 'file' parameter is left untouched and the GTFS object doesn't contain either the shapes or the stop_times table. Closes [#29](https://github.com/ipeaGIT/gtfstools/issues/29). ## Notes diff --git a/R/get_trip_geometry.R b/R/get_trip_geometry.R index c3b5b05..6af222c 100644 --- a/R/get_trip_geometry.R +++ b/R/get_trip_geometry.R @@ -1,27 +1,28 @@ #' Get trip geometry #' -#' Returns the geometry of each specified \code{trip_id}, based either on the -#' \code{shapes} or the \code{stop_times} file (or both). +#' Returns the geometry of each specified `trip_id`, based either on the +#' `shapes` or the `stop_times` file (or both). #' -#' @param gtfs A GTFS object as created by \code{\link{read_gtfs}}. -#' @param trip_id A string vector including the \code{trip_id}s to have their -#' geometries generated. If \code{NULL} (the default), the function generates -#' geometries for every \code{trip_id} in the GTFS. -#' @param file The file from which geometries should be generated. By default -#' uses both \code{shapes} and \code{stop_times}. +#' @param gtfs A GTFS object. +#' @param trip_id A character vector including the `trip_id`s to have their +#' geometries generated. If `NULL` (the default), the function generates +#' geometries for every `trip_id` in the GTFS. +#' @param file A character vector specifying the file from which geometries +#' should be generated (either one of or both `shapes` and `stop_times`). If +#' `NULL` (the default), the function attemps to generate the geometries from +#' both files, but only raises an error if none of the files exist. #' @param crs The CRS of the resulting object, either as an EPSG code or as an #' `crs` object. Defaults to 4326 (WGS 84). #' -#' @return A \code{LINESTRING sf}. +#' @return A `LINESTRING sf`. #' #' @section Details: #' The geometry generation works differently for the two files. In the case of -#' \code{shapes}, the shape as described in the text file is converted to an -#' \code{sf} object. For \code{stop_times} the geometry is the result of linking -#' subsequent stops along a straight line (stops' coordinates are retrieved from -#' the \code{stops} file). Thus, the resolution of the geometry when generated -#' with \code{shapes} tends to be much higher than when created with -#' \code{stop_times}. +#' `shapes`, the shape as described in the text file is converted to an `sf` +#' object. For `stop_times` the geometry is the result of linking subsequent +#' stops along a straight line (stops' coordinates are retrieved from the +#' `stops` file). Thus, the resolution of the geometry when generated with +#' `shapes` tends to be much higher than when created with `stop_times`. #' #' @examples #' data_path <- system.file("extdata/spo_gtfs.zip", package = "gtfstools") @@ -31,6 +32,10 @@ #' trip_geometry <- get_trip_geometry(gtfs) #' head(trip_geometry) #' +#' # the above is identical to +#' trip_geometry <- get_trip_geometry(gtfs, file = c("shapes", "stop_times")) +#' head(trip_geometry) +#' #' trip_ids <- c("CPTM L07-0", "2002-10-0") #' trip_geometry <- get_trip_geometry(gtfs, trip_id = trip_ids) #' trip_geometry @@ -39,20 +44,33 @@ #' @export get_trip_geometry <- function(gtfs, trip_id = NULL, - file = c("shapes", "stop_times"), + file = NULL, crs = 4326) { checkmate::assert_class(gtfs, "dt_gtfs") checkmate::assert_character(trip_id, null.ok = TRUE) - checkmate::assert_names(file, subset.of = c("shapes", "stop_times")) + checkmate::assert_character(file, null.ok = TRUE) checkmate::assert( checkmate::check_numeric(crs), checkmate::check_class(crs, "crs"), combine = "or" ) + if (!is.null(file)) + checkmate::assert_names(file, subset.of = c("shapes", "stop_times")) + # check if required fields and files exist + if (is.null(file)) { + file <- names(gtfs) + file <- file[file %chin% c("shapes", "stop_times")] + + if (identical(file, character(0))) + stop( + "The GTFS object must have either a 'shapes' or a 'stop_times' table." + ) + } + if ("shapes" %in% file) { checkmate::assert( diff --git a/codemeta.json b/codemeta.json index 37c01c8..c264574 100644 --- a/codemeta.json +++ b/codemeta.json @@ -10,7 +10,7 @@ "codeRepository": "https://github.com/ipeaGIT/gtfstools", "issueTracker": "https://github.com/ipeaGIT/gtfstools/issues", "license": "https://spdx.org/licenses/MIT", - "version": "0.1.0.9039", + "version": "0.1.0.9040", "programmingLanguage": { "@type": "ComputerLanguage", "name": "R", @@ -233,7 +233,7 @@ "sameAs": "https://CRAN.R-project.org/package=zip" } ], - "fileSize": "2527.683KB", + "fileSize": "2529.414KB", "contIntegration": "https://codecov.io/gh/ipeaGIT/gtfstools?branch=master", "developmentStatus": "https://lifecycle.r-lib.org/articles/stages.html", "keywords": [ diff --git a/man/get_trip_geometry.Rd b/man/get_trip_geometry.Rd index 0acb1ad..05e522a 100644 --- a/man/get_trip_geometry.Rd +++ b/man/get_trip_geometry.Rd @@ -4,28 +4,25 @@ \alias{get_trip_geometry} \title{Get trip geometry} \usage{ -get_trip_geometry( - gtfs, - trip_id = NULL, - file = c("shapes", "stop_times"), - crs = 4326 -) +get_trip_geometry(gtfs, trip_id = NULL, file = NULL, crs = 4326) } \arguments{ -\item{gtfs}{A GTFS object as created by \code{\link{read_gtfs}}.} +\item{gtfs}{A GTFS object.} -\item{trip_id}{A string vector including the \code{trip_id}s to have their +\item{trip_id}{A character vector including the \code{trip_id}s to have their geometries generated. If \code{NULL} (the default), the function generates geometries for every \code{trip_id} in the GTFS.} -\item{file}{The file from which geometries should be generated. By default -uses both \code{shapes} and \code{stop_times}.} +\item{file}{A character vector specifying the file from which geometries +should be generated (either one of or both \code{shapes} and \code{stop_times}). If +\code{NULL} (the default), the function attemps to generate the geometries from +both files, but only raises an error if none of the files exist.} \item{crs}{The CRS of the resulting object, either as an EPSG code or as an \code{crs} object. Defaults to 4326 (WGS 84).} } \value{ -A \code{LINESTRING sf}. +A \verb{LINESTRING sf}. } \description{ Returns the geometry of each specified \code{trip_id}, based either on the @@ -34,12 +31,11 @@ Returns the geometry of each specified \code{trip_id}, based either on the \section{Details}{ The geometry generation works differently for the two files. In the case of -\code{shapes}, the shape as described in the text file is converted to an -\code{sf} object. For \code{stop_times} the geometry is the result of linking -subsequent stops along a straight line (stops' coordinates are retrieved from -the \code{stops} file). Thus, the resolution of the geometry when generated -with \code{shapes} tends to be much higher than when created with -\code{stop_times}. +\code{shapes}, the shape as described in the text file is converted to an \code{sf} +object. For \code{stop_times} the geometry is the result of linking subsequent +stops along a straight line (stops' coordinates are retrieved from the +\code{stops} file). Thus, the resolution of the geometry when generated with +\code{shapes} tends to be much higher than when created with \code{stop_times}. } \examples{ @@ -50,6 +46,10 @@ gtfs <- read_gtfs(data_path) trip_geometry <- get_trip_geometry(gtfs) head(trip_geometry) +# the above is identical to +trip_geometry <- get_trip_geometry(gtfs, file = c("shapes", "stop_times")) +head(trip_geometry) + trip_ids <- c("CPTM L07-0", "2002-10-0") trip_geometry <- get_trip_geometry(gtfs, trip_id = trip_ids) trip_geometry diff --git a/tests/testthat/test-get_trip_geometry.R b/tests/testthat/test-get_trip_geometry.R index d7b8f34..13ba903 100644 --- a/tests/testthat/test-get_trip_geometry.R +++ b/tests/testthat/test-get_trip_geometry.R @@ -175,7 +175,7 @@ test_that("returns the geometries created by the given 'file'", { test_that("outputs an 'sf' object with correct crs", { - # crs is WGs by default + # crs is WGS by default point <- sf::st_sfc(sf::st_point(c(0, 0)), crs = 4326) @@ -281,3 +281,26 @@ test_that("returns empty sf if passed 'trip_id' isn't linked to a 'shape_id'", { expect_equal(nrow(sf_geom), 0) }) + +# issue #29 +test_that("works correctly if 'file' is untouched and one file is missing", { + no_shapes <- read_gtfs(data_path) + no_shapes$shapes <- NULL + expect_s3_class(get_trip_geometry(no_shapes), "sf") + expect_true(all(get_trip_geometry(no_shapes)$origin_file == "stop_times")) + + no_stop_times <- read_gtfs(data_path) + no_stop_times$stop_times <- NULL + expect_s3_class(get_trip_geometry(no_stop_times), "sf") + expect_true(all(get_trip_geometry(no_stop_times)$origin_file == "shapes")) + + none_of_them <- read_gtfs(data_path) + none_of_them$shapes <- none_of_them$stop_times <- NULL + expect_error( + get_trip_geometry(none_of_them), + regexp = paste0( + "The GTFS object must have either a ", + "'shapes' or a 'stop_times' table\\." + ) + ) +})