Getting started#

This notebook is a reproducibility example of the IPCC-WGI AR6 Interactive Atlas products. This work is licensed under a Creative Commons Attribution 4.0 International License.

Creative Commons License >

M. Iturbide (Santander Meteorology Group. Institute of Physics of Cantabria, CSIC-UC, Spain).

Welcome to the datalab “Getting Started” notebook! This guideline is structured to assist you in harnessing the wealth of resources available within the IPCC AR6 Interactive Atlas Datalab, enabling you to conduct meaningful climate research and analysis. The datalab serves as a reproducibility platform for the IPCC-WG-AR6 Interactive Atlas products, facilitating not only the reproducibility but also the reusability of the underlying data. It offers transparent access to a wide range of climate-related materials and data, thereby promoting robust scientific investigations and supporting climate change assessment efforts.

This guideline is divided into several sections. We will begin by outlining the overarching aim and motivation behind the datalab, clarifying its purpose and significance in the realm of climate research. Subsequently, we delve into the Description of the available material within the datalab, providing insights into the diverse datasets and resources at your disposal for climate analysis. Finally, in the section on Data loading and basic data operations, we walk you through the fundamental steps required to start working with climate data effectively.

Contents in this notebook#

  1. Aim and motivation

  2. Description of the available material within the datalab

  3. Data loading and basic data operations

    • 3.1. Library loading

    • 3.2. Data loading

    • 3.3. The structure of the climate4R grid

    • 3.4. Initial Data Exploration Plots

    • 3.5. Calculation of anomalies (future projections - historical simulations)

    • 3.6. Spatial aggregation


Before we start, or at any stage of the notebook, we can customize the plotting area within this notebook as follows:

library(repr)
# Change plot size 
options(repr.plot.width=18, repr.plot.height=8)

1. Aim and motivation#

The IPCC AR6 Interactive Atlas Datalab aims to support the reproducibility and reusability of the data underlying the Interactive Atlas of the IPCC-WGI. It leverages the latest technologies to provide an efficient research environment that accelerates data analysis. This is achieved by integrating data storage and computational resources with ready-to-use software frameworks. By utilizing these new technologies, climate data analysis can become more efficient, and the legacy of project results can be extended for the benefit of society.

2. Description of the available material within the datalab#

The datalab is more than just a computing resource; it encompasses data (including NcML catalogs), software, and notebooks that facilitate the reproducibility of the IPCC-WGI AR6 Atlas results. Additionally, this material enables the reusability of data, thereby extending the analysis provided by the IPCC-WGI Interactive Atlas.

Software#

The datalab comes with pre-installed ready-to-use software for managing and performing operations with climate data. This software is a collection of R packages known as the climate4R framework (Iturbide et al., 2019. DOI: 10.1016/j.envsoft.2018.09.009), which can be selected from the kernel menu. Go to the climate4R GitHub repository for more information.

For Python users, there is also a python 3 environment available. It’s worth noting, however, that in this case, the pre-installed software is more basic.

The core climate4R libraries that allow for data loading, transformation (e.g. spatio-temporal aggregations), and visualization are loadeR, transformeR and visualizeR.

library(loadeR)
library(transformeR)
library(visualizeR)
Loading required package: rJava

Loading required package: loadeR.java

Java version 20x amd64 by N/A detected

NetCDF Java Library v4.6.0-SNAPSHOT (23 Apr 2015) loaded and ready

Loading required package: climate4R.UDG

climate4R.UDG version 0.2.6 (2023-06-26) is loaded

Please use 'citation("climate4R.UDG")' to cite this package.

loadeR version 1.8.2 (2024-06-04) is loaded

Please use 'citation("loadeR")' to cite this package.
    _______   ____  ___________________  __  ________ 
   / ___/ /  / /  |/  / __  /_  __/ __/ / / / / __  / 
  / /  / /  / / /|_/ / /_/ / / / / __/ / /_/ / /_/_/  
 / /__/ /__/ / /  / / __  / / / / /__ /___  / / \ \ 
 \___/____/_/_/  /_/_/ /_/ /_/  \___/    /_/\/   \_\ 
 
      github.com/SantanderMetGroup/climate4R
transformeR version 2.2.2 (2023-10-26) is loaded

WARNING: Your current version of transformeR (v2.2.2) is not up-to-date

Get the latest stable version (2.2.3) using <devtools::install_github('SantanderMetGroup/transformeR')>

Please see 'citation("transformeR")' to cite this package.

visualizeR version 1.6.4 (2023-10-26) is loaded

Please see 'citation("visualizeR")' to cite this package.

