Skip to content

Commit 03640a4

Browse files
Renaming time to t (#2732)
* Changing a few last lon/lat to x/y * Changing time to t in _core and tests * Changing time to t in tutorials * Fixing particles.time in explanations
1 parent 4485d53 commit 03640a4

32 files changed

Lines changed: 319 additions & 323 deletions

docs/getting_started/explanation_concepts.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Here, we will explain the most important classes and functions. This overview ca
1313
A Parcels simulation is generally built up from four different components:
1414

1515
1. [**FieldSet**](#1-fieldset). The input dataset of gridded fields (e.g. ocean current velocity, temperature) in which virtual particles are defined.
16-
2. [**ParticleSet**](#2-particleset). The dataset of virtual particles. These always contain time, z, y, and x, for which initial values must be defined. The ParticleSet may also contain other, custom variables.
16+
2. [**ParticleSet**](#2-particleset). The dataset of virtual particles. These always contain t, z, y, and x, for which initial values must be defined. The ParticleSet may also contain other, custom variables.
1717
3. [**Kernels**](#3-kernels). Kernels perform some specific operation on the particles every time step (e.g. advect the particles with the three-dimensional flow; or interpolate the temperature field to the particle location).
1818
4. [**Execute**](#4-execute). Execute the simulation. The core method which integrates the operations defined in Kernels for a given runtime and timestep, and writes output to a ParticleFile.
1919

@@ -82,16 +82,16 @@ Once the environment has a `parcels.FieldSet` object, you can start defining you
8282

8383
1. The `parcels.FieldSet` object in which the particles will be released.
8484
2. The type of `parcels.Particle`: A default `Particle` or a custom `Particle`-type with additional `Variable`s (see the [custom kernel example](custom-kernel)).
85-
3. Initial conditions for each `Variable` defined in the `Particle`, most notably the release coordinates of `time`, `z`, `y` and `x`.
85+
3. Initial conditions for each `Variable` defined in the `Particle`, most notably the release coordinates of `t`, `z`, `y` and `x`.
8686

8787
```python
88-
time = np.array([0])
88+
t = np.array([0])
8989
z = np.array([0])
9090
y = np.array([0])
9191
x = np.array([0])
9292

9393
# Create a ParticleSet
94-
pset = parcels.ParticleSet(fieldset=fieldset, pclass=parcels.Particle, time=time, z=z, y=y, x=x)
94+
pset = parcels.ParticleSet(fieldset=fieldset, pclass=parcels.Particle, t=t, z=z, y=y, x=x)
9595
```
9696

9797
```{admonition} 🖥️ Learn more about how to create ParticleSets
@@ -126,7 +126,7 @@ def AdvectionEE(particles, fieldset):
126126
Basic kernels are included in Parcels to compute advection and diffusion. The standard advection kernel is `parcels.kernels.AdvectionRK2`, a [second-order Runge-Kutta integrator](https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods#The_Runge%E2%80%93Kutta_method) of the advection function.
127127

128128
```{warning}
129-
It is advised _not_ to update the particle coordinates (`particles.time`, `particles.z`, `particles.y`, or `particles.x`) directly within a Kernel, as that can negatively interfere with the way that particle movements by different kernels are vectorially added. Use a change in the coordinates: `particles.dy`, `particles.dx` and/or `particles.dz`. Read the [kernel loop tutorial](../user_guide/examples/explanation_kernelloop.md) to understand why.
129+
It is advised _not_ to update the particle coordinates (`particles.t`, `particles.z`, `particles.y`, or `particles.x`) directly within a Kernel, as that can negatively interfere with the way that particle movements by different kernels are vectorially added. Use a change in the coordinates: `particles.dy`, `particles.dx` and/or `particles.dz`. Read the [kernel loop tutorial](../user_guide/examples/explanation_kernelloop.md) to understand why.
130130
```
131131

132132
(custom-kernel)=
@@ -186,7 +186,7 @@ pset.execute(kernels=kernels, dt=dt, runtime=runtime)
186186

187187
### Output
188188

189-
To analyse the particle data generated in the simulation, we need to define a `parcels.ParticleFile` and add it as an argument to `parcels.ParticleSet.execute()`. The output will be written in a [parquet format](https://parquet.apache.org/), which can be opened as a `polars.DataFrame`. The dataset will contain the particle data with at least `time`, `z`, `y` and `x`, for each particle at timesteps defined by the `outputdt` argument.
189+
To analyse the particle data generated in the simulation, we need to define a `parcels.ParticleFile` and add it as an argument to `parcels.ParticleSet.execute()`. The output will be written in a [parquet format](https://parquet.apache.org/), which can be opened as a `polars.DataFrame`. The dataset will contain the particle data with at least `t`, `z`, `y` and `x`, for each particle at timesteps defined by the `outputdt` argument.
190190

191191
There are many ways to analyze particle output, and although we provide [a short tutorial to get started](./tutorial_output.ipynb), we recommend writing your own analysis code and checking out [related Lagrangian analysis projects in our community page](../community/index.md#analysis-code).
192192

docs/getting_started/tutorial_output.ipynb

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
"time = ds_fields.time.values[0] + np.arange(0, npart) * np.timedelta64(2, \"h\")\n",
8181
"\n",
8282
"pset = parcels.ParticleSet(\n",
83-
" fieldset=fieldset, pclass=parcels.Particle, x=lon, y=lat, z=z, time=time\n",
83+
" fieldset=fieldset, pclass=parcels.Particle, x=lon, y=lat, z=z, t=time\n",
8484
")\n",
8585
"\n",
8686
"output_file = parcels.ParticleFile(\"output.parquet\", outputdt=np.timedelta64(2, \"h\"))"
@@ -194,7 +194,7 @@
194194
"cell_type": "markdown",
195195
"metadata": {},
196196
"source": [
197-
"As you may have noticed above, the `time` is shown as a `float64` (in seconds) in `df_polars`. That is because `polars.read_parquet` does not automatically convert the cftime. To handle this, we also provide a helper function `parcels.read_particlefile` to read ParticleFiles, which does automatically convert the cftime. "
197+
"As you may have noticed above, the `t` is shown as a `float64` (in seconds) in `df_polars`. That is because `polars.read_parquet` does not automatically convert the cftime. To handle this, we also provide a helper function `parcels.read_particlefile` to read ParticleFiles, which does automatically convert the cftime. "
198198
]
199199
},
200200
{
@@ -226,7 +226,7 @@
226226
"source": [
227227
"for traj in df_particles.partition_by(\"particle_id\", maintain_order=True):\n",
228228
" time_origin = pd.Timestamp(fieldset.time_interval.left).to_pydatetime()\n",
229-
" time_in_hour = (traj[\"time\"] - time_origin).dt.total_hours()\n",
229+
" time_in_hour = (traj[\"t\"] - time_origin).dt.total_hours()\n",
230230
" traj_id = traj[\"particle_id\"][0]\n",
231231
" print(f\"Particle {traj_id}: \" + \"\".join(f\"{int(t):2d} \" for t in time_in_hour))"
232232
]
@@ -303,7 +303,7 @@
303303
"source": [
304304
"time_step = np.timedelta64(18, \"h\")\n",
305305
"time_to_plot = fieldset.time_interval.left + time_step\n",
306-
"particles = df_particles.filter(pl.col(\"time\") == pl.lit(time_to_plot))\n",
306+
"particles = df_particles.filter(pl.col(\"t\") == pl.lit(time_to_plot))\n",
307307
"\n",
308308
"fig, ax = plt.subplots(figsize=(5, 3))\n",
309309
"ax.plot(particles[\"x\"], particles[\"y\"], \"o\")\n",
@@ -327,7 +327,7 @@
327327
"source": [
328328
"time_step = np.timedelta64(18, \"h\")\n",
329329
"particles = df_particles.filter(\n",
330-
" (pl.col(\"time\") - pl.col(\"time\").min().over(\"particle_id\")) == pl.lit(time_step)\n",
330+
" (pl.col(\"t\") - pl.col(\"t\").min().over(\"particle_id\")) == pl.lit(time_step)\n",
331331
")\n",
332332
"\n",
333333
"fig, ax = plt.subplots(figsize=(5, 3))\n",
@@ -355,9 +355,9 @@
355355
" distance = np.sqrt(\n",
356356
" (traj[\"x\"] - traj[\"x\"][0]) ** 2 + (traj[\"y\"] - traj[\"y\"][0]) ** 2\n",
357357
" )\n",
358-
" ax[0].plot(traj[\"time\"], distance, \".-\", label=f\"P{traj['particle_id'][0]}\")\n",
358+
" ax[0].plot(traj[\"t\"], distance, \".-\", label=f\"P{traj['particle_id'][0]}\")\n",
359359
"\n",
360-
" rel_time = (traj[\"time\"] - traj[\"time\"][0]).dt.total_hours()\n",
360+
" rel_time = (traj[\"t\"] - traj[\"t\"][0]).dt.total_hours()\n",
361361
" ax[1].plot(rel_time, distance, \".-\", label=f\"P{traj['particle_id'][0]}\")\n",
362362
"\n",
363363
"ax[0].set_xlabel(\"Date\")\n",
@@ -410,8 +410,8 @@
410410
"time_step = np.timedelta64(2, \"h\") # time step for animation frames\n",
411411
"\n",
412412
"timerange = np.arange(\n",
413-
" np.nanmin(df_particles[\"time\"]),\n",
414-
" np.nanmax(df_particles[\"time\"]) + time_step,\n",
413+
" np.nanmin(df_particles[\"t\"]),\n",
414+
" np.nanmax(df_particles[\"t\"]) + time_step,\n",
415415
" time_step,\n",
416416
")\n",
417417
"\n",
@@ -436,7 +436,7 @@
436436
"ax.add_feature(cfeature.LAND)\n",
437437
"\n",
438438
"# --> plot first timestep\n",
439-
"particles = df_particles.filter(pl.col(\"time\") == pl.lit(timerange[0]))\n",
439+
"particles = df_particles.filter(pl.col(\"t\") == pl.lit(timerange[0]))\n",
440440
"scatter = ax.scatter(\n",
441441
" particles[\"x\"],\n",
442442
" particles[\"y\"],\n",
@@ -460,7 +460,7 @@
460460
" title.set_text(f\"Particles at t = {t_str}\")\n",
461461
"\n",
462462
" # Find particles at current time\n",
463-
" particles = df_particles.filter(pl.col(\"time\") == pl.lit(timerange[i]))\n",
463+
" particles = df_particles.filter(pl.col(\"t\") == pl.lit(timerange[i]))\n",
464464
"\n",
465465
" if len(particles) > 0:\n",
466466
" scatter.set_offsets(np.c_[particles[\"x\"], particles[\"y\"]])\n",
@@ -475,8 +475,8 @@
475475
" for traj in particles[\"particle_id\"].unique():\n",
476476
" traj_trail = df_particles.filter(\n",
477477
" (pl.col(\"particle_id\") == traj)\n",
478-
" & (pl.col(\"time\") >= pl.lit(timerange[max(0, i - trail_length)]))\n",
479-
" & (pl.col(\"time\") <= pl.lit(timerange[i]))\n",
478+
" & (pl.col(\"t\") >= pl.lit(timerange[max(0, i - trail_length)]))\n",
479+
" & (pl.col(\"t\") <= pl.lit(timerange[i]))\n",
480480
" )\n",
481481
" if len(traj_trail) > 1:\n",
482482
" (trail,) = ax.plot(\n",

docs/getting_started/tutorial_quickstart.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ the virtual particles for which we will calculate the trajectories.
7373

7474
We need to create a {py:obj}`parcels.ParticleSet` object with the particles' initial time and position. The `parcels.ParticleSet`
7575
object also needs to know about the `FieldSet` in which the particles "live". Finally, we need to specify the type of
76-
{py:obj}`parcels.ParticleClass` we want to use. The default particles have `time`, `z`, `y`, and `x`, but you can easily add
76+
{py:obj}`parcels.ParticleClass` we want to use. The default particles have `t`, `z`, `y`, and `x`, but you can easily add
7777
other {py:obj}`parcels.Variable`s such as size, temperature, or age to create your own particles to mimic plastic or an [ARGO float](../user_guide/examples/tutorial_Argofloats.ipynb).
7878

7979
```{code-cell}
@@ -86,7 +86,7 @@ time = np.repeat(ds_fields.time.values[0], npart) # at initial time of input dat
8686
z = np.repeat(ds_fields.depth.values[0], npart) # at the first depth (surface)
8787
8888
pset = parcels.ParticleSet(
89-
fieldset=fieldset, pclass=parcels.Particle, time=time, z=z, y=lat, x=lon
89+
fieldset=fieldset, pclass=parcels.Particle, t=time, z=z, y=lat, x=lon
9090
)
9191
```
9292

@@ -168,7 +168,7 @@ Let's verify that Parcels has computed the advection of the virtual particles!
168168
import matplotlib.pyplot as plt
169169
170170
# plot positions and color particles by time
171-
scatter = plt.scatter(df['x'], df['y'], c=df['time'])
171+
scatter = plt.scatter(df['x'], df['y'], c=df['t'])
172172
plt.scatter(df['x'][:npart], df['y'][:npart], facecolors="none", edgecolors='r') # starting positions
173173
plt.scatter(lon, lat, facecolors="none", edgecolors='r') # starting positions
174174
plt.xlim(31,33)
@@ -211,8 +211,8 @@ When we check the output, we can see that the particles have returned to their o
211211
```{code-cell}
212212
df_back = parcels.read_particlefile("output-backwards.parquet")
213213
214-
scatter = plt.scatter(df_back['x'], df_back['y'], c=df_back['time'])
215-
particles_at_max_time = df_back.filter(pl.col("time") == df_back["time"].max())
214+
scatter = plt.scatter(df_back['x'], df_back['y'], c=df_back['t'])
215+
particles_at_max_time = df_back.filter(pl.col("t") == df_back["t"].max())
216216
plt.scatter(particles_at_max_time['x'], particles_at_max_time['y'], facecolors="none", edgecolors='r') # starting positions
217217
plt.xlabel("Longitude [deg E]")
218218
plt.xlim(31,33)
@@ -226,7 +226,7 @@ Using Euler forward advection, the final positions are equal to the original pos
226226

227227
```{code-cell}
228228
# testing that final location == original location
229-
particles_at_min_time = df_back.filter(pl.col("time") == df_back["time"].min())
229+
particles_at_min_time = df_back.filter(pl.col("t") == df_back["t"].min())
230230
np.testing.assert_almost_equal(particles_at_min_time["y"], lat, 2)
231231
np.testing.assert_almost_equal(particles_at_min_time['x'], lon, 2)
232232
```

docs/user_guide/examples/explanation_interpolation.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ particles.temperature = fieldset.temperature[particles]
1414
````{note}
1515
The statement above is shorthand for
1616
```python
17-
particles.temperature = fieldset.temperature[particles.time, particles.z, particles.y, particles.x, particles]
17+
particles.temperature = fieldset.temperature[particles.t, particles.z, particles.y, particles.x, particles]
1818
```
1919
where the `particles` argument at the end provides the grid search algorithm with a first guess for the element indices to interpolate on.
2020
2121
If you want to sample at a different location, or time, that is not necessarily close to the particles location, you can use
2222
```python
23-
particles.temperature = fieldset.temperature[time, z, y, x]
23+
particles.temperature = fieldset.temperature[t, z, y, x]
2424
```
2525
but this could be slower for curvilinear and unstructured Grids because the entire grid needs to be searched.
2626
````
@@ -53,7 +53,7 @@ If we want to create a custom interpolation method, we need to look at the inter
5353
The `particle_positions` dictionary contains:
5454

5555
```
56-
particle_positions = {"time", time, "z", z, "y", y, "x", x}
56+
particle_positions = {"t", t, "z", z, "y", y, "x", x}
5757
```
5858

5959
For structured (`X`) grids, the `grid_positions` dictionary contains:
@@ -63,7 +63,7 @@ grid_positions = {
6363
"T": {"index": ti, "bcoord": tau},
6464
"Z": {"index": zi, "bcoord": zeta},
6565
"Y": {"index": yi, "bcoord": eta},
66-
"X": {"index": xi, "bcoord", xsi},
66+
"X": {"index": xi, "bcoord": xsi},
6767
}
6868
```
6969

docs/user_guide/examples/tutorial_Argofloats.ipynb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
"\n",
6464
" # Phase 3: Rising with vertical_speed until at surface\n",
6565
" ptcls3.dz -= vertical_speed * ptcls3.dt\n",
66-
" ptcls3.temp = fieldset.thetao[ptcls3.time, ptcls3.z, ptcls3.y, ptcls3.x]\n",
66+
" ptcls3.temp = fieldset.thetao[ptcls3.t, ptcls3.z, ptcls3.y, ptcls3.x]\n",
6767
" next_phase = ptcls3.z + ptcls3.dz <= mindepth\n",
6868
" ptcls3.cycle_phase[next_phase] = 4\n",
6969
" ptcls3.dz[next_phase] = mindepth - ptcls3.z[next_phase] # avoid overshoot\n",
@@ -183,8 +183,8 @@
183183
"\n",
184184
"fig = plt.figure(figsize=(13, 6))\n",
185185
"ax = plt.axes()\n",
186-
"ax.plot(df[\"time\"], df[\"z\"], color=\"gray\")\n",
187-
"cb = ax.scatter(df[\"time\"], df[\"z\"], c=df[\"temp\"], s=20, marker=\"o\", zorder=2)\n",
186+
"ax.plot(df[\"t\"], df[\"z\"], color=\"gray\")\n",
187+
"cb = ax.scatter(df[\"t\"], df[\"z\"], c=df[\"temp\"], s=20, marker=\"o\", zorder=2)\n",
188188
"ax.set_xlabel(\"Time [days]\")\n",
189189
"ax.set_ylabel(\"Depth (m)\")\n",
190190
"ax.invert_yaxis()\n",

docs/user_guide/examples/tutorial_croco_3D.ipynb

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,8 @@
265265
"```python\n",
266266
"def SampleTempCroco(particles, fieldset):\n",
267267
" \"\"\"Sample temperature field on a CROCO sigma grid by first converting z to sigma levels.\"\"\"\n",
268-
" sigma = convert_z_to_sigma_croco(fieldset, particles.time, particles.z, particles.y, particles.x, particles)\n",
269-
" particles.temp = fieldset.T[particles.time, sigma, particles.y, particles.x, particles]"
268+
" sigma = convert_z_to_sigma_croco(fieldset, particles.t, particles.z, particles.y, particles.x, particles)\n",
269+
" particles.temp = fieldset.T[particles.t, sigma, particles.y, particles.x, particles]"
270270
]
271271
},
272272
{
@@ -278,14 +278,14 @@
278278
"In particular, the following algorithm is used (note that the RK4 version is slightly more complex than this Euler-Forward version, but the idea is identical). Also note that the vertical velocity is linearly interpolated here, which gives much better results than the default C-grid interpolation.\n",
279279
"\n",
280280
"```python\n",
281-
"sigma = particles.z / fieldset.h[particles.time, 0, particles.y, particles.x]\n",
281+
"sigma = particles.z / fieldset.h[particles.t, 0, particles.y, particles.x]\n",
282282
"\n",
283-
"sigma_levels = convert_z_to_sigma_croco(fieldset, particles.time, particles.z, particles.y, particles.x, particles)\n",
284-
"(u, v) = fieldset.UV[time, sigma_levels, particles.y, particles.x, particles]\n",
285-
"w = fieldset.W[time, sigma_levels, particles.y, particles.x, particles]\n",
283+
"sigma_levels = convert_z_to_sigma_croco(fieldset, particles.t, particles.z, particles.y, particles.x, particles)\n",
284+
"(u, v) = fieldset.UV[particles.t, sigma_levels, particles.y, particles.x, particles]\n",
285+
"w = fieldset.W[particles.t, sigma_levels, particles.y, particles.x, particles]\n",
286286
"\n",
287287
"# scaling the w with the sigma level of the particle\n",
288-
"w_sigma = w * sigma / fieldset.h[particles.time, 0, particles.y, particles.x, particles]\n",
288+
"w_sigma = w * sigma / fieldset.h[particles.t, 0, particles.y, particles.x, particles]\n",
289289
"\n",
290290
"x_new = particles.x + u*particles.dt\n",
291291
"y_new = particles.y + v*particles.dt\n",
@@ -294,7 +294,7 @@
294294
"sigma_new = sigma + w_sigma*particles.dt \n",
295295
"\n",
296296
"# converting back from sigma to z, at _new_ location\n",
297-
"z_new = sigma_new * fieldset.h[particles.time, 0, y_new, x_new, particles]\n",
297+
"z_new = sigma_new * fieldset.h[particles.t, 0, y_new, x_new, particles]\n",
298298
"```"
299299
]
300300
}

0 commit comments

Comments
 (0)