Skip to content

Commit aa48db2

Browse files
authored
Merge pull request #3 from DeepExtremes/jl110
Jl110
2 parents 2e9de51 + 7f99170 commit aa48db2

48 files changed

Lines changed: 7769 additions & 2095 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Manifest.toml

Lines changed: 1271 additions & 936 deletions
Large diffs are not rendered by default.

Project.toml

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,31 @@
1-
name = "ExtremeEvents"
2-
uuid = "ace4fa40-4b0d-4fab-a937-802c9281da09"
3-
authors = ["Mel Wey <45990429+melwey@users.noreply.github.com> and contributors"]
4-
version = "0.2.0"
5-
61
[deps]
72
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
8-
DataConvenience = "3b531cbf-ee43-4e67-8118-dca2c9372f86"
3+
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
94
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
105
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
116
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
7+
DimensionalData = "0703355e-b756-11e9-17c0-8b28908087d0"
128
DiskArrayTools = "fcd2136c-9f69-4db6-97e5-f31981721d63"
139
DiskArrays = "3c3547ce-8d99-4f5e-a174-61eb10b00ae3"
1410
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
15-
EarthDataLab = "359177bc-a543-11e8-11b7-bb015dba3358"
16-
FastTransforms = "057dd010-8810-581a-b7be-e3fc3b93f78c"
11+
GeoMakie = "db073c08-6b98-4ee5-b6a4-5efafb3259c6"
1712
ImageFiltering = "6a3955dd-da59-5b1f-98d4-e7296123deb5"
1813
ImageMorphology = "787d08f9-d448-5407-9aad-5290dd7ab264"
19-
IndexedTables = "6deec6e2-d858-57c5-ab9b-e6ca5bd20e43"
2014
JLD = "4138dd39-2aa7-5051-a626-17a0bb65d9c8"
21-
Measures = "442fdcdd-2543-5da2-b0f3-8c86c306513e"
15+
MannKendall = "1761a1e1-e032-445b-870e-f3b23132a90a"
2216
NetCDF = "30363a11-5582-574a-97bb-aa9a979735b9"
2317
OnlineStats = "a15396b6-48d5-5d58-9928-6d29437db91e"
24-
OnlineStatsBase = "925886fa-5bf2-5e8e-b522-a9147a512338"
25-
ParallelUtilities = "fad6cfc8-4f83-11e9-06cc-151124046ad0"
26-
Pipe = "b98c9c47-44ae-5843-9183-064241ee97a0"
27-
PlotThemes = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a"
28-
PlotUtils = "995b91a9-d308-5afd-9ec6-746e21dbc043"
29-
PlotlyJS = "f0f68f2c-4968-5e81-91da-67840de0976a"
30-
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
18+
Primes = "27ebfcd6-29c5-5fa9-bf4b-fb8fc14df3ae"
19+
QuantileRegressions = "c6596682-b856-542f-9fff-31404643e889"
3120
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
3221
RollingFunctions = "b0e4dd01-7b14-53d8-9b45-175a3e362653"
3322
SlurmClusterManager = "c82cd089-7bf7-41d7-976b-6b5d413cbe0a"
3423
SphericalConvolutions = "7186af5b-8736-480f-81ff-8eb527665490"
3524
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
3625
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"
37-
StatsPlots = "f3b207a7-027a-5e70-b257-86293d7955fd"
26+
StatsFuns = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
3827
Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
39-
UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228"
4028
WeightedOnlineStats = "bbac0a1f-7c9d-5672-960b-c6ca726e5d5d"
4129
YAXArrayBase = "90b8fcef-0c2d-428d-9c56-5f86629e9d14"
4230
YAXArrays = "c21b50f5-aa40-41ea-b809-c0f5e47bfa5c"
4331
Zarr = "0a941bbe-ad1d-11e8-39d9-ab76183a1d99"
44-
45-
[compat]
46-
julia = "1.8"
47-
48-
[extras]
49-
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
50-
51-
[targets]
52-
test = ["Test"]

README.md