However, the software includes the entire climate4R framework and other useful libraries. For instance, it includes the powerful plotting library lattice or the magrittr library for piping operations (through %>%).

library(lattice)
library(magrittr)

Data#

The inventory (data_inventory.csv) catalogs the list of files of the the IPCC-WGI AR6 Interactive Atlas Dataset, originally published at DIGITAL.CSIC for the long-term archival, and also available through the Copernicus Data Store (CDS).

We simply need to read this file with the read.csv function to get the data.frame of this information, which contains four columns: location, type, variable, project, experiment, frequency.

df <- read.csv("../../data_inventory.csv")
head(df)
A data.frame: 6 × 6
locationtypevariableprojectexperimentfrequency
<chr><chr><chr><chr><chr><chr>
1https://hub.climate4r.ifca.es/thredds/dodsC/ipcc/ar6/atlas/ia-monthly/CORDEX-ANT/historical/pr_CORDEX-ANT_historical_mon_197001-200512.nc opendappr CORDEX-ANThistoricalmon
2https://hub.climate4r.ifca.es/thredds/dodsC/ipcc/ar6/atlas/ia-monthly/CORDEX-ANT/historical/tn_CORDEX-ANT_historical_mon_197001-200512.nc opendaptn CORDEX-ANThistoricalmon
3https://hub.climate4r.ifca.es/thredds/dodsC/ipcc/ar6/atlas/ia-monthly/CORDEX-ANT/historical/rx1day_CORDEX-ANT_historical_mon_197001-200512.ncopendaprx1dayCORDEX-ANThistoricalmon
4https://hub.climate4r.ifca.es/thredds/dodsC/ipcc/ar6/atlas/ia-monthly/CORDEX-ANT/historical/tx_CORDEX-ANT_historical_mon_197001-200512.nc opendaptx CORDEX-ANThistoricalmon
5https://hub.climate4r.ifca.es/thredds/dodsC/ipcc/ar6/atlas/ia-monthly/CORDEX-ANT/historical/txx_CORDEX-ANT_historical_mon_197001-200512.nc opendaptxx CORDEX-ANThistoricalmon
6https://hub.climate4r.ifca.es/thredds/dodsC/ipcc/ar6/atlas/ia-monthly/CORDEX-ANT/historical/tnn_CORDEX-ANT_historical_mon_197001-200512.nc opendaptnn CORDEX-ANThistoricalmon
  • location refers to the path

  • type refers to the access mode, local (netcdf) or remote (opendap).

  • variable referst to the climatic variable or index (i.e. tas, pr, tn, rx1day, etc.)

  • project refers to the project coordinating the datasets (i.e. CORDEX-EUR, CMIP5, CMIP6, etc.)

  • experiment referst to the scenario (i.e. historical, rcp26, ssp126, rcp85, etc.)

We can easily apply filters to narrow down to the desired file:

subset <- subset(df, project == "CMIP6" & variable == "pr" & experiment == "historical" & type == "opendap")
data.file <- subset$location

Once we have the path of the desired data file, we can easily display the characteristics of the data it contains. To do this, we use the dataInventory function from the loadeR package.

di <- dataInventory(data.file)
[2024-11-08 10:59:42.024006] Doing inventory ...

[2024-11-08 10:59:42.094116] Opening dataset...

[2024-11-08 10:59:43.237541] The dataset was successfuly opened

[2024-11-08 10:59:43.546959] Retrieving info for 'pr' (0 vars remaining)

[2024-11-08 10:59:43.613328] Done.

We could check for instance the members (CMIP6 models),

