CAMMAC https://cammac.readthedocs.io

S.Sénési for Météo-France - sept 2019 to march 2021

Build a figure showing change for a (plain or derived) variable, for three SSPs and two seasons

Parameters stand in first cell, are either commented here or in the doc (see above)

A few commands below are specific to the Notebook environment, and have no effect in pure Python

Default settings (some may be overriden by Papermill - this would show in next cell in the execution output notebook)

In [ ]:
import os
figure_title           = None  # if None, an automatic title will be generated
auto_title_prefix      = "Seasonal"
#
figure_name            = "Fig8-19" # Used for a symbolic link to an explicit filename,and for metadata filename
# Version number will be a suffix for figure filename. Use e.g. "_V1" for legibility
version                = ""
scheme                 = "AR5"
confidence_factor    = 1.645  # For AR6 comprehensive scheme : Multiplicative factor applied to control run 
                              # variability for deciding a change is significant (besides sqrt(2))
sign_threshold       = 0.66   # For AR6 and AR6S schemes : threshold on cross-model change sign agreeement fraction
same_models_for_var    = False

#See doc for data_versions in sibling directory data_versions
data_versions_tag      = "20200719"
data_versions_dir      = os.getenv("CAMMAC")+"/data"
excluded_models        = []
included_models        = None # If a list is provided, only these models may be used
variability_models     = None
variability_excluded_models = []
variability_sampling_args={"house_keeping":True,"compute":True,"detrend":True,"shift":100,"nyears":20,"number":20}

#
variable               = "mrso"
threshold              = None 
table                  = "Lmon"
field_type             = "mean_schange" # Any type of field as documented in function CAMMAClib.changes.change_fields
derivation_label       = "plain"        # Can plot the change of the raw variable, or its variability, or ... see CAMMAClib.changes.derivations
custom_plot            = {"colors": "-5 -2 -1 -0.5 -0.25 0. 0.25 0.5 1 2 5", "units":"-", "color":"AR6_Precip_12"}  # Should be tuned, usually
#
seasons                = ["DJF","JJA"]  # any CDO season, and/or "ANN". Figure is tuned for a pair of seasons
experiments            = ["ssp126","ssp245","ssp585"] # Figure is tuned for three experiments
proj_period            = "2081-2100"
ref_experiment         = "historical"
ref_period             = "1995-2014"  

#
# If pre-computed fields for these SSPs, seasons and projection_period are available, should we use it ?
# Set it to False for recomputing either :
#   - for printing fields and field changes statistics
#   - or if any external script launched by CliMAF was internally changed
use_cached_proj_fields = True   
drop_old_figures       = False
print_statistics       = True

# If some basic fields are to be plotted for each model :

#   - which fields should be actually plotted
# plot_for_each_model    = [ "reference", "projection", "change", "rchange", "schange", "variability" ]
plot_for_each_model    = [ ]

#   - and with which common plot_parameters
custom_plot_all_fields = { "proj" : "Robinson", "mpCenterLonF" : 0., "options" : "lbBoxEndCapStyle=TriangleBothEnds", "focus":"land"}
all_models_page_args   = {"page_width":3675,"page_height":5188,"insert_width":2000,"pt":48, "ybox":133,"y":52}

#   - and which range should be used
ranges = {}   # The baseline value !
# Values below fit the case of mrso
#ranges={ "reference" : { "min" : 0., "max" : 3000. , "delta" : 200. } ,
#        "projection" : { "min" : 0., "max" : 3000. , "delta" : 200. } ,
#        "change"     : { "min" :1000.,"max":-1000. , "delta":200.} , 
#        "rchange"    : { "min" : -25., "max" : 25. , "delta" : 5. } ,
#        "schange"    : { "colors": "-5 -2 -1 -0.5 -0.25 0. 0.25 0.5 1 2 5"  , "units":"-", "color":"AR6_Precip_12" } , 
#        "variability": { "min" : 0., "max" : 1. , "delta" : 0.1 } ,
#       }
#
outdir                 = "./figures"
cache_dir              = "./cache"
figure_details         = {"page_width":2450,"page_height":3444, "insert_width":1800,"pt":48, "ybox":133,"y":52}
common_grid            = "r360x180"
# Should we apply a mask to the figures (grid must fit with 'common_grid')
figure_mask            = None
#figure_mask            = CAMMAC+"/data/mask_hide_antarctic_360x180.nc"

do_test                = True
In [ ]:
if do_test :
    version             = "_test"
    proj_period         = "2100"
    ref_period          = "2014" 
    included_models     = ["CNRM-CM6-1"]    
    seasons             = ["DJF","DJF"]  
    experiments         = ["ssp126","ssp126","ssp126"] 
    figure_mask         = os.getenv("CAMMAC")+"/data/mask_hide_antarctic_360x180.nc"
    variability_sampling_args={"house_keeping":False,"compute":True,"detrend":True,"shift":100,"nyears":3,"number":3}

    #variability_sampling_args={}
    variability_models  = included_models
    #variability_excluded_models = []
    use_cached_proj_fields = False   


    #plot_for_each_model    = [ "reference", "projection", "change", "rchange", "schange", "variability" ]

Load libraries

In [ ]:
import sys

from climaf.api import *
climaf.cache.stamping=False
climaf.driver.dig_hard_into_cache = False

from CAMMAClib.changes    import change_figure_with_caching
from CAMMAClib.ancillary  import create_labelbar, prettier_label
from CAMMAClib.mips_et_al import TSU_metadata, read_versions_dictionnary

