Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve docs tutorial #164

Merged
merged 9 commits into from
Mar 30, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions aospy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from . import calc
from .calc import CalcInterface, Calc
from .automate import submit_mult_calcs
from . import examples

__all__ = ['Proj', 'Model', 'Run', 'Var', 'Units', 'Constant', 'Region',
'units', 'calc', 'constants', 'utils']
125 changes: 112 additions & 13 deletions aospy/automate.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,34 +290,133 @@ def _print_suite_summary(calc_suite_specs):
def submit_mult_calcs(calc_suite_specs, exec_options=None):
"""Generate and execute all specified computations.

Once the calculations are prepped and submitted for execution, any
calculation that triggers any exception or error is skipped, and the rest
of the calculations proceed unaffected. This prevents an error in a single
calculation from crashing a large suite of calculations.

Parameters
----------
calc_suite_specs : dict
The specifications describing the full set of calculations to be
generated and potentially executed.
generated and potentially executed. Accepted keys and their values:

library : module or package comprising an aospy object library
The aospy object library for these calculations.
projects : list of aospy.Proj objects
The projects to permute over.
models : 'all', 'default', or list of aospy.Model objects
The models to permute over. If 'all', use all models in the
``models`` attribute of each ``Proj``. If 'default', use all
models in the ``default_models`` attribute of each ``Proj``.
runs : 'all', 'default', or list of aospy.Run objects
The runs to permute over. If 'all', use all runs in the
``runs`` attribute of each ``Model``. If 'default', use all
runs in the ``default_runs`` attribute of each ``Model``.
variables : list of aospy.Var objects
The variables to be calculated.
regions : 'all' or list of aospy.Region objects
The region(s) over which any regional reductions will be performed.
If 'all', use all regions in the ``regions`` attribute of each
``Proj``.
date_ranges : 'default' or tuple of datetime.datetime objects
The range of dates (inclusive) over which to perform calculations.
If 'default', use the ``default_start_date`` and
``default_end_date`` attribute of each ``Run``.
output_time_intervals : {'ann', season-string, month-integer}
The sub-annual time interval over which to aggregate.

- 'ann' : Annual mean
- season-string : E.g. 'JJA' for June-July-August
- month-integer : 1 for January, 2 for February, etc. Each one is
a separate reduction, e.g. [1, 2] would produce averages (or
other specified time reduction) over all Januaries, and
separately over all Februaries.

output_time_regional_reductions : list of reduction string identifiers
Unlike most other keys, these are not permuted over when creating
the :py:class:`aospy.Calc` objects that execute the calculations;
each :py:class:`aospy.Calc` performs all of the specified
reductions. Accepted string identifiers are:

- Gridpoint-by-gridpoint output:

- 'av' : Gridpoint-by-gridpoint time-average
- 'std' : Gridpoint-by-gridpoint temporal standard deviation
- 'ts' : Gridpoint-by-gridpoint time-series

- Averages over each region specified via `region`:

- 'reg.av', 'reg.std', 'reg.ts' : analogous to 'av', 'std', 'ts'

output_vertical_reductions : {None, 'vert_av', 'vert_int'}, optional
How to reduce the data vertically:

- None : no vertical reduction
- 'vert_av' : mass-weighted vertical average
- 'vert_int' : mass-weighted vertical integral
input_time_intervals : {'annual', 'monthly', 'daily', '#hr'}
A string specifying the time resolution of the input data. In
'#hr' above, the '#' stands for a number, e.g. 3hr or 6hr, for
sub-daily output. These are the suggested specifiers, but others
may be used if they are also used by the DataLoaders for the given
Runs.
input_time_datatypes : {'inst', 'ts', 'av'}
What the time axis of the input data represents:

- 'inst' : Timeseries of instantaneous values
- 'ts' : Timeseries of averages over the period of each time-index
- 'av' : A single value averaged over a date range

input_vertical_datatypes : {False, 'pressure', 'sigma'}, optional
The vertical coordinate system used by the input data:

- False : not defined vertically
- 'pressure' : pressure coordinates
- 'sigma' : hybrid sigma-pressure coordinates

input_time_offsets : {None, dict}, optional
How to offset input data in time to correct for metadata errors

- None : no time offset applied
- dict : e.g. ``{'hours': -3}`` to offset times by -3 hours
See :py:meth:`aospy.utils.times.apply_time_offset`.

exec_options : dict or None (default None)
Options regarding how the calculations are reported, submitted, and
saved. If None, default settings are used for all options. Currently
supported options (each should be either `True` or `False`):

- prompt_verify : If True, print summary of calculations to be
performed and prompt user to confirm before submitting for
execution
- parallelize : If True, submit calculations in parallel
- write_to_tar : If True, write results of calculations to .tar files,
one for each object. These tar files have an identical directory
structures the standard output relative to their root directory,
which is specified via the `tar_direc_out` argument of each Proj
object's instantiation.
- prompt_verify : (default False) If True, print summary of
calculations to be performed and prompt user to confirm before
submitting for execution.
- parallelize : (default False) If True, submit calculations in
parallel. This requires the `multiprocess` library, which can be
installed via `pip install multiprocess`.
- write_to_tar : (default True) If True, write results of calculations
to .tar files, one for each :py:class:`aospy.Run` object. These tar files have an
identical directory structures the standard output relative to
their root directory, which is specified via the `tar_direc_out`
argument of each Proj object's instantiation.

Returns
-------
A list of the values returned by each Calc object that was executed.
A list of the return values from each :py:meth:`aospy.Calc.compute` call
If a calculation ran without error, this value is the
:py:class:`aospy.Calc` object itself, with the results of its
calculations saved in its ``data_out`` attribute. ``data_out`` is a
dictionary, with the keys being the temporal-regional reduction
identifiers (e.g. 'reg.av'), and the values being the corresponding
result.

If any error occurred during a calculation, the return value is None.

Raises
------
AospyException : if the ``prompt_verify`` option is set to True and the
user does not respond affirmatively to the prompt.
AospyException
If the ``prompt_verify`` option is set to True and the user does not
respond affirmatively to the prompt.

"""
if exec_options is None:
exec_options = dict()
Expand Down
12 changes: 5 additions & 7 deletions aospy/calc.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,25 +228,23 @@ class Calc(object):

