Skip to content

Commit f5d28e2

Browse files
committed
xarray illustrating examples
1 parent 8174e4e commit f5d28e2

File tree

5 files changed

+224
-1
lines changed

5 files changed

+224
-1
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,5 @@ venv.bak/
115115

116116
/art
117117
docs/source/generated/
118-
docs/source/auto_examples/
118+
docs/source/auto_examples/
119+
*.nc

docs/source/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@
147147
'../../examples/utils',
148148
'../../examples/statistics',
149149
'../../examples/simulations',
150+
'../../examples/xarray'
150151
]),
151152
# 'thumbnail_size': (100, 100),
152153
}

examples/xarray/README.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Xarray
2+
------
3+
4+
As Frites is entirely written arround Xarray ouput format, this set of examples illustrates how to work with xarray.
5+
6+
.. contents:: Contents
7+
:local:
8+
:depth: 2

examples/xarray/plot_xr_export.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
"""
2+
Xarray : Saving the results
3+
===========================
4+
5+
This example illustrates how to export and load your results. In details, we
6+
are going to show how to save and reload a single DataArray such as a Dataset.
7+
"""
8+
import numpy as np
9+
import xarray as xr
10+
import pandas as pd
11+
12+
###############################################################################
13+
# Simulate data
14+
# -------------
15+
#
16+
# lets start by creating two random spatio-temporal arrays
17+
18+
n_times = 30
19+
n_roi = 7
20+
times_vec = np.linspace(-1, 1, n_times)
21+
roi_vec = np.array([f"roi_{k}" for k in range(n_roi)])
22+
23+
# xarray.DataArray conversion
24+
arr_1 = xr.DataArray(np.random.rand(n_times, n_roi), dims=('times', 'roi'),
25+
coords=(times_vec, roi_vec))
26+
arr_2 = xr.DataArray(np.random.rand(n_times, n_roi), dims=('times', 'roi'),
27+
coords=(times_vec, roi_vec))
28+
29+
# just add a few attributes to each array
30+
arr_1.attrs['desc'] = "This is my first array"
31+
arr_1.attrs['sf'] = 1024.
32+
arr_2.attrs['desc'] = "This is my second array"
33+
arr_2.attrs['sf'] = 512.
34+
35+
# note that you can also concatenate DataArray
36+
arr_cat = xr.concat([arr_1, arr_2], 'roi')
37+
38+
###############################################################################
39+
# Export and load a single DataArray
40+
# ----------------------------------
41+
#
42+
# now we're going to save a single array and then reload it
43+
44+
# export a single array
45+
arr_1.to_netcdf("first_array.nc")
46+
47+
# delete it
48+
del arr_1
49+
50+
# reload it
51+
arr_1 = xr.load_dataarray("first_array.nc")
52+
print(arr_1)
53+
54+
###############################################################################
55+
# Export and load multiple DataArrays
56+
# -----------------------------------
57+
#
58+
# it's also possible to export and reload multiple DataArrays at once. To do
59+
# it, you can use a Dataset which is a container of DataArrays
60+
61+
# create a dataset
62+
dat = xr.Dataset({'first': arr_1, 'second': arr_2})
63+
64+
# you can also slice the dataset and also add attributes to it
65+
dat.attrs['desc'] = 'This is my dataset'
66+
dat.attrs['sf'] = 256.
67+
68+
# export your dataset
69+
dat.to_netcdf('full_dataset.nc')
70+
71+
# delete it
72+
del dat
73+
74+
# reload it
75+
dat = xr.load_dataset("full_dataset.nc")
76+
print(dat)
77+
78+
# finally, accessing array of a dataset is similar of using dictionary
79+
arr_1 = dat['first']
80+
arr_2 = dat['second']

