Skip to content

Commit a52ac28

Browse files
committed
pkgdown site
1 parent 0045839 commit a52ac28

4 files changed

Lines changed: 355 additions & 153 deletions

File tree

_pkgdown.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,14 @@ url: https://connorb.github.io/flowcam/
22
template:
33
bootstrap: 5
44

5+
navbar:
6+
structure:
7+
left: [intro, articles, reference]
8+
right: [search, github]
9+
10+
articles:
11+
- title: "Vignettes"
12+
navbar: ~
13+
contents:
14+
- getting-started
15+
- pecos-river

index.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# flowcam
2+
3+
**flowcam** provides a tidy interface to the USGS [National Imagery Management System (NIMS)](https://api.waterdata.usgs.gov/nims/v0), the API that stores and serves images collected by stream-gage cameras across the United States. Discover cameras, list and download images, and assemble them into animated GIFs or MP4 videos — all from R.
4+
5+
## Installation
6+
7+
```r
8+
# install.packages("pak")
9+
pak::pak("ConnorB/flowcam")
10+
```
11+
12+
## Quick start
13+
14+
```r
15+
library(flowcam)
16+
17+
# Store your free USGS API key (one-time setup)
18+
set_nims_key("your_api_key_here")
19+
20+
# Find the camera at a USGS monitoring location
21+
cam <- find_cameras(site_id = "08385630")
22+
23+
# List the 20 most recent images with timestamps
24+
list_images(cam$camId, limit = 20, raw_item = TRUE)
25+
26+
# Download a three-day window to disk
27+
dest <- file.path(tempdir(), "pecos")
28+
dir.create(dest)
29+
30+
download_images(
31+
cam_id = cam$camId,
32+
dest_dir = dest,
33+
size = "small",
34+
time = c("2025-06-10", "2025-06-12")
35+
)
36+
37+
# Assemble into an animated GIF
38+
make_gif(dir = dest, fps = 3, output = "pecos.gif")
39+
40+
# Or an MP4 video
41+
make_video(dir = dest, fps = 3, output = "pecos.mp4")
42+
```
43+
44+
## Core functions
45+
46+
| Function | Description |
47+
|---|---|
48+
| `find_cameras()` | Retrieve camera metadata; filter by NWIS site number or camera ID |
49+
| `find_gage_cameras()` | Like `find_cameras()`, plus NWIS site attributes (drainage area, HUC, state) via **dataRetrieval** |
50+
| `list_images()` | List image filenames for a camera; filter by time window |
51+
| `download_images()` | Download images to a local directory; resumes safely if interrupted |
52+
| `make_gif()` | Assemble images into an animated GIF |
53+
| `make_video()` | Assemble images into an MP4 video |
54+
55+
## Authentication
56+
57+
Register for a free key at <https://api.waterdata.usgs.gov/signup/>. Unauthenticated requests work but share a rate-limit pool. Store the key once and it persists across sessions:
58+
59+
```r
60+
set_nims_key("your_api_key_here")
61+
```
62+
63+
`flowcam` uses the same `API_USGS_PAT` environment variable as **dataRetrieval**, so one key covers both packages.
64+
65+
## Learn more
66+
67+
- [Getting started](articles/getting-started.html) — authentication, discovering cameras, listing images, downloading, and creating GIFs and videos in one walkthrough.
68+
- [Comparing two Pecos River gages](articles/pecos-river.html) — use `find_gage_cameras()` to enrich camera records with watershed metadata, download images from two sites on the same river reach, and produce a GIF and video to track a flow event moving downstream.
69+
- [Function reference](reference/index.html) — complete documentation for all exported functions.

vignettes/getting-started.qmd

Lines changed: 148 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -17,32 +17,47 @@ knitr::opts_chunk$set(
1717
)
1818
```
1919

20-
**flowcam** provides a tidy interface to the USGS [National Imagery Management System (NIMS)](https://api.waterdata.usgs.gov/nims/v0) API, which serves stream-gage camera images collected across the United States.
20+
**flowcam** gives you a tidy interface to the USGS [National Imagery Management System (NIMS)](https://api.waterdata.usgs.gov/nims/v0) API—the service that stores and serves images collected by stream-gage cameras across the United States. With a few function calls you can discover cameras, list available images, download them to disk, and stitch them into an animated GIF or MP4 video.
21+
22+
Full function reference: <https://connorb.github.io/flowcam/reference/>
23+
24+
```{r library}
25+
library(flowcam)
26+
```
2127

2228
## Authentication
2329

24-
NIMS requests can be made without an API key, but unauthenticated calls are rate-limited. Register for a free key at <https://api.waterdata.usgs.gov/signup/> and store it with `set_nims_key()`:
30+
NIMS requests work without a key, but unauthenticated traffic shares a rate-limit pool across all users. Register for a free key at <https://api.waterdata.usgs.gov/signup/> and store it once with `set_nims_key()`:
2531

2632
```{r auth}
27-
library(flowcam)
28-
2933
set_nims_key("your_api_key_here")
3034
```
3135

32-
`set_nims_key()` writes `API_USGS_PAT` to `~/.Renviron` and applies it to the current session immediately. All subsequent API calls in the session—and in future R sessions—use that key automatically. The same environment variable is read by the `dataRetrieval` package, so one key covers both.
36+
This writes `API_USGS_PAT` to `~/.Renviron` and applies it to the current session immediately. Every subsequent call—in this session and in future R sessions—picks up the key automatically. The `dataRetrieval` package reads the same environment variable, so one key covers both.
37+
38+
## Finding cameras
3339

34-
## Discovering cameras
40+
`find_cameras()` returns a tibble of camera metadata. Called with no arguments it fetches every camera currently registered in NIMS:
3541

36-
`find_cameras()` returns a tibble of camera metadata. With no arguments it fetches all available cameras; pass `site_id` to narrow results to a specific NWIS site.
42+
```{r find-all}
43+
all_cameras <- find_cameras()
44+
nrow(all_cameras)
45+
```
3746

38-
The Pecos Web Camera near Roswell, NM (NWIS site 08385630) is a well-known site on the Pecos River:
47+
Narrow to a specific USGS monitoring location by passing its NWIS site number:
3948

40-
```{r find-cameras}
49+
```{r find-by-site}
4150
cam <- find_cameras(site_id = "08385630")
4251
cam
4352
```
4453

45-
Key columns returned:
54+
This returns the Pecos Web Camera near Roswell, NM. The same record is reachable by its camera identifier:
55+
56+
```{r find-by-cam-id}
57+
find_cameras(cam_id = "NM_Pecos_Web_Camera_near_Roswell")
58+
```
59+
60+
Key columns in the result:
4661

4762
| Column | Description |
4863
|---|---|
@@ -53,97 +68,174 @@ Key columns returned:
5368
| `TL_enabled` | Whether daily timelapse videos are generated |
5469
| `smallDir`, `overlayDir`, `thumbDir` | S3 base directories for each image size |
5570

56-
If you already know a camera ID, look it up directly:
57-
58-
```{r find-by-cam-id}
59-
find_cameras(cam_id = cam$camId[[1]])
60-
```
61-
62-
To limit network traffic when you only need a few fields, use `return_fields`:
71+
When you only need a couple of fields—for example when scanning hundreds of cameras—use `return_fields` to keep the response small:
6372

6473
```{r return-fields}
6574
find_cameras(
6675
site_id = "08385630",
67-
return_fields = c("camName", "newestImageDT", "smallDir")
76+
return_fields = c("camName", "newestImageDT", "TL_enabled")
6877
)
6978
```
7079

71-
## Listing available images
80+
`camId` is always returned regardless of what you pass to `return_fields`.
7281

73-
`list_images()` returns the filenames stored for a camera. Filenames alone are enough to build download URLs via `build_image_url()`.
82+
## Listing available images
7483

75-
```{r list-images}
76-
cam_id <- cam$camId[[1]]
84+
`list_images()` returns the filenames stored for a camera. Pass either `cam_id` or `site_id`:
7785

78-
# 10 most recent images
79-
imgs <- list_images(cam_id, limit = 10)
86+
```{r list-default}
87+
imgs <- list_images("NM_Pecos_Web_Camera_near_Roswell", limit = 10)
8088
imgs
8189
```
8290

83-
By default the result is a single-column tibble of filenames. Set `raw_item = TRUE` to also retrieve timestamps and file sizes:
91+
The default is a single-column tibble of filenames ordered newest-first. Set `raw_item = TRUE` to also retrieve the capture timestamp and file size:
8492

8593
```{r list-raw}
86-
list_images(cam_id, limit = 10, raw_item = TRUE)
94+
list_images("NM_Pecos_Web_Camera_near_Roswell", limit = 10, raw_item = TRUE)
8795
```
8896

89-
### Filtering by date and time
97+
### Filtering by time
98+
99+
The `time` argument accepts a Date, POSIXct, or ISO 8601 character value. A single value means "on or after":
100+
101+
```{r time-single}
102+
list_images(
103+
"NM_Pecos_Web_Camera_near_Roswell",
104+
time = "2025-06-15"
105+
)
106+
```
90107

91-
Pass POSIXct values (in UTC) to `after` and `before` to fetch images from a specific window:
108+
A two-element vector sets a closed window. Use `NA` for an open bound:
92109

93-
```{r date-filter}
110+
```{r time-window}
94111
list_images(
95-
cam_id,
96-
after = as.POSIXct("2025-06-01 00:00:00", tz = "UTC"),
97-
before = as.POSIXct("2025-06-02 00:00:00", tz = "UTC")
112+
"NM_Pecos_Web_Camera_near_Roswell",
113+
time = c("2025-06-01", "2025-06-03")
98114
)
99115
```
100116

101-
## Building image URLs
117+
### Chronological order
102118

103-
`build_image_url()` combines the camera's base S3 directory with the filenames returned by `list_images()`:
119+
By default results are newest-first. Pass `recent = FALSE` to flip the order—useful when you want frames in chronological order before building an animation:
104120

105-
```{r build-urls}
106-
urls <- build_image_url(cam, imgs$filename, size = "small")
107-
head(urls)
121+
```{r oldest-first}
122+
list_images("NM_Pecos_Web_Camera_near_Roswell", limit = 20, recent = FALSE)
108123
```
109124

110-
The `size` argument controls image dimensions:
125+
### Pagination
111126

112-
- `"small"` (default) — ~720 px wide, suitable for monitoring dashboards
113-
- `"overlay"` — full-size overlay image with gage-reading annotation
114-
- `"thumb"` — thumbnail ~200 px tall
127+
The `limit` argument controls the API page size (1–50,000). When the camera has more images than `limit`, `list_images()` paginates automatically using a timestamp cursor and returns all matching records in a single tibble.
115128

116129
## Downloading images
117130

118-
`download_images()` wraps the steps above into a single call: it finds the camera, lists images, builds URLs, and saves the files to a local directory.
131+
`download_images()` lists the images for a camera and saves them to a local directory in one call. You must create the destination directory beforehand:
119132

120-
```{r download}
121-
dest <- tempdir()
133+
```{r download-basic}
134+
dest <- file.path(tempdir(), "roswell")
135+
dir.create(dest, showWarnings = FALSE)
122136
123137
paths <- download_images(
124-
cam_id = cam_id,
138+
cam_id = "NM_Pecos_Web_Camera_near_Roswell",
125139
dest_dir = dest,
126140
size = "small",
127-
limit = 5
141+
limit = 10
128142
)
143+
```
144+
145+
`paths` is a character vector of local file paths returned invisibly. Failed downloads are represented as `NA`.
146+
147+
### Image sizes
148+
149+
| `size` | Approximate dimensions | Best for |
150+
|---|---|---|
151+
| `"small"` (default) | ~720 px wide | Monitoring, animation |
152+
| `"overlay"` | Full resolution | Gage-reading annotation visible |
153+
| `"thumb"` | ~200 px tall | Quick visual overview |
154+
155+
### Time filtering
129156

130-
paths
157+
Pass the same `time` argument as `list_images()` to restrict which images are downloaded:
158+
159+
```{r download-window}
160+
paths <- download_images(
161+
cam_id = "NM_Pecos_Web_Camera_near_Roswell",
162+
dest_dir = dest,
163+
size = "small",
164+
time = c("2025-06-10", "2025-06-12")
165+
)
131166
```
132167

133-
Already-downloaded files are skipped by default (`overwrite = FALSE`), making it easy to resume a partially completed download. Pass `overwrite = TRUE` to force re-download.
168+
### Resuming partial downloads
169+
170+
`download_images()` skips files that already exist in `dest_dir` when `overwrite = FALSE` (the default). If a download is interrupted, simply re-run the same call and only the missing files will be fetched.
171+
172+
## Making a GIF
134173

135-
## Timelapse videos
174+
`make_gif()` fetches images and encodes them into an animated GIF. It requires the `gifski` package.
136175

137-
Many USGS cameras produce a daily timelapse MP4 stitched from images collected throughout the day. `get_timelapse_url()` returns the URL to that file:
176+
The simplest call streams images directly from NIMS—no separate download step needed:
177+
178+
```{r gif-direct}
179+
make_gif(
180+
cam_id = "NM_Pecos_Web_Camera_near_Roswell",
181+
time = c("2025-06-10", "2025-06-12"),
182+
fps = 2,
183+
output = "roswell.gif"
184+
)
185+
```
186+
187+
If you already downloaded images with `download_images()`, point to that directory with `dir` to skip re-downloading:
188+
189+
```{r gif-from-dir}
190+
make_gif(
191+
dir = dest,
192+
fps = 2,
193+
output = "roswell.gif"
194+
)
195+
```
138196

139-
```{r timelapse}
140-
url <- get_timelapse_url(cam_id)
141-
url
197+
### One frame per day
198+
199+
For a range spanning many days the result can be hundreds of frames. Pass `one_per_day = TRUE` to reduce the animation to a single frame per calendar day, selecting the image whose capture time is closest to local noon:
200+
201+
```{r gif-one-per-day}
202+
make_gif(
203+
cam_id = "NM_Pecos_Web_Camera_near_Roswell",
204+
time = c("2025-05-01", "2025-06-30"),
205+
fps = 4,
206+
one_per_day = TRUE,
207+
output = "roswell_monthly.gif"
208+
)
209+
```
210+
211+
When `output` is not specified the file is written to `"<cam_id>.gif"` in the working directory.
212+
213+
## Making a video
214+
215+
`make_video()` produces an MP4 instead of a GIF. It requires the `av` package and accepts the same arguments as `make_gif()`:
216+
217+
```{r video-direct}
218+
make_video(
219+
cam_id = "NM_Pecos_Web_Camera_near_Roswell",
220+
time = c("2025-06-10", "2025-06-12"),
221+
fps = 4,
222+
output = "roswell.mp4"
223+
)
224+
```
225+
226+
Build from an already-downloaded directory:
227+
228+
```{r video-from-dir}
229+
make_video(
230+
dir = dest,
231+
fps = 4,
232+
output = "roswell.mp4"
233+
)
142234
```
143235

144-
You can open the URL directly in a browser or pass it to a video tool. A warning is emitted when `TL_enabled` is `FALSE` for the camera.
236+
MP4 files are substantially smaller than equivalent GIFs at the same resolution and frame count, making them preferable for longer time ranges or larger image sizes. GIFs are more portable for sharing in contexts that don't support video embedding.
145237

146238
## Next steps
147239

148-
- See `vignette("pecos-river")` for a full monitoring workflow combining **flowcam** with streamflow data from **dataRetrieval**.
149-
- Use `find_gage_cameras()` to retrieve camera metadata enriched with NWIS site attributes (drainage area, elevation, hydrologic unit, etc.).
240+
- `vignette("pecos-river")` shows how to use `find_gage_cameras()` to enrich camera records with NWIS site metadata and compare two cameras on the same river reach.
241+
- The full function reference is at <https://connorb.github.io/flowcam/reference/>.

0 commit comments

Comments
 (0)