```
import matplotlib.pyplot as plt
import numpy as np
from scipy.special import i0
= np.linspace(-np.pi, np.pi, 200)
x
def von_misses(kappa):
= 0
mu = np.exp(kappa*np.cos(x-mu))/(2*np.pi*i0(kappa))
y return y
plt.figure()
for i in [0.5, 1, 2, 5, 10, 20]:
=f'$\kappa = {i}$')
plt.plot(x, von_misses(i), label
plt.legend()min(), x.max())
plt.xlim(x. plt.show()
```

# 6 Ichthyop processes

In this section, the different Ichthyop processes are described. These processes are implemented in the classes within the `action`

folder.

Parameters associated with these processes must be included in `action`

blocks. They can be activated or deactivated by setting the `enabled`

tag (cf. sec-xml-config).

## 6.1 Growth

There is 2 different implementations of the growth module. They can be selected by setting the `class_name`

parameter in the `action.growth`

action configuration block.

### 6.1.1 Linear growth

To use the linear growth method described in Lett et al. (2008), choose the `LinearGrowthAction.java`

class.

Length increment is provided as follows:

\[ \Delta L = C_1 + C_2 \times \dfrac{F}{F + K_S} \times max(T, T_{thres}) \times \Delta t \]

where \(\Delta t\) is the time-step (in days), \(C_1\) and \(C_2\) are parameters (`coeff1`

and `coeff2`

), \(T_{thres}\) is a temperature threshold (`threshold_temp`

parameter), \(F\) is the food quantity and \(K_S\) is a half-saturation constant (`half_saturation`

parameter). If the latter is not defined or equals 0, \(Q\) is assumed to be \(1\).

The name of the food and temperature variables are provided by the `food_field`

and `temperature_field`

parameters.

### 6.1.2 Sole growth

If the {samp}`SoleGrowthAction.java`

class is selected, the growth model used in Tanner et al. (2017) is used. It relies on the growth equation from Fonds (1979) and given by:

\[ \Delta L = C_1 \times T^{C_2} \times \Delta t \]

with \(L\) the length, \(T\) the temperature and \(\Delta t\) the time step in days, and \(C_1\) and \(C_2\) are parameters (`c1`

and `c2`

respectively).

The temperature field is provided by the `temperature_field`

parameter.

## 6.2 Lethal temperature and salinity

In Ichthyop, there is the possibility to define a range of temperature and salinity beyond which the particle is killed.

### 6.2.1 Lethal temperature

The functionning og the lethal temperature module depends on whether the growth module is enabled or not.

#### Growth disabled

lethal temperature can either be provided in a CSV file (`lethal_temp_file`

parameter), which provides the lower and upper temperature values that can be supported by the particle as a function of age (in hours). The file must have the following format:

```
Time(hour);Cold temperature (C);Warm temperature (C)
0;14;22
48;13;22
96;12;22
```

