collapse = TRUE,
  comment = "#>"


  1. Preparing your data
    1. Structuring the study area
    2. Creating a distances matrix
  2. explore()
    1. Processes behind explore()
    2. Inspecting the explore() results
  3. migration()
    1. Processes behind migration()
    2. Inspecting the migration() results
    3. One-way efficiency estimations
  4. residency()
    1. Processes behind residency()
    2. Inspecting the residency() results
    3. Multi-way efficiency estimations
  5. Manual mode
  6. Errors and messages

The explore() function

The arguments in the explore() function are transversal to the migration() and residency() functions.

Although there are many arguments available, you do not need to start working with all of them right away. This is because many of these arguments have default values. If you want to make a quick check of your study, just run explore() with a tz argument in the same directory as your data and you will be ready to get some results!


explore(tz = "Europe/London")

Curious about how explore() processes your data? Have a look under the hood!

Need help going through the output of explore()? Find more details here.

General arguments

All the arguments of explore(), which also exist in migration() and residency(), are explained below.

explore(path = NULL, tz, max.interval = 60, minimum.detections = 2, start.time = NULL, stop.time = NULL,
  speed.method = c("last to first", "first to first"), speed.warning = NULL, speed.error = NULL, 
  jump.warning = 2, jump.error = 3, inactive.warning = NULL, inactive.error = NULL, exclude.tags = NULL, 
  override = NULL, report = TRUE)


The path is the way to the folder where you want to run the analysis. If you are already working in the folder where you have your data files, leave path as NULL and the analysis will be run in the current directory.


Receivers usually work in Coordinated Universal Time (UTC). Although this is nice to integrate data from multiple receivers, depending on where you are working, it may mean that the receivers' time is actually displaced from the daytime in your study area. To correct for this, you must include your time zone in this field. For example, to analyse a study performed in Denmark, we must use tz = "Europe/Copenhagen".

Time zones can be complicated business, so to help you out, you can search this wiki page or the output of OlsonNames() for the time zone code which you should use.

Note: : This time zone must match the time zone of the release times listed in the biometrics file and in the deployments file.


If a fish is detected multiple times in one array without being detected in other arrays, these detections are grouped into a single event, assuming that the time difference between two consecutive detections does not exceed max.interval (which is set in minutes). Should the time between detections exceed max.interval, a new movement event will be created, in the same receiver array.

In the example below, you can see how the same detections can be interpreted as a different number of movement events depending on whether we set max.interval to a) 120 minutes, b) 60 minutes or c) 30 minutes.


Movements table for example a:

|Array | Detections|First station |Last station |First time |Last time |Time travelling |Time on array | |:------|----------:|:-------------|:------------|:-------------------|:-------------------|:---------------|:-------------| |Array1 | 14|St.1 |St.1 |2019-05-15 12:00:00 |2019-05-15 19:45:00 |NA |7:45 |

Movements table for example b:

|Array | Detections|First station |Last station |First time |Last time |Time travelling |Time on array | |:------|----------:|:-------------|:------------|:-------------------|:-------------------|:---------------|:-------------| |Array1 | 7|St.1 |St.1 |2019-05-15 12:00:00 |2019-05-15 14:40:00 |NA |2:40 | |Array1 | 6|St.1 |St.1 |2019-05-15 16:00:00 |2019-05-15 18:00:00 |1:20 |2:00 | |Array1 | 1|St.1 |St.1 |2019-05-15 19:45:00 |2019-05-15 19:45:00 |1:45 |0:00 |

Movements table for example c:

|Array | Detections|First station |Last station |First time |Last time |Time travelling |Time on array | |:------|----------:|:-------------|:------------|:-------------------|:-------------------|:---------------|:-------------| |Array1 | 4|St.1 |St.1 |2019-05-15 12:00:00 |2019-05-15 13:00:00 |NA |1:00 | |Array1 | 3|St.1 |St.1 |2019-05-15 13:50:00 |2019-05-15 14:40:00 |0:50 |0:50 | |Array1 | 2|St.1 |St.1 |2019-05-15 16:00:00 |2019-05-15 16:20:00 |1:20 |0:20 | |Array1 | 4|St.1 |St.1 |2019-05-15 17:10:00 |2019-05-15 18:00:00 |0:50 |0:50 | |Array1 | 1|St.1 |St.1 |2019-05-15 19:45:00 |2019-05-15 19:45:00 |1:45 |0:00 |


This argument controls how many times a fish must be registered to be considered valid, if there is only one movement event. Lets have a look at an example:

Fish A only has one movement event at River1, with one detection.

If a Fish has more than one movement event, then the minimum.detections argument no longer plays a role.

For example, if Fish B has two movement events at River1, both with one detection (i.e. two detections in total), these movements are considered valid even if minimum.detections = 3. This is because it is unlikely that an erroneous signal which matches a target tag would be recorded on two or more occasions separated in time and/or space.

start.time and stop.time

Sometimes your receivers contain much more detection data than what you are interested in, which can increase the time it takes to process all the detections. By including a start.time and/or an stop.time, you can trim the detection data to those target times.