di$pr$Dimensions$member
$Type
'Ensemble'
$Units
''
$Values
  1. 'CSIRO-ARCCSS_ACCESS-CM2_r1i1p1f1'
  2. 'CSIRO_ACCESS-ESM1-5_r1i1p1f1'
  3. 'BCC_BCC-CSM2-MR_r1i1p1f1'
  4. 'CAMS_CAMS-CSM1-0_r2i1p1f1'
  5. 'NCAR_CESM2-WACCM_r1i1p1f1'
  6. 'NCAR_CESM2_r4i1p1f1'
  7. 'CMCC_CMCC-CM2-SR5_r1i1p1f1'
  8. 'CNRM-CERFACS_CNRM-CM6-1-HR_r1i1p1f2'
  9. 'CNRM-CERFACS_CNRM-CM6-1_r1i1p1f2'
  10. 'CNRM-CERFACS_CNRM-ESM2-1_r1i1p1f2'
  11. 'CCCma_CanESM5_r1i1p1f1'
  12. 'EC-Earth-Consortium_EC-Earth3-Veg-LR_r1i1p1f1'
  13. 'EC-Earth-Consortium_EC-Earth3-Veg_r1i1p1f1'
  14. 'EC-Earth-Consortium_EC-Earth3_r1i1p1f1'
  15. 'CAS_FGOALS-g3_r1i1p1f1'
  16. 'NOAA-GFDL_GFDL-CM4_r1i1p1f1'
  17. 'NOAA-GFDL_GFDL-ESM4_r1i1p1f1'
  18. 'MOHC_HadGEM3-GC31-LL_r1i1p1f3'
  19. 'CCCR-IITM_IITM-ESM_r1i1p1f1'
  20. 'INM_INM-CM4-8_r1i1p1f1'
  21. 'INM_INM-CM5-0_r1i1p1f1'
  22. 'IPSL_IPSL-CM6A-LR_r1i1p1f1'
  23. 'NIMS-KMA_KACE-1-0-G_r2i1p1f1'
  24. 'KIOST_KIOST-ESM_r1i1p1f1'
  25. 'MIROC_MIROC-ES2L_r1i1p1f2'
  26. 'MIROC_MIROC6_r1i1p1f1'
  27. 'MPI-M_MPI-ESM1-2-HR_r1i1p1f1'
  28. 'MPI-M_MPI-ESM1-2-LR_r1i1p1f1'
  29. 'MRI_MRI-ESM2-0_r1i1p1f1'
  30. 'NUIST_NESM3_r1i1p1f1'
  31. 'NCC_NorESM2-LM_r1i1p1f1'
  32. 'NCC_NorESM2-MM_r1i1p1f1'
  33. 'AS-RCEC_TaiESM1_r1i1p1f1'
  34. 'MOHC_UKESM1-0-LL_r1i1p1f2'

or the description of the index, the corresponding units and the time resolution.

di$pr$Description
di$pr$Units
di$pr$Dimensions$time
'Monthly mean of daily accumulated precipitation'
'mm'
$Type
'Time'
$TimeStep
'30.436 days'
$Units
'days since 1850-01-01 00:00:00'
$Date_range
'1850-01-01T00:00:00Z - 2014-12-01T00:00:00Z'

3. Data loading and basic data operations#

Data loading is performed using the loadGridData function, which allows to point to a NetCDF file (object data.file in this example) or an NcML catalog as the data source.

The var parameter also needs to be specified, in this example as pr (mean precipitation). Note that loadGridData allows for additional parameter settings. We use lonLim and latLim to load only the subset of data over the Iberian Peninsula, and season to load data for specific months (in this example, JJA for boreal summer). In the years parameter, we specify the desired period (here, preindustrial). Run help(loadGridData) to check other available parameters.

cmip6.hist <- loadGridData(dataset = data.file,
             var = "pr",
             lonLim = c(-10, 4), latLim = c(36, 44),
             season = 6:8,
             years = 1850:1900)
[2024-11-08 10:59:43.818408] Opening dataset...

[2024-11-08 10:59:44.209382] The dataset was successfuly opened

[2024-11-08 10:59:44.215631] Defining geo-location parameters

[2024-11-08 10:59:44.272027] Defining time selection parameters

[2024-11-08 10:59:44.306239] Retrieving data subset ...

[2024-11-08 10:59:57.694737] Done

3.3. The structure of the climate4R grid#

The resulting object (here named cmip6.hist) is a climate4R grid, which is a list object containing the following slots: Variable, Data, xyCoordinates, Dates, and Members. The InitializationDates slot can be ignored here, as it is related to seasonal forecasting data.