def __str__(self):
"""String representation of the object."""
return "Calc object: " + ', '.join(
return "<aospy.Calc instance: " + ', '.join(
(self.name, self.proj_str, self.model_str, self.run_str_full)
)
) + ">"

__repr__ = __str__

def _dir_out(self):
"""Create string of the data directory to save individual .nc files."""
ens_label = utils.io.ens_label(self.ens_mem)
return os.path.join(self.proj[0].direc_out, self.proj_str,
self.model_str, self.run_str, ens_label,
self.name)
self.model_str, self.run_str, ens_label, self.name)

def _dir_tar_out(self):
"""Create string of the data directory to store a tar file."""
ens_label = utils.io.ens_label(self.ens_mem)
return os.path.join(self.proj[0].tar_direc_out,
self.proj_str, 'data', self.model_str,
self.run_str, ens_label)
return os.path.join(self.proj[0].tar_direc_out, self.proj_str,
self.model_str, self.run_str, ens_label)

def _file_name(self, dtype_out_time, extension='nc'):
"""Create the name of the aospy file."""
Expand Down
1 change: 1 addition & 0 deletions aospy/examples/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import example_obj_lib
15 changes: 9 additions & 6 deletions aospy/examples/example_obj_lib.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
"""Sample aospy object library using the included example data."""
import datetime
import os

import aospy
from aospy import Model, Proj, Region, Run, Var
from aospy.data_loader import DictDataLoader


_file_map = {'monthly':
'../test/data/netcdf/000[4-6]0101.precip_monthly.nc'}
rootdir = os.path.join(aospy.__path__[0], 'test', 'data', 'netcdf')


