From 7b6d3ad71d7e566948c9a9386a56e73e88fd0ccd Mon Sep 17 00:00:00 2001 From: "Phillip J. Wolfram" Date: Mon, 23 Jan 2017 06:57:09 -0700 Subject: [PATCH 1/3] Specify and apply numpy commands in config files Previously numpy commands were not valid to specify config file settings. Now, numpy commands can be used as the values in config key-value pairs. This is beneficial because long arrays are now easily specified, e.g., np.arange(0,1,100). --- .../configuration/MpasAnalysisConfigParser.py | 25 ++++++++++++------- mpas_analysis/test/test_mpas_config_parser.py | 15 +++++++++-- .../test_mpas_config_parser/config.analysis | 3 +++ 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/mpas_analysis/configuration/MpasAnalysisConfigParser.py b/mpas_analysis/configuration/MpasAnalysisConfigParser.py index fe1cd7ddf..8a73451d0 100644 --- a/mpas_analysis/configuration/MpasAnalysisConfigParser.py +++ b/mpas_analysis/configuration/MpasAnalysisConfigParser.py @@ -1,16 +1,17 @@ -import numbers -import ast - """ A configuratin parser class for MPAS analysis. MpasAnalysisConfigParser adds the capabilities to get an option including a default value (`getWithDefault(section, option, default, ...)`) and to get options that are lists, tuples, dicts, etc (`getExpression(section, option)`). -Author: Xylar Asay-Davis -Last Modified: 12/07/2016 +Author: Xylar Asay-Davis, Phillip J. Wolfram +Last Modified: 01/31/2017 """ +import numbers +import ast +import numpy as np +import numpy from ConfigParser import ConfigParser @@ -44,7 +45,7 @@ def getWithDefault(self, section, option, default): self.set(section, option, str(default)) return default - def getExpression(self, section, option, elementType=None): + def getExpression(self, section, option, elementType=None, usenumpy=False): """ Get an option as an expression (typically a list, though tuples and dicts should also work). `section` and `option` work as in `get(...)`. @@ -56,11 +57,17 @@ def getExpression(self, section, option, elementType=None): useful for ensuring that all elements in a list of numbers are of type float, rather than int, when the distinction is important. - Author: Xylar Asay-Davis - Last Modified: 12/0y/2016 + If `numpy` is True, expression is evaluated within the context of + having numpy and / or np available. + + Author: Xylar Asay-Davis, Phillip J. Wolfram + Last Modified: 01/31/2017 """ expressionString = self.get(section, option) - result = ast.literal_eval(expressionString) + if usenumpy: + result = eval(expressionString) + else: + result = ast.literal_eval(expressionString) if elementType is not None: if isinstance(result, (list, tuple)): diff --git a/mpas_analysis/test/test_mpas_config_parser.py b/mpas_analysis/test/test_mpas_config_parser.py index 4cb09cb1c..b416ecc80 100644 --- a/mpas_analysis/test/test_mpas_config_parser.py +++ b/mpas_analysis/test/test_mpas_config_parser.py @@ -1,14 +1,15 @@ """ Unit test infrastructure for MpasAnalysisConfigParser -Xylar Asay-Davis -12/05/2016 +Xylar Asay-Davis, Phillip J. Wolfram +01/31/2017 """ import pytest from mpas_analysis.test import TestCase, loaddatadir from mpas_analysis.configuration.MpasAnalysisConfigParser \ import MpasAnalysisConfigParser +from . import requires_numpy @pytest.mark.usefixtures("loaddatadir") @@ -64,5 +65,15 @@ def test_read_config(self): 'key2': -12, 'key3': False}) + @requires_numpy + def test_read_config_numpy(self): + self.setup_config() + + # tests numpy evaluation capability + import numpy as np + result = np.arange(0, 1, 10) + for testNumpy in ['testNumpy1', 'testNumpy2']: + self.assertArrayEqual(self.config.getExpression('TestNumpy', + testNumpy, usenumpy=True), result) # vim: foldmethod=marker ai ts=4 sts=4 et sw=4 ft=python diff --git a/mpas_analysis/test/test_mpas_config_parser/config.analysis b/mpas_analysis/test/test_mpas_config_parser/config.analysis index 18071dae5..43ce21f67 100644 --- a/mpas_analysis/test/test_mpas_config_parser/config.analysis +++ b/mpas_analysis/test/test_mpas_config_parser/config.analysis @@ -32,3 +32,6 @@ testDict = {'key1': 'string', 'key2': -12, 'key3': False} +[TestNumpy] +testNumpy1 = numpy.arange(0, 1, 10) +testNumpy2 = np.arange(0, 1, 10) From 9fca6998d10aaf61f0436ac5990862a9f159d3e5 Mon Sep 17 00:00:00 2001 From: "Phillip J. Wolfram" Date: Mon, 23 Jan 2017 07:10:23 -0700 Subject: [PATCH 2/3] Adds meridional overturning circulation diagnostic Takes existing moc.py workflow and integrates it into MPAS-Analysis. --- config.analysis | 15 ++ .../meridional_overturning_circulation.py | 128 ++++++++++++++++++ mpas_analysis/shared/constants/constants.py | 1 + mpas_analysis/shared/plot/plotting.py | 32 +++++ run_analysis.py | 6 + 5 files changed, 182 insertions(+) create mode 100644 mpas_analysis/ocean/meridional_overturning_circulation.py diff --git a/config.analysis b/config.analysis index 4605721ff..99a1b489c 100644 --- a/config.analysis +++ b/config.analysis @@ -82,6 +82,9 @@ generate = 1 [seaice_modelvsobs] generate = 1 +[moc_postprocess] +generate = 0 + [ohc_timeseries] ## compare to output from another model run? #compare_with_model = True @@ -131,6 +134,18 @@ compare_with_obs = True # output, N_movavg=12 corresponds to a 12-month moving average window) N_movavg = 12 + +[moc_postprocess] +filename = ../mpaso.hist.am.timeSeriesStats.yr100-119.avg.nc +filenamemesh = ../mpaso.rst.0002-01-01_00000.nc +filenamemask = ../EC60to30v3_SingleRegionAtlanticWTransportTransects_masks.nc +timeIndex = 0 +horVelName = time_avg_normalVelocity +vertVelName = time_avg_vertVelocityTop +contourLines = np.arange(-8,20.1,2) +# This is specific to Atlantic MOC: +mocLat = np.arange(-34.5,70.1,0.5) + [seaice_timeseries] ## compare to output from another model run? #compare_with_model = True diff --git a/mpas_analysis/ocean/meridional_overturning_circulation.py b/mpas_analysis/ocean/meridional_overturning_circulation.py new file mode 100644 index 000000000..a6497685c --- /dev/null +++ b/mpas_analysis/ocean/meridional_overturning_circulation.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +""" +Compute and plot moc, as a post-processing computation + +Author: Mark Petersen, Phillip J. Wolfram +Last Modified: 01/20/2017 +""" + +from netCDF4 import Dataset +import numpy as np +from ..shared.constants.constants import m3ps_to_Sv +from ..shared.plot.plotting import plot_moc + +def moc_postprocess(config, streamMap=None, variableMap=None): #{{{ + """ + Plots a comparison of ACME/MPAS output to SST or MLD observations + + config is an instance of MpasAnalysisConfigParser containing configuration + options. + + If present, streamMap is a dictionary of MPAS-O stream names that map to + their mpas_analysis counterparts. + + If present, variableMap is a dictionary of MPAS-O variable names that map + to their mpas_analysis counterparts. + + Authors: Mark Petersen, Phillip J. Wolfram + Modified: 01/20/2017 + """ + + # read parameters from config file + fileName = config.get('moc_postprocess', 'filename') + fileNameMesh = config.get('moc_postprocess', 'filenamemesh') + fileNameMask = config.get('moc_postprocess', 'filenamemask') + timeIndex = config.get('moc_postprocess', 'timeIndex') + horVelName = config.get('moc_postprocess', 'horVelName') + vertVelName = config.get('moc_postprocess', 'vertVelname') + mocLat = config.getExpression('moc_postprocess', 'mocLat', usenumpy=True) + + # open files, load variables + print('** load variables: \n') + + print 'Reading data from: ' + fileName + ncfile = Dataset(fileName,'r') + nCells = ncfile.dimensions['nCells'].size + nVertLevels = ncfile.dimensions['nVertLevels'].size + + horVel = ncfile.variables[horVelName][:,:,:] + vertVel = ncfile.variables[vertVelName][:,:,:] + + print 'Reading data from: ' + fileNameMesh + ncfileMesh = Dataset(fileNameMesh,'r') + dvEdge = ncfileMesh.variables['dvEdge'][:] + areaCell = ncfileMesh.variables['areaCell'][:] + latCell = ncfileMesh.variables['latCell'][:]*180./np.pi + refBottomDepth = ncfileMesh.variables['refBottomDepth'][:] + + refLayerThickness = np.zeros(nVertLevels) + refLayerThickness[0] = refBottomDepth[0] + refLayerThickness[1:nVertLevels] = refBottomDepth[1:nVertLevels]-refBottomDepth[0:nVertLevels-1] + + refTopDepth = np.zeros(nVertLevels+1) + refTopDepth[1:nVertLevels+1] = refBottomDepth[0:nVertLevels] + + print 'Reading transects from: ' + fileNameMask + ncfileMask = Dataset(fileNameMask,'r') + nTransects = ncfileMask.dimensions['nTransects'].size + maxEdgesInTransect = ncfileMask.dimensions['maxEdgesInTransect'].size + + transectEdgeMaskSigns = ncfileMask.variables['transectEdgeMaskSigns'][:,:] + transectEdgeGlobalIDs = ncfileMask.variables['transectEdgeGlobalIDs'][:,:] + + print 'Reading regionss from: ' + fileNameMask + ncfileMask = Dataset(fileNameMask,'r') + nRegions = ncfileMask.dimensions['nRegions'].size + regionCellMasks = ncfileMask.variables['regionCellMasks'] + + # compute transport through transects + print('** compute transport: \n') + + # the volume transport + transport = np.zeros(nTransects); + transportZ = np.zeros([nVertLevels,nTransects]); + transportZEdge = np.zeros([nVertLevels,maxEdgesInTransect,nTransects]); + + for iTransect in range(nTransects): + for i in range(maxEdgesInTransect): + if transectEdgeGlobalIDs[iTransect, i]==0: + break + iEdge = transectEdgeGlobalIDs[iTransect, i] - 1 # subtract 1 because of python 0-indexing + for k in range(nVertLevels): + transportZEdge[k,i,iTransect] = ( transectEdgeMaskSigns[iEdge,iTransect] + * horVel[timeIndex,iEdge,k] * dvEdge[iEdge] * refLayerThickness[k]*m3ps_to_Sv ) + transportZ[k,iTransect] = transportZ[k,iTransect] + transportZEdge[k,i,iTransect] + transport[iTransect] = transport[iTransect] + transportZEdge[k,i,iTransect] + + # compute MOC + print('** compute moc: \n') + + nLat = np.size(mocLat) + mocTop = np.zeros((nLat,nVertLevels+1)) + + for iRegion in range(nRegions): + # assume transects and regions have the same index ordering: + iTransect = iRegion + + for k in range(1,nVertLevels+1): + mocTop[0,k] = mocTop[0,k-1] + transportZ[k-1,iTransect]/m3ps_to_Sv + + for iLat in range(1,nLat): + ind =np.logical_and(np.logical_and(regionCellMasks[:,iRegion]==1,latCell >= mocLat[iLat-1] ), latCell < mocLat[iLat]) + + for k in range(1,nVertLevels+1): + mocTop[iLat,k] = mocTop[iLat-1,k] + np.sum(vertVel[timeIndex,ind,k]*areaCell[ind]) + + # convert m^3/s to Sverdrup + mocTop = mocTop * m3ps_to_Sv + + # plot MOC + print('** plot moc: \n') + plot_moc(config, mocLat, refTopDepth, mocTop) + + ncfile.close() + ncfileMask.close() + + return #}}} + +# vim: foldmethod=marker ai ts=4 sts=4 et sw=4 ft=python diff --git a/mpas_analysis/shared/constants/constants.py b/mpas_analysis/shared/constants/constants.py index 1e1a72f6d..c08fe2cfd 100644 --- a/mpas_analysis/shared/constants/constants.py +++ b/mpas_analysis/shared/constants/constants.py @@ -22,4 +22,5 @@ dinmonth = np.array([31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]) +m3ps_to_Sv = 1e-6; # m^3/sec flux to Sverdrups diff --git a/mpas_analysis/shared/plot/plotting.py b/mpas_analysis/shared/plot/plotting.py index ee72a1834..2db45b3e6 100644 --- a/mpas_analysis/shared/plot/plotting.py +++ b/mpas_analysis/shared/plot/plotting.py @@ -202,3 +202,35 @@ def plot_global_comparison( if not config.getboolean('plot','displayToScreen'): plt.close() + +def plot_moc(config, mocLat, + refTopDepth, + mocTop, + fileout = 'moc' + '.png', + figsize=(8, 4.5), + dpi=300): #{{{ + + contourLines = config.getExpression('moc_postprocess', 'contourLines', usenumpy=True) + + fig = plt.figure(figsize=figsize, dpi=dpi) + X, Y = np.meshgrid(mocLat,refTopDepth) # change to zMid + + contourSet = plt.contourf(X,Y,mocTop.T,levels=contourLines) + contourSet2 = plt.contour(X,Y,mocTop.T,levels=contourLines[::2],colors='k',hold='on') + + plt.xlabel('latitude') + plt.ylabel('depth, m') + plt.title('MPAS-Ocean Atlantic MOC, Sv') + plt.gca().invert_yaxis() + #plt.clabel(contourSet, fontsize=10) + # Make a colorbar for the ContourSet returned by the contourf call. + cbar = plt.colorbar(contourSet) + cbar.add_lines(contourSet2) + + if (fileout is not None): + plt.savefig(fileout,dpi=dpi,bbox_inches='tight',pad_inches=0.1) + + if not config.getboolean('plot', 'displayToScreen'): + plt.close() + + return #}}} diff --git a/run_analysis.py b/run_analysis.py index c02848818..2599a1bb6 100755 --- a/run_analysis.py +++ b/run_analysis.py @@ -148,6 +148,12 @@ def analysis(config): # {{{ ocn_modelvsobs(config, 'sss', streamMap=oceanStreamMap, variableMap=oceanVariableMap) + if config.getboolean('moc_postprocess', 'generate'): + print "" + print "Plotting post-process computed meridional overturning circulation..." + from mpas_analysis.ocean.meridional_overturning_circulation import moc_postprocess + moc_postprocess(config, streamMap=oceanStreamMap, + variableMap=oceanVariableMap) # GENERATE SEA-ICE DIAGNOSTICS if config.getboolean('seaice_timeseries', 'generate'): From 6c3fbad5b72a5ca30e6687ae6721f28dcdc19362 Mon Sep 17 00:00:00 2001 From: "Phillip J. Wolfram" Date: Mon, 23 Jan 2017 07:24:18 -0700 Subject: [PATCH 3/3] BFB Cleanup: adds docstring and PEP8 compliance --- mpas_analysis/shared/plot/plotting.py | 190 ++++++++++++++++---------- 1 file changed, 121 insertions(+), 69 deletions(-) diff --git a/mpas_analysis/shared/plot/plotting.py b/mpas_analysis/shared/plot/plotting.py index 2db45b3e6..9fd232eb1 100644 --- a/mpas_analysis/shared/plot/plotting.py +++ b/mpas_analysis/shared/plot/plotting.py @@ -1,12 +1,27 @@ +#!/usr/bin/env python +""" +Plotting routines + +Xylar Asay-Davis, Phillip Wolfram +Last modified: 01/23/2017 +""" + import matplotlib.pyplot as plt import pandas as pd from mpl_toolkits.basemap import Basemap import matplotlib.colors as cols import numpy as np -def timeseries_analysis_plot(config, dsvalues, N, title, xlabel, ylabel, fileout, - lineStyles, lineWidths, title_font_size=None, - figsize=(15,6), dpi=300): +def timeseries_analysis_plot(config, dsvalues, N, title, xlabel, ylabel, + fileout,lineStyles, lineWidths, + title_font_size=None, + figsize=(15, 6), dpi=300): # {{{ + """ + Timeseries plotting routine. + + Xylar Asay-Davis + Last modified: 09/15/2016 + """ plt.figure(figsize=figsize, dpi=dpi) @@ -31,11 +46,13 @@ def timeseries_analysis_plot(config, dsvalues, N, title, xlabel, ylabel, fileout if (ylabel != None): plt.ylabel(ylabel, **axis_font) if (fileout is not None): - plt.savefig(fileout,dpi=dpi,bbox_inches='tight',pad_inches=0.1) + plt.savefig(fileout,dpi=dpi, bbox_inches='tight', pad_inches=0.1) - if not config.getboolean('plot','displayToScreen'): + if not config.getboolean('plot', 'displayToScreen'): plt.close() + return # }}} + def plot_polar_comparison( config, @@ -58,8 +75,14 @@ def plot_polar_comparison( diffTitle = "Model-Observations", cbarlabel = "units", title_font_size = None, - figsize = (8,22), - dpi = 300): + figsize = (8, 22), + dpi = 300): # {{{ + """ + Plots model versus observations for polar regions. + + Xylar Asay-Davis + Last modified: 09/15/2016 + """ # set up figure fig = plt.figure(figsize=figsize, dpi=dpi) @@ -72,54 +95,61 @@ def plot_polar_comparison( fig.suptitle(title, y=0.95, **title_font) axis_font = {'size':config.get('plot', 'axis_font_size')} - m = Basemap(projection=plotProjection,boundinglat=latmin,lon_0=lon0,resolution='l') + m = Basemap(projection=plotProjection, boundinglat=latmin, + lon_0=lon0, resolution='l') x, y = m(Lons, Lats) # compute map proj coordinates normModelObs = cols.BoundaryNorm(clevsModelObs, cmapModelObs.N) normDiff = cols.BoundaryNorm(clevsDiff, cmapDiff.N) - plt.subplot(3,1,1) + plt.subplot(3, 1, 1) plt.title(modelTitle, y=1.06, **axis_font) m.drawcoastlines() m.fillcontinents(color='grey',lake_color='white') - m.drawparallels(np.arange(-80.,81.,10.)) - m.drawmeridians(np.arange(-180.,181.,20.),labels=[True,True,True,True]) - cs = m.contourf(x,y,modelArray,cmap=cmapModelObs,norm=normModelObs,spacing='uniform',levels=clevsModelObs) - cbar = m.colorbar(cs,location='right',pad="15%",spacing='uniform',ticks=clevsModelObs,boundaries=clevsModelObs) - #cbar = m.colorbar(cs,location='right',pad="15%",spacing='uniform',extendfrac='auto', - # extendrect='True',ticks=clevsModelObs, boundaries=clevsModelObs) + m.drawparallels(np.arange(-80., 81., 10.)) + m.drawmeridians(np.arange(-180., 181., 20.), + labels=[True, True, True, True]) + cs = m.contourf(x, y, modelArray, cmap=cmapModelObs, norm=normModelObs, + spacing='uniform', levels=clevsModelObs) + cbar = m.colorbar(cs, location='right', pad="15%", spacing='uniform', + ticks=clevsModelObs, boundaries=clevsModelObs) + cbar.set_label(cbarlabel) - plt.subplot(3,1,2) + plt.subplot(3, 1, 2) plt.title(obsTitle, y=1.06, **axis_font) m.drawcoastlines() m.fillcontinents(color='grey',lake_color='white') - m.drawparallels(np.arange(-80.,81.,10.)) - m.drawmeridians(np.arange(-180.,181.,20.),labels=[True,True,True,True]) - cs = m.contourf(x,y,obsArray,cmap=cmapModelObs,norm=normModelObs,spacing='uniform',levels=clevsModelObs) - cbar = m.colorbar(cs,location='right',pad="15%",spacing='uniform',ticks=clevsModelObs,boundaries=clevsModelObs) - #cbar = m.colorbar(cs,location='right',pad="15%",spacing='uniform',extendfrac='auto', - # extendrect='True',ticks=clevsModelObs, boundaries=clevsModelObs) + m.drawparallels(np.arange(-80., 81., 10.)) + m.drawmeridians(np.arange(-180., 181., 20.), + labels=[True, True, True, True]) + cs = m.contourf(x, y, obsArray, cmap=cmapModelObs, norm=normModelObs, + spacing='uniform', levels=clevsModelObs) + cbar = m.colorbar(cs, location='right', pad="15%", spacing='uniform', + ticks=clevsModelObs, boundaries=clevsModelObs) cbar.set_label(cbarlabel) - plt.subplot(3,1,3) + plt.subplot(3, 1, 3) plt.title(diffTitle, y=1.06, **axis_font) m.drawcoastlines() m.fillcontinents(color='grey',lake_color='white') - m.drawparallels(np.arange(-80.,81.,10.)) - m.drawmeridians(np.arange(-180.,181.,20.),labels=[True,True,True,True]) - cs = m.contourf(x,y,diffArray,cmap=cmapDiff,norm=normDiff,spacing='uniform',levels=clevsDiff) - cbar = m.colorbar(cs,location='right',pad="15%",spacing='uniform',ticks=clevsDiff,boundaries=clevsModelObs) - #cbar = m.colorbar(cs,location='right',pad="15%",spacing='uniform',extendfrac='auto', - # extendrect='True',ticks=clevsDiff, boundaries=clevsDiff) + m.drawparallels(np.arange(-80., 81., 10.)) + m.drawmeridians(np.arange(-180., 181., 20.), + labels=[True, True, True, True]) + cs = m.contourf(x, y, diffArray, cmap=cmapDiff, norm=normDiff, + spacing='uniform', levels=clevsDiff) + cbar = m.colorbar(cs,location='right', pad="15%", spacing='uniform', + ticks=clevsDiff, boundaries=clevsModelObs) cbar.set_label(cbarlabel) if (fileout is not None): - plt.savefig(fileout,dpi=dpi,bbox_inches='tight',pad_inches=0.1) + plt.savefig(fileout, dpi=dpi, bbox_inches='tight', pad_inches=0.1) - if not config.getboolean('plot','displayToScreen'): + if not config.getboolean('plot', 'displayToScreen'): plt.close() + return # }}} + def plot_global_comparison( config, Lons, @@ -138,8 +168,14 @@ def plot_global_comparison( diffTitle = "Model-Observations", cbarlabel = "units", title_font_size = None, - figsize = (8,12), - dpi = 300): + figsize = (8, 12), + dpi = 300): # {{{ + """ + Plots model versus observations for global projections. + + Xylar Asay-Davis + Last modified: 09/15/2016 + """ # set up figure fig = plt.figure(figsize=figsize, dpi=dpi) @@ -151,84 +187,100 @@ def plot_global_comparison( 'weight':config.get('plot', 'title_font_weight')} fig.suptitle(title, y=0.95, **title_font) axis_font = {'size':config.get('plot', 'axis_font_size')} - - m = Basemap(projection='cyl',llcrnrlat=-85,urcrnrlat=86,llcrnrlon=-180,urcrnrlon=181,resolution='l') - #m = Basemap(projection='robin',lon_0=200,resolution='l') # this doesn't work because lons are -180 to 180.. + + m = Basemap(projection='cyl', llcrnrlat=-85, urcrnrlat=86, llcrnrlon=-180, + urcrnrlon=181, resolution='l') + # this doesn't work because lons are -180 to 180.. + #m = Basemap(projection='robin', lon_0=200, resolution='l') x, y = m(Lons, Lats) # compute map proj coordinates normModelObs = cols.BoundaryNorm(clevsModelObs, cmapModelObs.N) normDiff = cols.BoundaryNorm(clevsDiff, cmapDiff.N) - - plt.subplot(3,1,1) + + plt.subplot(3, 1, 1) plt.title(modelTitle, y=1.06, **axis_font) m.drawcoastlines() - m.fillcontinents(color='grey',lake_color='white') - m.drawparallels(np.arange(-80.,80.,20.),labels=[True,False,False,False]) - m.drawmeridians(np.arange(-180.,180.,60.),labels=[False,False,False,True]) - cs = m.contourf(x,y,modelArray,cmap=cmapModelObs,norm=normModelObs,spacing='uniform',levels=clevsModelObs,extend='both') - cbar = m.colorbar(cs,location='right',pad="5%",spacing='uniform',ticks=clevsModelObs,boundaries=clevsModelObs) - #cbar = m.colorbar(cs,location='right',pad="5%",spacing='uniform',extendfrac='auto', - # extendrect='True',ticks=clevsModelObs, boundaries=clevsModelObs) + m.fillcontinents(color='grey', lake_color='white') + m.drawparallels(np.arange(-80., 80., 20.), + labels=[True, False, False, False]) + m.drawmeridians(np.arange(-180., 180., 60.), + labels=[False, False, False, True]) + cs = m.contourf(x, y, modelArray, cmap=cmapModelObs, norm=normModelObs, + spacing='uniform', levels=clevsModelObs, extend='both') + cbar = m.colorbar(cs,location='right', pad="5%", spacing='uniform', + ticks=clevsModelObs, boundaries=clevsModelObs) cbar.set_label(cbarlabel) - plt.subplot(3,1,2) + plt.subplot(3, 1, 2) plt.title(obsTitle, y=1.06, **axis_font) m.drawcoastlines() m.fillcontinents(color='grey',lake_color='white') - m.drawparallels(np.arange(-80.,80.,20.),labels=[True,False,False,False]) - m.drawmeridians(np.arange(-180.,180.,40.),labels=[False,False,False,True]) - cs = m.contourf(x,y,obsArray,cmap=cmapModelObs,norm=normModelObs,spacing='uniform',levels=clevsModelObs,extend='both') - cbar = m.colorbar(cs,location='right',pad="5%",spacing='uniform',ticks=clevsModelObs,boundaries=clevsModelObs) - #cbar = m.colorbar(cs,location='right',pad="5%",spacing='uniform',extendfrac='auto', - # extendrect='True',ticks=clevsModelObs, boundaries=clevsModelObs) + m.drawparallels(np.arange(-80., 80., 20.), + labels=[True, False, False, False]) + m.drawmeridians(np.arange(-180., 180., 40.), + labels=[False, False, False, True]) + cs = m.contourf(x, y, obsArray, cmap=cmapModelObs, norm=normModelObs, + spacing='uniform', levels=clevsModelObs, extend='both') + cbar = m.colorbar(cs, location='right', pad="5%", spacing='uniform', + ticks=clevsModelObs, boundaries=clevsModelObs) cbar.set_label(cbarlabel) - - plt.subplot(3,1,3) + + plt.subplot(3, 1, 3) plt.title(diffTitle, y=1.06, **axis_font) m.drawcoastlines() m.fillcontinents(color='grey',lake_color='white') - m.drawparallels(np.arange(-80.,80.,20.),labels=[True,False,False,False]) - m.drawmeridians(np.arange(-180.,180.,40.),labels=[False,False,False,True]) - cs = m.contourf(x,y,diffArray,cmap=cmapDiff,norm=normDiff,spacing='uniform',levels=clevsDiff,extend='both') - cbar = m.colorbar(cs,location='right',pad="5%",spacing='uniform',ticks=clevsDiff,boundaries=clevsModelObs) - #cbar = m.colorbar(cs,location='right',pad="5%",spacing='uniform',extendfrac='auto', - # extendrect='True',ticks=clevsDiff, boundaries=clevsDiff) + m.drawparallels(np.arange(-80., 80., 20.), + labels=[True, False, False, False]) + m.drawmeridians(np.arange(-180., 180., 40.), + labels=[False, False, False, True]) + cs = m.contourf(x, y, diffArray, cmap=cmapDiff, norm=normDiff, + spacing='uniform', levels=clevsDiff, extend='both') + cbar = m.colorbar(cs, location='right', pad="5%", spacing='uniform', + ticks=clevsDiff, boundaries=clevsModelObs) cs.cmap.set_over((1., 1., 1.)) cs.cmap.set_under((0., 0., 0.)) cbar.set_label(cbarlabel) if (fileout is not None): - plt.savefig(fileout,dpi=dpi,bbox_inches='tight',pad_inches=0.1) + plt.savefig(fileout, dpi=dpi, bbox_inches='tight', pad_inches=0.1) - if not config.getboolean('plot','displayToScreen'): + if not config.getboolean('plot', 'displayToScreen'): plt.close() + return # }}} + def plot_moc(config, mocLat, refTopDepth, mocTop, fileout = 'moc' + '.png', figsize=(8, 4.5), dpi=300): #{{{ + """ + Plots comparison of moc section + + Mark Petersen, Phillip Wolfram + Last modified: 01/23/2017 + """ - contourLines = config.getExpression('moc_postprocess', 'contourLines', usenumpy=True) + contourLines = config.getExpression('moc_postprocess', + 'contourLines', usenumpy=True) fig = plt.figure(figsize=figsize, dpi=dpi) - X, Y = np.meshgrid(mocLat,refTopDepth) # change to zMid + X, Y = np.meshgrid(mocLat, refTopDepth) # change to zMid - contourSet = plt.contourf(X,Y,mocTop.T,levels=contourLines) - contourSet2 = plt.contour(X,Y,mocTop.T,levels=contourLines[::2],colors='k',hold='on') + contourSet = plt.contourf(X, Y, mocTop.T, levels=contourLines) + contourSet2 = plt.contour(X, Y, mocTop.T, levels=contourLines[::2], + colors='k', hold='on') plt.xlabel('latitude') plt.ylabel('depth, m') plt.title('MPAS-Ocean Atlantic MOC, Sv') plt.gca().invert_yaxis() - #plt.clabel(contourSet, fontsize=10) - # Make a colorbar for the ContourSet returned by the contourf call. cbar = plt.colorbar(contourSet) cbar.add_lines(contourSet2) if (fileout is not None): - plt.savefig(fileout,dpi=dpi,bbox_inches='tight',pad_inches=0.1) + plt.savefig(fileout, dpi=dpi, bbox_inches='tight', pad_inches=0.1) if not config.getboolean('plot', 'displayToScreen'): plt.close()