str(cmip6.hist)
List of 6
 $ Variable           :List of 2
  ..$ varName: chr "pr"
  ..$ level  : NULL
  ..- attr(*, "use_dictionary")= logi FALSE
  ..- attr(*, "description")= chr "Monthly mean of daily accumulated precipitation"
  ..- attr(*, "units")= chr "mm"
  ..- attr(*, "longname")= chr "pr"
  ..- attr(*, "daily_agg_cellfun")= chr "none"
  ..- attr(*, "monthly_agg_cellfun")= chr "none"
  ..- attr(*, "verification_time")= chr "none"
 $ Data               : num [1:34, 1:153, 1:9, 1:15] 0.0801 0.832 1.7773 0.0732 0.2559 ...
  ..- attr(*, "dimensions")= chr [1:4] "member" "time" "lat" "lon"
 $ xyCoords           :List of 2
  ..$ x: num [1:15] -9.5 -8.5 -7.5 -6.5 -5.5 -4.5 -3.5 -2.5 -1.5 -0.5 ...
  ..$ y: num [1:9] 36.5 37.5 38.5 39.5 40.5 41.5 42.5 43.5 44.5
  ..- attr(*, "projection")= chr "LatLonProjection"
  ..- attr(*, "resX")= num 1
  ..- attr(*, "resY")= num 1
 $ Dates              :List of 2
  ..$ start: chr [1:153] "1850-06-01 00:00:00 GMT" "1850-07-01 00:00:00 GMT" "1850-08-01 00:00:00 GMT" "1851-06-01 00:00:00 GMT" ...
  ..$ end  : chr [1:153] "1850-06-01 00:00:00 GMT" "1850-07-01 00:00:00 GMT" "1850-08-01 00:00:00 GMT" "1851-06-01 00:00:00 GMT" ...
 $ Members            : chr [1:34] "CSIRO-ARCCSS_ACCESS-CM2_r1i1p1f1" "CSIRO_ACCESS-ESM1-5_r1i1p1f1" "BCC_BCC-CSM2-MR_r1i1p1f1" "CAMS_CAMS-CSM1-0_r2i1p1f1" ...
 $ InitializationDates:List of 34
  ..$ CSIRO-ARCCSS_ACCESS-CM2_r1i1p1f1             : NULL
  ..$ CSIRO_ACCESS-ESM1-5_r1i1p1f1                 : NULL
  ..$ BCC_BCC-CSM2-MR_r1i1p1f1                     : NULL
  ..$ CAMS_CAMS-CSM1-0_r2i1p1f1                    : NULL
  ..$ NCAR_CESM2-WACCM_r1i1p1f1                    : NULL
  ..$ NCAR_CESM2_r4i1p1f1                          : NULL
  ..$ CMCC_CMCC-CM2-SR5_r1i1p1f1                   : NULL
  ..$ CNRM-CERFACS_CNRM-CM6-1-HR_r1i1p1f2          : NULL
  ..$ CNRM-CERFACS_CNRM-CM6-1_r1i1p1f2             : NULL
  ..$ CNRM-CERFACS_CNRM-ESM2-1_r1i1p1f2            : NULL
  ..$ CCCma_CanESM5_r1i1p1f1                       : NULL
  ..$ EC-Earth-Consortium_EC-Earth3-Veg-LR_r1i1p1f1: NULL
  ..$ EC-Earth-Consortium_EC-Earth3-Veg_r1i1p1f1   : NULL
  ..$ EC-Earth-Consortium_EC-Earth3_r1i1p1f1       : NULL
  ..$ CAS_FGOALS-g3_r1i1p1f1                       : NULL
  ..$ NOAA-GFDL_GFDL-CM4_r1i1p1f1                  : NULL
  ..$ NOAA-GFDL_GFDL-ESM4_r1i1p1f1                 : NULL
  ..$ MOHC_HadGEM3-GC31-LL_r1i1p1f3                : NULL
  ..$ CCCR-IITM_IITM-ESM_r1i1p1f1                  : NULL
  ..$ INM_INM-CM4-8_r1i1p1f1                       : NULL
  ..$ INM_INM-CM5-0_r1i1p1f1                       : NULL
  ..$ IPSL_IPSL-CM6A-LR_r1i1p1f1                   : NULL
  ..$ NIMS-KMA_KACE-1-0-G_r2i1p1f1                 : NULL
  ..$ KIOST_KIOST-ESM_r1i1p1f1                     : NULL
  ..$ MIROC_MIROC-ES2L_r1i1p1f2                    : NULL
  ..$ MIROC_MIROC6_r1i1p1f1                        : NULL
  ..$ MPI-M_MPI-ESM1-2-HR_r1i1p1f1                 : NULL
  ..$ MPI-M_MPI-ESM1-2-LR_r1i1p1f1                 : NULL
  ..$ MRI_MRI-ESM2-0_r1i1p1f1                      : NULL
  ..$ NUIST_NESM3_r1i1p1f1                         : NULL
  ..$ NCC_NorESM2-LM_r1i1p1f1                      : NULL
  ..$ NCC_NorESM2-MM_r1i1p1f1                      : NULL
  ..$ AS-RCEC_TaiESM1_r1i1p1f1                     : NULL
  ..$ MOHC_UKESM1-0-LL_r1i1p1f2                    : NULL
 - attr(*, "dataset")= chr "https://hub.climate4r.ifca.es/thredds/dodsC/ipcc/ar6/atlas/ia-monthly/CMIP6/historical/pr_CMIP6_historical_mon_"| __truncated__
 - attr(*, "R_package_desc")= chr "loadeR-v1.8.2"
 - attr(*, "R_package_URL")= chr "https://github.com/SantanderMetGroup/loadeR"
 - attr(*, "R_package_ref")= chr "https://doi.org/10.1016/j.envsoft.2018.09.009"