This is particularly relevant if, for example, you used some of your tags as testers before the study started, or if you used one of the receivers to activate and test the tags. A fish being detected before being released is a major issue, and actel will complain about that:

Error: Fish R64K-1111 was detected before being released!
  Release time: 2018-04-10 12:00:00
  First detection time: 2018-04-10 09:33:02
  Number of detections before release: 1

You may either:
  a) Stop the analysis and check the data;
  b) Discard the before-release detections and continue.


When you get an error like this, it is highly recommended that you check potential errors in the input files before discarding data.

Note: : The timestamps must be written in yyyy-mm-dd hh:mm:ss format, in the same time zone as your study area. : Curious about that "comment" option in the decision? Read more about it here


When calculating movement speeds from one array to the next, it is important to know if actel should count the time from the last detection in one array to the first detection in the next, or if you want actel to count the time from the first detection in one array to the first detection in the next. This is what speed.method is doing. You can choose one of "last to first" or "first to first". The example below illustrates the difference between both methods:


Note: : If you do not supply a distance matrix, speeds cannot be calculated. Instead, the time difference will be displayed.

speed.warning and speed.error

These two variables control the speed checks. By default, they are NULL, and no speed checks are performed. actel will let you know this happened with the following message:

M: 'speed.warning'/'speed.error' were not set, skipping speed checks.

However, if you include a distances matrix in the analysis, you can specify the maximum espected speed for your fish, in metres per second. If a fish goes over these values, warnings and user interaction will be activated, as necessary.

Speed checks cannot be performed without a distance matrix. If you attempt to do this, actel will complain:

W: 'speed.warning'/'speed.error' were set, but a valid distance matrix is not present. Aborting speed checks.

jump.warning and jump.error

During the course of a study, fish can (hopefully not too often) pass through a receiver array undetected. However, if this happens consecutively for more than one array, then perhaps something fishy is going on. Was your fish eaten by a bird? Was there something wrong with the arrays? Whatever the cause, there is a point after which you get suspicious. The jump.warning and jump.error arguments control how suspicious you want to be.

You can have a look at these arguments in action here.

inactive.warning and inactive.error

These two variables control the inactiveness checks. inactive.warning and inactive.error must be set in days. That is, if inactive.warning = 2, any fish that is deemed inactive for two days or more will trigger a warning. By default, they are NULL, and no inactiveness checks are performed. Actel will let you know this happened with the following message:

M: 'inactive.warning'/'inactive.error' were not set, skipping inactivity checks.

Altough it is not a requirement, inactiveness checks work best if a distances matrix is present. If you choose to run inactiveness checks without a distances matrix, actel will remind you of this with the following message:

M: Running inactiveness checks without a distance matrix. Performance may be limited.

You can learn more about how the inactiveness checks operate here.


It is possible for a stray tag with the same signal as one of your tags to enter the study area. Although this is unexpected, it would mean you could end up with two tags that differ only in code spaces. As actel works based on the tag signals alone, it does not know which tag is yours, and which is a stray, so you must intervene. If this happens, the following error is issued:

Error: One or more signals match more than one tag in the detections! Showing relevant signals/tags.
   Signal 1081 was found on tags A69-1601-1081, R64K-1081.
Error in checkDupSignals(input = my.list, bio = bio, tag.list = tags$list) : 
  Fatal exception found. Stopping analysis.

As you can see above, signal 1081 appears both in tags A69-1601-1081 and R64K-1081. As you should be able to identify your tag between the two, you can exclude the other tag and re-start the analysis. Once you do that, actel will let you know the problem is solved:

M: Excluding tag(s) A69-1601-1081 from the analysis per used command (detections removed: 1, respectively).

If more than one tag causes trouble, you can list multiple tags to be excluded, like this: exclude.tags = c("A69-1601-1081", "A69-1601-1220").


Once you finish your analysis, you should go through the generated outputs and check for any strange behaviour. We will discuss this in more detail later on, but for now the important message is that, if you would like to manually change the results for any set of tags, you can list those tags in override to trigger full manual mode (e.g. override = c("R64K-1234", "R64K-1405")).

When you list tags in override, actel will recognise them and enter full manual mode when it is their turn to be analysed. You will know this is happening when you see the following message:

M: Override has been triggered for fish R64K-1234. Entering full manual mode.

You can find more information on how to operate full manual mode here.


The report option activates a series of print functions that draw tables and figures for later integration in an html report. When you activate this option, a new Report subdirectory is created, where all the relevant files are stored. Before finishing, actel assembles the html report and stores it in your working directory. If you already have a report in your working directory, actel will create a new file with a different name.

You can also inspect each graphic individually in the Report subdirectory.

Here are some examples:

drawing drawing

Note: : Even if something fails during the report printing, your results will still be saved the actel_explore_results.RData file in your working directory!

All done!

Now that you know how to run the explore analysis, you may want to:

Learn more about what explore() is doing

Learn more about the results of explore()

Back to top.

hugomflavio/actel documentation built on Jan. 11, 2020, 11:36 a.m.