diff --git a/esmvaltool/diag_scripts/perfmetrics/collect.ncl b/esmvaltool/diag_scripts/perfmetrics/collect.ncl index 15fdd5bbdf..199b4c2a85 100644 --- a/esmvaltool/diag_scripts/perfmetrics/collect.ncl +++ b/esmvaltool/diag_scripts/perfmetrics/collect.ncl @@ -8,7 +8,7 @@ ; portrait_plot or to the taylor function ; ; Required diag_script_info attributes -; metric: selected metric (RMSD, BIAS or taylor) +; metric: selected metric (RMSD, BIAS, SMPI or taylor) ; label_bounds (for RMSD and BIAS): min and max of the labelbar ; label_scale (for RMSD and BIAS): bin width of the labelbar ; colormap (for RMSD and BIAS): color table of the labelbar @@ -78,121 +78,303 @@ begin f = addfile(input_files(ii), "r") curr_file = tostring(f->temp_list) - data_temp = ncdf_read(curr_file, "grade") - ; Change to 3 dimensional - if (dimsizes(dimsizes(data_temp)).eq.2) then + if diag_script_info@metric.eq."SMPI" then + data_temp_smpi = ncdf_read(curr_file, "performance_index") - dim_temp = array_append_record(dimsizes(data_temp), 2, 0) - temp = new(dim_temp, typeof(data_temp)) - temp(:, :, 0) = data_temp - data_temp := temp - delete(temp) + if (.not.isdefined("data_all_smpi")) then - end if + dim_temp_smpi = dimsizes(data_temp_smpi) + n = dimsizes(dim_temp_smpi) + dim_data_smpi = new(n + 1, integer) + dim_data_smpi(0) = dimsizes(input_files) + dim_data_smpi(1:n) = dim_temp_smpi + vars = new(dimsizes(input_files), string) + data_all_smpi = new(dim_data_smpi, float) + delete(dim_data_smpi) + data_all_smpi(0, :, :) = data_temp_smpi + data_all_smpi!0 = "vars" + data_all_smpi!1 = "bootstrap_member" + data_all_smpi!2 = "models" + data_all_smpi&models = data_temp_smpi&models + data_all_smpi&bootstrap_member = data_temp_smpi&bootstrap_member - ; Create array for collecting all datasets - if (.not.isdefined("data_all")) then - dim_temp = dimsizes(data_temp) - dim_data = (/dimsizes(input_files), dim_temp(1), 2/) - data_all = new(dim_data, float) - data_all(0, :, :) = data_temp - data_all!1 = "models" - data_all&models = data_temp&models - end if + i_climo_cnt = 0 + + end if ; Make sure dataset coordinate is consistent - consistent = False - if (dimsizes(data_temp&models).eq.dimsizes(data_all&models)) then - if (all(data_temp&models.eq.data_all&models)) then - consistent = True + consistent = False + if (dimsizes(data_temp_smpi&models).eq. \ + dimsizes(data_all_smpi&models)) then + if (all(data_temp_smpi&models.eq.data_all_smpi&models)) then + consistent = True + end if end if - end if ; Append data - if (consistent) then - data_all(ii, :, :) = (/data_temp/) - copy_VarCoords(data_temp, data_all(ii:ii, :, :)) - else - do imod2 = 0, dimsizes(data_temp&models) - 1 - if (.not.any(data_temp&models(imod2).eq.data_all&models)) then - ; Append record for dataset(imod) - data_new = extend_var_at(data_all, 1, dimsizes(data_all&models)) - data_new(ii, dimsizes(data_all&models), :) = \ - (/data_temp(0, imod2, :)/) - data_new&models(dimsizes(data_all&models)) = \ - (/data_temp&models(imod2)/) - data_all := data_new - delete(data_new) - else - ; Loop over datasets of data - do imod = 0, dimsizes(data_all&models) - 1 - ; if no data dataset is similar to curreny entry, write data entry - if (data_all&models(imod).eq. data_temp&models(imod2)) then + if (consistent) then + data_all_smpi(ii, :, :) = (/data_temp_smpi/) + copy_VarCoords(data_temp_smpi, data_all_smpi(ii, :, :)) + else + ; Loop over datasets in new data entry + do imod_temp = 0, dimsizes(data_temp_smpi&models) - 1 + ; If current dataset is not already part of the model coordinate + if (.not.any(data_temp_smpi&models(imod_temp) .eq. \ + data_all_smpi&models)) then + ; Append record for dataset(imod) + data_new = extend_var_at(data_all_smpi, 2, \ + dimsizes(data_all_smpi&models)) + data_new(ii, :, dimsizes(data_all_smpi&models)) = \ + (/data_temp_smpi(0, :, imod_temp)/) + data_new&models(dimsizes(data_all_smpi&models)) = \ + (/data_temp_smpi&models(imod_temp)/) + delete(data_all_smpi) + data_all_smpi = data_new + delete(data_new) + else + ; Loop over datasets of data + do imod = 0, dimsizes(data_all_smpi&models) - 1 + ; if new dataset is identical to current + ; entry, write data entry + if (data_all_smpi&models(imod).eq. \ + data_temp_smpi&models(imod_temp)) then + data_all_smpi(ii, :, imod) = \ + (/data_temp_smpi(0, :, imod_temp)/) + copy_VarCoords( \ + data_temp_smpi(0:0, :, imod_temp), \ + data_all_smpi(ii:ii, :, imod)) + end if + end do + end if + end do + end if + + do iclim = 0, toint(data_temp_smpi@num_climofiles) - 1 + num_climo = "climofile_" + iclim + num_climo_all = "climofile_" + (i_climo_cnt + iclim) + data_all_smpi@$num_climo_all$ = data_temp_smpi@$num_climo$ + end do + + i_climo_cnt = i_climo_cnt + toint(data_temp_smpi@num_climofiles) + + vars(ii) = data_temp_smpi@invar + delete(data_temp_smpi) + + else ; Metric not SMPI + data_temp = ncdf_read(curr_file, "grade") + + ; Change to 3 dimensional + if (dimsizes(dimsizes(data_temp)).eq.2) then + + dim_temp = array_append_record(dimsizes(data_temp), 2, 0) + temp = new(dim_temp, typeof(data_temp)) + temp(:, :, 0) = data_temp + data_temp := temp + delete(temp) + + end if + + ; Create array for collecting all datasets + if (.not.isdefined("data_all")) then + dim_temp = dimsizes(data_temp) + dim_data = (/dimsizes(input_files), dim_temp(1), 2/) + data_all = new(dim_data, float) + data_all(0, :, :) = data_temp + data_all!1 = "models" + data_all&models = data_temp&models + end if + + ; Make sure model coordinate is consistent + consistent = False + if (dimsizes(data_temp&models).eq.dimsizes(data_all&models)) then + if (all(data_temp&models.eq.data_all&models)) then + consistent = True + end if + end if + + ; Append data + if (consistent) then + data_all(ii, :, :) = (/data_temp/) + copy_VarCoords(data_temp, data_all(ii:ii, :, :)) + else + do imod2 = 0, dimsizes(data_temp&models) - 1 + if (.not.any(data_temp&models(imod2).eq.data_all&models)) then + ; Append record for dataset(imod) + data_new = extend_var_at(data_all, 1, dimsizes(data_all&models)) + data_new(ii, dimsizes(data_all&models), :) = \ + (/data_temp(0, imod2, :)/) + data_new&models(dimsizes(data_all&models)) = \ + (/data_temp&models(imod2)/) + data_all := data_new + delete(data_new) + else + ; Loop over datasets of data + do imod = 0, dimsizes(data_all&models) - 1 + ; if no dataset is similar to curreny entry, write data entry + if (data_all&models(imod).eq. data_temp&models(imod2)) then data_all(ii, imod, :) = (/data_temp(0, imod2, :)/) copy_VarCoords(data_temp(0:0, imod2, :), \ data_all(ii:ii, imod, :)) + end if + end do + end if + end do + end if + delete(data_temp) + end if ; metric distinction end 1 + end do + + if diag_script_info@metric.eq."SMPI" then + data_all_smpi&vars = vars + delete(vars) + + data_all_smpi@num_climofiles = i_climo_cnt + + ; Check for incomplete array, SMPI only for datasets with all vars + if any(ismissing(data_all_smpi)) then + do ivar = 0, dimsizes(data_all_smpi&vars) - 1 + do ii = 0, dimsizes(data_all_smpi&models) - 1 + if all(ismissing(data_all_smpi(ivar, :, ii))) then + if (isvar("miss_mods")) then + newmm = array_append_record(miss_mod, \ + data_all_smpi&models(ii), 0) + delete(miss_mod) + miss_mod = newmm + delete(newmm) + else + miss_mod = data_all_smpi&models(ii) end if - end do + end if + end do + if (isvar("miss_mods")) then + log_info("Variable " + data_all_smpi&vars(ivar) \ + + " is missing dataset(s) " \ + + str_join(miss_mods, ", ")) + delete(miss_mods) + missing_mods = True end if end do + if (isvar("missing_mods")) then + error_msg("f", diag_script, "", "SMPI only supported for" \ + + " datasets containing all variables") + end if end if - delete(data_temp) - end do - ; Reduce size if all entries have only one reference - if (all(ismissing(data_all(:, :, 1)))) then - data_new = data_all(:, :, 0) - delete(data_all) - data_all = data_new - delete(data_new) - end if - delete(data_all@var) - delete(data_all@title) - delete(data_all@ncdf_dir) - if (isatt(data_all, "reference")) then - delete(data_all@reference) - end if + i2mean = dim_avg_n(data_all_smpi, 0) ; eq. 3 + dims = dimsizes(i2mean) + nboot = dims(0) - 1 + nmod = dims(1) + delete(dims) - ; Sort datasets in alphabetical order, excluding multi-model mean/median - ; which are placed at the beginning - if (isatt(diag_script_info, "sort")) then - if (diag_script_info@sort) then - idx = ind(data_all&models.eq."MultiModelMean" .or. \ - data_all&models.eq."MultiModelMedian") - pid = sort_alphabetically(data_all&models, idx, "begin") - if (dimsizes(dimsizes(data_all)).eq.3) then - data_all := data_all(:, pid, :) - else - data_all := data_all(:, pid) + data_smpi = new((/dimsizes(data_all_smpi&models), 2/), float) + data_smpi!0 = "models" + data_smpi&models = data_all_smpi&models + data_smpi(:, 0) = (/i2mean(0, :)/) ; clim. mean + + i5 = toint(0.05 * nboot) + i95 = toint(0.95 * nboot) + + do imod = 0, nmod - 1 + data_sorted = i2mean(1:nboot, imod) + qsort(data_sorted) + data_smpi(imod, 1) = 0.5 * (data_sorted(i95) - data_sorted(i5)) + delete(data_sorted) + end do + + data_smpi!1 = "statistic" + data_smpi&statistic = (/"SMPI", "95_conf"/) + name = "" ; str_sub_str(xml_name, suffix, "") + data_smpi@ncdf_dir = config_user_info@work_dir + "/" + \ + name + "_SMPI.nc" + data_smpi@diag_script = diag_script + data_smpi@var = "SMPI" + data_smpi@ensemble_name = data_all_smpi@ensemble_name + ; Create outfile directory + system("mkdir -p " + config_user_info@work_dir) + ncdf_outfile = ncdf_write(data_smpi, data_smpi@ncdf_dir) + + ; Sort datasets in alphabetical order (exclude MMM and set to end) + + pid = sort_alphabetically(data_smpi&models, \ + ind(data_smpi&models.eq."Mean-model".or. \ + data_smpi&models.eq."Median-model"), "end") + tmp = data_smpi(pid, :) + tmp&models = data_smpi&models(pid) + delete(data_smpi) + data_smpi = tmp + delete(tmp) + delete(pid) + + ; Attach plotting options + copy_VarAtts(diag_script_info, data_smpi) + if (isatt(diag_script_info, "title")) then + data_smpi@res_tiMainString = diag_script_info@title + end if + + ; Create outfile directory + system("mkdir -p " + config_user_info@plot_dir) + diags = "test" + + ; Define outfile name + outfile_plot = config_user_info@plot_dir + diags + "_SMPI" + + else ; if metric not SMPI + + ; Reduce size if all entries have only one reference + if (all(ismissing(data_all(:, :, 1)))) then + data_new = data_all(:, :, 0) + delete(data_all) + data_all = data_new + delete(data_new) + end if + delete(data_all@var) + delete(data_all@title) + delete(data_all@ncdf_dir) + if (isatt(data_all, "reference")) then + delete(data_all@reference) + end if + + ; Sort datasets in alphabetical order, excluding multi-model mean/median + ; which are placed at the beginning + if (isatt(diag_script_info, "sort")) then + if (diag_script_info@sort) then + idx = ind(data_all&models.eq."MultiModelMean" .or. \ + data_all&models.eq."MultiModelMedian") + pid = sort_alphabetically(data_all&models, idx, "begin") + if (dimsizes(dimsizes(data_all)).eq.3) then + data_all := data_all(:, pid, :) + else + data_all := data_all(:, pid) + end if + delete(pid) end if - delete(pid) end if - end if - ; Attach plotting options - copy_VarAtts(diag_script_info, data_all) - if (isatt(diag_script_info, "title")) then - data_all@res_tiMainString = diag_script_info@title - end if - if (diag_script_info@metric.eq."taylor") then - data_all@res_varLabels = data_all&models - data_all@res_caseLabels = data_all&diagnostics - end if + ; Attach plotting options + copy_VarAtts(diag_script_info, data_all) + if (isatt(diag_script_info, "title")) then + data_all@res_tiMainString = diag_script_info@title + end if + if (diag_script_info@metric.eq."taylor") then + data_all@res_varLabels = data_all&models + data_all@res_caseLabels = data_all&diagnostics + end if - ; Create outfile directory - system("mkdir -p " + config_user_info@plot_dir) - if (dimsizes(data_all&diagnostics).gt.1) then - diags = data_all&diagnostics(0) + "_to_" + \ - data_all&diagnostics(dimsizes(data_all&diagnostics) - 1) - else - diags = str_concat(data_all&diagnostics) - end if + ; Create outfile directory + system("mkdir -p " + config_user_info@plot_dir) + if (dimsizes(data_all&diagnostics).gt.1) then + diags = data_all&diagnostics(0) + "_to_" + \ + data_all&diagnostics(dimsizes(data_all&diagnostics) - 1) + else + diags = str_concat(data_all&diagnostics) + end if - ; Define outfile name - outfile_plot = config_user_info@plot_dir + diags - if (isatt(data_all, "metric")) then - outfile_plot = outfile_plot + "_" + data_all@metric + ; Define outfile name + outfile_plot = config_user_info@plot_dir + diags + if (isatt(data_all, "metric")) then + outfile_plot = outfile_plot + "_" + data_all@metric + end if end if ; Create workspace @@ -204,9 +386,13 @@ begin ; Call plotting function if (diag_script_info@metric.eq."taylor") then plot = taylor_plot(wks, data_all, "grade") + else if (diag_script_info@metric.eq."SMPI") then + plot = circle_plot(wks, data_smpi, "performance_index", \ + data_smpi@ensemble_name) else plot = portrait_plot(wks, data_all, "grade") end if + end if log_info(" gv " + outfile_plot + "." + file_type) diff --git a/esmvaltool/diag_scripts/perfmetrics/cycle_latlon.ncl b/esmvaltool/diag_scripts/perfmetrics/cycle_latlon.ncl index 4a5d32ed79..25963689bd 100644 --- a/esmvaltool/diag_scripts/perfmetrics/cycle_latlon.ncl +++ b/esmvaltool/diag_scripts/perfmetrics/cycle_latlon.ncl @@ -102,6 +102,14 @@ begin taylor(0, locidx, 1) = \ calculate_metric(var_all(:, :, :, 0), var_ref(:, :, :, 0), \ "correlation") + else if (diag_script_info@metric(met).eq."SMPI") then + locidx = ind(datasetnames(imod).eq.smpi&models) + if (ismissing(locidx)) then + continue + end if + smpi(:, locidx) = \ + (/calculate_metric(var_all(:, :, :, 0), var_ref(:, :, :, 0), \ + "SMPI")/) else locidx = ind(datasetnames(imod).eq.grading&models) if (ismissing(locidx)) then @@ -116,9 +124,9 @@ begin diag_script_info@metric(met)) end if end if + end if end do - end do end diff --git a/esmvaltool/diag_scripts/perfmetrics/cycle_zonal.ncl b/esmvaltool/diag_scripts/perfmetrics/cycle_zonal.ncl new file mode 100644 index 0000000000..2c39e8b750 --- /dev/null +++ b/esmvaltool/diag_scripts/perfmetrics/cycle_zonal.ncl @@ -0,0 +1,131 @@ +; ############################################################################# +; PROCEDURE FOR THE CYCLE-ZONAL PLOT OF THE PERFORMANCE METRICS +; Authors: Mattia Righi (DLR, Germany) and Franziska Frank (DLR, Germany) +; ESMVal project +; ############################################################################# + +procedure perfmetrics_ptype_script() +begin + + ; Set dataset indexes, with reference and alternative datasets first + modidx = ispan(0, dim_MOD - 1, 1) + if (l_altern) then + modidx := array_append_record( \ + (/ref_ind, alt_ind/), \ + modidx(ind(modidx.ne.ref_ind .and. modidx.ne.alt_ind)), 0) + else + modidx := array_append_record(ref_ind, modidx(ind(modidx.ne.ref_ind)), 0) + end if + + ; Loop over datasets + do ii = 0, dimsizes(modidx) - 1 + + imod = modidx(ii) + + log_debug("Processing " + datasetnames(imod)) + + ; Set path for saving processed data ; FIX-ME add preproc_id + fullpath = config_user_info@work_dir + "/" + system("mkdir -p " + fullpath) + fname = basename(systemfunc("basename " + dataset_info@filename(imod))) + fname = fname + "_" + basename(diag_script) + "_cycle_latlon" + fname = fname + "_" + diag_script_info@time_avg + if (isatt(diag_script_info, "level")) then + fname = fname + "_" + diag_script_info@level ; FIX-ME + end if + fname = fname + "_" + str_sub_str(diag_script_info@region, " ", "") + procpath = fullpath + fname + ".nc" + + ; Determine start/end year + start_year = get_start_year(imod) + end_year = get_end_year(imod) + + ; Read data + var = read_data(imod, var0, field_type0) + dnames = getVarDimNames(var) + + ; Calculate zonal mean + var_reg = dim_avg_Wrap(var) + delete(var) + + ; Calculate time average + var_avg = time_operations(var_reg, start_year, end_year, "average", \ + diag_script_info@time_avg, True) + delete(var_reg) + + ; Standard deviation calculation for this ptype is not yet implemented in + ; diag_scripts/shared/statistics.ncl, but is anyway not required here + + ; Write output + var_all = new(array_append_record(dimsizes(var_avg), 2, 0), float) + var_all!3 = "statistic" + var_all&statistic = (/"mean", "stddev"/) + var_all(:, :, :, 0) = var_avg + var_all@var = var0 + var_all@diag_script = (/diag_script/) + copy_VarAtts(diag_script_info, var_all) + var_all@ref_model = variable_info@reference_dataset + if (config_user_info@write_netcdf.eq."True") then + var_all@ncdf = procpath + ncdf_outfile = ncdf_write(var_all, procpath) + end if + + ; Calculate grading + if (.not.diag_script_info@calc_grading) then + continue + end if + + ; Store reference dataset + if (imod.eq.ref_ind) then + var_ref = var_all + end if + + ; Store alternative dataset + if (l_altern) then + if (imod.eq.alt_ind) then + var_alt = var_all + end if + end if + + ; Loop over requested metrics + do met = 0, nmetrics - 1 + + if (diag_script_info@metric(met).eq."taylor") then + locidx = ind(datasetnames(imod).eq.taylor&models) + if (ismissing(locidx)) then + continue + end if + taylor(0, locidx, 0) = \ + calculate_metric(var_all(:, :, :, 0), var_ref(:, :, :, 0), \ + "stddev_ratio") + taylor(0, locidx, 1) = \ + calculate_metric(var_all(:, :, :, 0), var_ref(:, :, :, 0), \ + "correlation") + else if (diag_script_info@metric(met).eq."SMPI") then + locidx = ind(datasetnames(imod).eq.smpi&models) + if (ismissing(locidx)) then + continue + end if + smpi(:, locidx) = \ + (/calculate_metric(var_all(:, :, :, 0), var_ref(:, :, :, 0), \ + "SMPI")/) + else + locidx = ind(datasetnames(imod).eq.grading&models) + if (ismissing(locidx)) then + continue + end if + grading(met, 0, locidx, 0) = \ + calculate_metric(var_all(:, :, :, 0), var_ref(:, :, :, 0), \ + diag_script_info@metric(met)) + if (l_altern) then + grading(met, 0, locidx, 1) = \ + calculate_metric(var_all(:, :, :, 0), var_alt(:, :, :, 0), \ + diag_script_info@metric(met)) + end if + end if + end if + + end do + + end do +end diff --git a/esmvaltool/diag_scripts/perfmetrics/main.ncl b/esmvaltool/diag_scripts/perfmetrics/main.ncl index 515891c9b9..162f4bc473 100644 --- a/esmvaltool/diag_scripts/perfmetrics/main.ncl +++ b/esmvaltool/diag_scripts/perfmetrics/main.ncl @@ -111,7 +111,8 @@ begin ; Store required attributes ptype = diag_script_info@plot_type - if (all(ptype.ne.(/"cycle", "zonal", "latlon", "cycle_latlon"/))) then + if (all(ptype.ne.(/"cycle", "zonal", "cycle_zonal", \ + "latlon", "cycle_latlon"/))) then error_msg("f", DIAG_SCRIPT, "", "plot_type " + ptype + " is not a " + \ "supported plot_type in this diagnostic") end if @@ -129,14 +130,14 @@ begin end if ; Check valid field - if ((ptype.eq."zonal" .and. \ + if (((ptype.eq."zonal" .or. ptype.eq."cycle_zonal") .and. \ all(field0.ne.(/"T3M", "T2Mz"/))) .or. \ (ptype.eq."cycle" .and. \ all(field0.ne.(/"T3M", "T2Ms", "T1M", "T0Ms"/))) .or. \ (ptype.eq."latlon" .and. \ - all(field0.ne.(/"T3M", "T2Ms"/))) .or. \ + all(field0.ne.(/"T3M", "T2Ms", "TO2Ms"/))) .or. \ (ptype.eq."cycle_latlon" .and. \ - all(field0.ne.(/"T3M", "T2Ms"/)))) then + all(field0.ne.(/"T3M", "T2Ms", "TO2Ms"/)))) then error_msg("f", DIAG_SCRIPT, "", "input field " + field0 + \ " is not compatible with plot_type " + ptype) end if @@ -170,6 +171,13 @@ begin error_msg("f", DIAG_SCRIPT, "", "normalization must be " + \ "provided for each requested metric") end if + if (any(diag_script_info@metric.eq."SMPI") .and. \ + diag_script_info@range_option.eq.0) then + error_msg("f", diag_script, "", "Currently Single Model " + \ + "Performance Index is only supported for time periods of " + \ + "the same length for all datasets") + end if + end if ; Set dataset names @@ -266,6 +274,16 @@ begin taylor&models = remove_index(datasetnames, ref_ind) end if + ; Special case SMPI + if (any(diag_script_info@metric.eq."SMPI")) then + nmodels = dimsizes(datasetnames) - 1 ; always 1 reference model + smpi = new((/diag_script_info@smpi_n_bootstrap + 1, nmodels/), float) + smpi!0 = "bootstrap_member" + smpi!1 = "models" + smpi&bootstrap_member = ispan(0, diag_script_info@smpi_n_bootstrap, 1) + smpi&models = remove_index(datasetnames, ref_ind) + end if + ; Define grading filename do met = 0, nmetrics - 1 ncdf_dir(met) = config_user_info@work_dir + "/" + \ @@ -296,7 +314,8 @@ begin end if ; Apply normalization - if (diag_script_info@metric(met).ne."taylor") then + if (diag_script_info@metric(met).ne."taylor" .and. \ + diag_script_info@metric(met).ne."SMPI") then do iobs = 0, nobs - 1 metric(:, :, iobs) = \ normalize_metric(metric(:, :, iobs), \ @@ -304,29 +323,78 @@ begin end do end if + ; Special case, SMPI normalization + if (diag_script_info@metric(met).eq."SMPI") then + ens_idx = new(dimsizes(smpi&models), integer) + do ii = 0, dimsizes(ens_idx) - 1 + loc_idx = ind(input_file_info@dataset.eq.smpi&models(ii)) + ; Select only the datasets of the specified project + if (input_file_info@project(loc_idx).ne. \ + diag_script_info@normalization(met)) then + ens_idx(ii) = ens_idx@_FillValue + else + ens_idx(ii) = ii + end if + end do + if (all(ismissing(ens_idx))) then + error_msg("f", diag_script, "", "No datasets for the selected " + \ + "normalization (" + diag_script_info@normalization(met) + \ + ") found") + end if + ens_idx := ens_idx(ind(.not.ismissing(ens_idx))) + ; Apply normalization + do iboot = 0, dimsizes(smpi&bootstrap_member)-1 + smpi(iboot, :) = smpi(iboot, :) / avg(smpi(iboot, ens_idx)) + end do + end if + ; Reduce dimensionality if no alternative dataset if (.not.l_altern .and. diag_script_info@metric(met).ne."taylor") then metric := metric(:, :, 0) delete(metric@reference) end if - ; Attach attributes to the results - metric@title = diag_script_info@metric(met) + " metric" - metric@long_name = \ - "Grading table of metric " + diag_script_info@metric(met) - metric@metric = diag_script_info@metric(met) - metric@diag_script = (/DIAG_SCRIPT/) - metric@var = "grade" - metric@region = location - metric@num_climofiles = nDatasets - do imod = 0, nDatasets - 1 - num_climo = "climofile_" + imod - metric@$num_climo$ = info_items[imod]@filename - end do - metric@ncdf_dir = ncdf_dir(met) - - ; Write NetCDF output - ncdf_outfile = ncdf_write(metric, metric@ncdf_dir) + if diag_script_info@metric.eq."SMPI" then + ; Attach attributes to results + smpi@title = "metrics" + smpi@long_name = "1 variable's Performance Index for " + \ + "the Single Model Performance Index" + ; val_smpi@metric = diag_script_info@metric + smpi@diag_script = (/DIAG_SCRIPT/) + smpi@var = "performance_index" + smpi@invar = var0 + smpi@region = location + smpi@ensemble_name = diag_script_info@normalization(met) + smpi@num_climofiles = dimsizes(input_file_info@dataset) ; FIX-ME ? + do imod = 0, dimsizes(input_file_info@dataset) - 1 + num_climo = "climofile_" + imod + smpi@$num_climo$ = input_file_info@filename(imod) + end do + smpi@ncdf_dir = ncdf_dir(met) + + ; Write NetCDF output + ncdf_outfile = ncdf_write(smpi, smpi@ncdf_dir) + + else + ; Attach attributes to the results + metric@title = diag_script_info@metric(met) + " metric" + metric@long_name = \ + "Grading table of metric " + diag_script_info@metric(met) + metric@metric = diag_script_info@metric(met) + metric@diag_script = (/DIAG_SCRIPT/) + metric@var = "grade" + metric@region = location + metric@num_climofiles = nDatasets + do imod = 0, nDatasets - 1 + num_climo = "climofile_" + imod + metric@$num_climo$ = info_items[imod]@filename + end do + metric@ncdf_dir = ncdf_dir(met) + + ; Write NetCDF output + ncdf_outfile = ncdf_write(metric, metric@ncdf_dir) + + end if ; Write results of temporary grading list temp_dir = config_user_info@work_dir + "/" + \ diff --git a/esmvaltool/diag_scripts/shared/plot/portrait_plot.ncl b/esmvaltool/diag_scripts/shared/plot/portrait_plot.ncl index 76575b0ef9..bfa91c0007 100644 --- a/esmvaltool/diag_scripts/shared/plot/portrait_plot.ncl +++ b/esmvaltool/diag_scripts/shared/plot/portrait_plot.ncl @@ -5,6 +5,7 @@ ; Check the header of each routine for documentation. ; ; function portrait_plot +; function circle_plot ; ############################################################################# load "./interface_scripts/auxiliary.ncl" @@ -599,6 +600,230 @@ begin draw(plot) frame(wks) + leave_msg(scriptname, funcname) + return(plot) +end + +; ############################################################################# + +undef("circle_plot") +function circle_plot(wks_in[1], + source, + varname[1]: string, + ensname[1]: string) +; +; Arguments +; wks_in: workstations (graphic object or default will be used). +; source: data to be plotted or a NetCDF filename with data. +; varname: variable name in the file. +; +; Source prototype: +; source = (nmod, 2) +; source!0 = models +; source!1 = statistic +; source(:, 0) = SMPI +; source(:, 1) = 95% conf radius +; +; Return value: +; A graphic variable. +; +; Caveats +; +; Modification history: +; 20170424-A_gier_be: written. +; +local funcname, scriptname, verbosity, wks, wks_in, data, source, res, atts, \ + base, varname +begin + + funcname = "circle_plot" + scriptname = "plot_scripts/ncl/portrait_plot.ncl" + enter_msg(scriptname, funcname) + + ; Get data, either directly or via netCDF file + if(typeof(source) .eq. "string") then + data = ncdf_read(source, varname) + else + data = source + copy_VarMeta(source, data) + end if + + ; Use -999 as fill value (easier to display as text) + data@_FillValue = -999. + + ; Retrieve basic metadata from data + defaults = (/"default", "dummy", "dummy_for_var", "Default", "Dummy"/) + if (any(varname.eq.defaults)) then + performance_index = att2var(data, "var") + diag_script = att2var(data, "diag_script") + else + performance_index = varname + end if + + ; Check if a valid wks has been provided, otherwise invoke default + wks = get_wks(wks_in, diag_script, performance_index) + + ; Make list of markers for different projects + symbols_1 = (/"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", \ + "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", \ + "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", \ + "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", \ + "S", "T", "U", "V", "X", "Y", "Z"/) + + ; Greek alphabet + symbols_2 = "~F5~" + symbols_1 + "~F~" + + n_projects = 1 + x_min = min((/0.38, min(data(:, 0)-data(:, 1))-0.05/)) ; was x_min = 0.01 + x_max = max(data(:, 0) + data(:, 1)) + 0.25 + y_max = n_projects + 2 + y_min = n_projects - 2 + + ; Default resources + res = True + res@xyXStyle = "Log" + res@gsnDraw = False + res@gsnFrame = False + res@tmBorderThicknessF = False + res@tmXBBorderOn = False + res@tmXTBorderOn = False + res@tmYLBorderOn = False + res@tmYRBorderOn = False + res@tmXBOn = False + res@tmXTOn = False + res@tmYLOn = False + res@tmYROn = False + res@trXMinF = x_min + res@trXMaxF = x_max + res@trYMinF = y_min + res@trYMaxF = y_max + res@vpXF = 0.1 + res@vpWidthF = 0.9 + res@vpYF = 1.0 + res@vpHeightF = 0.4 + res@tiXAxisString = "I~S~2" + res@tiXAxisOffsetYF = 0.1 + + res_lines = True + res_lines@gsLineDashPattern = 0. + res_lines@gsLineThicknessF = 2. + res_lines@tfPolyDrawOrder = "PreDraw" + + res_circles = True + res_circles@gsEdgesOn = True + res_circles@gsEdgeThicknessF = 1.5 + + res_text = True + res_text@txFontHeightF = 0.02 + + res_marker = True + res_marker@gsMarkerSizeF = 0.02 + res_marker@gsMarkerIndex = 1 + res_marker@gsMarkerColor = "black" + res_marker@tfPolyDrawOrder = "Draw" + res_marker@txFontHeightF = 0.015 + res_marker@txFontThicknessF = 2 + + plot = gsn_csm_xy(wks, (/x_min, x_max/), (/1., 1./), res) + ; Draw baseline + plot@$unique_string("dum")$ = \ + gsn_add_polyline(wks, plot, (/x_min, x_max/), (/1., 1./), res_lines) + + ; Draw ticks on baseline + x_ticks = ispan(toint(x_min*10), toint(x_max*10), 1)*0.1 + x_big_ticks = ispan(0, toint(x_max*10), 5)*0.1 + x_numbers = ispan(toint(x_min)+1, toint(x_max), 1) + + do ticks = 0, dimsizes(x_ticks) - 1 + plot@$unique_string("dum")$ = \ + gsn_add_polyline(wks, plot, (/x_ticks(ticks), x_ticks(ticks)/), \ + (/0.95, 1.05/), res_lines) + end do + + do ticks = 0, dimsizes(x_big_ticks) - 1 + plot@$unique_string("dum")$ = \ + gsn_add_polyline(wks, plot, \ + (/x_big_ticks(ticks), x_big_ticks(ticks)/), \ + (/0.85, 1.15/), res_lines) + end do + + do ticks = 0, dimsizes(x_numbers)-1 + plot@$unique_string("dum")$ = \ + gsn_add_text(wks, plot, tostring(x_numbers(ticks)), \ + x_numbers(ticks), 0.2, res_text) + end do + + ; Add models as circles, transform x-coords into ndc space + ; to keep circles in log + n = 50 ; nr of points to draw circle with + do imod = 0, dimsizes(data&models) - 1 + x_in = (/data(imod, 0), data(imod, 0) + data(imod, 1),\ + data(imod, 0)/) + y_in = (/1., 1., 1.26/) + x_ndc = new(3, float) + y_ndc = new(3, float) + datatondc(plot, x_in, y_in, x_ndc, y_ndc) + mod_r = x_ndc(1) - x_ndc(0) + x_1 = fspan(-mod_r, mod_r, n) + y_1 = sqrt(mod_r ^ 2 - x_1 ^ 2) + x = array_append_record(x_1, x_1(::-1), 0) + y = array_append_record(y_1, -y_1(::-1), 0) + x = x + x_ndc(0) + y = y + y_ndc(0) + if data&models(imod).eq."multi-model-mean" then + res_circles@gsFillColor = "black" + res_circles@gsFillOpacityF = 0.8 + else + res_circles@gsFillColor = "orange" + res_circles@gsFillOpacityF = 0.3 + end if + gsn_polygon_ndc(wks, x, y, res_circles) + gsn_polymarker_ndc(wks, x_ndc(0), y_ndc(0), res_marker) + delete([/mod_r, x_1, y_1, x, y, x_ndc, y_ndc, x_in, y_in/]) + end do + + ; Plot average I^2 and Project name + ; Multi Model Mean at the end + x_in = (/1., 1./) ; arbitrary value + y_in = (/1., 1./) + x_ndc = new(2, float) + y_ndc = new(2, float) + datatondc(plot, x_in, y_in, x_ndc, y_ndc) + res_text@txJust = "CenterLeft" + gsn_text_ndc(wks, ensname, 0.01, y_ndc(0), res_text) + delete([/x_in, y_in, x_ndc, y_ndc/]) + + ; Text symbols after all circles are drawn, in case they fall inside + x_in = data(:, 0) + y_in = new(dimsizes(data(:, 0)), float) + y_in(:) = max(data(:, 1)) + 1.5 + x_ndc = new(dimsizes(data(:, 0)), float) + y_ndc = new(dimsizes(data(:, 0)), float) + datatondc(plot, x_in, y_in, x_ndc, y_ndc) + + do imod = 0, dimsizes(data&models) - 1 + gsn_text_ndc(wks, symbols_2(imod), x_ndc(imod), y_ndc(imod), res_marker) + end do + delete([/x_in, y_in, x_ndc, y_ndc/]) + + ; Draw legend + txres = True + txres@txFontHeightF = 0.015 + txres@txJust = "CenterLeft" + ypos = fspan(0.55, 0.1, 20) + half = toint(dimsizes(data&models)/2) + do imod = 0, half + gsn_text_ndc(wks, symbols_2(imod) + ": " + \ + data&models(imod), 0.01, ypos(imod), txres) + end do + do imod = half + 1, dimsizes(data&models) - 1 + gsn_text_ndc(wks, symbols_2(imod) + ": " + \ + data&models(imod), 0.3, ypos(imod - half - 1), txres) + end do + + draw(plot) + frame(wks) + leave_msg(scriptname, funcname) return(plot) diff --git a/esmvaltool/diag_scripts/shared/statistics.ncl b/esmvaltool/diag_scripts/shared/statistics.ncl index abfdeab4a3..f15f5e2bff 100644 --- a/esmvaltool/diag_scripts/shared/statistics.ncl +++ b/esmvaltool/diag_scripts/shared/statistics.ncl @@ -1397,10 +1397,28 @@ begin time_weights = sdays end if + ; Annual-mean time-series + if (dim_names(0).eq."year") then + time_weights = new(dims_var(0), float) + time_weights = 1. + end if + if (dim_names(1).eq."lat" .and. dim_names(2).eq."lon") then area_weights = map_area(var&lat, var&lon) end if + if (dim_names(1).eq."plev" .and. dim_names(2).eq."lat") then + areas = map_area(ref&lat, (/1.0, 2.0/)) + nlev = dimsizes(ref&plev) + ptop = ref&plev(nlev - 1) - \ + 0.5 * (ref&plev(nlev - 2) - ref&plev(nlev - 1)) + delta_p = dpres_plevel(ref&plev, 101325., ptop, 0) + area_weights = new((/nlev, dimsizes(ref&lat)/), float) + wdims = dimsizes(area_weights) + area_weights = conform_dims(wdims, delta_p, 0) * \ + conform_dims(wdims, areas(:, 0), 1) + end if + if (isdefined("time_weights").and.isdefined("area_weights")) then weights = new(dimsizes(var), float) do ii = 0, dimsizes(time_weights) - 1 @@ -1461,6 +1479,63 @@ begin return(out) end if + ; Single Model Performance Index + if (metric.eq."SMPI") then + nyears = dimsizes(var&year) + out = new(diag_script_info@smpi_n_bootstrap + 1, float) + do ibootstrap = 0, diag_script_info@smpi_n_bootstrap + if (ibootstrap.eq.0) then + bootvect = ispan(0, nyears - 1, 1) + else + icnt = 0 + do while (icnt .le. 10) + bootvect = generate_sample_indices(nyears, 1) + icnt = icnt + 1 + if (.not.all(bootvect(:).eq.bootvect(0))) then + break + end if + end do + if (all(bootvect(:).eq.bootvect(0))) then + error_msg("f", scriptname, funcname, \ + "Number of years too small for bootstrapping. Abort.") + end if + end if + obs = ref(bootvect, :, :) + mod1D = ndtooned(dim_avg_n(var, 0)) + ref1D = ndtooned(dim_avg_n(obs, 0)) + sig1D = ndtooned(dim_stddev_n_Wrap(obs, 0)) + sig1D@_FillValue = default_fillvalue(typeof(sig1D)) + sig1D = where(sig1D.eq.0, sig1D@_FillValue, sig1D) + + delete(weights) + delete(wgt1d) + if (isdim(obs, "lon").and.isdim(obs, "lat")) then + weights = map_area(obs&lat, obs&lon) + else if (isdim(obs, "plev").and.isdim(obs, "lat")) then + areas = map_area(obs&lat, (/1.0, 2.0/)) + nlev = dimsizes(obs&plev) + ptop = obs&plev(nlev - 1) - 0.5 * (obs&plev(nlev - 2) \ + - obs&plev(nlev - 1)) + delta_p = dpres_plevel(obs&plev, 101325., ptop, 0) + weights = new((/dimsizes(obs&plev), dimsizes(obs&lat)/), float) + wdims = dimsizes(weights) + weights = (conform_dims(wdims, delta_p, 0) * \ + conform_dims(wdims, areas(:, 0), 1)) + else + error_msg("f", diag_script, "", "Ups. This should not happen." + \ + " Unknown dimensions in variable obs.") + end if + end if + + wgt1d = ndtooned(weights) + out(ibootstrap) = dim_avg_wgt_Wrap((mod1D - ref1D) ^ 2 \ + / sig1D ^ 2, wgt1d, 1) + + end do + leave_msg(scriptname, funcname) + return(out) + end if + error_msg("f", scriptname, funcname, "metric " + metric + " not available") end diff --git a/esmvaltool/recipes/recipe_reichlerkim08bams.yml b/esmvaltool/recipes/recipe_reichlerkim08bams.yml new file mode 100644 index 0000000000..f475acded5 --- /dev/null +++ b/esmvaltool/recipes/recipe_reichlerkim08bams.yml @@ -0,0 +1,410 @@ +############################################################################### +# recipe_ReichlerKim08bams.xml +--- +documentation: + description: | + Recipe for computing Single Model Performance Index. Follows Reichler + and Kim 2008. Considers variables: + Sea level pressure, Air Temperature, Zonal Wind Stress, Meridional Wind + Stress, 2m air temperature, Zonal Wind, Meridional Wind, Net surface heat + flux, Precipitation, Specific Humidity, Snow fraction, Sea Surface + Temperature, Sea Ice Fraction and sea surface salinity. + + authors: + - gier_be + - righ_ma + - eyri_ve + + references: + - rk2008bams #will need to be added + + projects: + - crescendo + +datasets: + - {dataset: CNRM-CM5, project: CMIP5, exp: historical, ensemble: r1i1p1, start_year: 1980, end_year: 2005} + - {dataset: CSIRO-Mk3-6-0, project: CMIP5, exp: historical, ensemble: r1i1p1, start_year: 1980, end_year: 2005} +# - {dataset: GFDL-ESM2G, project: CMIP5, exp: historical, ensemble: r1i1p1, start_year: 1980, end_year: 2005} +# - {dataset: MIROC5, project: CMIP5, exp: historical, ensemble: r1i1p1, start_year: 1980, end_year: 2005} +# - {dataset: MIROC-ESM, project: CMIP5, exp: historical, ensemble: r1i1p1, start_year: 1980, end_year: 2005} +# - {dataset: MIROC-ESM-CHEM, project: CMIP5, exp: historical, ensemble: r1i1p1, start_year: 1980, end_year: 2005} +# - {dataset: MPI-ESM-LR, project: CMIP5, exp: historical, ensemble: r1i1p1, start_year: 1980, end_year: 2005} +# - {dataset: MPI-ESM-MR, project: CMIP5, exp: historical, ensemble: r1i1p1, start_year: 1980, end_year: 2005} +# - {dataset: MRI-CGCM3, project: CMIP5, exp: historical, ensemble: r1i1p1, start_year: 1980, end_year: 2005} +# - {dataset: NorESM1-M, project: CMIP5, exp: historical, ensemble: r1i1p1, start_year: 1980, end_year: 2005} +# - {dataset: NorESM1-ME, project: CMIP5, exp: historical, ensemble: r1i1p1, start_year: 1980, end_year: 2005} + +preprocessors: + + ppALL: + extract_levels: + levels: reference_dataset + scheme: linear + regrid: + target_grid: reference_dataset + scheme: linear + mask_fillvalues: + threshold_fraction: 0.10 + multi_model_statistics: + span: overlap + statistics: [mean] + exclude: [reference_dataset] + + ppNOLEV: + # extract_levels: false + regrid: + target_grid: reference_dataset + scheme: linear + mask_fillvalues: + threshold_fraction: 0.10 + multi_model_statistics: + span: overlap + statistics: [mean] + exclude: [reference_dataset] + + ppNOLEVirreg: + #extract_levels: false + regrid: + target_grid: 1x1 + scheme: linear + mask_fillvalues: + threshold_fraction: 0.10 + multi_model_statistics: + span: overlap + statistics: [mean] + exclude: [reference_dataset] + +diagnostics: + +# ta: +# description: Air temperature zonal mean +# themes: +# - phys +# realms: +# - atmos +# variables: +# ta: +# preprocessor: ppALL +# reference_dataset: ERA-Interim +# mip: Amon +# field: T3M +# additional_datasets: +# - {dataset: ERA-Interim, project: OBS, type: reanaly, version: 1, start_year: 1980, end_year: 2005, tier: 3} +# scripts: +# grading: &grading_settings +# script: perfmetrics/main.ncl +# plot_type: cycle_zonal +# time_avg: yearly +# region: Global +# range_option: 1 +# draw_plots: false +# calc_grading: true +# metric: [SMPI] +# normalization: CMIP5 +# smpi_n_bootstrap: 100 + +# va: +# description: Meridional Wind +# themes: +# - phys +# realms: +# - atmos +# variables: +# va: +# preprocessor: ppALL +# reference_dataset: ERA-Interim +# mip: Amon +# field: T3M +# additional_datasets: +# - {dataset: ERA-Interim, project: OBS, type: reanaly, version: 1, start_year: 1980, end_year: 2005, tier: 3} +# scripts: +# grading: +# script: perfmetrics/main.ncl +# plot_type: cycle_zonal +# time_avg: yearly +# region: Global +# range_option: 1 +# draw_plots: false +# calc_grading: true +# metric: [SMPI] +# normalization: CMIP5 +# smpi_n_bootstrap: 100 + +# ua: +# description: Zonal Wind +# themes: +# - phys +# realms: +# - atmos +# variables: +# ua: +# preprocessor: ppALL +# reference_dataset: ERA-Interim +# mip: Amon +# field: T3M +# additional_datasets: +# - {dataset: ERA-Interim, project: OBS, type: reanaly, version: 1, start_year: 1980, end_year: 2005, tier: 3} +# scripts: +# grading: +# script: perfmetrics/main.ncl +# plot_type: cycle_zonal +# time_avg: yearly +# region: Global +# range_option: 1 +# draw_plots: false +# calc_grading: true +# metric: [SMPI] +# normalization: CMIP5 +# smpi_n_bootstrap: 100 + +# hus: +# description: Near-surface temperature +# themes: +# - phys +# realms: +# - atmos +# variables: +# hus: +# preprocessor: ppALL +# reference_dataset: ERA-Interim +# mip: Amon +# field: T3M +# additional_datasets: +# - {dataset: ERA-Interim, project: OBS, type: reanaly, version: 1, start_year: 1980, end_year: 2005, tier: 3} +# scripts: +# grading: +# script: perfmetrics/main.ncl +# plot_type: cycle_zonal +# time_avg: yearly +# region: Global +# range_option: 1 +# draw_plots: false +# calc_grading: true +# metric: [SMPI] +# normalization: CMIP5 +# smpi_n_bootstrap: 100 + +# tas: +# description: Near-surface temperature +# themes: +# - phys +# realms: +# - atmos +# variables: +# tas: +# preprocessor: ppNOLEV +# reference_dataset: ERA-Interim +# mip: Amon +# field: T2Ms +# additional_datasets: +# - {dataset: ERA-Interim, project: OBS, type: reanaly, version: 1, start_year: 1980, end_year: 2005, tier: 3} +# scripts: +# grading: +# script: perfmetrics/main.ncl +# plot_type: cycle_latlon +# time_avg: yearly +# region: Global +# range_option: 1 +# draw_plots: false +# calc_grading: true +# metric: [SMPI] +# normalization: CMIP5 +# smpi_n_bootstrap: 100 + +# psl: +# description: Sea-level pressure +# themes: +# - phys +# realms: +# - atmos +# variables: +# psl: +# preprocessor: ppNOLEV +# reference_dataset: ERA-Interim +# mip: Amon +# field: T2Ms +# additional_datasets: +# - {dataset: ERA-Interim, project: OBS, type: reanaly, version: 1, start_year: 1980, end_year: 2005, tier: 3} +# scripts: +# grading: +# script: perfmetrics/main.ncl +# plot_type: cycle_latlon +# time_avg: yearly +# region: Global +# range_option: 1 +# draw_plots: false +# calc_grading: true +# metric: [SMPI] +# normalization: CMIP5 +# smpi_n_bootstrap: 100 + + pr: + description: Precipitation + themes: + - phys + realms: + - atmos + variables: + pr: + preprocessor: ppNOLEV + reference_dataset: GPCP-SG + mip: Amon + field: T2Ms + additional_datasets: + - {dataset: GPCP-SG, project: obs4mips, level: L3, version: v2.2, start_year: 1980, end_year: 2005, tier: 1} + scripts: + grading: + script: perfmetrics/main.ncl + plot_type: cycle_latlon + time_avg: yearly + region: Global + range_option: 1 + draw_plots: false + calc_grading: true + metric: [SMPI] + normalization: CMIP5 + smpi_n_bootstrap: 100 + +# tos: +# description: Sea surface temperature +# themes: +# - phys +# realms: +# - ocean +# variables: +# tos: +# preprocessor: ppNOLEVirreg +# reference_dataset: HadISST +# mip: Omon +# field: T2Ms +# additional_datasets: +# - {dataset: HadISST, project: OBS, type: reanaly, version: 1, start_year: 1980, end_year: 2005, tier: 2} +# scripts: +# grading: +# script: perfmetrics/main.ncl +# plot_type: cycle_latlon +# time_avg: yearly +# region: Global +# range_option: 1 +# draw_plots: false +# calc_grading: true +# metric: [SMPI] +# normalization: CMIP5 +# smpi_n_bootstrap: 100 + +# sic: +# description: Sea ice fraction +# themes: +# - phys +# realms: +# - seaIce +# variables: +# sic: +# preprocessor: ppNOLEVirreg +# reference_dataset: HadISST +# mip: OImon +# field: T2Ms +# additional_datasets: +# - {dataset: HadISST, project: OBS, type: reanaly, version: 20130524, start_year: 1980, end_year: 2005, tier: 2} +# scripts: +# grading: +# script: perfmetrics/main.ncl +# plot_type: cycle_latlon +# time_avg: yearly +# region: Global +# range_option: 1 +# draw_plots: false +# calc_grading: true +# metric: [SMPI] +# normalization: CMIP5 +# smpi_n_bootstrap: 100 + +# hfds: +# description: Net Surface Heat Flux +# themes: +# - phys +# realms: +# - ocean +# variables: +# hfds: +# preprocessor: ppNOLEVirreg +# reference_dataset: ERA-Interim +# mip: Omon +# field: T2Ms +# additional_datasets: +# - {dataset: ERA-Interim, project: OBS, type: reanaly, version: 1, start_year: 2000, end_year: 2005, tier: 3} +# scripts: +# grading: +# script: perfmetrics/main.ncl +# plot_type: cycle_latlon +# time_avg: yearly +# region: Global +# range_option: 1 +# draw_plots: false +# calc_grading: true +# metric: [SMPI] +# normalization: CMIP5 +# smpi_n_bootstrap: 100 + + tauu: + description: Zonal Wind Stress + themes: + - phys + realms: + - atmos + variables: + tauu: + preprocessor: ppNOLEV + reference_dataset: ERA-Interim + mip: Amon + field: TO2Ms + additional_datasets: + - {dataset: ERA-Interim, project: OBS, type: reanaly, version: 1, start_year: 1980, end_year: 2005, tier: 3} + scripts: + grading: + script: perfmetrics/main.ncl + plot_type: cycle_latlon + time_avg: yearly + region: Global + range_option: 1 + draw_plots: false + calc_grading: true + metric: [SMPI] + normalization: CMIP5 + smpi_n_bootstrap: 100 + +# tauv: +# description: Meridional Wind Stress +# themes: +# - phys +# realms: +# - atmos +# variables: +# tauv: +# preprocessor: ppNOLEV +# reference_dataset: ERA-Interim +# mip: Amon +# field: TO2Ms +# additional_datasets: +# - {dataset: ERA-Interim, project: OBS, type: reanaly, version: 1, start_year: 1980, end_year: 2005, tier: 3} +# scripts: +# grading: +# script: perfmetrics/main.ncl +# plot_type: cycle_latlon +# time_avg: yearly +# region: Global +# range_option: 1 +# draw_plots: false +# calc_grading: true +# metric: [SMPI] +# normalization: CMIP5 +# smpi_n_bootstrap: 100 + +### COLLECT METRICS ################### + collect: + description: Wrapper to collect and plot previously calculated metrics + scripts: + SMPI: + script: perfmetrics/collect.ncl + ancestors: ['*/grading'] + metric: SMPI