Therefore, the information can be extracted using $. For instance, the data array can be extracted executing cmip6.hist$Data. Here we also apply str to display the structure of the data array.

data.array <- cmip6.hist$Data %>% str
 num [1:34, 1:153, 1:9, 1:15] 0.0801 0.832 1.7773 0.0732 0.2559 ...
 - attr(*, "dimensions")= chr [1:4] "member" "time" "lat" "lon"

However, as the climate4R functions work with the grid structure transparently, there is no need to extract any component of the list to perform different transformation and visualization operations.

3.4. Initial Data Exploration Plots#

Before we continue we can take a look at the data by, for instance, plotting maps. To do so we first compute the climatology with function climatology from the transformeR package. Finally, we use the spatialPlot function from the visualizeR package (run help(spatialPlot) to check different plotting parameters).

cmip6.hist.c <- climatology(cmip6.hist) 
spatialPlot(cmip6.hist.c, 
            backdrop.theme = "coastline", 
            col.theme = "Blues",
            at = seq(0, 8, 0.2),
            set.max = 8, set.min = 0,
            layout = c(9, 4),
            main = "Mean precipitation (mm/day) in the preindustrial period",
            strip = strip.custom(factor.levels = cmip6.hist.c$Members))
[2024-11-08 10:59:57.7728] - Computing climatology...

[2024-11-08 10:59:57.827338] - Done.
_images/d29512bfb340ac0e403ac4a45318c3791a4526752be37dde54c49324e08381f7.png

We could also display the temporal series with temporalPlot for the original monthly values…

temporalPlot(cmip6.hist, xyplot.custom = list(main = "Precipitation (mm/day) during summer months in the preindustrial era in the Iberian Peninsula."))
pad applied on the interval: month
_images/4dc44f968a5b3d6b8e42ed3e4377319a9f0352f6fe11c2e062fc2d6cc967b9d0.png

…or the aggregated yearly values by previously applying the aggregateGrid function (we will change the color this time, run help(temporalPlot) for further customization):

cmip6.hist.y <- aggregateGrid(cmip6.hist, aggr.y = list(FUN = "mean", na.rm = T))
temporalPlot(cmip6.hist.y, 
             cols = "orange",
             xyplot.custom = list(main = "Summer mean precipitation (mm/day) in the preindustrial era in the Iberian Peninsula."))
[2024-11-08 11:00:02.105277] Performing annual aggregation...

[2024-11-08 11:00:03.369865] Done.

pad applied on the interval: year
_images/0dbe0f1b4528806027ada754b86195f18f8798e028da3101a5bf17373ce3f485.png

Note that the temporalPlot function recognizes that our grid is multi-member (multi-model in this case) and shows the ensemble mean (solid line) and the multi-member spread (shadow).

3.5. Calculation of anomalies (future projections - historical simulations)#

We will now calculate the relative precipitation anomaly of a fixed future period (e.g. 2041-2060) relative to the preindustrial period. We will consider the SSP585 mitigation scenario. Therefore, we now point to another data source:

data.file.ssp585 <- subset(df, project == "CMIP6" & variable == "pr" & experiment == "ssp585" & type == "opendap")[["location"]]
cmip6.fut <- loadGridData(data.file.ssp585,
             var = "pr",
             lonLim = c(-10, 4), latLim = c(36, 44),
             season = 6:8,
             years = 2041:2060)
[2024-11-08 11:00:03.758623] Opening dataset...

[2024-11-08 11:00:04.096763] The dataset was successfuly opened

[2024-11-08 11:00:04.10151] Defining geo-location parameters

[2024-11-08 11:00:04.165869] Defining time selection parameters

[2024-11-08 11:00:04.185969] Retrieving data subset ...

[2024-11-08 11:00:09.657921] Done

We can combine the output with the historical data in the same time-series plot:

cmip6.fut.y <- aggregateGrid(cmip6.fut, aggr.y = list(FUN = "mean", na.rm = T))
temporalPlot(cmip6.hist.y, cmip6.fut.y)
[2024-11-08 11:00:09.676278] Performing annual aggregation...

[2024-11-08 11:00:10.236048] Done.

pad applied on the interval: year

pad applied on the interval: year
_images/3ef91baca2aa1c388af7e94b5c43b4a7de6b857249d63b6ddf1941702473ebc4.png

Lets calculate the anomaly. To do so, we must retain the common available members in both grids. These are de members (CMIP6 models) in the historical period:

