New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
plot_station_asf_OCE.py in NEMO/branches/2020/dev_r13648_ASINTER-04_laurent_bulk_ice/tests/STATION_ASF/EXPREF – NEMO

source: NEMO/branches/2020/dev_r13648_ASINTER-04_laurent_bulk_ice/tests/STATION_ASF/EXPREF/plot_station_asf_OCE.py @ 13690

Last change on this file since 13690 was 13690, checked in by laurent, 4 years ago

Improvements for "oce+ice capable" STATION_ASF!

  • Property svn:executable set to *
File size: 11.5 KB
RevLine 
[13676]1#!/usr/bin/env python3
2# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
[13690]3#
4##########################################################################################
5# Post-diagnostic of STATION_ASF for ocean only  (no sea-ice support)
6#
7#  L. Brodeau, 2020
8##########################################################################################
[13676]9
10import sys
11from os import path as path
[13690]12import argparse as ap
13from math import floor, ceil, copysign, log
[13676]14import numpy as nmp
15from netCDF4 import Dataset,num2date
16import matplotlib as mpl
17mpl.use('Agg')
18import matplotlib.pyplot as plt
19import matplotlib.dates as mdates
20
21dir_figs='.'
22size_fig=(13,8)
23size_fig0=(12,10)
24
25clr_red = '#AD0000'
26clr_mod = '#008ab8'
27
28rDPI=100.
29
[13690]30L_ALGOS = [ 'ANDREAS' , 'COARE3p6' , 'ECMWF'   , 'NCAR' ]
31l_color = [ '0.85'    ,  '#ffed00' , '#008ab8' , '0.4'  ] ; # colors to differentiate algos on the plot
32l_width = [  4        ,     3      ,    2      ,  1     ] ; # line-width to differentiate algos on the plot
33l_style = [ '-'       ,    '-'     ,   '-'     , '--'   ] ; # line-style
[13676]34
35
36# Variables to compare between algorithms
37############################################
38L_VNEM  = [   'Cd_oce'  ,   'Ce_oce'  ,   'qla_oce' , 'qsb_oce'     ,     'qt_oce' ,   'qlw_oce' ,  'taum'     ,    'dt_skin'         ]
39L_VARO  = [     'Cd'    ,     'Ce'    ,   'Qlat'    ,    'Qsen'     ,     'Qnet'   ,   'Qlw'     ,  'Tau'      ,    'dT_skin'         ] ; # name of variable on figure
40L_VARL  = [ r'$C_{D}$'  , r'$C_{E}$'  , r'$Q_{lat}$', r'$Q_{sens}$' , r'$Q_{net}$' , r'$Q_{lw}$' , r'$|\tau|$' , r'$\Delta T_{skin}$' ] ; # name of variable in latex mode
41L_VUNT  = [     ''      ,     ''      , r'$W/m^2$'  , r'$W/m^2$'    , r'$W/m^2$'   , r'$W/m^2$'  , r'$N/m^2$'  ,      'K'             ]
[13690]42L_BASE  = [    0.005    ,    0.005    ,      5.     ,      5.       ,       5      ,      5.     ,    0.05      ,       0.05           ]
43L_PREC  = [      3      ,      3      ,      0      ,      0        ,       0      ,      0      ,     2       ,        3             ]
[13676]44L_ANOM  = [   False     ,   False     ,   True      ,    True       ,    True      ,    True     ,   True      ,      False           ]
45
46
47nb_algos = len(L_ALGOS) ; print(nb_algos)
48
49
50
51
[13690]52################## ARGUMENT PARSING / USAGE ################################################################################################
53parser = ap.ArgumentParser(description='Generate pixel maps of a given scalar.')
54#
55requiredNamed = parser.add_argument_group('required arguments')
56requiredNamed.add_argument('-d', '--dirout' , required=True,                 help='Path to (production) directory where STATION_ASF was run')
57requiredNamed.add_argument('-f', '--forcing', required=True, default="PAPA", help='Name of forcing (ex: PAPA, ERA5_arctic')
58#
59parser.add_argument('-C', '--conf',   default="STATION_ASF",  help='specify NEMO config (ex: STATION_ASF)')
60parser.add_argument('-s', '--ystart', default="2018",         help='specify first year of experiment (ex: 2018)')
61parser.add_argument('-e', '--yend',   default="2018",         help='specify last  year of experiment (ex: 2018)')
62#
63parser.add_argument('-t', '--itype',   default="png",         help='specify the type of image you want to create (ex: png, svg, etc.)')
64#parser.add_argument('-l', '--lev' , type=int, default=0,    help='specify the level to use if 3D field (default: 0 => 2D)')
65#parser.add_argument('-I', '--ice' , action='store_true',    help='draw sea-ice concentration layer onto the field')
66#
67args = parser.parse_args()
68#
69cdir_data = args.dirout
70cforcing  = args.forcing
71#
72CONF      = args.conf
73cy1       = args.ystart
74cy2       = args.yend
75#
76fig_ext   = args.itype
77#jk    = args.lev
78#lshow_ice = args.ice
79#
80#print(''); print(' *** cdir_data = ', cdir_data); print(' *** cforcing  = ', cforcing)
81#print(' *** CONF = ', CONF); print(' *** cy1 = ', cy1); print(' *** cy2 = ', cy2)
82###############################################################################################################################################
83
84
85
[13676]86# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
87# Populating and checking existence of files to be read
88# >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
89def chck4f(cf):
90    cmesg = 'ERROR: File '+cf+' does not exist !!!'
91    if not path.exists(cf): print(cmesg) ; sys.exit(0)
92
93###cf_in = nmp.empty((), dtype="S10")
94cf_in = []
95for ja in range(nb_algos):
[13690]96    cfi = cdir_data+'/output/'+CONF+'-'+L_ALGOS[ja]+'_'+cforcing+'_1h_'+cy1+'0101_'+cy2+'1231_gridT.nc'
[13676]97    chck4f(cfi)
98    cf_in.append(cfi)
99print('Files we are goin to use:')
100for ja in range(nb_algos): print(cf_in[ja])
101#-----------------------------------------------------------------
102
103
[13690]104def round_bounds( x1, x2,  base=5, prec=3 ):
105    rmin =  base * round( floor(float(x1)/base), prec )
106    rmax =  base * round(  ceil(float(x2)/base), prec )
107    return rmin, rmax
108
109
110
[13676]111# Getting time array from the first file:
112id_in = Dataset(cf_in[0])
[13690]113vt = id_in.variables['time_counter'][:]
[13676]114cunit_t = id_in.variables['time_counter'].units ; print(' "time_counter" is in "'+cunit_t+'"')
115id_in.close()
116nbr = len(vt)
117
118vtime = num2date(vt, units=cunit_t) ; # something understandable!                                                                 
119vtime = vtime.astype(dtype='datetime64[D]')
120
121ii=nbr/300
122ib=max(ii-ii%10,1)
123xticks_d=int(30*ib)
124
125
126rat = 100./float(rDPI)
127params = { 'font.family':'Open Sans',
128           'font.size':       int(15.*rat),
129           'legend.fontsize': int(15.*rat),
130           'xtick.labelsize': int(15.*rat),
131           'ytick.labelsize': int(15.*rat),
132           'axes.labelsize':  int(16.*rat)
133}
134mpl.rcParams.update(params)
135font_inf = { 'fontname':'Open Sans', 'fontweight':'normal', 'fontsize':18.*rat }
136font_x   = { 'fontname':'Open Sans', 'fontweight':'normal', 'fontsize':15.*rat }
137
138
139
140
141
142# First for each algorithm we compare some input vs out put variables:                                                                       
143
144# t_skin
145vtemp_in = [ 'sst'            ,               'theta_zu'                 ,               't_skin'                   ] ; #,               'theta_zt'               
146vtemp_lb = [ 'SST (bulk SST)' , r'$\theta_{zu}$ (pot. air temp. at 10m)' ,           'Skin temperature'             ] ; #, r'$\theta_{zt}$ (pot. air temp. at 2m)'
147vtemp_cl = [  'k'             ,                clr_mod                   ,                clr_red                   ] ; #,                clr_mod                 
148vtemp_lw = [   3              ,                   1.3                    ,                   0.7                    ] ; #,                 2                       
149vtemp_ls = [     '-'          ,                   '-'                    ,                   '-'                    ] ; #,                 '-'                     
150
151ntemp = len(vtemp_in)
152
153xxx = nmp.zeros((nbr,ntemp))
154
155for ja in range(nb_algos):
156    #
157    # Temperatures...
158    id_in = Dataset(cf_in[ja])
159    for jv in range(ntemp):
[13690]160        xxx[:,jv] = id_in.variables[vtemp_in[jv]][:,1,1] # only the center point of the 3x3 spatial domain!
[13676]161    id_in.close()
162
163    fig = plt.figure(num = 1, figsize=size_fig0, facecolor='w', edgecolor='k')
164    ax1 = plt.axes([0.07, 0.2, 0.9, 0.75])
165    ax1.set_xticks(vtime[::xticks_d])
166    ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d %H:%M:%S'))
167    plt.xticks(rotation='60', **font_x)
168
169    for jv in range(ntemp):
170        plt.plot(vtime, xxx[:,jv], '-', color=vtemp_cl[jv], linestyle=vtemp_ls[jv], linewidth=vtemp_lw[jv], label=vtemp_lb[jv], zorder=10)
171
[13690]172    idx_okay = nmp.where( nmp.abs(xxx) < 1.e+10 )
173    fmin, fmax = round_bounds( nmp.min(xxx[idx_okay]) , nmp.max(xxx[idx_okay]), base=5, prec=0 )
174    ax1.set_ylim(fmin, fmax) ; ax1.set_xlim(vtime[0],vtime[nbr-1])
[13676]175    plt.ylabel(r'Temperature [$^{\circ}$C]')
176
177    ax1.grid(color='k', linestyle='-', linewidth=0.3)
178    plt.legend(loc='best', ncol=1, shadow=True, fancybox=True)
179    ax1.annotate('Algo: '+L_ALGOS[ja]+', station: '+cforcing, xy=(0.4, 1.), xycoords='axes fraction',  bbox={'facecolor':'w', 'alpha':1., 'pad':10}, zorder=50, **font_inf)
[13690]180    plt.savefig('01_temperatures_'+L_ALGOS[ja]+'_'+cforcing+'.'+fig_ext, dpi=int(rDPI), transparent=False)
[13676]181    plt.close(1)
182
183
184del xxx
185
186
187
188# Now we compare output variables from bulk algorithms between them:
189
190nb_var = len(L_VNEM)
191
192xF  = nmp.zeros((nbr,nb_algos))
193xFa = nmp.zeros((nbr,nb_algos))
194
195
196for jv in range(nb_var):
197    print('\n *** Treating variable: '+L_VARO[jv]+' !')
198
199    for ja in range(nb_algos):
200        #
201        id_in = Dataset(cf_in[ja])
[13690]202        xF[:,ja] = id_in.variables[L_VNEM[jv]][:,1,1] # only the center point of the 3x3 spatial domain!
[13676]203        if ja == 0: cvar_lnm = id_in.variables[L_VNEM[jv]].long_name
204        id_in.close()
205
[13690]206    idx_okay = nmp.where( nmp.abs(xF) < 1.e+10 )
207       
[13676]208    fig = plt.figure(num = jv, figsize=size_fig, facecolor='w', edgecolor='k')
209    ax1 = plt.axes([0.08, 0.25, 0.9, 0.7])
210    ax1.set_xticks(vtime[::xticks_d])
211    ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d %H:%M:%S'))
212    plt.xticks(rotation='60', **font_x)
213
214    for ja in range(nb_algos):
215        plt.plot(vtime, xF[:,ja], '-', color=l_color[ja], linestyle=l_style[ja], linewidth=l_width[ja], label=L_ALGOS[ja], zorder=10+ja)
[13690]216       
217    fmin, fmax = round_bounds( nmp.min(xF[idx_okay]) , nmp.max(xF[idx_okay]), base=L_BASE[jv], prec=L_PREC[jv])
218    #print("LOLO: fmin, fmax =",nmp.min(xF[idx_okay]), nmp.max(xF[idx_okay]) ); print("LOLO: fmin, fmax =",fmin, fmax) ; #sys.exit(0)
219   
220    ax1.set_ylim(fmin, fmax) ; ax1.set_xlim(vtime[0],vtime[nbr-1])
[13676]221    plt.ylabel(L_VARL[jv]+' ['+L_VUNT[jv]+']')
222
223    ax1.grid(color='k', linestyle='-', linewidth=0.3)
224    plt.legend(loc='best', ncol=1, shadow=True, fancybox=True)
[13690]225    ax1.annotate(cvar_lnm+', station: '+cforcing, xy=(0.3, 1.), xycoords='axes fraction',  bbox={'facecolor':'w', 'alpha':1., 'pad':10}, \
226                 zorder=50, **font_inf)
227    plt.savefig(L_VARO[jv]+'_'+cforcing+'.'+fig_ext, dpi=int(rDPI), transparent=False)
[13676]228    plt.close(jv)
229
230    if L_ANOM[jv]:
231
232        for ja in range(nb_algos): xFa[:,ja] = xF[:,ja] - nmp.mean(xF,axis=1)
233
234        if nmp.sum(xFa[:,:]) == 0.0:
235            print('     Well! Seems that for variable '+L_VARO[jv]+', choice of algo has no impact a all!')
236            print('          ==> skipping anomaly plot...')
237
238        else:
239
240            # Want a symetric y-range that makes sense for the anomaly we're looking at:
241            rmax = nmp.max(xFa) ; rmin = nmp.min(xFa)
242            rmax = max( abs(rmax) , abs(rmin) )
[13690]243            romagn = floor(log(rmax, 10)) ; # order of magnitude of the anomaly  we're dealing with
[13676]244            rmlt = 10.**(int(romagn)) / 2.
[13690]245            yrng = copysign( ceil(abs(rmax)/rmlt)*rmlt , rmax)
[13676]246
247            fig = plt.figure(num = 10+jv, figsize=size_fig, facecolor='w', edgecolor='k')
248            ax1 = plt.axes([0.08, 0.25, 0.9, 0.7])
249            ax1.set_xticks(vtime[::xticks_d])
250            ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d %H:%M:%S'))
251            plt.xticks(rotation='60', **font_x)
252
253            for ja in range(nb_algos):
254                plt.plot(vtime, xFa[:,ja], '-', color=l_color[ja], linewidth=l_width[ja], label=L_ALGOS[ja], zorder=10+ja)
255
256            ax1.set_ylim(-yrng,yrng) ; ax1.set_xlim(vtime[0],vtime[nbr-1])
257            plt.ylabel(L_VARL[jv]+' ['+L_VUNT[jv]+']')
258            ax1.grid(color='k', linestyle='-', linewidth=0.3)
259            plt.legend(bbox_to_anchor=(0.45, 0.2), ncol=1, shadow=True, fancybox=True)
260            ax1.annotate('Anomaly of '+cvar_lnm, xy=(0.3, 0.97), xycoords='axes fraction',  bbox={'facecolor':'w', 'alpha':1., 'pad':10}, zorder=50, **font_inf)
[13690]261            plt.savefig(L_VARO[jv]+'_'+cforcing+'.'+fig_ext, dpi=int(rDPI), transparent=False)
[13676]262            plt.close(10+jv)
263
264
265
266
Note: See TracBrowser for help on using the repository browser.