# Chapter 7 Patterns of activity

Many organismal activities are tied to the cycles of the day, particularly in temperate zones, cycles of the year. These cycles bring regular fluctuations in light levels, day lengths, temperatures, and various other influences. Often these cycles interact, with the dawn chorus peaking in the early daylight hours and its timing and intensity fluctuating on a yearly cycle. This chapter looks at visualising these cycles and the effects of lunar cycles.

These plots are created using the SonicScrewdriver package (Baker 2021), which uses the suncalc package (Thieurmel and Elmarhraoui 2019) to perform the required sun and moon position calculations. The Plotrix package (Lemon 2006) is used for creating the visualisation. These packages are installed as shown below.

The SonicScrewdriver package must be loaded before constructing a visual.

## 7.1 Daily Cycles

Broughton (1963) contests the term diel for daily cycles as an incorrectly formed, unnecessary neologism. However, it sees greater use (according to the online Oxford English Dictionary) than his suggested nycthemeral.

The design for these plots came from a desire to compare the dawn chorus at various locations around the UK. However, they also offer great potential for comparing locations with greater longitudinal or latitudinal separation. The plots show the times of day, night, twilight (7.1.1), sunrise, sunset, nadir and solar noon. The day part of the plot shows the altitude (angle of the sun above the horizon) throughout the day, with the maximum value representing the sun directly overhead.

### 7.1.1 The Types of Twilight

#### 7.1.1.1 Civil Twilight

Civil twilight occurs when the sun’s geometric centre (as seen from Earth) passes between 0° and 6° below the horizon. During this time, it is normal for humans not to need the assistance of artificial light for everyday tasks.

### 7.1.2 Diel Plots

As the times of the solar day are dependent both on the date and location these must be passed to the `dielPlot()`

function.

#### 7.1.2.1 Rotations of a `dielPlot()`

By default the information is plotted in the UTC timezone, so locations in other timezones will have an overall rotation.

```
par(mfrow=c(1,3))
dielPlot(Sys.Date(), lat=53, lon=-50)
dielPlot(Sys.Date(), lat=53, lon=-0)
dielPlot(Sys.Date(), lat=53, lon=50)
```

Plots can be made in any timezone by using the `rot`

parameter to `dielPlot()`

and the `tz()`

function.

```
par(mfrow=c(1,3))
dielPlot(Sys.Date(), lat=53, lon=-50, rot=tz(3))
dielPlot(Sys.Date(), lat=53, lon=-0, rot=tz(3))
dielPlot(Sys.Date(), lat=53, lon=50, rot=tz(3))
```

By setting the `rot`

parameter to `Solar Noon`

it is possible to align the plots to solar noon. Notice that this rotates the plot labels.

```
par(mfrow=c(1,3))
dielPlot(Sys.Date(), lat=53, lon=-50, rot="Solar Noon")
dielPlot(Sys.Date(), lat=53, lon=-0, rot="Solar Noon")
dielPlot(Sys.Date(), lat=53, lon=50, rot="Solar Noon")
```

#### 7.1.2.2 Customising a `dielPlot()`

In addition to the `date`

, `lat`

and `lon`

parameters to `dielPlot()`

it is possible to make additional customisations to how the information is presented.

**Legend**

A legend can be added to the plot by setting `legend=TRUE`

.

**Plotting Components**

The components that can be plotted are listed below. By default all are plotted except for `Solar Noon`

and `Nadir`

.

Name | Notes |
---|---|

Astronomical Twilight | |

Nautical Twilight | |

Civil Twilight | |

Sunrise | |

Solar Noon | The time when the sun is highest in the sky |

Sunset | |

Nadir |

The components that are plotted can be specified using the `plot`

parameter.

```
components <- c("Sunrise", "Sunset", "Solar Noon", "Nadir")
dielPlot("2022-08-08", lat=53, lon=0.1, plot=components)
```

## 7.2 Yearly Cycles

The `yearlyPlot()`

function from the SonicScrewdriver package shows daylight changes throughout a year. It behaves in a very similar fashion to `dielPlot`

but takes a single year rather a date as input.

## 7.4 Core and ring plots