cmip6.hist$Members
  1. 'CSIRO-ARCCSS_ACCESS-CM2_r1i1p1f1'
  2. 'CSIRO_ACCESS-ESM1-5_r1i1p1f1'
  3. 'BCC_BCC-CSM2-MR_r1i1p1f1'
  4. 'CAMS_CAMS-CSM1-0_r2i1p1f1'
  5. 'NCAR_CESM2-WACCM_r1i1p1f1'
  6. 'NCAR_CESM2_r4i1p1f1'
  7. 'CMCC_CMCC-CM2-SR5_r1i1p1f1'
  8. 'CNRM-CERFACS_CNRM-CM6-1-HR_r1i1p1f2'
  9. 'CNRM-CERFACS_CNRM-CM6-1_r1i1p1f2'
  10. 'CNRM-CERFACS_CNRM-ESM2-1_r1i1p1f2'
  11. 'CCCma_CanESM5_r1i1p1f1'
  12. 'EC-Earth-Consortium_EC-Earth3-Veg-LR_r1i1p1f1'
  13. 'EC-Earth-Consortium_EC-Earth3-Veg_r1i1p1f1'
  14. 'EC-Earth-Consortium_EC-Earth3_r1i1p1f1'
  15. 'CAS_FGOALS-g3_r1i1p1f1'
  16. 'NOAA-GFDL_GFDL-CM4_r1i1p1f1'
  17. 'NOAA-GFDL_GFDL-ESM4_r1i1p1f1'
  18. 'MOHC_HadGEM3-GC31-LL_r1i1p1f3'
  19. 'CCCR-IITM_IITM-ESM_r1i1p1f1'
  20. 'INM_INM-CM4-8_r1i1p1f1'
  21. 'INM_INM-CM5-0_r1i1p1f1'
  22. 'IPSL_IPSL-CM6A-LR_r1i1p1f1'
  23. 'NIMS-KMA_KACE-1-0-G_r2i1p1f1'
  24. 'KIOST_KIOST-ESM_r1i1p1f1'
  25. 'MIROC_MIROC-ES2L_r1i1p1f2'
  26. 'MIROC_MIROC6_r1i1p1f1'
  27. 'MPI-M_MPI-ESM1-2-HR_r1i1p1f1'
  28. 'MPI-M_MPI-ESM1-2-LR_r1i1p1f1'
  29. 'MRI_MRI-ESM2-0_r1i1p1f1'
  30. 'NUIST_NESM3_r1i1p1f1'
  31. 'NCC_NorESM2-LM_r1i1p1f1'
  32. 'NCC_NorESM2-MM_r1i1p1f1'
  33. 'AS-RCEC_TaiESM1_r1i1p1f1'
  34. 'MOHC_UKESM1-0-LL_r1i1p1f2'

and these in the future period for the SSP585 scenario:

cmip6.fut$Members
  1. 'CSIRO-ARCCSS_ACCESS-CM2_r1i1p1f1'
  2. 'CSIRO_ACCESS-ESM1-5_r1i1p1f1'
  3. 'BCC_BCC-CSM2-MR_r1i1p1f1'
  4. 'CAMS_CAMS-CSM1-0_r2i1p1f1'
  5. 'NCAR_CESM2-WACCM_r1i1p1f1'
  6. 'NCAR_CESM2_r4i1p1f1'
  7. 'CMCC_CMCC-CM2-SR5_r1i1p1f1'
  8. 'CNRM-CERFACS_CNRM-CM6-1-HR_r1i1p1f2'
  9. 'CNRM-CERFACS_CNRM-CM6-1_r1i1p1f2'
  10. 'CNRM-CERFACS_CNRM-ESM2-1_r1i1p1f2'
  11. 'CCCma_CanESM5_r1i1p1f1'
  12. 'EC-Earth-Consortium_EC-Earth3-Veg_r1i1p1f1'
  13. 'EC-Earth-Consortium_EC-Earth3_r1i1p1f1'
  14. 'CAS_FGOALS-g3_r1i1p1f1'
  15. 'NOAA-GFDL_GFDL-CM4_r1i1p1f1'
  16. 'NOAA-GFDL_GFDL-ESM4_r1i1p1f1'
  17. 'MOHC_HadGEM3-GC31-LL_r1i1p1f3'
  18. 'CCCR-IITM_IITM-ESM_r1i1p1f1'
  19. 'INM_INM-CM4-8_r1i1p1f1'
  20. 'INM_INM-CM5-0_r1i1p1f1'
  21. 'IPSL_IPSL-CM6A-LR_r1i1p1f1'
  22. 'NIMS-KMA_KACE-1-0-G_r2i1p1f1'
  23. 'KIOST_KIOST-ESM_r1i1p1f1'
  24. 'MIROC_MIROC-ES2L_r1i1p1f2'
  25. 'MIROC_MIROC6_r1i1p1f1'
  26. 'MPI-M_MPI-ESM1-2-HR_r1i1p1f1'
  27. 'MPI-M_MPI-ESM1-2-LR_r1i1p1f1'
  28. 'MRI_MRI-ESM2-0_r1i1p1f1'
  29. 'NUIST_NESM3_r1i1p1f1'
  30. 'NCC_NorESM2-LM_r1i1p1f1'
  31. 'NCC_NorESM2-MM_r1i1p1f1'
  32. 'AS-RCEC_TaiESM1_r1i1p1f1'
  33. 'MOHC_UKESM1-0-LL_r1i1p1f2'

