def run_task(self): # {{{ """ Performs analysis of the time-series output of Antarctic sub-ice-shelf melt rates. """ # Authors # ------- # Xylar Asay-Davis, Stephen Price self.logger.info("\nPlotting Antarctic melt rate time series...") self.logger.info(' Load melt rate data...') config = self.config calendar = self.calendar totalMeltFlux, meltRates = self._compute_ice_shelf_fluxes() plotRef = self.refConfig is not None if plotRef: refRunName = self.refConfig.get('runs', 'mainRunName') refTotalMeltFlux, refMeltRates = \ self._load_ice_shelf_fluxes(self.refConfig) # Load observations from multiple files and put in dictionary based # on shelf keyname observationsDirectory = build_config_full_path(config, 'oceanObservations', 'meltSubdirectory') obsFileNameDict = { 'Rignot et al. (2013)': 'Rignot_2013_melt_rates.csv', 'Rignot et al. (2013) SS': 'Rignot_2013_melt_rates_SS.csv' } obsDict = {} # dict for storing dict of obs data for obsName in obsFileNameDict: obsFileName = '{}/{}'.format(observationsDirectory, obsFileNameDict[obsName]) obsDict[obsName] = {} obsFile = csv.reader(open(obsFileName, 'rU')) next(obsFile, None) # skip the header line for line in obsFile: # some later useful values commented out shelfName = line[0] # surveyArea = line[1] meltFlux = float(line[2]) meltFluxUncertainty = float(line[3]) meltRate = float(line[4]) meltRateUncertainty = float(line[5]) # actualArea = float( line[6] ) # actual area here is in sq km # build dict of obs. keyed to filename description # (which will be used for plotting) obsDict[obsName][shelfName] = { 'meltFlux': meltFlux, 'meltFluxUncertainty': meltFluxUncertainty, 'meltRate': meltRate, 'meltRateUncertainty': meltRateUncertainty } # If areas from obs file used need to be converted from sq km to sq m mainRunName = config.get('runs', 'mainRunName') movingAverageMonths = config.getint('timeSeriesAntarcticMelt', 'movingAverageMonths') nRegions = totalMeltFlux.sizes['nRegions'] outputDirectory = build_config_full_path(config, 'output', 'timeseriesSubdirectory') make_directories(outputDirectory) self.logger.info(' Make plots...') for iRegion in range(nRegions): regionName = self.iceShelvesToPlot[iRegion] # get obs melt flux and unc. for shelf (similar for rates) obsMeltFlux = [] obsMeltFluxUnc = [] obsMeltRate = [] obsMeltRateUnc = [] for obsName in obsDict: if regionName in obsDict[obsName]: obsMeltFlux.append( obsDict[obsName][regionName]['meltFlux']) obsMeltFluxUnc.append( obsDict[obsName][regionName]['meltFluxUncertainty']) obsMeltRate.append( obsDict[obsName][regionName]['meltRate']) obsMeltRateUnc.append( obsDict[obsName][regionName]['meltRateUncertainty']) else: # append NaN so this particular obs won't plot self.logger.warning('{} observations not available for ' '{}'.format(obsName, regionName)) obsMeltFlux.append(None) obsMeltFluxUnc.append(None) obsMeltRate.append(None) obsMeltRateUnc.append(None) title = regionName.replace('_', ' ') regionName = regionName.replace(' ', '_') xLabel = 'Time (yr)' yLabel = 'Melt Flux (GT/yr)' timeSeries = totalMeltFlux.isel(nRegions=iRegion) filePrefix = 'melt_flux_{}'.format(regionName) figureName = '{}/{}.png'.format(self.plotsDirectory, filePrefix) fields = [timeSeries] lineColors = ['k'] lineWidths = [2.5] legendText = [mainRunName] if plotRef: fields.append(refTotalMeltFlux.isel(nRegions=iRegion)) lineColors.append('r') lineWidths.append(1.2) legendText.append(refRunName) timeseries_analysis_plot(config, fields, movingAverageMonths, title, xLabel, yLabel, figureName, calendar=calendar, lineColors=lineColors, lineWidths=lineWidths, legendText=legendText, obsMean=obsMeltFlux, obsUncertainty=obsMeltFluxUnc, obsLegend=list(obsDict.keys())) caption = 'Running Mean of Total Melt Flux under Ice ' \ 'Shelves in the {} Region'.format(title) write_image_xml(config=config, filePrefix=filePrefix, componentName='Ocean', componentSubdirectory='ocean', galleryGroup='Antarctic Melt Time Series', groupLink='antmelttime', gallery='Total Melt Flux', thumbnailDescription=title, imageDescription=caption, imageCaption=caption) xLabel = 'Time (yr)' yLabel = 'Melt Rate (m/yr)' timeSeries = meltRates.isel(nRegions=iRegion) filePrefix = 'melt_rate_{}'.format(regionName) figureName = '{}/{}.png'.format(self.plotsDirectory, filePrefix) fields = [timeSeries] lineColors = ['k'] lineWidths = [2.5] legendText = [mainRunName] if plotRef: fields.append(refMeltRates.isel(nRegions=iRegion)) lineColors.append('r') lineWidths.append(1.2) legendText.append(refRunName) 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, fields, movingAverageMonths, title, xLabel, yLabel, figureName, calendar=calendar, lineColors=lineColors, lineWidths=lineWidths, legendText=legendText, obsMean=obsMeltRate, obsUncertainty=obsMeltRateUnc, obsLegend=list(obsDict.keys()), firstYearXTicks=firstYearXTicks, yearStrideXTicks=yearStrideXTicks) caption = 'Running Mean of Area-averaged Melt Rate under Ice ' \ 'Shelves in the {} Region'.format(title) write_image_xml(config=config, filePrefix=filePrefix, componentName='Ocean', componentSubdirectory='ocean', galleryGroup='Antarctic Melt Time Series', groupLink='antmelttime', gallery='Area-averaged Melt Rate', thumbnailDescription=title, 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) # }}}
def run_task(self): # {{{ """ Performs analysis of time series of sea-ice properties. """ # Authors # ------- # Xylar Asay-Davis, Milena Veneziani self.logger.info("\nPlotting sea-ice area and volume time series...") config = self.config calendar = self.calendar sectionName = self.taskName plotTitles = { 'iceArea': 'Sea-ice area', 'iceVolume': 'Sea-ice volume', 'iceThickness': 'Sea-ice mean thickness' } units = { 'iceArea': '[km$^2$]', 'iceVolume': '[10$^3$ km$^3$]', 'iceThickness': '[m]' } obsFileNames = { 'iceArea': { 'NH': build_config_full_path(config=config, section='seaIceObservations', relativePathOption='areaNH', relativePathSection=sectionName), 'SH': build_config_full_path(config=config, section='seaIceObservations', relativePathOption='areaSH', relativePathSection=sectionName) }, 'iceVolume': { 'NH': build_config_full_path(config=config, section='seaIceObservations', relativePathOption='volNH', relativePathSection=sectionName), 'SH': build_config_full_path(config=config, section='seaIceObservations', relativePathOption='volSH', relativePathSection=sectionName) } } # Some plotting rules titleFontSize = config.get('timeSeriesSeaIceAreaVol', 'titleFontSize') mainRunName = config.get('runs', 'mainRunName') preprocessedReferenceRunName = \ config.get('runs', 'preprocessedReferenceRunName') preprocessedReferenceDirectory = \ config.get('seaIcePreprocessedReference', 'baseDirectory') compareWithObservations = config.getboolean('timeSeriesSeaIceAreaVol', 'compareWithObservations') movingAveragePoints = config.getint('timeSeriesSeaIceAreaVol', 'movingAveragePoints') polarPlot = config.getboolean('timeSeriesSeaIceAreaVol', 'polarPlot') outputDirectory = build_config_full_path(config, 'output', 'timeseriesSubdirectory') make_directories(outputDirectory) self.logger.info(' Load sea-ice data...') # Load mesh dsTimeSeries = self._compute_area_vol() yearStart = days_to_datetime(dsTimeSeries['NH'].Time.min(), calendar=calendar).year yearEnd = days_to_datetime(dsTimeSeries['NH'].Time.max(), calendar=calendar).year timeStart = date_to_days(year=yearStart, month=1, day=1, calendar=calendar) timeEnd = date_to_days(year=yearEnd, month=12, day=31, calendar=calendar) if preprocessedReferenceRunName != 'None': # determine if we're beyond the end of the preprocessed data # (and go ahead and cache the data set while we're checking) outFolder = '{}/preprocessed'.format(outputDirectory) make_directories(outFolder) inFilesPreprocessed = '{}/icevol.{}.year*.nc'.format( preprocessedReferenceDirectory, preprocessedReferenceRunName) outFileName = '{}/iceVolume.nc'.format(outFolder) combine_time_series_with_ncrcat(inFilesPreprocessed, outFileName, logger=self.logger) dsPreprocessed = open_mpas_dataset(fileName=outFileName, calendar=calendar, timeVariableNames='xtime') preprocessedYearEnd = days_to_datetime(dsPreprocessed.Time.max(), calendar=calendar).year if yearStart <= preprocessedYearEnd: dsPreprocessedTimeSlice = \ dsPreprocessed.sel(Time=slice(timeStart, timeEnd)) else: self.logger.warning('Preprocessed time series ends before the ' 'timeSeries startYear and will not be ' 'plotted.') preprocessedReferenceRunName = 'None' if self.refConfig is not None: dsTimeSeriesRef = {} baseDirectory = build_config_full_path(self.refConfig, 'output', 'timeSeriesSubdirectory') refRunName = self.refConfig.get('runs', 'mainRunName') for hemisphere in ['NH', 'SH']: inFileName = '{}/seaIceAreaVol{}.nc'.format( baseDirectory, hemisphere) dsTimeSeriesRef[hemisphere] = xr.open_dataset(inFileName) norm = { 'iceArea': 1e-6, # m^2 to km^2 'iceVolume': 1e-12, # m^3 to 10^3 km^3 'iceThickness': 1. } xLabel = 'Time [years]' galleryGroup = 'Time Series' groupLink = 'timeseries' obs = {} preprocessed = {} figureNameStd = {} figureNamePolar = {} title = {} plotVars = {} obsLegend = {} plotVarsRef = {} for hemisphere in ['NH', 'SH']: self.logger.info(' Make {} plots...'.format(hemisphere)) for variableName in ['iceArea', 'iceVolume']: key = (hemisphere, variableName) # apply the norm to each variable plotVars[key] = (norm[variableName] * dsTimeSeries[hemisphere][variableName]) if self.refConfig is not None: plotVarsRef[key] = norm[variableName] * \ dsTimeSeriesRef[hemisphere][variableName] prefix = '{}/{}{}_{}'.format(self.plotsDirectory, variableName, hemisphere, mainRunName) figureNameStd[key] = '{}.png'.format(prefix) figureNamePolar[key] = '{}_polar.png'.format(prefix) title[key] = '{} ({})'.format(plotTitles[variableName], hemisphere) if compareWithObservations: key = (hemisphere, 'iceArea') obsLegend[key] = 'SSM/I observations, annual cycle ' if hemisphere == 'NH': key = (hemisphere, 'iceVolume') obsLegend[key] = 'PIOMAS, annual cycle (blue)' if preprocessedReferenceRunName != 'None': for variableName in ['iceArea', 'iceVolume']: key = (hemisphere, variableName) if compareWithObservations: outFolder = '{}/obs'.format(outputDirectory) make_directories(outFolder) outFileName = '{}/iceArea{}.nc'.format(outFolder, hemisphere) combine_time_series_with_ncrcat( obsFileNames['iceArea'][hemisphere], outFileName, logger=self.logger) dsObs = open_mpas_dataset(fileName=outFileName, calendar=calendar, timeVariableNames='xtime') key = (hemisphere, 'iceArea') obs[key] = self._replicate_cycle(plotVars[key], dsObs.IceArea, calendar) key = (hemisphere, 'iceVolume') if hemisphere == 'NH': outFileName = '{}/iceVolume{}.nc'.format( outFolder, hemisphere) combine_time_series_with_ncrcat( obsFileNames['iceVolume'][hemisphere], outFileName, logger=self.logger) dsObs = open_mpas_dataset(fileName=outFileName, calendar=calendar, timeVariableNames='xtime') obs[key] = self._replicate_cycle(plotVars[key], dsObs.IceVol, calendar) else: obs[key] = None if preprocessedReferenceRunName != 'None': outFolder = '{}/preprocessed'.format(outputDirectory) inFilesPreprocessed = '{}/icearea.{}.year*.nc'.format( preprocessedReferenceDirectory, preprocessedReferenceRunName) outFileName = '{}/iceArea.nc'.format(outFolder) combine_time_series_with_ncrcat(inFilesPreprocessed, outFileName, logger=self.logger) dsPreprocessed = open_mpas_dataset(fileName=outFileName, calendar=calendar, timeVariableNames='xtime') dsPreprocessedTimeSlice = dsPreprocessed.sel( Time=slice(timeStart, timeEnd)) key = (hemisphere, 'iceArea') preprocessed[key] = dsPreprocessedTimeSlice[ 'icearea_{}'.format(hemisphere.lower())] inFilesPreprocessed = '{}/icevol.{}.year*.nc'.format( preprocessedReferenceDirectory, preprocessedReferenceRunName) outFileName = '{}/iceVolume.nc'.format(outFolder) combine_time_series_with_ncrcat(inFilesPreprocessed, outFileName, logger=self.logger) dsPreprocessed = open_mpas_dataset(fileName=outFileName, calendar=calendar, timeVariableNames='xtime') dsPreprocessedTimeSlice = dsPreprocessed.sel( Time=slice(timeStart, timeEnd)) key = (hemisphere, 'iceVolume') preprocessed[key] = dsPreprocessedTimeSlice[ 'icevolume_{}'.format(hemisphere.lower())] for variableName in ['iceArea', 'iceVolume']: key = (hemisphere, variableName) dsvalues = [plotVars[key]] legendText = [mainRunName] lineColors = ['k'] lineWidths = [3] if compareWithObservations and key in obsLegend.keys(): dsvalues.append(obs[key]) legendText.append(obsLegend[key]) lineColors.append('b') lineWidths.append(1.2) if preprocessedReferenceRunName != 'None': dsvalues.append(preprocessed[key]) legendText.append(preprocessedReferenceRunName) lineColors.append('purple') lineWidths.append(1.2) if self.refConfig is not None: dsvalues.append(plotVarsRef[key]) legendText.append(refRunName) lineColors.append('r') lineWidths.append(1.2) if config.has_option(sectionName, 'firstYearXTicks'): firstYearXTicks = config.getint(sectionName, 'firstYearXTicks') else: firstYearXTicks = None if config.has_option(sectionName, 'yearStrideXTicks'): yearStrideXTicks = config.getint(sectionName, 'yearStrideXTicks') else: yearStrideXTicks = None # separate plots for nothern and southern hemispheres timeseries_analysis_plot(config, dsvalues, movingAveragePoints, title[key], xLabel, units[variableName], figureNameStd[key], calendar=calendar, lineColors=lineColors, lineWidths=lineWidths, legendText=legendText, titleFontSize=titleFontSize, firstYearXTicks=firstYearXTicks, yearStrideXTicks=yearStrideXTicks) filePrefix = '{}{}_{}'.format(variableName, hemisphere, mainRunName) thumbnailDescription = '{} {}'.format(hemisphere, plotTitles[variableName]) caption = 'Running mean of {}'.format(thumbnailDescription) write_image_xml(config, filePrefix, componentName='Sea Ice', componentSubdirectory='sea_ice', galleryGroup=galleryGroup, groupLink=groupLink, thumbnailDescription=thumbnailDescription, imageDescription=caption, imageCaption=caption) if (polarPlot): timeseries_analysis_plot_polar(config, dsvalues, movingAveragePoints, title[key], figureNamePolar[key], lineColors=lineColors, lineWidths=lineWidths, legendText=legendText, titleFontSize=titleFontSize) filePrefix = '{}{}_{}_polar'.format( variableName, hemisphere, mainRunName) write_image_xml(config, filePrefix, componentName='Sea Ice', componentSubdirectory='sea_ice', galleryGroup=galleryGroup, groupLink=groupLink, thumbnailDescription=thumbnailDescription, 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 **** # 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): # {{{ """ Performs analysis of the time-series output of sea-surface temperature (SST). """ # Authors # ------- # Xylar Asay-Davis, Milena Veneziani self.logger.info("\nPlotting SST time series...") self.logger.info(' Load SST data...') config = self.config calendar = self.calendar mainRunName = config.get('runs', 'mainRunName') preprocessedReferenceRunName = \ config.get('runs', 'preprocessedReferenceRunName') preprocessedInputDirectory = config.get('oceanPreprocessedReference', 'baseDirectory') movingAveragePoints = config.getint('timeSeriesSST', 'movingAveragePoints') regions = config.getExpression('regions', 'regions') plotTitles = config.getExpression('regions', 'plotTitles') regionsToPlot = config.getExpression('timeSeriesSST', 'regions') regionIndicesToPlot = [ regions.index(region) for region in regionsToPlot ] outputDirectory = build_config_full_path(config, 'output', 'timeseriesSubdirectory') make_directories(outputDirectory) dsSST = open_mpas_dataset(fileName=self.inputFile, calendar=calendar, variableList=self.variableList, startDate=self.startDate, endDate=self.endDate) yearStart = days_to_datetime(dsSST.Time.min(), calendar=calendar).year yearEnd = days_to_datetime(dsSST.Time.max(), calendar=calendar).year timeStart = date_to_days(year=yearStart, month=1, day=1, calendar=calendar) timeEnd = date_to_days(year=yearEnd, month=12, day=31, calendar=calendar) if self.refConfig is not None: baseDirectory = build_config_full_path(self.refConfig, 'output', 'timeSeriesSubdirectory') refFileName = '{}/{}.nc'.format( baseDirectory, self.mpasTimeSeriesTask.fullTaskName) 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) dsRefSST = open_mpas_dataset(fileName=refFileName, calendar=calendar, variableList=self.variableList, startDate=refStartDate, endDate=refEndDate) else: dsRefSST = None if preprocessedReferenceRunName != 'None': self.logger.info(' Load in SST for a preprocesses reference ' 'run...') inFilesPreprocessed = '{}/SST.{}.year*.nc'.format( preprocessedInputDirectory, preprocessedReferenceRunName) outFolder = '{}/preprocessed'.format(outputDirectory) make_directories(outFolder) outFileName = '{}/sst.nc'.format(outFolder) combine_time_series_with_ncrcat(inFilesPreprocessed, outFileName, logger=self.logger) dsPreprocessed = open_mpas_dataset(fileName=outFileName, calendar=calendar, timeVariableNames='xtime') yearEndPreprocessed = days_to_datetime(dsPreprocessed.Time.max(), calendar=calendar).year if yearStart <= yearEndPreprocessed: dsPreprocessedTimeSlice = \ dsPreprocessed.sel(Time=slice(timeStart, timeEnd)) else: self.logger.warning('Preprocessed time series ends before the ' 'timeSeries startYear and will not be ' 'plotted.') preprocessedReferenceRunName = 'None' self.logger.info(' Make plots...') for regionIndex in regionIndicesToPlot: region = regions[regionIndex] title = '{} SST'.format(plotTitles[regionIndex]) xLabel = 'Time [years]' yLabel = '[$\degree$C]' varName = self.variableList[0] SST = dsSST[varName].isel(nOceanRegions=regionIndex) filePrefix = self.filePrefixes[region] figureName = '{}/{}.png'.format(self.plotsDirectory, filePrefix) lineColors = ['k'] lineWidths = [3] fields = [SST] legendText = [mainRunName] if dsRefSST is not None: refSST = dsRefSST[varName].isel(nOceanRegions=regionIndex) fields.append(refSST) lineColors.append('r') lineWidths.append(1.5) refRunName = self.refConfig.get('runs', 'mainRunName') legendText.append(refRunName) if preprocessedReferenceRunName != 'None': SST_v0 = dsPreprocessedTimeSlice.SST fields.append(SST_v0) lineColors.append('purple') lineWidths.append(1.5) legendText.append(preprocessedReferenceRunName) 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, fields, movingAveragePoints, title, xLabel, yLabel, figureName, calendar=calendar, lineColors=lineColors, lineWidths=lineWidths, legendText=legendText, firstYearXTicks=firstYearXTicks, yearStrideXTicks=yearStrideXTicks) caption = 'Running Mean of {} Sea Surface Temperature'.format( region) write_image_xml(config=config, filePrefix=filePrefix, componentName='Ocean', componentSubdirectory='ocean', galleryGroup='Time Series', groupLink='timeseries', thumbnailDescription='{} SST'.format(region), imageDescription=caption, imageCaption=caption)
def run_task(self): # {{{ """ Compute vertical agregates of the data and plot the time series """ # Authors # ------- # Xylar Asay-Davis, Milena Veneziani, Greg Streletz self.logger.info("\nPlotting depth-integrated time series of " "{}...".format(self.fieldNameInTitle)) config = self.config calendar = self.calendar mainRunName = config.get('runs', 'mainRunName') plotTitles = config.getExpression('regions', 'plotTitles') allRegionNames = config.getExpression('regions', 'regions') regionIndex = allRegionNames.index(self.regionName) regionNameInTitle = plotTitles[regionIndex] startDate = config.get('timeSeries', 'startDate') endDate = config.get('timeSeries', 'endDate') # Load data self.logger.info(' Load ocean data...') ds = open_mpas_dataset(fileName=self.inFileName, calendar=calendar, variableList=[self.mpasFieldName, 'depth'], timeVariableNames=None, startDate=startDate, endDate=endDate) ds = ds.isel(nOceanRegionsTmp=regionIndex) depths = ds.depth.values divisionDepths = config.getExpression(self.sectionName, 'depths') # for each depth interval to plot, determine the top and bottom depth topDepths = [0, 0] + divisionDepths bottomDepths = [depths[-1]] + divisionDepths + [depths[-1]] legends = [] for top, bottom in zip(topDepths, bottomDepths): if bottom == depths[-1]: legends.append('{}m-bottom'.format(top)) else: legends.append('{}m-{}m'.format(top, bottom)) # more possible symbols than we typically use lines = ['-', '-', '--', '+', 'o', '^', 'v'] widths = [5, 3, 3, 3, 3, 3, 3] points = [None, None, None, 300, 300, 300, 300] color = 'k' xLabel = 'Time [years]' yLabel = self.yAxisLabel title = '{}, {} \n {} (black)'.format(self.fieldNameInTitle, regionNameInTitle, mainRunName) figureName = '{}/{}.png'.format(self.plotsDirectory, self.filePrefix) timeSeries = [] lineStyles = [] lineWidths = [] maxPoints = [] legendText = [] for rangeIndex in range(len(topDepths)): top = topDepths[rangeIndex] bottom = bottomDepths[rangeIndex] field = ds[self.mpasFieldName].where(ds.depth > top) field = field.where(ds.depth <= bottom) timeSeries.append(field.sum('nVertLevels')) lineStyles.append('{}{}'.format(color, lines[rangeIndex])) lineWidths.append(widths[rangeIndex]) maxPoints.append(points[rangeIndex]) legendText.append(legends[rangeIndex]) preprocessedReferenceRunName = config.get( 'runs', 'preprocessedReferenceRunName') if preprocessedReferenceRunName != 'None': preprocessedInputDirectory = config.get( 'oceanPreprocessedReference', 'baseDirectory') self.logger.info(' Load in OHC from preprocessed reference ' 'run...') preprocessedFilePrefix = config.get(self.sectionName, 'preprocessedFilePrefix') inFilesPreprocessed = '{}/{}.{}.year*.nc'.format( preprocessedInputDirectory, preprocessedFilePrefix, preprocessedReferenceRunName) dsPreprocessed = open_multifile_dataset( fileNames=inFilesPreprocessed, calendar=calendar, config=config, timeVariableName='xtime') yearStart = days_to_datetime(ds.Time.min(), calendar=calendar).year yearEnd = days_to_datetime(ds.Time.max(), calendar=calendar).year timeStart = date_to_days(year=yearStart, month=1, day=1, calendar=calendar) timeEnd = date_to_days(year=yearEnd, month=12, day=31, calendar=calendar) yearEndPreprocessed = days_to_datetime(dsPreprocessed.Time.max(), calendar=calendar).year if yearStart <= yearEndPreprocessed: dsPreprocessed = dsPreprocessed.sel( Time=slice(timeStart, timeEnd)) else: self.logger.warning('Warning: Preprocessed time series ends ' 'before the timeSeries startYear and will ' 'not be plotted.') preprocessedReferenceRunName = 'None' # rolling mean seems to have trouble with dask data sets so we # write out the data set and read it back as a single-file data set # (without dask) dsPreprocessed = dsPreprocessed.drop('xtime') write_netcdf(dsPreprocessed, self.preprocessedFileName) dsPreprocessed = xarray.open_dataset(self.preprocessedFileName) if preprocessedReferenceRunName != 'None': color = 'r' title = '{} \n {} (red)'.format(title, preprocessedReferenceRunName) preprocessedFieldPrefix = config.get(self.sectionName, 'preprocessedFieldPrefix') movingAveragePoints = config.getint(self.sectionName, 'movingAveragePoints') suffixes = ['tot' ] + ['{}m'.format(depth) for depth in divisionDepths] + ['btm'] # these preprocessed data are OHC *anomalies* dsPreprocessed = compute_moving_avg(dsPreprocessed, movingAveragePoints) for rangeIndex in range(len(suffixes)): variableName = '{}_{}'.format(preprocessedFieldPrefix, suffixes[rangeIndex]) if variableName in list(dsPreprocessed.data_vars.keys()): timeSeries.append(dsPreprocessed[variableName]) else: self.logger.warning( 'Warning: Preprocessed variable {} ' 'not found. Skipping.'.format(variableName)) timeSeries.extend(None) lineStyles.append('{}{}'.format(color, lines[rangeIndex])) lineWidths.append(widths[rangeIndex]) maxPoints.append(points[rangeIndex]) legendText.append(None) if self.refConfig is not None: refRunName = self.refConfig.get('runs', 'mainRunName') title = '{} \n {} (blue)'.format(title, refRunName) self.logger.info(' Load ocean data from reference run...') 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) dsRef = open_mpas_dataset( fileName=self.refFileName, calendar=calendar, variableList=[self.mpasFieldName, 'depth'], timeVariableNames=None, startDate=refStartDate, endDate=refEndDate) dsRef = dsRef.isel(nOceanRegionsTmp=regionIndex) color = 'b' for rangeIndex in range(len(topDepths)): top = topDepths[rangeIndex] bottom = bottomDepths[rangeIndex] field = dsRef[self.mpasFieldName].where(dsRef.depth > top) field = field.where(dsRef.depth <= bottom) timeSeries.append(field.sum('nVertLevels')) lineStyles.append('{}{}'.format(color, lines[rangeIndex])) lineWidths.append(widths[rangeIndex]) maxPoints.append(points[rangeIndex]) legendText.append(None) 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=config, dsvalues=timeSeries, N=None, title=title, xlabel=xLabel, ylabel=yLabel, fileout=figureName, lineStyles=lineStyles, lineWidths=lineWidths, maxPoints=maxPoints, legendText=legendText, calendar=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)