# Load some user settings, if available
settings_file=os.getenv("CAMMAC_USER_PYTHON_CODE_DIR",".")+'/cammac_user_settings.py'
if os.path.exists(settings_file) :
    exec(compile(open(settings_file).read(),settings_file,'exec'))

If using a notebook, use wide display

In [ ]:
from IPython.core.display import display, HTML, Image
display(HTML("<style>.container { width:100% !important; }</style>"))

The basic engine is function change_figure_with_caching, which has numerous settings (use 'help(change_figure_with_caching)')

Next function allows to set most values with global variables, the others with its arguments values

In [ ]:
def afigure(experiment,season, title=None ,labelbar="False",outfile=None,threshold=threshold):
    fil,fig,dic,variab_models,used_models= change_figure_with_caching(
        variable,experiment,season,
        data_versions_tag=data_versions_tag, data_versions_dir=data_versions_dir,
        models=included_models, excluded_models=excluded_models,
        variability_models=variability_models, variability_excluded_models=variability_excluded_models,
        ref_period=ref_period, proj_period=proj_period, 
        table=table, ref_experiment=ref_experiment, 
        derivation_label=derivation_label, field_type=field_type,
        title=title, 
        custom_plot=custom_plot, labelbar=labelbar, 
        outdir=outdir, outfile=outfile,
        #
        common_grid=common_grid, mask=figure_mask,
        variab_sampling_args=variability_sampling_args,
        cache_dir=cache_dir, print_statistics=print_statistics,
        deep=None,  read=use_cached_proj_fields, write=True,
        threshold = threshold, scheme=scheme, 
        same_models_for_variability_and_changes=same_models_for_var,
        low_change_agree_threshold=confidence_factor,
        change_sign_agree_threshold = sign_threshold,
        drop=drop_old_figures)
    csync()
    return fig,dic,variab_models,used_models

Compute figures for the three experiments and two seasons

In [ ]:
figs=dict()
dics=dict()
number=0
letters=["a","b","c","d","e","f"]
metadata=""
data_versions=read_versions_dictionnary(data_versions_tag, data_versions_dir)

if len(plot_for_each_model) > 0 :
    use_cached_proj_fields = False

for exp in experiments :
    figs[exp]=dict()
    dics[exp]=dict()
    for season in seasons:
        dics[exp][season]=dict()
        title="(%s) %s %s"%(letters[number],prettier_label.get(exp,exp),season)
        #
        figs[exp][season],dic,variab_models,models = afigure(exp,season,title=title)
        #
        if not use_cached_proj_fields :
            dics[exp][season].update(dic[exp][season])
        metadata += TSU_metadata([ref_experiment,exp],models       ,variable,table,data_versions,letters[number])
        metadata += TSU_metadata(["piControl"]       ,variab_models,variable,table,data_versions,letters[number])
        #cdrop(figs[exp][season])
        number+=1

Write the metadata file

In [ ]:
import os.path
if not os.path.exists(outdir):
    os.makedirs(outdir)
with open("%s/%s%s_md.txt"%(outdir,figure_name,version),"w") as f:
        f.write(metadata)

Create the common labelbar and assemble it with plots

In [ ]:
# create a figure wih labelbar (using same plot settings as for figures above)
labelbar_figure=afigure(experiments[0],seasons[0],labelbar="True",
                        outfile="./fig_with_label.png",threshold=threshold)

# Call utility function for extracting labelbar and adding fill pattern for shadings
create_labelbar("./fig_with_label.png", "./insert.png",missing=False,scheme=scheme)

if figure_title is None :
    figure_title="%s %s for %s (%s vs %s)"%(auto_title_prefix,prettier_label.get(field_type,field_type),prettier_label[variable],proj_period,ref_period)

# Create multi-panel figure
page=cpage([
    [figs[experiments[0]][seasons[0]],figs[experiments[0]][seasons[1]]],
    [figs[experiments[1]][seasons[0]],figs[experiments[1]][seasons[1]]],
    [figs[experiments[2]][seasons[0]],figs[experiments[2]][seasons[1]]]],
    title=figure_title,
    insert="./insert.png",
    **figure_details
    )
#
outfile="%s_change_3SSPS_2seasons_%s_%s%s.png"%(variable,proj_period,data_versions_tag,version)
if drop_old_figures : cdrop(page)
cfile(page,outdir+"/"+outfile)
os.system("cd %s ; ln -sf %s %s%s.png"%(outdir,outfile,figure_name,version))
#
small=outfile.replace(".png",".small.png")
os.system("cd %s ; convert -geometry 50%% %s %s"%(outdir,outfile,small))
os.system("cd %s ; ln -sf %s %s%s_small.png"%(outdir,small,figure_name,version))
#
os.system("rm ./insert.png")
os.system("rm ./fig_with_label.png")

If using a notebook , display result on-line

In [ ]:
#Image(outdir+"/"+outfile,width=800)

dic[experiment][season][key][derivation_label][model] where key has values : reference, projection, change, rchange, schange, variability

Plotting all models for all field types and all cases

In [ ]:
for field_type in plot_for_each_model :
    #
    plotargs=custom_plot_all_fields.copy()
    plotargs.update(ranges.get(field_type,{}))
    #
    for experiment in experiments : 
        for season in seasons :
            allplots=plot(cens(dics[experiment][season][field_type][derivation_label]),**plotargs)
            title=title="%s_%s_%s_%s_%s"%(variable,derivation_label,field_type,experiment,season)
            page=cpage(allplots,title=title,**all_models_page_args)
            cdrop(page)
            pagename="%s/all_models_%s_%s_%s_%s_%s_%s.png"%(outdir,variable,derivation_label,field_type,experiment,season,data_versions_tag)
            cfile(page,pagename)