from IPython.display import Image
Image(url='https://vesg.ipsl.upmc.fr/thredds/fileServer/IPSLFS/jservon/CliMAF_Notebooks_html/CliMAF-logo-small.png')
A CliMAF ensemble is basically:
All the members are tagged with a name, or 'key'. This name will be used automatically by the operators that include ${labels} in the cscript declaration, such as plot.
In this notebook we will see how to:
CMIP6 and CORDEX are treated more specifically in two additionnal notebooks:
from climaf.api import *
clog('critical') # min verbosity = critical < warning < info < debug = max verbosity
# -- CMIP5: how to get all the models
req_cmip5 = ds(project='CMIP5',
model='*',
variable='tos',
experiment='historical',
period='1980-2000',
frequency='monthly',
version='latest'
)
# -- We use .explore('choices') to see all the possible values taken by model
req_cmip5.explore('choices')
ens_cmip5 = req_cmip5.explore('ensemble')
summary(ens_cmip5)
# -- Let's compute the annual mean of all the members
anm_ens_cmip5 = clim_average(ens_cmip5, 'ANM')
# -> Note that anm_ens_cmip5 is also a CliMAF ensemble
# -- Now I can use anm_ens_cmip5 to compute an ensemble average
ensavg_anm_ens_cmip5 = ccdo_ens(anm_ens_cmip5, operator='ensavg')
The CMIP6 project is addressed in details in an additionnal notebook: CMIP6_analysis_with_CliMAF.ipynb
The CMIP6 archive is slightly different from the CMIP5 archive.
The key 'institute' and the new key 'grid' implies that we can't build a CMIP6 multi-model ensemble in one move with .explore('ensemble') (example and solution below), since we easily have more than one key with multiple values.
Building a multi-realization ensemble on one model still remains an easy task.
# -- Let's start with an easy example, with the same behavior as described
# for the CMIP5 multi-model ensemble
req_cmip6 = ds(project='CMIP6', variable='pr', period='*',
table='Amon', model='CNRM-CM6-1',
realization='*'
)
req_cmip6.explore('choices')
# -- realization is the only key with a list of values, we can thus use .explore('ensemble')
# to create an ensemble
multirealization_cmip6 = req_cmip6.explore('ensemble')
summary(multirealization_cmip6)
ens_cmip5 = eds(project='CMIP5',
model=['IPSL-CM5A-MR','CNRM-CM5'],
variable='tos',
experiment='historical',
period='1980-2000',
frequency='monthly',
realization='r1i1p1',
)
summary(ens_cmip5)
# -- On every member I will apply:
# -- - a DJF average
djf_ens_cmip5 = clim_average(ens_cmip5, 'DJF')
# -- - a regridding on a common grid
rgrd_djf_ens_cmip5 = regridn(djf_ens_cmip5, cdogrid='r360x180')
# -- - a selection of geographical domain
NAtl_rgrd_djf_ens_cmip5 = llbox(rgrd_djf_ens_cmip5, lonmin=-80, lonmax=40, latmin=20, latmax=80)
# -- And do a multiplot (warning: limited to 24 plots...)
pp = dict(focus='ocean', offset=-273.15, contours=1)
# -> see plot() documentation: https://climaf.readthedocs.io/en/latest/scripts/plot.html
mp = cpage( plot(NAtl_rgrd_djf_ens_cmip5, **pp) )
iplot(mp)
req_cmip5_extent = ds(project='CMIP5_extent', variable='tas', experiment='historical',
model='*', period='1990-2010', table='Amon', version='latest')
ens_cmip5_extent = req_cmip5_extent.explore('ensemble')
ok_ens_cmip5_extent = ens_cmip5_extent.copy()
for elt in ens_cmip5_extent:
print elt
# -- Apply the time consistency check
if not check_time_consistency_CMIP(ens_cmip5_extent[elt]):
# -- And remove the elements that do not pass the test
print 'period not covered for ',elt
ok_ens_cmip5_extent.pop(elt)
ok_ens_cmip5_extent
new_member = ds(project='ref_ts', variable='tos', product='HadISST')
ok_new_member = new_member.explore('resolve')
summary(ok_new_member)
ok_ens_cmip5_extent.update(dict(HadISST=ok_new_member))
ok_ens_cmip5_extent
ok_ens_cmip5_extent.order
# -- We will put HadISST first, and sort the models in alphabetical order
tmp_members = ok_ens_cmip5_extent.order
# -- Remove HadISST from the list
tmp_members.remove('HadISST')
new_order = ['HadISST'] + sorted(tmp_members)
new_order
ok_ens_cmip5_extent.set_order(new_order)
ok_ens_cmip5_extent.order
req_dict = dict(project='CMIP6',
model='IPSL-CM6A-LR',
experiment='historical',
variable='tas',
table='Amon')
m1 = ds(period='1980-1989', **req_dict)
m2 = ds(period='1990-1999', **req_dict)
m3 = ds(period='2000-2009', **req_dict)
print m1.explore('choices')
print m2.explore('choices')
print m3.explore('choices')
ens_by_decades_r1i1p1f1 = cens( {'CMIP6_1980-1989': m1.explore('resolve'),
'CMIP6_1990-1999': m2.explore('resolve'),
'CMIP6_2000-2009': m3.explore('resolve')
},
order=['CMIP6_1980-1989', 'CMIP6_1990-1999', 'CMIP6_2000-2009']
)
ens_by_decades_r1i1p1f1
ens_by_decades_r1i1p1f1.order
hist_req = ds(project='CMIP5', experiment='historical', period='1980-2000',
model='*', variable='tas', frequency='monthly', version='latest')
rcp85_req = ds(project='CMIP5', experiment='rcp85', period='2040-2060',
model='*', variable='tas', frequency='monthly', version='latest')
print 'explore("choices") for request on historicals = '
print hist_req.explore('choices')
print '--'
print '--'
print 'explore("choices") for request on rcp85 = '
print rcp85_req.explore('choices')
print '--'
print '--'
# -- First, we build the two 'raw' ensembles
hist_tmp_ens = hist_req.explore('ensemble')
rcp85_tmp_ens = rcp85_req.explore('ensemble')
# -- and then we use ensemble_intersection to get the same ensembles but only
# with the members they have in common
hist_ensemble, rcp85_ensemble = ensemble_intersection([hist_tmp_ens, rcp85_tmp_ens])
print hist_ensemble.keys()
print rcp85_ensemble.keys()
# -- and then we use ensemble_intersection to get the same ensembles but only
# with the members they have in common
hist_tmp_ens2 = hist_tmp_ens.copy() # -- we make a trivial third ensemble just for the example
list_of_ensembles = ensemble_intersection([hist_tmp_ens, rcp85_tmp_ens, hist_tmp_ens2])
hist_ensemble = list_of_ensembles[0]
rcp85_ensemble = list_of_ensembles[1]
hist2_ensemble = list_of_ensembles[2]
Merging ensembles can be very useful if you want to make the same treatment on all the members. Let's say that you have a climatology over the historical period for an ensemble, and a climatology in a scenario, and that you want to retrieve all the pretreated files.
This example is the preparation for last point: get the path/filenames of all the pretreated members ready to be used in my favourite script without having to plug my script in CliMAF.
renamed_hist_ensemble = add_prefix_suffix_to_ens_req(hist_ensemble, suffix='_hist')
renamed_rcp85_ensemble = add_prefix_suffix_to_ens_req(rcp85_ensemble, suffix='_rcp85')
renamed_hist_ensemble.keys()
renamed_rcp85_ensemble.keys()
total_ensemble = merge_climaf_ensembles([renamed_hist_ensemble, renamed_rcp85_ensemble])
total_ensemble.keys()
# -- And save a json file (or txt) with the list of pretreated netcdf files tagged with their names in the ensemble
# -- This way you don't have to stay in CliMAF and can use your tools directly on the pretreated files
save_req_file(total_ensemble, filename='my_list_of_files.txt')
!cat my_list_of_files.txt
save_req_file(total_ensemble, filename='my_list_of_files.json')
!cat my_list_of_files.json
For the available operators, we invite you to go deeper in CliMAF documentation and other CliMAF notebooks.