# -*- coding: utf-8 -*-
# This software is open source software available under the BSD-3 license.
#
# Copyright (c) 2019 Triad National Security, LLC. All rights reserved.
# Copyright (c) 2019 Lawrence Livermore National Security, LLC. All rights
# reserved.
# Copyright (c) 2019 UT-Battelle, LLC. All rights reserved.
#
# Additional copyright and license information can be found in the LICENSE file
# distributed with this code, or at
# https://raw.githubusercontent.com/MPAS-Dev/MPAS-Analysis/master/LICENSE
#
from __future__ import absolute_import, division, print_function, \
unicode_literals
import xarray as xr
import numpy as np
import os
from mpas_analysis.shared import AnalysisTask
from mpas_analysis.shared.plot import plot_vertical_section, savefig
from mpas_analysis.shared.io.utility import build_config_full_path, \
decode_strings
from mpas_analysis.shared.html import write_image_xml
[docs]class PlotHovmollerSubtask(AnalysisTask):
"""
Plots a time series vs. depth
Attributes
----------
regionName : str
The name of the region to plot
inFileName : str
The file containing the time-depth data set to plot
outFileLabel : str
The prefix on each plot and associated XML file
fieldNameInTitle : str
The name of the field being plotted, as used in the plot title
mpasFieldName : str
The name of the variable in the MPAS timeSeriesStatsMonthly output
unitsLabel : str
The units of the plotted field, to be displayed on color bars
sectionName : str
A section in the config file where the colormap and contour values
are defined
thumbnailSuffix : str
The text to be displayed under the thumbnail image, to which the
region name will be prepended
imageCaption : str
The caption when mousing over the plot or displaying it full
screen
galleryGroup : str
The name of the group of galleries in which this plot belongs
groupSubtitle : str
The subtitle of the group in which this plot belongs (or blank
if none)
groupLink : str
A short name (with no spaces) for the link to the gallery group
galleryName : str
The name of the gallery in which this plot belongs
"""
# Authors
# -------
# Xylar Asay-Davis, Milena Veneziani, Greg Streletz
[docs] def __init__(self, parentTask, regionName, inFileName, outFileLabel,
fieldNameInTitle, mpasFieldName, unitsLabel, sectionName,
thumbnailSuffix, imageCaption, galleryGroup, groupSubtitle,
groupLink, galleryName, subtaskName=None): # {{{
"""
Construct the analysis task.
Parameters
----------
parentTask : ``AnalysisTask``
The parent task of which this is a subtask
regionName : str
The name of the region to plot
inFileName : str
The file containing the time-depth data set to plot
outFileLabel : str
The prefix on each plot and associated XML file
fieldNameInTitle : str
The name of the field being plotted, as used in the plot title
mpasFieldName : str
The name of the variable in the MPAS timeSeriesStatsMonthly output
unitsLabel : str
the units of the plotted field, to be displayed on color bars
sectionName : str
a section in the config file where the colormap and contour values
are defined
thumbnailSuffix : str
The text to be displayed under the thumbnail image, to which the
region name will be prepended
imageCaption : str
the caption when mousing over the plot or displaying it full
screen
galleryGroup : str
the name of the group of galleries in which this plot belongs
groupSubtitle : str
the subtitle of the group in which this plot belongs (or blank
if none)
groupLink : str
a short name (with no spaces) for the link to the gallery group
galleryName : str
the name of the gallery in which this plot belongs
subtaskName : str
The name of the subtask (``plotHovmoller<RegionName>`` by default)
"""
# Authors
# -------
# Xylar Asay-Davis
if subtaskName is None:
suffix = regionName[0].upper() + regionName[1:]
subtaskName = 'plotHovmoller{}'.format(suffix)
# first, call the constructor from the base class (AnalysisTask)
super(PlotHovmollerSubtask, self).__init__(
config=parentTask.config,
taskName=parentTask.taskName,
componentName='ocean',
tags=parentTask.tags,
subtaskName=subtaskName)
self.regionName = regionName
self.inFileName = inFileName
self.outFileLabel = outFileLabel
self.fieldNameInTitle = fieldNameInTitle
self.mpasFieldName = mpasFieldName
self.unitsLabel = unitsLabel
self.sectionName = sectionName
# xml/html related variables
self.thumbnailSuffix = thumbnailSuffix
self.imageCaption = imageCaption
self.galleryGroup = galleryGroup
self.groupSubtitle = groupSubtitle
self.groupLink = groupLink
self.galleryName = galleryName
# }}}
def setup_and_check(self): # {{{
"""
Perform steps to set up the analysis and check for errors in the setup.
"""
# Authors
# -------
# Xylar Asay-Davis, Greg Streletz
# first, call setup_and_check from the base class (AnalysisTask),
# which will perform some common setup, including storing:
# self.runDirectory , self.historyDirectory, self.plotsDirectory,
# self.namelist, self.runStreams, self.historyStreams,
# self.calendar
super(PlotHovmollerSubtask, self).setup_and_check()
config = self.config
if not os.path.isabs(self.inFileName):
baseDirectory = build_config_full_path(
config, 'output', 'timeSeriesSubdirectory')
self.inFileName = '{}/{}'.format(baseDirectory,
self.inFileName)
mainRunName = self.config.get('runs', 'mainRunName')
self.filePrefix = '{}_{}_{}'.format(self.outFileLabel,
self.regionName,
mainRunName)
self.xmlFileNames = ['{}/{}.xml'.format(
self.plotsDirectory, self.filePrefix)]
return # }}}
def run_task(self): # {{{
"""
Make the Hovmoller plot from the time series.
"""
# Authors
# -------
# Xylar Asay-Davis, Milena Veneziani, Greg Streletz
self.logger.info("\nPlotting {} time series vs. depth...".format(
self.fieldNameInTitle))
config = self.config
mainRunName = config.get('runs', 'mainRunName')
self.logger.info(' Load ocean data...')
ds = xr.open_dataset(self.inFileName)
if 'regionNames' in ds.coords:
allRegionNames = decode_strings(ds.regionNames)
regionIndex = allRegionNames.index(self.regionName)
regionNameInTitle = self.regionName.replace('_', ' ')
regionDim = ds.regionNames.dims[0]
else:
plotTitles = config.getExpression('regions', 'plotTitles')
allRegionNames = config.getExpression('regions', 'regions')
regionIndex = allRegionNames.index(self.regionName)
regionNameInTitle = plotTitles[regionIndex]
regionDim = 'nOceanRegionsTmp'
ds = ds.isel(**{regionDim: regionIndex})
# Note: restart file, not a mesh file because we need refBottomDepth,
# not in a mesh file
try:
restartFile = self.runStreams.readpath('restart')[0]
except ValueError:
raise IOError('No MPAS-O restart file found: need at least one '
'restart file for plotting time series vs. depth')
# Define/read in general variables
self.logger.info(' Read in depth...')
with xr.open_dataset(restartFile) as dsRestart:
# reference depth [m]
depths = dsRestart.refBottomDepth.values
z = np.zeros(depths.shape)
z[0] = -0.5 * depths[0]
z[1:] = -0.5 * (depths[0:-1] + depths[1:])
Time = ds.Time.values
field = ds[self.mpasFieldName].values.transpose()
xLabel = 'Time (years)'
yLabel = 'Depth (m)'
title = '{}, {} \n {}'.format(self.fieldNameInTitle, regionNameInTitle,
mainRunName)
outFileName = '{}/{}.png'.format(self.plotsDirectory, self.filePrefix)
if config.has_option(self.sectionName, 'firstYearXTicks'):
firstYearXTicks = config.getint(self.sectionName,
'firstYearXTicks')
else:
firstYearXTicks = None
if config.has_option(self.sectionName, 'yearStrideXTicks'):
yearStrideXTicks = config.getint(self.sectionName,
'yearStrideXTicks')
else:
yearStrideXTicks = None
if config.has_option(self.sectionName, 'yLim'):
yLim = config.getExpression(self.sectionName, 'yLim')
else:
yLim = None
plot_vertical_section(config, Time, z, field, self.sectionName,
suffix='', colorbarLabel=self.unitsLabel,
title=title, xlabel=xLabel, ylabel=yLabel,
lineWidth=1,
xArrayIsTime=True, calendar=self.calendar,
firstYearXTicks=firstYearXTicks,
yearStrideXTicks=yearStrideXTicks,
yLim=yLim, invertYAxis=False)
savefig(outFileName)
write_image_xml(
config=config,
filePrefix=self.filePrefix,
componentName='Ocean',
componentSubdirectory='ocean',
galleryGroup=self.galleryGroup,
groupSubtitle=self.groupSubtitle,
groupLink=self.groupLink,
gallery=self.galleryName,
thumbnailDescription='{} {}'.format(
regionNameInTitle, self.thumbnailSuffix),
imageDescription=self.imageCaption,
imageCaption=self.imageCaption)
# }}}
# }}}
# vim: foldmethod=marker ai ts=4 sts=4 et sw=4 ft=python