As is the case in this example, different scenarios for different variables may have less members than the corresponding historical experiment. We can therefore subset the historical grid to match the members with the future grid. An easy way to retain the common members in both grids is to use the function intersectGrid (which also allows for spatial and temporal intersections, by changing the value in the type argument):

cmip6.common.mems <- intersectGrid(cmip6.hist, cmip6.fut, type = "members", which.return = 1:2)
cmip6.hist.s <- cmip6.common.mems[[1]] ; cmip6.fut <- cmip6.common.mems[[2]]

It is always a good practice to make sure that the members in both grids are identical:

identical(cmip6.hist.s$Members, cmip6.fut$Members)
TRUE

Now we can calculate the anomaly by computing the difference between both climatologies:

anom <- gridArithmetics(climatology(cmip6.fut), climatology(cmip6.hist.s), operator = "-")
[2024-11-08 11:00:10.526133] - Computing climatology...

[2024-11-08 11:00:10.706641] - Done.

[2024-11-08 11:00:10.71262] - Computing climatology...

[2024-11-08 11:00:10.745056] - Done.

We can calculate the relative anomaly the same way:

rel.anom <- gridArithmetics(anom, climatology(cmip6.hist.s), 100, operator = c("/", "*"))
[2024-11-08 11:00:10.766294] - Computing climatology...

[2024-11-08 11:00:10.805385] - Done.

Finally, we can plot the output using an appropriate palette for the color.theme:

spatialPlot(rel.anom, 
            color.theme = "BrBG",
            backdrop.theme = "coastline", 
            at = seq(-50, 50),
            set.max = 50, set.min = -50,
            layout = c(9, 4),
            main = "Mean precipitation relative anomaly (mm/day)",
            strip = strip.custom(factor.levels = cmip6.fut$Members))
_images/f924b9832e85e0d8816dc4d88558a45e27544581a6e661c10f2f8592029a647a.png

We can do the same for the multi-model ensemble mean by previously applying the aggregateGrid function:

ens.mean.anom <- aggregateGrid(rel.anom, aggr.mem = list(FUN = "mean", na.rm = TRUE))
spatialPlot(ens.mean.anom, 
            color.theme = "BrBG",
            backdrop.theme = "coastline", 
            at = seq(-55, 55),
            set.max = 55, set.min = -55,
            main = "Mean precipitation relative anomaly (mm/day)",
            strip = strip.custom(factor.levels = cmip6.fut$Members))
[2024-11-08 11:00:14.246094] - Aggregating members...

[2024-11-08 11:00:14.248896] - Done.
_images/5e04367eba49f6559f15de5afba1b94905a62667bd277f4db4befafb8c6c9473.png

3.6. Spatial aggregation#

The time series plots we have created above, automatically performs spatial aggregations. However, we can control this operation by using the aggr.spatial parameter in the aggregateGrid function, which by default calculates weighted values according to the latitude. If we aggregate the rel.anom object, we will get a single value per model (member).

rel.anom.regional_mean <- aggregateGrid(rel.anom, aggr.spatial = list(FUN = "mean", na.rm = TRUE))
Calculating areal weights...

[2024-11-08 11:00:14.441585] - Aggregating spatially...

[2024-11-08 11:00:14.443421] - Done.

In the next code chunk we get the multi-model mean and the percentiles:

m <- aggregateGrid(rel.anom.regional_mean, aggr.mem = list(FUN = "mean", na.rm = TRUE)) 
p25 <- aggregateGrid(rel.anom.regional_mean, aggr.mem = list(FUN = "quantile", prob = 0.25, na.rm = TRUE)) 
p75 <- aggregateGrid(rel.anom.regional_mean, aggr.mem = list(FUN = "quantile", prob = 0.75, na.rm = TRUE)) 