_file_map = {'monthly': os.path.join(rootdir,
'000[4-6]0101.precip_monthly.nc')}
example_run = Run(
name='example_run',
description=(
Expand All @@ -20,10 +25,8 @@

example_model = Model(
name='example_model',
grid_file_paths=(
'../test/data/netcdf/00040101.precip_monthly.nc',
'../test/data/netcdf/im.landmask.nc'
),
grid_file_paths=(os.path.join(rootdir, '00040101.precip_monthly.nc'),
os.path.join(rootdir, 'im.landmask.nc')),
runs=[example_run]
)

Expand Down
75 changes: 41 additions & 34 deletions docs/api.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
.. _api-ref:

#############
API Reference
#############

Here we provide the reference documentation for aospy's public API.
If you are new to the package and/or just trying to get a feel for the
overall workflow, you are better off starting in the main
documentation sections.
overall workflow, you are better off starting in the :ref:`Overview
<overview>`, :ref:`using-aospy`, or :ref:`examples` sections of this
documentation.

.. warning::

Expand All @@ -18,8 +21,8 @@ Core Hierarchy for Input Data

aospy provides three classes for specifying the location and
characteristics of data saved on disk as netCDF files that the user
wishes to use as input data for aospy calculations: ``Proj``,
``Model``, and ``Run``.
wishes to use as input data for aospy calculations: :py:class:`Proj`,
:py:class:`Model`, and :py:class:`Run`.

Proj
----
Expand Down Expand Up @@ -51,15 +54,15 @@ Run
DataLoaders
===========

``Run`` objects rely on a helper "data loader" to specify how to find
:py:class:`Run` objects rely on a helper "data loader" to specify how to find
their underlying data that is saved on disk. This mapping of
variables, time ranges, and potentially other parameters to the
location of the corresponding data on disk can differ among modeling
centers or even between different models at the same center.

Currently supported data loader types are ``DictDataLoader``,
``NestedDictDataLoader``, and ``GFDLDataLoader`` Each of these inherit
from the abstract base ``DataLoader`` class.
Currently supported data loader types are :py:class:`DictDataLoader`,
:py:class:`NestedDictDataLoader`, and :py:class:`GFDLDataLoader` Each of these inherit
from the abstract base :py:class:`DataLoader` class.

.. autoclass:: aospy.data_loader.DataLoader
:members:
Expand Down Expand Up @@ -88,14 +91,14 @@ from the abstract base ``DataLoader`` class.
Variables and Regions
=====================

The ``Var`` and ``Region`` classes are used to represent,
The :py:class:`Var` and :py:class:`Region` classes are used to represent,
respectively, physical quantities the user wishes to be able to
compute and geographical regions over which the user wishes to
aggregate their calculations.

Whereas the ``Proj`` - ``Model`` - ``Run`` hierarchy is used to
describe the data resulting from particular model simulations, ``Var``
and ``Region`` represent the properties of generic physical entities
Whereas the :py:class:`Proj` - :py:class:`Model` - :py:class:`Run` hierarchy is used to
describe the data resulting from particular model simulations, :py:class:`Var`
and :py:class:`Region` represent the properties of generic physical entities
that do not depend on the underlying data.

Var
Expand All @@ -119,24 +122,24 @@ Region
Calculations
============

``Calc`` is the engine that combines the user's specifications of (1)
the data on disk via ``Proj``, ``Model``, and ``Run``, (2) the
physical quantity to compute and regions to aggregate over via ``Var``
and ``Region``, and (3) the desired date range, time reduction method,
:py:class:`Calc` is the engine that combines the user's specifications of (1)
the data on disk via :py:class:`Proj`, :py:class:`Model`, and :py:class:`Run`, (2) the
physical quantity to compute and regions to aggregate over via :py:class:`Var`
and :py:class:`Region`, and (3) the desired date range, time reduction method,
and other characteristics to actually perform the calculation

Whereas ``Proj``, ``Model``, ``Run``, ``Var``, and ``Region`` are all
intended to be saved in ``.py`` files for reuse, ``Calc`` objects are
Whereas :py:class:`Proj`, :py:class:`Model`, :py:class:`Run`, :py:class:`Var`, and :py:class:`Region` are all
intended to be saved in ``.py`` files for reuse, :py:class:`Calc` objects are
intended to be generated dynamically by a main script and then not
retained after they have written their outputs to disk following the
user's specifications.

Moreover, if the ``main.py`` script is used to execute calculations,
no direct interfacing with ``Calc`` or it's helper class,
``CalcInterface`` is required by the user, in which case this section
no direct interfacing with :py:class:`Calc` or it's helper class,
:py:class:`CalcInterface` is required by the user, in which case this section
should be skipped entirely.

Also included is the ``automate`` module, which enables aospy e.g. in
Also included is the :py:class:`automate` module, which enables aospy e.g. in
the main script to find objects in the user's object library that the
user specifies via their string names rather than having to import the
objects themselves.
Expand Down Expand Up @@ -168,7 +171,7 @@ operator

.. warning::

The ``operator`` module is in the process of being re-vamped and
The :py:class:`operator` module is in the process of being re-vamped and
is therefore currently not supported.

.. automodule:: aospy.operator
Expand All @@ -178,21 +181,25 @@ operator
Units and Constants
===================

aospy provides the classes ``Constant`` and ``Units`` for
representing, respectively, physical constants (e.g. Earth's
aospy provides the classes :py:class:`Constant` and :py:class:`Units`
for representing, respectively, physical constants (e.g. Earth's
gravitational acceleration at the surface = 9.81 m/s^2) and physical
units (e.g. meters per second squared in that example).

aospy comes with several commonly used constants saved within the
``constants`` module in which the ``Constant`` class is also defined.
In contrast, there are no pre-defined ``Units`` objects; the user must
define any ``Units`` objects they wish to use (e.g. to populate the
``units`` attribute of their ``Var`` objects).
:py:class:`constants` module in which the :py:class:`Constant` class
is also defined. In contrast, there are no pre-defined
:py:class:`Units` objects; the user must define any :py:class:`Units`
objects they wish to use (e.g. to populate the :py:class:`units`
attribute of their :py:class:`Var` objects).

.. warning::

Similarly, whereas these baked-in ``Constant`` objects are used by
aospy in various places, aospy currently does not actually use the
``Var.units`` attribute or the ``Units`` class more generally; they
are for the user's own informational purposes.
Whereas these baked-in :py:class:`Constant` objects are used by
aospy in various places, aospy currently does not actually use the
``Var.units`` attribute during calculations or the
:py:class:`Units` class more generally; they are solely for the
user's own informational purposes.

constants
---------
Expand All @@ -212,8 +219,8 @@ units

There has been discussion of implementing units-handling upstream
within xarray (see `here
<https://github.com/pydata/xarray/issues/525>`_). If and when that
happens, the ``Units`` class will likely be deprecated and replaced
<https://github.com/pydata/xarray/issues/525>`_). If that happens,
the :py:class:`Units` class will likely be deprecated and replaced
with the upstream version.

Utilities
Expand Down
Loading