1
- spocc_inat_obs <- function (query = NULL , taxon = NULL , quality = NULL , geo = TRUE ,
1
+ # API docs: https://api.inaturalist.org/v1/docs/#!/Observations/get_observations
2
+ spocc_inat_obs <- function (taxon_name = NULL , quality = NULL , geo = TRUE ,
2
3
year = NULL , month = NULL , day = NULL , bounds = NULL , date_start = NULL ,
3
4
date_end = NULL , maxresults = 100 , page = NULL , callopts ) {
4
5
5
6
# input parameter checks
6
- if (! is.null(quality )) quality <- match.arg(quality , c(" casual" ," research" ))
7
+ if (! is.null(quality )) quality <- match.arg(quality , c(" casual" ," research" , " needs_id " ))
7
8
if (! is.null(year )) {
8
9
if (length(year ) > 1 ) {
9
10
stop(" can only filter results by 1 year; enter only 1 value for year" ,
10
11
call. = FALSE )
11
12
}
12
13
}
14
+ assert(geo , " logical" )
13
15
if (! is.null(month )) {
14
16
month <- as.numeric(month )
15
17
if (is.na(month )) {
@@ -37,62 +39,63 @@ spocc_inat_obs <- function(query=NULL, taxon = NULL, quality=NULL, geo=TRUE,
37
39
if (day < 1 || day > 31 ) stop(" Please enter a valid day between 1 and 31" ,
38
40
call. = FALSE )
39
41
}
42
+
43
+ args <- sc(list (taxon_name = taxon_name , quality_grade = quality ,
44
+ geo = geo , year = year , month = month , day = day ,
45
+ d1 = date_start , d2 = date_end ))
46
+
40
47
if (! is.null(bounds )) {
41
48
if (length(bounds ) != 4 ) {
42
49
stop(" bounding box specifications must have 4 coordinates" , call. = FALSE )
43
50
}
51
+ bounds <- list (swlat = bounds [1 ], swlng = bounds [2 ], nelat = bounds [3 ],
52
+ nelng = bounds [4 ])
53
+ args <- sc(c(args , bounds ))
44
54
}
45
55
46
- args <- sc(list (q = query , quality_grade = quality , taxon_name = taxon ,
47
- `has[]` = if (! is.null(geo ) && geo ) " geo" else NULL ,
48
- year = year , month = month , day = day ,
49
- d1 = date_start , d2 = date_end ))
50
- bounds <- list (swlat = bounds [1 ], swlng = bounds [2 ], nelat = bounds [3 ],
51
- nelng = bounds [4 ])
52
- args <- sc(c(args , bounds ))
53
-
54
- q_path <- " observations.csv"
55
- ping_path <- " observations.json"
56
-
57
56
if (! is.null(page )) {
58
57
page_query <- c(args , per_page = maxresults , page = page )
59
- cli <- crul :: HttpClient $ new(url = inat_base_url() , opts = callopts )
60
- res <- cli $ get(path = q_path , query = page_query )
58
+ cli <- crul :: HttpClient $ new(url = inat_base_url , opts = callopts )
59
+ res <- cli $ get(path = inat_path , query = page_query )
61
60
62
- total_res <- as.numeric(res $ headers $ `x-total-entries` )
63
61
res <- spocc_inat_handle(res )
64
- data_out <- if (is.na(res )) NA else utils :: read.csv(textConnection(res ),
65
- stringsAsFactors = FALSE )
62
+ tmp <- jsonlite :: fromJSON(res , flatten = TRUE )
63
+ data_out <- tmp $ results
64
+ total_res <- tmp $ total_results
66
65
} else {
67
66
ping_query <- c(args , page = 1 , per_page = 1 )
68
- cli <- crul :: HttpClient $ new(url = inat_base_url() , opts = callopts )
69
- out <- cli $ get(path = ping_path , query = ping_query )
67
+ cli <- crul :: HttpClient $ new(url = inat_base_url , opts = callopts )
68
+ out <- cli $ get(path = inat_path , query = ping_query )
70
69
out $ raise_for_status()
71
- total_res <- as.numeric(out $ response_headers $ `x-total-entries` )
72
-
70
+
71
+ total_res <- jsonlite :: fromJSON(spocc_inat_handle(out ),
72
+ flatten = TRUE )$ total_results
73
73
if (total_res == 0 ) {
74
74
stop(" no results; either no records or entered an invalid search" ,
75
75
call. = FALSE )
76
76
}
77
77
78
78
page_query <- c(args , per_page = 200 , page = 1 )
79
- data <- cli $ get(path = ping_path , query = page_query )
79
+ data <- cli $ get(path = inat_path , query = page_query )
80
80
data <- spocc_inat_handle(data )
81
- data_out <- jsonlite :: fromJSON(data , flatten = TRUE )
82
- data_out $ tag_list <- sapply(data_out $ tag_list , function (x ) {
81
+ data_out <- jsonlite :: fromJSON(data , flatten = TRUE )$ results
82
+ data_out $ tags <- sapply(data_out $ tags , function (x ) {
83
83
if (length(x ) == 0 ) " " else paste0(x , collapse = " , " )
84
84
})
85
85
86
86
if (total_res < maxresults ) maxresults <- total_res
87
87
if (maxresults > 200 ) {
88
+ testing_out <- list ()
88
89
for (i in 2 : ceiling(maxresults / 200 )) {
90
+ cat(i , " \n " )
89
91
page_query <- c(args , per_page = 200 , page = i )
90
- data <- cli $ get(path = ping_path , query = page_query )
92
+ data <- cli $ get(path = inat_path , query = page_query )
91
93
data <- spocc_inat_handle(data )
92
- data_out2 <- jsonlite :: fromJSON(data , flatten = TRUE )
93
- data_out2 $ tag_list <- sapply(data_out2 $ tag_list , function (x ) {
94
+ data_out2 <- jsonlite :: fromJSON(data , flatten = TRUE )$ results
95
+ data_out2 $ tags <- sapply(data_out2 $ tags , function (x ) {
94
96
if (length(x ) == 0 ) " " else paste0(x , collapse = " , " )
95
97
})
98
+ testing_out [[i ]] <- data_out2
96
99
data_out <- rbindl(list (data_out , data_out2 ))
97
100
}
98
101
}
@@ -118,12 +121,13 @@ spocc_inat_handle <- function(x){
118
121
if (! x $ response_headers $ `content-type` ==
119
122
" application/json; charset=utf-8" ) {
120
123
warning(
121
- " Conent type incorrect, should be 'application/json; charset=utf-8'" )
124
+ " Content type incorrect, should be 'application/json; charset=utf-8'" )
122
125
NA
123
126
}
124
127
if (x $ status_code > 202 ) {
125
- warning(sprintf(" Error: HTTP Status %s" , data $ status_code ))
126
- NA
128
+ parsed <- jsonlite :: fromJSON(x $ parse(" UTF-8" ))
129
+ if (" error" %in% names(parsed )) stop(parsed $ error )
130
+ x $ raise_for_status()
127
131
}
128
132
if (nchar(res ) == 0 ) {
129
133
warning(" No data found" )
@@ -136,10 +140,11 @@ spocc_inat_handle <- function(x){
136
140
137
141
spocc_get_inat_obs_id <- function (id , callopts = list ()) {
138
142
q_path <- paste(" observations/" , as.character(id ), " .json" , sep = " " )
139
- cli <- crul :: HttpClient $ new(url = inat_base_url() , opts = callopts )
143
+ cli <- crul :: HttpClient $ new(url = inat_base_url , opts = callopts )
140
144
res <- cli $ get(path = q_path )
141
145
res $ raise_for_status()
142
146
jsonlite :: fromJSON(res $ parse(" UTF-8" ))
143
147
}
144
148
145
- inat_base_url <- function () " https://www.inaturalist.org/"
149
+ inat_base_url <- " https://api.inaturalist.org"
150
+ inat_path <- " v1/observations"
0 commit comments