In this case, three age classes will be considered: \([0, 48[\), \([48, 96[\) and \([96, \infty[\)

If the `lethal_temp_file`

parameter is not defined, single values will be used independently of the age. These values are provided in the `cold_lethal_salinity_egg`

and `warm_lethal_salinity_egg`

parameters.

Note that the `temperature_field`

parameter, providing the name of the temperature variable, must also be provided.

#### Growth enabled

If the growth module is enabled, two cold and warm lethal temperatures must be provided. One for eggs (`cold_lethal_temperature_egg`

and `hot_lethal_temperature_egg`

), one for larva (`cold_lethal_temperature_larva`

and `hot_lethal_temperature_larva`

).

The stage (`egg`

or `larva`

) is determined by the growth module, and the right temperature range is applied to the particle.

### 6.2.2 Lethal salinity

Lethal salinity can either be provided in a CSV file (`lethal_salt_file`

parameter), which provides the lower and upper salinity values that can be supported by the particle as a function of age (in hours). The file must have the following format:

```
Time(hour);Fresh salinity (PSU);Salty salinity (PSU)
0;35;40
48;30;40
96;30;45
```

In this case, three age classes will be considered: \([0, 48[\), \([48, 96[\) and \([96, \infty[\)

If the `lethal_salt_file`

parameter is not defined, single values will be used independently of the age. These values are provided in the `fresh_lethal_salinity_egg`

and `saline_lethal_salinity_egg`

parameters.

Note that the `salinity_field_`

parameter, providing the name of the salinity variable, must also be provided.

## 6.3 Buoyancy

The buoyancy module allow to vertically displace a particle, depending on it’s density and on the sea water density, following Parada et al. (2003).

The buoyancy-induced vertical velocity of the particle is given by:

\[ W_{buoy} = \dfrac{1}{24} \times g \times a \times b \times \dfrac{\rho_{water} - \rho_{part}}{\rho_{water}} \mu^{-1} \log\left(2 \dfrac{a}{b} + 0.5\right); \]

with \(a\) and \(b\) the semi-major axis and semi-minor axis of an ellipse (`mean_major_axis`

and `mean_minor_axis`

parameters), \(\mu\) the molecular viscosity (`molecular_viscosity`

parameter), \(\rho_{water}\) the water density, \(\rho_{part}\) the particle density and \(g\) the gravitational acceleration (\(cm.s^{-2}\)).

If the particle density varies with age, it can be provided in a CSV file (`density_file`

parameter), formatted as follows:

```
Age(hour);Density (g/cm3)
0;1.0235625
24;1.02374
48;1.023335
60;1.0239
66;1.025672
```

If the `density_file`

parameter is not found, a constant density will be assumed (`particle_density`

parameter).

The buoyancy process is only applied for the early life stages. If the growth process is disabled, it is controlled by the `age_max`

parameter (provided in days). If this parameter is not provided, the buoyancy process will always be applied.

If the growth process is enabled, the application of the buoyancy module will be automatically managed.

## 6.4 Daily vertical migration

The `MigrationAction.java`

manages the daily migration of the particles. It is done by providing daytime and nighttime depths, and the timing of the sunset and sunrise.

If the `daytime_depth_file`

parameter is defined, it provides the depth of the particle during daytime. It is formatted as follows:

```
Age (day);Depth (m)
0.0;-20
3.0;-25
5.0;-30
8.0;-35
```

If this parameter is not found, a constant daytime depth, provided by the `daytime_depth`

parameter, is assumed.

Same thing for the nighttime depths, which can be set by either the `nighttime_depth_file`

or the `nighttime_depth`

parameters.

The sunset and sunrise hours are set by the `sunset`

and `sunrise`

parameters, which must have a `HH::mm`

format.

If the growth module is deactivated, the user must provide the minimum age (in days) at which the particle starts to migrate (`age_min`

parameter). If the growth module is activated, it manages the activation or deactivation of the daily migration.

When the target depth is greater than the total depth, the particle does not move.

## 6.5 Ontogenetic vertical migration

The ontogenetic migration module controls the migration to different habitats as a function of age. Its implementation in Ichthyop follows the CMS one. It uses the CMS configuration file (`cms_ovm_config_file`

parameter), which is formatted as follows:

```
nTime
nDepth
z1 z2 z3 z4 z5 z6 ... znDepth
t1 t2 t3 t4 t5 t6 ... tnTime
P1,1 P1,2 ... P1,nTime
P2,1 P2,2 ... P2,nTime
P3,1 P3,2 ... P3,nTime
...
PnDepth,1 PnDepth,2 ... PnDepth,nTime
```

The first line provides the number of time steps in the CMS file, the second line provides the number of vertical levels in the CMS file. The third line provides the depth values and the fourth lines provides the time step values.

The remaining lines provide the probability matrix \(P_{z, t}\).

The sum of the probability matrix along the depth dimension should equal 100.

At each time step, the index of the CMS time step, \(k\), is determined by comparing the simulation and CMS times as follows:

\[ t_{CMS}(k) < t \leq t_{CMS}(k + 1) \]

When the CMS time index changes, all the particles are randomly distributed on the vertical, following the probability distribution of the given CMS time. If the CMS time index remains unchanged, nothing is done.

## 6.6 Wind drift

The wind-drift is implemented in the `WindDriftFileAction.java`

class. This class requires that 2D (time, latitude, longitude) wind fields are provided. This is done by providing a `input_path`

and a `file_filter`

parameter, which specify the location and names of the wind files.

The user also provides `field_time`

, `wind_u`

, `wind_v`

, `longitude`

, `latitude`

parameters, which specify the names of the time, zonal wind, meridional wind, longitude and latitude variables in the NetCDF files.

The user also provides a `depth_application`

parameter, which specifies the depth at which the wind will impact the trajectories (only valid for 3D simulations), a `wind_factor`

(\(F\), multiplication factor), an `angle`

(\(\theta\)) and a `wind_convention`

parameter (\(\varepsilon\), +1 if convention is ocean-based, i.e. wind-to, -1 if convention is atmospheric based, i.e. wind-from).

The changes in particle longitude (\(\lambda\)) and latitude (\(\phi\)) is provided as follows:

\[ \Delta \lambda_0 = \frac{\Delta t \times U_W }{\frac{R \pi}{180} \times \cos(\frac{\pi \phi}{ 180})} \]

\[ \Delta \phi_0 = \frac{\Delta t \times V_W}{ \frac{R \pi}{180}} \]

\[ \Delta \lambda = \varepsilon \times F \times \left(\Delta \lambda_0 \times \cos\left(\frac{\theta \pi}{180}\right) - \Delta \phi_0 \times \sin\left(\frac{\theta \pi}{180}\right)\right) \]

\[ \Delta \phi = \varepsilon \times F \times \left(\Delta \lambda_0 \times \sin\left(\frac{\theta \pi}{180}\right) + \Delta \phi_0 \times \sin\left(\frac{\theta \pi}{180}\right)\right) \]

\(R\) is the Earth Radius and equals 6367.74 km. In the code, \(\dfrac{R \pi}{180}\), which is the distance in m of a 1 degree cell, is approximated to 111138 m

## 6.7 Random swimming

Ichthyop allows particles to randomly swim. This is achieved by using the `SwimmingAction.java`

. The velocity may vary with the age of the particle.

The user provides a CSV absolute velocity file (`velocity_file`

parameter), which must me formatted as follows:

```
Age (days);Speed (m/s)
0;0.1
5;0.2
15;0.3
```

The user also provides a boolean parameter (`constant_velocity`

) that specifies whether the velocity should remain as defined in the CSV file, or if the absolute velocity should be randomly selected as follows:

\[ \|U\| = \|U\|_{file} \times \kappa \]

with \(\kappa\) a random value in the \([0, 2]\) interval and \(\|U\|_{file}\) the velocity defined in the CSV file.

At each time-step, the zonal and meridonal velocities are defined as follows:

\[ U = \kappa' \varepsilon \|U\| \]

\[ V = \varepsilon' \sqrt{\|U\|^2 - U^2} \]

with \(\kappa'\) a random value between 0 and 1, and \(\varepsilon\) and \(\varepsilon'\) random values either equal to 1 or -1.

## 6.8 Wave drift

Ichthyop can take into account the effects of waves on the particles trajectories, following the Stokes drift equations of Stokes (2009):

\[ U_{S} = w \times k \times a^2 \times \exp\left(2 \times k \times z\right) \]

In Ichthyop, the user provides zonal and meridional wave stokes drift and the wave periods. The horizontal displacement of particles is computed as follows:

\[ \|U_{wave}\| = U_{wave}^2 + V_{wave}^2 \]

\[ \lambda_{wave} = \|U_{wave}\| \times T_{wave} \]

\[ k_{wave} = \dfrac{2 \pi}{\lambda_{wave}} \]

\[ \Delta X = F \times U_{cur} \times \Delta t \times \exp\left(2 \times k_{wave} \times z\right) \]

\[ \Delta Y = F \times V_{cur} \times \Delta t \times \exp\left(2 \times k_{wave} \times z\right) \]

with \(U_{wave}\) and \(V_{wave}\) the zonal and meridional stokes components, \(T_{wave}\) the wave period, \(U_{cur}\) and \(V_{cur}\) the zonal and meridional ocean current components, \(z\) the depth and \(F\) a multiplication factor provided by the user.

## 6.9 Coastal behaviour

### 6.9.1 Bouncing

In the bouncing mode, the particle will bounce on the coast. First, whether the bouncing occurs on a meridional or a zonal coastline is determined.

In case of a meridional coastline, as shown in Figure fig-bouncing, the calculation of the new position is performed as follows.

Let’s assume that the particle is at the position \((x, y)\) and is moved at the postion \((x + \Delta x, y + \Delta y)\). We suppose that

\[ \Delta y = \Delta y_1 + \Delta y_2, \tag{6.1}\]

where \(\Delta y_1\) is the meridional distance between the particle and the coastline, and \(\Delta y_2\) is the distance that the particle will spend on land.

In the bouncing mode, the position increment can be written as

\[ \Delta_{cor} y = \Delta y_1 - \Delta y_2 \tag{6.2}\]

By replacing \(\Delta y_2\) using Equation eq-bounc_1, we can write:

\[ \Delta_{cor} y = \Delta y_1 - (\Delta y - \Delta y_1) \]

\[ \Delta_{cor} y = 2 \Delta y_1 - \Delta y \]

## 6.10 Orientation

Active swimming has been implemented in Ichthyop following the work of Romain Chaput. Three active swimming behaviours have been implemented: the rheotaxis orientation (i.e. against the current), the cardinal orientation (i.e toward a given direction) and the reef orientation, i.e. orientation toward points of interests.

These three implementations involve the computation of a swimming velocity and direction. The former is common to all three methods, but the directions depend on the method considered.

### 6.10.1 Swimming velocity

The orientation processes all share common features. They both depend on a swimming velocity and random directions. The methods described below differ on the way the random directions are drafted.

Swimming velocity is computed following Staaterman, Paris, and Helgers (2012):

#|echo: false \[ V = V_{hatch} + (V_{settle} - V_{hatch}) ^ {\log(age) / \log(PLD)} \]

with \(V_{hatch}\) and \(V_{settle}\) the larval velocity at hatching and settle, \(A\) the age of the larva and \(PLD\) the transport duraction.

### 6.10.2 Von Mises distributions

Von Mises distribution is used in all three methods.The Von Mises distribution is given by:

\[ f(\theta, \mu, \kappa) = \dfrac {\exp(\kappa \cos(\theta - \mu))} {2 \pi I_{0}(\kappa)} \]

where \(I_{0}(\kappa)\) is the modified Bessel function of the first kind of order 0, \(\mu\) is angle where the distribution is centerred and \(\kappa\) is the concentration parameter. The distribution is as follows:

For computation purposes, all the Von Mises drafts performed in Ichthyop are done by using \(mu = 0\). The angles are thus centerred around 0. Then, the \(mu\) value is added.

\(\theta = 0\) is eastward, \(\theta = \frac{\pi}{2}\) is northward, etc.

### 6.10.3 Computation of displacement

Given a swimming velocity \(V\) and a direction \(\theta\), the larva displacement (in \(m\)) is computed as follows:

\[ \Delta X = V \times \cos(\theta) \times \Delta t \]

\[ \Delta Y = V \times \sin(\theta) \times \Delta t \]

with \(\Delta t\) the time step. Next, the corresponding change in longitude (\(\lambda\)) and latitude (\(\varphi\)) is computed as follows:

\[ \Delta \lambda = \dfrac{\Delta X}{111138 \times \cos{\varphi}} \]

\[ \Delta \varphi = \dfrac{\Delta Y}{111138 } \]

### 6.10.4 Cardinal orientation

In cardinal orientation, the user provides a fixed heading \(\theta_{card}\) and a fixed \(\kappa\) parameter. Then, at each time step, a new angle is randomly drafted following a Von Misses distribution \(f(\theta, \theta_{card}, \kappa)\).

```
import xarray as xr
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import os
from glob import glob
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
= 'card'
config
if os.path.isdir('ichthyop_output'):
= os.path.join('ichthyop_output', config, '*nc')
pattern else :
= os.path.join('..', '..', 'ichthyop_output', config, '*nc')
pattern
pattern
= glob(pattern)
filelist
filelist
= xr.open_mfdataset(filelist, decode_times=False)
data
data
# +
= data['lon'].values
lon = data['lat'].values
lat = data['mortality'].values
mort
= np.ma.masked_where(mort > 0, lon)
lon = np.ma.masked_where(mort > 0, lat)
lat = lon.shape
ntime, ndrifters
# +
= np.arange(ntime)
time = np.arange(ndrifters)
drifters
= np.meshgrid(drifters, time)
d2d, t2d
# +
plt.figure()
= ccrs.PlateCarree()
projin = ccrs.PlateCarree()
projout
= plt.axes(projection = projout)
ax =t2d, marker='.', transform=projin, s=0.5, cmap=mpl.colormaps['jet'])
ax.scatter(lon[:, :], lat[:, :], c= ax.add_feature(cfeature.LAND)
feat = ax.add_feature(cfeature.COASTLINE)
feat 49, 55.25, -13.13, -9.45], crs=projin) ax.set_extent([
```

### 6.10.5 Rheotaxis orientation

In the rheotaxis orientation method, the particles swim against the current. The user only provides a kappa parameter.

First, the angle of the current is computed as follows:

\[ \theta_{current} = \arctan2(V_{current}, U_{current}) \]

Then, the angle that the particle must follow is given by adding \(\pi\):

\[ \theta_{direction} = \theta_{current} + \pi \]

Finally, a random angle is picked up following a Von Mises distribution \(f(\theta, \theta_{direction}, \kappa_{reef})\)

(ref-rheo)=

```
import xarray as xr
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import os
from glob import glob
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
= 'rheo'
config
if os.path.isdir('ichthyop_output'):
= os.path.join('ichthyop_output', config, '*nc')
pattern else :
= os.path.join('..', '..', 'ichthyop_output', config, '*nc')
pattern
pattern
= glob(pattern)
filelist
filelist
= xr.open_mfdataset(filelist, decode_times=False)
data
data
# +
= data['lon'].values
lon = data['lat'].values
lat = data['mortality'].values
mort
= np.ma.masked_where(mort > 0, lon)
lon = np.ma.masked_where(mort > 0, lat)
lat = lon.shape
ntime, ndrifters
# +
= np.arange(ntime)
time = np.arange(ndrifters)
drifters
= np.meshgrid(drifters, time)
d2d, t2d
# +
plt.figure()
= ccrs.PlateCarree()
projin = ccrs.PlateCarree()
projout
= plt.axes(projection = projout)
ax =t2d, marker='.', transform=projin, s=0.5, cmap=mpl.colormaps['jet'])
ax.scatter(lon[:, :], lat[:, :], c= ax.add_feature(cfeature.LAND)
feat = ax.add_feature(cfeature.COASTLINE)
feat 49, 55.25, -13.13, -9.45], crs=projin) ax.set_extent([
```

### 6.10.6 Reef orientation

In the reef orientation method, the larva will target the closest target area (for instance coral reef). These areas are defined in an `XML`

zone file by a polygon and a zone-specific \(\kappa\) parameter. The user also provides the sensory detection threshold of the larva (maximum detection distance \(\beta\)).

If the distance between the particle and the barycenter of the closest reef (\(D\)) is below the detection thereshold \(\beta\), the larva will swim in the direction of the reef.

(ref-orientation)=

```
import numpy as np
import matplotlib.pyplot as plt
'font.size'] = 15
plt.rcParams[
= (10, 10))
plt.figure(figsize
= 0
xnew = 0
ynew
#draw point at orgin
= 'red', marker = 'o')
plt.plot(xnew, ynew, color '$P_{t}$', xy=(0 + 0.05, 0 - 0.07), xycoords='data', color='red')
plt.gca().annotate(
#draw circle
= 1.5
r = np.linspace(0 * np.pi, 2 * np.pi, 100 )
angles = r * np.cos(angles)
xs = r * np.sin(angles)
ys = 'k', ls='--', lw=0.5)
plt.plot(xs, ys, color
= np.pi / 6.
angle_old = 1.
rold = rold * np.cos(angle_old)
xold = rold * np.sin(angle_old)
yold
='o', color='blue')
plt.plot(xold, yold, marker'$P_{t - 1}$', xy=(xold + 0.05, yold), xycoords='data', color='blue')
plt.gca().annotate(
= np.pi + np.pi / 3.
angle_reef print(np.rad2deg(angle_reef))
= 1
rreef = rreef * np.cos(angle_reef)
xreef = rreef * np.sin(angle_reef)
yreef print(yreef)
='o', color='orange')
plt.plot(xreef, yreef, marker'$R$', xy=(xreef + 0.1, yreef), xycoords='data', color='orange')
plt.gca().annotate(
r'$D$', xy=(0.5*(xreef) + 0.02, 0.5*yreef), xycoords='data', color='orange', ha='left')
plt.gca().annotate(
='k', ls='--', lw=0.5)
plt.axvline(xnew, color='k', ls='--', lw=0.5)
plt.axhline(ynew, color
= np.polyfit([xold, xnew], [yold, ynew], deg=1)
p = np.linspace(xold, xold -2, 100)
xtemp ='black', ls='--')
plt.plot(xtemp, np.polyval(p, xtemp), color
= angle_old + np.pi
angle_current = np.linspace(0, angle_current, 100)
tmp_angle = 0.2
rtmp 0 + rtmp * np.cos(tmp_angle), 0 + rtmp * np.sin(tmp_angle), color='k', ls='--')
plt.plot(r'$\theta_{actual}$', xy=(xnew + 0.2, ynew+0.05), xycoords='data', color='k')
plt.gca().annotate(
='orange', ls='--')
plt.plot([xnew, xreef], [ynew, yreef], color= angle_reef
angle_current = np.linspace(0, angle_current, 100)
tmp_angle = 0.3
rtmp 0 + rtmp * np.cos(tmp_angle), 0 + rtmp * np.sin(tmp_angle), color='orange', ls='--')
plt.plot(r'$\theta_{reef}$', xy=(xnew - 0.3, ynew+0.1), xycoords='data', color='orange',ha='right')
plt.gca().annotate(
= angle_old + np.pi
angle_current = np.linspace(angle_current, angle_reef, 100)
tmp_angle = 0.4
rtmp 0 + rtmp * np.cos(tmp_angle), 0 + rtmp * np.sin(tmp_angle), color='plum', ls='--')
plt.plot(r'$\theta_{turning}$', xy=(-0.43, -0.34), xycoords='data', color='plum')
plt.gca().annotate(
= 0.05
off - off, xold + off)
plt.xlim(xreef - off, yold + off)
plt.ylim(yreef 'equal')
plt.gca().set_aspect('off')
plt.axis( plt.show()
```

```
239.99999999999997
-0.8660254037844384
```

First, the angle of the current trajectory, \(\theta_{actual}\), is computed by using the particle position at the previous time step (blue point) and the actual position (red point).

\[ \Delta_X = (X_{t - 1} - X_{t}) \]

\[ \Delta_Y = (Y_{t - 1} - Y_{t}) \]

\[ \theta_{actual} = \arctan2(\Delta Y, \Delta X) + \pi \]

The direction toward the reef, \(\theta_{reef}\) is also computed.

\[ \Delta_X = (X_{reef} - X_{t}) \]

\[ \Delta_Y = (Y_{reef} - Y_{t}) \]

\[ \theta_{reef} = \arctan2(\Delta Y, \Delta X) \]

The angles are computed in the \((X, Y)\) space. Therefore, longitude and latitude coordinates are converted in \((X, Y)\) using the `latlon2xy`

Dataset methods.

The turning angle \(\theta_{turning}\) is given by:

\[ \theta_{turning} = \theta_{reef} - \theta_{actual} \]

The turning angle is then ponderated by the ratio of the distance from the reef to the detection threshold as follows:

\[ \theta_{ponderated} = \left(1 - \dfrac{D}{\beta}\right) \theta_{turning} \]

\[ \theta_{ponderated} = \left(1 - \dfrac{D}{\beta}\right) \left(\theta_{reef} - \theta_{actual}\right) \]

Therefore, the closest to the reef, the strongest the turning angle.

Then, a random angle is picked up following a Von Mises distribution \(f(\theta, \theta_{ponderated}, \kappa_{reef})\)

An example of a trajectory is provided below. In this case, two target destinations are provided (black boxes). The same \(\kappa\) value was used for both ares (1.2) and the \(\beta\) parameter has been set equal to 3 km.

(ref-orientation-2)=

```
import xarray as xr
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import os
from glob import glob
import matplotlib.pyplot as plt
import numpy as np
import matplotlib as mpl
= 'reef'
config
if os.path.isdir('ichthyop_output'):
= os.path.join('ichthyop_output', config, '*nc')
pattern else :
= os.path.join('..', '..', 'ichthyop_output', config, '*nc')
pattern
pattern
= glob(pattern)
filelist
filelist
= xr.open_mfdataset(filelist, decode_times=False)
data
data
# +
= data['lon'].values
lon = data['lat'].values
lat = data['mortality'].values
mort
= np.ma.masked_where(mort > 0, lon)
lon = np.ma.masked_where(mort > 0, lat)
lat = lon.shape
ntime, ndrifters
# +
= np.arange(ntime)
time = np.arange(ndrifters)
drifters
= np.meshgrid(drifters, time)
d2d, t2d
# +
plt.figure()
= ccrs.PlateCarree()
projin = ccrs.PlateCarree()
projout
= plt.axes(projection = projout)
ax =t2d, marker='.', transform=projin, s=0.5, cmap=mpl.colormaps['jet'])
ax.scatter(lon[:, :], lat[:, :], c= ax.add_feature(cfeature.LAND)
feat = ax.add_feature(cfeature.COASTLINE)
feat = np.array([51.625, 52.625, 52.625,51.625, 51.625])
xp = np.array([-1.179878E1, -1.179878E1, -1.079878E1, -1.079878E1, -1.179878E1])
yp =projin, color='k', ls='--')
ax.plot(xp, yp, transform= np.array([51.625, 52.625 - 0.5, 52.625 - 0.5,51.625, 51.625]) - 1
xp = np.array([-1.179878E1 + 0.5, -1.179878E1 + 0.5, -1.079878E1, -1.079878E1, -1.179878E1 + 0.5]) - 0.25
yp =projin, color='k', ls='--')
ax.plot(xp, yp, transform49, 55.25, -13.13, -9.45], crs=projin) ax.set_extent([
```

*Mar. Ecol. Prog. Ser*1 (9).

*Environmental Modelling & Software*23 (9): 1210–14. https://doi.org/https://doi.org/10.1016/j.envsoft.2008.02.005.

*Fisheries Oceanography*12 (3): 170–84.

*Journal of Theoretical Biology*304 (July): 188–96. https://doi.org/10.1016/j.jtbi.2012.03.016.

*Mathematical and Physical Papers*, 1:197–229. Cambridge Library Collection - Mathematics. Cambridge University Press. https://doi.org/10.1017/CBO9780511702242.013.

*Progress in Oceanography*156: 78–90. https://doi.org/https://doi.org/10.1016/j.pocean.2017.06.005.