-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
self.variableList = []
self.seasons = []
@@ -86,6 +100,8 @@ def __init__(self, config, componentName, taskName=None): # {{{
suffix = componentName[0].upper() + componentName[1:]
taskName = 'mpasClimatology{}'.format(suffix)
+ self.allVariables = None
+
# call the constructor from the base class (AnalysisTask)
super(MpasClimatologyTask, self).__init__(
config=config,
@@ -111,12 +127,31 @@ def add_variables(self, variableList, seasons=None): # {{{
to be computed or ['none'] (not ``None``) if only monthly
climatologies are needed.
- Authors
- -------
- Xylar Asay-Davis
+ Raises
+ ------
+ ValueError
+ if this funciton is called before this task has been set up (so
+ the list of available variables has not yet been set) or if one
+ or more of the requested variables is not available in the
+ ``timeSeriesStatsMonthly`` output.
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
+ if self.allVariables is None:
+ raise ValueError('add_variables() can only be called after '
+ 'setup_and_check() in MpasClimatologyTask.\n'
+ 'Presumably tasks were added in the wrong order '
+ 'or add_variables() is being called in the wrong '
+ 'place.')
for variable in variableList:
+ if variable not in self.allVariables:
+ raise ValueError(
+ '{} is not available in timeSeriesStatsMonthly '
+ 'output:\n{}'.format(variable, self.allVariables))
+
if variable not in self.variableList:
self.variableList.append(variable)
@@ -137,11 +172,10 @@ def setup_and_check(self): # {{{
If a restart file is not available from which to read mesh
information or if no history files are available from which to
compute the climatology in the desired time range.
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
# first, call setup_and_check from the base class (AnalysisTask),
# which will perform some common setup, including storing:
@@ -167,18 +201,21 @@ def setup_and_check(self): # {{{
raise IOError('No files were found in stream {} between {} and '
'{}.'.format(streamName, startDate, endDate))
- self._update_climatology_bounds_from_file_names()
+ self.symlinkDirectory = \
+ self._update_climatology_bounds_and_create_symlinks()
+
+ with xarray.open_dataset(self.inputFiles[0]) as ds:
+ self.allVariables = list(ds.data_vars.keys())
# }}}
def run_task(self): # {{{
'''
Compute the requested climatologies
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
if len(self.variableList) == 0:
# nothing to do
@@ -216,7 +253,7 @@ def run_task(self): # {{{
if not allExist:
self._compute_climatologies_with_ncclimo(
- inDirectory=self.historyDirectory,
+ inDirectory=self.symlinkDirectory,
outDirectory=climatologyDirectory)
# }}}
@@ -235,35 +272,42 @@ def get_file_name(self, season): # {{{
-------
fileName : str
The path to the climatology file for the specified season.
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
return get_unmasked_mpas_climatology_file_name(self.config, season,
self.componentName)
# }}}
- def _update_climatology_bounds_from_file_names(self): # {{{
+ def _update_climatology_bounds_and_create_symlinks(self): # {{{
"""
Update the start and end years and dates for climatologies based on the
- years actually available in the list of files.
+ years actually available in the list of files. Create symlinks to
+ monthly mean files so they have the expected file naming convention
+ for ncclimo.
- Authors
+ Returns
-------
- Xylar Asay-Davis
+ symlinkDirectory : str
+ The path to the symlinks created for each timeSeriesStatsMonthly
+ input file
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
config = self.config
requestedStartYear = config.getint('climatology', 'startYear')
requestedEndYear = config.getint('climatology', 'endYear')
- dates = sorted([fileName[-13:-6] for fileName in self.inputFiles])
- years = [int(date[0:4]) for date in dates]
- months = [int(date[5:7]) for date in dates]
+ fileNames = sorted(self.inputFiles)
+ years, months = get_files_year_month(fileNames,
+ self.historyStreams,
+ 'timeSeriesStatsMonthlyOutput')
# search for the start of the first full year
firstIndex = 0
@@ -302,6 +346,25 @@ def _update_climatology_bounds_from_file_names(self): # {{{
self.startYear = startYear
self.endYear = endYear
+ # now, create the symlinks
+ climatologyBaseDirectory = build_config_full_path(
+ config, 'output', 'mpasClimatologySubdirectory')
+
+ symlinkDirectory = '{}/source_symlinks'.format(
+ climatologyBaseDirectory)
+
+ make_directories(symlinkDirectory)
+
+ for inFileName, year, month in zip(fileNames, years, months):
+ outFileName = '{}/{}.hist.am.timeSeriesStatsMonthly.{:04d}-' \
+ '{:02d}-01.nc'.format(symlinkDirectory, self.ncclimoModel,
+ year, month)
+
+ if not os.path.exists(outFileName):
+ os.symlink(inFileName, outFileName)
+
+ return symlinkDirectory
+
# }}}
def _compute_climatologies_with_ncclimo(self, inDirectory, outDirectory,
diff --git a/mpas_analysis/shared/climatology/remap_mpas_climatology_subtask.py b/mpas_analysis/shared/climatology/remap_mpas_climatology_subtask.py
index 3e9d55067..5a7f6b99d 100644
--- a/mpas_analysis/shared/climatology/remap_mpas_climatology_subtask.py
+++ b/mpas_analysis/shared/climatology/remap_mpas_climatology_subtask.py
@@ -1,3 +1,10 @@
+# Copyright (c) 2017, Los Alamos National Security, LLC (LANS)
+# and the University Corporation for Atmospheric Research (UCAR).
+#
+# Unless noted otherwise source code is licensed under the BSD license.
+# Additional copyright and license information can be found in the LICENSE file
+# distributed with this code, or at http://mpas-dev.github.com/license.html
+#
from __future__ import absolute_import, division, print_function, \
unicode_literals
@@ -6,20 +13,23 @@
import numpy
import os
-from ..analysis_task import AnalysisTask
+from mpas_analysis.shared.analysis_task import AnalysisTask
-from ..constants import constants
+from mpas_analysis.shared.constants import constants
-from ..io.utility import build_config_full_path, make_directories
-from ..io import write_netcdf
+from mpas_analysis.shared.io.utility import build_config_full_path, \
+ make_directories
+from mpas_analysis.shared.io import write_netcdf
-from .climatology import get_remapper, get_masked_mpas_climatology_file_name, \
+from mpas_analysis.shared.climatology.climatology import get_remapper, \
+ get_masked_mpas_climatology_file_name, \
get_remapped_mpas_climatology_file_name
-from .comparison_descriptors import get_comparison_descriptor
+from mpas_analysis.shared.climatology.comparison_descriptors import \
+ get_comparison_descriptor
-from ..grid import MpasMeshDescriptor
+from mpas_analysis.shared.grid import MpasMeshDescriptor
-from ..mpas_xarray import mpas_xarray
+from mpas_analysis.shared.mpas_xarray import mpas_xarray
class RemapMpasClimatologySubtask(AnalysisTask): # {{{
@@ -55,14 +65,19 @@ class RemapMpasClimatologySubtask(AnalysisTask): # {{{
If ``comparisonGridName`` is not ``None``, the name of a restart
file from which the MPAS mesh can be read.
- Authors
- -------
- Xylar Asay-Davis
+ useNcremap : bool, optional
+ Whether to use ncremap to do the remapping (the other option being
+ an internal python code that handles more grid types and extra
+ dimensions)
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
def __init__(self, mpasClimatologyTask, parentTask, climatologyName,
variableList, seasons, comparisonGridNames=['latlon'],
- iselValues=None, subtaskName='remapMpasClimatology'):
+ iselValues=None, subtaskName='remapMpasClimatology',
+ useNcremap=None):
# {{{
'''
Construct the analysis task and adds it as a subtask of the
@@ -101,10 +116,18 @@ def __init__(self, mpasClimatologyTask, parentTask, climatologyName,
subtaskName : str, optional
The name of the subtask
- Authors
- -------
- Xylar Asay-Davis
+ useNcremap : bool, optional
+ Whether to use ncremap to do the remapping (the other option being
+ an internal python code that handles more grid types and extra
+ dimensions). This defaults to the config option ``useNcremap``
+ if it is not explicitly given. If a comparison grid other than
+ ``latlon`` is given, ncremap is not supported so this flag is set
+ to ``False``.
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
tags = ['climatology']
# call the constructor from the base class (AnalysisTask)
@@ -130,6 +153,12 @@ def __init__(self, mpasClimatologyTask, parentTask, climatologyName,
# correctly
self._fillValue = -9.99999979021476795361e+33
+ if useNcremap is None:
+ self.useNcremap = self.config.getboolean('climatology',
+ 'useNcremap')
+ else:
+ self.useNcremap = useNcremap
+
# }}}
def setup_and_check(self): # {{{
@@ -142,11 +171,10 @@ def setup_and_check(self): # {{{
If a restart file is not available from which to read mesh
information or if no history files are available from which to
compute the climatology in the desired time range.
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
# first, call setup_and_check from the base class (AnalysisTask),
# which will perform some common setup, including storing:
@@ -181,11 +209,10 @@ def setup_and_check(self): # {{{
def run_task(self): # {{{
'''
Compute the requested climatologies
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
self.logger.info('\nRemapping climatology {}'.format(
self.climatologyName))
@@ -234,11 +261,10 @@ def get_masked_file_name(self, season): # {{{
-------
fileName : str
The path to the climatology file for the specified season.
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
fileName = get_masked_mpas_climatology_file_name(self.config,
season,
@@ -265,11 +291,10 @@ def get_remapped_file_name(self, season, comparisonGridName): # {{{
-------
fileName : str
The path to the climatology file for the specified season.
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
fileName = get_remapped_mpas_climatology_file_name(
self.config, season, self.componentName, self.climatologyName,
@@ -281,11 +306,11 @@ def _setup_remappers(self): # {{{
"""
Set up the remappers for remapping from the MPAS to the comparison
grids.
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
config = self.config
# make reamppers
@@ -326,11 +351,10 @@ def customize_masked_climatology(self, climatology): # {{{
climatology : ``xarray.Dataset```
The same data set with any custom fields added or modifications
made
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
return climatology # }}}
@@ -348,22 +372,20 @@ def customize_remapped_climatology(self, climatology): # {{{
climatology : ``xarray.Dataset```
The same data set with any custom fields added or modifications
made
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
return climatology # }}}
def _setup_file_names(self): # {{{
"""
Create a dictionary of file names and directories for this climatology
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
config = self.config
climatologyBaseDirectory = build_config_full_path(
@@ -499,25 +521,20 @@ def _remap(self, inFileName, outFileName, remapper, comparisonGridName):
comparisonGridNames : {'latlon', 'antarctic'}
The name of the comparison grid to use for remapping.
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
if remapper.mappingFileName is None:
# no remapping is needed
return
- useNcremap = self.config.getboolean('climatology', 'useNcremap')
-
- if comparisonGridName != 'latlon':
- # ncremap doesn't support grids other than lat/lon
- useNcremap = False
-
renormalizationThreshold = self.config.getfloat(
'climatology', 'renormalizationThreshold')
- if useNcremap:
+ # ncremap doesn't support grids other than lat/lon
+ if self.useNcremap and comparisonGridName == 'latlon':
remapper.remap_file(inFileName=inFileName,
outFileName=outFileName,
overwrite=True,
diff --git a/mpas_analysis/shared/climatology/remap_observed_climatology_subtask.py b/mpas_analysis/shared/climatology/remap_observed_climatology_subtask.py
index ac4c14af6..532490916 100644
--- a/mpas_analysis/shared/climatology/remap_observed_climatology_subtask.py
+++ b/mpas_analysis/shared/climatology/remap_observed_climatology_subtask.py
@@ -1,3 +1,10 @@
+# Copyright (c) 2017, Los Alamos National Security, LLC (LANS)
+# and the University Corporation for Atmospheric Research (UCAR).
+#
+# Unless noted otherwise source code is licensed under the BSD license.
+# Additional copyright and license information can be found in the LICENSE file
+# distributed with this code, or at http://mpas-dev.github.com/license.html
+#
from __future__ import absolute_import, division, print_function, \
unicode_literals
@@ -5,17 +12,19 @@
import os.path
import xarray as xr
-from ..analysis_task import AnalysisTask
+from mpas_analysis.shared.analysis_task import AnalysisTask
-from ..constants import constants
+from mpas_analysis.shared.constants import constants
-from ..io.utility import build_config_full_path, make_directories
-from ..io import write_netcdf
+from mpas_analysis.shared.io.utility import build_config_full_path, \
+ make_directories
+from mpas_analysis.shared.io import write_netcdf
-from .climatology import get_remapper, remap_and_write_climatology, \
- compute_climatology
+from mpas_analysis.shared.climatology.climatology import get_remapper, \
+ remap_and_write_climatology, compute_climatology
-from .comparison_descriptors import get_comparison_descriptor
+from mpas_analysis.shared.climatology.comparison_descriptors import \
+ get_comparison_descriptor
class RemapObservedClimatologySubtask(AnalysisTask): # {{{
@@ -37,10 +46,10 @@ class RemapObservedClimatologySubtask(AnalysisTask): # {{{
comparisonGridNames : list of {'latlon', 'antarctic'}
The name(s) of the comparison grid to use for remapping.
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
def __init__(self, parentTask, seasons, fileName, outFilePrefix,
comparisonGridNames=['latlon'],
@@ -71,12 +80,10 @@ def __init__(self, parentTask, seasons, fileName, outFilePrefix,
subtaskName : str, optional
The name of the subtask
-
- Authors
- -------
- Xylar Asay-Davis
-
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
self.seasons = seasons
self.fileName = fileName
@@ -97,11 +104,11 @@ def __init__(self, parentTask, seasons, fileName, outFilePrefix,
def setup_and_check(self): # {{{
"""
Perform steps to set up the analysis and check for errors in the setup.
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
# call setup_and_check from the base class (AnalysisTask),
# which will perform some common setup, including storing:
# self.runDirectory , self.historyDirectory, self.plotsDirectory,
@@ -125,11 +132,10 @@ def setup_and_check(self): # {{{
def run_task(self): # {{{
"""
Performs remapping of obsrevations to the comparsion grid
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
config = self.config
@@ -198,11 +204,10 @@ def get_observation_descriptor(self, fileName): # {{{
-------
obsDescriptor : ``MeshDescriptor``
The descriptor for the observation grid
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
return None # }}}
@@ -221,11 +226,10 @@ def build_observational_dataset(self, fileName): # {{{
-------
dsObs : ``xarray.Dataset``
The observational dataset
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
return None # }}}
@@ -253,11 +257,10 @@ def get_file_name(self, stage, season=None, comparisonGridName=None):
-------
fileName : str
The path to the climatology file for the specified season.
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
config = self.config
obsSection = '{}Observations'.format(self.componentName)
@@ -314,11 +317,11 @@ def _setup_remappers(self, fileName): # {{{
----------
fileName : str
The name of the observation file used to determine the source grid
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
config = self.config
sectionName = '{}Observations'.format(self.componentName)
diff --git a/mpas_analysis/shared/constants/constants.py b/mpas_analysis/shared/constants/constants.py
index 9f901aadf..7635ca678 100644
--- a/mpas_analysis/shared/constants/constants.py
+++ b/mpas_analysis/shared/constants/constants.py
@@ -1,14 +1,16 @@
+# Copyright (c) 2017, Los Alamos National Security, LLC (LANS)
+# and the University Corporation for Atmospheric Research (UCAR).
+#
+# Unless noted otherwise source code is licensed under the BSD license.
+# Additional copyright and license information can be found in the LICENSE file
+# distributed with this code, or at http://mpas-dev.github.com/license.html
+#
"""
Constants that are common to all analysis tasks
-
-Authors
--------
-Luke Van Roekel, Xylar Asay-Davis, Milena Veneziani
-
-Last modified
--------------
-03/15/2017
"""
+# Authors
+# -------
+# Luke Van Roekel, Xylar Asay-Davis, Milena Veneziani
from __future__ import absolute_import, division, print_function, \
unicode_literals
@@ -64,4 +66,7 @@
# kilograms per gigatonne
kg_per_GT = 1e12
+# cm per m
+cm_per_m = 100.
+
# vim: foldmethod=marker ai ts=4 sts=4 et sw=4 ft=python
diff --git a/mpas_analysis/shared/containers.py b/mpas_analysis/shared/containers.py
index a0b30f004..27e725412 100644
--- a/mpas_analysis/shared/containers.py
+++ b/mpas_analysis/shared/containers.py
@@ -1,4 +1,11 @@
#!/usr/bin/env python
+# Copyright (c) 2017, Los Alamos National Security, LLC (LANS)
+# and the University Corporation for Atmospheric Research (UCAR).
+#
+# Unless noted otherwise source code is licensed under the BSD license.
+# Additional copyright and license information can be found in the LICENSE file
+# distributed with this code, or at http://mpas-dev.github.com/license.html
+#
"""
Module of custom container data types
@@ -10,7 +17,9 @@
unicode_literals
import collections
-class ReadOnlyDict(collections.Mapping): #{{{
+
+
+class ReadOnlyDict(collections.Mapping): # {{{
""" Read only-dictionary
http://stackoverflow.com/questions/19022868/how-to-make-dictionary-read-only-in-python
310/22/2016
@@ -28,6 +37,6 @@ def __len__(self):
def __iter__(self):
return iter(self._data)
-#}}}
+# }}}
# vim: foldmethod=marker ai ts=4 sts=4 et sw=4 ft=python
diff --git a/mpas_analysis/shared/generalized_reader/__init__.py b/mpas_analysis/shared/generalized_reader/__init__.py
index 6db020e3b..4e5b85ce4 100644
--- a/mpas_analysis/shared/generalized_reader/__init__.py
+++ b/mpas_analysis/shared/generalized_reader/__init__.py
@@ -1 +1,2 @@
-from .generalized_reader import open_multifile_dataset
\ No newline at end of file
+from mpas_analysis.shared.generalized_reader.generalized_reader import \
+ open_multifile_dataset
diff --git a/mpas_analysis/shared/generalized_reader/generalized_reader.py b/mpas_analysis/shared/generalized_reader/generalized_reader.py
index a7c1c4375..419e74a2b 100644
--- a/mpas_analysis/shared/generalized_reader/generalized_reader.py
+++ b/mpas_analysis/shared/generalized_reader/generalized_reader.py
@@ -1,3 +1,10 @@
+# Copyright (c) 2017, Los Alamos National Security, LLC (LANS)
+# and the University Corporation for Atmospheric Research (UCAR).
+#
+# Unless noted otherwise source code is licensed under the BSD license.
+# Additional copyright and license information can be found in the LICENSE file
+# distributed with this code, or at http://mpas-dev.github.com/license.html
+#
"""
Utility functions for importing MPAS files into xarray. These functions extend
the capabilities of mpas_xarray to include mapping variable names from MPAS
@@ -7,11 +14,10 @@
open_multifile_dataset : opens a data set, maps variable names, preprocess
the data set removes repeated time indices, and slices the time coordinate
to lie between desired start and end dates.
-
-Authors
--------
-Xylar Asay-Davis
"""
+# Authors
+# -------
+# Xylar Asay-Davis
from __future__ import absolute_import, division, print_function, \
unicode_literals
@@ -21,8 +27,9 @@
from functools import partial
import resource
-from ..mpas_xarray import mpas_xarray
-from ..timekeeping.utility import string_to_days_since_date, days_to_datetime
+from mpas_analysis.shared.mpas_xarray import mpas_xarray
+from mpas_analysis.shared.timekeeping.utility import \
+ string_to_days_since_date, days_to_datetime
def open_multifile_dataset(fileNames, calendar, config,
@@ -116,11 +123,10 @@ def open_multifile_dataset(fileNames, calendar, config,
If the time variable is not found in the data set or if the time
variable is a number of days since the start of the simulation but
simulationStartTime is None.
-
- Authors
- -------
- Xylar Asay-Davis, Phillip J. Wolfram
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis, Phillip J. Wolfram
preprocess_partial = partial(_preprocess,
calendar=calendar,
@@ -270,11 +276,10 @@ def _preprocess(ds, calendar, simulationStartTime, timeVariableName,
ds : xarray.DataSet object
A copy of the data set with the time coordinate set and which
has been sliced.
-
- Authors
- -------
- Xylar Asay-Davis, Phillip J. Wolfram
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis, Phillip J. Wolfram
submap = variableMap
@@ -342,11 +347,11 @@ def _map_variable_name(variableName, ds, variableMap): # {{{
ValueError
If none of the possible variable names in `variableMap[variableName]`
can be found in `ds`.
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
possibleVariables = variableMap[variableName]
for variable in possibleVariables:
if isinstance(variable, (list, tuple)):
@@ -390,11 +395,10 @@ def _rename_variables(ds, variableMap): # {{{
Returns
-------
outDataSEt : A new `xarray.DataSet` object with the variable renamed.
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
renameDict = {}
for datasetVariable in ds.data_vars:
diff --git a/mpas_analysis/shared/grid/__init__.py b/mpas_analysis/shared/grid/__init__.py
index beffc841f..4155437f5 100644
--- a/mpas_analysis/shared/grid/__init__.py
+++ b/mpas_analysis/shared/grid/__init__.py
@@ -1,2 +1,2 @@
-from .grid import MpasMeshDescriptor, LatLonGridDescriptor, \
- ProjectionGridDescriptor, interp_extrap_corner
+from mpas_analysis.shared.grid.grid import MpasMeshDescriptor, \
+ LatLonGridDescriptor, ProjectionGridDescriptor, interp_extrap_corner
diff --git a/mpas_analysis/shared/grid/grid.py b/mpas_analysis/shared/grid/grid.py
index ba7c4096d..26fe38032 100644
--- a/mpas_analysis/shared/grid/grid.py
+++ b/mpas_analysis/shared/grid/grid.py
@@ -1,3 +1,10 @@
+# Copyright (c) 2017, Los Alamos National Security, LLC (LANS)
+# and the University Corporation for Atmospheric Research (UCAR).
+#
+# Unless noted otherwise source code is licensed under the BSD license.
+# Additional copyright and license information can be found in the LICENSE file
+# distributed with this code, or at http://mpas-dev.github.com/license.html
+#
'''
Classes for describing meshes and grids , including creating SCRIP files,
used to create mapping files
@@ -10,12 +17,10 @@
ProjectionGridDescriptor - describes a logically rectangular grid on a pyproj
projection
-
-Authors
--------
-Xylar Asay-Davis
-
'''
+# Authors
+# -------
+# Xylar Asay-Davis
from __future__ import absolute_import, division, print_function, \
unicode_literals
@@ -30,23 +35,20 @@
class MeshDescriptor(object): # {{{
'''
A class for describing a mesh
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
def __init__(self): # {{{
'''
Constructor creates a common ``meshName`` member variable, ``None`` by
default. Each Subclass should define or use input arguments to set
``meshName`` to a short description of the mesh or grid.
-
- Authors
- -------
- Xylar Asay-Davis
-
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
self.meshName = None # }}}
@@ -59,11 +61,10 @@ def to_scrip(self, scripFileName): # {{{
----------
scripFileName : str
The path to which the SCRIP file should be written
-
- Authors
- ------
- Xylar Asay-Davis
'''
+ # Authors
+ # ------
+ # Xylar Asay-Davis
return # }}}
@@ -73,11 +74,10 @@ def to_scrip(self, scripFileName): # {{{
class MpasMeshDescriptor(MeshDescriptor): # {{{
'''
A class for describing an MPAS mesh
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
def __init__(self, fileName, meshName=None): # {{{
'''
@@ -93,11 +93,10 @@ def __init__(self, fileName, meshName=None): # {{{
``'oRRS18to6'``). If not provided, the data set in ``fileName``
must have a global attribute ``meshName`` that will be used
instead.
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
ds = xarray.open_dataset(fileName)
@@ -130,11 +129,11 @@ def to_scrip(self, scripFileName): # {{{
----------
scripFileName : str
The path to which the SCRIP file should be written
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
self.scripFileName = scripFileName
inFile = netCDF4.Dataset(self.fileName, 'r')
@@ -195,11 +194,11 @@ def to_scrip(self, scripFileName): # {{{
class LatLonGridDescriptor(MeshDescriptor): # {{{
'''
A class for describing a lat-lon grid
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
def __init__(self): # {{{
'''
Constructor stores the file name
@@ -208,11 +207,11 @@ def __init__(self): # {{{
----------
fileName : str
The path of the file containing the MPAS mesh
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
self.regional = False
self.meshName = None # }}}
@@ -234,11 +233,11 @@ def read(cls, fileName=None, ds=None, latVarName='lat',
latVarName, lonVarName : str, optional
The name of the latitude and longitude variables in the grid file
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
if ds is None:
ds = xarray.open_dataset(fileName)
@@ -282,11 +281,11 @@ def create(cls, latCorner, lonCorner, units='degrees'): # {{{
units : {'degrees', 'radians'}, optional
The units of `latCorner` and `lonCorner`
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
descriptor = cls()
descriptor.latCorner = latCorner
@@ -306,11 +305,11 @@ def to_scrip(self, scripFileName): # {{{
----------
scripFileName : str
The path to which the SCRIP file should be written
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
self.scripFileName = scripFileName
outFile = netCDF4.Dataset(scripFileName, 'w')
@@ -375,11 +374,10 @@ class ProjectionGridDescriptor(MeshDescriptor): # {{{
'''
A class for describing a general logically rectangular grid that can be
defined by a `pyproj` projection.
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
def __init__(self, projection): # {{{
'''
@@ -390,11 +388,11 @@ def __init__(self, projection): # {{{
projection : ``pyproj.Proj`` object
The projection used to map from grid x-y space to latitude and
longitude
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
self.projection = projection
self.latLonProjection = pyproj.Proj(proj='latlong', datum='WGS84')
self.regional = True
@@ -423,11 +421,11 @@ def read(cls, projection, fileName, meshName=None, xVarName='x',
xVarName, yVarName : str, optional
The name of the x and y (in meters) variables in the grid file
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
descriptor = cls(projection)
ds = xarray.open_dataset(fileName)
@@ -473,11 +471,11 @@ def create(cls, projection, x, y, meshName): # {{{
meshName : str
The name of the grid (e.g. ``'10km_Antarctic_stereo'``)
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
descriptor = cls(projection)
descriptor.meshName = meshName
@@ -501,11 +499,11 @@ def to_scrip(self, scripFileName): # {{{
----------
scripFileName : str
The path to which the SCRIP file should be written
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
self.scripFileName = scripFileName
outFile = netCDF4.Dataset(scripFileName, 'w')
@@ -553,11 +551,10 @@ def project_to_lat_lon(self, X, Y): # {{{
-------
Lat, Lon : numpy.array with same shape as X and Y
the latitude and longitude in degrees of the points
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
Lon, Lat = pyproj.transform(self.projection, self.latLonProjection,
X, Y, radians=False)
@@ -627,11 +624,11 @@ def _create_scrip(outFile, grid_size, grid_corners, grid_rank, units,
meshName : str
The name of the mesh
-
- Authors
- -------
- Xylar Asay-Davis
'''
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
# Write to output file
# Dimensions
outFile.createDimension("grid_size", grid_size)
diff --git a/mpas_analysis/shared/html/__init__.py b/mpas_analysis/shared/html/__init__.py
index 209d380a7..85962d2ac 100644
--- a/mpas_analysis/shared/html/__init__.py
+++ b/mpas_analysis/shared/html/__init__.py
@@ -1,2 +1,3 @@
-from .pages import MainPage, ComponentPage, generate_html
-from .image_xml import write_image_xml
+from mpas_analysis.shared.html.pages import MainPage, ComponentPage, \
+ generate_html
+from mpas_analysis.shared.html.image_xml import write_image_xml
diff --git a/mpas_analysis/shared/html/image_xml.py b/mpas_analysis/shared/html/image_xml.py
index 001e62602..b16c80a82 100644
--- a/mpas_analysis/shared/html/image_xml.py
+++ b/mpas_analysis/shared/html/image_xml.py
@@ -1,3 +1,10 @@
+# Copyright (c) 2017, Los Alamos National Security, LLC (LANS)
+# and the University Corporation for Atmospheric Research (UCAR).
+#
+# Unless noted otherwise source code is licensed under the BSD license.
+# Additional copyright and license information can be found in the LICENSE file
+# distributed with this code, or at http://mpas-dev.github.com/license.html
+#
from __future__ import absolute_import, division, print_function, \
unicode_literals
@@ -11,7 +18,7 @@
from lxml import etree
from PIL import Image
-from ..io.utility import build_config_full_path
+from mpas_analysis.shared.io.utility import build_config_full_path
def write_image_xml(config, filePrefix, componentName, componentSubdirectory,
@@ -74,11 +81,11 @@ def write_image_xml(config, filePrefix, componentName, componentSubdirectory,
kwargs : dict
additional keyword arguments will be used to add additional xml tags
with the associated values
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
imageFileName = '{}.png'.format(filePrefix)
plotsDirectory = build_config_full_path(config, 'output',
'plotsSubdirectory')
@@ -141,11 +148,11 @@ def write_image_xml(config, filePrefix, componentName, componentSubdirectory,
def _provenance_command(root, history): # {{{
"""
Utility funciton for provenance of xml file associated with a plot.
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
call = ' '.join(sys.argv)
if history is None:
history = call
diff --git a/mpas_analysis/shared/html/pages.py b/mpas_analysis/shared/html/pages.py
index 7c3640228..ea9a7a03c 100644
--- a/mpas_analysis/shared/html/pages.py
+++ b/mpas_analysis/shared/html/pages.py
@@ -1,3 +1,10 @@
+# Copyright (c) 2017, Los Alamos National Security, LLC (LANS)
+# and the University Corporation for Atmospheric Research (UCAR).
+#
+# Unless noted otherwise source code is licensed under the BSD license.
+# Additional copyright and license information can be found in the LICENSE file
+# distributed with this code, or at http://mpas-dev.github.com/license.html
+#
from __future__ import absolute_import, division, print_function, \
unicode_literals
@@ -8,7 +15,7 @@
from lxml import etree
from collections import OrderedDict
-from ..io.utility import build_config_full_path
+from mpas_analysis.shared.io.utility import build_config_full_path
def generate_html(config, analyses, refConfig=None): # {{{
@@ -29,11 +36,11 @@ def generate_html(config, analyses, refConfig=None): # {{{
refConfig : ``MpasAnalysisConfigParser``, optional
Config options for a reference run
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
generateHTML = config.getboolean('html', 'generate')
if not generateHTML:
return
@@ -88,11 +95,11 @@ class MainPage(object):
components : OrederdDict of dict
Each component has a name, subdirectory and image name used to find
the appropriate thumbnail.
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
def __init__(self, config, refConfig=None):
"""
Create a MainPage object, reading in the templates
@@ -104,11 +111,10 @@ def __init__(self, config, refConfig=None):
refConfig : ``MpasAnalysisConfigParser``, optional
Config options for a reference run
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
self.config = config
self.refConfig = refConfig
@@ -148,11 +154,11 @@ def add_component(self, name, subdirectory, imageFileName):
The name of an image file (without path) that will be used as the
thumbnail for the gallery. Typically, this is the first image
from the first gallery.
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
self.components[name] = {'subdirectory': subdirectory,
'imageFileName': imageFileName}
@@ -160,11 +166,11 @@ def generate(self):
"""
Generate the webpage from templates and components, and write it out to
the HTML directory.
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
runName = self.config.get('runs', 'mainRunName')
if self.refConfig is None:
@@ -253,11 +259,11 @@ class ComponentPage(object):
groups : tree of OrederdDict
A tree of information describing the the gallery groups in the page,
the galleries in each group and the images in each gallery.
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
def __init__(self, config, name, subdirectory, refConfig=None):
"""
Create a ComponentPage object, reading in the templates
@@ -277,11 +283,10 @@ def __init__(self, config, name, subdirectory, refConfig=None):
refConfig : ``MpasAnalysisConfigParser``, optional
Config options for a reference run
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
self.config = config
self.refConfig = refConfig
@@ -331,11 +336,11 @@ def add_image(xmlFileName, config, components, refConfig=None):
refConfig : ``MpasAnalysisConfigParser``, optional
Config options for a reference run
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
xmlRoot = etree.parse(xmlFileName).getroot()
componentName = ComponentPage._get_required_xml_text(xmlRoot,
@@ -398,11 +403,11 @@ def generate(self):
"""
Generate the webpage from templates and groups, and write it out to
the HTML directory.
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
runName = self.config.get('runs', 'mainRunName')
if self.refConfig is None:
@@ -444,11 +449,11 @@ def get_first_image(self):
-------
firstImageFilename : str
The name (with out path) of the first image in the first gallery
-
- Authors
- -------
- Xylar Asay-Davis
"""
+ # Authors
+ # -------
+ # Xylar Asay-Davis
+
# get the first image name
firstGroup = next(iter(self.groups.values()))
firstGallery = next(iter(firstGroup['galleries'].values()))
diff --git a/mpas_analysis/shared/html/templates/component_gallery.html b/mpas_analysis/shared/html/templates/component_gallery.html
index a016c5e8f..ee0400a57 100644
--- a/mpas_analysis/shared/html/templates/component_gallery.html
+++ b/mpas_analysis/shared/html/templates/component_gallery.html
@@ -1,3 +1,13 @@
+
+
+
@galleryTitle