These visualisations for cyclical data plot their information onto a circle with a radius of two units. It is possible to limit the plot either to the centre of the circle (a ‘core’ plot) or to the edge (a ‘ring plot’). These alternative forms may be more useful when these plots are used to visualise addition variables (7.7).

## 7.5 Behind the scenes

### 7.5.1 `radialPolygon()`

The `radialPolygon()`

function handles most of the plotting functionality for cyclical data in `SonicScrewdriveR`

. It handles sectors, annuli, horizon plots and irregular polygons. It is used by the plotting functions such as `dielPlot()`

and helper functions such as `dielRings()`

to add data to cyclical plots.

For simple use cases, knowledge of the operation of `radialPolygon()`

may not be needed. Several helper functions cover the most common uses. However, understanding how this function works will allow for far greater customisation of cyclical plots than would otherwise be possible.

The various types of plots are created by changing the angle and radius parameters to `radialPolygon().`

#### 7.5.1.1 Orientation

Unlike traditional polar plots, diel and yearly plots start their periods on the left hand horizontal, and proceed clockwise. This orientation is assumed by `radialPolygon()`

, although it may be modified (e.g. the parameters `reverse=FALSE`

and `rot=0`

will plot using the standard conventions for polar coordinate systems.)

#### 7.5.1.2 Sectors

A sector is a section of a circle defined by two radii and an arc between them. Sectors are used widely in the default settings of `dielPlot()`

to plot the times of night and twilight.

Reversing the angle arguments allows the complementary sector to be drawn.

#### 7.5.1.3 Annuli

An annulus is the region between two concentric circles. Annuli and annular sectors are generated by `radialPolygon()`

when the parameter `radius`

is greater than zero.

```
emptyDiel()
radialPolygon(0, 2*pi, 1.75, 2, col="blue")
radialPolygon(pi, 4*pi/3, 1, 1.5, col="red")
legend(
-3,2.5,
c("annulus", "annuluar sector"),
col=c("blue", "red"),
lty=1,
lwd=5,
bty = "n",
cex = 1)
```

#### 7.5.1.4 Horizons

Horizons have one circular edge, and one that represents data, they are named as they often resemble a landscape or cityscape horizon. The example below uses a generated sine pattern to form the data edge.

```
library(tuneR)
angles <- (0:200)*pi/200 + pi/2
values <- 0.05*sine(10, samp.rate=201)@left
emptyDiel()
radialPolygon(NA,angles,0.5,1+values)
```

Setting the first angle parameter to `NA`

uses the range of the second to calculate the inner edge.

The inner edge can be used to show data by swapping the order of the angle and radius parameters.

```
library(tuneR)
angles <- (0:200)*pi/200 + pi/2
values <- 0.05*sine(10, samp.rate=201)@left
emptyDiel()
radialPolygon(angles,NA,1+values,2)
```

The `yearlyPlot()`

function uses two horizon plots, with a shared data edge.

## 7.6 Empty plots

The uses of daily and yearly plots extend beyond linking data to earthly cycles. The following functions provide the basic coordinate system without any data plotted (these functions are used intenally by `dielPlot()`

and `yearlyPlot()`

to establish their coordinate system).

## 7.7 Adding data to the visualisation

### 7.7.1 Periodic data: rings

The ring functions (`dielRing()`

,…) plot ring segments on top of a base cyclical plot. These rings are useful for showing typical periods of activity for a species, or events that happen continuously for a specified period of time.

By defaults the limits for the rings are `1,2`

for use with a *core* type plot, but this can be changed by specifying the `limits`

parameter to the ring function. Similarly, the plot legend may be removed with the paramater `legend=FALSE`

.

#### 7.7.1.1 `dielRings()`

```
names <- c("activity 1", "activity 2", "activity 3")
starts <- c("0600", "0900", "1500")
ends <- c("1200", "1700", "1900")
cols <- c("red", "green", "blue")
dielPlot("2022-08-08", lat=53, lon=0.1, limits=c(0,1))
dielRings(names, starts, ends, cols=cols)
```