Lines changed: 169 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,169 @@
1-
# ExtremeEvents
2-
Extreme events detection for DeepExtremes project.
1+
# Workflow for building and analysing Dheed v3
2+
Dheed v3 is an ERA5 based global database dry and hot extreme events from 1950 to 2022, developed in the context of ESA funded project [DeepExtremes](https://eo4society.esa.int/projects/deep-extremes/).
3+
The workflow runs in Julia 1.10.0, except for the consolidation of the data cubes, which is run in python.
4+
Most steps of the workflow were run on the [MPI BGC-jena](https://bgc-jena.mpg.de) cluster. The input data are hourly ERA5 data retrieved from the [Copernicus Climate Data Store](https://cds.climate.copernicus.eu/) and stored on a local server as netcdf files. Some derived variables were calculated prior to the processing presented here.
5+
6+
## Preprocessing
7+
8+
1. Rechunk ERA5 data, agregating from hourly to daily: t2m (min, mean, max), tp (sum), ssrd (sum).
9+
10+
```
11+
cd SlurmScripts
12+
sbatch rechunk_data.slurm
13+
```
14+
15+
*Output*: ERA5Cube.zarr
16+
17+
2. Compute PET on hourly data (t2m, tp , u10, v10, sp, snr (calc), vpd_cf (calc)) and aggregate to daily.
18+
19+
```
20+
cd SlurmScripts
21+
sbatch compute_pet.slurm
22+
```
23+
24+
*Output*: PET yearly cubes
25+
26+
3. Rechunk PET and add to ER5cube
27+
28+
The daily PET is rechunked to match the chunk size of the ERA5cube and added to it.
29+
30+
```
31+
cd SlurmScripts
32+
sbatch rechunk_pet.slurm
33+
```
34+
35+
*Output*: updated ERA5Cube.zarr
36+
37+
4. Consolidate metadata of ERA5Cube
38+
39+
Metadata from the different variables in the ERA5cube are consolidated, so as to reduce the number of read operations on the backend store.
40+
41+
```
42+
python -c import zarr; g = zarr.open_group(path2cube); zarr.consolidate_metadata(g.store)
43+
```
44+
45+
*Output*: consolidated ERA5Cube.zarr
46+
47+
5. Compute PEI
48+
49+
The precipitation evaporation index (PEI) is a moving average of the water balance between daily potential evapotranspiration and precipitation. The moving window is 30, 90 or 180 days.
50+
51+
```
52+
cd SlurmScripts
53+
sbatch compute_pei.slurm
54+
```
55+
56+
*Output*: PEICube.zarr
57+
58+
59+
## Processing
60+
### Temporal analysis
61+
62+
The time series of the four indicators: t2mmax, PEI_30, PEI_90 and PEI_180 are ranked transformed between 0 and 1. No convolutional spatial filter is run on the results to smoothe the extent of the extreme events.
63+
64+
```
65+
cd SlurmScripts
66+
sbatch smooth_events.slurm
67+
```
68+
69+
*Output*: tmax_ranked.zarr and pei_ranks.zarr
70+
71+
### Compute extremes
72+
A pass over threshold is applied to the rescaled indicators and they are combined into a Byte integer (Int8), with one bit for each indicator and an extra bit encoding for non extremes. The first bit (little end) encodes the maximum temperature extremes.
73+
74+
```
75+
cd SlurmScripts
76+
sbatch compute_events.slurm
77+
```
78+
79+
*Output*: EventCube.zarr
80+
81+
### Label extreme events
82+
Unique labels are assigned to blobs of co-occurrent hot and dry extremes, i.e. where values are uneven (t2mmax extremes) and larger than one (PEI extremes), connected in space and time. A filter is applied before runnning the connected component analysis: temperature extremes must last at least three consecutive days.
83+
84+
*Note*: this will reduce the total number of tmax extremes in the cube...
85+
86+
Because the connected component analysis requires to load the full cube into memory and the algorithm is greedy, the analysis was split into seven tasks, covering each 13 years, with three years overlap between two successive periods.
87+
88+
```
89+
cd SlurmScripts
90+
sbatch label_events.slurm
91+
```
92+
93+
*Output*:
94+
- labelcube_ranked_pot0.01_ne0.1_cmp_S1_T3_1950_1962.zarr
95+
- labelcube_ranked_pot0.01_ne0.1_cmp_S1_T3_1960_1972.zarr
96+
- labelcube_ranked_pot0.01_ne0.1_cmp_S1_T3_1970_1982.zarr
97+
- labelcube_ranked_pot0.01_ne0.1_cmp_S1_T3_1980_1992.zarr
98+
- labelcube_ranked_pot0.01_ne0.1_cmp_S1_T3_1990_2002.zarr
99+
- labelcube_ranked_pot0.01_ne0.1_cmp_S1_T3_2000_2012.zarr
100+
- labelcube_ranked_pot0.01_ne0.1_cmp_S1_T3_2010_2022.zarr
101+
102+
The labels are then merged into a single mergedlabels cube with `scripts/merge_labels.jl`.
103+
104+
*Output*:
105+
- mergedlabels.zarr
106+
107+
### Compute statistics
108+
Statistics for all labelled events are computed and gathered in a unique table.
109+
110+
```
111+
cd SlurmScripts
112+
sbatch stats_extremes_merged.slurm
113+
```
114+
115+
*Output*:
116+
- MergedEventStats_landonly.csv
117+
118+
## Figures and Postprocessing
119+
120+
### fig01_workflow.png
121+
122+
Flowchart designed in ppt.
123+
124+
### fig02_workflow-plot-33.png
125+
126+
Example of dry and hot extreme event detection workflow over the 2003 summer heatwave in Europe.
127+
128+
See `scripts/fig4dheed.jl`
129+
130+
### fig03: timeseries
131+
132+
Timeseries of indicators for 2 contrasted locations: Jena (timeseries_11.59_50.92_2012_2023.png) and Niamey (timeseries_2.1254_13.5116_2012_2023.png).
133+
134+
See `scripts/plot_t2mmax.jl`
135+
136+
### fig04 - fig06: Trends -- Annual global/continental summary
137+
138+
Trends in annual global/continental indicators.
139+
140+
Compute annual statistics of indicators, globally and by continent.
141+
142+
See `scripts/plot_ind_annual.jl`
143+
144+
Compute annual statistics of EventCube at global and continental scale, by summing all extremes by type.
145+
146+
See `scripts/hist_EventType.jl`
147+
148+
Plot the results of the EventCube analysis.
149+
150+
```
151+
julia --project="ExtremeEvents.toml" plot_EventType.jl
152+
```
153+
154+
### fig07: events_stats_ranked_pot0.01_ne0.1_cmp_S1_T3_2010_2022_landonly_1970.png
155+
156+
Extract largest and longest events from `MergedEventStats_landonly` with `largest_labels.jl` and plot statistics with `plot_stats.jl`.
157+
158+
### fig08: largest_ranked_pot0.01_ne0.1_cmp_S1_T3_2010_2022_landonly_1970.png
159+
160+
A map of the spatial footprint of the largest events is generated with `plot_stats.jl`.
161+
162+
### fig09: Validation
163+
164+
Compare MergedEventStats_landonly with table of reported events compiled *a priori* with `SanityCheck.jl`.
165+
166+
### fig10: Lytton.png
167+
168+
Extract timeseries at single locations with `plot_city.jl`
169+

SlurmScripts/add2cube.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import xarray as xr
2+
3+
def add2cube(oldcube, newcube):
4+
ds = xr.open_zarr(newcube)
5+
ds.to_zarr(
6+
oldcube,
7+
mode = "a",
8+
append_dim = "time",
9+
consolidated = True,
10+
)
11+
12+

SlurmScripts/compute_pei_add.slurm

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
#SBATCH --job-name pei_jl
3+
#SBATCH -o ./pei-%A.out
4+
#SBATCH -p work
5+
#SBATCH --ntasks=8
6+
#SBATCH --cpus-per-task=1
7+
#SBATCH --mem-per-cpu=10GB
8+
#SBATCH --time=2:00:00
9+
#SBATCH --mail-type FAIL,END
10+
11+
export JULIA_NUM_THREADS=${SLURM_CPUS_PER_TASK}
12+
13+
julia --project=../ ../scripts/compute_pei_add.jl 2023 2023
14+
15+
OLDCUBE="/Net/Groups/BGI/scratch/mweynants/DeepExtremes/v3/PEICube.zarr"
16+
NEWCUBE="/Net/Groups/BGI/scratch/mweynants/DeepExtremes/v3/PEICube_2023.zarr"
17+
srun /Net/Groups/BGI/scratch/mweynants/miniconda3/bin/python -c "import add2cube as ac;ac.add2cube(\"${OLDCUBE}\", \"${NEWCUBE}\")"
18+
19+
echo "Success?"

SlurmScripts/compute_pet.slurm

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/bash
2+
#SBATCH --job-name pet_jl10
3+
#SBATCH -o ./pet-%A.out
4+
#SBATCH -p work
5+
#SBATCH --nodes=1
6+
#SBATCH --ntasks=1
7+
#SBATCH --cpus-per-task=1
8+
#SBATCH --mem-per-cpu=10GB
9+
#SBATCH --time=2-00
10+
11+
export JULIA_NUM_THREADS=${SLURM_CPUS_PER_TASK}
12+
13+
julia --project=../ ../scripts/compute_pet.jl 2023
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
PATH2CUBE="/Net/Groups/BGI/scratch/mweynants/DeepExtremes/v3/ERA5Cube_2023.zarr"
3+
python -c "import zarr; g = zarr.open_group(\"${PATH2CUBE}\"); zarr.consolidate_metadata(g.store)"
4+
5+
# # manually edit .zmetadata: modify per dimensions :Time => :time
6+
# # find
7+
# ".zattrs": {
8+
# "_ARRAY_DIMENSIONS": [
9+
# "Time",
10+
# # replace by
11+
# ".zattrs": {
12+
# "_ARRAY_DIMENSIONS": [
13+
# "time",
14+
# # in ./time/.zattrs, replace Time => time
15+
# # in ./pet/.zattrs
16+
# rm -rf /Net/Groups/BGI/scratch/mweynants/DeepExtremes/v3/ERA5Cube.zarr/Time
17+
# rm -rf /Net/Groups/BGI/scratch/mweynants/DeepExtremes/v3/ERA5Cube.zarr/layer
18+
# # consolidate metadata
19+
# python -c "import zarr; g = zarr.open_group(\"${PATH2CUBE}\"); zarr.consolidate_metadata(g.store)"

SlurmScripts/largest_labels.slurm

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/bash
2+
#SBATCH --job-name jl_llbls
3+
#SBATCH -o ./llbls-%A.out
4+
#SBATCH --mail-type FAIL,END
5+
#SBATCH -p work
6+
#SBATCH --ntasks=8
7+
#SBATCH --nodes=1
8+
#SBATCH --cpus-per-task=8
9+
#SBATCH --mem-per-cpu=7GB
10+
#SBATCH --time=5-00
11+
12+
export JULIA_NUM_THREADS=${SLURM_CPUS_PER_TASK}
13+
14+
julia --project=../ ../scripts/largest_labels.jl

SlurmScripts/qdoy.slurm

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/bash
2+
#SBATCH --job-name julia_qdoy
3+
#SBATCH -o ./detect-%A.out
4+
#SBATCH -p work
5+
#SBATCH --ntasks=10
6+
#SBATCH --nodes=1
7+
#SBATCH --cpus-per-task=1
8+
#SBATCH --mem-per-cpu=20GB
9+
#SBATCH --time=36:00:00
10+
11+
export JULIA_NUM_THREADS=${SLURM_CPUS_PER_TASK}
12+
13+
julia --project=../ ../scripts/qdoy.jl

SlurmScripts/rechunk_tp.slurm

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/bash
2+
#SBATCH --job-name rchk_tp
3+
#SBATCH -o ./rechunk-htp-%A.out
4+
#SBATCH --partition work
5+
#SBATCH --mail-type FAIL,END
6+
#SBATCH --ntasks=1
7+
#SBATCH --cpus-per-task=1
8+
#SBATCH --mem-per-cpu=40GB
9+
#SBATCH --time=5-00
10+
#SBATCH --nodes=1
11+
12+
export JULIA_NUM_THREADS=${SLURM_CPUS_PER_TASK}
13+
14+
julia --project=../ ../scripts/Rechunk_htp.jl

0 commit comments

Comments
 (0)