examples/xarray/plot_xr_quick_tour.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
"""
2+
Xarray : Quick tour
3+
===================
4+
5+
Basically, this example gives a very small introduction to Xarray (very small).
6+
We illustrate how to define a DataArray container, access its components,
7+
perform some of the basic operations and slicing / indexing.
8+
"""
9+
import numpy as np
10+
import xarray as xr
11+
import pandas as pd
12+
13+
###############################################################################
14+
# Simulate data
15+
# -------------
16+
#
17+
# lets start by creating a random spatio-temporal array
18+
19+
n_times = 30
20+
n_roi = 7
21+
times_vec = np.linspace(-1, 1, n_times)
22+
roi_vec = np.array([f"roi_{k}" for k in range(n_roi)])
23+
np_data = np.random.rand(n_times, n_roi)
24+
print(np_data.shape)
25+
print('*' * 79)
26+
27+
###############################################################################
28+
# Xarray conversion and access to the internal components
29+
# -------------------------------------------------------
30+
#
31+
# A DataArray is a container (like a well known numpy array) except that you
32+
# can add a label to each coordinate. To this end, the input `dims` is a tuple
33+
# that describes the dimension names and `coords` describes the value along
34+
# this coordinate
35+
36+
# let's convert it to a DataArray
37+
da_data = xr.DataArray(np_data, dims=('times', 'roi'),
38+
coords=(times_vec, roi_vec))
39+
print(da_data.shape)
40+
print(da_data)
41+
print('*' * 79)
42+
43+
# if you want to get the dimension names and values
44+
print(f'Dimension names : {da_data.dims}')
45+
print(f'Dimension values : {da_data.coords}')
46+
print(f"Data of a specific dimension : {da_data.roi.data}")
47+
print('*' * 79)
48+
49+
# if you want to get the original NumPy array enter the following :
50+
da_data.data
51+
52+
# if you want to change the values of a coordinate
53+
da_data['roi'] = np.array([f"roi_{k % 3}" for k in range(n_roi)])
54+
print(f"New ROI names : {da_data.roi.data}")
55+
print('*' * 79)
56+
57+
# if you need to compute or get the min / max / mean across a specific
58+
# dimension
59+
da_data.min('times') # minimum across time points
60+
da_data.max('times') # maximum across time points
61+
da_data.mean('roi') # mean across all ROI
62+
63+
# similarly to Pandas, it's also possible to group along a dimension and then
64+
# take the mean. For example, here's how to group and mean by roi names
65+
da_m = da_data.groupby('roi').mean('roi')
66+
print(da_m)
67+
print('*' * 79)
68+
69+
70+
###############################################################################
71+
# Xarray slicing and indexing
72+
# ---------------------------
73+
#
74+
# Now we show how to slice the container
75+
76+
# select a single specific ROI based on it's name
77+
da_data.sel(roi='roi_0')
78+
79+
# select a time range
80+
da_time_slice = da_data.sel(times=slice(-.5, .5))
81+
print(f"Temporal selection : {da_time_slice.coords}")
82+
print('*' * 79)
83+
84+
# off course, spatio-temporal selection is also supported
85+
da_st = da_data.sel(times=slice(-.5, .5), roi='roi_1')
86+
print(f"Spatio-temporal selection : {da_st.coords}")
87+
print('*' * 79)
88+
89+
# you can also slice according to indices
90+
da_isel = da_data.isel(times=slice(10, 20))
91+
print(f"Integer selection : {da_isel.coords}")
92+
print('*' * 79)
93+
94+
# however, if you want for example select multiple items based on their names,
95+
# you have to use booleans. Here's a small example that's using Pandas
96+
roi = da_data.roi.data
97+
use_roi = ['roi_0', 'roi_2']
98+
is_roi = pd.Series(roi).str.contains('|'.join(use_roi))
99+
da_mi = da_data.isel(roi=is_roi)
100+
print(f"Multi-items selection : {da_mi.coords}")
101+
102+
###############################################################################
103+
# Xarray attributes
104+
# -----------------
105+
#
106+
# One of the nice features of DataArray is that it supporting setting
107+
# attributes. Therefore you can add, for example, the parameters that describe
108+
# your analysis
109+
110+
# adding a few string attributes
111+
da_data.attrs['inference'] = 'ffx'
112+
da_data.attrs['stats'] = 'cluster-based'
113+
da_data.attrs['description'] = """Here's a small description of the analysis
114+
I'm currently running. Trying to find a difference between condition 1. vs 2.
115+
"""
116+
117+
# you can also add vectors (but not arrays) to the attributes
118+
da_data.attrs['vector'] = np.arange(30)
119+
120+
# however, "None" seems to pose a problem when saving the results. Therefore,
121+
# one quick way to solve this is simply to convert it into a string
122+
da_data.attrs['none_problem'] = str(None)
123+
124+
print(da_data)
125+
126+
###############################################################################
127+
# Xarray to an other format
128+
# -------------------------
129+
#
130+
# Finally, we quickly illustrate how to convert a DataArray into, for example,
131+
# a pandas.DataFrame
132+
133+
print(da_data.to_pandas())

0 commit comments

Comments
 (0)