```
names <- c("activity 1", "activity 2", "activity 3")
starts <- c("0600", "0900", "1500")
ends <- c("1200", "1700", "1900")
cols <- c("red", "green", "blue")
dielPlot("2022-08-08", lat=53, lon=0.1, limits=c(1,2))
dielRings(names, starts, ends, cols=cols, limits=c(0,1))
```

### 7.7.2 Periodic data: horizons

In this example we will plot the average monthly minimum and maximum temperatures for Lyme Regis, UK onto a `yearlyPlot()`

. This example introduces three small helper functions; `yearlyLabels()`

, `yearlyPositions()`

and `circularise()`

.

#### 7.7.2.1 `yearlyLabels()`

and `yearlyPositions`

These two functions are closely related, and used internally by `SonicScrewdriveR`

to label a yearly plot.

`## [1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug" "Sep" "Oct" "Nov" "Dec"`

The related `yearlyPositions()`

gives angular positions for the data around the plot (in radians).

```
## [1] 0.0000000 0.5336404 1.0156382 1.5492786 2.0657048 2.5993452 3.1157713
## [8] 3.6494117 4.1830521 4.6994783 5.2331187 5.7495449
```

The temperature data we have for Lyme Regis is monthly, however we would like to plot the values at the middle of the respective month. For this we add the parameter `format="mid-month"`

to get the appropriate radial angles.

```
## [1] 0.2668202 0.7746393 1.2824584 1.8074917 2.3325250 2.8575582 3.3825915
## [8] 3.9162319 4.4412652 4.9662985 5.4913318 5.9733296
```

If we now plot this data we see that the output is not quite a complete ring or horizon data as we might have expected.

```
# Temperature data for Lyme Regis
t_min <- c(3, 2.7, 3.4, 5.2, 8.2, 11.2, 13.1, 13, 14.4, 9.2, 5.8, 3.8)
t_max <- c(7.9,8, 9.8, 12.4, 15.4, 18.2, 20.1, 19.5, 17.8, 14.4, 10.6, 8.4)
# Scale the data
sf <- max(t_max)
t_min <- t_min/sf
t_max <- t_max/sf
angles <- yearlyPositions(format="mid-months")
yearlyPlot(lat=50.7, lon=-2.9)
radialPolygon(angles, angles, t_min, t_max, col="orange")
```

#### 7.7.2.2 `circularise()`

In order to join the horizons into a complete ring we can use the `circularise()`

function on the angle and temperature vectors.

```
# Temperature data for Lyme Regis
t_min <- c(3, 2.7, 3.4, 5.2, 8.2, 11.2, 13.1, 13, 14.4, 9.2, 5.8, 3.8)
t_max <- c(7.9,8, 9.8, 12.4, 15.4, 18.2, 20.1, 19.5, 17.8, 14.4, 10.6, 8.4)
# Scale the data
sf <- max(t_max)
t_min <- t_min/sf
t_max <- t_max/sf
angles <- yearlyPositions(format="mid-months")
# Circularise
t_min <- circularise(t_min)
t_max <- circularise(t_max)
angles <- circularise(angles)
yearlyPlot(lat=50.7, lon=-2.9)
radialPolygon(angles, angles, t_min, t_max, col="orange")
```

### 7.7.3 Helper functions

#### 7.7.3.1 `dielFraction()`

The `dielFraction()`

function is used to convert a POSIX time, or a time in `HHMM`

string format, into a radial fraction. This function is called by `dielPlot()`

and `dielRings()`

. By default the output is multiplied by 2π to output a position round a circle.

`## [1] "2024-01-24 19:11:25 GMT"`

`## [1] 5.024044`

The raw fraction can be specified using the parameter `unit="fraction"`

.

`## [1] "2024-01-24 19:11:25 GMT"`

`## [1] 0.7996016`

## 7.8 Interactive Plots

These plots can be used to create Shiny apps

- shiny-diel is an example that shows diel plots for a number of locations, and can be animated using the play button under the date slider.

### References

*SonicScrewdriveR*. https://cran.r-project.org/package=sonicscrewdriver.

*R-News*6 (4): 8–12.

*Suncalc: Compute Sun Position, Sunlight Phases, Moon Position and Lunar Phase*. https://CRAN.R-project.org/package=suncalc.