-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathREADME.Rmd
256 lines (201 loc) · 9.5 KB
/
README.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
---
output: github_document
editor_options:
chunk_output_type: console
---
# geoplumber · [![Build Status](https://travis-ci.org/ATFutures/geoplumber.svg)](https://travis-ci.org/ATFutures/geoplumber) [![codecov](https://codecov.io/gh/ATFutures/geoplumber/branch/master/graph/badge.svg)](https://codecov.io/gh/ATFutures/geoplumber) [![Project Status: WIP](https://www.repostatus.org/badges/latest/wip.svg)](https://www.repostatus.org/#wip) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](#)
<!-- README.md is generated from README.Rmd. Please edit that file -->
```{r setup, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```
geoplumber is an R package which enables data scientists and developers in general to develop scalable geospatial web applications. It is work in progress, and right now we consider it an R powered web application "framework". It utilizes [`plumber`](https://github.com/trestletech/plumber), which was designed for creating web APIs with R which is Swagger compliant. It supports [React](https://reactjs.org/) frontends at present (it may support other frontend frameworks such as VueJS in the future) and geographic data, building on [`sf`](https://github.com/r-spatial/sf).
It can be installed with the following command as it is not yet on CRAN:
```{r install_github, message=FALSE, eval=FALSE}
devtools::install_github("ATFutures/geoplumber")
#> the latest dev version
```
<!-- ## Installation -->
<!-- Currently repo is available only on github. To install the package using `devtools`: -->
<!-- geoplumber, like `devtools` and similar packages works by working directory. It does not currently create an `.Rproj` file but may do so in future. -->
## Usage
* For more detailed introduction see the [vignette](https://atfutures.github.io/geoplumber/articles/geoplumber.html)
To create a new web application:
```{r hidden1, echo=FALSE, eval=FALSE}
# knitr::opts_knit$set(root.dir = tempdir())
```
```{r create-example, eval=FALSE}
library(geoplumber)
gp_create("my_app")
```
This will create a `my_app` folder at your current working directory. Suppose you started an R session from a folder with path `/Users/ruser/`, you will have `/Users/ruser/my_app` on your machine.
You can then build the new project
```{r build-example, eval=FALSE}
setwd("my_app")
gp_build() # the front end and create minified js files.
```
You can then serve endpoints and front end with:
`gp_plumb()` \# provide custom port if you wish, default is 8000
Then visit `localhost:8000` to see your app.
## Example (1) reproducible web app
```{r nofuss}
library(geoplumber)
d <- file.path(tempdir(), "gp")
gp_create(d)
ow <- setwd(d)
ps <- gp_plumb()
Sys.sleep(1) # needed on automated build machines :)
ps
require(RCurl)
webpage <- getURL("http://localhost:8000")
webpage <- readLines(tc <- textConnection(webpage)); close(tc)
tail(webpage)
ps$kill()
setwd(ow)
# should fail
# getURL("http://localhost:8000")
```
## Example (2)
Serve the `geoplumber::traffic` dataset (data.frame) at a "/api/data" endpoint, and view it on the front end.
The `traffic` [dataset](https://data.cdrc.ac.uk/dataset/southwark-traffic-counts) is from CDRC at University of Leeds which is traffic data locations for the larger traffic dataset.
To achive this copy the following endpoint/API to the clipboard of your machine. If you like to understand the function, you need to learn `plumber` package.
```{r eval=FALSE}
#' Serve geoplumber::traffic from /api/data
#' @get /api/data
get_traffic <- function(res) {
geojson <- geojsonsf::sf_geojson(geoplumber::traffic)
res$body <- geojson
res
}
```
Then run (re-copied into clipboard just in case):
```{r hidden2, echo=FALSE}
Sys.setenv(CLIPR_ALLOW=TRUE)
```
```{r add-endpoint-manually, eval=FALSE}
setwd("my_app")
old_clip <- clipr::read_clip()
# adding above to clipboard
clipr::write_clip(c(
"#' Serve geoplumber::traffic from /api/data",
"#' @get /api/data",
"get_traffic <- function(res) {",
" geojson <- geojsonsf::sf_geojson(geoplumber::traffic)",
" res$body <- geojson",
" res",
"}"
))
gp_endpoint_from_clip()
clipr::write_clip(old_clip)
```
This has now added a new endpoint at: `/api/data`. To consume it, we can simply run:
```{r add-geojson, eval=FALSE}
setwd("my_app")
gp_add_geojson("/api/data")
```
You can now see the data by running:
```{r eval=FALSE}
gp_build() # build changes
gp_plumb()
```
Or in the following "export" function a basic `leaflet` map using the "headless" `gp_map` funciton:
```{r, echo=FALSE, fig.align='center', out.width="70%", fig.cap="<a href='https://www.cdrc.ac.uk/'>CDRC</a> London traffic data on geoplumber"}
knitr::include_graphics("man/figures/gp.png")
```
```{r, echo=TRUE, eval=FALSE}
# cd into a geoplumber app
setwd("my-app/")
library(geoplumber)
# view a dataset such as the `traffic` sf object bundled
t <- gp_map(geoplumber::traffic, browse_map = FALSE,
height = "320px", width = "90%")
# use includeHTML for markdown
htmltools::includeHTML(t)
```
You can also now see the raw JSON dataset at `http://localhost:8000/api/data`,
and on a map on a browser view the map at `http://localhost:8000`.
## Example (3)
We would like to see default University of Leeds `uni_poly` grow/shrink using `sf::st_buffer()` function. Here is a reproducible example (please take a look at the default `plumber.R` file in your `my_app` project):
```{r, eval=FALSE}
gp_create(tolower(tempdir()))
setwd(tolower(tempdir()))
gp_is_wd_geoplumber()
gp_add_slider(
min = 0.001,
max = 0.01,
step = 0.001
)
gp_change_file(
path = "src/Welcome.js",
what = '<GeoJSONComponent fetchURL={"http://localhost:8000/api/uol?grow=" + this.state.sliderInput} />
',
pattern = '<GeoJSONComponent fetchURL="http://localhost:8000/api/uol" />',
replace = TRUE,
verbose = TRUE
)
```
Run the project (this time at `tempdir()` location) by:
```{r eval=FALSE}
gp_build() # build changes
r <- gp_plumb() # run in bg
r¢kill()
```
Now you can see:
```{r, echo=FALSE, fig.align='center', out.width="70%", fig.cap="geoplumber::uni_poly grow/shrinking using sf::st_buffer function on server side."}
knitr::include_graphics("https://user-images.githubusercontent.com/1825120/46699371-7f79d000-cc11-11e8-9716-e1223296c7d6.gif")
```
## geoplumber stack
We have worked with Shiny and [`plumber`](https://github.com/trestletech/plumber/) and we consider ourselves experienced in ReactJS, too. In order to put together a web application powered at the backend with R and React at the front-end, there is a lot of setup and boilerplate to put together. This would be also correct for other front end stack such as Angular or VueJS.
Currently geoplumber uses Facebook's `create-react-app` (CRA) npm package to deal with underlying app management (including building and running) to keep you up to date with updates. `geoplumber` will generally provide detailed installation instructions for all required `npm` packages, but if not, the following are minimally required:
```
sudo npm i -g create-react-app
```
### Front end ###
Once the geoplumber app `my_app` has been created. It will have a `create-react-app` directory structure with an extra `R` folder to hold the backend R code. The React components, as they are in CRA apps, are in the `src` folder and ready to be customised and developed for your own purposes. So, a React developer could run `npm start` on the root directory and run the built in CRA development server which is what `gp_plumb_front()` does too.
### npm packages used
The following are included by default, the versions are just from old .Rmd file. geoplumber updates these as the package is developed. Feel free to replace it with your own .json package definer as and when.
```{r, echo=FALSE}
data <- read.csv(text=
"package , Usage
create-react-app , main package to manage front end
prop-types , React propTypes
react , React main
react-dom , React DOM
react-bootstrap , bootstrapZ
leaflet , current default web mapping library
react-leaflet , React wrapper around leaflet above
react-leaflet-control , React map control
react-router , React router (RR)
react-router-dom , React dom for RR
react-scripts , main package to manage front end
react-test-renderer , test suite
enzyme , test suite
enzyme-adapter-react-16 , test suite adapter for React
sinon , test suite")
```
```{r kable-npm}
knitr::kable(data)
```
## Showcase
An example application is deployed at [www.geoplumber.com](www.geoplumber.com). It showcases some zone and flow data using both `LeafletJS` and `MapboxGL` both in React. The application is dockerised automating the production and deployment.
## End-points
R package `plumber` comes with a default end-point for documenting the API using Swagger. This is also available from `geoplumber`'s `/__swagger__/` path.
We follow a pattern of `/api/` before the end-points and without for other URL's.
A new web app will have `/api/helloworld` and you can `curl` it:
```{sh eval=FALSE}
curl localhost:8000/api/helloworld
#> {"msg":["The message is: 'nothing given'"]}
```
## Tests
Tests currently only apply to restricted components of full functionality.
```{r, eval=FALSE}
devtools::test()
```
## Roadmap
What I (Layik) think will work for a version 0.1 to hit CRAN is geoplumber would be able to have:
* basic structure of a R + React app running
* basics of a production environment via Docker