Example #1
0
    def run_task(self):  # {{{
        """
        Make the Hovmoller plot from the time series.
        """
        # Authors
        # -------
        # Xylar Asay-Davis, Milena Veneziani, Greg Streletz

        self.logger.info("\nPlotting {} trends vs. depth...".format(
            self.fieldNameInTitle))

        config = self.config

        mainRunName = config.get('runs', 'mainRunName')

        plotTitles = config.getExpression('regions', 'plotTitles')
        allRegionNames = config.getExpression('regions', 'regions')
        regionIndex = allRegionNames.index(self.regionName)
        regionNameInTitle = plotTitles[regionIndex]

        startDate = self.config.get('timeSeries', 'startDate')
        endDate = self.config.get('timeSeries', 'endDate')

        # Load data
        self.logger.info('  Load ocean data...')
        ds = open_mpas_dataset(fileName=self.inFileName,
                               calendar=self.calendar,
                               variableList=[self.mpasFieldName],
                               timeVariableNames=None,
                               startDate=startDate,
                               endDate=endDate)
        ds = ds.isel(nOceanRegionsTmp=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 OHC calculation')

        # Define/read in general variables
        self.logger.info('  Read in depth...')
        with xr.open_dataset(restartFile) as dsRestart:
            # reference depth [m]
            depth = dsRestart.refBottomDepth.values

        Time = ds.Time.values
        field = ds[self.mpasFieldName].values.transpose()

        xLabel = 'Time [years]'
        yLabel = 'Depth [m]'

        title = '{}, {} \n {}'.format(self.fieldNameInTitle, regionNameInTitle,
                                      mainRunName)

        figureName = '{}/{}.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

        plot_vertical_section(config,
                              Time,
                              depth,
                              field,
                              self.sectionName,
                              suffix='',
                              colorbarLabel=self.unitsLabel,
                              title=title,
                              xlabel=xLabel,
                              ylabel=yLabel,
                              fileout=figureName,
                              linewidths=1,
                              xArrayIsTime=True,
                              calendar=self.calendar,
                              firstYearXTicks=firstYearXTicks,
                              yearStrideXTicks=yearStrideXTicks)

        write_image_xml(config=config,
                        filePrefix=self.filePrefix,
                        componentName='Ocean',
                        componentSubdirectory='ocean',
                        galleryGroup=self.galleryGroup,
                        groupLink=self.groupLink,
                        galleryName=self.galleryName,
                        thumbnailDescription='{} {}'.format(
                            self.regionName, self.thumbnailSuffix),
                        imageDescription=self.imageCaption,
                        imageCaption=self.imageCaption)
    def run_task(self):  # {{{
        '''
        Process MOC analysis member data if available, or compute MOC at
        post-processing if not. Plots streamfunction climatolgoical sections
        as well as time series of max Atlantic MOC at 26.5N (latitude of
        RAPID MOC Array).
        '''
        # Authors
        # -------
        # Milena Veneziani, Mark Petersen, Phillip J. Wolfram, Xylar Asay-Davis

        self.logger.info("\nPlotting streamfunction of Meridional Overturning "
                         "Circulation (MOC)...")

        config = self.config

        # **** Compute MOC ****
        # Check whether MOC Analysis Member is enabled
        if self.mocAnalysisMemberEnabled:
            # Add a moc_analisysMember_processing
            self.logger.info('*** MOC Analysis Member is on ***')
            # (mocDictClimo, mocDictTseries) = \
            #     self._compute_moc_analysismember(config, streams, calendar,
            #                                      sectionName, dictClimo,
            #                                      dictTseries)

            # delete the following 3 lines after analysis of the MOC AM is
            # supported
            self.logger.info('...but not yet supported. Using offline MOC')
            self._compute_moc_climo_postprocess()
            dsMOCTimeSeries = self._compute_moc_time_series_postprocess()
        else:
            self._compute_moc_climo_postprocess()
            dsMOCTimeSeries = self._compute_moc_time_series_postprocess()

        # **** Plot MOC ****
        # Define plotting variables
        mainRunName = config.get('runs', 'mainRunName')
        movingAveragePoints = config.getint(self.sectionName,
                                            'movingAveragePoints')
        movingAveragePointsClimatological = config.getint(
            self.sectionName, 'movingAveragePointsClimatological')
        colorbarLabel = '[Sv]'
        xLabel = 'latitude [deg]'
        yLabel = 'depth [m]'

        for region in self.regionNames:
            self.logger.info('   Plot climatological {} MOC...'.format(region))
            title = '{} MOC (ANN, years {:04d}-{:04d})\n {}'.format(
                region, self.startYearClimo, self.endYearClimo, mainRunName)
            filePrefix = self.filePrefixes[region]
            figureName = '{}/{}.png'.format(self.plotsDirectory, filePrefix)

            x = self.lat[region]
            y = self.depth
            z = self.moc[region]
            plot_vertical_section(config,
                                  x,
                                  y,
                                  z,
                                  self.sectionName,
                                  suffix=region,
                                  colorbarLabel=colorbarLabel,
                                  title=title,
                                  xlabel=xLabel,
                                  ylabel=yLabel,
                                  fileout=figureName,
                                  N=movingAveragePointsClimatological)

            caption = '{} Meridional Overturning Streamfunction'.format(region)
            write_image_xml(
                config=config,
                filePrefix=filePrefix,
                componentName='Ocean',
                componentSubdirectory='ocean',
                galleryGroup='Meridional Overturning Streamfunction',
                groupLink='moc',
                thumbnailDescription=region,
                imageDescription=caption,
                imageCaption=caption)  # }}}

        # Plot time series
        self.logger.info('   Plot time series of max Atlantic MOC at 26.5N...')
        xLabel = 'Time [years]'
        yLabel = '[Sv]'
        title = 'Max Atlantic MOC at $26.5^\circ$N\n {}'.format(mainRunName)
        filePrefix = self.filePrefixes['timeSeries']

        figureName = '{}/{}.png'.format(self.plotsDirectory, filePrefix)

        if config.has_option(self.taskName, 'firstYearXTicks'):
            firstYearXTicks = config.getint(self.taskName, 'firstYearXTicks')
        else:
            firstYearXTicks = None

        if config.has_option(self.taskName, 'yearStrideXTicks'):
            yearStrideXTicks = config.getint(self.taskName, 'yearStrideXTicks')
        else:
            yearStrideXTicks = None

        timeseries_analysis_plot(config, [dsMOCTimeSeries.mocAtlantic26],
                                 movingAveragePoints,
                                 title,
                                 xLabel,
                                 yLabel,
                                 figureName,
                                 lineStyles=['k-'],
                                 lineWidths=[2],
                                 legendText=[None],
                                 calendar=self.calendar,
                                 firstYearXTicks=firstYearXTicks,
                                 yearStrideXTicks=yearStrideXTicks)

        caption = u'Time Series of maximum Meridional Overturning ' \
                  u'Circulation at 26.5°N'
        write_image_xml(config=config,
                        filePrefix=filePrefix,
                        componentName='Ocean',
                        componentSubdirectory='ocean',
                        galleryGroup='Meridional Overturning Streamfunction',
                        groupLink='moc',
                        thumbnailDescription='Time Series',
                        imageDescription=caption,
                        imageCaption=caption)  # }}}
    def run_task(self):  # {{{
        '''
        Process MOC analysis member data if available, or compute MOC at
        post-processing if not. Plots streamfunction climatolgoical sections
        as well as time series of max Atlantic MOC at 26.5N (latitude of
        RAPID MOC Array).
        '''
        # Authors
        # -------
        # Milena Veneziani, Mark Petersen, Phillip J. Wolfram, Xylar Asay-Davis

        self.logger.info("\nPlotting streamfunction of Meridional Overturning "
                         "Circulation (MOC)...")

        config = self.config

        # **** Compute MOC ****
        if not self.usePostprocessing and self.mocAnalysisMemberEnabled:
            self._compute_moc_climo_analysismember()
            dsMOCTimeSeries = self._compute_moc_time_series_analysismember()
        else:
            self._compute_moc_climo_postprocess()
            dsMOCTimeSeries = self._compute_moc_time_series_postprocess()

        # **** Plot MOC ****
        # Define plotting variables
        mainRunName = config.get('runs', 'mainRunName')
        movingAveragePoints = config.getint(self.sectionName,
                                            'movingAveragePoints')
        movingAveragePointsClimatological = config.getint(
            self.sectionName, 'movingAveragePointsClimatological')
        colorbarLabel = '[Sv]'
        xLabel = 'latitude [deg]'
        yLabel = 'depth [m]'

        for region in self.regionNames:
            self.logger.info('   Plot climatological {} MOC...'.format(region))
            title = '{} MOC (ANN, years {:04d}-{:04d})\n {}'.format(
                region, self.startYearClimo, self.endYearClimo, mainRunName)
            filePrefix = self.filePrefixes[region]
            figureName = '{}/{}.png'.format(self.plotsDirectory, filePrefix)

            x = self.lat[region]
            y = self.depth
            z = self.moc[region]
            # Subset lat range
            minLat = config.getExpression(self.sectionName,
                                          'latBinMin{}'.format(region))
            maxLat = config.getExpression(self.sectionName,
                                          'latBinMax{}'.format(region))
            indLat = np.logical_and(x >= minLat, x <= maxLat)
            x = x[indLat]
            z = z[:, indLat]

            plot_vertical_section(config,
                                  x,
                                  y,
                                  z,
                                  self.sectionName,
                                  suffix=region,
                                  colorbarLabel=colorbarLabel,
                                  title=title,
                                  xlabel=xLabel,
                                  ylabel=yLabel,
                                  fileout=figureName,
                                  N=movingAveragePointsClimatological)

            caption = '{} Meridional Overturning Streamfunction'.format(region)
            write_image_xml(
                config=config,
                filePrefix=filePrefix,
                componentName='Ocean',
                componentSubdirectory='ocean',
                galleryGroup='Meridional Overturning Streamfunction',
                groupLink='moc',
                thumbnailDescription=region,
                imageDescription=caption,
                imageCaption=caption)  # }}}

        # Plot time series
        self.logger.info('   Plot time series of max Atlantic MOC at 26.5N...')
        xLabel = 'Time [years]'
        yLabel = '[Sv]'
        title = 'Max Atlantic MOC at $26.5\degree$N\n {}'.format(mainRunName)
        filePrefix = self.filePrefixes['timeSeries']

        figureName = '{}/{}.png'.format(self.plotsDirectory, filePrefix)

        if config.has_option(self.taskName, 'firstYearXTicks'):
            firstYearXTicks = config.getint(self.taskName, 'firstYearXTicks')
        else:
            firstYearXTicks = None

        if config.has_option(self.taskName, 'yearStrideXTicks'):
            yearStrideXTicks = config.getint(self.taskName, 'yearStrideXTicks')
        else:
            yearStrideXTicks = None

        fields = [dsMOCTimeSeries.mocAtlantic26]
        lineColors = ['k']
        lineWidths = [2]
        legendText = [mainRunName]

        if self.refConfig is not None:

            refDirectory = build_config_full_path(self.refConfig, 'output',
                                                  'timeseriesSubdirectory')

            refStartYear = self.refConfig.getint('timeSeries', 'startYear')
            refEndYear = self.refConfig.getint('timeSeries', 'endYear')
            refStartDate = '{:04d}-01-01_00:00:00'.format(refStartYear)
            refEndDate = '{:04d}-12-31_23:59:59'.format(refEndYear)

            refFileName = '{}/mocTimeSeries.nc'.format(refDirectory)
            self.logger.info('   Read in reference run MOC time series')
            dsRefMOC = open_mpas_dataset(fileName=refFileName,
                                         calendar=self.calendar,
                                         timeVariableNames=None,
                                         variableList=['mocAtlantic26'],
                                         startDate=refStartDate,
                                         endDate=refEndDate)
            fields.append(dsRefMOC.mocAtlantic26)
            lineColors.append('r')
            lineWidths.append(2)
            refRunName = self.refConfig.get('runs', 'mainRunName')
            legendText.append(refRunName)

        timeseries_analysis_plot(config,
                                 fields,
                                 movingAveragePoints,
                                 title,
                                 xLabel,
                                 yLabel,
                                 figureName,
                                 calendar=self.calendar,
                                 lineColors=lineColors,
                                 lineWidths=lineWidths,
                                 legendText=legendText,
                                 firstYearXTicks=firstYearXTicks,
                                 yearStrideXTicks=yearStrideXTicks)

        caption = u'Time Series of maximum Meridional Overturning ' \
                  u'Circulation at 26.5°N'
        write_image_xml(config=config,
                        filePrefix=filePrefix,
                        componentName='Ocean',
                        componentSubdirectory='ocean',
                        galleryGroup='Meridional Overturning Streamfunction',
                        groupLink='moc',
                        thumbnailDescription='Time Series',
                        imageDescription=caption,
                        imageCaption=caption)  # }}}
Example #4
0
    def run_task(self):  # {{{
        """
        Process MHT analysis member data if available.
        Plots MHT as:
           1D function of latitude
           2D function of latitude and depth
        """
        # Authors
        # -------
        # Mark Petersen, Milena Veneziani, Xylar Asay-Davis

        self.logger.info("\nPlotting meridional heat transport (MHT)...")

        config = self.config

        mainRunName = config.get('runs', 'mainRunName')

        depthLimGlobal = config.getExpression(self.sectionName,
                                              'depthLimGlobal')
        xLimGlobal = config.getExpression(self.sectionName, 'xLimGlobal')
        movingAveragePoints = config.getint('meridionalHeatTransport',
                                            'movingAveragePoints')

        outputDirectory = build_config_full_path(
            config, 'output', 'mpasClimatologySubdirectory')

        make_directories(outputDirectory)

        outFileName = \
            '{}/meridionalHeatTransport_years{:04d}-{:04d}.nc'.format(
                outputDirectory, self.startYear, self.endYear)

        if os.path.exists(outFileName):
            self.logger.info('  Reading results from previous analysis run...')
            annualClimatology = xr.open_dataset(outFileName)
            refZMid = annualClimatology.refZMid.values
            binBoundaryMerHeatTrans = \
                annualClimatology.binBoundaryMerHeatTrans.values
        else:

            # Read in depth and MHT latitude points
            # Latitude is from binBoundaryMerHeatTrans
            try:
                restartFileName = self.runStreams.readpath('restart')[0]
            except ValueError:
                raise IOError('No MPAS-O restart file found: need at least '
                              'one for MHT calcuation')

            with xr.open_dataset(restartFileName) as dsRestart:
                refBottomDepth = dsRestart.refBottomDepth.values

            nVertLevels = len(refBottomDepth)
            refLayerThickness = np.zeros(nVertLevels)
            refLayerThickness[0] = refBottomDepth[0]
            refLayerThickness[1:nVertLevels] = \
                refBottomDepth[1:nVertLevels] - refBottomDepth[0:nVertLevels-1]

            refZMid = -refBottomDepth + 0.5 * refLayerThickness

            binBoundaryMerHeatTrans = None
            # first try timeSeriesStatsMonthly for bin boundaries, then try
            # meridionalHeatTransport stream as a backup option
            for streamName in [
                    'timeSeriesStatsMonthlyOutput',
                    'meridionalHeatTransportOutput'
            ]:
                try:
                    inputFile = self.historyStreams.readpath(streamName)[0]
                except ValueError:
                    raise IOError('At least one file from stream {} is needed '
                                  'to compute MHT'.format(streamName))

                with xr.open_dataset(inputFile) as ds:
                    if 'binBoundaryMerHeatTrans' in ds.data_vars:
                        binBoundaryMerHeatTrans = \
                            ds.binBoundaryMerHeatTrans.values
                        break

            if binBoundaryMerHeatTrans is None:
                raise ValueError('Could not find binBoundaryMerHeatTrans in '
                                 'either timeSeriesStatsMonthlyOutput or '
                                 'meridionalHeatTransportOutput streams')

            binBoundaryMerHeatTrans = np.rad2deg(binBoundaryMerHeatTrans)

            ###################################################################
            # Mark P Note: Currently only supports global MHT.
            # Need to add variables merHeatTransLatRegion and
            # merHeatTransLatZRegion
            # These are not computed by default in ACME right now.
            # Then we will need to add another section for regions with a loop
            # over number of regions.
            ###################################################################

            self.logger.info('\n   Plotting global meridional heat transport')

            self.logger.info('   Load data...')

            climatologyFileName = self.mpasClimatologyTask.get_file_name(
                season='ANN')

            variableList = [
                'timeMonthly_avg_meridionalHeatTransportLat',
                'timeMonthly_avg_meridionalHeatTransportLatZ'
            ]

            annualClimatology = xr.open_dataset(climatologyFileName)
            annualClimatology = subset_variables(annualClimatology,
                                                 variableList)
            annualClimatology = annualClimatology.isel(Time=0)

            annualClimatology.coords['refZMid'] = (('nVertLevels', ), refZMid)
            annualClimatology.coords['binBoundaryMerHeatTrans'] = \
                (('nMerHeatTransBinsP1',), binBoundaryMerHeatTrans)

            write_netcdf(annualClimatology, outFileName)

        # **** Plot MHT ****
        self.logger.info('   Plot global MHT...')
        # Plot 1D MHT (zonally averaged, depth integrated)
        x = binBoundaryMerHeatTrans
        y = annualClimatology.timeMonthly_avg_meridionalHeatTransportLat
        xLabel = 'latitude [deg]'
        yLabel = 'meridional heat transport [PW]'
        title = 'Global MHT (ANN, years {:04d}-{:04d})\n {}'.format(
            self.startYear, self.endYear, mainRunName)
        filePrefix = self.filePrefixes['mht']
        figureName = '{}/{}.png'.format(self.plotsDirectory, filePrefix)
        lineColors = ['k']
        lineWidths = [1.6]
        legendText = [mainRunName]
        xArrays = [x]
        fieldArrays = [y]
        errArrays = [None]
        if self.observationsFile is not None:
            # Load in observations
            dsObs = xr.open_dataset(self.observationsFile)
            xObs = dsObs.LATITUDE
            ncepGlobal = dsObs.GLOBALNCEP_ADJUSTED
            ncepErrGlobal = dsObs.GLOBALNCEP_ERR
            ecmwfGlobal = dsObs.GLOBALECMWF_ADJUSTED
            ecmwfErrGlobal = dsObs.GLOBALECMWF_ERR

            lineColors.extend(['b', 'g'])
            lineWidths.extend([1.2, 1.2])
            legendText.extend(
                ['Trenberth and Caron - NCEP', 'Trenberth and Caron - ECMWF'])
            xArrays.extend([xObs, xObs])
            fieldArrays.extend([ncepGlobal, ecmwfGlobal])
            errArrays.extend([ncepErrGlobal, ecmwfErrGlobal])

        if self.refConfig is not None:

            refStartYear = self.refConfig.getint('climatology', 'startYear')
            refEndYear = self.refConfig.getint('climatology', 'endYear')
            refDirectory = build_config_full_path(
                self.refConfig, 'output', 'mpasClimatologySubdirectory')

            refFileName = \
                '{}/meridionalHeatTransport_years{:04d}-{:04d}.nc'.format(
                    refDirectory, refStartYear, refEndYear)

            dsRef = xr.open_dataset(refFileName)
            refRunName = self.refConfig.get('runs', 'mainRunName')

            lineColors.append('r')
            lineWidths.append(1.2)
            legendText.append(refRunName)
            xArrays.append(dsRef.binBoundaryMerHeatTrans)
            fieldArrays.append(
                dsRef.timeMonthly_avg_meridionalHeatTransportLat)
            errArrays.append(None)

        if len(legendText) == 1:
            # no need for a legend
            legendText = [None]

        plot_1D(config,
                xArrays,
                fieldArrays,
                errArrays,
                lineColors=lineColors,
                lineWidths=lineWidths,
                legendText=legendText,
                title=title,
                xlabel=xLabel,
                ylabel=yLabel,
                fileout=figureName,
                xLim=xLimGlobal)

        self._write_xml(filePrefix)

        if config.getboolean(self.sectionName, 'plotVerticalSection'):
            # Plot 2D MHT (zonally integrated)

            # normalize 2D MHT by layer thickness
            MHTLatZVar = \
                annualClimatology.timeMonthly_avg_meridionalHeatTransportLatZ
            MHTLatZ = MHTLatZVar.values.T[:, :]
            for k in range(nVertLevels):
                MHTLatZ[k, :] = MHTLatZ[k, :] / refLayerThickness[k]

            x = binBoundaryMerHeatTrans
            y = refZMid
            z = MHTLatZ
            xLabel = 'latitude [deg]'
            yLabel = 'depth [m]'
            title = 'Global MHT (ANN, years {:04d}-{:04d})\n {}'.format(
                self.startYear, self.endYear, mainRunName)
            filePrefix = self.filePrefixes['mhtZ']
            figureName = '{}/{}.png'.format(self.plotsDirectory, filePrefix)
            colorbarLabel = '[PW/m]'
            plot_vertical_section(config,
                                  x,
                                  y,
                                  z,
                                  self.sectionName,
                                  suffix='',
                                  colorbarLabel=colorbarLabel,
                                  title=title,
                                  xlabel=xLabel,
                                  ylabel=yLabel,
                                  fileout=figureName,
                                  xLim=xLimGlobal,
                                  yLim=depthLimGlobal,
                                  invertYAxis=False,
                                  N=movingAveragePoints)

            self._write_xml(filePrefix)