Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 119 additions & 18 deletions docs/user_guide/examples/tutorial_manipulating_field_data.ipynb

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure why this diff looks so large. The only change is adding the new section "Looping field data and overriding the time dimension" near the top

Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,121 @@
"id": "1",
"metadata": {},
"source": [
"Because Parcels `Field` objects are built on top of `xarray` DataArrays, you can leverage the powerful data manipulation capabilities of `xarray` to preprocess or modify your field data before using it in particle simulations. This tutorial provides some examples of how to leverage that power."
"Because Parcels `Field` objects are built on top of `xarray` DataArrays, you can leverage the powerful data manipulation capabilities of `xarray` to preprocess or modify your field data before using it in particle simulations. This tutorial provides some common examples of how to leverage that power - however we highly recommend also reading the Xarray documentation!\n",
"\n",
"Let's start with some imports."
]
},
{
"cell_type": "markdown",
"cell_type": "code",
"execution_count": null,
"id": "2",
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import xarray as xr\n",
"\n",
"import parcels\n",
"import parcels.tutorial"
]
},
{
"cell_type": "markdown",
"id": "3",
"metadata": {},
"source": [
"## Looping field data and overriding the time dimension\n",
"\n",
"Sometimes we want to loop field data (e.g., use one year of data again ten times), or we want to completely override the time dimension.\n",
"\n",
"In previous versions of Parcels (pre version 4) this was done via Parcels function parameters `timestamps` and `time_periodic`. In this version of Parcels, we simply just manipulate the Xarray objects directly before passing the objects to Parcels."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4",
"metadata": {},
"outputs": [],
"source": [
"ds_fields = parcels.tutorial.open_dataset(\n",
" \"CopernicusMarine_data_for_Argo_tutorial/data\"\n",
")\n",
"ds_fields"
]
},
{
"cell_type": "markdown",
"id": "5",
"metadata": {},
"source": [
"Here we're dealing with daily data for from 2024-01-01 to 2024-02-01 (32 observations in total).\n",
"\n",
"Let's loop this data for a total of 90 days."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6",
"metadata": {},
"outputs": [],
"source": [
"N_TIME = ds_fields.time.size\n",
"N_TIME_TARGET = 90\n",
"\n",
"time_indices = np.arange(N_TIME_TARGET) % N_TIME\n",
"new_time_coordinate = np.arange(\n",
" np.datetime64(\"2000-01-01\"),\n",
" np.datetime64(\"2000-01-01\") + N_TIME_TARGET * np.timedelta64(1, \"D\"),\n",
" np.timedelta64(1, \"D\"),\n",
").astype(\"datetime64[ns]\")\n",
"print(time_indices)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7",
"metadata": {},
"outputs": [],
"source": [
"ds_periodic = ds_fields.isel(time=time_indices)\n",
"ds_periodic[\"time\"] = new_time_coordinate\n",
"\n",
"# Now we have our periodic Dataset, let's take a look at the U velocity at a given position\n",
"# to verify\n",
"ds_periodic[\"uo\"].isel(depth=0, latitude=0, longitude=0).plot()"
]
},
{
"cell_type": "markdown",
"id": "8",
"metadata": {},
"source": [
"From this example, its easy to see how we can completely override the time dimension. For example, by adding a linear offset to the coordinates to make the data for February (and the first few days of March)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9",
"metadata": {},
"outputs": [],
"source": [
"new_time_coordinate = ds_fields.time.values + np.timedelta64(31, \"D\")\n",
"\n",
"ds_offset = ds_fields.copy()\n",
"ds_offset[\"time\"] = new_time_coordinate\n",
"ds_offset"
]
},
{
"cell_type": "markdown",
"id": "10",
"metadata": {},
"source": [
"## Summing Fields\n",
"In some applications, you may want to sum multiple fields together to create a combined effect on particle movement. For example, you might want to combine ocean currents with wind-driven surface drift. This tutorial demonstrates how to sum multiple fields in Parcels and visualize the resulting particle trajectories.\n",
Expand All @@ -34,17 +142,10 @@
{
"cell_type": "code",
"execution_count": null,
"id": "3",
"id": "11",
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"import numpy as np\n",
"import xarray as xr\n",
"\n",
"import parcels\n",
"import parcels.tutorial\n",
"\n",
"# Load the CopernicusMarine data in the Agulhas region from the example_datasets\n",
"ds_fields = parcels.tutorial.open_dataset(\n",
" \"CopernicusMarine_data_for_Argo_tutorial/data\"\n",
Expand All @@ -67,7 +168,7 @@
},
{
"cell_type": "markdown",
"id": "4",
"id": "12",
"metadata": {},
"source": [
"Now here comes the trick: we can simply sum the fields together using `xarray` operations"
Expand All @@ -76,7 +177,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "5",
"id": "13",
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -87,7 +188,7 @@
},
{
"cell_type": "markdown",
"id": "6",
"id": "14",
"metadata": {},
"source": [
"```{note}\n",
Expand All @@ -97,7 +198,7 @@
},
{
"cell_type": "markdown",
"id": "7",
"id": "15",
"metadata": {},
"source": [
"We can then run the same simulation as in the [Kernel loop explanation tutorial](explanation_kernelloop.md), but now using the combined fields. We only need the default advection kernel now, since the effects of both currents and winds are already included in the summed fields."
Expand All @@ -106,7 +207,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "8",
"id": "16",
"metadata": {
"tags": [
"hide-output"
Expand Down Expand Up @@ -143,7 +244,7 @@
},
{
"cell_type": "markdown",
"id": "9",
"id": "17",
"metadata": {},
"source": [
"We can then plot the trajectories, and confirm that they particles move the same as in the [Kernel loop explanation tutorial](explanation_kernelloop.md), where we combined the effects of currents and winds using two separate kernels."
Expand All @@ -152,7 +253,7 @@
{
"cell_type": "code",
"execution_count": null,
"id": "10",
"id": "18",
"metadata": {},
"outputs": [],
"source": [
Expand All @@ -167,7 +268,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Parcels:test (3.14.6)",
"display_name": "docs",
"language": "python",
"name": "python3"
},
Expand Down
8 changes: 8 additions & 0 deletions docs/user_guide/v4-migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,14 @@ Use <code>Particle.add_variables()</code>, which also takes a list of <code>Vari
</div>
<hr class="migration-divider" />

<div class="migration-bubble migration-change">
Parameters <code>indices</code>, <code>timestamps</code>, and <code>time_periodic</code> removed from <code>FieldSet</code> constructors.
</div>
<div class="migration-bubble migration-how">
Simply manipulate the datasets with Xarray to the same effect before passing them to Parcels.
</div>
<hr class="migration-divider" />

</div>

## ParticleSet
Expand Down