Skip to content

Commit 3935d46

Browse files
committed
Article peaks and valleys
Add annotated plots showing how thresholds work
1 parent 92fa058 commit 3935d46

File tree

1 file changed

+115
-16
lines changed

1 file changed

+115
-16
lines changed

vignettes/articles/peaks-and-valleys.Rmd

Lines changed: 115 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -169,41 +169,119 @@ p0 +
169169
### Peak height: `global.threshold`
170170

171171
Above, the default value for `global.threshold` is `0.01` and enables the
172-
"filtering-out" of the smallest peaks. Passing `global.threshold = NULL`
172+
"filtering-out" of the smallest "peaks". Passing `global.threshold = NULL`
173173
disables filtering.
174174

175175
```{r}
176176
p0 +
177177
stat_peaks(span = 11, colour = "red", size = 1, global.threshold = NULL)
178178
```
179179

180+
The search for peaks can be constrained by giving a minimum height threshold in data units. For example,
181+
we can keep only peaks exceeding a value of 0.7 for `s.e.irrad`, the variable mapped
182+
to the _y_ aesthetic. We indicate the use of data units by enclosing the argument for `global.threshold` in a
183+
call to `I()`. (Function `I()` sets the class of its argument to `"AsIs"`, thus
184+
such values can be saved in variables and passed as arguments also by name.)
185+
186+
```{r}
187+
p0 +
188+
stat_peaks(global.threshold = I(0.7), colour = "red", size = 1)
189+
```
190+
191+
The same plot as above, annotated with the threshold and the range of the observations.
192+
193+
```{r}
194+
p0 +
195+
stat_peaks(global.threshold = I(0.7), colour = "red", size = 1) +
196+
geom_hline(yintercept = 0.7, linetype = "dashed", colour = "red") +
197+
scale_y_continuous(
198+
sec.axis =
199+
dup_axis(name = "global.threshold (\"AsIs\")",
200+
breaks =
201+
c(min(sun.spct$s.e.irrad), 0.7, max(sun.spct$s.e.irrad)), labels = function(x) round(x, 2))) +
202+
theme(axis.text.y.right = element_text(colour = "red"),
203+
axis.title.y.right = element_text(colour = "red"))
204+
```
205+
206+
180207
To limit the detected (and highlighted) peaks to taller ones than by default, we
181208
can limit the search, for example, to the top 1/3 of the _y_ range, by
182209
filtering-out those in the lower 2/3 of the _y_ range of the data.
183210

184211
```{r}
185212
p0 +
186-
stat_peaks(global.threshold = 2/3, colour = "red", size = 1)
213+
stat_peaks(global.threshold = 2/3, colour = "red", size = 1)
187214
```
188215

189-
We can also limit the search by giving a threshold in data units, for example,
190-
to keeå only those exceeding a value of 0.7 for `s.e.irrad`, the variable mapped
191-
to the _y_ aesthetic. We indicate use of data units by enclosing the value in a
192-
call to `I()`. Function `I()` sets the class of its argument to `"AsIs"`, thus
193-
such values can be saved in variables and passed as arguments also by name.
216+
The same plot annotated to show how the threshold range of $0\ldots 1$ relates to the data range.
194217

195218
```{r}
196219
p0 +
197-
stat_peaks(global.threshold = I(0.7), colour = "red", size = 1)
220+
stat_peaks(global.threshold = 0.67, colour = "red", size = 1) +
221+
geom_hline(aes(yintercept = min(s.e.irrad) + (max(s.e.irrad) - min(s.e.irrad)) * 0.67),
222+
linetype = "dashed", colour = "red") +
223+
scale_y_continuous(
224+
sec.axis =
225+
dup_axis(name = "global.threshold (relative)",
226+
breaks =
227+
min(sun.spct$s.e.irrad) +
228+
(max(sun.spct$s.e.irrad) - min(sun.spct$s.e.irrad)) * c(0, 0.25, 0.5, 0.67, 0.75, 1),
229+
labels = c(0, 0.25, 0.5, 0.67, 0.75, 1))) +
230+
theme(axis.text.y.right = element_text(colour = "red"),
231+
axis.title.y.right = element_text(colour = "red"))
232+
```
233+
234+
Very rarely the tallest peaks need to be discarded, but if needed this can be achieved by passing a number in $-1\ldots 0$ as argument to `global.threshold`.
235+
236+
```{r}
237+
p0 +
238+
stat_peaks(global.threshold = -0.5, colour = "red", size = 1)
239+
```
240+
241+
The same plot as above, annotated.
242+
243+
```{r}
244+
p0 +
245+
stat_peaks(global.threshold = -0.5, colour = "red", size = 1) +
246+
geom_hline(aes(yintercept = min(s.e.irrad) + (max(s.e.irrad) - min(s.e.irrad)) * 0.5),
247+
linetype = "dashed", colour = "red") +
248+
scale_y_continuous(
249+
sec.axis =
250+
dup_axis(name = "global.threshold (negative, relative)",
251+
breaks =
252+
min(sun.spct$s.e.irrad) +
253+
(max(sun.spct$s.e.irrad) - min(sun.spct$s.e.irrad)) * c(0, 0.25, 0.5, 0.75, 1),
254+
labels = -c(0, 0.25, 0.5, 0.75, 1))) +
255+
theme(axis.text.y.right = element_text(colour = "red"),
256+
axis.title.y.right = element_text(colour = "red"))
257+
```
258+
259+
Global thresholds work similarly with `stat_valleys()`, and numbers closer to one apply a more stringent threshold than smaller values.
260+
261+
262+
```{r}
263+
p0 +
264+
stat_valleys(global.threshold = 0.5, colour = "blue", size = 1)
198265
```
199266