c("mean" = m$Data, "P25" = p25$Data, "P75" = p75$Data)
[2024-11-08 11:00:14.456018] - Aggregating members...

[2024-11-08 11:00:14.457539] - Done.

[2024-11-08 11:00:14.459882] - Aggregating members...

[2024-11-08 11:00:14.462046] - Done.

[2024-11-08 11:00:14.464226] - Aggregating members...

[2024-11-08 11:00:14.466114] - Done.
mean
-27.2475711759013
P25
-34.6696350110102
P75
-17.8717848503489

At this stage it is easy to operate directly with the data array and use other R functionalities, for instance:

boxplot(rel.anom.regional_mean$Data)
_images/2437cad7c4662a9c17babc2f7208bd9e7ad37fc0d315eecddfb6265d2126c9ac.png

The climate4R framework provides many other spatial and temporal operations functionalities, such as interpolation, subsetting or spatial intersection. It also provides functionalities for bias correction and downscaling (see Iturbide et al., 2019. DOI: 10.1016/j.envsoft.2018.09.009).


Session Info#

sessionInfo()
R version 4.3.3 (2024-02-29)
Platform: x86_64-conda-linux-gnu (64-bit)
Running under: Ubuntu 22.04.5 LTS

Matrix products: default
BLAS/LAPACK: /home/zequi/miniconda3/lib/libopenblasp-r0.3.21.so;  LAPACK version 3.9.0

locale:
 [1] LC_CTYPE=en_US.UTF-8          LC_NUMERIC=C                 
 [3] LC_TIME=es_ES.UTF-8           LC_COLLATE=en_US.UTF-8       
 [5] LC_MONETARY=es_ES.UTF-8       LC_MESSAGES=en_US.UTF-8      
 [7] LC_PAPER=es_ES.UTF-8          LC_NAME=es_ES.UTF-8          
 [9] LC_ADDRESS=es_ES.UTF-8        LC_TELEPHONE=es_ES.UTF-8     
[11] LC_MEASUREMENT=es_ES.UTF-8    LC_IDENTIFICATION=es_ES.UTF-8

time zone: Europe/Madrid
tzcode source: system (glibc)

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] magrittr_2.0.3      lattice_0.22-6      visualizeR_1.6.4   
[4] transformeR_2.2.2   loadeR_1.8.2        climate4R.UDG_0.2.6
[7] loadeR.java_1.1.1   rJava_1.0-11        repr_1.1.7         

loaded via a namespace (and not attached):
 [1] dotCall64_1.1-1         spam_2.10-0             latticeExtra_0.6-30    
 [4] vctrs_0.6.5             mapplots_1.5.2          tools_4.3.3            
 [7] bitops_1.0-8            generics_0.1.3          parallel_4.3.3         
[10] tibble_3.2.1            proxy_0.4-27            fansi_1.0.6            
[13] SpecsVerification_0.5-3 pkgconfig_2.0.3         data.table_1.15.2      
[16] RColorBrewer_1.1-3      uuid_1.2-1              lifecycle_1.0.4        
[19] compiler_4.3.3          kohonen_3.0.12          deldir_2.0-4           
[22] fields_16.2             munsell_0.5.1           akima_0.6-3.4          
[25] htmltools_0.5.8.1       maps_3.4.2              RCurl_1.98-1.13        
[28] pillar_1.9.0            crayon_1.5.3            MASS_7.3-60.0.1        
[31] boot_1.3-31             abind_1.4-5             vioplot_0.5.0          
[34] padr_0.6.2              verification_1.42       tidyselect_1.2.1       
[37] digest_0.6.37           dplyr_1.1.4             fastmap_1.2.0          
[40] grid_4.3.3              colorspace_2.1-1        cli_3.6.3              
[43] base64enc_0.1-3         utf8_1.2.4              sm_2.2-6.0             
[46] IRdisplay_1.1           withr_3.0.1             scales_1.3.0           
[49] sp_2.1-4                IRkernel_1.3.2          jpeg_0.1-10            
[52] interp_1.1-6            pbdZMQ_0.3-10           RcppEigen_0.3.4.0.1    
[55] zoo_1.8-12              png_0.1-8               pbapply_1.7-2          
[58] evaluate_1.0.0          dtw_1.23-1              viridisLite_0.4.2      
[61] rlang_1.1.4             Rcpp_1.0.13             glue_1.7.0             
[64] easyVerification_0.4.5  CircStats_0.2-6         jsonlite_1.8.9         
[67] R6_2.5.1