diff --git a/docs/users_guide/tasks/timeSeriesTransport.rst b/docs/users_guide/tasks/timeSeriesTransport.rst index 044ba77dd..ebb747cb5 100644 --- a/docs/users_guide/tasks/timeSeriesTransport.rst +++ b/docs/users_guide/tasks/timeSeriesTransport.rst @@ -23,8 +23,7 @@ The following configuration options are available for this task:: # available transects. transectsToPlot = ['Drake Passage', 'Tasmania-Ant', 'Africa-Ant', 'Antilles Inflow', 'Mona Passage', 'Windward Passage', 'Florida-Cuba', 'Florida-Bahamas', - 'Indonesian Throughflow', 'Agulhas', 'Mozambique Channel', 'Bering Strait', - 'Lancaster Sound', 'Fram Strait', 'Nares Strait'] + 'Indonesian Throughflow', 'Agulhas', 'Mozambique Channel'] # Number of months over which to compute moving average movingAverageMonths = 1 @@ -54,8 +53,9 @@ defined in the ``transportTransects`` transect group. These are:: "Japan blockage", "Lancaster Sound", "Mona Passage", "Mozambique Channel", "Nares Strait", "Nares Strait Deepen", "Persian Gulf Deepen", "Red Sea Deepen", "Sakhalin blockage", "Strait of Gibralter Deepen 1", - "Strait of Gibralter Deepen 2", "Tasmania-Ant", "White Sea", - "Windward Passage"] + "Hudson Bay-Labrador Sea", "OSNAP section East", "OSNAP section West", + "Strait of Gibralter Deepen 2", "Tasmania-Ant", "White Sea", + "Windward Passage"] Many of these are likely not of interest in most simulations, so a subset of the most relevant transects has been chosen in the default configuration. diff --git a/mpas_analysis/default.cfg b/mpas_analysis/default.cfg index a15281bb1..b453faec9 100755 --- a/mpas_analysis/default.cfg +++ b/mpas_analysis/default.cfg @@ -1763,15 +1763,15 @@ obs = ['SOSE', 'WOA18'] [timeSeriesTransport] ## options related to plotting time series of transport through transects +transportGroups = ['Transport Transects'] +[timeSeriesTransportTransects] # list of ocean transects from geometric_features to plot or ['all'] for all # available transects. transectsToPlot = ['Drake Passage', 'Tasmania-Ant', 'Africa-Ant', 'Antilles Inflow', 'Mona Passage', 'Windward Passage', 'Florida-Cuba', 'Florida-Bahamas', 'Indonesian Throughflow', - 'Agulhas', 'Mozambique Channel', 'Bering Strait', - 'Lancaster Sound', 'Fram Strait', 'Nares Strait', - 'Denmark Strait', 'Iceland-Faroe-Scotland'] + 'Agulhas', 'Mozambique Channel'] # Number of months over which to compute moving average movingAveragePoints = 1 @@ -1790,6 +1790,27 @@ movingAveragePoints = 1 # Analysis may run faster for large meshes when this value is set to 2 or 3 subprocessCount = 1 +[timeSeriesArcticTransportTransects] + +transectsToPlot = ['all'] +# Number of months over which to compute moving average +movingAveragePoints = 1 + +# An optional first year for the tick marks on the x axis. Leave commented out +# to start at the beginning of the time series. + +# firstYearXTicks = 1 + +# An optional number of years between tick marks on the x axis. Leave +# commented out to determine the distance between ticks automatically. + +# yearStrideXTicks = 1 + +# The number of parallel tasks occupied by each timeSeriesTransport task. +# Analysis may run faster for large meshes when this value is set to 2 or 3 +subprocessCount = 1 + + [regionalTSDiagrams] ## options related to plotting T/S diagrams of ocean regions diff --git a/mpas_analysis/ocean/time_series_transport.py b/mpas_analysis/ocean/time_series_transport.py index a6c52008a..0d00a6a64 100644 --- a/mpas_analysis/ocean/time_series_transport.py +++ b/mpas_analysis/ocean/time_series_transport.py @@ -60,7 +60,7 @@ def __init__(self, config, controlConfig=None): # Xylar Asay-Davis # first, call the constructor from the base class (AnalysisTask) - super(TimeSeriesTransport, self).__init__( + super().__init__( config=config, taskName='timeSeriesTransport', componentName='ocean', @@ -69,41 +69,45 @@ def __init__(self, config, controlConfig=None): startYear = config.getint('timeSeries', 'startYear') endYear = config.getint('timeSeries', 'endYear') - years = [year for year in range(startYear, endYear + 1)] - - transectsToPlot = config.getexpression('timeSeriesTransport', - 'transectsToPlot') - if len(transectsToPlot) == 0: - return - - masksSubtask = ComputeTransectMasksSubtask( - parentTask=self, transectGroup='Transport Transects') - - transectsToPlot = masksSubtask.expand_transect_names(transectsToPlot) - transportTransectFileName = masksSubtask.geojsonFileName + transportGroups = config.getexpression('timeSeriesTransport', 'transportGroups') - self.add_subtask(masksSubtask) - - # in the end, we'll combine all the time series into one, but we - # create this task first so it's easier to tell it to run after all - # the compute tasks - combineSubtask = CombineTransportSubtask( - self, startYears=years, endYears=years) - - # run one subtask per year - for year in years: - computeSubtask = ComputeTransportSubtask( - self, startYear=year, endYear=year, masksSubtask=masksSubtask, - transectsToPlot=transectsToPlot) - self.add_subtask(computeSubtask) - computeSubtask.run_after(masksSubtask) - combineSubtask.run_after(computeSubtask) - - for index, transect in enumerate(transectsToPlot): - plotTransportSubtask = PlotTransportSubtask( - self, transect, index, controlConfig, transportTransectFileName) - plotTransportSubtask.run_after(combineSubtask) - self.add_subtask(plotTransportSubtask) + years = [year for year in range(startYear, endYear + 1)] + for transportGroup in transportGroups: + groupSuffix = transportGroup.replace(' ', '') + transectsToPlot = config.getexpression(f'timeSeries{groupSuffix}', + 'transectsToPlot') + if len(transectsToPlot) == 0: + return + + masksSubtask = ComputeTransectMasksSubtask( + parentTask=self, transectGroup=transportGroup) + + transectsToPlot = masksSubtask.expand_transect_names(transectsToPlot) + transportTransectFileName = masksSubtask.geojsonFileName + + self.add_subtask(masksSubtask) + + # in the end, we'll combine all the time series into one, but we + # create this task first so it's easier to tell it to run after all + # the compute tasks + combineSubtask = CombineTransportSubtask( + self, startYears=years, endYears=years, groupSuffix=groupSuffix) + + # run one subtask per year + for year in years: + computeSubtask = ComputeTransportSubtask( + self, startYear=year, endYear=year, masksSubtask=masksSubtask, + transectsToPlot=transectsToPlot, groupSuffix=groupSuffix) + self.add_subtask(computeSubtask) + computeSubtask.run_after(masksSubtask) + combineSubtask.run_after(computeSubtask) + + for index, transect in enumerate(transectsToPlot): + plotTransportSubtask = PlotTransportSubtask( + self, transect, index, controlConfig, transportTransectFileName, + transportGroup) + plotTransportSubtask.run_after(combineSubtask) + self.add_subtask(plotTransportSubtask) class ComputeTransportSubtask(AnalysisTask): @@ -120,6 +124,9 @@ class ComputeTransportSubtask(AnalysisTask): transectsToPlot : list of str A list of transects to plot + + groupSuffix : str + standard transects vs Arctic transects """ # Authors @@ -127,7 +134,7 @@ class ComputeTransportSubtask(AnalysisTask): # Xylar Asay-Davis, Stephen Price def __init__(self, parentTask, startYear, endYear, - masksSubtask, transectsToPlot): + masksSubtask, transectsToPlot, groupSuffix): """ Construct the analysis task. @@ -145,21 +152,23 @@ def __init__(self, parentTask, startYear, endYear, transectsToPlot : list of str A list of transects to plot + + groupSuffix : str + standard transects vs Arctic transects """ # Authors # ------- # Xylar Asay-Davis - + subtaskName = f'compute{groupSuffix}_{startYear:04d}-{endYear:04d}' # first, call the constructor from the base class (AnalysisTask) - super(ComputeTransportSubtask, self).__init__( + super().__init__( config=parentTask.config, taskName=parentTask.taskName, componentName=parentTask.componentName, tags=parentTask.tags, - subtaskName='computeTransport_{:04d}-{:04d}'.format(startYear, - endYear)) - - self.subprocessCount = self.config.getint('timeSeriesTransport', + subtaskName=subtaskName) + + self.subprocessCount = self.config.getint(f'timeSeries{groupSuffix}', 'subprocessCount') self.startYear = startYear self.endYear = endYear @@ -169,6 +178,7 @@ def __init__(self, parentTask, startYear, endYear, self.transectsToPlot = transectsToPlot self.restartFileName = None + self.groupSuffix = groupSuffix def setup_and_check(self): """ @@ -227,8 +237,7 @@ def run_task(self): except OSError: pass - outFileName = '{}/transport_{:04d}-{:04d}.nc'.format( - outputDirectory, self.startYear, self.endYear) + outFileName = f'{outputDirectory}/{self.groupSuffix}_{self.startYear:04d}-{self.endYear:04d}.nc' inputFiles = sorted(self.historyStreams.readpath( 'timeSeriesStatsMonthlyOutput', startDate=startDate, @@ -389,7 +398,7 @@ class CombineTransportSubtask(AnalysisTask): # ------- # Xylar Asay-Davis - def __init__(self, parentTask, startYears, endYears): + def __init__(self, parentTask, startYears, endYears, groupSuffix): """ Construct the analysis task. @@ -401,21 +410,25 @@ def __init__(self, parentTask, startYears, endYears): startYears, endYears : list of int The beginning and end of each time series to combine + groupSuffix : str + standard transects vs Arctic transects + """ # Authors # ------- # Xylar Asay-Davis - + # first, call the constructor from the base class (AnalysisTask) super(CombineTransportSubtask, self).__init__( config=parentTask.config, taskName=parentTask.taskName, componentName=parentTask.componentName, tags=parentTask.tags, - subtaskName='combineTimeSeries') - + subtaskName=f'combine{groupSuffix}TimeSeries') + #print(self.taskName, self.subtaskName) self.startYears = startYears self.endYears = endYears + self.groupSuffix = groupSuffix def run_task(self): """ @@ -424,19 +437,17 @@ def run_task(self): # Authors # ------- # Xylar Asay-Davis - + groupSuffix = self.groupSuffix outputDirectory = '{}/transport/'.format( build_config_full_path(self.config, 'output', 'timeseriesSubdirectory')) + outFileName = f'{outputDirectory}/{groupSuffix}_{self.startYears[0]:04d}-{self.endYears[-1]:04d}.nc' - outFileName = '{}/transport_{:04d}-{:04d}.nc'.format( - outputDirectory, self.startYears[0], self.endYears[-1]) if not os.path.exists(outFileName): inFileNames = [] for startYear, endYear in zip(self.startYears, self.endYears): - inFileName = '{}/transport_{:04d}-{:04d}.nc'.format( - outputDirectory, startYear, endYear) + inFileName = f'{outputDirectory}/{groupSuffix}_{startYear:04d}-{endYear:04d}.nc' inFileNames.append(inFileName) ds = xarray.open_mfdataset(inFileNames, combine='nested', @@ -460,6 +471,10 @@ class PlotTransportSubtask(AnalysisTask): controlConfig : mpas_tools.config.MpasConfigParser The configuration options for the control run (if any) + transportGroup : str (with spaces) + standard transects (``Transport Transects``) + vs Arctic transects (``Arctic Transport Transects``) + """ # Authors @@ -467,7 +482,7 @@ class PlotTransportSubtask(AnalysisTask): # Xylar Asay-Davis, Stephen Price def __init__(self, parentTask, transect, transectIndex, controlConfig, - transportTransectFileName): + transportTransectFileName, transportGroup): """ Construct the analysis task. @@ -486,23 +501,29 @@ def __init__(self, parentTask, transect, transectIndex, controlConfig, controlconfig : mpas_tools.config.MpasConfigParser, optional Configuration options for a control run (if any) + + transportGroup : str (with spaces) + standard transects (``Transport Transects``) + vs Arctic transects (``Arctic Transport Transects``) """ # Authors # ------- # Xylar Asay-Davis # first, call the constructor from the base class (AnalysisTask) + transectKey = transect.replace(' ', '_') super(PlotTransportSubtask, self).__init__( config=parentTask.config, taskName=parentTask.taskName, componentName=parentTask.componentName, tags=parentTask.tags, - subtaskName='plotTransport_{}'.format(transect.replace(' ', '_'))) + subtaskName=f'plotTransport_{transectKey}') self.transportTransectFileName = transportTransectFileName self.transect = transect self.transectIndex = transectIndex self.controlConfig = controlConfig + self.transportGroup = transportGroup def setup_and_check(self): """ @@ -556,6 +577,8 @@ def run_task(self): 'Davis Strait': [-1.6, -3.6], 'Barents Sea Opening': [1.4, 2.6], 'Nares Strait': [-1.8, 0.2], + 'OSNAP section East': [15.6 - 0.8, 15.6 + 0.8], + 'OSNAP section West': [2.1 - 0.3, 2.1 + 0.3], 'Denmark Strait': None, 'Iceland-Faroe-Scotland': None} @@ -580,7 +603,8 @@ def run_task(self): plotControl = self.controlConfig is not None mainRunName = config.get('runs', 'mainRunName') - movingAveragePoints = config.getint('timeSeriesTransport', + groupSuffix = self.transportGroup.replace(' ','') + movingAveragePoints = config.getint(f'timeSeries{groupSuffix}', 'movingAveragePoints') self.logger.info(' Plotting...') @@ -661,7 +685,8 @@ def run_task(self): groupLink='transporttime', thumbnailDescription=thumbnailDescription, imageDescription=caption, - imageCaption=caption) + imageCaption=caption, + gallery=self.transportGroup) def _load_transport(self, config): """ @@ -670,15 +695,13 @@ def _load_transport(self, config): # Authors # ------- # Xylar Asay-Davis - + groupSuffix = self.transportGroup.replace(' ', '') baseDirectory = build_config_full_path( config, 'output', 'timeSeriesSubdirectory') startYear = config.getint('timeSeries', 'startYear') endYear = config.getint('timeSeries', 'endYear') - - inFileName = '{}/transport/transport_{:04d}-{:04d}.nc'.format( - baseDirectory, startYear, endYear) + inFileName = f'{baseDirectory}/transport/{groupSuffix}_{startYear:04d}-{endYear:04d}.nc' dsIn = xarray.open_dataset(inFileName) transport = dsIn.transport.isel(nTransects=self.transectIndex) diff --git a/mpas_analysis/polar_regions.cfg b/mpas_analysis/polar_regions.cfg index cf3fe0630..f0b05f03a 100644 --- a/mpas_analysis/polar_regions.cfg +++ b/mpas_analysis/polar_regions.cfg @@ -549,6 +549,9 @@ makeTables = True # ['all'] for all 106 ice shelves and regions. iceShelvesInTable = ['all'] +[timeSeriesTransport] +## options related to plotting time series of transport through transects +transportGroups = ['Transport Transects', 'Arctic Transport Transects'] [timeSeriesConservation] ## options related to producing time series plots from the conservation