200-
Very rarely the tallest peaks need to be discarded, but it is also possible,
201-
when using relative sizes.
267+
And the same plot as above, annotated with the threshold used and the possible range.
268+
202269

203270
```{r}
204271
p0 +
205-
stat_peaks(global.threshold = -1/2,
206-
colour = "red", size = 1)
272+
stat_valleys(global.threshold = 0.5, colour = "blue", size = 1) +
273+
geom_hline(aes(yintercept = min(s.e.irrad) + (max(s.e.irrad) - min(s.e.irrad)) * 0.5),
274+
linetype = "dashed", colour = "blue") +
275+
scale_y_continuous(
276+
sec.axis =
277+
dup_axis(name = "global.threshold (relative)",
278+
breaks =
279+
max(sun.spct$s.e.irrad) -
280+
(max(sun.spct$s.e.irrad) - min(sun.spct$s.e.irrad)) * c(0, 0.25, 0.5, 0.75, 1),
281+
labels = c(0, 0.25, 0.5, 0.75, 1))) +
282+
theme(axis.text.y.right = element_text(colour = "blue"),
283+
axis.title.y.right = element_text(colour = "blue"))
284+
207285
```
208286

209287
### Peak prominence: `local.threshold`
@@ -219,14 +297,34 @@ p0 +
219297
stat_peaks(colour = "red", size = 1, span = 11, local.threshold = 0.03)
220298
```
221299

222-
By default the reference for the local prominence of a peak is the median observation within the window. Alternatively, the minimum of the values in the window can be used as reference, in which case larger `local.threshold` values tend to be needed to obtain a similar effect with `"minimum"` as with `"median"`. The reference used is controlled by parameter `local.reference`.
300+
The same plot as above, annotated with the running median, used as local reference for the threshold.
301+
302+
```{r}
303+
p0 +
304+
stat_peaks(colour = "red", size = 1, span = 11, local.threshold = 0.03) +
305+
geom_line(aes(y = stats::runmed(s.e.irrad, k = 5, endrule = "median")), colour = "red", linetype = "dashed")
306+
```
307+
308+
By default the reference for the local prominence of a peak is the median observation within the window. Alternatively, the farthest value in the window can be used as reference, in which case larger `local.threshold` values tend to be needed to obtain a similar effect with `"farthest"` as with `"median"`. The reference used is controlled by parameter `local.reference`.
223309

224310
```{r}
225311
p0 +
226312
stat_peaks(colour = "red", size = 1, span = 11,
227313
local.reference = "farthest", local.threshold = 0.1)
228314
```
229315

316+
The same plot as above, annotated with the running minimum line.
317+
318+
```{r}
319+
p0 +
320+
stat_peaks(colour = "red", size = 1, span = 11,
321+
local.reference = "farthest", local.threshold = 0.1) +
322+
geom_line(aes(y = caTools::runmin(s.e.irrad,
323+
k = 5,
324+
endrule = "min")),
325+
colour = "red", linetype = "dashed")
326+
```
327+
230328
As for `global.threshold` we can specify the minimum local height in data units
231329
with a call to `I()`.
232330

@@ -236,9 +334,8 @@ p0 +
236334
```
237335

238336
It is important to keep in mind that `span`, `local.threshold` and
239-
`global.threshold` can be combined. However, `span` affects the effect of
240-
`local.threshold` by widening the window in which the minimum value is searched
241-
for.
337+
`global.threshold` can be combined. However, `span` modifies the effect of
338+
`local.threshold` by widening the window in which the median or farthest value is searched.
242339

243340
```{r}
244341
p0 +
@@ -248,6 +345,8 @@ p0 +
248345
global.threshold = I(0.5))
249346
```
250347

348+
Local thresholds also are implemented in `stat_valleys()` or work similarly as in `stat_peaks()`. The reference lines are as for peaks but the distance is assessed downwards from the line instead of upwards, even if arguments passed to `local.threshold` are in $0\ldots 1$ or data units as for peaks.
349+
251350
### Fitting peaks: `refine.wl`
252351

253352
The solar spectrum data used above has values at `r nrow(sun.spct)` different

0 commit comments

Comments
 (0)