Skip to content
Open
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
10 changes: 10 additions & 0 deletions fluttering/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
data

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class


# Jupyter Notebook
.ipynb_checkpoints
14 changes: 14 additions & 0 deletions fluttering/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
_Author: Petr Dolezal Date:2022-06-12_

As a part of the **ECMWF 2022 Visualization hackathon**, I tried to develop new ways to display the data held in multiple ensemble members.

I've developped a way to animate the datasets to show the predictions of different ensemble members as a flutter at each visualized time step.

The script to generate the videos presented can be found in the `export_flutter_*.py` files which use functions in the `flutter.py` module.

Scripts must be run in an environment specified in `environment.yml`:
```
conda env create --file environment.yml
conda activate hack_2022_ecmwf_fluttering
```
Data downloaded from https://get.ecmwf.int/#browse/browse:vishackathon (Thanks to Milana Vuckovic for providing them)
Empty file added fluttering/__init__.py
Empty file.
32 changes: 32 additions & 0 deletions fluttering/environment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# run: conda env create --file environment.yml
name: hack_2022_ecmwf_fluttering
channels:
- defaults
- conda-forge
dependencies:
- python>=3.10
- ipython>=7.30
- ipykernel>=6.4
- jupyter>=1.0
# Data download API
- cdsapi>=0.5

- numpy>=1.22
- xarray>=0.21
- pandas>=1.3
# Xarray voluntary dependencies
- dask
- netCDF4
- bottleneck
- cfgrib

- pip

# plotting
- cartopy>=0.18
- matplotlib>=3.5
- seaborn>=0.11

# animation VS Code
- ipympl>=0.9.1

103 changes: 103 additions & 0 deletions fluttering/export_flutter_animations_rain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
from matplotlib.pyplot import tight_layout
import xarray as xr
import cartopy.crs as ccrs
from pathlib import Path
import flutter


## Directories
dir_data = Path("data/reduced")
dir_fig = Path("data/fig")
dir_vid = dir_fig/ "vid"

#%% Shared parameters

## variable to animate
var = "tp"

Es=[50,100]

timesteps = 5
Ts = range(0,11,11//timesteps)

n_repetitions = 2
shuffle = True

params_prec = dict(vmin=0, vmax=0.025, cmap="inferno")
threshold_op = "gt"

tight_layout=False



#%% Plumbing
## Mapping between two different variable naming schemes
var_map = {
"2t":"t2m",
"msl":"msl",
"10fg":"fg10",
"tp":"tp"
}
var2 = var_map[var]


## generating filenames
f_var_fun = lambda var : f"hundred_members_{var}_pf.nc"
f_var = {var:f_var_fun(var) for var in
["2t",
"msl",
"10fg",
"tp"]}


## Load data set
filename = dir_data/f_var[var]
da = xr.load_dataset(filename)
da = da.assign_coords({"longitude": [ i if i <= 180 else i-360 for i in da.longitude.values]})
# reduce spatial range
da = da.sel(longitude=slice(-20,20),latitude=slice(65,35))
# remove cumulative aggregation in total precipitation
da_diff = da.diff("time",label="upper")
da = xr.concat([da.isel(time=0).copy(),da_diff], dim="time")


#%% Animation
## evolving timesteps
## temperature - no threshold

prec_threshold = None

for E in Es:
flutter.export_flutter(da,var2,Ts,E,
filename=dir_vid/f"ensembles_time_prec_all_T{timesteps}_{E}.mp4",
projection= ccrs.PlateCarree(),
transform = ccrs.PlateCarree(),
plot_params=params_prec,
threshold=prec_threshold,
threshold_op=threshold_op,
n_repetitions=n_repetitions, shuffle=shuffle,
title=f"Precipitation field N_ens:{E:3}",
tight_layout=tight_layout
)


#%% Animation
## evolving timesteps
## threshold temperature - freezing

prec_threshold = 0.001

## loop through parameters and export
for E in Es:
flutter.export_flutter(da,var2,Ts,E,
filename=dir_vid/f"ensembles_time_prec_T{timesteps}_{E}.mp4",
projection= ccrs.PlateCarree(),
transform = ccrs.PlateCarree(),
plot_params=params_prec,
threshold=prec_threshold,
threshold_op=threshold_op,
n_repetitions=n_repetitions, shuffle=shuffle,
title=f"Precipitation N_ens:{E:3}",
tight_layout=tight_layout
)

119 changes: 119 additions & 0 deletions fluttering/export_flutter_animations_temp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import xarray as xr
import cartopy.crs as ccrs
from pathlib import Path
import flutter


## Directories
dir_data = Path("data/reduced")
dir_fig = Path("data/fig")
dir_vid = dir_fig/ "vid"



#%% Shared parameters

## Variable to animate
var = "2t"

Es=[50,100]

timesteps = 5
Ts = range(0,11,11//timesteps)

n_repetitions = 2
shuffle = True

params_temp = dict(vmin=250, vmax=290, cmap="viridis")
threshold_op = "lt"

tight_layout=False

#%% Plumbing
## Mapping between two different variable naming schemes
var_map = {
"2t":"t2m",
"msl":"msl",
"10fg":"fg10",
"tp":"tp"
}
var2 = var_map[var]


## generating filenames
f_var_fun = lambda var : f"hundred_members_{var}_pf.nc"
f_var = {var:f_var_fun(var) for var in
["2t",
"msl",
"10fg",
"tp"]}


## Load data set
filename = dir_data/f_var[var]
da = xr.load_dataset(filename)
da = da.assign_coords({"longitude": [ i if i <= 180 else i-360 for i in da.longitude.values]})
# reduce spatial range
da = da.sel(longitude=slice(-20,20),latitude=slice(65,35))


#%% Animation
## evolving timesteps
## temperature - no threshold

temp_threshold = None

for E in Es:
flutter.export_flutter(da,var2,Ts,E,
filename=dir_vid/f"ensembles_time_temp_T{timesteps}_{E}.mp4",
projection= ccrs.PlateCarree(),
transform = ccrs.PlateCarree(),
plot_params=params_temp,
threshold=temp_threshold,
threshold_op=threshold_op,
n_repetitions=n_repetitions, shuffle=shuffle,
title=f"Temperatures N_ens:{E:3}",
tight_layout=tight_layout
)


#%% Animation
## evolving timesteps
## threshold temperature - freezing

temp_threshold = 273.15

## loop through parameters and export
for E in Es:
flutter.export_flutter(da,var2,Ts,E,
filename=dir_vid/f"ensembles_time_freezing_T{timesteps}_{E}.mp4",
projection= ccrs.PlateCarree(),
transform = ccrs.PlateCarree(),
plot_params=params_temp,
threshold=temp_threshold,
threshold_op=threshold_op,
n_repetitions=n_repetitions, shuffle=shuffle,
title=f"Temperatures <0⁰C N_ens:{E:3}",
tight_layout=tight_layout
)


# %% Animation
## evolving timesteps
## threshold temperature - subfreezing

temp_threshold = 268
for E in Es:
flutter.export_flutter(da,var2,Ts,E,
filename=dir_vid/f"ensembles_time_subfreezing_T{timesteps}_{E}.mp4",
projection= ccrs.PlateCarree(),
transform = ccrs.PlateCarree(),
plot_params=params_temp,
threshold=temp_threshold,
threshold_op=threshold_op,
n_repetitions=n_repetitions, shuffle=shuffle,
title=f"Temperatures <-5⁰C N_ens:{E:3}",
tight_layout=tight_layout
)


Loading